vendor: 19,564 bytes, lines 1-397
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.
vendor: 11,478 bytes, lines 398-715
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 () { }); 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: 60,490 bytes, lines 716-2405
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 params.element[0].classList.add('select2-results__option--highlighted'); 1271 params.element[0].setAttribute('aria-selected', 'true'); 1272 }); 1273 1274 container.on('results:message', function (params) { 1275 self.displayMessage(params); 1276 }); 1277 1278 if ($.fn.mousewheel) { 1279 this.$results.on('mousewheel', function (e) { 1280 var top = self.$results.scrollTop(); 1281 1282 var bottom = self.$results.get(0).scrollHeight - top + e.deltaY; 1283 1284 var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0; 1285 var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height(); 1286 1287 if (isAtTop) { 1288 self.$results.scrollTop(0); 1289 1290 e.preventDefault(); 1291 e.stopPropagation(); 1292 } else if (isAtBottom) { 1293 self.$results.scrollTop( 1294 self.$results.get(0).scrollHeight - self.$results.height() 1295 ); 1296 1297 e.preventDefault(); 1298 e.stopPropagation(); 1299 } 1300 }); 1301 } 1302 1303 this.$results.on('mouseup', '.select2-results__option--selectable', 1304 function (evt) { 1305 var $this = $(this); 1306 1307 var data = Utils.GetData(this, 'data'); 1308 1309 if ($this.hasClass('select2-results__option--selected')) { 1310 if (self.options.get('multiple')) { 1311 self.trigger('unselect', { 1312 originalEvent: evt, 1313 data: data 1314 }); 1315 } else { 1316 self.trigger('close', {}); 1317 } 1318 1319 return; 1320 } 1321 1322 self.trigger('select', { 1323 originalEvent: evt, 1324 data: data 1325 }); 1326 }); 1327 1328 this.$results.on('mouseenter', '.select2-results__option--selectable', 1329 function (evt) { 1330 var data = Utils.GetData(this, 'data'); 1331 1332 self.getHighlightedResults() 1333 .removeClass('select2-results__option--highlighted') 1334 .attr('aria-selected', 'false'); 1335 1336 self.trigger('results:focus', { 1337 data: data, 1338 element: $(this) 1339 }); 1340 }); 1341 }; 1342 1343 Results.prototype.getHighlightedResults = function () { 1344 var $highlighted = this.$results 1345 .find('.select2-results__option--highlighted'); 1346 1347 return $highlighted; 1348 }; 1349 1350 Results.prototype.destroy = function () { 1351 this.$results.remove(); 1352 }; 1353 1354 Results.prototype.ensureHighlightVisible = function () { 1355 var $highlighted = this.getHighlightedResults(); 1356 1357 if ($highlighted.length === 0) { 1358 return; 1359 } 1360 1361 var $options = this.$results.find('.select2-results__option--selectable'); 1362 1363 var currentIndex = $options.index($highlighted); 1364 1365 var currentOffset = this.$results.offset().top; 1366 var nextTop = $highlighted.offset().top; 1367 var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset); 1368 1369 var offsetDelta = nextTop - currentOffset; 1370 nextOffset -= $highlighted.outerHeight(false) * 2; 1371 1372 if (currentIndex <= 2) { 1373 this.$results.scrollTop(0); 1374 } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) { 1375 this.$results.scrollTop(nextOffset); 1376 } 1377 }; 1378 1379 Results.prototype.template = function (result, container) { 1380 var template = this.options.get('templateResult'); 1381 var escapeMarkup = this.options.get('escapeMarkup'); 1382 1383 var content = template(result, container); 1384 1385 if (content == null) { 1386 container.style.display = 'none'; 1387 } else if (typeof content === 'string') { 1388 container.innerHTML = escapeMarkup(content); 1389 } else { 1390 $(container).append(content); 1391 } 1392 }; 1393 1394 return Results; 1395 }); 1396 1397 S2.define('select2/keys', [ 1398 1399 ], function () { 1400 var KEYS = { 1401 BACKSPACE: 8, 1402 TAB: 9, 1403 ENTER: 13, 1404 SHIFT: 16, 1405 CTRL: 17, 1406 ALT: 18, 1407 ESC: 27, 1408 SPACE: 32, 1409 PAGE_UP: 33, 1410 PAGE_DOWN: 34, 1411 END: 35, 1412 HOME: 36, 1413 LEFT: 37, 1414 UP: 38, 1415 RIGHT: 39, 1416 DOWN: 40, 1417 DELETE: 46 1418 }; 1419 1420 return KEYS; 1421 }); 1422 1423 S2.define('select2/selection/base', [ 1424 'jquery', 1425 '../utils', 1426 '../keys' 1427 ], function ($, Utils, KEYS) { 1428 function BaseSelection($element, options) { 1429 this.$element = $element; 1430 this.options = options; 1431 1432 BaseSelection.__super__.constructor.call(this); 1433 } 1434 1435 Utils.Extend(BaseSelection, Utils.Observable); 1436 1437 BaseSelection.prototype.render = function () { 1438 var $selection = $( 1439 '<span class="select2-selection" role="combobox" ' + 1440 ' aria-haspopup="true" aria-expanded="false">' + 1441 '</span>' 1442 ); 1443 1444 this._tabindex = 0; 1445 1446 if (Utils.GetData(this.$element[0], 'old-tabindex') != null) { 1447 this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex'); 1448 } else if (this.$element.attr('tabindex') != null) { 1449 this._tabindex = this.$element.attr('tabindex'); 1450 } 1451 1452 $selection.attr('title', this.$element.attr('title')); 1453 $selection.attr('tabindex', this._tabindex); 1454 $selection.attr('aria-disabled', 'false'); 1455 1456 this.$selection = $selection; 1457 1458 return $selection; 1459 }; 1460 1461 BaseSelection.prototype.bind = function (container, $container) { 1462 var self = this; 1463 1464 var resultsId = container.id + '-results'; 1465 1466 this.container = container; 1467 1468 this.$selection.on('focus', function (evt) { 1469 self.trigger('focus', evt); 1470 }); 1471 1472 this.$selection.on('blur', function (evt) { 1473 self._handleBlur(evt); 1474 }); 1475 1476 this.$selection.on('keydown', function (evt) { 1477 self.trigger('keypress', evt); 1478 1479 if (evt.which === KEYS.SPACE) { 1480 evt.preventDefault(); 1481 } 1482 }); 1483 1484 container.on('results:focus', function (params) { 1485 self.$selection.attr('aria-activedescendant', params.data._resultId); 1486 }); 1487 1488 container.on('selection:update', function (params) { 1489 self.update(params.data); 1490 }); 1491 1492 container.on('open', function () { 1493 // When the dropdown is open, aria-expanded="true" 1494 self.$selection.attr('aria-expanded', 'true'); 1495 self.$selection.attr('aria-owns', resultsId); 1496 1497 self._attachCloseHandler(container); 1498 }); 1499 1500 container.on('close', function () { 1501 // When the dropdown is closed, aria-expanded="false" 1502 self.$selection.attr('aria-expanded', 'false'); 1503 self.$selection.removeAttr('aria-activedescendant'); 1504 self.$selection.removeAttr('aria-owns'); 1505 1506 self.$selection.trigger('focus'); 1507 1508 self._detachCloseHandler(container); 1509 }); 1510 1511 container.on('enable', function () { 1512 self.$selection.attr('tabindex', self._tabindex); 1513 self.$selection.attr('aria-disabled', 'false'); 1514 }); 1515 1516 container.on('disable', function () { 1517 self.$selection.attr('tabindex', '-1'); 1518 self.$selection.attr('aria-disabled', 'true'); 1519 }); 1520 }; 1521 1522 BaseSelection.prototype._handleBlur = function (evt) { 1523 var self = this; 1524 1525 // This needs to be delayed as the active element is the body when the tab 1526 // key is pressed, possibly along with others. 1527 window.setTimeout(function () { 1528 // Don't trigger `blur` if the focus is still in the selection 1529 if ( 1530 (document.activeElement == self.$selection[0]) || 1531 ($.contains(self.$selection[0], document.activeElement)) 1532 ) { 1533 return; 1534 } 1535 1536 self.trigger('blur', evt); 1537 }, 1); 1538 }; 1539 1540 BaseSelection.prototype._attachCloseHandler = function (container) { 1541 1542 $(document.body).on('mousedown.select2.' + container.id, function (e) { 1543 var $target = $(e.target); 1544 1545 var $select = $target.closest('.select2'); 1546 1547 var $all = $('.select2.select2-container--open'); 1548 1549 $all.each(function () { 1550 if (this == $select[0]) { 1551 return; 1552 } 1553 1554 var $element = Utils.GetData(this, 'element'); 1555 1556 $element.select2('close'); 1557 }); 1558 }); 1559 }; 1560 1561 BaseSelection.prototype._detachCloseHandler = function (container) { 1562 $(document.body).off('mousedown.select2.' + container.id); 1563 }; 1564 1565 BaseSelection.prototype.position = function ($selection, $container) { 1566 var $selectionContainer = $container.find('.selection'); 1567 $selectionContainer.append($selection); 1568 }; 1569 1570 BaseSelection.prototype.destroy = function () { 1571 this._detachCloseHandler(this.container); 1572 }; 1573 1574 BaseSelection.prototype.update = function (data) { 1575 throw new Error('The `update` method must be defined in child classes.'); 1576 }; 1577 1578 /** 1579 * Helper method to abstract the "enabled" (not "disabled") state of this 1580 * object. 1581 * 1582 * @return {true} if the instance is not disabled. 1583 * @return {false} if the instance is disabled. 1584 */ 1585 BaseSelection.prototype.isEnabled = function () { 1586 return !this.isDisabled(); 1587 }; 1588 1589 /** 1590 * Helper method to abstract the "disabled" state of this object. 1591 * 1592 * @return {true} if the disabled option is true. 1593 * @return {false} if the disabled option is false. 1594 */ 1595 BaseSelection.prototype.isDisabled = function () { 1596 return this.options.get('disabled'); 1597 }; 1598 1599 return BaseSelection; 1600 }); 1601 1602 S2.define('select2/selection/single', [ 1603 'jquery', 1604 './base', 1605 '../utils', 1606 '../keys' 1607 ], function ($, BaseSelection, Utils, KEYS) { 1608 function SingleSelection() { 1609 SingleSelection.__super__.constructor.apply(this, arguments); 1610 } 1611 1612 Utils.Extend(SingleSelection, BaseSelection); 1613 1614 SingleSelection.prototype.render = function () { 1615 var $selection = SingleSelection.__super__.render.call(this); 1616 1617 $selection[0].classList.add('select2-selection--single'); 1618 1619 $selection.html( 1620 '<span class="select2-selection__rendered"></span>' + 1621 '<span class="select2-selection__arrow" role="presentation">' + 1622 '<b role="presentation"></b>' + 1623 '</span>' 1624 ); 1625 1626 return $selection; 1627 }; 1628 1629 SingleSelection.prototype.bind = function (container, $container) { 1630 var self = this; 1631 1632 SingleSelection.__super__.bind.apply(this, arguments); 1633 1634 var id = container.id + '-container'; 1635 1636 this.$selection.find('.select2-selection__rendered') 1637 .attr('id', id) 1638 .attr('role', 'textbox') 1639 .attr('aria-readonly', 'true'); 1640 this.$selection.attr('aria-labelledby', id); 1641 this.$selection.attr('aria-controls', id); 1642 1643 this.$selection.on('mousedown', function (evt) { 1644 // Only respond to left clicks 1645 if (evt.which !== 1) { 1646 return; 1647 } 1648 1649 self.trigger('toggle', { 1650 originalEvent: evt 1651 }); 1652 }); 1653 1654 this.$selection.on('focus', function (evt) { 1655 // User focuses on the container 1656 }); 1657 1658 this.$selection.on('blur', function (evt) { 1659 // User exits the container 1660 }); 1661 1662 container.on('focus', function (evt) { 1663 if (!container.isOpen()) { 1664 self.$selection.trigger('focus'); 1665 } 1666 }); 1667 }; 1668 1669 SingleSelection.prototype.clear = function () { 1670 var $rendered = this.$selection.find('.select2-selection__rendered'); 1671 $rendered.empty(); 1672 $rendered.removeAttr('title'); // clear tooltip on empty 1673 }; 1674 1675 SingleSelection.prototype.display = function (data, container) { 1676 var template = this.options.get('templateSelection'); 1677 var escapeMarkup = this.options.get('escapeMarkup'); 1678 1679 return escapeMarkup(template(data, container)); 1680 }; 1681 1682 SingleSelection.prototype.selectionContainer = function () { 1683 return $('<span></span>'); 1684 }; 1685 1686 SingleSelection.prototype.update = function (data) { 1687 if (data.length === 0) { 1688 this.clear(); 1689 return; 1690 } 1691 1692 var selection = data[0]; 1693 1694 var $rendered = this.$selection.find('.select2-selection__rendered'); 1695 var formatted = this.display(selection, $rendered); 1696 1697 $rendered.empty().append(formatted); 1698 1699 var title = selection.title || selection.text; 1700 1701 if (title) { 1702 $rendered.attr('title', title); 1703 } else { 1704 $rendered.removeAttr('title'); 1705 } 1706 }; 1707 1708 return SingleSelection; 1709 }); 1710 1711 S2.define('select2/selection/multiple', [ 1712 'jquery', 1713 './base', 1714 '../utils' 1715 ], function ($, BaseSelection, Utils) { 1716 function MultipleSelection($element, options) { 1717 MultipleSelection.__super__.constructor.apply(this, arguments); 1718 } 1719 1720 Utils.Extend(MultipleSelection, BaseSelection); 1721 1722 MultipleSelection.prototype.render = function () { 1723 var $selection = MultipleSelection.__super__.render.call(this); 1724 1725 $selection[0].classList.add('select2-selection--multiple'); 1726 1727 $selection.html( 1728 '<ul class="select2-selection__rendered"></ul>' 1729 ); 1730 1731 return $selection; 1732 }; 1733 1734 MultipleSelection.prototype.bind = function (container, $container) { 1735 var self = this; 1736 1737 MultipleSelection.__super__.bind.apply(this, arguments); 1738 1739 var id = container.id + '-container'; 1740 this.$selection.find('.select2-selection__rendered').attr('id', id); 1741 1742 this.$selection.on('click', function (evt) { 1743 self.trigger('toggle', { 1744 originalEvent: evt 1745 }); 1746 }); 1747 1748 this.$selection.on( 1749 'click', 1750 '.select2-selection__choice__remove', 1751 function (evt) { 1752 // Ignore the event if it is disabled 1753 if (self.isDisabled()) { 1754 return; 1755 } 1756 1757 var $remove = $(this); 1758 var $selection = $remove.parent(); 1759 1760 var data = Utils.GetData($selection[0], 'data'); 1761 1762 self.trigger('unselect', { 1763 originalEvent: evt, 1764 data: data 1765 }); 1766 } 1767 ); 1768 1769 this.$selection.on( 1770 'keydown', 1771 '.select2-selection__choice__remove', 1772 function (evt) { 1773 // Ignore the event if it is disabled 1774 if (self.isDisabled()) { 1775 return; 1776 } 1777 1778 evt.stopPropagation(); 1779 } 1780 ); 1781 }; 1782 1783 MultipleSelection.prototype.clear = function () { 1784 var $rendered = this.$selection.find('.select2-selection__rendered'); 1785 $rendered.empty(); 1786 $rendered.removeAttr('title'); 1787 }; 1788 1789 MultipleSelection.prototype.display = function (data, container) { 1790 var template = this.options.get('templateSelection'); 1791 var escapeMarkup = this.options.get('escapeMarkup'); 1792 1793 return escapeMarkup(template(data, container)); 1794 }; 1795 1796 MultipleSelection.prototype.selectionContainer = function () { 1797 var $container = $( 1798 '<li class="select2-selection__choice">' + 1799 '<button type="button" class="select2-selection__choice__remove" ' + 1800 'tabindex="-1">' + 1801 '<span aria-hidden="true">×</span>' + 1802 '</button>' + 1803 '<span class="select2-selection__choice__display"></span>' + 1804 '</li>' 1805 ); 1806 1807 return $container; 1808 }; 1809 1810 MultipleSelection.prototype.update = function (data) { 1811 this.clear(); 1812 1813 if (data.length === 0) { 1814 return; 1815 } 1816 1817 var $selections = []; 1818 1819 var selectionIdPrefix = this.$selection.find('.select2-selection__rendered') 1820 .attr('id') + '-choice-'; 1821 1822 for (var d = 0; d < data.length; d++) { 1823 var selection = data[d]; 1824 1825 var $selection = this.selectionContainer(); 1826 var formatted = this.display(selection, $selection); 1827 1828 var selectionId = selectionIdPrefix + Utils.generateChars(4) + '-'; 1829 1830 if (selection.id) { 1831 selectionId += selection.id; 1832 } else { 1833 selectionId += Utils.generateChars(4); 1834 } 1835 1836 $selection.find('.select2-selection__choice__display') 1837 .append(formatted) 1838 .attr('id', selectionId); 1839 1840 var title = selection.title || selection.text; 1841 1842 if (title) { 1843 $selection.attr('title', title); 1844 } 1845 1846 var removeItem = this.options.get('translations').get('removeItem'); 1847 1848 var $remove = $selection.find('.select2-selection__choice__remove'); 1849 1850 $remove.attr('title', removeItem()); 1851 $remove.attr('aria-label', removeItem()); 1852 $remove.attr('aria-describedby', selectionId); 1853 1854 Utils.StoreData($selection[0], 'data', selection); 1855 1856 $selections.push($selection); 1857 } 1858 1859 var $rendered = this.$selection.find('.select2-selection__rendered'); 1860 1861 $rendered.append($selections); 1862 }; 1863 1864 return MultipleSelection; 1865 }); 1866 1867 S2.define('select2/selection/placeholder', [ 1868 1869 ], function () { 1870 function Placeholder(decorated, $element, options) { 1871 this.placeholder = this.normalizePlaceholder(options.get('placeholder')); 1872 1873 decorated.call(this, $element, options); 1874 } 1875 1876 Placeholder.prototype.normalizePlaceholder = function (_, placeholder) { 1877 if (typeof placeholder === 'string') { 1878 placeholder = { 1879 id: '', 1880 text: placeholder 1881 }; 1882 } 1883 1884 return placeholder; 1885 }; 1886 1887 Placeholder.prototype.createPlaceholder = function (decorated, placeholder) { 1888 var $placeholder = this.selectionContainer(); 1889 1890 $placeholder.html(this.display(placeholder)); 1891 $placeholder[0].classList.add('select2-selection__placeholder'); 1892 $placeholder[0].classList.remove('select2-selection__choice'); 1893 1894 var placeholderTitle = placeholder.title || 1895 placeholder.text || 1896 $placeholder.text(); 1897 1898 this.$selection.find('.select2-selection__rendered').attr( 1899 'title', 1900 placeholderTitle 1901 ); 1902 1903 return $placeholder; 1904 }; 1905 1906 Placeholder.prototype.update = function (decorated, data) { 1907 var singlePlaceholder = ( 1908 data.length == 1 && data[0].id != this.placeholder.id 1909 ); 1910 var multipleSelections = data.length > 1; 1911 1912 if (multipleSelections || singlePlaceholder) { 1913 return decorated.call(this, data); 1914 } 1915 1916 this.clear(); 1917 1918 var $placeholder = this.createPlaceholder(this.placeholder); 1919 1920 this.$selection.find('.select2-selection__rendered').append($placeholder); 1921 }; 1922 1923 return Placeholder; 1924 }); 1925 1926 S2.define('select2/selection/allowClear', [ 1927 'jquery', 1928 '../keys', 1929 '../utils' 1930 ], function ($, KEYS, Utils) { 1931 function AllowClear() { } 1932 1933 AllowClear.prototype.bind = function (decorated, container, $container) { 1934 var self = this; 1935 1936 decorated.call(this, container, $container); 1937 1938 if (this.placeholder == null) { 1939 if (this.options.get('debug') && window.console && console.error) { 1940 console.error( 1941 'Select2: The `allowClear` option should be used in combination ' + 1942 'with the `placeholder` option.' 1943 ); 1944 } 1945 } 1946 1947 this.$selection.on('mousedown', '.select2-selection__clear', 1948 function (evt) { 1949 self._handleClear(evt); 1950 }); 1951 1952 container.on('keypress', function (evt) { 1953 self._handleKeyboardClear(evt, container); 1954 }); 1955 }; 1956 1957 AllowClear.prototype._handleClear = function (_, evt) { 1958 // Ignore the event if it is disabled 1959 if (this.isDisabled()) { 1960 return; 1961 } 1962 1963 var $clear = this.$selection.find('.select2-selection__clear'); 1964 1965 // Ignore the event if nothing has been selected 1966 if ($clear.length === 0) { 1967 return; 1968 } 1969 1970 evt.stopPropagation(); 1971 1972 var data = Utils.GetData($clear[0], 'data'); 1973 1974 var previousVal = this.$element.val(); 1975 this.$element.val(this.placeholder.id); 1976 1977 var unselectData = { 1978 data: data 1979 }; 1980 this.trigger('clear', unselectData); 1981 if (unselectData.prevented) { 1982 this.$element.val(previousVal); 1983 return; 1984 } 1985 1986 for (var d = 0; d < data.length; d++) { 1987 unselectData = { 1988 data: data[d] 1989 }; 1990 1991 // Trigger the `unselect` event, so people can prevent it from being 1992 // cleared. 1993 this.trigger('unselect', unselectData); 1994 1995 // If the event was prevented, don't clear it out. 1996 if (unselectData.prevented) { 1997 this.$element.val(previousVal); 1998 return; 1999 } 2000 } 2001 2002 this.$element.trigger('input').trigger('change'); 2003 2004 this.trigger('toggle', {}); 2005 }; 2006 2007 AllowClear.prototype._handleKeyboardClear = function (_, evt, container) { 2008 if (container.isOpen()) { 2009 return; 2010 } 2011 2012 if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) { 2013 this._handleClear(evt); 2014 } 2015 }; 2016 2017 AllowClear.prototype.update = function (decorated, data) { 2018 decorated.call(this, data); 2019 2020 this.$selection.find('.select2-selection__clear').remove(); 2021 this.$selection[0].classList.remove('select2-selection--clearable'); 2022 2023 if (this.$selection.find('.select2-selection__placeholder').length > 0 || 2024 data.length === 0) { 2025 return; 2026 } 2027 2028 var selectionId = this.$selection.find('.select2-selection__rendered') 2029 .attr('id'); 2030 2031 var removeAll = this.options.get('translations').get('removeAllItems'); 2032 2033 var $remove = $( 2034 '<button type="button" class="select2-selection__clear" tabindex="-1">' + 2035 '<span aria-hidden="true">×</span>' + 2036 '</button>' 2037 ); 2038 $remove.attr('title', removeAll()); 2039 $remove.attr('aria-label', removeAll()); 2040 $remove.attr('aria-describedby', selectionId); 2041 Utils.StoreData($remove[0], 'data', data); 2042 2043 this.$selection.prepend($remove); 2044 this.$selection[0].classList.add('select2-selection--clearable'); 2045 }; 2046 2047 return AllowClear; 2048 }); 2049 2050 S2.define('select2/selection/search', [ 2051 'jquery', 2052 '../utils', 2053 '../keys' 2054 ], function ($, Utils, KEYS) { 2055 function Search(decorated, $element, options) { 2056 decorated.call(this, $element, options); 2057 } 2058 2059 Search.prototype.render = function (decorated) { 2060 var searchLabel = this.options.get('translations').get('search'); 2061 var $search = $( 2062 '<span class="select2-search select2-search--inline">' + 2063 '<textarea class="select2-search__field"' + 2064 ' type="search" tabindex="-1"' + 2065 ' autocorrect="off" autocapitalize="none"' + 2066 ' spellcheck="false" role="searchbox" aria-autocomplete="list" >' + 2067 '</textarea>' + 2068 '</span>' 2069 ); 2070 2071 this.$searchContainer = $search; 2072 this.$search = $search.find('textarea'); 2073 2074 this.$search.prop('autocomplete', this.options.get('autocomplete')); 2075 this.$search.attr('aria-label', searchLabel()); 2076 2077 var $rendered = decorated.call(this); 2078 2079 this._transferTabIndex(); 2080 $rendered.append(this.$searchContainer); 2081 2082 return $rendered; 2083 }; 2084 2085 Search.prototype.bind = function (decorated, container, $container) { 2086 var self = this; 2087 2088 var resultsId = container.id + '-results'; 2089 var selectionId = container.id + '-container'; 2090 2091 decorated.call(this, container, $container); 2092 2093 self.$search.attr('aria-describedby', selectionId); 2094 2095 container.on('open', function () { 2096 self.$search.attr('aria-controls', resultsId); 2097 self.$search.trigger('focus'); 2098 }); 2099 2100 container.on('close', function () { 2101 self.$search.val(''); 2102 self.resizeSearch(); 2103 self.$search.removeAttr('aria-controls'); 2104 self.$search.removeAttr('aria-activedescendant'); 2105 self.$search.trigger('focus'); 2106 }); 2107 2108 container.on('enable', function () { 2109 self.$search.prop('disabled', false); 2110 2111 self._transferTabIndex(); 2112 }); 2113 2114 container.on('disable', function () { 2115 self.$search.prop('disabled', true); 2116 }); 2117 2118 container.on('focus', function (evt) { 2119 self.$search.trigger('focus'); 2120 }); 2121 2122 container.on('results:focus', function (params) { 2123 if (params.data._resultId) { 2124 self.$search.attr('aria-activedescendant', params.data._resultId); 2125 } else { 2126 self.$search.removeAttr('aria-activedescendant'); 2127 } 2128 }); 2129 2130 this.$selection.on('focusin', '.select2-search--inline', function (evt) { 2131 self.trigger('focus', evt); 2132 }); 2133 2134 this.$selection.on('focusout', '.select2-search--inline', function (evt) { 2135 self._handleBlur(evt); 2136 }); 2137 2138 this.$selection.on('keydown', '.select2-search--inline', function (evt) { 2139 evt.stopPropagation(); 2140 2141 self.trigger('keypress', evt); 2142 2143 self._keyUpPrevented = evt.isDefaultPrevented(); 2144 2145 var key = evt.which; 2146 2147 if (key === KEYS.BACKSPACE && self.$search.val() === '') { 2148 var $previousChoice = self.$selection 2149 .find('.select2-selection__choice').last(); 2150 2151 if ($previousChoice.length > 0) { 2152 var item = Utils.GetData($previousChoice[0], 'data'); 2153 2154 self.searchRemoveChoice(item); 2155 2156 evt.preventDefault(); 2157 } 2158 } 2159 }); 2160 2161 this.$selection.on('click', '.select2-search--inline', function (evt) { 2162 if (self.$search.val()) { 2163 evt.stopPropagation(); 2164 } 2165 }); 2166 2167 // Try to detect the IE version should the `documentMode` property that 2168 // is stored on the document. This is only implemented in IE and is 2169 // slightly cleaner than doing a user agent check. 2170 // This property is not available in Edge, but Edge also doesn't have 2171 // this bug. 2172 var msie = document.documentMode; 2173 var disableInputEvents = msie && msie <= 11; 2174 2175 // Workaround for browsers which do not support the `input` event 2176 // This will prevent double-triggering of events for browsers which support 2177 // both the `keyup` and `input` events. 2178 this.$selection.on( 2179 'input.searchcheck', 2180 '.select2-search--inline', 2181 function (evt) { 2182 // IE will trigger the `input` event when a placeholder is used on a 2183 // search box. To get around this issue, we are forced to ignore all 2184 // `input` events in IE and keep using `keyup`. 2185 if (disableInputEvents) { 2186 self.$selection.off('input.search input.searchcheck'); 2187 return; 2188 } 2189 2190 // Unbind the duplicated `keyup` event 2191 self.$selection.off('keyup.search'); 2192 } 2193 ); 2194 2195 this.$selection.on( 2196 'keyup.search input.search', 2197 '.select2-search--inline', 2198 function (evt) { 2199 // IE will trigger the `input` event when a placeholder is used on a 2200 // search box. To get around this issue, we are forced to ignore all 2201 // `input` events in IE and keep using `keyup`. 2202 if (disableInputEvents && evt.type === 'input') { 2203 self.$selection.off('input.search input.searchcheck'); 2204 return; 2205 } 2206 2207 var key = evt.which; 2208 2209 // We can freely ignore events from modifier keys 2210 if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) { 2211 return; 2212 } 2213 2214 // Tabbing will be handled during the `keydown` phase 2215 if (key == KEYS.TAB) { 2216 return; 2217 } 2218 2219 self.handleSearch(evt); 2220 } 2221 ); 2222 }; 2223 2224 /** 2225 * This method will transfer the tabindex attribute from the rendered 2226 * selection to the search box. This allows for the search box to be used as 2227 * the primary focus instead of the selection container. 2228 * 2229 * @private 2230 */ 2231 Search.prototype._transferTabIndex = function (decorated) { 2232 this.$search.attr('tabindex', this.$selection.attr('tabindex')); 2233 this.$selection.attr('tabindex', '-1'); 2234 }; 2235 2236 Search.prototype.createPlaceholder = function (decorated, placeholder) { 2237 this.$search.attr('placeholder', placeholder.text); 2238 }; 2239 2240 Search.prototype.update = function (decorated, data) { 2241 var searchHadFocus = this.$search[0] == document.activeElement; 2242 2243 this.$search.attr('placeholder', ''); 2244 2245 decorated.call(this, data); 2246 2247 this.resizeSearch(); 2248 if (searchHadFocus) { 2249 this.$search.trigger('focus'); 2250 } 2251 }; 2252 2253 Search.prototype.handleSearch = function () { 2254 this.resizeSearch(); 2255 2256 if (!this._keyUpPrevented) { 2257 var input = this.$search.val(); 2258 2259 this.trigger('query', { 2260 term: input 2261 }); 2262 } 2263 2264 this._keyUpPrevented = false; 2265 }; 2266 2267 Search.prototype.searchRemoveChoice = function (decorated, item) { 2268 this.trigger('unselect', { 2269 data: item 2270 }); 2271 2272 this.$search.val(item.text); 2273 this.handleSearch(); 2274 }; 2275 2276 Search.prototype.resizeSearch = function () { 2277 this.$search.css('width', '25px'); 2278 2279 var width = '100%'; 2280 2281 if (this.$search.attr('placeholder') === '') { 2282 var minimumWidth = this.$search.val().length + 1; 2283 2284 width = (minimumWidth * 0.75) + 'em'; 2285 } 2286 2287 this.$search.css('width', width); 2288 }; 2289 2290 return Search; 2291 }); 2292 2293 S2.define('select2/selection/selectionCss', [ 2294 '../utils' 2295 ], function (Utils) { 2296 function SelectionCSS() { } 2297 2298 SelectionCSS.prototype.render = function (decorated) { 2299 var $selection = decorated.call(this); 2300 2301 var selectionCssClass = this.options.get('selectionCssClass') || ''; 2302 2303 if (selectionCssClass.indexOf(':all:') !== -1) { 2304 selectionCssClass = selectionCssClass.replace(':all:', ''); 2305 2306 Utils.copyNonInternalCssClasses($selection[0], this.$element[0]); 2307 } 2308 2309 $selection.addClass(selectionCssClass); 2310 2311 return $selection; 2312 }; 2313 2314 return SelectionCSS; 2315 }); 2316 2317 S2.define('select2/selection/eventRelay', [ 2318 'jquery' 2319 ], function ($) { 2320 function EventRelay() { } 2321 2322 EventRelay.prototype.bind = function (decorated, container, $container) { 2323 var self = this; 2324 var relayEvents = [ 2325 'open', 'opening', 2326 'close', 'closing', 2327 'select', 'selecting', 2328 'unselect', 'unselecting', 2329 'clear', 'clearing' 2330 ]; 2331 2332 var preventableEvents = [ 2333 'opening', 'closing', 'selecting', 'unselecting', 'clearing' 2334 ]; 2335 2336 decorated.call(this, container, $container); 2337 2338 container.on('*', function (name, params) { 2339 // Ignore events that should not be relayed 2340 if (relayEvents.indexOf(name) === -1) { 2341 return; 2342 } 2343 2344 // The parameters should always be an object 2345 params = params || {}; 2346 2347 // Generate the jQuery event for the Select2 event 2348 var evt = $.Event('select2:' + name, { 2349 params: params 2350 }); 2351 2352 self.$element.trigger(evt); 2353 2354 // Only handle preventable events if it was one 2355 if (preventableEvents.indexOf(name) === -1) { 2356 return; 2357 } 2358 2359 params.prevented = evt.isDefaultPrevented(); 2360 }); 2361 }; 2362 2363 return EventRelay; 2364 }); 2365 2366 S2.define('select2/translation', [ 2367 'jquery', 2368 'require' 2369 ], function ($, require) { 2370 function Translation(dict) { 2371 this.dict = dict || {}; 2372 } 2373 2374 Translation.prototype.all = function () { 2375 return this.dict; 2376 }; 2377 2378 Translation.prototype.get = function (key) { 2379 return this.dict[key]; 2380 }; 2381 2382 Translation.prototype.extend = function (translation) { 2383 this.dict = $.extend({}, translation.all(), this.dict); 2384 }; 2385 2386 // Static functions 2387 2388 Translation._cache = {}; 2389 2390 Translation.loadPath = function (path) { 2391 if (!(path in Translation._cache)) { 2392 var translations = require(path); 2393 2394 Translation._cache[path] = translations; 2395 } 2396 2397 return new Translation(Translation._cache[path]); 2398 }; 2399 2400 return Translation; 2401 }); 2402 2403 S2.define('select2/diacritics', [ 2404 2405 ], function () {
2406 var diacritics = { 2407 '\u24B6': 'A', 2408 '\uFF21': 'A', 2409 '\u00C0': 'A', 2410 '\u00C1': 'A', 2411 '\u00C2': 'A', 2412 '\u1EA6': 'A', 2413 '\u1EA4': 'A', 2414 '\u1EAA': 'A', 2415 '\u1EA8': 'A', 2416 '\u00C3': 'A', 2417 '\u0100': 'A', 2418 '\u0102': 'A', 2419 '\u1EB0': 'A', 2420 '\u1EAE': 'A', 2421 '\u1EB4': 'A', 2422 '\u1EB2': 'A', 2423 '\u0226': 'A', 2424 '\u01E0': 'A', 2425 '\u00C4': 'A', 2426 '\u01DE': 'A', 2427 '\u1EA2': 'A', 2428 '\u00C5': 'A', 2429 '\u01FA': 'A', 2430 '\u01CD': 'A', 2431 '\u0200': 'A', 2432 '\u0202': 'A', 2433 '\u1EA0': 'A', 2434 '\u1EAC': 'A', 2435 '\u1EB6': 'A', 2436 '\u1E00': 'A', 2437 '\u0104': 'A', 2438 '\u023A': 'A', 2439 '\u2C6F': 'A', 2440 '\uA732': 'AA', 2441 '\u00C6': 'AE', 2442 '\u01FC': 'AE', 2443 '\u01E2': 'AE', 2444 '\uA734': 'AO', 2445 '\uA736': 'AU', 2446 '\uA738': 'AV', 2447 '\uA73A': 'AV', 2448 '\uA73C': 'AY', 2449 '\u24B7': 'B', 2450 '\uFF22': 'B', 2451 '\u1E02': 'B', 2452 '\u1E04': 'B', 2453 '\u1E06': 'B', 2454 '\u0243': 'B', 2455 '\u0182': 'B', 2456 '\u0181': 'B', 2457 '\u24B8': 'C', 2458 '\uFF23': 'C', 2459 '\u0106': 'C', 2460 '\u0108': 'C', 2461 '\u010A': 'C', 2462 '\u010C': 'C', 2463 '\u00C7': 'C', 2464 '\u1E08': 'C', 2465 '\u0187': 'C', 2466 '\u023B': 'C', 2467 '\uA73E': 'C', 2468 '\u24B9': 'D', 2469 '\uFF24': 'D', 2470 '\u1E0A': 'D', 2471 '\u010E': 'D', 2472 '\u1E0C': 'D', 2473 '\u1E10': 'D', 2474 '\u1E12': 'D', 2475 '\u1E0E': 'D', 2476 '\u0110': 'D', 2477 '\u018B': 'D', 2478 '\u018A': 'D', 2479 '\u0189': 'D', 2480 '\uA779': 'D', 2481 '\u01F1': 'DZ', 2482 '\u01C4': 'DZ', 2483 '\u01F2': 'Dz', 2484 '\u01C5': 'Dz', 2485 '\u24BA': 'E', 2486 '\uFF25': 'E', 2487 '\u00C8': 'E', 2488 '\u00C9': 'E', 2489 '\u00CA': 'E', 2490 '\u1EC0': 'E', 2491 '\u1EBE': 'E', 2492 '\u1EC4': 'E', 2493 '\u1EC2': 'E', 2494 '\u1EBC': 'E', 2495 '\u0112': 'E', 2496 '\u1E14': 'E', 2497 '\u1E16': 'E', 2498 '\u0114': 'E', 2499 '\u0116': 'E', 2500 '\u00CB': 'E', 2501 '\u1EBA': 'E', 2502 '\u011A': 'E', 2503 '\u0204': 'E', 2504 '\u0206': 'E', 2505 '\u1EB8': 'E', 2506 '\u1EC6': 'E', 2507 '\u0228': 'E', 2508 '\u1E1C': 'E', 2509 '\u0118': 'E', 2510 '\u1E18': 'E', 2511 '\u1E1A': 'E', 2512 '\u0190': 'E', 2513 '\u018E': 'E', 2514 '\u24BB': 'F', 2515 '\uFF26': 'F', 2516 '\u1E1E': 'F', 2517 '\u0191': 'F', 2518 '\uA77B': 'F', 2519 '\u24BC': 'G', 2520 '\uFF27': 'G', 2521 '\u01F4': 'G', 2522 '\u011C': 'G', 2523 '\u1E20': 'G', 2524 '\u011E': 'G', 2525 '\u0120': 'G', 2526 '\u01E6': 'G', 2527 '\u0122': 'G', 2528 '\u01E4': 'G', 2529 '\u0193': 'G', 2530 '\uA7A0': 'G', 2531 '\uA77D': 'G', 2532 '\uA77E': 'G', 2533 '\u24BD': 'H', 2534 '\uFF28': 'H', 2535 '\u0124': 'H', 2536 '\u1E22': 'H', 2537 '\u1E26': 'H', 2538 '\u021E': 'H', 2539 '\u1E24': 'H', 2540 '\u1E28': 'H', 2541 '\u1E2A': 'H', 2542 '\u0126': 'H', 2543 '\u2C67': 'H', 2544 '\u2C75': 'H', 2545 '\uA78D': 'H', 2546 '\u24BE': 'I', 2547 '\uFF29': 'I', 2548 '\u00CC': 'I', 2549 '\u00CD': 'I', 2550 '\u00CE': 'I', 2551 '\u0128': 'I', 2552 '\u012A': 'I', 2553 '\u012C': 'I', 2554 '\u0130': 'I', 2555 '\u00CF': 'I', 2556 '\u1E2E': 'I', 2557 '\u1EC8': 'I', 2558 '\u01CF': 'I', 2559 '\u0208': 'I', 2560 '\u020A': 'I', 2561 '\u1ECA': 'I', 2562 '\u012E': 'I', 2563 '\u1E2C': 'I', 2564 '\u0197': 'I', 2565 '\u24BF': 'J', 2566 '\uFF2A': 'J', 2567 '\u0134': 'J', 2568 '\u0248': 'J', 2569 '\u24C0': 'K', 2570 '\uFF2B': 'K', 2571 '\u1E30': 'K', 2572 '\u01E8': 'K', 2573 '\u1E32': 'K', 2574 '\u0136': 'K', 2575 '\u1E34': 'K', 2576 '\u0198': 'K', 2577 '\u2C69': 'K', 2578 '\uA740': 'K', 2579 '\uA742': 'K', 2580 '\uA744': 'K', 2581 '\uA7A2': 'K', 2582 '\u24C1': 'L', 2583 '\uFF2C': 'L', 2584 '\u013F': 'L', 2585 '\u0139': 'L', 2586 '\u013D': 'L', 2587 '\u1E36': 'L', 2588 '\u1E38': 'L', 2589 '\u013B': 'L', 2590 '\u1E3C': 'L', 2591 '\u1E3A': 'L', 2592 '\u0141': 'L', 2593 '\u023D': 'L', 2594 '\u2C62': 'L', 2595 '\u2C60': 'L', 2596 '\uA748': 'L', 2597 '\uA746': 'L', 2598 '\uA780': 'L', 2599 '\u01C7': 'LJ', 2600 '\u01C8': 'Lj', 2601 '\u24C2': 'M', 2602 '\uFF2D': 'M', 2603 '\u1E3E': 'M', 2604 '\u1E40': 'M', 2605 '\u1E42': 'M', 2606 '\u2C6E': 'M', 2607 '\u019C': 'M', 2608 '\u24C3': 'N', 2609 '\uFF2E': 'N', 2610 '\u01F8': 'N', 2611 '\u0143': 'N', 2612 '\u00D1': 'N', 2613 '\u1E44': 'N', 2614 '\u0147': 'N', 2615 '\u1E46': 'N', 2616 '\u0145': 'N', 2617 '\u1E4A': 'N', 2618 '\u1E48': 'N', 2619 '\u0220': 'N', 2620 '\u019D': 'N', 2621 '\uA790': 'N', 2622 '\uA7A4': 'N', 2623 '\u01CA': 'NJ', 2624 '\u01CB': 'Nj', 2625 '\u24C4': 'O', 2626 '\uFF2F': 'O', 2627 '\u00D2': 'O', 2628 '\u00D3': 'O', 2629 '\u00D4': 'O', 2630 '\u1ED2': 'O', 2631 '\u1ED0': 'O', 2632 '\u1ED6': 'O', 2633 '\u1ED4': 'O', 2634 '\u00D5': 'O', 2635 '\u1E4C': 'O', 2636 '\u022C': 'O', 2637 '\u1E4E': 'O', 2638 '\u014C': 'O', 2639 '\u1E50': 'O', 2640 '\u1E52': 'O', 2641 '\u014E': 'O', 2642 '\u022E': 'O', 2643 '\u0230': 'O', 2644 '\u00D6': 'O', 2645 '\u022A': 'O', 2646 '\u1ECE': 'O', 2647 '\u0150': 'O', 2648 '\u01D1': 'O', 2649 '\u020C': 'O', 2650 '\u020E': 'O', 2651 '\u01A0': 'O', 2652 '\u1EDC': 'O', 2653 '\u1EDA': 'O', 2654 '\u1EE0': 'O', 2655 '\u1EDE': 'O', 2656 '\u1EE2': 'O', 2657 '\u1ECC': 'O', 2658 '\u1ED8': 'O', 2659 '\u01EA': 'O', 2660 '\u01EC': 'O', 2661 '\u00D8': 'O', 2662 '\u01FE': 'O', 2663 '\u0186': 'O', 2664 '\u019F': 'O', 2665 '\uA74A': 'O', 2666 '\uA74C': 'O', 2667 '\u0152': 'OE', 2668 '\u01A2': 'OI', 2669 '\uA74E': 'OO', 2670 '\u0222': 'OU', 2671 '\u24C5': 'P', 2672 '\uFF30': 'P', 2673 '\u1E54': 'P', 2674 '\u1E56': 'P', 2675 '\u01A4': 'P', 2676 '\u2C63': 'P', 2677 '\uA750': 'P', 2678 '\uA752': 'P', 2679 '\uA754': 'P', 2680 '\u24C6': 'Q', 2681 '\uFF31': 'Q', 2682 '\uA756': 'Q', 2683 '\uA758': 'Q', 2684 '\u024A': 'Q', 2685 '\u24C7': 'R', 2686 '\uFF32': 'R', 2687 '\u0154': 'R', 2688 '\u1E58': 'R', 2689 '\u0158': 'R', 2690 '\u0210': 'R', 2691 '\u0212': 'R', 2692 '\u1E5A': 'R', 2693 '\u1E5C': 'R', 2694 '\u0156': 'R', 2695 '\u1E5E': 'R', 2696 '\u024C': 'R', 2697 '\u2C64': 'R', 2698 '\uA75A': 'R', 2699 '\uA7A6': 'R', 2700 '\uA782': 'R', 2701 '\u24C8': 'S', 2702 '\uFF33': 'S', 2703 '\u1E9E': 'S', 2704 '\u015A': 'S', 2705 '\u1E64': 'S', 2706 '\u015C': 'S', 2707 '\u1E60': 'S', 2708 '\u0160': 'S', 2709 '\u1E66': 'S', 2710 '\u1E62': 'S', 2711 '\u1E68': 'S', 2712 '\u0218': 'S', 2713 '\u015E': 'S', 2714 '\u2C7E': 'S', 2715 '\uA7A8': 'S', 2716 '\uA784': 'S', 2717 '\u24C9': 'T', 2718 '\uFF34': 'T', 2719 '\u1E6A': 'T', 2720 '\u0164': 'T', 2721 '\u1E6C': 'T', 2722 '\u021A': 'T', 2723 '\u0162': 'T', 2724 '\u1E70': 'T', 2725 '\u1E6E': 'T', 2726 '\u0166': 'T', 2727 '\u01AC': 'T', 2728 '\u01AE': 'T', 2729 '\u023E': 'T', 2730 '\uA786': 'T', 2731 '\uA728': 'TZ', 2732 '\u24CA': 'U', 2733 '\uFF35': 'U', 2734 '\u00D9': 'U', 2735 '\u00DA': 'U', 2736 '\u00DB': 'U', 2737 '\u0168': 'U', 2738 '\u1E78': 'U', 2739 '\u016A': 'U', 2740 '\u1E7A': 'U', 2741 '\u016C': 'U', 2742 '\u00DC': 'U', 2743 '\u01DB': 'U', 2744 '\u01D7': 'U', 2745 '\u01D5': 'U', 2746 '\u01D9': 'U', 2747 '\u1EE6': 'U', 2748 '\u016E': 'U', 2749 '\u0170': 'U', 2750 '\u01D3': 'U', 2751 '\u0214': 'U', 2752 '\u0216': 'U', 2753 '\u01AF': 'U', 2754 '\u1EEA': 'U', 2755 '\u1EE8': 'U', 2756 '\u1EEE': 'U', 2757 '\u1EEC': 'U', 2758 '\u1EF0': 'U', 2759 '\u1EE4': 'U', 2760 '\u1E72': 'U', 2761 '\u0172': 'U', 2762 '\u1E76': 'U', 2763 '\u1E74': 'U', 2764 '\u0244': 'U', 2765 '\u24CB': 'V', 2766 '\uFF36': 'V', 2767 '\u1E7C': 'V', 2768 '\u1E7E': 'V', 2769 '\u01B2': 'V', 2770 '\uA75E': 'V', 2771 '\u0245': 'V', 2772 '\uA760': 'VY', 2773 '\u24CC': 'W', 2774 '\uFF37': 'W', 2775 '\u1E80': 'W', 2776 '\u1E82': 'W', 2777 '\u0174': 'W', 2778 '\u1E86': 'W', 2779 '\u1E84': 'W', 2780 '\u1E88': 'W', 2781 '\u2C72': 'W', 2782 '\u24CD': 'X', 2783 '\uFF38': 'X', 2784 '\u1E8A': 'X', 2785 '\u1E8C': 'X', 2786 '\u24CE': 'Y', 2787 '\uFF39': 'Y', 2788 '\u1EF2': 'Y', 2789 '\u00DD': 'Y', 2790 '\u0176': 'Y', 2791 '\u1EF8': 'Y', 2792 '\u0232': 'Y', 2793 '\u1E8E': 'Y', 2794 '\u0178': 'Y', 2795 '\u1EF6': 'Y', 2796 '\u1EF4': 'Y', 2797 '\u01B3': 'Y', 2798 '\u024E': 'Y', 2799 '\u1EFE': 'Y', 2800 '\u24CF': 'Z', 2801 '\uFF3A': 'Z', 2802 '\u0179': 'Z', 2803 '\u1E90': 'Z', 2804 '\u017B': 'Z', 2805 '\u017D': 'Z', 2806 '\u1E92': 'Z', 2807 '\u1E94': 'Z', 2808 '\u01B5': 'Z', 2809 '\u0224': 'Z', 2810 '\u2C7F': 'Z', 2811 '\u2C6B': 'Z', 2812 '\uA762': 'Z', 2813 '\u24D0': 'a', 2814 '\uFF41': 'a', 2815 '\u1E9A': 'a', 2816 '\u00E0': 'a', 2817 '\u00E1': 'a', 2818 '\u00E2': 'a', 2819 '\u1EA7': 'a', 2820 '\u1EA5': 'a', 2821 '\u1EAB': 'a', 2822 '\u1EA9': 'a', 2823 '\u00E3': 'a', 2824 '\u0101': 'a', 2825 '\u0103': 'a', 2826 '\u1EB1': 'a', 2827 '\u1EAF': 'a', 2828 '\u1EB5': 'a', 2829 '\u1EB3': 'a', 2830 '\u0227': 'a', 2831 '\u01E1': 'a', 2832 '\u00E4': 'a', 2833 '\u01DF': 'a', 2834 '\u1EA3': 'a', 2835 '\u00E5': 'a', 2836 '\u01FB': 'a', 2837 '\u01CE': 'a', 2838 '\u0201': 'a', 2839 '\u0203': 'a', 2840 '\u1EA1': 'a', 2841 '\u1EAD': 'a', 2842 '\u1EB7': 'a', 2843 '\u1E01': 'a', 2844 '\u0105': 'a', 2845 '\u2C65': 'a', 2846 '\u0250': 'a', 2847 '\uA733': 'aa', 2848 '\u00E6': 'ae', 2849 '\u01FD': 'ae', 2850 '\u01E3': 'ae', 2851 '\uA735': 'ao', 2852 '\uA737': 'au', 2853 '\uA739': 'av', 2854 '\uA73B': 'av', 2855 '\uA73D': 'ay', 2856 '\u24D1': 'b', 2857 '\uFF42': 'b', 2858 '\u1E03': 'b', 2859 '\u1E05': 'b', 2860 '\u1E07': 'b', 2861 '\u0180': 'b', 2862 '\u0183': 'b', 2863 '\u0253': 'b', 2864 '\u24D2': 'c', 2865 '\uFF43': 'c', 2866 '\u0107': 'c', 2867 '\u0109': 'c', 2868 '\u010B': 'c', 2869 '\u010D': 'c', 2870 '\u00E7': 'c', 2871 '\u1E09': 'c', 2872 '\u0188': 'c', 2873 '\u023C': 'c', 2874 '\uA73F': 'c', 2875 '\u2184': 'c', 2876 '\u24D3': 'd', 2877 '\uFF44': 'd', 2878 '\u1E0B': 'd', 2879 '\u010F': 'd', 2880 '\u1E0D': 'd', 2881 '\u1E11': 'd', 2882 '\u1E13': 'd', 2883 '\u1E0F': 'd', 2884 '\u0111': 'd', 2885 '\u018C': 'd', 2886 '\u0256': 'd', 2887 '\u0257': 'd', 2888 '\uA77A': 'd', 2889 '\u01F3': 'dz', 2890 '\u01C6': 'dz', 2891 '\u24D4': 'e', 2892 '\uFF45': 'e', 2893 '\u00E8': 'e', 2894 '\u00E9': 'e', 2895 '\u00EA': 'e', 2896 '\u1EC1': 'e', 2897 '\u1EBF': 'e', 2898 '\u1EC5': 'e', 2899 '\u1EC3': 'e', 2900 '\u1EBD': 'e', 2901 '\u0113': 'e', 2902 '\u1E15': 'e', 2903 '\u1E17': 'e', 2904 '\u0115': 'e', 2905 '\u0117': 'e', 2906 '\u00EB': 'e', 2907 '\u1EBB': 'e', 2908 '\u011B': 'e', 2909 '\u0205': 'e', 2910 '\u0207': 'e', 2911 '\u1EB9': 'e', 2912 '\u1EC7': 'e', 2913 '\u0229': 'e', 2914 '\u1E1D': 'e', 2915 '\u0119': 'e', 2916 '\u1E19': 'e', 2917 '\u1E1B': 'e', 2918 '\u0247': 'e', 2919 '\u025B': 'e', 2920 '\u01DD': 'e', 2921 '\u24D5': 'f', 2922 '\uFF46': 'f', 2923 '\u1E1F': 'f', 2924 '\u0192': 'f', 2925 '\uA77C': 'f', 2926 '\u24D6': 'g', 2927 '\uFF47': 'g', 2928 '\u01F5': 'g', 2929 '\u011D': 'g', 2930 '\u1E21': 'g', 2931 '\u011F': 'g', 2932 '\u0121': 'g', 2933
2933 '\u01E7': 'g', 2934 '\u0123': 'g', 2935 '\u01E5': 'g', 2936 '\u0260': 'g', 2937 '\uA7A1': 'g', 2938 '\u1D79': 'g', 2939 '\uA77F': 'g', 2940 '\u24D7': 'h', 2941 '\uFF48': 'h', 2942 '\u0125': 'h', 2943 '\u1E23': 'h', 2944 '\u1E27': 'h', 2945 '\u021F': 'h', 2946 '\u1E25': 'h', 2947 '\u1E29': 'h', 2948 '\u1E2B': 'h', 2949 '\u1E96': 'h', 2950 '\u0127': 'h', 2951 '\u2C68': 'h', 2952 '\u2C76': 'h', 2953 '\u0265': 'h', 2954 '\u0195': 'hv', 2955 '\u24D8': 'i', 2956 '\uFF49': 'i', 2957 '\u00EC': 'i', 2958 '\u00ED': 'i', 2959 '\u00EE': 'i', 2960 '\u0129': 'i', 2961 '\u012B': 'i', 2962 '\u012D': 'i', 2963 '\u00EF': 'i', 2964 '\u1E2F': 'i', 2965 '\u1EC9': 'i', 2966 '\u01D0': 'i', 2967 '\u0209': 'i', 2968 '\u020B': 'i', 2969 '\u1ECB': 'i', 2970 '\u012F': 'i', 2971 '\u1E2D': 'i', 2972 '\u0268': 'i', 2973 '\u0131': 'i', 2974 '\u24D9': 'j', 2975 '\uFF4A': 'j', 2976 '\u0135': 'j', 2977 '\u01F0': 'j', 2978 '\u0249': 'j', 2979 '\u24DA': 'k', 2980 '\uFF4B': 'k', 2981 '\u1E31': 'k', 2982 '\u01E9': 'k', 2983 '\u1E33': 'k', 2984 '\u0137': 'k', 2985 '\u1E35': 'k', 2986 '\u0199': 'k', 2987 '\u2C6A': 'k', 2988 '\uA741': 'k', 2989 '\uA743': 'k', 2990 '\uA745': 'k', 2991 '\uA7A3': 'k', 2992 '\u24DB': 'l', 2993 '\uFF4C': 'l', 2994 '\u0140': 'l', 2995 '\u013A': 'l', 2996 '\u013E': 'l', 2997 '\u1E37': 'l', 2998 '\u1E39': 'l', 2999 '\u013C': 'l', 3000 '\u1E3D': 'l', 3001 '\u1E3B': 'l', 3002 '\u017F': 'l', 3003 '\u0142': 'l', 3004 '\u019A': 'l', 3005 '\u026B': 'l', 3006 '\u2C61': 'l', 3007 '\uA749': 'l', 3008 '\uA781': 'l', 3009 '\uA747': 'l', 3010 '\u01C9': 'lj', 3011 '\u24DC': 'm', 3012 '\uFF4D': 'm', 3013 '\u1E3F': 'm', 3014 '\u1E41': 'm', 3015 '\u1E43': 'm', 3016 '\u0271': 'm', 3017 '\u026F': 'm', 3018 '\u24DD': 'n', 3019 '\uFF4E': 'n', 3020 '\u01F9': 'n', 3021 '\u0144': 'n', 3022 '\u00F1': 'n', 3023 '\u1E45': 'n', 3024 '\u0148': 'n', 3025 '\u1E47': 'n', 3026 '\u0146': 'n', 3027 '\u1E4B': 'n', 3028 '\u1E49': 'n', 3029 '\u019E': 'n', 3030 '\u0272': 'n', 3031 '\u0149': 'n', 3032 '\uA791': 'n', 3033 '\uA7A5': 'n', 3034 '\u01CC': 'nj', 3035 '\u24DE': 'o', 3036 '\uFF4F': 'o', 3037 '\u00F2': 'o', 3038 '\u00F3': 'o', 3039 '\u00F4': 'o', 3040 '\u1ED3': 'o', 3041 '\u1ED1': 'o', 3042 '\u1ED7': 'o', 3043 '\u1ED5': 'o', 3044 '\u00F5': 'o', 3045 '\u1E4D': 'o', 3046 '\u022D': 'o', 3047 '\u1E4F': 'o', 3048 '\u014D': 'o', 3049 '\u1E51': 'o', 3050 '\u1E53': 'o', 3051 '\u014F': 'o', 3052 '\u022F': 'o', 3053 '\u0231': 'o', 3054 '\u00F6': 'o', 3055 '\u022B': 'o', 3056 '\u1ECF': 'o', 3057 '\u0151': 'o', 3058 '\u01D2': 'o', 3059 '\u020D': 'o', 3060 '\u020F': 'o', 3061 '\u01A1': 'o', 3062 '\u1EDD': 'o', 3063 '\u1EDB': 'o', 3064 '\u1EE1': 'o', 3065 '\u1EDF': 'o', 3066 '\u1EE3': 'o', 3067 '\u1ECD': 'o', 3068 '\u1ED9': 'o', 3069 '\u01EB': 'o', 3070 '\u01ED': 'o', 3071 '\u00F8': 'o', 3072 '\u01FF': 'o', 3073 '\u0254': 'o', 3074 '\uA74B': 'o', 3075 '\uA74D': 'o', 3076 '\u0275': 'o', 3077 '\u0153': 'oe', 3078 '\u01A3': 'oi', 3079 '\u0223': 'ou', 3080 '\uA74F': 'oo', 3081 '\u24DF': 'p', 3082 '\uFF50': 'p', 3083 '\u1E55': 'p', 3084 '\u1E57': 'p', 3085 '\u01A5': 'p', 3086 '\u1D7D': 'p', 3087 '\uA751': 'p', 3088 '\uA753': 'p', 3089 '\uA755': 'p', 3090 '\u24E0': 'q', 3091 '\uFF51': 'q', 3092 '\u024B': 'q', 3093 '\uA757': 'q', 3094 '\uA759': 'q', 3095 '\u24E1': 'r', 3096 '\uFF52': 'r', 3097 '\u0155': 'r', 3098 '\u1E59': 'r', 3099 '\u0159': 'r', 3100 '\u0211': 'r', 3101 '\u0213': 'r', 3102 '\u1E5B': 'r', 3103 '\u1E5D': 'r', 3104 '\u0157': 'r', 3105 '\u1E5F': 'r', 3106 '\u024D': 'r', 3107 '\u027D': 'r', 3108 '\uA75B': 'r', 3109 '\uA7A7': 'r', 3110 '\uA783': 'r',
vendor: 96,631 bytes, lines 3111-5888
3111 '\u24E2': 's', 3112 '\uFF53': 's', 3113 '\u00DF': 's', 3114 '\u015B': 's', 3115 '\u1E65': 's', 3116 '\u015D': 's', 3117 '\u1E61': 's', 3118 '\u0161': 's', 3119 '\u1E67': 's', 3120 '\u1E63': 's', 3121 '\u1E69': 's', 3122 '\u0219': 's', 3123 '\u015F': 's', 3124 '\u023F': 's', 3125 '\uA7A9': 's', 3126 '\uA785': 's', 3127 '\u1E9B': 's', 3128 '\u24E3': 't', 3129 '\uFF54': 't', 3130 '\u1E6B': 't', 3131 '\u1E97': 't', 3132 '\u0165': 't', 3133 '\u1E6D': 't', 3134 '\u021B': 't', 3135 '\u0163': 't', 3136 '\u1E71': 't', 3137 '\u1E6F': 't', 3138 '\u0167': 't', 3139 '\u01AD': 't', 3140 '\u0288': 't', 3141 '\u2C66': 't', 3142 '\uA787': 't', 3143 '\uA729': 'tz', 3144 '\u24E4': 'u', 3145 '\uFF55': 'u', 3146 '\u00F9': 'u', 3147 '\u00FA': 'u', 3148 '\u00FB': 'u', 3149 '\u0169': 'u', 3150 '\u1E79': 'u', 3151 '\u016B': 'u', 3152 '\u1E7B': 'u', 3153 '\u016D': 'u', 3154 '\u00FC': 'u', 3155 '\u01DC': 'u', 3156 '\u01D8': 'u', 3157 '\u01D6': 'u', 3158 '\u01DA': 'u', 3159 '\u1EE7': 'u', 3160 '\u016F': 'u', 3161 '\u0171': 'u', 3162 '\u01D4': 'u', 3163 '\u0215': 'u', 3164 '\u0217': 'u', 3165 '\u01B0': 'u', 3166 '\u1EEB': 'u', 3167 '\u1EE9': 'u', 3168 '\u1EEF': 'u', 3169 '\u1EED': 'u', 3170 '\u1EF1': 'u', 3171 '\u1EE5': 'u', 3172 '\u1E73': 'u', 3173 '\u0173': 'u', 3174 '\u1E77': 'u', 3175 '\u1E75': 'u', 3176 '\u0289': 'u', 3177 '\u24E5': 'v', 3178 '\uFF56': 'v', 3179 '\u1E7D': 'v', 3180 '\u1E7F': 'v', 3181 '\u028B': 'v', 3182 '\uA75F': 'v', 3183 '\u028C': 'v', 3184 '\uA761': 'vy', 3185 '\u24E6': 'w', 3186 '\uFF57': 'w', 3187 '\u1E81': 'w', 3188 '\u1E83': 'w', 3189 '\u0175': 'w', 3190 '\u1E87': 'w', 3191 '\u1E85': 'w', 3192 '\u1E98': 'w', 3193 '\u1E89': 'w', 3194 '\u2C73': 'w', 3195 '\u24E7': 'x', 3196 '\uFF58': 'x', 3197 '\u1E8B': 'x', 3198 '\u1E8D': 'x', 3199 '\u24E8': 'y', 3200 '\uFF59': 'y', 3201 '\u1EF3': 'y', 3202 '\u00FD': 'y', 3203 '\u0177': 'y', 3204 '\u1EF9': 'y', 3205 '\u0233': 'y', 3206 '\u1E8F': 'y', 3207 '\u00FF': 'y', 3208 '\u1EF7': 'y', 3209 '\u1E99': 'y', 3210 '\u1EF5': 'y', 3211 '\u01B4': 'y', 3212 '\u024F': 'y', 3213 '\u1EFF': 'y', 3214 '\u24E9': 'z', 3215 '\uFF5A': 'z', 3216 '\u017A': 'z', 3217 '\u1E91': 'z', 3218 '\u017C': 'z', 3219 '\u017E': 'z', 3220 '\u1E93': 'z', 3221 '\u1E95': 'z', 3222 '\u01B6': 'z', 3223 '\u0225': 'z', 3224 '\u0240': 'z', 3225 '\u2C6C': 'z', 3226 '\uA763': 'z', 3227 '\u0386': '\u0391', 3228 '\u0388': '\u0395', 3229 '\u0389': '\u0397', 3230 '\u038A': '\u0399', 3231 '\u03AA': '\u0399', 3232 '\u038C': '\u039F', 3233 '\u038E': '\u03A5', 3234 '\u03AB': '\u03A5', 3235 '\u038F': '\u03A9', 3236 '\u03AC': '\u03B1', 3237 '\u03AD': '\u03B5', 3238 '\u03AE': '\u03B7', 3239 '\u03AF': '\u03B9', 3240 '\u03CA': '\u03B9', 3241 '\u0390': '\u03B9', 3242 '\u03CC': '\u03BF', 3243 '\u03CD': '\u03C5', 3244 '\u03CB': '\u03C5', 3245 '\u03B0': '\u03C5', 3246 '\u03CE': '\u03C9', 3247 '\u03C2': '\u03C3', 3248 '\u2019': '\'' 3249 }; 3250 3251 return diacritics; 3252 }); 3253 3254 S2.define('select2/data/base', [ 3255 '../utils' 3256 ], function (Utils) { 3257 function BaseAdapter($element, options) { 3258 BaseAdapter.__super__.constructor.call(this); 3259 } 3260 3261 Utils.Extend(BaseAdapter, Utils.Observable); 3262 3263 BaseAdapter.prototype.current = function (callback) { 3264 throw new Error('The `current` method must be defined in child classes.'); 3265 }; 3266 3267 BaseAdapter.prototype.query = function (params, callback) { 3268 throw new Error('The `query` method must be defined in child classes.'); 3269 }; 3270 3271 BaseAdapter.prototype.bind = function (container, $container) { 3272 // Can be implemented in subclasses 3273 }; 3274 3275 BaseAdapter.prototype.destroy = function () { 3276 // Can be implemented in subclasses 3277 }; 3278 3279 BaseAdapter.prototype.generateResultId = function (container, data) { 3280 var id = container.id + '-result-'; 3281 3282 id += Utils.generateChars(4); 3283 3284 if (data.id != null) { 3285 id += '-' + data.id.toString(); 3286 } else { 3287 id += '-' + Utils.generateChars(4); 3288 } 3289 return id; 3290 }; 3291 3292 return BaseAdapter; 3293 }); 3294 3295 S2.define('select2/data/select', [ 3296 './base', 3297 '../utils', 3298 'jquery' 3299 ], function (BaseAdapter, Utils, $) { 3300 function SelectAdapter($element, options) { 3301 this.$element = $element; 3302 this.options = options; 3303 3304 SelectAdapter.__super__.constructor.call(this); 3305 } 3306 3307 Utils.Extend(SelectAdapter, BaseAdapter); 3308 3309 SelectAdapter.prototype.current = function (callback) { 3310 var self = this; 3311 3312 var data = Array.prototype.map.call( 3313 this.$element[0].querySelectorAll(':checked'), 3314 function (selectedElement) { 3315 return self.item($(selectedElement)); 3316 } 3317 ); 3318 3319 callback(data); 3320 }; 3321 3322 SelectAdapter.prototype.select = function (data) { 3323 var self = this; 3324 3325 data.selected = true; 3326 3327 // If data.element is a DOM node, use it instead 3328 if ( 3329 data.element != null && data.element.tagName.toLowerCase() === 'option' 3330 ) { 3331 data.element.selected = true; 3332 3333 this.$element.trigger('input').trigger('change'); 3334 3335 return; 3336 } 3337 3338 if (this.$element.prop('multiple')) { 3339 this.current(function (currentData) { 3340 var val = []; 3341 3342 data = [data]; 3343 data.push.apply(data, currentData); 3344 3345 for (var d = 0; d < data.length; d++) { 3346 var id = data[d].id; 3347 3348 if (val.indexOf(id) === -1) { 3349 val.push(id); 3350 } 3351 } 3352 3353 self.$element.val(val); 3354 self.$element.trigger('input').trigger('change'); 3355 }); 3356 } else { 3357 var val = data.id; 3358 3359 this.$element.val(val); 3360 this.$element.trigger('input').trigger('change'); 3361 } 3362 }; 3363 3364 SelectAdapter.prototype.unselect = function (data) { 3365 var self = this; 3366 3367 if (!this.$element.prop('multiple')) { 3368 return; 3369 } 3370 3371 data.selected = false; 3372 3373 if ( 3374 data.element != null && 3375 data.element.tagName.toLowerCase() === 'option' 3376 ) { 3377 data.element.selected = false; 3378 3379 this.$element.trigger('input').trigger('change'); 3380 3381 return; 3382 } 3383 3384 this.current(function (currentData) { 3385 var val = []; 3386 3387 for (var d = 0; d < currentData.length; d++) { 3388 var id = currentData[d].id; 3389 3390 if (id !== data.id && val.indexOf(id) === -1) { 3391 val.push(id); 3392 } 3393 } 3394 3395 self.$element.val(val); 3396 3397 self.$element.trigger('input').trigger('change'); 3398 }); 3399 }; 3400 3401 SelectAdapter.prototype.bind = function (container, $container) { 3402 var self = this; 3403 3404 this.container = container; 3405 3406 container.on('select', function (params) { 3407 self.select(params.data); 3408 }); 3409 3410 container.on('unselect', function (params) { 3411 self.unselect(params.data); 3412 }); 3413 }; 3414 3415 SelectAdapter.prototype.destroy = function () { 3416 // Remove anything added to child elements 3417 this.$element.find('*').each(function () { 3418 // Remove any custom data set by Select2 3419 Utils.RemoveData(this); 3420 }); 3421 }; 3422 3423 SelectAdapter.prototype.query = function (params, callback) { 3424 var data = []; 3425 var self = this; 3426 3427 var $options = this.$element.children(); 3428 3429 $options.each(function () { 3430 if ( 3431 this.tagName.toLowerCase() !== 'option' && 3432 this.tagName.toLowerCase() !== 'optgroup' 3433 ) { 3434 return; 3435 } 3436 3437 var $option = $(this); 3438 3439 var option = self.item($option); 3440 3441 var matches = self.matches(params, option); 3442 3443 if (matches !== null) { 3444 data.push(matches); 3445 } 3446 }); 3447 3448 callback({ 3449 results: data 3450 }); 3451 }; 3452 3453 SelectAdapter.prototype.addOptions = function ($options) { 3454 this.$element.append($options); 3455 }; 3456 3457 SelectAdapter.prototype.option = function (data) { 3458 var option; 3459 3460 if (data.children) { 3461 option = document.createElement('optgroup'); 3462 option.label = data.text; 3463 } else { 3464 option = document.createElement('option'); 3465 3466 if (option.textContent !== undefined) { 3467 option.textContent = data.text; 3468 } else { 3469 option.innerText = data.text; 3470 } 3471 } 3472 3473 if (data.id !== undefined) { 3474 option.value = data.id; 3475 } 3476 3477 if (data.disabled) { 3478 option.disabled = true; 3479 } 3480 3481 if (data.selected) { 3482 option.selected = true; 3483 } 3484 3485 if (data.title) { 3486 option.title = data.title; 3487 } 3488 3489 var normalizedData = this._normalizeItem(data); 3490 normalizedData.element = option; 3491 3492 // Override the option's data with the combined data 3493 Utils.StoreData(option, 'data', normalizedData); 3494 3495 return $(option); 3496 }; 3497 3498 SelectAdapter.prototype.item = function ($option) { 3499 var data = {}; 3500 3501 data = Utils.GetData($option[0], 'data'); 3502 3503 if (data != null) { 3504 return data; 3505 } 3506 3507 var option = $option[0]; 3508 3509 if (option.tagName.toLowerCase() === 'option') { 3510 data = { 3511 id: $option.val(), 3512 text: $option.text(), 3513 disabled: $option.prop('disabled'), 3514 selected: $option.prop('selected'), 3515 title: $option.prop('title') 3516 }; 3517 } else if (option.tagName.toLowerCase() === 'optgroup') { 3518 data = { 3519 text: $option.prop('label'), 3520 children: [], 3521 title: $option.prop('title') 3522 }; 3523 3524 var $children = $option.children('option'); 3525 var children = []; 3526 3527 for (var c = 0; c < $children.length; c++) { 3528 var $child = $($children[c]); 3529 3530 var child = this.item($child); 3531 3532 children.push(child); 3533 } 3534 3535 data.children = children; 3536 } 3537 3538 data = this._normalizeItem(data); 3539 data.element = $option[0]; 3540 3541 Utils.StoreData($option[0], 'data', data); 3542 3543 return data; 3544 }; 3545 3546 SelectAdapter.prototype._normalizeItem = function (item) { 3547 if (item !== Object(item)) { 3548 item = { 3549 id: item, 3550 text: item 3551 }; 3552 } 3553 3554 item = $.extend({}, { 3555 text: '' 3556 }, item); 3557 3558 var defaults = { 3559 selected: false, 3560 disabled: false 3561 }; 3562 3563 if (item.id != null) { 3564 item.id = item.id.toString(); 3565 } 3566 3567 if (item.text != null) { 3568 item.text = item.text.toString(); 3569 } 3570 3571 if (item._resultId == null && item.id && this.container != null) { 3572 item._resultId = this.generateResultId(this.container, item); 3573 } 3574 3575 return $.extend({}, defaults, item); 3576 }; 3577 3578 SelectAdapter.prototype.matches = function (params, data) { 3579 var matcher = this.options.get('matcher'); 3580 3581 return matcher(params, data); 3582 }; 3583 3584 return SelectAdapter; 3585 }); 3586 3587 S2.define('select2/data/array', [ 3588 './select', 3589 '../utils', 3590 'jquery' 3591 ], function (SelectAdapter, Utils, $) { 3592 function ArrayAdapter($element, options) { 3593 this._dataToConvert = options.get('data') || []; 3594 3595 ArrayAdapter.__super__.constructor.call(this, $element, options); 3596 } 3597 3598 Utils.Extend(ArrayAdapter, SelectAdapter); 3599 3600 ArrayAdapter.prototype.bind = function (container, $container) { 3601 ArrayAdapter.__super__.bind.call(this, container, $container); 3602 3603 this.addOptions(this.convertToOptions(this._dataToConvert)); 3604 }; 3605 3606 ArrayAdapter.prototype.select = function (data) { 3607 var $option = this.$element.find('option').filter(function (i, elm) { 3608 return elm.value == data.id.toString(); 3609 }); 3610 3611 if ($option.length === 0) { 3612 $option = this.option(data); 3613 3614 this.addOptions($option); 3615 } 3616 3617 ArrayAdapter.__super__.select.call(this, data); 3618 }; 3619 3620 ArrayAdapter.prototype.convertToOptions = function (data) { 3621 var self = this; 3622 3623 var $existing = this.$element.find('option'); 3624 var existingIds = $existing.map(function () { 3625 return self.item($(this)).id; 3626 }).get(); 3627 3628 var $options = []; 3629 3630 // Filter out all items except for the one passed in the argument 3631 function onlyItem(item) { 3632 return function () { 3633 return $(this).val() == item.id; 3634 }; 3635 } 3636 3637 for (var d = 0; d < data.length; d++) { 3638 var item = this._normalizeItem(data[d]); 3639 3640 // Skip items which were pre-loaded, only merge the data 3641 if (existingIds.indexOf(item.id) >= 0) { 3642 var $existingOption = $existing.filter(onlyItem(item)); 3643 3644 var existingData = this.item($existingOption); 3645 var newData = $.extend(true, {}, item, existingData); 3646 3647 var $newOption = this.option(newData); 3648 3649 $existingOption.replaceWith($newOption); 3650 3651 continue; 3652 } 3653 3654 var $option = this.option(item); 3655 3656 if (item.children) { 3657 var $children = this.convertToOptions(item.children); 3658 3659 $option.append($children); 3660 } 3661 3662 $options.push($option); 3663 } 3664 3665 return $options; 3666 }; 3667 3668 return ArrayAdapter; 3669 }); 3670 3671 S2.define('select2/data/ajax', [ 3672 './array', 3673 '../utils', 3674 'jquery' 3675 ], function (ArrayAdapter, Utils, $) { 3676 function AjaxAdapter($element, options) { 3677 this.ajaxOptions = this._applyDefaults(options.get('ajax')); 3678 3679 if (this.ajaxOptions.processResults != null) { 3680 this.processResults = this.ajaxOptions.processResults; 3681 } 3682 3683 AjaxAdapter.__super__.constructor.call(this, $element, options); 3684 } 3685 3686 Utils.Extend(AjaxAdapter, ArrayAdapter); 3687 3688 AjaxAdapter.prototype._applyDefaults = function (options) { 3689 var defaults = { 3690 data: function (params) { 3691 return $.extend({}, params, { 3692 q: params.term 3693 }); 3694 }, 3695 transport: function (params, success, failure) { 3696 var $request = $.ajax(params); 3697 3698 $request.then(success); 3699 $request.fail(failure); 3700 3701 return $request; 3702 } 3703 }; 3704 3705 return $.extend({}, defaults, options, true); 3706 }; 3707 3708 AjaxAdapter.prototype.processResults = function (results) { 3709 return results; 3710 }; 3711 3712 AjaxAdapter.prototype.query = function (params, callback) { 3713 var matches = []; 3714 var self = this; 3715 3716 if (this._request != null) { 3717 // JSONP requests cannot always be aborted 3718 if (typeof this._request.abort === 'function') { 3719 this._request.abort(); 3720 } 3721 3722 this._request = null; 3723 } 3724 3725 var options = $.extend({ 3726 type: 'GET' 3727 }, this.ajaxOptions); 3728 3729 if (typeof options.url === 'function') { 3730 options.url = options.url.call(this.$element, params); 3731 } 3732 3733 if (typeof options.data === 'function') { 3734 options.data = options.data.call(this.$element, params); 3735 } 3736 3737 function request() { 3738 var $request = options.transport(options, function (data) { 3739 var results = self.processResults(data, params); 3740 3741 if (self.options.get('debug') && window.console && console.error) { 3742 // Check to make sure that the response included a `results` key. 3743 if (!results || !results.results || !Array.isArray(results.results)) { 3744 console.error( 3745 'Select2: The AJAX results did not return an array in the ' + 3746 '`results` key of the response.' 3747 ); 3748 } 3749 } 3750 3751 callback(results); 3752 }, function () { 3753 // Attempt to detect if a request was aborted 3754 // Only works if the transport exposes a status property 3755 if ('status' in $request && 3756 ($request.status === 0 || $request.status === '0')) { 3757 return; 3758 } 3759 3760 self.trigger('results:message', { 3761 message: 'errorLoading' 3762 }); 3763 }); 3764 3765 self._request = $request; 3766 } 3767 3768 if (this.ajaxOptions.delay && params.term != null) { 3769 if (this._queryTimeout) { 3770 window.clearTimeout(this._queryTimeout); 3771 } 3772 3773 this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); 3774 } else { 3775 request(); 3776 } 3777 }; 3778 3779 return AjaxAdapter; 3780 }); 3781 3782 S2.define('select2/data/tags', [ 3783 'jquery' 3784 ], function ($) { 3785 function Tags(decorated, $element, options) { 3786 var tags = options.get('tags'); 3787 3788 var createTag = options.get('createTag'); 3789 3790 if (createTag !== undefined) { 3791 this.createTag = createTag; 3792 } 3793 3794 var insertTag = options.get('insertTag'); 3795 3796 if (insertTag !== undefined) { 3797 this.insertTag = insertTag; 3798 } 3799 3800 decorated.call(this, $element, options); 3801 3802 if (Array.isArray(tags)) { 3803 for (var t = 0; t < tags.length; t++) { 3804 var tag = tags[t]; 3805 var item = this._normalizeItem(tag); 3806 3807 var $option = this.option(item); 3808 3809 this.$element.append($option); 3810 } 3811 } 3812 } 3813 3814 Tags.prototype.query = function (decorated, params, callback) { 3815 var self = this; 3816 3817 this._removeOldTags(); 3818 3819 if (params.term == null || params.page != null) { 3820 decorated.call(this, params, callback); 3821 return; 3822 } 3823 3824 function wrapper(obj, child) { 3825 var data = obj.results; 3826 3827 for (var i = 0; i < data.length; i++) { 3828 var option = data[i]; 3829 3830 var checkChildren = ( 3831 option.children != null && 3832 !wrapper({ 3833 results: option.children 3834 }, true) 3835 ); 3836 3837 var optionText = (option.text || '').toUpperCase(); 3838 var paramsTerm = (params.term || '').toUpperCase(); 3839 3840 var checkText = optionText === paramsTerm; 3841 3842 if (checkText || checkChildren) { 3843 if (child) { 3844 return false; 3845 } 3846 3847 obj.data = data; 3848 callback(obj); 3849 3850 return; 3851 } 3852 } 3853 3854 if (child) { 3855 return true; 3856 } 3857 3858 var tag = self.createTag(params); 3859 3860 if (tag != null) { 3861 var $option = self.option(tag); 3862 $option.attr('data-select2-tag', 'true'); 3863 3864 self.addOptions([$option]); 3865 3866 self.insertTag(data, tag); 3867 } 3868 3869 obj.results = data; 3870 3871 callback(obj); 3872 } 3873 3874 decorated.call(this, params, wrapper); 3875 }; 3876 3877 Tags.prototype.createTag = function (decorated, params) { 3878 if (params.term == null) { 3879 return null; 3880 } 3881 3882 var term = params.term.trim(); 3883 3884 if (term === '') { 3885 return null; 3886 } 3887 3888 return { 3889 id: term, 3890 text: term 3891 }; 3892 }; 3893 3894 Tags.prototype.insertTag = function (_, data, tag) { 3895 data.unshift(tag); 3896 }; 3897 3898 Tags.prototype._removeOldTags = function (_) { 3899 var $options = this.$element.find('option[data-select2-tag]'); 3900 3901 $options.each(function () { 3902 if (this.selected) { 3903 return; 3904 } 3905 3906 $(this).remove(); 3907 }); 3908 }; 3909 3910 return Tags; 3911 }); 3912 3913 S2.define('select2/data/tokenizer', [ 3914 'jquery' 3915 ], function ($) { 3916 function Tokenizer(decorated, $element, options) { 3917 var tokenizer = options.get('tokenizer'); 3918 3919 if (tokenizer !== undefined) { 3920 this.tokenizer = tokenizer; 3921 } 3922 3923 decorated.call(this, $element, options); 3924 } 3925 3926 Tokenizer.prototype.bind = function (decorated, container, $container) { 3927 decorated.call(this, container, $container); 3928 3929 this.$search = container.dropdown.$search || container.selection.$search || 3930 $container.find('.select2-search__field'); 3931 }; 3932 3933 Tokenizer.prototype.query = function (decorated, params, callback) { 3934 var self = this; 3935 3936 function createAndSelect(data) { 3937 // Normalize the data object so we can use it for checks 3938 var item = self._normalizeItem(data); 3939 3940 // Check if the data object already exists as a tag 3941 // Select it if it doesn't 3942 var $existingOptions = self.$element.find('option').filter(function () { 3943 return $(this).val() === item.id; 3944 }); 3945 3946 // If an existing option wasn't found for it, create the option 3947 if (!$existingOptions.length) { 3948 var $option = self.option(item); 3949 $option.attr('data-select2-tag', true); 3950 3951 self._removeOldTags(); 3952 self.addOptions([$option]); 3953 } 3954 3955 // Select the item, now that we know there is an option for it 3956 select(item); 3957 } 3958 3959 function select(data) { 3960 self.trigger('select', { 3961 data: data 3962 }); 3963 } 3964 3965 params.term = params.term || ''; 3966 3967 var tokenData = this.tokenizer(params, this.options, createAndSelect); 3968 3969 if (tokenData.term !== params.term) { 3970 // Replace the search term if we have the search box 3971 if (this.$search.length) { 3972 this.$search.val(tokenData.term); 3973 this.$search.trigger('focus'); 3974 } 3975 3976 params.term = tokenData.term; 3977 } 3978 3979 decorated.call(this, params, callback); 3980 }; 3981 3982 Tokenizer.prototype.tokenizer = function (_, params, options, callback) { 3983 var separators = options.get('tokenSeparators') || []; 3984 var term = params.term; 3985 var i = 0; 3986 3987 var createTag = this.createTag || function (params) { 3988 return { 3989 id: params.term, 3990 text: params.term 3991 }; 3992 }; 3993 3994 while (i < term.length) { 3995 var termChar = term[i]; 3996 3997 if (separators.indexOf(termChar) === -1) { 3998 i++; 3999 4000 continue; 4001 } 4002 4003 var part = term.substr(0, i); 4004 var partParams = $.extend({}, params, { 4005 term: part 4006 }); 4007 4008 var data = createTag(partParams); 4009 4010 if (data == null) { 4011 i++; 4012 continue; 4013 } 4014 4015 callback(data); 4016 4017 // Reset the term to not include the tokenized portion 4018 term = term.substr(i + 1) || ''; 4019 i = 0; 4020 } 4021 4022 return { 4023 term: term 4024 }; 4025 }; 4026 4027 return Tokenizer; 4028 }); 4029 4030 S2.define('select2/data/minimumInputLength', [ 4031 4032 ], function () { 4033 function MinimumInputLength(decorated, $e, options) { 4034 this.minimumInputLength = options.get('minimumInputLength'); 4035 4036 decorated.call(this, $e, options); 4037 } 4038 4039 MinimumInputLength.prototype.query = function (decorated, params, callback) { 4040 params.term = params.term || ''; 4041 4042 if (params.term.length < this.minimumInputLength) { 4043 this.trigger('results:message', { 4044 message: 'inputTooShort', 4045 args: { 4046 minimum: this.minimumInputLength, 4047 input: params.term, 4048 params: params 4049 } 4050 }); 4051 4052 return; 4053 } 4054 4055 decorated.call(this, params, callback); 4056 }; 4057 4058 return MinimumInputLength; 4059 }); 4060 4061 S2.define('select2/data/maximumInputLength', [ 4062 4063 ], function () { 4064 function MaximumInputLength(decorated, $e, options) { 4065 this.maximumInputLength = options.get('maximumInputLength'); 4066 4067 decorated.call(this, $e, options); 4068 } 4069 4070 MaximumInputLength.prototype.query = function (decorated, params, callback) { 4071 params.term = params.term || ''; 4072 4073 if (this.maximumInputLength > 0 && 4074 params.term.length > this.maximumInputLength) { 4075 this.trigger('results:message', { 4076 message: 'inputTooLong', 4077 args: { 4078 maximum: this.maximumInputLength, 4079 input: params.term, 4080 params: params 4081 } 4082 }); 4083 4084 return; 4085 } 4086 4087 decorated.call(this, params, callback); 4088 }; 4089 4090 return MaximumInputLength; 4091 }); 4092 4093 S2.define('select2/data/maximumSelectionLength', [ 4094 4095 ], function () { 4096 function MaximumSelectionLength(decorated, $e, options) { 4097 this.maximumSelectionLength = options.get('maximumSelectionLength'); 4098 4099 decorated.call(this, $e, options); 4100 } 4101 4102 MaximumSelectionLength.prototype.bind = 4103 function (decorated, container, $container) { 4104 var self = this; 4105 4106 decorated.call(this, container, $container); 4107 4108 container.on('select', function () { 4109 self._checkIfMaximumSelected(); 4110 }); 4111 }; 4112 4113 MaximumSelectionLength.prototype.query = 4114 function (decorated, params, callback) { 4115 var self = this; 4116 4117 this._checkIfMaximumSelected(function () { 4118 decorated.call(self, params, callback); 4119 }); 4120 }; 4121 4122 MaximumSelectionLength.prototype._checkIfMaximumSelected = 4123 function (_, successCallback) { 4124 var self = this; 4125 4126 this.current(function (currentData) { 4127 var count = currentData != null ? currentData.length : 0; 4128 if (self.maximumSelectionLength > 0 && 4129 count >= self.maximumSelectionLength) { 4130 self.trigger('results:message', { 4131 message: 'maximumSelected', 4132 args: { 4133 maximum: self.maximumSelectionLength 4134 } 4135 }); 4136 return; 4137 } 4138 4139 if (successCallback) { 4140 successCallback(); 4141 } 4142 }); 4143 }; 4144 4145 return MaximumSelectionLength; 4146 }); 4147 4148 S2.define('select2/dropdown', [ 4149 'jquery', 4150 './utils' 4151 ], function ($, Utils) { 4152 function Dropdown($element, options) { 4153 this.$element = $element; 4154 this.options = options; 4155 4156 Dropdown.__super__.constructor.call(this); 4157 } 4158 4159 Utils.Extend(Dropdown, Utils.Observable); 4160 4161 Dropdown.prototype.render = function () { 4162 var $dropdown = $( 4163 '<span class="select2-dropdown">' + 4164 '<span class="select2-results"></span>' + 4165 '</span>' 4166 ); 4167 4168 $dropdown.attr('dir', this.options.get('dir')); 4169 4170 this.$dropdown = $dropdown; 4171 4172 return $dropdown; 4173 }; 4174 4175 Dropdown.prototype.bind = function () { 4176 // Should be implemented in subclasses 4177 }; 4178 4179 Dropdown.prototype.position = function ($dropdown, $container) { 4180 // Should be implemented in subclasses 4181 }; 4182 4183 Dropdown.prototype.destroy = function () { 4184 // Remove the dropdown from the DOM 4185 this.$dropdown.remove(); 4186 }; 4187 4188 return Dropdown; 4189 }); 4190 4191 S2.define('select2/dropdown/search', [ 4192 'jquery' 4193 ], function ($) { 4194 function Search() { } 4195 4196 Search.prototype.render = function (decorated) { 4197 var $rendered = decorated.call(this); 4198 var searchLabel = this.options.get('translations').get('search'); 4199 4200 var $search = $( 4201 '<span class="select2-search select2-search--dropdown">' + 4202 '<input class="select2-search__field" type="search" tabindex="-1"' + 4203 ' autocorrect="off" autocapitalize="none"' + 4204 ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' + 4205 '</span>' 4206 ); 4207 4208 this.$searchContainer = $search; 4209 this.$search = $search.find('input'); 4210 4211 this.$search.prop('autocomplete', this.options.get('autocomplete')); 4212 this.$search.attr('aria-label', searchLabel()); 4213 4214 $rendered.prepend($search); 4215 4216 return $rendered; 4217 }; 4218 4219 Search.prototype.bind = function (decorated, container, $container) { 4220 var self = this; 4221 4222 var resultsId = container.id + '-results'; 4223 4224 decorated.call(this, container, $container); 4225 4226 this.$search.on('keydown', function (evt) { 4227 self.trigger('keypress', evt); 4228 4229 self._keyUpPrevented = evt.isDefaultPrevented(); 4230 }); 4231 4232 // Workaround for browsers which do not support the `input` event 4233 // This will prevent double-triggering of events for browsers which support 4234 // both the `keyup` and `input` events. 4235 this.$search.on('input', function (evt) { 4236 // Unbind the duplicated `keyup` event 4237 $(this).off('keyup'); 4238 }); 4239 4240 this.$search.on('keyup input', function (evt) { 4241 self.handleSearch(evt); 4242 }); 4243 4244 container.on('open', function () { 4245 self.$search.attr('tabindex', 0); 4246 self.$search.attr('aria-controls', resultsId); 4247 4248 self.$search.trigger('focus'); 4249 4250 window.setTimeout(function () { 4251 self.$search.trigger('focus'); 4252 }, 0); 4253 }); 4254 4255 container.on('close', function () { 4256 self.$search.attr('tabindex', -1); 4257 self.$search.removeAttr('aria-controls'); 4258 self.$search.removeAttr('aria-activedescendant'); 4259 4260 self.$search.val(''); 4261 self.$search.trigger('blur'); 4262 }); 4263 4264 container.on('focus', function () { 4265 if (!container.isOpen()) { 4266 self.$search.trigger('focus'); 4267 } 4268 }); 4269 4270 container.on('results:all', function (params) { 4271 if (params.query.term == null || params.query.term === '') { 4272 var showSearch = self.showSearch(params); 4273 4274 if (showSearch) { 4275 self.$searchContainer[0].classList.remove('select2-search--hide'); 4276 } else { 4277 self.$searchContainer[0].classList.add('select2-search--hide'); 4278 } 4279 } 4280 }); 4281 4282 container.on('results:focus', function (params) { 4283 if (params.data._resultId) { 4284 self.$search.attr('aria-activedescendant', params.data._resultId); 4285 } else { 4286 self.$search.removeAttr('aria-activedescendant'); 4287 } 4288 }); 4289 }; 4290 4291 Search.prototype.handleSearch = function (evt) { 4292 if (!this._keyUpPrevented) { 4293 var input = this.$search.val(); 4294 4295 this.trigger('query', { 4296 term: input 4297 }); 4298 } 4299 4300 this._keyUpPrevented = false; 4301 }; 4302 4303 Search.prototype.showSearch = function (_, params) { 4304 return true; 4305 }; 4306 4307 return Search; 4308 }); 4309 4310 S2.define('select2/dropdown/hidePlaceholder', [ 4311 4312 ], function () { 4313 function HidePlaceholder(decorated, $element, options, dataAdapter) { 4314 this.placeholder = this.normalizePlaceholder(options.get('placeholder')); 4315 4316 decorated.call(this, $element, options, dataAdapter); 4317 } 4318 4319 HidePlaceholder.prototype.append = function (decorated, data) { 4320 data.results = this.removePlaceholder(data.results); 4321 4322 decorated.call(this, data); 4323 }; 4324 4325 HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) { 4326 if (typeof placeholder === 'string') { 4327 placeholder = { 4328 id: '', 4329 text: placeholder 4330 }; 4331 } 4332 4333 return placeholder; 4334 }; 4335 4336 HidePlaceholder.prototype.removePlaceholder = function (_, data) { 4337 var modifiedData = data.slice(0); 4338 4339 for (var d = data.length - 1; d >= 0; d--) { 4340 var item = data[d]; 4341 4342 if (this.placeholder.id === item.id) { 4343 modifiedData.splice(d, 1); 4344 } 4345 } 4346 4347 return modifiedData; 4348 }; 4349 4350 return HidePlaceholder; 4351 }); 4352 4353 S2.define('select2/dropdown/infiniteScroll', [ 4354 'jquery' 4355 ], function ($) { 4356 function InfiniteScroll(decorated, $element, options, dataAdapter) { 4357 this.lastParams = {}; 4358 4359 decorated.call(this, $element, options, dataAdapter); 4360 4361 this.$loadingMore = this.createLoadingMore(); 4362 this.loading = false; 4363 } 4364 4365 InfiniteScroll.prototype.append = function (decorated, data) { 4366 this.$loadingMore.remove(); 4367 this.loading = false; 4368 4369 decorated.call(this, data); 4370 4371 if (this.showLoadingMore(data)) { 4372 this.$results.append(this.$loadingMore); 4373 this.loadMoreIfNeeded(); 4374 } 4375 }; 4376 4377 InfiniteScroll.prototype.bind = function (decorated, container, $container) { 4378 var self = this; 4379 4380 decorated.call(this, container, $container); 4381 4382 container.on('query', function (params) { 4383 self.lastParams = params; 4384 self.loading = true; 4385 }); 4386 4387 container.on('query:append', function (params) { 4388 self.lastParams = params; 4389 self.loading = true; 4390 }); 4391 4392 this.$results.on('scroll', this.loadMoreIfNeeded.bind(this)); 4393 }; 4394 4395 InfiniteScroll.prototype.loadMoreIfNeeded = function () { 4396 var isLoadMoreVisible = $.contains( 4397 document.documentElement, 4398 this.$loadingMore[0] 4399 ); 4400 4401 if (this.loading || !isLoadMoreVisible) { 4402 return; 4403 } 4404 4405 var currentOffset = this.$results.offset().top + 4406 this.$results.outerHeight(false); 4407 var loadingMoreOffset = this.$loadingMore.offset().top + 4408 this.$loadingMore.outerHeight(false); 4409 4410 if (currentOffset + 50 >= loadingMoreOffset) { 4411 this.loadMore(); 4412 } 4413 }; 4414 4415 InfiniteScroll.prototype.loadMore = function () { 4416 this.loading = true; 4417 4418 var params = $.extend({}, { page: 1 }, this.lastParams); 4419 4420 params.page++; 4421 4422 this.trigger('query:append', params); 4423 }; 4424 4425 InfiniteScroll.prototype.showLoadingMore = function (_, data) { 4426 return data.pagination && data.pagination.more; 4427 }; 4428 4429 InfiniteScroll.prototype.createLoadingMore = function () { 4430 var $option = $( 4431 '<li ' + 4432 'class="select2-results__option select2-results__option--load-more"' + 4433 'role="option" aria-disabled="true"></li>' 4434 ); 4435 4436 var message = this.options.get('translations').get('loadingMore'); 4437 4438 $option.html(message(this.lastParams)); 4439 4440 return $option; 4441 }; 4442 4443 return InfiniteScroll; 4444 }); 4445 4446 S2.define('select2/dropdown/attachBody', [ 4447 'jquery', 4448 '../utils' 4449 ], function ($, Utils) { 4450 function AttachBody(decorated, $element, options) { 4451 this.$dropdownParent = $(options.get('dropdownParent') || document.body); 4452 4453 decorated.call(this, $element, options); 4454 } 4455 4456 AttachBody.prototype.bind = function (decorated, container, $container) { 4457 var self = this; 4458 4459 decorated.call(this, container, $container); 4460 4461 container.on('open', function () { 4462 self._showDropdown(); 4463 self._attachPositioningHandler(container); 4464 4465 // Must bind after the results handlers to ensure correct sizing 4466 self._bindContainerResultHandlers(container); 4467 }); 4468 4469 container.on('close', function () { 4470 self._hideDropdown(); 4471 self._detachPositioningHandler(container); 4472 }); 4473 4474 this.$dropdownContainer.on('mousedown', function (evt) { 4475 evt.stopPropagation(); 4476 }); 4477 }; 4478 4479 AttachBody.prototype.destroy = function (decorated) { 4480 decorated.call(this); 4481 4482 this.$dropdownContainer.remove(); 4483 }; 4484 4485 AttachBody.prototype.position = function (decorated, $dropdown, $container) { 4486 // Clone all of the container classes 4487 $dropdown.attr('class', $container.attr('class')); 4488 4489 $dropdown[0].classList.remove('select2'); 4490 $dropdown[0].classList.add('select2-container--open'); 4491 4492 $dropdown.css({ 4493 position: 'absolute', 4494 top: -999999 4495 }); 4496 4497 this.$container = $container; 4498 }; 4499 4500 AttachBody.prototype.render = function (decorated) { 4501 var $container = $('<span></span>'); 4502 4503 var $dropdown = decorated.call(this); 4504 $container.append($dropdown); 4505 4506 this.$dropdownContainer = $container; 4507 4508 return $container; 4509 }; 4510 4511 AttachBody.prototype._hideDropdown = function (decorated) { 4512 this.$dropdownContainer.detach(); 4513 }; 4514 4515 AttachBody.prototype._bindContainerResultHandlers = 4516 function (decorated, container) { 4517 4518 // These should only be bound once 4519 if (this._containerResultsHandlersBound) { 4520 return; 4521 } 4522 4523 var self = this; 4524 4525 container.on('results:all', function () { 4526 self._positionDropdown(); 4527 self._resizeDropdown(); 4528 }); 4529 4530 container.on('results:append', function () { 4531 self._positionDropdown(); 4532 self._resizeDropdown(); 4533 }); 4534 4535 container.on('results:message', function () { 4536 self._positionDropdown(); 4537 self._resizeDropdown(); 4538 }); 4539 4540 container.on('select', function () { 4541 self._positionDropdown(); 4542 self._resizeDropdown(); 4543 }); 4544 4545 container.on('unselect', function () { 4546 self._positionDropdown(); 4547 self._resizeDropdown(); 4548 }); 4549 4550 this._containerResultsHandlersBound = true; 4551 }; 4552 4553 AttachBody.prototype._attachPositioningHandler = 4554 function (decorated, container) { 4555 var self = this; 4556 4557 var scrollEvent = 'scroll.select2.' + container.id; 4558 var resizeEvent = 'resize.select2.' + container.id; 4559 var orientationEvent = 'orientationchange.select2.' + container.id; 4560 4561 var $watchers = this.$container.parents().filter(Utils.hasScroll); 4562 $watchers.each(function () { 4563 Utils.StoreData(this, 'select2-scroll-position', { 4564 x: $(this).scrollLeft(), 4565 y: $(this).scrollTop() 4566 }); 4567 }); 4568 4569 $watchers.on(scrollEvent, function (ev) { 4570 var position = Utils.GetData(this, 'select2-scroll-position'); 4571 $(this).scrollTop(position.y); 4572 }); 4573 4574 $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent, 4575 function (e) { 4576 self._positionDropdown(); 4577 self._resizeDropdown(); 4578 }); 4579 }; 4580 4581 AttachBody.prototype._detachPositioningHandler = 4582 function (decorated, container) { 4583 var scrollEvent = 'scroll.select2.' + container.id; 4584 var resizeEvent = 'resize.select2.' + container.id; 4585 var orientationEvent = 'orientationchange.select2.' + container.id; 4586 4587 var $watchers = this.$container.parents().filter(Utils.hasScroll); 4588 $watchers.off(scrollEvent); 4589 4590 $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent); 4591 }; 4592 4593 AttachBody.prototype._positionDropdown = function () { 4594 var $window = $(window); 4595 4596 var isCurrentlyAbove = this.$dropdown[0].classList 4597 .contains('select2-dropdown--above'); 4598 var isCurrentlyBelow = this.$dropdown[0].classList 4599 .contains('select2-dropdown--below'); 4600 4601 var newDirection = null; 4602 4603 var offset = this.$container.offset(); 4604 4605 offset.bottom = offset.top + this.$container.outerHeight(false); 4606 4607 var container = { 4608 height: this.$container.outerHeight(false) 4609 }; 4610 4611 container.top = offset.top; 4612 container.bottom = offset.top + container.height; 4613 4614 var dropdown = { 4615 height: this.$dropdown.outerHeight(false) 4616 }; 4617 4618 var viewport = { 4619 top: $window.scrollTop(), 4620 bottom: $window.scrollTop() + $window.height() 4621 }; 4622 4623 var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); 4624 var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); 4625 4626 var css = { 4627 left: offset.left, 4628 top: container.bottom 4629 }; 4630 4631 // Determine what the parent element is to use for calculating the offset 4632 var $offsetParent = this.$dropdownParent; 4633 4634 // For statically positioned elements, we need to get the element 4635 // that is determining the offset 4636 if ($offsetParent.css('position') === 'static') { 4637 $offsetParent = $offsetParent.offsetParent(); 4638 } 4639 4640 var parentOffset = { 4641 top: 0, 4642 left: 0 4643 }; 4644 4645 if ( 4646 $.contains(document.body, $offsetParent[0]) || 4647 $offsetParent[0].isConnected 4648 ) { 4649 parentOffset = $offsetParent.offset(); 4650 } 4651 4652 css.top -= parentOffset.top; 4653 css.left -= parentOffset.left; 4654 4655 if (!isCurrentlyAbove && !isCurrentlyBelow) { 4656 newDirection = 'below'; 4657 } 4658 4659 if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { 4660 newDirection = 'above'; 4661 } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { 4662 newDirection = 'below'; 4663 } 4664 4665 if (newDirection == 'above' || 4666 (isCurrentlyAbove && newDirection !== 'below')) { 4667 css.top = container.top - parentOffset.top - dropdown.height; 4668 } 4669 4670 if (newDirection != null) { 4671 this.$dropdown[0].classList.remove('select2-dropdown--below'); 4672 this.$dropdown[0].classList.remove('select2-dropdown--above'); 4673 this.$dropdown[0].classList.add('select2-dropdown--' + newDirection); 4674 4675 this.$container[0].classList.remove('select2-container--below'); 4676 this.$container[0].classList.remove('select2-container--above'); 4677 this.$container[0].classList.add('select2-container--' + newDirection); 4678 } 4679 4680 this.$dropdownContainer.css(css); 4681 }; 4682 4683 AttachBody.prototype._resizeDropdown = function () { 4684 var css = { 4685 width: this.$container.outerWidth(false) + 'px' 4686 }; 4687 4688 if (this.options.get('dropdownAutoWidth')) { 4689 css.minWidth = css.width; 4690 css.position = 'relative'; 4691 css.width = 'auto'; 4692 } 4693 4694 this.$dropdown.css(css); 4695 }; 4696 4697 AttachBody.prototype._showDropdown = function (decorated) { 4698 this.$dropdownContainer.appendTo(this.$dropdownParent); 4699 4700 this._positionDropdown(); 4701 this._resizeDropdown(); 4702 }; 4703 4704 return AttachBody; 4705 }); 4706 4707 S2.define('select2/dropdown/minimumResultsForSearch', [ 4708 4709 ], function () { 4710 function countResults(data) { 4711 var count = 0; 4712 4713 for (var d = 0; d < data.length; d++) { 4714 var item = data[d]; 4715 4716 if (item.children) { 4717 count += countResults(item.children); 4718 } else { 4719 count++; 4720 } 4721 } 4722 4723 return count; 4724 } 4725 4726 function MinimumResultsForSearch(decorated, $element, options, dataAdapter) { 4727 this.minimumResultsForSearch = options.get('minimumResultsForSearch'); 4728 4729 if (this.minimumResultsForSearch < 0) { 4730 this.minimumResultsForSearch = Infinity; 4731 } 4732 4733 decorated.call(this, $element, options, dataAdapter); 4734 } 4735 4736 MinimumResultsForSearch.prototype.showSearch = function (decorated, params) { 4737 if (countResults(params.data.results) < this.minimumResultsForSearch) { 4738 return false; 4739 } 4740 4741 return decorated.call(this, params); 4742 }; 4743 4744 return MinimumResultsForSearch; 4745 }); 4746 4747 S2.define('select2/dropdown/selectOnClose', [ 4748 '../utils' 4749 ], function (Utils) { 4750 function SelectOnClose() { } 4751 4752 SelectOnClose.prototype.bind = function (decorated, container, $container) { 4753 var self = this; 4754 4755 decorated.call(this, container, $container); 4756 4757 container.on('close', function (params) { 4758 self._handleSelectOnClose(params); 4759 }); 4760 }; 4761 4762 SelectOnClose.prototype._handleSelectOnClose = function (_, params) { 4763 if (params && params.originalSelect2Event != null) { 4764 var event = params.originalSelect2Event; 4765 4766 // Don't select an item if the close event was triggered from a select or 4767 // unselect event 4768 if (event._type === 'select' || event._type === 'unselect') { 4769 return; 4770 } 4771 } 4772 4773 var $highlightedResults = this.getHighlightedResults(); 4774 4775 // Only select highlighted results 4776 if ($highlightedResults.length < 1) { 4777 return; 4778 } 4779 4780 var data = Utils.GetData($highlightedResults[0], 'data'); 4781 4782 // Don't re-select already selected resulte 4783 if ( 4784 (data.element != null && data.element.selected) || 4785 (data.element == null && data.selected) 4786 ) { 4787 return; 4788 } 4789 4790 this.trigger('select', { 4791 data: data 4792 }); 4793 }; 4794 4795 return SelectOnClose; 4796 }); 4797 4798 S2.define('select2/dropdown/closeOnSelect', [ 4799 4800 ], function () { 4801 function CloseOnSelect() { } 4802 4803 CloseOnSelect.prototype.bind = function (decorated, container, $container) { 4804 var self = this; 4805 4806 decorated.call(this, container, $container); 4807 4808 container.on('select', function (evt) { 4809 self._selectTriggered(evt); 4810 }); 4811 4812 container.on('unselect', function (evt) { 4813 self._selectTriggered(evt); 4814 }); 4815 }; 4816 4817 CloseOnSelect.prototype._selectTriggered = function (_, evt) { 4818 var originalEvent = evt.originalEvent; 4819 4820 // Don't close if the control key is being held 4821 if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) { 4822 return; 4823 } 4824 4825 this.trigger('close', { 4826 originalEvent: originalEvent, 4827 originalSelect2Event: evt 4828 }); 4829 }; 4830 4831 return CloseOnSelect; 4832 }); 4833 4834 S2.define('select2/dropdown/dropdownCss', [ 4835 '../utils' 4836 ], function (Utils) { 4837 function DropdownCSS() { } 4838 4839 DropdownCSS.prototype.render = function (decorated) { 4840 var $dropdown = decorated.call(this); 4841 4842 var dropdownCssClass = this.options.get('dropdownCssClass') || ''; 4843 4844 if (dropdownCssClass.indexOf(':all:') !== -1) { 4845 dropdownCssClass = dropdownCssClass.replace(':all:', ''); 4846 4847 Utils.copyNonInternalCssClasses($dropdown[0], this.$element[0]); 4848 } 4849 4850 $dropdown.addClass(dropdownCssClass); 4851 4852 return $dropdown; 4853 }; 4854 4855 return DropdownCSS; 4856 }); 4857 4858 S2.define('select2/dropdown/tagsSearchHighlight', [ 4859 '../utils' 4860 ], function (Utils) { 4861 function TagsSearchHighlight() { } 4862 4863 TagsSearchHighlight.prototype.highlightFirstItem = function (decorated) { 4864 var $options = this.$results 4865 .find( 4866 '.select2-results__option--selectable' + 4867 ':not(.select2-results__option--selected)' 4868 ); 4869 4870 if ($options.length > 0) { 4871 var $firstOption = $options.first(); 4872 var data = Utils.GetData($firstOption[0], 'data'); 4873 var firstElement = data.element; 4874 4875 if (firstElement && firstElement.getAttribute) { 4876 if (firstElement.getAttribute('data-select2-tag') === 'true') { 4877 $firstOption.trigger('mouseenter'); 4878 4879 return; 4880 } 4881 } 4882 } 4883 4884 decorated.call(this); 4885 }; 4886 4887 return TagsSearchHighlight; 4888 }); 4889 4890 S2.define('select2/i18n/en', [], function () { 4891 // English 4892 return { 4893 errorLoading: function () { 4894 return 'The results could not be loaded.'; 4895 }, 4896 inputTooLong: function (args) { 4897 var overChars = args.input.length - args.maximum; 4898 4899 var message = 'Please delete ' + overChars + ' character'; 4900 4901 if (overChars != 1) { 4902 message += 's'; 4903 } 4904 4905 return message; 4906 }, 4907 inputTooShort: function (args) { 4908 var remainingChars = args.minimum - args.input.length; 4909 4910 var message = 'Please enter ' + remainingChars + ' or more characters'; 4911 4912 return message; 4913 }, 4914 loadingMore: function () { 4915 return 'Loading more resultsâ¦'; 4916 }, 4917 maximumSelected: function (args) { 4918 var message = 'You can only select ' + args.maximum + ' item'; 4919 4920 if (args.maximum != 1) { 4921 message += 's'; 4922 } 4923 4924 return message; 4925 }, 4926 noResults: function () { 4927 return 'No results found'; 4928 }, 4929 searching: function () { 4930 return 'Searchingâ¦'; 4931 }, 4932 removeAllItems: function () { 4933 return 'Remove all items'; 4934 }, 4935 removeItem: function () { 4936 return 'Remove item'; 4937 }, 4938 search: function () { 4939 return 'Search'; 4940 } 4941 }; 4942 }); 4943 4944 S2.define('select2/defaults', [ 4945 'jquery', 4946 4947 './results', 4948 4949 './selection/single', 4950 './selection/multiple', 4951 './selection/placeholder', 4952 './selection/allowClear', 4953 './selection/search', 4954 './selection/selectionCss', 4955 './selection/eventRelay', 4956 4957 './utils', 4958 './translation', 4959 './diacritics', 4960 4961 './data/select', 4962 './data/array', 4963 './data/ajax', 4964 './data/tags', 4965 './data/tokenizer', 4966 './data/minimumInputLength', 4967 './data/maximumInputLength', 4968 './data/maximumSelectionLength', 4969 4970 './dropdown', 4971 './dropdown/search', 4972 './dropdown/hidePlaceholder', 4973 './dropdown/infiniteScroll', 4974 './dropdown/attachBody', 4975 './dropdown/minimumResultsForSearch', 4976 './dropdown/selectOnClose', 4977 './dropdown/closeOnSelect', 4978 './dropdown/dropdownCss', 4979 './dropdown/tagsSearchHighlight', 4980 4981 './i18n/en' 4982 ], function ($, 4983 4984 ResultsList, 4985 4986 SingleSelection, MultipleSelection, Placeholder, AllowClear, 4987 SelectionSearch, SelectionCSS, EventRelay, 4988 4989 Utils, Translation, DIACRITICS, 4990 4991 SelectData, ArrayData, AjaxData, Tags, Tokenizer, 4992 MinimumInputLength, MaximumInputLength, MaximumSelectionLength, 4993 4994 Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll, 4995 AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect, 4996 DropdownCSS, TagsSearchHighlight, 4997 4998 EnglishTranslation) { 4999 function Defaults() { 5000 this.reset(); 5001 } 5002 5003 Defaults.prototype.apply = function (options) { 5004 options = $.extend(true, {}, this.defaults, options); 5005 5006 if (options.dataAdapter == null) { 5007 if (options.ajax != null) { 5008 options.dataAdapter = AjaxData; 5009 } else if (options.data != null) { 5010 options.dataAdapter = ArrayData; 5011 } else { 5012 options.dataAdapter = SelectData; 5013 } 5014 5015 if (options.minimumInputLength > 0) { 5016 options.dataAdapter = Utils.Decorate( 5017 options.dataAdapter, 5018 MinimumInputLength 5019 ); 5020 } 5021 5022 if (options.maximumInputLength > 0) { 5023 options.dataAdapter = Utils.Decorate( 5024 options.dataAdapter, 5025 MaximumInputLength 5026 ); 5027 } 5028 5029 if (options.maximumSelectionLength > 0) { 5030 options.dataAdapter = Utils.Decorate( 5031 options.dataAdapter, 5032 MaximumSelectionLength 5033 ); 5034 } 5035 5036 if (options.tags) { 5037 options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); 5038 } 5039 5040 if (options.tokenSeparators != null || options.tokenizer != null) { 5041 options.dataAdapter = Utils.Decorate( 5042 options.dataAdapter, 5043 Tokenizer 5044 ); 5045 } 5046 } 5047 5048 if (options.resultsAdapter == null) { 5049 options.resultsAdapter = ResultsList; 5050 5051 if (options.ajax != null) { 5052 options.resultsAdapter = Utils.Decorate( 5053 options.resultsAdapter, 5054 InfiniteScroll 5055 ); 5056 } 5057 5058 if (options.placeholder != null) { 5059 options.resultsAdapter = Utils.Decorate( 5060 options.resultsAdapter, 5061 HidePlaceholder 5062 ); 5063 } 5064 5065 if (options.selectOnClose) { 5066 options.resultsAdapter = Utils.Decorate( 5067 options.resultsAdapter, 5068 SelectOnClose 5069 ); 5070 } 5071 5072 if (options.tags) { 5073 options.resultsAdapter = Utils.Decorate( 5074 options.resultsAdapter, 5075 TagsSearchHighlight 5076 ); 5077 } 5078 } 5079 5080 if (options.dropdownAdapter == null) { 5081 if (options.multiple) { 5082 options.dropdownAdapter = Dropdown; 5083 } else { 5084 var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch); 5085 5086 options.dropdownAdapter = SearchableDropdown; 5087 } 5088 5089 if (options.minimumResultsForSearch !== 0) { 5090 options.dropdownAdapter = Utils.Decorate( 5091 options.dropdownAdapter, 5092 MinimumResultsForSearch 5093 ); 5094 } 5095 5096 if (options.closeOnSelect) { 5097 options.dropdownAdapter = Utils.Decorate( 5098 options.dropdownAdapter, 5099 CloseOnSelect 5100 ); 5101 } 5102 5103 if (options.dropdownCssClass != null) { 5104 options.dropdownAdapter = Utils.Decorate( 5105 options.dropdownAdapter, 5106 DropdownCSS 5107 ); 5108 } 5109 5110 options.dropdownAdapter = Utils.Decorate( 5111 options.dropdownAdapter, 5112 AttachBody 5113 ); 5114 } 5115 5116 if (options.selectionAdapter == null) { 5117 if (options.multiple) { 5118 options.selectionAdapter = MultipleSelection; 5119 } else { 5120 options.selectionAdapter = SingleSelection; 5121 } 5122 5123 // Add the placeholder mixin if a placeholder was specified 5124 if (options.placeholder != null) { 5125 options.selectionAdapter = Utils.Decorate( 5126 options.selectionAdapter, 5127 Placeholder 5128 ); 5129 } 5130 5131 if (options.allowClear) { 5132 options.selectionAdapter = Utils.Decorate( 5133 options.selectionAdapter, 5134 AllowClear 5135 ); 5136 } 5137 5138 if (options.multiple) { 5139 options.selectionAdapter = Utils.Decorate( 5140 options.selectionAdapter, 5141 SelectionSearch 5142 ); 5143 } 5144 5145 if (options.selectionCssClass != null) { 5146 options.selectionAdapter = Utils.Decorate( 5147 options.selectionAdapter, 5148 SelectionCSS 5149 ); 5150 } 5151 5152 options.selectionAdapter = Utils.Decorate( 5153 options.selectionAdapter, 5154 EventRelay 5155 ); 5156 } 5157 5158 // If the defaults were not previously applied from an element, it is 5159 // possible for the language option to have not been resolved 5160 options.language = this._resolveLanguage(options.language); 5161 5162 // Always fall back to English since it will always be complete 5163 options.language.push('en'); 5164 5165 var uniqueLanguages = []; 5166 5167 for (var l = 0; l < options.language.length; l++) { 5168 var language = options.language[l]; 5169 5170 if (uniqueLanguages.indexOf(language) === -1) { 5171 uniqueLanguages.push(language); 5172 } 5173 } 5174 5175 options.language = uniqueLanguages; 5176 5177 options.translations = this._processTranslations( 5178 options.language, 5179 options.debug 5180 ); 5181 5182 return options; 5183 }; 5184 5185 Defaults.prototype.reset = function () { 5186 function stripDiacritics(text) { 5187 // Used 'uni range + named function' from http://jsperf.com/diacritics/18 5188 function match(a) { 5189 return DIACRITICS[a] || a; 5190 } 5191 5192 return text.replace(/[^\u0000-\u007E]/g, match); 5193 } 5194 5195 function matcher(params, data) { 5196 // Always return the object if there is nothing to compare 5197 if (params.term == null || params.term.trim() === '') { 5198 return data; 5199 } 5200 5201 // Do a recursive check for options with children 5202 if (data.children && data.children.length > 0) { 5203 // Clone the data object if there are children 5204 // This is required as we modify the object to remove any non-matches 5205 var match = $.extend(true, {}, data); 5206 5207 // Check each child of the option 5208 for (var c = data.children.length - 1; c >= 0; c--) { 5209 var child = data.children[c]; 5210 5211 var matches = matcher(params, child); 5212 5213 // If there wasn't a match, remove the object in the array 5214 if (matches == null) { 5215 match.children.splice(c, 1); 5216 } 5217 } 5218 5219 // If any children matched, return the new object 5220 if (match.children.length > 0) { 5221 return match; 5222 } 5223 5224 // If there were no matching children, check just the plain object 5225 return matcher(params, match); 5226 } 5227 5228 var original = stripDiacritics(data.text).toUpperCase(); 5229 var term = stripDiacritics(params.term).toUpperCase(); 5230 5231 // Check if the text contains the term 5232 if (original.indexOf(term) > -1) { 5233 return data; 5234 } 5235 5236 // If it doesn't contain the term, don't return anything 5237 return null; 5238 } 5239 5240 this.defaults = { 5241 amdLanguageBase: './i18n/', 5242 autocomplete: 'off', 5243 closeOnSelect: true, 5244 debug: false, 5245 dropdownAutoWidth: false, 5246 escapeMarkup: Utils.escapeMarkup, 5247 language: {}, 5248 matcher: matcher, 5249 minimumInputLength: 0, 5250 maximumInputLength: 0, 5251 maximumSelectionLength: 0, 5252 minimumResultsForSearch: 0, 5253 selectOnClose: false, 5254 scrollAfterSelect: false, 5255 sorter: function (data) { 5256 return data; 5257 }, 5258 templateResult: function (result) { 5259 return result.text; 5260 }, 5261 templateSelection: function (selection) { 5262 return selection.text; 5263 }, 5264 theme: 'default', 5265 width: 'resolve' 5266 }; 5267 }; 5268 5269 Defaults.prototype.applyFromElement = function (options, $element) { 5270 var optionLanguage = options.language; 5271 var defaultLanguage = this.defaults.language; 5272 var elementLanguage = $element.prop('lang'); 5273 var parentLanguage = $element.closest('[lang]').prop('lang'); 5274 5275 var languages = Array.prototype.concat.call( 5276 this._resolveLanguage(elementLanguage), 5277 this._resolveLanguage(optionLanguage), 5278 this._resolveLanguage(defaultLanguage), 5279 this._resolveLanguage(parentLanguage) 5280 ); 5281 5282 options.language = languages; 5283 5284 return options; 5285 }; 5286 5287 Defaults.prototype._resolveLanguage = function (language) { 5288 if (!language) { 5289 return []; 5290 } 5291 5292 if ($.isEmptyObject(language)) { 5293 return []; 5294 } 5295 5296 if ($.isPlainObject(language)) { 5297 return [language]; 5298 } 5299 5300 var languages; 5301 5302 if (!Array.isArray(language)) { 5303 languages = [language]; 5304 } else { 5305 languages = language; 5306 } 5307 5308 var resolvedLanguages = []; 5309 5310 for (var l = 0; l < languages.length; l++) { 5311 resolvedLanguages.push(languages[l]); 5312 5313 if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) { 5314 // Extract the region information if it is included 5315 var languageParts = languages[l].split('-'); 5316 var baseLanguage = languageParts[0]; 5317 5318 resolvedLanguages.push(baseLanguage); 5319 } 5320 } 5321 5322 return resolvedLanguages; 5323 }; 5324 5325 Defaults.prototype._processTranslations = function (languages, debug) { 5326 var translations = new Translation(); 5327 5328 for (var l = 0; l < languages.length; l++) { 5329 var languageData = new Translation(); 5330 5331 var language = languages[l]; 5332 5333 if (typeof language === 'string') { 5334 try { 5335 // Try to load it with the original name 5336 languageData = Translation.loadPath(language); 5337 } catch (e) { 5338 try { 5339 // If we couldn't load it, check if it wasn't the full path 5340 language = this.defaults.amdLanguageBase + language; 5341 languageData = Translation.loadPath(language); 5342 } catch (ex) { 5343 // The translation could not be loaded at all. Sometimes this is 5344 // because of a configuration problem, other times this can be 5345 // because of how Select2 helps load all possible translation files 5346 if (debug && window.console && console.warn) { 5347 console.warn( 5348 'Select2: The language file for "' + language + '" could ' + 5349 'not be automatically loaded. A fallback will be used instead.' 5350 ); 5351 } 5352 } 5353 } 5354 } else if ($.isPlainObject(language)) { 5355 languageData = new Translation(language); 5356 } else { 5357 languageData = language; 5358 } 5359 5360 translations.extend(languageData); 5361 } 5362 5363 return translations; 5364 }; 5365 5366 Defaults.prototype.set = function (key, value) { 5367 var camelKey = $.camelCase(key); 5368 5369 var data = {}; 5370 data[camelKey] = value; 5371 5372 var convertedData = Utils._convertData(data); 5373 5374 $.extend(true, this.defaults, convertedData); 5375 }; 5376 5377 var defaults = new Defaults(); 5378 5379 return defaults; 5380 }); 5381 5382 S2.define('select2/options', [ 5383 'jquery', 5384 './defaults', 5385 './utils' 5386 ], function ($, Defaults, Utils) { 5387 function Options(options, $element) { 5388 this.options = options; 5389 5390 if ($element != null) { 5391 this.fromElement($element); 5392 } 5393 5394 if ($element != null) { 5395 this.options = Defaults.applyFromElement(this.options, $element); 5396 } 5397 5398 this.options = Defaults.apply(this.options); 5399 } 5400 5401 Options.prototype.fromElement = function ($e) { 5402 var excludedData = ['select2']; 5403 5404 if (this.options.multiple == null) { 5405 this.options.multiple = $e.prop('multiple'); 5406 } 5407 5408 if (this.options.disabled == null) { 5409 this.options.disabled = $e.prop('disabled'); 5410 } 5411 5412 if (this.options.autocomplete == null && $e.prop('autocomplete')) { 5413 this.options.autocomplete = $e.prop('autocomplete'); 5414 } 5415 5416 if (this.options.dir == null) { 5417 if ($e.prop('dir')) { 5418 this.options.dir = $e.prop('dir'); 5419 } else if ($e.closest('[dir]').prop('dir')) { 5420 this.options.dir = $e.closest('[dir]').prop('dir'); 5421 } else { 5422 this.options.dir = 'ltr'; 5423 } 5424 } 5425 5426 $e.prop('disabled', this.options.disabled); 5427 $e.prop('multiple', this.options.multiple); 5428 5429 if (Utils.GetData($e[0], 'select2Tags')) { 5430 if (this.options.debug && window.console && console.warn) { 5431 console.warn( 5432 'Select2: The `data-select2-tags` attribute has been changed to ' + 5433 'use the `data-data` and `data-tags="true"` attributes and will be ' + 5434 'removed in future versions of Select2.' 5435 ); 5436 } 5437 5438 Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags')); 5439 Utils.StoreData($e[0], 'tags', true); 5440 } 5441 5442 if (Utils.GetData($e[0], 'ajaxUrl')) { 5443 if (this.options.debug && window.console && console.warn) { 5444 console.warn( 5445 'Select2: The `data-ajax-url` attribute has been changed to ' + 5446 '`data-ajax--url` and support for the old attribute will be removed' + 5447 ' in future versions of Select2.' 5448 ); 5449 } 5450 5451 $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl')); 5452 Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl')); 5453 } 5454 5455 var dataset = {}; 5456 5457 function upperCaseLetter(_, letter) { 5458 return letter.toUpperCase(); 5459 } 5460 5461 // Pre-load all of the attributes which are prefixed with `data-` 5462 for (var attr = 0; attr < $e[0].attributes.length; attr++) { 5463 var attributeName = $e[0].attributes[attr].name; 5464 var prefix = 'data-'; 5465 5466 if (attributeName.substr(0, prefix.length) == prefix) { 5467 // Get the contents of the attribute after `data-` 5468 var dataName = attributeName.substring(prefix.length); 5469 5470 // Get the data contents from the consistent source 5471 // This is more than likely the jQuery data helper 5472 var dataValue = Utils.GetData($e[0], dataName); 5473 5474 // camelCase the attribute name to match the spec 5475 var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter); 5476 5477 // Store the data attribute contents into the dataset since 5478 dataset[camelDataName] = dataValue; 5479 } 5480 } 5481 5482 // Prefer the element's `dataset` attribute if it exists 5483 // jQuery 1.x does not correctly handle data attributes with multiple dashes 5484 if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { 5485 dataset = $.extend(true, {}, $e[0].dataset, dataset); 5486 } 5487 5488 // Prefer our internal data cache if it exists 5489 var data = $.extend(true, {}, Utils.GetData($e[0]), dataset); 5490 5491 data = Utils._convertData(data); 5492 5493 for (var key in data) { 5494 if (excludedData.indexOf(key) > -1) { 5495 continue; 5496 } 5497 5498 if ($.isPlainObject(this.options[key])) { 5499 $.extend(this.options[key], data[key]); 5500 } else { 5501 this.options[key] = data[key]; 5502 } 5503 } 5504 5505 return this; 5506 }; 5507 5508 Options.prototype.get = function (key) { 5509 return this.options[key]; 5510 }; 5511 5512 Options.prototype.set = function (key, val) { 5513 this.options[key] = val; 5514 }; 5515 5516 return Options; 5517 }); 5518 5519 S2.define('select2/core', [ 5520 'jquery', 5521 './options', 5522 './utils', 5523 './keys' 5524 ], function ($, Options, Utils, KEYS) { 5525 var Select2 = function ($element, options) { 5526 if (Utils.GetData($element[0], 'select2') != null) { 5527 Utils.GetData($element[0], 'select2').destroy(); 5528 } 5529 5530 this.$element = $element; 5531 5532 this.id = this._generateId($element); 5533 5534 options = options || {}; 5535 5536 this.options = new Options(options, $element); 5537 5538 Select2.__super__.constructor.call(this); 5539 5540 // Set up the tabindex 5541 5542 var tabindex = $element.attr('tabindex') || 0; 5543 Utils.StoreData($element[0], 'old-tabindex', tabindex); 5544 $element.attr('tabindex', '-1'); 5545 5546 // Set up containers and adapters 5547 5548 var DataAdapter = this.options.get('dataAdapter'); 5549 this.dataAdapter = new DataAdapter($element, this.options); 5550 5551 var $container = this.render(); 5552 5553 this._placeContainer($container); 5554 5555 var SelectionAdapter = this.options.get('selectionAdapter'); 5556 this.selection = new SelectionAdapter($element, this.options); 5557 this.$selection = this.selection.render(); 5558 5559 this.selection.position(this.$selection, $container); 5560 5561 var DropdownAdapter = this.options.get('dropdownAdapter'); 5562 this.dropdown = new DropdownAdapter($element, this.options); 5563 this.$dropdown = this.dropdown.render(); 5564 5565 this.dropdown.position(this.$dropdown, $container); 5566 5567 var ResultsAdapter = this.options.get('resultsAdapter'); 5568 this.results = new ResultsAdapter($element, this.options, this.dataAdapter); 5569 this.$results = this.results.render(); 5570 5571 this.results.position(this.$results, this.$dropdown); 5572 5573 // Bind events 5574 5575 var self = this; 5576 5577 // Bind the container to all of the adapters 5578 this._bindAdapters(); 5579 5580 // Register any DOM event handlers 5581 this._registerDomEvents(); 5582 5583 // Register any internal event handlers 5584 this._registerDataEvents(); 5585 this._registerSelectionEvents(); 5586 this._registerDropdownEvents(); 5587 this._registerResultsEvents(); 5588 this._registerEvents(); 5589 5590 // Set the initial state 5591 this.dataAdapter.current(function (initialData) { 5592 self.trigger('selection:update', { 5593 data: initialData 5594 }); 5595 }); 5596 5597 // Hide the original select 5598 $element[0].classList.add('select2-hidden-accessible'); 5599 $element.attr('aria-hidden', 'true'); 5600 5601 // Synchronize any monitored attributes 5602 this._syncAttributes(); 5603 5604 Utils.StoreData($element[0], 'select2', this); 5605 5606 // Ensure backwards compatibility with $element.data('select2'). 5607 $element.data('select2', this); 5608 }; 5609 5610 Utils.Extend(Select2, Utils.Observable); 5611 5612 Select2.prototype._generateId = function ($element) { 5613 var id = ''; 5614 5615 if ($element.attr('id') != null) { 5616 id = $element.attr('id'); 5617 } else if ($element.attr('name') != null) { 5618 id = $element.attr('name') + '-' + Utils.generateChars(2); 5619 } else { 5620 id = Utils.generateChars(4); 5621 } 5622 5623 id = id.replace(/(:|\.|\[|\]|,)/g, ''); 5624 id = 'select2-' + id; 5625 5626 return id; 5627 }; 5628 5629 Select2.prototype._placeContainer = function ($container) { 5630 $container.insertAfter(this.$element); 5631 5632 var width = this._resolveWidth(this.$element, this.options.get('width')); 5633 5634 if (width != null) { 5635 $container.css('width', width); 5636 } 5637 }; 5638 5639 Select2.prototype._resolveWidth = function ($element, method) { 5640 var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; 5641 5642 if (method == 'resolve') { 5643 var styleWidth = this._resolveWidth($element, 'style'); 5644 5645 if (styleWidth != null) { 5646 return styleWidth; 5647 } 5648 5649 return this._resolveWidth($element, 'element'); 5650 } 5651 5652 if (method == 'element') { 5653 var elementWidth = $element.outerWidth(false); 5654 5655 if (elementWidth <= 0) { 5656 return 'auto'; 5657 } 5658 5659 return elementWidth + 'px'; 5660 } 5661 5662 if (method == 'style') { 5663 var style = $element.attr('style'); 5664 5665 if (typeof (style) !== 'string') { 5666 return null; 5667 } 5668 5669 var attrs = style.split(';'); 5670 5671 for (var i = 0, l = attrs.length; i < l; i = i + 1) { 5672 var attr = attrs[i].replace(/\s/g, ''); 5673 var matches = attr.match(WIDTH); 5674 5675 if (matches !== null && matches.length >= 1) { 5676 return matches[1]; 5677 } 5678 } 5679 5680 return null; 5681 } 5682 5683 if (method == 'computedstyle') { 5684 var computedStyle = window.getComputedStyle($element[0]); 5685 5686 return computedStyle.width; 5687 } 5688 5689 return method; 5690 }; 5691 5692 Select2.prototype._bindAdapters = function () { 5693 this.dataAdapter.bind(this, this.$container); 5694 this.selection.bind(this, this.$container); 5695 5696 this.dropdown.bind(this, this.$container); 5697 this.results.bind(this, this.$container); 5698 }; 5699 5700 Select2.prototype._registerDomEvents = function () { 5701 var self = this; 5702 5703 this.$element.on('change.select2', function () { 5704 self.dataAdapter.current(function (data) { 5705 self.trigger('selection:update', { 5706 data: data 5707 }); 5708 }); 5709 }); 5710 5711 this.$element.on('focus.select2', function (evt) { 5712 self.trigger('focus', evt); 5713 }); 5714 5715 this._syncA = Utils.bind(this._syncAttributes, this); 5716 this._syncS = Utils.bind(this._syncSubtree, this); 5717 5718 this._observer = new window.MutationObserver(function (mutations) { 5719 self._syncA(); 5720 self._syncS(mutations); 5721 }); 5722 this._observer.observe(this.$element[0], { 5723 attributes: true, 5724 childList: true, 5725 subtree: false 5726 }); 5727 }; 5728 5729 Select2.prototype._registerDataEvents = function () { 5730 var self = this; 5731 5732 this.dataAdapter.on('*', function (name, params) { 5733 self.trigger(name, params); 5734 }); 5735 }; 5736 5737 Select2.prototype._registerSelectionEvents = function () { 5738 var self = this; 5739 var nonRelayEvents = ['toggle', 'focus']; 5740 5741 this.selection.on('toggle', function () { 5742 self.toggleDropdown(); 5743 }); 5744 5745 this.selection.on('focus', function (params) { 5746 self.focus(params); 5747 }); 5748 5749 this.selection.on('*', function (name, params) { 5750 if (nonRelayEvents.indexOf(name) !== -1) { 5751 return; 5752 } 5753 5754 self.trigger(name, params); 5755 }); 5756 }; 5757 5758 Select2.prototype._registerDropdownEvents = function () { 5759 var self = this; 5760 5761 this.dropdown.on('*', function (name, params) { 5762 self.trigger(name, params); 5763 }); 5764 }; 5765 5766 Select2.prototype._registerResultsEvents = function () { 5767 var self = this; 5768 5769 this.results.on('*', function (name, params) { 5770 self.trigger(name, params); 5771 }); 5772 }; 5773 5774 Select2.prototype._registerEvents = function () { 5775 var self = this; 5776 5777 this.on('open', function () { 5778 self.$container[0].classList.add('select2-container--open'); 5779 }); 5780 5781 this.on('close', function () { 5782 self.$container[0].classList.remove('select2-container--open'); 5783 }); 5784 5785 this.on('enable', function () { 5786 self.$container[0].classList.remove('select2-container--disabled'); 5787 }); 5788 5789 this.on('disable', function () { 5790 self.$container[0].classList.add('select2-container--disabled'); 5791 }); 5792 5793 this.on('blur', function () { 5794 self.$container[0].classList.remove('select2-container--focus'); 5795 }); 5796 5797 this.on('query', function (params) { 5798 if (!self.isOpen()) { 5799 self.trigger('open', {}); 5800 } 5801 5802 this.dataAdapter.query(params, function (data) { 5803 self.trigger('results:all', { 5804 data: data, 5805 query: params 5806 }); 5807 }); 5808 }); 5809 5810 this.on('query:append', function (params) { 5811 this.dataAdapter.query(params, function (data) { 5812 self.trigger('results:append', { 5813 data: data, 5814 query: params 5815 }); 5816 }); 5817 }); 5818 5819 this.on('keypress', function (evt) { 5820 var key = evt.which; 5821 5822 if (self.isOpen()) { 5823 if (key === KEYS.ESC || (key === KEYS.UP && evt.altKey)) { 5824 self.close(evt); 5825 5826 evt.preventDefault(); 5827 } else if (key === KEYS.ENTER || key === KEYS.TAB) { 5828 self.trigger('results:select', {}); 5829 5830 evt.preventDefault(); 5831 } else if ((key === KEYS.SPACE && evt.ctrlKey)) { 5832 self.trigger('results:toggle', {}); 5833 5834 evt.preventDefault(); 5835 } else if (key === KEYS.UP) { 5836 self.trigger('results:previous', {}); 5837 5838 evt.preventDefault(); 5839 } else if (key === KEYS.DOWN) { 5840 self.trigger('results:next', {}); 5841 5842 evt.preventDefault(); 5843 } 5844 } else { 5845 if (key === KEYS.ENTER || key === KEYS.SPACE || 5846 (key === KEYS.DOWN && evt.altKey)) { 5847 self.open(); 5848 5849 evt.preventDefault(); 5850 } 5851 } 5852 }); 5853 }; 5854 5855 Select2.prototype._syncAttributes = function () { 5856 this.options.set('disabled', this.$element.prop('disabled')); 5857 5858 if (this.isDisabled()) { 5859 if (this.isOpen()) { 5860 this.close(); 5861 } 5862 5863 this.trigger('disable', {}); 5864 } else { 5865 this.trigger('enable', {}); 5866 } 5867 }; 5868 5869 Select2.prototype._isChangeMutation = function (mutations) { 5870 var self = this; 5871 5872 if (mutations.addedNodes && mutations.addedNodes.length > 0) { 5873 for (var n = 0; n < mutations.addedNodes.length; n++) { 5874 var node = mutations.addedNodes[n]; 5875 5876 if (node.selected) { 5877 return true; 5878 } 5879 } 5880 } else if (mutations.removedNodes && mutations.removedNodes.length > 0) { 5881 return true; 5882 } else if (Array.isArray(mutations)) { 5883 return mutations.some(function (mutation) { 5884 return self._isChangeMutation(mutation); 5885 }); 5886 } 5887 5888 return false;
vendor: 11,071 bytes, lines 5889-6211
5889 }; 5890 5891 Select2.prototype._syncSubtree = function (mutations) { 5892 var changed = this._isChangeMutation(mutations); 5893 var self = this; 5894 5895 // Only re-pull the data if we think there is a change 5896 if (changed) { 5897 this.dataAdapter.current(function (currentData) { 5898 self.trigger('selection:update', { 5899 data: currentData 5900 }); 5901 }); 5902 } 5903 }; 5904 5905 /** 5906 * Override the trigger method to automatically trigger pre-events when 5907 * there are events that can be prevented. 5908 */ 5909 Select2.prototype.trigger = function (name, args) { 5910 var actualTrigger = Select2.__super__.trigger; 5911 var preTriggerMap = { 5912 'open': 'opening', 5913 'close': 'closing', 5914 'select': 'selecting', 5915 'unselect': 'unselecting', 5916 'clear': 'clearing' 5917 }; 5918 5919 if (args === undefined) { 5920 args = {}; 5921 } 5922 5923 if (name in preTriggerMap) { 5924 var preTriggerName = preTriggerMap[name]; 5925 var preTriggerArgs = { 5926 prevented: false, 5927 name: name, 5928 args: args 5929 }; 5930 5931 actualTrigger.call(this, preTriggerName, preTriggerArgs); 5932 5933 if (preTriggerArgs.prevented) { 5934 args.prevented = true; 5935 5936 return; 5937 } 5938 } 5939 5940 actualTrigger.call(this, name, args); 5941 }; 5942 5943 Select2.prototype.toggleDropdown = function () { 5944 if (this.isDisabled()) { 5945 return; 5946 } 5947 5948 if (this.isOpen()) { 5949 this.close(); 5950 } else { 5951 this.open(); 5952 } 5953 }; 5954 5955 Select2.prototype.open = function () { 5956 if (this.isOpen()) { 5957 return; 5958 } 5959 5960 if (this.isDisabled()) { 5961 return; 5962 } 5963 5964 this.trigger('query', {}); 5965 }; 5966 5967 Select2.prototype.close = function (evt) { 5968 if (!this.isOpen()) { 5969 return; 5970 } 5971 5972 this.trigger('close', { originalEvent: evt }); 5973 }; 5974 5975 /** 5976 * Helper method to abstract the "enabled" (not "disabled") state of this 5977 * object. 5978 * 5979 * @return {true} if the instance is not disabled. 5980 * @return {false} if the instance is disabled. 5981 */ 5982 Select2.prototype.isEnabled = function () { 5983 return !this.isDisabled(); 5984 }; 5985 5986 /** 5987 * Helper method to abstract the "disabled" state of this object. 5988 * 5989 * @return {true} if the disabled option is true. 5990 * @return {false} if the disabled option is false. 5991 */ 5992 Select2.prototype.isDisabled = function () { 5993 return this.options.get('disabled'); 5994 }; 5995 5996 Select2.prototype.isOpen = function () { 5997 return this.$container[0].classList.contains('select2-container--open'); 5998 }; 5999 6000 Select2.prototype.hasFocus = function () { 6001 return this.$container[0].classList.contains('select2-container--focus'); 6002 }; 6003 6004 Select2.prototype.focus = function (data) { 6005 // No need to re-trigger focus events if we are already focused 6006 if (this.hasFocus()) { 6007 return; 6008 } 6009 6010 this.$container[0].classList.add('select2-container--focus'); 6011 this.trigger('focus', {}); 6012 }; 6013 6014 Select2.prototype.enable = function (args) { 6015 if (this.options.get('debug') && window.console && console.warn) { 6016 console.warn( 6017 'Select2: The `select2("enable")` method has been deprecated and will' + 6018 ' be removed in later Select2 versions. Use $element.prop("disabled")' + 6019 ' instead.' 6020 ); 6021 } 6022 6023 if (args == null || args.length === 0) { 6024 args = [true]; 6025 } 6026 6027 var disabled = !args[0]; 6028 6029 this.$element.prop('disabled', disabled); 6030 }; 6031 6032 Select2.prototype.data = function () { 6033 if (this.options.get('debug') && 6034 arguments.length > 0 && window.console && console.warn) { 6035 console.warn( 6036 'Select2: Data can no longer be set using `select2("data")`. You ' + 6037 'should consider setting the value instead using `$element.val()`.' 6038 ); 6039 } 6040 6041 var data = []; 6042 6043 this.dataAdapter.current(function (currentData) { 6044 data = currentData; 6045 }); 6046 6047 return data; 6048 }; 6049 6050 Select2.prototype.val = function (args) { 6051 if (this.options.get('debug') && window.console && console.warn) { 6052 console.warn( 6053 'Select2: The `select2("val")` method has been deprecated and will be' + 6054 ' removed in later Select2 versions. Use $element.val() instead.' 6055 ); 6056 } 6057 6058 if (args == null || args.length === 0) { 6059 return this.$element.val(); 6060 } 6061 6062 var newVal = args[0]; 6063 6064 if (Array.isArray(newVal)) { 6065 newVal = newVal.map(function (obj) { 6066 return obj.toString(); 6067 }); 6068 } 6069 6070 this.$element.val(newVal).trigger('input').trigger('change'); 6071 }; 6072 6073 Select2.prototype.destroy = function () { 6074 Utils.RemoveData(this.$container[0]); 6075 this.$container.remove(); 6076 6077 this._observer.disconnect(); 6078 this._observer = null; 6079 6080 this._syncA = null; 6081 this._syncS = null; 6082 6083 this.$element.off('.select2'); 6084 this.$element.attr('tabindex', 6085 Utils.GetData(this.$element[0], 'old-tabindex')); 6086 6087 this.$element[0].classList.remove('select2-hidden-accessible'); 6088 this.$element.attr('aria-hidden', 'false'); 6089 Utils.RemoveData(this.$element[0]); 6090 this.$element.removeData('select2'); 6091 6092 this.dataAdapter.destroy(); 6093 this.selection.destroy(); 6094 this.dropdown.destroy(); 6095 this.results.destroy(); 6096 6097 this.dataAdapter = null; 6098 this.selection = null; 6099 this.dropdown = null; 6100 this.results = null; 6101 }; 6102 6103 Select2.prototype.render = function () { 6104 var $container = $( 6105 '<span class="select2 select2-container">' + 6106 '<span class="selection"></span>' + 6107 '<span class="dropdown-wrapper" aria-hidden="true"></span>' + 6108 '</span>' 6109 ); 6110 6111 $container.attr('dir', this.options.get('dir')); 6112 6113 this.$container = $container; 6114 6115 this.$container[0].classList 6116 .add('select2-container--' + this.options.get('theme')); 6117 6118 Utils.StoreData($container[0], 'element', this.$element); 6119 6120 return $container; 6121 }; 6122 6123 return Select2; 6124 }); 6125 6126 S2.define('jquery-mousewheel', [ 6127 'jquery' 6128 ], function ($) { 6129 // Used to shim jQuery.mousewheel for non-full builds. 6130 return $; 6131 }); 6132 6133 S2.define('jquery.select2', [ 6134 'jquery', 6135 'jquery-mousewheel', 6136 6137 './select2/core', 6138 './select2/defaults', 6139 './select2/utils' 6140 ], function ($, _, Select2, Defaults, Utils) { 6141 if ($.fn.select2 == null) { 6142 // All methods that should return the element 6143 var thisMethods = ['open', 'close', 'destroy']; 6144 6145 $.fn.select2 = function (options) { 6146 options = options || {}; 6147 6148 if (typeof options === 'object') { 6149 this.each(function () { 6150 var instanceOptions = $.extend(true, {}, options); 6151 6152 var instance = new Select2($(this), instanceOptions); 6153 }); 6154 6155 return this; 6156 } else if (typeof options === 'string') { 6157 var ret; 6158 var args = Array.prototype.slice.call(arguments, 1); 6159 6160 this.each(function () { 6161 var instance = Utils.GetData(this, 'select2'); 6162 6163 if (instance == null && window.console && console.error) { 6164 console.error( 6165 'The select2(\'' + options + '\') method was called on an ' + 6166 'element that is not using Select2.' 6167 ); 6168 } 6169 6170 ret = instance[options].apply(instance, args); 6171 }); 6172 6173 // Check if we should be returning `this` 6174 if (thisMethods.indexOf(options) > -1) { 6175 return this; 6176 } 6177 6178 return ret; 6179 } else { 6180 throw new Error('Invalid arguments for Select2: ' + options); 6181 } 6182 }; 6183 } 6184 6185 if ($.fn.select2.defaults == null) { 6186 $.fn.select2.defaults = Defaults; 6187 } 6188 6189 return Select2; 6190 }); 6191 6192 // Return the AMD loader configuration so it can be used outside of this file 6193 return { 6194 define: S2.define, 6195 require: S2.require 6196 }; 6197 }()); 6198 6199 // Autoload the jQuery bindings 6200 // We know that all of the modules exist above this, so we're safe 6201 var select2 = S2.require('jquery.select2'); 6202 6203 // Hold the AMD module references on the jQuery function that was just loaded 6204 // This allows Select2 to use the internal loader outside of this file, such 6205 // as in the language files. 6206 jQuery.fn.select2.amd = S2; 6207 6208 // Return the Select2 instance for anyone who is importing it. 6209 return select2; 6210})); 6211
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.