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