From 4e240ce415400b0ee14d3a78e07fb76bd696b067 Mon Sep 17 00:00:00 2001 From: "AppleGrew (applegrew)" Date: Thu, 23 Aug 2012 00:22:49 +0530 Subject: [PATCH] v2.0.1 * Auto field register fix. * Prevent multiple execution of heavy_data.js. --- django_select2/__init__.py | 2 +- django_select2/fields.py | 4 +- django_select2/static/js/heavy_data.js | 435 +++++++++++++------------ django_select2/widgets.py | 10 +- testapp/test.db | Bin 172032 -> 172032 bytes testapp/testapp/templates/index.html | 1 + testapp/testmain/forms.py | 10 + testapp/testmain/urls.py | 2 + testapp/testmain/views.py | 5 +- 9 files changed, 248 insertions(+), 221 deletions(-) diff --git a/django_select2/__init__.py b/django_select2/__init__.py index 6e129e1..5564c55 100644 --- a/django_select2/__init__.py +++ b/django_select2/__init__.py @@ -1,4 +1,4 @@ -__version__ = "2.0" +__version__ = "2.0.1" from django.conf import settings if settings.configured: diff --git a/django_select2/fields.py b/django_select2/fields.py index 05cda4c..db1131d 100644 --- a/django_select2/fields.py +++ b/django_select2/fields.py @@ -9,8 +9,8 @@ class AutoViewFieldMixin(object): if logger.isEnabledFor(logging.INFO): logger.info("Registering auto field: %s", name) - from .util import register_field - id_ = register_field(name, self) + from . import util + id_ = util.register_field(name, self) self.widget.field_id = id_ super(AutoViewFieldMixin, self).__init__(*args, **kwargs) diff --git a/django_select2/static/js/heavy_data.js b/django_select2/static/js/heavy_data.js index 1ae10e4..d49b98a 100644 --- a/django_select2/static/js/heavy_data.js +++ b/django_select2/static/js/heavy_data.js @@ -1,243 +1,246 @@ +if (!window['django_select2']) { + // This JS file can be included multiple times. So, as not to ovverwrite previous states, we run this only once. -var django_select2 = { - MULTISEPARATOR: String.fromCharCode(0), // We use this unprintable char as separator, since this can't be entered by user. - get_url_params: function (term, page, context) { - var field_id = $(this).data('field_id'), - res = { - 'term': term, - 'page': page, - 'context': context - }; - if (field_id) { - res['field_id'] = field_id; - } - return res; - }, - process_results: function (data, page, context) { - var results; - if (data.err && data.err.toLowerCase() === 'nil') { - results = { - 'results': data.results - }; - if (context) { - results['context'] = context; + var django_select2 = { + MULTISEPARATOR: String.fromCharCode(0), // We use this unprintable char as separator, since this can't be entered by user. + get_url_params: function (term, page, context) { + var field_id = $(this).data('field_id'), + res = { + 'term': term, + 'page': page, + 'context': context + }; + if (field_id) { + res['field_id'] = field_id; } - if (data.more === true || data.more === false) { - results['more'] = data.more; + return res; + }, + process_results: function (data, page, context) { + var results; + if (data.err && data.err.toLowerCase() === 'nil') { + results = { + 'results': data.results + }; + if (context) { + results['context'] = context; + } + if (data.more === true || data.more === false) { + results['more'] = data.more; + } + } else { + results = {'results':[]}; } - } else { - results = {'results':[]}; - } - if (results.results) { - $(this).data('results', results.results); - } else { - $(this).removeData('results'); - } - return results; - }, - setCookie: function (c_name, value) { - document.cookie = c_name + "=" + escape(value); - }, - getCookie: function (c_name) { - var i, x, y, ARRcookies = document.cookie.split(";"); - - for (i = 0; i < ARRcookies.length; i++) { - x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("=")); - y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1); - x = x.replace(/^\s+|\s+$/g,""); - if (x == c_name) { - return unescape(y); + if (results.results) { + $(this).data('results', results.results); + } else { + $(this).removeData('results'); } - } - }, - delCookie: function (c_name, isStartsWithPattern) { - var i, x, ARRcookies; - - if (!isStartsWithPattern) { - document.cookie = c_name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; - } else { - ARRcookies = document.cookie.split(";"); + return results; + }, + setCookie: function (c_name, value) { + document.cookie = c_name + "=" + escape(value); + }, + getCookie: function (c_name) { + var i, x, y, ARRcookies = document.cookie.split(";"); for (i = 0; i < ARRcookies.length; i++) { x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("=")); + y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1); x = x.replace(/^\s+|\s+$/g,""); - if (x.indexOf(c_name) == 0) { - document.cookie = c_name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + if (x == c_name) { + return unescape(y); } } - } - }, - onValChange: function () { - var e = $(this), res, id = e.attr('id'); + }, + delCookie: function (c_name, isStartsWithPattern) { + var i, x, ARRcookies; - res = django_select2.getValText(e, false); - - if (res && res[1]) { - // Cookies are used to persist selection's text. This is needed - // when the form springs back if there is any validation failure. - $(res[0]).each(function (idx) { - django_select2.setCookie(id + '_heavy_val:' + idx, this); - django_select2.setCookie(id + '_heavy_txt:' + idx, res[1][idx]); - }); - } else { - django_select2.delCookie(id + '_heavy_val:', true); - django_select2.delCookie(id + '_heavy_txt:', true); - } - }, - prepareValText: function (vals, txts, isMultiple) { - var data = [] - $(vals).each(function (index) { - data.push({id: this, text: txts[index]}); - }); - if (isMultiple) { - return data; - } else { - if (data.length > 0) { - return data[0]; + if (!isStartsWithPattern) { + document.cookie = c_name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; } else { - return null; - } - } - }, - getValText: function ($e, isGetFromCookieAllowed) { - var val = $e.select2('val'), res = $e.data('results'), txt = $e.txt(), isMultiple = !!$e.attr('multiple'), - f, id = $e.attr('id'); - if (val || val === 0) { // Means value is set. A numerical 0 is also a valid value. + ARRcookies = document.cookie.split(";"); - if (!isMultiple) { - val = [val]; - if (txt || txt === 0) { - txt = [txt]; + for (i = 0; i < ARRcookies.length; i++) { + x = ARRcookies[i].substr(0,ARRcookies[i].indexOf("=")); + x = x.replace(/^\s+|\s+$/g,""); + if (x.indexOf(c_name) == 0) { + document.cookie = c_name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + } } } + }, + onValChange: function () { + var e = $(this), res, id = e.attr('id'); - if (txt || txt === 0) { - return [val, txt]; - } - - f = $e.data('userGetValText'); - if (f) { - txt = f($e, val, isMultiple); - if (txt || txt === 0) { - return [val, txt]; - } - } + res = django_select2.getValText(e, false); - if (res) { - txt = []; - $(val).each(function (idx) { - var i, value = this; - - for (i in res) { - if (res[i].id == value) { - val[idx] = res[i].id; // To set it to correct data type. - txt.push(res[i].text); - } - } + if (res && res[1]) { + // Cookies are used to persist selection's text. This is needed + // when the form springs back if there is any validation failure. + $(res[0]).each(function (idx) { + django_select2.setCookie(id + '_heavy_val:' + idx, this); + django_select2.setCookie(id + '_heavy_txt:' + idx, res[1][idx]); }); - if (txt || txt === 0) { - return [val, txt]; - } + } else { + django_select2.delCookie(id + '_heavy_val:', true); + django_select2.delCookie(id + '_heavy_txt:', true); } - - if (isGetFromCookieAllowed) { - txt = []; - $(val).each(function (idx) { - var value = this, cookieVal; - - cookieVal = django_select2.getCookie(id + '_heavy_val:' + idx); - - if (cookieVal == value) { - txt.push(django_select2.getCookie(id + '_heavy_txt:' + idx)); - } - }); - if (txt || txt === 0) { - return [val, txt]; - } - } - - } - return null; - }, - onInit: function (e, callback) { - e = $(e); - var id = e.attr('id'), data = null, val = e.select2('val'); - - if (!val && val !== 0) { - val = e.data('initVal'); - } - - if (val || val === 0) { - // Value is set so need to get the text. - data = django_select2.getValText(e); - if (data && data[0]) { - data = django_select2.prepareValText(data[0], data[1], !!e.attr('multiple')); - } - } - if (!data) { - e.val(null); // Nulling out set value so as not to confuse users. - } - callback(data); // Change for 2.3.x - }, - onMultipleHiddenChange: function () { - var $e = $(this), valContainer = $e.data('valContainer'), name = $e.data('name'), vals = $e.val(); - valContainer.empty(); - if (vals) { - vals = vals.split(django_select2.MULTISEPARATOR); - $(vals).each(function () { - var inp = $('').appendTo(valContainer); - inp.attr('name', name); - inp.val(this); + }, + prepareValText: function (vals, txts, isMultiple) { + var data = [] + $(vals).each(function (index) { + data.push({id: this, text: txts[index]}); }); - } - }, - initMultipleHidden: function ($e) { - var valContainer; + if (isMultiple) { + return data; + } else { + if (data.length > 0) { + return data[0]; + } else { + return null; + } + } + }, + getValText: function ($e, isGetFromCookieAllowed) { + var val = $e.select2('val'), res = $e.data('results'), txt = $e.txt(), isMultiple = !!$e.attr('multiple'), + f, id = $e.attr('id'); + if (val || val === 0) { // Means value is set. A numerical 0 is also a valid value. - $e.data('name', $e.attr('name')); - $e.attr('name', ''); - - valContainer = $('
').insertAfter($e).css({'display': 'none'}); - $e.data('valContainer', valContainer); - - $e.change(django_select2.onMultipleHiddenChange); - if ($e.val()) { - $e.change(); - } - }, - convertArrToStr: function (arr) { - return arr.join(django_select2.MULTISEPARATOR); - }, - runInContextHelper: function (f, id) { - return function () { - var args = Array.prototype.slice.call(arguments); - return f.apply($('#' + id).get(0), args); - } - } -}; - -(function( $ ){ - // This sets or gets the text lables for an element. It merely takes care returing array or single - // value, based on if element is multiple type. - $.fn.txt = function(val) { - if (typeof(val) !== 'undefined') { - if (val) { - if (val instanceof Array) { - if (this.attr('multiple')) { - val = django_select2.convertArrToStr(val); - } else { - val = val[0] + if (!isMultiple) { + val = [val]; + if (txt || txt === 0) { + txt = [txt]; } } - this.attr('txt', val); + + if (txt || txt === 0) { + return [val, txt]; + } + + f = $e.data('userGetValText'); + if (f) { + txt = f($e, val, isMultiple); + if (txt || txt === 0) { + return [val, txt]; + } + } + + if (res) { + txt = []; + $(val).each(function (idx) { + var i, value = this; + + for (i in res) { + if (res[i].id == value) { + val[idx] = res[i].id; // To set it to correct data type. + txt.push(res[i].text); + } + } + }); + if (txt || txt === 0) { + return [val, txt]; + } + } + + if (isGetFromCookieAllowed) { + txt = []; + $(val).each(function (idx) { + var value = this, cookieVal; + + cookieVal = django_select2.getCookie(id + '_heavy_val:' + idx); + + if (cookieVal == value) { + txt.push(django_select2.getCookie(id + '_heavy_txt:' + idx)); + } + }); + if (txt || txt === 0) { + return [val, txt]; + } + } + } - return this; - } else { - val = this.attr('txt'); - if (val && this.attr('multiple')) { - val = val.split(django_select2.MULTISEPARATOR); + return null; + }, + onInit: function (e, callback) { + e = $(e); + var id = e.attr('id'), data = null, val = e.select2('val'); + + if (!val && val !== 0) { + val = e.data('initVal'); } - return val; + + if (val || val === 0) { + // Value is set so need to get the text. + data = django_select2.getValText(e); + if (data && data[0]) { + data = django_select2.prepareValText(data[0], data[1], !!e.attr('multiple')); + } + } + if (!data) { + e.val(null); // Nulling out set value so as not to confuse users. + } + callback(data); // Change for 2.3.x + }, + onMultipleHiddenChange: function () { + var $e = $(this), valContainer = $e.data('valContainer'), name = $e.data('name'), vals = $e.val(); + valContainer.empty(); + if (vals) { + vals = vals.split(django_select2.MULTISEPARATOR); + $(vals).each(function () { + var inp = $('').appendTo(valContainer); + inp.attr('name', name); + inp.val(this); + }); + } + }, + initMultipleHidden: function ($e) { + var valContainer; + + $e.data('name', $e.attr('name')); + $e.attr('name', ''); + + valContainer = $('
').insertAfter($e).css({'display': 'none'}); + $e.data('valContainer', valContainer); + + $e.change(django_select2.onMultipleHiddenChange); + if ($e.val()) { + $e.change(); + } + }, + convertArrToStr: function (arr) { + return arr.join(django_select2.MULTISEPARATOR); + }, + runInContextHelper: function (f, id) { + return function () { + var args = Array.prototype.slice.call(arguments); + return f.apply($('#' + id).get(0), args); + } } }; -})( jQuery ); \ No newline at end of file + + (function( $ ){ + // This sets or gets the text lables for an element. It merely takes care returing array or single + // value, based on if element is multiple type. + $.fn.txt = function(val) { + if (typeof(val) !== 'undefined') { + if (val) { + if (val instanceof Array) { + if (this.attr('multiple')) { + val = django_select2.convertArrToStr(val); + } else { + val = val[0] + } + } + this.attr('txt', val); + } + return this; + } else { + val = this.attr('txt'); + if (val && this.attr('multiple')) { + val = val.split(django_select2.MULTISEPARATOR); + } + return val; + } + }; + })( jQuery ); +} \ No newline at end of file diff --git a/django_select2/widgets.py b/django_select2/widgets.py index e1a199d..f6d7085 100644 --- a/django_select2/widgets.py +++ b/django_select2/widgets.py @@ -207,7 +207,15 @@ class HeavySelect2MultipleWidget(HeavySelect2Mixin, MultipleSelect2HiddenInput): ### Auto Heavy widgets ### -class AutoHeavySelect2Mixin(HeavySelect2Mixin): +class AutoHeavySelect2Mixin(object): + def __init__(self, *args, **kwargs): + if hasattr(self.__class__, 'field_id'): # By the time AutoViewFieldMixin runs widget is not instantiated + # so it sets the value on the widget class. + self.field_id = getattr(self.__class__, 'field_id') + delattr(self.__class__, 'field_id') + + super(AutoHeavySelect2Mixin, self).__init__(*args, **kwargs) + def render_inner_js_code(self, id_, *args): js = u"$('#%s').data('field_id', '%s');" % (id_, self.field_id) js += super(AutoHeavySelect2Mixin, self).render_inner_js_code(id_, *args) diff --git a/testapp/test.db b/testapp/test.db index 0c694af5ac34b9132fce589491c7981769dd1311..9873b7954ae4c38fe0914a7a1fb5ce5cf0fa48c3 100644 GIT binary patch delta 268 zcmXZWJqp4=5C!0!>?UeN9!VwW4Mfn|Lcs&1vR;o8Z=fJ}0Sn6o5$#NoLbS0G3k$Kb z5(@=M<>aS%)66$-!pIFHciN!QtU097WV{*EvR|*j2%K?1ggdS<*x`pa%-ZYBu`mJk zx@97gj;{ny+wrogTs%c)^ZnfBccQ{->eblFYDuvq+u!~)oiwR!yr)6P)v>@42|jq@ zffzSj_?0vB6&7(|wObBVZOPWp(sS|RQdT#1mqI0MJ~$RiTkVP?GsT68w!VE&*-8qM IX;^8{A81ud9RL6T delta 268 zcmXZWF$%&!5Czbk-6*<7zUc(Lfe2b#D0qMzVLeK`fr5|=SXc%`v~!CT5*sVAun;RN zJ3&%8Yr?>vX5ajctd6W+bSPYQrxea-yBV#=?HUq+3r?_j;D!VTd^wYCFjyf@LK+QQ zM5KfeZp&)m3ErN@OZ=^SU&!K$g)Ob2QIm~o6jti}*U;IJ+NVdFL|mN;WXSQt6DjVv z@<(`>ZxE-U?Du?f*e6|4TpDP+xs=tN-L-T%n+#d0jO^F_f2Gfbxsji7pemjcq+CcB F^aJEfNkaet diff --git a/testapp/testapp/templates/index.html b/testapp/testapp/templates/index.html index 5768d1c..a39027c 100644 --- a/testapp/testapp/templates/index.html +++ b/testapp/testapp/templates/index.html @@ -8,5 +8,6 @@ diff --git a/testapp/testmain/forms.py b/testapp/testmain/forms.py index 6abe284..384d803 100644 --- a/testapp/testmain/forms.py +++ b/testapp/testmain/forms.py @@ -12,6 +12,9 @@ class ClassRoomChoices(AutoModelSelect2MultipleField): queryset = ClassRoom.objects search_fields = ['number__icontains', ] +class ClassRoomSingleChoices(AutoModelSelect2Field): + queryset = ClassRoom.objects + search_fields = ['number__icontains', ] class EmployeeForm(forms.ModelForm): manager = EmployeeChoices(required=False) @@ -27,6 +30,13 @@ class DeptForm(forms.ModelForm): class Meta: model = Dept +class MixedForm(forms.Form): + emp1 = EmployeeChoices() + rooms1 = ClassRoomChoices() + emp2 = EmployeeChoices() + rooms2 = ClassRoomChoices() + rooms3 = ClassRoomSingleChoices() + # These are just for testing Auto registration of fields EmployeeChoices() # Should already be registered EmployeeChoices(auto_id="EmployeeChoices_CustomAutoId") # Should get registered diff --git a/testapp/testmain/urls.py b/testapp/testmain/urls.py index 0727880..9611a26 100644 --- a/testapp/testmain/urls.py +++ b/testapp/testmain/urls.py @@ -6,4 +6,6 @@ urlpatterns = patterns("", url(r'multi/model/field/$', 'testmain.views.test_multi_values_model_field', name='test_multi_values_model_field'), url(r'multi/model/field/([0-9]+)/$', 'testmain.views.test_multi_values_model_field1', name='test_multi_values_model_field1'), + + url(r'mixed/form/$', 'testmain.views.test_mixed_form', name='test_mixed_form'), ) diff --git a/testapp/testmain/views.py b/testapp/testmain/views.py index 92a713b..3a9c8d4 100644 --- a/testapp/testmain/views.py +++ b/testapp/testmain/views.py @@ -3,7 +3,7 @@ from django.http import HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext -from .forms import EmployeeForm, DeptForm +from .forms import EmployeeForm, DeptForm, MixedForm from .models import Employee, Dept def test_single_value_model_field(request): @@ -43,3 +43,6 @@ def test_multi_values_model_field1(request, id): form = DeptForm(instance=dept) return render_to_response('form.html', RequestContext(request, {'form': form})) +def test_mixed_form(request): + return render_to_response('form.html', RequestContext(request, {'form': MixedForm()})) +