PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / trunk
Secure Custom Fields vtrunk
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.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.js
6945 lines
1 /*!
2 * Select2 4.0.13
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 self.$search.trigger( 'focus' );
4591
4592 window.setTimeout( function () {
4593 self.$search.trigger( 'focus' );
4594 }, 0 );
4595 } );
4596
4597 container.on( 'close', function () {
4598 self.$search.attr( 'tabindex', -1 );
4599 self.$search.removeAttr( 'aria-controls' );
4600 self.$search.removeAttr( 'aria-activedescendant' );
4601
4602 self.$search.val( '' );
4603 self.$search.trigger( 'blur' );
4604 } );
4605
4606 container.on( 'focus', function () {
4607 if ( ! container.isOpen() ) {
4608 self.$search.trigger( 'focus' );
4609 }
4610 } );
4611
4612 container.on( 'results:all', function ( params ) {
4613 if (
4614 params.query.term == null ||
4615 params.query.term === ''
4616 ) {
4617 var showSearch = self.showSearch( params );
4618
4619 if ( showSearch ) {
4620 self.$searchContainer.removeClass(
4621 'select2-search--hide'
4622 );
4623 } else {
4624 self.$searchContainer.addClass(
4625 'select2-search--hide'
4626 );
4627 }
4628 }
4629 } );
4630
4631 container.on( 'results:focus', function ( params ) {
4632 if ( params.data._resultId ) {
4633 self.$search.attr(
4634 'aria-activedescendant',
4635 params.data._resultId
4636 );
4637 } else {
4638 self.$search.removeAttr( 'aria-activedescendant' );
4639 }
4640 } );
4641 };
4642
4643 Search.prototype.handleSearch = function ( evt ) {
4644 if ( ! this._keyUpPrevented ) {
4645 var input = this.$search.val();
4646
4647 this.trigger( 'query', {
4648 term: input,
4649 } );
4650 }
4651
4652 this._keyUpPrevented = false;
4653 };
4654
4655 Search.prototype.showSearch = function ( _, params ) {
4656 return true;
4657 };
4658
4659 return Search;
4660 }
4661 );
4662
4663 S2.define( 'select2/dropdown/hidePlaceholder', [], function () {
4664 function HidePlaceholder(
4665 decorated,
4666 $element,
4667 options,
4668 dataAdapter
4669 ) {
4670 this.placeholder = this.normalizePlaceholder(
4671 options.get( 'placeholder' )
4672 );
4673
4674 decorated.call( this, $element, options, dataAdapter );
4675 }
4676
4677 HidePlaceholder.prototype.append = function ( decorated, data ) {
4678 data.results = this.removePlaceholder( data.results );
4679
4680 decorated.call( this, data );
4681 };
4682
4683 HidePlaceholder.prototype.normalizePlaceholder = function (
4684 _,
4685 placeholder
4686 ) {
4687 if ( typeof placeholder === 'string' ) {
4688 placeholder = {
4689 id: '',
4690 text: placeholder,
4691 };
4692 }
4693
4694 return placeholder;
4695 };
4696
4697 HidePlaceholder.prototype.removePlaceholder = function ( _, data ) {
4698 var modifiedData = data.slice( 0 );
4699
4700 for ( var d = data.length - 1; d >= 0; d-- ) {
4701 var item = data[ d ];
4702
4703 if ( this.placeholder.id === item.id ) {
4704 modifiedData.splice( d, 1 );
4705 }
4706 }
4707
4708 return modifiedData;
4709 };
4710
4711 return HidePlaceholder;
4712 } );
4713
4714 S2.define(
4715 'select2/dropdown/infiniteScroll',
4716 [ 'jquery' ],
4717 function ( $ ) {
4718 function InfiniteScroll(
4719 decorated,
4720 $element,
4721 options,
4722 dataAdapter
4723 ) {
4724 this.lastParams = {};
4725
4726 decorated.call( this, $element, options, dataAdapter );
4727
4728 this.$loadingMore = this.createLoadingMore();
4729 this.loading = false;
4730 }
4731
4732 InfiniteScroll.prototype.append = function ( decorated, data ) {
4733 this.$loadingMore.remove();
4734 this.loading = false;
4735
4736 decorated.call( this, data );
4737
4738 if ( this.showLoadingMore( data ) ) {
4739 this.$results.append( this.$loadingMore );
4740 this.loadMoreIfNeeded();
4741 }
4742 };
4743
4744 InfiniteScroll.prototype.bind = function (
4745 decorated,
4746 container,
4747 $container
4748 ) {
4749 var self = this;
4750
4751 decorated.call( this, container, $container );
4752
4753 container.on( 'query', function ( params ) {
4754 self.lastParams = params;
4755 self.loading = true;
4756 } );
4757
4758 container.on( 'query:append', function ( params ) {
4759 self.lastParams = params;
4760 self.loading = true;
4761 } );
4762
4763 this.$results.on(
4764 'scroll',
4765 this.loadMoreIfNeeded.bind( this )
4766 );
4767 };
4768
4769 InfiniteScroll.prototype.loadMoreIfNeeded = function () {
4770 var isLoadMoreVisible = $.contains(
4771 document.documentElement,
4772 this.$loadingMore[ 0 ]
4773 );
4774
4775 if ( this.loading || ! isLoadMoreVisible ) {
4776 return;
4777 }
4778
4779 var currentOffset =
4780 this.$results.offset().top +
4781 this.$results.outerHeight( false );
4782 var loadingMoreOffset =
4783 this.$loadingMore.offset().top +
4784 this.$loadingMore.outerHeight( false );
4785
4786 if ( currentOffset + 50 >= loadingMoreOffset ) {
4787 this.loadMore();
4788 }
4789 };
4790
4791 InfiniteScroll.prototype.loadMore = function () {
4792 this.loading = true;
4793
4794 var params = $.extend( {}, { page: 1 }, this.lastParams );
4795
4796 params.page++;
4797
4798 this.trigger( 'query:append', params );
4799 };
4800
4801 InfiniteScroll.prototype.showLoadingMore = function (
4802 _,
4803 data
4804 ) {
4805 return data.pagination && data.pagination.more;
4806 };
4807
4808 InfiniteScroll.prototype.createLoadingMore = function () {
4809 var $option = $(
4810 '<li ' +
4811 'class="select2-results__option select2-results__option--load-more"' +
4812 'role="option" aria-disabled="true"></li>'
4813 );
4814
4815 var message = this.options
4816 .get( 'translations' )
4817 .get( 'loadingMore' );
4818
4819 $option.html( message( this.lastParams ) );
4820
4821 return $option;
4822 };
4823
4824 return InfiniteScroll;
4825 }
4826 );
4827
4828 S2.define(
4829 'select2/dropdown/attachBody',
4830 [ 'jquery', '../utils' ],
4831 function ( $, Utils ) {
4832 function AttachBody( decorated, $element, options ) {
4833 this.$dropdownParent = $(
4834 options.get( 'dropdownParent' ) || document.body
4835 );
4836
4837 decorated.call( this, $element, options );
4838 }
4839
4840 AttachBody.prototype.bind = function (
4841 decorated,
4842 container,
4843 $container
4844 ) {
4845 var self = this;
4846
4847 decorated.call( this, container, $container );
4848
4849 container.on( 'open', function () {
4850 self._showDropdown();
4851 self._attachPositioningHandler( container );
4852
4853 // Must bind after the results handlers to ensure correct sizing
4854 self._bindContainerResultHandlers( container );
4855 } );
4856
4857 container.on( 'close', function () {
4858 self._hideDropdown();
4859 self._detachPositioningHandler( container );
4860 } );
4861
4862 this.$dropdownContainer.on( 'mousedown', function ( evt ) {
4863 evt.stopPropagation();
4864 } );
4865 };
4866
4867 AttachBody.prototype.destroy = function ( decorated ) {
4868 decorated.call( this );
4869
4870 this.$dropdownContainer.remove();
4871 };
4872
4873 AttachBody.prototype.position = function (
4874 decorated,
4875 $dropdown,
4876 $container
4877 ) {
4878 // Clone all of the container classes
4879 $dropdown.attr( 'class', $container.attr( 'class' ) );
4880
4881 $dropdown.removeClass( 'select2' );
4882 $dropdown.addClass( 'select2-container--open' );
4883
4884 $dropdown.css( {
4885 position: 'absolute',
4886 top: -999999,
4887 } );
4888
4889 this.$container = $container;
4890 };
4891
4892 AttachBody.prototype.render = function ( decorated ) {
4893 var $container = $( '<span></span>' );
4894
4895 var $dropdown = decorated.call( this );
4896 $container.append( $dropdown );
4897
4898 this.$dropdownContainer = $container;
4899
4900 return $container;
4901 };
4902
4903 AttachBody.prototype._hideDropdown = function ( decorated ) {
4904 this.$dropdownContainer.detach();
4905 };
4906
4907 AttachBody.prototype._bindContainerResultHandlers = function (
4908 decorated,
4909 container
4910 ) {
4911 // These should only be bound once
4912 if ( this._containerResultsHandlersBound ) {
4913 return;
4914 }
4915
4916 var self = this;
4917
4918 container.on( 'results:all', function () {
4919 self._positionDropdown();
4920 self._resizeDropdown();
4921 } );
4922
4923 container.on( 'results:append', function () {
4924 self._positionDropdown();
4925 self._resizeDropdown();
4926 } );
4927
4928 container.on( 'results:message', function () {
4929 self._positionDropdown();
4930 self._resizeDropdown();
4931 } );
4932
4933 container.on( 'select', function () {
4934 self._positionDropdown();
4935 self._resizeDropdown();
4936 } );
4937
4938 container.on( 'unselect', function () {
4939 self._positionDropdown();
4940 self._resizeDropdown();
4941 } );
4942
4943 this._containerResultsHandlersBound = true;
4944 };
4945
4946 AttachBody.prototype._attachPositioningHandler = function (
4947 decorated,
4948 container
4949 ) {
4950 var self = this;
4951
4952 var scrollEvent = 'scroll.select2.' + container.id;
4953 var resizeEvent = 'resize.select2.' + container.id;
4954 var orientationEvent =
4955 'orientationchange.select2.' + container.id;
4956
4957 var $watchers = this.$container
4958 .parents()
4959 .filter( Utils.hasScroll );
4960 $watchers.each( function () {
4961 Utils.StoreData( this, 'select2-scroll-position', {
4962 x: $( this ).scrollLeft(),
4963 y: $( this ).scrollTop(),
4964 } );
4965 } );
4966
4967 $watchers.on( scrollEvent, function ( ev ) {
4968 var position = Utils.GetData(
4969 this,
4970 'select2-scroll-position'
4971 );
4972 $( this ).scrollTop( position.y );
4973 } );
4974
4975 $( window ).on(
4976 scrollEvent +
4977 ' ' +
4978 resizeEvent +
4979 ' ' +
4980 orientationEvent,
4981 function ( e ) {
4982 self._positionDropdown();
4983 self._resizeDropdown();
4984 }
4985 );
4986 };
4987
4988 AttachBody.prototype._detachPositioningHandler = function (
4989 decorated,
4990 container
4991 ) {
4992 var scrollEvent = 'scroll.select2.' + container.id;
4993 var resizeEvent = 'resize.select2.' + container.id;
4994 var orientationEvent =
4995 'orientationchange.select2.' + container.id;
4996
4997 var $watchers = this.$container
4998 .parents()
4999 .filter( Utils.hasScroll );
5000 $watchers.off( scrollEvent );
5001
5002 $( window ).off(
5003 scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent
5004 );
5005 };
5006
5007 AttachBody.prototype._positionDropdown = function () {
5008 var $window = $( window );
5009
5010 var isCurrentlyAbove = this.$dropdown.hasClass(
5011 'select2-dropdown--above'
5012 );
5013 var isCurrentlyBelow = this.$dropdown.hasClass(
5014 'select2-dropdown--below'
5015 );
5016
5017 var newDirection = null;
5018
5019 var offset = this.$container.offset();
5020
5021 offset.bottom =
5022 offset.top + this.$container.outerHeight( false );
5023
5024 var container = {
5025 height: this.$container.outerHeight( false ),
5026 };
5027
5028 container.top = offset.top;
5029 container.bottom = offset.top + container.height;
5030
5031 var dropdown = {
5032 height: this.$dropdown.outerHeight( false ),
5033 };
5034
5035 var viewport = {
5036 top: $window.scrollTop(),
5037 bottom: $window.scrollTop() + $window.height(),
5038 };
5039
5040 var enoughRoomAbove =
5041 viewport.top < offset.top - dropdown.height;
5042 var enoughRoomBelow =
5043 viewport.bottom > offset.bottom + dropdown.height;
5044
5045 var css = {
5046 left: offset.left,
5047 top: container.bottom,
5048 };
5049
5050 // Determine what the parent element is to use for calculating the offset
5051 var $offsetParent = this.$dropdownParent;
5052
5053 // For statically positioned elements, we need to get the element
5054 // that is determining the offset
5055 if ( $offsetParent.css( 'position' ) === 'static' ) {
5056 $offsetParent = $offsetParent.offsetParent();
5057 }
5058
5059 var parentOffset = {
5060 top: 0,
5061 left: 0,
5062 };
5063
5064 if (
5065 $.contains( document.body, $offsetParent[ 0 ] ) ||
5066 $offsetParent[ 0 ].isConnected
5067 ) {
5068 parentOffset = $offsetParent.offset();
5069 }
5070
5071 css.top -= parentOffset.top;
5072 css.left -= parentOffset.left;
5073
5074 if ( ! isCurrentlyAbove && ! isCurrentlyBelow ) {
5075 newDirection = 'below';
5076 }
5077
5078 if (
5079 ! enoughRoomBelow &&
5080 enoughRoomAbove &&
5081 ! isCurrentlyAbove
5082 ) {
5083 newDirection = 'above';
5084 } else if (
5085 ! enoughRoomAbove &&
5086 enoughRoomBelow &&
5087 isCurrentlyAbove
5088 ) {
5089 newDirection = 'below';
5090 }
5091
5092 if (
5093 newDirection == 'above' ||
5094 ( isCurrentlyAbove && newDirection !== 'below' )
5095 ) {
5096 css.top =
5097 container.top - parentOffset.top - dropdown.height;
5098 }
5099
5100 if ( newDirection != null ) {
5101 this.$dropdown
5102 .removeClass(
5103 'select2-dropdown--below select2-dropdown--above'
5104 )
5105 .addClass( 'select2-dropdown--' + newDirection );
5106 this.$container
5107 .removeClass(
5108 'select2-container--below select2-container--above'
5109 )
5110 .addClass( 'select2-container--' + newDirection );
5111 }
5112
5113 this.$dropdownContainer.css( css );
5114 };
5115
5116 AttachBody.prototype._resizeDropdown = function () {
5117 var css = {
5118 width: this.$container.outerWidth( false ) + 'px',
5119 };
5120
5121 if ( this.options.get( 'dropdownAutoWidth' ) ) {
5122 css.minWidth = css.width;
5123 css.position = 'relative';
5124 css.width = 'auto';
5125 }
5126
5127 this.$dropdown.css( css );
5128 };
5129
5130 AttachBody.prototype._showDropdown = function ( decorated ) {
5131 this.$dropdownContainer.appendTo( this.$dropdownParent );
5132
5133 this._positionDropdown();
5134 this._resizeDropdown();
5135 };
5136
5137 return AttachBody;
5138 }
5139 );
5140
5141 S2.define( 'select2/dropdown/minimumResultsForSearch', [], function () {
5142 function countResults( data ) {
5143 var count = 0;
5144
5145 for ( var d = 0; d < data.length; d++ ) {
5146 var item = data[ d ];
5147
5148 if ( item.children ) {
5149 count += countResults( item.children );
5150 } else {
5151 count++;
5152 }
5153 }
5154
5155 return count;
5156 }
5157
5158 function MinimumResultsForSearch(
5159 decorated,
5160 $element,
5161 options,
5162 dataAdapter
5163 ) {
5164 this.minimumResultsForSearch = options.get(
5165 'minimumResultsForSearch'
5166 );
5167
5168 if ( this.minimumResultsForSearch < 0 ) {
5169 this.minimumResultsForSearch = Infinity;
5170 }
5171
5172 decorated.call( this, $element, options, dataAdapter );
5173 }
5174
5175 MinimumResultsForSearch.prototype.showSearch = function (
5176 decorated,
5177 params
5178 ) {
5179 if (
5180 countResults( params.data.results ) <
5181 this.minimumResultsForSearch
5182 ) {
5183 return false;
5184 }
5185
5186 return decorated.call( this, params );
5187 };
5188
5189 return MinimumResultsForSearch;
5190 } );
5191
5192 S2.define(
5193 'select2/dropdown/selectOnClose',
5194 [ '../utils' ],
5195 function ( Utils ) {
5196 function SelectOnClose() {}
5197
5198 SelectOnClose.prototype.bind = function (
5199 decorated,
5200 container,
5201 $container
5202 ) {
5203 var self = this;
5204
5205 decorated.call( this, container, $container );
5206
5207 container.on( 'close', function ( params ) {
5208 self._handleSelectOnClose( params );
5209 } );
5210 };
5211
5212 SelectOnClose.prototype._handleSelectOnClose = function (
5213 _,
5214 params
5215 ) {
5216 if ( params && params.originalSelect2Event != null ) {
5217 var event = params.originalSelect2Event;
5218
5219 // Don't select an item if the close event was triggered from a select or
5220 // unselect event
5221 if (
5222 event._type === 'select' ||
5223 event._type === 'unselect'
5224 ) {
5225 return;
5226 }
5227 }
5228
5229 var $highlightedResults = this.getHighlightedResults();
5230
5231 // Only select highlighted results
5232 if ( $highlightedResults.length < 1 ) {
5233 return;
5234 }
5235
5236 var data = Utils.GetData(
5237 $highlightedResults[ 0 ],
5238 'data'
5239 );
5240
5241 // Don't re-select already selected result
5242 if (
5243 ( data.element != null && data.element.selected ) ||
5244 ( data.element == null && data.selected )
5245 ) {
5246 return;
5247 }
5248
5249 this.trigger( 'select', {
5250 data: data,
5251 } );
5252 };
5253
5254 return SelectOnClose;
5255 }
5256 );
5257
5258 S2.define( 'select2/dropdown/closeOnSelect', [], function () {
5259 function CloseOnSelect() {}
5260
5261 CloseOnSelect.prototype.bind = function (
5262 decorated,
5263 container,
5264 $container
5265 ) {
5266 var self = this;
5267
5268 decorated.call( this, container, $container );
5269
5270 container.on( 'select', function ( evt ) {
5271 self._selectTriggered( evt );
5272 } );
5273
5274 container.on( 'unselect', function ( evt ) {
5275 self._selectTriggered( evt );
5276 } );
5277 };
5278
5279 CloseOnSelect.prototype._selectTriggered = function ( _, evt ) {
5280 var originalEvent = evt.originalEvent;
5281
5282 // Don't close if the control key is being held
5283 if (
5284 originalEvent &&
5285 ( originalEvent.ctrlKey || originalEvent.metaKey )
5286 ) {
5287 return;
5288 }
5289
5290 this.trigger( 'close', {
5291 originalEvent: originalEvent,
5292 originalSelect2Event: evt,
5293 } );
5294 };
5295
5296 return CloseOnSelect;
5297 } );
5298
5299 S2.define( 'select2/i18n/en', [], function () {
5300 // English
5301 return {
5302 errorLoading: function () {
5303 return 'The results could not be loaded.';
5304 },
5305 inputTooLong: function ( args ) {
5306 var overChars = args.input.length - args.maximum;
5307
5308 var message = 'Please delete ' + overChars + ' character';
5309
5310 if ( overChars != 1 ) {
5311 message += 's';
5312 }
5313
5314 return message;
5315 },
5316 inputTooShort: function ( args ) {
5317 var remainingChars = args.minimum - args.input.length;
5318
5319 var message =
5320 'Please enter ' +
5321 remainingChars +
5322 ' or more characters';
5323
5324 return message;
5325 },
5326 loadingMore: function () {
5327 return 'Loading more results…';
5328 },
5329 maximumSelected: function ( args ) {
5330 var message =
5331 'You can only select ' + args.maximum + ' item';
5332
5333 if ( args.maximum != 1 ) {
5334 message += 's';
5335 }
5336
5337 return message;
5338 },
5339 noResults: function () {
5340 return 'No results found';
5341 },
5342 searching: function () {
5343 return 'Searching…';
5344 },
5345 removeAllItems: function () {
5346 return 'Remove all items';
5347 },
5348 };
5349 } );
5350
5351 S2.define(
5352 'select2/defaults',
5353 [
5354 'jquery',
5355 'require',
5356
5357 './results',
5358
5359 './selection/single',
5360 './selection/multiple',
5361 './selection/placeholder',
5362 './selection/allowClear',
5363 './selection/search',
5364 './selection/eventRelay',
5365
5366 './utils',
5367 './translation',
5368 './diacritics',
5369
5370 './data/select',
5371 './data/array',
5372 './data/ajax',
5373 './data/tags',
5374 './data/tokenizer',
5375 './data/minimumInputLength',
5376 './data/maximumInputLength',
5377 './data/maximumSelectionLength',
5378
5379 './dropdown',
5380 './dropdown/search',
5381 './dropdown/hidePlaceholder',
5382 './dropdown/infiniteScroll',
5383 './dropdown/attachBody',
5384 './dropdown/minimumResultsForSearch',
5385 './dropdown/selectOnClose',
5386 './dropdown/closeOnSelect',
5387
5388 './i18n/en',
5389 ],
5390 function (
5391 $,
5392 require,
5393
5394 ResultsList,
5395
5396 SingleSelection,
5397 MultipleSelection,
5398 Placeholder,
5399 AllowClear,
5400 SelectionSearch,
5401 EventRelay,
5402
5403 Utils,
5404 Translation,
5405 DIACRITICS,
5406
5407 SelectData,
5408 ArrayData,
5409 AjaxData,
5410 Tags,
5411 Tokenizer,
5412 MinimumInputLength,
5413 MaximumInputLength,
5414 MaximumSelectionLength,
5415
5416 Dropdown,
5417 DropdownSearch,
5418 HidePlaceholder,
5419 InfiniteScroll,
5420 AttachBody,
5421 MinimumResultsForSearch,
5422 SelectOnClose,
5423 CloseOnSelect,
5424
5425 EnglishTranslation
5426 ) {
5427 function Defaults() {
5428 this.reset();
5429 }
5430
5431 Defaults.prototype.apply = function ( options ) {
5432 options = $.extend( true, {}, this.defaults, options );
5433
5434 if ( options.dataAdapter == null ) {
5435 if ( options.ajax != null ) {
5436 options.dataAdapter = AjaxData;
5437 } else if ( options.data != null ) {
5438 options.dataAdapter = ArrayData;
5439 } else {
5440 options.dataAdapter = SelectData;
5441 }
5442
5443 if ( options.minimumInputLength > 0 ) {
5444 options.dataAdapter = Utils.Decorate(
5445 options.dataAdapter,
5446 MinimumInputLength
5447 );
5448 }
5449
5450 if ( options.maximumInputLength > 0 ) {
5451 options.dataAdapter = Utils.Decorate(
5452 options.dataAdapter,
5453 MaximumInputLength
5454 );
5455 }
5456
5457 if ( options.maximumSelectionLength > 0 ) {
5458 options.dataAdapter = Utils.Decorate(
5459 options.dataAdapter,
5460 MaximumSelectionLength
5461 );
5462 }
5463
5464 if ( options.tags ) {
5465 options.dataAdapter = Utils.Decorate(
5466 options.dataAdapter,
5467 Tags
5468 );
5469 }
5470
5471 if (
5472 options.tokenSeparators != null ||
5473 options.tokenizer != null
5474 ) {
5475 options.dataAdapter = Utils.Decorate(
5476 options.dataAdapter,
5477 Tokenizer
5478 );
5479 }
5480
5481 if ( options.query != null ) {
5482 var Query = require( options.amdBase +
5483 'compat/query' );
5484
5485 options.dataAdapter = Utils.Decorate(
5486 options.dataAdapter,
5487 Query
5488 );
5489 }
5490
5491 if ( options.initSelection != null ) {
5492 var InitSelection = require( options.amdBase +
5493 'compat/initSelection' );
5494
5495 options.dataAdapter = Utils.Decorate(
5496 options.dataAdapter,
5497 InitSelection
5498 );
5499 }
5500 }
5501
5502 if ( options.resultsAdapter == null ) {
5503 options.resultsAdapter = ResultsList;
5504
5505 if ( options.ajax != null ) {
5506 options.resultsAdapter = Utils.Decorate(
5507 options.resultsAdapter,
5508 InfiniteScroll
5509 );
5510 }
5511
5512 if ( options.placeholder != null ) {
5513 options.resultsAdapter = Utils.Decorate(
5514 options.resultsAdapter,
5515 HidePlaceholder
5516 );
5517 }
5518
5519 if ( options.selectOnClose ) {
5520 options.resultsAdapter = Utils.Decorate(
5521 options.resultsAdapter,
5522 SelectOnClose
5523 );
5524 }
5525 }
5526
5527 if ( options.dropdownAdapter == null ) {
5528 if ( options.multiple ) {
5529 options.dropdownAdapter = Dropdown;
5530 } else {
5531 var SearchableDropdown = Utils.Decorate(
5532 Dropdown,
5533 DropdownSearch
5534 );
5535
5536 options.dropdownAdapter = SearchableDropdown;
5537 }
5538
5539 if ( options.minimumResultsForSearch !== 0 ) {
5540 options.dropdownAdapter = Utils.Decorate(
5541 options.dropdownAdapter,
5542 MinimumResultsForSearch
5543 );
5544 }
5545
5546 if ( options.closeOnSelect ) {
5547 options.dropdownAdapter = Utils.Decorate(
5548 options.dropdownAdapter,
5549 CloseOnSelect
5550 );
5551 }
5552
5553 if (
5554 options.dropdownCssClass != null ||
5555 options.dropdownCss != null ||
5556 options.adaptDropdownCssClass != null
5557 ) {
5558 var DropdownCSS = require( options.amdBase +
5559 'compat/dropdownCss' );
5560
5561 options.dropdownAdapter = Utils.Decorate(
5562 options.dropdownAdapter,
5563 DropdownCSS
5564 );
5565 }
5566
5567 options.dropdownAdapter = Utils.Decorate(
5568 options.dropdownAdapter,
5569 AttachBody
5570 );
5571 }
5572
5573 if ( options.selectionAdapter == null ) {
5574 if ( options.multiple ) {
5575 options.selectionAdapter = MultipleSelection;
5576 } else {
5577 options.selectionAdapter = SingleSelection;
5578 }
5579
5580 // Add the placeholder mixin if a placeholder was specified
5581 if ( options.placeholder != null ) {
5582 options.selectionAdapter = Utils.Decorate(
5583 options.selectionAdapter,
5584 Placeholder
5585 );
5586 }
5587
5588 if ( options.allowClear ) {
5589 options.selectionAdapter = Utils.Decorate(
5590 options.selectionAdapter,
5591 AllowClear
5592 );
5593 }
5594
5595 if ( options.multiple ) {
5596 options.selectionAdapter = Utils.Decorate(
5597 options.selectionAdapter,
5598 SelectionSearch
5599 );
5600 }
5601
5602 if (
5603 options.containerCssClass != null ||
5604 options.containerCss != null ||
5605 options.adaptContainerCssClass != null
5606 ) {
5607 var ContainerCSS = require( options.amdBase +
5608 'compat/containerCss' );
5609
5610 options.selectionAdapter = Utils.Decorate(
5611 options.selectionAdapter,
5612 ContainerCSS
5613 );
5614 }
5615
5616 options.selectionAdapter = Utils.Decorate(
5617 options.selectionAdapter,
5618 EventRelay
5619 );
5620 }
5621
5622 // If the defaults were not previously applied from an element, it is
5623 // possible for the language option to have not been resolved
5624 options.language = this._resolveLanguage(
5625 options.language
5626 );
5627
5628 // Always fall back to English since it will always be complete
5629 options.language.push( 'en' );
5630
5631 var uniqueLanguages = [];
5632
5633 for ( var l = 0; l < options.language.length; l++ ) {
5634 var language = options.language[ l ];
5635
5636 if ( uniqueLanguages.indexOf( language ) === -1 ) {
5637 uniqueLanguages.push( language );
5638 }
5639 }
5640
5641 options.language = uniqueLanguages;
5642
5643 options.translations = this._processTranslations(
5644 options.language,
5645 options.debug
5646 );
5647
5648 return options;
5649 };
5650
5651 Defaults.prototype.reset = function () {
5652 function stripDiacritics( text ) {
5653 // Used 'uni range + named function' from http://jsperf.com/diacritics/18
5654 function match( a ) {
5655 return DIACRITICS[ a ] || a;
5656 }
5657
5658 return text.replace( /[^\u0000-\u007E]/g, match );
5659 }
5660
5661 function matcher( params, data ) {
5662 // Always return the object if there is nothing to compare
5663 if ( $.trim( params.term ) === '' ) {
5664 return data;
5665 }
5666
5667 // Do a recursive check for options with children
5668 if ( data.children && data.children.length > 0 ) {
5669 // Clone the data object if there are children
5670 // This is required as we modify the object to remove any non-matches
5671 var match = $.extend( true, {}, data );
5672
5673 // Check each child of the option
5674 for (
5675 var c = data.children.length - 1;
5676 c >= 0;
5677 c--
5678 ) {
5679 var child = data.children[ c ];
5680
5681 var matches = matcher( params, child );
5682
5683 // If there wasn't a match, remove the object in the array
5684 if ( matches == null ) {
5685 match.children.splice( c, 1 );
5686 }
5687 }
5688
5689 // If any children matched, return the new object
5690 if ( match.children.length > 0 ) {
5691 return match;
5692 }
5693
5694 // If there were no matching children, check just the plain object
5695 return matcher( params, match );
5696 }
5697
5698 var original = stripDiacritics(
5699 data.text
5700 ).toUpperCase();
5701 var term = stripDiacritics( params.term ).toUpperCase();
5702
5703 // Check if the text contains the term
5704 if ( original.indexOf( term ) > -1 ) {
5705 return data;
5706 }
5707
5708 // If it doesn't contain the term, don't return anything
5709 return null;
5710 }
5711
5712 this.defaults = {
5713 amdBase: './',
5714 amdLanguageBase: './i18n/',
5715 closeOnSelect: true,
5716 debug: false,
5717 dropdownAutoWidth: false,
5718 escapeMarkup: Utils.escapeMarkup,
5719 language: {},
5720 matcher: matcher,
5721 minimumInputLength: 0,
5722 maximumInputLength: 0,
5723 maximumSelectionLength: 0,
5724 minimumResultsForSearch: 0,
5725 selectOnClose: false,
5726 scrollAfterSelect: false,
5727 sorter: function ( data ) {
5728 return data;
5729 },
5730 templateResult: function ( result ) {
5731 return result.text;
5732 },
5733 templateSelection: function ( selection ) {
5734 return selection.text;
5735 },
5736 theme: 'default',
5737 width: 'resolve',
5738 };
5739 };
5740
5741 Defaults.prototype.applyFromElement = function (
5742 options,
5743 $element
5744 ) {
5745 var optionLanguage = options.language;
5746 var defaultLanguage = this.defaults.language;
5747 var elementLanguage = $element.prop( 'lang' );
5748 var parentLanguage = $element
5749 .closest( '[lang]' )
5750 .prop( 'lang' );
5751
5752 var languages = Array.prototype.concat.call(
5753 this._resolveLanguage( elementLanguage ),
5754 this._resolveLanguage( optionLanguage ),
5755 this._resolveLanguage( defaultLanguage ),
5756 this._resolveLanguage( parentLanguage )
5757 );
5758
5759 options.language = languages;
5760
5761 return options;
5762 };
5763
5764 Defaults.prototype._resolveLanguage = function ( language ) {
5765 if ( ! language ) {
5766 return [];
5767 }
5768
5769 if ( $.isEmptyObject( language ) ) {
5770 return [];
5771 }
5772
5773 if ( $.isPlainObject( language ) ) {
5774 return [ language ];
5775 }
5776
5777 var languages;
5778
5779 if ( ! $.isArray( language ) ) {
5780 languages = [ language ];
5781 } else {
5782 languages = language;
5783 }
5784
5785 var resolvedLanguages = [];
5786
5787 for ( var l = 0; l < languages.length; l++ ) {
5788 resolvedLanguages.push( languages[ l ] );
5789
5790 if (
5791 typeof languages[ l ] === 'string' &&
5792 languages[ l ].indexOf( '-' ) > 0
5793 ) {
5794 // Extract the region information if it is included
5795 var languageParts = languages[ l ].split( '-' );
5796 var baseLanguage = languageParts[ 0 ];
5797
5798 resolvedLanguages.push( baseLanguage );
5799 }
5800 }
5801
5802 return resolvedLanguages;
5803 };
5804
5805 Defaults.prototype._processTranslations = function (
5806 languages,
5807 debug
5808 ) {
5809 var translations = new Translation();
5810
5811 for ( var l = 0; l < languages.length; l++ ) {
5812 var languageData = new Translation();
5813
5814 var language = languages[ l ];
5815
5816 if ( typeof language === 'string' ) {
5817 try {
5818 // Try to load it with the original name
5819 languageData = Translation.loadPath( language );
5820 } catch ( e ) {
5821 try {
5822 // If we couldn't load it, check if it wasn't the full path
5823 language =
5824 this.defaults.amdLanguageBase +
5825 language;
5826 languageData = Translation.loadPath(
5827 language
5828 );
5829 } catch ( ex ) {
5830 // The translation could not be loaded at all. Sometimes this is
5831 // because of a configuration problem, other times this can be
5832 // because of how Select2 helps load all possible translation files
5833 if (
5834 debug &&
5835 window.console &&
5836 console.warn
5837 ) {
5838 console.warn(
5839 'Select2: The language file for "' +
5840 language +
5841 '" could ' +
5842 'not be automatically loaded. A fallback will be used instead.'
5843 );
5844 }
5845 }
5846 }
5847 } else if ( $.isPlainObject( language ) ) {
5848 languageData = new Translation( language );
5849 } else {
5850 languageData = language;
5851 }
5852
5853 translations.extend( languageData );
5854 }
5855
5856 return translations;
5857 };
5858
5859 Defaults.prototype.set = function ( key, value ) {
5860 var camelKey = $.camelCase( key );
5861
5862 var data = {};
5863 data[ camelKey ] = value;
5864
5865 var convertedData = Utils._convertData( data );
5866
5867 $.extend( true, this.defaults, convertedData );
5868 };
5869
5870 var defaults = new Defaults();
5871
5872 return defaults;
5873 }
5874 );
5875
5876 S2.define(
5877 'select2/options',
5878 [ 'require', 'jquery', './defaults', './utils' ],
5879 function ( require, $, Defaults, Utils ) {
5880 function Options( options, $element ) {
5881 this.options = options;
5882
5883 if ( $element != null ) {
5884 this.fromElement( $element );
5885 }
5886
5887 if ( $element != null ) {
5888 this.options = Defaults.applyFromElement(
5889 this.options,
5890 $element
5891 );
5892 }
5893
5894 this.options = Defaults.apply( this.options );
5895
5896 if ( $element && $element.is( 'input' ) ) {
5897 var InputCompat = require( this.get( 'amdBase' ) +
5898 'compat/inputData' );
5899
5900 this.options.dataAdapter = Utils.Decorate(
5901 this.options.dataAdapter,
5902 InputCompat
5903 );
5904 }
5905 }
5906
5907 Options.prototype.fromElement = function ( $e ) {
5908 var excludedData = [ 'select2' ];
5909
5910 if ( this.options.multiple == null ) {
5911 this.options.multiple = $e.prop( 'multiple' );
5912 }
5913
5914 if ( this.options.disabled == null ) {
5915 this.options.disabled = $e.prop( 'disabled' );
5916 }
5917
5918 if ( this.options.dir == null ) {
5919 if ( $e.prop( 'dir' ) ) {
5920 this.options.dir = $e.prop( 'dir' );
5921 } else if ( $e.closest( '[dir]' ).prop( 'dir' ) ) {
5922 this.options.dir = $e
5923 .closest( '[dir]' )
5924 .prop( 'dir' );
5925 } else {
5926 this.options.dir = 'ltr';
5927 }
5928 }
5929
5930 $e.prop( 'disabled', this.options.disabled );
5931 $e.prop( 'multiple', this.options.multiple );
5932
5933 if ( Utils.GetData( $e[ 0 ], 'select2Tags' ) ) {
5934 if (
5935 this.options.debug &&
5936 window.console &&
5937 console.warn
5938 ) {
5939 console.warn(
5940 'Select2: The `data-select2-tags` attribute has been changed to ' +
5941 'use the `data-data` and `data-tags="true"` attributes and will be ' +
5942 'removed in future versions of Select2.'
5943 );
5944 }
5945
5946 Utils.StoreData(
5947 $e[ 0 ],
5948 'data',
5949 Utils.GetData( $e[ 0 ], 'select2Tags' )
5950 );
5951 Utils.StoreData( $e[ 0 ], 'tags', true );
5952 }
5953
5954 if ( Utils.GetData( $e[ 0 ], 'ajaxUrl' ) ) {
5955 if (
5956 this.options.debug &&
5957 window.console &&
5958 console.warn
5959 ) {
5960 console.warn(
5961 'Select2: The `data-ajax-url` attribute has been changed to ' +
5962 '`data-ajax--url` and support for the old attribute will be removed' +
5963 ' in future versions of Select2.'
5964 );
5965 }
5966
5967 $e.attr(
5968 'ajax--url',
5969 Utils.GetData( $e[ 0 ], 'ajaxUrl' )
5970 );
5971 Utils.StoreData(
5972 $e[ 0 ],
5973 'ajax-Url',
5974 Utils.GetData( $e[ 0 ], 'ajaxUrl' )
5975 );
5976 }
5977
5978 var dataset = {};
5979
5980 function upperCaseLetter( _, letter ) {
5981 return letter.toUpperCase();
5982 }
5983
5984 // Pre-load all of the attributes which are prefixed with `data-`
5985 for (
5986 var attr = 0;
5987 attr < $e[ 0 ].attributes.length;
5988 attr++
5989 ) {
5990 var attributeName = $e[ 0 ].attributes[ attr ].name;
5991 var prefix = 'data-';
5992
5993 if (
5994 attributeName.substr( 0, prefix.length ) == prefix
5995 ) {
5996 // Get the contents of the attribute after `data-`
5997 var dataName = attributeName.substring(
5998 prefix.length
5999 );
6000
6001 // Get the data contents from the consistent source
6002 // This is more than likely the jQuery data helper
6003 var dataValue = Utils.GetData( $e[ 0 ], dataName );
6004
6005 // camelCase the attribute name to match the spec
6006 var camelDataName = dataName.replace(
6007 /-([a-z])/g,
6008 upperCaseLetter
6009 );
6010
6011 // Store the data attribute contents into the dataset since
6012 dataset[ camelDataName ] = dataValue;
6013 }
6014 }
6015
6016 // Prefer the element's `dataset` attribute if it exists
6017 // jQuery 1.x does not correctly handle data attributes with multiple dashes
6018 if (
6019 $.fn.jquery &&
6020 $.fn.jquery.substr( 0, 2 ) == '1.' &&
6021 $e[ 0 ].dataset
6022 ) {
6023 dataset = $.extend(
6024 true,
6025 {},
6026 $e[ 0 ].dataset,
6027 dataset
6028 );
6029 }
6030
6031 // Prefer our internal data cache if it exists
6032 var data = $.extend(
6033 true,
6034 {},
6035 Utils.GetData( $e[ 0 ] ),
6036 dataset
6037 );
6038
6039 data = Utils._convertData( data );
6040
6041 for ( var key in data ) {
6042 if ( $.inArray( key, excludedData ) > -1 ) {
6043 continue;
6044 }
6045
6046 if ( $.isPlainObject( this.options[ key ] ) ) {
6047 $.extend( this.options[ key ], data[ key ] );
6048 } else {
6049 this.options[ key ] = data[ key ];
6050 }
6051 }
6052
6053 return this;
6054 };
6055
6056 Options.prototype.get = function ( key ) {
6057 return this.options[ key ];
6058 };
6059
6060 Options.prototype.set = function ( key, val ) {
6061 this.options[ key ] = val;
6062 };
6063
6064 return Options;
6065 }
6066 );
6067
6068 S2.define(
6069 'select2/core',
6070 [ 'jquery', './options', './utils', './keys' ],
6071 function ( $, Options, Utils, KEYS ) {
6072 var Select2 = function ( $element, options ) {
6073 if ( Utils.GetData( $element[ 0 ], 'select2' ) != null ) {
6074 Utils.GetData( $element[ 0 ], 'select2' ).destroy();
6075 }
6076
6077 this.$element = $element;
6078
6079 this.id = this._generateId( $element );
6080
6081 options = options || {};
6082
6083 this.options = new Options( options, $element );
6084
6085 Select2.__super__.constructor.call( this );
6086
6087 // Set up the tabindex
6088
6089 var tabindex = $element.attr( 'tabindex' ) || 0;
6090 Utils.StoreData( $element[ 0 ], 'old-tabindex', tabindex );
6091 $element.attr( 'tabindex', '-1' );
6092
6093 // Set up containers and adapters
6094
6095 var DataAdapter = this.options.get( 'dataAdapter' );
6096 this.dataAdapter = new DataAdapter(
6097 $element,
6098 this.options
6099 );
6100
6101 var $container = this.render();
6102
6103 this._placeContainer( $container );
6104
6105 var SelectionAdapter = this.options.get(
6106 'selectionAdapter'
6107 );
6108 this.selection = new SelectionAdapter(
6109 $element,
6110 this.options
6111 );
6112 this.$selection = this.selection.render();
6113
6114 this.selection.position( this.$selection, $container );
6115
6116 var DropdownAdapter = this.options.get( 'dropdownAdapter' );
6117 this.dropdown = new DropdownAdapter(
6118 $element,
6119 this.options
6120 );
6121 this.$dropdown = this.dropdown.render();
6122
6123 this.dropdown.position( this.$dropdown, $container );
6124
6125 var ResultsAdapter = this.options.get( 'resultsAdapter' );
6126 this.results = new ResultsAdapter(
6127 $element,
6128 this.options,
6129 this.dataAdapter
6130 );
6131 this.$results = this.results.render();
6132
6133 this.results.position( this.$results, this.$dropdown );
6134
6135 // Bind events
6136
6137 var self = this;
6138
6139 // Bind the container to all of the adapters
6140 this._bindAdapters();
6141
6142 // Register any DOM event handlers
6143 this._registerDomEvents();
6144
6145 // Register any internal event handlers
6146 this._registerDataEvents();
6147 this._registerSelectionEvents();
6148 this._registerDropdownEvents();
6149 this._registerResultsEvents();
6150 this._registerEvents();
6151
6152 // Set the initial state
6153 this.dataAdapter.current( function ( initialData ) {
6154 self.trigger( 'selection:update', {
6155 data: initialData,
6156 } );
6157 } );
6158
6159 // Hide the original select
6160 $element.addClass( 'select2-hidden-accessible' );
6161 $element.attr( 'aria-hidden', 'true' );
6162
6163 // Synchronize any monitored attributes
6164 this._syncAttributes();
6165
6166 Utils.StoreData( $element[ 0 ], 'select2', this );
6167
6168 // Ensure backwards compatibility with $element.data('select2').
6169 $element.data( 'select2', this );
6170 };
6171
6172 Utils.Extend( Select2, Utils.Observable );
6173
6174 Select2.prototype._generateId = function ( $element ) {
6175 var id = '';
6176
6177 if ( $element.attr( 'id' ) != null ) {
6178 id = $element.attr( 'id' );
6179 } else if ( $element.attr( 'name' ) != null ) {
6180 id =
6181 $element.attr( 'name' ) +
6182 '-' +
6183 Utils.generateChars( 2 );
6184 } else {
6185 id = Utils.generateChars( 4 );
6186 }
6187
6188 id = id.replace( /(:|\.|\[|\]|,)/g, '' );
6189 id = 'select2-' + id;
6190
6191 return id;
6192 };
6193
6194 Select2.prototype._placeContainer = function ( $container ) {
6195 $container.insertAfter( this.$element );
6196
6197 var width = this._resolveWidth(
6198 this.$element,
6199 this.options.get( 'width' )
6200 );
6201
6202 if ( width != null ) {
6203 $container.css( 'width', width );
6204 }
6205 };
6206
6207 Select2.prototype._resolveWidth = function (
6208 $element,
6209 method
6210 ) {
6211 var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
6212
6213 if ( method == 'resolve' ) {
6214 var styleWidth = this._resolveWidth(
6215 $element,
6216 'style'
6217 );
6218
6219 if ( styleWidth != null ) {
6220 return styleWidth;
6221 }
6222
6223 return this._resolveWidth( $element, 'element' );
6224 }
6225
6226 if ( method == 'element' ) {
6227 var elementWidth = $element.outerWidth( false );
6228
6229 if ( elementWidth <= 0 ) {
6230 return 'auto';
6231 }
6232
6233 return elementWidth + 'px';
6234 }
6235
6236 if ( method == 'style' ) {
6237 var style = $element.attr( 'style' );
6238
6239 if ( typeof style !== 'string' ) {
6240 return null;
6241 }
6242
6243 var attrs = style.split( ';' );
6244
6245 for ( var i = 0, l = attrs.length; i < l; i = i + 1 ) {
6246 var attr = attrs[ i ].replace( /\s/g, '' );
6247 var matches = attr.match( WIDTH );
6248
6249 if ( matches !== null && matches.length >= 1 ) {
6250 return matches[ 1 ];
6251 }
6252 }
6253
6254 return null;
6255 }
6256
6257 if ( method == 'computedstyle' ) {
6258 var computedStyle = window.getComputedStyle(
6259 $element[ 0 ]
6260 );
6261
6262 return computedStyle.width;
6263 }
6264
6265 return method;
6266 };
6267
6268 Select2.prototype._bindAdapters = function () {
6269 this.dataAdapter.bind( this, this.$container );
6270 this.selection.bind( this, this.$container );
6271
6272 this.dropdown.bind( this, this.$container );
6273 this.results.bind( this, this.$container );
6274 };
6275
6276 Select2.prototype._registerDomEvents = function () {
6277 var self = this;
6278
6279 this.$element.on( 'change.select2', function () {
6280 self.dataAdapter.current( function ( data ) {
6281 self.trigger( 'selection:update', {
6282 data: data,
6283 } );
6284 } );
6285 } );
6286
6287 this.$element.on( 'focus.select2', function ( evt ) {
6288 self.trigger( 'focus', evt );
6289 } );
6290
6291 this._syncA = Utils.bind( this._syncAttributes, this );
6292 this._syncS = Utils.bind( this._syncSubtree, this );
6293
6294 if ( this.$element[ 0 ].attachEvent ) {
6295 this.$element[ 0 ].attachEvent(
6296 'onpropertychange',
6297 this._syncA
6298 );
6299 }
6300
6301 var observer =
6302 window.MutationObserver ||
6303 window.WebKitMutationObserver ||
6304 window.MozMutationObserver;
6305 if ( observer != null ) {
6306 this._observer = new observer( function ( mutations ) {
6307 self._syncA();
6308 self._syncS( null, mutations );
6309 } );
6310 this._observer.observe( this.$element[ 0 ], {
6311 attributes: true,
6312 childList: true,
6313 subtree: false,
6314 } );
6315 } else if ( this.$element[ 0 ].addEventListener ) {
6316 this.$element[ 0 ].addEventListener(
6317 'DOMAttrModified',
6318 self._syncA,
6319 false
6320 );
6321 this.$element[ 0 ].addEventListener(
6322 'DOMNodeInserted',
6323 self._syncS,
6324 false
6325 );
6326 this.$element[ 0 ].addEventListener(
6327 'DOMNodeRemoved',
6328 self._syncS,
6329 false
6330 );
6331 }
6332 };
6333
6334 Select2.prototype._registerDataEvents = function () {
6335 var self = this;
6336
6337 this.dataAdapter.on( '*', function ( name, params ) {
6338 self.trigger( name, params );
6339 } );
6340 };
6341
6342 Select2.prototype._registerSelectionEvents = function () {
6343 var self = this;
6344 var nonRelayEvents = [ 'toggle', 'focus' ];
6345
6346 this.selection.on( 'toggle', function () {
6347 self.toggleDropdown();
6348 } );
6349
6350 this.selection.on( 'focus', function ( params ) {
6351 self.focus( params );
6352 } );
6353
6354 this.selection.on( '*', function ( name, params ) {
6355 if ( $.inArray( name, nonRelayEvents ) !== -1 ) {
6356 return;
6357 }
6358
6359 self.trigger( name, params );
6360 } );
6361 };
6362
6363 Select2.prototype._registerDropdownEvents = function () {
6364 var self = this;
6365
6366 this.dropdown.on( '*', function ( name, params ) {
6367 self.trigger( name, params );
6368 } );
6369 };
6370
6371 Select2.prototype._registerResultsEvents = function () {
6372 var self = this;
6373
6374 this.results.on( '*', function ( name, params ) {
6375 self.trigger( name, params );
6376 } );
6377 };
6378
6379 Select2.prototype._registerEvents = function () {
6380 var self = this;
6381
6382 this.on( 'open', function () {
6383 self.$container.addClass( 'select2-container--open' );
6384 } );
6385
6386 this.on( 'close', function () {
6387 self.$container.removeClass(
6388 'select2-container--open'
6389 );
6390 } );
6391
6392 this.on( 'enable', function () {
6393 self.$container.removeClass(
6394 'select2-container--disabled'
6395 );
6396 } );
6397
6398 this.on( 'disable', function () {
6399 self.$container.addClass(
6400 'select2-container--disabled'
6401 );
6402 } );
6403
6404 this.on( 'blur', function () {
6405 self.$container.removeClass(
6406 'select2-container--focus'
6407 );
6408 } );
6409
6410 this.on( 'query', function ( params ) {
6411 if ( ! self.isOpen() ) {
6412 self.trigger( 'open', {} );
6413 }
6414
6415 this.dataAdapter.query( params, function ( data ) {
6416 self.trigger( 'results:all', {
6417 data: data,
6418 query: params,
6419 } );
6420 } );
6421 } );
6422
6423 this.on( 'query:append', function ( params ) {
6424 this.dataAdapter.query( params, function ( data ) {
6425 self.trigger( 'results:append', {
6426 data: data,
6427 query: params,
6428 } );
6429 } );
6430 } );
6431
6432 this.on( 'keypress', function ( evt ) {
6433 var key = evt.which;
6434
6435 if ( self.isOpen() ) {
6436 if (
6437 key === KEYS.ESC ||
6438 key === KEYS.TAB ||
6439 ( key === KEYS.UP && evt.altKey )
6440 ) {
6441 self.close( evt );
6442
6443 evt.preventDefault();
6444 } else if ( key === KEYS.ENTER ) {
6445 self.trigger( 'results:select', {} );
6446
6447 evt.preventDefault();
6448 } else if ( key === KEYS.SPACE && evt.ctrlKey ) {
6449 self.trigger( 'results:toggle', {} );
6450
6451 evt.preventDefault();
6452 } else if ( key === KEYS.UP ) {
6453 self.trigger( 'results:previous', {} );
6454
6455 evt.preventDefault();
6456 } else if ( key === KEYS.DOWN ) {
6457 self.trigger( 'results:next', {} );
6458
6459 evt.preventDefault();
6460 }
6461 } else {
6462 if (
6463 key === KEYS.ENTER ||
6464 key === KEYS.SPACE ||
6465 ( key === KEYS.DOWN && evt.altKey )
6466 ) {
6467 self.open();
6468
6469 evt.preventDefault();
6470 }
6471 }
6472 } );
6473 };
6474
6475 Select2.prototype._syncAttributes = function () {
6476 this.options.set(
6477 'disabled',
6478 this.$element.prop( 'disabled' )
6479 );
6480
6481 if ( this.isDisabled() ) {
6482 if ( this.isOpen() ) {
6483 this.close();
6484 }
6485
6486 this.trigger( 'disable', {} );
6487 } else {
6488 this.trigger( 'enable', {} );
6489 }
6490 };
6491
6492 Select2.prototype._isChangeMutation = function (
6493 evt,
6494 mutations
6495 ) {
6496 var changed = false;
6497 var self = this;
6498
6499 // Ignore any mutation events raised for elements that aren't options or
6500 // optgroups. This handles the case when the select element is destroyed
6501 if (
6502 evt &&
6503 evt.target &&
6504 evt.target.nodeName !== 'OPTION' &&
6505 evt.target.nodeName !== 'OPTGROUP'
6506 ) {
6507 return;
6508 }
6509
6510 if ( ! mutations ) {
6511 // If mutation events aren't supported, then we can only assume that the
6512 // change affected the selections
6513 changed = true;
6514 } else if (
6515 mutations.addedNodes &&
6516 mutations.addedNodes.length > 0
6517 ) {
6518 for (
6519 var n = 0;
6520 n < mutations.addedNodes.length;
6521 n++
6522 ) {
6523 var node = mutations.addedNodes[ n ];
6524
6525 if ( node.selected ) {
6526 changed = true;
6527 }
6528 }
6529 } else if (
6530 mutations.removedNodes &&
6531 mutations.removedNodes.length > 0
6532 ) {
6533 changed = true;
6534 } else if ( $.isArray( mutations ) ) {
6535 $.each( mutations, function ( evt, mutation ) {
6536 if ( self._isChangeMutation( evt, mutation ) ) {
6537 // We've found a change mutation.
6538 // Let's escape from the loop and continue
6539 changed = true;
6540 return false;
6541 }
6542 } );
6543 }
6544 return changed;
6545 };
6546
6547 Select2.prototype._syncSubtree = function ( evt, mutations ) {
6548 var changed = this._isChangeMutation( evt, mutations );
6549 var self = this;
6550
6551 // Only re-pull the data if we think there is a change
6552 if ( changed ) {
6553 this.dataAdapter.current( function ( currentData ) {
6554 self.trigger( 'selection:update', {
6555 data: currentData,
6556 } );
6557 } );
6558 }
6559 };
6560
6561 /**
6562 * Override the trigger method to automatically trigger pre-events when
6563 * there are events that can be prevented.
6564 */
6565 Select2.prototype.trigger = function ( name, args ) {
6566 var actualTrigger = Select2.__super__.trigger;
6567 var preTriggerMap = {
6568 open: 'opening',
6569 close: 'closing',
6570 select: 'selecting',
6571 unselect: 'unselecting',
6572 clear: 'clearing',
6573 };
6574
6575 if ( args === undefined ) {
6576 args = {};
6577 }
6578
6579 if ( name in preTriggerMap ) {
6580 var preTriggerName = preTriggerMap[ name ];
6581 var preTriggerArgs = {
6582 prevented: false,
6583 name: name,
6584 args: args,
6585 };
6586
6587 actualTrigger.call(
6588 this,
6589 preTriggerName,
6590 preTriggerArgs
6591 );
6592
6593 if ( preTriggerArgs.prevented ) {
6594 args.prevented = true;
6595
6596 return;
6597 }
6598 }
6599
6600 actualTrigger.call( this, name, args );
6601 };
6602
6603 Select2.prototype.toggleDropdown = function () {
6604 if ( this.isDisabled() ) {
6605 return;
6606 }
6607
6608 if ( this.isOpen() ) {
6609 this.close();
6610 } else {
6611 this.open();
6612 }
6613 };
6614
6615 Select2.prototype.open = function () {
6616 if ( this.isOpen() ) {
6617 return;
6618 }
6619
6620 if ( this.isDisabled() ) {
6621 return;
6622 }
6623
6624 this.trigger( 'query', {} );
6625 };
6626
6627 Select2.prototype.close = function ( evt ) {
6628 if ( ! this.isOpen() ) {
6629 return;
6630 }
6631
6632 this.trigger( 'close', { originalEvent: evt } );
6633 };
6634
6635 /**
6636 * Helper method to abstract the "enabled" (not "disabled") state of this
6637 * object.
6638 *
6639 * @return {true} if the instance is not disabled.
6640 * @return {false} if the instance is disabled.
6641 */
6642 Select2.prototype.isEnabled = function () {
6643 return ! this.isDisabled();
6644 };
6645
6646 /**
6647 * Helper method to abstract the "disabled" state of this object.
6648 *
6649 * @return {true} if the disabled option is true.
6650 * @return {false} if the disabled option is false.
6651 */
6652 Select2.prototype.isDisabled = function () {
6653 return this.options.get( 'disabled' );
6654 };
6655
6656 Select2.prototype.isOpen = function () {
6657 return this.$container.hasClass(
6658 'select2-container--open'
6659 );
6660 };
6661
6662 Select2.prototype.hasFocus = function () {
6663 return this.$container.hasClass(
6664 'select2-container--focus'
6665 );
6666 };
6667
6668 Select2.prototype.focus = function ( data ) {
6669 // No need to re-trigger focus events if we are already focused
6670 if ( this.hasFocus() ) {
6671 return;
6672 }
6673
6674 this.$container.addClass( 'select2-container--focus' );
6675 this.trigger( 'focus', {} );
6676 };
6677
6678 Select2.prototype.enable = function ( args ) {
6679 if (
6680 this.options.get( 'debug' ) &&
6681 window.console &&
6682 console.warn
6683 ) {
6684 console.warn(
6685 'Select2: The `select2("enable")` method has been deprecated and will' +
6686 ' be removed in later Select2 versions. Use $element.prop("disabled")' +
6687 ' instead.'
6688 );
6689 }
6690
6691 if ( args == null || args.length === 0 ) {
6692 args = [ true ];
6693 }
6694
6695 var disabled = ! args[ 0 ];
6696
6697 this.$element.prop( 'disabled', disabled );
6698 };
6699
6700 Select2.prototype.data = function () {
6701 if (
6702 this.options.get( 'debug' ) &&
6703 arguments.length > 0 &&
6704 window.console &&
6705 console.warn
6706 ) {
6707 console.warn(
6708 'Select2: Data can no longer be set using `select2("data")`. You ' +
6709 'should consider setting the value instead using `$element.val()`.'
6710 );
6711 }
6712
6713 var data = [];
6714
6715 this.dataAdapter.current( function ( currentData ) {
6716 data = currentData;
6717 } );
6718
6719 return data;
6720 };
6721
6722 Select2.prototype.val = function ( args ) {
6723 if (
6724 this.options.get( 'debug' ) &&
6725 window.console &&
6726 console.warn
6727 ) {
6728 console.warn(
6729 'Select2: The `select2("val")` method has been deprecated and will be' +
6730 ' removed in later Select2 versions. Use $element.val() instead.'
6731 );
6732 }
6733
6734 if ( args == null || args.length === 0 ) {
6735 return this.$element.val();
6736 }
6737
6738 var newVal = args[ 0 ];
6739
6740 if ( $.isArray( newVal ) ) {
6741 newVal = $.map( newVal, function ( obj ) {
6742 return obj.toString();
6743 } );
6744 }
6745
6746 this.$element
6747 .val( newVal )
6748 .trigger( 'input' )
6749 .trigger( 'change' );
6750 };
6751
6752 Select2.prototype.destroy = function () {
6753 this.$container.remove();
6754
6755 if ( this.$element[ 0 ].detachEvent ) {
6756 this.$element[ 0 ].detachEvent(
6757 'onpropertychange',
6758 this._syncA
6759 );
6760 }
6761
6762 if ( this._observer != null ) {
6763 this._observer.disconnect();
6764 this._observer = null;
6765 } else if ( this.$element[ 0 ].removeEventListener ) {
6766 this.$element[ 0 ].removeEventListener(
6767 'DOMAttrModified',
6768 this._syncA,
6769 false
6770 );
6771 this.$element[ 0 ].removeEventListener(
6772 'DOMNodeInserted',
6773 this._syncS,
6774 false
6775 );
6776 this.$element[ 0 ].removeEventListener(
6777 'DOMNodeRemoved',
6778 this._syncS,
6779 false
6780 );
6781 }
6782
6783 this._syncA = null;
6784 this._syncS = null;
6785
6786 this.$element.off( '.select2' );
6787 this.$element.attr(
6788 'tabindex',
6789 Utils.GetData( this.$element[ 0 ], 'old-tabindex' )
6790 );
6791
6792 this.$element.removeClass( 'select2-hidden-accessible' );
6793 this.$element.attr( 'aria-hidden', 'false' );
6794 Utils.RemoveData( this.$element[ 0 ] );
6795 this.$element.removeData( 'select2' );
6796
6797 this.dataAdapter.destroy();
6798 this.selection.destroy();
6799 this.dropdown.destroy();
6800 this.results.destroy();
6801
6802 this.dataAdapter = null;
6803 this.selection = null;
6804 this.dropdown = null;
6805 this.results = null;
6806 };
6807
6808 Select2.prototype.render = function () {
6809 var $container = $(
6810 '<span class="select2 select2-container">' +
6811 '<span class="selection"></span>' +
6812 '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
6813 '</span>'
6814 );
6815
6816 $container.attr( 'dir', this.options.get( 'dir' ) );
6817
6818 this.$container = $container;
6819
6820 this.$container.addClass(
6821 'select2-container--' + this.options.get( 'theme' )
6822 );
6823
6824 Utils.StoreData(
6825 $container[ 0 ],
6826 'element',
6827 this.$element
6828 );
6829
6830 return $container;
6831 };
6832
6833 return Select2;
6834 }
6835 );
6836
6837 S2.define( 'jquery-mousewheel', [ 'jquery' ], function ( $ ) {
6838 // Used to shim jQuery.mousewheel for non-full builds.
6839 return $;
6840 } );
6841
6842 S2.define(
6843 'jquery.select2',
6844 [
6845 'jquery',
6846 'jquery-mousewheel',
6847
6848 './select2/core',
6849 './select2/defaults',
6850 './select2/utils',
6851 ],
6852 function ( $, _, Select2, Defaults, Utils ) {
6853 if ( $.fn.select2 == null ) {
6854 // All methods that should return the element
6855 var thisMethods = [ 'open', 'close', 'destroy' ];
6856
6857 $.fn.select2 = function ( options ) {
6858 options = options || {};
6859
6860 if ( typeof options === 'object' ) {
6861 this.each( function () {
6862 var instanceOptions = $.extend(
6863 true,
6864 {},
6865 options
6866 );
6867
6868 var instance = new Select2(
6869 $( this ),
6870 instanceOptions
6871 );
6872 } );
6873
6874 return this;
6875 } else if ( typeof options === 'string' ) {
6876 var ret;
6877 var args = Array.prototype.slice.call(
6878 arguments,
6879 1
6880 );
6881
6882 this.each( function () {
6883 var instance = Utils.GetData( this, 'select2' );
6884
6885 if (
6886 instance == null &&
6887 window.console &&
6888 console.error
6889 ) {
6890 console.error(
6891 "The select2('" +
6892 options +
6893 "') method was called on an " +
6894 'element that is not using Select2.'
6895 );
6896 }
6897
6898 ret = instance[ options ].apply(
6899 instance,
6900 args
6901 );
6902 } );
6903
6904 // Check if we should be returning `this`
6905 if ( $.inArray( options, thisMethods ) > -1 ) {
6906 return this;
6907 }
6908
6909 return ret;
6910 } else {
6911 throw new Error(
6912 'Invalid arguments for Select2: ' + options
6913 );
6914 }
6915 };
6916 }
6917
6918 if ( $.fn.select2.defaults == null ) {
6919 $.fn.select2.defaults = Defaults;
6920 }
6921
6922 return Select2;
6923 }
6924 );
6925
6926 // Return the AMD loader configuration so it can be used outside of this file
6927 return {
6928 define: S2.define,
6929 require: S2.require,
6930 };
6931 } )();
6932
6933 // Autoload the jQuery bindings
6934 // We know that all of the modules exist above this, so we're safe
6935 var select2 = S2.require( 'jquery.select2' );
6936
6937 // Hold the AMD module references on the jQuery function that was just loaded
6938 // This allows Select2 to use the internal loader outside of this file, such
6939 // as in the language files.
6940 jQuery.fn.select2.amd = S2;
6941
6942 // Return the Select2 instance for anyone who is importing it.
6943 return select2;
6944 } );
6945