PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.0
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.0
1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 1.8.0 All 210 releases
charitable / assets / js / libraries / select2.js

select2.js in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.0, at assets/js/libraries/select2.js

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