From 54033cdb0422ef7cc5c35ff5e94e3034a0539df5 Mon Sep 17 00:00:00 2001 From: Igor Vaynberg Date: Wed, 11 Apr 2012 00:51:27 -0700 Subject: [PATCH] monitors source element for change events and syncs the selection. opts.initSelection function has to be specified by the user for this to work because ids have to be mapped back to objects. select2 provides this function automatically for select elements and tags helper. --- select2.js | 84 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/select2.js b/select2.js index 21552373..4dce400c 100755 --- a/select2.js +++ b/select2.js @@ -369,6 +369,15 @@ this.focusSearch(); } })); + + if ($.isFunction(this.opts.initSelection)) { + // initialize selection based on the current value of the source element + this.initSelection(); + + // if the user has provided a function that can set selection based on the value of the source element + // we monitor the change event on the element and trigger it, allowing for two way synchronization + this.monitorSource(); + } }; AbstractSelect2.prototype.prepareOpts = function (opts) { @@ -447,11 +456,25 @@ return opts; }; + /** + * Monitor the original element for changes and update select2 accordingly + */ + AbstractSelect2.prototype.monitorSource = function () { + this.opts.element.bind("change", this.bind(function (e) { + if (this.opts.element.data("select2-change-triggered") !== true) { + this.initSelection(); + } + })); + }; + /** * Triggers the change event on the source element */ AbstractSelect2.prototype.triggerChange = function () { + // Prevents recursive triggering + this.opts.element.data("select2-change-triggered", true); this.opts.element.trigger("change"); + this.opts.element.data("select2-change-triggered", false); }; AbstractSelect2.prototype.opened = function () { @@ -829,15 +852,24 @@ this.triggerChange(); })); - if ($.isFunction(this.opts.initSelection)) { - if (this.select || this.opts.element.val() !== "") { - selected = this.opts.initSelection.call(null, this.opts.element); - if (selected !== undefined && selected != null) { - this.updateSelection(selected); - } + this.setPlaceholder(); + }; + + /** + * Sets selection based on source element's value + */ + SingleSelect2.prototype.initSelection = function () { + var selected; + if (this.opts.element.val() === "") { + this.updateSelection({id: "", text: ""}); + } else { + selected = this.opts.initSelection.call(null, this.opts.element); + if (selected !== undefined && selected !== null) { + this.updateSelection(selected); } } + this.close(); this.setPlaceholder(); }; @@ -1066,15 +1098,24 @@ this.clearPlaceholder(); })); - if ($.isFunction(this.opts.initSelection)) { - if (this.select || this.opts.element.val() !== "") { - data = this.opts.initSelection.call(null, this.opts.element); - if (data !== undefined && data != null) { - this.updateSelection(data); - } + // set the placeholder if necessary + this.clearSearch(); + }; + + MultiSelect2.prototype.initSelection = function () { + var data; + if (this.opts.element.val() === "") { + this.updateSelection([]); + } + if (this.select || this.opts.element.val() !== "") { + data = this.opts.initSelection.call(null, this.opts.element); + if (data !== undefined && data != null) { + this.updateSelection(data); } } + this.close(); + // set the placeholder if necessary this.clearSearch(); }; @@ -1109,7 +1150,16 @@ }; MultiSelect2.prototype.updateSelection = function (data) { - var self = this; + var ids = [], filtered = [], self = this; + + // filter out duplicates + $(data).each(function () { + if (indexOf(this.id, ids) < 0) { + ids.push(this.id); filtered.push(this); + } + }); + data = filtered; + this.selection.find(".select2-search-choice").remove(); $(data).each(function () { self.addSelectedChoice(this); @@ -1247,10 +1297,16 @@ }; MultiSelect2.prototype.setVal = function (val) { + var unique = []; if (this.select) { this.select.val(val); } else { - this.opts.element.val(val.length === 0 ? "" : val.join(",")); + // filter out duplicates + $(val).each(function () { + if (indexOf(this, unique) < 0) unique.push(this); + }); + + this.opts.element.val(unique.length === 0 ? "" : unique.join(",")); } };