--- form2/widget.py.orig0 2003-11-16 16:09:37.000000000 -0500 +++ form2/widget.py 2003-11-30 10:07:31.000000000 -0500 @@ -31,14 +31,21 @@ name : string value : any error : string + html_attrs : { string : any } + arbitrary HTML attribute values; will be added to the tag + used to render this widget Feel free to access these directly; to set them, use the 'set_*()' modifier methods. """ - def __init__(self, name, value=None): + def __init__(self, name, value=None, html_attrs=None): assert self.__class__ is not Widget, "abstract class" self.name = name + if html_attrs is None: + self.html_attrs = {} + else: + self.html_attrs = html_attrs self.error = None request = get_request() if request.form: @@ -106,27 +113,20 @@ Instance attributes: value : string - size : int - maxlength : int """ # This lets PasswordWidget be a trivial subclass HTML_TYPE = "text" - def __init__(self, name, value=None, - size=None, maxlength=None): - Widget.__init__(self, name, value) - self.size = size - self.maxlength = maxlength + def __init__(self, name, value=None, html_attrs=None): + Widget.__init__(self, name, value, html_attrs) - def render(self, **attributes): + def render(self): return htmltag("input", xml_end=True, type=self.HTML_TYPE, name=self.name, - size=self.size, - maxlength=self.maxlength, value=self.value, - **attributes) + **self.html_attrs) class FileWidget(StringWidget): @@ -161,17 +161,10 @@ Instance attributes: value : string - cols : int - rows : int - wrap : string - (see an HTML book for details on text widget wrap options) """ - def __init__(self, name, value=None, cols=None, rows=None, wrap=None): - Widget.__init__(self, name, value) - self.cols = cols - self.rows = rows - self.wrap = wrap + def __init__(self, name, value=None, html_attrs=None): + Widget.__init__(self, name, value, html_attrs) def _parse(self, request): Widget._parse(self, request) @@ -179,10 +172,7 @@ self.value = self.value.replace("\r\n", "\n") def render(self): - return (htmltag("textarea", name=self.name, - cols=self.cols, - rows=self.rows, - wrap=self.wrap) + + return (htmltag("textarea", name=self.name, **self.html_attrs) + htmlescape(self.value or "") + htmltext("")) @@ -204,7 +194,8 @@ type="checkbox", name=self.name, value="yes", - checked=self.value and ValuelessAttr or None) + checked=self.value and ValuelessAttr or None, + **self.html_attrs) @@ -225,17 +216,16 @@ def __init__(self, name, value=None, options=None, - size=None, sort=True, - verify_selection=True): + verify_selection=True, + html_attrs=None): assert self.__class__ is not SelectWidget, "abstract class" self.options = [] if options is not None: assert options, 'cannot pass empty options list' self.set_options(options, sort) self.verify_selection = verify_selection - self.size = size - Widget.__init__(self, name, value) + Widget.__init__(self, name, value, html_attrs) def get_allowed_values(self): return [item[0] for item in self.options] @@ -371,13 +361,13 @@ multiple = ValuelessAttr else: multiple = None - if self.SELECT_TYPE == "option_select": - onchange = "submit()" - else: - onchange = None - tags = [htmltag("select", name=self.name, - multiple=multiple, onchange=onchange, - size=self.size)] + if ('onchange' not in self.html_attrs and + self.SELECT_TYPE == "option_select"): + self.html_attrs['onchange'] = "submit()" + tags = [htmltag("select", + name=self.name, + multiple=multiple, + **self.html_attrs)] for object, description, key in self.options: if self.is_selected(object): selected = ValuelessAttr @@ -423,10 +413,12 @@ def __init__(self, name, value=None, options=None, - delim=None): + delim=None, + html_attrs=None): SingleSelectWidget.__init__(self, name, value=value, - options=options) + options=options, + html_attrs=html_attrs) if delim is None: self.delim = "\n" else: @@ -443,7 +435,8 @@ type="radio", name=self.name, value=key, - checked=checked) + checked=checked, + **html_attrs) tags.append(r + htmlescape(description) + htmltext('')) return htmlescape(self.delim).join(tags) @@ -498,7 +491,7 @@ HTML_TYPE = "button" - def __init__(self, name, value=None): + def __init__(self, name, value=None, html_attrs=None): self.name = name self.error = None # slightly different behavior here, we always render the @@ -506,6 +499,10 @@ # attribute is a boolean that is true if the button's name appears # in the request. self.label = value + if html_attrs is None: + self.html_attrs = {} + else: + self.html_attrs = html_attrs request = get_request() if request.form: self._parse(request) @@ -518,7 +515,7 @@ def render(self): value = (self.label and htmlescape(self.label) or None) return htmltag("input", xml_end=True, type=self.HTML_TYPE, - name=self.name, value=value) + name=self.name, value=value, **self.html_attrs) def _parse(self, request): self.value = request.form.has_key(self.name) @@ -549,7 +546,8 @@ return htmltag("input", xml_end=True, type="hidden", name=self.name, - value=value) + value=value, + **self.html_attrs) # -- Derived widget types ---------------------------------------------- @@ -569,13 +567,13 @@ def __init__(self, name, value=None, - size=None, maxlength=None): + html_attrs=None): assert self.__class__ is not NumberWidget, "abstract class" assert value is None or type(value) is self.TYPE_OBJECT, ( "form value '%s' not a %s: got %r" % (name, self.TYPE_OBJECT, value)) - StringWidget.__init__(self, name, value, size, maxlength) + StringWidget.__init__(self, name, value, html_attrs) def _parse(self, request): StringWidget._parse(self, request)