summaryrefslogtreecommitdiff
path: root/ishtar_common/widgets.py
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common/widgets.py')
-rw-r--r--ishtar_common/widgets.py138
1 files changed, 96 insertions, 42 deletions
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index 3fbf24f29..94709406c 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2017 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# Copyright (C) 2007 skam <massimo dot scamarcia at gmail.com>
# (http://djangosnippets.org/snippets/233/)
@@ -45,21 +45,89 @@ reverse_lazy = lazy(reverse, unicode)
class Select2Multiple(forms.SelectMultiple):
- class Media:
+ def __init__(self, attrs=None, choices=(), remote=None, model=None,
+ available=None):
+ super(Select2Multiple, self).__init__(attrs, choices)
+ self.remote = remote
+ self.available = available
+ self.model = model
+
+ @property
+ def media(self):
+ media = super(Select2Multiple, self).media
css = {
'all': ('select2/css/select2.css',)
}
- js = ('select2/js/select2.min.js',
- 'select2/js/init.js')
+ js = ['select2/js/select2.min.js']
+ for lang_code, lang in settings.LANGUAGES:
+ js.append('select2/js/i18n/{}.js'.format(lang_code))
+ media.add_css(css)
+ media.add_js(js)
+ return media
+
+ def get_q(self):
+ q = self.model.objects
+ if self.available:
+ q = q.filter(available=True)
+ return q
+
+ def get_choices(self):
+ for i in self.get_q().all():
+ yield (i.pk, unicode(i))
def render(self, name, value, attrs=None, choices=()):
+ self.remote = unicode(self.remote)
+ if self.remote in ('None', 'false'):
+ # test on lazy object is buggy... so we have this ugly test
+ self.remote = None
+ if not choices and not self.remote and self.model:
+ choices = self.get_choices()
klass = attrs and attrs.get('class') or ''
klass += ' ' if klass else '' + 'js-select2'
if not attrs:
attrs = {}
attrs['class'] = klass
- return super(Select2Multiple, self).render(name, value, attrs,
+ attrs['style'] = "width: 370px"
+ options = ""
+ if self.remote:
+ options = """{
+ ajax: {
+ url: '%s',
+ delay: 250,
+ dataType: 'json',
+ minimumInputLength: 2,
+ processResults: function (data) {
+ if(!data) return {results: []};
+ var result = $.map(data, function (item) {
+ return {
+ text: item['value'],
+ id: item['id']
+ }
+ });
+ return {
+ results: result
+ }
+ }
+ }
+ }""" % self.remote
+ if value:
+ choices = []
+ if type(value) not in (list, tuple):
+ value = value.split(',')
+ for v in value:
+ try:
+ choices.append((v, self.model.objects.get(pk=v)))
+ except (self.model.DoesNotExist, ValueError):
+ # an old reference ? it should not happen
+ pass
+ html = super(Select2Multiple, self).render(name, value, attrs,
choices)
+ html += """<script type="text/javascript">
+ $(document).ready(function() {{
+ $("#id_{}").select2({});
+ }});</script>
+ """.format(name, options)
+ return mark_safe(html)
class CheckboxSelectMultiple(CheckboxSelectMultipleBase):
@@ -77,49 +145,35 @@ class CheckboxSelectMultiple(CheckboxSelectMultipleBase):
choices)
-class MultipleAutocompleteField(forms.MultipleChoiceField):
+class Select2MultipleField(forms.MultipleChoiceField):
def __init__(self, *args, **kwargs):
- self.model = None
+ remote = None
+ if 'remote' in kwargs:
+ remote = kwargs.pop('remote')
+ self.model, self.remote = None, None
if 'model' in kwargs:
self.model = kwargs.pop('model')
- if 'choices' not in kwargs and self.model:
- kwargs['choices'] = []
- new = kwargs.pop('new') if 'new' in kwargs else None
- if 'widget' not in kwargs and self.model:
- kwargs['widget'] = JQueryAutoComplete(
- reverse_lazy('autocomplete-' + self.model.__name__.lower()),
- associated_model=self.model, new=new,
- multiple=True)
- super(MultipleAutocompleteField, self).__init__(*args, **kwargs)
-
- def get_choices(self):
- return [(i.pk, unicode(i)) for i in self.model.objects.all()]
+ if remote:
+ self.remote = reverse_lazy(
+ 'autocomplete-' + self.model.__name__.lower())
+ self.available = False
+ if 'available' in kwargs:
+ self.available = kwargs.pop('available')
+ kwargs['widget'] = Select2Multiple(model=self.model,
+ available=self.available,
+ remote=self.remote)
+ super(Select2MultipleField, self).__init__(*args, **kwargs)
+
+ def get_q(self):
+ q = self.model.objects
+ if self.available:
+ q = q.filter(available=True)
+ return q
def valid_value(self, value):
if not self.model:
- return super(MultipleAutocompleteField, self).valid_value(value)
- return bool(self.model.objects.filter(pk=value).count())
-
- def clean(self, value):
- if value:
- # clean JS messup with values
- try:
- if type(value) not in (list, tuple):
- value = [int(value)]
- else:
- val = value
- value = []
- for v in val:
- v = unicode(v).strip('[').strip(']')\
- .strip('u').strip("'").strip('"')
- value += [int(va.strip())
- for va in list(set(v.split(',')))
- if va.strip()]
- except (TypeError, ValueError):
- value = []
- else:
- value = []
- return super(MultipleAutocompleteField, self).clean(value)
+ return super(Select2MultipleField, self).valid_value(value)
+ return bool(self.get_q().filter(pk=value).count())
class DeleteWidget(forms.CheckboxInput):