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