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