diff --git a/select2-2.0/README.md b/select2-2.0/README.md new file mode 100755 index 00000000..3cc3a2e7 --- /dev/null +++ b/select2-2.0/README.md @@ -0,0 +1,38 @@ +Select2 +================= + +Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results. Look and feel of Select2 is based on the excellent [Chosen](http://harvesthq.github.com/chosen/) library. + +To get started -- checkout http://ivaynberg.github.com/select2! + +Bug tracker +----------- + +Have a bug? Please create an issue here on GitHub! + +https://github.com/ivaynberg/select2/issues + + +Mailing list +------------ + +Have a question? Ask on our mailing list! + +select2@googlegroups.com + +https://groups.google.com/d/forum/select2 + + +Copyright and License +--------------------- + +Copyright 2012 Igor Vaynberg + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in +compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is +distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and limitations under the License. \ No newline at end of file diff --git a/select2-2.0/select2.css b/select2-2.0/select2.css new file mode 100755 index 00000000..20c03d9b --- /dev/null +++ b/select2-2.0/select2.css @@ -0,0 +1,411 @@ +/* +Version: 2.0 Timestamp: Wed, May 16, 2012 10:38:37 AM +*/ +.select2-container { + position: relative; + display: inline-block; + /* inline-block for ie7 */ + zoom: 1; + *display: inline; + +} + +.select2-container, +.select2-drop, +.select2-search, +.select2-container .select2-search input{ + /* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + + More Info : http://www.quirksmode.org/css/box.html + */ + -moz-box-sizing: border-box; /* firefox */ + -ms-box-sizing: border-box; /* ie */ + -webkit-box-sizing: border-box; /* webkit */ + -khtml-box-sizing: border-box; /* konqueror */ + box-sizing: border-box; /* css3 */ +} + +.select2-container .select2-choice { + background-color: #fff; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)); + background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image: -o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%); + background-image: -ms-linear-gradient(top, #eeeeee 0%, #ffffff 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#ffffff', GradientType = 0); + background-image: linear-gradient(top, #eeeeee 0%, #ffffff 50%); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #aaa; + display: block; + overflow: hidden; + white-space: nowrap; + position: relative; + height: 26px; + line-height: 26px; + padding: 0 0 0 8px; + color: #444; + text-decoration: none; +} + +.select2-container .select2-choice span { + margin-right: 26px; + display: block; + overflow: hidden; + white-space: nowrap; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + text-overflow: ellipsis; +} + +.select2-container .select2-choice abbr { + display: block; + position: absolute; + right: 26px; + top: 8px; + width: 12px; + height: 12px; + font-size: 1px; + background: url(select2.png) right top no-repeat; + cursor: pointer; + text-decoration: none; + border:0; + outline: 0; +} +.select2-container .select2-choice abbr:hover { + background-position: right -11px; + cursor: pointer; +} + +.select2-container .select2-drop { + background: #fff; + border: 1px solid #aaa; + border-top: 0; + position: absolute; + top: 100%; + -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + -o-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + z-index: 999; + width:100%; + margin-top:-1px; + + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.select2-container .select2-choice div { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + background: #ccc; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); + background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%); + background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#cccccc', endColorstr = '#eeeeee', GradientType = 0); + background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%); + border-left: 1px solid #aaa; + position: absolute; + right: 0; + top: 0; + display: block; + height: 100%; + width: 18px; +} + +.select2-container .select2-choice div b { + background: url('select2.png') no-repeat 0 1px; + display: block; + width: 100%; + height: 100%; +} + +.select2-container .select2-search { + display: inline-block; + white-space: nowrap; + z-index: 1010; + min-height: 26px; + width: 100%; + margin: 0; + padding-left: 4px; + padding-right: 4px; +} + +.select2-container .select2-search input { + background: #fff url('select2.png') no-repeat 100% -22px; + background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%); + padding: 4px 20px 4px 5px; + outline: 0; + border: 1px solid #aaa; + font-family: sans-serif; + font-size: 1em; + width:100%; + margin:0; + height:auto !important; + min-height: 26px; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; +} + +.select2-container .select2-search input.select2-active { + background: #fff url('spinner.gif') no-repeat 100%; + background: url('spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%); +} + + +.select2-container-active .select2-choice, +.select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; + outline: none; +} + +.select2-dropdown-open .select2-choice { + border: 1px solid #aaa; + border-bottom-color: transparent; + -webkit-box-shadow: 0 1px 0 #fff inset; + -moz-box-shadow : 0 1px 0 #fff inset; + -o-box-shadow : 0 1px 0 #fff inset; + box-shadow : 0 1px 0 #fff inset; + background-color: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee)); + background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%); + background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); + background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%); + -webkit-border-bottom-left-radius : 0; + -webkit-border-bottom-right-radius: 0; + -moz-border-radius-bottomleft : 0; + -moz-border-radius-bottomright: 0; + border-bottom-left-radius : 0; + border-bottom-right-radius: 0; +} + +.select2-dropdown-open .select2-choice div { + background: transparent; + border-left: none; +} +.select2-dropdown-open .select2-choice div b { + background-position: -18px 1px; +} + +/* results */ +.select2-container .select2-results { + margin: 4px 4px 4px 0; + padding: 0 0 0 4px; + position: relative; + overflow-x: hidden; + overflow-y: auto; + max-height: 200px; +} +.select2-container .select2-results li { + line-height: 80%; + padding: 7px 7px 8px; + margin: 0; + list-style: none; + cursor: pointer; + display: list-item; +} + +.select2-container .select2-results .select2-highlighted { + background: #3875d7; + color: #fff; +} +.select2-container .select2-results li em { + background: #feffde; + font-style: normal; +} +.select2-container .select2-results .select2-highlighted em { + background: transparent; +} +.select2-container .select2-results .select2-no-results { + background: #f4f4f4; + display: list-item; +} + +/* +disabled look for already selected choices in the results dropdown +.select2-container .select2-results .select2-disabled.select2-highlighted { + color: #666; + background: #f4f4f4; + display: list-item; + cursor: default; +} +.select2-container .select2-results .select2-disabled { + background: #f4f4f4; + display: list-item; + cursor: default; +} +*/ +.select2-container .select2-results .select2-disabled { + display: none; +} + +.select2-more-results.select2-active { + background: #f4f4f4 url('spinner.gif') no-repeat 100%; +} + +.select2-more-results { + background: #f4f4f4; + display: list-item; +} + +/* multiselect */ + +.select2-container-multi .select2-choices { + background-color: #fff; + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); + background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%); + border: 1px solid #aaa; + margin: 0; + padding: 0; + cursor: text; + overflow: hidden; + height: auto !important; + height: 1%; + position: relative; +} + +.select2-container-multi .select2-drop { + margin-top:0; +} + +.select2-container-multi.select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; + outline: none; +} +.select2-container-multi .select2-choices li { + float: left; + list-style: none; +} +.select2-container-multi .select2-choices .select2-search-field { + white-space: nowrap; + margin: 0; + padding: 0; +} + +.select2-container-multi .select2-choices .select2-search-field input { + color: #666; + background: transparent !important; + font-family: sans-serif; + font-size: 100%; + height: 15px; + padding: 5px; + margin: 1px 0; + outline: 0; + border: 0; + -webkit-box-shadow: none; + -moz-box-shadow : none; + -o-box-shadow : none; + box-shadow : none; +} + + +.select2-default { + color: #999 !important; +} + +.select2-container-multi .select2-choices .select2-search-choice { + -webkit-border-radius: 3px; + -moz-border-radius : 3px; + border-radius : 3px; + -moz-background-clip : padding; + -webkit-background-clip: padding-box; + background-clip : padding-box; + background-color: #e4e4e4; + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 ); + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); + background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + -moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + color: #333; + border: 1px solid #aaaaaa; + line-height: 13px; + padding: 3px 5px 3px 18px; + margin: 3px 0 3px 5px; + position: relative; + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice span { + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice-focus { + background: #d4d4d4; +} + +.select2-search-choice-close { + display: block; + position: absolute; + right: 3px; + top: 4px; + width: 12px; + height: 13px; + font-size: 1px; + background: url(select2.png) right top no-repeat; + outline: none; +} + +.select2-container-multi .select2-search-choice-close { + left: 3px; +} + + +.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover { + background-position: right -11px; +} +.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close { + background-position: right -11px; +} + + +.select2-container-multi .select2-results { + margin: -1px 0 0; + padding: 0; +} + +/* end multiselect */ diff --git a/select2-2.0/select2.js b/select2-2.0/select2.js new file mode 100755 index 00000000..e5bc30a1 --- /dev/null +++ b/select2-2.0/select2.js @@ -0,0 +1,1473 @@ +/* + Copyright 2012 Igor Vaynberg + + Version: 2.0 Timestamp: Wed, May 16, 2012 10:38:37 AM + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in + compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the License is + distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and limitations under the License. + */ +(function ($, undefined) { + "use strict"; + /*global document, window, jQuery, console */ + + if (window.Select2 !== undefined) { + return; + } + + var KEY, AbstractSelect2, SingleSelect2, MultiSelect2; + + KEY = { + TAB: 9, + ENTER: 13, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SHIFT: 16, + CTRL: 17, + ALT: 18, + PAGE_UP: 33, + PAGE_DOWN: 34, + HOME: 36, + END: 35, + BACKSPACE: 8, + DELETE: 46, + isArrow: function (k) { + k = k.which ? k.which : k; + switch (k) { + case KEY.LEFT: + case KEY.RIGHT: + case KEY.UP: + case KEY.DOWN: + return true; + } + return false; + }, + isControl: function (k) { + k = k.which ? k.which : k; + switch (k) { + case KEY.SHIFT: + case KEY.CTRL: + case KEY.ALT: + return true; + } + return false; + }, + isFunctionKey: function (k) { + k = k.which ? k.which : k; + return k >= 112 && k <= 123; + } + }; + + function indexOf(value, array) { + var i = 0, l = array.length, v; + + if (value.constructor === String) { + for (; i < l; i = i + 1) if (value.localeCompare(array[i]) === 0) return i; + } else { + for (; i < l; i = i + 1) { + v = array[i]; + if (v.constructor === String) { + if (v.localeCompare(value) === 0) return i; + } else { + if (v === value) return i; + } + } + } + return -1; + } + + /** + * Compares equality of a and b taking into account that a and b may be strings, in which case localCompare is used + * @param a + * @param b + */ + function equal(a, b) { + if (a === b) return true; + if (a === undefined || b === undefined) return false; + if (a === null || b === null) return false; + if (a.constructor === String) return a.localeCompare(b) === 0; + if (b.constructor === String) return b.localeCompare(a) === 0; + return false; + } + + /** + * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty + * strings + * @param string + * @param separator + */ + function splitVal(string, separator) { + var val, i, l; + if (string === null || string.length < 1) return []; + val = string.split(separator); + for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]); + return val; + } + + function getSideBorderPadding(element) { + return element.outerWidth() - element.width(); + } + + function installKeyUpChangeEvent(element) { + element.bind("keydown", function () { + element.data("keyup-change-value", element.val()); + }); + element.bind("keyup", function () { + if (element.val() !== element.data("keyup-change-value")) { + element.trigger("keyup-change"); + } + }); + } + + /** + * filters mouse events so an event is fired only if the mouse moved. + * + * filters out mouse events that occur when mouse is stationary but + * the elements under the pointer are scrolled. + */ + $(document).delegate("*", "mousemove", function (e) { + $(document).data("select2-lastpos", {x: e.pageX, y: e.pageY}); + }); + function installFilteredMouseMove(element) { + element.bind("mousemove", function (e) { + var lastpos = $(document).data("select2-lastpos"); + if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) { + $(e.target).trigger("mousemove-filtered", e); + } + }); + } + + /** + * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made + * within the last quietMillis milliseconds. + * + * @param quietMillis number of milliseconds to wait before invoking fn + * @param fn function to be debounced + * @return debounced version of fn + */ + function debounce(quietMillis, fn) { + var timeout; + return function () { + window.clearTimeout(timeout); + timeout = window.setTimeout(fn, quietMillis); + }; + } + + function installDebouncedScroll(threshold, element) { + var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);}); + element.bind("scroll", function (e) { + if (indexOf(e.target, element.get()) >= 0) notify(e); + }); + } + + function killEvent(event) { + event.preventDefault(); + event.stopPropagation(); + } + + function measureTextWidth(e) { + var sizer, width; + sizer = $("
").css({ + position: "absolute", + left: "-1000px", + top: "-1000px", + display: "none", + fontSize: e.css("fontSize"), + fontFamily: e.css("fontFamily"), + fontStyle: e.css("fontStyle"), + fontWeight: e.css("fontWeight"), + letterSpacing: e.css("letterSpacing"), + textTransform: e.css("textTransform"), + whiteSpace: "nowrap" + }); + sizer.text(e.val()); + $("body").append(sizer); + width = sizer.width(); + sizer.remove(); + return width; + } + + /** + * Produces an ajax-based query function + * + * @param options object containing configuration paramters + * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax + * @param options.url url for the data + * @param options.data a function(searchTerm, pageNumber) that should return an object containing query string parameters for the above url. + * @param options.dataType request data type: ajax, jsonp, other datatatypes supported by jQuery's $.ajax function or the transport function if specified + * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often + * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2. + * The expected format is an object containing the following keys: + * results array of objects that will be used as choices + * more (optional) boolean indicating whether there are more results available + * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true} + */ + function ajax(options) { + var timeout, // current scheduled but not yet executed request + requestSequence = 0, // sequence used to drop out-of-order responses + handler = null, + quietMillis = options.quietMillis || 100; + + return function (query) { + window.clearTimeout(timeout); + timeout = window.setTimeout(function () { + requestSequence += 1; // increment the sequence + var requestNumber = requestSequence, // this request's sequence number + data = options.data, // ajax data function + transport = options.transport || $.ajax; + + data = data.call(this, query.term, query.page); + + if( null !== handler){ + handler.abort(); + } + handler = transport.call(null, { + url: options.url, + dataType: options.dataType, + data: data, + success: function (data) { + if (requestNumber < requestSequence) { + return; + } + // TODO 3.0 - replace query.page with query so users have access to term, page, etc. + query.callback(options.results(data, query.page)); + } + }); + }, quietMillis); + }; + } + + /** + * Produces a query function that works with a local array + * + * @param options object containing configuration parameters. The options parameter can either be an array or an + * object. + * + * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys. + * + * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain + * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text' + * key can either be a String in which case it is expected that each element in the 'data' array has a key with the + * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract + * the text. + */ + function local(options) { + var data = options, // data elements + text = function (item) { return item.text; }; // function used to retrieve the text portion of a data item that is matched against the search + + if (!$.isArray(data)) { + text = data.text; + // if text is not a function we assume it to be a key name + if (!$.isFunction(text)) text = function (item) { return item[data.text]; }; + data = data.results; + } + + return function (query) { + var t = query.term.toUpperCase(), filtered = {}; + if (t === "") { + query.callback({results: data}); + return; + } + filtered.results = $(data) + .filter(function () {return text(this).toUpperCase().indexOf(t) >= 0;}) + .get(); + query.callback(filtered); + }; + } + + // TODO javadoc + function tags(data) { + // TODO even for a function we should probably return a wrapper that does the same object/string check as + // the function for arrays. otherwise only functions that return objects are supported. + if ($.isFunction(data)) { + return data; + } + + // if not a function we assume it to be an array + + return function (query) { + var t = query.term.toUpperCase(), filtered = {results: []}; + $(data).each(function () { + var isObject = this.text !== undefined, + text = isObject ? this.text : this; + if (t === "" || text.toUpperCase().indexOf(t) >= 0) { + filtered.results.push(isObject ? this : {id: this, text: this}); + } + }); + query.callback(filtered); + }; + } + + /** + * blurs any Select2 container that has focus when an element outside them was clicked or received focus + */ + $(document).ready(function () { + $(document).delegate("*", "mousedown focusin", function (e) { + var target = $(e.target).closest("div.select2-container").get(0); + $(document).find("div.select2-container-active").each(function () { + if (this !== target) $(this).data("select2").blur(); + }); + }); + }); + + /** + * Creates a new class + * + * @param superClass + * @param methods + */ + function clazz(SuperClass, methods) { + var constructor = function () {}; + constructor.prototype = new SuperClass; + constructor.prototype.constructor = constructor; + constructor.prototype.parent = SuperClass.prototype; + constructor.prototype = $.extend(constructor.prototype, methods); + return constructor; + } + + AbstractSelect2 = clazz(Object, { + + bind: function (func) { + var self = this; + return function () { + func.apply(self, arguments); + }; + }, + + init: function (opts) { + var results, search, resultsSelector = ".select2-results"; + + // prepare options + this.opts = opts = this.prepareOpts(opts); + + this.id=opts.id; + + // destroy if called on an existing component + if (opts.element.data("select2") !== undefined) { + this.destroy(); + } + + this.container = this.createContainer(); + + if (opts.element.attr("class") !== undefined) { + this.container.addClass(opts.element.attr("class")); + } + + // swap container for the element + this.opts.element + .data("select2", this) + .hide() + .after(this.container); + this.container.data("select2", this); + + this.dropdown = this.container.find(".select2-drop"); + this.results = results = this.container.find(resultsSelector); + this.search = search = this.container.find("input[type=text]"); + + this.resultsPage = 0; + + // initialize the container + this.initContainer(); + + installFilteredMouseMove(this.results); + this.container.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent)); + + installDebouncedScroll(80, this.results); + this.container.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded)); + + // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel + if ($.fn.mousewheel) { + results.mousewheel(function (e, delta, deltaX, deltaY) { + var top = results.scrollTop(), height; + if (deltaY > 0 && top - deltaY <= 0) { + results.scrollTop(0); + killEvent(e); + } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) { + results.scrollTop(results.get(0).scrollHeight - results.height()); + killEvent(e); + } + }); + } + + installKeyUpChangeEvent(search); + search.bind("keyup-change", this.bind(this.updateResults)); + search.bind("focus", function () { search.addClass("select2-focused");}); + search.bind("blur", function () { search.removeClass("select2-focused");}); + + this.container.delegate(resultsSelector, "click", this.bind(function (e) { + if ($(e.target).closest(".select2-result:not(.select2-disabled)").length > 0) { + this.highlightUnderEvent(e); + this.selectHighlighted(e); + } else { + killEvent(e); + 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(); + } + }, + + destroy: function () { + var select2 = this.opts.element.data("select2"); + if (select2 !== undefined) { + select2.container.remove(); + select2.opts.element + .removeData("select2") + .unbind(".select2") + .show(); + } + }, + + prepareOpts: function (opts) { + var element, select, idKey; + + element = opts.element; + + if (element.get(0).tagName.toLowerCase() === "select") { + this.select = select = opts.element; + } + + if (select) { + // these options are not allowed when attached to a select because they are picked up off the element itself + $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () { + if (this in opts) { + throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a " , + " " , + " " , + ""].join("")); + }, + + open: function () { + + if (this.opened()) return; + + this.parent.open.apply(this, arguments); + + }, + + close: function () { + if (!this.opened()) return; + this.parent.close.apply(this, arguments); + }, + + focus: function () { + this.close(); + this.selection.focus(); + }, + + isFocused: function () { + return this.selection.is(":focus"); + }, + + cancel: function () { + this.parent.cancel.apply(this, arguments); + this.selection.focus(); + }, + + initContainer: function () { + + var selection, container = this.container, clickingInside = false, + selector = ".select2-choice"; + + this.selection = selection = container.find(selector); + + this.search.bind("keydown", this.bind(function (e) { + switch (e.which) { + case KEY.UP: + case KEY.DOWN: + this.moveHighlight((e.which === KEY.UP) ? -1 : 1); + killEvent(e); + return; + case KEY.TAB: + case KEY.ENTER: + this.selectHighlighted(); + killEvent(e); + return; + case KEY.ESC: + this.cancel(e); + e.preventDefault(); + return; + } + })); + + container.delegate(selector, "click", this.bind(function (e) { + clickingInside = true; + + if (this.opened()) { + this.close(); + selection.focus(); + } else { + this.open(); + } + e.preventDefault(); + + clickingInside = false; + })); + container.delegate(selector, "keydown", this.bind(function (e) { + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) { + return; + } + this.open(); + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN || e.which === KEY.SPACE) { + // prevent the page from scrolling + killEvent(e); + } + if (e.which === KEY.ENTER) { + // do not propagate the event otherwise we open, and propagate enter which closes + killEvent(e); + } + })); + container.delegate(selector, "focus", function () { container.addClass("select2-container-active"); }); + container.delegate(selector, "blur", this.bind(function () { + if (clickingInside) return; + if (!this.opened()) this.blur(); + })); + + selection.delegate("abbr", "click", this.bind(function (e) { + this.val(""); + killEvent(e); + this.close(); + this.triggerChange(); + })); + + this.setPlaceholder(); + }, + + /** + * Sets selection based on source element's value + */ + 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(); + }, + + prepareOpts: function () { + var opts = this.parent.prepareOpts.apply(this, arguments); + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + // install sthe selection initializer + opts.initSelection = function (element) { + var selected = element.find(":selected"); + // a single select box always has a value, no need to null check 'selected' + return {id: selected.attr("value"), text: selected.text()}; + }; + } + + return opts; + }, + + setPlaceholder: function () { + var placeholder = this.getPlaceholder(); + + if (this.opts.element.val() === "" && placeholder !== undefined) { + + // check for a first blank option if attached to a select + if (this.select && this.select.find("option:first").text() !== "") return; + + if (typeof(placeholder) === "object") { + this.updateSelection(placeholder); + } else { + this.selection.find("span").html(placeholder); + } + this.selection.addClass("select2-default"); + + this.selection.find("abbr").hide(); + } + }, + + postprocessResults: function (data, initial) { + var selected = 0, self = this, showSearchInput = true; + + // find the selected element in the result list + + this.results.find(".select2-result").each(function (i) { + if (equal(self.id($(this).data("select2-data")), self.opts.element.val())) { + selected = i; + return false; + } + }); + + // and highlight it + + this.highlight(selected); + + // hide the search box if this is the first we got the results and there are a few of them + + if (initial === true) { + showSearchInput = data.results.length >= this.opts.minimumResultsForSearch; + this.search.parent().toggle(showSearchInput); + + //add "select2-with-searchbox" to the container if search box is shown + this.container[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox"); + } + + }, + + onSelect: function (data) { + var old = this.opts.element.val(); + + this.opts.element.val(this.id(data)); + this.updateSelection(data); + this.close(); + this.selection.focus(); + + if (!equal(old, this.id(data))) { this.triggerChange(); } + }, + + updateSelection: function (data) { + this.selection + .find("span") + .html(this.opts.formatSelection(data)); + + this.selection.removeClass("select2-default"); + + if (this.opts.allowClear && this.getPlaceholder() !== undefined) { + this.selection.find("abbr").show(); + } + }, + + val: function () { + var val, data = null; + + if (arguments.length === 0) { + return this.opts.element.val(); + } + + val = arguments[0]; + + if (this.select) { + // val is an id + this.select + .val(val) + .find(":selected").each(function () { + data = {id: $(this).attr("value"), text: $(this).text()}; + return false; + }); + this.updateSelection(data); + } else { + // val is an object. !val is true for [undefined,null,''] + this.opts.element.val(!val ? "" : this.id(val)); + this.updateSelection(val); + } + this.setPlaceholder(); + + }, + + clearSearch: function () { + this.search.val(""); + } + }); + + MultiSelect2 = clazz(AbstractSelect2, { + + createContainer: function () { + return $("
", { + "class": "select2-container select2-container-multi", + "style": "width: " + this.getContainerWidth() + }).html([ + " " , + ""].join("")); + }, + + prepareOpts: function () { + var opts = this.parent.prepareOpts.apply(this, arguments); + + opts = $.extend({}, { + closeOnSelect: true + }, opts); + + // TODO validate placeholder is a string if specified + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + // install sthe selection initializer + opts.initSelection = function (element) { + var data = []; + element.find(":selected").each(function () { + data.push({id: $(this).attr("value"), text: $(this).text()}); + }); + return data; + }; + } + + return opts; + }, + + initContainer: function () { + + var selector = ".select2-choices", selection; + + this.searchContainer = this.container.find(".select2-search-field"); + this.selection = selection = this.container.find(selector); + + this.search.bind("keydown", this.bind(function (e) { + if (e.which === KEY.BACKSPACE && this.search.val() === "") { + this.close(); + + var choices, + selected = selection.find(".select2-search-choice-focus"); + if (selected.length > 0) { + this.unselect(selected.first()); + this.search.width(10); + killEvent(e); + return; + } + + choices = selection.find(".select2-search-choice"); + if (choices.length > 0) { + choices.last().addClass("select2-search-choice-focus"); + } + } else { + selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + } + + if (this.opened()) { + switch (e.which) { + case KEY.UP: + case KEY.DOWN: + this.moveHighlight((e.which === KEY.UP) ? -1 : 1); + killEvent(e); + return; + case KEY.ENTER: + this.selectHighlighted(); + killEvent(e); + return; + case KEY.ESC: + this.cancel(e); + e.preventDefault(); + return; + } + } + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.BACKSPACE || e.which === KEY.ESC) { + return; + } + + this.open(); + + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { + // prevent the page from scrolling + killEvent(e); + } + })); + + this.search.bind("keyup", this.bind(this.resizeSearch)); + + this.container.delegate(selector, "click", this.bind(function (e) { + this.open(); + this.focusSearch(); + e.preventDefault(); + })); + + this.container.delegate(selector, "focus", this.bind(function () { + this.container.addClass("select2-container-active"); + this.clearPlaceholder(); + })); + + // set the placeholder if necessary + this.clearSearch(); + }, + + 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(); + }, + + clearSearch: function () { + var placeholder = this.getPlaceholder(); + + if (placeholder !== undefined + && this.getVal().length === 0 + && this.search.hasClass("select2-focused") === false) { + + this.search.val(placeholder).addClass("select2-default"); + // stretch the search box to full width of the container so as much of the placeholder is visible as possible + this.search.width(this.getContainerWidth()); + } else { + this.search.val("").width(10); + } + }, + + clearPlaceholder: function () { + if (this.search.hasClass("select2-default")) { + this.search.val("").removeClass("select2-default"); + } + }, + + open: function () { + if (this.opened()) return; + this.parent.open.apply(this, arguments); + this.resizeSearch(); + this.focusSearch(); + }, + + close: function () { + if (!this.opened()) return; + this.parent.close.apply(this, arguments); + }, + + focus: function () { + this.close(); + this.search.focus(); + }, + + isFocused: function () { + return this.search.hasClass("select2-focused"); + }, + + updateSelection: function (data) { + var ids = [], filtered = [], self = this; + + // filter out duplicates + $(data).each(function () { + if (indexOf(self.id(this), ids) < 0) { + ids.push(self.id(this)); + filtered.push(this); + } + }); + data = filtered; + + this.selection.find(".select2-search-choice").remove(); + $(data).each(function () { + self.addSelectedChoice(this); + }); + self.postprocessResults(); + }, + + onSelect: function (data) { + this.addSelectedChoice(data); + if (this.select) { this.postprocessResults(); } + + if (this.opts.closeOnSelect) { + this.close(); + this.search.width(10); + } else { + this.search.width(10); + this.resizeSearch(); + } + + // since its not possible to select an element that has already been + // added we do not need to check if this is a new element before firing change + this.triggerChange(); + + this.focusSearch(); + }, + + cancel: function () { + this.close(); + this.focusSearch(); + }, + + addSelectedChoice: function (data) { + var choice, + id = this.id(data), + parts, + val = this.getVal(); + + parts = ["
  • ", + this.opts.formatSelection(data), + "", + "
  • " + ]; + + choice = $(parts.join("")); + choice.find("a") + .bind("click dblclick", this.bind(function (e) { + this.unselect($(e.target)); + this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + killEvent(e); + this.close(); + this.focusSearch(); + })).bind("focus", this.bind(function () { + this.container.addClass("select2-container-active"); + })); + + choice.data("select2-data", data); + choice.insertBefore(this.searchContainer); + + val.push(id); + this.setVal(val); + }, + + unselect: function (selected) { + var val = this.getVal(), + index; + + selected = selected.closest(".select2-search-choice"); + + if (selected.length === 0) { + throw "Invalid argument: " + selected + ". Must be .select2-search-choice"; + } + + index = indexOf(this.id(selected.data("select2-data")), val); + + if (index >= 0) { + val.splice(index, 1); + this.setVal(val); + if (this.select) this.postprocessResults(); + } + selected.remove(); + this.triggerChange(); + }, + + postprocessResults: function () { + var val = this.getVal(), + choices = this.results.find(".select2-result"), + self = this; + + choices.each(function () { + var choice = $(this), id = self.id(choice.data("select2-data")); + if (indexOf(id, val) >= 0) { + choice.addClass("select2-disabled"); + } else { + choice.removeClass("select2-disabled"); + } + }); + + choices.each(function (i) { + if (!$(this).hasClass("select2-disabled")) { + self.highlight(i); + return false; + } + }); + + }, + + resizeSearch: function () { + + var minimumWidth, left, maxWidth, containerLeft, searchWidth; + + minimumWidth = measureTextWidth(this.search) + 10; + + left = this.search.offset().left; + + maxWidth = this.selection.width(); + containerLeft = this.selection.offset().left; + + searchWidth = maxWidth - (left - containerLeft) - getSideBorderPadding(this.search); + + if (searchWidth < minimumWidth) { + searchWidth = maxWidth - getSideBorderPadding(this.search); + } + + if (searchWidth < 40) { + searchWidth = maxWidth - getSideBorderPadding(this.search); + } + this.search.width(searchWidth); + }, + + getVal: function () { + var val; + if (this.select) { + val = this.select.val(); + return val === null ? [] : val; + } else { + val = this.opts.element.val(); + return splitVal(val, ","); + } + }, + + setVal: function (val) { + var unique = []; + if (this.select) { + this.select.val(val); + } else { + // filter out duplicates + $(val).each(function () { + if (indexOf(this, unique) < 0) unique.push(this); + }); + + this.opts.element.val(unique.length === 0 ? "" : unique.join(",")); + } + }, + + val: function () { + var val, data = [], self=this; + + if (arguments.length === 0) { + return this.getVal(); + } + + val = arguments[0]; + + if (this.select) { + // val is a list of ids + this.setVal(val); + this.select.find(":selected").each(function () { + data.push({id: $(this).attr("value"), text: $(this).text()}); + }); + this.updateSelection(data); + } else { + val = (val === null) ? [] : val; + this.setVal(val); + // val is a list of objects + + $(val).each(function () { data.push(self.id(this)); }); + this.setVal(data); + this.updateSelection(val); + } + + this.clearSearch(); + } + }); + + $.fn.select2 = function () { + + var args = Array.prototype.slice.call(arguments, 0), + opts, + select2, + value, multiple, allowedMethods = ["val", "destroy", "open", "close", "focus", "isFocused"]; + + this.each(function () { + if (args.length === 0 || typeof(args[0]) === "object") { + opts = args.length === 0 ? {} : $.extend({}, args[0]); + opts.element = $(this); + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + multiple = opts.element.attr("multiple"); + } else { + multiple = opts.multiple || false; + if ("tags" in opts) {opts.multiple = multiple = true;} + } + + select2 = multiple ? new MultiSelect2() : new SingleSelect2(); + select2.init(opts); + } else if (typeof(args[0]) === "string") { + + if (indexOf(args[0], allowedMethods) < 0) { + throw "Unknown method: " + args[0]; + } + + value = undefined; + select2 = $(this).data("select2"); + if (select2 === undefined) return; + value = select2[args[0]].apply(select2, args.slice(1)); + if (value !== undefined) {return false;} + } else { + throw "Invalid arguments to select2 plugin: " + args; + } + }); + return (value === undefined) ? this : value; + }; + + // exports + window.Select2 = { + query: { + ajax: ajax, + local: local, + tags: tags + }, util: { + debounce: debounce + }, "class": { + "abstract": AbstractSelect2, + "single": SingleSelect2, + "multi": MultiSelect2 + } + }; + +}(jQuery)); diff --git a/select2-2.0/select2.min.js b/select2-2.0/select2.min.js new file mode 100755 index 00000000..e240bb5c --- /dev/null +++ b/select2-2.0/select2.min.js @@ -0,0 +1,55 @@ +/* +Copyright 2012 Igor Vaynberg + +Version: 2.0 Timestamp: Wed, May 16, 2012 10:38:37 AM + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in +compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is +distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and limitations under the License.*/ +(function(e,g){function j(a,b){var c=0,f=b.length,h;if(a.constructor===String)for(;ca.length)return[];c=a.split(b);f=0;for(h=c.length;f< +h;f+=1)c[f]=e.trim(c[f]);return c}function w(a){a.bind("keydown",function(){a.data("keyup-change-value",a.val())});a.bind("keyup",function(){a.val()!==a.data("keyup-change-value")&&a.trigger("keyup-change")})}function x(a){a.bind("mousemove",function(a){var c=e(document).data("select2-lastpos");(c===g||c.x!==a.pageX||c.y!==a.pageY)&&e(a.target).trigger("mousemove-filtered",a)})}function s(a,b){var c;return function(){window.clearTimeout(c);c=window.setTimeout(b,a)}}function y(a,b){var c=s(a,function(a){b.trigger("scroll-debounced", +a)});b.bind("scroll",function(a){0<=j(a.target,b.get())&&c(a)})}function i(a){a.preventDefault();a.stopPropagation()}function t(a){var b,c=0,f=null,h=a.quietMillis||100;return function(d){window.clearTimeout(b);b=window.setTimeout(function(){var b=c+=1,h=a.data,g=a.transport||e.ajax,h=h.call(this,d.term,d.page);null!==f&&f.abort();f=g.call(null,{url:a.url,dataType:a.dataType,data:h,success:function(f){b=0}).get();a.callback(d)}}}function v(a){return e.isFunction(a)?a:function(b){var c=b.term.toUpperCase(),f={results:[]};e(a).each(function(){var a=this.text!==g,b=a?this.text:this;if(""===c||0<=b.toUpperCase().indexOf(c))f.results.push(a?this:{id:this, +text:this})});b.callback(f)}}function o(a,b){var c=function(){};c.prototype=new a;c.prototype.constructor=c;c.prototype.parent=a.prototype;c.prototype=e.extend(c.prototype,b);return c}if(window.Select2===g){var d,m,p,q;d={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){a=a.which?a.which:a;switch(a){case d.LEFT:case d.RIGHT:case d.UP:case d.DOWN:return!0}return!1},isControl:function(a){a= +a.which?a.which:a;switch(a){case d.SHIFT:case d.CTRL:case d.ALT:return!0}return!1},isFunctionKey:function(a){a=a.which?a.which:a;return 112<=a&&123>=a}};e(document).delegate("*","mousemove",function(a){e(document).data("select2-lastpos",{x:a.pageX,y:a.pageY})});e(document).ready(function(){e(document).delegate("*","mousedown focusin",function(a){var b=e(a.target).closest("div.select2-container").get(0);e(document).find("div.select2-container-active").each(function(){this!==b&&e(this).data("select2").blur()})})}); +m=o(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(a){var b,c;this.opts=a=this.prepareOpts(a);this.id=a.id;a.element.data("select2")!==g&&this.destroy();this.container=this.createContainer();a.element.attr("class")!==g&&this.container.addClass(a.element.attr("class"));this.opts.element.data("select2",this).hide().after(this.container);this.container.data("select2",this);this.dropdown=this.container.find(".select2-drop");this.results=b=this.container.find(".select2-results"); +this.search=c=this.container.find("input[type=text]");this.resultsPage=0;this.initContainer();x(this.results);this.container.delegate(".select2-results","mousemove-filtered",this.bind(this.highlightUnderEvent));y(80,this.results);this.container.delegate(".select2-results","scroll-debounced",this.bind(this.loadMoreIfNeeded));e.fn.mousewheel&&b.mousewheel(function(a,c,e,d){c=b.scrollTop();0=c-d?(b.scrollTop(0),i(a)):0>d&&b.get(0).scrollHeight-b.scrollTop()+d<=b.height()&&(b.scrollTop(b.get(0).scrollHeight- +b.height()),i(a))});w(c);c.bind("keyup-change",this.bind(this.updateResults));c.bind("focus",function(){c.addClass("select2-focused")});c.bind("blur",function(){c.removeClass("select2-focused")});this.container.delegate(".select2-results","click",this.bind(function(a){0 element.");});a=e.extend({},{formatResult:function(a){return a.text}, +formatSelection:function(a){return a.text},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(a,b){return"Please enter "+(b-a.length)+" more characters"},minimumResultsForSearch:0,minimumInputLength:0,id:function(a){return a.id}},a);"function"!==typeof a.id&&(f=a.id,a.id=function(a){return a[f]});c?(a.query=this.bind(function(a){var c={results:[],more:false},f=a.term.toUpperCase(),d=this.getPlaceholder();b.find("option").each(function(a){var b=e(this),h=b.text();if(a=== +0&&d!==g&&h==="")return true;h.toUpperCase().indexOf(f)>=0&&c.results.push({id:b.attr("value"),text:h})});a.callback(c)}),a.id=function(a){return a.id}):"query"in a||("ajax"in a?a.query=t(a.ajax):"data"in a?a.query=u(a.data):"tags"in a&&(a.query=v(a.tags),a.createSearchChoice=function(a){return{id:a,text:a}},a.initSelection=function(a){var b=[];e(r(a.val(),",")).each(function(){b.push({id:this,text:this})});return b}));if("function"!==typeof a.query)throw"query function not defined for Select2 "+ +a.element.attr("id");return a},monitorSource:function(){this.opts.element.bind("change.select2",this.bind(function(){!0!==this.opts.element.data("select2-change-triggered")&&this.initSelection()}))},triggerChange:function(){this.opts.element.data("select2-change-triggered",!0);this.opts.element.trigger("change");this.opts.element.data("select2-change-triggered",!1)},opened:function(){return this.container.hasClass("select2-dropdown-open")},open:function(){this.opened()||(this.container.addClass("select2-dropdown-open").addClass("select2-container-active"), +this.updateResults(!0),this.dropdown.show(),this.focusSearch())},close:function(){this.opened()&&(this.dropdown.hide(),this.container.removeClass("select2-dropdown-open"),this.results.empty(),this.clearSearch())},clearSearch:function(){},ensureHighlightVisible:function(){var a=this.results,b,c,f,d;b=a.children(".select2-result");c=this.highlight();0>c||(f=e(b[c]),d=f.offset().top+f.outerHeight(),c===b.length-1&&(b=a.find("li.select2-more-results"),0b&&a.scrollTop(a.scrollTop()+(d-b)),f=f.offset().top-a.offset().top,0>f&&a.scrollTop(a.scrollTop()+f))},moveHighlight:function(a){for(var b=this.results.children(".select2-result"),c=this.highlight();-1=b.length&&(a=b.length-1);0>a&&(a=0);e(b[a]).addClass("select2-highlighted");this.ensureHighlightVisible();this.opened()&&this.focusSearch()},highlightUnderEvent:function(a){a=e(a.target).closest(".select2-result");0=c&&(b.addClass("select2-active"),this.opts.query({term:this.search.val(), +page:d,callback:this.bind(function(c){var k=[],i=this;e(c.results).each(function(){k.push("
  • ");k.push(i.opts.formatResult(this));k.push("
  • ")});b.before(k.join(""));a.find(".select2-result").each(function(a){var b=e(this);b.data("select2-data")!==g?f=a:b.data("select2-data",c.results[a-f-1])});c.more?b.removeClass("select2-active"):b.remove();this.resultsPage=d})})))},updateResults:function(a){function b(a){f.html(a);f.scrollTop(0);c.removeClass("select2-active")}var c= +this.search,f=this.results,d=this.opts,i=this;c.addClass("select2-active");c.val().length"+d.formatInputTooShort(c.val(),d.minimumInputLength)+""):(this.resultsPage=1,d.query({term:c.val(),page:this.resultsPage,callback:this.bind(function(k){var j=[],l;this.opts.createSearchChoice&&""!==c.val()&&(l=this.opts.createSearchChoice.call(null,c.val(),k.results),l!==g&&null!==l&&i.id(l)!==g&&null!==i.id(l)&&0===e(k.results).filter(function(){return n(i.id(this), +i.id(l))}).length&&k.results.unshift(l));0===k.results.length?b("
  • "+d.formatNoMatches(c.val())+"
  • "):(e(k.results).each(function(){j.push("
  • ");j.push(d.formatResult(this));j.push("
  • ")}),!0===k.more&&j.push("
  • Loading more results...
  • "),b(j.join("")),f.children(".select2-result").each(function(a){a=k.results[a];e(this).data("select2-data",a)}),this.postprocessResults(k,a))})}))},cancel:function(){this.close()}, +blur:function(){window.setTimeout(this.bind(function(){this.close();this.container.removeClass("select2-container-active");this.clearSearch();this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");this.search.blur()}),10)},focusSearch:function(){window.setTimeout(this.bind(function(){this.search.focus()}),10)},selectHighlighted:function(){var a=this.results.find(".select2-highlighted:not(.select2-disabled)").data("select2-data");if(a)this.onSelect(a)},getPlaceholder:function(){return this.opts.element.attr("placeholder")|| +this.opts.element.data("placeholder")||this.opts.placeholder},getContainerWidth:function(){var a,b,c,f;if(this.opts.width!==g)return this.opts.width;a=this.opts.element.attr("style");if(a!==g){a=a.split(";");c=0;for(f=a.length;c",{"class":"select2-container",style:"width: "+ +this.getContainerWidth()}).html("
    ")},open:function(){this.opened()||this.parent.open.apply(this,arguments)},close:function(){this.opened()&&this.parent.close.apply(this, +arguments)},focus:function(){this.close();this.selection.focus()},isFocused:function(){return this.selection.is(":focus")},cancel:function(){this.parent.cancel.apply(this,arguments);this.selection.focus()},initContainer:function(){var a,b=this.container,c=!1;this.selection=a=b.find(".select2-choice");this.search.bind("keydown",this.bind(function(a){switch(a.which){case d.UP:case d.DOWN:this.moveHighlight(a.which===d.UP?-1:1);i(a);break;case d.TAB:case d.ENTER:this.selectHighlighted();i(a);break;case d.ESC:this.cancel(a), +a.preventDefault()}}));b.delegate(".select2-choice","click",this.bind(function(b){c=!0;this.opened()?(this.close(),a.focus()):this.open();b.preventDefault();c=!1}));b.delegate(".select2-choice","keydown",this.bind(function(a){a.which===d.TAB||(d.isControl(a)||d.isFunctionKey(a)||a.which===d.ESC)||(this.open(),(a.which===d.PAGE_UP||a.which===d.PAGE_DOWN||a.which===d.SPACE)&&i(a),a.which===d.ENTER&&i(a))}));b.delegate(".select2-choice","focus",function(){b.addClass("select2-container-active")});b.delegate(".select2-choice", +"blur",this.bind(function(){c||this.opened()||this.blur()}));a.delegate("abbr","click",this.bind(function(a){this.val("");i(a);this.close();this.triggerChange()}));this.setPlaceholder()},initSelection:function(){var a;""===this.opts.element.val()?this.updateSelection({id:"",text:""}):(a=this.opts.initSelection.call(null,this.opts.element),a!==g&&null!==a&&this.updateSelection(a));this.close();this.setPlaceholder()},prepareOpts:function(){var a=this.parent.prepareOpts.apply(this,arguments);"select"=== +a.element.get(0).tagName.toLowerCase()&&(a.initSelection=function(a){a=a.find(":selected");return{id:a.attr("value"),text:a.text()}});return a},setPlaceholder:function(){var a=this.getPlaceholder();""===this.opts.element.val()&&a!==g&&!(this.select&&""!==this.select.find("option:first").text())&&("object"===typeof a?this.updateSelection(a):this.selection.find("span").html(a),this.selection.addClass("select2-default"),this.selection.find("abbr").hide())},postprocessResults:function(a,b){var c=0,f= +this,d=!0;this.results.find(".select2-result").each(function(a){if(n(f.id(e(this).data("select2-data")),f.opts.element.val()))return c=a,!1});this.highlight(c);!0===b&&(d=a.results.length>=this.opts.minimumResultsForSearch,this.search.parent().toggle(d),this.container[d?"addClass":"removeClass"]("select2-with-searchbox"))},onSelect:function(a){var b=this.opts.element.val();this.opts.element.val(this.id(a));this.updateSelection(a);this.close();this.selection.focus();n(b,this.id(a))||this.triggerChange()}, +updateSelection:function(a){this.selection.find("span").html(this.opts.formatSelection(a));this.selection.removeClass("select2-default");this.opts.allowClear&&this.getPlaceholder()!==g&&this.selection.find("abbr").show()},val:function(){var a,b=null;if(0===arguments.length)return this.opts.element.val();a=arguments[0];this.select?(this.select.val(a).find(":selected").each(function(){b={id:e(this).attr("value"),text:e(this).text()};return!1}),this.updateSelection(b)):(this.opts.element.val(!a?"":this.id(a)), +this.updateSelection(a));this.setPlaceholder()},clearSearch:function(){this.search.val("")}});q=o(m,{createContainer:function(){return e("
    ",{"class":"select2-container select2-container-multi",style:"width: "+this.getContainerWidth()}).html("
    ")},prepareOpts:function(){var a= +this.parent.prepareOpts.apply(this,arguments),a=e.extend({},{closeOnSelect:!0},a);"select"===a.element.get(0).tagName.toLowerCase()&&(a.initSelection=function(a){var c=[];a.find(":selected").each(function(){c.push({id:e(this).attr("value"),text:e(this).text()})});return c});return a},initContainer:function(){var a;this.searchContainer=this.container.find(".select2-search-field");this.selection=a=this.container.find(".select2-choices");this.search.bind("keydown",this.bind(function(b){if(b.which=== +d.BACKSPACE&&""===this.search.val()){this.close();var c;c=a.find(".select2-search-choice-focus");if(0j(d.id(this),b)&&(b.push(d.id(this)),c.push(this))});a=c;this.selection.find(".select2-search-choice").remove();e(a).each(function(){d.addSelectedChoice(this)});d.postprocessResults()},onSelect:function(a){this.addSelectedChoice(a);this.select&&this.postprocessResults();this.opts.closeOnSelect?(this.close(),this.search.width(10)):(this.search.width(10),this.resizeSearch());this.triggerChange();this.focusSearch()},cancel:function(){this.close();this.focusSearch()},addSelectedChoice:function(a){var b, +c=this.id(a),d=this.getVal();b=["
  • ",this.opts.formatSelection(a),"","
  • "];b=e(b.join(""));b.find("a").bind("click dblclick",this.bind(function(a){this.unselect(e(a.target));this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");i(a);this.close();this.focusSearch()})).bind("focus",this.bind(function(){this.container.addClass("select2-container-active")})); +b.data("select2-data",a);b.insertBefore(this.searchContainer);d.push(c);this.setVal(d)},unselect:function(a){var b=this.getVal(),c,a=a.closest(".select2-search-choice");if(0===a.length)throw"Invalid argument: "+a+". Must be .select2-search-choice";c=j(this.id(a.data("select2-data")),b);0<=c&&(b.splice(c,1),this.setVal(b),this.select&&this.postprocessResults());a.remove();this.triggerChange()},postprocessResults:function(){var a=this.getVal(),b=this.results.find(".select2-result"),c=this;b.each(function(){var b= +e(this),d=c.id(b.data("select2-data"));0<=j(d,a)?b.addClass("select2-disabled"):b.removeClass("select2-disabled")});b.each(function(a){if(!e(this).hasClass("select2-disabled"))return c.highlight(a),!1})},resizeSearch:function(){var a,b,c,d;c=this.search;a=e("
    ").css({position:"absolute",left:"-1000px",top:"-1000px",display:"none",fontSize:c.css("fontSize"),fontFamily:c.css("fontFamily"),fontStyle:c.css("fontStyle"),fontWeight:c.css("fontWeight"),letterSpacing:c.css("letterSpacing"),textTransform:c.css("textTransform"), +whiteSpace:"nowrap"});a.text(c.val());e("body").append(a);c=a.width();a.remove();a=c+10;b=this.search.offset().left;c=this.selection.width();d=this.selection.offset().left;b=c-(b-d)-(this.search.outerWidth()-this.search.width());bb&&(b=c-(this.search.outerWidth()-this.search.width()));this.search.width(b)},getVal:function(){var a;if(this.select)return a=this.select.val(),null===a?[]:a;a=this.opts.element.val();return r(a,",")},setVal:function(a){var b= +[];this.select?this.select.val(a):(e(a).each(function(){0>j(this,b)&&b.push(this)}),this.opts.element.val(0===b.length?"":b.join(",")))},val:function(){var a,b=[],c=this;if(0===arguments.length)return this.getVal();a=arguments[0];this.select?(this.setVal(a),this.select.find(":selected").each(function(){b.push({id:e(this).attr("value"),text:e(this).text()})}),this.updateSelection(b)):(a=null===a?[]:a,this.setVal(a),e(a).each(function(){b.push(c.id(this))}),this.setVal(b),this.updateSelection(a));this.clearSearch()}}); +e.fn.select2=function(){var a=Array.prototype.slice.call(arguments,0),b,c,d,h,i="val destroy open close focus isFocused".split(" ");this.each(function(){if(0===a.length||"object"===typeof a[0])b=0===a.length?{}:e.extend({},a[0]),b.element=e(this),"select"===b.element.get(0).tagName.toLowerCase()?h=b.element.attr("multiple"):(h=b.multiple||!1,"tags"in b&&(b.multiple=h=!0)),c=h?new q:new p,c.init(b);else if("string"===typeof a[0]){if(0>j(a[0],i))throw"Unknown method: "+a[0];d=g;c=e(this).data("select2"); +if(c!==g&&(d=c[a[0]].apply(c,a.slice(1)),d!==g))return!1}else throw"Invalid arguments to select2 plugin: "+a;});return d===g?this:d};window.Select2={query:{ajax:t,local:u,tags:v},util:{debounce:s},"class":{"abstract":m,single:p,multi:q}}}})(jQuery); diff --git a/select2-2.0/select2.png b/select2-2.0/select2.png new file mode 100755 index 00000000..d08e4b7e Binary files /dev/null and b/select2-2.0/select2.png differ diff --git a/select2-2.0/spinner.gif b/select2-2.0/spinner.gif new file mode 100755 index 00000000..5b33f7e5 Binary files /dev/null and b/select2-2.0/spinner.gif differ