Add a DropDownMultiple form widget.
authorMatthijs Kooijman <matthijs@stdin.nl>
Sun, 1 Feb 2009 17:31:37 +0000 (18:31 +0100)
committerMatthijs Kooijman <matthijs@stdin.nl>
Sun, 1 Feb 2009 17:37:29 +0000 (18:37 +0100)
This code is taken literally from
http://www.djangosnippets.org/snippets/747/, only "newforms" was changed
to "forms".

tools/widgets/__init__.py [new file with mode: 0644]
tools/widgets/dropdownmultiple.py [new file with mode: 0644]

diff --git a/tools/widgets/__init__.py b/tools/widgets/__init__.py
new file mode 100644 (file)
index 0000000..1608809
--- /dev/null
@@ -0,0 +1 @@
+from dropdownmultiple import DropDownMultiple
diff --git a/tools/widgets/dropdownmultiple.py b/tools/widgets/dropdownmultiple.py
new file mode 100644 (file)
index 0000000..37e17e4
--- /dev/null
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+from django.forms import widgets
+from django.utils.safestring import mark_safe
+from django.utils.datastructures import MultiValueDict
+from django.newforms.util import flatatt
+
+TPL_OPTION = """<option value="%(value)s" %(selected)s>%(desc)s</option>"""
+
+TPL_SELECT = """
+<select class="dropdown_select" %(attrs)s>
+%(opts)s
+</select>
+"""
+
+TPL_SCRIPT = """
+<script>
+    $('span#%(id)s>select.dropdown_select').change(function(){
+        var pattern = 'span#%(id)s>select.dropdown_select';
+        var last_item = $(pattern+':last');
+
+        if (last_item.val()) {
+            last_item.clone(true).appendTo($('span#%(id)s'));
+            $('span#%(id)s').append(' ');
+        };
+
+        var values = [];
+
+        for (var i=$(pattern).length-1; i>=0; i--) {
+            if (values.indexOf($($(pattern).get(i)).val()) >= 0) {
+                $($(pattern).get(i)).remove();
+            } else {
+                values.push($($(pattern).get(i)).val());
+            }
+        };
+    });
+</script>
+"""
+
+TPL_FULL = """
+<span class="dropdown_multiple" id="%(id)s">
+%(values)s
+%(script)s
+</span>
+"""
+
+class DropDownMultiple(widgets.Widget):
+    choices = None
+
+    def __init__(self, attrs=None, choices=()):
+        self.choices = choices
+
+        super(DropDownMultiple, self).__init__(attrs)
+
+    def render(self, name, value, attrs=None, choices=()):
+        if value is None: value = []
+        final_attrs = self.build_attrs(attrs, name=name)
+
+        # Pop id
+        id = final_attrs['id']
+        del final_attrs['id']
+
+        # Insert blank value
+        choices = [('','---')] + list(self.choices)
+
+        # Build values
+        items = []
+        for val in value:
+            opts = "\n".join([TPL_OPTION %{'value': k, 'desc': v, 'selected': val == k and 'selected="selected"' or ''} for k, v in choices])
+            
+            items.append(TPL_SELECT %{'attrs': flatatt(final_attrs), 'opts': opts})
+
+        # Build blank value
+        opts = "\n".join([TPL_OPTION %{'value': k, 'desc': v, 'selected': ''} for k, v in choices])
+        items.append(TPL_SELECT %{'attrs': flatatt(final_attrs), 'opts': opts})
+
+        script = TPL_SCRIPT %{'id': id}
+        output = TPL_FULL %{'id': id, 'values': '\n'.join(items), 'script': script}
+
+        return mark_safe(output)
+
+    def value_from_datadict(self, data, files, name):
+        if isinstance(data, MultiValueDict):
+            return [i for i in data.getlist(name) if i]
+        
+        return data.get(name, None)