Mercurial > p > roundup > code
comparison roundup/cgi/templating.py @ 5988:39b8bc511ed7
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.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sat, 14 Dec 2019 16:18:15 -0500 |
| parents | fe334430ca07 |
| children | b0940ad50f43 |
comparison
equal
deleted
inserted
replaced
| 5987:ea3485c67f94 | 5988:39b8bc511ed7 |
|---|---|
| 435 else: | 435 else: |
| 436 dic['id'] = dic['name'] | 436 dic['id'] = dic['name'] |
| 437 except KeyError: | 437 except KeyError: |
| 438 pass | 438 pass |
| 439 | 439 |
| 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 ''' | |
| 441 return ' '.join(['%s="%s"'%(k,html_escape(str(v), True)) | 463 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())]) | |
| 443 | 466 |
| 444 def input_html4(**attrs): | 467 def input_html4(**attrs): |
| 445 """Generate an 'input' (html4) element with given attributes""" | 468 """Generate an 'input' (html4) element with given attributes""" |
| 446 _set_input_default_args(attrs) | 469 _set_input_default_args(attrs) |
| 447 return '<input %s>'%cgi_escape_attrs(**attrs) | 470 return '<input %s>'%html4_cgi_escape_attrs(**attrs) |
| 448 | 471 |
| 449 def input_xhtml(**attrs): | 472 def input_xhtml(**attrs): |
| 450 """Generate an 'input' (xhtml) element with given attributes""" | 473 """Generate an 'input' (xhtml) element with given attributes""" |
| 451 _set_input_default_args(attrs) | 474 _set_input_default_args(attrs) |
| 452 return '<input %s/>'%cgi_escape_attrs(**attrs) | 475 return '<input %s/>'%xhtml_cgi_escape_attrs(**attrs) |
| 453 | 476 |
| 454 class HTMLInputMixin(object): | 477 class HTMLInputMixin(object): |
| 455 """ requires a _client property """ | 478 """ requires a _client property """ |
| 456 def __init__(self): | 479 def __init__(self): |
| 457 html_version = 'html4' | 480 html_version = 'html4' |
| 458 if hasattr(self._client.instance.config, 'HTML_VERSION'): | 481 if hasattr(self._client.instance.config, 'HTML_VERSION'): |
| 459 html_version = self._client.instance.config.HTML_VERSION | 482 html_version = self._client.instance.config.HTML_VERSION |
| 460 if html_version == 'xhtml': | 483 if html_version == 'xhtml': |
| 461 self.input = input_xhtml | 484 self.input = input_xhtml |
| 485 self.cgi_escape_attrs=xhtml_cgi_escape_attrs | |
| 462 else: | 486 else: |
| 463 self.input = input_html4 | 487 self.input = input_html4 |
| 488 self.cgi_escape_attrs=html4_cgi_escape_attrs | |
| 464 # self._context is used for translations. | 489 # self._context is used for translations. |
| 465 # will be initialized by the first call to .gettext() | 490 # will be initialized by the first call to .gettext() |
| 466 self._context = None | 491 self._context = None |
| 467 | 492 |
| 468 def gettext(self, msgid): | 493 def gettext(self, msgid): |
| 765 (self.classname, properties, property, form, type, | 790 (self.classname, properties, property, form, type, |
| 766 group, sort, pagesize, filter) | 791 group, sort, pagesize, filter) |
| 767 onclick = "javascript:help_window('%s', '%s', '%s');return false;" % \ | 792 onclick = "javascript:help_window('%s', '%s', '%s');return false;" % \ |
| 768 (help_url, width, height) | 793 (help_url, width, height) |
| 769 return '<a class="classhelp" href="%s" onclick="%s" %s>%s</a>' % \ | 794 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), |
| 771 self._(label)) | 796 self._(label)) |
| 772 | 797 |
| 773 def submit(self, label=''"Submit New Entry", action="new"): | 798 def submit(self, label=''"Submit New Entry", action="new"): |
| 774 """ Generate a submit button (and action hidden element) | 799 """ Generate a submit button (and action hidden element) |
| 775 | 800 |
| 1602 else: | 1627 else: |
| 1603 value = html_escape(str(self._value)) | 1628 value = html_escape(str(self._value)) |
| 1604 | 1629 |
| 1605 value = '"'.join(value.split('"')) | 1630 value = '"'.join(value.split('"')) |
| 1606 name = self._formname | 1631 name = self._formname |
| 1607 passthrough_args = cgi_escape_attrs(**kwargs) | 1632 passthrough_args = self.cgi_escape_attrs(**kwargs) |
| 1608 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"' | 1633 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"' |
| 1609 ' rows="%(rows)s" cols="%(cols)s">' | 1634 ' rows="%(rows)s" cols="%(cols)s">' |
| 1610 '%(value)s</textarea>') % locals() | 1635 '%(value)s</textarea>') % locals() |
| 1611 | 1636 |
| 1612 def email(self, escape=1): | 1637 def email(self, escape=1): |
| 2179 value = self._value | 2204 value = self._value |
| 2180 elif value == '-1': | 2205 elif value == '-1': |
| 2181 value = None | 2206 value = None |
| 2182 | 2207 |
| 2183 linkcl = self._db.getclass(self._prop.classname) | 2208 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, |
| 2185 **html_kwargs)] | 2210 **html_kwargs)] |
| 2186 k = linkcl.labelprop(1) | 2211 k = linkcl.labelprop(1) |
| 2187 s = '' | 2212 s = '' |
| 2188 if value is None: | 2213 if value is None: |
| 2189 s = 'selected="selected" ' | 2214 s = 'selected="selected" ' |
| 2441 height = len(options) | 2466 height = len(options) |
| 2442 if value: | 2467 if value: |
| 2443 # The "no selection" option. | 2468 # The "no selection" option. |
| 2444 height += 1 | 2469 height += 1 |
| 2445 height = min(height, 7) | 2470 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, |
| 2447 size = height, | 2472 size = height, |
| 2448 **html_kwargs)] | 2473 **html_kwargs)] |
| 2449 k = linkcl.labelprop(1) | 2474 k = linkcl.labelprop(1) |
| 2450 | 2475 |
| 2451 if value: | 2476 if value: |
