diff options
Diffstat (limited to 'ishtar_common/widgets.py')
| -rw-r--r-- | ishtar_common/widgets.py | 113 | 
1 files changed, 87 insertions, 26 deletions
| diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index a97cfe70b..fc3ada283 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -27,6 +27,7 @@ from django.forms import ClearableFileInput  from django.forms.widgets import flatatt
  from django.template import Context, loader
  from django.utils.encoding import smart_unicode
 +from django.utils.functional import lazy
  from django.utils.html import escape
  from django.utils.safestring import mark_safe
  from django.utils.simplejson import JSONEncoder
 @@ -34,6 +35,44 @@ from django.utils.translation import ugettext_lazy as _  import models
 +reverse_lazy = lazy(reverse, unicode)
 +
 +class MultipleAutocompleteField(forms.MultipleChoiceField):
 +    def __init__(self, *args, **kwargs):
 +        model = None
 +        if 'model' in kwargs:
 +            model = kwargs.pop('model')
 +        if 'choices' not in kwargs and model:
 +            kwargs['choices'] = [(i.pk, unicode(i))for i in model.objects.all()]
 +        new = kwargs.pop('new') if 'new' in kwargs else None
 +        if 'widget' not in kwargs and model:
 +            kwargs['widget'] = JQueryAutoComplete(reverse_lazy(
 +                    'autocomplete-'+model.__name__.lower()),
 +                    associated_model=model, new=new,
 +                    multiple=True)
 +        super(MultipleAutocompleteField, self).__init__(*args, **kwargs)
 +
 +    def clean(self, value):
 +        if value:
 +            # clean JS messup with values
 +            try:
 +                if type(value) not in (list, tuple):
 +                    value = [value]
 +                else:
 +                    val = value
 +                    value = []
 +                    for v in val:
 +                        v = unicode(v).strip('[').strip(']'
 +                                     ).strip('u').strip("'").strip('"')
 +                        value += [int(v.strip())
 +                                            for v in list(set(v.split(',')))
 +                                                                if v.strip()]
 +            except (TypeError, ValueError):
 +                value = []
 +        else:
 +            value = []
 +        return super(MultipleAutocompleteField, self).clean(value)
 +
  class DeleteWidget(forms.CheckboxInput):
      def render(self, name, value, attrs=None):
          final_attrs = flatatt(self.build_attrs(attrs, name=name,
 @@ -95,7 +134,7 @@ class JQueryDate(forms.TextInput):  class JQueryAutoComplete(forms.TextInput):
      def __init__(self, source, associated_model=None, options={}, attrs={},
 -                 new=False):
 +                 new=False, multiple=False):
          """
          Source can be a list containing the autocomplete values or a
          string containing the url used for the request.
 @@ -108,6 +147,13 @@ class JQueryAutoComplete(forms.TextInput):              self.options = JSONEncoder().encode(options)
          self.attrs.update(attrs)
          self.new = new
 +        self.multiple = multiple
 +
 +    def value_from_datadict(self, data, files, name):
 +        if self.multiple:
 +            return data.getlist(name, None)
 +        else:
 +            return data.get(name, None)
      def render_js(self, field_id):
          if isinstance(self.source, list):
 @@ -119,39 +165,54 @@ class JQueryAutoComplete(forms.TextInput):                  source = "'" + unicode(self.source) + "'"
              except:
                  raise ValueError('source type is not valid')
 -        options = 'source : ' + source
 -        options += ''', select: function( event, ui ) {
 -            if(ui.item){
 -                $('#id_%s').val(ui.item.id);
 -            } else {
 -                $('#id_%s').val(null);
 -            }
 -        }, minLength: 2
 -        ''' % (field_id, field_id)
 +        dct = {'source':mark_safe(source),
 +               'field_id':field_id}
          if self.options:
 -            options += ',%s' % self.options
 +            dct['options'] = mark_safe('%s' % self.options)
 -        js = u'$(\'#id_select_%s\').autocomplete({%s});\n' % (field_id, options)
 -        js += u'''$(\'#id_select_%s\').live('click', function(){
 -                $('#id_%s').val(null);
 -                $('#id_select_%s').val(null);
 -});''' % (field_id, field_id, field_id)
 +        js = ""
 +        tpl = 'blocks/JQueryAutocomplete.js'
 +        if self.multiple:
 +            tpl = 'blocks/JQueryAutocompleteMultiple.js'
 +        t = loader.get_template(tpl)
 +        js = t.render(Context(dct))
          return js
      def render(self, name, value=None, attrs=None):
          attrs_hidden = self.build_attrs(attrs, name=name)
          attrs_select = self.build_attrs(attrs)
 -
          if value:
 -            val =  escape(smart_unicode(value))
 -            attrs_hidden['value'] = val
 -            attrs_select['value'] = val
 -            if self.associated_model:
 -                try:
 -                    attrs_select['value'] = unicode(
 -                        self.associated_model.objects.get(pk=value))
 -                except:
 -                    attrs_select['value'] = ""
 +            hiddens = []
 +            selects = []
 +            values = value
 +            if type(value) not in (list, tuple):
 +                values = unicode(escape(smart_unicode(value)))
 +                values = values.replace('[', '').replace(']', '')
 +                values = values.split(',')
 +            else:
 +                values = []
 +                for v in value:
 +                    values += v.split(',')
 +            for v in values:
 +                if not v:
 +                    continue
 +                hiddens.append(v)
 +                selects.append(v)
 +                if self.associated_model:
 +                    try:
 +                        selects[-1] = unicode(
 +                            self.associated_model.objects.get(pk=v))
 +                    except (self.associated_model.DoesNotExist, ValueError):
 +                        selects.pop()
 +                        hiddens.pop()
 +            if self.multiple:
 +                attrs_hidden['value'] = ", ".join(hiddens)
 +                if selects:
 +                    selects.append("")
 +                attrs_select['value'] = ", ".join(selects)
 +            else:
 +                attrs_hidden['value'] = hiddens[0]
 +                attrs_select['value'] = selects[0]
          if not self.attrs.has_key('id'):
              attrs_hidden['id'] = 'id_%s' % name
              attrs_select['id'] = 'id_select_%s' % name
 | 
