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