[gen] Optimized PXs. [px] added tag 'var2', similar to 'var', but that is executed after tags 'for' and 'if'.

This commit is contained in:
Gaetan Delannay 2013-07-15 11:23:29 +02:00
parent 73c3cfb2c7
commit 1810373304
18 changed files with 834 additions and 956 deletions

View file

@ -33,17 +33,15 @@ class Action(Field):
<input type="hidden" name="action" value="ExecuteAppyAction"/> <input type="hidden" name="action" value="ExecuteAppyAction"/>
<input type="hidden" name="objectUid" value=":contextObj.UID()"/> <input type="hidden" name="objectUid" value=":contextObj.UID()"/>
<input type="hidden" name="fieldName" value=":name"/> <input type="hidden" name="fieldName" value=":name"/>
<x if="field.confirm"><input <input if="field.confirm" type="button" class="button"
type="button" class="button"
var="labelConfirm=_(field.labelId + '_confirm')" var="labelConfirm=_(field.labelId + '_confirm')"
value=":ztool.truncateValue(label)" title=":label" value=":ztool.truncateValue(label)" title=":label"
style=":'background-image: url(%s/ui/buttonAction.png)' % appUrl" style=":img('buttonAction', bg=True)"
onclick=":'askConfirm(%s,%s,%s)' % (q('form'), q(formId), \ onclick=":'askConfirm(%s,%s,%s)' % (q('form'), q(formId), \
q(labelConfirm))"/> q(labelConfirm))"/>
</x>
<input if="not field.confirm" type="submit" class="button" name="do" <input if="not field.confirm" type="submit" class="button" name="do"
value=":ztool.truncateValue(label)" title=":label" value=":ztool.truncateValue(label)" title=":label"
style=":'background-image: url(%s/ui/buttonAction.png)' % appUrl"/> style=":img('buttonAction', bg=True)"/>
</form>''') </form>''')
# It is not possible to edit an action, not to search it. # It is not possible to edit an action, not to search it.

View file

@ -36,25 +36,22 @@ class Calendar(Field):
otherCalendars=field.getOtherCalendars(contextObj, preComputed)" otherCalendars=field.getOtherCalendars(contextObj, preComputed)"
id=":ajaxHookId"> id=":ajaxHookId">
<script type="text/javascript">:'var %s_maxEventLength = %d;' % \ <script type="text/javascript">:'var %s_maxEventLength = %d;' % \
(field.name, field.maxEventLength)"> (field.name, field.maxEventLength)"></script>
</script>
<!-- Month chooser --> <!-- Month chooser -->
<div style="margin-bottom: 5px" <div style="margin-bottom: 5px"
var="fmt='%Y/%m/%d'; var="fmt='%Y/%m/%d';
goBack=not startDate or (startDate.strftime(fmt) &lt; \ goBack=not startDate or (startDate.strftime(fmt) &lt; \
grid[0][0].strftime(fmt)); grid[0][0].strftime(fmt));
goForward=not endDate or (endDate.strftime(fmt) &gt; \ goForward=not endDate or (endDate.strftime(fmt) &gt; \
grid[-1][-1].strftime(fmt))"> grid[-1][-1].strftime(fmt))">
<!-- Go to the previous month --> <!-- Go to the previous month -->
<img style="cursor:pointer" tal:condition="goBack" <img style="cursor:pointer" if="goBack" src=":img('arrowLeftSimple')"
src=":'%s/ui/arrowLeftSimple.png' % appUrl" onclick=":'askMonthView(%s,%s,%s,%s)' % \
onclick=":'askMonthView(%s, %s, %s, %s)' % \
(q(ajaxHookId),q(objUrl),q(field.name),q(previousMonth))"/> (q(ajaxHookId),q(objUrl),q(field.name),q(previousMonth))"/>
<!-- Go back to the default date --> <!-- Go back to the default date -->
<x if="goBack or goForward"> <input type="button" if="goBack or goForward"
<input type="button"
var="fmt='%Y/%m'; var="fmt='%Y/%m';
label=(defaultDate.strftime(fmt)==today.strftime(fmt)) and \ label=(defaultDate.strftime(fmt)==today.strftime(fmt)) and \
'today' or 'goto_source'" 'today' or 'goto_source'"
@ -62,170 +59,158 @@ class Calendar(Field):
onclick=":'askMonthView(%s, %s, %s, %s)' % (q(ajaxHookId), \ onclick=":'askMonthView(%s, %s, %s, %s)' % (q(ajaxHookId), \
q(objUrl), q(field.name), q(defaultDateMonth))" q(objUrl), q(field.name), q(defaultDateMonth))"
disabled=":defaultDate.strftime(fmt)==monthDayOne.strftime(fmt)"/> disabled=":defaultDate.strftime(fmt)==monthDayOne.strftime(fmt)"/>
</x> <!-- Go to the next month -->
<!-- Go to the next month --> <img style="cursor:pointer" if="goForward" src=":img('arrowRightSimple')"
<img style="cursor:pointer" if="goForward" onclick=":'askMonthView(%s, %s, %s, %s)' % (q(ajaxHookId), \
src=":'%s/ui/arrowRightSimple.png' % appUrl"
onclick=":'askMonthView(%s, %s, %s, %s)' % (q(ajaxHookId), \
q(objUrl), q(field.name), q(nextMonth))"/> q(objUrl), q(field.name), q(nextMonth))"/>
<span>:_('month_%s' % monthDayOne.aMonth())</span> <span>:_('month_%s' % monthDayOne.aMonth())</span>
<span>:month.split('/')[0]</span> <span>:month.split('/')[0]</span>
</div> </div>
<!-- Calendar month view --> <!-- Calendar month view -->
<table cellpadding="0" cellspacing="0" width="100%" class="list" <table cellpadding="0" cellspacing="0" width="100%" class="list"
style="font-size: 95%" style="font-size: 95%"
var="rowHeight=int(field.height/float(len(grid)))"> var="rowHeight=int(field.height/float(len(grid)))">
<!-- 1st row: names of days --> <!-- 1st row: names of days -->
<tr height="22px"> <tr height="22px">
<th for="dayName in field.getNamesOfDays(contextObj)" <th for="dayName in field.getNamesOfDays(contextObj)"
width="14%">:dayName</th> width="14%">:dayName</th>
</tr> </tr>
<!-- The calendar in itself --> <!-- The calendar in itself -->
<tr for="row in grid" valign="top" height=":rowHeight"> <tr for="row in grid" valign="top" height=":rowHeight">
<x for="date in row"> <x for="date in row"
<x var="tooEarly=startDate and (date &lt; startDate); var2="tooEarly=startDate and (date &lt; startDate);
tooLate=endDate and not tooEarly and (date &gt; endDate); tooLate=endDate and not tooEarly and (date &gt; endDate);
inRange=not tooEarly and not tooLate; inRange=not tooEarly and not tooLate;
cssClasses=field.getCellStyle(contextObj, date, today)"> cssClasses=field.getCellStyle(contextObj, date, today)">
<!-- Dump an empty cell if we are out of the supported date range --> <!-- Dump an empty cell if we are out of the supported date range -->
<td if="not inRange" class=":cssClasses"></td> <td if="not inRange" class=":cssClasses"></td>
<!-- Dump a normal cell if we are in range --> <!-- Dump a normal cell if we are in range -->
<x if="inRange"> <td if="inRange"
<td var="events=field.getEventsAt(contextObj, date); var2="events=field.getEventsAt(contextObj, date);
spansDays=field.hasEventsAt(contextObj, date+1, events); spansDays=field.hasEventsAt(contextObj, date+1, events);
mayCreate=mayEdit and not events; mayCreate=mayEdit and not events;
mayDelete=mayEdit and events" mayDelete=mayEdit and events;
style="date.isCurrentDay() and 'font-weight:bold' or \ day=date.day();
'font-weight:normal'" dayString=date.strftime('%Y/%m/%d')"
class=":cssClasses" style="date.isCurrentDay() and 'font-weight:bold' or \
onmouseover=":mayEdit and 'this.getElementsByTagName(\ 'font-weight:normal'"
%s)[0].style.visibility=%s' % (q('img'), q('visible')) or ''" class=":cssClasses"
onmouseout="mayEdit and 'this.getElementsByTagName(\ onmouseover=":mayEdit and 'this.getElementsByTagName(\
%s)[0].style.visibility=%s' % (q('img'), q('hidden')) or ''"> %s)[0].style.visibility=%s' % (q('img'), q('visible')) or ''"
<x var="day=date.day(); onmouseout="mayEdit and 'this.getElementsByTagName(\
dayString=date.strftime('%Y/%m/%d')"> %s)[0].style.visibility=%s' % (q('img'), q('hidden')) or ''">
<span>:day</span> <span>:day</span>
<span if="day == 1">:_('month_%s_short' % date.aMonth())"></span> <span if="day == 1">:_('month_%s_short' % date.aMonth())"></span>
<!-- Icon for adding an event --> <!-- Icon for adding an event -->
<x if="mayCreate"> <x if="mayCreate">
<img style="visibility:hidden; cursor:pointer" <img style="visibility:hidden; cursor:pointer"
var="info=field.getApplicableEventsTypesAt(contextObj, date, \ var="info=field.getApplicableEventsTypesAt(contextObj, date, \
allEventTypes, preComputed, True)" allEventTypes, preComputed, True)"
if="info['eventTypes']" if="info['eventTypes']" src=":img('plus')"
src=":'%s/ui/plus.png' % appUrl" onclick=":'openEventPopup(%s, %s, %s, null, %s, %s)' % \
onclick=":'openEventPopup(%s, %s, %s, null, %s, %s)' % \ (q('new'), q(field.name), q(dayString), q(info['eventTypes']),\
(q('new'), q(field.name), q(dayString), \ q(info['message']))"/>
q(info['eventTypes']), q(info['message']))"/> </x>
</x> <!-- Icon for deleting an event -->
<!-- Icon for deleting an event --> <img if="mayDelete" style="visibility:hidden; cursor:pointer"
<img if="mayDelete" style="visibility:hidden; cursor:pointer" src=":img('delete')"
src=":'%s/ui/delete.png' % appUrl" onclick=":'openEventPopup(%s, %s, %s, %s, null, null)' % \
onclick=":'openEventPopup(%s, %s, %s, %s, null, null)' % \ (q('del'), q(field.name), q(dayString), q(str(spansDays)))"/>
(q('del'), q(field.name), q(dayString), q(str(spansDays)))"/> <!-- A single event is allowed for the moment -->
<x if="events"> <div if="events" var2="eventType=events[0]['eventType']">
<!-- A single event is allowed for the moment --> <span style="color: grey">:field.getEventName(contextObj, \
<div var="eventType=events[0]['eventType']"> eventType)"></span>
<span style="color: grey">:field.getEventName(contextObj, \ </div>
eventType)"></span> <!-- Events from other calendars -->
</div> <x if="otherCalendars"
</x> var2="otherEvents=field.getOtherEventsAt(contextObj, date, \
<!-- Events from other calendars --> otherCalendars)">
<x if="otherCalendars"> <div style=":'color: %s; font-style: italic' % event['color']"
<x var="otherEvents=field.getOtherEventsAt(contextObj, date, \ for="event in otherEvents">:event['name']</div>
otherCalendars)" </x>
if="otherEvents"> <!-- Additional info -->
<div style=":'color: %s; font-style: italic' % event['color']" <x var="info=field.getAdditionalInfoAt(contextObj,date,preComputed)"
for="event in otherEvents">:event['name']</div> if="info">::info</x>
</x> </td>
</x>
<!-- Additional info -->
<x var="info=field.getAdditionalInfoAt(contextObj,date,preComputed)"
if="info">::info</x>
</x>
</td>
</x>
</x> </x>
</x> </tr>
</tr> </table>
</table>
<!-- Popup for creating a calendar event --> <!-- Popup for creating a calendar event -->
<div var="prefix='%s_newEvent' % field.name; <div var="prefix='%s_newEvent' % field.name;
popupId=prefix + 'Popup'" popupId=prefix + 'Popup'"
id=":popupId" class="popup" align="center"> id=":popupId" class="popup" align="center">
<form id="prefix + 'Form'" method="post"> <form id="prefix + 'Form'" method="post">
<input type="hidden" name="fieldName" value=":field.name"/> <input type="hidden" name="fieldName" value=":field.name"/>
<input type="hidden" name="month" value=":month"/> <input type="hidden" name="month" value=":month"/>
<input type="hidden" name="name" value=":field.name"/> <input type="hidden" name="name" value=":field.name"/>
<input type="hidden" name="action" value="Process"/> <input type="hidden" name="action" value="Process"/>
<input type="hidden" name="actionType" value="createEvent"/> <input type="hidden" name="actionType" value="createEvent"/>
<input type="hidden" name="day"/> <input type="hidden" name="day"/>
<!-- Choose an event type --> <!-- Choose an event type -->
<div align="center" style="margin-bottom: 3px">:_('which_event')"></div> <div align="center" style="margin-bottom: 3px">:_('which_event')"></div>
<select name="eventType"> <select name="eventType">
<option value="">:_('choose_a_value')"></option> <option value="">:_('choose_a_value')"></option>
<option for="eventType in allEventTypes" <option for="eventType in allEventTypes"
value=":eventType">:field.getEventName(contextObj, eventType)"> value=":eventType">:field.getEventName(contextObj, eventType)">
</option> </option>
</select><br/><br/> </select><br/><br/>
<!--Span the event on several days --> <!--Span the event on several days -->
<div align="center" class="discreet" style="margin-bottom: 3px"> <div align="center" class="discreet" style="margin-bottom: 3px">
<span>:_('event_span')"></span> <span>:_('event_span')"></span>
<input type="text" size="3" name="eventSpan"/> <input type="text" size="3" name="eventSpan"/>
</div> </div>
<input type="button" <input type="button"
value=":_('object_save')" value=":_('object_save')"
onclick=":'triggerCalendarEvent(%s, %s, %s, %s, \ onclick=":'triggerCalendarEvent(%s, %s, %s, %s, \
%s_maxEventLength)' % (q('new'), q(ajaxHookId), \ %s_maxEventLength)' % (q('new'), q(ajaxHookId), \
q(field.name), q(objUrl), field.name)"/> q(field.name), q(objUrl), field.name)"/>
<input type="button" <input type="button"
value=":_('object_cancel')" value=":_('object_cancel')"
onclick=":'closePopup(%s)' % q(popupId)"/> onclick=":'closePopup(%s)' % q(popupId)"/>
</form> </form>
</div> </div>
<!-- Popup for deleting a calendar event --> <!-- Popup for deleting a calendar event -->
<div var="prefix='%s_delEvent' % field.name; <div var="prefix='%s_delEvent' % field.name;
popupId=prefix + 'Popup'" popupId=prefix + 'Popup'"
id=":popupId" class="popup" align="center"> id=":popupId" class="popup" align="center">
<form id=":prefix + 'Form'" method="post"> <form id=":prefix + 'Form'" method="post">
<input type="hidden" name="fieldName" value=":field.name"/> <input type="hidden" name="fieldName" value=":field.name"/>
<input type="hidden" name="month" value=":month"/> <input type="hidden" name="month" value=":month"/>
<input type="hidden" name="name" value=":field.name"/> <input type="hidden" name="name" value=":field.name"/>
<input type="hidden" name="action" value="Process"/> <input type="hidden" name="action" value="Process"/>
<input type="hidden" name="actionType" value="deleteEvent"/> <input type="hidden" name="actionType" value="deleteEvent"/>
<input type="hidden" name="day"/> <input type="hidden" name="day"/>
<div align="center" style="margin-bottom: 5px">_('delete_confirm')"> <div align="center" style="margin-bottom: 5px">_('delete_confirm')">
</div> </div>
<!-- Delete successive events ? --> <!-- Delete successive events ? -->
<div class="discreet" style="margin-bottom: 10px" <div class="discreet" style="margin-bottom: 10px"
id=":prefix + 'DelNextEvent'"> id=":prefix + 'DelNextEvent'">
<input type="checkbox" name="deleteNext_cb" <input type="checkbox" name="deleteNext_cb"
id=":prefix + '_cb'" id=":prefix + '_cb'"
onClick=":'toggleCheckbox(%s, %s)' % \ onClick=":'toggleCheckbox(%s, %s)' % \
(q('%s_cb' % prefix), q('%s_hd' % prefix))"/> (q('%s_cb' % prefix), q('%s_hd' % prefix))"/>
<input type="hidden" id=":prefix + '_hd'" name="deleteNext"/> <input type="hidden" id=":prefix + '_hd'" name="deleteNext"/>
<span>:_('del_next_events')"></span> <span>:_('del_next_events')"></span>
</div> </div>
<input type="button" value=":_('yes')" <input type="button" value=":_('yes')"
onClick=":'triggerCalendarEvent(%s, %s, %s, %s)' % \ onClick=":'triggerCalendarEvent(%s, %s, %s, %s)' % \
(q('del'), q(ajaxHookId), q(field.name), q(objUrl))"/> (q('del'), q(ajaxHookId), q(field.name), q(objUrl))"/>
<input type="button" value=":_('no')" <input type="button" value=":_('no')"
onclick=":'closePopup(%s)' % q(popupId)"/> onclick=":'closePopup(%s)' % q(popupId)"/>
</form> </form>
</div> </div>
</div>''') </div>''')
pxView = pxCell = Px(''' pxView = pxCell = Px('''
<x var="defaultDate=field.getDefaultDate(contextObj); <x var="defaultDate=field.getDefaultDate(contextObj);
x=req.set('fieldName', field.name); x=req.set('month', defaultDate.strftime('%Y/%m'));
x=req.set('month', defaultDate.strftime('%Y/%m'))"> x=req.set('fieldName', field.name)">:field.pxMonthView</x>''')
<x>:field.pxMonthView</x>
</x>''')
pxEdit = pxSearch = '' pxEdit = pxSearch = ''

View file

@ -28,27 +28,23 @@ class Computed(Field):
value=contextObj.getFieldValue(name); value=contextObj.getFieldValue(name);
sync=True">:field.pxView</x>''') sync=True">:field.pxView</x>''')
pxView = pxCell = pxEdit = Px(''' pxView = pxCell = pxEdit = Px('''<x>
<x> <x if="sync">
<x if="sync"> <x if="field.plainText">:value</x><x if="not field.plainText">::value></x>
<x if="field.plainText">:value</x> </x>
<x if="not field.plainText">::value></x> <div if="not sync">
</x> var2="ajaxHookId=contextObj.UID() + name" id="ajaxHookId">
<x if="not sync"> <script type="text/javascript">:'askComputedField(%s, %s, %s)' % \
<div var="ajaxHookId=contextObj.UID() + name" id="ajaxHookId"> (q(ajaxHookId), q(contextObj.absolute_url()), q(name))">
<script type="text/javascript">:'askComputedField(%s, %s, %s)' % \ </script>
(q(ajaxHookId), q(contextObj.absolute_url()), q(name))"> </div>
</script> </x>''')
</div>
</x>
</x>''')
pxSearch = Px(''' pxSearch = Px('''<x>
<x> <label lfor=":name">:field.labelId</label><br/>&nbsp;&nbsp;
<label lfor=":name">:field.labelId</label><br/>&nbsp;&nbsp; <input type="text" name=":'%s*string' % name" maxlength=":field.maxChars"
<input type="text" name=":'%s*string' % name" maxlength=":field.maxChars" size=":field.width" value=":field.sdefault"/>
size=":field.width" value=":field.sdefault"/> </x>''')
</x>''')
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show='view', page='main', group=None, layouts=None, move=0, show='view', page='main', group=None, layouts=None, move=0,

View file

@ -29,20 +29,20 @@ class Date(Field):
<select var="days=range(1,32)" <select var="days=range(1,32)"
name=":'%s_day' % name" id=":'%s_day' % name"> name=":'%s_day' % name" id=":'%s_day' % name">
<option value="">-</option> <option value="">-</option>
<x for="day in days"> <option for="day in days"
<option var="zDay=str(day).zfill(2)" value=":zDay" var2="zDay=str(day).zfill(2)" value=":zDay"
selected="field.isSelected(contextObj, 'day', day, \ selected="field.isSelected(contextObj, 'day', day, \
rawValue)">:zDay</option></x> rawValue)">:zDay</option>
</select> </select>
<!-- Month --> <!-- Month -->
<select var="months=range(1,13)" <select var="months=range(1,13)"
name=":'%s_month' % name" id=":'%s_month' % name"> name=":'%s_month' % name" id=":'%s_month' % name">
<option value="">-</option> <option value="">-</option>
<x for="month in months"> <option for="month in months"
<option var="zMonth=str(month).zfill(2)" value=":zMonth" var2="zMonth=str(month).zfill(2)" value=":zMonth"
selected="field.isSelected(contextObj, 'month', month, \ selected="field.isSelected(contextObj, 'month', month, \
rawValue)">:zMonth</option></x> rawValue)">:zMonth</option>
</select> </select>
<!-- Year --> <!-- Year -->
@ -56,7 +56,7 @@ class Date(Field):
<!-- The icon for displaying the calendar popup --> <!-- The icon for displaying the calendar popup -->
<x if="field.calendar"> <x if="field.calendar">
<input type="hidden" id=":name" name=":name"/> <input type="hidden" id=":name" name=":name"/>
<img id=":'%s_img' % name" src=":'%s/ui/calendar.gif' % appUrl"/> <img id=":'%s_img' % name" src=":img('calendar.gif')"/>
<script type="text/javascript">:field.getJsInit(name, years)</script> <script type="text/javascript">:field.getJsInit(name, years)</script>
</x> </x>
@ -65,19 +65,18 @@ class Date(Field):
<select var="hours=range(0,24)" name=":'%s_hour' % name" <select var="hours=range(0,24)" name=":'%s_hour' % name"
id=":'%s_hour' % name"> id=":'%s_hour' % name">
<option value="">-</option> <option value="">-</option>
<x for="hour in hours"> <option for="hour in hours"
<option var="zHour=str(hour).zfill(2)" value=":zHour" var2="zHour=str(hour).zfill(2)" value=":zHour"
selected=":field.isSelected(contextObj, 'hour', hour, \ selected=":field.isSelected(contextObj, 'hour', hour, \
rawValue)">:zHour</option> rawValue)">:zHour</option>
</x>
</select> : </select> :
<select var="minutes=range(0,60,5)" name=":'%s_minute' % name" <select var="minutes=range(0,60,5)" name=":'%s_minute' % name"
id=":'%s_minute' % name"> id=":'%s_minute' % name">
<option value="">-</option> <option value="">-</option>
<x for="minute in minutes"> <option for="minute in minutes"
<option var="zMinute=str(minute).zfill(2)" value=":zMinute" var2="zMinute=str(minute).zfill(2)" value=":zMinute"
selected=":field.isSelected(contextObj, 'minute', minute,\ selected=":field.isSelected(contextObj, 'minute', minute,\
rawValue)">:zMinute</option></x> rawValue)">:zMinute</option>
</select> </select>
</x> </x>
</x>''') </x>''')
@ -112,7 +111,7 @@ class Date(Field):
<!-- The icon for displaying the calendar popup --> <!-- The icon for displaying the calendar popup -->
<x if="field.calendar"> <x if="field.calendar">
<input type="hidden" id=":fromName" name=":fromName"/> <input type="hidden" id=":fromName" name=":fromName"/>
<img id=":'%s_img' % fromName" src=":'%s/ui/calendar.gif' % appUrl"/> <img id=":'%s_img' % fromName" src=":img('calendar.gif')"/>
<script type="text/javascript">:field.getJsInit(fromName, years) <script type="text/javascript">:field.getJsInit(fromName, years)
</script> </script>
</x> </x>
@ -145,7 +144,7 @@ class Date(Field):
<!-- The icon for displaying the calendar popup --> <!-- The icon for displaying the calendar popup -->
<x if="widget.calendar"> <x if="widget.calendar">
<input type="hidden" id=":toName" name=":toName"/> <input type="hidden" id=":toName" name=":toName"/>
<img id=":'%s_img' % toName" src=":%s/ui/calendar.gif' % appUrl"/> <img id=":'%s_img' % toName" src=":img('calendar.gif')"/>
<script type="text/javascript">:field.getJsInit(toName, years)"> <script type="text/javascript">:field.getJsInit(toName, years)">
</script> </script>
</x> </x>

View file

@ -31,26 +31,25 @@ class Float(Field):
</x>''') </x>''')
pxEdit = Px(''' pxEdit = Px('''
<input id=":name" name=":name" size=":field.width" <input id=":name" name=":name" size=":field.width"
maxlength=":field.maxChars" maxlength=":field.maxChars"
value=":inRequest and requestValue or value" type="text"/>''') value=":inRequest and requestValue or value" type="text"/>''')
pxSearch = Px(''' pxSearch = Px('''<x>
<x> <label>:_(field.labelId)"></label><br/>&nbsp;&nbsp;
<label>:_(field.labelId)"></label><br/>&nbsp;&nbsp; <!-- From -->
<!-- From --> <x var="fromName='%s*float' % widgetName">
<x var="fromName='%s*float' % widgetName"> <label lfor=":fromName">:_('search_from')"></label>
<label lfor=":fromName">:_('search_from')"></label> <input type="text" name=":fromName" maxlength=":field.maxChars"
<input type="text" name=":fromName" maxlength=":field.maxChars" value=":field.sdefault[0]" size=":field.swidth"/>
value=":field.sdefault[0]" size=":field.swidth"/> </x>
</x> <!-- To -->
<!-- To --> <x var="toName='%s_to' % name">
<x var="toName='%s_to' % name"> <label lfor=":toName">:_('search_to')</label>
<label lfor=":toName">:_('search_to')</label> <input type="text" name=":toName" maxlength=":field.maxChars"
<input type="text" name=":toName" maxlength=":field.maxChars" value=":field.sdefault[1]" size="field.swidth"/>
value=":field.sdefault[1]" size="field.swidth"/> </x><br/>
</x><br/> </x>''')
</x>''')
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,

View file

@ -32,22 +32,21 @@ class Integer(Field):
maxlength=":field.maxChars" maxlength=":field.maxChars"
value=":inRequest and requestValue or value" type="text"/>''') value=":inRequest and requestValue or value" type="text"/>''')
pxSearch = Px(''' pxSearch = Px('''<x>
<x> <label>:_(field.labelId)"></label><br/>&nbsp;&nbsp;
<label>:_(field.labelId)"></label><br/>&nbsp;&nbsp; <!-- From -->
<!-- From --> <x var="fromName='%s*int' % widgetName">
<x var="fromName='%s*int' % widgetName"> <label lfor=":fromName">:_('search_from')</label>
<label lfor=":fromName">:_('search_from')</label> <input type="text" name=":fromName" maxlength=":field.maxChars"
<input type="text" name=":fromName" maxlength=":field.maxChars" value=":field.sdefault[0]" size=":field.swidth"/>
value=":field.sdefault[0]" size=":field.swidth"/> </x>
</x> <!-- To -->
<!-- To --> <x var="toName='%s_to' % name">
<x var="toName='%s_to' % name"> <label lfor=":toName">:_('search_to')"></label>
<label lfor=":toName">:_('search_to')"></label> <input type="text" name=":toName" maxlength=":field.maxChars"
<input type="text" name=":toName" maxlength=":field.maxChars" value=":field.sdefault[1]" size=":field.swidth"/>
value=":field.sdefault[1]" size=":field.swidth"/> </x><br/>
</x><br/> </x>''')
</x>''')
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,

View file

@ -27,15 +27,14 @@ class List(Field):
# PX for rendering a single row. # PX for rendering a single row.
pxRow = Px(''' pxRow = Px('''
<tr valign="top" style="(rowIndex==-1) and 'display: none' or ''"> <tr valign="top" style="(rowIndex==-1) and 'display: none' or ''">
<td align="center" for="info in field.fields"> <td align="center" for="info in field.fields"
<x var="field=info[1]; var2="field=info[1];
tagCss='noStyle'; tagCss='noStyle';
widgetName='%s*%d' % (field.name, rowIndex)">:field.pxView</x> widgetName='%s*%d' % (field.name, rowIndex)">:field.pxView</td>
</td>
<!-- Icon for removing the row --> <!-- Icon for removing the row -->
<td if="layoutType=='edit'" align=":dright"> <td if="layoutType=='edit'" align=":dright">
<img style="cursor:pointer" src=":'%s/ui/delete.png' % appUrl" <img style="cursor:pointer" src=":img(delete')"
title="Delete" title=":_('object_delete')"
onclick=":'deleteRow(%s, this)' % q('list_%s' % name)"/> onclick=":'deleteRow(%s, this)' % q('list_%s' % name)"/>
</td> </td>
</tr>''') </tr>''')
@ -49,8 +48,7 @@ class List(Field):
<th for="info in field.fields">::_(info[1].labelId)</th> <th for="info in field.fields">::_(info[1].labelId)</th>
<!-- Icon for adding a new row. --> <!-- Icon for adding a new row. -->
<th if="isEdit"> <th if="isEdit">
<img style="cursor:pointer" src=":'%s/ui/plus.png' % appUrl" <img style="cursor:pointer" src=":img('plus')" title=":_('add_ref')"
title=":_('add_ref')"
onclick=":'insertRow(%s)' % q('list_%s' % name)"/> onclick=":'insertRow(%s)' % q('list_%s' % name)"/>
</th> </th>
</tr> </tr>
@ -60,17 +58,15 @@ class List(Field):
<tr height="7px" if="isEdit"><td></td></tr> <tr height="7px" if="isEdit"><td></td></tr>
<!-- Rows of data --> <!-- Rows of data -->
<x var="rows=inRequest and requestValue or value" for="row in rows"> <x var="rows=inRequest and requestValue or value"
<x var="rowIndex=loop.row.nb">:field.pxRow</x> for="row in rows" var2="rowIndex=loop.row.nb">:field.pxRow</x>
</x>
</table>''') </table>''')
pxView = pxCell = Px('''<x>:field.pxTable</x>''') pxView = pxCell = Px('''<x>:field.pxTable</x>''')
pxEdit = Px(''' pxEdit = Px('''<x>
<x> <!-- This input makes Appy aware that this field is in the request -->
<!-- This input makes Appy aware that this field is in the request --> <input type="hidden" name=":name" value=""/><x>:field.pxTable</x>
<input type="hidden" name=":name" value=""/><x>:field.pxTable</x> </x>''')
</x>''')
pxSearch = '' pxSearch = ''

View file

@ -30,21 +30,18 @@ class Ogone(Field):
'''This field allows to perform payments with the Ogone (r) system.''' '''This field allows to perform payments with the Ogone (r) system.'''
urlTypes = ('accept', 'decline', 'exception', 'cancel') urlTypes = ('accept', 'decline', 'exception', 'cancel')
pxView = pxCell = Px(''' pxView = pxCell = Px('''<x>
<x> <!-- var "value" is misused and contains the contact params for Ogone -->
<!-- var "value" is misused and contains the contact params for Ogone --> <!-- The form for sending the payment request to Ogone -->
<!-- The form for sending the payment request to Ogone --> <form method="post" id="form1" name="form1" var="env=value['env']"
<form method="post" id="form1" name="form1" var="env=value['env']" action=":'https://secure.ogone.com/ncol/%s/orderstandard.asp'% env">
action=":'https://secure.ogone.com/ncol/%s/orderstandard.asp'% env"> <input type="hidden" for="item in value.items()" if="item[0] != 'env'"
<x for="item in value.items()"> id=":item[0]" name=":item[0]" value=":item[1]"/>
<input type="hidden" if="item[0] != 'env'" id=":item[0]" <!-- Submit image -->
name=":item[0]" value=":item[1]"/> <input type="image" id="submit2" name="submit2" src=":img('ogone.gif')"
</x> title=":_('custom_pay')"/>
<!-- Submit image --> </form>
<input type="image" id="submit2" name="submit2" </x>''')
src=":'%s/ui/ogone.gif' % $appUrl" title=":_('custom_pay')"/>
</form>
</x>''')
pxEdit = pxSearch = '' pxEdit = pxSearch = ''

View file

@ -35,23 +35,19 @@ class Pod(Field):
'contact the system administrator.' 'contact the system administrator.'
DELETE_TEMP_DOC_ERROR = 'A temporary document could not be removed. %s.' DELETE_TEMP_DOC_ERROR = 'A temporary document could not be removed. %s.'
pxView = pxCell = Px(''' pxView = pxCell = Px('''<x>
<x> <!-- Ask action -->
<!-- Ask action --> <x if="field.askAction"
<x if="field.askAction"> var2="doLabel='%s_askaction' % field.labelId;
<x var="doLabel='%s_askaction' % field.labelId; chekboxId='%s_%s_cb' % (contextObj.UID(), name)">
chekboxId='%s_%s_cb' % (contextObj.UID(), name)"> <input type="checkbox" name=":doLabel" id=":chekboxId"/>
<input type="checkbox" name=":doLabel" id=":chekboxId"/> <label lfor=":chekboxId" class="discreet">:_(doLabel)"></label>
<label lfor=":chekboxId" class="discreet">:_(doLabel)"></label> </x>
</x> <img for="fmt in field.getToolInfo(contextObj.appy())[1]" src=":img(fmt)"
</x> onclick=":'generatePodDocument(%s, %s, %s, %s)' % \
<img for="podFormat in field.getToolInfo(contextObj.appy())[1]" (q(contextObj.UID()), q(name), q(fmt), q(ztool.getQueryInfo()))"
src=":'%s/ui/%s.png' % (appUrl, podFormat)" title=":fmt.capitalize()" style="cursor:pointer"/>
onclick=":'generatePodDocument(%s, %s, %s, %s)' % \ </x>''')
(q(contextObj.UID()), q(name), q(podFormat), \
q(ztool.getQueryInfo()))"
title=":podFormat.capitalize()" style="cursor:pointer"/>
</x>''')
pxEdit = pxSearch = '' pxEdit = pxSearch = ''

View file

@ -56,41 +56,37 @@ class Ref(Field):
<table class="noStyle" var="isBack=field.isBack"> <table class="noStyle" var="isBack=field.isBack">
<tr> <tr>
<!-- Arrows for moving objects up or down --> <!-- Arrows for moving objects up or down -->
<td if="not isBack and (len(objs)&gt;1) and changeOrder and canWrite"> <td if="not isBack and (len(objs)&gt;1) and changeOrder and canWrite"
<x var="objectIndex=field.getIndexOf(contextObj, obj); var2="objectIndex=field.getIndexOf(contextObj, obj);
ajaxBaseCall=navBaseCall.replace('**v**','%s,%s,{%s:%s,%s:%s}'%\ ajaxBaseCall=navBaseCall.replace('**v**','%s,%s,{%s:%s,%s:%s}'%\
(q(startNumber), q('ChangeRefOrder'), q('refObjectUid'), (q(startNumber), q('ChangeRefOrder'), q('refObjectUid'),
q(obj.UID()), q('move'), q('**v**')))"> q(obj.UID()), q('move'), q('**v**')))">
<img if="objectIndex &gt; 0" style="cursor:pointer" <img if="objectIndex &gt; 0" style="cursor:pointer"
src=":'%s/ui/arrowUp.png' % appUrl" title=":_('move_up')" src=":img('arrowUp')" title=":_('move_up')"
onclick=":ajaxBaseCall.replace('**v**', 'up')"/><img onclick=":ajaxBaseCall.replace('**v**', 'up')"/>
style="cursor:pointer" if="objectIndex &lt; (totalNumber-1)" <img if="objectIndex &lt; (totalNumber-1)" style="cursor:pointer"
src=":'%s/ui/arrowDown.png' % appUrl" title=":_('move_down')" src=":img('arrowDown')" title=":_('move_down')"
onclick=":ajaxBaseCall.replace('**v**', 'down')"/> onclick=":ajaxBaseCall.replace('**v**', 'down')"/>
</x>
</td> </td>
<!-- Workflow transitions --> <!-- Workflow transitions -->
<td if="obj.showTransitions('result')"> <td if="obj.showTransitions('result')"
<x var="targetObj=obj">:targetObj.appy().pxTransitions</x> var2="targetObj=obj">:targetObj.appy().pxTransitions</td>
</td>
<!-- Edit --> <!-- Edit -->
<td if="not field.noForm and obj.mayEdit() and field.delete"> <td if="not field.noForm and obj.mayEdit() and field.delete">
<a var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), field.name, \ <a var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), field.name, \
field.pageName, loop.obj.nb + startNumber, totalNumber)" field.pageName, loop.obj.nb + startNumber, totalNumber)"
href=":obj.getUrl(mode='edit', page='main', nav=navInfo)"> href=":obj.getUrl(mode='edit', page='main', nav=navInfo)">
<img src=":'%s/ui/edit.png' % appUrl" title=":_('object_edit')"/> <img src=":img('edit')" title=":_('object_edit')"/></a>
</a>
</td> </td>
<!-- Delete --> <!-- Delete -->
<td if="not isBack and field.delete and canWrite and obj.mayDelete()"> <td if="not isBack and field.delete and canWrite and obj.mayDelete()">
<img style="cursor:pointer" title=":_('object_delete')" <img style="cursor:pointer" title=":_('object_delete')"
src=":'%s/ui/delete.png' % appUrl" src=":img('delete')" onclick=":'onDeleteObject(%s)'%q(obj.UID())"/>
onclick=":'onDeleteObject(%s)' % q(obj.UID())"/>
</td> </td>
<!-- Unlink --> <!-- Unlink -->
<td if="not isBack and field.unlink and canWrite"> <td if="not isBack and field.unlink and canWrite">
<img style="cursor:pointer" title=":_('object_unlink')" <img style="cursor:pointer" title=":_('object_unlink')"
src=":'%s/ui/unlink.png' % appUrl" src=":img('unlink')"
onclick=":'onUnlinkObject(%s,%s,%s)' % (q(contextObj.UID()), \ onclick=":'onUnlinkObject(%s,%s,%s)' % (q(contextObj.UID()), \
q(field.name), q(obj.UID()))"/> q(field.name), q(obj.UID()))"/>
</td> </td>
@ -100,37 +96,34 @@ class Ref(Field):
# Displays the button allowing to add a new object through a Ref field, if # Displays the button allowing to add a new object through a Ref field, if
# it has been declared as addable and if multiplicities allow it. # it has been declared as addable and if multiplicities allow it.
pxAdd = Px(''' pxAdd = Px('''
<x if="showPlusIcon"> <input if="showPlusIcon" type="button" class="button"
<input type="button" class="button" var2="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), \
var="navInfo='ref.%s.%s:%s.%d.%d' % (contextObj.UID(), \ field.name, field.pageName, 0, totalNumber);
field.name, field.pageName, 0, totalNumber); formCall='window.location=%s' % \
formCall='window.location=%s' % \ q('%s/do?action=Create&amp;className=%s&amp;nav=%s' % \
q('%s/do?action=Create&amp;className=%s&amp;nav=%s' % \ (folder.absolute_url(), linkedPortalType, navInfo));
(folder.absolute_url(), linkedPortalType, navInfo)); formCall=not field.addConfirm and formCall or \
formCall=not field.addConfirm and formCall or \ 'askConfirm(%s,%s,%s)' % (q('script'), q(formCall), \
'askConfirm(%s,%s,%s)' % (q('script'), q(formCall), \ q(addConfirmMsg));
q(addConfirmMsg)); noFormCall=navBaseCall.replace('**v**', \
noFormCall=navBaseCall.replace('**v**', \ '%d,%s' % (startNumber, q('CreateWithoutForm')));
'%d,%s' % (startNumber, q('CreateWithoutForm'))); noFormCall=not field.addConfirm and noFormCall or \
noFormCall=not field.addConfirm and noFormCall or \ 'askConfirm(%s, %s, %s)' % (q('script'), q(noFormCall), \
'askConfirm(%s, %s, %s)' % (q('script'), q(noFormCall), \ q(addConfirmMsg))"
q(addConfirmMsg))" style=":img('buttonAdd', bg=True)" value=":_('add_ref')"
style=":'background-image: url(%s/ui/buttonAdd.png)' % appUrl" onclick=":field.noForm and noFormCall or formCall"/>''')
value=":_('add_ref')"
onclick=":field.noForm and noFormCall or formCall"/>
</x>''')
# This PX displays, in a cell header from a ref table, icons for sorting the # This PX displays, in a cell header from a ref table, icons for sorting the
# ref field according to the field that corresponds to this column. # ref field according to the field that corresponds to this column.
pxSortIcons = Px(''' pxSortIcons = Px('''
<x var="ajaxBaseCall=navBaseCall.replace('**v**', '%s,%s,{%s:%s,%s:%s}' % \ <x if="changeOrder and canWrite and ztool.isSortable(field.name, \
objs[0].meta_type, 'ref')"
var2="ajaxBaseCall=navBaseCall.replace('**v**', '%s,%s,{%s:%s,%s:%s}'% \
(q(startNumber), q('SortReference'), q('sortKey'), \ (q(startNumber), q('SortReference'), q('sortKey'), \
q(field.name), q('reverse'), q('**v**')))" q(field.name), q('reverse'), q('**v**')))">
if="changeOrder and canWrite and ztool.isSortable(field.name, \ <img style="cursor:pointer" src=":img('sortAsc')"
objs[0].meta_type, 'ref')">
<img style="cursor:pointer" src=":'%s/ui/sortAsc.png' % appUrl"
onclick=":ajaxBaseCall.replace('**v**', 'False')"/> onclick=":ajaxBaseCall.replace('**v**', 'False')"/>
<img style="cursor:pointer" src=":'%s/ui/sortDesc.png' % appUrl" <img style="cursor:pointer" src=":img('sortDesc')"
onclick=":ajaxBaseCall.replace('**v**', 'True')"/> onclick=":ajaxBaseCall.replace('**v**', 'True')"/>
</x>''') </x>''')
@ -165,25 +158,21 @@ class Ref(Field):
shouldn't check the actual number of referenced objects. But for shouldn't check the actual number of referenced objects. But for
back references people often forget to specify multiplicities. So back references people often forget to specify multiplicities. So
concretely, multiplicities (0,None) are coded as (0,1). --> concretely, multiplicities (0,None) are coded as (0,1). -->
<x if="atMostOneRef"> <!-- Display a simplified widget if at most 1 referenced object. -->
<!-- Display a simplified widget if maximum number of referenced objects <table if="atMostOneRef">
is 1. --> <tr valign="top">
<table> <!-- If there is no object -->
<tr valign="top"> <x if="not objs">
<!-- If there is no object --> <td class="discreet">:_('no_ref')</td>
<x if="not objs"> <td>:field.pxAdd</td>
<td class="discreet">:_('no_ref')</td> </x>
<td>:field.pxAdd</td> <!-- If there is an object... -->
</x> <x if="objs">
<!-- If there is an object... --> <td for="obj in objs"
<x if="objs"> var2="includeShownInfo=True">:field.pxObjectTitle</td>
<x for="obj in objs"> </x>
<td var="includeShownInfo=True">:field.pxObjectTitle</td> </tr>
</x> </table>
</x>
</tr>
</table>
</x>
<!-- Display a table in all other cases --> <!-- Display a table in all other cases -->
<x if="not atMostOneRef"> <x if="not atMostOneRef">
@ -192,8 +181,7 @@ class Ref(Field):
<x>:field.pxAdd</x> <x>:field.pxAdd</x>
<!-- The search button if field is queryable --> <!-- The search button if field is queryable -->
<input if="objs and field.queryable" type="button" class="button" <input if="objs and field.queryable" type="button" class="button"
style=":'background-image: url(%s/ui/buttonSearch.png)' % appUrl" style=":img('buttonSearch', bg=True)" value=":_('search_title')"
value=":_('search_title')"
onclick=":'window.location=%s' % \ onclick=":'window.location=%s' % \
q('%s/ui/search?className=%s&amp;ref=%s:%s' % \ q('%s/ui/search?className=%s&amp;ref=%s:%s' % \
(ztool.absolute_url(), linkedPortalType, contextObj.UID(), \ (ztool.absolute_url(), linkedPortalType, contextObj.UID(), \
@ -207,7 +195,7 @@ class Ref(Field):
<p class="discreet" if="not objs">:_('no_ref')</p> <p class="discreet" if="not objs">:_('no_ref')</p>
<table if="objs" class=":innerRef and 'innerAppyTable' or ''" <table if="objs" class=":innerRef and 'innerAppyTable' or ''"
width="100%"> width="100%">
<tr valign="bottom"> <tr valign="bottom">
<td> <td>
<!-- Show forward or backward reference(s) --> <!-- Show forward or backward reference(s) -->
@ -216,39 +204,32 @@ class Ref(Field):
var="columns=objs[0].getColumnsSpecifiers(field.shownInfo, dir)"> var="columns=objs[0].getColumnsSpecifiers(field.shownInfo, dir)">
<tr if="field.showHeaders"> <tr if="field.showHeaders">
<th for="column in columns" width=":column['width']" <th for="column in columns" width=":column['width']"
align="column['align']"> align="column['align']"
<x var="field=column['field']"> var2="field=column['field']">
<span>_(field.labelId)</span> <span>:_(field.labelId)</span>
<x>:field.pxSortIcons</x> <x>:field.pxSortIcons</x>
<x var="className=linkedPortalType">:contextObj.appy(\ <x var="className=linkedPortalType">:contextObj.appy(\
).pxShowDetails</x> ).pxShowDetails</x>
</x>
</th> </th>
</tr> </tr>
<x for="obj in objs"> <tr for="obj in objs" var2="odd=loop.obj.odd" valign="top"
<tr valign="top" var="odd=loop.obj.odd" class=":odd and 'even' or 'odd'">
class=":odd and 'even' or 'odd'"> <td for="column in columns"
<td for="column in columns" width=":column['width']" align=":column['align']"
width=":column['width']" align=":column['align']"> var2="field=column['field']">
<x var="field=column['field']"> <!-- The "title" field -->
<!-- The "title" field --> <x if="python: field.name == 'title'">
<x if="python: field.name == 'title'"> <x>:field.pxObjectTitle</x>
<x>:field.pxObjectTitle</x> <div if="obj.mayAct()">:field.pxObjectActions</div>
<div if="obj.mayAct()">:field.pxObjectActions</div> </x>
</x> <!-- Any other field -->
<!-- Any other field --> <x if="field.name != 'title'">
<x if="field.name != 'title'"> <x var="contextObj=obj; layoutType='cell'; innerRef=True"
<x var="contextObj=obj; if="obj.showField(field.name, \
layoutType='cell'; layoutType='result')">:field.pxView</x>
innerRef=True" </x>
if="obj.showField(field.name, layoutType='result')"> </td>
<!-- use-macro="app/ui/widgets/show/macros/field"/--> </tr>
</x>
</x>
</x>
</td>
</tr>
</x>
</table> </table>
</td> </td>
</tr> </tr>
@ -256,56 +237,49 @@ class Ref(Field):
<!-- Appy (bottom) navigation --> <!-- Appy (bottom) navigation -->
<x>:contextObj.appy().pxAppyNavigate</x> <x>:contextObj.appy().pxAppyNavigate</x>
</x> </x>
</div>''') </div>''')
pxView = pxCell = Px(''' pxView = pxCell = Px('''
<x var="x=req.set('fieldName', field.name)">:field.pxViewContent</x>''') <x var="x=req.set('fieldName', field.name)">:field.pxViewContent</x>''')
pxEdit = Px(''' pxEdit = Px('''
<x if="field.link" <select if="field.link"
var="requestValue=req.get(name, []); var2="requestValue=req.get(name, []);
inRequest=req.has_key(name); inRequest=req.has_key(name);
allObjects=field.getSelectableObjects(); allObjects=field.getSelectableObjects();
uids=[o.UID() for o in field.getLinkedObjects(contextObj).objects]; uids=[o.UID() for o in \
isBeingCreated=contextObj.isTemporary()"> field.getLinkedObjects(contextObj).objects];
<select name=":name" size="isMultiple and field.height or ''" isBeingCreated=contextObj.isTemporary()"
multiple="isMultiple and 'multiple' or ''"> name=":name" size="isMultiple and field.height or ''"
<option value="" if="not isMultiple">:_('choose_a_value')"></option> multiple="isMultiple and 'multiple' or ''">
<x for="refObj in allObjects"> <option value="" if="not isMultiple">:_('choose_a_value')"></option>
<option var="uid=refObj.o.UID()" <option for="refObj in allObjects" var2="uid=refObj.o.UID()"
selected=":inRequest and (uid in requestValue) or \ selected=":inRequest and (uid in requestValue) or \
(uid in uids)" (uid in uids)"
value=":uid">:field.getReferenceLabel(refObj)</option> value=":uid">:field.getReferenceLabel(refObj)</option>
</x> </select>''')
</select>
</x>''')
pxSearch = Px(''' pxSearch = Px('''<x>
<x> <label lfor=":widgetName">:_(field.labelId)"></label><br/>&nbsp;&nbsp;
<label lfor=":widgetName">:_(field.labelId)"></label><br/>&nbsp;&nbsp; <!-- The "and" / "or" radio buttons -->
<!-- The "and" / "or" radio buttons --> <x if="field.multiplicity[1] != 1"
<x var="operName='o_%s' % name; var2="operName='o_%s' % name;
orName='%s_or' % operName; orName='%s_or' % operName;
andName='%s_and' % operName" andName='%s_and' % operName">
if="field.multiplicity[1] != 1"> <input type="radio" name=":operName" id=":orName" checked="checked"
<input type="radio" name=":operName" id=":orName" value="or"/>
checked="checked" value="or"/> <label lfor=":orName">:_('search_or')"></label>
<label lfor=":orName">:_('search_or')"></label> <input type="radio" name=":operName" id=":andName" value="and"/>
<input type="radio" name=":operName" id=":andName" value="and"/> <label lfor=":andName">:_('search_and')"></label><br/>
<label lfor=":andName">:_('search_and')"></label><br/> </x>
</x> <!-- The list of values -->
<!-- The list of values --> <select name=":widgetName" size=":field.sheight" multiple="multiple">
<select name=":widgetName" size=":field.sheight" multiple="multiple"> <option for="v in ztool.getSearchValues(name, className)"
<x for="v in ztool.getSearchValues(name, className)"> var2="uid=v[0]; title=field.getReferenceLabel(v[1])" value=":uid"
<option var="uid=v[0]; title=":title">:ztool.truncateValue(title,field.swidth)"></option>
title=field.getReferenceLabel(v[1])" </select>
value=":uid" </x>''')
title=":title">:ztool.truncateValue(title, field.swidth)">
</option>
</x>
</select>
</x>''')
def __init__(self, klass=None, attribute=None, validator=None, def __init__(self, klass=None, attribute=None, validator=None,
multiplicity=(0,1), default=None, add=False, addConfirm=False, multiplicity=(0,1), default=None, add=False, addConfirm=False,

View file

@ -108,29 +108,28 @@ class String(Field):
isSelect=field.isSelect; isSelect=field.isSelect;
isMaster=field.slaves; isMaster=field.slaves;
isOneLine=fmt in (0,3,4)"> isOneLine=fmt in (0,3,4)">
<x if="isSelect"> <select if="isSelect"
<select var="possibleValues=field.getPossibleValues(contextObj, \ var2="possibleValues=field.getPossibleValues(contextObj, \
withTranslations=True, withBlankValue=True)" withTranslations=True, withBlankValue=True)"
name=":name" id=":name" class=":masterCss" name=":name" id=":name" class=":masterCss"
multiple=":isMultiple and 'multiple' or ''" multiple=":isMultiple and 'multiple' or ''"
onchange=":isMaster and 'updateSlaves(this)' or ''" onchange=":isMaster and 'updateSlaves(this)' or ''"
size=":isMultiple and field.height or 1"> size=":isMultiple and field.height or 1">
<option for="val in possibleValues" value=":val[0]" <option for="val in possibleValues" value=":val[0]"
selected=":field.isSelected(contextObj, val[0], rawValue)" selected=":field.isSelected(contextObj, val[0], rawValue)"
title=":val[1]">:ztool.truncateValue(val[1], field.width)"> title=":val[1]">:ztool.truncateValue(val[1], field.width)">
</option> </option>
</select> </select>
</x>
<x if="isOneLine and not isSelect"> <x if="isOneLine and not isSelect">
<input id=":name" name=":name" size=":field.width" <input id=":name" name=":name" size=":field.width"
maxlength=":field.maxChars" maxlength=":field.maxChars"
value=":inRequest and requestValue or value" value=":inRequest and requestValue or value"
style=":'text-transform:%s' % field.transform" style=":'text-transform:%s' % field.transform"
type=":(fmt == 3) and 'password' or 'text'"/> type=":(fmt == 3) and 'password' or 'text'"/>
<!-- Display a captcha if required --> <!-- Display a captcha if required -->
<span if="fmt == 4">:_('captcha_text', \ <span if="fmt == 4">:_('captcha_text', \
mapping=field.getCaptchaChallenge(req.SESSION)) mapping=field.getCaptchaChallenge(req.SESSION))
</span> </span>
</x> </x>
<x if="fmt in (1,2)"> <x if="fmt in (1,2)">
<textarea id=":name" name=":name" cols=":field.width" <textarea id=":name" name=":name" cols=":field.width"
@ -149,40 +148,37 @@ class String(Field):
<x if="not multipleValues">:field.pxView</x> <x if="not multipleValues">:field.pxView</x>
</x>''') </x>''')
pxSearch = Px(''' pxSearch = Px('''<x>
<x> <label lfor="widgetName">:_(field.labelId)"></label><br/>&nbsp;&nbsp;
<label lfor="widgetName">:_(field.labelId)"></label><br/>&nbsp;&nbsp; <!-- Show a simple search field for most String fields -->
<!-- Show a simple search field for most String fields --> <input if="not field.isSelect" type="text" maxlength=":field.maxChars"
<x if="not field.isSelect"> size=":field.swidth" value=":field.sdefault"
<input type="text" maxlength=":field.maxChars" size=":field.swidth" name=":'%s*string-%s' % (widgetName, field.transform)"
name=":'%s*string-%s' % (widgetName, field.transform)" style=":'text-transform:%s' % field.transform"/>
style=":'text-transform:%s' % field.transform" <!-- Show a multi-selection box for fields whose validator defines a list
value=":field.sdefault"/> of values, with a "AND/OR" checkbox. -->
<x if="field.isSelect">
<!-- The "and" / "or" radio buttons -->
<x if="field.multiplicity[1] != 1"
var2="operName='o_%s' % name;
orName='%s_or' % operName;
andName='%s_and' % operName">
<input type="radio" name=":operName" id=":orName" checked="checked"
value="or"/>
<label lfor=":orName">:_('search_or')</label>
<input type="radio" name=":operName" id=":andName" value="and"/>
<label lfor=":andName">:_('search_and')"></label><br/>
</x> </x>
<!-- Show a multi-selection box for fields whose validator defines a list <!-- The list of values -->
of values, with a "AND/OR" checkbox. --> <select var="preSelected=field.sdefault"
<x if="field.isSelect"> name=":widgetName" size=":field.sheight" multiple="multiple">
<!-- The "and" / "or" radio buttons --> <option for="v in field.getPossibleValues(ztool, withTranslations=True,\
<x var="operName='o_%s' % name;
orName='%s_or' % operName;
andName='%s_and' % operName"
if="field.multiplicity[1] != 1">
<input type="radio" name=":operName" id=":orName" checked="checked"
value="or"/>
<label lfor=":orName">:_('search_or')</label>
<input type="radio" name=":operName" id=":andName" value="and"/>
<label lfor=":andName">:_('search_and')"></label><br/>
</x>
<!-- The list of values -->
<select var="preSelected=field.sdefault"
name=":widgetName" size=":field.sheight" multiple="multiple">
<option for="v in field.getPossibleValues(ztool, withTranslations=True,\
withBlankValue=False, className=className)" withBlankValue=False, className=className)"
selected=":v[0] in preSelected" value=":v[0]" selected=":v[0] in preSelected" value=":v[0]"
title=":v[1]">ztool.truncateValue(v[1], field.swidth)</option> title=":v[1]">ztool.truncateValue(v[1], field.swidth)</option>
</select> </select>
</x><br/> </x><br/>
</x>''') </x>''')
# Some predefined functions that may also be used as validators # Some predefined functions that may also be used as validators
@staticmethod @staticmethod

View file

@ -105,6 +105,17 @@ class ToolMixin(BaseMixin):
podField = self.getAppyType(name, className=obj.meta_type) podField = self.getAppyType(name, className=obj.meta_type)
return podField.getToolInfo(obj.appy()) return podField.getToolInfo(obj.appy())
def getImageUrl(self, name, bg=False):
'''Gets the full URL of an image named p_name. If p_bg is False, the URL
is meant to be used as content for an img's "src" attribute. If p_bg
is True, the URL is meant to be used in a "style" attribute for
defining the background image of the current tag.'''
# If not extension is found in the image p_name, suppose it is a png.
if '.' not in name: name += '.png'
url = '%s/ui/%s' % (self.getPhysicalRoot(),absolute_url(), name)
if not bg: return url
return 'background-image: url(%s)' % url
def generateDocument(self): def generateDocument(self):
'''Generates the document from field-related info. UID of object that '''Generates the document from field-related info. UID of object that
is the template target is given in the request.''' is the template target is given in the request.'''

View file

@ -64,38 +64,34 @@ class GroupDescr(Descr):
sharing the same appy.gen.Group instance, that some logged user can sharing the same appy.gen.Group instance, that some logged user can
see.''' see.'''
# PX that renders a group of fields # PX that renders a group of fields
pxGroupedFields = Px('''<p>pxGroupedFields</p>''') pxView = Px('''<p>pxGroupedFields</p>''')
# PX that renders a group of fields # PX that renders a group of searches
pxGroupedSearches = Px(''' pxViewSearches = Px('''
<x var="expanded=req.get(widget['labelId'], 'collapsed') == 'expanded'"> <x var="expanded=req.get(field.labelId, 'collapsed') == 'expanded'">
<!-- Group name, prefixed by the expand/collapse icon --> <!-- Group name, prefixed by the expand/collapse icon -->
<div class="portletGroup"> <div class="portletGroup">
<img style="cursor:pointer; margin-right: 3px" align=":dleft" <img style="cursor:pointer; margin-right: 3px" align=":dleft"
id=":'%s_img' % widget['labelId']" id=":'%s_img' % field.labelId"
src=":expanded and 'ui/collapse.gif' or 'ui/expand.gif'" src=":expanded and img('collapse.gif') or img('expand.gif')"
onclick=":'toggleCookie(&quot;%s&quot;)' % widget['labelId']"/> onclick=":'toggleCookie(%s)' % q(field.labelId)"/>
<x if="not widget['translated']">:_(widget['labelId'])</x> <x if="not field.translated">:_(field.labelId)</x>
<x if="widget['translated']">:widget['translated']</x> <x if="field.translated">:field.translated</x>
</div> </div>
<!-- Group content --> <!-- Group content -->
<div var="display=expanded and 'display:block' or 'display:none'" <div var="display=expanded and 'display:block' or 'display:none'"
id=":widget['labelId']" style=":'padding-left: 10px; %s' % display"> id=":field.labelId" style=":'padding-left: 10px; %s' % display">
<x for="searches in widget['widgets']"> <x for="searches in field.widgets">
<x for="searchElem in searches"> <x for="elem in searches">
<!-- An inner group within this group --> <!-- An inner group within this group -->
<x if="searchElem['type'] == 'group'"> <x if="elem['type'] == 'group'"
<x var="widget=searchElem">:widget['px']</x> var2="field=elem">:field.pxViewSearches</x>
</x>
<!-- A search --> <!-- A search -->
<x if="searchElem['type'] != 'group'"> <x if="elem['type'] != 'group'" var2="search=elem">:search.pxView</x>
<x var="search=searchElem">:search['px']</x>
</x>
</x> </x>
</x> </x>
</div> </div>
</x> </x>''')
''')
def __init__(self, group, page, metaType, forSearch=False): def __init__(self, group, page, metaType, forSearch=False):
self.type = 'group' self.type = 'group'
@ -125,7 +121,7 @@ class GroupDescr(Descr):
# they will be rendered as a table. # they will be rendered as a table.
self.widgets = [[]] self.widgets = [[]]
# PX to user for rendering this group. # PX to user for rendering this group.
self.px = forSearch and self.pxGroupedSearches or self.pxGroupedFields self.px = forSearch and self.pxViewSearches or self.pxView
@staticmethod @staticmethod
def addWidget(groupDict, newWidget): def addWidget(groupDict, newWidget):
@ -178,20 +174,19 @@ class PhaseDescr(Descr):
editable=mayEdit and phase['pagesInfo'][aPage]['showOnEdit']"> editable=mayEdit and phase['pagesInfo'][aPage]['showOnEdit']">
<a if="editable and not locked" <a if="editable and not locked"
href="contextObj.getUrl(mode='edit', page=aPage)"> href="contextObj.getUrl(mode='edit', page=aPage)">
<img src=":'%s/ui/edit.png' % appUrl" title=":_('object_edit')"/> <img src=":img('edit')" title=":_('object_edit')"/></a>
</a>
<a if="editable and locked"> <a if="editable and locked">
<img style="cursor: help" <img style="cursor: help"
var="lockDate=tool.formatDate(locked[1]); var="lockDate=tool.formatDate(locked[1]);
lockMap={'user':ztool.getUserName(locked[0]), \ lockMap={'user':ztool.getUserName(locked[0]), \
'date':lockDate}; 'date':lockDate};
lockMsg=_('page_locked', mapping=lockMap)" lockMsg=_('page_locked', mapping=lockMap)"
src=":'%s/ui/locked.png' % appUrl" title=":lockMsg"/></a> src=":img('locked')" title=":lockMsg"/></a>
<a if="editable and locked and user.has_role('Manager')"> <a if="editable and locked and user.has_role('Manager')">
<img style="cursor: pointer" title=":_('page_unlock')" <img style="cursor: pointer" title=":_('page_unlock')"
src=":'%s/ui/unlock.png' % appUrl" src=":img('unlock')"
onclick=":'onUnlockPage(&quot;%s&quot;,&quot;%s&quot;)' % \ onclick=":'onUnlockPage(%s,%s)' % \
(contextObj.UID(), aPage)"/></a> (q(contextObj.UID()), q(aPage))"/></a>
</x> </x>
</div> </div>
<!-- Next lines: links --> <!-- Next lines: links -->
@ -202,8 +197,7 @@ class PhaseDescr(Descr):
</x> </x>
</x> </x>
</td> </td>
</tr> </tr>''')
''')
def __init__(self, name, obj): def __init__(self, name, obj):
self.name = name self.name = name
@ -266,14 +260,13 @@ class PhaseDescr(Descr):
class SearchDescr(Descr): class SearchDescr(Descr):
'''Describes a Search.''' '''Describes a Search.'''
# PX for rendering a search. # PX for rendering a search.
pxSearch = Px(''' pxView = Px('''
<div class="portletSearch"> <div class="portletSearch">
<a href=":'%s?className=%s&amp;search=%s' % \ <a href=":'%s?className=%s&amp;search=%s' % \
(queryUrl, rootClass, search['name'])" (queryUrl, rootClass, search['name'])"
class=":search['name'] == currentSearch and 'portletCurrent' or ''" class=":search['name'] == currentSearch and 'portletCurrent' or ''"
title=":search['translatedDescr']">:search['translated']</a> title=":search['translatedDescr']">:search['translated']</a>
</div> </div>''')
''')
def __init__(self, search, className, tool): def __init__(self, search, className, tool):
self.search = search self.search = search

View file

@ -29,75 +29,63 @@ class ToolWrapper(AbstractWrapper):
</table>''', template=AbstractWrapper.pxTemplate, hook='content') </table>''', template=AbstractWrapper.pxTemplate, hook='content')
# Show on query list or grid, the field content for a given object. # Show on query list or grid, the field content for a given object.
pxQueryField = Px(''' pxQueryField = Px('''<x>
<x><!-- Title --> <!-- Title -->
<x if="widget['name'] == 'title'"> <x if="field.name == 'title'"
<x var="navInfo='search.%s.%s.%d.%d' % (className, searchName, \ var2="navInfo='search.%s.%s.%d.%d' % \
startNumber+currentNumber, \ (className, searchName, startNumber+currentNumber, totalNumber);
totalNumber); cssClass=obj.getCssFor('title')">
cssClass=obj.getCssFor('title')"> <x>::obj.getSupTitle(navInfo)</x>
<x>::obj.getSupTitle(navInfo)</x> <a href=":obj.getUrl(nav=navInfo, page=obj.getDefaultViewPage())"
<a href=":obj.getUrl(nav=navInfo, page=obj.getDefaultViewPage())" if="enableLinks" class=":cssClass">:obj.Title()</a><span
if="enableLinks" class=":cssClass">:obj.Title()</a><span if="not enableLinks" class=":cssClass">:obj.Title()</span><span
if="not enableLinks" class=":cssClass">:obj.Title()</span><span style=":showSubTitles and 'display:inline' or 'display:none'"
style=":showSubTitles and 'display:inline' or 'display:none'" name="subTitle">::obj.getSubTitle()</span>
name="subTitle">::obj.getSubTitle()</span>
<!-- Actions: edit, delete --> <!-- Actions: edit, delete -->
<div if="obj.mayAct()"> <div if="obj.mayAct()">
<a var="navInfo='search.%s.%s.%d.%d' % (className, searchName, \ <a if="obj.mayEdit()"
loop.obj.nb+1+startNumber, \ var2="navInfo='search.%s.%s.%d.%d' % \
totalNumber)" (className, searchName, loop.obj.nb+1+startNumber, totalNumber)"
if="obj.mayEdit()" href=":obj.getUrl(mode='edit', page=obj.getDefaultEditPage(), \
href=":obj.getUrl(mode='edit', page=obj.getDefaultEditPage(), \ nav=navInfo)">
nav=navInfo)"> <img src=":img('edit')" title=":_('object_edit')"/></a>
<img src=":'%s/ui/edit.png' % appUrl" <img if="obj.mayDelete()" style="cursor:pointer" src=":img('delete')"
title=":_('object_edit')"/></a><img title=":_('object_delete')"
if="obj.mayDelete()" style="cursor:pointer" onClick="'onDeleteObject(%s)' % q(obj.UID())"/>
src=":'%s/ui/delete.png' % appUrl" </div>
title=":_('object_delete')" </x>
onClick="'onDeleteObject(&quot;%s&quot;)' % obj.UID()"/> <!-- Any other field -->
</div> <x if="field.name != 'title'">
</x> <x var="contextObj=obj; layoutType='cell'; innerRef=True"
</x> if="contextObj.showField(field.name, 'result')">field.pxView</x>
<!-- Any other field --> </x>
<x if="widget['name'] != 'title'"> </x>''')
<x var="contextObj=obj;
layoutType='cell';
innerRef=True"
if="contextObj.showField(widget['name'], 'result')">
<!-- metal:f use-macro="context/ui/widgets/show/macros/field"/-->
</x>
</x>
</x>''')
# Show query results as a list. # Show query results as a list.
pxQueryResultList = Px(''' pxQueryResultList = Px('''
<table class="list" width="100%"> <table class="list" width="100%">
<!-- Headers, with filters and sort arrows --> <!-- Headers, with filters and sort arrows -->
<tr if="showHeaders"> <tr if="showHeaders">
<x for="column in columns"> <th for="column in columns"
<th var="widget=column['field']; var2="widget=column['field'];
sortable=ztool.isSortable(widget['name'], className, 'search'); sortable=ztool.isSortable(field.name, className, 'search');
filterable=widget.get('filterable', None)" filterable=widget.filterable"
width=":column['width']" align=":column['align']"> width=":column['width']" align=":column['align']">
<x>::ztool.truncateText(_(widget['labelId']))</x> <x>::ztool.truncateText(_(field.labelId))</x>
<x>:self.pxSortAndFilter</x><x>:self.pxShowDetails</x> <x>:self.pxSortAndFilter</x><x>:self.pxShowDetails</x>
</th> </th>
</x>
</tr> </tr>
<!-- Results --> <!-- Results -->
<x for="obj in objs"> <tr for="obj in objs"
<tr var="odd=loop.obj.odd; currentNumber=currentNumber + 1" var2="odd=loop.obj.odd; currentNumber=currentNumber + 1"
id="query_row" valign="top" class=":odd and 'even' or 'odd'"> id="query_row" valign="top" class=":odd and 'even' or 'odd'">
<x for="column in columns"> <td for="column in columns"
<td var="widget=column['field']" id=":'field_%s' % widget['name']" var2="widget=column['field']" id=":'field_%s' % field.name"
width=":column['width']" width=":column['width']"
align=":column['align']">:self.pxQueryField</td> align=":column['align']">:self.pxQueryField</td>
</x> </tr>
</tr>
</x>
</table>''') </table>''')
# Show query results as a grid. # Show query results as a grid.
@ -110,9 +98,8 @@ class ToolWrapper(AbstractWrapper):
<td for="obj in row" width=":'%d%%' % (100/cols)" align="center" <td for="obj in row" width=":'%d%%' % (100/cols)" align="center"
style="padding-top: 25px"> style="padding-top: 25px">
<x var="currentNumber=currentNumber + 1" <x var="currentNumber=currentNumber + 1"
for="column in columns"> for="column in columns"
<x var="widget = column['field']">:self.pxQueryField</x> var2="widget = column['field']">:self.pxQueryField</x>
</x>
</td> </td>
</tr> </tr>
</table>''') </table>''')
@ -144,9 +131,9 @@ class ToolWrapper(AbstractWrapper):
totalNumber=queryResult['totalNumber']; totalNumber=queryResult['totalNumber'];
batchSize=queryResult['batchSize']; batchSize=queryResult['batchSize'];
ajaxHookId='queryResult'; ajaxHookId='queryResult';
navBaseCall='askQueryResult(&quot;%s&quot;,&quot;%s&quot;, \ navBaseCall='askQueryResult(%s,%s,%s,%s,**v**)' % \
&quot;%s&quot;, &quot;%s&quot;, **v**)' % (ajaxHookId, \ (q(ajaxHookId), q(ztool.absolute_url()), q(className), \
ztool.absolute_url(), className, searchName); q(searchName));
newSearchUrl='%s/ui/search?className=%s%s' % \ newSearchUrl='%s/ui/search?className=%s%s' % \
(ztool.absolute_url(), className, refUrlPart); (ztool.absolute_url(), className, refUrlPart);
showSubTitles=req.get('showSubTitles', 'true') == 'true'; showSubTitles=req.get('showSubTitles', 'true') == 'true';
@ -158,9 +145,7 @@ class ToolWrapper(AbstractWrapper):
layoutType='view'" layoutType='view'"
if="objs and widgets" align=":dright"> if="objs and widgets" align=":dright">
<tr> <tr>
<td var="contextObj=objs[0]" for="widget in widgets"> <td var="contextObj=objs[0]" for="field in widgets">:field.pxView</td>
<!--use-macro="context/ui/widgets/show/macros/field"/>&nbsp;&nbsp;&nbsp;-->
</td>
</tr> </tr>
</table> </table>
@ -238,30 +223,25 @@ class ToolWrapper(AbstractWrapper):
<table width="100%"> <table width="100%">
<tr for="searchRow in ztool.getGroupedSearchFields(searchInfo)" <tr for="searchRow in ztool.getGroupedSearchFields(searchInfo)"
valign="top"> valign="top">
<x for="widget in searchRow"> <td for="field in searchRow"
<td var="scolspan=widget and widget['scolspan'] or 1" var2="scolspan=field and field.scolspan or 1"
colspan=":scolspan" colspan=":scolspan"
width=":'%d%%' % ((100/searchInfo['nbOfColumns'])*scolspan)"> width=":'%d%%' % ((100/searchInfo['nbOfColumns'])*scolspan)">
<x if="widget"> <x if="field"
<x var="name=widget['name']; var2="name=field.name;
widgetName='w_%s' % name; widgetName='w_%s' % name">field.pxSearch</x>
macroPage=widget['type'].lower()"> <br class="discreet"/>
<!--metal:call use-macro="python: getattr(appFolder.ui.widgets, macroPage).macros['search']"/--> </td>
</x>
</x><br class="discreet"/>
</td>
</x>
</tr> </tr>
</table> </table>
<!-- Submit button --> <!-- Submit button -->
<p align=":dright"><br/> <p align=":dright"><br/>
<input type="submit" class="button" value=":_('search_button')" <input type="submit" class="button" value=":_('search_button')"
style=":'background-image: url(%s/ui/buttonSearch.png)'%appUrl"/> style=":img('buttonSearch', bg=True)"/>
</p> </p>
</form> </form>
</x> </x>''', template=AbstractWrapper.pxTemplate, hook='content')
''', template=AbstractWrapper.pxTemplate, hook='content')
pxImport = Px(''' pxImport = Px('''
<x var="className=req['className']; <x var="className=req['className'];
@ -325,37 +305,35 @@ class ToolWrapper(AbstractWrapper):
<table class="list" width="100%"> <table class="list" width="100%">
<tr> <tr>
<th for="columnHeader in importElems[0]"> <th for="columnHeader in importElems[0]">
<img if="loop.columnHeader.nb == 0" src=":'%s/ui/eye.png' % appUrl" <img if="loop.columnHeader.nb == 0" src=":img('eye')"
title="_('import_show_hide')" style="cursor:pointer" title="_('import_show_hide')" style="cursor:pointer"
onClick="toggleViewableElements()" align=":dleft" /> onClick="toggleViewableElements()" align=":dleft" />
<x>:columnHeader</x> <x>:columnHeader</x>
</th> </th>
<th></th> <th></th>
<th width="20px"><img src=":'%s/ui/select_elems.png' % $appUrl" <th width="20px"><img src=":img('select_elems')" style="cursor:pointer"
title=":_('select_delesect')" onClick="toggleCheckboxes()" title=":_('select_delesect')" onClick="toggleCheckboxes()"/></th>
style="cursor:pointer"/></th>
</tr> </tr>
<x for="row in importElems[1]"> <tr for="row in importElems[1]"
<tr var="alreadyImported=ztool.isAlreadyImported(className, row[0]); var2="alreadyImported=ztool.isAlreadyImported(className, row[0]);
allAreImported=allAreImported and alreadyImported; allAreImported=allAreImported and alreadyImported;
odd=loop.row.odd" odd=loop.row.odd"
id=":alreadyImported and 'importedElem' or 'notImportedElem'" id=":alreadyImported and 'importedElem' or 'notImportedElem'"
name=":alreadyImported and 'importedElem' or 'notImportedElem'" name=":alreadyImported and 'importedElem' or 'notImportedElem'"
style=":alreadyImported and 'display:none' or 'display:table-row'" style=":alreadyImported and 'display:none' or 'display:table-row'"
class=":odd and 'even' or 'odd'"> class=":odd and 'even' or 'odd'">
<td for="elem in row[1:]">:elem</td> <td for="elem in row[1:]">:elem</td>
<td> <td>
<input type="button" if="not alreadyImported" <input type="button" if="not alreadyImported"
onClick=":'importSingleElement(&quot;%s&quot;)' % row[0]" onClick=":'importSingleElement(%s)' % q(row[0])"
value=":_('query_import')"/> value=":_('query_import')"/>
<x if="alreadyImported">:_('import_already')</x> <x if="alreadyImported">:_('import_already')</x>
</td> </td>
<td align="center"> <td align="center">
<input if="not alreadyImported" type="checkbox" checked="checked" <input if="not alreadyImported" type="checkbox" checked="checked"
id="cbElem" name="cbElem" value="row[0]" /> id="cbElem" name="cbElem" value="row[0]"/>
</td> </td>
</tr> </tr>
</x>
<tr if="not importElems[1] or allAreImported"> <tr if="not importElems[1] or allAreImported">
<td colspan="15">:_('query_no_result')</td></tr> <td colspan="15">:_('query_no_result')</td></tr>
</table> </table>

View file

@ -32,35 +32,30 @@ class AbstractWrapper(object):
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Icon for hiding/showing details below the title. # Icon for hiding/showing details below the title.
pxShowDetails = Px(''' pxShowDetails = Px('''
<x if="ztool.subTitleIsUsed(className)"> <img if="ztool.subTitleIsUsed(className) and (field.name == 'title')"
<img if="widget['name'] == 'title'" style="cursor:pointer" style="cursor:pointer" src=":img('toggleDetails')"
src=":'%s/ui/toggleDetails.png'%appUrl" onClick="toggleSubTitles()"/> onClick="toggleSubTitles()"/>''')
</x>''')
# Displays up/down arrows in a table header column for sorting a given # Displays up/down arrows in a table header column for sorting a given
# column. Requires variables "sortable", 'filterable' and 'fieldName'. # column. Requires variables "sortable", 'filterable' and 'field'.
pxSortAndFilter = Px(''' pxSortAndFilter = Px('''<x>
<x var="fieldName=widget['name']"> <x if="sortable">
<x if="sortable"> <img if="(sortKey != field.name) or (sortOrder == 'desc')"
<img if="(sortKey != fieldName) or (sortOrder == 'desc')" onclick=":navBaseCall.replace('**v**', '0,%s,%s,%s' % \
onclick=":navBaseCall.replace('**v**', '0,&quot;%s&quot;, \ (q(field.name), q('asc'), q(filterKey)))"
&quot;asc&quot;, &quot;%s&quot;' % (fieldName,filterKey))" src=":img('sortDown.gif')" style="cursor:pointer"/>
src=":'%s/ui/sortDown.gif' % appUrl" style="cursor:pointer"/> <img if="(sortKey != field.name) or (sortOrder == 'asc')"
<img if="(sortKey != fieldName) or (sortOrder == 'asc')" onClick=":navBaseCall.replace('**v**', '0,%s,%s,%s' % \
onClick=":navBaseCall.replace('**v**', '0,&quot;%s&quot;, \ (q(field.name), q('desc'), q(filterKey)))"
&quot;desc&quot;, &quot;%s&quot;' % (fieldName,filterKey))" src=":img('sortUp.gif')" style="cursor:pointer"/>
src=":'%s/ui/sortUp.gif' % appUrl" style="cursor:pointer"/> </x>
</x> <x if="filterable">
<x if="filterable"> <input type="text" size="7" id=":'%s_%s' % (ajaxHookId, field.name)"
<input type="text" size="7" value=":filterKey == field.name and filterValue or ''"/>
id=":'%s_%s' % (ajaxHookId, fieldName)" <img onClick=":navBaseCall.replace('**v**', '0, %s,%s,%s' % \
value=":filterKey == fieldName and filterValue or ''"/> (q(sortKey), q(sortOrder), q(field.name)))"
<img onClick=":navBaseCall.replace('**v**', '0, &quot;%s&quot;, \ src=":img('funnel')" style="cursor:pointer"/>
&quot;%s&quot;, &quot;%s&quot;' % \ </x></x>''')
(sortKey, sortOrder, fieldName))"
src=":'%s/ui/funnel.png' % appUrl" style="cursor:pointer"/>
</x>
</x>''')
# Buttons for navigating among a list of elements: next,back,first,last... # Buttons for navigating among a list of elements: next,back,first,last...
pxAppyNavigate = Px(''' pxAppyNavigate = Px('''
@ -68,33 +63,31 @@ class AbstractWrapper(object):
<table class="listNavigate" <table class="listNavigate"
var="mustSortAndFilter=ajaxHookId == 'queryResult'; var="mustSortAndFilter=ajaxHookId == 'queryResult';
sortAndFilter=mustSortAndFilter and \ sortAndFilter=mustSortAndFilter and \
',&quot;%s&quot;, &quot;%s&quot;, &quot;%s&quot;' % \ ',%s,%s,%s' % (q(sortKey),q(sortOrder),q(filterKey)) or ''">
(sortKey, sortOrder, filterKey) or ''">
<tr valign="middle"> <tr valign="middle">
<!-- Go to the first page --> <!-- Go to the first page -->
<td if="(startNumber != 0) and (startNumber != batchSize)"><img <td if="(startNumber != 0) and (startNumber != batchSize)"><img
style="cursor:pointer" src=":'%s/ui/arrowLeftDouble.png' % appUrl" style="cursor:pointer" src=":img('arrowLeftDouble')"
title=":_('goto_first')" title=":_('goto_first')"
onClick=":navBaseCall.replace('**v**', '0'+sortAndFilter)"/></td> onClick=":navBaseCall.replace('**v**', '0'+sortAndFilter)"/></td>
<!-- Go to the previous page --> <!-- Go to the previous page -->
<td var="sNumber=startNumber - batchSize" if="startNumber != 0"><img <td var="sNumber=startNumber - batchSize" if="startNumber != 0"><img
style="cursor:pointer" src=":'%s/ui/arrowLeftSimple.png' % appUrl" style="cursor:pointer" src=":img('arrowLeftSimple')"
title=":_('goto_previous')" title=":_('goto_previous')"
onClick="navBaseCall.replace('**v**', \ onClick="navBaseCall.replace('**v**', \
str(sNumber)+sortAndFilter)"/></td> str(sNumber)+sortAndFilter)"/></td>
<!-- Explain which elements are currently shown --> <!-- Explain which elements are currently shown -->
<td class="discreet">&nbsp; <td class="discreet">&nbsp;
<x>:startNumber + 1</x><img src=":'%s/ui/to.png' % appUrl"/> <x>:startNumber + 1</x><img src=":img('to')"/>
<x>:startNumber + len(objs)</x>&nbsp;<b>//</b> <x>:startNumber + len(objs)</x>&nbsp;<b>//</b>
<x>:totalNumber</x>&nbsp;&nbsp;</td> <x>:totalNumber</x>&nbsp;&nbsp;</td>
<!-- Go to the next page --> <!-- Go to the next page -->
<td var="sNumber=startNumber + batchSize" <td var="sNumber=startNumber + batchSize"
if="sNumber &lt; totalNumber"><img style="cursor:pointer" if="sNumber &lt; totalNumber"><img style="cursor:pointer"
src=":'%s/ui/arrowRightSimple.png' % appUrl" src=":img('arrowRightSimple')" title=":_('goto_next')"
title=":_('goto_next')"
onClick=":navBaseCall.replace('**v**', \ onClick=":navBaseCall.replace('**v**', \
str(sNumber)+sortAndFilter)"/></td> str(sNumber)+sortAndFilter)"/></td>
@ -106,8 +99,7 @@ class AbstractWrapper(object):
sNumber= nbOfCountedPages * batchSize" sNumber= nbOfCountedPages * batchSize"
if="(startNumber != sNumber) and \ if="(startNumber != sNumber) and \
(startNumber != sNumber-batchSize)"><img style="cursor:pointer" (startNumber != sNumber-batchSize)"><img style="cursor:pointer"
src=":'%s/ui/arrowRightDouble.png' % appUrl" src=":img('arrowRightDouble')" title=":_('goto_last')"
title=":_('goto_last')"
onClick="navBaseCall.replace('**v**', \ onClick="navBaseCall.replace('**v**', \
str(sNumber)+sortAndFilter)"/></td> str(sNumber)+sortAndFilter)"/></td>
</tr> </tr>
@ -117,8 +109,8 @@ class AbstractWrapper(object):
# Buttons for going to next/previous elements if this one is among bunch of # Buttons for going to next/previous elements if this one is among bunch of
# referenced or searched objects. currentNumber starts with 1. # referenced or searched objects. currentNumber starts with 1.
pxObjectNavigate = Px(''' pxObjectNavigate = Px('''
<x if="req.get('nav', None)"> <div if="req.get('nav', None)"
<div var="navInfo=ztool.getNavigationInfo(); var2="navInfo=ztool.getNavigationInfo();
currentNumber=navInfo['currentNumber']; currentNumber=navInfo['currentNumber'];
totalNumber=navInfo['totalNumber']; totalNumber=navInfo['totalNumber'];
firstUrl=navInfo['firstUrl']; firstUrl=navInfo['firstUrl'];
@ -133,15 +125,15 @@ class AbstractWrapper(object):
var="gotoSource=_('goto_source'); var="gotoSource=_('goto_source');
goBack=backText and ('%s - %s' % (backText, gotoSource)) \ goBack=backText and ('%s - %s' % (backText, gotoSource)) \
or gotoSource" or gotoSource"
src=":'%s/ui/gotoSource.png' % appUrl" title=":goBack"/></a> src=":img('gotoSource')" title=":goBack"/></a>
<!-- Go to the first page --> <!-- Go to the first page -->
<a if="firstUrl" href=":firstUrl"><img title=":_('goto_first')" <a if="firstUrl" href=":firstUrl"><img title=":_('goto_first')"
src=":'%s/ui/arrowLeftDouble.png' % appUrl"/></a> src=":img('arrowLeftDouble')"/></a>
<!-- Go to the previous page --> <!-- Go to the previous page -->
<a if="previousUrl" href=":previousUrl"><img title=":_('goto_previous')" <a if="previousUrl" href=":previousUrl"><img title=":_('goto_previous')"
src=":'%s/ui/arrowLeftSimple.png' % appUrl"/></a> src=":img('arrowLeftSimple')"/></a>
<!-- Explain which element is currently shown --> <!-- Explain which element is currently shown -->
<span class="discreet">&nbsp; <span class="discreet">&nbsp;
@ -151,29 +143,28 @@ class AbstractWrapper(object):
<!-- Go to the next page --> <!-- Go to the next page -->
<a if="nextUrl" href=":nextUrl"><img title=":_('goto_next')" <a if="nextUrl" href=":nextUrl"><img title=":_('goto_next')"
src=":'%s/ui/arrowRightSimple.png' % appUrl"/></a> src=":img('arrowRightSimple')"/></a>
<!-- Go to the last page --> <!-- Go to the last page -->
<a if="lastUrl" href=":lastUrl"><img title=":_('goto_last')" <a if="lastUrl" href=":lastUrl"><img title=":_('goto_last')"
src=":'%s/ui/arrowRightDouble.png' % appUrl"/></a> src=":img('arrowRightDouble')"/></a>
</div> </div>''')
</x>''')
pxNavigationStrip = Px(''' pxNavigationStrip = Px('''
<table width="100%" class="navigate"> <table width="100%" class="navigate">
<tr> <tr>
<!-- Breadcrumb -->
<td var="breadcrumb=contextObj.getBreadCrumb()" class="breadcrumb"> <td var="breadcrumb=contextObj.getBreadCrumb()" class="breadcrumb">
<x for="bc in breadcrumb"> <x for="bc in breadcrumb" var2="nb=loop.bc.nb">
<x var="nb=loop.bc.nb"> <img if="nb != 0" src=":img('to')"/>
<img if="nb != 0" src=":'%s/ui/to.png' % appUrl"/> <!-- Display only the title of the current object -->
<!-- Display only the title of the current object --> <span if="nb == len(breadcrumb)-1">:bc['title']</span>
<span if="nb == len(breadcrumb)-1">:bc['title']</span> <!-- Display a link for parent objects -->
<!-- Display a link for parent objects --> <a if="nb != len(breadcrumb)-1" href=":bc['url']">:bc['title']</a>
<a if="nb != len(breadcrumb)-1" href=":bc['url']">:bc['title']</a>
</x>
</x> </x>
</td> </td>
<td align="right">:self.pxObjectNavigate</td> <!-- Object navigation -->
<td align=":dright">:self.pxObjectNavigate</td>
</tr> </tr>
</table>''') </table>''')
@ -181,53 +172,52 @@ class AbstractWrapper(object):
# PXs for graphical elements shown on every page # PXs for graphical elements shown on every page
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Global elements included in every page. # Global elements included in every page.
pxPagePrologue = Px(''' pxPagePrologue = Px('''<x>
<div> <!-- Include type-specific CSS and JS. -->
<!-- Include type-specific CSS and JS. --> <x if="cssJs">
<x if="cssJs"> <link for="cssFile in cssJs['css']" rel="stylesheet" type="text/css"
<link for="cssFile in cssJs['css']" rel="stylesheet" type="text/css" href=":'%s/ui/%s' % (appUrl, cssFile)"/>
href=":'%s/ui/%s' % (appUrl, cssFile)"/> <script for="jsFile in cssJs['js']" type="text/javascript"
<script for="jsFile in cssJs['js']" type="text/javascript" src=":'%s/ui/%s' % (appUrl, jsFile)"></script></x>
src=":'%s/ui/%s' % (appUrl, jsFile)"></script></x>
<!-- Javascript messages --> <!-- Javascript messages -->
<script type="text/javascript">:ztool.getJavascriptMessages()</script> <script type="text/javascript">:ztool.getJavascriptMessages()</script>
<!-- Global form for deleting an object --> <!-- Global form for deleting an object -->
<form id="deleteForm" method="post" action="do"> <form id="deleteForm" method="post" action="do">
<input type="hidden" name="action" value="Delete"/> <input type="hidden" name="action" value="Delete"/>
<input type="hidden" name="objectUid"/> <input type="hidden" name="objectUid"/>
</form> </form>
<!-- Global form for deleting an event from an object's history --> <!-- Global form for deleting an event from an object's history -->
<form id="deleteEventForm" method="post" action="do"> <form id="deleteEventForm" method="post" action="do">
<input type="hidden" name="action" value="DeleteEvent"/> <input type="hidden" name="action" value="DeleteEvent"/>
<input type="hidden" name="objectUid"/> <input type="hidden" name="objectUid"/>
<input type="hidden" name="eventTime"/> <input type="hidden" name="eventTime"/>
</form> </form>
<!-- Global form for unlinking an object --> <!-- Global form for unlinking an object -->
<form id="unlinkForm" method="post" action="do"> <form id="unlinkForm" method="post" action="do">
<input type="hidden" name="action" value="Unlink"/> <input type="hidden" name="action" value="Unlink"/>
<input type="hidden" name="sourceUid"/> <input type="hidden" name="sourceUid"/>
<input type="hidden" name="fieldName"/> <input type="hidden" name="fieldName"/>
<input type="hidden" name="targetUid"/> <input type="hidden" name="targetUid"/>
</form> </form>
<!-- Global form for unlocking a page --> <!-- Global form for unlocking a page -->
<form id="unlockForm" method="post" action="do"> <form id="unlockForm" method="post" action="do">
<input type="hidden" name="action" value="Unlock"/> <input type="hidden" name="action" value="Unlock"/>
<input type="hidden" name="objectUid"/> <input type="hidden" name="objectUid"/>
<input type="hidden" name="pageName"/> <input type="hidden" name="pageName"/>
</form> </form>
<!-- Global form for generating a document from a pod template --> <!-- Global form for generating a document from a pod template -->
<form id="podTemplateForm" name="podTemplateForm" method="post" <form id="podTemplateForm" name="podTemplateForm" method="post"
action=":ztool.absolute_url() + '/generateDocument'"> action=":ztool.absolute_url() + '/generateDocument'">
<input type="hidden" name="objectUid"/> <input type="hidden" name="objectUid"/>
<input type="hidden" name="fieldName"/> <input type="hidden" name="fieldName"/>
<input type="hidden" name="podFormat"/> <input type="hidden" name="podFormat"/>
<input type="hidden" name="askAction"/> <input type="hidden" name="askAction"/>
<input type="hidden" name="queryData"/> <input type="hidden" name="queryData"/>
<input type="hidden" name="customParams"/> <input type="hidden" name="customParams"/>
</form> </form>
</div>''') </x>''')
pxPageBottom = Px(''' pxPageBottom = Px('''
<script type="text/javascript">initSlaves();</script>''') <script type="text/javascript">initSlaves();</script>''')
@ -241,14 +231,13 @@ class AbstractWrapper(object):
rootClasses=ztool.getRootClasses(); rootClasses=ztool.getRootClasses();
phases=contextObj and contextObj.getAppyPhases() or None"> phases=contextObj and contextObj.getAppyPhases() or None">
<x if="contextObj and phases and contextObj.mayNavigate()"> <table class="portletContent"
<table class="portletContent" if="contextObj and phases and contextObj.mayNavigate()"
var="singlePhase=phases and (len(phases) == 1); var2="singlePhase=phases and (len(phases) == 1);
page=req.get('page', ''); page=req.get('page', '');
mayEdit=contextObj.mayEdit()"> mayEdit=contextObj.mayEdit()">
<x for="phase in phases">:phase['px']</x> <x for="phase in phases">:phase['px']</x>
</table> </table>
</x>
<!-- One section for every searchable root class --> <!-- One section for every searchable root class -->
<x for="rootClass in [rc for rc in rootClasses \ <x for="rootClass in [rc for rc in rootClasses \
@ -279,18 +268,17 @@ class AbstractWrapper(object):
<!-- Create a new object from a web form --> <!-- Create a new object from a web form -->
<input type="button" class="button" <input type="button" class="button"
if="userMayAdd and ('form' in createMeans)" if="userMayAdd and ('form' in createMeans)"
style=":'background-image: url(%s/ui/buttonAdd.png)' % appUrl" style=":img('buttonAdd', bg=True)" value=":_('query_create')"
value=":_('query_create')" onclick=":'window.location=%s' % \
onclick=":'window.location=&quot;%s/do?action=Create&amp;' \ q('%s/do?action=Create&amp;className=%s' % \
'className=%s&quot;' % (toolUrl, rootClass)"/> (toolUrl, rootClass))"/>
<!-- Create object(s) by importing data --> <!-- Create object(s) by importing data -->
<input type="button" class="button" <input type="button" class="button"
if="userMayAdd and ('import' in createMeans)" if="userMayAdd and ('import' in createMeans)"
style=":'background-image: url(%s/ui/buttonImport.png)'% appUrl" style=":img('buttonImport', bg=True)" value=":_('query_import')"
value=":_('query_import')" onclick=":'window.location=%s' % \
onclick=":'window.location=&quot;%s/ui/import?' \ q('%s/ui/import?className=%s' % (toolUrl, rootClass))"/>
'className=%s&quot;' % (toolUrl, rootClass)"/>
</x> </x>
<!-- Searches --> <!-- Searches -->
@ -304,9 +292,9 @@ class AbstractWrapper(object):
<tr valign="bottom"> <tr valign="bottom">
<td><input type="text" size="14" name="w_SearchableText" <td><input type="text" size="14" name="w_SearchableText"
class="inputSearch"/></td> class="inputSearch"/></td>
<td><input type="image" style="cursor:pointer" <td>
src=":'%s/ui/search.gif' % appUrl" <input type="image" style="cursor:pointer" src=":img('search.gif')"
title=":_('search_button')"/></td> title=":_('search_button')"/></td>
</tr> </tr>
</table> </table>
</form> </form>
@ -325,10 +313,8 @@ class AbstractWrapper(object):
<!-- Predefined searches --> <!-- Predefined searches -->
<x for="widget in searchInfo['searches']"> <x for="widget in searchInfo['searches']">
<x if="widget['type'] == 'group'">:widget['px']</x> <x if="widget['type']=='group'">:widget['px']</x>
<x if="widget['type'] != 'group'"> <x if="widget['type']!='group'" var2="search=widget">:search['px']</x>
<x var="search=widget">:search['px']</x>
</x>
</x> </x>
</div> </div>
</x> </x>
@ -336,16 +322,13 @@ class AbstractWrapper(object):
# The message that is shown when a user triggers an action. # The message that is shown when a user triggers an action.
pxMessage = Px(''' pxMessage = Px('''
<x var="messages=ztool.consumeMessages()" if="messages"> <div var="messages=ztool.consumeMessages()" if="messages" class="message">
<div class="message"> <!-- The icon for closing the message -->
<!-- The icon for closing the message --> <img src=":img('close')" align=":dright" style="cursor:pointer"
<img src=":'%s/ui/close.png' % appUrl" align=":dright" onclick="this.parentNode.style.display='none'"/>
style="cursor:pointer" <!-- The message content -->
onclick="this.parentNode.style.display='none'"/> <x>::messages</x>
<!-- The message content --> </div>''')
<x>::messages</x>
</div>
</x>''')
# The page footer. # The page footer.
pxFooter = Px(''' pxFooter = Px('''
@ -371,6 +354,7 @@ class AbstractWrapper(object):
appName=ztool.getAppName(); _=ztool.translate; appName=ztool.getAppName(); _=ztool.translate;
req=ztool.REQUEST; resp=req.RESPONSE; req=ztool.REQUEST; resp=req.RESPONSE;
lang=ztool.getUserLanguage(); q=ztool.quote; lang=ztool.getUserLanguage(); q=ztool.quote;
img = ztool.getImageUrl;
layoutType=ztool.getLayoutType(); layoutType=ztool.getLayoutType();
contextObj=ztool.getPublishedObject(layoutType) or \ contextObj=ztool.getPublishedObject(layoutType) or \
ztool.getHomeObject(); ztool.getHomeObject();
@ -405,52 +389,51 @@ class AbstractWrapper(object):
<!-- Popup for confirming an action --> <!-- Popup for confirming an action -->
<div id="confirmActionPopup" class="popup"> <div id="confirmActionPopup" class="popup">
<form id="confirmActionForm" method="post"> <form id="confirmActionForm" method="post">
<div align="center"> <div align="center">
<p id="appyConfirmText"></p> <p id="appyConfirmText"></p>
<input type="hidden" name="actionType"/> <input type="hidden" name="actionType"/>
<input type="hidden" name="action"/> <input type="hidden" name="action"/>
<div id="commentArea" align=":dleft"><br/> <div id="commentArea" align=":dleft"><br/>
<span class="discreet">:_('workflow_comment')</span> <span class="discreet">:_('workflow_comment')</span>
<textarea name="comment" cols="30" rows="3"></textarea> <textarea name="comment" cols="30" rows="3"></textarea>
<br/> <br/>
</div> </div><br/>
<br/> <input type="button" onclick="doConfirm()" value=":_('yes')"/>
<input type="button" onclick="doConfirm()" value=":_('yes')"/> <input type="button" onclick="closePopup('confirmActionPopup')"
<input type="button" onclick="closePopup('confirmActionPopup')"
value=":_('no')"/> value=":_('no')"/>
</div> </div>
</form> </form>
</div> </div>
<!-- Popup for reinitializing the password --> <!-- Popup for reinitializing the password -->
<div id="askPasswordReinitPopup" class="popup" <div id="askPasswordReinitPopup" class="popup"
if="isAnon and ztool.showForgotPassword()"> if="isAnon and ztool.showForgotPassword()">
<form id="askPasswordReinitForm" method="post" <form id="askPasswordReinitForm" method="post"
action=":ztool.absolute_url() + '/askPasswordReinit'"> action=":ztool.absolute_url() + '/askPasswordReinit'">
<div align="center"> <div align="center">
<p>:_('app_login')</p> <p>:_('app_login')</p>
<input type="text" size="35" name="login" id="login" value=""/> <input type="text" size="35" name="login" id="login" value=""/>
<br/><br/> <br/><br/>
<input type="button" onclick="doAskPasswordReinit()" <input type="button" onclick="doAskPasswordReinit()"
value=":_('ask_password_reinit')"/> value=":_('ask_password_reinit')"/>
<input type="button" onclick="closePopup('askPasswordReinitPopup')" <input type="button" onclick="closePopup('askPasswordReinitPopup')"
value=":_('object_cancel')"/> value=":_('object_cancel')"/>
</div> </div>
</form> </form>
</div> </div>
<table class="main" align="center" cellpadding="0"> <table class="main" align="center" cellpadding="0">
<tr class="top"> <tr class="top">
<!-- Top banner --> <!-- Top banner -->
<td var="bannerName=(dir == 'ltr') and 'banner' or 'bannerrtl'" <td var="bannerName=(dir == 'ltr') and 'banner' or 'bannerrtl'"
style=":'background-image: url(%s/ui/%s.jpg)'% (appUrl,bannerName)"> style=":img('%s.jpg' % bannerName, bg=True)">
<!-- Top links --> <!-- Top links -->
<div style="margin-top: 4px" align=":dright"> <div style="margin-top: 4px" align=":dright">
<!-- Icon "home" --> <!-- Icon "home" -->
<a class="pageLink" href=":appUrl" title=": _('app_home')"> <a class="pageLink" href=":appUrl" title=": _('app_home')">
<img src=":'%s/ui/home.gif' % appUrl" style="margin-right: 3px"/> <img src=":img('home.gif')" style="margin-right: 3px"/>
</a> </a>
<!-- Additional links --> <!-- Additional links -->
@ -466,14 +449,13 @@ class AbstractWrapper(object):
style="cursor:pointer">:_('app_connect')</a> style="cursor:pointer">:_('app_connect')</a>
<!-- Language selector --> <!-- Language selector -->
<x if="ztool.showLanguageSelector()"> <select if="ztool.showLanguageSelector()"
<select var="languages=ztool.getLanguages(); var2="languages=ztool.getLanguages();
defaultLanguage=languages[0]" defaultLanguage=languages[0]"
class="pageLink" onchange="switchLanguage(this)"> class="pageLink" onchange="switchLanguage(this)">
<option for="lg in languages" value=":lg" <option for="lg in languages" value=":lg"
selected=":lang == lg">:ztool.getLanguageName(lg)</option> selected=":lang == lg">:ztool.getLanguageName(lg)</option>
</select> </select>
</x>
</div> </div>
</td> </td>
</tr> </tr>
@ -526,18 +508,18 @@ class AbstractWrapper(object):
<!-- Config --> <!-- Config -->
<a if="user.has_role('Manager')" href=":tool.url" <a if="user.has_role('Manager')" href=":tool.url"
title=":_('%sTool' % appName)"> title=":_('%sTool' % appName)">
<img src=":'%s/ui/appyConfig.gif' % appUrl"/></a> <img src=":img('appyConfig.gif')"/></a>
<!-- Additional icons --> <!-- Additional icons -->
<x>:self.pxIcons</x> <x>:self.pxIcons</x>
<!-- Log out --> <!-- Log out -->
<a href=":tool.url + '/performLogout'" title=":_('app_logout')"> <a href=":tool.url + '/performLogout'" title=":_('app_logout')">
<img src=":'%s/ui/logout.gif' % appUrl"/></a> <img src=":img('logout.gif')"/></a>
</td> </td>
<td class="userStripText" var="userInfo=ztool.getUserLine()" <td class="userStripText" var="userInfo=ztool.getUserLine()"
align=":dright"> align=":dright">
<span>:userInfo[0]</span> <span>:userInfo[0]</span>
<a if="userInfo[1]" href=":userInfo[1]"> <a if="userInfo[1]"
<img src=":'%s/ui/edit.png' % appUrl"/></a> href=":userInfo[1]"><img src=":img('edit')"/></a>
</td> </td>
</tr> </tr>
</table> </table>
@ -578,130 +560,121 @@ class AbstractWrapper(object):
<x var="startNumber=req.get'startNumber', 0); <x var="startNumber=req.get'startNumber', 0);
startNumber=int(startNumber); startNumber=int(startNumber);
batchSize=int(req.get('maxPerPage', 5)); batchSize=int(req.get('maxPerPage', 5));
historyInfo=contextObj.getHistory(startNumber,batchSize=batchSize); historyInfo=contextObj.getHistory(startNumber,batchSize=batchSize)"
objs=historyInfo['events']; if="historyInfo['events']"
totalNumber=historyInfo['totalNumber']; var2="objs=historyInfo['events'];
ajaxHookId='appyHistory'; totalNumber=historyInfo['totalNumber'];
navBaseCall='askObjectHistory(&quot;%s&quot;, &quot;%s&quot;, \ ajaxHookId='appyHistory';
%d, **v**)' % (ajaxHookId,contextObj.absolute_url(),batchSize)"> navBaseCall='askObjectHistory(%s,%s,%d,**v**)' % \
(q(ajaxHookId), q(contextObj.absolute_url()), batchSize)">
<!-- Table containing the history --> <!-- Navigate between history pages -->
<x if="objs"> <x>:self.pxAppyNavigate</x>
<x>:self.pxAppyNavigate</x> <!-- History -->
<table width="100%" class="history"> <table width="100%" class="history">
<tr> <tr>
<th align=":dleft">:_('object_action')</th> <th align=":dleft">:_('object_action')</th>
<th align=":dleft">:_('object_author')</th> <th align=":dleft">:_('object_author')</th>
<th align=":dleft">:_('action_date')</th> <th align=":dleft">:_('action_date')</th>
<th align=":dleft">:_('action_comment')</th> <th align=":dleft">:_('action_comment')</th>
</tr> </tr>
<x for="event in objs"> <tr for="event in objs"
<tr var="odd=loop.event.odd; var2="odd=loop.event.odd;
rhComments=event.get('comments', None); rhComments=event.get('comments', None);
state=event.get('review_state', None); state=event.get('review_state', None);
action=event['action']; action=event['action'];
isDataChange=action == '_datachange_'" isDataChange=action == '_datachange_'"
class="odd and 'even' or 'odd'" valign="top"> class="odd and 'even' or 'odd'" valign="top">
<td if="isDataChange"> <td if="isDataChange">
<x>:_('data_change')</x> <x>:_('data_change')</x>
<img if="user.has_role('Manager')" style="cursor:pointer" <img if="user.has_role('Manager')" style="cursor:pointer"
src=":'%s/ui/delete.png' % appUrl" src=":img('delete')"
onclick=":'onDeleteEvent(&quot;%s&quot;, &quot;%s&quot;)' % \ onclick=":'onDeleteEvent(%s,%s)' % \
(contextObj.UID(), event['time'])"/> (q(contextObj.UID()), q(event['time']))"/>
</td> </td>
<td if="not isDataChange">:_(contextObj.getWorkflowLabel(action))</td> <td if="not isDataChange">:_(contextObj.getWorkflowLabel(action))</td>
<td var="actorId=event.get('actor')"> <td var="actorId=event.get('actor')">
<x if="not actorId">?</x> <x if="not actorId">?</x>
<x if="actorId">:ztool.getUserName(actorId)</x> <x if="actorId">:ztool.getUserName(actorId)</x>
</td> </td>
<td>:ztool.formatDate(event['time'], withHour=True)"></td> <td>:ztool.formatDate(event['time'], withHour=True)"></td>
<td if="not isDataChange"> <td if="not isDataChange">
<x if="rhComments">::contextObj.formatText(rhComments)</x> <x if="rhComments">::contextObj.formatText(rhComments)</x>
<x if="not rhComments">-</x> <x if="not rhComments">-</x>
</td> </td>
<td if="isDataChange"> <td if="isDataChange">
<!-- Display the previous values of the fields whose value were <!-- Display the previous values of the fields whose value were
modified in this change. --> modified in this change. -->
<table class="appyChanges" width="100%"> <table class="appyChanges" width="100%">
<tr> <tr>
<th align=":dleft" width="30%">:_('modified_field')</th> <th align=":dleft" width="30%">:_('modified_field')</th>
<th align=":dleft" width="70%">:_('previous_value')</th> <th align=":dleft" width="70%">:_('previous_value')</th>
</tr> </tr>
<tr for="change in event['changes'].items()" valign="top"> <tr for="change in event['changes'].items()" valign="top"
<x var="appyType=contextObj.getAppyType(change[0], asDict=True)"> var2="appyType=contextObj.getAppyType(change[0], asDict=True)">
<td>::_(appyType['labelId'])</td> <td>::_(appyType['labelId'])</td>
<td>::change[1][0]</td> <td>::change[1][0]</td>
</x> </tr>
</tr> </table>
</table> </td>
</td> </tr>
</tr> </table>
</x> </x>''')
</table>
</x>
</x>
''')
# Displays an object's transitions(s). # Displays an object's transitions(s).
pxTransitions = Px(''' pxTransitions = Px('''
<x var="transitions=targetObj.getAppyTransitions()" if="transitions"> <form var="transitions=targetObj.getAppyTransitions()" if="transitions"
<form var="formId='trigger_%s' % targetObj.UID()" method="post" var2="formId='trigger_%s' % targetObj.UID()" method="post"
id=":formId" action=":targetObj.absolute_url() + '/do'"> id=":formId" action=":targetObj.absolute_url() + '/do'">
<input type="hidden" name="action" value="Trigger"/> <input type="hidden" name="action" value="Trigger"/>
<input type="hidden" name="workflow_action"/> <input type="hidden" name="workflow_action"/>
<table> <table>
<tr valign="middle"> <tr valign="middle">
<!-- Input field for storing comment --> <!-- Input field for storing comment -->
<textarea id="comment" name="comment" cols="30" rows="3" <textarea id="comment" name="comment" cols="30" rows="3"
style="display:none"></textarea> style="display:none"></textarea>
<!-- Buttons for triggering transitions --> <!-- Buttons for triggering transitions -->
<td align=":dright" for="transition in transitions"> <td align=":dright" for="transition in transitions">
<!-- Real button --> <!-- Real button -->
<input type="button" class="button" if="transition['may_trigger']" <input type="button" class="button" if="transition['may_trigger']"
style=":'background-image: \ style=":img('buttonTransition', bg=True)"
url(%s/ui/buttonTransition.png)' % appUrl" title=":transition['title']"
title=":transition['title']" value=":ztool.truncateValue(transition['title'])"
value=":ztool.truncateValue(transition['title'])" onclick=":'triggerTransition(%s,%s,%s)' % (q(formId), \
onclick=":'triggerTransition(&quot;%s&quot;, &quot;%s&quot;, \ q(transition['name']), q(transition['confirm']))"/>
&quot;%s&quot;)' % (formId, transition['name'], \
transition['confirm'])"/>
<!-- Fake button, explaining why the transition can't be triggered --> <!-- Fake button, explaining why the transition can't be triggered -->
<input type="button" class="button" if="not transition['may_trigger']" <input type="button" class="button" if="not transition['may_trigger']"
style=":'background-image: url(%s/ui/buttonFake.png); \ style=":img('buttonFake', bg=True) + ';cursor: help'"
cursor: help' % appUrl" value=":ztool.truncateValue(transition['title'])"
value=":ztool.truncateValue(transition['title'])" title=":'%s: %s' % (transition['title'], \
title=":'%s: %s' % (transition['title'], \ transition['reason'])"/>
transition['reason'])"/> </td>
</td> </tr>
</tr> </table>
</table> </form>''')
</form>
</x>''')
# Displays header information about an object: title, workflow-related info, # Displays header information about an object: title, workflow-related info,
# history... # history...
pxObjectHeader = Px(''' pxObjectHeader = Px('''
<div var="hasHistory=contextObj.hasHistory(); <div if="not contextObj.isTemporary()"
historyMaxPerPage=req.get('maxPerPage', 5); var2="hasHistory=contextObj.hasHistory();
historyExpanded=req.get('appyHistory','collapsed') == 'expanded'; historyMaxPerPage=req.get('maxPerPage', 5);
creator=contextObj.Creator()" historyExpanded=req.get('appyHistory','collapsed') == 'expanded';
if="not contextObj.isTemporary()"> creator=contextObj.Creator()">
<table width="100%" class="summary"> <table width="100%" class="summary">
<tr> <tr>
<td colspan="2" class="by"> <td colspan="2" class="by">
<!-- Plus/minus icon for accessing history --> <!-- Plus/minus icon for accessing history -->
<x if="hasHistory"> <x if="hasHistory">
<img style="cursor:pointer" onClick="toggleCookie('appyHistory')" <img style="cursor:pointer" onclick="toggleCookie('appyHistory')"
src="historyExpanded and 'ui/collapse.gif' or 'ui/expand.gif'" src="historyExpanded and img('collapse.gif') or img('expand.gif')"
align=":dleft" id="appyHistory_img"/> align=":dleft" id="appyHistory_img"/>
<x>:_('object_history')</x> || <x>:_('object_history')</x> ||
</x> </x>
<!-- Creator and last modification date --> <!-- Creator and last modification date -->
<x>:_('object_created_by')</x> <x>:_('object_created_by')</x><x>:ztool.getUserName(creator)</x>
<x>:ztool.getUserName(creator)</x>
<!-- Creation and last modification dates --> <!-- Creation and last modification dates -->
<x>:_('object_created_on')</x> <x>:_('object_created_on')</x>
@ -726,18 +699,16 @@ class AbstractWrapper(object):
<td colspan="2"> <td colspan="2">
<span id="appyHistory" <span id="appyHistory"
style=":historyExpanded and 'display:block' or 'display:none')"> style=":historyExpanded and 'display:block' or 'display:none')">
<div var="ajaxHookId=contextObj.UID() + '_history'" <div var="ajaxHookId=contextObj.UID() + '_history'" id=":ajaxHookId">
id=":ajaxHookId"> <script type="text/javascript">:'askObjectHistory(%s,%s,%d,0)' % \
<script type="text/javascript">:'askObjectHistory(&quot;%s&quot;, \ (q(ajaxHookId), q(contextObj.absolute_url()), \
&quot;%s&quot;, %d, 0)' % (ajaxHookId, contextObj.absolute_url(),\ historyMaxPerPage)</script>
historyMaxPerPage)</script>
</div> </div>
</span> </span>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>''')
''')
# Shows the range of buttons (next, previous, save,...) and the workflow # Shows the range of buttons (next, previous, save,...) and the workflow
# transitions. # transitions.
@ -754,73 +725,61 @@ class AbstractWrapper(object):
<x if="isEdit"> <x if="isEdit">
<input type="button" class="button" value=":_('page_previous')" <input type="button" class="button" value=":_('page_previous')"
onClick="submitAppyForm('previous')" onClick="submitAppyForm('previous')"
style=":'background-image: \ style=":img('buttonPrevious', bg=True)"/>
url(%s/ui/buttonPrevious.png)' % appUrl"/>
<input type="hidden" name="previousPage" value=":previousPage"/> <input type="hidden" name="previousPage" value=":previousPage"/>
</x> </x>
<!-- Button on the view page --> <!-- Button on the view page -->
<x if="not isEdit"> <input if="not isEdit" type="button" class="button"
<input type="button" class="button" value=":_('page_previous')" value=":_('page_previous')"
style=":'background-image: \ style=":img('buttonPrevious', bg=True)"
url(%s/ui/buttonPrevious.png)' % appUrl" onclick=":'window.location=%s' % \
onclick=":'window.location=&quot;%s&quot;' % \ q(contextObj.getUrl(page=previousPage))"/>
contextObj.getUrl(page=previousPage)"/>
</x>
</td> </td>
<!-- Save --> <!-- Save -->
<td if="isEdit and pageInfo['showSave']"> <td if="isEdit and pageInfo['showSave']">
<input type="button" class="button" onClick="submitAppyForm('save')" <input type="button" class="button" onClick="submitAppyForm('save')"
style=":'background-image: url(%s/ui/buttonSave.png)' % appUrl" style=":img(buttonSave', bg=True)" value=":_('object_save')"/>
value=":_('object_save')"/>
</td> </td>
<!-- Cancel --> <!-- Cancel -->
<td if="isEdit and pageInfo['showCancel']"> <td if="isEdit and pageInfo['showCancel']">
<input type="button" class="button" onClick="submitAppyForm('cancel')" <input type="button" class="button" onClick="submitAppyForm('cancel')"
style=":'background-image: url(%s/ui/buttonCancel.png)' % appUrl" style=":img('buttonCancel', bg=True)" value=":_('object_cancel')"/>
value=":_('object_cancel')"/>
</td> </td>
<x if="not isEdit"> <td if="not isEdit"
<td var="locked=contextObj.isLocked(user, page); var2="locked=contextObj.isLocked(user, page);
editable=pageInfo['showOnEdit'] and contextObj.mayEdit()"> editable=pageInfo['showOnEdit'] and contextObj.mayEdit()">
<!-- Edit --> <!-- Edit -->
<input type="button" class="button" if="editable and not locked" <input type="button" class="button" if="editable and not locked"
style=":'background-image: url(%s/ui/buttonEdit.png)' % appUrl" style=":img('buttonEdit', bg=True)" value=":_('object_edit')"
value=":_('object_edit')" onclick=":'window.location=%s' % \
onclick=":'window.location=&quot;%s&quot;' % \ q(contextObj.getUrl(mode='edit', page=page))"/>
contextObj.getUrl(mode='edit', page=page)"/>
<!-- Locked --> <!-- Locked -->
<a if="editable and locked"> <a if="editable and locked">
<img style="cursor: help" <img style="cursor: help"
var="lockDate=tool.formatDate(locked[1]); var="lockDate=tool.formatDate(locked[1]);
lockMap={'user': tool.getUserName(locked[0]),\ lockMap={'user':tool.getUserName(locked[0]),'date':lockDate};
'date': lockDate}; lockMsg=_('page_locked', mapping=lockMap)"
lockMsg=_('page_locked', mapping=lockMap)" src=":img('lockedBig')" title=":lockMsg"/></a>
src=":'%s/ui/lockedBig.png' % appUrl" title=":lockMsg"/></a> </td>
</td>
</x>
<!-- Next --> <!-- Next -->
<td if="nextPage and pageInfo['showNext']"> <td if="nextPage and pageInfo['showNext']">
<!-- Button on the edit page --> <!-- Button on the edit page -->
<x if="isEdit"> <x if="isEdit">
<input type="button" class="button" onClick="submitAppyForm('next')" <input type="button" class="button" onClick="submitAppyForm('next')"
style=":'background-image: url(%s/ui/buttonNext.png)' % appUrl" style=":img('buttonNext', bg=True)" value=":_('page_next')"/>
value=":_('page_next')"/>
<input type="hidden" name="nextPage" value=":nextPage"/> <input type="hidden" name="nextPage" value=":nextPage"/>
</x> </x>
<!-- Button on the view page --> <!-- Button on the view page -->
<x if="not isEdit"> <input if="not isEdit" type="button" class="button"
<input type="button" class="button" style=":img('buttonNext', bg=True)" value=":_('page_next')"
style=":'background-image: url(%s/ui/buttonNext.png)' % appUrl" onclick=":'window.location=%s' % \
value=":_('page_next')" q(contextObj.getUrl(page=nextPage))"/>
onclick=":'window.location=&quot;%s&quot;' % \
contextObj.getUrl(page=nextPage)"/>
</x>
</td> </td>
<!-- Workflow transitions --> <!-- Workflow transitions -->
@ -830,8 +789,8 @@ class AbstractWrapper(object):
<!-- Refresh --> <!-- Refresh -->
<td if="contextObj.isDebug()"> <td if="contextObj.isDebug()">
<a href="contextObj.getUrl(mode=layoutType, page=page, refresh='yes')"> <a href="contextObj.getUrl(mode=layoutType, page=page, refresh='yes')">
<img title="Refresh" style="vertical-align:top" <img title="Refresh" style="vertical-align:top" src=":img('refresh')"/>
src=":'%s/ui/refresh.png' % appUrl"/></a> </a>
</td> </td>
</tr> </tr>
</table>''') </table>''')
@ -869,7 +828,7 @@ class AbstractWrapper(object):
cssJs=cssJs)"> cssJs=cssJs)">
<x>:self.pxPagePrologue</x> <x>:self.pxPagePrologue</x>
<!-- Warn the user that the form should be left via buttons --> <!-- Warn the user that the form should be left via buttons -->
<script type="text/javascript"> <script type="text/javascript"><![CDATA[
window.onbeforeunload = function(e){ window.onbeforeunload = function(e){
theForm = document.getElementById('appyForm'); theForm = document.getElementById('appyForm');
if (theForm.button.value == "") { if (theForm.button.value == "") {
@ -877,22 +836,21 @@ class AbstractWrapper(object):
if (e) {e.returnValue = warn_leave_form;} if (e) {e.returnValue = warn_leave_form;}
return warn_leave_form; return warn_leave_form;
} }
} }]]>
</script> </script>
<form id="appyForm" name="appyForm" method="post" <form id="appyForm" name="appyForm" method="post"
enctype="multipart/form-data" enctype="multipart/form-data"
action=":contextObj.absolute_url()+'/do'"> action=":contextObj.absolute_url()+'/do'">
<input type="hidden" name="action" value="Update"/> <input type="hidden" name="action" value="Update"/>
<input type="hidden" name="button" value=""/> <input type="hidden" name="button" value=""/>
<input type="hidden" name="page" value=":page"/> <input type="hidden" name="page" value=":page"/>
<input type="hidden" name="nav" value=":req.get('nav', None)"/> <input type="hidden" name="nav" value=":req.get('nav', None)"/>
<input type="hidden" name="confirmed" value="False"/> <input type="hidden" name="confirmed" value="False"/>
<x var="tagId='pageLayout'">:self.pxLayoutedObject</x> <x var="tagId='pageLayout'">:self.pxLayoutedObject</x>
</form> </form>
<script type="text/javascript" <script type="text/javascript"
if="confirmMsg">:'askConfirm(&quot;script&quot;, \ if="confirmMsg">:'askConfirm(%s,%s,%s)' % \
&quot;postConfirmedEditForm()&quot;, \ (q('script'), q('postConfirmedEditForm()'), q(confirmMsg))</script>
&quot;%s&quot;)' % confirmMsg</script>
<x>:self.pxPageBottom</x> <x>:self.pxPageBottom</x>
</x>''', template=pxTemplate, hook='content') </x>''', template=pxTemplate, hook='content')

View file

@ -135,7 +135,10 @@ class IfAction(BufferAction):
the result or not.''' the result or not.'''
def do(self, result, context, exprRes): def do(self, result, context, exprRes):
if exprRes: if exprRes:
self.evaluateBuffer(result, context) if self.subAction:
self.subAction.execute(result, context)
else:
self.evaluateBuffer(result, context)
else: else:
if self.buffer.isMainElement(Cell.OD): if self.buffer.isMainElement(Cell.OD):
# Don't leave the current row with a wrong number of cells # Don't leave the current row with a wrong number of cells

View file

@ -499,7 +499,7 @@ class MemoryBuffer(Buffer):
'buffer', None) 'buffer', None)
elif actionType == 'if': elif actionType == 'if':
action= IfAction('if', self, statement, elem, False, 'buffer', None) action= IfAction('if', self, statement, elem, False, 'buffer', None)
elif actionType == 'var': elif actionType in ('var', 'var2'):
variables = self._getVariables(statement) variables = self._getVariables(statement)
action = VariablesAction('var', self, elem, False, variables, action = VariablesAction('var', self, elem, False, variables,
'buffer', None) 'buffer', None)

View file

@ -44,7 +44,7 @@ class PxEnvironment(XmlEnvironment):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class PxParser(XmlParser): class PxParser(XmlParser):
'''PX parser that is specific for parsing PX data.''' '''PX parser that is specific for parsing PX data.'''
pxAttributes = ('var', 'for', 'if') pxAttributes = ('var', 'for', 'if', 'var2')
# No-end tags # No-end tags
noEndTags = ('br', 'img', 'link', 'input') noEndTags = ('br', 'img', 'link', 'input')
noDumpTags = ('selected', 'checked', 'disabled', 'multiple') noDumpTags = ('selected', 'checked', 'disabled', 'multiple')
@ -79,7 +79,7 @@ class PxParser(XmlParser):
# the main element or to a sub-element. # the main element or to a sub-element.
e.currentBuffer.addElement(elem, elemType='px') e.currentBuffer.addElement(elem, elemType='px')
if elem != 'x': if elem != 'x':
# Dump the start elements and its attributes. But as a preamble, # Dump the start element and its attributes. But as a preamble,
# manage special attributes that could not be dumped at all, like # manage special attributes that could not be dumped at all, like
# "selected" or "checked". # "selected" or "checked".
hook = None hook = None