diff --git a/src/js/jquery.select2.js b/src/js/jquery.select2.js
index a3f8eff4..9136ff78 100644
--- a/src/js/jquery.select2.js
+++ b/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(
diff --git a/src/js/select2/compat/inputData.js b/src/js/select2/compat/inputData.js
index a338bf1e..6e1dee26 100644
--- a/src/js/select2/compat/inputData.js
+++ b/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);
diff --git a/src/js/select2/core.js b/src/js/select2/core.js
index 1445f17b..61fee6ca 100644
--- a/src/js/select2/core.js
+++ b/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;
};
diff --git a/src/js/select2/data/select.js b/src/js/select2/data/select.js
index abad2a05..a897198b 100644
--- a/src/js/select2/data/select.js
+++ b/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;
};
diff --git a/src/js/select2/dropdown/attachBody.js b/src/js/select2/dropdown/attachBody.js
index 70a10d40..2c099963 100644
--- a/src/js/select2/dropdown/attachBody.js
+++ b/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);
});
diff --git a/src/js/select2/dropdown/selectOnClose.js b/src/js/select2/dropdown/selectOnClose.js
index 430c0329..8c633356 100644
--- a/src/js/select2/dropdown/selectOnClose.js
+++ b/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 (
diff --git a/src/js/select2/options.js b/src/js/select2/options.js
index 3e48deea..d667c4f1 100644
--- a/src/js/select2/options.js
+++ b/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);
diff --git a/src/js/select2/results.js b/src/js/select2/results.js
index a16b65fd..f155821c 100644
--- a/src/js/select2/results.js
+++ b/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');
diff --git a/src/js/select2/selection/allowClear.js b/src/js/select2/selection/allowClear.js
index a7bbc2ea..3f7d0826 100644
--- a/src/js/select2/selection/allowClear.js
+++ b/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([
'×' +
''
);
- $remove.data('data', data);
+ Utils.StoreData($remove[0], 'data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove);
};
diff --git a/src/js/select2/selection/base.js b/src/js/select2/selection/base.js
index cd3aafda..2efb1039 100644
--- a/src/js/select2/selection/base.js
+++ b/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');
});
diff --git a/src/js/select2/selection/multiple.js b/src/js/select2/selection/multiple.js
index 45225256..6f106788 100644
--- a/src/js/select2/selection/multiple.js
+++ b/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);
}
diff --git a/src/js/select2/selection/search.js b/src/js/select2/selection/search.js
index 1bc4b096..9ce321be 100644
--- a/src/js/select2/selection/search.js
+++ b/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);
diff --git a/src/js/select2/utils.js b/src/js/select2/utils.js
index d1a23d29..7905e49b 100644
--- a/src/js/select2/utils.js
+++ b/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;
});
diff --git a/tests/data/array-tests.js b/tests/data/array-tests.js
index 08b806ae..70ead12d 100644
--- a/tests/data/array-tests.js
+++ b/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,
'