Code

Ticket #3515: 00-widget-outer-attrs.3.diff

File 00-widget-outer-attrs.3.diff, 8.7 KB (added by Petr Marhoun <petr.marhoun@…>, 6 years ago)
Line 
1=== modified file 'django/newforms/extras/widgets.py'
2--- django/newforms/extras/widgets.py   2007-11-13 02:22:10 +0000
3+++ django/newforms/extras/widgets.py   2007-11-21 21:28:06 +0000
4@@ -20,9 +20,9 @@
5     day_field = '%s_day'
6     year_field = '%s_year'
7 
8-    def __init__(self, attrs=None, years=None):
9+    def __init__(self, attrs=None, outer_attrs=None, years=None):
10         # years is an optional list/tuple of years to use in the "year" select box.
11-        self.attrs = attrs or {}
12+        super(SelectDateWidget, self).__init__(attrs, outer_attrs)
13         if years:
14             self.years = years
15         else:
16
17=== modified file 'django/newforms/forms.py'
18--- django/newforms/forms.py    2007-11-13 02:22:10 +0000
19+++ django/newforms/forms.py    2007-11-21 21:53:24 +0000
20@@ -131,6 +131,14 @@
21                     top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
22                 hidden_fields.append(unicode(bf))
23             else:
24+                outer_attrs = bf.field.widget.outer_attrs
25+                outer_class_list = outer_attrs.pop('class', '').split()
26+                if bf.field.required:
27+                    outer_class_list.append('required')
28+                if bf_errors:
29+                    outer_class_list.append('error')
30+                if outer_class_list:
31+                    outer_attrs['class'] = ' '.join(outer_class_list)
32                 if errors_on_separate_row and bf_errors:
33                     output.append(error_row % force_unicode(bf_errors))
34                 if bf.label:
35@@ -146,7 +154,8 @@
36                     help_text = help_text_html % force_unicode(field.help_text)
37                 else:
38                     help_text = u''
39-                output.append(normal_row % {'errors': force_unicode(bf_errors), 'label': force_unicode(label), 'field': unicode(bf), 'help_text': help_text})
40+                output.append(normal_row % {'errors': force_unicode(bf_errors), 'label': force_unicode(label),
41+                    'field': unicode(bf), 'help_text': help_text, 'outer_attrs': flatatt(outer_attrs)})
42         if top_errors:
43             output.insert(0, error_row % top_errors)
44         if hidden_fields: # Insert any hidden fields in the last row.
45@@ -161,15 +170,15 @@
46 
47     def as_table(self):
48         "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
49-        return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False)
50+        return self._html_output(u'<tr%(outer_attrs)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False)
51 
52     def as_ul(self):
53         "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
54-        return self._html_output(u'<li>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False)
55+        return self._html_output(u'<li%(outer_attrs)s>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False)
56 
57     def as_p(self):
58         "Returns this form rendered as HTML <p>s."
59-        return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'%s', '</p>', u' %s', True)
60+        return self._html_output(u'<p%(outer_attrs)s>%(label)s %(field)s%(help_text)s</p>', u'%s', '</p>', u' %s', True)
61 
62     def non_field_errors(self):
63         """
64
65=== modified file 'django/newforms/widgets.py'
66--- django/newforms/widgets.py  2007-11-13 02:22:10 +0000
67+++ django/newforms/widgets.py  2007-11-21 21:28:06 +0000
68@@ -130,15 +130,20 @@
69     is_hidden = False          # Determines whether this corresponds to an <input type="hidden">.
70     needs_multipart_form = False # Determines does this widget need multipart-encrypted form
71 
72-    def __init__(self, attrs=None):
73+    def __init__(self, attrs=None, outer_attrs=None):
74         if attrs is not None:
75             self.attrs = attrs.copy()
76         else:
77             self.attrs = {}
78+        if outer_attrs is not None:
79+            self.outer_attrs = outer_attrs.copy()
80+        else:
81+            self.outer_attrs = {}
82 
83     def __deepcopy__(self, memo):
84         obj = copy.copy(self)
85         obj.attrs = self.attrs.copy()
86+        obj.outer_attrs = self.outer_attrs.copy()
87         memo[id(self)] = obj
88         return obj
89 
90@@ -197,8 +202,8 @@
91 class PasswordInput(Input):
92     input_type = 'password'
93 
94-    def __init__(self, attrs=None, render_value=True):
95-        super(PasswordInput, self).__init__(attrs)
96+    def __init__(self, attrs=None, outer_attrs=None, render_value=True):
97+        super(PasswordInput, self).__init__(attrs, outer_attrs)
98         self.render_value = render_value
99 
100     def render(self, name, value, attrs=None):
101@@ -214,8 +219,8 @@
102     A widget that handles <input type="hidden"> for fields that have a list
103     of values.
104     """
105-    def __init__(self, attrs=None, choices=()):
106-        super(MultipleHiddenInput, self).__init__(attrs)
107+    def __init__(self, attrs=None, outer_attrs=None, choices=()):
108+        super(MultipleHiddenInput, self).__init__(attrs, outer_attrs)
109         # choices can be any iterable
110         self.choices = choices
111 
112@@ -241,11 +246,12 @@
113         return files.get(name, None)
114 
115 class Textarea(Widget):
116-    def __init__(self, attrs=None):
117+    def __init__(self, attrs=None, outer_attrs=None):
118         # The 'rows' and 'cols' attributes are required for HTML correctness.
119-        self.attrs = {'cols': '40', 'rows': '10'}
120+        default_attrs = {'cols': '40', 'rows': '10'}
121         if attrs:
122-            self.attrs.update(attrs)
123+            default_attrs.update(attrs)
124+        super(Textarea, self, default_attrs, outer_attrs)
125 
126     def render(self, name, value, attrs=None):
127         if value is None: value = ''
128@@ -257,8 +263,8 @@
129     input_type = 'text'
130     format = '%Y-%m-%d %H:%M:%S'     # '2006-10-25 14:30:59'
131 
132-    def __init__(self, attrs=None, format=None):
133-        super(DateTimeInput, self).__init__(attrs)
134+    def __init__(self, attrs=None, outer_attrs=None, format=None):
135+        super(DateTimeInput, self).__init__(attrs, outer_attrs)
136         if format:
137             self.format = format
138 
139@@ -270,8 +276,8 @@
140         return super(DateTimeInput, self).render(name, value, attrs)
141 
142 class CheckboxInput(Widget):
143-    def __init__(self, attrs=None, check_test=bool):
144-        super(CheckboxInput, self).__init__(attrs)
145+    def __init__(self, attrs=None, outer_attrs=None, check_test=bool):
146+        super(CheckboxInput, self).__init__(attrs, outer_attrs)
147         # check_test is a callable that takes a value and returns True
148         # if the checkbox should be checked for that value.
149         self.check_test = check_test
150@@ -296,8 +302,8 @@
151         return super(CheckboxInput, self).value_from_datadict(data, files, name)
152 
153 class Select(Widget):
154-    def __init__(self, attrs=None, choices=()):
155-        super(Select, self).__init__(attrs)
156+    def __init__(self, attrs=None, outer_attrs=None, choices=()):
157+        super(Select, self).__init__(attrs, outer_attrs)
158         # choices can be any iterable, but we may need to render this widget
159         # multiple times. Thus, collapse it into a list so it can be consumed
160         # more than once.
161@@ -319,9 +325,9 @@
162     """
163     A Select Widget intended to be used with NullBooleanField.
164     """
165-    def __init__(self, attrs=None):
166+    def __init__(self, attrs=None, outer_attrs=None):
167         choices = ((u'1', ugettext('Unknown')), (u'2', ugettext('Yes')), (u'3', ugettext('No')))
168-        super(NullBooleanSelect, self).__init__(attrs, choices)
169+        super(NullBooleanSelect, self).__init__(attrs, outer_attrs, choices)
170 
171     def render(self, name, value, attrs=None, choices=()):
172         try:
173@@ -490,9 +496,9 @@
174 
175     You'll probably want to use this class with MultiValueField.
176     """
177-    def __init__(self, widgets, attrs=None):
178+    def __init__(self, widgets, attrs=None, outer_attrs=None):
179         self.widgets = [isinstance(w, type) and w() or w for w in widgets]
180-        super(MultiWidget, self).__init__(attrs)
181+        super(MultiWidget, self).__init__(attrs, outer_attrs)
182 
183     def render(self, name, value, attrs=None):
184         # value is a list of values, each corresponding to a widget
185@@ -552,9 +558,9 @@
186     """
187     A Widget that splits datetime input into two <input type="text"> boxes.
188     """
189-    def __init__(self, attrs=None):
190+    def __init__(self, attrs=None, outer_attrs=None):
191         widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs))
192-        super(SplitDateTimeWidget, self).__init__(widgets, attrs)
193+        super(SplitDateTimeWidget, self).__init__(widgets, attrs, outer_attrs)
194 
195     def decompress(self, value):
196         if value:
197