summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_files/forms.py6
-rw-r--r--archaeological_files_pdl/forms.py12
-rw-r--r--archaeological_finds/forms.py12
-rw-r--r--ishtar_common/static/media/style.css9
-rw-r--r--ishtar_common/widgets.py116
5 files changed, 102 insertions, 53 deletions
diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py
index 45a05b9b1..99fe6e0db 100644
--- a/archaeological_files/forms.py
+++ b/archaeological_files/forms.py
@@ -336,10 +336,8 @@ class FileFormResearch(ManageOldType, forms.Form):
'requested_operation_type': OperationType,
'organization': Organization,
'department': Department}
- department = widgets.MultipleAutocompleteField(
- model=Department,
- label=_("Departments"),
- required=False)
+ department = widgets.Select2MultipleField(
+ model=Department, label=_("Departments"), required=False)
scientist = forms.IntegerField(
widget=widgets.JQueryAutoComplete(
reverse_lazy(
diff --git a/archaeological_files_pdl/forms.py b/archaeological_files_pdl/forms.py
index 4890eb5d6..8bb1f9156 100644
--- a/archaeological_files_pdl/forms.py
+++ b/archaeological_files_pdl/forms.py
@@ -86,9 +86,9 @@ class FileFormPlanning(forms.Form):
associated_models = {'town': Town, 'department': Department}
name = forms.CharField(label=_(u"Planning name"), required=False,
max_length=100)
- town = widgets.MultipleAutocompleteField(
- model=Town, label=_("Towns"), required=False)
- department = widgets.MultipleAutocompleteField(
+ town = widgets.Select2MultipleField(
+ model=Town, label=_("Towns"), required=False, remote=True)
+ department = widgets.Select2MultipleField(
model=Department, label=_("Departments"), required=False)
locality = forms.CharField(label=_(u"Locality"), max_length=100,
required=False)
@@ -118,9 +118,9 @@ class FileFormResearchAddress(forms.Form):
associated_models = {'town': Town, 'department': Department}
name = forms.CharField(label=_(u"Project name"), required=False,
max_length=100)
- town = widgets.MultipleAutocompleteField(
- model=Town, label=_("Towns"), required=False)
- department = widgets.MultipleAutocompleteField(
+ town = widgets.Select2MultipleField(
+ model=Town, label=_("Towns"), required=False, remote=True)
+ department = widgets.Select2MultipleField(
model=Department, label=_("Departments"), required=False)
locality = forms.CharField(label=_(u"Locality"), max_length=100,
required=False)
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py
index bbc8729d0..8fe945e88 100644
--- a/archaeological_finds/forms.py
+++ b/archaeological_finds/forms.py
@@ -147,15 +147,19 @@ class FindForm(ManageOldType, forms.Form):
required=False)
is_complete = forms.NullBooleanField(label=_(u"Is complete?"),
required=False)
- material_type = widgets.MultipleAutocompleteField(
- model=models.MaterialType, label=_(u"Material type"), required=False)
+ material_type = widgets.Select2MultipleField(
+ model=models.MaterialType, label=_(u"Material type"), required=False,
+ available=True
+ )
conservatory_state = forms.ChoiceField(label=_(u"Conservatory state"),
choices=[], required=False)
conservatory_comment = forms.CharField(
label=_(u"Conservatory comment"), required=False,
widget=forms.Textarea)
- object_type = widgets.MultipleAutocompleteField(
- model=models.ObjectType, label=_(u"Object types"), required=False)
+ object_type = widgets.Select2MultipleField(
+ model=models.ObjectType, label=_(u"Object types"), required=False,
+ available=True
+ )
preservation_to_consider = forms.MultipleChoiceField(
label=_(u"Preservation type"), choices=[],
widget=widgets.Select2Multiple, required=False)
diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css
index adaf94200..fc840526e 100644
--- a/ishtar_common/static/media/style.css
+++ b/ishtar_common/static/media/style.css
@@ -92,6 +92,15 @@ div.form {
border-bottom:1px solid #D14;
}
+.form .select2-container--default .select2-selection--multiple {
+ border: 1px solid #FFF;
+}
+
+.form .select2-container--default.select2-container--focus
+.select2-selection--multiple {
+ border:1px solid #D14;
+}
+
hr.spacer{
clear:both;
border:0;
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index ffa09e7b4..f0e1dc775 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -45,6 +45,12 @@ reverse_lazy = lazy(reverse, unicode)
class Select2Multiple(forms.SelectMultiple):
+ 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):
@@ -59,20 +65,66 @@ class Select2Multiple(forms.SelectMultiple):
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
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 = []
+ for v in value:
+ try:
+ choices.append((v, self.model.objects.get(pk=v)))
+ except self.model.DoesNotExist:
+ # 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();
+ $("#id_{}").select2({});
}});</script>
- """.format(name)
+ """.format(name, options)
return mark_safe(html)
@@ -91,49 +143,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):