Add a DropDownMultiple form widget.
[matthijs/projects/xerxes.git] / tools / widgets / dropdownmultiple.py
1 # -*- coding: utf-8 -*-
2 from django.forms import widgets
3 from django.utils.safestring import mark_safe
4 from django.utils.datastructures import MultiValueDict
5 from django.newforms.util import flatatt
6
7 TPL_OPTION = """<option value="%(value)s" %(selected)s>%(desc)s</option>"""
8
9 TPL_SELECT = """
10 <select class="dropdown_select" %(attrs)s>
11 %(opts)s
12 </select>
13 """
14
15 TPL_SCRIPT = """
16 <script>
17     $('span#%(id)s>select.dropdown_select').change(function(){
18         var pattern = 'span#%(id)s>select.dropdown_select';
19         var last_item = $(pattern+':last');
20
21         if (last_item.val()) {
22             last_item.clone(true).appendTo($('span#%(id)s'));
23             $('span#%(id)s').append(' ');
24         };
25
26         var values = [];
27
28         for (var i=$(pattern).length-1; i>=0; i--) {
29             if (values.indexOf($($(pattern).get(i)).val()) >= 0) {
30                 $($(pattern).get(i)).remove();
31             } else {
32                 values.push($($(pattern).get(i)).val());
33             }
34         };
35     });
36 </script>
37 """
38
39 TPL_FULL = """
40 <span class="dropdown_multiple" id="%(id)s">
41 %(values)s
42 %(script)s
43 </span>
44 """
45
46 class DropDownMultiple(widgets.Widget):
47     choices = None
48
49     def __init__(self, attrs=None, choices=()):
50         self.choices = choices
51
52         super(DropDownMultiple, self).__init__(attrs)
53
54     def render(self, name, value, attrs=None, choices=()):
55         if value is None: value = []
56         final_attrs = self.build_attrs(attrs, name=name)
57
58         # Pop id
59         id = final_attrs['id']
60         del final_attrs['id']
61
62         # Insert blank value
63         choices = [('','---')] + list(self.choices)
64
65         # Build values
66         items = []
67         for val in value:
68             opts = "\n".join([TPL_OPTION %{'value': k, 'desc': v, 'selected': val == k and 'selected="selected"' or ''} for k, v in choices])
69             
70             items.append(TPL_SELECT %{'attrs': flatatt(final_attrs), 'opts': opts})
71
72         # Build blank value
73         opts = "\n".join([TPL_OPTION %{'value': k, 'desc': v, 'selected': ''} for k, v in choices])
74         items.append(TPL_SELECT %{'attrs': flatatt(final_attrs), 'opts': opts})
75
76         script = TPL_SCRIPT %{'id': id}
77         output = TPL_FULL %{'id': id, 'values': '\n'.join(items), 'script': script}
78
79         return mark_safe(output)
80
81     def value_from_datadict(self, data, files, name):
82         if isinstance(data, MultiValueDict):
83             return [i for i in data.getlist(name) if i]
84         
85         return data.get(name, None)