1
0
mirror of synced 2024-11-22 21:16:10 +03:00

rewrite classes in a more readable way. closes #20

This commit is contained in:
Igor Vaynberg 2012-04-12 00:33:10 -07:00
parent 1faea146d4
commit 8323051ce3

View File

@ -24,7 +24,9 @@
return; return;
} }
var KEY = { var KEY, AbstractSelect2, SingleSelect2, MultiSelect2;
KEY = {
TAB: 9, TAB: 9,
ENTER: 13, ENTER: 13,
ESC: 27, ESC: 27,
@ -298,21 +300,32 @@
}); });
}); });
/** /**
* Creates a new class
* *
* @param opts * @param superClass
* @param methods
*/ */
function AbstractSelect2() { function clazz(superClass, methods) {
var clazz = function () {};
clazz.prototype = new superClass;
clazz.prototype.constructor = clazz;
clazz.prototype.parent = superClass.prototype;
clazz.prototype = $.extend(clazz.prototype, methods);
return clazz;
} }
AbstractSelect2.prototype.bind = function (func) { AbstractSelect2 = clazz(Object, {
bind: function (func) {
var self = this; var self = this;
return function () { return function () {
func.apply(self, arguments); func.apply(self, arguments);
}; };
}; },
AbstractSelect2.prototype.init = function (opts) { init: function (opts) {
var results, search, resultsSelector = ".select2-results"; var results, search, resultsSelector = ".select2-results";
// prepare options // prepare options
@ -386,9 +399,9 @@
// we monitor the change event on the element and trigger it, allowing for two way synchronization // we monitor the change event on the element and trigger it, allowing for two way synchronization
this.monitorSource(); this.monitorSource();
} }
}; },
AbstractSelect2.prototype.destroy = function () { destroy: function () {
var select2 = this.opts.element.data("select2"); var select2 = this.opts.element.data("select2");
if (select2 !== undefined) { if (select2 !== undefined) {
select2.container.remove(); select2.container.remove();
@ -396,9 +409,9 @@
.removeData("select2") .removeData("select2")
.show(); .show();
} }
}; },
AbstractSelect2.prototype.prepareOpts = function (opts) { prepareOpts: function (opts) {
var element, select; var element, select;
opts = $.extend({}, { opts = $.extend({}, {
@ -472,40 +485,40 @@
} }
return opts; return opts;
}; },
/** /**
* Monitor the original element for changes and update select2 accordingly * Monitor the original element for changes and update select2 accordingly
*/ */
AbstractSelect2.prototype.monitorSource = function () { monitorSource: function () {
this.opts.element.bind("change", this.bind(function (e) { this.opts.element.bind("change", this.bind(function (e) {
if (this.opts.element.data("select2-change-triggered") !== true) { if (this.opts.element.data("select2-change-triggered") !== true) {
this.initSelection(); this.initSelection();
} }
})); }));
}; },
/** /**
* Triggers the change event on the source element * Triggers the change event on the source element
*/ */
AbstractSelect2.prototype.triggerChange = function () { triggerChange: function () {
// Prevents recursive triggering // Prevents recursive triggering
this.opts.element.data("select2-change-triggered", true); this.opts.element.data("select2-change-triggered", true);
this.opts.element.trigger("change"); this.opts.element.trigger("change");
this.opts.element.data("select2-change-triggered", false); this.opts.element.data("select2-change-triggered", false);
}; },
AbstractSelect2.prototype.opened = function () { opened: function () {
return this.container.hasClass("select2-dropdown-open"); return this.container.hasClass("select2-dropdown-open");
}; },
AbstractSelect2.prototype.alignDropdown = function () { alignDropdown: function () {
this.dropdown.css({ this.dropdown.css({
top: this.container.height() top: this.container.height()
}); });
}; },
AbstractSelect2.prototype.open = function () { open: function () {
if (this.opened()) return; if (this.opened()) return;
this.container.addClass("select2-dropdown-open").addClass("select2-container-active"); this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
@ -514,22 +527,22 @@
this.alignDropdown(); this.alignDropdown();
this.dropdown.show(); this.dropdown.show();
this.focusSearch(); this.focusSearch();
}; },
AbstractSelect2.prototype.close = function () { close: function () {
if (!this.opened()) return; if (!this.opened()) return;
this.dropdown.hide(); this.dropdown.hide();
this.container.removeClass("select2-dropdown-open"); this.container.removeClass("select2-dropdown-open");
this.results.empty(); this.results.empty();
this.clearSearch(); this.clearSearch();
}; },
AbstractSelect2.prototype.clearSearch = function () { clearSearch: function () {
}; },
AbstractSelect2.prototype.ensureHighlightVisible = function () { ensureHighlightVisible: function () {
var results = this.results, children, index, child, hb, rb, y, more; var results = this.results, children, index, child, hb, rb, y, more;
children = results.children(".select2-result"); children = results.children(".select2-result");
@ -559,9 +572,9 @@
if (y < 0) { if (y < 0) {
results.scrollTop(results.scrollTop() + y); // y is negative results.scrollTop(results.scrollTop() + y); // y is negative
} }
}; },
AbstractSelect2.prototype.moveHighlight = function (delta) { moveHighlight: function (delta) {
var choices = this.results.children(".select2-result"), var choices = this.results.children(".select2-result"),
index = this.highlight(); index = this.highlight();
@ -572,9 +585,9 @@
break; break;
} }
} }
}; },
AbstractSelect2.prototype.highlight = function (index) { highlight: function (index) {
var choices = this.results.children(".select2-result"); var choices = this.results.children(".select2-result");
if (arguments.length === 0) { if (arguments.length === 0) {
@ -590,16 +603,16 @@
this.ensureHighlightVisible(); this.ensureHighlightVisible();
if (this.opened()) this.focusSearch(); if (this.opened()) this.focusSearch();
}; },
AbstractSelect2.prototype.highlightUnderEvent = function (event) { highlightUnderEvent: function (event) {
var el = $(event.target).closest(".select2-result"); var el = $(event.target).closest(".select2-result");
if (el.length > 0) { if (el.length > 0) {
this.highlight(el.index()); this.highlight(el.index());
} }
}; },
AbstractSelect2.prototype.loadMoreIfNeeded = function () { loadMoreIfNeeded: function () {
var results = this.results, var results = this.results,
more = results.find("li.select2-more-results"), more = results.find("li.select2-more-results"),
below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
@ -636,12 +649,12 @@
this.resultsPage = page; this.resultsPage = page;
})}); })});
} }
}; },
/** /**
* @param initial whether or not this is the call to this method right after the dropdown has been opened * @param initial whether or not this is the call to this method right after the dropdown has been opened
*/ */
AbstractSelect2.prototype.updateResults = function (initial) { updateResults: function (initial) {
var search = this.search, results = this.results, opts = this.opts; var search = this.search, results = this.results, opts = this.opts;
search.addClass("select2-active"); search.addClass("select2-active");
@ -697,13 +710,13 @@
}); });
this.postprocessResults(data, initial); this.postprocessResults(data, initial);
})}); })});
}; },
AbstractSelect2.prototype.cancel = function () { cancel: function () {
this.close(); this.close();
}; },
AbstractSelect2.prototype.blur = function () { blur: function () {
/* we do this in a timeout so that current event processing can complete before this code is executed. /* we do this in a timeout so that current event processing can complete before this code is executed.
this allows tab index to be preserved even if this code blurs the textfield */ this allows tab index to be preserved even if this code blurs the textfield */
window.setTimeout(this.bind(function () { window.setTimeout(this.bind(function () {
@ -713,28 +726,28 @@
this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
this.search.blur(); this.search.blur();
}), 10); }), 10);
}; },
AbstractSelect2.prototype.focusSearch = function () { focusSearch: function () {
/* we do this in a timeout so that current event processing can complete before this code is executed. /* we do this in a timeout so that current event processing can complete before this code is executed.
this makes sure the search field is focussed even if the current event would blur it */ this makes sure the search field is focussed even if the current event would blur it */
window.setTimeout(this.bind(function () { window.setTimeout(this.bind(function () {
this.search.focus(); this.search.focus();
}), 10); }), 10);
}; },
AbstractSelect2.prototype.selectHighlighted = function () { selectHighlighted: function () {
var data = this.results.find(".select2-highlighted:not(.select2-disabled)").data("select2-data"); var data = this.results.find(".select2-highlighted:not(.select2-disabled)").data("select2-data");
if (data) { if (data) {
this.onSelect(data); this.onSelect(data);
} }
}; },
AbstractSelect2.prototype.getPlaceholder = function () { getPlaceholder: function () {
var placeholder = this.opts.element.data("placeholder"); var placeholder = this.opts.element.data("placeholder");
if (placeholder !== undefined) return placeholder; if (placeholder !== undefined) return placeholder;
return this.opts.placeholder; return this.opts.placeholder;
}; },
/** /**
* Get the desired width for the container element. This is * Get the desired width for the container element. This is
@ -744,7 +757,7 @@
* *
* @returns The width string (with units) for the container. * @returns The width string (with units) for the container.
*/ */
AbstractSelect2.prototype.getContainerWidth = function () { getContainerWidth: function () {
if (this.opts.width !== undefined) if (this.opts.width !== undefined)
return this.opts.width; return this.opts.width;
@ -759,16 +772,12 @@
} }
} }
return this.opts.element.width() + 'px'; return this.opts.element.width() + 'px';
};
function SingleSelect2() {
} }
});
SingleSelect2.prototype = new AbstractSelect2(); SingleSelect2 = clazz(AbstractSelect2, {
SingleSelect2.prototype.constructor = SingleSelect2;
SingleSelect2.prototype.parent = AbstractSelect2.prototype;
SingleSelect2.prototype.createContainer = function () { createContainer: function () {
return $("<div></div>", { return $("<div></div>", {
"class": "select2-container", "class": "select2-container",
"style": "width: " + this.getContainerWidth() "style": "width: " + this.getContainerWidth()
@ -784,27 +793,27 @@
" <ul class='select2-results'>" , " <ul class='select2-results'>" ,
" </ul>" , " </ul>" ,
"</div>"].join("")); "</div>"].join(""));
}; },
SingleSelect2.prototype.open = function () { open: function () {
if (this.opened()) return; if (this.opened()) return;
this.parent.open.apply(this, arguments); this.parent.open.apply(this, arguments);
}; },
SingleSelect2.prototype.close = function () { close: function () {
if (!this.opened()) return; if (!this.opened()) return;
this.parent.close.apply(this, arguments); this.parent.close.apply(this, arguments);
}; },
SingleSelect2.prototype.cancel = function () { cancel: function () {
this.parent.cancel.apply(this, arguments); this.parent.cancel.apply(this, arguments);
this.selection.focus(); this.selection.focus();
}; },
SingleSelect2.prototype.initContainer = function () { initContainer: function () {
var selection, container = this.container, clickingInside = false, var selection, container = this.container, clickingInside = false,
selector = ".select2-choice", selected; selector = ".select2-choice", selected;
@ -871,12 +880,12 @@
})); }));
this.setPlaceholder(); this.setPlaceholder();
}; },
/** /**
* Sets selection based on source element's value * Sets selection based on source element's value
*/ */
SingleSelect2.prototype.initSelection = function () { initSelection: function () {
var selected; var selected;
if (this.opts.element.val() === "") { if (this.opts.element.val() === "") {
this.updateSelection({id: "", text: ""}); this.updateSelection({id: "", text: ""});
@ -889,9 +898,9 @@
this.close(); this.close();
this.setPlaceholder(); this.setPlaceholder();
}; },
SingleSelect2.prototype.prepareOpts = function () { prepareOpts: function () {
var opts = this.parent.prepareOpts.apply(this, arguments); var opts = this.parent.prepareOpts.apply(this, arguments);
if (opts.element.get(0).tagName.toLowerCase() === "select") { if (opts.element.get(0).tagName.toLowerCase() === "select") {
@ -904,9 +913,9 @@
} }
return opts; return opts;
}; },
SingleSelect2.prototype.setPlaceholder = function () { setPlaceholder: function () {
var placeholder = this.getPlaceholder(); var placeholder = this.getPlaceholder();
if (this.opts.element.val() === "" && placeholder !== undefined) { if (this.opts.element.val() === "" && placeholder !== undefined) {
@ -923,9 +932,9 @@
this.selection.find("abbr").hide(); this.selection.find("abbr").hide();
} }
}; },
SingleSelect2.prototype.postprocessResults = function (data, initial) { postprocessResults: function (data, initial) {
var selected = 0, self = this; var selected = 0, self = this;
// find the selected element in the result list // find the selected element in the result list
@ -947,9 +956,9 @@
this.search.parent().toggle(data.results.length >= this.opts.minimumResultsForSearch); this.search.parent().toggle(data.results.length >= this.opts.minimumResultsForSearch);
} }
}; },
SingleSelect2.prototype.onSelect = function (data) { onSelect: function (data) {
var old = this.opts.element.val(); var old = this.opts.element.val();
this.opts.element.val(data.id); this.opts.element.val(data.id);
@ -958,9 +967,9 @@
this.selection.focus(); this.selection.focus();
if (!equal(old, data.id)) { this.triggerChange(); } if (!equal(old, data.id)) { this.triggerChange(); }
}; },
SingleSelect2.prototype.updateSelection = function (data) { updateSelection: function (data) {
this.selection this.selection
.find("span") .find("span")
.html(this.opts.formatSelection(data)); .html(this.opts.formatSelection(data));
@ -970,9 +979,9 @@
if (this.opts.allowClear && this.getPlaceholder() !== undefined) { if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
this.selection.find("abbr").show(); this.selection.find("abbr").show();
} }
}; },
SingleSelect2.prototype.val = function () { val: function () {
var val, data = null; var val, data = null;
if (arguments.length === 0) { if (arguments.length === 0) {
@ -997,21 +1006,16 @@
} }
this.setPlaceholder(); this.setPlaceholder();
}; },
SingleSelect2.prototype.clearSearch = function () { clearSearch: function () {
this.search.val(""); this.search.val("");
};
function MultiSelect2(opts) {
} }
});
MultiSelect2.prototype = new AbstractSelect2(); MultiSelect2 = clazz(AbstractSelect2, {
MultiSelect2.prototype.constructor = AbstractSelect2;
MultiSelect2.prototype.parent = AbstractSelect2.prototype;
MultiSelect2.prototype.createContainer = function () { createContainer: function () {
return $("<div></div>", { return $("<div></div>", {
"class": "select2-container select2-container-multi", "class": "select2-container select2-container-multi",
"style": "width: " + this.getContainerWidth() "style": "width: " + this.getContainerWidth()
@ -1026,9 +1030,9 @@
" <ul class='select2-results'>" , " <ul class='select2-results'>" ,
" </ul>" , " </ul>" ,
"</div>"].join("")); "</div>"].join(""));
}; },
MultiSelect2.prototype.prepareOpts = function () { prepareOpts: function () {
var opts = this.parent.prepareOpts.apply(this, arguments); var opts = this.parent.prepareOpts.apply(this, arguments);
if (opts.element.get(0).tagName.toLowerCase() === "select") { if (opts.element.get(0).tagName.toLowerCase() === "select") {
@ -1043,9 +1047,9 @@
} }
return opts; return opts;
}; },
MultiSelect2.prototype.initContainer = function () { initContainer: function () {
var selector = ".select2-choices", selection, data; var selector = ".select2-choices", selection, data;
@ -1118,9 +1122,9 @@
// set the placeholder if necessary // set the placeholder if necessary
this.clearSearch(); this.clearSearch();
}; },
MultiSelect2.prototype.initSelection = function () { initSelection: function () {
var data; var data;
if (this.opts.element.val() === "") { if (this.opts.element.val() === "") {
this.updateSelection([]); this.updateSelection([]);
@ -1136,9 +1140,9 @@
// set the placeholder if necessary // set the placeholder if necessary
this.clearSearch(); this.clearSearch();
}; },
MultiSelect2.prototype.clearSearch = function () { clearSearch: function () {
var placeholder = this.getPlaceholder(); var placeholder = this.getPlaceholder();
this.search.val("").width(10); this.search.val("").width(10);
@ -1147,27 +1151,27 @@
this.search.val(placeholder).addClass("select2-default"); this.search.val(placeholder).addClass("select2-default");
this.resizeSearch(); this.resizeSearch();
} }
}; },
MultiSelect2.prototype.clearPlaceholder = function () { clearPlaceholder: function () {
if (this.search.hasClass("select2-default")) { if (this.search.hasClass("select2-default")) {
this.search.val("").removeClass("select2-default"); this.search.val("").removeClass("select2-default");
} }
}; },
MultiSelect2.prototype.open = function () { open: function () {
if (this.opened()) return; if (this.opened()) return;
this.parent.open.apply(this, arguments); this.parent.open.apply(this, arguments);
this.resizeSearch(); this.resizeSearch();
this.focusSearch(); this.focusSearch();
}; },
MultiSelect2.prototype.close = function () { close: function () {
if (!this.opened()) return; if (!this.opened()) return;
this.parent.close.apply(this, arguments); this.parent.close.apply(this, arguments);
}; },
MultiSelect2.prototype.updateSelection = function (data) { updateSelection: function (data) {
var ids = [], filtered = [], self = this; var ids = [], filtered = [], self = this;
// filter out duplicates // filter out duplicates
@ -1185,9 +1189,9 @@
}); });
self.postprocessResults(); self.postprocessResults();
this.alignDropdown(); this.alignDropdown();
}; },
MultiSelect2.prototype.onSelect = function (data) { onSelect: function (data) {
this.addSelectedChoice(data); this.addSelectedChoice(data);
if (this.select) { this.postprocessResults(); } if (this.select) { this.postprocessResults(); }
this.close(); this.close();
@ -1198,14 +1202,14 @@
this.triggerChange(); this.triggerChange();
this.focusSearch(); this.focusSearch();
}; },
MultiSelect2.prototype.cancel = function () { cancel: function () {
this.close(); this.close();
this.focusSearch(); this.focusSearch();
}; },
MultiSelect2.prototype.addSelectedChoice = function (data) { addSelectedChoice: function (data) {
var choice, var choice,
id = data.id, id = data.id,
parts, parts,
@ -1234,9 +1238,9 @@
val.push(id); val.push(id);
this.setVal(val); this.setVal(val);
}; },
MultiSelect2.prototype.unselect = function (selected) { unselect: function (selected) {
var val = this.getVal(), var val = this.getVal(),
index; index;
@ -1256,9 +1260,9 @@
selected.remove(); selected.remove();
this.triggerChange(); this.triggerChange();
window.setTimeout(this.bind(this.alignDropdown), 20); window.setTimeout(this.bind(this.alignDropdown), 20);
}; },
MultiSelect2.prototype.postprocessResults = function () { postprocessResults: function () {
var val = this.getVal(), var val = this.getVal(),
choices = this.results.find(".select2-result"), choices = this.results.find(".select2-result"),
self = this; self = this;
@ -1279,9 +1283,9 @@
} }
}); });
}; },
MultiSelect2.prototype.resizeSearch = function () { resizeSearch: function () {
var minimumWidth, left, maxWidth, containerLeft, searchWidth; var minimumWidth, left, maxWidth, containerLeft, searchWidth;
@ -1302,9 +1306,9 @@
searchWidth = maxWidth - getSideBorderPadding(this.search); searchWidth = maxWidth - getSideBorderPadding(this.search);
} }
this.search.width(searchWidth); this.search.width(searchWidth);
}; },
MultiSelect2.prototype.getVal = function () { getVal: function () {
var val; var val;
if (this.select) { if (this.select) {
val = this.select.val(); val = this.select.val();
@ -1313,9 +1317,9 @@
val = this.opts.element.val(); val = this.opts.element.val();
return (val === null || val === "") ? [] : val.split(","); return (val === null || val === "") ? [] : val.split(",");
} }
}; },
MultiSelect2.prototype.setVal = function (val) { setVal: function (val) {
var unique = []; var unique = [];
if (this.select) { if (this.select) {
this.select.val(val); this.select.val(val);
@ -1327,9 +1331,9 @@
this.opts.element.val(unique.length === 0 ? "" : unique.join(",")); this.opts.element.val(unique.length === 0 ? "" : unique.join(","));
} }
}; },
MultiSelect2.prototype.val = function () { val: function () {
var val, data = []; var val, data = [];
if (arguments.length === 0) { if (arguments.length === 0) {
@ -1354,7 +1358,8 @@
this.setVal(data); this.setVal(data);
this.updateSelection(val); this.updateSelection(val);
} }
}; }
});
$.fn.select2 = function () { $.fn.select2 = function () {