Skip to content

Commit 735c2a2

Browse files
committed
Fix for selectize#11 & selectize#23 - "change" events are now only triggered once.
1 parent 01aa9cc commit 735c2a2

File tree

2 files changed

+86
-52
lines changed

2 files changed

+86
-52
lines changed

src/selectize.js

Lines changed: 56 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,13 @@ Selectize.prototype.getValue = function() {
457457
* @param {mixed} value
458458
*/
459459
Selectize.prototype.setValue = function(value) {
460-
this.clear();
461-
var items = $.isArray(value) ? value : [value];
462-
for (var i = 0, n = items.length; i < n; i++) {
463-
this.addItem(items[i]);
464-
}
460+
debounce_events(this, ['change'], function() {
461+
this.clear();
462+
var items = $.isArray(value) ? value : [value];
463+
for (var i = 0, n = items.length; i < n; i++) {
464+
this.addItem(items[i]);
465+
}
466+
});
465467
};
466468

467469
/**
@@ -993,59 +995,61 @@ Selectize.prototype.getItem = function(value) {
993995
* @param {string} value
994996
*/
995997
Selectize.prototype.addItem = function(value) {
996-
var $item;
997-
var self = this;
998-
var inputMode = this.settings.mode;
999-
value = String(value);
1000-
1001-
if (inputMode === 'single') this.clear();
1002-
if (inputMode === 'multi' && this.isFull()) return;
1003-
if (this.items.indexOf(value) !== -1) return;
1004-
if (!this.options.hasOwnProperty(value)) return;
1005-
1006-
$item = $(this.render('item', this.options[value]));
1007-
this.items.splice(this.caretPos, 0, value);
1008-
this.insertAtCaret($item);
1009-
this.refreshClasses();
998+
debounce_events(this, ['change'], function() {
999+
var $item;
1000+
var self = this;
1001+
var inputMode = this.settings.mode;
1002+
value = String(value);
1003+
1004+
if (inputMode === 'single') this.clear();
1005+
if (inputMode === 'multi' && this.isFull()) return;
1006+
if (this.items.indexOf(value) !== -1) return;
1007+
if (!this.options.hasOwnProperty(value)) return;
1008+
1009+
$item = $(this.render('item', this.options[value]));
1010+
this.items.splice(this.caretPos, 0, value);
1011+
this.insertAtCaret($item);
1012+
this.refreshClasses();
10101013

1011-
if (this.isSetup) {
1012-
// remove the option from the menu
1013-
var options = this.$dropdown[0].childNodes;
1014-
for (var i = 0; i < options.length; i++) {
1015-
var $option = $(options[i]);
1016-
if ($option.attr('data-value') === value) {
1017-
$option.remove();
1018-
if ($option[0] === this.$activeOption[0]) {
1019-
this.setActiveOption(options.length ? $(options[0]).addClass('active') : null);
1014+
if (this.isSetup) {
1015+
// remove the option from the menu
1016+
var options = this.$dropdown[0].childNodes;
1017+
for (var i = 0; i < options.length; i++) {
1018+
var $option = $(options[i]);
1019+
if ($option.attr('data-value') === value) {
1020+
$option.remove();
1021+
if ($option[0] === this.$activeOption[0]) {
1022+
this.setActiveOption(options.length ? $(options[0]).addClass('active') : null);
1023+
}
1024+
break;
10201025
}
1021-
break;
10221026
}
1023-
}
10241027

1025-
// hide the menu if the maximum number of items have been selected or no options are left
1026-
if (!options.length || (this.settings.maxItems !== null && this.items.length >= this.settings.maxItems)) {
1027-
this.close();
1028-
} else {
1029-
this.positionDropdown();
1030-
}
1028+
// hide the menu if the maximum number of items have been selected or no options are left
1029+
if (!options.length || (this.settings.maxItems !== null && this.items.length >= this.settings.maxItems)) {
1030+
this.close();
1031+
} else {
1032+
this.positionDropdown();
1033+
}
10311034

1032-
// restore focus to input
1033-
if (this.isFocused) {
1034-
window.setTimeout(function() {
1035-
if (inputMode === 'single') {
1036-
self.blur();
1037-
self.focus(false);
1038-
self.hideInput();
1039-
} else {
1040-
self.focus(false);
1041-
}
1042-
}, 0);
1043-
}
1035+
// restore focus to input
1036+
if (this.isFocused) {
1037+
window.setTimeout(function() {
1038+
if (inputMode === 'single') {
1039+
self.blur();
1040+
self.focus(false);
1041+
self.hideInput();
1042+
} else {
1043+
self.focus(false);
1044+
}
1045+
}, 0);
1046+
}
10441047

1045-
this.updatePlaceholder();
1046-
this.updateOriginalInput();
1047-
this.trigger('onItemAdd', value, $item);
1048-
}
1048+
this.updatePlaceholder();
1049+
this.trigger('onItemAdd', value, $item);
1050+
this.updateOriginalInput();
1051+
}
1052+
});
10491053
};
10501054

10511055
/**

src/utils.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,36 @@ var debounce = function(fn, delay) {
3131
};
3232
};
3333

34+
/**
35+
* Debounce all fired events types listed in `types`
36+
* while executing the provided `fn`.
37+
*
38+
* @param {object} self
39+
* @param {array} types
40+
* @param {function} fn
41+
*/
42+
var debounce_events = function(self, types, fn) {
43+
var type;
44+
var trigger = self.trigger;
45+
var event_args = {};
46+
47+
// override trigger method
48+
self.trigger = function() {
49+
event_args[arguments[0]] = arguments;
50+
};
51+
52+
// invoke provided function
53+
fn.apply(self, []);
54+
self.trigger = trigger;
55+
56+
// trigger queued events
57+
for (type in event_args) {
58+
if (event_args.hasOwnProperty(type)) {
59+
trigger.apply(self, event_args[type]);
60+
}
61+
}
62+
};
63+
3464
/**
3565
* A workaround for http://bugs.jquery.com/ticket/6696
3666
*

0 commit comments

Comments
 (0)