Skip to content

Commit

Permalink
Only trigger 'selection:update' once on DOM change events (#5734)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
dbramwell and kevin-brown committed Jan 28, 2020
1 parent 3b69d35 commit e0855a2
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
21 changes: 18 additions & 3 deletions src/js/select2/core.js
Expand Up @@ -208,8 +208,8 @@ define([

if (observer != null) {
this._observer = new observer(function (mutations) {
$.each(mutations, self._syncA);
$.each(mutations, self._syncS);
self._syncA();
self._syncS(null, mutations);
});
this._observer.observe(this.$element[0], {
attributes: true,
Expand Down Expand Up @@ -376,7 +376,7 @@ define([
}
};

Select2.prototype._syncSubtree = function (evt, mutations) {
Select2.prototype._isChangeMutation = function (evt, mutations) {
var changed = false;
var self = this;

Expand Down Expand Up @@ -404,7 +404,22 @@ define([
}
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
changed = true;
} else if ($.isArray(mutations)) {
$.each(mutations, function(evt, mutation) {
if (self._isChangeMutation(evt, mutation)) {
// We've found a change mutation.
// Let's escape from the loop and continue
changed = true;
return false;
}
});
}
return changed;
};

Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = this._isChangeMutation(evt, mutations);
var self = this;

// Only re-pull the data if we think there is a change
if (changed) {
Expand Down
44 changes: 44 additions & 0 deletions tests/integration/dom-changes.js
@@ -1,3 +1,4 @@
/*jshint browser: true */
module('DOM integration');

test('adding a new unselected option changes nothing', function (assert) {
Expand Down Expand Up @@ -286,3 +287,46 @@ test('searching tags does not loose focus', function (assert) {
select.selection.trigger('query', {term: 'f'});
select.selection.trigger('query', {term: 'ff'});
});


test('adding multiple options calls selection:update once', function (assert) {
assert.expect(1);

var asyncDone = assert.async();

var $ = require('jquery');
var Select2 = require('select2/core');

var content = '<select>';
var options = '';

for (var i = 0; i < 4000; i++) {
options += '<option>' + i + '</option>';
}

content += options;
content += '</select>';

var $select = $(content);

$('#qunit-fixture').append($select);

var select = new Select2($select);

var eventCalls = 0;

select.on('selection:update', function () {
eventCalls++;
});

$select.html(options);

setTimeout(function () {
assert.equal(
eventCalls,
1,
'selection:update was called more than once'
);
asyncDone();
}, 0);
});

0 comments on commit e0855a2

Please sign in to comment.