Source code for easy_select2.widgets

import json

from django import forms
from django.templatetags.static import static
from django.conf import settings
from django.utils.safestring import mark_safe


SELECT2_JS = getattr(settings, 'SELECT2_JS',
                     'easy_select2/vendor/select2/select2.min.js')
SELECT2_CSS = getattr(settings, 'SELECT2_CSS',
                      'easy_select2/vendor/select2/select2.min.css')
SELECT2_USE_BUNDLED_JQUERY = getattr(settings, 'SELECT2_USE_BUNDLED_JQUERY', True)

SELECT2_WIDGET_JS = [
    static('easy_select2/js/easy_select2.js'),
    static('easy_select2/js/lookup_override.js'),
    static(SELECT2_JS),
]

if SELECT2_USE_BUNDLED_JQUERY:
    SELECT2_WIDGET_JS.insert(0, static('easy_select2/vendor/jquery/jquery.min.js'))


[docs]class Select2Mixin(object): """ This mixin provides a mechanism to construct custom widget class, that will be rendered using Select2 input. Generally should be mixed with widgets that render select input. """ inline_script = """ <script> $("#%(id)s").on('select2changed', function(e){ $("#%(id)s").select2(%(options)s); }).trigger('select2changed'); </script> """ def __init__(self, select2attrs=None, *args, **kwargs): """ Initializes default select2 attributes. If width is not provided, sets Select2 width to 250px. Args: select2attrs: a dictionary or string, which then converted to unicode string representation and passed to Select2 constructor function as options. """ self.select2attrs = select2attrs or {} if not 'width' in self.select2attrs: self.select2attrs.update({'width': '250px'}) super(Select2Mixin, self).__init__(*args, **kwargs)
[docs] def render(self, *args, **kwargs): """ Extends base class's `render` method by appending javascript inline text to html output. """ output = super(Select2Mixin, self).render(*args, **kwargs) id_ = kwargs['attrs']['id'] if isinstance(self.select2attrs, str): options = self.select2attrs else: options = json.dumps(self.select2attrs) output += self.inline_script % { 'id': id_, 'options': options, } return mark_safe(output)
class Media: js = SELECT2_WIDGET_JS css = { 'screen': [ static(SELECT2_CSS) ], }
[docs]class Select2(Select2Mixin, forms.Select): """Implements single-valued select widget with Select2.""" pass
[docs]class Select2Multiple(Select2Mixin, forms.SelectMultiple): """Implements multiple select widget with Select2.""" pass
[docs]class Select2TextMixin(Select2Mixin): """ This mixin provides a mechanism to construct custom widget class, that will be rendered using Select2. It will work as :class:`Select2Mixin` if there is no *data* attribute in `select2attrs`. If *data* attribute is passed, Select2 will be configured to use pre-set list of choices. Generally should be mixed with widgets, that renders as text input. """ def __init__(self, select2attrs=None, *args, **kwargs): super(Select2TextMixin, self).__init__(select2attrs, *args, **kwargs) if 'data' in self.select2attrs: self.inline_script = """ <script> (function(){ var options = %(options)s; options['createSearchChoice'] = function(term){ return { 'id': term, 'text': term }; }; $("#%(id)s").select2(options); }()); </script> """
[docs]class Select2TextInput(Select2TextMixin, forms.TextInput): """ A Select2-enabled combo box for non-choice fields which can provide a list of pre-set choices, or can accept arbitrary input. To use this, do NOT set a *choices* attribute on the model field, but DO supply a *data* attribute to select2attrs that contains a list of dictionaries each having at least an *id* and *text* terms like so:: form.fields['myfield'].widget = Select2TextInput( select2attrs={ 'data': [ {'id': 'your data', 'text': 'your data'}, ... ], }, ) """ pass