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