Skip to content

Commit e0855a2

Browse files
Only trigger 'selection:update' once on DOM change events (select2#5734)
* Only trigger 'selection:update' once on DOM change events * Fix linting errors * Add test for adding multiple options to a select * Switch Array.isArray to jQuery.isArray Because we're still doing best-effort IE8 support for some reason. * Fixed formatting in tests Co-authored-by: Kevin Brown <kevin-brown@users.noreply.github.com>
1 parent 3b69d35 commit e0855a2

2 files changed

Lines changed: 62 additions & 3 deletions

File tree

src/js/select2/core.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@ define([
208208

209209
if (observer != null) {
210210
this._observer = new observer(function (mutations) {
211-
$.each(mutations, self._syncA);
212-
$.each(mutations, self._syncS);
211+
self._syncA();
212+
self._syncS(null, mutations);
213213
});
214214
this._observer.observe(this.$element[0], {
215215
attributes: true,
@@ -376,7 +376,7 @@ define([
376376
}
377377
};
378378

379-
Select2.prototype._syncSubtree = function (evt, mutations) {
379+
Select2.prototype._isChangeMutation = function (evt, mutations) {
380380
var changed = false;
381381
var self = this;
382382

@@ -404,7 +404,22 @@ define([
404404
}
405405
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
406406
changed = true;
407+
} else if ($.isArray(mutations)) {
408+
$.each(mutations, function(evt, mutation) {
409+
if (self._isChangeMutation(evt, mutation)) {
410+
// We've found a change mutation.
411+
// Let's escape from the loop and continue
412+
changed = true;
413+
return false;
414+
}
415+
});
407416
}
417+
return changed;
418+
};
419+
420+
Select2.prototype._syncSubtree = function (evt, mutations) {
421+
var changed = this._isChangeMutation(evt, mutations);
422+
var self = this;
408423

409424
// Only re-pull the data if we think there is a change
410425
if (changed) {

tests/integration/dom-changes.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/*jshint browser: true */
12
module('DOM integration');
23

34
test('adding a new unselected option changes nothing', function (assert) {
@@ -286,3 +287,46 @@ test('searching tags does not loose focus', function (assert) {
286287
select.selection.trigger('query', {term: 'f'});
287288
select.selection.trigger('query', {term: 'ff'});
288289
});
290+
291+
292+
test('adding multiple options calls selection:update once', function (assert) {
293+
assert.expect(1);
294+
295+
var asyncDone = assert.async();
296+
297+
var $ = require('jquery');
298+
var Select2 = require('select2/core');
299+
300+
var content = '<select>';
301+
var options = '';
302+
303+
for (var i = 0; i < 4000; i++) {
304+
options += '<option>' + i + '</option>';
305+
}
306+
307+
content += options;
308+
content += '</select>';
309+
310+
var $select = $(content);
311+
312+
$('#qunit-fixture').append($select);
313+
314+
var select = new Select2($select);
315+
316+
var eventCalls = 0;
317+
318+
select.on('selection:update', function () {
319+
eventCalls++;
320+
});
321+
322+
$select.html(options);
323+
324+
setTimeout(function () {
325+
assert.equal(
326+
eventCalls,
327+
1,
328+
'selection:update was called more than once'
329+
);
330+
asyncDone();
331+
}, 0);
332+
});

0 commit comments

Comments
 (0)