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