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