comparison roundup/cgi/templating.py @ 4267:c5f52c2c9e36

Provide ability to specify arbitrary HTML attributes.
author Stefan Seefeld <stefan@seefeld.name>
date Fri, 09 Oct 2009 13:58:43 +0000
parents 01ef28bffcbd
children b78eb8fc821a
comparison
equal deleted inserted replaced
4266:2b75274936bc 4267:c5f52c2c9e36
418 else: 418 else:
419 dic['id'] = dic['name'] 419 dic['id'] = dic['name']
420 except KeyError: 420 except KeyError:
421 pass 421 pass
422 422
423 def cgi_escape_attrs(**attrs):
424 return ' '.join(['%s="%s"'%(k,cgi.escape(str(v), True))
425 for k,v in attrs.items()])
426
423 def input_html4(**attrs): 427 def input_html4(**attrs):
424 """Generate an 'input' (html4) element with given attributes""" 428 """Generate an 'input' (html4) element with given attributes"""
425 _set_input_default_args(attrs) 429 _set_input_default_args(attrs)
426 return '<input %s>'%' '.join(['%s="%s"'%(k,cgi.escape(str(v), True)) 430 return '<input %s>'%cgi_escape_attrs(**attrs)
427 for k,v in attrs.items()])
428 431
429 def input_xhtml(**attrs): 432 def input_xhtml(**attrs):
430 """Generate an 'input' (xhtml) element with given attributes""" 433 """Generate an 'input' (xhtml) element with given attributes"""
431 _set_input_default_args(attrs) 434 _set_input_default_args(attrs)
432 return '<input %s/>'%' '.join(['%s="%s"'%(k,cgi.escape(str(v), True)) 435 return '<input %s/>'%cgi_escape_attrs(**attrs)
433 for k,v in attrs.items()])
434 436
435 class HTMLInputMixin: 437 class HTMLInputMixin:
436 """ requires a _client property """ 438 """ requires a _client property """
437 def __init__(self): 439 def __init__(self):
438 html_version = 'html4' 440 html_version = 'html4'
1462 else: 1464 else:
1463 value = cgi.escape(str(self._value)) 1465 value = cgi.escape(str(self._value))
1464 1466
1465 value = '&quot;'.join(value.split('"')) 1467 value = '&quot;'.join(value.split('"'))
1466 name = self._formname 1468 name = self._formname
1467 passthrough_args = ' '.join(['%s="%s"' % (k, cgi.escape(str(v), True)) 1469 passthrough_args = cgi_escape_attrs(**kwargs)
1468 for k,v in kwargs.items()])
1469 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"' 1470 return ('<textarea %(passthrough_args)s name="%(name)s" id="%(name)s"'
1470 ' rows="%(rows)s" cols="%(cols)s">' 1471 ' rows="%(rows)s" cols="%(cols)s">'
1471 '%(value)s</textarea>') % locals() 1472 '%(value)s</textarea>') % locals()
1472 1473
1473 def email(self, escape=1): 1474 def email(self, escape=1):
1501 1502
1502 if self._value is None: 1503 if self._value is None:
1503 return '' 1504 return ''
1504 return self._('*encrypted*') 1505 return self._('*encrypted*')
1505 1506
1506 def field(self, size=30): 1507 def field(self, size=30, **kwargs):
1507 """ Render a form edit field for the property. 1508 """ Render a form edit field for the property.
1508 1509
1509 If not editable, just display the value via plain(). 1510 If not editable, just display the value via plain().
1510 """ 1511 """
1511 if not self.is_edit_ok(): 1512 if not self.is_edit_ok():
1512 return self.plain(escape=1) 1513 return self.plain(escape=1)
1513 1514
1514 return self.input(type="password", name=self._formname, size=size) 1515 return self.input(type="password", name=self._formname, size=size,
1516 **kwargs)
1515 1517
1516 def confirm(self, size=30): 1518 def confirm(self, size=30):
1517 """ Render a second form edit field for the property, used for 1519 """ Render a second form edit field for the property, used for
1518 confirmation that the user typed the password correctly. Generates 1520 confirmation that the user typed the password correctly. Generates
1519 a field with name "@confirm@name". 1521 a field with name "@confirm@name".
1538 if self._value is None: 1540 if self._value is None:
1539 return '' 1541 return ''
1540 1542
1541 return str(self._value) 1543 return str(self._value)
1542 1544
1543 def field(self, size=30): 1545 def field(self, size=30, **kwargs):
1544 """ Render a form edit field for the property. 1546 """ Render a form edit field for the property.
1545 1547
1546 If not editable, just display the value via plain(). 1548 If not editable, just display the value via plain().
1547 """ 1549 """
1548 if not self.is_edit_ok(): 1550 if not self.is_edit_ok():
1550 1552
1551 value = self._value 1553 value = self._value
1552 if value is None: 1554 if value is None:
1553 value = '' 1555 value = ''
1554 1556
1555 return self.input(name=self._formname, value=value, size=size) 1557 return self.input(name=self._formname, value=value, size=size,
1558 **kwargs)
1556 1559
1557 def __int__(self): 1560 def __int__(self):
1558 """ Return an int of me 1561 """ Return an int of me
1559 """ 1562 """
1560 return int(self._value) 1563 return int(self._value)
1574 1577
1575 if self._value is None: 1578 if self._value is None:
1576 return '' 1579 return ''
1577 return self._value and self._("Yes") or self._("No") 1580 return self._value and self._("Yes") or self._("No")
1578 1581
1579 def field(self): 1582 def field(self, **kwargs):
1580 """ Render a form edit field for the property 1583 """ Render a form edit field for the property
1581 1584
1582 If not editable, just display the value via plain(). 1585 If not editable, just display the value via plain().
1583 """ 1586 """
1584 if not self.is_edit_ok(): 1587 if not self.is_edit_ok():
1590 'on', '1') 1593 'on', '1')
1591 1594
1592 checked = value and "checked" or "" 1595 checked = value and "checked" or ""
1593 if value: 1596 if value:
1594 s = self.input(type="radio", name=self._formname, value="yes", 1597 s = self.input(type="radio", name=self._formname, value="yes",
1595 checked="checked") 1598 checked="checked", **kwargs)
1596 s += self._('Yes') 1599 s += self._('Yes')
1597 s +=self.input(type="radio", name=self._formname, value="no") 1600 s +=self.input(type="radio", name=self._formname, value="no",
1601 **kwargs)
1598 s += self._('No') 1602 s += self._('No')
1599 else: 1603 else:
1600 s = self.input(type="radio", name=self._formname, value="yes") 1604 s = self.input(type="radio", name=self._formname, value="yes",
1605 **kwargs)
1601 s += self._('Yes') 1606 s += self._('Yes')
1602 s +=self.input(type="radio", name=self._formname, value="no", 1607 s +=self.input(type="radio", name=self._formname, value="no",
1603 checked="checked") 1608 checked="checked", **kwargs)
1604 s += self._('No') 1609 s += self._('No')
1605 return s 1610 return s
1606 1611
1607 class DateHTMLProperty(HTMLProperty): 1612 class DateHTMLProperty(HTMLProperty):
1608 1613
1656 ret = ret - interval 1661 ret = ret - interval
1657 1662
1658 return DateHTMLProperty(self._client, self._classname, self._nodeid, 1663 return DateHTMLProperty(self._client, self._classname, self._nodeid,
1659 self._prop, self._formname, ret) 1664 self._prop, self._formname, ret)
1660 1665
1661 def field(self, size=30, default=None, format=_marker, popcal=True): 1666 def field(self, size=30, default=None, format=_marker, popcal=True,
1667 **kwargs):
1662 """Render a form edit field for the property 1668 """Render a form edit field for the property
1663 1669
1664 If not editable, just display the value via plain(). 1670 If not editable, just display the value via plain().
1665 1671
1666 If "popcal" then include the Javascript calendar editor. 1672 If "popcal" then include the Javascript calendar editor.
1691 'DateHTMLProperty must be either DateHTMLProperty ' 1697 'DateHTMLProperty must be either DateHTMLProperty '
1692 'or string date representation.') 1698 'or string date representation.')
1693 elif isinstance(value, str) or isinstance(value, unicode): 1699 elif isinstance(value, str) or isinstance(value, unicode):
1694 # most likely erroneous input to be passed back to user 1700 # most likely erroneous input to be passed back to user
1695 if isinstance(value, unicode): value = value.encode('utf8') 1701 if isinstance(value, unicode): value = value.encode('utf8')
1696 return self.input(name=self._formname, value=value, size=size) 1702 return self.input(name=self._formname, value=value, size=size,
1703 **kwargs)
1697 else: 1704 else:
1698 raw_value = value 1705 raw_value = value
1699 1706
1700 if raw_value is None: 1707 if raw_value is None:
1701 value = '' 1708 value = ''
1711 offset = self._offset 1718 offset = self._offset
1712 value = raw_value.local(offset) 1719 value = raw_value.local(offset)
1713 if format is not self._marker: 1720 if format is not self._marker:
1714 value = value.pretty(format) 1721 value = value.pretty(format)
1715 1722
1716 s = self.input(name=self._formname, value=value, size=size) 1723 s = self.input(name=self._formname, value=value, size=size,
1724 **kwargs)
1717 if popcal: 1725 if popcal:
1718 s += self.popcal() 1726 s += self.popcal()
1719 return s 1727 return s
1720 1728
1721 def reldate(self, pretty=1): 1729 def reldate(self, pretty=1):
1806 if not self.is_view_ok(): 1814 if not self.is_view_ok():
1807 return self._('[hidden]') 1815 return self._('[hidden]')
1808 1816
1809 return self._value.pretty() 1817 return self._value.pretty()
1810 1818
1811 def field(self, size=30): 1819 def field(self, size=30, **kwargs):
1812 """ Render a form edit field for the property 1820 """ Render a form edit field for the property
1813 1821
1814 If not editable, just display the value via plain(). 1822 If not editable, just display the value via plain().
1815 """ 1823 """
1816 if not self.is_edit_ok(): 1824 if not self.is_edit_ok():
1818 1826
1819 value = self._value 1827 value = self._value
1820 if value is None: 1828 if value is None:
1821 value = '' 1829 value = ''
1822 1830
1823 return self.input(name=self._formname, value=value, size=size) 1831 return self.input(name=self._formname, value=value, size=size,
1832 **kwargs)
1824 1833
1825 class LinkHTMLProperty(HTMLProperty): 1834 class LinkHTMLProperty(HTMLProperty):
1826 """ Link HTMLProperty 1835 """ Link HTMLProperty
1827 Include the above as well as being able to access the class 1836 Include the above as well as being able to access the class
1828 information. Stringifying the object itself results in the value 1837 information. Stringifying the object itself results in the value
1871 value = self._value 1880 value = self._value
1872 if escape: 1881 if escape:
1873 value = cgi.escape(value) 1882 value = cgi.escape(value)
1874 return value 1883 return value
1875 1884
1876 def field(self, showid=0, size=None): 1885 def field(self, showid=0, size=None, **kwargs):
1877 """ Render a form edit field for the property 1886 """ Render a form edit field for the property
1878 1887
1879 If not editable, just display the value via plain(). 1888 If not editable, just display the value via plain().
1880 """ 1889 """
1881 if not self.is_edit_ok(): 1890 if not self.is_edit_ok():
1889 k = linkcl.getkey() 1898 k = linkcl.getkey()
1890 if k and num_re.match(self._value): 1899 if k and num_re.match(self._value):
1891 value = linkcl.get(self._value, k) 1900 value = linkcl.get(self._value, k)
1892 else: 1901 else:
1893 value = self._value 1902 value = self._value
1894 return self.input(name=self._formname, value=value, size=size) 1903 return self.input(name=self._formname, value=value, size=size,
1904 **kwargs)
1895 1905
1896 def menu(self, size=None, height=None, showid=0, additional=[], value=None, 1906 def menu(self, size=None, height=None, showid=0, additional=[], value=None,
1897 sort_on=None, **conditions): 1907 sort_on=None, html_kwargs = {}, **conditions):
1898 """ Render a form select list for this property 1908 """ Render a form select list for this property
1899 1909
1900 "size" is used to limit the length of the list labels 1910 "size" is used to limit the length of the list labels
1901 "height" is used to set the <select> tag's "size" attribute 1911 "height" is used to set the <select> tag's "size" attribute
1902 "showid" includes the item ids in the list labels 1912 "showid" includes the item ids in the list labels
1925 value = self._value 1935 value = self._value
1926 elif value == '-1': 1936 elif value == '-1':
1927 value = None 1937 value = None
1928 1938
1929 linkcl = self._db.getclass(self._prop.classname) 1939 linkcl = self._db.getclass(self._prop.classname)
1930 l = ['<select name="%s">'%self._formname] 1940 l = ['<select %s>'%cgi_escape_attrs(name = self._formname,
1941 **html_kwargs)]
1931 k = linkcl.labelprop(1) 1942 k = linkcl.labelprop(1)
1932 s = '' 1943 s = ''
1933 if value is None: 1944 if value is None:
1934 s = 'selected="selected" ' 1945 s = 'selected="selected" '
1935 l.append(self._('<option %svalue="-1">- no selection -</option>')%s) 1946 l.append(self._('<option %svalue="-1">- no selection -</option>')%s)
2091 value = ', '.join(labels) 2102 value = ', '.join(labels)
2092 if escape: 2103 if escape:
2093 value = cgi.escape(value) 2104 value = cgi.escape(value)
2094 return value 2105 return value
2095 2106
2096 def field(self, size=30, showid=0): 2107 def field(self, size=30, showid=0, **kwargs):
2097 """ Render a form edit field for the property 2108 """ Render a form edit field for the property
2098 2109
2099 If not editable, just display the value via plain(). 2110 If not editable, just display the value via plain().
2100 """ 2111 """
2101 if not self.is_edit_ok(): 2112 if not self.is_edit_ok():
2108 showid=1 2119 showid=1
2109 if not showid: 2120 if not showid:
2110 k = linkcl.labelprop(1) 2121 k = linkcl.labelprop(1)
2111 value = lookupKeys(linkcl, k, value) 2122 value = lookupKeys(linkcl, k, value)
2112 value = ','.join(value) 2123 value = ','.join(value)
2113 return self.input(name=self._formname, size=size, value=value) 2124 return self.input(name=self._formname, size=size, value=value,
2125 **kwargs)
2114 2126
2115 def menu(self, size=None, height=None, showid=0, additional=[], 2127 def menu(self, size=None, height=None, showid=0, additional=[],
2116 value=None, sort_on=None, **conditions): 2128 value=None, sort_on=None, html_kwargs = {}, **conditions):
2117 """ Render a form <select> list for this property. 2129 """ Render a form <select> list for this property.
2118 2130
2119 "size" is used to limit the length of the list labels 2131 "size" is used to limit the length of the list labels
2120 "height" is used to set the <select> tag's "size" attribute 2132 "height" is used to set the <select> tag's "size" attribute
2121 "showid" includes the item ids in the list labels 2133 "showid" includes the item ids in the list labels
2164 height = len(options) 2176 height = len(options)
2165 if value: 2177 if value:
2166 # The "no selection" option. 2178 # The "no selection" option.
2167 height += 1 2179 height += 1
2168 height = min(height, 7) 2180 height = min(height, 7)
2169 l = ['<select multiple name="%s" size="%s">'%(self._formname, height)] 2181 l = ['<select multiple %s>'%cgi_escape_attrs(name = self._formname,
2182 size = height,
2183 **html_kwargs)]
2170 k = linkcl.labelprop(1) 2184 k = linkcl.labelprop(1)
2171 2185
2172 if value: 2186 if value:
2173 l.append('<option value="%s">- no selection -</option>' 2187 l.append('<option value="%s">- no selection -</option>'
2174 % ','.join(['-' + v for v in value])) 2188 % ','.join(['-' + v for v in value]))

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