Skip to content

Commit 63c9e3a

Browse files
committed
Fix html generation errors for boolean options.
Code was generating xhtml form for html4 output. In xhtml, Boolean attributes like 'disabled', 'required' are represented with a value that is the same as the attribute name. E.G. <input required="required" ...>. Html 5 (and 4) represents the same as <input required ...> . Recognize booleans in one of two ways: value is None value is the same as the attribute name Make html4 and xhtml variants of cgi_escape_attrs. Have input_htmlp4 and input_xhtml call the proper variant. Also set HTMLInputMixin property cgi_escape_atrs to select proper one similar to self.input definition. Then replace calls to cgi_escape_attr with self.cgi_escape_attrs to get correct output.
1 parent f3e007e commit 63c9e3a

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

roundup/cgi/templating.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -437,19 +437,42 @@ def _set_input_default_args(dic):
437437
except KeyError:
438438
pass
439439

440-
def cgi_escape_attrs(**attrs):
440+
def html4_cgi_escape_attrs(**attrs):
441+
''' Boolean attributes like 'disabled', 'required'
442+
are represented without a value. E.G.
443+
<input required ..> not <input required="required" ...>
444+
The latter is xhtml. Recognize booleans by:
445+
value is None
446+
value is the same as the atribute
447+
Code can use either method to indicate a pure boolean.
448+
'''
449+
return ' '.join(['%s="%s"'%(k,html_escape(str(v), True))
450+
if v != None and k != v else '%s'%(k)
451+
for k,v in sorted(attrs.items())])
452+
453+
def xhtml_cgi_escape_attrs(**attrs):
454+
''' Boolean attributes like 'disabled', 'required'
455+
are represented with a value that is the same as
456+
the attribute name.. E.G.
457+
<input required="required" ...> not <input required ..>
458+
The latter is html4 or 5. Recognize booleans by:
459+
value is None
460+
value is the same as the atribute
461+
Code can use either method to indicate a pure boolean.
462+
'''
441463
return ' '.join(['%s="%s"'%(k,html_escape(str(v), True))
442-
for k,v in sorted(attrs.items())])
464+
if v != None else '%s="%s"'%(k,k)
465+
for k,v in sorted(attrs.items())])
443466

444467
def input_html4(**attrs):
445468
"""Generate an 'input' (html4) element with given attributes"""
446469
_set_input_default_args(attrs)
447-
return '<input %s>'%cgi_escape_attrs(**attrs)
470+
return '<input %s>'%html4_cgi_escape_attrs(**attrs)
448471

449472
def input_xhtml(**attrs):
450473
"""Generate an 'input' (xhtml) element with given attributes"""
451474
_set_input_default_args(attrs)
452-
return '<input %s/>'%cgi_escape_attrs(**attrs)
475+
return '<input %s/>'%xhtml_cgi_escape_attrs(**attrs)
453476

454477
class HTMLInputMixin(object):
455478
""" requires a _client property """
@@ -459,8 +482,10 @@ def __init__(self):
459482
html_version = self._client.instance.config.HTML_VERSION
460483
if html_version == 'xhtml':
461484
self.input = input_xhtml
485+
self.cgi_escape_attrs=xhtml_cgi_escape_attrs
462486
else:
463487
self.input = input_html4
488+
self.cgi_escape_attrs=html4_cgi_escape_attrs
464489
# self._context is used for translations.
465490
# will be initialized by the first call to .gettext()
466491
self._context = None
@@ -767,7 +792,7 @@ def classhelp(self, properties=None, label=''"(list)", width='500',
767792
onclick = "javascript:help_window('%s', '%s', '%s');return false;" % \
768793
(help_url, width, height)
769794
return '<a class="classhelp" href="%s" onclick="%s" %s>%s</a>' % \
770-
(help_url, onclick, cgi_escape_attrs(**html_kwargs),
795+
(help_url, onclick, self.cgi_escape_attrs(**html_kwargs),
771796
self._(label))
772797

773798
def submit(self, label=''"Submit New Entry", action="new"):
@@ -1604,7 +1629,7 @@ def multiline(self, escape=0, rows=5, cols=40, **kwargs):
16041629

16051630
value = '&quot;'.join(value.split('"'))
16061631
name = self._formname
1607-
passthrough_args = cgi_escape_attrs(**kwargs)
1632+
passthrough_args = self.cgi_escape_attrs(**kwargs)
16081633
return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"'
16091634
' rows="%(rows)s" cols="%(cols)s">'
16101635
'%(value)s</textarea>') % locals()
@@ -2181,7 +2206,7 @@ def menu(self, size=None, height=None, showid=0, additional=[], value=None,
21812206
value = None
21822207

21832208
linkcl = self._db.getclass(self._prop.classname)
2184-
l = ['<select %s>'%cgi_escape_attrs(name = self._formname,
2209+
l = ['<select %s>'%self.cgi_escape_attrs(name = self._formname,
21852210
**html_kwargs)]
21862211
k = linkcl.labelprop(1)
21872212
s = ''
@@ -2443,7 +2468,7 @@ def menu(self, size=None, height=None, showid=0, additional=[],
24432468
# The "no selection" option.
24442469
height += 1
24452470
height = min(height, 7)
2446-
l = ['<select multiple %s>'%cgi_escape_attrs(name = self._formname,
2471+
l = ['<select multiple %s>'%self.cgi_escape_attrs(name = self._formname,
24472472
size = height,
24482473
**html_kwargs)]
24492474
k = linkcl.labelprop(1)

0 commit comments

Comments
 (0)