PluginProbe
UpdraftCentral Dashboard / 0.8.26
UpdraftCentral Dashboard v0.8.26
0.8.33 0.7.2 0.7.3 0.7.4 0.8.0 0.8.1 0.8.10 0.8.11 0.8.12 0.8.13 0.8.14 0.8.15 0.8.16 0.8.17 0.8.18 0.8.19 0.8.2 0.8.20 0.8.21 0.8.22 0.8.23 0.8.24 0.8.25 0.8.26 0.8.27 All 51 releases
updraftcentral / js / select2 / select2.js

select2.js in UpdraftCentral Dashboard 0.8.26, at js/select2/select2.js

6,109 lines 150.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*!
2 * Select2 4.0.13
3 * https://select2.github.io
4 *
5 * Released under the MIT license
6 * https://github.com/select2/select2/blob/master/LICENSE.md
7 */
8 ;(function (factory) {
9 if (typeof define === 'function' && define.amd) {
10 // AMD. Register as an anonymous module.
11 define(['jquery'], factory);
12 } else if (typeof module === 'object' && module.exports) {
13 // Node/CommonJS
14 module.exports = function (root, jQuery) {
15 if (jQuery === undefined) {
16 // require('jQuery') returns a factory that requires window to
17 // build a jQuery instance, we normalize how we use modules
18 // that require this pattern but the window provided is a noop
19 // if it's defined (how jquery works)
20 if (typeof window !== 'undefined') {
21 jQuery = require('jquery');
22 }
23 else {
24 jQuery = require('jquery')(root);
25 }
26 }
27 factory(jQuery);
28 return jQuery;
29 };
30 } else {
31 // Browser globals
32 factory(jQuery);
33 }
34 } (function (jQuery) {
35 // This is needed so we can catch the AMD loader configuration and use it
36 // The inner file should be wrapped (by `banner.start.js`) in a function that
37 // returns the AMD loader references.
38 var S2 =(function () {
39 // Restore the Select2 AMD loader so it can be used
40 // Needed mostly in the language files, where the loader is not inserted
41 if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
42 var S2 = jQuery.fn.select2.amd;
43 }
44 var S2;(function () { if (!S2 || !S2.requirejs) {
45 if (!S2) { S2 = {}; } else { require = S2; }
46 /**
47 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
48 * Released under MIT license, http://github.com/requirejs/almond/LICENSE
49 */
50 //Going sloppy to avoid 'use strict' string cost, but strict practices should
51 //be followed.
52 /*global setTimeout: false */
53
54 var requirejs, require, define;
55 (function (undef) {
56 var main, req, makeMap, handlers,
57 defined = {},
58 waiting = {},
59 config = {},
60 defining = {},
61 hasOwn = Object.prototype.hasOwnProperty,
62 aps = [].slice,
63 jsSuffixRegExp = /\.js$/;
64
65 function hasProp(obj, prop) {
66 return hasOwn.call(obj, prop);
67 }
68
69 /**
70 * Given a relative module name, like ./something, normalize it to
71 * a real name that can be mapped to a path.
72 * @param {String} name the relative name
73 * @param {String} baseName a real name that the name arg is relative
74 * to.
75 * @returns {String} normalized name
76 */
77 function normalize(name, baseName) {
78 var nameParts, nameSegment, mapValue, foundMap, lastIndex,
79 foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
80 baseParts = baseName && baseName.split("/"),
81 map = config.map,
82 starMap = (map && map['*']) || {};
83
84 //Adjust any relative paths.
85 if (name) {
86 name = name.split('/');
87 lastIndex = name.length - 1;
88
89 // If wanting node ID compatibility, strip .js from end
90 // of IDs. Have to do this here, and not in nameToUrl
91 // because node allows either .js or non .js to map
92 // to same file.
93 if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
94 name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
95 }
96
97 // Starts with a '.' so need the baseName
98 if (name[0].charAt(0) === '.' && baseParts) {
99 //Convert baseName to array, and lop off the last part,
100 //so that . matches that 'directory' and not name of the baseName's
101 //module. For instance, baseName of 'one/two/three', maps to
102 //'one/two/three.js', but we want the directory, 'one/two' for
103 //this normalization.
104 normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
105 name = normalizedBaseParts.concat(name);
106 }
107
108 //start trimDots
109 for (i = 0; i < name.length; i++) {
110 part = name[i];
111 if (part === '.') {
112 name.splice(i, 1);
113 i -= 1;
114 } else if (part === '..') {
115 // If at the start, or previous value is still ..,
116 // keep them so that when converted to a path it may
117 // still work when converted to a path, even though
118 // as an ID it is less than ideal. In larger point
119 // releases, may be better to just kick out an error.
120 if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
121 continue;
122 } else if (i > 0) {
123 name.splice(i - 1, 2);
124 i -= 2;
125 }
126 }
127 }
128 //end trimDots
129
130 name = name.join('/');
131 }
132
133 //Apply map config if available.
134 if ((baseParts || starMap) && map) {
135 nameParts = name.split('/');
136
137 for (i = nameParts.length; i > 0; i -= 1) {
138 nameSegment = nameParts.slice(0, i).join("/");
139
140 if (baseParts) {
141 //Find the longest baseName segment match in the config.
142 //So, do joins on the biggest to smallest lengths of baseParts.
143 for (j = baseParts.length; j > 0; j -= 1) {
144 mapValue = map[baseParts.slice(0, j).join('/')];
145
146 //baseName segment has config, find if it has one for
147 //this name.
148 if (mapValue) {
149 mapValue = mapValue[nameSegment];
150 if (mapValue) {
151 //Match, update name to the new value.
152 foundMap = mapValue;
153 foundI = i;
154 break;
155 }
156 }
157 }
158 }
159
160 if (foundMap) {
161 break;
162 }
163
164 //Check for a star map match, but just hold on to it,
165 //if there is a shorter segment match later in a matching
166 //config, then favor over this star map.
167 if (!foundStarMap && starMap && starMap[nameSegment]) {
168 foundStarMap = starMap[nameSegment];
169 starI = i;
170 }
171 }
172
173 if (!foundMap && foundStarMap) {
174 foundMap = foundStarMap;
175 foundI = starI;
176 }
177
178 if (foundMap) {
179 nameParts.splice(0, foundI, foundMap);
180 name = nameParts.join('/');
181 }
182 }
183
184 return name;
185 }
186
187 function makeRequire(relName, forceSync) {
188 return function () {
189 //A version of a require function that passes a moduleName
190 //value for items that may need to
191 //look up paths relative to the moduleName
192 var args = aps.call(arguments, 0);
193
194 //If first arg is not require('string'), and there is only
195 //one arg, it is the array form without a callback. Insert
196 //a null so that the following concat is correct.
197 if (typeof args[0] !== 'string' && args.length === 1) {
198 args.push(null);
199 }
200 return req.apply(undef, args.concat([relName, forceSync]));
201 };
202 }
203
204 function makeNormalize(relName) {
205 return function (name) {
206 return normalize(name, relName);
207 };
208 }
209
210 function makeLoad(depName) {
211 return function (value) {
212 defined[depName] = value;
213 };
214 }
215
216 function callDep(name) {
217 if (hasProp(waiting, name)) {
218 var args = waiting[name];
219 delete waiting[name];
220 defining[name] = true;
221 main.apply(undef, args);
222 }
223
224 if (!hasProp(defined, name) && !hasProp(defining, name)) {
225 throw new Error('No ' + name);
226 }
227 return defined[name];
228 }
229
230 //Turns a plugin!resource to [plugin, resource]
231 //with the plugin being undefined if the name
232 //did not have a plugin prefix.
233 function splitPrefix(name) {
234 var prefix,
235 index = name ? name.indexOf('!') : -1;
236 if (index > -1) {
237 prefix = name.substring(0, index);
238 name = name.substring(index + 1, name.length);
239 }
240 return [prefix, name];
241 }
242
243 //Creates a parts array for a relName where first part is plugin ID,
244 //second part is resource ID. Assumes relName has already been normalized.
245 function makeRelParts(relName) {
246 return relName ? splitPrefix(relName) : [];
247 }
248
249 /**
250 * Makes a name map, normalizing the name, and using a plugin
251 * for normalization if necessary. Grabs a ref to plugin
252 * too, as an optimization.
253 */
254 makeMap = function (name, relParts) {
255 var plugin,
256 parts = splitPrefix(name),
257 prefix = parts[0],
258 relResourceName = relParts[1];
259
260 name = parts[1];
261
262 if (prefix) {
263 prefix = normalize(prefix, relResourceName);
264 plugin = callDep(prefix);
265 }
266
267 //Normalize according
268 if (prefix) {
269 if (plugin && plugin.normalize) {
270 name = plugin.normalize(name, makeNormalize(relResourceName));
271 } else {
272 name = normalize(name, relResourceName);
273 }
274 } else {
275 name = normalize(name, relResourceName);
276 parts = splitPrefix(name);
277 prefix = parts[0];
278 name = parts[1];
279 if (prefix) {
280 plugin = callDep(prefix);
281 }
282 }
283
284 //Using ridiculous property names for space reasons
285 return {
286 f: prefix ? prefix + '!' + name : name, //fullName
287 n: name,
288 pr: prefix,
289 p: plugin
290 };
291 };
292
293 function makeConfig(name) {
294 return function () {
295 return (config && config.config && config.config[name]) || {};
296 };
297 }
298
299 handlers = {
300 require: function (name) {
301 return makeRequire(name);
302 },
303 exports: function (name) {
304 var e = defined[name];
305 if (typeof e !== 'undefined') {
306 return e;
307 } else {
308 return (defined[name] = {});
309 }
310 },
311 module: function (name) {
312 return {
313 id: name,
314 uri: '',
315 exports: defined[name],
316 config: makeConfig(name)
317 };
318 }
319 };
320
321 main = function (name, deps, callback, relName) {
322 var cjsModule, depName, ret, map, i, relParts,
323 args = [],
324 callbackType = typeof callback,
325 usingExports;
326
327 //Use name if no relName
328 relName = relName || name;
329 relParts = makeRelParts(relName);
330
331 //Call the callback to define the module, if necessary.
332 if (callbackType === 'undefined' || callbackType === 'function') {
333 //Pull out the defined dependencies and pass the ordered
334 //values to the callback.
335 //Default to [require, exports, module] if no deps
336 deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
337 for (i = 0; i < deps.length; i += 1) {
338 map = makeMap(deps[i], relParts);
339 depName = map.f;
340
341 //Fast path CommonJS standard dependencies.
342 if (depName === "require") {
343 args[i] = handlers.require(name);
344 } else if (depName === "exports") {
345 //CommonJS module spec 1.1
346 args[i] = handlers.exports(name);
347 usingExports = true;
348 } else if (depName === "module") {
349 //CommonJS module spec 1.1
350 cjsModule = args[i] = handlers.module(name);
351 } else if (hasProp(defined, depName) ||
352 hasProp(waiting, depName) ||
353 hasProp(defining, depName)) {
354 args[i] = callDep(depName);
355 } else if (map.p) {
356 map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
357 args[i] = defined[depName];
358 } else {
359 throw new Error(name + ' missing ' + depName);
360 }
361 }
362
363 ret = callback ? callback.apply(defined[name], args) : undefined;
364
365 if (name) {
366 //If setting exports via "module" is in play,
367 //favor that over return value and exports. After that,
368 //favor a non-undefined return value over exports use.
369 if (cjsModule && cjsModule.exports !== undef &&
370 cjsModule.exports !== defined[name]) {
371 defined[name] = cjsModule.exports;
372 } else if (ret !== undef || !usingExports) {
373 //Use the return value from the function.
374 defined[name] = ret;
375 }
376 }
377 } else if (name) {
378 //May just be an object definition for the module. Only
379 //worry about defining if have a module name.
380 defined[name] = callback;
381 }
382 };
383
384 requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
385 if (typeof deps === "string") {
386 if (handlers[deps]) {
387 //callback in this case is really relName
388 return handlers[deps](callback);
389 }
390 //Just return the module wanted. In this scenario, the
391 //deps arg is the module name, and second arg (if passed)
392 //is just the relName.
393 //Normalize module name, if it contains . or ..
394 return callDep(makeMap(deps, makeRelParts(callback)).f);
395 } else if (!deps.splice) {
396 //deps is a config object, not an array.
397 config = deps;
398 if (config.deps) {
399 req(config.deps, config.callback);
400 }
401 if (!callback) {
402 return;
403 }
404
405 if (callback.splice) {
406 //callback is an array, which means it is a dependency list.
407 //Adjust args if there are dependencies
408 deps = callback;
409 callback = relName;
410 relName = null;
411 } else {
412 deps = undef;
413 }
414 }
415
416 //Support require(['a'])
417 callback = callback || function () {};
418
419 //If relName is a function, it is an errback handler,
420 //so remove it.
421 if (typeof relName === 'function') {
422 relName = forceSync;
423 forceSync = alt;
424 }
425
426 //Simulate async callback;
427 if (forceSync) {
428 main(undef, deps, callback, relName);
429 } else {
430 //Using a non-zero value because of concern for what old browsers
431 //do, and latest browsers "upgrade" to 4 if lower value is used:
432 //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
433 //If want a value immediately, use require('id') instead -- something
434 //that works in almond on the global level, but not guaranteed and
435 //unlikely to work in other AMD implementations.
436 setTimeout(function () {
437 main(undef, deps, callback, relName);
438 }, 4);
439 }
440
441 return req;
442 };
443
444 /**
445 * Just drops the config on the floor, but returns req in case
446 * the config return value is used.
447 */
448 req.config = function (cfg) {
449 return req(cfg);
450 };
451
452 /**
453 * Expose module registry for debugging and tooling
454 */
455 requirejs._defined = defined;
456
457 define = function (name, deps, callback) {
458 if (typeof name !== 'string') {
459 throw new Error('See almond README: incorrect module build, no module name');
460 }
461
462 //This module may not have dependencies
463 if (!deps.splice) {
464 //deps is not an array, so probably means
465 //an object literal or factory function for
466 //the value. Adjust args.
467 callback = deps;
468 deps = [];
469 }
470
471 if (!hasProp(defined, name) && !hasProp(waiting, name)) {
472 waiting[name] = [name, deps, callback];
473 }
474 };
475
476 define.amd = {
477 jQuery: true
478 };
479 }());
480
481 S2.requirejs = requirejs;S2.require = require;S2.define = define;
482 }
483 }());
484 S2.define("almond", function(){});
485
486 /* global jQuery:false, $:false */
487 S2.define('jquery',[],function () {
488 var _$ = jQuery || $;
489
490 if (_$ == null && console && console.error) {
491 console.error(
492 'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
493 'found. Make sure that you are including jQuery before Select2 on your ' +
494 'web page.'
495 );
496 }
497
498 return _$;
499 });
500
501 S2.define('select2/utils',[
502 'jquery'
503 ], function ($) {
504 var Utils = {};
505
506 Utils.Extend = function (ChildClass, SuperClass) {
507 var __hasProp = {}.hasOwnProperty;
508
509 function BaseConstructor () {
510 this.constructor = ChildClass;
511 }
512
513 for (var key in SuperClass) {
514 if (__hasProp.call(SuperClass, key)) {
515 ChildClass[key] = SuperClass[key];
516 }
517 }
518
519 BaseConstructor.prototype = SuperClass.prototype;
520 ChildClass.prototype = new BaseConstructor();
521 ChildClass.__super__ = SuperClass.prototype;
522
523 return ChildClass;
524 };
525
526 function getMethods (theClass) {
527 var proto = theClass.prototype;
528
529 var methods = [];
530
531 for (var methodName in proto) {
532 var m = proto[methodName];
533
534 if (typeof m !== 'function') {
535 continue;
536 }
537
538 if (methodName === 'constructor') {
539 continue;
540 }
541
542 methods.push(methodName);
543 }
544
545 return methods;
546 }
547
548 Utils.Decorate = function (SuperClass, DecoratorClass) {
549 var decoratedMethods = getMethods(DecoratorClass);
550 var superMethods = getMethods(SuperClass);
551
552 function DecoratedClass () {
553 var unshift = Array.prototype.unshift;
554
555 var argCount = DecoratorClass.prototype.constructor.length;
556
557 var calledConstructor = SuperClass.prototype.constructor;
558
559 if (argCount > 0) {
560 unshift.call(arguments, SuperClass.prototype.constructor);
561
562 calledConstructor = DecoratorClass.prototype.constructor;
563 }
564
565 calledConstructor.apply(this, arguments);
566 }
567
568 DecoratorClass.displayName = SuperClass.displayName;
569
570 function ctr () {
571 this.constructor = DecoratedClass;
572 }
573
574 DecoratedClass.prototype = new ctr();
575
576 for (var m = 0; m < superMethods.length; m++) {
577 var superMethod = superMethods[m];
578
579 DecoratedClass.prototype[superMethod] =
580 SuperClass.prototype[superMethod];
581 }
582
583 var calledMethod = function (methodName) {
584 // Stub out the original method if it's not decorating an actual method
585 var originalMethod = function () {};
586
587 if (methodName in DecoratedClass.prototype) {
588 originalMethod = DecoratedClass.prototype[methodName];
589 }
590
591 var decoratedMethod = DecoratorClass.prototype[methodName];
592
593 return function () {
594 var unshift = Array.prototype.unshift;
595
596 unshift.call(arguments, originalMethod);
597
598 return decoratedMethod.apply(this, arguments);
599 };
600 };
601
602 for (var d = 0; d < decoratedMethods.length; d++) {
603 var decoratedMethod = decoratedMethods[d];
604
605 DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
606 }
607
608 return DecoratedClass;
609 };
610
611 var Observable = function () {
612 this.listeners = {};
613 };
614
615 Observable.prototype.on = function (event, callback) {
616 this.listeners = this.listeners || {};
617
618 if (event in this.listeners) {
619 this.listeners[event].push(callback);
620 } else {
621 this.listeners[event] = [callback];
622 }
623 };
624
625 Observable.prototype.trigger = function (event) {
626 var slice = Array.prototype.slice;
627 var params = slice.call(arguments, 1);
628
629 this.listeners = this.listeners || {};
630
631 // Params should always come in as an array
632 if (params == null) {
633 params = [];
634 }
635
636 // If there are no arguments to the event, use a temporary object
637 if (params.length === 0) {
638 params.push({});
639 }
640
641 // Set the `_type` of the first object to the event
642 params[0]._type = event;
643
644 if (event in this.listeners) {
645 this.invoke(this.listeners[event], slice.call(arguments, 1));
646 }
647
648 if ('*' in this.listeners) {
649 this.invoke(this.listeners['*'], arguments);
650 }
651 };
652
653 Observable.prototype.invoke = function (listeners, params) {
654 for (var i = 0, len = listeners.length; i < len; i++) {
655 listeners[i].apply(this, params);
656 }
657 };
658
659 Utils.Observable = Observable;
660
661 Utils.generateChars = function (length) {
662 var chars = '';
663
664 for (var i = 0; i < length; i++) {
665 var randomChar = Math.floor(Math.random() * 36);
666 chars += randomChar.toString(36);
667 }
668
669 return chars;
670 };
671
672 Utils.bind = function (func, context) {
673 return function () {
674 func.apply(context, arguments);
675 };
676 };
677
678 Utils._convertData = function (data) {
679 for (var originalKey in data) {
680 var keys = originalKey.split('-');
681
682 var dataLevel = data;
683
684 if (keys.length === 1) {
685 continue;
686 }
687
688 for (var k = 0; k < keys.length; k++) {
689 var key = keys[k];
690
691 // Lowercase the first letter
692 // By default, dash-separated becomes camelCase
693 key = key.substring(0, 1).toLowerCase() + key.substring(1);
694
695 if (!(key in dataLevel)) {
696 dataLevel[key] = {};
697 }
698
699 if (k == keys.length - 1) {
700 dataLevel[key] = data[originalKey];
701 }
702
703 dataLevel = dataLevel[key];
704 }
705
706 delete data[originalKey];
707 }
708
709 return data;
710 };
711
712 Utils.hasScroll = function (index, el) {
713 // Adapted from the function created by @ShadowScripter
714 // and adapted by @BillBarry on the Stack Exchange Code Review website.
715 // The original code can be found at
716 // http://codereview.stackexchange.com/q/13338
717 // and was designed to be used with the Sizzle selector engine.
718
719 var $el = $(el);
720 var overflowX = el.style.overflowX;
721 var overflowY = el.style.overflowY;
722
723 //Check both x and y declarations
724 if (overflowX === overflowY &&
725 (overflowY === 'hidden' || overflowY === 'visible')) {
726 return false;
727 }
728
729 if (overflowX === 'scroll' || overflowY === 'scroll') {
730 return true;
731 }
732
733 return ($el.innerHeight() < el.scrollHeight ||
734 $el.innerWidth() < el.scrollWidth);
735 };
736
737 Utils.escapeMarkup = function (markup) {
738 var replaceMap = {
739 '\\': '&#92;',
740 '&': '&amp;',
741 '<': '&lt;',
742 '>': '&gt;',
743 '"': '&quot;',
744 '\'': '&#39;',
745 '/': '&#47;'
746 };
747
748 // Do not try to escape the markup if it's not a string
749 if (typeof markup !== 'string') {
750 return markup;
751 }
752
753 return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
754 return replaceMap[match];
755 });
756 };
757
758 // Append an array of jQuery nodes to a given element.
759 Utils.appendMany = function ($element, $nodes) {
760 // jQuery 1.7.x does not support $.fn.append() with an array
761 // Fall back to a jQuery object collection using $.fn.add()
762 if ($.fn.jquery.substr(0, 3) === '1.7') {
763 var $jqNodes = $();
764
765 $.map($nodes, function (node) {
766 $jqNodes = $jqNodes.add(node);
767 });
768
769 $nodes = $jqNodes;
770 }
771
772 $element.append($nodes);
773 };
774
775 // Cache objects in Utils.__cache instead of $.data (see #4346)
776 Utils.__cache = {};
777
778 var id = 0;
779 Utils.GetUniqueElementId = function (element) {
780 // Get a unique element Id. If element has no id,
781 // creates a new unique number, stores it in the id
782 // attribute and returns the new id.
783 // If an id already exists, it simply returns it.
784
785 var select2Id = element.getAttribute('data-select2-id');
786 if (select2Id == null) {
787 // If element has id, use it.
788 if (element.id) {
789 select2Id = element.id;
790 element.setAttribute('data-select2-id', select2Id);
791 } else {
792 element.setAttribute('data-select2-id', ++id);
793 select2Id = id.toString();
794 }
795 }
796 return select2Id;
797 };
798
799 Utils.StoreData = function (element, name, value) {
800 // Stores an item in the cache for a specified element.
801 // name is the cache key.
802 var id = Utils.GetUniqueElementId(element);
803 if (!Utils.__cache[id]) {
804 Utils.__cache[id] = {};
805 }
806
807 Utils.__cache[id][name] = value;
808 };
809
810 Utils.GetData = function (element, name) {
811 // Retrieves a value from the cache by its key (name)
812 // name is optional. If no name specified, return
813 // all cache items for the specified element.
814 // and for a specified element.
815 var id = Utils.GetUniqueElementId(element);
816 if (name) {
817 if (Utils.__cache[id]) {
818 if (Utils.__cache[id][name] != null) {
819 return Utils.__cache[id][name];
820 }
821 return $(element).data(name); // Fallback to HTML5 data attribs.
822 }
823 return $(element).data(name); // Fallback to HTML5 data attribs.
824 } else {
825 return Utils.__cache[id];
826 }
827 };
828
829 Utils.RemoveData = function (element) {
830 // Removes all cached items for a specified element.
831 var id = Utils.GetUniqueElementId(element);
832 if (Utils.__cache[id] != null) {
833 delete Utils.__cache[id];
834 }
835
836 element.removeAttribute('data-select2-id');
837 };
838
839 return Utils;
840 });
841
842 S2.define('select2/results',[
843 'jquery',
844 './utils'
845 ], function ($, Utils) {
846 function Results ($element, options, dataAdapter) {
847 this.$element = $element;
848 this.data = dataAdapter;
849 this.options = options;
850
851 Results.__super__.constructor.call(this);
852 }
853
854 Utils.Extend(Results, Utils.Observable);
855
856 Results.prototype.render = function () {
857 var $results = $(
858 '<ul class="select2-results__options" role="listbox"></ul>'
859 );
860
861 if (this.options.get('multiple')) {
862 $results.attr('aria-multiselectable', 'true');
863 }
864
865 this.$results = $results;
866
867 return $results;
868 };
869
870 Results.prototype.clear = function () {
871 this.$results.empty();
872 };
873
874 Results.prototype.displayMessage = function (params) {
875 var escapeMarkup = this.options.get('escapeMarkup');
876
877 this.clear();
878 this.hideLoading();
879
880 var $message = $(
881 '<li role="alert" aria-live="assertive"' +
882 ' class="select2-results__option"></li>'
883 );
884
885 var message = this.options.get('translations').get(params.message);
886
887 $message.append(
888 escapeMarkup(
889 message(params.args)
890 )
891 );
892
893 $message[0].className += ' select2-results__message';
894
895 this.$results.append($message);
896 };
897
898 Results.prototype.hideMessages = function () {
899 this.$results.find('.select2-results__message').remove();
900 };
901
902 Results.prototype.append = function (data) {
903 this.hideLoading();
904
905 var $options = [];
906
907 if (data.results == null || data.results.length === 0) {
908 if (this.$results.children().length === 0) {
909 this.trigger('results:message', {
910 message: 'noResults'
911 });
912 }
913
914 return;
915 }
916
917 data.results = this.sort(data.results);
918
919 for (var d = 0; d < data.results.length; d++) {
920 var item = data.results[d];
921
922 var $option = this.option(item);
923
924 $options.push($option);
925 }
926
927 this.$results.append($options);
928 };
929
930 Results.prototype.position = function ($results, $dropdown) {
931 var $resultsContainer = $dropdown.find('.select2-results');
932 $resultsContainer.append($results);
933 };
934
935 Results.prototype.sort = function (data) {
936 var sorter = this.options.get('sorter');
937
938 return sorter(data);
939 };
940
941 Results.prototype.highlightFirstItem = function () {
942 var $options = this.$results
943 .find('.select2-results__option[aria-selected]');
944
945 var $selected = $options.filter('[aria-selected=true]');
946
947 // Check if there are any selected options
948 if ($selected.length > 0) {
949 // If there are selected options, highlight the first
950 $selected.first().trigger('mouseenter');
951 } else {
952 // If there are no selected options, highlight the first option
953 // in the dropdown
954 $options.first().trigger('mouseenter');
955 }
956
957 this.ensureHighlightVisible();
958 };
959
960 Results.prototype.setClasses = function () {
961 var self = this;
962
963 this.data.current(function (selected) {
964 var selectedIds = $.map(selected, function (s) {
965 return s.id.toString();
966 });
967
968 var $options = self.$results
969 .find('.select2-results__option[aria-selected]');
970
971 $options.each(function () {
972 var $option = $(this);
973
974 var item = Utils.GetData(this, 'data');
975
976 // id needs to be converted to a string when comparing
977 var id = '' + item.id;
978
979 if ((item.element != null && item.element.selected) ||
980 (item.element == null && $.inArray(id, selectedIds) > -1)) {
981 $option.attr('aria-selected', 'true');
982 } else {
983 $option.attr('aria-selected', 'false');
984 }
985 });
986
987 });
988 };
989
990 Results.prototype.showLoading = function (params) {
991 this.hideLoading();
992
993 var loadingMore = this.options.get('translations').get('searching');
994
995 var loading = {
996 disabled: true,
997 loading: true,
998 text: loadingMore(params)
999 };
1000 var $loading = this.option(loading);
1001 $loading.className += ' loading-results';
1002
1003 this.$results.prepend($loading);
1004 };
1005
1006 Results.prototype.hideLoading = function () {
1007 this.$results.find('.loading-results').remove();
1008 };
1009
1010 Results.prototype.option = function (data) {
1011 var option = document.createElement('li');
1012 option.className = 'select2-results__option';
1013
1014 var attrs = {
1015 'role': 'option',
1016 'aria-selected': 'false'
1017 };
1018
1019 var matches = window.Element.prototype.matches ||
1020 window.Element.prototype.msMatchesSelector ||
1021 window.Element.prototype.webkitMatchesSelector;
1022
1023 if ((data.element != null && matches.call(data.element, ':disabled')) ||
1024 (data.element == null && data.disabled)) {
1025 delete attrs['aria-selected'];
1026 attrs['aria-disabled'] = 'true';
1027 }
1028
1029 if (data.id == null) {
1030 delete attrs['aria-selected'];
1031 }
1032
1033 if (data._resultId != null) {
1034 option.id = data._resultId;
1035 }
1036
1037 if (data.title) {
1038 option.title = data.title;
1039 }
1040
1041 if (data.children) {
1042 attrs.role = 'group';
1043 attrs['aria-label'] = data.text;
1044 delete attrs['aria-selected'];
1045 }
1046
1047 for (var attr in attrs) {
1048 var val = attrs[attr];
1049
1050 option.setAttribute(attr, val);
1051 }
1052
1053 if (data.children) {
1054 var $option = $(option);
1055
1056 var label = document.createElement('strong');
1057 label.className = 'select2-results__group';
1058
1059 var $label = $(label);
1060 this.template(data, label);
1061
1062 var $children = [];
1063
1064 for (var c = 0; c < data.children.length; c++) {
1065 var child = data.children[c];
1066
1067 var $child = this.option(child);
1068
1069 $children.push($child);
1070 }
1071
1072 var $childrenContainer = $('<ul></ul>', {
1073 'class': 'select2-results__options select2-results__options--nested'
1074 });
1075
1076 $childrenContainer.append($children);
1077
1078 $option.append(label);
1079 $option.append($childrenContainer);
1080 } else {
1081 this.template(data, option);
1082 }
1083
1084 Utils.StoreData(option, 'data', data);
1085
1086 return option;
1087 };
1088
1089 Results.prototype.bind = function (container, $container) {
1090 var self = this;
1091
1092 var id = container.id + '-results';
1093
1094 this.$results.attr('id', id);
1095
1096 container.on('results:all', function (params) {
1097 self.clear();
1098 self.append(params.data);
1099
1100 if (container.isOpen()) {
1101 self.setClasses();
1102 self.highlightFirstItem();
1103 }
1104 });
1105
1106 container.on('results:append', function (params) {
1107 self.append(params.data);
1108
1109 if (container.isOpen()) {
1110 self.setClasses();
1111 }
1112 });
1113
1114 container.on('query', function (params) {
1115 self.hideMessages();
1116 self.showLoading(params);
1117 });
1118
1119 container.on('select', function () {
1120 if (!container.isOpen()) {
1121 return;
1122 }
1123
1124 self.setClasses();
1125
1126 if (self.options.get('scrollAfterSelect')) {
1127 self.highlightFirstItem();
1128 }
1129 });
1130
1131 container.on('unselect', function () {
1132 if (!container.isOpen()) {
1133 return;
1134 }
1135
1136 self.setClasses();
1137
1138 if (self.options.get('scrollAfterSelect')) {
1139 self.highlightFirstItem();
1140 }
1141 });
1142
1143 container.on('open', function () {
1144 // When the dropdown is open, aria-expended="true"
1145 self.$results.attr('aria-expanded', 'true');
1146 self.$results.attr('aria-hidden', 'false');
1147
1148 self.setClasses();
1149 self.ensureHighlightVisible();
1150 });
1151
1152 container.on('close', function () {
1153 // When the dropdown is closed, aria-expended="false"
1154 self.$results.attr('aria-expanded', 'false');
1155 self.$results.attr('aria-hidden', 'true');
1156 self.$results.removeAttr('aria-activedescendant');
1157 });
1158
1159 container.on('results:toggle', function () {
1160 var $highlighted = self.getHighlightedResults();
1161
1162 if ($highlighted.length === 0) {
1163 return;
1164 }
1165
1166 $highlighted.trigger('mouseup');
1167 });
1168
1169 container.on('results:select', function () {
1170 var $highlighted = self.getHighlightedResults();
1171
1172 if ($highlighted.length === 0) {
1173 return;
1174 }
1175
1176 var data = Utils.GetData($highlighted[0], 'data');
1177
1178 if ($highlighted.attr('aria-selected') == 'true') {
1179 self.trigger('close', {});
1180 } else {
1181 self.trigger('select', {
1182 data: data
1183 });
1184 }
1185 });
1186
1187 container.on('results:previous', function () {
1188 var $highlighted = self.getHighlightedResults();
1189
1190 var $options = self.$results.find('[aria-selected]');
1191
1192 var currentIndex = $options.index($highlighted);
1193
1194 // If we are already at the top, don't move further
1195 // If no options, currentIndex will be -1
1196 if (currentIndex <= 0) {
1197 return;
1198 }
1199
1200 var nextIndex = currentIndex - 1;
1201
1202 // If none are highlighted, highlight the first
1203 if ($highlighted.length === 0) {
1204 nextIndex = 0;
1205 }
1206
1207 var $next = $options.eq(nextIndex);
1208
1209 $next.trigger('mouseenter');
1210
1211 var currentOffset = self.$results.offset().top;
1212 var nextTop = $next.offset().top;
1213 var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
1214
1215 if (nextIndex === 0) {
1216 self.$results.scrollTop(0);
1217 } else if (nextTop - currentOffset < 0) {
1218 self.$results.scrollTop(nextOffset);
1219 }
1220 });
1221
1222 container.on('results:next', function () {
1223 var $highlighted = self.getHighlightedResults();
1224
1225 var $options = self.$results.find('[aria-selected]');
1226
1227 var currentIndex = $options.index($highlighted);
1228
1229 var nextIndex = currentIndex + 1;
1230
1231 // If we are at the last option, stay there
1232 if (nextIndex >= $options.length) {
1233 return;
1234 }
1235
1236 var $next = $options.eq(nextIndex);
1237
1238 $next.trigger('mouseenter');
1239
1240 var currentOffset = self.$results.offset().top +
1241 self.$results.outerHeight(false);
1242 var nextBottom = $next.offset().top + $next.outerHeight(false);
1243 var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
1244
1245 if (nextIndex === 0) {
1246 self.$results.scrollTop(0);
1247 } else if (nextBottom > currentOffset) {
1248 self.$results.scrollTop(nextOffset);
1249 }
1250 });
1251
1252 container.on('results:focus', function (params) {
1253 params.element.addClass('select2-results__option--highlighted');
1254 });
1255
1256 container.on('results:message', function (params) {
1257 self.displayMessage(params);
1258 });
1259
1260 if ($.fn.mousewheel) {
1261 this.$results.on('mousewheel', function (e) {
1262 var top = self.$results.scrollTop();
1263
1264 var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
1265
1266 var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
1267 var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
1268
1269 if (isAtTop) {
1270 self.$results.scrollTop(0);
1271
1272 e.preventDefault();
1273 e.stopPropagation();
1274 } else if (isAtBottom) {
1275 self.$results.scrollTop(
1276 self.$results.get(0).scrollHeight - self.$results.height()
1277 );
1278
1279 e.preventDefault();
1280 e.stopPropagation();
1281 }
1282 });
1283 }
1284
1285 this.$results.on('mouseup', '.select2-results__option[aria-selected]',
1286 function (evt) {
1287 var $this = $(this);
1288
1289 var data = Utils.GetData(this, 'data');
1290
1291 if ($this.attr('aria-selected') === 'true') {
1292 if (self.options.get('multiple')) {
1293 self.trigger('unselect', {
1294 originalEvent: evt,
1295 data: data
1296 });
1297 } else {
1298 self.trigger('close', {});
1299 }
1300
1301 return;
1302 }
1303
1304 self.trigger('select', {
1305 originalEvent: evt,
1306 data: data
1307 });
1308 });
1309
1310 this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
1311 function (evt) {
1312 var data = Utils.GetData(this, 'data');
1313
1314 self.getHighlightedResults()
1315 .removeClass('select2-results__option--highlighted');
1316
1317 self.trigger('results:focus', {
1318 data: data,
1319 element: $(this)
1320 });
1321 });
1322 };
1323
1324 Results.prototype.getHighlightedResults = function () {
1325 var $highlighted = this.$results
1326 .find('.select2-results__option--highlighted');
1327
1328 return $highlighted;
1329 };
1330
1331 Results.prototype.destroy = function () {
1332 this.$results.remove();
1333 };
1334
1335 Results.prototype.ensureHighlightVisible = function () {
1336 var $highlighted = this.getHighlightedResults();
1337
1338 if ($highlighted.length === 0) {
1339 return;
1340 }
1341
1342 var $options = this.$results.find('[aria-selected]');
1343
1344 var currentIndex = $options.index($highlighted);
1345
1346 var currentOffset = this.$results.offset().top;
1347 var nextTop = $highlighted.offset().top;
1348 var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
1349
1350 var offsetDelta = nextTop - currentOffset;
1351 nextOffset -= $highlighted.outerHeight(false) * 2;
1352
1353 if (currentIndex <= 2) {
1354 this.$results.scrollTop(0);
1355 } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
1356 this.$results.scrollTop(nextOffset);
1357 }
1358 };
1359
1360 Results.prototype.template = function (result, container) {
1361 var template = this.options.get('templateResult');
1362 var escapeMarkup = this.options.get('escapeMarkup');
1363
1364 var content = template(result, container);
1365
1366 if (content == null) {
1367 container.style.display = 'none';
1368 } else if (typeof content === 'string') {
1369 container.innerHTML = escapeMarkup(content);
1370 } else {
1371 $(container).append(content);
1372 }
1373 };
1374
1375 return Results;
1376 });
1377
1378 S2.define('select2/keys',[
1379
1380 ], function () {
1381 var KEYS = {
1382 BACKSPACE: 8,
1383 TAB: 9,
1384 ENTER: 13,
1385 SHIFT: 16,
1386 CTRL: 17,
1387 ALT: 18,
1388 ESC: 27,
1389 SPACE: 32,
1390 PAGE_UP: 33,
1391 PAGE_DOWN: 34,
1392 END: 35,
1393 HOME: 36,
1394 LEFT: 37,
1395 UP: 38,
1396 RIGHT: 39,
1397 DOWN: 40,
1398 DELETE: 46
1399 };
1400
1401 return KEYS;
1402 });
1403
1404 S2.define('select2/selection/base',[
1405 'jquery',
1406 '../utils',
1407 '../keys'
1408 ], function ($, Utils, KEYS) {
1409 function BaseSelection ($element, options) {
1410 this.$element = $element;
1411 this.options = options;
1412
1413 BaseSelection.__super__.constructor.call(this);
1414 }
1415
1416 Utils.Extend(BaseSelection, Utils.Observable);
1417
1418 BaseSelection.prototype.render = function () {
1419 var $selection = $(
1420 '<span class="select2-selection" role="combobox" ' +
1421 ' aria-haspopup="true" aria-expanded="false">' +
1422 '</span>'
1423 );
1424
1425 this._tabindex = 0;
1426
1427 if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
1428 this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
1429 } else if (this.$element.attr('tabindex') != null) {
1430 this._tabindex = this.$element.attr('tabindex');
1431 }
1432
1433 $selection.attr('title', this.$element.attr('title'));
1434 $selection.attr('tabindex', this._tabindex);
1435 $selection.attr('aria-disabled', 'false');
1436
1437 this.$selection = $selection;
1438
1439 return $selection;
1440 };
1441
1442 BaseSelection.prototype.bind = function (container, $container) {
1443 var self = this;
1444
1445 var resultsId = container.id + '-results';
1446
1447 this.container = container;
1448
1449 this.$selection.on('focus', function (evt) {
1450 self.trigger('focus', evt);
1451 });
1452
1453 this.$selection.on('blur', function (evt) {
1454 self._handleBlur(evt);
1455 });
1456
1457 this.$selection.on('keydown', function (evt) {
1458 self.trigger('keypress', evt);
1459
1460 if (evt.which === KEYS.SPACE) {
1461 evt.preventDefault();
1462 }
1463 });
1464
1465 container.on('results:focus', function (params) {
1466 self.$selection.attr('aria-activedescendant', params.data._resultId);
1467 });
1468
1469 container.on('selection:update', function (params) {
1470 self.update(params.data);
1471 });
1472
1473 container.on('open', function () {
1474 // When the dropdown is open, aria-expanded="true"
1475 self.$selection.attr('aria-expanded', 'true');
1476 self.$selection.attr('aria-owns', resultsId);
1477
1478 self._attachCloseHandler(container);
1479 });
1480
1481 container.on('close', function () {
1482 // When the dropdown is closed, aria-expanded="false"
1483 self.$selection.attr('aria-expanded', 'false');
1484 self.$selection.removeAttr('aria-activedescendant');
1485 self.$selection.removeAttr('aria-owns');
1486
1487 self.$selection.trigger('focus');
1488
1489 self._detachCloseHandler(container);
1490 });
1491
1492 container.on('enable', function () {
1493 self.$selection.attr('tabindex', self._tabindex);
1494 self.$selection.attr('aria-disabled', 'false');
1495 });
1496
1497 container.on('disable', function () {
1498 self.$selection.attr('tabindex', '-1');
1499 self.$selection.attr('aria-disabled', 'true');
1500 });
1501 };
1502
1503 BaseSelection.prototype._handleBlur = function (evt) {
1504 var self = this;
1505
1506 // This needs to be delayed as the active element is the body when the tab
1507 // key is pressed, possibly along with others.
1508 window.setTimeout(function () {
1509 // Don't trigger `blur` if the focus is still in the selection
1510 if (
1511 (document.activeElement == self.$selection[0]) ||
1512 ($.contains(self.$selection[0], document.activeElement))
1513 ) {
1514 return;
1515 }
1516
1517 self.trigger('blur', evt);
1518 }, 1);
1519 };
1520
1521 BaseSelection.prototype._attachCloseHandler = function (container) {
1522
1523 $(document.body).on('mousedown.select2.' + container.id, function (e) {
1524 var $target = $(e.target);
1525
1526 var $select = $target.closest('.select2');
1527
1528 var $all = $('.select2.select2-container--open');
1529
1530 $all.each(function () {
1531 if (this == $select[0]) {
1532 return;
1533 }
1534
1535 var $element = Utils.GetData(this, 'element');
1536
1537 $element.select2('close');
1538 });
1539 });
1540 };
1541
1542 BaseSelection.prototype._detachCloseHandler = function (container) {
1543 $(document.body).off('mousedown.select2.' + container.id);
1544 };
1545
1546 BaseSelection.prototype.position = function ($selection, $container) {
1547 var $selectionContainer = $container.find('.selection');
1548 $selectionContainer.append($selection);
1549 };
1550
1551 BaseSelection.prototype.destroy = function () {
1552 this._detachCloseHandler(this.container);
1553 };
1554
1555 BaseSelection.prototype.update = function (data) {
1556 throw new Error('The `update` method must be defined in child classes.');
1557 };
1558
1559 /**
1560 * Helper method to abstract the "enabled" (not "disabled") state of this
1561 * object.
1562 *
1563 * @return {true} if the instance is not disabled.
1564 * @return {false} if the instance is disabled.
1565 */
1566 BaseSelection.prototype.isEnabled = function () {
1567 return !this.isDisabled();
1568 };
1569
1570 /**
1571 * Helper method to abstract the "disabled" state of this object.
1572 *
1573 * @return {true} if the disabled option is true.
1574 * @return {false} if the disabled option is false.
1575 */
1576 BaseSelection.prototype.isDisabled = function () {
1577 return this.options.get('disabled');
1578 };
1579
1580 return BaseSelection;
1581 });
1582
1583 S2.define('select2/selection/single',[
1584 'jquery',
1585 './base',
1586 '../utils',
1587 '../keys'
1588 ], function ($, BaseSelection, Utils, KEYS) {
1589 function SingleSelection () {
1590 SingleSelection.__super__.constructor.apply(this, arguments);
1591 }
1592
1593 Utils.Extend(SingleSelection, BaseSelection);
1594
1595 SingleSelection.prototype.render = function () {
1596 var $selection = SingleSelection.__super__.render.call(this);
1597
1598 $selection.addClass('select2-selection--single');
1599
1600 $selection.html(
1601 '<span class="select2-selection__rendered"></span>' +
1602 '<span class="select2-selection__arrow" role="presentation">' +
1603 '<b role="presentation"></b>' +
1604 '</span>'
1605 );
1606
1607 return $selection;
1608 };
1609
1610 SingleSelection.prototype.bind = function (container, $container) {
1611 var self = this;
1612
1613 SingleSelection.__super__.bind.apply(this, arguments);
1614
1615 var id = container.id + '-container';
1616
1617 this.$selection.find('.select2-selection__rendered')
1618 .attr('id', id)
1619 .attr('role', 'textbox')
1620 .attr('aria-readonly', 'true');
1621 this.$selection.attr('aria-labelledby', id);
1622
1623 this.$selection.on('mousedown', function (evt) {
1624 // Only respond to left clicks
1625 if (evt.which !== 1) {
1626 return;
1627 }
1628
1629 self.trigger('toggle', {
1630 originalEvent: evt
1631 });
1632 });
1633
1634 this.$selection.on('focus', function (evt) {
1635 // User focuses on the container
1636 });
1637
1638 this.$selection.on('blur', function (evt) {
1639 // User exits the container
1640 });
1641
1642 container.on('focus', function (evt) {
1643 if (!container.isOpen()) {
1644 self.$selection.trigger('focus');
1645 }
1646 });
1647 };
1648
1649 SingleSelection.prototype.clear = function () {
1650 var $rendered = this.$selection.find('.select2-selection__rendered');
1651 $rendered.empty();
1652 $rendered.removeAttr('title'); // clear tooltip on empty
1653 };
1654
1655 SingleSelection.prototype.display = function (data, container) {
1656 var template = this.options.get('templateSelection');
1657 var escapeMarkup = this.options.get('escapeMarkup');
1658
1659 return escapeMarkup(template(data, container));
1660 };
1661
1662 SingleSelection.prototype.selectionContainer = function () {
1663 return $('<span></span>');
1664 };
1665
1666 SingleSelection.prototype.update = function (data) {
1667 if (data.length === 0) {
1668 this.clear();
1669 return;
1670 }
1671
1672 var selection = data[0];
1673
1674 var $rendered = this.$selection.find('.select2-selection__rendered');
1675 var formatted = this.display(selection, $rendered);
1676
1677 $rendered.empty().append(formatted);
1678
1679 var title = selection.title || selection.text;
1680
1681 if (title) {
1682 $rendered.attr('title', title);
1683 } else {
1684 $rendered.removeAttr('title');
1685 }
1686 };
1687
1688 return SingleSelection;
1689 });
1690
1691 S2.define('select2/selection/multiple',[
1692 'jquery',
1693 './base',
1694 '../utils'
1695 ], function ($, BaseSelection, Utils) {
1696 function MultipleSelection ($element, options) {
1697 MultipleSelection.__super__.constructor.apply(this, arguments);
1698 }
1699
1700 Utils.Extend(MultipleSelection, BaseSelection);
1701
1702 MultipleSelection.prototype.render = function () {
1703 var $selection = MultipleSelection.__super__.render.call(this);
1704
1705 $selection.addClass('select2-selection--multiple');
1706
1707 $selection.html(
1708 '<ul class="select2-selection__rendered"></ul>'
1709 );
1710
1711 return $selection;
1712 };
1713
1714 MultipleSelection.prototype.bind = function (container, $container) {
1715 var self = this;
1716
1717 MultipleSelection.__super__.bind.apply(this, arguments);
1718
1719 this.$selection.on('click', function (evt) {
1720 self.trigger('toggle', {
1721 originalEvent: evt
1722 });
1723 });
1724
1725 this.$selection.on(
1726 'click',
1727 '.select2-selection__choice__remove',
1728 function (evt) {
1729 // Ignore the event if it is disabled
1730 if (self.isDisabled()) {
1731 return;
1732 }
1733
1734 var $remove = $(this);
1735 var $selection = $remove.parent();
1736
1737 var data = Utils.GetData($selection[0], 'data');
1738
1739 self.trigger('unselect', {
1740 originalEvent: evt,
1741 data: data
1742 });
1743 }
1744 );
1745 };
1746
1747 MultipleSelection.prototype.clear = function () {
1748 var $rendered = this.$selection.find('.select2-selection__rendered');
1749 $rendered.empty();
1750 $rendered.removeAttr('title');
1751 };
1752
1753 MultipleSelection.prototype.display = function (data, container) {
1754 var template = this.options.get('templateSelection');
1755 var escapeMarkup = this.options.get('escapeMarkup');
1756
1757 return escapeMarkup(template(data, container));
1758 };
1759
1760 MultipleSelection.prototype.selectionContainer = function () {
1761 var $container = $(
1762 '<li class="select2-selection__choice">' +
1763 '<span class="select2-selection__choice__remove" role="presentation">' +
1764 '&times;' +
1765 '</span>' +
1766 '</li>'
1767 );
1768
1769 return $container;
1770 };
1771
1772 MultipleSelection.prototype.update = function (data) {
1773 this.clear();
1774
1775 if (data.length === 0) {
1776 return;
1777 }
1778
1779 var $selections = [];
1780
1781 for (var d = 0; d < data.length; d++) {
1782 var selection = data[d];
1783
1784 var $selection = this.selectionContainer();
1785 var formatted = this.display(selection, $selection);
1786
1787 $selection.append(formatted);
1788
1789 var title = selection.title || selection.text;
1790
1791 if (title) {
1792 $selection.attr('title', title);
1793 }
1794
1795 Utils.StoreData($selection[0], 'data', selection);
1796
1797 $selections.push($selection);
1798 }
1799
1800 var $rendered = this.$selection.find('.select2-selection__rendered');
1801
1802 Utils.appendMany($rendered, $selections);
1803 };
1804
1805 return MultipleSelection;
1806 });
1807
1808 S2.define('select2/selection/placeholder',[
1809 '../utils'
1810 ], function (Utils) {
1811 function Placeholder (decorated, $element, options) {
1812 this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
1813
1814 decorated.call(this, $element, options);
1815 }
1816
1817 Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
1818 if (typeof placeholder === 'string') {
1819 placeholder = {
1820 id: '',
1821 text: placeholder
1822 };
1823 }
1824
1825 return placeholder;
1826 };
1827
1828 Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
1829 var $placeholder = this.selectionContainer();
1830
1831 $placeholder.html(this.display(placeholder));
1832 $placeholder.addClass('select2-selection__placeholder')
1833 .removeClass('select2-selection__choice');
1834
1835 return $placeholder;
1836 };
1837
1838 Placeholder.prototype.update = function (decorated, data) {
1839 var singlePlaceholder = (
1840 data.length == 1 && data[0].id != this.placeholder.id
1841 );
1842 var multipleSelections = data.length > 1;
1843
1844 if (multipleSelections || singlePlaceholder) {
1845 return decorated.call(this, data);
1846 }
1847
1848 this.clear();
1849
1850 var $placeholder = this.createPlaceholder(this.placeholder);
1851
1852 this.$selection.find('.select2-selection__rendered').append($placeholder);
1853 };
1854
1855 return Placeholder;
1856 });
1857
1858 S2.define('select2/selection/allowClear',[
1859 'jquery',
1860 '../keys',
1861 '../utils'
1862 ], function ($, KEYS, Utils) {
1863 function AllowClear () { }
1864
1865 AllowClear.prototype.bind = function (decorated, container, $container) {
1866 var self = this;
1867
1868 decorated.call(this, container, $container);
1869
1870 if (this.placeholder == null) {
1871 if (this.options.get('debug') && window.console && console.error) {
1872 console.error(
1873 'Select2: The `allowClear` option should be used in combination ' +
1874 'with the `placeholder` option.'
1875 );
1876 }
1877 }
1878
1879 this.$selection.on('mousedown', '.select2-selection__clear',
1880 function (evt) {
1881 self._handleClear(evt);
1882 });
1883
1884 container.on('keypress', function (evt) {
1885 self._handleKeyboardClear(evt, container);
1886 });
1887 };
1888
1889 AllowClear.prototype._handleClear = function (_, evt) {
1890 // Ignore the event if it is disabled
1891 if (this.isDisabled()) {
1892 return;
1893 }
1894
1895 var $clear = this.$selection.find('.select2-selection__clear');
1896
1897 // Ignore the event if nothing has been selected
1898 if ($clear.length === 0) {
1899 return;
1900 }
1901
1902 evt.stopPropagation();
1903
1904 var data = Utils.GetData($clear[0], 'data');
1905
1906 var previousVal = this.$element.val();
1907 this.$element.val(this.placeholder.id);
1908
1909 var unselectData = {
1910 data: data
1911 };
1912 this.trigger('clear', unselectData);
1913 if (unselectData.prevented) {
1914 this.$element.val(previousVal);
1915 return;
1916 }
1917
1918 for (var d = 0; d < data.length; d++) {
1919 unselectData = {
1920 data: data[d]
1921 };
1922
1923 // Trigger the `unselect` event, so people can prevent it from being
1924 // cleared.
1925 this.trigger('unselect', unselectData);
1926
1927 // If the event was prevented, don't clear it out.
1928 if (unselectData.prevented) {
1929 this.$element.val(previousVal);
1930 return;
1931 }
1932 }
1933
1934 this.$element.trigger('input').trigger('change');
1935
1936 this.trigger('toggle', {});
1937 };
1938
1939 AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
1940 if (container.isOpen()) {
1941 return;
1942 }
1943
1944 if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
1945 this._handleClear(evt);
1946 }
1947 };
1948
1949 AllowClear.prototype.update = function (decorated, data) {
1950 decorated.call(this, data);
1951
1952 if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
1953 data.length === 0) {
1954 return;
1955 }
1956
1957 var removeAll = this.options.get('translations').get('removeAllItems');
1958
1959 var $remove = $(
1960 '<span class="select2-selection__clear" title="' + removeAll() +'">' +
1961 '&times;' +
1962 '</span>'
1963 );
1964 Utils.StoreData($remove[0], 'data', data);
1965
1966 this.$selection.find('.select2-selection__rendered').prepend($remove);
1967 };
1968
1969 return AllowClear;
1970 });
1971
1972 S2.define('select2/selection/search',[
1973 'jquery',
1974 '../utils',
1975 '../keys'
1976 ], function ($, Utils, KEYS) {
1977 function Search (decorated, $element, options) {
1978 decorated.call(this, $element, options);
1979 }
1980
1981 Search.prototype.render = function (decorated) {
1982 var $search = $(
1983 '<li class="select2-search select2-search--inline">' +
1984 '<input class="select2-search__field" type="search" tabindex="-1"' +
1985 ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
1986 ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
1987 '</li>'
1988 );
1989
1990 this.$searchContainer = $search;
1991 this.$search = $search.find('input');
1992
1993 var $rendered = decorated.call(this);
1994
1995 this._transferTabIndex();
1996
1997 return $rendered;
1998 };
1999
2000 Search.prototype.bind = function (decorated, container, $container) {
2001 var self = this;
2002
2003 var resultsId = container.id + '-results';
2004
2005 decorated.call(this, container, $container);
2006
2007 container.on('open', function () {
2008 self.$search.attr('aria-controls', resultsId);
2009 self.$search.trigger('focus');
2010 });
2011
2012 container.on('close', function () {
2013 self.$search.val('');
2014 self.$search.removeAttr('aria-controls');
2015 self.$search.removeAttr('aria-activedescendant');
2016 self.$search.trigger('focus');
2017 });
2018
2019 container.on('enable', function () {
2020 self.$search.prop('disabled', false);
2021
2022 self._transferTabIndex();
2023 });
2024
2025 container.on('disable', function () {
2026 self.$search.prop('disabled', true);
2027 });
2028
2029 container.on('focus', function (evt) {
2030 self.$search.trigger('focus');
2031 });
2032
2033 container.on('results:focus', function (params) {
2034 if (params.data._resultId) {
2035 self.$search.attr('aria-activedescendant', params.data._resultId);
2036 } else {
2037 self.$search.removeAttr('aria-activedescendant');
2038 }
2039 });
2040
2041 this.$selection.on('focusin', '.select2-search--inline', function (evt) {
2042 self.trigger('focus', evt);
2043 });
2044
2045 this.$selection.on('focusout', '.select2-search--inline', function (evt) {
2046 self._handleBlur(evt);
2047 });
2048
2049 this.$selection.on('keydown', '.select2-search--inline', function (evt) {
2050 evt.stopPropagation();
2051
2052 self.trigger('keypress', evt);
2053
2054 self._keyUpPrevented = evt.isDefaultPrevented();
2055
2056 var key = evt.which;
2057
2058 if (key === KEYS.BACKSPACE && self.$search.val() === '') {
2059 var $previousChoice = self.$searchContainer
2060 .prev('.select2-selection__choice');
2061
2062 if ($previousChoice.length > 0) {
2063 var item = Utils.GetData($previousChoice[0], 'data');
2064
2065 self.searchRemoveChoice(item);
2066
2067 evt.preventDefault();
2068 }
2069 }
2070 });
2071
2072 this.$selection.on('click', '.select2-search--inline', function (evt) {
2073 if (self.$search.val()) {
2074 evt.stopPropagation();
2075 }
2076 });
2077
2078 // Try to detect the IE version should the `documentMode` property that
2079 // is stored on the document. This is only implemented in IE and is
2080 // slightly cleaner than doing a user agent check.
2081 // This property is not available in Edge, but Edge also doesn't have
2082 // this bug.
2083 var msie = document.documentMode;
2084 var disableInputEvents = msie && msie <= 11;
2085
2086 // Workaround for browsers which do not support the `input` event
2087 // This will prevent double-triggering of events for browsers which support
2088 // both the `keyup` and `input` events.
2089 this.$selection.on(
2090 'input.searchcheck',
2091 '.select2-search--inline',
2092 function (evt) {
2093 // IE will trigger the `input` event when a placeholder is used on a
2094 // search box. To get around this issue, we are forced to ignore all
2095 // `input` events in IE and keep using `keyup`.
2096 if (disableInputEvents) {
2097 self.$selection.off('input.search input.searchcheck');
2098 return;
2099 }
2100
2101 // Unbind the duplicated `keyup` event
2102 self.$selection.off('keyup.search');
2103 }
2104 );
2105
2106 this.$selection.on(
2107 'keyup.search input.search',
2108 '.select2-search--inline',
2109 function (evt) {
2110 // IE will trigger the `input` event when a placeholder is used on a
2111 // search box. To get around this issue, we are forced to ignore all
2112 // `input` events in IE and keep using `keyup`.
2113 if (disableInputEvents && evt.type === 'input') {
2114 self.$selection.off('input.search input.searchcheck');
2115 return;
2116 }
2117
2118 var key = evt.which;
2119
2120 // We can freely ignore events from modifier keys
2121 if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
2122 return;
2123 }
2124
2125 // Tabbing will be handled during the `keydown` phase
2126 if (key == KEYS.TAB) {
2127 return;
2128 }
2129
2130 self.handleSearch(evt);
2131 }
2132 );
2133 };
2134
2135 /**
2136 * This method will transfer the tabindex attribute from the rendered
2137 * selection to the search box. This allows for the search box to be used as
2138 * the primary focus instead of the selection container.
2139 *
2140 * @private
2141 */
2142 Search.prototype._transferTabIndex = function (decorated) {
2143 this.$search.attr('tabindex', this.$selection.attr('tabindex'));
2144 this.$selection.attr('tabindex', '-1');
2145 };
2146
2147 Search.prototype.createPlaceholder = function (decorated, placeholder) {
2148 this.$search.attr('placeholder', placeholder.text);
2149 };
2150
2151 Search.prototype.update = function (decorated, data) {
2152 var searchHadFocus = this.$search[0] == document.activeElement;
2153
2154 this.$search.attr('placeholder', '');
2155
2156 decorated.call(this, data);
2157
2158 this.$selection.find('.select2-selection__rendered')
2159 .append(this.$searchContainer);
2160
2161 this.resizeSearch();
2162 if (searchHadFocus) {
2163 this.$search.trigger('focus');
2164 }
2165 };
2166
2167 Search.prototype.handleSearch = function () {
2168 this.resizeSearch();
2169
2170 if (!this._keyUpPrevented) {
2171 var input = this.$search.val();
2172
2173 this.trigger('query', {
2174 term: input
2175 });
2176 }
2177
2178 this._keyUpPrevented = false;
2179 };
2180
2181 Search.prototype.searchRemoveChoice = function (decorated, item) {
2182 this.trigger('unselect', {
2183 data: item
2184 });
2185
2186 this.$search.val(item.text);
2187 this.handleSearch();
2188 };
2189
2190 Search.prototype.resizeSearch = function () {
2191 this.$search.css('width', '25px');
2192
2193 var width = '';
2194
2195 if (this.$search.attr('placeholder') !== '') {
2196 width = this.$selection.find('.select2-selection__rendered').width();
2197 } else {
2198 var minimumWidth = this.$search.val().length + 1;
2199
2200 width = (minimumWidth * 0.75) + 'em';
2201 }
2202
2203 this.$search.css('width', width);
2204 };
2205
2206 return Search;
2207 });
2208
2209 S2.define('select2/selection/eventRelay',[
2210 'jquery'
2211 ], function ($) {
2212 function EventRelay () { }
2213
2214 EventRelay.prototype.bind = function (decorated, container, $container) {
2215 var self = this;
2216 var relayEvents = [
2217 'open', 'opening',
2218 'close', 'closing',
2219 'select', 'selecting',
2220 'unselect', 'unselecting',
2221 'clear', 'clearing'
2222 ];
2223
2224 var preventableEvents = [
2225 'opening', 'closing', 'selecting', 'unselecting', 'clearing'
2226 ];
2227
2228 decorated.call(this, container, $container);
2229
2230 container.on('*', function (name, params) {
2231 // Ignore events that should not be relayed
2232 if ($.inArray(name, relayEvents) === -1) {
2233 return;
2234 }
2235
2236 // The parameters should always be an object
2237 params = params || {};
2238
2239 // Generate the jQuery event for the Select2 event
2240 var evt = $.Event('select2:' + name, {
2241 params: params
2242 });
2243
2244 self.$element.trigger(evt);
2245
2246 // Only handle preventable events if it was one
2247 if ($.inArray(name, preventableEvents) === -1) {
2248 return;
2249 }
2250
2251 params.prevented = evt.isDefaultPrevented();
2252 });
2253 };
2254
2255 return EventRelay;
2256 });
2257
2258 S2.define('select2/translation',[
2259 'jquery',
2260 'require'
2261 ], function ($, require) {
2262 function Translation (dict) {
2263 this.dict = dict || {};
2264 }
2265
2266 Translation.prototype.all = function () {
2267 return this.dict;
2268 };
2269
2270 Translation.prototype.get = function (key) {
2271 return this.dict[key];
2272 };
2273
2274 Translation.prototype.extend = function (translation) {
2275 this.dict = $.extend({}, translation.all(), this.dict);
2276 };
2277
2278 // Static functions
2279
2280 Translation._cache = {};
2281
2282 Translation.loadPath = function (path) {
2283 if (!(path in Translation._cache)) {
2284 var translations = require(path);
2285
2286 Translation._cache[path] = translations;
2287 }
2288
2289 return new Translation(Translation._cache[path]);
2290 };
2291
2292 return Translation;
2293 });
2294
2295 S2.define('select2/diacritics',[
2296
2297 ], function () {
2298 var diacritics = {
2299 '\u24B6': 'A',
2300 '\uFF21': 'A',
2301 '\u00C0': 'A',
2302 '\u00C1': 'A',
2303 '\u00C2': 'A',
2304 '\u1EA6': 'A',
2305 '\u1EA4': 'A',
2306 '\u1EAA': 'A',
2307 '\u1EA8': 'A',
2308 '\u00C3': 'A',
2309 '\u0100': 'A',
2310 '\u0102': 'A',
2311 '\u1EB0': 'A',
2312 '\u1EAE': 'A',
2313 '\u1EB4': 'A',
2314 '\u1EB2': 'A',
2315 '\u0226': 'A',
2316 '\u01E0': 'A',
2317 '\u00C4': 'A',
2318 '\u01DE': 'A',
2319 '\u1EA2': 'A',
2320 '\u00C5': 'A',
2321 '\u01FA': 'A',
2322 '\u01CD': 'A',
2323 '\u0200': 'A',
2324 '\u0202': 'A',
2325 '\u1EA0': 'A',
2326 '\u1EAC': 'A',
2327 '\u1EB6': 'A',
2328 '\u1E00': 'A',
2329 '\u0104': 'A',
2330 '\u023A': 'A',
2331 '\u2C6F': 'A',
2332 '\uA732': 'AA',
2333 '\u00C6': 'AE',
2334 '\u01FC': 'AE',
2335 '\u01E2': 'AE',
2336 '\uA734': 'AO',
2337 '\uA736': 'AU',
2338 '\uA738': 'AV',
2339 '\uA73A': 'AV',
2340 '\uA73C': 'AY',
2341 '\u24B7': 'B',
2342 '\uFF22': 'B',
2343 '\u1E02': 'B',
2344 '\u1E04': 'B',
2345 '\u1E06': 'B',
2346 '\u0243': 'B',
2347 '\u0182': 'B',
2348 '\u0181': 'B',
2349 '\u24B8': 'C',
2350 '\uFF23': 'C',
2351 '\u0106': 'C',
2352 '\u0108': 'C',
2353 '\u010A': 'C',
2354 '\u010C': 'C',
2355 '\u00C7': 'C',
2356 '\u1E08': 'C',
2357 '\u0187': 'C',
2358 '\u023B': 'C',
2359 '\uA73E': 'C',
2360 '\u24B9': 'D',
2361 '\uFF24': 'D',
2362 '\u1E0A': 'D',
2363 '\u010E': 'D',
2364 '\u1E0C': 'D',
2365 '\u1E10': 'D',
2366 '\u1E12': 'D',
2367 '\u1E0E': 'D',
2368 '\u0110': 'D',
2369 '\u018B': 'D',
2370 '\u018A': 'D',
2371 '\u0189': 'D',
2372 '\uA779': 'D',
2373 '\u01F1': 'DZ',
2374 '\u01C4': 'DZ',
2375 '\u01F2': 'Dz',
2376 '\u01C5': 'Dz',
2377 '\u24BA': 'E',
2378 '\uFF25': 'E',
2379 '\u00C8': 'E',
2380 '\u00C9': 'E',
2381 '\u00CA': 'E',
2382 '\u1EC0': 'E',
2383 '\u1EBE': 'E',
2384 '\u1EC4': 'E',
2385 '\u1EC2': 'E',
2386 '\u1EBC': 'E',
2387 '\u0112': 'E',
2388 '\u1E14': 'E',
2389 '\u1E16': 'E',
2390 '\u0114': 'E',
2391 '\u0116': 'E',
2392 '\u00CB': 'E',
2393 '\u1EBA': 'E',
2394 '\u011A': 'E',
2395 '\u0204': 'E',
2396 '\u0206': 'E',
2397 '\u1EB8': 'E',
2398 '\u1EC6': 'E',
2399 '\u0228': 'E',
2400 '\u1E1C': 'E',
2401 '\u0118': 'E',
2402 '\u1E18': 'E',
2403 '\u1E1A': 'E',
2404 '\u0190': 'E',
2405 '\u018E': 'E',
2406 '\u24BB': 'F',
2407 '\uFF26': 'F',
2408 '\u1E1E': 'F',
2409 '\u0191': 'F',
2410 '\uA77B': 'F',
2411 '\u24BC': 'G',
2412 '\uFF27': 'G',
2413 '\u01F4': 'G',
2414 '\u011C': 'G',
2415 '\u1E20': 'G',
2416 '\u011E': 'G',
2417 '\u0120': 'G',
2418 '\u01E6': 'G',
2419 '\u0122': 'G',
2420 '\u01E4': 'G',
2421 '\u0193': 'G',
2422 '\uA7A0': 'G',
2423 '\uA77D': 'G',
2424 '\uA77E': 'G',
2425 '\u24BD': 'H',
2426 '\uFF28': 'H',
2427 '\u0124': 'H',
2428 '\u1E22': 'H',
2429 '\u1E26': 'H',
2430 '\u021E': 'H',
2431 '\u1E24': 'H',
2432 '\u1E28': 'H',
2433 '\u1E2A': 'H',
2434 '\u0126': 'H',
2435 '\u2C67': 'H',
2436 '\u2C75': 'H',
2437 '\uA78D': 'H',
2438 '\u24BE': 'I',
2439 '\uFF29': 'I',
2440 '\u00CC': 'I',
2441 '\u00CD': 'I',
2442 '\u00CE': 'I',
2443 '\u0128': 'I',
2444 '\u012A': 'I',
2445 '\u012C': 'I',
2446 '\u0130': 'I',
2447 '\u00CF': 'I',
2448 '\u1E2E': 'I',
2449 '\u1EC8': 'I',
2450 '\u01CF': 'I',
2451 '\u0208': 'I',
2452 '\u020A': 'I',
2453 '\u1ECA': 'I',
2454 '\u012E': 'I',
2455 '\u1E2C': 'I',
2456 '\u0197': 'I',
2457 '\u24BF': 'J',
2458 '\uFF2A': 'J',
2459 '\u0134': 'J',
2460 '\u0248': 'J',
2461 '\u24C0': 'K',
2462 '\uFF2B': 'K',
2463 '\u1E30': 'K',
2464 '\u01E8': 'K',
2465 '\u1E32': 'K',
2466 '\u0136': 'K',
2467 '\u1E34': 'K',
2468 '\u0198': 'K',
2469 '\u2C69': 'K',
2470 '\uA740': 'K',
2471 '\uA742': 'K',
2472 '\uA744': 'K',
2473 '\uA7A2': 'K',
2474 '\u24C1': 'L',
2475 '\uFF2C': 'L',
2476 '\u013F': 'L',
2477 '\u0139': 'L',
2478 '\u013D': 'L',
2479 '\u1E36': 'L',
2480 '\u1E38': 'L',
2481 '\u013B': 'L',
2482 '\u1E3C': 'L',
2483 '\u1E3A': 'L',
2484 '\u0141': 'L',
2485 '\u023D': 'L',
2486 '\u2C62': 'L',
2487 '\u2C60': 'L',
2488 '\uA748': 'L',
2489 '\uA746': 'L',
2490 '\uA780': 'L',
2491 '\u01C7': 'LJ',
2492 '\u01C8': 'Lj',
2493 '\u24C2': 'M',
2494 '\uFF2D': 'M',
2495 '\u1E3E': 'M',
2496 '\u1E40': 'M',
2497 '\u1E42': 'M',
2498 '\u2C6E': 'M',
2499 '\u019C': 'M',
2500 '\u24C3': 'N',
2501 '\uFF2E': 'N',
2502 '\u01F8': 'N',
2503 '\u0143': 'N',
2504 '\u00D1': 'N',
2505 '\u1E44': 'N',
2506 '\u0147': 'N',
2507 '\u1E46': 'N',
2508 '\u0145': 'N',
2509 '\u1E4A': 'N',
2510 '\u1E48': 'N',
2511 '\u0220': 'N',
2512 '\u019D': 'N',
2513 '\uA790': 'N',
2514 '\uA7A4': 'N',
2515 '\u01CA': 'NJ',
2516 '\u01CB': 'Nj',
2517 '\u24C4': 'O',
2518 '\uFF2F': 'O',
2519 '\u00D2': 'O',
2520 '\u00D3': 'O',
2521 '\u00D4': 'O',
2522 '\u1ED2': 'O',
2523 '\u1ED0': 'O',
2524 '\u1ED6': 'O',
2525 '\u1ED4': 'O',
2526 '\u00D5': 'O',
2527 '\u1E4C': 'O',
2528 '\u022C': 'O',
2529 '\u1E4E': 'O',
2530 '\u014C': 'O',
2531 '\u1E50': 'O',
2532 '\u1E52': 'O',
2533 '\u014E': 'O',
2534 '\u022E': 'O',
2535 '\u0230': 'O',
2536 '\u00D6': 'O',
2537 '\u022A': 'O',
2538 '\u1ECE': 'O',
2539 '\u0150': 'O',
2540 '\u01D1': 'O',
2541 '\u020C': 'O',
2542 '\u020E': 'O',
2543 '\u01A0': 'O',
2544 '\u1EDC': 'O',
2545 '\u1EDA': 'O',
2546 '\u1EE0': 'O',
2547 '\u1EDE': 'O',
2548 '\u1EE2': 'O',
2549 '\u1ECC': 'O',
2550 '\u1ED8': 'O',
2551 '\u01EA': 'O',
2552 '\u01EC': 'O',
2553 '\u00D8': 'O',
2554 '\u01FE': 'O',
2555 '\u0186': 'O',
2556 '\u019F': 'O',
2557 '\uA74A': 'O',
2558 '\uA74C': 'O',
2559 '\u0152': 'OE',
2560 '\u01A2': 'OI',
2561 '\uA74E': 'OO',
2562 '\u0222': 'OU',
2563 '\u24C5': 'P',
2564 '\uFF30': 'P',
2565 '\u1E54': 'P',
2566 '\u1E56': 'P',
2567 '\u01A4': 'P',
2568 '\u2C63': 'P',
2569 '\uA750': 'P',
2570 '\uA752': 'P',
2571 '\uA754': 'P',
2572 '\u24C6': 'Q',
2573 '\uFF31': 'Q',
2574 '\uA756': 'Q',
2575 '\uA758': 'Q',
2576 '\u024A': 'Q',
2577 '\u24C7': 'R',
2578 '\uFF32': 'R',
2579 '\u0154': 'R',
2580 '\u1E58': 'R',
2581 '\u0158': 'R',
2582 '\u0210': 'R',
2583 '\u0212': 'R',
2584 '\u1E5A': 'R',
2585 '\u1E5C': 'R',
2586 '\u0156': 'R',
2587 '\u1E5E': 'R',
2588 '\u024C': 'R',
2589 '\u2C64': 'R',
2590 '\uA75A': 'R',
2591 '\uA7A6': 'R',
2592 '\uA782': 'R',
2593 '\u24C8': 'S',
2594 '\uFF33': 'S',
2595 '\u1E9E': 'S',
2596 '\u015A': 'S',
2597 '\u1E64': 'S',
2598 '\u015C': 'S',
2599 '\u1E60': 'S',
2600 '\u0160': 'S',
2601 '\u1E66': 'S',
2602 '\u1E62': 'S',
2603 '\u1E68': 'S',
2604 '\u0218': 'S',
2605 '\u015E': 'S',
2606 '\u2C7E': 'S',
2607 '\uA7A8': 'S',
2608 '\uA784': 'S',
2609 '\u24C9': 'T',
2610 '\uFF34': 'T',
2611 '\u1E6A': 'T',
2612 '\u0164': 'T',
2613 '\u1E6C': 'T',
2614 '\u021A': 'T',
2615 '\u0162': 'T',
2616 '\u1E70': 'T',
2617 '\u1E6E': 'T',
2618 '\u0166': 'T',
2619 '\u01AC': 'T',
2620 '\u01AE': 'T',
2621 '\u023E': 'T',
2622 '\uA786': 'T',
2623 '\uA728': 'TZ',
2624 '\u24CA': 'U',
2625 '\uFF35': 'U',
2626 '\u00D9': 'U',
2627 '\u00DA': 'U',
2628 '\u00DB': 'U',
2629 '\u0168': 'U',
2630 '\u1E78': 'U',
2631 '\u016A': 'U',
2632 '\u1E7A': 'U',
2633 '\u016C': 'U',
2634 '\u00DC': 'U',
2635 '\u01DB': 'U',
2636 '\u01D7': 'U',
2637 '\u01D5': 'U',
2638 '\u01D9': 'U',
2639 '\u1EE6': 'U',
2640 '\u016E': 'U',
2641 '\u0170': 'U',
2642 '\u01D3': 'U',
2643 '\u0214': 'U',
2644 '\u0216': 'U',
2645 '\u01AF': 'U',
2646 '\u1EEA': 'U',
2647 '\u1EE8': 'U',
2648 '\u1EEE': 'U',
2649 '\u1EEC': 'U',
2650 '\u1EF0': 'U',
2651 '\u1EE4': 'U',
2652 '\u1E72': 'U',
2653 '\u0172': 'U',
2654 '\u1E76': 'U',
2655 '\u1E74': 'U',
2656 '\u0244': 'U',
2657 '\u24CB': 'V',
2658 '\uFF36': 'V',
2659 '\u1E7C': 'V',
2660 '\u1E7E': 'V',
2661 '\u01B2': 'V',
2662 '\uA75E': 'V',
2663 '\u0245': 'V',
2664 '\uA760': 'VY',
2665 '\u24CC': 'W',
2666 '\uFF37': 'W',
2667 '\u1E80': 'W',
2668 '\u1E82': 'W',
2669 '\u0174': 'W',
2670 '\u1E86': 'W',
2671 '\u1E84': 'W',
2672 '\u1E88': 'W',
2673 '\u2C72': 'W',
2674 '\u24CD': 'X',
2675 '\uFF38': 'X',
2676 '\u1E8A': 'X',
2677 '\u1E8C': 'X',
2678 '\u24CE': 'Y',
2679 '\uFF39': 'Y',
2680 '\u1EF2': 'Y',
2681 '\u00DD': 'Y',
2682 '\u0176': 'Y',
2683 '\u1EF8': 'Y',
2684 '\u0232': 'Y',
2685 '\u1E8E': 'Y',
2686 '\u0178': 'Y',
2687 '\u1EF6': 'Y',
2688 '\u1EF4': 'Y',
2689 '\u01B3': 'Y',
2690 '\u024E': 'Y',
2691 '\u1EFE': 'Y',
2692 '\u24CF': 'Z',
2693 '\uFF3A': 'Z',
2694 '\u0179': 'Z',
2695 '\u1E90': 'Z',
2696 '\u017B': 'Z',
2697 '\u017D': 'Z',
2698 '\u1E92': 'Z',
2699 '\u1E94': 'Z',
2700 '\u01B5': 'Z',
2701 '\u0224': 'Z',
2702 '\u2C7F': 'Z',
2703 '\u2C6B': 'Z',
2704 '\uA762': 'Z',
2705 '\u24D0': 'a',
2706 '\uFF41': 'a',
2707 '\u1E9A': 'a',
2708 '\u00E0': 'a',
2709 '\u00E1': 'a',
2710 '\u00E2': 'a',
2711 '\u1EA7': 'a',
2712 '\u1EA5': 'a',
2713 '\u1EAB': 'a',
2714 '\u1EA9': 'a',
2715 '\u00E3': 'a',
2716 '\u0101': 'a',
2717 '\u0103': 'a',
2718 '\u1EB1': 'a',
2719 '\u1EAF': 'a',
2720 '\u1EB5': 'a',
2721 '\u1EB3': 'a',
2722 '\u0227': 'a',
2723 '\u01E1': 'a',
2724 '\u00E4': 'a',
2725 '\u01DF': 'a',
2726 '\u1EA3': 'a',
2727 '\u00E5': 'a',
2728 '\u01FB': 'a',
2729 '\u01CE': 'a',
2730 '\u0201': 'a',
2731 '\u0203': 'a',
2732 '\u1EA1': 'a',
2733 '\u1EAD': 'a',
2734 '\u1EB7': 'a',
2735 '\u1E01': 'a',
2736 '\u0105': 'a',
2737 '\u2C65': 'a',
2738 '\u0250': 'a',
2739 '\uA733': 'aa',
2740 '\u00E6': 'ae',
2741 '\u01FD': 'ae',
2742 '\u01E3': 'ae',
2743 '\uA735': 'ao',
2744 '\uA737': 'au',
2745 '\uA739': 'av',
2746 '\uA73B': 'av',
2747 '\uA73D': 'ay',
2748 '\u24D1': 'b',
2749 '\uFF42': 'b',
2750 '\u1E03': 'b',
2751 '\u1E05': 'b',
2752 '\u1E07': 'b',
2753 '\u0180': 'b',
2754 '\u0183': 'b',
2755 '\u0253': 'b',
2756 '\u24D2': 'c',
2757 '\uFF43': 'c',
2758 '\u0107': 'c',
2759 '\u0109': 'c',
2760 '\u010B': 'c',
2761 '\u010D': 'c',
2762 '\u00E7': 'c',
2763 '\u1E09': 'c',
2764 '\u0188': 'c',
2765 '\u023C': 'c',
2766 '\uA73F': 'c',
2767 '\u2184': 'c',
2768 '\u24D3': 'd',
2769 '\uFF44': 'd',
2770 '\u1E0B': 'd',
2771 '\u010F': 'd',
2772 '\u1E0D': 'd',
2773 '\u1E11': 'd',
2774 '\u1E13': 'd',
2775 '\u1E0F': 'd',
2776 '\u0111': 'd',
2777 '\u018C': 'd',
2778 '\u0256': 'd',
2779 '\u0257': 'd',
2780 '\uA77A': 'd',
2781 '\u01F3': 'dz',
2782 '\u01C6': 'dz',
2783 '\u24D4': 'e',
2784 '\uFF45': 'e',
2785 '\u00E8': 'e',
2786 '\u00E9': 'e',
2787 '\u00EA': 'e',
2788 '\u1EC1': 'e',
2789 '\u1EBF': 'e',
2790 '\u1EC5': 'e',
2791 '\u1EC3': 'e',
2792 '\u1EBD': 'e',
2793 '\u0113': 'e',
2794 '\u1E15': 'e',
2795 '\u1E17': 'e',
2796 '\u0115': 'e',
2797 '\u0117': 'e',
2798 '\u00EB': 'e',
2799 '\u1EBB': 'e',
2800 '\u011B': 'e',
2801 '\u0205': 'e',
2802 '\u0207': 'e',
2803 '\u1EB9': 'e',
2804 '\u1EC7': 'e',
2805 '\u0229': 'e',
2806 '\u1E1D': 'e',
2807 '\u0119': 'e',
2808 '\u1E19': 'e',
2809 '\u1E1B': 'e',
2810 '\u0247': 'e',
2811 '\u025B': 'e',
2812 '\u01DD': 'e',
2813 '\u24D5': 'f',
2814 '\uFF46': 'f',
2815 '\u1E1F': 'f',
2816 '\u0192': 'f',
2817 '\uA77C': 'f',
2818 '\u24D6': 'g',
2819 '\uFF47': 'g',
2820 '\u01F5': 'g',
2821 '\u011D': 'g',
2822 '\u1E21': 'g',
2823 '\u011F': 'g',
2824 '\u0121': 'g',
2825 '\u01E7': 'g',
2826 '\u0123': 'g',
2827 '\u01E5': 'g',
2828 '\u0260': 'g',
2829 '\uA7A1': 'g',
2830 '\u1D79': 'g',
2831 '\uA77F': 'g',
2832 '\u24D7': 'h',
2833 '\uFF48': 'h',
2834 '\u0125': 'h',
2835 '\u1E23': 'h',
2836 '\u1E27': 'h',
2837 '\u021F': 'h',
2838 '\u1E25': 'h',
2839 '\u1E29': 'h',
2840 '\u1E2B': 'h',
2841 '\u1E96': 'h',
2842 '\u0127': 'h',
2843 '\u2C68': 'h',
2844 '\u2C76': 'h',
2845 '\u0265': 'h',
2846 '\u0195': 'hv',
2847 '\u24D8': 'i',
2848 '\uFF49': 'i',
2849 '\u00EC': 'i',
2850 '\u00ED': 'i',
2851 '\u00EE': 'i',
2852 '\u0129': 'i',
2853 '\u012B': 'i',
2854 '\u012D': 'i',
2855 '\u00EF': 'i',
2856 '\u1E2F': 'i',
2857 '\u1EC9': 'i',
2858 '\u01D0': 'i',
2859 '\u0209': 'i',
2860 '\u020B': 'i',
2861 '\u1ECB': 'i',
2862 '\u012F': 'i',
2863 '\u1E2D': 'i',
2864 '\u0268': 'i',
2865 '\u0131': 'i',
2866 '\u24D9': 'j',
2867 '\uFF4A': 'j',
2868 '\u0135': 'j',
2869 '\u01F0': 'j',
2870 '\u0249': 'j',
2871 '\u24DA': 'k',
2872 '\uFF4B': 'k',
2873 '\u1E31': 'k',
2874 '\u01E9': 'k',
2875 '\u1E33': 'k',
2876 '\u0137': 'k',
2877 '\u1E35': 'k',
2878 '\u0199': 'k',
2879 '\u2C6A': 'k',
2880 '\uA741': 'k',
2881 '\uA743': 'k',
2882 '\uA745': 'k',
2883 '\uA7A3': 'k',
2884 '\u24DB': 'l',
2885 '\uFF4C': 'l',
2886 '\u0140': 'l',
2887 '\u013A': 'l',
2888 '\u013E': 'l',
2889 '\u1E37': 'l',
2890 '\u1E39': 'l',
2891 '\u013C': 'l',
2892 '\u1E3D': 'l',
2893 '\u1E3B': 'l',
2894 '\u017F': 'l',
2895 '\u0142': 'l',
2896 '\u019A': 'l',
2897 '\u026B': 'l',
2898 '\u2C61': 'l',
2899 '\uA749': 'l',
2900 '\uA781': 'l',
2901 '\uA747': 'l',
2902 '\u01C9': 'lj',
2903 '\u24DC': 'm',
2904 '\uFF4D': 'm',
2905 '\u1E3F': 'm',
2906 '\u1E41': 'm',
2907 '\u1E43': 'm',
2908 '\u0271': 'm',
2909 '\u026F': 'm',
2910 '\u24DD': 'n',
2911 '\uFF4E': 'n',
2912 '\u01F9': 'n',
2913 '\u0144': 'n',
2914 '\u00F1': 'n',
2915 '\u1E45': 'n',
2916 '\u0148': 'n',
2917 '\u1E47': 'n',
2918 '\u0146': 'n',
2919 '\u1E4B': 'n',
2920 '\u1E49': 'n',
2921 '\u019E': 'n',
2922 '\u0272': 'n',
2923 '\u0149': 'n',
2924 '\uA791': 'n',
2925 '\uA7A5': 'n',
2926 '\u01CC': 'nj',
2927 '\u24DE': 'o',
2928 '\uFF4F': 'o',
2929 '\u00F2': 'o',
2930 '\u00F3': 'o',
2931 '\u00F4': 'o',
2932 '\u1ED3': 'o',
2933 '\u1ED1': 'o',
2934 '\u1ED7': 'o',
2935 '\u1ED5': 'o',
2936 '\u00F5': 'o',
2937 '\u1E4D': 'o',
2938 '\u022D': 'o',
2939 '\u1E4F': 'o',
2940 '\u014D': 'o',
2941 '\u1E51': 'o',
2942 '\u1E53': 'o',
2943 '\u014F': 'o',
2944 '\u022F': 'o',
2945 '\u0231': 'o',
2946 '\u00F6': 'o',
2947 '\u022B': 'o',
2948 '\u1ECF': 'o',
2949 '\u0151': 'o',
2950 '\u01D2': 'o',
2951 '\u020D': 'o',
2952 '\u020F': 'o',
2953 '\u01A1': 'o',
2954 '\u1EDD': 'o',
2955 '\u1EDB': 'o',
2956 '\u1EE1': 'o',
2957 '\u1EDF': 'o',
2958 '\u1EE3': 'o',
2959 '\u1ECD': 'o',
2960 '\u1ED9': 'o',
2961 '\u01EB': 'o',
2962 '\u01ED': 'o',
2963 '\u00F8': 'o',
2964 '\u01FF': 'o',
2965 '\u0254': 'o',
2966 '\uA74B': 'o',
2967 '\uA74D': 'o',
2968 '\u0275': 'o',
2969 '\u0153': 'oe',
2970 '\u01A3': 'oi',
2971 '\u0223': 'ou',
2972 '\uA74F': 'oo',
2973 '\u24DF': 'p',
2974 '\uFF50': 'p',
2975 '\u1E55': 'p',
2976 '\u1E57': 'p',
2977 '\u01A5': 'p',
2978 '\u1D7D': 'p',
2979 '\uA751': 'p',
2980 '\uA753': 'p',
2981 '\uA755': 'p',
2982 '\u24E0': 'q',
2983 '\uFF51': 'q',
2984 '\u024B': 'q',
2985 '\uA757': 'q',
2986 '\uA759': 'q',
2987 '\u24E1': 'r',
2988 '\uFF52': 'r',
2989 '\u0155': 'r',
2990 '\u1E59': 'r',
2991 '\u0159': 'r',
2992 '\u0211': 'r',
2993 '\u0213': 'r',
2994 '\u1E5B': 'r',
2995 '\u1E5D': 'r',
2996 '\u0157': 'r',
2997 '\u1E5F': 'r',
2998 '\u024D': 'r',
2999 '\u027D': 'r',
3000 '\uA75B': 'r',
3001 '\uA7A7': 'r',
3002 '\uA783': 'r',
3003 '\u24E2': 's',
3004 '\uFF53': 's',
3005 '\u00DF': 's',
3006 '\u015B': 's',
3007 '\u1E65': 's',
3008 '\u015D': 's',
3009 '\u1E61': 's',
3010 '\u0161': 's',
3011 '\u1E67': 's',
3012 '\u1E63': 's',
3013 '\u1E69': 's',
3014 '\u0219': 's',
3015 '\u015F': 's',
3016 '\u023F': 's',
3017 '\uA7A9': 's',
3018 '\uA785': 's',
3019 '\u1E9B': 's',
3020 '\u24E3': 't',
3021 '\uFF54': 't',
3022 '\u1E6B': 't',
3023 '\u1E97': 't',
3024 '\u0165': 't',
3025 '\u1E6D': 't',
3026 '\u021B': 't',
3027 '\u0163': 't',
3028 '\u1E71': 't',
3029 '\u1E6F': 't',
3030 '\u0167': 't',
3031 '\u01AD': 't',
3032 '\u0288': 't',
3033 '\u2C66': 't',
3034 '\uA787': 't',
3035 '\uA729': 'tz',
3036 '\u24E4': 'u',
3037 '\uFF55': 'u',
3038 '\u00F9': 'u',
3039 '\u00FA': 'u',
3040 '\u00FB': 'u',
3041 '\u0169': 'u',
3042 '\u1E79': 'u',
3043 '\u016B': 'u',
3044 '\u1E7B': 'u',
3045 '\u016D': 'u',
3046 '\u00FC': 'u',
3047 '\u01DC': 'u',
3048 '\u01D8': 'u',
3049 '\u01D6': 'u',
3050 '\u01DA': 'u',
3051 '\u1EE7': 'u',
3052 '\u016F': 'u',
3053 '\u0171': 'u',
3054 '\u01D4': 'u',
3055 '\u0215': 'u',
3056 '\u0217': 'u',
3057 '\u01B0': 'u',
3058 '\u1EEB': 'u',
3059 '\u1EE9': 'u',
3060 '\u1EEF': 'u',
3061 '\u1EED': 'u',
3062 '\u1EF1': 'u',
3063 '\u1EE5': 'u',
3064 '\u1E73': 'u',
3065 '\u0173': 'u',
3066 '\u1E77': 'u',
3067 '\u1E75': 'u',
3068 '\u0289': 'u',
3069 '\u24E5': 'v',
3070 '\uFF56': 'v',
3071 '\u1E7D': 'v',
3072 '\u1E7F': 'v',
3073 '\u028B': 'v',
3074 '\uA75F': 'v',
3075 '\u028C': 'v',
3076 '\uA761': 'vy',
3077 '\u24E6': 'w',
3078 '\uFF57': 'w',
3079 '\u1E81': 'w',
3080 '\u1E83': 'w',
3081 '\u0175': 'w',
3082 '\u1E87': 'w',
3083 '\u1E85': 'w',
3084 '\u1E98': 'w',
3085 '\u1E89': 'w',
3086 '\u2C73': 'w',
3087 '\u24E7': 'x',
3088 '\uFF58': 'x',
3089 '\u1E8B': 'x',
3090 '\u1E8D': 'x',
3091 '\u24E8': 'y',
3092 '\uFF59': 'y',
3093 '\u1EF3': 'y',
3094 '\u00FD': 'y',
3095 '\u0177': 'y',
3096 '\u1EF9': 'y',
3097 '\u0233': 'y',
3098 '\u1E8F': 'y',
3099 '\u00FF': 'y',
3100 '\u1EF7': 'y',
3101 '\u1E99': 'y',
3102 '\u1EF5': 'y',
3103 '\u01B4': 'y',
3104 '\u024F': 'y',
3105 '\u1EFF': 'y',
3106 '\u24E9': 'z',
3107 '\uFF5A': 'z',
3108 '\u017A': 'z',
3109 '\u1E91': 'z',
3110 '\u017C': 'z',
3111 '\u017E': 'z',
3112 '\u1E93': 'z',
3113 '\u1E95': 'z',
3114 '\u01B6': 'z',
3115 '\u0225': 'z',
3116 '\u0240': 'z',
3117 '\u2C6C': 'z',
3118 '\uA763': 'z',
3119 '\u0386': '\u0391',
3120 '\u0388': '\u0395',
3121 '\u0389': '\u0397',
3122 '\u038A': '\u0399',
3123 '\u03AA': '\u0399',
3124 '\u038C': '\u039F',
3125 '\u038E': '\u03A5',
3126 '\u03AB': '\u03A5',
3127 '\u038F': '\u03A9',
3128 '\u03AC': '\u03B1',
3129 '\u03AD': '\u03B5',
3130 '\u03AE': '\u03B7',
3131 '\u03AF': '\u03B9',
3132 '\u03CA': '\u03B9',
3133 '\u0390': '\u03B9',
3134 '\u03CC': '\u03BF',
3135 '\u03CD': '\u03C5',
3136 '\u03CB': '\u03C5',
3137 '\u03B0': '\u03C5',
3138 '\u03CE': '\u03C9',
3139 '\u03C2': '\u03C3',
3140 '\u2019': '\''
3141 };
3142
3143 return diacritics;
3144 });
3145
3146 S2.define('select2/data/base',[
3147 '../utils'
3148 ], function (Utils) {
3149 function BaseAdapter ($element, options) {
3150 BaseAdapter.__super__.constructor.call(this);
3151 }
3152
3153 Utils.Extend(BaseAdapter, Utils.Observable);
3154
3155 BaseAdapter.prototype.current = function (callback) {
3156 throw new Error('The `current` method must be defined in child classes.');
3157 };
3158
3159 BaseAdapter.prototype.query = function (params, callback) {
3160 throw new Error('The `query` method must be defined in child classes.');
3161 };
3162
3163 BaseAdapter.prototype.bind = function (container, $container) {
3164 // Can be implemented in subclasses
3165 };
3166
3167 BaseAdapter.prototype.destroy = function () {
3168 // Can be implemented in subclasses
3169 };
3170
3171 BaseAdapter.prototype.generateResultId = function (container, data) {
3172 var id = container.id + '-result-';
3173
3174 id += Utils.generateChars(4);
3175
3176 if (data.id != null) {
3177 id += '-' + data.id.toString();
3178 } else {
3179 id += '-' + Utils.generateChars(4);
3180 }
3181 return id;
3182 };
3183
3184 return BaseAdapter;
3185 });
3186
3187 S2.define('select2/data/select',[
3188 './base',
3189 '../utils',
3190 'jquery'
3191 ], function (BaseAdapter, Utils, $) {
3192 function SelectAdapter ($element, options) {
3193 this.$element = $element;
3194 this.options = options;
3195
3196 SelectAdapter.__super__.constructor.call(this);
3197 }
3198
3199 Utils.Extend(SelectAdapter, BaseAdapter);
3200
3201 SelectAdapter.prototype.current = function (callback) {
3202 var data = [];
3203 var self = this;
3204
3205 this.$element.find(':selected').each(function () {
3206 var $option = $(this);
3207
3208 var option = self.item($option);
3209
3210 data.push(option);
3211 });
3212
3213 callback(data);
3214 };
3215
3216 SelectAdapter.prototype.select = function (data) {
3217 var self = this;
3218
3219 data.selected = true;
3220
3221 // If data.element is a DOM node, use it instead
3222 if ($(data.element).is('option')) {
3223 data.element.selected = true;
3224
3225 this.$element.trigger('input').trigger('change');
3226
3227 return;
3228 }
3229
3230 if (this.$element.prop('multiple')) {
3231 this.current(function (currentData) {
3232 var val = [];
3233
3234 data = [data];
3235 data.push.apply(data, currentData);
3236
3237 for (var d = 0; d < data.length; d++) {
3238 var id = data[d].id;
3239
3240 if ($.inArray(id, val) === -1) {
3241 val.push(id);
3242 }
3243 }
3244
3245 self.$element.val(val);
3246 self.$element.trigger('input').trigger('change');
3247 });
3248 } else {
3249 var val = data.id;
3250
3251 this.$element.val(val);
3252 this.$element.trigger('input').trigger('change');
3253 }
3254 };
3255
3256 SelectAdapter.prototype.unselect = function (data) {
3257 var self = this;
3258
3259 if (!this.$element.prop('multiple')) {
3260 return;
3261 }
3262
3263 data.selected = false;
3264
3265 if ($(data.element).is('option')) {
3266 data.element.selected = false;
3267
3268 this.$element.trigger('input').trigger('change');
3269
3270 return;
3271 }
3272
3273 this.current(function (currentData) {
3274 var val = [];
3275
3276 for (var d = 0; d < currentData.length; d++) {
3277 var id = currentData[d].id;
3278
3279 if (id !== data.id && $.inArray(id, val) === -1) {
3280 val.push(id);
3281 }
3282 }
3283
3284 self.$element.val(val);
3285
3286 self.$element.trigger('input').trigger('change');
3287 });
3288 };
3289
3290 SelectAdapter.prototype.bind = function (container, $container) {
3291 var self = this;
3292
3293 this.container = container;
3294
3295 container.on('select', function (params) {
3296 self.select(params.data);
3297 });
3298
3299 container.on('unselect', function (params) {
3300 self.unselect(params.data);
3301 });
3302 };
3303
3304 SelectAdapter.prototype.destroy = function () {
3305 // Remove anything added to child elements
3306 this.$element.find('*').each(function () {
3307 // Remove any custom data set by Select2
3308 Utils.RemoveData(this);
3309 });
3310 };
3311
3312 SelectAdapter.prototype.query = function (params, callback) {
3313 var data = [];
3314 var self = this;
3315
3316 var $options = this.$element.children();
3317
3318 $options.each(function () {
3319 var $option = $(this);
3320
3321 if (!$option.is('option') && !$option.is('optgroup')) {
3322 return;
3323 }
3324
3325 var option = self.item($option);
3326
3327 var matches = self.matches(params, option);
3328
3329 if (matches !== null) {
3330 data.push(matches);
3331 }
3332 });
3333
3334 callback({
3335 results: data
3336 });
3337 };
3338
3339 SelectAdapter.prototype.addOptions = function ($options) {
3340 Utils.appendMany(this.$element, $options);
3341 };
3342
3343 SelectAdapter.prototype.option = function (data) {
3344 var option;
3345
3346 if (data.children) {
3347 option = document.createElement('optgroup');
3348 option.label = data.text;
3349 } else {
3350 option = document.createElement('option');
3351
3352 if (option.textContent !== undefined) {
3353 option.textContent = data.text;
3354 } else {
3355 option.innerText = data.text;
3356 }
3357 }
3358
3359 if (data.id !== undefined) {
3360 option.value = data.id;
3361 }
3362
3363 if (data.disabled) {
3364 option.disabled = true;
3365 }
3366
3367 if (data.selected) {
3368 option.selected = true;
3369 }
3370
3371 if (data.title) {
3372 option.title = data.title;
3373 }
3374
3375 var $option = $(option);
3376
3377 var normalizedData = this._normalizeItem(data);
3378 normalizedData.element = option;
3379
3380 // Override the option's data with the combined data
3381 Utils.StoreData(option, 'data', normalizedData);
3382
3383 return $option;
3384 };
3385
3386 SelectAdapter.prototype.item = function ($option) {
3387 var data = {};
3388
3389 data = Utils.GetData($option[0], 'data');
3390
3391 if (data != null) {
3392 return data;
3393 }
3394
3395 if ($option.is('option')) {
3396 data = {
3397 id: $option.val(),
3398 text: $option.text(),
3399 disabled: $option.prop('disabled'),
3400 selected: $option.prop('selected'),
3401 title: $option.prop('title')
3402 };
3403 } else if ($option.is('optgroup')) {
3404 data = {
3405 text: $option.prop('label'),
3406 children: [],
3407 title: $option.prop('title')
3408 };
3409
3410 var $children = $option.children('option');
3411 var children = [];
3412
3413 for (var c = 0; c < $children.length; c++) {
3414 var $child = $($children[c]);
3415
3416 var child = this.item($child);
3417
3418 children.push(child);
3419 }
3420
3421 data.children = children;
3422 }
3423
3424 data = this._normalizeItem(data);
3425 data.element = $option[0];
3426
3427 Utils.StoreData($option[0], 'data', data);
3428
3429 return data;
3430 };
3431
3432 SelectAdapter.prototype._normalizeItem = function (item) {
3433 if (item !== Object(item)) {
3434 item = {
3435 id: item,
3436 text: item
3437 };
3438 }
3439
3440 item = $.extend({}, {
3441 text: ''
3442 }, item);
3443
3444 var defaults = {
3445 selected: false,
3446 disabled: false
3447 };
3448
3449 if (item.id != null) {
3450 item.id = item.id.toString();
3451 }
3452
3453 if (item.text != null) {
3454 item.text = item.text.toString();
3455 }
3456
3457 if (item._resultId == null && item.id && this.container != null) {
3458 item._resultId = this.generateResultId(this.container, item);
3459 }
3460
3461 return $.extend({}, defaults, item);
3462 };
3463
3464 SelectAdapter.prototype.matches = function (params, data) {
3465 var matcher = this.options.get('matcher');
3466
3467 return matcher(params, data);
3468 };
3469
3470 return SelectAdapter;
3471 });
3472
3473 S2.define('select2/data/array',[
3474 './select',
3475 '../utils',
3476 'jquery'
3477 ], function (SelectAdapter, Utils, $) {
3478 function ArrayAdapter ($element, options) {
3479 this._dataToConvert = options.get('data') || [];
3480
3481 ArrayAdapter.__super__.constructor.call(this, $element, options);
3482 }
3483
3484 Utils.Extend(ArrayAdapter, SelectAdapter);
3485
3486 ArrayAdapter.prototype.bind = function (container, $container) {
3487 ArrayAdapter.__super__.bind.call(this, container, $container);
3488
3489 this.addOptions(this.convertToOptions(this._dataToConvert));
3490 };
3491
3492 ArrayAdapter.prototype.select = function (data) {
3493 var $option = this.$element.find('option').filter(function (i, elm) {
3494 return elm.value == data.id.toString();
3495 });
3496
3497 if ($option.length === 0) {
3498 $option = this.option(data);
3499
3500 this.addOptions($option);
3501 }
3502
3503 ArrayAdapter.__super__.select.call(this, data);
3504 };
3505
3506 ArrayAdapter.prototype.convertToOptions = function (data) {
3507 var self = this;
3508
3509 var $existing = this.$element.find('option');
3510 var existingIds = $existing.map(function () {
3511 return self.item($(this)).id;
3512 }).get();
3513
3514 var $options = [];
3515
3516 // Filter out all items except for the one passed in the argument
3517 function onlyItem (item) {
3518 return function () {
3519 return $(this).val() == item.id;
3520 };
3521 }
3522
3523 for (var d = 0; d < data.length; d++) {
3524 var item = this._normalizeItem(data[d]);
3525
3526 // Skip items which were pre-loaded, only merge the data
3527 if ($.inArray(item.id, existingIds) >= 0) {
3528 var $existingOption = $existing.filter(onlyItem(item));
3529
3530 var existingData = this.item($existingOption);
3531 var newData = $.extend(true, {}, item, existingData);
3532
3533 var $newOption = this.option(newData);
3534
3535 $existingOption.replaceWith($newOption);
3536
3537 continue;
3538 }
3539
3540 var $option = this.option(item);
3541
3542 if (item.children) {
3543 var $children = this.convertToOptions(item.children);
3544
3545 Utils.appendMany($option, $children);
3546 }
3547
3548 $options.push($option);
3549 }
3550
3551 return $options;
3552 };
3553
3554 return ArrayAdapter;
3555 });
3556
3557 S2.define('select2/data/ajax',[
3558 './array',
3559 '../utils',
3560 'jquery'
3561 ], function (ArrayAdapter, Utils, $) {
3562 function AjaxAdapter ($element, options) {
3563 this.ajaxOptions = this._applyDefaults(options.get('ajax'));
3564
3565 if (this.ajaxOptions.processResults != null) {
3566 this.processResults = this.ajaxOptions.processResults;
3567 }
3568
3569 AjaxAdapter.__super__.constructor.call(this, $element, options);
3570 }
3571
3572 Utils.Extend(AjaxAdapter, ArrayAdapter);
3573
3574 AjaxAdapter.prototype._applyDefaults = function (options) {
3575 var defaults = {
3576 data: function (params) {
3577 return $.extend({}, params, {
3578 q: params.term
3579 });
3580 },
3581 transport: function (params, success, failure) {
3582 var $request = $.ajax(params);
3583
3584 $request.then(success);
3585 $request.fail(failure);
3586
3587 return $request;
3588 }
3589 };
3590
3591 return $.extend({}, defaults, options, true);
3592 };
3593
3594 AjaxAdapter.prototype.processResults = function (results) {
3595 return results;
3596 };
3597
3598 AjaxAdapter.prototype.query = function (params, callback) {
3599 var matches = [];
3600 var self = this;
3601
3602 if (this._request != null) {
3603 // JSONP requests cannot always be aborted
3604 if ($.isFunction(this._request.abort)) {
3605 this._request.abort();
3606 }
3607
3608 this._request = null;
3609 }
3610
3611 var options = $.extend({
3612 type: 'GET'
3613 }, this.ajaxOptions);
3614
3615 if (typeof options.url === 'function') {
3616 options.url = options.url.call(this.$element, params);
3617 }
3618
3619 if (typeof options.data === 'function') {
3620 options.data = options.data.call(this.$element, params);
3621 }
3622
3623 function request () {
3624 var $request = options.transport(options, function (data) {
3625 var results = self.processResults(data, params);
3626
3627 if (self.options.get('debug') && window.console && console.error) {
3628 // Check to make sure that the response included a `results` key.
3629 if (!results || !results.results || !$.isArray(results.results)) {
3630 console.error(
3631 'Select2: The AJAX results did not return an array in the ' +
3632 '`results` key of the response.'
3633 );
3634 }
3635 }
3636
3637 callback(results);
3638 }, function () {
3639 // Attempt to detect if a request was aborted
3640 // Only works if the transport exposes a status property
3641 if ('status' in $request &&
3642 ($request.status === 0 || $request.status === '0')) {
3643 return;
3644 }
3645
3646 self.trigger('results:message', {
3647 message: 'errorLoading'
3648 });
3649 });
3650
3651 self._request = $request;
3652 }
3653
3654 if (this.ajaxOptions.delay && params.term != null) {
3655 if (this._queryTimeout) {
3656 window.clearTimeout(this._queryTimeout);
3657 }
3658
3659 this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
3660 } else {
3661 request();
3662 }
3663 };
3664
3665 return AjaxAdapter;
3666 });
3667
3668 S2.define('select2/data/tags',[
3669 'jquery'
3670 ], function ($) {
3671 function Tags (decorated, $element, options) {
3672 var tags = options.get('tags');
3673
3674 var createTag = options.get('createTag');
3675
3676 if (createTag !== undefined) {
3677 this.createTag = createTag;
3678 }
3679
3680 var insertTag = options.get('insertTag');
3681
3682 if (insertTag !== undefined) {
3683 this.insertTag = insertTag;
3684 }
3685
3686 decorated.call(this, $element, options);
3687
3688 if ($.isArray(tags)) {
3689 for (var t = 0; t < tags.length; t++) {
3690 var tag = tags[t];
3691 var item = this._normalizeItem(tag);
3692
3693 var $option = this.option(item);
3694
3695 this.$element.append($option);
3696 }
3697 }
3698 }
3699
3700 Tags.prototype.query = function (decorated, params, callback) {
3701 var self = this;
3702
3703 this._removeOldTags();
3704
3705 if (params.term == null || params.page != null) {
3706 decorated.call(this, params, callback);
3707 return;
3708 }
3709
3710 function wrapper (obj, child) {
3711 var data = obj.results;
3712
3713 for (var i = 0; i < data.length; i++) {
3714 var option = data[i];
3715
3716 var checkChildren = (
3717 option.children != null &&
3718 !wrapper({
3719 results: option.children
3720 }, true)
3721 );
3722
3723 var optionText = (option.text || '').toUpperCase();
3724 var paramsTerm = (params.term || '').toUpperCase();
3725
3726 var checkText = optionText === paramsTerm;
3727
3728 if (checkText || checkChildren) {
3729 if (child) {
3730 return false;
3731 }
3732
3733 obj.data = data;
3734 callback(obj);
3735
3736 return;
3737 }
3738 }
3739
3740 if (child) {
3741 return true;
3742 }
3743
3744 var tag = self.createTag(params);
3745
3746 if (tag != null) {
3747 var $option = self.option(tag);
3748 $option.attr('data-select2-tag', true);
3749
3750 self.addOptions([$option]);
3751
3752 self.insertTag(data, tag);
3753 }
3754
3755 obj.results = data;
3756
3757 callback(obj);
3758 }
3759
3760 decorated.call(this, params, wrapper);
3761 };
3762
3763 Tags.prototype.createTag = function (decorated, params) {
3764 var term = $.trim(params.term);
3765
3766 if (term === '') {
3767 return null;
3768 }
3769
3770 return {
3771 id: term,
3772 text: term
3773 };
3774 };
3775
3776 Tags.prototype.insertTag = function (_, data, tag) {
3777 data.unshift(tag);
3778 };
3779
3780 Tags.prototype._removeOldTags = function (_) {
3781 var $options = this.$element.find('option[data-select2-tag]');
3782
3783 $options.each(function () {
3784 if (this.selected) {
3785 return;
3786 }
3787
3788 $(this).remove();
3789 });
3790 };
3791
3792 return Tags;
3793 });
3794
3795 S2.define('select2/data/tokenizer',[
3796 'jquery'
3797 ], function ($) {
3798 function Tokenizer (decorated, $element, options) {
3799 var tokenizer = options.get('tokenizer');
3800
3801 if (tokenizer !== undefined) {
3802 this.tokenizer = tokenizer;
3803 }
3804
3805 decorated.call(this, $element, options);
3806 }
3807
3808 Tokenizer.prototype.bind = function (decorated, container, $container) {
3809 decorated.call(this, container, $container);
3810
3811 this.$search = container.dropdown.$search || container.selection.$search ||
3812 $container.find('.select2-search__field');
3813 };
3814
3815 Tokenizer.prototype.query = function (decorated, params, callback) {
3816 var self = this;
3817
3818 function createAndSelect (data) {
3819 // Normalize the data object so we can use it for checks
3820 var item = self._normalizeItem(data);
3821
3822 // Check if the data object already exists as a tag
3823 // Select it if it doesn't
3824 var $existingOptions = self.$element.find('option').filter(function () {
3825 return $(this).val() === item.id;
3826 });
3827
3828 // If an existing option wasn't found for it, create the option
3829 if (!$existingOptions.length) {
3830 var $option = self.option(item);
3831 $option.attr('data-select2-tag', true);
3832
3833 self._removeOldTags();
3834 self.addOptions([$option]);
3835 }
3836
3837 // Select the item, now that we know there is an option for it
3838 select(item);
3839 }
3840
3841 function select (data) {
3842 self.trigger('select', {
3843 data: data
3844 });
3845 }
3846
3847 params.term = params.term || '';
3848
3849 var tokenData = this.tokenizer(params, this.options, createAndSelect);
3850
3851 if (tokenData.term !== params.term) {
3852 // Replace the search term if we have the search box
3853 if (this.$search.length) {
3854 this.$search.val(tokenData.term);
3855 this.$search.trigger('focus');
3856 }
3857
3858 params.term = tokenData.term;
3859 }
3860
3861 decorated.call(this, params, callback);
3862 };
3863
3864 Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
3865 var separators = options.get('tokenSeparators') || [];
3866 var term = params.term;
3867 var i = 0;
3868
3869 var createTag = this.createTag || function (params) {
3870 return {
3871 id: params.term,
3872 text: params.term
3873 };
3874 };
3875
3876 while (i < term.length) {
3877 var termChar = term[i];
3878
3879 if ($.inArray(termChar, separators) === -1) {
3880 i++;
3881
3882 continue;
3883 }
3884
3885 var part = term.substr(0, i);
3886 var partParams = $.extend({}, params, {
3887 term: part
3888 });
3889
3890 var data = createTag(partParams);
3891
3892 if (data == null) {
3893 i++;
3894 continue;
3895 }
3896
3897 callback(data);
3898
3899 // Reset the term to not include the tokenized portion
3900 term = term.substr(i + 1) || '';
3901 i = 0;
3902 }
3903
3904 return {
3905 term: term
3906 };
3907 };
3908
3909 return Tokenizer;
3910 });
3911
3912 S2.define('select2/data/minimumInputLength',[
3913
3914 ], function () {
3915 function MinimumInputLength (decorated, $e, options) {
3916 this.minimumInputLength = options.get('minimumInputLength');
3917
3918 decorated.call(this, $e, options);
3919 }
3920
3921 MinimumInputLength.prototype.query = function (decorated, params, callback) {
3922 params.term = params.term || '';
3923
3924 if (params.term.length < this.minimumInputLength) {
3925 this.trigger('results:message', {
3926 message: 'inputTooShort',
3927 args: {
3928 minimum: this.minimumInputLength,
3929 input: params.term,
3930 params: params
3931 }
3932 });
3933
3934 return;
3935 }
3936
3937 decorated.call(this, params, callback);
3938 };
3939
3940 return MinimumInputLength;
3941 });
3942
3943 S2.define('select2/data/maximumInputLength',[
3944
3945 ], function () {
3946 function MaximumInputLength (decorated, $e, options) {
3947 this.maximumInputLength = options.get('maximumInputLength');
3948
3949 decorated.call(this, $e, options);
3950 }
3951
3952 MaximumInputLength.prototype.query = function (decorated, params, callback) {
3953 params.term = params.term || '';
3954
3955 if (this.maximumInputLength > 0 &&
3956 params.term.length > this.maximumInputLength) {
3957 this.trigger('results:message', {
3958 message: 'inputTooLong',
3959 args: {
3960 maximum: this.maximumInputLength,
3961 input: params.term,
3962 params: params
3963 }
3964 });
3965
3966 return;
3967 }
3968
3969 decorated.call(this, params, callback);
3970 };
3971
3972 return MaximumInputLength;
3973 });
3974
3975 S2.define('select2/data/maximumSelectionLength',[
3976
3977 ], function (){
3978 function MaximumSelectionLength (decorated, $e, options) {
3979 this.maximumSelectionLength = options.get('maximumSelectionLength');
3980
3981 decorated.call(this, $e, options);
3982 }
3983
3984 MaximumSelectionLength.prototype.bind =
3985 function (decorated, container, $container) {
3986 var self = this;
3987
3988 decorated.call(this, container, $container);
3989
3990 container.on('select', function () {
3991 self._checkIfMaximumSelected();
3992 });
3993 };
3994
3995 MaximumSelectionLength.prototype.query =
3996 function (decorated, params, callback) {
3997 var self = this;
3998
3999 this._checkIfMaximumSelected(function () {
4000 decorated.call(self, params, callback);
4001 });
4002 };
4003
4004 MaximumSelectionLength.prototype._checkIfMaximumSelected =
4005 function (_, successCallback) {
4006 var self = this;
4007
4008 this.current(function (currentData) {
4009 var count = currentData != null ? currentData.length : 0;
4010 if (self.maximumSelectionLength > 0 &&
4011 count >= self.maximumSelectionLength) {
4012 self.trigger('results:message', {
4013 message: 'maximumSelected',
4014 args: {
4015 maximum: self.maximumSelectionLength
4016 }
4017 });
4018 return;
4019 }
4020
4021 if (successCallback) {
4022 successCallback();
4023 }
4024 });
4025 };
4026
4027 return MaximumSelectionLength;
4028 });
4029
4030 S2.define('select2/dropdown',[
4031 'jquery',
4032 './utils'
4033 ], function ($, Utils) {
4034 function Dropdown ($element, options) {
4035 this.$element = $element;
4036 this.options = options;
4037
4038 Dropdown.__super__.constructor.call(this);
4039 }
4040
4041 Utils.Extend(Dropdown, Utils.Observable);
4042
4043 Dropdown.prototype.render = function () {
4044 var $dropdown = $(
4045 '<span class="select2-dropdown">' +
4046 '<span class="select2-results"></span>' +
4047 '</span>'
4048 );
4049
4050 $dropdown.attr('dir', this.options.get('dir'));
4051
4052 this.$dropdown = $dropdown;
4053
4054 return $dropdown;
4055 };
4056
4057 Dropdown.prototype.bind = function () {
4058 // Should be implemented in subclasses
4059 };
4060
4061 Dropdown.prototype.position = function ($dropdown, $container) {
4062 // Should be implemented in subclasses
4063 };
4064
4065 Dropdown.prototype.destroy = function () {
4066 // Remove the dropdown from the DOM
4067 this.$dropdown.remove();
4068 };
4069
4070 return Dropdown;
4071 });
4072
4073 S2.define('select2/dropdown/search',[
4074 'jquery',
4075 '../utils'
4076 ], function ($, Utils) {
4077 function Search () { }
4078
4079 Search.prototype.render = function (decorated) {
4080 var $rendered = decorated.call(this);
4081
4082 var $search = $(
4083 '<span class="select2-search select2-search--dropdown">' +
4084 '<input class="select2-search__field" type="search" tabindex="-1"' +
4085 ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
4086 ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
4087 '</span>'
4088 );
4089
4090 this.$searchContainer = $search;
4091 this.$search = $search.find('input');
4092
4093 $rendered.prepend($search);
4094
4095 return $rendered;
4096 };
4097
4098 Search.prototype.bind = function (decorated, container, $container) {
4099 var self = this;
4100
4101 var resultsId = container.id + '-results';
4102
4103 decorated.call(this, container, $container);
4104
4105 this.$search.on('keydown', function (evt) {
4106 self.trigger('keypress', evt);
4107
4108 self._keyUpPrevented = evt.isDefaultPrevented();
4109 });
4110
4111 // Workaround for browsers which do not support the `input` event
4112 // This will prevent double-triggering of events for browsers which support
4113 // both the `keyup` and `input` events.
4114 this.$search.on('input', function (evt) {
4115 // Unbind the duplicated `keyup` event
4116 $(this).off('keyup');
4117 });
4118
4119 this.$search.on('keyup input', function (evt) {
4120 self.handleSearch(evt);
4121 });
4122
4123 container.on('open', function () {
4124 self.$search.attr('tabindex', 0);
4125 self.$search.attr('aria-controls', resultsId);
4126
4127 self.$search.trigger('focus');
4128
4129 window.setTimeout(function () {
4130 self.$search.trigger('focus');
4131 }, 0);
4132 });
4133
4134 container.on('close', function () {
4135 self.$search.attr('tabindex', -1);
4136 self.$search.removeAttr('aria-controls');
4137 self.$search.removeAttr('aria-activedescendant');
4138
4139 self.$search.val('');
4140 self.$search.trigger('blur');
4141 });
4142
4143 container.on('focus', function () {
4144 if (!container.isOpen()) {
4145 self.$search.trigger('focus');
4146 }
4147 });
4148
4149 container.on('results:all', function (params) {
4150 if (params.query.term == null || params.query.term === '') {
4151 var showSearch = self.showSearch(params);
4152
4153 if (showSearch) {
4154 self.$searchContainer.removeClass('select2-search--hide');
4155 } else {
4156 self.$searchContainer.addClass('select2-search--hide');
4157 }
4158 }
4159 });
4160
4161 container.on('results:focus', function (params) {
4162 if (params.data._resultId) {
4163 self.$search.attr('aria-activedescendant', params.data._resultId);
4164 } else {
4165 self.$search.removeAttr('aria-activedescendant');
4166 }
4167 });
4168 };
4169
4170 Search.prototype.handleSearch = function (evt) {
4171 if (!this._keyUpPrevented) {
4172 var input = this.$search.val();
4173
4174 this.trigger('query', {
4175 term: input
4176 });
4177 }
4178
4179 this._keyUpPrevented = false;
4180 };
4181
4182 Search.prototype.showSearch = function (_, params) {
4183 return true;
4184 };
4185
4186 return Search;
4187 });
4188
4189 S2.define('select2/dropdown/hidePlaceholder',[
4190
4191 ], function () {
4192 function HidePlaceholder (decorated, $element, options, dataAdapter) {
4193 this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
4194
4195 decorated.call(this, $element, options, dataAdapter);
4196 }
4197
4198 HidePlaceholder.prototype.append = function (decorated, data) {
4199 data.results = this.removePlaceholder(data.results);
4200
4201 decorated.call(this, data);
4202 };
4203
4204 HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
4205 if (typeof placeholder === 'string') {
4206 placeholder = {
4207 id: '',
4208 text: placeholder
4209 };
4210 }
4211
4212 return placeholder;
4213 };
4214
4215 HidePlaceholder.prototype.removePlaceholder = function (_, data) {
4216 var modifiedData = data.slice(0);
4217
4218 for (var d = data.length - 1; d >= 0; d--) {
4219 var item = data[d];
4220
4221 if (this.placeholder.id === item.id) {
4222 modifiedData.splice(d, 1);
4223 }
4224 }
4225
4226 return modifiedData;
4227 };
4228
4229 return HidePlaceholder;
4230 });
4231
4232 S2.define('select2/dropdown/infiniteScroll',[
4233 'jquery'
4234 ], function ($) {
4235 function InfiniteScroll (decorated, $element, options, dataAdapter) {
4236 this.lastParams = {};
4237
4238 decorated.call(this, $element, options, dataAdapter);
4239
4240 this.$loadingMore = this.createLoadingMore();
4241 this.loading = false;
4242 }
4243
4244 InfiniteScroll.prototype.append = function (decorated, data) {
4245 this.$loadingMore.remove();
4246 this.loading = false;
4247
4248 decorated.call(this, data);
4249
4250 if (this.showLoadingMore(data)) {
4251 this.$results.append(this.$loadingMore);
4252 this.loadMoreIfNeeded();
4253 }
4254 };
4255
4256 InfiniteScroll.prototype.bind = function (decorated, container, $container) {
4257 var self = this;
4258
4259 decorated.call(this, container, $container);
4260
4261 container.on('query', function (params) {
4262 self.lastParams = params;
4263 self.loading = true;
4264 });
4265
4266 container.on('query:append', function (params) {
4267 self.lastParams = params;
4268 self.loading = true;
4269 });
4270
4271 this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
4272 };
4273
4274 InfiniteScroll.prototype.loadMoreIfNeeded = function () {
4275 var isLoadMoreVisible = $.contains(
4276 document.documentElement,
4277 this.$loadingMore[0]
4278 );
4279
4280 if (this.loading || !isLoadMoreVisible) {
4281 return;
4282 }
4283
4284 var currentOffset = this.$results.offset().top +
4285 this.$results.outerHeight(false);
4286 var loadingMoreOffset = this.$loadingMore.offset().top +
4287 this.$loadingMore.outerHeight(false);
4288
4289 if (currentOffset + 50 >= loadingMoreOffset) {
4290 this.loadMore();
4291 }
4292 };
4293
4294 InfiniteScroll.prototype.loadMore = function () {
4295 this.loading = true;
4296
4297 var params = $.extend({}, {page: 1}, this.lastParams);
4298
4299 params.page++;
4300
4301 this.trigger('query:append', params);
4302 };
4303
4304 InfiniteScroll.prototype.showLoadingMore = function (_, data) {
4305 return data.pagination && data.pagination.more;
4306 };
4307
4308 InfiniteScroll.prototype.createLoadingMore = function () {
4309 var $option = $(
4310 '<li ' +
4311 'class="select2-results__option select2-results__option--load-more"' +
4312 'role="option" aria-disabled="true"></li>'
4313 );
4314
4315 var message = this.options.get('translations').get('loadingMore');
4316
4317 $option.html(message(this.lastParams));
4318
4319 return $option;
4320 };
4321
4322 return InfiniteScroll;
4323 });
4324
4325 S2.define('select2/dropdown/attachBody',[
4326 'jquery',
4327 '../utils'
4328 ], function ($, Utils) {
4329 function AttachBody (decorated, $element, options) {
4330 this.$dropdownParent = $(options.get('dropdownParent') || document.body);
4331
4332 decorated.call(this, $element, options);
4333 }
4334
4335 AttachBody.prototype.bind = function (decorated, container, $container) {
4336 var self = this;
4337
4338 decorated.call(this, container, $container);
4339
4340 container.on('open', function () {
4341 self._showDropdown();
4342 self._attachPositioningHandler(container);
4343
4344 // Must bind after the results handlers to ensure correct sizing
4345 self._bindContainerResultHandlers(container);
4346 });
4347
4348 container.on('close', function () {
4349 self._hideDropdown();
4350 self._detachPositioningHandler(container);
4351 });
4352
4353 this.$dropdownContainer.on('mousedown', function (evt) {
4354 evt.stopPropagation();
4355 });
4356 };
4357
4358 AttachBody.prototype.destroy = function (decorated) {
4359 decorated.call(this);
4360
4361 this.$dropdownContainer.remove();
4362 };
4363
4364 AttachBody.prototype.position = function (decorated, $dropdown, $container) {
4365 // Clone all of the container classes
4366 $dropdown.attr('class', $container.attr('class'));
4367
4368 $dropdown.removeClass('select2');
4369 $dropdown.addClass('select2-container--open');
4370
4371 $dropdown.css({
4372 position: 'absolute',
4373 top: -999999
4374 });
4375
4376 this.$container = $container;
4377 };
4378
4379 AttachBody.prototype.render = function (decorated) {
4380 var $container = $('<span></span>');
4381
4382 var $dropdown = decorated.call(this);
4383 $container.append($dropdown);
4384
4385 this.$dropdownContainer = $container;
4386
4387 return $container;
4388 };
4389
4390 AttachBody.prototype._hideDropdown = function (decorated) {
4391 this.$dropdownContainer.detach();
4392 };
4393
4394 AttachBody.prototype._bindContainerResultHandlers =
4395 function (decorated, container) {
4396
4397 // These should only be bound once
4398 if (this._containerResultsHandlersBound) {
4399 return;
4400 }
4401
4402 var self = this;
4403
4404 container.on('results:all', function () {
4405 self._positionDropdown();
4406 self._resizeDropdown();
4407 });
4408
4409 container.on('results:append', function () {
4410 self._positionDropdown();
4411 self._resizeDropdown();
4412 });
4413
4414 container.on('results:message', function () {
4415 self._positionDropdown();
4416 self._resizeDropdown();
4417 });
4418
4419 container.on('select', function () {
4420 self._positionDropdown();
4421 self._resizeDropdown();
4422 });
4423
4424 container.on('unselect', function () {
4425 self._positionDropdown();
4426 self._resizeDropdown();
4427 });
4428
4429 this._containerResultsHandlersBound = true;
4430 };
4431
4432 AttachBody.prototype._attachPositioningHandler =
4433 function (decorated, container) {
4434 var self = this;
4435
4436 var scrollEvent = 'scroll.select2.' + container.id;
4437 var resizeEvent = 'resize.select2.' + container.id;
4438 var orientationEvent = 'orientationchange.select2.' + container.id;
4439
4440 var $watchers = this.$container.parents().filter(Utils.hasScroll);
4441 $watchers.each(function () {
4442 Utils.StoreData(this, 'select2-scroll-position', {
4443 x: $(this).scrollLeft(),
4444 y: $(this).scrollTop()
4445 });
4446 });
4447
4448 $watchers.on(scrollEvent, function (ev) {
4449 var position = Utils.GetData(this, 'select2-scroll-position');
4450 $(this).scrollTop(position.y);
4451 });
4452
4453 $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
4454 function (e) {
4455 self._positionDropdown();
4456 self._resizeDropdown();
4457 });
4458 };
4459
4460 AttachBody.prototype._detachPositioningHandler =
4461 function (decorated, container) {
4462 var scrollEvent = 'scroll.select2.' + container.id;
4463 var resizeEvent = 'resize.select2.' + container.id;
4464 var orientationEvent = 'orientationchange.select2.' + container.id;
4465
4466 var $watchers = this.$container.parents().filter(Utils.hasScroll);
4467 $watchers.off(scrollEvent);
4468
4469 $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
4470 };
4471
4472 AttachBody.prototype._positionDropdown = function () {
4473 var $window = $(window);
4474
4475 var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
4476 var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
4477
4478 var newDirection = null;
4479
4480 var offset = this.$container.offset();
4481
4482 offset.bottom = offset.top + this.$container.outerHeight(false);
4483
4484 var container = {
4485 height: this.$container.outerHeight(false)
4486 };
4487
4488 container.top = offset.top;
4489 container.bottom = offset.top + container.height;
4490
4491 var dropdown = {
4492 height: this.$dropdown.outerHeight(false)
4493 };
4494
4495 var viewport = {
4496 top: $window.scrollTop(),
4497 bottom: $window.scrollTop() + $window.height()
4498 };
4499
4500 var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
4501 var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
4502
4503 var css = {
4504 left: offset.left,
4505 top: container.bottom
4506 };
4507
4508 // Determine what the parent element is to use for calculating the offset
4509 var $offsetParent = this.$dropdownParent;
4510
4511 // For statically positioned elements, we need to get the element
4512 // that is determining the offset
4513 if ($offsetParent.css('position') === 'static') {
4514 $offsetParent = $offsetParent.offsetParent();
4515 }
4516
4517 var parentOffset = {
4518 top: 0,
4519 left: 0
4520 };
4521
4522 if (
4523 $.contains(document.body, $offsetParent[0]) ||
4524 $offsetParent[0].isConnected
4525 ) {
4526 parentOffset = $offsetParent.offset();
4527 }
4528
4529 css.top -= parentOffset.top;
4530 css.left -= parentOffset.left;
4531
4532 if (!isCurrentlyAbove && !isCurrentlyBelow) {
4533 newDirection = 'below';
4534 }
4535
4536 if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
4537 newDirection = 'above';
4538 } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
4539 newDirection = 'below';
4540 }
4541
4542 if (newDirection == 'above' ||
4543 (isCurrentlyAbove && newDirection !== 'below')) {
4544 css.top = container.top - parentOffset.top - dropdown.height;
4545 }
4546
4547 if (newDirection != null) {
4548 this.$dropdown
4549 .removeClass('select2-dropdown--below select2-dropdown--above')
4550 .addClass('select2-dropdown--' + newDirection);
4551 this.$container
4552 .removeClass('select2-container--below select2-container--above')
4553 .addClass('select2-container--' + newDirection);
4554 }
4555
4556 this.$dropdownContainer.css(css);
4557 };
4558
4559 AttachBody.prototype._resizeDropdown = function () {
4560 var css = {
4561 width: this.$container.outerWidth(false) + 'px'
4562 };
4563
4564 if (this.options.get('dropdownAutoWidth')) {
4565 css.minWidth = css.width;
4566 css.position = 'relative';
4567 css.width = 'auto';
4568 }
4569
4570 this.$dropdown.css(css);
4571 };
4572
4573 AttachBody.prototype._showDropdown = function (decorated) {
4574 this.$dropdownContainer.appendTo(this.$dropdownParent);
4575
4576 this._positionDropdown();
4577 this._resizeDropdown();
4578 };
4579
4580 return AttachBody;
4581 });
4582
4583 S2.define('select2/dropdown/minimumResultsForSearch',[
4584
4585 ], function () {
4586 function countResults (data) {
4587 var count = 0;
4588
4589 for (var d = 0; d < data.length; d++) {
4590 var item = data[d];
4591
4592 if (item.children) {
4593 count += countResults(item.children);
4594 } else {
4595 count++;
4596 }
4597 }
4598
4599 return count;
4600 }
4601
4602 function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
4603 this.minimumResultsForSearch = options.get('minimumResultsForSearch');
4604
4605 if (this.minimumResultsForSearch < 0) {
4606 this.minimumResultsForSearch = Infinity;
4607 }
4608
4609 decorated.call(this, $element, options, dataAdapter);
4610 }
4611
4612 MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
4613 if (countResults(params.data.results) < this.minimumResultsForSearch) {
4614 return false;
4615 }
4616
4617 return decorated.call(this, params);
4618 };
4619
4620 return MinimumResultsForSearch;
4621 });
4622
4623 S2.define('select2/dropdown/selectOnClose',[
4624 '../utils'
4625 ], function (Utils) {
4626 function SelectOnClose () { }
4627
4628 SelectOnClose.prototype.bind = function (decorated, container, $container) {
4629 var self = this;
4630
4631 decorated.call(this, container, $container);
4632
4633 container.on('close', function (params) {
4634 self._handleSelectOnClose(params);
4635 });
4636 };
4637
4638 SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
4639 if (params && params.originalSelect2Event != null) {
4640 var event = params.originalSelect2Event;
4641
4642 // Don't select an item if the close event was triggered from a select or
4643 // unselect event
4644 if (event._type === 'select' || event._type === 'unselect') {
4645 return;
4646 }
4647 }
4648
4649 var $highlightedResults = this.getHighlightedResults();
4650
4651 // Only select highlighted results
4652 if ($highlightedResults.length < 1) {
4653 return;
4654 }
4655
4656 var data = Utils.GetData($highlightedResults[0], 'data');
4657
4658 // Don't re-select already selected resulte
4659 if (
4660 (data.element != null && data.element.selected) ||
4661 (data.element == null && data.selected)
4662 ) {
4663 return;
4664 }
4665
4666 this.trigger('select', {
4667 data: data
4668 });
4669 };
4670
4671 return SelectOnClose;
4672 });
4673
4674 S2.define('select2/dropdown/closeOnSelect',[
4675
4676 ], function () {
4677 function CloseOnSelect () { }
4678
4679 CloseOnSelect.prototype.bind = function (decorated, container, $container) {
4680 var self = this;
4681
4682 decorated.call(this, container, $container);
4683
4684 container.on('select', function (evt) {
4685 self._selectTriggered(evt);
4686 });
4687
4688 container.on('unselect', function (evt) {
4689 self._selectTriggered(evt);
4690 });
4691 };
4692
4693 CloseOnSelect.prototype._selectTriggered = function (_, evt) {
4694 var originalEvent = evt.originalEvent;
4695
4696 // Don't close if the control key is being held
4697 if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
4698 return;
4699 }
4700
4701 this.trigger('close', {
4702 originalEvent: originalEvent,
4703 originalSelect2Event: evt
4704 });
4705 };
4706
4707 return CloseOnSelect;
4708 });
4709
4710 S2.define('select2/i18n/en',[],function () {
4711 // English
4712 return {
4713 errorLoading: function () {
4714 return 'The results could not be loaded.';
4715 },
4716 inputTooLong: function (args) {
4717 var overChars = args.input.length - args.maximum;
4718
4719 var message = 'Please delete ' + overChars + ' character';
4720
4721 if (overChars != 1) {
4722 message += 's';
4723 }
4724
4725 return message;
4726 },
4727 inputTooShort: function (args) {
4728 var remainingChars = args.minimum - args.input.length;
4729
4730 var message = 'Please enter ' + remainingChars + ' or more characters';
4731
4732 return message;
4733 },
4734 loadingMore: function () {
4735 return 'Loading more results…';
4736 },
4737 maximumSelected: function (args) {
4738 var message = 'You can only select ' + args.maximum + ' item';
4739
4740 if (args.maximum != 1) {
4741 message += 's';
4742 }
4743
4744 return message;
4745 },
4746 noResults: function () {
4747 return 'No results found';
4748 },
4749 searching: function () {
4750 return 'Searching…';
4751 },
4752 removeAllItems: function () {
4753 return 'Remove all items';
4754 }
4755 };
4756 });
4757
4758 S2.define('select2/defaults',[
4759 'jquery',
4760 'require',
4761
4762 './results',
4763
4764 './selection/single',
4765 './selection/multiple',
4766 './selection/placeholder',
4767 './selection/allowClear',
4768 './selection/search',
4769 './selection/eventRelay',
4770
4771 './utils',
4772 './translation',
4773 './diacritics',
4774
4775 './data/select',
4776 './data/array',
4777 './data/ajax',
4778 './data/tags',
4779 './data/tokenizer',
4780 './data/minimumInputLength',
4781 './data/maximumInputLength',
4782 './data/maximumSelectionLength',
4783
4784 './dropdown',
4785 './dropdown/search',
4786 './dropdown/hidePlaceholder',
4787 './dropdown/infiniteScroll',
4788 './dropdown/attachBody',
4789 './dropdown/minimumResultsForSearch',
4790 './dropdown/selectOnClose',
4791 './dropdown/closeOnSelect',
4792
4793 './i18n/en'
4794 ], function ($, require,
4795
4796 ResultsList,
4797
4798 SingleSelection, MultipleSelection, Placeholder, AllowClear,
4799 SelectionSearch, EventRelay,
4800
4801 Utils, Translation, DIACRITICS,
4802
4803 SelectData, ArrayData, AjaxData, Tags, Tokenizer,
4804 MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
4805
4806 Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
4807 AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
4808
4809 EnglishTranslation) {
4810 function Defaults () {
4811 this.reset();
4812 }
4813
4814 Defaults.prototype.apply = function (options) {
4815 options = $.extend(true, {}, this.defaults, options);
4816
4817 if (options.dataAdapter == null) {
4818 if (options.ajax != null) {
4819 options.dataAdapter = AjaxData;
4820 } else if (options.data != null) {
4821 options.dataAdapter = ArrayData;
4822 } else {
4823 options.dataAdapter = SelectData;
4824 }
4825
4826 if (options.minimumInputLength > 0) {
4827 options.dataAdapter = Utils.Decorate(
4828 options.dataAdapter,
4829 MinimumInputLength
4830 );
4831 }
4832
4833 if (options.maximumInputLength > 0) {
4834 options.dataAdapter = Utils.Decorate(
4835 options.dataAdapter,
4836 MaximumInputLength
4837 );
4838 }
4839
4840 if (options.maximumSelectionLength > 0) {
4841 options.dataAdapter = Utils.Decorate(
4842 options.dataAdapter,
4843 MaximumSelectionLength
4844 );
4845 }
4846
4847 if (options.tags) {
4848 options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
4849 }
4850
4851 if (options.tokenSeparators != null || options.tokenizer != null) {
4852 options.dataAdapter = Utils.Decorate(
4853 options.dataAdapter,
4854 Tokenizer
4855 );
4856 }
4857
4858 if (options.query != null) {
4859 var Query = require(options.amdBase + 'compat/query');
4860
4861 options.dataAdapter = Utils.Decorate(
4862 options.dataAdapter,
4863 Query
4864 );
4865 }
4866
4867 if (options.initSelection != null) {
4868 var InitSelection = require(options.amdBase + 'compat/initSelection');
4869
4870 options.dataAdapter = Utils.Decorate(
4871 options.dataAdapter,
4872 InitSelection
4873 );
4874 }
4875 }
4876
4877 if (options.resultsAdapter == null) {
4878 options.resultsAdapter = ResultsList;
4879
4880 if (options.ajax != null) {
4881 options.resultsAdapter = Utils.Decorate(
4882 options.resultsAdapter,
4883 InfiniteScroll
4884 );
4885 }
4886
4887 if (options.placeholder != null) {
4888 options.resultsAdapter = Utils.Decorate(
4889 options.resultsAdapter,
4890 HidePlaceholder
4891 );
4892 }
4893
4894 if (options.selectOnClose) {
4895 options.resultsAdapter = Utils.Decorate(
4896 options.resultsAdapter,
4897 SelectOnClose
4898 );
4899 }
4900 }
4901
4902 if (options.dropdownAdapter == null) {
4903 if (options.multiple) {
4904 options.dropdownAdapter = Dropdown;
4905 } else {
4906 var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
4907
4908 options.dropdownAdapter = SearchableDropdown;
4909 }
4910
4911 if (options.minimumResultsForSearch !== 0) {
4912 options.dropdownAdapter = Utils.Decorate(
4913 options.dropdownAdapter,
4914 MinimumResultsForSearch
4915 );
4916 }
4917
4918 if (options.closeOnSelect) {
4919 options.dropdownAdapter = Utils.Decorate(
4920 options.dropdownAdapter,
4921 CloseOnSelect
4922 );
4923 }
4924
4925 if (
4926 options.dropdownCssClass != null ||
4927 options.dropdownCss != null ||
4928 options.adaptDropdownCssClass != null
4929 ) {
4930 var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
4931
4932 options.dropdownAdapter = Utils.Decorate(
4933 options.dropdownAdapter,
4934 DropdownCSS
4935 );
4936 }
4937
4938 options.dropdownAdapter = Utils.Decorate(
4939 options.dropdownAdapter,
4940 AttachBody
4941 );
4942 }
4943
4944 if (options.selectionAdapter == null) {
4945 if (options.multiple) {
4946 options.selectionAdapter = MultipleSelection;
4947 } else {
4948 options.selectionAdapter = SingleSelection;
4949 }
4950
4951 // Add the placeholder mixin if a placeholder was specified
4952 if (options.placeholder != null) {
4953 options.selectionAdapter = Utils.Decorate(
4954 options.selectionAdapter,
4955 Placeholder
4956 );
4957 }
4958
4959 if (options.allowClear) {
4960 options.selectionAdapter = Utils.Decorate(
4961 options.selectionAdapter,
4962 AllowClear
4963 );
4964 }
4965
4966 if (options.multiple) {
4967 options.selectionAdapter = Utils.Decorate(
4968 options.selectionAdapter,
4969 SelectionSearch
4970 );
4971 }
4972
4973 if (
4974 options.containerCssClass != null ||
4975 options.containerCss != null ||
4976 options.adaptContainerCssClass != null
4977 ) {
4978 var ContainerCSS = require(options.amdBase + 'compat/containerCss');
4979
4980 options.selectionAdapter = Utils.Decorate(
4981 options.selectionAdapter,
4982 ContainerCSS
4983 );
4984 }
4985
4986 options.selectionAdapter = Utils.Decorate(
4987 options.selectionAdapter,
4988 EventRelay
4989 );
4990 }
4991
4992 // If the defaults were not previously applied from an element, it is
4993 // possible for the language option to have not been resolved
4994 options.language = this._resolveLanguage(options.language);
4995
4996 // Always fall back to English since it will always be complete
4997 options.language.push('en');
4998
4999 var uniqueLanguages = [];
5000
5001 for (var l = 0; l < options.language.length; l++) {
5002 var language = options.language[l];
5003
5004 if (uniqueLanguages.indexOf(language) === -1) {
5005 uniqueLanguages.push(language);
5006 }
5007 }
5008
5009 options.language = uniqueLanguages;
5010
5011 options.translations = this._processTranslations(
5012 options.language,
5013 options.debug
5014 );
5015
5016 return options;
5017 };
5018
5019 Defaults.prototype.reset = function () {
5020 function stripDiacritics (text) {
5021 // Used 'uni range + named function' from http://jsperf.com/diacritics/18
5022 function match(a) {
5023 return DIACRITICS[a] || a;
5024 }
5025
5026 return text.replace(/[^\u0000-\u007E]/g, match);
5027 }
5028
5029 function matcher (params, data) {
5030 // Always return the object if there is nothing to compare
5031 if ($.trim(params.term) === '') {
5032 return data;
5033 }
5034
5035 // Do a recursive check for options with children
5036 if (data.children && data.children.length > 0) {
5037 // Clone the data object if there are children
5038 // This is required as we modify the object to remove any non-matches
5039 var match = $.extend(true, {}, data);
5040
5041 // Check each child of the option
5042 for (var c = data.children.length - 1; c >= 0; c--) {
5043 var child = data.children[c];
5044
5045 var matches = matcher(params, child);
5046
5047 // If there wasn't a match, remove the object in the array
5048 if (matches == null) {
5049 match.children.splice(c, 1);
5050 }
5051 }
5052
5053 // If any children matched, return the new object
5054 if (match.children.length > 0) {
5055 return match;
5056 }
5057
5058 // If there were no matching children, check just the plain object
5059 return matcher(params, match);
5060 }
5061
5062 var original = stripDiacritics(data.text).toUpperCase();
5063 var term = stripDiacritics(params.term).toUpperCase();
5064
5065 // Check if the text contains the term
5066 if (original.indexOf(term) > -1) {
5067 return data;
5068 }
5069
5070 // If it doesn't contain the term, don't return anything
5071 return null;
5072 }
5073
5074 this.defaults = {
5075 amdBase: './',
5076 amdLanguageBase: './i18n/',
5077 closeOnSelect: true,
5078 debug: false,
5079 dropdownAutoWidth: false,
5080 escapeMarkup: Utils.escapeMarkup,
5081 language: {},
5082 matcher: matcher,
5083 minimumInputLength: 0,
5084 maximumInputLength: 0,
5085 maximumSelectionLength: 0,
5086 minimumResultsForSearch: 0,
5087 selectOnClose: false,
5088 scrollAfterSelect: false,
5089 sorter: function (data) {
5090 return data;
5091 },
5092 templateResult: function (result) {
5093 return result.text;
5094 },
5095 templateSelection: function (selection) {
5096 return selection.text;
5097 },
5098 theme: 'default',
5099 width: 'resolve'
5100 };
5101 };
5102
5103 Defaults.prototype.applyFromElement = function (options, $element) {
5104 var optionLanguage = options.language;
5105 var defaultLanguage = this.defaults.language;
5106 var elementLanguage = $element.prop('lang');
5107 var parentLanguage = $element.closest('[lang]').prop('lang');
5108
5109 var languages = Array.prototype.concat.call(
5110 this._resolveLanguage(elementLanguage),
5111 this._resolveLanguage(optionLanguage),
5112 this._resolveLanguage(defaultLanguage),
5113 this._resolveLanguage(parentLanguage)
5114 );
5115
5116 options.language = languages;
5117
5118 return options;
5119 };
5120
5121 Defaults.prototype._resolveLanguage = function (language) {
5122 if (!language) {
5123 return [];
5124 }
5125
5126 if ($.isEmptyObject(language)) {
5127 return [];
5128 }
5129
5130 if ($.isPlainObject(language)) {
5131 return [language];
5132 }
5133
5134 var languages;
5135
5136 if (!$.isArray(language)) {
5137 languages = [language];
5138 } else {
5139 languages = language;
5140 }
5141
5142 var resolvedLanguages = [];
5143
5144 for (var l = 0; l < languages.length; l++) {
5145 resolvedLanguages.push(languages[l]);
5146
5147 if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
5148 // Extract the region information if it is included
5149 var languageParts = languages[l].split('-');
5150 var baseLanguage = languageParts[0];
5151
5152 resolvedLanguages.push(baseLanguage);
5153 }
5154 }
5155
5156 return resolvedLanguages;
5157 };
5158
5159 Defaults.prototype._processTranslations = function (languages, debug) {
5160 var translations = new Translation();
5161
5162 for (var l = 0; l < languages.length; l++) {
5163 var languageData = new Translation();
5164
5165 var language = languages[l];
5166
5167 if (typeof language === 'string') {
5168 try {
5169 // Try to load it with the original name
5170 languageData = Translation.loadPath(language);
5171 } catch (e) {
5172 try {
5173 // If we couldn't load it, check if it wasn't the full path
5174 language = this.defaults.amdLanguageBase + language;
5175 languageData = Translation.loadPath(language);
5176 } catch (ex) {
5177 // The translation could not be loaded at all. Sometimes this is
5178 // because of a configuration problem, other times this can be
5179 // because of how Select2 helps load all possible translation files
5180 if (debug && window.console && console.warn) {
5181 console.warn(
5182 'Select2: The language file for "' + language + '" could ' +
5183 'not be automatically loaded. A fallback will be used instead.'
5184 );
5185 }
5186 }
5187 }
5188 } else if ($.isPlainObject(language)) {
5189 languageData = new Translation(language);
5190 } else {
5191 languageData = language;
5192 }
5193
5194 translations.extend(languageData);
5195 }
5196
5197 return translations;
5198 };
5199
5200 Defaults.prototype.set = function (key, value) {
5201 var camelKey = $.camelCase(key);
5202
5203 var data = {};
5204 data[camelKey] = value;
5205
5206 var convertedData = Utils._convertData(data);
5207
5208 $.extend(true, this.defaults, convertedData);
5209 };
5210
5211 var defaults = new Defaults();
5212
5213 return defaults;
5214 });
5215
5216 S2.define('select2/options',[
5217 'require',
5218 'jquery',
5219 './defaults',
5220 './utils'
5221 ], function (require, $, Defaults, Utils) {
5222 function Options (options, $element) {
5223 this.options = options;
5224
5225 if ($element != null) {
5226 this.fromElement($element);
5227 }
5228
5229 if ($element != null) {
5230 this.options = Defaults.applyFromElement(this.options, $element);
5231 }
5232
5233 this.options = Defaults.apply(this.options);
5234
5235 if ($element && $element.is('input')) {
5236 var InputCompat = require(this.get('amdBase') + 'compat/inputData');
5237
5238 this.options.dataAdapter = Utils.Decorate(
5239 this.options.dataAdapter,
5240 InputCompat
5241 );
5242 }
5243 }
5244
5245 Options.prototype.fromElement = function ($e) {
5246 var excludedData = ['select2'];
5247
5248 if (this.options.multiple == null) {
5249 this.options.multiple = $e.prop('multiple');
5250 }
5251
5252 if (this.options.disabled == null) {
5253 this.options.disabled = $e.prop('disabled');
5254 }
5255
5256 if (this.options.dir == null) {
5257 if ($e.prop('dir')) {
5258 this.options.dir = $e.prop('dir');
5259 } else if ($e.closest('[dir]').prop('dir')) {
5260 this.options.dir = $e.closest('[dir]').prop('dir');
5261 } else {
5262 this.options.dir = 'ltr';
5263 }
5264 }
5265
5266 $e.prop('disabled', this.options.disabled);
5267 $e.prop('multiple', this.options.multiple);
5268
5269 if (Utils.GetData($e[0], 'select2Tags')) {
5270 if (this.options.debug && window.console && console.warn) {
5271 console.warn(
5272 'Select2: The `data-select2-tags` attribute has been changed to ' +
5273 'use the `data-data` and `data-tags="true"` attributes and will be ' +
5274 'removed in future versions of Select2.'
5275 );
5276 }
5277
5278 Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
5279 Utils.StoreData($e[0], 'tags', true);
5280 }
5281
5282 if (Utils.GetData($e[0], 'ajaxUrl')) {
5283 if (this.options.debug && window.console && console.warn) {
5284 console.warn(
5285 'Select2: The `data-ajax-url` attribute has been changed to ' +
5286 '`data-ajax--url` and support for the old attribute will be removed' +
5287 ' in future versions of Select2.'
5288 );
5289 }
5290
5291 $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
5292 Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
5293 }
5294
5295 var dataset = {};
5296
5297 function upperCaseLetter(_, letter) {
5298 return letter.toUpperCase();
5299 }
5300
5301 // Pre-load all of the attributes which are prefixed with `data-`
5302 for (var attr = 0; attr < $e[0].attributes.length; attr++) {
5303 var attributeName = $e[0].attributes[attr].name;
5304 var prefix = 'data-';
5305
5306 if (attributeName.substr(0, prefix.length) == prefix) {
5307 // Get the contents of the attribute after `data-`
5308 var dataName = attributeName.substring(prefix.length);
5309
5310 // Get the data contents from the consistent source
5311 // This is more than likely the jQuery data helper
5312 var dataValue = Utils.GetData($e[0], dataName);
5313
5314 // camelCase the attribute name to match the spec
5315 var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
5316
5317 // Store the data attribute contents into the dataset since
5318 dataset[camelDataName] = dataValue;
5319 }
5320 }
5321
5322 // Prefer the element's `dataset` attribute if it exists
5323 // jQuery 1.x does not correctly handle data attributes with multiple dashes
5324 if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
5325 dataset = $.extend(true, {}, $e[0].dataset, dataset);
5326 }
5327
5328 // Prefer our internal data cache if it exists
5329 var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
5330
5331 data = Utils._convertData(data);
5332
5333 for (var key in data) {
5334 if ($.inArray(key, excludedData) > -1) {
5335 continue;
5336 }
5337
5338 if ($.isPlainObject(this.options[key])) {
5339 $.extend(this.options[key], data[key]);
5340 } else {
5341 this.options[key] = data[key];
5342 }
5343 }
5344
5345 return this;
5346 };
5347
5348 Options.prototype.get = function (key) {
5349 return this.options[key];
5350 };
5351
5352 Options.prototype.set = function (key, val) {
5353 this.options[key] = val;
5354 };
5355
5356 return Options;
5357 });
5358
5359 S2.define('select2/core',[
5360 'jquery',
5361 './options',
5362 './utils',
5363 './keys'
5364 ], function ($, Options, Utils, KEYS) {
5365 var Select2 = function ($element, options) {
5366 if (Utils.GetData($element[0], 'select2') != null) {
5367 Utils.GetData($element[0], 'select2').destroy();
5368 }
5369
5370 this.$element = $element;
5371
5372 this.id = this._generateId($element);
5373
5374 options = options || {};
5375
5376 this.options = new Options(options, $element);
5377
5378 Select2.__super__.constructor.call(this);
5379
5380 // Set up the tabindex
5381
5382 var tabindex = $element.attr('tabindex') || 0;
5383 Utils.StoreData($element[0], 'old-tabindex', tabindex);
5384 $element.attr('tabindex', '-1');
5385
5386 // Set up containers and adapters
5387
5388 var DataAdapter = this.options.get('dataAdapter');
5389 this.dataAdapter = new DataAdapter($element, this.options);
5390
5391 var $container = this.render();
5392
5393 this._placeContainer($container);
5394
5395 var SelectionAdapter = this.options.get('selectionAdapter');
5396 this.selection = new SelectionAdapter($element, this.options);
5397 this.$selection = this.selection.render();
5398
5399 this.selection.position(this.$selection, $container);
5400
5401 var DropdownAdapter = this.options.get('dropdownAdapter');
5402 this.dropdown = new DropdownAdapter($element, this.options);
5403 this.$dropdown = this.dropdown.render();
5404
5405 this.dropdown.position(this.$dropdown, $container);
5406
5407 var ResultsAdapter = this.options.get('resultsAdapter');
5408 this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
5409 this.$results = this.results.render();
5410
5411 this.results.position(this.$results, this.$dropdown);
5412
5413 // Bind events
5414
5415 var self = this;
5416
5417 // Bind the container to all of the adapters
5418 this._bindAdapters();
5419
5420 // Register any DOM event handlers
5421 this._registerDomEvents();
5422
5423 // Register any internal event handlers
5424 this._registerDataEvents();
5425 this._registerSelectionEvents();
5426 this._registerDropdownEvents();
5427 this._registerResultsEvents();
5428 this._registerEvents();
5429
5430 // Set the initial state
5431 this.dataAdapter.current(function (initialData) {
5432 self.trigger('selection:update', {
5433 data: initialData
5434 });
5435 });
5436
5437 // Hide the original select
5438 $element.addClass('select2-hidden-accessible');
5439 $element.attr('aria-hidden', 'true');
5440
5441 // Synchronize any monitored attributes
5442 this._syncAttributes();
5443
5444 Utils.StoreData($element[0], 'select2', this);
5445
5446 // Ensure backwards compatibility with $element.data('select2').
5447 $element.data('select2', this);
5448 };
5449
5450 Utils.Extend(Select2, Utils.Observable);
5451
5452 Select2.prototype._generateId = function ($element) {
5453 var id = '';
5454
5455 if ($element.attr('id') != null) {
5456 id = $element.attr('id');
5457 } else if ($element.attr('name') != null) {
5458 id = $element.attr('name') + '-' + Utils.generateChars(2);
5459 } else {
5460 id = Utils.generateChars(4);
5461 }
5462
5463 id = id.replace(/(:|\.|\[|\]|,)/g, '');
5464 id = 'select2-' + id;
5465
5466 return id;
5467 };
5468
5469 Select2.prototype._placeContainer = function ($container) {
5470 $container.insertAfter(this.$element);
5471
5472 var width = this._resolveWidth(this.$element, this.options.get('width'));
5473
5474 if (width != null) {
5475 $container.css('width', width);
5476 }
5477 };
5478
5479 Select2.prototype._resolveWidth = function ($element, method) {
5480 var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
5481
5482 if (method == 'resolve') {
5483 var styleWidth = this._resolveWidth($element, 'style');
5484
5485 if (styleWidth != null) {
5486 return styleWidth;
5487 }
5488
5489 return this._resolveWidth($element, 'element');
5490 }
5491
5492 if (method == 'element') {
5493 var elementWidth = $element.outerWidth(false);
5494
5495 if (elementWidth <= 0) {
5496 return 'auto';
5497 }
5498
5499 return elementWidth + 'px';
5500 }
5501
5502 if (method == 'style') {
5503 var style = $element.attr('style');
5504
5505 if (typeof(style) !== 'string') {
5506 return null;
5507 }
5508
5509 var attrs = style.split(';');
5510
5511 for (var i = 0, l = attrs.length; i < l; i = i + 1) {
5512 var attr = attrs[i].replace(/\s/g, '');
5513 var matches = attr.match(WIDTH);
5514
5515 if (matches !== null && matches.length >= 1) {
5516 return matches[1];
5517 }
5518 }
5519
5520 return null;
5521 }
5522
5523 if (method == 'computedstyle') {
5524 var computedStyle = window.getComputedStyle($element[0]);
5525
5526 return computedStyle.width;
5527 }
5528
5529 return method;
5530 };
5531
5532 Select2.prototype._bindAdapters = function () {
5533 this.dataAdapter.bind(this, this.$container);
5534 this.selection.bind(this, this.$container);
5535
5536 this.dropdown.bind(this, this.$container);
5537 this.results.bind(this, this.$container);
5538 };
5539
5540 Select2.prototype._registerDomEvents = function () {
5541 var self = this;
5542
5543 this.$element.on('change.select2', function () {
5544 self.dataAdapter.current(function (data) {
5545 self.trigger('selection:update', {
5546 data: data
5547 });
5548 });
5549 });
5550
5551 this.$element.on('focus.select2', function (evt) {
5552 self.trigger('focus', evt);
5553 });
5554
5555 this._syncA = Utils.bind(this._syncAttributes, this);
5556 this._syncS = Utils.bind(this._syncSubtree, this);
5557
5558 if (this.$element[0].attachEvent) {
5559 this.$element[0].attachEvent('onpropertychange', this._syncA);
5560 }
5561
5562 var observer = window.MutationObserver ||
5563 window.WebKitMutationObserver ||
5564 window.MozMutationObserver
5565 ;
5566
5567 if (observer != null) {
5568 this._observer = new observer(function (mutations) {
5569 self._syncA();
5570 self._syncS(null, mutations);
5571 });
5572 this._observer.observe(this.$element[0], {
5573 attributes: true,
5574 childList: true,
5575 subtree: false
5576 });
5577 } else if (this.$element[0].addEventListener) {
5578 this.$element[0].addEventListener(
5579 'DOMAttrModified',
5580 self._syncA,
5581 false
5582 );
5583 this.$element[0].addEventListener(
5584 'DOMNodeInserted',
5585 self._syncS,
5586 false
5587 );
5588 this.$element[0].addEventListener(
5589 'DOMNodeRemoved',
5590 self._syncS,
5591 false
5592 );
5593 }
5594 };
5595
5596 Select2.prototype._registerDataEvents = function () {
5597 var self = this;
5598
5599 this.dataAdapter.on('*', function (name, params) {
5600 self.trigger(name, params);
5601 });
5602 };
5603
5604 Select2.prototype._registerSelectionEvents = function () {
5605 var self = this;
5606 var nonRelayEvents = ['toggle', 'focus'];
5607
5608 this.selection.on('toggle', function () {
5609 self.toggleDropdown();
5610 });
5611
5612 this.selection.on('focus', function (params) {
5613 self.focus(params);
5614 });
5615
5616 this.selection.on('*', function (name, params) {
5617 if ($.inArray(name, nonRelayEvents) !== -1) {
5618 return;
5619 }
5620
5621 self.trigger(name, params);
5622 });
5623 };
5624
5625 Select2.prototype._registerDropdownEvents = function () {
5626 var self = this;
5627
5628 this.dropdown.on('*', function (name, params) {
5629 self.trigger(name, params);
5630 });
5631 };
5632
5633 Select2.prototype._registerResultsEvents = function () {
5634 var self = this;
5635
5636 this.results.on('*', function (name, params) {
5637 self.trigger(name, params);
5638 });
5639 };
5640
5641 Select2.prototype._registerEvents = function () {
5642 var self = this;
5643
5644 this.on('open', function () {
5645 self.$container.addClass('select2-container--open');
5646 });
5647
5648 this.on('close', function () {
5649 self.$container.removeClass('select2-container--open');
5650 });
5651
5652 this.on('enable', function () {
5653 self.$container.removeClass('select2-container--disabled');
5654 });
5655
5656 this.on('disable', function () {
5657 self.$container.addClass('select2-container--disabled');
5658 });
5659
5660 this.on('blur', function () {
5661 self.$container.removeClass('select2-container--focus');
5662 });
5663
5664 this.on('query', function (params) {
5665 if (!self.isOpen()) {
5666 self.trigger('open', {});
5667 }
5668
5669 this.dataAdapter.query(params, function (data) {
5670 self.trigger('results:all', {
5671 data: data,
5672 query: params
5673 });
5674 });
5675 });
5676
5677 this.on('query:append', function (params) {
5678 this.dataAdapter.query(params, function (data) {
5679 self.trigger('results:append', {
5680 data: data,
5681 query: params
5682 });
5683 });
5684 });
5685
5686 this.on('keypress', function (evt) {
5687 var key = evt.which;
5688
5689 if (self.isOpen()) {
5690 if (key === KEYS.ESC || key === KEYS.TAB ||
5691 (key === KEYS.UP && evt.altKey)) {
5692 self.close(evt);
5693
5694 evt.preventDefault();
5695 } else if (key === KEYS.ENTER) {
5696 self.trigger('results:select', {});
5697
5698 evt.preventDefault();
5699 } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
5700 self.trigger('results:toggle', {});
5701
5702 evt.preventDefault();
5703 } else if (key === KEYS.UP) {
5704 self.trigger('results:previous', {});
5705
5706 evt.preventDefault();
5707 } else if (key === KEYS.DOWN) {
5708 self.trigger('results:next', {});
5709
5710 evt.preventDefault();
5711 }
5712 } else {
5713 if (key === KEYS.ENTER || key === KEYS.SPACE ||
5714 (key === KEYS.DOWN && evt.altKey)) {
5715 self.open();
5716
5717 evt.preventDefault();
5718 }
5719 }
5720 });
5721 };
5722
5723 Select2.prototype._syncAttributes = function () {
5724 this.options.set('disabled', this.$element.prop('disabled'));
5725
5726 if (this.isDisabled()) {
5727 if (this.isOpen()) {
5728 this.close();
5729 }
5730
5731 this.trigger('disable', {});
5732 } else {
5733 this.trigger('enable', {});
5734 }
5735 };
5736
5737 Select2.prototype._isChangeMutation = function (evt, mutations) {
5738 var changed = false;
5739 var self = this;
5740
5741 // Ignore any mutation events raised for elements that aren't options or
5742 // optgroups. This handles the case when the select element is destroyed
5743 if (
5744 evt && evt.target && (
5745 evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
5746 )
5747 ) {
5748 return;
5749 }
5750
5751 if (!mutations) {
5752 // If mutation events aren't supported, then we can only assume that the
5753 // change affected the selections
5754 changed = true;
5755 } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
5756 for (var n = 0; n < mutations.addedNodes.length; n++) {
5757 var node = mutations.addedNodes[n];
5758
5759 if (node.selected) {
5760 changed = true;
5761 }
5762 }
5763 } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
5764 changed = true;
5765 } else if ($.isArray(mutations)) {
5766 $.each(mutations, function(evt, mutation) {
5767 if (self._isChangeMutation(evt, mutation)) {
5768 // We've found a change mutation.
5769 // Let's escape from the loop and continue
5770 changed = true;
5771 return false;
5772 }
5773 });
5774 }
5775 return changed;
5776 };
5777
5778 Select2.prototype._syncSubtree = function (evt, mutations) {
5779 var changed = this._isChangeMutation(evt, mutations);
5780 var self = this;
5781
5782 // Only re-pull the data if we think there is a change
5783 if (changed) {
5784 this.dataAdapter.current(function (currentData) {
5785 self.trigger('selection:update', {
5786 data: currentData
5787 });
5788 });
5789 }
5790 };
5791
5792 /**
5793 * Override the trigger method to automatically trigger pre-events when
5794 * there are events that can be prevented.
5795 */
5796 Select2.prototype.trigger = function (name, args) {
5797 var actualTrigger = Select2.__super__.trigger;
5798 var preTriggerMap = {
5799 'open': 'opening',
5800 'close': 'closing',
5801 'select': 'selecting',
5802 'unselect': 'unselecting',
5803 'clear': 'clearing'
5804 };
5805
5806 if (args === undefined) {
5807 args = {};
5808 }
5809
5810 if (name in preTriggerMap) {
5811 var preTriggerName = preTriggerMap[name];
5812 var preTriggerArgs = {
5813 prevented: false,
5814 name: name,
5815 args: args
5816 };
5817
5818 actualTrigger.call(this, preTriggerName, preTriggerArgs);
5819
5820 if (preTriggerArgs.prevented) {
5821 args.prevented = true;
5822
5823 return;
5824 }
5825 }
5826
5827 actualTrigger.call(this, name, args);
5828 };
5829
5830 Select2.prototype.toggleDropdown = function () {
5831 if (this.isDisabled()) {
5832 return;
5833 }
5834
5835 if (this.isOpen()) {
5836 this.close();
5837 } else {
5838 this.open();
5839 }
5840 };
5841
5842 Select2.prototype.open = function () {
5843 if (this.isOpen()) {
5844 return;
5845 }
5846
5847 if (this.isDisabled()) {
5848 return;
5849 }
5850
5851 this.trigger('query', {});
5852 };
5853
5854 Select2.prototype.close = function (evt) {
5855 if (!this.isOpen()) {
5856 return;
5857 }
5858
5859 this.trigger('close', { originalEvent : evt });
5860 };
5861
5862 /**
5863 * Helper method to abstract the "enabled" (not "disabled") state of this
5864 * object.
5865 *
5866 * @return {true} if the instance is not disabled.
5867 * @return {false} if the instance is disabled.
5868 */
5869 Select2.prototype.isEnabled = function () {
5870 return !this.isDisabled();
5871 };
5872
5873 /**
5874 * Helper method to abstract the "disabled" state of this object.
5875 *
5876 * @return {true} if the disabled option is true.
5877 * @return {false} if the disabled option is false.
5878 */
5879 Select2.prototype.isDisabled = function () {
5880 return this.options.get('disabled');
5881 };
5882
5883 Select2.prototype.isOpen = function () {
5884 return this.$container.hasClass('select2-container--open');
5885 };
5886
5887 Select2.prototype.hasFocus = function () {
5888 return this.$container.hasClass('select2-container--focus');
5889 };
5890
5891 Select2.prototype.focus = function (data) {
5892 // No need to re-trigger focus events if we are already focused
5893 if (this.hasFocus()) {
5894 return;
5895 }
5896
5897 this.$container.addClass('select2-container--focus');
5898 this.trigger('focus', {});
5899 };
5900
5901 Select2.prototype.enable = function (args) {
5902 if (this.options.get('debug') && window.console && console.warn) {
5903 console.warn(
5904 'Select2: The `select2("enable")` method has been deprecated and will' +
5905 ' be removed in later Select2 versions. Use $element.prop("disabled")' +
5906 ' instead.'
5907 );
5908 }
5909
5910 if (args == null || args.length === 0) {
5911 args = [true];
5912 }
5913
5914 var disabled = !args[0];
5915
5916 this.$element.prop('disabled', disabled);
5917 };
5918
5919 Select2.prototype.data = function () {
5920 if (this.options.get('debug') &&
5921 arguments.length > 0 && window.console && console.warn) {
5922 console.warn(
5923 'Select2: Data can no longer be set using `select2("data")`. You ' +
5924 'should consider setting the value instead using `$element.val()`.'
5925 );
5926 }
5927
5928 var data = [];
5929
5930 this.dataAdapter.current(function (currentData) {
5931 data = currentData;
5932 });
5933
5934 return data;
5935 };
5936
5937 Select2.prototype.val = function (args) {
5938 if (this.options.get('debug') && window.console && console.warn) {
5939 console.warn(
5940 'Select2: The `select2("val")` method has been deprecated and will be' +
5941 ' removed in later Select2 versions. Use $element.val() instead.'
5942 );
5943 }
5944
5945 if (args == null || args.length === 0) {
5946 return this.$element.val();
5947 }
5948
5949 var newVal = args[0];
5950
5951 if ($.isArray(newVal)) {
5952 newVal = $.map(newVal, function (obj) {
5953 return obj.toString();
5954 });
5955 }
5956
5957 this.$element.val(newVal).trigger('input').trigger('change');
5958 };
5959
5960 Select2.prototype.destroy = function () {
5961 this.$container.remove();
5962
5963 if (this.$element[0].detachEvent) {
5964 this.$element[0].detachEvent('onpropertychange', this._syncA);
5965 }
5966
5967 if (this._observer != null) {
5968 this._observer.disconnect();
5969 this._observer = null;
5970 } else if (this.$element[0].removeEventListener) {
5971 this.$element[0]
5972 .removeEventListener('DOMAttrModified', this._syncA, false);
5973 this.$element[0]
5974 .removeEventListener('DOMNodeInserted', this._syncS, false);
5975 this.$element[0]
5976 .removeEventListener('DOMNodeRemoved', this._syncS, false);
5977 }
5978
5979 this._syncA = null;
5980 this._syncS = null;
5981
5982 this.$element.off('.select2');
5983 this.$element.attr('tabindex',
5984 Utils.GetData(this.$element[0], 'old-tabindex'));
5985
5986 this.$element.removeClass('select2-hidden-accessible');
5987 this.$element.attr('aria-hidden', 'false');
5988 Utils.RemoveData(this.$element[0]);
5989 this.$element.removeData('select2');
5990
5991 this.dataAdapter.destroy();
5992 this.selection.destroy();
5993 this.dropdown.destroy();
5994 this.results.destroy();
5995
5996 this.dataAdapter = null;
5997 this.selection = null;
5998 this.dropdown = null;
5999 this.results = null;
6000 };
6001
6002 Select2.prototype.render = function () {
6003 var $container = $(
6004 '<span class="select2 select2-container">' +
6005 '<span class="selection"></span>' +
6006 '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
6007 '</span>'
6008 );
6009
6010 $container.attr('dir', this.options.get('dir'));
6011
6012 this.$container = $container;
6013
6014 this.$container.addClass('select2-container--' + this.options.get('theme'));
6015
6016 Utils.StoreData($container[0], 'element', this.$element);
6017
6018 return $container;
6019 };
6020
6021 return Select2;
6022 });
6023
6024 S2.define('jquery-mousewheel',[
6025 'jquery'
6026 ], function ($) {
6027 // Used to shim jQuery.mousewheel for non-full builds.
6028 return $;
6029 });
6030
6031 S2.define('jquery.select2',[
6032 'jquery',
6033 'jquery-mousewheel',
6034
6035 './select2/core',
6036 './select2/defaults',
6037 './select2/utils'
6038 ], function ($, _, Select2, Defaults, Utils) {
6039 if ($.fn.select2 == null) {
6040 // All methods that should return the element
6041 var thisMethods = ['open', 'close', 'destroy'];
6042
6043 $.fn.select2 = function (options) {
6044 options = options || {};
6045
6046 if (typeof options === 'object') {
6047 this.each(function () {
6048 var instanceOptions = $.extend(true, {}, options);
6049
6050 var instance = new Select2($(this), instanceOptions);
6051 });
6052
6053 return this;
6054 } else if (typeof options === 'string') {
6055 var ret;
6056 var args = Array.prototype.slice.call(arguments, 1);
6057
6058 this.each(function () {
6059 var instance = Utils.GetData(this, 'select2');
6060
6061 if (instance == null && window.console && console.error) {
6062 console.error(
6063 'The select2(\'' + options + '\') method was called on an ' +
6064 'element that is not using Select2.'
6065 );
6066 }
6067
6068 ret = instance[options].apply(instance, args);
6069 });
6070
6071 // Check if we should be returning `this`
6072 if ($.inArray(options, thisMethods) > -1) {
6073 return this;
6074 }
6075
6076 return ret;
6077 } else {
6078 throw new Error('Invalid arguments for Select2: ' + options);
6079 }
6080 };
6081 }
6082
6083 if ($.fn.select2.defaults == null) {
6084 $.fn.select2.defaults = Defaults;
6085 }
6086
6087 return Select2;
6088 });
6089
6090 // Return the AMD loader configuration so it can be used outside of this file
6091 return {
6092 define: S2.define,
6093 require: S2.require
6094 };
6095 }());
6096
6097 // Autoload the jQuery bindings
6098 // We know that all of the modules exist above this, so we're safe
6099 var select2 = S2.require('jquery.select2');
6100
6101 // Hold the AMD module references on the jQuery function that was just loaded
6102 // This allows Select2 to use the internal loader outside of this file, such
6103 // as in the language files.
6104 jQuery.fn.select2.amd = S2;
6105
6106 // Return the Select2 instance for anyone who is importing it.
6107 return select2;
6108 }));
6109