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