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