Hi all,

the select-form-widget and the selectmultiple-form-widget display's a 
choices-list as

<select ...>
 <option>...
 ...
</select>

From the per-row-level-permision branch there is an alternative issue to do 
something like this:

<select ...>
 <optgroup label="...">
   <option>...
 </optgroup>
 ...
</select>

I made 2 new widgets, selectgrouped and selectmultiplegrouped, which would 
resolve such an issue. The optgroup is inserted into choices like a normal 
option: choices= ( ['__group__', 'label for group'], ['value1', 'label1'])

I added a simple example into the regression tests.

I would be also possible to merge the select/selectgrouped widget into one 
widget, which I would prefer to be the best solution.

Regards,
Dirk
--
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen! Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Index: django/newforms/widgets.py
===================================================================
--- django/newforms/widgets.py	(Revision 4293)
+++ django/newforms/widgets.py	(Arbeitskopie)
@@ -134,6 +134,28 @@
         output.append(u'</select>')
         return u'\n'.join(output)
 
+class SelectGrouped(Select):
+    def render(self, name, value, attrs=None, choices=()):
+        in_optgroup = False
+        if value is None: value = ''
+        final_attrs = self.build_attrs(attrs, name=name)
+        output = [u'<select%s>' % flatatt(final_attrs)]
+        str_value = smart_unicode(value) # Normalize to string.
+        for option_value, option_label in chain(self.choices, choices):
+            option_value = smart_unicode(option_value)
+            if option_value == u'__group__':
+                if in_optgroup:
+                    output.append(u'</optgroup>')
+                output.append(u'<optgroup label="%s">' % escape(smart_unicode(option_label)))
+                in_optgroup = True
+                continue
+            selected_html = (option_value == str_value) and u' selected="selected"' or ''
+            output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(smart_unicode(option_label))))
+        if in_optgroup:
+            output.append(u'</optgroup>')
+        output.append(u'</select>')
+        return u'\n'.join(output)
+      
 class SelectMultiple(Widget):
     def __init__(self, attrs=None, choices=()):
         # choices can be any iterable
@@ -157,6 +179,28 @@
             return data.getlist(name)
         return data.get(name, None)
 
+class SelectMultipleGrouped(SelectMultiple):
+    def render(self, name, value, attrs=None, choices=()):
+        in_optgroup = False
+        if value is None: value = []
+        final_attrs = self.build_attrs(attrs, name=name)
+        output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)]
+        str_values = set([smart_unicode(v) for v in value]) # Normalize to strings.
+        for option_value, option_label in chain(self.choices, choices):
+            option_value = smart_unicode(option_value)
+            if option_value == u'__group__':
+                if in_optgroup:
+                    output.append(u'</optgroup>')
+                output.append(u'<optgroup label="%s">' % escape(smart_unicode(option_label)))
+                in_optgroup = True
+                continue
+            selected_html = (option_value in str_values) and ' selected="selected"' or ''
+            output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(smart_unicode(option_label))))
+        if in_optgroup:
+            output.append(u'</optgroup>')
+        output.append(u'</select>')
+        return u'\n'.join(output)
+
 class RadioInput(StrAndUnicode):
     "An object used by RadioFieldRenderer that represents a single <input type='radio'>."
     def __init__(self, name, value, attrs, choice, index):
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(Revision 4293)
+++ tests/regressiontests/forms/tests.py	(Arbeitskopie)
@@ -3,6 +3,7 @@
 >>> from django.newforms import *
 >>> import datetime
 >>> import re
+>>> from django.newforms.widgets import SelectGrouped, SelectMultipleGrouped
 
 ###########
 # Widgets #
@@ -31,6 +32,31 @@
 >>> w.render('email', 'ŠĐĆŜćşšđ', attrs={'class': 'fun'})
 u'<input type="text" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" class="fun" />'
 
+### SelectGrouped Widget
+
+>>> choices = []
+>>> choices.append(['__group__', 'label for group 1'])
+>>> choices.append(['value1', 'label1'])
+>>> choices.append(['value2', 'label2'])
+>>> choices.append(['__group__', 'label for group 2'])
+>>> choices.append(['value3', 'label3'])
+>>> choices.append(['value4', 'label4'])
+>>> w = SelectGrouped(choices=choices)
+>>> w.render('name','value1')
+u'<select name="name">\n<optgroup label="label for group 1">\n<option value="value1" selected="selected">label1</option>\n<option value="value2">label2</option>\n</optgroup>\n<optgroup label="label for group 2">\n<option value="value3">label3</option>\n<option value="value4">label4</option>\n</optgroup>\n</select>'
+
+### SelectMultipleGrouped Widget
+>>> choices = []
+>>> choices.append(['__group__', 'label for group 1'])
+>>> choices.append(['value1', 'label1'])
+>>> choices.append(['value2', 'label2'])
+>>> choices.append(['__group__', 'label for group 2'])
+>>> choices.append(['value3', 'label3'])
+>>> choices.append(['value4', 'label4'])
+>>> w = SelectGrouped(choices=choices)
+>>> w.render('name','value1')
+u'<select name="name">\n<optgroup label="label for group 1">\n<option value="value1" selected="selected">label1</option>\n<option value="value2">label2</option>\n</optgroup>\n<optgroup label="label for group 2">\n<option value="value3">label3</option>\n<option value="value4">label4</option>\n</optgroup>\n</select>'
+
 You can also pass 'attrs' to the constructor:
 >>> w = TextInput(attrs={'class': 'fun'})
 >>> w.render('email', '')

Reply via email to