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