浏览代码

Merge branch 'master' of https://github.com/NadeemAfana/select2 into develop

alexweissman 7 年之前
父节点
当前提交
62c4f6332b

+ 4 - 3
src/js/jquery.select2.js

@@ -3,8 +3,9 @@ define([
   'jquery-mousewheel',
 
   './select2/core',
-  './select2/defaults'
-], function ($, _, Select2, Defaults) {
+  './select2/defaults',
+  './select2/utils'
+], function ($, _, Select2, Defaults, Utils) {
   if ($.fn.select2 == null) {
     // All methods that should return the element
     var thisMethods = ['open', 'close', 'destroy'];
@@ -25,7 +26,7 @@ define([
         var args = Array.prototype.slice.call(arguments, 1);
 
         this.each(function () {
-          var instance = $(this).data('select2');
+          var instance = Utils.GetData(this, 'select2');
 
           if (instance == null && window.console && console.error) {
             console.error(

+ 4 - 3
src/js/select2/compat/inputData.js

@@ -1,6 +1,7 @@
 define([
-  'jquery'
-], function ($) {
+  'jquery',
+  '../utils'
+], function ($, Utils) {
   function InputData (decorated, $element, options) {
     this._currentData = [];
     this._valueSeparator = options.get('valueSeparator') || ',';
@@ -117,7 +118,7 @@ define([
 
   InputData.prototype.addOptions = function (_, $options) {
     var options = $.map($options, function ($option) {
-      return $.data($option[0], 'data');
+      return Utils.GetData($option[0], 'data');
     });
 
     this._currentData.push.apply(this._currentData, options);

+ 8 - 7
src/js/select2/core.js

@@ -5,8 +5,8 @@ define([
   './keys'
 ], function ($, Options, Utils, KEYS) {
   var Select2 = function ($element, options) {
-    if ($element.data('select2') != null) {
-      $element.data('select2').destroy();
+    if (Utils.GetData($element[0], 'select2') != null) {
+        Utils.GetData($element[0], 'select2').destroy();
     }
 
     this.$element = $element;
@@ -22,7 +22,7 @@ define([
     // Set up the tabindex
 
     var tabindex = $element.attr('tabindex') || 0;
-    $element.data('old-tabindex', tabindex);
+    Utils.StoreData($element[0], 'old-tabindex', tabindex);
     $element.attr('tabindex', '-1');
 
     // Set up containers and adapters
@@ -83,7 +83,7 @@ define([
     // Synchronize any monitored attributes
     this._syncAttributes();
 
-    $element.data('select2', this);
+    Utils.StoreData($element[0], 'select2', this);
   };
 
   Utils.Extend(Select2, Utils.Observable);
@@ -573,11 +573,12 @@ define([
     this._syncS = null;
 
     this.$element.off('.select2');
-    this.$element.attr('tabindex', this.$element.data('old-tabindex'));
+    this.$element.attr('tabindex', 
+    Utils.GetData(this.$element[0], 'old-tabindex'));
 
     this.$element.removeClass('select2-hidden-accessible');
     this.$element.attr('aria-hidden', 'false');
-    this.$element.removeData('select2');
+    Utils.RemoveData(this.$element[0]);
 
     this.dataAdapter.destroy();
     this.selection.destroy();
@@ -604,7 +605,7 @@ define([
 
     this.$container.addClass('select2-container--' + this.options.get('theme'));
 
-    $container.data('element', this.$element);
+    Utils.StoreData($container[0], 'element', this.$element);
 
     return $container;
   };

+ 4 - 4
src/js/select2/data/select.js

@@ -119,7 +119,7 @@ define([
     // Remove anything added to child elements
     this.$element.find('*').each(function () {
       // Remove any custom data set by Select2
-      $.removeData(this, 'data');
+      Utils.RemoveData(this);
     });
   };
 
@@ -192,7 +192,7 @@ define([
     normalizedData.element = option;
 
     // Override the option's data with the combined data
-    $.data(option, 'data', normalizedData);
+    Utils.StoreData(option, 'data', normalizedData);
 
     return $option;
   };
@@ -200,7 +200,7 @@ define([
   SelectAdapter.prototype.item = function ($option) {
     var data = {};
 
-    data = $.data($option[0], 'data');
+    data = Utils.GetData($option[0], 'data');
 
     if (data != null) {
       return data;
@@ -238,7 +238,7 @@ define([
     data = this._normalizeItem(data);
     data.element = $option[0];
 
-    $.data($option[0], 'data', data);
+    Utils.StoreData($option[0], 'data', data);
 
     return data;
   };

+ 2 - 2
src/js/select2/dropdown/attachBody.js

@@ -90,14 +90,14 @@ define([
 
     var $watchers = this.$container.parents().filter(Utils.hasScroll);
     $watchers.each(function () {
-      $(this).data('select2-scroll-position', {
+      Utils.StoreData(this, 'select2-scroll-position', {
         x: $(this).scrollLeft(),
         y: $(this).scrollTop()
       });
     });
 
     $watchers.on(scrollEvent, function (ev) {
-      var position = $(this).data('select2-scroll-position');
+      var position = Utils.GetData(this, 'select2-scroll-position');
       $(this).scrollTop(position.y);
     });
 

+ 3 - 3
src/js/select2/dropdown/selectOnClose.js

@@ -1,6 +1,6 @@
 define([
-
-], function () {
+  '../utils'
+], function (Utils) {
   function SelectOnClose () { }
 
   SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -31,7 +31,7 @@ define([
       return;
     }
 
-    var data = $highlightedResults.data('data');
+    var data = Utils.GetData($highlightedResults[0], 'data');
 
     // Don't re-select already selected resulte
     if (

+ 9 - 8
src/js/select2/options.js

@@ -55,7 +55,7 @@ define([
     $e.prop('disabled', this.options.disabled);
     $e.prop('multiple', this.options.multiple);
 
-    if ($e.data('select2Tags')) {
+    if (Utils.GetData($e[0], 'select2Tags')) {
       if (this.options.debug && window.console && console.warn) {
         console.warn(
           'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -64,11 +64,11 @@ define([
         );
       }
 
-      $e.data('data', $e.data('select2Tags'));
-      $e.data('tags', true);
+      Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
+      Utils.StoreData($e[0], 'tags', true);
     }
 
-    if ($e.data('ajaxUrl')) {
+    if (Utils.GetData($e[0], 'ajaxUrl')) {
       if (this.options.debug && window.console && console.warn) {
         console.warn(
           'Select2: The `data-ajax-url` attribute has been changed to ' +
@@ -77,8 +77,9 @@ define([
         );
       }
 
-      $e.attr('ajax--url', $e.data('ajaxUrl'));
-      $e.data('ajax--url', $e.data('ajaxUrl'));
+      $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
+      Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
+	  
     }
 
     var dataset = {};
@@ -86,9 +87,9 @@ define([
     // Prefer the element's `dataset` attribute if it exists
     // jQuery 1.x does not correctly handle data attributes with multiple dashes
     if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
-      dataset = $.extend(true, {}, $e[0].dataset, $e.data());
+      dataset = $.extend(true, {}, $e[0].dataset, Utils.GetData($e[0]));
     } else {
-      dataset = $e.data();
+      dataset = Utils.GetData($e[0]);
     }
 
     var data = $.extend(true, {}, dataset);

+ 5 - 5
src/js/select2/results.js

@@ -130,7 +130,7 @@ define([
       $options.each(function () {
         var $option = $(this);
 
-        var item = $.data(this, 'data');
+        var item = Utils.GetData(this, 'data');
 
         // id needs to be converted to a string when comparing
         var id = '' + item.id;
@@ -235,7 +235,7 @@ define([
       this.template(data, option);
     }
 
-    $.data(option, 'data', data);
+    Utils.StoreData(option, 'data', data);
 
     return option;
   };
@@ -321,7 +321,7 @@ define([
         return;
       }
 
-      var data = $highlighted.data('data');
+      var data = Utils.GetData($highlighted[0], 'data');
 
       if ($highlighted.attr('aria-selected') == 'true') {
         self.trigger('close', {});
@@ -433,7 +433,7 @@ define([
       function (evt) {
       var $this = $(this);
 
-      var data = $this.data('data');
+      var data = Utils.GetData(this, 'data');
 
       if ($this.attr('aria-selected') === 'true') {
         if (self.options.get('multiple')) {
@@ -456,7 +456,7 @@ define([
 
     this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
       function (evt) {
-      var data = $(this).data('data');
+      var data = Utils.GetData(this, 'data');
 
       self.getHighlightedResults()
           .removeClass('select2-results__option--highlighted');

+ 5 - 4
src/js/select2/selection/allowClear.js

@@ -1,7 +1,8 @@
 define([
   'jquery',
-  '../keys'
-], function ($, KEYS) {
+  '../keys',
+  '../utils'
+], function ($, KEYS, Utils) {
   function AllowClear () { }
 
   AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -43,7 +44,7 @@ define([
 
     evt.stopPropagation();
 
-    var data = $clear.data('data');
+    var data = Utils.GetData($clear[0], 'data');
 
     var previousVal = this.$element.val();
     this.$element.val(this.placeholder.id);
@@ -101,7 +102,7 @@ define([
         '×' +
       '</span>'
     );
-    $remove.data('data', data);
+    Utils.StoreData($remove[0], 'data', data);
 
     this.$selection.find('.select2-selection__rendered').prepend($remove);
   };

+ 3 - 3
src/js/select2/selection/base.js

@@ -21,8 +21,8 @@ define([
 
     this._tabindex = 0;
 
-    if (this.$element.data('old-tabindex') != null) {
-      this._tabindex = this.$element.data('old-tabindex');
+    if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
+      this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
     } else if (this.$element.attr('tabindex') != null) {
       this._tabindex = this.$element.attr('tabindex');
     }
@@ -130,7 +130,7 @@ define([
           return;
         }
 
-        var $element = $this.data('element');
+        var $element = Utils.GetData(this, 'element');
 
         $element.select2('close');
       });

+ 2 - 2
src/js/select2/selection/multiple.js

@@ -44,7 +44,7 @@ define([
         var $remove = $(this);
         var $selection = $remove.parent();
 
-        var data = $selection.data('data');
+        var data = Utils.GetData($selection[0], 'data');
 
         self.trigger('unselect', {
           originalEvent: evt,
@@ -97,7 +97,7 @@ define([
       $selection.append(formatted);
       $selection.attr('title', selection.title || selection.text);
 
-      $selection.data('data', selection);
+      Utils.StoreData($selection[0], 'data', selection);
 
       $selections.push($selection);
     }

+ 1 - 1
src/js/select2/selection/search.js

@@ -81,7 +81,7 @@ define([
           .prev('.select2-selection__choice');
 
         if ($previousChoice.length > 0) {
-          var item = $previousChoice.data('data');
+          var item = Utils.GetData($previousChoice[0], 'data');
 
           self.searchRemoveChoice(item);
 

+ 63 - 0
src/js/select2/utils.js

@@ -272,5 +272,68 @@ define([
     $element.append($nodes);
   };
 
+  // Cache objects in Utils.__cache instead of $.data
+  Utils.__cache = {};
+
+
+  var id = 0;
+  Utils.GetUniqueElementId = function (element) {
+    // Get a unique element Id. If element has no id, 
+    // creates a new unique number, stores it in the id 
+    // attribute and returns the new id. 
+    // If an id already exists, it simply returns it.
+
+    var select2Id = element.getAttribute('data-select2-id');
+    if (select2Id == null) {
+        // If element has id, use it.
+        if (element.id) {
+            select2Id = element.id;
+            element.setAttribute('data-select2-id', select2Id);
+        } else {
+            element.setAttribute('data-select2-id', ++id);
+            select2Id = id.toString();
+        }
+    }
+    return select2Id;
+  };
+
+  Utils.StoreData = function (element, name, value) {
+    // Stores an item in the cache for a specified element.
+    // name is the cache key.    
+    var id = Utils.GetUniqueElementId(element);
+    if (!Utils.__cache[id]) {
+        Utils.__cache[id] = {};
+    }
+
+    Utils.__cache[id][name] = value;
+  };
+
+
+  Utils.GetData = function (element, name) {
+    // Retrieves a value from the cache by its key (name)
+    // name is optional. If no name specified, return 
+    // all cache items for the specified element.
+    // and for a specified element.
+    var id = Utils.GetUniqueElementId(element);
+    if (name) {
+        if (Utils.__cache[id]) {
+            return Utils.__cache[id][name] != null ? 
+			       Utils.__cache[id][name]:
+				   $(element).data(name); // Fallback to HTML5 data attribs.
+        }
+        return $(element).data(name); // Fallback to HTML5 data attribs.
+    } else {
+        return Utils.__cache[id];			   
+    }
+  };
+
+  Utils.RemoveData = function (element) {
+    // Removes all cached items for a specified element.
+    var id = Utils.GetUniqueElementId(element);
+    if (Utils.__cache[id] != null) {
+        delete Utils.__cache[id];
+    }
+  };
+
   return Utils;
 });

+ 3 - 2
tests/data/array-tests.js

@@ -3,6 +3,7 @@ module('Data adapters - Array');
 var ArrayData = require('select2/data/array');
 var $ = require('jquery');
 var Options = require('select2/options');
+var Utils = require('select2/utils');
 
 var UserDefinedType = function (id, text) {
   var self = this;
@@ -247,7 +248,7 @@ test('option tags can receive new data', function(assert) {
   });
 
   assert.ok(
-    $select.find(':selected').data('data').extra,
+    Utils.GetData($select.find(':selected')[0], 'data').extra,
     '<option> default should have new data'
   );
 
@@ -256,7 +257,7 @@ test('option tags can receive new data', function(assert) {
   });
 
   assert.ok(
-    $select.find(':selected').data('data').extra,
+    Utils.GetData($select.find(':selected')[0], 'data').extra,
     '<option> One should have new data'
   );
 });

+ 29 - 0
tests/integration/jquery-calls.js

@@ -27,4 +27,33 @@ test('multiple elements with arguments works', function (assert) {
     '2',
     'The call should also change the value on the second element'
   );
+});
+
+test('initializes when jQuery $.data contains' +
+  ' cyclic reference', function (assert) {
+  var $ = require('jquery');
+  require('jquery.select2');
+
+  var $select = $(
+    '<select>' +
+      '<option>One</option>' +
+      '<option>Two</option>' +
+      '<option value="3" selected>Three</option>' +
+    '</select>'
+  );
+
+  // Add a circular reference object using jQuery.
+  var recursiveObject = {};
+
+  recursiveObject.same =  recursiveObject;
+
+  $select.data('same', recursiveObject);
+
+  $select.select2();
+
+  assert.equal(
+    $select.val(),
+    '3',
+    'The option value should be pulled correctly'
+  );
 });