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