comparison roundup/cgi/templating.py @ 1952:c40ed9113285

Applied Stefan Seefeld's html4/xhtml patch with some changes.
author Richard Jones <richard@users.sourceforge.net>
date Sat, 06 Dec 2003 00:00:54 +0000
parents cd7af2579d20
children 1e2cccf6b53b
comparison
equal deleted inserted replaced
1951:767ff2a03eee 1952:c40ed9113285
21 # bring in the templating support 21 # bring in the templating support
22 from roundup.cgi.PageTemplates import PageTemplate 22 from roundup.cgi.PageTemplates import PageTemplate
23 from roundup.cgi.PageTemplates.Expressions import getEngine 23 from roundup.cgi.PageTemplates.Expressions import getEngine
24 from roundup.cgi.TAL.TALInterpreter import TALInterpreter 24 from roundup.cgi.TAL.TALInterpreter import TALInterpreter
25 from roundup.cgi import ZTUtils 25 from roundup.cgi import ZTUtils
26
27 def input_html4(**attrs):
28 """Generate an 'input' (html4) element with given attributes"""
29 return '<input %s>'%' '.join(['%s="%s"'%item for item in attrs.items()])
30
31 def input_xhtml(**attrs):
32 """Generate an 'input' (xhtml) element with given attributes"""
33 return '<input %s/>'%' '.join(['%s="%s"'%item for item in attrs.items()])
26 34
27 class NoTemplate(Exception): 35 class NoTemplate(Exception):
28 pass 36 pass
29 37
30 def find_template(dir, name, extension): 38 def find_template(dir, name, extension):
293 # consistent API for extending Class/Item 301 # consistent API for extending Class/Item
294 self._classname = self.classname = classname 302 self._classname = self.classname = classname
295 self._klass = self._db.getclass(self.classname) 303 self._klass = self._db.getclass(self.classname)
296 self._props = self._klass.getprops() 304 self._props = self._klass.getprops()
297 305
306 html_version = 'html4'
307 if hasattr(self._client.instance.config, 'HTML_VERSION'):
308 html_version = self._client.instance.config.HTML_VERSION
309 if html_version == 'xhtml':
310 self.input = input_xhtml
311 else:
312 self.input = input_html4
313
298 def __repr__(self): 314 def __repr__(self):
299 return '<HTMLClass(0x%x) %s>'%(id(self), self.classname) 315 return '<HTMLClass(0x%x) %s>'%(id(self), self.classname)
300 316
301 def __getitem__(self, item): 317 def __getitem__(self, item):
302 ''' return an HTMLProperty instance 318 ''' return an HTMLProperty instance
476 height, label) 492 height, label)
477 493
478 def submit(self, label="Submit New Entry"): 494 def submit(self, label="Submit New Entry"):
479 ''' Generate a submit button (and action hidden element) 495 ''' Generate a submit button (and action hidden element)
480 ''' 496 '''
481 return ' <input type="hidden" name="@action" value="new">\n'\ 497 return self.input(type="hidden",name="@action",value="new") + '\n' + \
482 ' <input type="submit" name="submit" value="%s">'%label 498 self.input(type="submit",name="submit",value=label)
483 499
484 def history(self): 500 def history(self):
485 return 'New node - no history' 501 return 'New node - no history'
486 502
487 def renderWith(self, name, **kwargs): 503 def renderWith(self, name, **kwargs):
554 return '%s%s'%(self._classname, self._nodeid) 570 return '%s%s'%(self._classname, self._nodeid)
555 571
556 def submit(self, label="Submit Changes"): 572 def submit(self, label="Submit Changes"):
557 ''' Generate a submit button (and action hidden element) 573 ''' Generate a submit button (and action hidden element)
558 ''' 574 '''
559 return ' <input type="hidden" name="@action" value="edit">\n'\ 575 return self.input(type="hidden",name="@action",value="edit") + '\n' + \
560 ' <input type="submit" name="submit" value="%s">'%label 576 self.input(type="submit",name="submit",value=label)
561 577
562 def journal(self, direction='descending'): 578 def journal(self, direction='descending'):
563 ''' Return a list of HTMLJournalEntry instances. 579 ''' Return a list of HTMLJournalEntry instances.
564 ''' 580 '''
565 # XXX do this 581 # XXX do this
842 self._name = name 858 self._name = name
843 if not anonymous: 859 if not anonymous:
844 self._formname = '%s%s@%s'%(classname, nodeid, name) 860 self._formname = '%s%s@%s'%(classname, nodeid, name)
845 else: 861 else:
846 self._formname = name 862 self._formname = name
863
864 html_version = 'html4'
865 if hasattr(self._client.instance.config, 'HTML_VERSION'):
866 html_version = self._client.instance.config.HTML_VERSION
867 if html_version == 'xhtml':
868 self.input = input_xhtml
869 else:
870 self.input = input_html4
871
847 def __repr__(self): 872 def __repr__(self):
848 return '<HTMLProperty(0x%x) %s %r %r>'%(id(self), self._formname, 873 return '<HTMLProperty(0x%x) %s %r %r>'%(id(self), self._formname,
849 self._prop, self._value) 874 self._prop, self._value)
850 def __str__(self): 875 def __str__(self):
851 return self.plain() 876 return self.plain()
916 if self._value is None: 941 if self._value is None:
917 value = '' 942 value = ''
918 else: 943 else:
919 value = cgi.escape(str(self._value)) 944 value = cgi.escape(str(self._value))
920 value = '&quot;'.join(value.split('"')) 945 value = '&quot;'.join(value.split('"'))
921 return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size) 946 return self.input(name=self._formname,value=value,size=size)
922 947
923 def multiline(self, escape=0, rows=5, cols=40): 948 def multiline(self, escape=0, rows=5, cols=40):
924 ''' Render a multiline form edit field for the property 949 ''' Render a multiline form edit field for the property
925 ''' 950 '''
926 if self._value is None: 951 if self._value is None:
956 return _('*encrypted*') 981 return _('*encrypted*')
957 982
958 def field(self, size = 30): 983 def field(self, size = 30):
959 ''' Render a form edit field for the property. 984 ''' Render a form edit field for the property.
960 ''' 985 '''
961 return '<input type="password" name="%s" size="%s">'%(self._formname, size) 986 return self.input(type="password", name=self._formname, size=size)
962 987
963 def confirm(self, size = 30): 988 def confirm(self, size = 30):
964 ''' Render a second form edit field for the property, used for 989 ''' Render a second form edit field for the property, used for
965 confirmation that the user typed the password correctly. Generates 990 confirmation that the user typed the password correctly. Generates
966 a field with name "@confirm@name". 991 a field with name "@confirm@name".
967 ''' 992 '''
968 return '<input type="password" name="@confirm@%s" size="%s">'%( 993 return self.input(type="password", name="@confirm@%s"%self._formname,
969 self._formname, size) 994 size=size)
970 995
971 class NumberHTMLProperty(HTMLProperty): 996 class NumberHTMLProperty(HTMLProperty):
972 def plain(self): 997 def plain(self):
973 ''' Render a "plain" representation of the property 998 ''' Render a "plain" representation of the property
974 ''' 999 '''
980 if self._value is None: 1005 if self._value is None:
981 value = '' 1006 value = ''
982 else: 1007 else:
983 value = cgi.escape(str(self._value)) 1008 value = cgi.escape(str(self._value))
984 value = '&quot;'.join(value.split('"')) 1009 value = '&quot;'.join(value.split('"'))
985 return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size) 1010 return self.input(name=self._formname,value=value,size=size)
986 1011
987 def __int__(self): 1012 def __int__(self):
988 ''' Return an int of me 1013 ''' Return an int of me
989 ''' 1014 '''
990 return int(self._value) 1015 return int(self._value)
1005 1030
1006 def field(self): 1031 def field(self):
1007 ''' Render a form edit field for the property 1032 ''' Render a form edit field for the property
1008 ''' 1033 '''
1009 checked = self._value and "checked" or "" 1034 checked = self._value and "checked" or ""
1010 s = '<input type="radio" name="%s" value="yes" %s>Yes'%(self._formname, 1035 if self._value:
1011 checked) 1036 s = self.input(type="radio",name=self._formname,value="yes",checked="checked")
1012 if checked: 1037 s += 'Yes'
1013 checked = "" 1038 s +=self.input(type="radio",name=self._formname,value="no")
1014 else: 1039 s += 'No'
1015 checked = "checked" 1040 else:
1016 s += '<input type="radio" name="%s" value="no" %s>No'%(self._formname, 1041 s = self.input(type="radio",name=self._formname,value="yes")
1017 checked) 1042 s += 'Yes'
1043 s +=self.input(type="radio",name=self._formname,value="no",checked="checked")
1044 s += 'No'
1018 return s 1045 return s
1019 1046
1020 class DateHTMLProperty(HTMLProperty): 1047 class DateHTMLProperty(HTMLProperty):
1021 def plain(self): 1048 def plain(self):
1022 ''' Render a "plain" representation of the property 1049 ''' Render a "plain" representation of the property
1040 if self._value is None: 1067 if self._value is None:
1041 value = '' 1068 value = ''
1042 else: 1069 else:
1043 value = cgi.escape(str(self._value.local(self._db.getUserTimezone()))) 1070 value = cgi.escape(str(self._value.local(self._db.getUserTimezone())))
1044 value = '&quot;'.join(value.split('"')) 1071 value = '&quot;'.join(value.split('"'))
1045 return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size) 1072 return self.input(name=self._formname,value=value,size=size)
1046 1073
1047 def reldate(self, pretty=1): 1074 def reldate(self, pretty=1):
1048 ''' Render the interval between the date and now. 1075 ''' Render the interval between the date and now.
1049 1076
1050 If the "pretty" flag is true, then make the display pretty. 1077 If the "pretty" flag is true, then make the display pretty.
1097 if self._value is None: 1124 if self._value is None:
1098 value = '' 1125 value = ''
1099 else: 1126 else:
1100 value = cgi.escape(str(self._value)) 1127 value = cgi.escape(str(self._value))
1101 value = '&quot;'.join(value.split('"')) 1128 value = '&quot;'.join(value.split('"'))
1102 return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size) 1129 return self.input(name=self._formname,value=value,size=size)
1103 1130
1104 class LinkHTMLProperty(HTMLProperty): 1131 class LinkHTMLProperty(HTMLProperty):
1105 ''' Link HTMLProperty 1132 ''' Link HTMLProperty
1106 Include the above as well as being able to access the class 1133 Include the above as well as being able to access the class
1107 information. Stringifying the object itself results in the value 1134 information. Stringifying the object itself results in the value
1153 options = linkcl.filter(None, {}, ('+', sort_on), (None, None)) 1180 options = linkcl.filter(None, {}, ('+', sort_on), (None, None))
1154 # TODO: make this a field display, not a menu one! 1181 # TODO: make this a field display, not a menu one!
1155 l = ['<select name="%s">'%self._formname] 1182 l = ['<select name="%s">'%self._formname]
1156 k = linkcl.labelprop(1) 1183 k = linkcl.labelprop(1)
1157 if self._value is None: 1184 if self._value is None:
1158 s = 'selected ' 1185 s = 'selected="selected" '
1159 else: 1186 else:
1160 s = '' 1187 s = ''
1161 l.append(_('<option %svalue="-1">- no selection -</option>')%s) 1188 l.append(_('<option %svalue="-1">- no selection -</option>')%s)
1162 1189
1163 # make sure we list the current value if it's retired 1190 # make sure we list the current value if it's retired
1169 option = linkcl.get(optionid, k) or '' 1196 option = linkcl.get(optionid, k) or ''
1170 1197
1171 # figure if this option is selected 1198 # figure if this option is selected
1172 s = '' 1199 s = ''
1173 if optionid == self._value: 1200 if optionid == self._value:
1174 s = 'selected ' 1201 s = 'selected="selected" '
1175 1202
1176 # figure the label 1203 # figure the label
1177 if showid: 1204 if showid:
1178 lab = '%s%s: %s'%(self._prop.classname, optionid, option) 1205 lab = '%s%s: %s'%(self._prop.classname, optionid, option)
1179 else: 1206 else:
1198 linkcl = self._db.getclass(self._prop.classname) 1225 linkcl = self._db.getclass(self._prop.classname)
1199 l = ['<select name="%s">'%self._formname] 1226 l = ['<select name="%s">'%self._formname]
1200 k = linkcl.labelprop(1) 1227 k = linkcl.labelprop(1)
1201 s = '' 1228 s = ''
1202 if value is None: 1229 if value is None:
1203 s = 'selected ' 1230 s = 'selected="selected" '
1204 l.append(_('<option %svalue="-1">- no selection -</option>')%s) 1231 l.append(_('<option %svalue="-1">- no selection -</option>')%s)
1205 if linkcl.getprops().has_key('order'): 1232 if linkcl.getprops().has_key('order'):
1206 sort_on = ('+', 'order') 1233 sort_on = ('+', 'order')
1207 else: 1234 else:
1208 sort_on = ('+', linkcl.labelprop()) 1235 sort_on = ('+', linkcl.labelprop())
1217 option = linkcl.get(optionid, k) or '' 1244 option = linkcl.get(optionid, k) or ''
1218 1245
1219 # figure if this option is selected 1246 # figure if this option is selected
1220 s = '' 1247 s = ''
1221 if value in [optionid, option]: 1248 if value in [optionid, option]:
1222 s = 'selected ' 1249 s = 'selected="selected" '
1223 1250
1224 # figure the label 1251 # figure the label
1225 if showid: 1252 if showid:
1226 lab = '%s%s: %s'%(self._prop.classname, optionid, option) 1253 lab = '%s%s: %s'%(self._prop.classname, optionid, option)
1227 else: 1254 else:
1313 showid=1 1340 showid=1
1314 if not showid: 1341 if not showid:
1315 k = linkcl.labelprop(1) 1342 k = linkcl.labelprop(1)
1316 value = [linkcl.get(v, k) for v in value] 1343 value = [linkcl.get(v, k) for v in value]
1317 value = cgi.escape(','.join(value)) 1344 value = cgi.escape(','.join(value))
1318 return '<input name="%s" size="%s" value="%s">'%(self._formname, size, value) 1345 return self.input(name=self._formname,size=size,value=value)
1319 1346
1320 def menu(self, size=None, height=None, showid=0, additional=[], 1347 def menu(self, size=None, height=None, showid=0, additional=[],
1321 **conditions): 1348 **conditions):
1322 ''' Render a form select list for this property 1349 ''' Render a form select list for this property
1323 ''' 1350 '''
1340 option = linkcl.get(optionid, k) or '' 1367 option = linkcl.get(optionid, k) or ''
1341 1368
1342 # figure if this option is selected 1369 # figure if this option is selected
1343 s = '' 1370 s = ''
1344 if optionid in value or option in value: 1371 if optionid in value or option in value:
1345 s = 'selected ' 1372 s = 'selected="selected" '
1346 1373
1347 # figure the label 1374 # figure the label
1348 if showid: 1375 if showid:
1349 lab = '%s%s: %s'%(self._prop.classname, optionid, option) 1376 lab = '%s%s: %s'%(self._prop.classname, optionid, option)
1350 else: 1377 else:
1448 self.classname = client.classname 1475 self.classname = client.classname
1449 self.template = client.template 1476 self.template = client.template
1450 1477
1451 # the special char to use for special vars 1478 # the special char to use for special vars
1452 self.special_char = '@' 1479 self.special_char = '@'
1480
1481 html_version = 'html4'
1482 if hasattr(self.client.instance.config, 'HTML_VERSION'):
1483 html_version = self.client.instance.config.HTML_VERSION
1484 if html_version == 'xhtml':
1485 self.input = input_xhtml
1486 else:
1487 self.input = input_html4
1453 1488
1454 self._post_init() 1489 self._post_init()
1455 1490
1456 def _post_init(self): 1491 def _post_init(self):
1457 ''' Set attributes based on self.form 1492 ''' Set attributes based on self.form
1601 def indexargs_form(self, columns=1, sort=1, group=1, filter=1, 1636 def indexargs_form(self, columns=1, sort=1, group=1, filter=1,
1602 filterspec=1): 1637 filterspec=1):
1603 ''' return the current index args as form elements ''' 1638 ''' return the current index args as form elements '''
1604 l = [] 1639 l = []
1605 sc = self.special_char 1640 sc = self.special_char
1606 s = '<input type="hidden" name="%s" value="%s">' 1641 s = self.input(type="hidden",name="%s",value="%s")
1607 if columns and self.columns: 1642 if columns and self.columns:
1608 l.append(s%(sc+'columns', ','.join(self.columns))) 1643 l.append(s%(sc+'columns', ','.join(self.columns)))
1609 if sort and self.sort[1] is not None: 1644 if sort and self.sort[1] is not None:
1610 if self.sort[0] == '-': 1645 if self.sort[0] == '-':
1611 val = '-'+self.sort[1] 1646 val = '-'+self.sort[1]

Roundup Issue Tracker: http://roundup-tracker.org/