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