9
if (typeof define === 'function' && define.amd) {
11
define(['jquery'], factory);
12
} else if (typeof module === 'object' && module.exports) {
14
module.exports = function (root, jQuery) {
15
if (jQuery === undefined) {
20
if (typeof window !== 'undefined') {
21
jQuery = require('jquery');
24
jQuery = require('jquery')(root);
38
var S2 =(function () {
41
if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
42
var S2 = jQuery.fn.select2.amd;
44
var S2;(function () { if (!S2 || !S2.requirejs) {
45
if (!S2) { S2 = {}; } else { require = S2; }
54
var requirejs, require, define;
56
var main, req, makeMap, handlers,
61
hasOwn = Object.prototype.hasOwnProperty,
63
jsSuffixRegExp = /\.js$/;
65
function hasProp(obj, prop) {
66
return hasOwn.call(obj, prop);
77
function normalize(name, baseName) {
78
var nameParts, nameSegment, mapValue, foundMap, lastIndex,
79
foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
80
baseParts = baseName && baseName.split("/"),
82
starMap = (map && map['*']) || {};
86
name = name.split('/');
87
lastIndex = name.length - 1;
93
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
94
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
98
if (name[0].charAt(0) === '.' && baseParts) {
104
normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
105
name = normalizedBaseParts.concat(name);
109
for (i = 0; i < name.length; i++) {
114
} else if (part === '..') {
120
if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
123
name.splice(i - 1, 2);
130
name = name.join('/');
134
if ((baseParts || starMap) && map) {
135
nameParts = name.split('/');
137
for (i = nameParts.length; i > 0; i -= 1) {
138
nameSegment = nameParts.slice(0, i).join("/");
143
for (j = baseParts.length; j > 0; j -= 1) {
144
mapValue = map[baseParts.slice(0, j).join('/')];
149
mapValue = mapValue[nameSegment];
167
if (!foundStarMap && starMap && starMap[nameSegment]) {
168
foundStarMap = starMap[nameSegment];
173
if (!foundMap && foundStarMap) {
174
foundMap = foundStarMap;
179
nameParts.splice(0, foundI, foundMap);
180
name = nameParts.join('/');
187
function makeRequire(relName, forceSync) {
192
var args = aps.call(arguments, 0);
197
if (typeof args[0] !== 'string' && args.length === 1) {
200
return req.apply(undef, args.concat([relName, forceSync]));
204
function makeNormalize(relName) {
205
return function (name) {
206
return normalize(name, relName);
210
function makeLoad(depName) {
211
return function (value) {
212
defined[depName] = value;
216
function callDep(name) {
217
if (hasProp(waiting, name)) {
218
var args = waiting[name];
219
delete waiting[name];
220
defining[name] = true;
221
main.apply(undef, args);
224
if (!hasProp(defined, name) && !hasProp(defining, name)) {
225
throw new Error('No ' + name);
227
return defined[name];
233
function splitPrefix(name) {
235
index = name ? name.indexOf('!') : -1;
237
prefix = name.substring(0, index);
238
name = name.substring(index + 1, name.length);
240
return [prefix, name];
245
function makeRelParts(relName) {
246
return relName ? splitPrefix(relName) : [];
254
makeMap = function (name, relParts) {
256
parts = splitPrefix(name),
258
relResourceName = relParts[1];
263
prefix = normalize(prefix, relResourceName);
264
plugin = callDep(prefix);
269
if (plugin && plugin.normalize) {
270
name = plugin.normalize(name, makeNormalize(relResourceName));
272
name = normalize(name, relResourceName);
275
name = normalize(name, relResourceName);
276
parts = splitPrefix(name);
280
plugin = callDep(prefix);
286
f: prefix ? prefix + '!' + name : name,
293
function makeConfig(name) {
295
return (config && config.config && config.config[name]) || {};
300
require: function (name) {
301
return makeRequire(name);
303
exports: function (name) {
304
var e = defined[name];
305
if (typeof e !== 'undefined') {
308
return (defined[name] = {});
311
module: function (name) {
315
exports: defined[name],
316
config: makeConfig(name)
321
main = function (name, deps, callback, relName) {
322
var cjsModule, depName, ret, map, i, relParts,
324
callbackType = typeof callback,
328
relName = relName || name;
329
relParts = makeRelParts(relName);
332
if (callbackType === 'undefined' || callbackType === 'function') {
336
deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
337
for (i = 0; i < deps.length; i += 1) {
338
map = makeMap(deps[i], relParts);
342
if (depName === "require") {
343
args[i] = handlers.require(name);
344
} else if (depName === "exports") {
346
args[i] = handlers.exports(name);
348
} else if (depName === "module") {
350
cjsModule = args[i] = handlers.module(name);
351
} else if (hasProp(defined, depName) ||
352
hasProp(waiting, depName) ||
353
hasProp(defining, depName)) {
354
args[i] = callDep(depName);
356
map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
357
args[i] = defined[depName];
359
throw new Error(name + ' missing ' + depName);
363
ret = callback ? callback.apply(defined[name], args) : undefined;
369
if (cjsModule && cjsModule.exports !== undef &&
370
cjsModule.exports !== defined[name]) {
371
defined[name] = cjsModule.exports;
372
} else if (ret !== undef || !usingExports) {
380
defined[name] = callback;
384
requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
385
if (typeof deps === "string") {
386
if (handlers[deps]) {
388
return handlers[deps](callback);
394
return callDep(makeMap(deps, makeRelParts(callback)).f);
395
} else if (!deps.splice) {
399
req(config.deps, config.callback);
405
if (callback.splice) {
417
callback = callback || function () {};
421
if (typeof relName === 'function') {
428
main(undef, deps, callback, relName);
436
setTimeout(function () {
437
main(undef, deps, callback, relName);
448
req.config = function (cfg) {
455
requirejs._defined = defined;
457
define = function (name, deps, callback) {
458
if (typeof name !== 'string') {
459
throw new Error('See almond README: incorrect module build, no module name');
471
if (!hasProp(defined, name) && !hasProp(waiting, name)) {
472
waiting[name] = [name, deps, callback];
481
S2.requirejs = requirejs;S2.require = require;S2.define = define;
484
S2.define("almond", function(){});
487
S2.define('jquery',[],function () {
488
var _$ = jQuery || $;
490
if (_$ == null && console && console.error) {
492
'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
493
'found. Make sure that you are including jQuery before Select2 on your ' +
501
S2.define('select2/utils',[
506
Utils.Extend = function (ChildClass, SuperClass) {
507
var __hasProp = {}.hasOwnProperty;
509
function BaseConstructor () {
510
this.constructor = ChildClass;
513
for (var key in SuperClass) {
514
if (__hasProp.call(SuperClass, key)) {
515
ChildClass[key] = SuperClass[key];
519
BaseConstructor.prototype = SuperClass.prototype;
520
ChildClass.prototype = new BaseConstructor();
521
ChildClass.__super__ = SuperClass.prototype;
526
function getMethods (theClass) {
527
var proto = theClass.prototype;
531
for (var methodName in proto) {
532
var m = proto[methodName];
534
if (typeof m !== 'function') {
538
if (methodName === 'constructor') {
542
methods.push(methodName);
548
Utils.Decorate = function (SuperClass, DecoratorClass) {
549
var decoratedMethods = getMethods(DecoratorClass);
550
var superMethods = getMethods(SuperClass);
552
function DecoratedClass () {
553
var unshift = Array.prototype.unshift;
555
var argCount = DecoratorClass.prototype.constructor.length;
557
var calledConstructor = SuperClass.prototype.constructor;
560
unshift.call(arguments, SuperClass.prototype.constructor);
562
calledConstructor = DecoratorClass.prototype.constructor;
565
calledConstructor.apply(this, arguments);
568
DecoratorClass.displayName = SuperClass.displayName;
571
this.constructor = DecoratedClass;
574
DecoratedClass.prototype = new ctr();
576
for (var m = 0; m < superMethods.length; m++) {
577
var superMethod = superMethods[m];
579
DecoratedClass.prototype[superMethod] =
580
SuperClass.prototype[superMethod];
583
var calledMethod = function (methodName) {
585
var originalMethod = function () {};
587
if (methodName in DecoratedClass.prototype) {
588
originalMethod = DecoratedClass.prototype[methodName];
591
var decoratedMethod = DecoratorClass.prototype[methodName];
594
var unshift = Array.prototype.unshift;
596
unshift.call(arguments, originalMethod);
598
return decoratedMethod.apply(this, arguments);
602
for (var d = 0; d < decoratedMethods.length; d++) {
603
var decoratedMethod = decoratedMethods[d];
605
DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
608
return DecoratedClass;
611
var Observable = function () {
615
Observable.prototype.on = function (event, callback) {
616
this.listeners = this.listeners || {};
618
if (event in this.listeners) {
619
this.listeners[event].push(callback);
621
this.listeners[event] = [callback];
625
Observable.prototype.trigger = function (event) {
626
var slice = Array.prototype.slice;
627
var params = slice.call(arguments, 1);
629
this.listeners = this.listeners || {};
632
if (params == null) {
637
if (params.length === 0) {
642
params[0]._type = event;
644
if (event in this.listeners) {
645
this.invoke(this.listeners[event], slice.call(arguments, 1));
648
if ('*' in this.listeners) {
649
this.invoke(this.listeners['*'], arguments);
653
Observable.prototype.invoke = function (listeners, params) {
654
for (var i = 0, len = listeners.length; i < len; i++) {
655
listeners[i].apply(this, params);
659
Utils.Observable = Observable;
661
Utils.generateChars = function (length) {
664
for (var i = 0; i < length; i++) {
665
var randomChar = Math.floor(Math.random() * 36);
666
chars += randomChar.toString(36);
672
Utils.bind = function (func, context) {
674
func.apply(context, arguments);
678
Utils._convertData = function (data) {
679
for (var originalKey in data) {
680
var keys = originalKey.split('-');
682
var dataLevel = data;
684
if (keys.length === 1) {
688
for (var k = 0; k < keys.length; k++) {
693
key = key.substring(0, 1).toLowerCase() + key.substring(1);
695
if (!(key in dataLevel)) {
699
if (k == keys.length - 1) {
700
dataLevel[key] = data[originalKey];
703
dataLevel = dataLevel[key];
706
delete data[originalKey];
712
Utils.hasScroll = function (index, el) {
720
var overflowX = el.style.overflowX;
721
var overflowY = el.style.overflowY;
724
if (overflowX === overflowY &&
725
(overflowY === 'hidden' || overflowY === 'visible')) {
729
if (overflowX === 'scroll' || overflowY === 'scroll') {
733
return ($el.innerHeight() < el.scrollHeight ||
734
$el.innerWidth() < el.scrollWidth);
737
Utils.escapeMarkup = function (markup) {
749
if (typeof markup !== 'string') {
753
return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
754
return replaceMap[match];
759
Utils.appendMany = function ($element, $nodes) {
762
if ($.fn.jquery.substr(0, 3) === '1.7') {
765
$.map($nodes, function (node) {
766
$jqNodes = $jqNodes.add(node);
772
$element.append($nodes);
779
Utils.GetUniqueElementId = function (element) {
785
var select2Id = element.getAttribute('data-select2-id');
786
if (select2Id == null) {
789
select2Id = element.id;
790
element.setAttribute('data-select2-id', select2Id);
792
element.setAttribute('data-select2-id', ++id);
793
select2Id = id.toString();
799
Utils.StoreData = function (element, name, value) {
802
var id = Utils.GetUniqueElementId(element);
803
if (!Utils.__cache[id]) {
804
Utils.__cache[id] = {};
807
Utils.__cache[id][name] = value;
810
Utils.GetData = function (element, name) {
815
var id = Utils.GetUniqueElementId(element);
817
if (Utils.__cache[id]) {
818
if (Utils.__cache[id][name] != null) {
819
return Utils.__cache[id][name];
821
return $(element).data(name);
823
return $(element).data(name);
825
return Utils.__cache[id];
829
Utils.RemoveData = function (element) {
831
var id = Utils.GetUniqueElementId(element);
832
if (Utils.__cache[id] != null) {
833
delete Utils.__cache[id];
836
element.removeAttribute('data-select2-id');
842
S2.define('select2/results',[
845
], function ($, Utils) {
846
function Results ($element, options, dataAdapter) {
847
this.$element = $element;
848
this.data = dataAdapter;
849
this.options = options;
851
Results.__super__.constructor.call(this);
854
Utils.Extend(Results, Utils.Observable);
856
Results.prototype.render = function () {
858
'<ul class="select2-results__options" role="listbox"></ul>'
861
if (this.options.get('multiple')) {
862
$results.attr('aria-multiselectable', 'true');
865
this.$results = $results;
870
Results.prototype.clear = function () {
871
this.$results.empty();
874
Results.prototype.displayMessage = function (params) {
875
var escapeMarkup = this.options.get('escapeMarkup');
881
'<li role="alert" aria-live="assertive"' +
882
' class="select2-results__option"></li>'
885
var message = this.options.get('translations').get(params.message);
893
$message[0].className += ' select2-results__message';
895
this.$results.append($message);
898
Results.prototype.hideMessages = function () {
899
this.$results.find('.select2-results__message').remove();
902
Results.prototype.append = function (data) {
907
if (data.results == null || data.results.length === 0) {
908
if (this.$results.children().length === 0) {
909
this.trigger('results:message', {
917
data.results = this.sort(data.results);
919
for (var d = 0; d < data.results.length; d++) {
920
var item = data.results[d];
922
var $option = this.option(item);
924
$options.push($option);
927
this.$results.append($options);
930
Results.prototype.position = function ($results, $dropdown) {
931
var $resultsContainer = $dropdown.find('.select2-results');
932
$resultsContainer.append($results);
935
Results.prototype.sort = function (data) {
936
var sorter = this.options.get('sorter');
941
Results.prototype.highlightFirstItem = function () {
942
var $options = this.$results
943
.find('.select2-results__option[aria-selected]');
945
var $selected = $options.filter('[aria-selected=true]');
948
if ($selected.length > 0) {
950
$selected.first().trigger('mouseenter');
954
$options.first().trigger('mouseenter');
957
this.ensureHighlightVisible();
960
Results.prototype.setClasses = function () {
963
this.data.current(function (selected) {
964
var selectedIds = $.map(selected, function (s) {
965
return s.id.toString();
968
var $options = self.$results
969
.find('.select2-results__option[aria-selected]');
971
$options.each(function () {
972
var $option = $(this);
974
var item = Utils.GetData(this, 'data');
977
var id = '' + item.id;
979
if ((item.element != null && item.element.selected) ||
980
(item.element == null && $.inArray(id, selectedIds) > -1)) {
981
$option.attr('aria-selected', 'true');
983
$option.attr('aria-selected', 'false');
990
Results.prototype.showLoading = function (params) {
993
var loadingMore = this.options.get('translations').get('searching');
998
text: loadingMore(params)
1000
var $loading = this.option(loading);
1001
$loading.className += ' loading-results';
1003
this.$results.prepend($loading);
1006
Results.prototype.hideLoading = function () {
1007
this.$results.find('.loading-results').remove();
1010
Results.prototype.option = function (data) {
1011
var option = document.createElement('li');
1012
option.className = 'select2-results__option';
1016
'aria-selected': 'false'
1019
var matches = window.Element.prototype.matches ||
1020
window.Element.prototype.msMatchesSelector ||
1021
window.Element.prototype.webkitMatchesSelector;
1023
if ((data.element != null && matches.call(data.element, ':disabled')) ||
1024
(data.element == null && data.disabled)) {
1025
delete attrs['aria-selected'];
1026
attrs['aria-disabled'] = 'true';
1029
if (data.id == null) {
1030
delete attrs['aria-selected'];
1033
if (data._resultId != null) {
1034
option.id = data._resultId;
1038
option.title = data.title;
1041
if (data.children) {
1042
attrs.role = 'group';
1043
attrs['aria-label'] = data.text;
1044
delete attrs['aria-selected'];
1047
for (var attr in attrs) {
1048
var val = attrs[attr];
1050
option.setAttribute(attr, val);
1053
if (data.children) {
1054
var $option = $(option);
1056
var label = document.createElement('strong');
1057
label.className = 'select2-results__group';
1059
var $label = $(label);
1060
this.template(data, label);
1064
for (var c = 0; c < data.children.length; c++) {
1065
var child = data.children[c];
1067
var $child = this.option(child);
1069
$children.push($child);
1072
var $childrenContainer = $('<ul></ul>', {
1073
'class': 'select2-results__options select2-results__options--nested'
1076
$childrenContainer.append($children);
1078
$option.append(label);
1079
$option.append($childrenContainer);
1081
this.template(data, option);
1084
Utils.StoreData(option, 'data', data);
1089
Results.prototype.bind = function (container, $container) {
1092
var id = container.id + '-results';
1094
this.$results.attr('id', id);
1096
container.on('results:all', function (params) {
1098
self.append(params.data);
1100
if (container.isOpen()) {
1102
self.highlightFirstItem();
1106
container.on('results:append', function (params) {
1107
self.append(params.data);
1109
if (container.isOpen()) {
1114
container.on('query', function (params) {
1115
self.hideMessages();
1116
self.showLoading(params);
1119
container.on('select', function () {
1120
if (!container.isOpen()) {
1126
if (self.options.get('scrollAfterSelect')) {
1127
self.highlightFirstItem();
1131
container.on('unselect', function () {
1132
if (!container.isOpen()) {
1138
if (self.options.get('scrollAfterSelect')) {
1139
self.highlightFirstItem();
1143
container.on('open', function () {
1145
self.$results.attr('aria-expanded', 'true');
1146
self.$results.attr('aria-hidden', 'false');
1149
self.ensureHighlightVisible();
1152
container.on('close', function () {
1154
self.$results.attr('aria-expanded', 'false');
1155
self.$results.attr('aria-hidden', 'true');
1156
self.$results.removeAttr('aria-activedescendant');
1159
container.on('results:toggle', function () {
1160
var $highlighted = self.getHighlightedResults();
1162
if ($highlighted.length === 0) {
1166
$highlighted.trigger('mouseup');
1169
container.on('results:select', function () {
1170
var $highlighted = self.getHighlightedResults();
1172
if ($highlighted.length === 0) {
1176
var data = Utils.GetData($highlighted[0], 'data');
1178
if ($highlighted.attr('aria-selected') == 'true') {
1179
self.trigger('close', {});
1181
self.trigger('select', {
1187
container.on('results:previous', function () {
1188
var $highlighted = self.getHighlightedResults();
1190
var $options = self.$results.find('[aria-selected]');
1192
var currentIndex = $options.index($highlighted);
1196
if (currentIndex <= 0) {
1200
var nextIndex = currentIndex - 1;
1203
if ($highlighted.length === 0) {
1207
var $next = $options.eq(nextIndex);
1209
$next.trigger('mouseenter');
1211
var currentOffset = self.$results.offset().top;
1212
var nextTop = $next.offset().top;
1213
var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
1215
if (nextIndex === 0) {
1216
self.$results.scrollTop(0);
1217
} else if (nextTop - currentOffset < 0) {
1218
self.$results.scrollTop(nextOffset);
1222
container.on('results:next', function () {
1223
var $highlighted = self.getHighlightedResults();
1225
var $options = self.$results.find('[aria-selected]');
1227
var currentIndex = $options.index($highlighted);
1229
var nextIndex = currentIndex + 1;
1232
if (nextIndex >= $options.length) {
1236
var $next = $options.eq(nextIndex);
1238
$next.trigger('mouseenter');
1240
var currentOffset = self.$results.offset().top +
1241
self.$results.outerHeight(false);
1242
var nextBottom = $next.offset().top + $next.outerHeight(false);
1243
var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
1245
if (nextIndex === 0) {
1246
self.$results.scrollTop(0);
1247
} else if (nextBottom > currentOffset) {
1248
self.$results.scrollTop(nextOffset);
1252
container.on('results:focus', function (params) {
1253
params.element.addClass('select2-results__option--highlighted');
1256
container.on('results:message', function (params) {
1257
self.displayMessage(params);
1260
if ($.fn.mousewheel) {
1261
this.$results.on('mousewheel', function (e) {
1262
var top = self.$results.scrollTop();
1264
var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
1266
var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
1267
var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
1270
self.$results.scrollTop(0);
1273
e.stopPropagation();
1274
} else if (isAtBottom) {
1275
self.$results.scrollTop(
1276
self.$results.get(0).scrollHeight - self.$results.height()
1280
e.stopPropagation();
1285
this.$results.on('mouseup', '.select2-results__option[aria-selected]',
1287
var $this = $(this);
1289
var data = Utils.GetData(this, 'data');
1291
if ($this.attr('aria-selected') === 'true') {
1292
if (self.options.get('multiple')) {
1293
self.trigger('unselect', {
1298
self.trigger('close', {});
1304
self.trigger('select', {
1310
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
1312
var data = Utils.GetData(this, 'data');
1314
self.getHighlightedResults()
1315
.removeClass('select2-results__option--highlighted');
1317
self.trigger('results:focus', {
1324
Results.prototype.getHighlightedResults = function () {
1325
var $highlighted = this.$results
1326
.find('.select2-results__option--highlighted');
1328
return $highlighted;
1331
Results.prototype.destroy = function () {
1332
this.$results.remove();
1335
Results.prototype.ensureHighlightVisible = function () {
1336
var $highlighted = this.getHighlightedResults();
1338
if ($highlighted.length === 0) {
1342
var $options = this.$results.find('[aria-selected]');
1344
var currentIndex = $options.index($highlighted);
1346
var currentOffset = this.$results.offset().top;
1347
var nextTop = $highlighted.offset().top;
1348
var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
1350
var offsetDelta = nextTop - currentOffset;
1351
nextOffset -= $highlighted.outerHeight(false) * 2;
1353
if (currentIndex <= 2) {
1354
this.$results.scrollTop(0);
1355
} else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
1356
this.$results.scrollTop(nextOffset);
1360
Results.prototype.template = function (result, container) {
1361
var template = this.options.get('templateResult');
1362
var escapeMarkup = this.options.get('escapeMarkup');
1364
var content = template(result, container);
1366
if (content == null) {
1367
container.style.display = 'none';
1368
} else if (typeof content === 'string') {
1369
container.innerHTML = escapeMarkup(content);
1371
$(container).append(content);
1378
S2.define('select2/keys',[
1404
S2.define('select2/selection/base',[
1408
], function ($, Utils, KEYS) {
1409
function BaseSelection ($element, options) {
1410
this.$element = $element;
1411
this.options = options;
1413
BaseSelection.__super__.constructor.call(this);
1416
Utils.Extend(BaseSelection, Utils.Observable);
1418
BaseSelection.prototype.render = function () {
1420
'<span class="select2-selection" role="combobox" ' +
1421
' aria-haspopup="true" aria-expanded="false">' +
1427
if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
1428
this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
1429
} else if (this.$element.attr('tabindex') != null) {
1430
this._tabindex = this.$element.attr('tabindex');
1433
$selection.attr('title', this.$element.attr('title'));
1434
$selection.attr('tabindex', this._tabindex);
1435
$selection.attr('aria-disabled', 'false');
1437
this.$selection = $selection;
1442
BaseSelection.prototype.bind = function (container, $container) {
1445
var resultsId = container.id + '-results';
1447
this.container = container;
1449
this.$selection.on('focus', function (evt) {
1450
self.trigger('focus', evt);
1453
this.$selection.on('blur', function (evt) {
1454
self._handleBlur(evt);
1457
this.$selection.on('keydown', function (evt) {
1458
self.trigger('keypress', evt);
1460
if (evt.which === KEYS.SPACE) {
1461
evt.preventDefault();
1465
container.on('results:focus', function (params) {
1466
self.$selection.attr('aria-activedescendant', params.data._resultId);
1469
container.on('selection:update', function (params) {
1470
self.update(params.data);
1473
container.on('open', function () {
1475
self.$selection.attr('aria-expanded', 'true');
1476
self.$selection.attr('aria-owns', resultsId);
1478
self._attachCloseHandler(container);
1481
container.on('close', function () {
1483
self.$selection.attr('aria-expanded', 'false');
1484
self.$selection.removeAttr('aria-activedescendant');
1485
self.$selection.removeAttr('aria-owns');
1487
self.$selection.trigger('focus');
1489
self._detachCloseHandler(container);
1492
container.on('enable', function () {
1493
self.$selection.attr('tabindex', self._tabindex);
1494
self.$selection.attr('aria-disabled', 'false');
1497
container.on('disable', function () {
1498
self.$selection.attr('tabindex', '-1');
1499
self.$selection.attr('aria-disabled', 'true');
1503
BaseSelection.prototype._handleBlur = function (evt) {
1508
window.setTimeout(function () {
1511
(document.activeElement == self.$selection[0]) ||
1512
($.contains(self.$selection[0], document.activeElement))
1517
self.trigger('blur', evt);
1521
BaseSelection.prototype._attachCloseHandler = function (container) {
1523
$(document.body).on('mousedown.select2.' + container.id, function (e) {
1524
var $target = $(e.target);
1526
var $select = $target.closest('.select2');
1528
var $all = $('.select2.select2-container--open');
1530
$all.each(function () {
1531
if (this == $select[0]) {
1535
var $element = Utils.GetData(this, 'element');
1537
$element.select2('close');
1542
BaseSelection.prototype._detachCloseHandler = function (container) {
1543
$(document.body).off('mousedown.select2.' + container.id);
1546
BaseSelection.prototype.position = function ($selection, $container) {
1547
var $selectionContainer = $container.find('.selection');
1548
$selectionContainer.append($selection);
1551
BaseSelection.prototype.destroy = function () {
1552
this._detachCloseHandler(this.container);
1555
BaseSelection.prototype.update = function (data) {
1556
throw new Error('The `update` method must be defined in child classes.');
1566
BaseSelection.prototype.isEnabled = function () {
1567
return !this.isDisabled();
1576
BaseSelection.prototype.isDisabled = function () {
1577
return this.options.get('disabled');
1580
return BaseSelection;
1583
S2.define('select2/selection/single',[
1588
], function ($, BaseSelection, Utils, KEYS) {
1589
function SingleSelection () {
1590
SingleSelection.__super__.constructor.apply(this, arguments);
1593
Utils.Extend(SingleSelection, BaseSelection);
1595
SingleSelection.prototype.render = function () {
1596
var $selection = SingleSelection.__super__.render.call(this);
1598
$selection.addClass('select2-selection--single');
1601
'<span class="select2-selection__rendered"></span>' +
1602
'<span class="select2-selection__arrow" role="presentation">' +
1603
'<b role="presentation"></b>' +
1610
SingleSelection.prototype.bind = function (container, $container) {
1613
SingleSelection.__super__.bind.apply(this, arguments);
1615
var id = container.id + '-container';
1617
this.$selection.find('.select2-selection__rendered')
1619
.attr('role', 'textbox')
1620
.attr('aria-readonly', 'true');
1621
this.$selection.attr('aria-labelledby', id);
1623
this.$selection.on('mousedown', function (evt) {
1625
if (evt.which !== 1) {
1629
self.trigger('toggle', {
1634
this.$selection.on('focus', function (evt) {
1638
this.$selection.on('blur', function (evt) {
1642
container.on('focus', function (evt) {
1643
if (!container.isOpen()) {
1644
self.$selection.trigger('focus');
1649
SingleSelection.prototype.clear = function () {
1650
var $rendered = this.$selection.find('.select2-selection__rendered');
1652
$rendered.removeAttr('title');
1655
SingleSelection.prototype.display = function (data, container) {
1656
var template = this.options.get('templateSelection');
1657
var escapeMarkup = this.options.get('escapeMarkup');
1659
return escapeMarkup(template(data, container));
1662
SingleSelection.prototype.selectionContainer = function () {
1663
return $('<span></span>');
1666
SingleSelection.prototype.update = function (data) {
1667
if (data.length === 0) {
1672
var selection = data[0];
1674
var $rendered = this.$selection.find('.select2-selection__rendered');
1675
var formatted = this.display(selection, $rendered);
1677
$rendered.empty().append(formatted);
1679
var title = selection.title || selection.text;
1682
$rendered.attr('title', title);
1684
$rendered.removeAttr('title');
1688
return SingleSelection;
1691
S2.define('select2/selection/multiple',[
1695
], function ($, BaseSelection, Utils) {
1696
function MultipleSelection ($element, options) {
1697
MultipleSelection.__super__.constructor.apply(this, arguments);
1700
Utils.Extend(MultipleSelection, BaseSelection);
1702
MultipleSelection.prototype.render = function () {
1703
var $selection = MultipleSelection.__super__.render.call(this);
1705
$selection.addClass('select2-selection--multiple');
1708
'<ul class="select2-selection__rendered"></ul>'
1714
MultipleSelection.prototype.bind = function (container, $container) {
1717
MultipleSelection.__super__.bind.apply(this, arguments);
1719
this.$selection.on('click', function (evt) {
1720
self.trigger('toggle', {
1727
'.select2-selection__choice__remove',
1730
if (self.isDisabled()) {
1734
var $remove = $(this);
1735
var $selection = $remove.parent();
1737
var data = Utils.GetData($selection[0], 'data');
1739
self.trigger('unselect', {
1747
MultipleSelection.prototype.clear = function () {
1748
var $rendered = this.$selection.find('.select2-selection__rendered');
1750
$rendered.removeAttr('title');
1753
MultipleSelection.prototype.display = function (data, container) {
1754
var template = this.options.get('templateSelection');
1755
var escapeMarkup = this.options.get('escapeMarkup');
1757
return escapeMarkup(template(data, container));
1760
MultipleSelection.prototype.selectionContainer = function () {
1762
'<li class="select2-selection__choice">' +
1763
'<span class="select2-selection__choice__remove" role="presentation">' +
1772
MultipleSelection.prototype.update = function (data) {
1775
if (data.length === 0) {
1779
var $selections = [];
1781
for (var d = 0; d < data.length; d++) {
1782
var selection = data[d];
1784
var $selection = this.selectionContainer();
1785
var formatted = this.display(selection, $selection);
1787
$selection.append(formatted);
1789
var title = selection.title || selection.text;
1792
$selection.attr('title', title);
1795
Utils.StoreData($selection[0], 'data', selection);
1797
$selections.push($selection);
1800
var $rendered = this.$selection.find('.select2-selection__rendered');
1802
Utils.appendMany($rendered, $selections);
1805
return MultipleSelection;
1808
S2.define('select2/selection/placeholder',[
1810
], function (Utils) {
1811
function Placeholder (decorated, $element, options) {
1812
this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
1814
decorated.call(this, $element, options);
1817
Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
1818
if (typeof placeholder === 'string') {
1828
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
1829
var $placeholder = this.selectionContainer();
1831
$placeholder.html(this.display(placeholder));
1832
$placeholder.addClass('select2-selection__placeholder')
1833
.removeClass('select2-selection__choice');
1835
return $placeholder;
1838
Placeholder.prototype.update = function (decorated, data) {
1839
var singlePlaceholder = (
1840
data.length == 1 && data[0].id != this.placeholder.id
1842
var multipleSelections = data.length > 1;
1844
if (multipleSelections || singlePlaceholder) {
1845
return decorated.call(this, data);
1850
var $placeholder = this.createPlaceholder(this.placeholder);
1852
this.$selection.find('.select2-selection__rendered').append($placeholder);
1858
S2.define('select2/selection/allowClear',[
1862
], function ($, KEYS, Utils) {
1863
function AllowClear () { }
1865
AllowClear.prototype.bind = function (decorated, container, $container) {
1868
decorated.call(this, container, $container);
1870
if (this.placeholder == null) {
1871
if (this.options.get('debug') && window.console && console.error) {
1873
'Select2: The `allowClear` option should be used in combination ' +
1874
'with the `placeholder` option.'
1879
this.$selection.on('mousedown', '.select2-selection__clear',
1881
self._handleClear(evt);
1884
container.on('keypress', function (evt) {
1885
self._handleKeyboardClear(evt, container);
1889
AllowClear.prototype._handleClear = function (_, evt) {
1891
if (this.isDisabled()) {
1895
var $clear = this.$selection.find('.select2-selection__clear');
1898
if ($clear.length === 0) {
1902
evt.stopPropagation();
1904
var data = Utils.GetData($clear[0], 'data');
1906
var previousVal = this.$element.val();
1907
this.$element.val(this.placeholder.id);
1909
var unselectData = {
1912
this.trigger('clear', unselectData);
1913
if (unselectData.prevented) {
1914
this.$element.val(previousVal);
1918
for (var d = 0; d < data.length; d++) {
1925
this.trigger('unselect', unselectData);
1928
if (unselectData.prevented) {
1929
this.$element.val(previousVal);
1934
this.$element.trigger('input').trigger('change');
1936
this.trigger('toggle', {});
1939
AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
1940
if (container.isOpen()) {
1944
if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
1945
this._handleClear(evt);
1949
AllowClear.prototype.update = function (decorated, data) {
1950
decorated.call(this, data);
1952
if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
1953
data.length === 0) {
1957
var removeAll = this.options.get('translations').get('removeAllItems');
1960
'<span class="select2-selection__clear" title="' + removeAll() +'">' +
1964
Utils.StoreData($remove[0], 'data', data);
1966
this.$selection.find('.select2-selection__rendered').prepend($remove);
1972
S2.define('select2/selection/search',[
1976
], function ($, Utils, KEYS) {
1977
function Search (decorated, $element, options) {
1978
decorated.call(this, $element, options);
1981
Search.prototype.render = function (decorated) {
1983
'<li class="select2-search select2-search--inline">' +
1984
'<input class="select2-search__field" type="search" tabindex="-1"' +
1985
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
1986
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
1990
this.$searchContainer = $search;
1991
this.$search = $search.find('input');
1993
var $rendered = decorated.call(this);
1995
this._transferTabIndex();
2000
Search.prototype.bind = function (decorated, container, $container) {
2003
var resultsId = container.id + '-results';
2005
decorated.call(this, container, $container);
2007
container.on('open', function () {
2008
self.$search.attr('aria-controls', resultsId);
2009
self.$search.trigger('focus');
2012
container.on('close', function () {
2013
self.$search.val('');
2014
self.$search.removeAttr('aria-controls');
2015
self.$search.removeAttr('aria-activedescendant');
2016
self.$search.trigger('focus');
2019
container.on('enable', function () {
2020
self.$search.prop('disabled', false);
2022
self._transferTabIndex();
2025
container.on('disable', function () {
2026
self.$search.prop('disabled', true);
2029
container.on('focus', function (evt) {
2030
self.$search.trigger('focus');
2033
container.on('results:focus', function (params) {
2034
if (params.data._resultId) {
2035
self.$search.attr('aria-activedescendant', params.data._resultId);
2037
self.$search.removeAttr('aria-activedescendant');
2041
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
2042
self.trigger('focus', evt);
2045
this.$selection.on('focusout', '.select2-search--inline', function (evt) {
2046
self._handleBlur(evt);
2049
this.$selection.on('keydown', '.select2-search--inline', function (evt) {
2050
evt.stopPropagation();
2052
self.trigger('keypress', evt);
2054
self._keyUpPrevented = evt.isDefaultPrevented();
2056
var key = evt.which;
2058
if (key === KEYS.BACKSPACE && self.$search.val() === '') {
2059
var $previousChoice = self.$searchContainer
2060
.prev('.select2-selection__choice');
2062
if ($previousChoice.length > 0) {
2063
var item = Utils.GetData($previousChoice[0], 'data');
2065
self.searchRemoveChoice(item);
2067
evt.preventDefault();
2072
this.$selection.on('click', '.select2-search--inline', function (evt) {
2073
if (self.$search.val()) {
2074
evt.stopPropagation();
2083
var msie = document.documentMode;
2084
var disableInputEvents = msie && msie <= 11;
2090
'input.searchcheck',
2091
'.select2-search--inline',
2096
if (disableInputEvents) {
2097
self.$selection.off('input.search input.searchcheck');
2102
self.$selection.off('keyup.search');
2107
'keyup.search input.search',
2108
'.select2-search--inline',
2113
if (disableInputEvents && evt.type === 'input') {
2114
self.$selection.off('input.search input.searchcheck');
2118
var key = evt.which;
2121
if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
2126
if (key == KEYS.TAB) {
2130
self.handleSearch(evt);
2142
Search.prototype._transferTabIndex = function (decorated) {
2143
this.$search.attr('tabindex', this.$selection.attr('tabindex'));
2144
this.$selection.attr('tabindex', '-1');
2147
Search.prototype.createPlaceholder = function (decorated, placeholder) {
2148
this.$search.attr('placeholder', placeholder.text);
2151
Search.prototype.update = function (decorated, data) {
2152
var searchHadFocus = this.$search[0] == document.activeElement;
2154
this.$search.attr('placeholder', '');
2156
decorated.call(this, data);
2158
this.$selection.find('.select2-selection__rendered')
2159
.append(this.$searchContainer);
2161
this.resizeSearch();
2162
if (searchHadFocus) {
2163
this.$search.trigger('focus');
2167
Search.prototype.handleSearch = function () {
2168
this.resizeSearch();
2170
if (!this._keyUpPrevented) {
2171
var input = this.$search.val();
2173
this.trigger('query', {
2178
this._keyUpPrevented = false;
2181
Search.prototype.searchRemoveChoice = function (decorated, item) {
2182
this.trigger('unselect', {
2186
this.$search.val(item.text);
2187
this.handleSearch();
2190
Search.prototype.resizeSearch = function () {
2191
this.$search.css('width', '25px');
2195
if (this.$search.attr('placeholder') !== '') {
2196
width = this.$selection.find('.select2-selection__rendered').width();
2198
var minimumWidth = this.$search.val().length + 1;
2200
width = (minimumWidth * 0.75) + 'em';
2203
this.$search.css('width', width);
2209
S2.define('select2/selection/eventRelay',[
2212
function EventRelay () { }
2214
EventRelay.prototype.bind = function (decorated, container, $container) {
2219
'select', 'selecting',
2220
'unselect', 'unselecting',
2224
var preventableEvents = [
2225
'opening', 'closing', 'selecting', 'unselecting', 'clearing'
2228
decorated.call(this, container, $container);
2230
container.on('*', function (name, params) {
2232
if ($.inArray(name, relayEvents) === -1) {
2237
params = params || {};
2240
var evt = $.Event('select2:' + name, {
2244
self.$element.trigger(evt);
2247
if ($.inArray(name, preventableEvents) === -1) {
2251
params.prevented = evt.isDefaultPrevented();
2258
S2.define('select2/translation',[
2261
], function ($, require) {
2262
function Translation (dict) {
2263
this.dict = dict || {};
2266
Translation.prototype.all = function () {
2270
Translation.prototype.get = function (key) {
2271
return this.dict[key];
2274
Translation.prototype.extend = function (translation) {
2275
this.dict = $.extend({}, translation.all(), this.dict);
2280
Translation._cache = {};
2282
Translation.loadPath = function (path) {
2283
if (!(path in Translation._cache)) {
2284
var translations = require(path);
2286
Translation._cache[path] = translations;
2289
return new Translation(Translation._cache[path]);
2295
S2.define('select2/diacritics',[
3146
S2.define('select2/data/base',[
3148
], function (Utils) {
3149
function BaseAdapter ($element, options) {
3150
BaseAdapter.__super__.constructor.call(this);
3153
Utils.Extend(BaseAdapter, Utils.Observable);
3155
BaseAdapter.prototype.current = function (callback) {
3156
throw new Error('The `current` method must be defined in child classes.');
3159
BaseAdapter.prototype.query = function (params, callback) {
3160
throw new Error('The `query` method must be defined in child classes.');
3163
BaseAdapter.prototype.bind = function (container, $container) {
3167
BaseAdapter.prototype.destroy = function () {
3171
BaseAdapter.prototype.generateResultId = function (container, data) {
3172
var id = container.id + '-result-';
3174
id += Utils.generateChars(4);
3176
if (data.id != null) {
3177
id += '-' + data.id.toString();
3179
id += '-' + Utils.generateChars(4);
3187
S2.define('select2/data/select',[
3191
], function (BaseAdapter, Utils, $) {
3192
function SelectAdapter ($element, options) {
3193
this.$element = $element;
3194
this.options = options;
3196
SelectAdapter.__super__.constructor.call(this);
3199
Utils.Extend(SelectAdapter, BaseAdapter);
3201
SelectAdapter.prototype.current = function (callback) {
3205
this.$element.find(':selected').each(function () {
3206
var $option = $(this);
3208
var option = self.item($option);
3216
SelectAdapter.prototype.select = function (data) {
3219
data.selected = true;
3222
if ($(data.element).is('option')) {
3223
data.element.selected = true;
3225
this.$element.trigger('input').trigger('change');
3230
if (this.$element.prop('multiple')) {
3231
this.current(function (currentData) {
3235
data.push.apply(data, currentData);
3237
for (var d = 0; d < data.length; d++) {
3238
var id = data[d].id;
3240
if ($.inArray(id, val) === -1) {
3245
self.$element.val(val);
3246
self.$element.trigger('input').trigger('change');
3251
this.$element.val(val);
3252
this.$element.trigger('input').trigger('change');
3256
SelectAdapter.prototype.unselect = function (data) {
3259
if (!this.$element.prop('multiple')) {
3263
data.selected = false;
3265
if ($(data.element).is('option')) {
3266
data.element.selected = false;
3268
this.$element.trigger('input').trigger('change');
3273
this.current(function (currentData) {
3276
for (var d = 0; d < currentData.length; d++) {
3277
var id = currentData[d].id;
3279
if (id !== data.id && $.inArray(id, val) === -1) {
3284
self.$element.val(val);
3286
self.$element.trigger('input').trigger('change');
3290
SelectAdapter.prototype.bind = function (container, $container) {
3293
this.container = container;
3295
container.on('select', function (params) {
3296
self.select(params.data);
3299
container.on('unselect', function (params) {
3300
self.unselect(params.data);
3304
SelectAdapter.prototype.destroy = function () {
3306
this.$element.find('*').each(function () {
3308
Utils.RemoveData(this);
3312
SelectAdapter.prototype.query = function (params, callback) {
3316
var $options = this.$element.children();
3318
$options.each(function () {
3319
var $option = $(this);
3321
if (!$option.is('option') && !$option.is('optgroup')) {
3325
var option = self.item($option);
3327
var matches = self.matches(params, option);
3329
if (matches !== null) {
3339
SelectAdapter.prototype.addOptions = function ($options) {
3340
Utils.appendMany(this.$element, $options);
3343
SelectAdapter.prototype.option = function (data) {
3346
if (data.children) {
3347
option = document.createElement('optgroup');
3348
option.label = data.text;
3350
option = document.createElement('option');
3352
if (option.textContent !== undefined) {
3353
option.textContent = data.text;
3355
option.innerText = data.text;
3359
if (data.id !== undefined) {
3360
option.value = data.id;
3363
if (data.disabled) {
3364
option.disabled = true;
3367
if (data.selected) {
3368
option.selected = true;
3372
option.title = data.title;
3375
var $option = $(option);
3377
var normalizedData = this._normalizeItem(data);
3378
normalizedData.element = option;
3381
Utils.StoreData(option, 'data', normalizedData);
3386
SelectAdapter.prototype.item = function ($option) {
3389
data = Utils.GetData($option[0], 'data');
3395
if ($option.is('option')) {
3398
text: $option.text(),
3399
disabled: $option.prop('disabled'),
3400
selected: $option.prop('selected'),
3401
title: $option.prop('title')
3403
} else if ($option.is('optgroup')) {
3405
text: $option.prop('label'),
3407
title: $option.prop('title')
3410
var $children = $option.children('option');
3413
for (var c = 0; c < $children.length; c++) {
3414
var $child = $($children[c]);
3416
var child = this.item($child);
3418
children.push(child);
3421
data.children = children;
3424
data = this._normalizeItem(data);
3425
data.element = $option[0];
3427
Utils.StoreData($option[0], 'data', data);
3432
SelectAdapter.prototype._normalizeItem = function (item) {
3433
if (item !== Object(item)) {
3440
item = $.extend({}, {
3449
if (item.id != null) {
3450
item.id = item.id.toString();
3453
if (item.text != null) {
3454
item.text = item.text.toString();
3457
if (item._resultId == null && item.id && this.container != null) {
3458
item._resultId = this.generateResultId(this.container, item);
3461
return $.extend({}, defaults, item);
3464
SelectAdapter.prototype.matches = function (params, data) {
3465
var matcher = this.options.get('matcher');
3467
return matcher(params, data);
3470
return SelectAdapter;
3473
S2.define('select2/data/array',[
3477
], function (SelectAdapter, Utils, $) {
3478
function ArrayAdapter ($element, options) {
3479
this._dataToConvert = options.get('data') || [];
3481
ArrayAdapter.__super__.constructor.call(this, $element, options);
3484
Utils.Extend(ArrayAdapter, SelectAdapter);
3486
ArrayAdapter.prototype.bind = function (container, $container) {
3487
ArrayAdapter.__super__.bind.call(this, container, $container);
3489
this.addOptions(this.convertToOptions(this._dataToConvert));
3492
ArrayAdapter.prototype.select = function (data) {
3493
var $option = this.$element.find('option').filter(function (i, elm) {
3494
return elm.value == data.id.toString();
3497
if ($option.length === 0) {
3498
$option = this.option(data);
3500
this.addOptions($option);
3503
ArrayAdapter.__super__.select.call(this, data);
3506
ArrayAdapter.prototype.convertToOptions = function (data) {
3509
var $existing = this.$element.find('option');
3510
var existingIds = $existing.map(function () {
3511
return self.item($(this)).id;
3517
function onlyItem (item) {
3518
return function () {
3519
return $(this).val() == item.id;
3523
for (var d = 0; d < data.length; d++) {
3524
var item = this._normalizeItem(data[d]);
3527
if ($.inArray(item.id, existingIds) >= 0) {
3528
var $existingOption = $existing.filter(onlyItem(item));
3530
var existingData = this.item($existingOption);
3531
var newData = $.extend(true, {}, item, existingData);
3533
var $newOption = this.option(newData);
3535
$existingOption.replaceWith($newOption);
3540
var $option = this.option(item);
3542
if (item.children) {
3543
var $children = this.convertToOptions(item.children);
3545
Utils.appendMany($option, $children);
3548
$options.push($option);
3554
return ArrayAdapter;
3557
S2.define('select2/data/ajax',[
3561
], function (ArrayAdapter, Utils, $) {
3562
function AjaxAdapter ($element, options) {
3563
this.ajaxOptions = this._applyDefaults(options.get('ajax'));
3565
if (this.ajaxOptions.processResults != null) {
3566
this.processResults = this.ajaxOptions.processResults;
3569
AjaxAdapter.__super__.constructor.call(this, $element, options);
3572
Utils.Extend(AjaxAdapter, ArrayAdapter);
3574
AjaxAdapter.prototype._applyDefaults = function (options) {
3576
data: function (params) {
3577
return $.extend({}, params, {
3581
transport: function (params, success, failure) {
3582
var $request = $.ajax(params);
3584
$request.then(success);
3585
$request.fail(failure);
3591
return $.extend({}, defaults, options, true);
3594
AjaxAdapter.prototype.processResults = function (results) {
3598
AjaxAdapter.prototype.query = function (params, callback) {
3602
if (this._request != null) {
3604
if ($.isFunction(this._request.abort)) {
3605
this._request.abort();
3608
this._request = null;
3611
var options = $.extend({
3613
}, this.ajaxOptions);
3615
if (typeof options.url === 'function') {
3616
options.url = options.url.call(this.$element, params);
3619
if (typeof options.data === 'function') {
3620
options.data = options.data.call(this.$element, params);
3623
function request () {
3624
var $request = options.transport(options, function (data) {
3625
var results = self.processResults(data, params);
3627
if (self.options.get('debug') && window.console && console.error) {
3629
if (!results || !results.results || !$.isArray(results.results)) {
3631
'Select2: The AJAX results did not return an array in the ' +
3632
'`results` key of the response.'
3641
if ('status' in $request &&
3642
($request.status === 0 || $request.status === '0')) {
3646
self.trigger('results:message', {
3647
message: 'errorLoading'
3651
self._request = $request;
3654
if (this.ajaxOptions.delay && params.term != null) {
3655
if (this._queryTimeout) {
3656
window.clearTimeout(this._queryTimeout);
3659
this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
3668
S2.define('select2/data/tags',[
3671
function Tags (decorated, $element, options) {
3672
var tags = options.get('tags');
3674
var createTag = options.get('createTag');
3676
if (createTag !== undefined) {
3677
this.createTag = createTag;
3680
var insertTag = options.get('insertTag');
3682
if (insertTag !== undefined) {
3683
this.insertTag = insertTag;
3686
decorated.call(this, $element, options);
3688
if ($.isArray(tags)) {
3689
for (var t = 0; t < tags.length; t++) {
3691
var item = this._normalizeItem(tag);
3693
var $option = this.option(item);
3695
this.$element.append($option);
3700
Tags.prototype.query = function (decorated, params, callback) {
3703
this._removeOldTags();
3705
if (params.term == null || params.page != null) {
3706
decorated.call(this, params, callback);
3710
function wrapper (obj, child) {
3711
var data = obj.results;
3713
for (var i = 0; i < data.length; i++) {
3714
var option = data[i];
3716
var checkChildren = (
3717
option.children != null &&
3719
results: option.children
3723
var optionText = (option.text || '').toUpperCase();
3724
var paramsTerm = (params.term || '').toUpperCase();
3726
var checkText = optionText === paramsTerm;
3728
if (checkText || checkChildren) {
3744
var tag = self.createTag(params);
3747
var $option = self.option(tag);
3748
$option.attr('data-select2-tag', true);
3750
self.addOptions([$option]);
3752
self.insertTag(data, tag);
3760
decorated.call(this, params, wrapper);
3763
Tags.prototype.createTag = function (decorated, params) {
3764
var term = $.trim(params.term);
3776
Tags.prototype.insertTag = function (_, data, tag) {
3780
Tags.prototype._removeOldTags = function (_) {
3781
var $options = this.$element.find('option[data-select2-tag]');
3783
$options.each(function () {
3784
if (this.selected) {
3795
S2.define('select2/data/tokenizer',[
3798
function Tokenizer (decorated, $element, options) {
3799
var tokenizer = options.get('tokenizer');
3801
if (tokenizer !== undefined) {
3802
this.tokenizer = tokenizer;
3805
decorated.call(this, $element, options);
3808
Tokenizer.prototype.bind = function (decorated, container, $container) {
3809
decorated.call(this, container, $container);
3811
this.$search = container.dropdown.$search || container.selection.$search ||
3812
$container.find('.select2-search__field');
3815
Tokenizer.prototype.query = function (decorated, params, callback) {
3818
function createAndSelect (data) {
3820
var item = self._normalizeItem(data);
3824
var $existingOptions = self.$element.find('option').filter(function () {
3825
return $(this).val() === item.id;
3829
if (!$existingOptions.length) {
3830
var $option = self.option(item);
3831
$option.attr('data-select2-tag', true);
3833
self._removeOldTags();
3834
self.addOptions([$option]);
3841
function select (data) {
3842
self.trigger('select', {
3847
params.term = params.term || '';
3849
var tokenData = this.tokenizer(params, this.options, createAndSelect);
3851
if (tokenData.term !== params.term) {
3853
if (this.$search.length) {
3854
this.$search.val(tokenData.term);
3855
this.$search.trigger('focus');
3858
params.term = tokenData.term;
3861
decorated.call(this, params, callback);
3864
Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
3865
var separators = options.get('tokenSeparators') || [];
3866
var term = params.term;
3869
var createTag = this.createTag || function (params) {
3876
while (i < term.length) {
3877
var termChar = term[i];
3879
if ($.inArray(termChar, separators) === -1) {
3885
var part = term.substr(0, i);
3886
var partParams = $.extend({}, params, {
3890
var data = createTag(partParams);
3900
term = term.substr(i + 1) || '';
3912
S2.define('select2/data/minimumInputLength',[
3915
function MinimumInputLength (decorated, $e, options) {
3916
this.minimumInputLength = options.get('minimumInputLength');
3918
decorated.call(this, $e, options);
3921
MinimumInputLength.prototype.query = function (decorated, params, callback) {
3922
params.term = params.term || '';
3924
if (params.term.length < this.minimumInputLength) {
3925
this.trigger('results:message', {
3926
message: 'inputTooShort',
3928
minimum: this.minimumInputLength,
3937
decorated.call(this, params, callback);
3940
return MinimumInputLength;
3943
S2.define('select2/data/maximumInputLength',[
3946
function MaximumInputLength (decorated, $e, options) {
3947
this.maximumInputLength = options.get('maximumInputLength');
3949
decorated.call(this, $e, options);
3952
MaximumInputLength.prototype.query = function (decorated, params, callback) {
3953
params.term = params.term || '';
3955
if (this.maximumInputLength > 0 &&
3956
params.term.length > this.maximumInputLength) {
3957
this.trigger('results:message', {
3958
message: 'inputTooLong',
3960
maximum: this.maximumInputLength,
3969
decorated.call(this, params, callback);
3972
return MaximumInputLength;
3975
S2.define('select2/data/maximumSelectionLength',[
3978
function MaximumSelectionLength (decorated, $e, options) {
3979
this.maximumSelectionLength = options.get('maximumSelectionLength');
3981
decorated.call(this, $e, options);
3984
MaximumSelectionLength.prototype.bind =
3985
function (decorated, container, $container) {
3988
decorated.call(this, container, $container);
3990
container.on('select', function () {
3991
self._checkIfMaximumSelected();
3995
MaximumSelectionLength.prototype.query =
3996
function (decorated, params, callback) {
3999
this._checkIfMaximumSelected(function () {
4000
decorated.call(self, params, callback);
4004
MaximumSelectionLength.prototype._checkIfMaximumSelected =
4005
function (_, successCallback) {
4008
this.current(function (currentData) {
4009
var count = currentData != null ? currentData.length : 0;
4010
if (self.maximumSelectionLength > 0 &&
4011
count >= self.maximumSelectionLength) {
4012
self.trigger('results:message', {
4013
message: 'maximumSelected',
4015
maximum: self.maximumSelectionLength
4021
if (successCallback) {
4027
return MaximumSelectionLength;
4030
S2.define('select2/dropdown',[
4033
], function ($, Utils) {
4034
function Dropdown ($element, options) {
4035
this.$element = $element;
4036
this.options = options;
4038
Dropdown.__super__.constructor.call(this);
4041
Utils.Extend(Dropdown, Utils.Observable);
4043
Dropdown.prototype.render = function () {
4045
'<span class="select2-dropdown">' +
4046
'<span class="select2-results"></span>' +
4050
$dropdown.attr('dir', this.options.get('dir'));
4052
this.$dropdown = $dropdown;
4057
Dropdown.prototype.bind = function () {
4061
Dropdown.prototype.position = function ($dropdown, $container) {
4065
Dropdown.prototype.destroy = function () {
4067
this.$dropdown.remove();
4073
S2.define('select2/dropdown/search',[
4076
], function ($, Utils) {
4077
function Search () { }
4079
Search.prototype.render = function (decorated) {
4080
var $rendered = decorated.call(this);
4083
'<span class="select2-search select2-search--dropdown">' +
4084
'<input class="select2-search__field" type="search" tabindex="-1"' +
4085
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
4086
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
4090
this.$searchContainer = $search;
4091
this.$search = $search.find('input');
4093
$rendered.prepend($search);
4098
Search.prototype.bind = function (decorated, container, $container) {
4101
var resultsId = container.id + '-results';
4103
decorated.call(this, container, $container);
4105
this.$search.on('keydown', function (evt) {
4106
self.trigger('keypress', evt);
4108
self._keyUpPrevented = evt.isDefaultPrevented();
4114
this.$search.on('input', function (evt) {
4116
$(this).off('keyup');
4119
this.$search.on('keyup input', function (evt) {
4120
self.handleSearch(evt);
4123
container.on('open', function () {
4124
self.$search.attr('tabindex', 0);
4125
self.$search.attr('aria-controls', resultsId);
4127
self.$search.trigger('focus');
4129
window.setTimeout(function () {
4130
self.$search.trigger('focus');
4134
container.on('close', function () {
4135
self.$search.attr('tabindex', -1);
4136
self.$search.removeAttr('aria-controls');
4137
self.$search.removeAttr('aria-activedescendant');
4139
self.$search.val('');
4140
self.$search.trigger('blur');
4143
container.on('focus', function () {
4144
if (!container.isOpen()) {
4145
self.$search.trigger('focus');
4149
container.on('results:all', function (params) {
4150
if (params.query.term == null || params.query.term === '') {
4151
var showSearch = self.showSearch(params);
4154
self.$searchContainer.removeClass('select2-search--hide');
4156
self.$searchContainer.addClass('select2-search--hide');
4161
container.on('results:focus', function (params) {
4162
if (params.data._resultId) {
4163
self.$search.attr('aria-activedescendant', params.data._resultId);
4165
self.$search.removeAttr('aria-activedescendant');
4170
Search.prototype.handleSearch = function (evt) {
4171
if (!this._keyUpPrevented) {
4172
var input = this.$search.val();
4174
this.trigger('query', {
4179
this._keyUpPrevented = false;
4182
Search.prototype.showSearch = function (_, params) {
4189
S2.define('select2/dropdown/hidePlaceholder',[
4192
function HidePlaceholder (decorated, $element, options, dataAdapter) {
4193
this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
4195
decorated.call(this, $element, options, dataAdapter);
4198
HidePlaceholder.prototype.append = function (decorated, data) {
4199
data.results = this.removePlaceholder(data.results);
4201
decorated.call(this, data);
4204
HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
4205
if (typeof placeholder === 'string') {
4215
HidePlaceholder.prototype.removePlaceholder = function (_, data) {
4216
var modifiedData = data.slice(0);
4218
for (var d = data.length - 1; d >= 0; d--) {
4221
if (this.placeholder.id === item.id) {
4222
modifiedData.splice(d, 1);
4226
return modifiedData;
4229
return HidePlaceholder;
4232
S2.define('select2/dropdown/infiniteScroll',[
4235
function InfiniteScroll (decorated, $element, options, dataAdapter) {
4236
this.lastParams = {};
4238
decorated.call(this, $element, options, dataAdapter);
4240
this.$loadingMore = this.createLoadingMore();
4241
this.loading = false;
4244
InfiniteScroll.prototype.append = function (decorated, data) {
4245
this.$loadingMore.remove();
4246
this.loading = false;
4248
decorated.call(this, data);
4250
if (this.showLoadingMore(data)) {
4251
this.$results.append(this.$loadingMore);
4252
this.loadMoreIfNeeded();
4256
InfiniteScroll.prototype.bind = function (decorated, container, $container) {
4259
decorated.call(this, container, $container);
4261
container.on('query', function (params) {
4262
self.lastParams = params;
4263
self.loading = true;
4266
container.on('query:append', function (params) {
4267
self.lastParams = params;
4268
self.loading = true;
4271
this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
4274
InfiniteScroll.prototype.loadMoreIfNeeded = function () {
4275
var isLoadMoreVisible = $.contains(
4276
document.documentElement,
4277
this.$loadingMore[0]
4280
if (this.loading || !isLoadMoreVisible) {
4284
var currentOffset = this.$results.offset().top +
4285
this.$results.outerHeight(false);
4286
var loadingMoreOffset = this.$loadingMore.offset().top +
4287
this.$loadingMore.outerHeight(false);
4289
if (currentOffset + 50 >= loadingMoreOffset) {
4294
InfiniteScroll.prototype.loadMore = function () {
4295
this.loading = true;
4297
var params = $.extend({}, {page: 1}, this.lastParams);
4301
this.trigger('query:append', params);
4304
InfiniteScroll.prototype.showLoadingMore = function (_, data) {
4305
return data.pagination && data.pagination.more;
4308
InfiniteScroll.prototype.createLoadingMore = function () {
4311
'class="select2-results__option select2-results__option--load-more"' +
4312
'role="option" aria-disabled="true"></li>'
4315
var message = this.options.get('translations').get('loadingMore');
4317
$option.html(message(this.lastParams));
4322
return InfiniteScroll;
4325
S2.define('select2/dropdown/attachBody',[
4328
], function ($, Utils) {
4329
function AttachBody (decorated, $element, options) {
4330
this.$dropdownParent = $(options.get('dropdownParent') || document.body);
4332
decorated.call(this, $element, options);
4335
AttachBody.prototype.bind = function (decorated, container, $container) {
4338
decorated.call(this, container, $container);
4340
container.on('open', function () {
4341
self._showDropdown();
4342
self._attachPositioningHandler(container);
4345
self._bindContainerResultHandlers(container);
4348
container.on('close', function () {
4349
self._hideDropdown();
4350
self._detachPositioningHandler(container);
4353
this.$dropdownContainer.on('mousedown', function (evt) {
4354
evt.stopPropagation();
4358
AttachBody.prototype.destroy = function (decorated) {
4359
decorated.call(this);
4361
this.$dropdownContainer.remove();
4364
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
4366
$dropdown.attr('class', $container.attr('class'));
4368
$dropdown.removeClass('select2');
4369
$dropdown.addClass('select2-container--open');
4372
position: 'absolute',
4376
this.$container = $container;
4379
AttachBody.prototype.render = function (decorated) {
4380
var $container = $('<span></span>');
4382
var $dropdown = decorated.call(this);
4383
$container.append($dropdown);
4385
this.$dropdownContainer = $container;
4390
AttachBody.prototype._hideDropdown = function (decorated) {
4391
this.$dropdownContainer.detach();
4394
AttachBody.prototype._bindContainerResultHandlers =
4395
function (decorated, container) {
4398
if (this._containerResultsHandlersBound) {
4404
container.on('results:all', function () {
4405
self._positionDropdown();
4406
self._resizeDropdown();
4409
container.on('results:append', function () {
4410
self._positionDropdown();
4411
self._resizeDropdown();
4414
container.on('results:message', function () {
4415
self._positionDropdown();
4416
self._resizeDropdown();
4419
container.on('select', function () {
4420
self._positionDropdown();
4421
self._resizeDropdown();
4424
container.on('unselect', function () {
4425
self._positionDropdown();
4426
self._resizeDropdown();
4429
this._containerResultsHandlersBound = true;
4432
AttachBody.prototype._attachPositioningHandler =
4433
function (decorated, container) {
4436
var scrollEvent = 'scroll.select2.' + container.id;
4437
var resizeEvent = 'resize.select2.' + container.id;
4438
var orientationEvent = 'orientationchange.select2.' + container.id;
4440
var $watchers = this.$container.parents().filter(Utils.hasScroll);
4441
$watchers.each(function () {
4442
Utils.StoreData(this, 'select2-scroll-position', {
4443
x: $(this).scrollLeft(),
4444
y: $(this).scrollTop()
4448
$watchers.on(scrollEvent, function (ev) {
4449
var position = Utils.GetData(this, 'select2-scroll-position');
4450
$(this).scrollTop(position.y);
4453
$(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
4455
self._positionDropdown();
4456
self._resizeDropdown();
4460
AttachBody.prototype._detachPositioningHandler =
4461
function (decorated, container) {
4462
var scrollEvent = 'scroll.select2.' + container.id;
4463
var resizeEvent = 'resize.select2.' + container.id;
4464
var orientationEvent = 'orientationchange.select2.' + container.id;
4466
var $watchers = this.$container.parents().filter(Utils.hasScroll);
4467
$watchers.off(scrollEvent);
4469
$(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
4472
AttachBody.prototype._positionDropdown = function () {
4473
var $window = $(window);
4475
var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
4476
var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
4478
var newDirection = null;
4480
var offset = this.$container.offset();
4482
offset.bottom = offset.top + this.$container.outerHeight(false);
4485
height: this.$container.outerHeight(false)
4488
container.top = offset.top;
4489
container.bottom = offset.top + container.height;
4492
height: this.$dropdown.outerHeight(false)
4496
top: $window.scrollTop(),
4497
bottom: $window.scrollTop() + $window.height()
4500
var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
4501
var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
4505
top: container.bottom
4509
var $offsetParent = this.$dropdownParent;
4513
if ($offsetParent.css('position') === 'static') {
4514
$offsetParent = $offsetParent.offsetParent();
4517
var parentOffset = {
4523
$.contains(document.body, $offsetParent[0]) ||
4524
$offsetParent[0].isConnected
4526
parentOffset = $offsetParent.offset();
4529
css.top -= parentOffset.top;
4530
css.left -= parentOffset.left;
4532
if (!isCurrentlyAbove && !isCurrentlyBelow) {
4533
newDirection = 'below';
4536
if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
4537
newDirection = 'above';
4538
} else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
4539
newDirection = 'below';
4542
if (newDirection == 'above' ||
4543
(isCurrentlyAbove && newDirection !== 'below')) {
4544
css.top = container.top - parentOffset.top - dropdown.height;
4547
if (newDirection != null) {
4549
.removeClass('select2-dropdown--below select2-dropdown--above')
4550
.addClass('select2-dropdown--' + newDirection);
4552
.removeClass('select2-container--below select2-container--above')
4553
.addClass('select2-container--' + newDirection);
4556
this.$dropdownContainer.css(css);
4559
AttachBody.prototype._resizeDropdown = function () {
4561
width: this.$container.outerWidth(false) + 'px'
4564
if (this.options.get('dropdownAutoWidth')) {
4565
css.minWidth = css.width;
4566
css.position = 'relative';
4570
this.$dropdown.css(css);
4573
AttachBody.prototype._showDropdown = function (decorated) {
4574
this.$dropdownContainer.appendTo(this.$dropdownParent);
4576
this._positionDropdown();
4577
this._resizeDropdown();
4583
S2.define('select2/dropdown/minimumResultsForSearch',[
4586
function countResults (data) {
4589
for (var d = 0; d < data.length; d++) {
4592
if (item.children) {
4593
count += countResults(item.children);
4602
function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
4603
this.minimumResultsForSearch = options.get('minimumResultsForSearch');
4605
if (this.minimumResultsForSearch < 0) {
4606
this.minimumResultsForSearch = Infinity;
4609
decorated.call(this, $element, options, dataAdapter);
4612
MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
4613
if (countResults(params.data.results) < this.minimumResultsForSearch) {
4617
return decorated.call(this, params);
4620
return MinimumResultsForSearch;
4623
S2.define('select2/dropdown/selectOnClose',[
4625
], function (Utils) {
4626
function SelectOnClose () { }
4628
SelectOnClose.prototype.bind = function (decorated, container, $container) {
4631
decorated.call(this, container, $container);
4633
container.on('close', function (params) {
4634
self._handleSelectOnClose(params);
4638
SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
4639
if (params && params.originalSelect2Event != null) {
4640
var event = params.originalSelect2Event;
4644
if (event._type === 'select' || event._type === 'unselect') {
4649
var $highlightedResults = this.getHighlightedResults();
4652
if ($highlightedResults.length < 1) {
4656
var data = Utils.GetData($highlightedResults[0], 'data');
4660
(data.element != null && data.element.selected) ||
4661
(data.element == null && data.selected)
4666
this.trigger('select', {
4671
return SelectOnClose;
4674
S2.define('select2/dropdown/closeOnSelect',[
4677
function CloseOnSelect () { }
4679
CloseOnSelect.prototype.bind = function (decorated, container, $container) {
4682
decorated.call(this, container, $container);
4684
container.on('select', function (evt) {
4685
self._selectTriggered(evt);
4688
container.on('unselect', function (evt) {
4689
self._selectTriggered(evt);
4693
CloseOnSelect.prototype._selectTriggered = function (_, evt) {
4694
var originalEvent = evt.originalEvent;
4697
if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
4701
this.trigger('close', {
4702
originalEvent: originalEvent,
4703
originalSelect2Event: evt
4707
return CloseOnSelect;
4710
S2.define('select2/i18n/en',[],function () {
4713
errorLoading: function () {
4714
return 'The results could not be loaded.';
4716
inputTooLong: function (args) {
4717
var overChars = args.input.length - args.maximum;
4719
var message = 'Please delete ' + overChars + ' character';
4721
if (overChars != 1) {
4727
inputTooShort: function (args) {
4728
var remainingChars = args.minimum - args.input.length;
4730
var message = 'Please enter ' + remainingChars + ' or more characters';
4734
loadingMore: function () {
4735
return 'Loading more results…';
4737
maximumSelected: function (args) {
4738
var message = 'You can only select ' + args.maximum + ' item';
4740
if (args.maximum != 1) {
4746
noResults: function () {
4747
return 'No results found';
4749
searching: function () {
4750
return 'Searching…';
4752
removeAllItems: function () {
4753
return 'Remove all items';
4758
S2.define('select2/defaults',[
4764
'./selection/single',
4765
'./selection/multiple',
4766
'./selection/placeholder',
4767
'./selection/allowClear',
4768
'./selection/search',
4769
'./selection/eventRelay',
4780
'./data/minimumInputLength',
4781
'./data/maximumInputLength',
4782
'./data/maximumSelectionLength',
4785
'./dropdown/search',
4786
'./dropdown/hidePlaceholder',
4787
'./dropdown/infiniteScroll',
4788
'./dropdown/attachBody',
4789
'./dropdown/minimumResultsForSearch',
4790
'./dropdown/selectOnClose',
4791
'./dropdown/closeOnSelect',
4794
], function ($, require,
4798
SingleSelection, MultipleSelection, Placeholder, AllowClear,
4799
SelectionSearch, EventRelay,
4801
Utils, Translation, DIACRITICS,
4803
SelectData, ArrayData, AjaxData, Tags, Tokenizer,
4804
MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
4806
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
4807
AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
4809
EnglishTranslation) {
4810
function Defaults () {
4814
Defaults.prototype.apply = function (options) {
4815
options = $.extend(true, {}, this.defaults, options);
4817
if (options.dataAdapter == null) {
4818
if (options.ajax != null) {
4819
options.dataAdapter = AjaxData;
4820
} else if (options.data != null) {
4821
options.dataAdapter = ArrayData;
4823
options.dataAdapter = SelectData;
4826
if (options.minimumInputLength > 0) {
4827
options.dataAdapter = Utils.Decorate(
4828
options.dataAdapter,
4833
if (options.maximumInputLength > 0) {
4834
options.dataAdapter = Utils.Decorate(
4835
options.dataAdapter,
4840
if (options.maximumSelectionLength > 0) {
4841
options.dataAdapter = Utils.Decorate(
4842
options.dataAdapter,
4843
MaximumSelectionLength
4848
options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
4851
if (options.tokenSeparators != null || options.tokenizer != null) {
4852
options.dataAdapter = Utils.Decorate(
4853
options.dataAdapter,
4858
if (options.query != null) {
4859
var Query = require(options.amdBase + 'compat/query');
4861
options.dataAdapter = Utils.Decorate(
4862
options.dataAdapter,
4867
if (options.initSelection != null) {
4868
var InitSelection = require(options.amdBase + 'compat/initSelection');
4870
options.dataAdapter = Utils.Decorate(
4871
options.dataAdapter,
4877
if (options.resultsAdapter == null) {
4878
options.resultsAdapter = ResultsList;
4880
if (options.ajax != null) {
4881
options.resultsAdapter = Utils.Decorate(
4882
options.resultsAdapter,
4887
if (options.placeholder != null) {
4888
options.resultsAdapter = Utils.Decorate(
4889
options.resultsAdapter,
4894
if (options.selectOnClose) {
4895
options.resultsAdapter = Utils.Decorate(
4896
options.resultsAdapter,
4902
if (options.dropdownAdapter == null) {
4903
if (options.multiple) {
4904
options.dropdownAdapter = Dropdown;
4906
var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
4908
options.dropdownAdapter = SearchableDropdown;
4911
if (options.minimumResultsForSearch !== 0) {
4912
options.dropdownAdapter = Utils.Decorate(
4913
options.dropdownAdapter,
4914
MinimumResultsForSearch
4918
if (options.closeOnSelect) {
4919
options.dropdownAdapter = Utils.Decorate(
4920
options.dropdownAdapter,
4926
options.dropdownCssClass != null ||
4927
options.dropdownCss != null ||
4928
options.adaptDropdownCssClass != null
4930
var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
4932
options.dropdownAdapter = Utils.Decorate(
4933
options.dropdownAdapter,
4938
options.dropdownAdapter = Utils.Decorate(
4939
options.dropdownAdapter,
4944
if (options.selectionAdapter == null) {
4945
if (options.multiple) {
4946
options.selectionAdapter = MultipleSelection;
4948
options.selectionAdapter = SingleSelection;
4952
if (options.placeholder != null) {
4953
options.selectionAdapter = Utils.Decorate(
4954
options.selectionAdapter,
4959
if (options.allowClear) {
4960
options.selectionAdapter = Utils.Decorate(
4961
options.selectionAdapter,
4966
if (options.multiple) {
4967
options.selectionAdapter = Utils.Decorate(
4968
options.selectionAdapter,
4974
options.containerCssClass != null ||
4975
options.containerCss != null ||
4976
options.adaptContainerCssClass != null
4978
var ContainerCSS = require(options.amdBase + 'compat/containerCss');
4980
options.selectionAdapter = Utils.Decorate(
4981
options.selectionAdapter,
4986
options.selectionAdapter = Utils.Decorate(
4987
options.selectionAdapter,
4994
options.language = this._resolveLanguage(options.language);
4997
options.language.push('en');
4999
var uniqueLanguages = [];
5001
for (var l = 0; l < options.language.length; l++) {
5002
var language = options.language[l];
5004
if (uniqueLanguages.indexOf(language) === -1) {
5005
uniqueLanguages.push(language);
5009
options.language = uniqueLanguages;
5011
options.translations = this._processTranslations(
5019
Defaults.prototype.reset = function () {
5020
function stripDiacritics (text) {
5023
return DIACRITICS[a] || a;
5026
return text.replace(/[^\u0000-\u007E]/g, match);
5029
function matcher (params, data) {
5031
if ($.trim(params.term) === '') {
5036
if (data.children && data.children.length > 0) {
5039
var match = $.extend(true, {}, data);
5042
for (var c = data.children.length - 1; c >= 0; c--) {
5043
var child = data.children[c];
5045
var matches = matcher(params, child);
5048
if (matches == null) {
5049
match.children.splice(c, 1);
5054
if (match.children.length > 0) {
5059
return matcher(params, match);
5062
var original = stripDiacritics(data.text).toUpperCase();
5063
var term = stripDiacritics(params.term).toUpperCase();
5066
if (original.indexOf(term) > -1) {
5076
amdLanguageBase: './i18n/',
5077
closeOnSelect: true,
5079
dropdownAutoWidth: false,
5080
escapeMarkup: Utils.escapeMarkup,
5083
minimumInputLength: 0,
5084
maximumInputLength: 0,
5085
maximumSelectionLength: 0,
5086
minimumResultsForSearch: 0,
5087
selectOnClose: false,
5088
scrollAfterSelect: false,
5089
sorter: function (data) {
5092
templateResult: function (result) {
5095
templateSelection: function (selection) {
5096
return selection.text;
5103
Defaults.prototype.applyFromElement = function (options, $element) {
5104
var optionLanguage = options.language;
5105
var defaultLanguage = this.defaults.language;
5106
var elementLanguage = $element.prop('lang');
5107
var parentLanguage = $element.closest('[lang]').prop('lang');
5109
var languages = Array.prototype.concat.call(
5110
this._resolveLanguage(elementLanguage),
5111
this._resolveLanguage(optionLanguage),
5112
this._resolveLanguage(defaultLanguage),
5113
this._resolveLanguage(parentLanguage)
5116
options.language = languages;
5121
Defaults.prototype._resolveLanguage = function (language) {
5126
if ($.isEmptyObject(language)) {
5130
if ($.isPlainObject(language)) {
5136
if (!$.isArray(language)) {
5137
languages = [language];
5139
languages = language;
5142
var resolvedLanguages = [];
5144
for (var l = 0; l < languages.length; l++) {
5145
resolvedLanguages.push(languages[l]);
5147
if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
5149
var languageParts = languages[l].split('-');
5150
var baseLanguage = languageParts[0];
5152
resolvedLanguages.push(baseLanguage);
5156
return resolvedLanguages;
5159
Defaults.prototype._processTranslations = function (languages, debug) {
5160
var translations = new Translation();
5162
for (var l = 0; l < languages.length; l++) {
5163
var languageData = new Translation();
5165
var language = languages[l];
5167
if (typeof language === 'string') {
5170
languageData = Translation.loadPath(language);
5174
language = this.defaults.amdLanguageBase + language;
5175
languageData = Translation.loadPath(language);
5180
if (debug && window.console && console.warn) {
5182
'Select2: The language file for "' + language + '" could ' +
5183
'not be automatically loaded. A fallback will be used instead.'
5188
} else if ($.isPlainObject(language)) {
5189
languageData = new Translation(language);
5191
languageData = language;
5194
translations.extend(languageData);
5197
return translations;
5200
Defaults.prototype.set = function (key, value) {
5201
var camelKey = $.camelCase(key);
5204
data[camelKey] = value;
5206
var convertedData = Utils._convertData(data);
5208
$.extend(true, this.defaults, convertedData);
5211
var defaults = new Defaults();
5216
S2.define('select2/options',[
5221
], function (require, $, Defaults, Utils) {
5222
function Options (options, $element) {
5223
this.options = options;
5225
if ($element != null) {
5226
this.fromElement($element);
5229
if ($element != null) {
5230
this.options = Defaults.applyFromElement(this.options, $element);
5233
this.options = Defaults.apply(this.options);
5235
if ($element && $element.is('input')) {
5236
var InputCompat = require(this.get('amdBase') + 'compat/inputData');
5238
this.options.dataAdapter = Utils.Decorate(
5239
this.options.dataAdapter,
5245
Options.prototype.fromElement = function ($e) {
5246
var excludedData = ['select2'];
5248
if (this.options.multiple == null) {
5249
this.options.multiple = $e.prop('multiple');
5252
if (this.options.disabled == null) {
5253
this.options.disabled = $e.prop('disabled');
5256
if (this.options.dir == null) {
5257
if ($e.prop('dir')) {
5258
this.options.dir = $e.prop('dir');
5259
} else if ($e.closest('[dir]').prop('dir')) {
5260
this.options.dir = $e.closest('[dir]').prop('dir');
5262
this.options.dir = 'ltr';
5266
$e.prop('disabled', this.options.disabled);
5267
$e.prop('multiple', this.options.multiple);
5269
if (Utils.GetData($e[0], 'select2Tags')) {
5270
if (this.options.debug && window.console && console.warn) {
5272
'Select2: The `data-select2-tags` attribute has been changed to ' +
5273
'use the `data-data` and `data-tags="true"` attributes and will be ' +
5274
'removed in future versions of Select2.'
5278
Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
5279
Utils.StoreData($e[0], 'tags', true);
5282
if (Utils.GetData($e[0], 'ajaxUrl')) {
5283
if (this.options.debug && window.console && console.warn) {
5285
'Select2: The `data-ajax-url` attribute has been changed to ' +
5286
'`data-ajax--url` and support for the old attribute will be removed' +
5287
' in future versions of Select2.'
5291
$e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
5292
Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
5297
function upperCaseLetter(_, letter) {
5298
return letter.toUpperCase();
5302
for (var attr = 0; attr < $e[0].attributes.length; attr++) {
5303
var attributeName = $e[0].attributes[attr].name;
5304
var prefix = 'data-';
5306
if (attributeName.substr(0, prefix.length) == prefix) {
5308
var dataName = attributeName.substring(prefix.length);
5312
var dataValue = Utils.GetData($e[0], dataName);
5315
var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
5318
dataset[camelDataName] = dataValue;
5324
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
5325
dataset = $.extend(true, {}, $e[0].dataset, dataset);
5329
var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
5331
data = Utils._convertData(data);
5333
for (var key in data) {
5334
if ($.inArray(key, excludedData) > -1) {
5338
if ($.isPlainObject(this.options[key])) {
5339
$.extend(this.options[key], data[key]);
5341
this.options[key] = data[key];
5348
Options.prototype.get = function (key) {
5349
return this.options[key];
5352
Options.prototype.set = function (key, val) {
5353
this.options[key] = val;
5359
S2.define('select2/core',[
5364
], function ($, Options, Utils, KEYS) {
5365
var Select2 = function ($element, options) {
5366
if (Utils.GetData($element[0], 'select2') != null) {
5367
Utils.GetData($element[0], 'select2').destroy();
5370
this.$element = $element;
5372
this.id = this._generateId($element);
5374
options = options || {};
5376
this.options = new Options(options, $element);
5378
Select2.__super__.constructor.call(this);
5382
var tabindex = $element.attr('tabindex') || 0;
5383
Utils.StoreData($element[0], 'old-tabindex', tabindex);
5384
$element.attr('tabindex', '-1');
5388
var DataAdapter = this.options.get('dataAdapter');
5389
this.dataAdapter = new DataAdapter($element, this.options);
5391
var $container = this.render();
5393
this._placeContainer($container);
5395
var SelectionAdapter = this.options.get('selectionAdapter');
5396
this.selection = new SelectionAdapter($element, this.options);
5397
this.$selection = this.selection.render();
5399
this.selection.position(this.$selection, $container);
5401
var DropdownAdapter = this.options.get('dropdownAdapter');
5402
this.dropdown = new DropdownAdapter($element, this.options);
5403
this.$dropdown = this.dropdown.render();
5405
this.dropdown.position(this.$dropdown, $container);
5407
var ResultsAdapter = this.options.get('resultsAdapter');
5408
this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
5409
this.$results = this.results.render();
5411
this.results.position(this.$results, this.$dropdown);
5418
this._bindAdapters();
5421
this._registerDomEvents();
5424
this._registerDataEvents();
5425
this._registerSelectionEvents();
5426
this._registerDropdownEvents();
5427
this._registerResultsEvents();
5428
this._registerEvents();
5431
this.dataAdapter.current(function (initialData) {
5432
self.trigger('selection:update', {
5438
$element.addClass('select2-hidden-accessible');
5439
$element.attr('aria-hidden', 'true');
5442
this._syncAttributes();
5444
Utils.StoreData($element[0], 'select2', this);
5447
$element.data('select2', this);
5450
Utils.Extend(Select2, Utils.Observable);
5452
Select2.prototype._generateId = function ($element) {
5455
if ($element.attr('id') != null) {
5456
id = $element.attr('id');
5457
} else if ($element.attr('name') != null) {
5458
id = $element.attr('name') + '-' + Utils.generateChars(2);
5460
id = Utils.generateChars(4);
5463
id = id.replace(/(:|\.|\[|\]|,)/g, '');
5464
id = 'select2-' + id;
5469
Select2.prototype._placeContainer = function ($container) {
5470
$container.insertAfter(this.$element);
5472
var width = this._resolveWidth(this.$element, this.options.get('width'));
5474
if (width != null) {
5475
$container.css('width', width);
5479
Select2.prototype._resolveWidth = function ($element, method) {
5480
var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
5482
if (method == 'resolve') {
5483
var styleWidth = this._resolveWidth($element, 'style');
5485
if (styleWidth != null) {
5489
return this._resolveWidth($element, 'element');
5492
if (method == 'element') {
5493
var elementWidth = $element.outerWidth(false);
5495
if (elementWidth <= 0) {
5499
return elementWidth + 'px';
5502
if (method == 'style') {
5503
var style = $element.attr('style');
5505
if (typeof(style) !== 'string') {
5509
var attrs = style.split(';');
5511
for (var i = 0, l = attrs.length; i < l; i = i + 1) {
5512
var attr = attrs[i].replace(/\s/g, '');
5513
var matches = attr.match(WIDTH);
5515
if (matches !== null && matches.length >= 1) {
5523
if (method == 'computedstyle') {
5524
var computedStyle = window.getComputedStyle($element[0]);
5526
return computedStyle.width;
5532
Select2.prototype._bindAdapters = function () {
5533
this.dataAdapter.bind(this, this.$container);
5534
this.selection.bind(this, this.$container);
5536
this.dropdown.bind(this, this.$container);
5537
this.results.bind(this, this.$container);
5540
Select2.prototype._registerDomEvents = function () {
5543
this.$element.on('change.select2', function () {
5544
self.dataAdapter.current(function (data) {
5545
self.trigger('selection:update', {
5551
this.$element.on('focus.select2', function (evt) {
5552
self.trigger('focus', evt);
5555
this._syncA = Utils.bind(this._syncAttributes, this);
5556
this._syncS = Utils.bind(this._syncSubtree, this);
5558
if (this.$element[0].attachEvent) {
5559
this.$element[0].attachEvent('onpropertychange', this._syncA);
5562
var observer = window.MutationObserver ||
5563
window.WebKitMutationObserver ||
5564
window.MozMutationObserver
5567
if (observer != null) {
5568
this._observer = new observer(function (mutations) {
5570
self._syncS(null, mutations);
5572
this._observer.observe(this.$element[0], {
5577
} else if (this.$element[0].addEventListener) {
5578
this.$element[0].addEventListener(
5583
this.$element[0].addEventListener(
5588
this.$element[0].addEventListener(
5596
Select2.prototype._registerDataEvents = function () {
5599
this.dataAdapter.on('*', function (name, params) {
5600
self.trigger(name, params);
5604
Select2.prototype._registerSelectionEvents = function () {
5606
var nonRelayEvents = ['toggle', 'focus'];
5608
this.selection.on('toggle', function () {
5609
self.toggleDropdown();
5612
this.selection.on('focus', function (params) {
5616
this.selection.on('*', function (name, params) {
5617
if ($.inArray(name, nonRelayEvents) !== -1) {
5621
self.trigger(name, params);
5625
Select2.prototype._registerDropdownEvents = function () {
5628
this.dropdown.on('*', function (name, params) {
5629
self.trigger(name, params);
5633
Select2.prototype._registerResultsEvents = function () {
5636
this.results.on('*', function (name, params) {
5637
self.trigger(name, params);
5641
Select2.prototype._registerEvents = function () {
5644
this.on('open', function () {
5645
self.$container.addClass('select2-container--open');
5648
this.on('close', function () {
5649
self.$container.removeClass('select2-container--open');
5652
this.on('enable', function () {
5653
self.$container.removeClass('select2-container--disabled');
5656
this.on('disable', function () {
5657
self.$container.addClass('select2-container--disabled');
5660
this.on('blur', function () {
5661
self.$container.removeClass('select2-container--focus');
5664
this.on('query', function (params) {
5665
if (!self.isOpen()) {
5666
self.trigger('open', {});
5669
this.dataAdapter.query(params, function (data) {
5670
self.trigger('results:all', {
5677
this.on('query:append', function (params) {
5678
this.dataAdapter.query(params, function (data) {
5679
self.trigger('results:append', {
5686
this.on('keypress', function (evt) {
5687
var key = evt.which;
5689
if (self.isOpen()) {
5690
if (key === KEYS.ESC || key === KEYS.TAB ||
5691
(key === KEYS.UP && evt.altKey)) {
5694
evt.preventDefault();
5695
} else if (key === KEYS.ENTER) {
5696
self.trigger('results:select', {});
5698
evt.preventDefault();
5699
} else if ((key === KEYS.SPACE && evt.ctrlKey)) {
5700
self.trigger('results:toggle', {});
5702
evt.preventDefault();
5703
} else if (key === KEYS.UP) {
5704
self.trigger('results:previous', {});
5706
evt.preventDefault();
5707
} else if (key === KEYS.DOWN) {
5708
self.trigger('results:next', {});
5710
evt.preventDefault();
5713
if (key === KEYS.ENTER || key === KEYS.SPACE ||
5714
(key === KEYS.DOWN && evt.altKey)) {
5717
evt.preventDefault();
5723
Select2.prototype._syncAttributes = function () {
5724
this.options.set('disabled', this.$element.prop('disabled'));
5726
if (this.isDisabled()) {
5727
if (this.isOpen()) {
5731
this.trigger('disable', {});
5733
this.trigger('enable', {});
5737
Select2.prototype._isChangeMutation = function (evt, mutations) {
5738
var changed = false;
5744
evt && evt.target && (
5745
evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
5755
} else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
5756
for (var n = 0; n < mutations.addedNodes.length; n++) {
5757
var node = mutations.addedNodes[n];
5759
if (node.selected) {
5763
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
5765
} else if ($.isArray(mutations)) {
5766
$.each(mutations, function(evt, mutation) {
5767
if (self._isChangeMutation(evt, mutation)) {
5778
Select2.prototype._syncSubtree = function (evt, mutations) {
5779
var changed = this._isChangeMutation(evt, mutations);
5784
this.dataAdapter.current(function (currentData) {
5785
self.trigger('selection:update', {
5796
Select2.prototype.trigger = function (name, args) {
5797
var actualTrigger = Select2.__super__.trigger;
5798
var preTriggerMap = {
5801
'select': 'selecting',
5802
'unselect': 'unselecting',
5806
if (args === undefined) {
5810
if (name in preTriggerMap) {
5811
var preTriggerName = preTriggerMap[name];
5812
var preTriggerArgs = {
5818
actualTrigger.call(this, preTriggerName, preTriggerArgs);
5820
if (preTriggerArgs.prevented) {
5821
args.prevented = true;
5827
actualTrigger.call(this, name, args);
5830
Select2.prototype.toggleDropdown = function () {
5831
if (this.isDisabled()) {
5835
if (this.isOpen()) {
5842
Select2.prototype.open = function () {
5843
if (this.isOpen()) {
5847
if (this.isDisabled()) {
5851
this.trigger('query', {});
5854
Select2.prototype.close = function (evt) {
5855
if (!this.isOpen()) {
5859
this.trigger('close', { originalEvent : evt });
5869
Select2.prototype.isEnabled = function () {
5870
return !this.isDisabled();
5879
Select2.prototype.isDisabled = function () {
5880
return this.options.get('disabled');
5883
Select2.prototype.isOpen = function () {
5884
return this.$container.hasClass('select2-container--open');
5887
Select2.prototype.hasFocus = function () {
5888
return this.$container.hasClass('select2-container--focus');
5891
Select2.prototype.focus = function (data) {
5893
if (this.hasFocus()) {
5897
this.$container.addClass('select2-container--focus');
5898
this.trigger('focus', {});
5901
Select2.prototype.enable = function (args) {
5902
if (this.options.get('debug') && window.console && console.warn) {
5904
'Select2: The `select2("enable")` method has been deprecated and will' +
5905
' be removed in later Select2 versions. Use $element.prop("disabled")' +
5910
if (args == null || args.length === 0) {
5914
var disabled = !args[0];
5916
this.$element.prop('disabled', disabled);
5919
Select2.prototype.data = function () {
5920
if (this.options.get('debug') &&
5921
arguments.length > 0 && window.console && console.warn) {
5923
'Select2: Data can no longer be set using `select2("data")`. You ' +
5924
'should consider setting the value instead using `$element.val()`.'
5930
this.dataAdapter.current(function (currentData) {
5937
Select2.prototype.val = function (args) {
5938
if (this.options.get('debug') && window.console && console.warn) {
5940
'Select2: The `select2("val")` method has been deprecated and will be' +
5941
' removed in later Select2 versions. Use $element.val() instead.'
5945
if (args == null || args.length === 0) {
5946
return this.$element.val();
5949
var newVal = args[0];
5951
if ($.isArray(newVal)) {
5952
newVal = $.map(newVal, function (obj) {
5953
return obj.toString();
5957
this.$element.val(newVal).trigger('input').trigger('change');
5960
Select2.prototype.destroy = function () {
5961
this.$container.remove();
5963
if (this.$element[0].detachEvent) {
5964
this.$element[0].detachEvent('onpropertychange', this._syncA);
5967
if (this._observer != null) {
5968
this._observer.disconnect();
5969
this._observer = null;
5970
} else if (this.$element[0].removeEventListener) {
5972
.removeEventListener('DOMAttrModified', this._syncA, false);
5974
.removeEventListener('DOMNodeInserted', this._syncS, false);
5976
.removeEventListener('DOMNodeRemoved', this._syncS, false);
5982
this.$element.off('.select2');
5983
this.$element.attr('tabindex',
5984
Utils.GetData(this.$element[0], 'old-tabindex'));
5986
this.$element.removeClass('select2-hidden-accessible');
5987
this.$element.attr('aria-hidden', 'false');
5988
Utils.RemoveData(this.$element[0]);
5989
this.$element.removeData('select2');
5991
this.dataAdapter.destroy();
5992
this.selection.destroy();
5993
this.dropdown.destroy();
5994
this.results.destroy();
5996
this.dataAdapter = null;
5997
this.selection = null;
5998
this.dropdown = null;
5999
this.results = null;
6002
Select2.prototype.render = function () {
6004
'<span class="select2 select2-container">' +
6005
'<span class="selection"></span>' +
6006
'<span class="dropdown-wrapper" aria-hidden="true"></span>' +
6010
$container.attr('dir', this.options.get('dir'));
6012
this.$container = $container;
6014
this.$container.addClass('select2-container--' + this.options.get('theme'));
6016
Utils.StoreData($container[0], 'element', this.$element);
6024
S2.define('select2/compat/utils',[
6027
function syncCssClasses ($dest, $src, adapter) {
6028
var classes, replacements = [], adapted;
6030
classes = $.trim($dest.attr('class'));
6033
classes = '' + classes;
6035
$(classes.split(/\s+/)).each(function () {
6037
if (this.indexOf('select2-') === 0) {
6038
replacements.push(this);
6043
classes = $.trim($src.attr('class'));
6046
classes = '' + classes;
6048
$(classes.split(/\s+/)).each(function () {
6050
if (this.indexOf('select2-') !== 0) {
6051
adapted = adapter(this);
6053
if (adapted != null) {
6054
replacements.push(adapted);
6060
$dest.attr('class', replacements.join(' '));
6064
syncCssClasses: syncCssClasses
6068
S2.define('select2/compat/containerCss',[
6071
], function ($, CompatUtils) {
6073
function _containerAdapter (clazz) {
6077
function ContainerCSS () { }
6079
ContainerCSS.prototype.render = function (decorated) {
6080
var $container = decorated.call(this);
6082
var containerCssClass = this.options.get('containerCssClass') || '';
6084
if ($.isFunction(containerCssClass)) {
6085
containerCssClass = containerCssClass(this.$element);
6088
var containerCssAdapter = this.options.get('adaptContainerCssClass');
6089
containerCssAdapter = containerCssAdapter || _containerAdapter;
6091
if (containerCssClass.indexOf(':all:') !== -1) {
6092
containerCssClass = containerCssClass.replace(':all:', '');
6094
var _cssAdapter = containerCssAdapter;
6096
containerCssAdapter = function (clazz) {
6097
var adapted = _cssAdapter(clazz);
6099
if (adapted != null) {
6101
return adapted + ' ' + clazz;
6108
var containerCss = this.options.get('containerCss') || {};
6110
if ($.isFunction(containerCss)) {
6111
containerCss = containerCss(this.$element);
6114
CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter);
6116
$container.css(containerCss);
6117
$container.addClass(containerCssClass);
6122
return ContainerCSS;
6125
S2.define('select2/compat/dropdownCss',[
6128
], function ($, CompatUtils) {
6130
function _dropdownAdapter (clazz) {
6134
function DropdownCSS () { }
6136
DropdownCSS.prototype.render = function (decorated) {
6137
var $dropdown = decorated.call(this);
6139
var dropdownCssClass = this.options.get('dropdownCssClass') || '';
6141
if ($.isFunction(dropdownCssClass)) {
6142
dropdownCssClass = dropdownCssClass(this.$element);
6145
var dropdownCssAdapter = this.options.get('adaptDropdownCssClass');
6146
dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;
6148
if (dropdownCssClass.indexOf(':all:') !== -1) {
6149
dropdownCssClass = dropdownCssClass.replace(':all:', '');
6151
var _cssAdapter = dropdownCssAdapter;
6153
dropdownCssAdapter = function (clazz) {
6154
var adapted = _cssAdapter(clazz);
6156
if (adapted != null) {
6158
return adapted + ' ' + clazz;
6165
var dropdownCss = this.options.get('dropdownCss') || {};
6167
if ($.isFunction(dropdownCss)) {
6168
dropdownCss = dropdownCss(this.$element);
6171
CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter);
6173
$dropdown.css(dropdownCss);
6174
$dropdown.addClass(dropdownCssClass);
6182
S2.define('select2/compat/initSelection',[
6185
function InitSelection (decorated, $element, options) {
6186
if (options.get('debug') && window.console && console.warn) {
6188
'Select2: The `initSelection` option has been deprecated in favor' +
6189
' of a custom data adapter that overrides the `current` method. ' +
6190
'This method is now called multiple times instead of a single ' +
6191
'time when the instance is initialized. Support will be removed ' +
6192
'for the `initSelection` option in future versions of Select2'
6196
this.initSelection = options.get('initSelection');
6197
this._isInitialized = false;
6199
decorated.call(this, $element, options);
6202
InitSelection.prototype.current = function (decorated, callback) {
6205
if (this._isInitialized) {
6206
decorated.call(this, callback);
6211
this.initSelection.call(null, this.$element, function (data) {
6212
self._isInitialized = true;
6214
if (!$.isArray(data)) {
6222
return InitSelection;
6225
S2.define('select2/compat/inputData',[
6228
], function ($, Utils) {
6229
function InputData (decorated, $element, options) {
6230
this._currentData = [];
6231
this._valueSeparator = options.get('valueSeparator') || ',';
6233
if ($element.prop('type') === 'hidden') {
6234
if (options.get('debug') && console && console.warn) {
6236
'Select2: Using a hidden input with Select2 is no longer ' +
6237
'supported and may stop working in the future. It is recommended ' +
6238
'to use a `<select>` element instead.'
6243
decorated.call(this, $element, options);
6246
InputData.prototype.current = function (_, callback) {
6247
function getSelected (data, selectedIds) {
6250
if (data.selected || $.inArray(data.id, selectedIds) !== -1) {
6251
data.selected = true;
6252
selected.push(data);
6254
data.selected = false;
6257
if (data.children) {
6258
selected.push.apply(selected, getSelected(data.children, selectedIds));
6266
for (var d = 0; d < this._currentData.length; d++) {
6267
var data = this._currentData[d];
6269
selected.push.apply(
6273
this.$element.val().split(
6274
this._valueSeparator
6283
InputData.prototype.select = function (_, data) {
6284
if (!this.options.get('multiple')) {
6285
this.current(function (allData) {
6286
$.map(allData, function (data) {
6287
data.selected = false;
6291
this.$element.val(data.id);
6292
this.$element.trigger('input').trigger('change');
6294
var value = this.$element.val();
6295
value += this._valueSeparator + data.id;
6297
this.$element.val(value);
6298
this.$element.trigger('input').trigger('change');
6302
InputData.prototype.unselect = function (_, data) {
6305
data.selected = false;
6307
this.current(function (allData) {
6310
for (var d = 0; d < allData.length; d++) {
6311
var item = allData[d];
6313
if (data.id == item.id) {
6317
values.push(item.id);
6320
self.$element.val(values.join(self._valueSeparator));
6321
self.$element.trigger('input').trigger('change');
6325
InputData.prototype.query = function (_, params, callback) {
6328
for (var d = 0; d < this._currentData.length; d++) {
6329
var data = this._currentData[d];
6331
var matches = this.matches(params, data);
6333
if (matches !== null) {
6334
results.push(matches);
6343
InputData.prototype.addOptions = function (_, $options) {
6344
var options = $.map($options, function ($option) {
6345
return Utils.GetData($option[0], 'data');
6348
this._currentData.push.apply(this._currentData, options);
6354
S2.define('select2/compat/matcher',[
6357
function oldMatcher (matcher) {
6358
function wrappedMatcher (params, data) {
6359
var match = $.extend(true, {}, data);
6361
if (params.term == null || $.trim(params.term) === '') {
6365
if (data.children) {
6366
for (var c = data.children.length - 1; c >= 0; c--) {
6367
var child = data.children[c];
6371
var doesMatch = matcher(params.term, child.text, child);
6375
match.children.splice(c, 1);
6379
if (match.children.length > 0) {
6384
if (matcher(params.term, data.text, data)) {
6391
return wrappedMatcher;
6397
S2.define('select2/compat/query',[
6400
function Query (decorated, $element, options) {
6401
if (options.get('debug') && window.console && console.warn) {
6403
'Select2: The `query` option has been deprecated in favor of a ' +
6404
'custom data adapter that overrides the `query` method. Support ' +
6405
'will be removed for the `query` option in future versions of ' +
6410
decorated.call(this, $element, options);
6413
Query.prototype.query = function (_, params, callback) {
6414
params.callback = callback;
6416
var query = this.options.get('query');
6418
query.call(null, params);
6424
S2.define('select2/dropdown/attachContainer',[
6427
function AttachContainer (decorated, $element, options) {
6428
decorated.call(this, $element, options);
6431
AttachContainer.prototype.position =
6432
function (decorated, $dropdown, $container) {
6433
var $dropdownContainer = $container.find('.dropdown-wrapper');
6434
$dropdownContainer.append($dropdown);
6436
$dropdown.addClass('select2-dropdown--below');
6437
$container.addClass('select2-container--below');
6440
return AttachContainer;
6443
S2.define('select2/dropdown/stopPropagation',[
6446
function StopPropagation () { }
6448
StopPropagation.prototype.bind = function (decorated, container, $container) {
6449
decorated.call(this, container, $container);
6451
var stoppedEvents = [
6474
this.$dropdown.on(stoppedEvents.join(' '), function (evt) {
6475
evt.stopPropagation();
6479
return StopPropagation;
6482
S2.define('select2/selection/stopPropagation',[
6485
function StopPropagation () { }
6487
StopPropagation.prototype.bind = function (decorated, container, $container) {
6488
decorated.call(this, container, $container);
6490
var stoppedEvents = [
6513
this.$selection.on(stoppedEvents.join(' '), function (evt) {
6514
evt.stopPropagation();
6518
return StopPropagation;
6529
(function (factory) {
6530
if ( typeof S2.define === 'function' && S2.define.amd ) {
6532
S2.define('jquery-mousewheel',['jquery'], factory);
6533
} else if (typeof exports === 'object') {
6535
module.exports = factory;
6542
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
6543
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
6544
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
6545
slice = Array.prototype.slice,
6546
nullLowestDeltaTimeout, lowestDelta;
6548
if ( $.event.fixHooks ) {
6549
for ( var i = toFix.length; i; ) {
6550
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
6554
var special = $.event.special.mousewheel = {
6558
if ( this.addEventListener ) {
6559
for ( var i = toBind.length; i; ) {
6560
this.addEventListener( toBind[--i], handler, false );
6563
this.onmousewheel = handler;
6566
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
6567
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
6570
teardown: function() {
6571
if ( this.removeEventListener ) {
6572
for ( var i = toBind.length; i; ) {
6573
this.removeEventListener( toBind[--i], handler, false );
6576
this.onmousewheel = null;
6579
$.removeData(this, 'mousewheel-line-height');
6580
$.removeData(this, 'mousewheel-page-height');
6583
getLineHeight: function(elem) {
6584
var $elem = $(elem),
6585
$parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
6586
if (!$parent.length) {
6587
$parent = $('body');
6589
return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
6592
getPageHeight: function(elem) {
6593
return $(elem).height();
6597
adjustOldDeltas: true,
6598
normalizeOffset: true
6603
mousewheel: function(fn) {
6604
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
6607
unmousewheel: function(fn) {
6608
return this.unbind('mousewheel', fn);
6613
function handler(event) {
6614
var orgEvent = event || window.event,
6615
args = slice.call(arguments, 1),
6622
event = $.event.fix(orgEvent);
6623
event.type = 'mousewheel';
6626
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
6627
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
6628
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
6629
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
6632
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
6633
deltaX = deltaY * -1;
6638
delta = deltaY === 0 ? deltaX : deltaY;
6641
if ( 'deltaY' in orgEvent ) {
6642
deltaY = orgEvent.deltaY * -1;
6645
if ( 'deltaX' in orgEvent ) {
6646
deltaX = orgEvent.deltaX;
6647
if ( deltaY === 0 ) { delta = deltaX * -1; }
6651
if ( deltaY === 0 && deltaX === 0 ) { return; }
6658
if ( orgEvent.deltaMode === 1 ) {
6659
var lineHeight = $.data(this, 'mousewheel-line-height');
6660
delta *= lineHeight;
6661
deltaY *= lineHeight;
6662
deltaX *= lineHeight;
6663
} else if ( orgEvent.deltaMode === 2 ) {
6664
var pageHeight = $.data(this, 'mousewheel-page-height');
6665
delta *= pageHeight;
6666
deltaY *= pageHeight;
6667
deltaX *= pageHeight;
6671
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
6673
if ( !lowestDelta || absDelta < lowestDelta ) {
6674
lowestDelta = absDelta;
6677
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
6683
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
6691
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
6692
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
6693
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
6696
if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
6697
var boundingRect = this.getBoundingClientRect();
6698
offsetX = event.clientX - boundingRect.left;
6699
offsetY = event.clientY - boundingRect.top;
6703
event.deltaX = deltaX;
6704
event.deltaY = deltaY;
6705
event.deltaFactor = lowestDelta;
6706
event.offsetX = offsetX;
6707
event.offsetY = offsetY;
6711
event.deltaMode = 0;
6714
args.unshift(event, delta, deltaX, deltaY);
6720
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
6721
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
6723
return ($.event.dispatch || $.event.handle).apply(this, args);
6726
function nullLowestDelta() {
6730
function shouldAdjustOldDeltas(orgEvent, absDelta) {
6738
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
6743
S2.define('jquery.select2',[
6745
'jquery-mousewheel',
6748
'./select2/defaults',
6750
], function ($, _, Select2, Defaults, Utils) {
6751
if ($.fn.select2 == null) {
6753
var thisMethods = ['open', 'close', 'destroy'];
6755
$.fn.select2 = function (options) {
6756
options = options || {};
6758
if (typeof options === 'object') {
6759
this.each(function () {
6760
var instanceOptions = $.extend(true, {}, options);
6762
var instance = new Select2($(this), instanceOptions);
6766
} else if (typeof options === 'string') {
6768
var args = Array.prototype.slice.call(arguments, 1);
6770
this.each(function () {
6771
var instance = Utils.GetData(this, 'select2');
6773
if (instance == null && window.console && console.error) {
6775
'The select2(\'' + options + '\') method was called on an ' +
6776
'element that is not using Select2.'
6780
ret = instance[options].apply(instance, args);
6784
if ($.inArray(options, thisMethods) > -1) {
6790
throw new Error('Invalid arguments for Select2: ' + options);
6795
if ($.fn.select2.defaults == null) {
6796
$.fn.select2.defaults = Defaults;
6811
var select2 = S2.require('jquery.select2');
6816
jQuery.fn.select2.amd = S2;