# -*- coding:utf-8 -*- """ Contains all the Django widgets for Select2. """ from __future__ import absolute_import, unicode_literals import json import logging import re from itertools import chain from django import forms from django.core.urlresolvers import reverse from django.core.validators import EMPTY_VALUES from django.utils.datastructures import MergeDict, MultiValueDict from django.utils.encoding import force_text from django.utils.safestring import mark_safe from django.utils.six import text_type from django_select2.media import (get_select2_css_libs, get_select2_heavy_js_libs, get_select2_js_libs) from . import __RENDER_SELECT2_STATICS as RENDER_SELECT2_STATICS logger = logging.getLogger(__name__) # ## Light mixin and widgets ## class Select2Mixin(object): """ The base mixin of all Select2 widgets. This mixin is responsible for rendering the necessary JavaScript and CSS codes which turns normal `` 'closeOnSelect': False, } """ The options listed here are rendered as JS map and passed to Select2 JS code. Complete description of these options are available in Select2_ JS' site. .. _Select2: http://ivaynberg.github.com/select2/#documentation. """ def __init__(self, **kwargs): """ Constructor of the class. The following additional kwarg is allowed:- :param select2_options: This is similar to standard Django way to pass extra attributes to widgets. This is meant to override values of existing :py:attr:`.options`. Example:: class MyForm(ModelForm): class Meta: model = MyModel widgets = { 'name': Select2WidgetName(select2_options={ 'minimumResultsForSearch': 10, 'closeOnSelect': True, }) } .. tip:: You cannot introduce new options using this. For that you should sub-class and override :py:meth:`.init_options`. The reason for this is, few options are not compatible with each other or are not applicable in some scenarios. For example, when Select2 is attached to a ```` list. Otherwise the field will be rendered without a placeholder and the clear feature will stay disabled. :type select2_options: :py:obj:`dict` or None """ # Making an instance specific copy self.options = dict(self.options) select2_options = kwargs.pop('select2_options', None) if select2_options: for name, value in select2_options.items(): self.options[name] = value self.init_options() super(Select2Mixin, self).__init__(**kwargs) def init_options(self): """ Sub-classes can use this to suppress or override options passed to Select2 JS library. Example:: def init_options(self): self.options['createSearchChoice'] = 'Your_js_function' In the above example we are setting ``Your_js_function`` as Select2's ``createSearchChoice`` function. """ pass def set_placeholder(self, val): """ Placeholder is a value which Select2 JS library shows when nothing is selected. This should be string. :return: None """ self.options['placeholder'] = val def get_options(self): """ :return: Dictionary of options to be passed to Select2 JS. :rtype: :py:obj:`dict` """ options = dict(self.options) if options.get('allowClear', None) is not None: options['allowClear'] = not self.is_required if options.get('placeholder'): options['placeholder'] = force_text(options['placeholder']) return options def render_js_code(self, id_, *args): """ Renders the `` :rtype: :py:obj:`unicode` """ return """ """ % inner_code def render_inner_js_code(self, id_, *args): """ Renders all the JS code required for this widget. :return: The rendered JS code which will be later enclosed inside ``