Skip to content

Commit 4fc874a

Browse files
committed
Improve jQuery performance issues
This improves a regression added in b9b55ce that reduced performance for large number of options when using a jQuery collection object to append multiple options instead of using a bare array containing the jQuery elements. As `$.fn.add` is only required for jQuery 1.7.x, we can use a utility function that only falls back to it for that specific version of jQuery, and uses `$.fn.append` with an array for all other versions. This closes select2#3230.
1 parent c24293f commit 4fc874a

File tree

10 files changed

+90
-33
lines changed

10 files changed

+90
-33
lines changed

dist/js/select2.full.js

+29-10
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,23 @@ S2.define('select2/utils',[
714714
});
715715
};
716716

717+
// Append an array of jQuery nodes to a given element.
718+
Utils.appendMany = function ($element, $nodes) {
719+
// jQuery 1.7.x does not support $.fn.append() with an array
720+
// Fall back to a jQuery object collection using $.fn.add()
721+
if ($.fn.jquery.substr(0, 3) === '1.7') {
722+
var $jqNodes = $();
723+
724+
$.map($nodes, function (node) {
725+
$jqNodes = $jqNodes.add(node);
726+
});
727+
728+
$nodes = $jqNodes;
729+
}
730+
731+
$element.append($nodes);
732+
};
733+
717734
return Utils;
718735
});
719736

@@ -1565,7 +1582,7 @@ S2.define('select2/selection/multiple',[
15651582
return;
15661583
}
15671584

1568-
var $selections = $();
1585+
var $selections = [];
15691586

15701587
for (var d = 0; d < data.length; d++) {
15711588
var selection = data[d];
@@ -1578,10 +1595,12 @@ S2.define('select2/selection/multiple',[
15781595

15791596
$selection.data('data', selection);
15801597

1581-
$selections = $selections.add($selection);
1598+
$selections.push($selection);
15821599
}
15831600

1584-
this.$selection.find('.select2-selection__rendered').append($selections);
1601+
var $rendered = this.$selection.find('.select2-selection__rendered');
1602+
1603+
Utils.appendMany($rendered, $selections);
15851604
};
15861605

15871606
return MultipleSelection;
@@ -3015,7 +3034,7 @@ S2.define('select2/data/select',[
30153034
};
30163035

30173036
SelectAdapter.prototype.addOptions = function ($options) {
3018-
this.$element.append($options);
3037+
Utils.appendMany(this.$element, $options);
30193038
};
30203039

30213040
SelectAdapter.prototype.option = function (data) {
@@ -3185,7 +3204,7 @@ S2.define('select2/data/array',[
31853204
return self.item($(this)).id;
31863205
}).get();
31873206

3188-
var $options = $();
3207+
var $options = [];
31893208

31903209
// Filter out all items except for the one passed in the argument
31913210
function onlyItem (item) {
@@ -3216,10 +3235,10 @@ S2.define('select2/data/array',[
32163235
if (item.children) {
32173236
var $children = this.convertToOptions(item.children);
32183237

3219-
$option.append($children);
3238+
Utils.appendMany($option, $children);
32203239
}
32213240

3222-
$options = $options.add($option);
3241+
$options.push($option);
32233242
}
32243243

32253244
return $options;
@@ -3403,7 +3422,7 @@ S2.define('select2/data/tags',[
34033422
var $option = self.option(tag);
34043423
$option.attr('data-select2-tag', true);
34053424

3406-
self.addOptions($option);
3425+
self.addOptions([$option]);
34073426

34083427
self.insertTag(data, tag);
34093428
}
@@ -5468,8 +5487,8 @@ S2.define('select2/compat/inputData',[
54685487
};
54695488

54705489
InputData.prototype.addOptions = function (_, $options) {
5471-
var options = $.map($options, function (option) {
5472-
return $.data(option, 'data');
5490+
var options = $.map($options, function ($option) {
5491+
return $.data($option[0], 'data');
54735492
});
54745493

54755494
this._currentData.push.apply(this._currentData, options);

dist/js/select2.full.min.js

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/select2.js

+27-8
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,23 @@ S2.define('select2/utils',[
714714
});
715715
};
716716

717+
// Append an array of jQuery nodes to a given element.
718+
Utils.appendMany = function ($element, $nodes) {
719+
// jQuery 1.7.x does not support $.fn.append() with an array
720+
// Fall back to a jQuery object collection using $.fn.add()
721+
if ($.fn.jquery.substr(0, 3) === '1.7') {
722+
var $jqNodes = $();
723+
724+
$.map($nodes, function (node) {
725+
$jqNodes = $jqNodes.add(node);
726+
});
727+
728+
$nodes = $jqNodes;
729+
}
730+
731+
$element.append($nodes);
732+
};
733+
717734
return Utils;
718735
});
719736

@@ -1565,7 +1582,7 @@ S2.define('select2/selection/multiple',[
15651582
return;
15661583
}
15671584

1568-
var $selections = $();
1585+
var $selections = [];
15691586

15701587
for (var d = 0; d < data.length; d++) {
15711588
var selection = data[d];
@@ -1578,10 +1595,12 @@ S2.define('select2/selection/multiple',[
15781595

15791596
$selection.data('data', selection);
15801597

1581-
$selections = $selections.add($selection);
1598+
$selections.push($selection);
15821599
}
15831600

1584-
this.$selection.find('.select2-selection__rendered').append($selections);
1601+
var $rendered = this.$selection.find('.select2-selection__rendered');
1602+
1603+
Utils.appendMany($rendered, $selections);
15851604
};
15861605

15871606
return MultipleSelection;
@@ -3015,7 +3034,7 @@ S2.define('select2/data/select',[
30153034
};
30163035

30173036
SelectAdapter.prototype.addOptions = function ($options) {
3018-
this.$element.append($options);
3037+
Utils.appendMany(this.$element, $options);
30193038
};
30203039

30213040
SelectAdapter.prototype.option = function (data) {
@@ -3185,7 +3204,7 @@ S2.define('select2/data/array',[
31853204
return self.item($(this)).id;
31863205
}).get();
31873206

3188-
var $options = $();
3207+
var $options = [];
31893208

31903209
// Filter out all items except for the one passed in the argument
31913210
function onlyItem (item) {
@@ -3216,10 +3235,10 @@ S2.define('select2/data/array',[
32163235
if (item.children) {
32173236
var $children = this.convertToOptions(item.children);
32183237

3219-
$option.append($children);
3238+
Utils.appendMany($option, $children);
32203239
}
32213240

3222-
$options = $options.add($option);
3241+
$options.push($option);
32233242
}
32243243

32253244
return $options;
@@ -3403,7 +3422,7 @@ S2.define('select2/data/tags',[
34033422
var $option = self.option(tag);
34043423
$option.attr('data-select2-tag', true);
34053424

3406-
self.addOptions($option);
3425+
self.addOptions([$option]);
34073426

34083427
self.insertTag(data, tag);
34093428
}

dist/js/select2.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/js/select2/compat/inputData.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ define([
116116
};
117117

118118
InputData.prototype.addOptions = function (_, $options) {
119-
var options = $.map($options, function (option) {
120-
return $.data(option, 'data');
119+
var options = $.map($options, function ($option) {
120+
return $.data($option[0], 'data');
121121
});
122122

123123
this._currentData.push.apply(this._currentData, options);

src/js/select2/data/array.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ define([
3535
return self.item($(this)).id;
3636
}).get();
3737

38-
var $options = $();
38+
var $options = [];
3939

4040
// Filter out all items except for the one passed in the argument
4141
function onlyItem (item) {
@@ -66,10 +66,10 @@ define([
6666
if (item.children) {
6767
var $children = this.convertToOptions(item.children);
6868

69-
$option.append($children);
69+
Utils.appendMany($option, $children);
7070
}
7171

72-
$options = $options.add($option);
72+
$options.push($option);
7373
}
7474

7575
return $options;

src/js/select2/data/select.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ define([
151151
};
152152

153153
SelectAdapter.prototype.addOptions = function ($options) {
154-
this.$element.append($options);
154+
Utils.appendMany(this.$element, $options);
155155
};
156156

157157
SelectAdapter.prototype.option = function (data) {

src/js/select2/data/tags.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ define([
7171
var $option = self.option(tag);
7272
$option.attr('data-select2-tag', true);
7373

74-
self.addOptions($option);
74+
self.addOptions([$option]);
7575

7676
self.insertTag(data, tag);
7777
}

src/js/select2/selection/multiple.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ define([
7676
return;
7777
}
7878

79-
var $selections = $();
79+
var $selections = [];
8080

8181
for (var d = 0; d < data.length; d++) {
8282
var selection = data[d];
@@ -89,10 +89,12 @@ define([
8989

9090
$selection.data('data', selection);
9191

92-
$selections = $selections.add($selection);
92+
$selections.push($selection);
9393
}
9494

95-
this.$selection.find('.select2-selection__rendered').append($selections);
95+
var $rendered = this.$selection.find('.select2-selection__rendered');
96+
97+
Utils.appendMany($rendered, $selections);
9698
};
9799

98100
return MultipleSelection;

src/js/select2/utils.js

+17
Original file line numberDiff line numberDiff line change
@@ -241,5 +241,22 @@ define([
241241
});
242242
};
243243

244+
// Append an array of jQuery nodes to a given element.
245+
Utils.appendMany = function ($element, $nodes) {
246+
// jQuery 1.7.x does not support $.fn.append() with an array
247+
// Fall back to a jQuery object collection using $.fn.add()
248+
if ($.fn.jquery.substr(0, 3) === '1.7') {
249+
var $jqNodes = $();
250+
251+
$.map($nodes, function (node) {
252+
$jqNodes = $jqNodes.add(node);
253+
});
254+
255+
$nodes = $jqNodes;
256+
}
257+
258+
$element.append($nodes);
259+
};
260+
244261
return Utils;
245262
});

0 commit comments

Comments
 (0)