PluginProbe
Smart Grid-Layout Design for Contact Form 7 / 3.2.0
Smart Grid-Layout Design for Contact Form 7 v3.2.0
4.18.0 4.17.0 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 4.0.0 4.0.1 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10 4.11 4.12 4.13 4.14 All 119 releases
cf7-grid-layout / assets / select2 / js / select2.full.js

select2.full.js in Smart Grid-Layout Design for Contact Form 7 3.2.0, at assets/select2/js/select2.full.js

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