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