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