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