Your IP : 216.73.216.95


Current Path : /var/www/ooareogundevinitiative/wp-content/plugins/forminator/assets/js/library/
Upload File :
Current File : /var/www/ooareogundevinitiative/wp-content/plugins/forminator/assets/js/library/select2.full.min.js

/*!
 * https://github.com/select2/select2/blob/master/dist/js/select2.full.js
 *
 * Note: This is a branded version with following changes:
 *  1) `jQuery.fn.select2` renamed to `jQuery.fn.wpmuiSelect`
 *     Replace occurances of "fn.select2" and ".select2(" in this file.
 *  2) Add/Set the following values to Defaults.prototype.reset()
 *     dropdownAutoWidth: true
 *     containerCssClass: 'wpmui-select2 :all:'
 *     dropdownCssClass: 'wpmui-select2'
 *
 * Select2 4.0.3
 * https://select2.github.io
 *
 * Released under the MIT license
 * https://github.com/select2/select2/blob/master/LICENSE.md
 */
(function(factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define(['jquery'], factory);
	} else if (typeof exports === 'object') {
		// Node/CommonJS
		factory(require('jquery'));
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function(jQuery) {
	// This is needed so we can catch the AMD loader configuration and use it
	// The inner file should be wrapped (by `banner.start.js`) in a function that
	// returns the AMD loader references.
	var S2 =
		(function() {
			// Restore the Select2 AMD loader so it can be used
			// Needed mostly in the language files, where the loader is not inserted
			if (jQuery && jQuery.fn && jQuery.fn.wpmuiSelect && jQuery.fn.wpmuiSelect.amd) {
				var S2 = jQuery.fn.wpmuiSelect.amd;
			}
			var S2;
			(function() {
				if (!S2 || !S2.requirejs) {
					if (!S2) {
						S2 = {};
					} else {
						require = S2;
					}
					/**
					 * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
					 * Available via the MIT or new BSD license.
					 * see: http://github.com/jrburke/almond for details
					 */
					//Going sloppy to avoid 'use strict' string cost, but strict practices should
					//be followed.
					/*jslint sloppy: true */
					/*global setTimeout: false */

					var requirejs, require, define;
					(function(undef) {
						var main, req, makeMap, handlers,
							defined = {},
							waiting = {},
							config = {},
							defining = {},
							hasOwn = Object.prototype.hasOwnProperty,
							aps = [].slice,
							jsSuffixRegExp = /\.js$/;

						function hasProp(obj, prop) {
							return hasOwn.call(obj, prop);
						}

						/**
						 * Given a relative module name, like ./something, normalize it to
						 * a real name that can be mapped to a path.
						 * @param {String} name the relative name
						 * @param {String} baseName a real name that the name arg is relative
						 * to.
						 * @returns {String} normalized name
						 */

						function normalize(name, baseName) {
							var nameParts, nameSegment, mapValue, foundMap, lastIndex,
								foundI, foundStarMap, starI, i, j, part,
								baseParts = baseName && baseName.split("/"),
								map = config.map,
								starMap = (map && map['*']) || {};

							//Adjust any relative paths.
							if (name && name.charAt(0) === ".") {
								//If have a base name, try to normalize against it,
								//otherwise, assume it is a top-level require that will
								//be relative to baseUrl in the end.
								if (baseName) {
									name = name.split('/');
									lastIndex = name.length - 1;

									// Node .js allowance:
									if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
										name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
									}

									//Lop off the last part of baseParts, so that . matches the
									//"directory" and not name of the baseName's module. For instance,
									//baseName of "one/two/three", maps to "one/two/three.js", but we
									//want the directory, "one/two" for this normalization.
									name = baseParts.slice(0, baseParts.length - 1).concat(name);

									//start trimDots
									for (i = 0; i < name.length; i += 1) {
										part = name[i];
										if (part === ".") {
											name.splice(i, 1);
											i -= 1;
										} else if (part === "..") {
											if (i === 1 && (name[2] === '..' || name[0] === '..')) {
												//End of the line. Keep at least one non-dot
												//path segment at the front so it can be mapped
												//correctly to disk. Otherwise, there is likely
												//no path mapping for a path starting with '..'.
												//This can still fail, but catches the most reasonable
												//uses of ..
												break;
											} else if (i > 0) {
												name.splice(i - 1, 2);
												i -= 2;
											}
										}
									}
									//end trimDots

									name = name.join("/");
								} else if (name.indexOf('./') === 0) {
									// No baseName, so this is ID is resolved relative
									// to baseUrl, pull off the leading dot.
									name = name.substring(2);
								}
							}

							//Apply map config if available.
							if ((baseParts || starMap) && map) {
								nameParts = name.split('/');

								for (i = nameParts.length; i > 0; i -= 1) {
									nameSegment = nameParts.slice(0, i).join("/");

									if (baseParts) {
										//Find the longest baseName segment match in the config.
										//So, do joins on the biggest to smallest lengths of baseParts.
										for (j = baseParts.length; j > 0; j -= 1) {
											mapValue = map[baseParts.slice(0, j).join('/')];

											//baseName segment has  config, find if it has one for
											//this name.
											if (mapValue) {
												mapValue = mapValue[nameSegment];
												if (mapValue) {
													//Match, update name to the new value.
													foundMap = mapValue;
													foundI = i;
													break;
												}
											}
										}
									}

									if (foundMap) {
										break;
									}

									//Check for a star map match, but just hold on to it,
									//if there is a shorter segment match later in a matching
									//config, then favor over this star map.
									if (!foundStarMap && starMap && starMap[nameSegment]) {
										foundStarMap = starMap[nameSegment];
										starI = i;
									}
								}

								if (!foundMap && foundStarMap) {
									foundMap = foundStarMap;
									foundI = starI;
								}

								if (foundMap) {
									nameParts.splice(0, foundI, foundMap);
									name = nameParts.join('/');
								}
							}

							return name;
						}

						function makeRequire(relName, forceSync) {
							return function() {
								//A version of a require function that passes a moduleName
								//value for items that may need to
								//look up paths relative to the moduleName
								var args = aps.call(arguments, 0);

								//If first arg is not require('string'), and there is only
								//one arg, it is the array form without a callback. Insert
								//a null so that the following concat is correct.
								if (typeof args[0] !== 'string' && args.length === 1) {
									args.push(null);
								}
								return req.apply(undef, args.concat([relName, forceSync]));
							};
						}

						function makeNormalize(relName) {
							return function(name) {
								return normalize(name, relName);
							};
						}

						function makeLoad(depName) {
							return function(value) {
								defined[depName] = value;
							};
						}

						function callDep(name) {
							if (hasProp(waiting, name)) {
								var args = waiting[name];
								delete waiting[name];
								defining[name] = true;
								main.apply(undef, args);
							}

							if (!hasProp(defined, name) && !hasProp(defining, name)) {
								throw new Error('No ' + name);
							}
							return defined[name];
						}

						//Turns a plugin!resource to [plugin, resource]
						//with the plugin being undefined if the name
						//did not have a plugin prefix.

						function splitPrefix(name) {
							var prefix,
								index = name ? name.indexOf('!') : -1;
							if (index > -1) {
								prefix = name.substring(0, index);
								name = name.substring(index + 1, name.length);
							}
							return [prefix, name];
						}

						/**
						 * Makes a name map, normalizing the name, and using a plugin
						 * for normalization if necessary. Grabs a ref to plugin
						 * too, as an optimization.
						 */
						makeMap = function(name, relName) {
							var plugin,
								parts = splitPrefix(name),
								prefix = parts[0];

							name = parts[1];

							if (prefix) {
								prefix = normalize(prefix, relName);
								plugin = callDep(prefix);
							}

							//Normalize according
							if (prefix) {
								if (plugin && plugin.normalize) {
									name = plugin.normalize(name, makeNormalize(relName));
								} else {
									name = normalize(name, relName);
								}
							} else {
								name = normalize(name, relName);
								parts = splitPrefix(name);
								prefix = parts[0];
								name = parts[1];
								if (prefix) {
									plugin = callDep(prefix);
								}
							}

							//Using ridiculous property names for space reasons
							return {
								f: prefix ? prefix + '!' + name : name, //fullName
								n: name,
								pr: prefix,
								p: plugin
							};
						};

						function makeConfig(name) {
							return function() {
								return (config && config.config && config.config[name]) || {};
							};
						}

						handlers = {
							require: function(name) {
								return makeRequire(name);
							},
							exports: function(name) {
								var e = defined[name];
								if (typeof e !== 'undefined') {
									return e;
								} else {
									return (defined[name] = {});
								}
							},
							module: function(name) {
								return {
									id: name,
									uri: '',
									exports: defined[name],
									config: makeConfig(name)
								};
							}
						};

						main = function(name, deps, callback, relName) {
							var cjsModule, depName, ret, map, i,
								args = [],
								callbackType = typeof callback,
								usingExports;

							//Use name if no relName
							relName = relName || name;

							//Call the callback to define the module, if necessary.
							if (callbackType === 'undefined' || callbackType === 'function') {
								//Pull out the defined dependencies and pass the ordered
								//values to the callback.
								//Default to [require, exports, module] if no deps
								deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
								for (i = 0; i < deps.length; i += 1) {
									map = makeMap(deps[i], relName);
									depName = map.f;

									//Fast path CommonJS standard dependencies.
									if (depName === "require") {
										args[i] = handlers.require(name);
									} else if (depName === "exports") {
										//CommonJS module spec 1.1
										args[i] = handlers.exports(name);
										usingExports = true;
									} else if (depName === "module") {
										//CommonJS module spec 1.1
										cjsModule = args[i] = handlers.module(name);
									} else if (hasProp(defined, depName) ||
										hasProp(waiting, depName) ||
										hasProp(defining, depName)) {
										args[i] = callDep(depName);
									} else if (map.p) {
										map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
										args[i] = defined[depName];
									} else {
										throw new Error(name + ' missing ' + depName);
									}
								}

								ret = callback ? callback.apply(defined[name], args) : undefined;

								if (name) {
									//If setting exports via "module" is in play,
									//favor that over return value and exports. After that,
									//favor a non-undefined return value over exports use.
									if (cjsModule && cjsModule.exports !== undef &&
										cjsModule.exports !== defined[name]) {
										defined[name] = cjsModule.exports;
									} else if (ret !== undef || !usingExports) {
										//Use the return value from the function.
										defined[name] = ret;
									}
								}
							} else if (name) {
								//May just be an object definition for the module. Only
								//worry about defining if have a module name.
								defined[name] = callback;
							}
						};

						requirejs = require = req = function(deps, callback, relName, forceSync, alt) {
							if (typeof deps === "string") {
								if (handlers[deps]) {
									//callback in this case is really relName
									return handlers[deps](callback);
								}
								//Just return the module wanted. In this scenario, the
								//deps arg is the module name, and second arg (if passed)
								//is just the relName.
								//Normalize module name, if it contains . or ..
								return callDep(makeMap(deps, callback).f);
							} else if (!deps.splice) {
								//deps is a config object, not an array.
								config = deps;
								if (config.deps) {
									req(config.deps, config.callback);
								}
								if (!callback) {
									return;
								}

								if (callback.splice) {
									//callback is an array, which means it is a dependency list.
									//Adjust args if there are dependencies
									deps = callback;
									callback = relName;
									relName = null;
								} else {
									deps = undef;
								}
							}

							//Support require(['a'])
							callback = callback || function() {};

							//If relName is a function, it is an errback handler,
							//so remove it.
							if (typeof relName === 'function') {
								relName = forceSync;
								forceSync = alt;
							}

							//Simulate async callback;
							if (forceSync) {
								main(undef, deps, callback, relName);
							} else {
								//Using a non-zero value because of concern for what old browsers
								//do, and latest browsers "upgrade" to 4 if lower value is used:
								//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
								//If want a value immediately, use require('id') instead -- something
								//that works in almond on the global level, but not guaranteed and
								//unlikely to work in other AMD implementations.
								setTimeout(function() {
									main(undef, deps, callback, relName);
								}, 4);
							}

							return req;
						};

						/**
						 * Just drops the config on the floor, but returns req in case
						 * the config return value is used.
						 */
						req.config = function(cfg) {
							return req(cfg);
						};

						/**
						 * Expose module registry for debugging and tooling
						 */
						requirejs._defined = defined;

						define = function(name, deps, callback) {
							if (typeof name !== 'string') {
								throw new Error('See almond README: incorrect module build, no module name');
							}

							//This module may not have dependencies
							if (!deps.splice) {
								//deps is not an array, so probably means
								//an object literal or factory function for
								//the value. Adjust args.
								callback = deps;
								deps = [];
							}

							if (!hasProp(defined, name) && !hasProp(waiting, name)) {
								waiting[name] = [name, deps, callback];
							}
						};

						define.amd = {
							jQuery: true
						};
					}());

					S2.requirejs = requirejs;
					S2.require = require;
					S2.define = define;
				}
			}());
			S2.define("almond", function() {});

			/* global jQuery:false, $:false */
			S2.define('jquery', [], function() {
				var _$ = jQuery || $;

				if (_$ == null && console && console.error) {
					console.error(
						'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
						'found. Make sure that you are including jQuery before Select2 on your ' +
						'web page.'
					);
				}

				return _$;
			});

			S2.define('select2/utils', [
				'jquery'
			], function($) {
				var Utils = {};

				Utils.Extend = function(ChildClass, SuperClass) {
					var __hasProp = {}.hasOwnProperty;

					function BaseConstructor() {
						this.constructor = ChildClass;
					}

					for (var key in SuperClass) {
						if (__hasProp.call(SuperClass, key)) {
							ChildClass[key] = SuperClass[key];
						}
					}

					BaseConstructor.prototype = SuperClass.prototype;
					ChildClass.prototype = new BaseConstructor();
					ChildClass.__super__ = SuperClass.prototype;

					return ChildClass;
				};

				function getMethods(theClass) {
					var proto = theClass.prototype;

					var methods = [];

					for (var methodName in proto) {
						var m = proto[methodName];

						if (typeof m !== 'function') {
							continue;
						}

						if (methodName === 'constructor') {
							continue;
						}

						methods.push(methodName);
					}

					return methods;
				}

				Utils.Decorate = function(SuperClass, DecoratorClass) {
					var decoratedMethods = getMethods(DecoratorClass);
					var superMethods = getMethods(SuperClass);

					function DecoratedClass() {
						var unshift = Array.prototype.unshift;

						var argCount = DecoratorClass.prototype.constructor.length;

						var calledConstructor = SuperClass.prototype.constructor;

						if (argCount > 0) {
							unshift.call(arguments, SuperClass.prototype.constructor);

							calledConstructor = DecoratorClass.prototype.constructor;
						}

						calledConstructor.apply(this, arguments);
					}

					DecoratorClass.displayName = SuperClass.displayName;

					function ctr() {
						this.constructor = DecoratedClass;
					}

					DecoratedClass.prototype = new ctr();

					for (var m = 0; m < superMethods.length; m++) {
						var superMethod = superMethods[m];

						DecoratedClass.prototype[superMethod] =
							SuperClass.prototype[superMethod];
					}

					var calledMethod = function(methodName) {
						// Stub out the original method if it's not decorating an actual method
						var originalMethod = function() {};

						if (methodName in DecoratedClass.prototype) {
							originalMethod = DecoratedClass.prototype[methodName];
						}

						var decoratedMethod = DecoratorClass.prototype[methodName];

						return function() {
							var unshift = Array.prototype.unshift;

							unshift.call(arguments, originalMethod);

							return decoratedMethod.apply(this, arguments);
						};
					};

					for (var d = 0; d < decoratedMethods.length; d++) {
						var decoratedMethod = decoratedMethods[d];

						DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
					}

					return DecoratedClass;
				};

				var Observable = function() {
					this.listeners = {};
				};

				Observable.prototype.on = function(event, callback) {
					this.listeners = this.listeners || {};

					if (event in this.listeners) {
						this.listeners[event].push(callback);
					} else {
						this.listeners[event] = [callback];
					}
				};

				Observable.prototype.trigger = function(event) {
					var slice = Array.prototype.slice;
					var params = slice.call(arguments, 1);

					this.listeners = this.listeners || {};

					// Params should always come in as an array
					if (params == null) {
						params = [];
					}

					// If there are no arguments to the event, use a temporary object
					if (params.length === 0) {
						params.push({});
					}

					// Set the `_type` of the first object to the event
					params[0]._type = event;

					if (event in this.listeners) {
						this.invoke(this.listeners[event], slice.call(arguments, 1));
					}

					if ('*' in this.listeners) {
						this.invoke(this.listeners['*'], arguments);
					}
				};

				Observable.prototype.invoke = function(listeners, params) {
					for (var i = 0, len = listeners.length; i < len; i++) {
						listeners[i].apply(this, params);
					}
				};

				Utils.Observable = Observable;

				Utils.generateChars = function(length) {
					var chars = '';

					for (var i = 0; i < length; i++) {
						var randomChar = Math.floor(Math.random() * 36);
						chars += randomChar.toString(36);
					}

					return chars;
				};

				Utils.bind = function(func, context) {
					return function() {
						func.apply(context, arguments);
					};
				};

				Utils._convertData = function(data) {
					for (var originalKey in data) {
						var keys = originalKey.split('-');

						var dataLevel = data;

						if (keys.length === 1) {
							continue;
						}

						for (var k = 0; k < keys.length; k++) {
							var key = keys[k];

							// Lowercase the first letter
							// By default, dash-separated becomes camelCase
							key = key.substring(0, 1).toLowerCase() + key.substring(1);

							if (!(key in dataLevel)) {
								dataLevel[key] = {};
							}

							if (k == keys.length - 1) {
								dataLevel[key] = data[originalKey];
							}

							dataLevel = dataLevel[key];
						}

						delete data[originalKey];
					}

					return data;
				};

				Utils.hasScroll = function(index, el) {
					// Adapted from the function created by @ShadowScripter
					// and adapted by @BillBarry on the Stack Exchange Code Review website.
					// The original code can be found at
					// http://codereview.stackexchange.com/q/13338
					// and was designed to be used with the Sizzle selector engine.

					var $el = $(el);
					var overflowX = el.style.overflowX;
					var overflowY = el.style.overflowY;

					//Check both x and y declarations
					if (overflowX === overflowY &&
						(overflowY === 'hidden' || overflowY === 'visible')) {
						return false;
					}

					if (overflowX === 'scroll' || overflowY === 'scroll') {
						return true;
					}

					return ($el.innerHeight() < el.scrollHeight ||
						$el.innerWidth() < el.scrollWidth);
				};

				Utils.escapeMarkup = function(markup) {
					var replaceMap = {
						'\\': '&#92;',
						'&': '&amp;',
						'<': '&lt;',
						'>': '&gt;',
						'"': '&quot;',
						'\'': '&#39;',
						'/': '&#47;'
					};

					// Do not try to escape the markup if it's not a string
					if (typeof markup !== 'string') {
						return markup;
					}

					return String(markup).replace(/[&<>"'\/\\]/g, function(match) {
						return replaceMap[match];
					});
				};

				// Append an array of jQuery nodes to a given element.
				Utils.appendMany = function($element, $nodes) {
					// jQuery 1.7.x does not support $.fn.append() with an array
					// Fall back to a jQuery object collection using $.fn.add()
					if ($.fn.jquery.substr(0, 3) === '1.7') {
						var $jqNodes = $();

						$.map($nodes, function(node) {
							$jqNodes = $jqNodes.add(node);
						});

						$nodes = $jqNodes;
					}

					$element.append($nodes);
				};

				return Utils;
			});

			S2.define('select2/results', [
				'jquery',
				'./utils'
			], function($, Utils) {
				function Results($element, options, dataAdapter) {
					this.$element = $element;
					this.data = dataAdapter;
					this.options = options;

					Results.__super__.constructor.call(this);
				}

				Utils.Extend(Results, Utils.Observable);

				Results.prototype.render = function() {
					var $results = $(
						'<ul class="select2-results__options" role="tree"></ul>'
					);

					if (this.options.get('multiple')) {
						$results.attr('aria-multiselectable', 'true');
					}

					this.$results = $results;

					return $results;
				};

				Results.prototype.clear = function() {
					this.$results.empty();
				};

				Results.prototype.displayMessage = function(params) {
					var escapeMarkup = this.options.get('escapeMarkup');

					this.clear();
					this.hideLoading();

					var $message = $(
						'<li role="treeitem" aria-live="assertive"' +
						' class="select2-results__option"></li>'
					);

					var message = this.options.get('translations').get(params.message);

					$message.append(
						escapeMarkup(
							message(params.args)
						)
					);

					$message[0].className += ' select2-results__message';

					this.$results.append($message);
				};

				Results.prototype.hideMessages = function() {
					this.$results.find('.select2-results__message').remove();
				};

				Results.prototype.append = function(data) {
					this.hideLoading();

					var $options = [];

					if (data.results == null || data.results.length === 0) {
						if (this.$results.children().length === 0) {
							this.trigger('results:message', {
								message: 'noResults'
							});
						}

						return;
					}

					data.results = this.sort(data.results);

					for (var d = 0; d < data.results.length; d++) {
						var item = data.results[d];

						var $option = this.option(item);

						$options.push($option);
					}

					this.$results.append($options);
				};

				Results.prototype.position = function($results, $dropdown) {
					var $resultsContainer = $dropdown.find('.select2-results');
					$resultsContainer.append($results);
				};

				Results.prototype.sort = function(data) {
					var sorter = this.options.get('sorter');

					return sorter(data);
				};

				Results.prototype.highlightFirstItem = function() {
					var $options = this.$results
						.find('.select2-results__option[aria-selected]');

					var $selected = $options.filter('[aria-selected=true]');

					// Check if there are any selected options
					if ($selected.length > 0) {
						// If there are selected options, highlight the first
						$selected.first().trigger('mouseenter');
					} else {
						// If there are no selected options, highlight the first option
						// in the dropdown
						$options.first().trigger('mouseenter');
					}

					this.ensureHighlightVisible();
				};

				Results.prototype.setClasses = function() {
					var self = this;

					this.data.current(function(selected) {
						var selectedIds = $.map(selected, function(s) {
							return s.id.toString();
						});

						var $options = self.$results
							.find('.select2-results__option[aria-selected]');

						$options.each(function() {
							var $option = $(this);

							var item = $.data(this, 'data');

							// id needs to be converted to a string when comparing
							var id = '' + item.id;

							if ((item.element != null && item.element.selected) ||
								(item.element == null && $.inArray(id, selectedIds) > -1)) {
								$option.attr('aria-selected', 'true');
							} else {
								$option.attr('aria-selected', 'false');
							}
						});

					});
				};

				Results.prototype.showLoading = function(params) {
					this.hideLoading();

					var loadingMore = this.options.get('translations').get('searching');

					var loading = {
						disabled: true,
						loading: true,
						text: loadingMore(params)
					};
					var $loading = this.option(loading);
					$loading.className += ' loading-results';

					this.$results.prepend($loading);
				};

				Results.prototype.hideLoading = function() {
					this.$results.find('.loading-results').remove();
				};

				Results.prototype.option = function(data) {
					var option = document.createElement('li');
					option.className = 'select2-results__option';

					var attrs = {
						'role': 'treeitem',
						'aria-selected': 'false'
					};

					if (data.disabled) {
						delete attrs['aria-selected'];
						attrs['aria-disabled'] = 'true';
					}

					if (data.id == null) {
						delete attrs['aria-selected'];
					}

					if (data._resultId != null) {
						option.id = data._resultId;
					}

					if (data.title) {
						option.title = data.title;
					}

					if (data.children) {
						attrs.role = 'group';
						attrs['aria-label'] = data.text;
						delete attrs['aria-selected'];
					}

					for (var attr in attrs) {
						var val = attrs[attr];

						option.setAttribute(attr, val);
					}

					if (data.children) {
						var $option = $(option);

						var label = document.createElement('strong');
						label.className = 'select2-results__group';

						var $label = $(label);
						this.template(data, label);

						var $children = [];

						for (var c = 0; c < data.children.length; c++) {
							var child = data.children[c];

							var $child = this.option(child);

							$children.push($child);
						}

						var $childrenContainer = $('<ul></ul>', {
							'class': 'select2-results__options select2-results__options--nested'
						});

						$childrenContainer.append($children);

						$option.append(label);
						$option.append($childrenContainer);
					} else {
						this.template(data, option);
					}

					$.data(option, 'data', data);

					return option;
				};

				Results.prototype.bind = function(container, $container) {
					var self = this;

					var id = container.id + '-results';

					this.$results.attr('id', id);

					container.on('results:all', function(params) {
						self.clear();
						self.append(params.data);

						if (container.isOpen()) {
							self.setClasses();
							self.highlightFirstItem();
						}
					});

					container.on('results:append', function(params) {
						self.append(params.data);

						if (container.isOpen()) {
							self.setClasses();
						}
					});

					container.on('query', function(params) {
						self.hideMessages();
						self.showLoading(params);
					});

					container.on('select', function() {
						if (!container.isOpen()) {
							return;
						}

						self.setClasses();
						self.highlightFirstItem();
					});

					container.on('unselect', function() {
						if (!container.isOpen()) {
							return;
						}

						self.setClasses();
						self.highlightFirstItem();
					});

					container.on('open', function() {
						// When the dropdown is open, aria-expended="true"
						self.$results.attr('aria-expanded', 'true');
						self.$results.attr('aria-hidden', 'false');

						self.setClasses();
						self.ensureHighlightVisible();
					});

					container.on('close', function() {
						// When the dropdown is closed, aria-expended="false"
						self.$results.attr('aria-expanded', 'false');
						self.$results.attr('aria-hidden', 'true');
						self.$results.removeAttr('aria-activedescendant');
					});

					container.on('results:toggle', function() {
						var $highlighted = self.getHighlightedResults();

						if ($highlighted.length === 0) {
							return;
						}

						$highlighted.trigger('mouseup');
					});

					container.on('results:select', function() {
						var $highlighted = self.getHighlightedResults();

						if ($highlighted.length === 0) {
							return;
						}

						var data = $highlighted.data('data');

						if ($highlighted.attr('aria-selected') == 'true') {
							self.trigger('close', {});
						} else {
							self.trigger('select', {
								data: data
							});
						}
					});

					container.on('results:previous', function() {
						var $highlighted = self.getHighlightedResults();

						var $options = self.$results.find('[aria-selected]');

						var currentIndex = $options.index($highlighted);

						// If we are already at te top, don't move further
						if (currentIndex === 0) {
							return;
						}

						var nextIndex = currentIndex - 1;

						// If none are highlighted, highlight the first
						if ($highlighted.length === 0) {
							nextIndex = 0;
						}

						var $next = $options.eq(nextIndex);

						$next.trigger('mouseenter');

						var currentOffset = self.$results.offset().top;
						var nextTop = $next.offset().top;
						var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);

						if (nextIndex === 0) {
							self.$results.scrollTop(0);
						} else if (nextTop - currentOffset < 0) {
							self.$results.scrollTop(nextOffset);
						}
					});

					container.on('results:next', function() {
						var $highlighted = self.getHighlightedResults();

						var $options = self.$results.find('[aria-selected]');

						var currentIndex = $options.index($highlighted);

						var nextIndex = currentIndex + 1;

						// If we are at the last option, stay there
						if (nextIndex >= $options.length) {
							return;
						}

						var $next = $options.eq(nextIndex);

						$next.trigger('mouseenter');

						var currentOffset = self.$results.offset().top +
							self.$results.outerHeight(false);
						var nextBottom = $next.offset().top + $next.outerHeight(false);
						var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;

						if (nextIndex === 0) {
							self.$results.scrollTop(0);
						} else if (nextBottom > currentOffset) {
							self.$results.scrollTop(nextOffset);
						}
					});

					container.on('results:focus', function(params) {
						params.element.addClass('select2-results__option--highlighted');
					});

					container.on('results:message', function(params) {
						self.displayMessage(params);
					});

					if ($.fn.mousewheel) {
						this.$results.on('mousewheel', function(e) {
							var top = self.$results.scrollTop();

							var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;

							var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
							var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();

							if (isAtTop) {
								self.$results.scrollTop(0);

								e.preventDefault();
								e.stopPropagation();
							} else if (isAtBottom) {
								self.$results.scrollTop(
									self.$results.get(0).scrollHeight - self.$results.height()
								);

								e.preventDefault();
								e.stopPropagation();
							}
						});
					}

					this.$results.on('mouseup', '.select2-results__option[aria-selected]',
						function(evt) {
							var $this = $(this);

							var data = $this.data('data');

							if ($this.attr('aria-selected') === 'true') {
								if (self.options.get('multiple')) {
									self.trigger('unselect', {
										originalEvent: evt,
										data: data
									});
								} else {
									self.trigger('close', {});
								}

								return;
							}

							self.trigger('select', {
								originalEvent: evt,
								data: data
							});
						});

					this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
						function(evt) {
							var data = $(this).data('data');

							self.getHighlightedResults()
								.removeClass('select2-results__option--highlighted');

							self.trigger('results:focus', {
								data: data,
								element: $(this)
							});
						});
				};

				Results.prototype.getHighlightedResults = function() {
					var $highlighted = this.$results
						.find('.select2-results__option--highlighted');

					return $highlighted;
				};

				Results.prototype.destroy = function() {
					this.$results.remove();
				};

				Results.prototype.ensureHighlightVisible = function() {
					var $highlighted = this.getHighlightedResults();

					if ($highlighted.length === 0) {
						return;
					}

					var $options = this.$results.find('[aria-selected]');

					var currentIndex = $options.index($highlighted);

					var currentOffset = this.$results.offset().top;
					var nextTop = $highlighted.offset().top;
					var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);

					var offsetDelta = nextTop - currentOffset;
					nextOffset -= $highlighted.outerHeight(false) * 2;

					if (currentIndex <= 2) {
						this.$results.scrollTop(0);
					} else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
						this.$results.scrollTop(nextOffset);
					}
				};

				Results.prototype.template = function(result, container) {
					var template = this.options.get('templateResult');
					var escapeMarkup = this.options.get('escapeMarkup');

					var content = template(result, container);

					if (content == null) {
						container.style.display = 'none';
					} else if (typeof content === 'string') {
						container.innerHTML = escapeMarkup(content);
					} else {
						$(container).append(content);
					}
				};

				return Results;
			});

			S2.define('select2/keys', [

			], function() {
				var KEYS = {
					BACKSPACE: 8,
					TAB: 9,
					ENTER: 13,
					SHIFT: 16,
					CTRL: 17,
					ALT: 18,
					ESC: 27,
					SPACE: 32,
					PAGE_UP: 33,
					PAGE_DOWN: 34,
					END: 35,
					HOME: 36,
					LEFT: 37,
					UP: 38,
					RIGHT: 39,
					DOWN: 40,
					DELETE: 46
				};

				return KEYS;
			});

			S2.define('select2/selection/base', [
				'jquery',
				'../utils',
				'../keys'
			], function($, Utils, KEYS) {
				function BaseSelection($element, options) {
					this.$element = $element;
					this.options = options;

					BaseSelection.__super__.constructor.call(this);
				}

				Utils.Extend(BaseSelection, Utils.Observable);

				BaseSelection.prototype.render = function() {
					var $selection = $(
						'<span class="select2-selection" role="combobox" ' +
						' aria-haspopup="true" aria-expanded="false">' +
						'</span>'
					);

					this._tabindex = 0;

					if (this.$element.data('old-tabindex') != null) {
						this._tabindex = this.$element.data('old-tabindex');
					} else if (this.$element.attr('tabindex') != null) {
						this._tabindex = this.$element.attr('tabindex');
					}

					$selection.attr('title', this.$element.attr('title'));
					$selection.attr('tabindex', this._tabindex);

					this.$selection = $selection;

					return $selection;
				};

				BaseSelection.prototype.bind = function(container, $container) {
					var self = this;

					var id = container.id + '-container';
					var resultsId = container.id + '-results';

					this.container = container;

					this.$selection.on('focus', function(evt) {
						self.trigger('focus', evt);
					});

					this.$selection.on('blur', function(evt) {
						self._handleBlur(evt);
					});

					this.$selection.on('keydown', function(evt) {
						self.trigger('keypress', evt);

						if (evt.which === KEYS.SPACE) {
							evt.preventDefault();
						}
					});

					container.on('results:focus', function(params) {
						self.$selection.attr('aria-activedescendant', params.data._resultId);
					});

					container.on('selection:update', function(params) {
						self.update(params.data);
					});

					container.on('open', function() {
						// When the dropdown is open, aria-expanded="true"
						self.$selection.attr('aria-expanded', 'true');
						self.$selection.attr('aria-owns', resultsId);

						self._attachCloseHandler(container);
					});

					container.on('close', function() {
						// When the dropdown is closed, aria-expanded="false"
						self.$selection.attr('aria-expanded', 'false');
						self.$selection.removeAttr('aria-activedescendant');
						self.$selection.removeAttr('aria-owns');

						self.$selection.focus();

						self._detachCloseHandler(container);
					});

					container.on('enable', function() {
						self.$selection.attr('tabindex', self._tabindex);
					});

					container.on('disable', function() {
						self.$selection.attr('tabindex', '-1');
					});
				};

				BaseSelection.prototype._handleBlur = function(evt) {
					var self = this;

					// This needs to be delayed as the active element is the body when the tab
					// key is pressed, possibly along with others.
					window.setTimeout(function() {
						// Don't trigger `blur` if the focus is still in the selection
						if (
							(document.activeElement == self.$selection[0]) ||
							($.contains(self.$selection[0], document.activeElement))
						) {
							return;
						}

						self.trigger('blur', evt);
					}, 1);
				};

				BaseSelection.prototype._attachCloseHandler = function(container) {
					var self = this;

					$(document.body).on('mousedown.select2.' + container.id, function(e) {
						var $target = $(e.target);

						var $select = $target.closest('.select2');

						var $all = $('.select2.select2-container--open');

						$all.each(function() {
							var $this = $(this);

							if (this == $select[0]) {
								return;
							}

							var $element = $this.data('element');

							$element.wpmuiSelect('close');
						});
					});
				};

				BaseSelection.prototype._detachCloseHandler = function(container) {
					$(document.body).off('mousedown.select2.' + container.id);
				};

				BaseSelection.prototype.position = function($selection, $container) {
					var $selectionContainer = $container.find('.selection');
					$selectionContainer.append($selection);
				};

				BaseSelection.prototype.destroy = function() {
					this._detachCloseHandler(this.container);
				};

				BaseSelection.prototype.update = function(data) {
					throw new Error('The `update` method must be defined in child classes.');
				};

				return BaseSelection;
			});

			S2.define('select2/selection/single', [
				'jquery',
				'./base',
				'../utils',
				'../keys'
			], function($, BaseSelection, Utils, KEYS) {
				function SingleSelection() {
					SingleSelection.__super__.constructor.apply(this, arguments);
				}

				Utils.Extend(SingleSelection, BaseSelection);

				SingleSelection.prototype.render = function() {
					var $selection = SingleSelection.__super__.render.call(this);

					$selection.addClass('select2-selection--single');

					$selection.html(
						'<span class="select2-selection__rendered"></span>' +
						'<span class="select2-selection__arrow" role="presentation">' +
						'<b role="presentation"></b>' +
						'</span>'
					);

					return $selection;
				};

				SingleSelection.prototype.bind = function(container, $container) {
					var self = this;

					SingleSelection.__super__.bind.apply(this, arguments);

					var id = container.id + '-container';

					this.$selection.find('.select2-selection__rendered').attr('id', id);
					this.$selection.attr('aria-labelledby', id);

					this.$selection.on('mousedown', function(evt) {
						// Only respond to left clicks
						if (evt.which !== 1) {
							return;
						}

						self.trigger('toggle', {
							originalEvent: evt
						});
					});

					this.$selection.on('focus', function(evt) {
						// User focuses on the container
					});

					this.$selection.on('blur', function(evt) {
						// User exits the container
					});

					container.on('focus', function(evt) {
						if (!container.isOpen()) {
							self.$selection.focus();
						}
					});

					container.on('selection:update', function(params) {
						self.update(params.data);
					});
				};

				SingleSelection.prototype.clear = function() {
					this.$selection.find('.select2-selection__rendered').empty();
				};

				SingleSelection.prototype.display = function(data, container) {
					var template = this.options.get('templateSelection');
					var escapeMarkup = this.options.get('escapeMarkup');

					return escapeMarkup(template(data, container));
				};

				SingleSelection.prototype.selectionContainer = function() {
					return $('<span></span>');
				};

				SingleSelection.prototype.update = function(data) {
					if (data.length === 0) {
						this.clear();
						return;
					}

					var selection = data[0];

					var $rendered = this.$selection.find('.select2-selection__rendered');
					var formatted = this.display(selection, $rendered);

					$rendered.empty().append(formatted);
					$rendered.prop('title', selection.title || selection.text);
				};

				return SingleSelection;
			});

			S2.define('select2/selection/multiple', [
				'jquery',
				'./base',
				'../utils'
			], function($, BaseSelection, Utils) {
				function MultipleSelection($element, options) {
					MultipleSelection.__super__.constructor.apply(this, arguments);
				}

				Utils.Extend(MultipleSelection, BaseSelection);

				MultipleSelection.prototype.render = function() {
					var $selection = MultipleSelection.__super__.render.call(this);

					$selection.addClass('select2-selection--multiple');

					$selection.html(
						'<ul class="select2-selection__rendered"></ul>'
					);

					return $selection;
				};

				MultipleSelection.prototype.bind = function(container, $container) {
					var self = this;

					MultipleSelection.__super__.bind.apply(this, arguments);

					this.$selection.on('click', function(evt) {
						self.trigger('toggle', {
							originalEvent: evt
						});
					});

					this.$selection.on(
						'click',
						'.select2-selection__choice__remove',
						function(evt) {
							// Ignore the event if it is disabled
							if (self.options.get('disabled')) {
								return;
							}

							var $remove = $(this);
							var $selection = $remove.parent();

							var data = $selection.data('data');

							self.trigger('unselect', {
								originalEvent: evt,
								data: data
							});
						}
					);
				};

				MultipleSelection.prototype.clear = function() {
					this.$selection.find('.select2-selection__rendered').empty();
				};

				MultipleSelection.prototype.display = function(data, container) {
					var template = this.options.get('templateSelection');
					var escapeMarkup = this.options.get('escapeMarkup');

					return escapeMarkup(template(data, container));
				};

				MultipleSelection.prototype.selectionContainer = function() {
					var $container = $(
						'<li class="select2-selection__choice">' +
						'<span class="select2-selection__choice__remove" role="presentation">' +
						'&times;' +
						'</span>' +
						'</li>'
					);

					return $container;
				};

				MultipleSelection.prototype.update = function(data) {
					this.clear();

					if (data.length === 0) {
						return;
					}

					var $selections = [];

					for (var d = 0; d < data.length; d++) {
						var selection = data[d];

						var $selection = this.selectionContainer();
						var formatted = this.display(selection, $selection);

						$selection.append(formatted);
						$selection.prop('title', selection.title || selection.text);

						$selection.data('data', selection);

						$selections.push($selection);
					}

					var $rendered = this.$selection.find('.select2-selection__rendered');

					Utils.appendMany($rendered, $selections);
				};

				return MultipleSelection;
			});

			S2.define('select2/selection/placeholder', [
				'../utils'
			], function(Utils) {
				function Placeholder(decorated, $element, options) {
					this.placeholder = this.normalizePlaceholder(options.get('placeholder'));

					decorated.call(this, $element, options);
				}

				Placeholder.prototype.normalizePlaceholder = function(_, placeholder) {
					if (typeof placeholder === 'string') {
						placeholder = {
							id: '',
							text: placeholder
						};
					}

					return placeholder;
				};

				Placeholder.prototype.createPlaceholder = function(decorated, placeholder) {
					var $placeholder = this.selectionContainer();

					$placeholder.html(this.display(placeholder));
					$placeholder.addClass('select2-selection__placeholder')
						.removeClass('select2-selection__choice');

					return $placeholder;
				};

				Placeholder.prototype.update = function(decorated, data) {
					var singlePlaceholder = (
						data.length == 1 && data[0].id != this.placeholder.id
					);
					var multipleSelections = data.length > 1;

					if (multipleSelections || singlePlaceholder) {
						return decorated.call(this, data);
					}

					this.clear();

					var $placeholder = this.createPlaceholder(this.placeholder);

					this.$selection.find('.select2-selection__rendered').append($placeholder);
				};

				return Placeholder;
			});

			S2.define('select2/selection/allowClear', [
				'jquery',
				'../keys'
			], function($, KEYS) {
				function AllowClear() {}

				AllowClear.prototype.bind = function(decorated, container, $container) {
					var self = this;

					decorated.call(this, container, $container);

					if (this.placeholder == null) {
						if (this.options.get('debug') && window.console && console.error) {
							console.error(
								'Select2: The `allowClear` option should be used in combination ' +
								'with the `placeholder` option.'
							);
						}
					}

					this.$selection.on('mousedown', '.select2-selection__clear',
						function(evt) {
							self._handleClear(evt);
						});

					container.on('keypress', function(evt) {
						self._handleKeyboardClear(evt, container);
					});
				};

				AllowClear.prototype._handleClear = function(_, evt) {
					// Ignore the event if it is disabled
					if (this.options.get('disabled')) {
						return;
					}

					var $clear = this.$selection.find('.select2-selection__clear');

					// Ignore the event if nothing has been selected
					if ($clear.length === 0) {
						return;
					}

					evt.stopPropagation();

					var data = $clear.data('data');

					for (var d = 0; d < data.length; d++) {
						var unselectData = {
							data: data[d]
						};

						// Trigger the `unselect` event, so people can prevent it from being
						// cleared.
						this.trigger('unselect', unselectData);

						// If the event was prevented, don't clear it out.
						if (unselectData.prevented) {
							return;
						}
					}

					this.$element.val(this.placeholder.id).trigger('change');

					this.trigger('toggle', {});
				};

				AllowClear.prototype._handleKeyboardClear = function(_, evt, container) {
					if (container.isOpen()) {
						return;
					}

					if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
						this._handleClear(evt);
					}
				};

				AllowClear.prototype.update = function(decorated, data) {
					decorated.call(this, data);

					if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
						data.length === 0) {
						return;
					}

					var $remove = $(
						'<span class="select2-selection__clear">' +
						'&times;' +
						'</span>'
					);
					$remove.data('data', data);

					this.$selection.find('.select2-selection__rendered').prepend($remove);
				};

				return AllowClear;
			});

			S2.define('select2/selection/search', [
				'jquery',
				'../utils',
				'../keys'
			], function($, Utils, KEYS) {
				function Search(decorated, $element, options) {
					decorated.call(this, $element, options);
				}

				Search.prototype.render = function(decorated) {
					var $search = $(
						'<li class="select2-search select2-search--inline">' +
						'<input class="select2-search__field" type="search" tabindex="-1"' +
						' autocomplete="off" autocorrect="off" autocapitalize="off"' +
						' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
						'</li>'
					);

					this.$searchContainer = $search;
					this.$search = $search.find('input');

					var $rendered = decorated.call(this);

					this._transferTabIndex();

					return $rendered;
				};

				Search.prototype.bind = function(decorated, container, $container) {
					var self = this;

					decorated.call(this, container, $container);

					container.on('open', function() {
						self.$search.trigger('focus');
					});

					container.on('close', function() {
						self.$search.val('');
						self.$search.removeAttr('aria-activedescendant');
						self.$search.trigger('focus');
					});

					container.on('enable', function() {
						self.$search.prop('disabled', false);

						self._transferTabIndex();
					});

					container.on('disable', function() {
						self.$search.prop('disabled', true);
					});

					container.on('focus', function(evt) {
						self.$search.trigger('focus');
					});

					container.on('results:focus', function(params) {
						self.$search.attr('aria-activedescendant', params.id);
					});

					this.$selection.on('focusin', '.select2-search--inline', function(evt) {
						self.trigger('focus', evt);
					});

					this.$selection.on('focusout', '.select2-search--inline', function(evt) {
						self._handleBlur(evt);
					});

					this.$selection.on('keydown', '.select2-search--inline', function(evt) {
						evt.stopPropagation();

						self.trigger('keypress', evt);

						self._keyUpPrevented = evt.isDefaultPrevented();

						var key = evt.which;

						if (key === KEYS.BACKSPACE && self.$search.val() === '') {
							var $previousChoice = self.$searchContainer
								.prev('.select2-selection__choice');

							if ($previousChoice.length > 0) {
								var item = $previousChoice.data('data');

								self.searchRemoveChoice(item);

								evt.preventDefault();
							}
						}
					});

					// Try to detect the IE version should the `documentMode` property that
					// is stored on the document. This is only implemented in IE and is
					// slightly cleaner than doing a user agent check.
					// This property is not available in Edge, but Edge also doesn't have
					// this bug.
					var msie = document.documentMode;
					var disableInputEvents = msie && msie <= 11;

					// Workaround for browsers which do not support the `input` event
					// This will prevent double-triggering of events for browsers which support
					// both the `keyup` and `input` events.
					this.$selection.on(
						'input.searchcheck',
						'.select2-search--inline',
						function(evt) {
							// IE will trigger the `input` event when a placeholder is used on a
							// search box. To get around this issue, we are forced to ignore all
							// `input` events in IE and keep using `keyup`.
							if (disableInputEvents) {
								self.$selection.off('input.search input.searchcheck');
								return;
							}

							// Unbind the duplicated `keyup` event
							self.$selection.off('keyup.search');
						}
					);

					this.$selection.on(
						'keyup.search input.search',
						'.select2-search--inline',
						function(evt) {
							// IE will trigger the `input` event when a placeholder is used on a
							// search box. To get around this issue, we are forced to ignore all
							// `input` events in IE and keep using `keyup`.
							if (disableInputEvents && evt.type === 'input') {
								self.$selection.off('input.search input.searchcheck');
								return;
							}

							var key = evt.which;

							// We can freely ignore events from modifier keys
							if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
								return;
							}

							// Tabbing will be handled during the `keydown` phase
							if (key == KEYS.TAB) {
								return;
							}

							self.handleSearch(evt);
						}
					);
				};

				/**
				 * This method will transfer the tabindex attribute from the rendered
				 * selection to the search box. This allows for the search box to be used as
				 * the primary focus instead of the selection container.
				 *
				 * @private
				 */
				Search.prototype._transferTabIndex = function(decorated) {
					this.$search.attr('tabindex', this.$selection.attr('tabindex'));
					this.$selection.attr('tabindex', '-1');
				};

				Search.prototype.createPlaceholder = function(decorated, placeholder) {
					this.$search.attr('placeholder', placeholder.text);
				};

				Search.prototype.update = function(decorated, data) {
					var searchHadFocus = this.$search[0] == document.activeElement;

					this.$search.attr('placeholder', '');

					decorated.call(this, data);

					this.$selection.find('.select2-selection__rendered')
						.append(this.$searchContainer);

					this.resizeSearch();
					if (searchHadFocus) {
						this.$search.focus();
					}
				};

				Search.prototype.handleSearch = function() {
					this.resizeSearch();

					if (!this._keyUpPrevented) {
						var input = this.$search.val();

						this.trigger('query', {
							term: input
						});
					}

					this._keyUpPrevented = false;
				};

				Search.prototype.searchRemoveChoice = function(decorated, item) {
					this.trigger('unselect', {
						data: item
					});

					this.$search.val(item.text);
					this.handleSearch();
				};

				Search.prototype.resizeSearch = function() {
					this.$search.css('width', '25px');

					var width = '';

					if (this.$search.attr('placeholder') !== '') {
						width = this.$selection.find('.select2-selection__rendered').innerWidth();
					} else {
						var minimumWidth = this.$search.val().length + 1;

						width = (minimumWidth * 0.75) + 'em';
					}

					this.$search.css('width', width);
				};

				return Search;
			});

			S2.define('select2/selection/eventRelay', [
				'jquery'
			], function($) {
				function EventRelay() {}

				EventRelay.prototype.bind = function(decorated, container, $container) {
					var self = this;
					var relayEvents = [
						'open', 'opening',
						'close', 'closing',
						'select', 'selecting',
						'unselect', 'unselecting'
					];

					var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];

					decorated.call(this, container, $container);

					container.on('*', function(name, params) {
						// Ignore events that should not be relayed
						if ($.inArray(name, relayEvents) === -1) {
							return;
						}

						// The parameters should always be an object
						params = params || {};

						// Generate the jQuery event for the Select2 event
						var evt = $.Event('select2:' + name, {
							params: params
						});

						self.$element.trigger(evt);

						// Only handle preventable events if it was one
						if ($.inArray(name, preventableEvents) === -1) {
							return;
						}

						params.prevented = evt.isDefaultPrevented();
					});
				};

				return EventRelay;
			});

			S2.define('select2/translation', [
				'jquery',
				'require'
			], function($, require) {
				function Translation(dict) {
					this.dict = dict || {};
				}

				Translation.prototype.all = function() {
					return this.dict;
				};

				Translation.prototype.get = function(key) {
					return this.dict[key];
				};

				Translation.prototype.extend = function(translation) {
					this.dict = $.extend({}, translation.all(), this.dict);
				};

				// Static functions

				Translation._cache = {};

				Translation.loadPath = function(path) {
					if (!(path in Translation._cache)) {
						var translations = require(path);

						Translation._cache[path] = translations;
					}

					return new Translation(Translation._cache[path]);
				};

				return Translation;
			});

			S2.define('select2/diacritics', [

			], function() {
				var diacritics = {
					'\u24B6': 'A',
					'\uFF21': 'A',
					'\u00C0': 'A',
					'\u00C1': 'A',
					'\u00C2': 'A',
					'\u1EA6': 'A',
					'\u1EA4': 'A',
					'\u1EAA': 'A',
					'\u1EA8': 'A',
					'\u00C3': 'A',
					'\u0100': 'A',
					'\u0102': 'A',
					'\u1EB0': 'A',
					'\u1EAE': 'A',
					'\u1EB4': 'A',
					'\u1EB2': 'A',
					'\u0226': 'A',
					'\u01E0': 'A',
					'\u00C4': 'A',
					'\u01DE': 'A',
					'\u1EA2': 'A',
					'\u00C5': 'A',
					'\u01FA': 'A',
					'\u01CD': 'A',
					'\u0200': 'A',
					'\u0202': 'A',
					'\u1EA0': 'A',
					'\u1EAC': 'A',
					'\u1EB6': 'A',
					'\u1E00': 'A',
					'\u0104': 'A',
					'\u023A': 'A',
					'\u2C6F': 'A',
					'\uA732': 'AA',
					'\u00C6': 'AE',
					'\u01FC': 'AE',
					'\u01E2': 'AE',
					'\uA734': 'AO',
					'\uA736': 'AU',
					'\uA738': 'AV',
					'\uA73A': 'AV',
					'\uA73C': 'AY',
					'\u24B7': 'B',
					'\uFF22': 'B',
					'\u1E02': 'B',
					'\u1E04': 'B',
					'\u1E06': 'B',
					'\u0243': 'B',
					'\u0182': 'B',
					'\u0181': 'B',
					'\u24B8': 'C',
					'\uFF23': 'C',
					'\u0106': 'C',
					'\u0108': 'C',
					'\u010A': 'C',
					'\u010C': 'C',
					'\u00C7': 'C',
					'\u1E08': 'C',
					'\u0187': 'C',
					'\u023B': 'C',
					'\uA73E': 'C',
					'\u24B9': 'D',
					'\uFF24': 'D',
					'\u1E0A': 'D',
					'\u010E': 'D',
					'\u1E0C': 'D',
					'\u1E10': 'D',
					'\u1E12': 'D',
					'\u1E0E': 'D',
					'\u0110': 'D',
					'\u018B': 'D',
					'\u018A': 'D',
					'\u0189': 'D',
					'\uA779': 'D',
					'\u01F1': 'DZ',
					'\u01C4': 'DZ',
					'\u01F2': 'Dz',
					'\u01C5': 'Dz',
					'\u24BA': 'E',
					'\uFF25': 'E',
					'\u00C8': 'E',
					'\u00C9': 'E',
					'\u00CA': 'E',
					'\u1EC0': 'E',
					'\u1EBE': 'E',
					'\u1EC4': 'E',
					'\u1EC2': 'E',
					'\u1EBC': 'E',
					'\u0112': 'E',
					'\u1E14': 'E',
					'\u1E16': 'E',
					'\u0114': 'E',
					'\u0116': 'E',
					'\u00CB': 'E',
					'\u1EBA': 'E',
					'\u011A': 'E',
					'\u0204': 'E',
					'\u0206': 'E',
					'\u1EB8': 'E',
					'\u1EC6': 'E',
					'\u0228': 'E',
					'\u1E1C': 'E',
					'\u0118': 'E',
					'\u1E18': 'E',
					'\u1E1A': 'E',
					'\u0190': 'E',
					'\u018E': 'E',
					'\u24BB': 'F',
					'\uFF26': 'F',
					'\u1E1E': 'F',
					'\u0191': 'F',
					'\uA77B': 'F',
					'\u24BC': 'G',
					'\uFF27': 'G',
					'\u01F4': 'G',
					'\u011C': 'G',
					'\u1E20': 'G',
					'\u011E': 'G',
					'\u0120': 'G',
					'\u01E6': 'G',
					'\u0122': 'G',
					'\u01E4': 'G',
					'\u0193': 'G',
					'\uA7A0': 'G',
					'\uA77D': 'G',
					'\uA77E': 'G',
					'\u24BD': 'H',
					'\uFF28': 'H',
					'\u0124': 'H',
					'\u1E22': 'H',
					'\u1E26': 'H',
					'\u021E': 'H',
					'\u1E24': 'H',
					'\u1E28': 'H',
					'\u1E2A': 'H',
					'\u0126': 'H',
					'\u2C67': 'H',
					'\u2C75': 'H',
					'\uA78D': 'H',
					'\u24BE': 'I',
					'\uFF29': 'I',
					'\u00CC': 'I',
					'\u00CD': 'I',
					'\u00CE': 'I',
					'\u0128': 'I',
					'\u012A': 'I',
					'\u012C': 'I',
					'\u0130': 'I',
					'\u00CF': 'I',
					'\u1E2E': 'I',
					'\u1EC8': 'I',
					'\u01CF': 'I',
					'\u0208': 'I',
					'\u020A': 'I',
					'\u1ECA': 'I',
					'\u012E': 'I',
					'\u1E2C': 'I',
					'\u0197': 'I',
					'\u24BF': 'J',
					'\uFF2A': 'J',
					'\u0134': 'J',
					'\u0248': 'J',
					'\u24C0': 'K',
					'\uFF2B': 'K',
					'\u1E30': 'K',
					'\u01E8': 'K',
					'\u1E32': 'K',
					'\u0136': 'K',
					'\u1E34': 'K',
					'\u0198': 'K',
					'\u2C69': 'K',
					'\uA740': 'K',
					'\uA742': 'K',
					'\uA744': 'K',
					'\uA7A2': 'K',
					'\u24C1': 'L',
					'\uFF2C': 'L',
					'\u013F': 'L',
					'\u0139': 'L',
					'\u013D': 'L',
					'\u1E36': 'L',
					'\u1E38': 'L',
					'\u013B': 'L',
					'\u1E3C': 'L',
					'\u1E3A': 'L',
					'\u0141': 'L',
					'\u023D': 'L',
					'\u2C62': 'L',
					'\u2C60': 'L',
					'\uA748': 'L',
					'\uA746': 'L',
					'\uA780': 'L',
					'\u01C7': 'LJ',
					'\u01C8': 'Lj',
					'\u24C2': 'M',
					'\uFF2D': 'M',
					'\u1E3E': 'M',
					'\u1E40': 'M',
					'\u1E42': 'M',
					'\u2C6E': 'M',
					'\u019C': 'M',
					'\u24C3': 'N',
					'\uFF2E': 'N',
					'\u01F8': 'N',
					'\u0143': 'N',
					'\u00D1': 'N',
					'\u1E44': 'N',
					'\u0147': 'N',
					'\u1E46': 'N',
					'\u0145': 'N',
					'\u1E4A': 'N',
					'\u1E48': 'N',
					'\u0220': 'N',
					'\u019D': 'N',
					'\uA790': 'N',
					'\uA7A4': 'N',
					'\u01CA': 'NJ',
					'\u01CB': 'Nj',
					'\u24C4': 'O',
					'\uFF2F': 'O',
					'\u00D2': 'O',
					'\u00D3': 'O',
					'\u00D4': 'O',
					'\u1ED2': 'O',
					'\u1ED0': 'O',
					'\u1ED6': 'O',
					'\u1ED4': 'O',
					'\u00D5': 'O',
					'\u1E4C': 'O',
					'\u022C': 'O',
					'\u1E4E': 'O',
					'\u014C': 'O',
					'\u1E50': 'O',
					'\u1E52': 'O',
					'\u014E': 'O',
					'\u022E': 'O',
					'\u0230': 'O',
					'\u00D6': 'O',
					'\u022A': 'O',
					'\u1ECE': 'O',
					'\u0150': 'O',
					'\u01D1': 'O',
					'\u020C': 'O',
					'\u020E': 'O',
					'\u01A0': 'O',
					'\u1EDC': 'O',
					'\u1EDA': 'O',
					'\u1EE0': 'O',
					'\u1EDE': 'O',
					'\u1EE2': 'O',
					'\u1ECC': 'O',
					'\u1ED8': 'O',
					'\u01EA': 'O',
					'\u01EC': 'O',
					'\u00D8': 'O',
					'\u01FE': 'O',
					'\u0186': 'O',
					'\u019F': 'O',
					'\uA74A': 'O',
					'\uA74C': 'O',
					'\u01A2': 'OI',
					'\uA74E': 'OO',
					'\u0222': 'OU',
					'\u24C5': 'P',
					'\uFF30': 'P',
					'\u1E54': 'P',
					'\u1E56': 'P',
					'\u01A4': 'P',
					'\u2C63': 'P',
					'\uA750': 'P',
					'\uA752': 'P',
					'\uA754': 'P',
					'\u24C6': 'Q',
					'\uFF31': 'Q',
					'\uA756': 'Q',
					'\uA758': 'Q',
					'\u024A': 'Q',
					'\u24C7': 'R',
					'\uFF32': 'R',
					'\u0154': 'R',
					'\u1E58': 'R',
					'\u0158': 'R',
					'\u0210': 'R',
					'\u0212': 'R',
					'\u1E5A': 'R',
					'\u1E5C': 'R',
					'\u0156': 'R',
					'\u1E5E': 'R',
					'\u024C': 'R',
					'\u2C64': 'R',
					'\uA75A': 'R',
					'\uA7A6': 'R',
					'\uA782': 'R',
					'\u24C8': 'S',
					'\uFF33': 'S',
					'\u1E9E': 'S',
					'\u015A': 'S',
					'\u1E64': 'S',
					'\u015C': 'S',
					'\u1E60': 'S',
					'\u0160': 'S',
					'\u1E66': 'S',
					'\u1E62': 'S',
					'\u1E68': 'S',
					'\u0218': 'S',
					'\u015E': 'S',
					'\u2C7E': 'S',
					'\uA7A8': 'S',
					'\uA784': 'S',
					'\u24C9': 'T',
					'\uFF34': 'T',
					'\u1E6A': 'T',
					'\u0164': 'T',
					'\u1E6C': 'T',
					'\u021A': 'T',
					'\u0162': 'T',
					'\u1E70': 'T',
					'\u1E6E': 'T',
					'\u0166': 'T',
					'\u01AC': 'T',
					'\u01AE': 'T',
					'\u023E': 'T',
					'\uA786': 'T',
					'\uA728': 'TZ',
					'\u24CA': 'U',
					'\uFF35': 'U',
					'\u00D9': 'U',
					'\u00DA': 'U',
					'\u00DB': 'U',
					'\u0168': 'U',
					'\u1E78': 'U',
					'\u016A': 'U',
					'\u1E7A': 'U',
					'\u016C': 'U',
					'\u00DC': 'U',
					'\u01DB': 'U',
					'\u01D7': 'U',
					'\u01D5': 'U',
					'\u01D9': 'U',
					'\u1EE6': 'U',
					'\u016E': 'U',
					'\u0170': 'U',
					'\u01D3': 'U',
					'\u0214': 'U',
					'\u0216': 'U',
					'\u01AF': 'U',
					'\u1EEA': 'U',
					'\u1EE8': 'U',
					'\u1EEE': 'U',
					'\u1EEC': 'U',
					'\u1EF0': 'U',
					'\u1EE4': 'U',
					'\u1E72': 'U',
					'\u0172': 'U',
					'\u1E76': 'U',
					'\u1E74': 'U',
					'\u0244': 'U',
					'\u24CB': 'V',
					'\uFF36': 'V',
					'\u1E7C': 'V',
					'\u1E7E': 'V',
					'\u01B2': 'V',
					'\uA75E': 'V',
					'\u0245': 'V',
					'\uA760': 'VY',
					'\u24CC': 'W',
					'\uFF37': 'W',
					'\u1E80': 'W',
					'\u1E82': 'W',
					'\u0174': 'W',
					'\u1E86': 'W',
					'\u1E84': 'W',
					'\u1E88': 'W',
					'\u2C72': 'W',
					'\u24CD': 'X',
					'\uFF38': 'X',
					'\u1E8A': 'X',
					'\u1E8C': 'X',
					'\u24CE': 'Y',
					'\uFF39': 'Y',
					'\u1EF2': 'Y',
					'\u00DD': 'Y',
					'\u0176': 'Y',
					'\u1EF8': 'Y',
					'\u0232': 'Y',
					'\u1E8E': 'Y',
					'\u0178': 'Y',
					'\u1EF6': 'Y',
					'\u1EF4': 'Y',
					'\u01B3': 'Y',
					'\u024E': 'Y',
					'\u1EFE': 'Y',
					'\u24CF': 'Z',
					'\uFF3A': 'Z',
					'\u0179': 'Z',
					'\u1E90': 'Z',
					'\u017B': 'Z',
					'\u017D': 'Z',
					'\u1E92': 'Z',
					'\u1E94': 'Z',
					'\u01B5': 'Z',
					'\u0224': 'Z',
					'\u2C7F': 'Z',
					'\u2C6B': 'Z',
					'\uA762': 'Z',
					'\u24D0': 'a',
					'\uFF41': 'a',
					'\u1E9A': 'a',
					'\u00E0': 'a',
					'\u00E1': 'a',
					'\u00E2': 'a',
					'\u1EA7': 'a',
					'\u1EA5': 'a',
					'\u1EAB': 'a',
					'\u1EA9': 'a',
					'\u00E3': 'a',
					'\u0101': 'a',
					'\u0103': 'a',
					'\u1EB1': 'a',
					'\u1EAF': 'a',
					'\u1EB5': 'a',
					'\u1EB3': 'a',
					'\u0227': 'a',
					'\u01E1': 'a',
					'\u00E4': 'a',
					'\u01DF': 'a',
					'\u1EA3': 'a',
					'\u00E5': 'a',
					'\u01FB': 'a',
					'\u01CE': 'a',
					'\u0201': 'a',
					'\u0203': 'a',
					'\u1EA1': 'a',
					'\u1EAD': 'a',
					'\u1EB7': 'a',
					'\u1E01': 'a',
					'\u0105': 'a',
					'\u2C65': 'a',
					'\u0250': 'a',
					'\uA733': 'aa',
					'\u00E6': 'ae',
					'\u01FD': 'ae',
					'\u01E3': 'ae',
					'\uA735': 'ao',
					'\uA737': 'au',
					'\uA739': 'av',
					'\uA73B': 'av',
					'\uA73D': 'ay',
					'\u24D1': 'b',
					'\uFF42': 'b',
					'\u1E03': 'b',
					'\u1E05': 'b',
					'\u1E07': 'b',
					'\u0180': 'b',
					'\u0183': 'b',
					'\u0253': 'b',
					'\u24D2': 'c',
					'\uFF43': 'c',
					'\u0107': 'c',
					'\u0109': 'c',
					'\u010B': 'c',
					'\u010D': 'c',
					'\u00E7': 'c',
					'\u1E09': 'c',
					'\u0188': 'c',
					'\u023C': 'c',
					'\uA73F': 'c',
					'\u2184': 'c',
					'\u24D3': 'd',
					'\uFF44': 'd',
					'\u1E0B': 'd',
					'\u010F': 'd',
					'\u1E0D': 'd',
					'\u1E11': 'd',
					'\u1E13': 'd',
					'\u1E0F': 'd',
					'\u0111': 'd',
					'\u018C': 'd',
					'\u0256': 'd',
					'\u0257': 'd',
					'\uA77A': 'd',
					'\u01F3': 'dz',
					'\u01C6': 'dz',
					'\u24D4': 'e',
					'\uFF45': 'e',
					'\u00E8': 'e',
					'\u00E9': 'e',
					'\u00EA': 'e',
					'\u1EC1': 'e',
					'\u1EBF': 'e',
					'\u1EC5': 'e',
					'\u1EC3': 'e',
					'\u1EBD': 'e',
					'\u0113': 'e',
					'\u1E15': 'e',
					'\u1E17': 'e',
					'\u0115': 'e',
					'\u0117': 'e',
					'\u00EB': 'e',
					'\u1EBB': 'e',
					'\u011B': 'e',
					'\u0205': 'e',
					'\u0207': 'e',
					'\u1EB9': 'e',
					'\u1EC7': 'e',
					'\u0229': 'e',
					'\u1E1D': 'e',
					'\u0119': 'e',
					'\u1E19': 'e',
					'\u1E1B': 'e',
					'\u0247': 'e',
					'\u025B': 'e',
					'\u01DD': 'e',
					'\u24D5': 'f',
					'\uFF46': 'f',
					'\u1E1F': 'f',
					'\u0192': 'f',
					'\uA77C': 'f',
					'\u24D6': 'g',
					'\uFF47': 'g',
					'\u01F5': 'g',
					'\u011D': 'g',
					'\u1E21': 'g',
					'\u011F': 'g',
					'\u0121': 'g',
					'\u01E7': 'g',
					'\u0123': 'g',
					'\u01E5': 'g',
					'\u0260': 'g',
					'\uA7A1': 'g',
					'\u1D79': 'g',
					'\uA77F': 'g',
					'\u24D7': 'h',
					'\uFF48': 'h',
					'\u0125': 'h',
					'\u1E23': 'h',
					'\u1E27': 'h',
					'\u021F': 'h',
					'\u1E25': 'h',
					'\u1E29': 'h',
					'\u1E2B': 'h',
					'\u1E96': 'h',
					'\u0127': 'h',
					'\u2C68': 'h',
					'\u2C76': 'h',
					'\u0265': 'h',
					'\u0195': 'hv',
					'\u24D8': 'i',
					'\uFF49': 'i',
					'\u00EC': 'i',
					'\u00ED': 'i',
					'\u00EE': 'i',
					'\u0129': 'i',
					'\u012B': 'i',
					'\u012D': 'i',
					'\u00EF': 'i',
					'\u1E2F': 'i',
					'\u1EC9': 'i',
					'\u01D0': 'i',
					'\u0209': 'i',
					'\u020B': 'i',
					'\u1ECB': 'i',
					'\u012F': 'i',
					'\u1E2D': 'i',
					'\u0268': 'i',
					'\u0131': 'i',
					'\u24D9': 'j',
					'\uFF4A': 'j',
					'\u0135': 'j',
					'\u01F0': 'j',
					'\u0249': 'j',
					'\u24DA': 'k',
					'\uFF4B': 'k',
					'\u1E31': 'k',
					'\u01E9': 'k',
					'\u1E33': 'k',
					'\u0137': 'k',
					'\u1E35': 'k',
					'\u0199': 'k',
					'\u2C6A': 'k',
					'\uA741': 'k',
					'\uA743': 'k',
					'\uA745': 'k',
					'\uA7A3': 'k',
					'\u24DB': 'l',
					'\uFF4C': 'l',
					'\u0140': 'l',
					'\u013A': 'l',
					'\u013E': 'l',
					'\u1E37': 'l',
					'\u1E39': 'l',
					'\u013C': 'l',
					'\u1E3D': 'l',
					'\u1E3B': 'l',
					'\u017F': 'l',
					'\u0142': 'l',
					'\u019A': 'l',
					'\u026B': 'l',
					'\u2C61': 'l',
					'\uA749': 'l',
					'\uA781': 'l',
					'\uA747': 'l',
					'\u01C9': 'lj',
					'\u24DC': 'm',
					'\uFF4D': 'm',
					'\u1E3F': 'm',
					'\u1E41': 'm',
					'\u1E43': 'm',
					'\u0271': 'm',
					'\u026F': 'm',
					'\u24DD': 'n',
					'\uFF4E': 'n',
					'\u01F9': 'n',
					'\u0144': 'n',
					'\u00F1': 'n',
					'\u1E45': 'n',
					'\u0148': 'n',
					'\u1E47': 'n',
					'\u0146': 'n',
					'\u1E4B': 'n',
					'\u1E49': 'n',
					'\u019E': 'n',
					'\u0272': 'n',
					'\u0149': 'n',
					'\uA791': 'n',
					'\uA7A5': 'n',
					'\u01CC': 'nj',
					'\u24DE': 'o',
					'\uFF4F': 'o',
					'\u00F2': 'o',
					'\u00F3': 'o',
					'\u00F4': 'o',
					'\u1ED3': 'o',
					'\u1ED1': 'o',
					'\u1ED7': 'o',
					'\u1ED5': 'o',
					'\u00F5': 'o',
					'\u1E4D': 'o',
					'\u022D': 'o',
					'\u1E4F': 'o',
					'\u014D': 'o',
					'\u1E51': 'o',
					'\u1E53': 'o',
					'\u014F': 'o',
					'\u022F': 'o',
					'\u0231': 'o',
					'\u00F6': 'o',
					'\u022B': 'o',
					'\u1ECF': 'o',
					'\u0151': 'o',
					'\u01D2': 'o',
					'\u020D': 'o',
					'\u020F': 'o',
					'\u01A1': 'o',
					'\u1EDD': 'o',
					'\u1EDB': 'o',
					'\u1EE1': 'o',
					'\u1EDF': 'o',
					'\u1EE3': 'o',
					'\u1ECD': 'o',
					'\u1ED9': 'o',
					'\u01EB': 'o',
					'\u01ED': 'o',
					'\u00F8': 'o',
					'\u01FF': 'o',
					'\u0254': 'o',
					'\uA74B': 'o',
					'\uA74D': 'o',
					'\u0275': 'o',
					'\u01A3': 'oi',
					'\u0223': 'ou',
					'\uA74F': 'oo',
					'\u24DF': 'p',
					'\uFF50': 'p',
					'\u1E55': 'p',
					'\u1E57': 'p',
					'\u01A5': 'p',
					'\u1D7D': 'p',
					'\uA751': 'p',
					'\uA753': 'p',
					'\uA755': 'p',
					'\u24E0': 'q',
					'\uFF51': 'q',
					'\u024B': 'q',
					'\uA757': 'q',
					'\uA759': 'q',
					'\u24E1': 'r',
					'\uFF52': 'r',
					'\u0155': 'r',
					'\u1E59': 'r',
					'\u0159': 'r',
					'\u0211': 'r',
					'\u0213': 'r',
					'\u1E5B': 'r',
					'\u1E5D': 'r',
					'\u0157': 'r',
					'\u1E5F': 'r',
					'\u024D': 'r',
					'\u027D': 'r',
					'\uA75B': 'r',
					'\uA7A7': 'r',
					'\uA783': 'r',
					'\u24E2': 's',
					'\uFF53': 's',
					'\u00DF': 's',
					'\u015B': 's',
					'\u1E65': 's',
					'\u015D': 's',
					'\u1E61': 's',
					'\u0161': 's',
					'\u1E67': 's',
					'\u1E63': 's',
					'\u1E69': 's',
					'\u0219': 's',
					'\u015F': 's',
					'\u023F': 's',
					'\uA7A9': 's',
					'\uA785': 's',
					'\u1E9B': 's',
					'\u24E3': 't',
					'\uFF54': 't',
					'\u1E6B': 't',
					'\u1E97': 't',
					'\u0165': 't',
					'\u1E6D': 't',
					'\u021B': 't',
					'\u0163': 't',
					'\u1E71': 't',
					'\u1E6F': 't',
					'\u0167': 't',
					'\u01AD': 't',
					'\u0288': 't',
					'\u2C66': 't',
					'\uA787': 't',
					'\uA729': 'tz',
					'\u24E4': 'u',
					'\uFF55': 'u',
					'\u00F9': 'u',
					'\u00FA': 'u',
					'\u00FB': 'u',
					'\u0169': 'u',
					'\u1E79': 'u',
					'\u016B': 'u',
					'\u1E7B': 'u',
					'\u016D': 'u',
					'\u00FC': 'u',
					'\u01DC': 'u',
					'\u01D8': 'u',
					'\u01D6': 'u',
					'\u01DA': 'u',
					'\u1EE7': 'u',
					'\u016F': 'u',
					'\u0171': 'u',
					'\u01D4': 'u',
					'\u0215': 'u',
					'\u0217': 'u',
					'\u01B0': 'u',
					'\u1EEB': 'u',
					'\u1EE9': 'u',
					'\u1EEF': 'u',
					'\u1EED': 'u',
					'\u1EF1': 'u',
					'\u1EE5': 'u',
					'\u1E73': 'u',
					'\u0173': 'u',
					'\u1E77': 'u',
					'\u1E75': 'u',
					'\u0289': 'u',
					'\u24E5': 'v',
					'\uFF56': 'v',
					'\u1E7D': 'v',
					'\u1E7F': 'v',
					'\u028B': 'v',
					'\uA75F': 'v',
					'\u028C': 'v',
					'\uA761': 'vy',
					'\u24E6': 'w',
					'\uFF57': 'w',
					'\u1E81': 'w',
					'\u1E83': 'w',
					'\u0175': 'w',
					'\u1E87': 'w',
					'\u1E85': 'w',
					'\u1E98': 'w',
					'\u1E89': 'w',
					'\u2C73': 'w',
					'\u24E7': 'x',
					'\uFF58': 'x',
					'\u1E8B': 'x',
					'\u1E8D': 'x',
					'\u24E8': 'y',
					'\uFF59': 'y',
					'\u1EF3': 'y',
					'\u00FD': 'y',
					'\u0177': 'y',
					'\u1EF9': 'y',
					'\u0233': 'y',
					'\u1E8F': 'y',
					'\u00FF': 'y',
					'\u1EF7': 'y',
					'\u1E99': 'y',
					'\u1EF5': 'y',
					'\u01B4': 'y',
					'\u024F': 'y',
					'\u1EFF': 'y',
					'\u24E9': 'z',
					'\uFF5A': 'z',
					'\u017A': 'z',
					'\u1E91': 'z',
					'\u017C': 'z',
					'\u017E': 'z',
					'\u1E93': 'z',
					'\u1E95': 'z',
					'\u01B6': 'z',
					'\u0225': 'z',
					'\u0240': 'z',
					'\u2C6C': 'z',
					'\uA763': 'z',
					'\u0386': '\u0391',
					'\u0388': '\u0395',
					'\u0389': '\u0397',
					'\u038A': '\u0399',
					'\u03AA': '\u0399',
					'\u038C': '\u039F',
					'\u038E': '\u03A5',
					'\u03AB': '\u03A5',
					'\u038F': '\u03A9',
					'\u03AC': '\u03B1',
					'\u03AD': '\u03B5',
					'\u03AE': '\u03B7',
					'\u03AF': '\u03B9',
					'\u03CA': '\u03B9',
					'\u0390': '\u03B9',
					'\u03CC': '\u03BF',
					'\u03CD': '\u03C5',
					'\u03CB': '\u03C5',
					'\u03B0': '\u03C5',
					'\u03C9': '\u03C9',
					'\u03C2': '\u03C3'
				};

				return diacritics;
			});

			S2.define('select2/data/base', [
				'../utils'
			], function(Utils) {
				function BaseAdapter($element, options) {
					BaseAdapter.__super__.constructor.call(this);
				}

				Utils.Extend(BaseAdapter, Utils.Observable);

				BaseAdapter.prototype.current = function(callback) {
					throw new Error('The `current` method must be defined in child classes.');
				};

				BaseAdapter.prototype.query = function(params, callback) {
					throw new Error('The `query` method must be defined in child classes.');
				};

				BaseAdapter.prototype.bind = function(container, $container) {
					// Can be implemented in subclasses
				};

				BaseAdapter.prototype.destroy = function() {
					// Can be implemented in subclasses
				};

				BaseAdapter.prototype.generateResultId = function(container, data) {
					var id = container.id + '-result-';

					id += Utils.generateChars(4);

					if (data.id != null) {
						id += '-' + data.id.toString();
					} else {
						id += '-' + Utils.generateChars(4);
					}
					return id;
				};

				return BaseAdapter;
			});

			S2.define('select2/data/select', [
				'./base',
				'../utils',
				'jquery'
			], function(BaseAdapter, Utils, $) {
				function SelectAdapter($element, options) {
					this.$element = $element;
					this.options = options;

					SelectAdapter.__super__.constructor.call(this);
				}

				Utils.Extend(SelectAdapter, BaseAdapter);

				SelectAdapter.prototype.current = function(callback) {
					var data = [];
					var self = this;

					this.$element.find(':selected').each(function() {
						var $option = $(this);

						var option = self.item($option);

						data.push(option);
					});

					callback(data);
				};

				SelectAdapter.prototype.select = function(data) {
					var self = this;

					data.selected = true;

					// If data.element is a DOM node, use it instead
					if ($(data.element).is('option')) {
						data.element.selected = true;

						this.$element.trigger('change');

						return;
					}

					if (this.$element.prop('multiple')) {
						this.current(function(currentData) {
							var val = [];

							data = [data];
							data.push.apply(data, currentData);

							for (var d = 0; d < data.length; d++) {
								var id = data[d].id;

								if ($.inArray(id, val) === -1) {
									val.push(id);
								}
							}

							self.$element.val(val);
							self.$element.trigger('change');
						});
					} else {
						var val = data.id;

						this.$element.val(val);
						this.$element.trigger('change');
					}
				};

				SelectAdapter.prototype.unselect = function(data) {
					var self = this;

					if (!this.$element.prop('multiple')) {
						return;
					}

					data.selected = false;

					if ($(data.element).is('option')) {
						data.element.selected = false;

						this.$element.trigger('change');

						return;
					}

					this.current(function(currentData) {
						var val = [];

						for (var d = 0; d < currentData.length; d++) {
							var id = currentData[d].id;

							if (id !== data.id && $.inArray(id, val) === -1) {
								val.push(id);
							}
						}

						self.$element.val(val);

						self.$element.trigger('change');
					});
				};

				SelectAdapter.prototype.bind = function(container, $container) {
					var self = this;

					this.container = container;

					container.on('select', function(params) {
						self.select(params.data);
					});

					container.on('unselect', function(params) {
						self.unselect(params.data);
					});
				};

				SelectAdapter.prototype.destroy = function() {
					// Remove anything added to child elements
					this.$element.find('*').each(function() {
						// Remove any custom data set by Select2
						$.removeData(this, 'data');
					});
				};

				SelectAdapter.prototype.query = function(params, callback) {
					var data = [];
					var self = this;

					var $options = this.$element.children();

					$options.each(function() {
						var $option = $(this);

						if (!$option.is('option') && !$option.is('optgroup')) {
							return;
						}

						var option = self.item($option);

						var matches = self.matches(params, option);

						if (matches !== null) {
							data.push(matches);
						}
					});

					callback({
						results: data
					});
				};

				SelectAdapter.prototype.addOptions = function($options) {
					Utils.appendMany(this.$element, $options);
				};

				SelectAdapter.prototype.option = function(data) {
					var option;

					if (data.children) {
						option = document.createElement('optgroup');
						option.label = data.text;
					} else {
						option = document.createElement('option');

						if (option.textContent !== undefined) {
							option.textContent = data.text;
						} else {
							option.innerText = data.text;
						}
					}

					if (data.id) {
						option.value = data.id;
					}

					if (data.disabled) {
						option.disabled = true;
					}

					if (data.selected) {
						option.selected = true;
					}

					if (data.title) {
						option.title = data.title;
					}

					var $option = $(option);

					var normalizedData = this._normalizeItem(data);
					normalizedData.element = option;

					// Override the option's data with the combined data
					$.data(option, 'data', normalizedData);

					return $option;
				};

				SelectAdapter.prototype.item = function($option) {
					var data = {};

					data = $.data($option[0], 'data');

					if (data != null) {
						return data;
					}

					if ($option.is('option')) {
						data = {
							id: $option.val(),
							text: $option.text(),
							disabled: $option.prop('disabled'),
							selected: $option.prop('selected'),
							title: $option.prop('title')
						};
					} else if ($option.is('optgroup')) {
						data = {
							text: $option.prop('label'),
							children: [],
							title: $option.prop('title')
						};

						var $children = $option.children('option');
						var children = [];

						for (var c = 0; c < $children.length; c++) {
							var $child = $($children[c]);

							var child = this.item($child);

							children.push(child);
						}

						data.children = children;
					}

					data = this._normalizeItem(data);
					data.element = $option[0];

					$.data($option[0], 'data', data);

					return data;
				};

				SelectAdapter.prototype._normalizeItem = function(item) {
					if (!$.isPlainObject(item)) {
						item = {
							id: item,
							text: item
						};
					}

					item = $.extend({}, {
						text: ''
					}, item);

					var defaults = {
						selected: false,
						disabled: false
					};

					if (item.id != null) {
						item.id = item.id.toString();
					}

					if (item.text != null) {
						item.text = item.text.toString();
					}

					if (item._resultId == null && item.id && this.container != null) {
						item._resultId = this.generateResultId(this.container, item);
					}

					return $.extend({}, defaults, item);
				};

				SelectAdapter.prototype.matches = function(params, data) {
					var matcher = this.options.get('matcher');

					return matcher(params, data);
				};

				return SelectAdapter;
			});

			S2.define('select2/data/array', [
				'./select',
				'../utils',
				'jquery'
			], function(SelectAdapter, Utils, $) {
				function ArrayAdapter($element, options) {
					var data = options.get('data') || [];

					ArrayAdapter.__super__.constructor.call(this, $element, options);

					this.addOptions(this.convertToOptions(data));
				}

				Utils.Extend(ArrayAdapter, SelectAdapter);

				ArrayAdapter.prototype.select = function(data) {
					var $option = this.$element.find('option').filter(function(i, elm) {
						return elm.value == data.id.toString();
					});

					if ($option.length === 0) {
						$option = this.option(data);

						this.addOptions($option);
					}

					ArrayAdapter.__super__.select.call(this, data);
				};

				ArrayAdapter.prototype.convertToOptions = function(data) {
					var self = this;

					var $existing = this.$element.find('option');
					var existingIds = $existing.map(function() {
						return self.item($(this)).id;
					}).get();

					var $options = [];

					// Filter out all items except for the one passed in the argument

					function onlyItem(item) {
						return function() {
							return $(this).val() == item.id;
						};
					}

					for (var d = 0; d < data.length; d++) {
						var item = this._normalizeItem(data[d]);

						// Skip items which were pre-loaded, only merge the data
						if ($.inArray(item.id, existingIds) >= 0) {
							var $existingOption = $existing.filter(onlyItem(item));

							var existingData = this.item($existingOption);
							var newData = $.extend(true, {}, item, existingData);

							var $newOption = this.option(newData);

							$existingOption.replaceWith($newOption);

							continue;
						}

						var $option = this.option(item);

						if (item.children) {
							var $children = this.convertToOptions(item.children);

							Utils.appendMany($option, $children);
						}

						$options.push($option);
					}

					return $options;
				};

				return ArrayAdapter;
			});

			S2.define('select2/data/ajax', [
				'./array',
				'../utils',
				'jquery'
			], function(ArrayAdapter, Utils, $) {
				function AjaxAdapter($element, options) {
					this.ajaxOptions = this._applyDefaults(options.get('ajax'));

					if (this.ajaxOptions.processResults != null) {
						this.processResults = this.ajaxOptions.processResults;
					}

					AjaxAdapter.__super__.constructor.call(this, $element, options);
				}

				Utils.Extend(AjaxAdapter, ArrayAdapter);

				AjaxAdapter.prototype._applyDefaults = function(options) {
					var defaults = {
						data: function(params) {
							return $.extend({}, params, {
								q: params.term
							});
						},
						transport: function(params, success, failure) {
							var $request = $.ajax(params);

							$request.then(success);
							$request.fail(failure);

							return $request;
						}
					};

					return $.extend({}, defaults, options, true);
				};

				AjaxAdapter.prototype.processResults = function(results) {
					return results;
				};

				AjaxAdapter.prototype.query = function(params, callback) {
					var matches = [];
					var self = this;

					if (this._request != null) {
						// JSONP requests cannot always be aborted
						if ($.isFunction(this._request.abort)) {
							this._request.abort();
						}

						this._request = null;
					}

					var options = $.extend({
						type: 'GET'
					}, this.ajaxOptions);

					if (typeof options.url === 'function') {
						options.url = options.url.call(this.$element, params);
					}

					if (typeof options.data === 'function') {
						options.data = options.data.call(this.$element, params);
					}

					function request() {
						var $request = options.transport(options, function(data) {
							var results = self.processResults(data, params);

							if (self.options.get('debug') && window.console && console.error) {
								// Check to make sure that the response included a `results` key.
								if (!results || !results.results || !$.isArray(results.results)) {
									console.error(
										'Select2: The AJAX results did not return an array in the ' +
										'`results` key of the response.'
									);
								}
							}

							callback(results);
						}, function() {
							// Attempt to detect if a request was aborted
							// Only works if the transport exposes a status property
							if ($request.status && $request.status === '0') {
								return;
							}

							self.trigger('results:message', {
								message: 'errorLoading'
							});
						});

						self._request = $request;
					}

					if (this.ajaxOptions.delay && params.term != null) {
						if (this._queryTimeout) {
							window.clearTimeout(this._queryTimeout);
						}

						this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
					} else {
						request();
					}
				};

				return AjaxAdapter;
			});

			S2.define('select2/data/tags', [
				'jquery'
			], function($) {
				function Tags(decorated, $element, options) {
					var tags = options.get('tags');

					var createTag = options.get('createTag');

					if (createTag !== undefined) {
						this.createTag = createTag;
					}

					var insertTag = options.get('insertTag');

					if (insertTag !== undefined) {
						this.insertTag = insertTag;
					}

					decorated.call(this, $element, options);

					if ($.isArray(tags)) {
						for (var t = 0; t < tags.length; t++) {
							var tag = tags[t];
							var item = this._normalizeItem(tag);

							var $option = this.option(item);

							this.$element.append($option);
						}
					}
				}

				Tags.prototype.query = function(decorated, params, callback) {
					var self = this;

					this._removeOldTags();

					if (params.term == null || params.page != null) {
						decorated.call(this, params, callback);
						return;
					}

					function wrapper(obj, child) {
						var data = obj.results;

						for (var i = 0; i < data.length; i++) {
							var option = data[i];

							var checkChildren = (
								option.children != null && !wrapper({
									results: option.children
								}, true)
							);

							var checkText = option.text === params.term;

							if (checkText || checkChildren) {
								if (child) {
									return false;
								}

								obj.data = data;
								callback(obj);

								return;
							}
						}

						if (child) {
							return true;
						}

						var tag = self.createTag(params);

						if (tag != null) {
							var $option = self.option(tag);
							$option.attr('data-select2-tag', true);

							self.addOptions([$option]);

							self.insertTag(data, tag);
						}

						obj.results = data;

						callback(obj);
					}

					decorated.call(this, params, wrapper);
				};

				Tags.prototype.createTag = function(decorated, params) {
					var term = $.trim(params.term);

					if (term === '') {
						return null;
					}

					return {
						id: term,
						text: term
					};
				};

				Tags.prototype.insertTag = function(_, data, tag) {
					data.unshift(tag);
				};

				Tags.prototype._removeOldTags = function(_) {
					var tag = this._lastTag;

					var $options = this.$element.find('option[data-select2-tag]');

					$options.each(function() {
						if (this.selected) {
							return;
						}

						$(this).remove();
					});
				};

				return Tags;
			});

			S2.define('select2/data/tokenizer', [
				'jquery'
			], function($) {
				function Tokenizer(decorated, $element, options) {
					var tokenizer = options.get('tokenizer');

					if (tokenizer !== undefined) {
						this.tokenizer = tokenizer;
					}

					decorated.call(this, $element, options);
				}

				Tokenizer.prototype.bind = function(decorated, container, $container) {
					decorated.call(this, container, $container);

					this.$search = container.dropdown.$search || container.selection.$search ||
						$container.find('.select2-search__field');
				};

				Tokenizer.prototype.query = function(decorated, params, callback) {
					var self = this;

					function createAndSelect(data) {
						// Normalize the data object so we can use it for checks
						var item = self._normalizeItem(data);

						// Check if the data object already exists as a tag
						// Select it if it doesn't
						var $existingOptions = self.$element.find('option').filter(function() {
							return $(this).val() === item.id;
						});

						// If an existing option wasn't found for it, create the option
						if (!$existingOptions.length) {
							var $option = self.option(item);
							$option.attr('data-select2-tag', true);

							self._removeOldTags();
							self.addOptions([$option]);
						}

						// Select the item, now that we know there is an option for it
						select(item);
					}

					function select(data) {
						self.trigger('select', {
							data: data
						});
					}

					params.term = params.term || '';

					var tokenData = this.tokenizer(params, this.options, createAndSelect);

					if (tokenData.term !== params.term) {
						// Replace the search term if we have the search box
						if (this.$search.length) {
							this.$search.val(tokenData.term);
							this.$search.focus();
						}

						params.term = tokenData.term;
					}

					decorated.call(this, params, callback);
				};

				Tokenizer.prototype.tokenizer = function(_, params, options, callback) {
					var separators = options.get('tokenSeparators') || [];
					var term = params.term;
					var i = 0;

					var createTag = this.createTag || function(params) {
						return {
							id: params.term,
							text: params.term
						};
					};

					while (i < term.length) {
						var termChar = term[i];

						if ($.inArray(termChar, separators) === -1) {
							i++;

							continue;
						}

						var part = term.substr(0, i);
						var partParams = $.extend({}, params, {
							term: part
						});

						var data = createTag(partParams);

						if (data == null) {
							i++;
							continue;
						}

						callback(data);

						// Reset the term to not include the tokenized portion
						term = term.substr(i + 1) || '';
						i = 0;
					}

					return {
						term: term
					};
				};

				return Tokenizer;
			});

			S2.define('select2/data/minimumInputLength', [

			], function() {
				function MinimumInputLength(decorated, $e, options) {
					this.minimumInputLength = options.get('minimumInputLength');

					decorated.call(this, $e, options);
				}

				MinimumInputLength.prototype.query = function(decorated, params, callback) {
					params.term = params.term || '';

					if (params.term.length < this.minimumInputLength) {
						this.trigger('results:message', {
							message: 'inputTooShort',
							args: {
								minimum: this.minimumInputLength,
								input: params.term,
								params: params
							}
						});

						return;
					}

					decorated.call(this, params, callback);
				};

				return MinimumInputLength;
			});

			S2.define('select2/data/maximumInputLength', [

			], function() {
				function MaximumInputLength(decorated, $e, options) {
					this.maximumInputLength = options.get('maximumInputLength');

					decorated.call(this, $e, options);
				}

				MaximumInputLength.prototype.query = function(decorated, params, callback) {
					params.term = params.term || '';

					if (this.maximumInputLength > 0 &&
						params.term.length > this.maximumInputLength) {
						this.trigger('results:message', {
							message: 'inputTooLong',
							args: {
								maximum: this.maximumInputLength,
								input: params.term,
								params: params
							}
						});

						return;
					}

					decorated.call(this, params, callback);
				};

				return MaximumInputLength;
			});

			S2.define('select2/data/maximumSelectionLength', [

			], function() {
				function MaximumSelectionLength(decorated, $e, options) {
					this.maximumSelectionLength = options.get('maximumSelectionLength');

					decorated.call(this, $e, options);
				}

				MaximumSelectionLength.prototype.query =
					function(decorated, params, callback) {
						var self = this;

						this.current(function(currentData) {
							var count = currentData != null ? currentData.length : 0;
							if (self.maximumSelectionLength > 0 &&
								count >= self.maximumSelectionLength) {
								self.trigger('results:message', {
									message: 'maximumSelected',
									args: {
										maximum: self.maximumSelectionLength
									}
								});
								return;
							}
							decorated.call(self, params, callback);
						});
					};

				return MaximumSelectionLength;
			});

			S2.define('select2/dropdown', [
				'jquery',
				'./utils'
			], function($, Utils) {
				function Dropdown($element, options) {
					this.$element = $element;
					this.options = options;

					Dropdown.__super__.constructor.call(this);
				}

				Utils.Extend(Dropdown, Utils.Observable);

				Dropdown.prototype.render = function() {
					var $dropdown = $(
						'<span class="select2-dropdown">' +
						'<span class="select2-results"></span>' +
						'</span>'
					);

					$dropdown.attr('dir', this.options.get('dir'));

					this.$dropdown = $dropdown;

					return $dropdown;
				};

				Dropdown.prototype.bind = function() {
					// Should be implemented in subclasses
				};

				Dropdown.prototype.position = function($dropdown, $container) {
					// Should be implmented in subclasses
				};

				Dropdown.prototype.destroy = function() {
					// Remove the dropdown from the DOM
					this.$dropdown.remove();
				};

				return Dropdown;
			});

			S2.define('select2/dropdown/search', [
				'jquery',
				'../utils'
			], function($, Utils) {
				function Search() {}

				Search.prototype.render = function(decorated) {
					var $rendered = decorated.call(this);

					var $search = $(
						'<span class="select2-search select2-search--dropdown">' +
						'<input class="select2-search__field" type="search" tabindex="-1"' +
						' autocomplete="off" autocorrect="off" autocapitalize="off"' +
						' spellcheck="false" role="textbox" />' +
						'</span>'
					);

					this.$searchContainer = $search;
					this.$search = $search.find('input');

					$rendered.prepend($search);

					return $rendered;
				};

				Search.prototype.bind = function(decorated, container, $container) {
					var self = this;

					decorated.call(this, container, $container);

					this.$search.on('keydown', function(evt) {
						self.trigger('keypress', evt);

						self._keyUpPrevented = evt.isDefaultPrevented();
					});

					// Workaround for browsers which do not support the `input` event
					// This will prevent double-triggering of events for browsers which support
					// both the `keyup` and `input` events.
					this.$search.on('input', function(evt) {
						// Unbind the duplicated `keyup` event
						$(this).off('keyup');
					});

					this.$search.on('keyup input', function(evt) {
						self.handleSearch(evt);
					});

					container.on('open', function() {
						self.$search.attr('tabindex', 0);

						self.$search.focus();

						window.setTimeout(function() {
							self.$search.focus();
						}, 0);
					});

					container.on('close', function() {
						self.$search.attr('tabindex', -1);

						self.$search.val('');
					});

					container.on('focus', function() {
						if (container.isOpen()) {
							self.$search.focus();
						}
					});

					container.on('results:all', function(params) {
						if (params.query.term == null || params.query.term === '') {
							var showSearch = self.showSearch(params);

							if (showSearch) {
								self.$searchContainer.removeClass('select2-search--hide');
							} else {
								self.$searchContainer.addClass('select2-search--hide');
							}
						}
					});
				};

				Search.prototype.handleSearch = function(evt) {
					if (!this._keyUpPrevented) {
						var input = this.$search.val();

						this.trigger('query', {
							term: input
						});
					}

					this._keyUpPrevented = false;
				};

				Search.prototype.showSearch = function(_, params) {
					return true;
				};

				return Search;
			});

			S2.define('select2/dropdown/hidePlaceholder', [

			], function() {
				function HidePlaceholder(decorated, $element, options, dataAdapter) {
					this.placeholder = this.normalizePlaceholder(options.get('placeholder'));

					decorated.call(this, $element, options, dataAdapter);
				}

				HidePlaceholder.prototype.append = function(decorated, data) {
					data.results = this.removePlaceholder(data.results);

					decorated.call(this, data);
				};

				HidePlaceholder.prototype.normalizePlaceholder = function(_, placeholder) {
					if (typeof placeholder === 'string') {
						placeholder = {
							id: '',
							text: placeholder
						};
					}

					return placeholder;
				};

				HidePlaceholder.prototype.removePlaceholder = function(_, data) {
					var modifiedData = data.slice(0);

					for (var d = data.length - 1; d >= 0; d--) {
						var item = data[d];

						if (this.placeholder.id === item.id) {
							modifiedData.splice(d, 1);
						}
					}

					return modifiedData;
				};

				return HidePlaceholder;
			});

			S2.define('select2/dropdown/infiniteScroll', [
				'jquery'
			], function($) {
				function InfiniteScroll(decorated, $element, options, dataAdapter) {
					this.lastParams = {};

					decorated.call(this, $element, options, dataAdapter);

					this.$loadingMore = this.createLoadingMore();
					this.loading = false;
				}

				InfiniteScroll.prototype.append = function(decorated, data) {
					this.$loadingMore.remove();
					this.loading = false;

					decorated.call(this, data);

					if (this.showLoadingMore(data)) {
						this.$results.append(this.$loadingMore);
					}
				};

				InfiniteScroll.prototype.bind = function(decorated, container, $container) {
					var self = this;

					decorated.call(this, container, $container);

					container.on('query', function(params) {
						self.lastParams = params;
						self.loading = true;
					});

					container.on('query:append', function(params) {
						self.lastParams = params;
						self.loading = true;
					});

					this.$results.on('scroll', function() {
						var isLoadMoreVisible = $.contains(
							document.documentElement,
							self.$loadingMore[0]
						);

						if (self.loading || !isLoadMoreVisible) {
							return;
						}

						var currentOffset = self.$results.offset().top +
							self.$results.outerHeight(false);
						var loadingMoreOffset = self.$loadingMore.offset().top +
							self.$loadingMore.outerHeight(false);

						if (currentOffset + 50 >= loadingMoreOffset) {
							self.loadMore();
						}
					});
				};

				InfiniteScroll.prototype.loadMore = function() {
					this.loading = true;

					var params = $.extend({}, {
						page: 1
					}, this.lastParams);

					params.page++;

					this.trigger('query:append', params);
				};

				InfiniteScroll.prototype.showLoadingMore = function(_, data) {
					return data.pagination && data.pagination.more;
				};

				InfiniteScroll.prototype.createLoadingMore = function() {
					var $option = $(
						'<li ' +
						'class="select2-results__option select2-results__option--load-more"' +
						'role="treeitem" aria-disabled="true"></li>'
					);

					var message = this.options.get('translations').get('loadingMore');

					$option.html(message(this.lastParams));

					return $option;
				};

				return InfiniteScroll;
			});

			S2.define('select2/dropdown/attachBody', [
				'jquery',
				'../utils'
			], function($, Utils) {
				function AttachBody(decorated, $element, options) {
					this.$dropdownParent = options.get('dropdownParent') || $(document.body);

					decorated.call(this, $element, options);
				}

				AttachBody.prototype.bind = function(decorated, container, $container) {
					var self = this;

					var setupResultsEvents = false;

					decorated.call(this, container, $container);

					container.on('open', function() {
						self._showDropdown();
						self._attachPositioningHandler(container);

						if (!setupResultsEvents) {
							setupResultsEvents = true;

							container.on('results:all', function() {
								self._positionDropdown();
								self._resizeDropdown();
							});

							container.on('results:append', function() {
								self._positionDropdown();
								self._resizeDropdown();
							});
						}
					});

					container.on('close', function() {
						self._hideDropdown();
						self._detachPositioningHandler(container);
					});

					this.$dropdownContainer.on('mousedown', function(evt) {
						evt.stopPropagation();
					});
				};

				AttachBody.prototype.destroy = function(decorated) {
					decorated.call(this);

					this.$dropdownContainer.remove();
				};

				AttachBody.prototype.position = function(decorated, $dropdown, $container) {
					// Clone all of the container classes
					$dropdown.attr('class', $container.attr('class'));

					$dropdown.removeClass('select2');
					$dropdown.addClass('select2-container--open');

					$dropdown.css({
						position: 'absolute',
						top: -999999
					});

					this.$container = $container;
				};

				AttachBody.prototype.render = function(decorated) {
					var $container = $('<span></span>');

					var $dropdown = decorated.call(this);
					$container.append($dropdown);

					this.$dropdownContainer = $container;

					return $container;
				};

				AttachBody.prototype._hideDropdown = function(decorated) {
					this.$dropdownContainer.detach();
				};

				AttachBody.prototype._attachPositioningHandler =
					function(decorated, container) {
						var self = this;

						var scrollEvent = 'scroll.select2.' + container.id;
						var resizeEvent = 'resize.select2.' + container.id;
						var orientationEvent = 'orientationchange.select2.' + container.id;

						var $watchers = this.$container.parents().filter(Utils.hasScroll);
						$watchers.each(function() {
							$(this).data('select2-scroll-position', {
								x: $(this).scrollLeft(),
								y: $(this).scrollTop()
							});
						});

						$watchers.on(scrollEvent, function(ev) {
							var position = $(this).data('select2-scroll-position');
							$(this).scrollTop(position.y);
						});

						$(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
							function(e) {
								self._positionDropdown();
								self._resizeDropdown();
							});
					};

				AttachBody.prototype._detachPositioningHandler =
					function(decorated, container) {
						var scrollEvent = 'scroll.select2.' + container.id;
						var resizeEvent = 'resize.select2.' + container.id;
						var orientationEvent = 'orientationchange.select2.' + container.id;

						var $watchers = this.$container.parents().filter(Utils.hasScroll);
						$watchers.off(scrollEvent);

						$(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
					};

				AttachBody.prototype._positionDropdown = function() {
					var $window = $(window);

					var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
					var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');

					var newDirection = null;

					var offset = this.$container.offset();

					offset.bottom = offset.top + this.$container.outerHeight(false);

					var container = {
						height: this.$container.outerHeight(false)
					};

					container.top = offset.top;
					container.bottom = offset.top + container.height;

					var dropdown = {
						height: this.$dropdown.outerHeight(false)
					};

					var viewport = {
						top: $window.scrollTop(),
						bottom: $window.scrollTop() + $window.height()
					};

					var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
					var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);

					var css = {
						left: offset.left,
						top: container.bottom
					};

					// Determine what the parent element is to use for calciulating the offset
					var $offsetParent = this.$dropdownParent;

					// For statically positoned elements, we need to get the element
					// that is determining the offset
					if ($offsetParent.css('position') === 'static') {
						$offsetParent = $offsetParent.offsetParent();
					}

					var parentOffset = $offsetParent.offset();

					css.top -= parentOffset.top;
					css.left -= parentOffset.left;

					if (!isCurrentlyAbove && !isCurrentlyBelow) {
						newDirection = 'below';
					}

					if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
						newDirection = 'above';
					} else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
						newDirection = 'below';
					}

					if (newDirection == 'above' ||
						(isCurrentlyAbove && newDirection !== 'below')) {
						css.top = container.top - parentOffset.top - dropdown.height;
					}

					if (newDirection != null) {
						this.$dropdown
							.removeClass('select2-dropdown--below select2-dropdown--above')
							.addClass('select2-dropdown--' + newDirection);
						this.$container
							.removeClass('select2-container--below select2-container--above')
							.addClass('select2-container--' + newDirection);
					}

					this.$dropdownContainer.css(css);
				};

				AttachBody.prototype._resizeDropdown = function() {
					var css = {
						width: this.$container.outerWidth(false) + 'px'
					};

					if (this.options.get('dropdownAutoWidth')) {
						css.minWidth = css.width;
						css.position = 'relative';
						css.width = 'auto';
					}

					this.$dropdown.css(css);
				};

				AttachBody.prototype._showDropdown = function(decorated) {
					this.$dropdownContainer.appendTo(this.$dropdownParent);

					this._positionDropdown();
					this._resizeDropdown();
				};

				return AttachBody;
			});

			S2.define('select2/dropdown/minimumResultsForSearch', [

			], function() {
				function countResults(data) {
					var count = 0;

					for (var d = 0; d < data.length; d++) {
						var item = data[d];

						if (item.children) {
							count += countResults(item.children);
						} else {
							count++;
						}
					}

					return count;
				}

				function MinimumResultsForSearch(decorated, $element, options, dataAdapter) {
					this.minimumResultsForSearch = options.get('minimumResultsForSearch');

					if (this.minimumResultsForSearch < 0) {
						this.minimumResultsForSearch = Infinity;
					}

					decorated.call(this, $element, options, dataAdapter);
				}

				MinimumResultsForSearch.prototype.showSearch = function(decorated, params) {
					if (countResults(params.data.results) < this.minimumResultsForSearch) {
						return false;
					}

					return decorated.call(this, params);
				};

				return MinimumResultsForSearch;
			});

			S2.define('select2/dropdown/selectOnClose', [

			], function() {
				function SelectOnClose() {}

				SelectOnClose.prototype.bind = function(decorated, container, $container) {
					var self = this;

					decorated.call(this, container, $container);

					container.on('close', function(params) {
						self._handleSelectOnClose(params);
					});
				};

				SelectOnClose.prototype._handleSelectOnClose = function(_, params) {
					if (params && params.originalSelect2Event != null) {
						var event = params.originalSelect2Event;

						// Don't select an item if the close event was triggered from a select or
						// unselect event
						if (event._type === 'select' || event._type === 'unselect') {
							return;
						}
					}

					var $highlightedResults = this.getHighlightedResults();

					// Only select highlighted results
					if ($highlightedResults.length < 1) {
						return;
					}

					var data = $highlightedResults.data('data');

					// Don't re-select already selected resulte
					if (
						(data.element != null && data.element.selected) ||
						(data.element == null && data.selected)
					) {
						return;
					}

					this.trigger('select', {
						data: data
					});
				};

				return SelectOnClose;
			});

			S2.define('select2/dropdown/closeOnSelect', [

			], function() {
				function CloseOnSelect() {}

				CloseOnSelect.prototype.bind = function(decorated, container, $container) {
					var self = this;

					decorated.call(this, container, $container);

					container.on('select', function(evt) {
						self._selectTriggered(evt);
					});

					container.on('unselect', function(evt) {
						self._selectTriggered(evt);
					});
				};

				CloseOnSelect.prototype._selectTriggered = function(_, evt) {
					var originalEvent = evt.originalEvent;

					// Don't close if the control key is being held
					if (originalEvent && originalEvent.ctrlKey) {
						return;
					}

					this.trigger('close', {
						originalEvent: originalEvent,
						originalSelect2Event: evt
					});
				};

				return CloseOnSelect;
			});

			S2.define('select2/i18n/en', [], function() {
				// English
				return {
					errorLoading: function() {
						return ForminatorFront.select2.loaded_error;
					},
					inputTooLong: function(args) {
						var overChars = args.input.length - args.maximum;

						var message = 'Please delete ' + overChars + ' character';

						if (overChars != 1) {
							message += 's';
						}

						return message;
					},
					inputTooShort: function(args) {
						var remainingChars = args.minimum - args.input.length;

						var message = 'Please enter ' + remainingChars + ' or more characters';

						return message;
					},
					loadingMore: function() {
						return ForminatorFront.select2.load_more;
					},
					maximumSelected: function(args) {
						var message = 'You can only select ' + args.maximum + ' item';

						if (args.maximum != 1) {
							message += 's';
						}

						return message;
					},
					noResults: function() {
						return ForminatorFront.select2.no_result_found;
					},
					searching: function() {
						return ForminatorFront.select2.searching;
					}
				};
			});

			S2.define('select2/defaults', [
				'jquery',
				'require',

				'./results',

				'./selection/single',
				'./selection/multiple',
				'./selection/placeholder',
				'./selection/allowClear',
				'./selection/search',
				'./selection/eventRelay',

				'./utils',
				'./translation',
				'./diacritics',

				'./data/select',
				'./data/array',
				'./data/ajax',
				'./data/tags',
				'./data/tokenizer',
				'./data/minimumInputLength',
				'./data/maximumInputLength',
				'./data/maximumSelectionLength',

				'./dropdown',
				'./dropdown/search',
				'./dropdown/hidePlaceholder',
				'./dropdown/infiniteScroll',
				'./dropdown/attachBody',
				'./dropdown/minimumResultsForSearch',
				'./dropdown/selectOnClose',
				'./dropdown/closeOnSelect',

				'./i18n/en'
			], function($, require,

						ResultsList,

						SingleSelection, MultipleSelection, Placeholder, AllowClear,
						SelectionSearch, EventRelay,

						Utils, Translation, DIACRITICS,

						SelectData, ArrayData, AjaxData, Tags, Tokenizer,
						MinimumInputLength, MaximumInputLength, MaximumSelectionLength,

						Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
						AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,

						EnglishTranslation) {
				function Defaults() {
					this.reset();
				}

				Defaults.prototype.apply = function(options) {
					options = $.extend(true, {}, this.defaults, options);

					if (options.dataAdapter == null) {
						if (options.ajax != null) {
							options.dataAdapter = AjaxData;
						} else if (options.data != null) {
							options.dataAdapter = ArrayData;
						} else {
							options.dataAdapter = SelectData;
						}

						if (options.minimumInputLength > 0) {
							options.dataAdapter = Utils.Decorate(
								options.dataAdapter,
								MinimumInputLength
							);
						}

						if (options.maximumInputLength > 0) {
							options.dataAdapter = Utils.Decorate(
								options.dataAdapter,
								MaximumInputLength
							);
						}

						if (options.maximumSelectionLength > 0) {
							options.dataAdapter = Utils.Decorate(
								options.dataAdapter,
								MaximumSelectionLength
							);
						}

						if (options.tags) {
							options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
						}

						if (options.tokenSeparators != null || options.tokenizer != null) {
							options.dataAdapter = Utils.Decorate(
								options.dataAdapter,
								Tokenizer
							);
						}

						if (options.query != null) {
							var Query = require(options.amdBase + 'compat/query');

							options.dataAdapter = Utils.Decorate(
								options.dataAdapter,
								Query
							);
						}

						if (options.initSelection != null) {
							var InitSelection = require(options.amdBase + 'compat/initSelection');

							options.dataAdapter = Utils.Decorate(
								options.dataAdapter,
								InitSelection
							);
						}
					}

					if (options.resultsAdapter == null) {
						options.resultsAdapter = ResultsList;

						if (options.ajax != null) {
							options.resultsAdapter = Utils.Decorate(
								options.resultsAdapter,
								InfiniteScroll
							);
						}

						if (options.placeholder != null) {
							options.resultsAdapter = Utils.Decorate(
								options.resultsAdapter,
								HidePlaceholder
							);
						}

						if (options.selectOnClose) {
							options.resultsAdapter = Utils.Decorate(
								options.resultsAdapter,
								SelectOnClose
							);
						}
					}

					if (options.dropdownAdapter == null) {
						if (options.multiple) {
							options.dropdownAdapter = Dropdown;
						} else {
							var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);

							options.dropdownAdapter = SearchableDropdown;
						}

						if (options.minimumResultsForSearch !== 0) {
							options.dropdownAdapter = Utils.Decorate(
								options.dropdownAdapter,
								MinimumResultsForSearch
							);
						}

						if (options.closeOnSelect) {
							options.dropdownAdapter = Utils.Decorate(
								options.dropdownAdapter,
								CloseOnSelect
							);
						}

						if (
							options.dropdownCssClass != null ||
							options.dropdownCss != null ||
							options.adaptDropdownCssClass != null
						) {
							var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');

							options.dropdownAdapter = Utils.Decorate(
								options.dropdownAdapter,
								DropdownCSS
							);
						}

						options.dropdownAdapter = Utils.Decorate(
							options.dropdownAdapter,
							AttachBody
						);
					}

					if (options.selectionAdapter == null) {
						if (options.multiple) {
							options.selectionAdapter = MultipleSelection;
						} else {
							options.selectionAdapter = SingleSelection;
						}

						// Add the placeholder mixin if a placeholder was specified
						if (options.placeholder != null) {
							options.selectionAdapter = Utils.Decorate(
								options.selectionAdapter,
								Placeholder
							);
						}

						if (options.allowClear) {
							options.selectionAdapter = Utils.Decorate(
								options.selectionAdapter,
								AllowClear
							);
						}

						if (options.multiple) {
							options.selectionAdapter = Utils.Decorate(
								options.selectionAdapter,
								SelectionSearch
							);
						}

						if (
							options.containerCssClass != null ||
							options.containerCss != null ||
							options.adaptContainerCssClass != null
						) {
							var ContainerCSS = require(options.amdBase + 'compat/containerCss');

							options.selectionAdapter = Utils.Decorate(
								options.selectionAdapter,
								ContainerCSS
							);
						}

						options.selectionAdapter = Utils.Decorate(
							options.selectionAdapter,
							EventRelay
						);
					}

					if (typeof options.language === 'string') {
						// Check if the language is specified with a region
						if (options.language.indexOf('-') > 0) {
							// Extract the region information if it is included
							var languageParts = options.language.split('-');
							var baseLanguage = languageParts[0];

							options.language = [options.language, baseLanguage];
						} else {
							options.language = [options.language];
						}
					}

					if ($.isArray(options.language)) {
						var languages = new Translation();
						options.language.push('en');

						var languageNames = options.language;

						for (var l = 0; l < languageNames.length; l++) {
							var name = languageNames[l];
							var language = {};

							try {
								// Try to load it with the original name
								language = Translation.loadPath(name);
							} catch (e) {
								try {
									// If we couldn't load it, check if it wasn't the full path
									name = this.defaults.amdLanguageBase + name;
									language = Translation.loadPath(name);
								} catch (ex) {
									// The translation could not be loaded at all. Sometimes this is
									// because of a configuration problem, other times this can be
									// because of how Select2 helps load all possible translation files.
									if (options.debug && window.console && console.warn) {
										console.warn(
											'Select2: The language file for "' + name + '" could not be ' +
											'automatically loaded. A fallback will be used instead.'
										);
									}

									continue;
								}
							}

							languages.extend(language);
						}

						options.translations = languages;
					} else {
						var baseTranslation = Translation.loadPath(
							this.defaults.amdLanguageBase + 'en'
						);
						var customTranslation = new Translation(options.language);

						customTranslation.extend(baseTranslation);

						options.translations = customTranslation;
					}

					return options;
				};

				Defaults.prototype.reset = function() {
					function stripDiacritics(text) {
						// Used 'uni range + named function' from http://jsperf.com/diacritics/18
						function match(a) {
							return DIACRITICS[a] || a;
						}

						return text.replace(/[^\u0000-\u007E]/g, match);
					}

					function matcher(params, data) {
						// Always return the object if there is nothing to compare
						if ($.trim(params.term) === '') {
							return data;
						}

						// Do a recursive check for options with children
						if (data.children && data.children.length > 0) {
							// Clone the data object if there are children
							// This is required as we modify the object to remove any non-matches
							var match = $.extend(true, {}, data);

							// Check each child of the option
							for (var c = data.children.length - 1; c >= 0; c--) {
								var child = data.children[c];

								var matches = matcher(params, child);

								// If there wasn't a match, remove the object in the array
								if (matches == null) {
									match.children.splice(c, 1);
								}
							}

							// If any children matched, return the new object
							if (match.children.length > 0) {
								return match;
							}

							// If there were no matching children, check just the plain object
							return matcher(params, match);
						}

						var original = stripDiacritics(data.text).toUpperCase();
						var term = stripDiacritics(params.term).toUpperCase();

						// Check if the text contains the term
						if (original.indexOf(term) > -1) {
							return data;
						}

						// If it doesn't contain the term, don't return anything
						return null;
					}

					this.defaults = {
						amdBase: './',
						amdLanguageBase: './i18n/',
						closeOnSelect: true,
						debug: false,
						dropdownAutoWidth: true,
						escapeMarkup: Utils.escapeMarkup,
						language: EnglishTranslation,
						matcher: matcher,
						minimumInputLength: 0,
						maximumInputLength: 0,
						maximumSelectionLength: 0,
						minimumResultsForSearch: 0,
						selectOnClose: false,
						containerCssClass: 'wpmui-select2 :all:',
						dropdownCssClass: 'wpmui-select2',
						sorter: function(data) {
							return data;
						},
						templateResult: function(result) {
							return result.text;
						},
						templateSelection: function(selection) {
							return selection.text;
						},
						theme: 'default',
						width: 'resolve'
					};
				};

				Defaults.prototype.set = function(key, value) {
					var camelKey = $.camelCase(key);

					var data = {};
					data[camelKey] = value;

					var convertedData = Utils._convertData(data);

					$.extend(this.defaults, convertedData);
				};

				var defaults = new Defaults();

				return defaults;
			});

			S2.define('select2/options', [
				'require',
				'jquery',
				'./defaults',
				'./utils'
			], function(require, $, Defaults, Utils) {
				function Options(options, $element) {
					this.options = options;

					if ($element != null) {
						this.fromElement($element);
					}

					this.options = Defaults.apply(this.options);

					if ($element && $element.is('input')) {
						var InputCompat = require(this.get('amdBase') + 'compat/inputData');

						this.options.dataAdapter = Utils.Decorate(
							this.options.dataAdapter,
							InputCompat
						);
					}
				}

				Options.prototype.fromElement = function($e) {
					var excludedData = ['select2'];

					if (this.options.multiple == null) {
						this.options.multiple = $e.prop('multiple');
					}

					if (this.options.disabled == null) {
						this.options.disabled = $e.prop('disabled');
					}

					if (this.options.language == null) {
						if ($e.prop('lang')) {
							this.options.language = $e.prop('lang').toLowerCase();
						} else if ($e.closest('[lang]').prop('lang')) {
							this.options.language = $e.closest('[lang]').prop('lang');
						}
					}

					if (this.options.dir == null) {
						if ($e.prop('dir')) {
							this.options.dir = $e.prop('dir');
						} else if ($e.closest('[dir]').prop('dir')) {
							this.options.dir = $e.closest('[dir]').prop('dir');
						} else {
							this.options.dir = 'ltr';
						}
					}

					$e.prop('disabled', this.options.disabled);
					$e.prop('multiple', this.options.multiple);

					if ($e.data('select2Tags')) {
						if (this.options.debug && window.console && console.warn) {
							console.warn(
								'Select2: The `data-select2-tags` attribute has been changed to ' +
								'use the `data-data` and `data-tags="true"` attributes and will be ' +
								'removed in future versions of Select2.'
							);
						}

						$e.data('data', $e.data('select2Tags'));
						$e.data('tags', true);
					}

					if ($e.data('ajaxUrl')) {
						if (this.options.debug && window.console && console.warn) {
							console.warn(
								'Select2: The `data-ajax-url` attribute has been changed to ' +
								'`data-ajax--url` and support for the old attribute will be removed' +
								' in future versions of Select2.'
							);
						}

						$e.attr('ajax--url', $e.data('ajaxUrl'));
						$e.data('ajax--url', $e.data('ajaxUrl'));
					}

					var dataset = {};

					// Prefer the element's `dataset` attribute if it exists
					// jQuery 1.x does not correctly handle data attributes with multiple dashes
					if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
						dataset = $.extend(true, {}, $e[0].dataset, $e.data());
					} else {
						dataset = $e.data();
					}

					var data = $.extend(true, {}, dataset);

					data = Utils._convertData(data);

					for (var key in data) {
						if ($.inArray(key, excludedData) > -1) {
							continue;
						}

						if ($.isPlainObject(this.options[key])) {
							$.extend(this.options[key], data[key]);
						} else {
							this.options[key] = data[key];
						}
					}

					return this;
				};

				Options.prototype.get = function(key) {
					return this.options[key];
				};

				Options.prototype.set = function(key, val) {
					this.options[key] = val;
				};

				return Options;
			});

			S2.define('select2/core', [
				'jquery',
				'./options',
				'./utils',
				'./keys'
			], function($, Options, Utils, KEYS) {
				var Select2 = function($element, options) {
					if ($element.data('select2') != null) {
						$element.data('select2').destroy();
					}

					this.$element = $element;

					this.id = this._generateId($element);

					options = options || {};

					this.options = new Options(options, $element);

					Select2.__super__.constructor.call(this);

					// Set up the tabindex

					var tabindex = $element.attr('tabindex') || 0;
					$element.data('old-tabindex', tabindex);
					$element.attr('tabindex', '-1');

					// Set up containers and adapters

					var DataAdapter = this.options.get('dataAdapter');
					this.dataAdapter = new DataAdapter($element, this.options);

					var $container = this.render();

					this._placeContainer($container);

					var SelectionAdapter = this.options.get('selectionAdapter');
					this.selection = new SelectionAdapter($element, this.options);
					this.$selection = this.selection.render();

					this.selection.position(this.$selection, $container);

					var DropdownAdapter = this.options.get('dropdownAdapter');
					this.dropdown = new DropdownAdapter($element, this.options);
					this.$dropdown = this.dropdown.render();

					this.dropdown.position(this.$dropdown, $container);

					var ResultsAdapter = this.options.get('resultsAdapter');
					this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
					this.$results = this.results.render();

					this.results.position(this.$results, this.$dropdown);

					// Bind events

					var self = this;

					// Bind the container to all of the adapters
					this._bindAdapters();

					// Register any DOM event handlers
					this._registerDomEvents();

					// Register any internal event handlers
					this._registerDataEvents();
					this._registerSelectionEvents();
					this._registerDropdownEvents();
					this._registerResultsEvents();
					this._registerEvents();

					// Set the initial state
					this.dataAdapter.current(function(initialData) {
						self.trigger('selection:update', {
							data: initialData
						});
					});

					// Hide the original select
					$element.addClass('select2-hidden-accessible');
					$element.attr('aria-hidden', 'true');

					// Synchronize any monitored attributes
					this._syncAttributes();

					$element.data('select2', this);
				};

				Utils.Extend(Select2, Utils.Observable);

				Select2.prototype._generateId = function($element) {
					var id = '';

					if ($element.attr('id') != null) {
						id = $element.attr('id');
					} else if ($element.attr('name') != null) {
						id = $element.attr('name') + '-' + Utils.generateChars(2);
					} else {
						id = Utils.generateChars(4);
					}

					id = id.replace(/(:|\.|\[|\]|,)/g, '');
					id = 'select2-' + id;

					return id;
				};

				Select2.prototype._placeContainer = function($container) {
					$container.insertAfter(this.$element);

					var width = this._resolveWidth(this.$element, this.options.get('width'));

					if (width != null) {
						$container.css('width', width);
					}
				};

				Select2.prototype._resolveWidth = function($element, method) {
					var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;

					if (method == 'resolve') {
						var styleWidth = this._resolveWidth($element, 'style');

						if (styleWidth != null) {
							return styleWidth;
						}

						return this._resolveWidth($element, 'element');
					}

					if (method == 'element') {
						var elementWidth = $element.outerWidth(false);

						if (elementWidth <= 0) {
							return 'auto';
						}

						return elementWidth + 'px';
					}

					if (method == 'style') {
						var style = $element.attr('style');

						if (typeof(style) !== 'string') {
							return null;
						}

						var attrs = style.split(';');

						for (var i = 0, l = attrs.length; i < l; i = i + 1) {
							var attr = attrs[i].replace(/\s/g, '');
							var matches = attr.match(WIDTH);

							if (matches !== null && matches.length >= 1) {
								return matches[1];
							}
						}

						return null;
					}

					return method;
				};

				Select2.prototype._bindAdapters = function() {
					this.dataAdapter.bind(this, this.$container);
					this.selection.bind(this, this.$container);

					this.dropdown.bind(this, this.$container);
					this.results.bind(this, this.$container);
				};

				Select2.prototype._registerDomEvents = function() {
					var self = this;

					this.$element.on('change.select2', function() {
						self.dataAdapter.current(function(data) {
							self.trigger('selection:update', {
								data: data
							});
						});
					});

					this.$element.on('focus.select2', function(evt) {
						self.trigger('focus', evt);
					});

					this._syncA = Utils.bind(this._syncAttributes, this);
					this._syncS = Utils.bind(this._syncSubtree, this);

					if (this.$element[0].attachEvent) {
						this.$element[0].attachEvent('onpropertychange', this._syncA);
					}

					var observer = window.MutationObserver ||
						window.WebKitMutationObserver ||
						window.MozMutationObserver;

					if (observer != null) {
						this._observer = new observer(function(mutations) {
							$.each(mutations, self._syncA);
							$.each(mutations, self._syncS);
						});
						this._observer.observe(this.$element[0], {
							attributes: true,
							childList: true,
							subtree: false
						});
					} else if (this.$element[0].addEventListener) {
						this.$element[0].addEventListener(
							'DOMAttrModified',
							self._syncA,
							false
						);
						this.$element[0].addEventListener(
							'DOMNodeInserted',
							self._syncS,
							false
						);
						this.$element[0].addEventListener(
							'DOMNodeRemoved',
							self._syncS,
							false
						);
					}
				};

				Select2.prototype._registerDataEvents = function() {
					var self = this;

					this.dataAdapter.on('*', function(name, params) {
						self.trigger(name, params);
					});
				};

				Select2.prototype._registerSelectionEvents = function() {
					var self = this;
					var nonRelayEvents = ['toggle', 'focus'];

					this.selection.on('toggle', function() {
						self.toggleDropdown();
					});

					this.selection.on('focus', function(params) {
						self.focus(params);
					});

					this.selection.on('*', function(name, params) {
						if ($.inArray(name, nonRelayEvents) !== -1) {
							return;
						}

						self.trigger(name, params);
					});
				};

				Select2.prototype._registerDropdownEvents = function() {
					var self = this;

					this.dropdown.on('*', function(name, params) {
						self.trigger(name, params);
					});
				};

				Select2.prototype._registerResultsEvents = function() {
					var self = this;

					this.results.on('*', function(name, params) {
						self.trigger(name, params);
					});
				};

				Select2.prototype._registerEvents = function() {
					var self = this;

					this.on('open', function() {
						self.$container.addClass('select2-container--open');
					});

					this.on('close', function() {
						self.$container.removeClass('select2-container--open');
					});

					this.on('enable', function() {
						self.$container.removeClass('select2-container--disabled');
					});

					this.on('disable', function() {
						self.$container.addClass('select2-container--disabled');
					});

					this.on('blur', function() {
						self.$container.removeClass('select2-container--focus');
					});

					this.on('query', function(params) {
						if (!self.isOpen()) {
							self.trigger('open', {});
						}

						this.dataAdapter.query(params, function(data) {
							self.trigger('results:all', {
								data: data,
								query: params
							});
						});
					});

					this.on('query:append', function(params) {
						this.dataAdapter.query(params, function(data) {
							self.trigger('results:append', {
								data: data,
								query: params
							});
						});
					});

					this.on('keypress', function(evt) {
						var key = evt.which;

						if (self.isOpen()) {
							if (key === KEYS.ESC || key === KEYS.TAB ||
								(key === KEYS.UP && evt.altKey)) {
								self.close();

								evt.preventDefault();
							} else if (key === KEYS.ENTER) {
								self.trigger('results:select', {});

								evt.preventDefault();
							} else if ((key === KEYS.SPACE && evt.ctrlKey)) {
								self.trigger('results:toggle', {});

								evt.preventDefault();
							} else if (key === KEYS.UP) {
								self.trigger('results:previous', {});

								evt.preventDefault();
							} else if (key === KEYS.DOWN) {
								self.trigger('results:next', {});

								evt.preventDefault();
							}
						} else {
							if (key === KEYS.ENTER || key === KEYS.SPACE ||
								(key === KEYS.DOWN && evt.altKey)) {
								self.open();

								evt.preventDefault();
							}
						}
					});
				};

				Select2.prototype._syncAttributes = function() {
					this.options.set('disabled', this.$element.prop('disabled'));

					if (this.options.get('disabled')) {
						if (this.isOpen()) {
							this.close();
						}

						this.trigger('disable', {});
					} else {
						this.trigger('enable', {});
					}
				};

				Select2.prototype._syncSubtree = function(evt, mutations) {
					var changed = false;
					var self = this;

					// Ignore any mutation events raised for elements that aren't options or
					// optgroups. This handles the case when the select element is destroyed
					if (
						evt && evt.target && (
							evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
						)
					) {
						return;
					}

					if (!mutations) {
						// If mutation events aren't supported, then we can only assume that the
						// change affected the selections
						changed = true;
					} else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
						for (var n = 0; n < mutations.addedNodes.length; n++) {
							var node = mutations.addedNodes[n];

							if (node.selected) {
								changed = true;
							}
						}
					} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
						changed = true;
					}

					// Only re-pull the data if we think there is a change
					if (changed) {
						this.dataAdapter.current(function(currentData) {
							self.trigger('selection:update', {
								data: currentData
							});
						});
					}
				};

				/**
				 * Override the trigger method to automatically trigger pre-events when
				 * there are events that can be prevented.
				 */
				Select2.prototype.trigger = function(name, args) {
					var actualTrigger = Select2.__super__.trigger;
					var preTriggerMap = {
						'open': 'opening',
						'close': 'closing',
						'select': 'selecting',
						'unselect': 'unselecting'
					};

					if (args === undefined) {
						args = {};
					}

					if (name in preTriggerMap) {
						var preTriggerName = preTriggerMap[name];
						var preTriggerArgs = {
							prevented: false,
							name: name,
							args: args
						};

						actualTrigger.call(this, preTriggerName, preTriggerArgs);

						if (preTriggerArgs.prevented) {
							args.prevented = true;

							return;
						}
					}

					actualTrigger.call(this, name, args);
				};

				Select2.prototype.toggleDropdown = function() {
					if (this.options.get('disabled')) {
						return;
					}

					if (this.isOpen()) {
						this.close();
					} else {
						this.open();
					}
				};

				Select2.prototype.open = function() {
					if (this.isOpen()) {
						return;
					}

					this.trigger('query', {});
				};

				Select2.prototype.close = function() {
					if (!this.isOpen()) {
						return;
					}

					this.trigger('close', {});
				};

				Select2.prototype.isOpen = function() {
					return this.$container.hasClass('select2-container--open');
				};

				Select2.prototype.hasFocus = function() {
					return this.$container.hasClass('select2-container--focus');
				};

				Select2.prototype.focus = function(data) {
					// No need to re-trigger focus events if we are already focused
					if (this.hasFocus()) {
						return;
					}

					this.$container.addClass('select2-container--focus');
					this.trigger('focus', {});
				};

				Select2.prototype.enable = function(args) {
					if (this.options.get('debug') && window.console && console.warn) {
						console.warn(
							'Select2: The `select2("enable")` method has been deprecated and will' +
							' be removed in later Select2 versions. Use $element.prop("disabled")' +
							' instead.'
						);
					}

					if (args == null || args.length === 0) {
						args = [true];
					}

					var disabled = !args[0];

					this.$element.prop('disabled', disabled);
				};

				Select2.prototype.data = function() {
					if (this.options.get('debug') &&
						arguments.length > 0 && window.console && console.warn) {
						console.warn(
							'Select2: Data can no longer be set using `select2("data")`. You ' +
							'should consider setting the value instead using `$element.val()`.'
						);
					}

					var data = [];

					this.dataAdapter.current(function(currentData) {
						data = currentData;
					});

					return data;
				};

				Select2.prototype.val = function(args) {
					if (this.options.get('debug') && window.console && console.warn) {
						console.warn(
							'Select2: The `select2("val")` method has been deprecated and will be' +
							' removed in later Select2 versions. Use $element.val() instead.'
						);
					}

					if (args == null || args.length === 0) {
						return this.$element.val();
					}

					var newVal = args[0];

					if ($.isArray(newVal)) {
						newVal = $.map(newVal, function(obj) {
							return obj.toString();
						});
					}

					this.$element.val(newVal).trigger('change');
				};

				Select2.prototype.destroy = function() {
					this.$container.remove();

					if (this.$element[0].detachEvent) {
						this.$element[0].detachEvent('onpropertychange', this._syncA);
					}

					if (this._observer != null) {
						this._observer.disconnect();
						this._observer = null;
					} else if (this.$element[0].removeEventListener) {
						this.$element[0]
							.removeEventListener('DOMAttrModified', this._syncA, false);
						this.$element[0]
							.removeEventListener('DOMNodeInserted', this._syncS, false);
						this.$element[0]
							.removeEventListener('DOMNodeRemoved', this._syncS, false);
					}

					this._syncA = null;
					this._syncS = null;

					this.$element.off('.select2');
					this.$element.attr('tabindex', this.$element.data('old-tabindex'));

					this.$element.removeClass('select2-hidden-accessible');
					this.$element.attr('aria-hidden', 'false');
					this.$element.removeData('select2');

					this.dataAdapter.destroy();
					this.selection.destroy();
					this.dropdown.destroy();
					this.results.destroy();

					this.dataAdapter = null;
					this.selection = null;
					this.dropdown = null;
					this.results = null;
				};

				Select2.prototype.render = function() {
					var $container = $(
						'<span class="select2 select2-container">' +
						'<span class="selection"></span>' +
						'<span class="dropdown-wrapper" aria-hidden="true"></span>' +
						'</span>'
					);

					$container.attr('dir', this.options.get('dir'));

					this.$container = $container;

					this.$container.addClass('select2-container--' + this.options.get('theme'));

					$container.data('element', this.$element);

					return $container;
				};

				return Select2;
			});

			S2.define('select2/compat/utils', [
				'jquery'
			], function($) {
				function syncCssClasses($dest, $src, adapter) {
					var classes, replacements = [],
						adapted;

					classes = $.trim($dest.attr('class'));

					if (classes) {
						classes = '' + classes; // for IE which returns object

						$(classes.split(/\s+/)).each(function() {
							// Save all Select2 classes
							if (this.indexOf('select2-') === 0) {
								replacements.push(this);
							}
						});
					}

					classes = $.trim($src.attr('class'));

					if (classes) {
						classes = '' + classes; // for IE which returns object

						$(classes.split(/\s+/)).each(function() {
							// Only adapt non-Select2 classes
							if (this.indexOf('select2-') !== 0) {
								adapted = adapter(this);

								if (adapted != null) {
									replacements.push(adapted);
								}
							}
						});
					}

					$dest.attr('class', replacements.join(' '));
				}

				return {
					syncCssClasses: syncCssClasses
				};
			});

			S2.define('select2/compat/containerCss', [
				'jquery',
				'./utils'
			], function($, CompatUtils) {
				// No-op CSS adapter that discards all classes by default
				function _containerAdapter(clazz) {
					return null;
				}

				function ContainerCSS() {}

				ContainerCSS.prototype.render = function(decorated) {
					var $container = decorated.call(this);

					var containerCssClass = this.options.get('containerCssClass') || '';

					if ($.isFunction(containerCssClass)) {
						containerCssClass = containerCssClass(this.$element);
					}

					var containerCssAdapter = this.options.get('adaptContainerCssClass');
					containerCssAdapter = containerCssAdapter || _containerAdapter;

					if (containerCssClass.indexOf(':all:') !== -1) {
						containerCssClass = containerCssClass.replace(':all:', '');

						var _cssAdapter = containerCssAdapter;

						containerCssAdapter = function(clazz) {
							var adapted = _cssAdapter(clazz);

							if (adapted != null) {
								// Append the old one along with the adapted one
								return adapted + ' ' + clazz;
							}

							return clazz;
						};
					}

					var containerCss = this.options.get('containerCss') || {};

					if ($.isFunction(containerCss)) {
						containerCss = containerCss(this.$element);
					}

					CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter);

					$container.css(containerCss);
					$container.addClass(containerCssClass);

					return $container;
				};

				return ContainerCSS;
			});

			S2.define('select2/compat/dropdownCss', [
				'jquery',
				'./utils'
			], function($, CompatUtils) {
				// No-op CSS adapter that discards all classes by default
				function _dropdownAdapter(clazz) {
					return null;
				}

				function DropdownCSS() {}

				DropdownCSS.prototype.render = function(decorated) {
					var $dropdown = decorated.call(this);

					var dropdownCssClass = this.options.get('dropdownCssClass') || '';

					if ($.isFunction(dropdownCssClass)) {
						dropdownCssClass = dropdownCssClass(this.$element);
					}

					var dropdownCssAdapter = this.options.get('adaptDropdownCssClass');
					dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;

					if (dropdownCssClass.indexOf(':all:') !== -1) {
						dropdownCssClass = dropdownCssClass.replace(':all:', '');

						var _cssAdapter = dropdownCssAdapter;

						dropdownCssAdapter = function(clazz) {
							var adapted = _cssAdapter(clazz);

							if (adapted != null) {
								// Append the old one along with the adapted one
								return adapted + ' ' + clazz;
							}

							return clazz;
						};
					}

					var dropdownCss = this.options.get('dropdownCss') || {};

					if ($.isFunction(dropdownCss)) {
						dropdownCss = dropdownCss(this.$element);
					}

					CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter);

					$dropdown.css(dropdownCss);
					$dropdown.addClass(dropdownCssClass);

					return $dropdown;
				};

				return DropdownCSS;
			});

			S2.define('select2/compat/initSelection', [
				'jquery'
			], function($) {
				function InitSelection(decorated, $element, options) {
					if (options.get('debug') && window.console && console.warn) {
						console.warn(
							'Select2: The `initSelection` option has been deprecated in favor' +
							' of a custom data adapter that overrides the `current` method. ' +
							'This method is now called multiple times instead of a single ' +
							'time when the instance is initialized. Support will be removed ' +
							'for the `initSelection` option in future versions of Select2'
						);
					}

					this.initSelection = options.get('initSelection');
					this._isInitialized = false;

					decorated.call(this, $element, options);
				}

				InitSelection.prototype.current = function(decorated, callback) {
					var self = this;

					if (this._isInitialized) {
						decorated.call(this, callback);

						return;
					}

					this.initSelection.call(null, this.$element, function(data) {
						self._isInitialized = true;

						if (!$.isArray(data)) {
							data = [data];
						}

						callback(data);
					});
				};

				return InitSelection;
			});

			S2.define('select2/compat/inputData', [
				'jquery'
			], function($) {
				function InputData(decorated, $element, options) {
					this._currentData = [];
					this._valueSeparator = options.get('valueSeparator') || ',';

					if ($element.prop('type') === 'hidden') {
						if (options.get('debug') && console && console.warn) {
							console.warn(
								'Select2: Using a hidden input with Select2 is no longer ' +
								'supported and may stop working in the future. It is recommended ' +
								'to use a `<select>` element instead.'
							);
						}
					}

					decorated.call(this, $element, options);
				}

				InputData.prototype.current = function(_, callback) {
					function getSelected(data, selectedIds) {
						var selected = [];

						if (data.selected || $.inArray(data.id, selectedIds) !== -1) {
							data.selected = true;
							selected.push(data);
						} else {
							data.selected = false;
						}

						if (data.children) {
							selected.push.apply(selected, getSelected(data.children, selectedIds));
						}

						return selected;
					}

					var selected = [];

					for (var d = 0; d < this._currentData.length; d++) {
						var data = this._currentData[d];

						selected.push.apply(
							selected,
							getSelected(
								data,
								this.$element.val().split(
									this._valueSeparator
								)
							)
						);
					}

					callback(selected);
				};

				InputData.prototype.select = function(_, data) {
					if (!this.options.get('multiple')) {
						this.current(function(allData) {
							$.map(allData, function(data) {
								data.selected = false;
							});
						});

						this.$element.val(data.id);
						this.$element.trigger('change');
					} else {
						var value = this.$element.val();
						value += this._valueSeparator + data.id;

						this.$element.val(value);
						this.$element.trigger('change');
					}
				};

				InputData.prototype.unselect = function(_, data) {
					var self = this;

					data.selected = false;

					this.current(function(allData) {
						var values = [];

						for (var d = 0; d < allData.length; d++) {
							var item = allData[d];

							if (data.id == item.id) {
								continue;
							}

							values.push(item.id);
						}

						self.$element.val(values.join(self._valueSeparator));
						self.$element.trigger('change');
					});
				};

				InputData.prototype.query = function(_, params, callback) {
					var results = [];

					for (var d = 0; d < this._currentData.length; d++) {
						var data = this._currentData[d];

						var matches = this.matches(params, data);

						if (matches !== null) {
							results.push(matches);
						}
					}

					callback({
						results: results
					});
				};

				InputData.prototype.addOptions = function(_, $options) {
					var options = $.map($options, function($option) {
						return $.data($option[0], 'data');
					});

					this._currentData.push.apply(this._currentData, options);
				};

				return InputData;
			});

			S2.define('select2/compat/matcher', [
				'jquery'
			], function($) {
				function oldMatcher(matcher) {
					function wrappedMatcher(params, data) {
						var match = $.extend(true, {}, data);

						if (params.term == null || $.trim(params.term) === '') {
							return match;
						}

						if (data.children) {
							for (var c = data.children.length - 1; c >= 0; c--) {
								var child = data.children[c];

								// Check if the child object matches
								// The old matcher returned a boolean true or false
								var doesMatch = matcher(params.term, child.text, child);

								// If the child didn't match, pop it off
								if (!doesMatch) {
									match.children.splice(c, 1);
								}
							}

							if (match.children.length > 0) {
								return match;
							}
						}

						if (matcher(params.term, data.text, data)) {
							return match;
						}

						return null;
					}

					return wrappedMatcher;
				}

				return oldMatcher;
			});

			S2.define('select2/compat/query', [

			], function() {
				function Query(decorated, $element, options) {
					if (options.get('debug') && window.console && console.warn) {
						console.warn(
							'Select2: The `query` option has been deprecated in favor of a ' +
							'custom data adapter that overrides the `query` method. Support ' +
							'will be removed for the `query` option in future versions of ' +
							'Select2.'
						);
					}

					decorated.call(this, $element, options);
				}

				Query.prototype.query = function(_, params, callback) {
					params.callback = callback;

					var query = this.options.get('query');

					query.call(null, params);
				};

				return Query;
			});

			S2.define('select2/dropdown/attachContainer', [

			], function() {
				function AttachContainer(decorated, $element, options) {
					decorated.call(this, $element, options);
				}

				AttachContainer.prototype.position =
					function(decorated, $dropdown, $container) {
						var $dropdownContainer = $container.find('.dropdown-wrapper');
						$dropdownContainer.append($dropdown);

						$dropdown.addClass('select2-dropdown--below');
						$container.addClass('select2-container--below');
					};

				return AttachContainer;
			});

			S2.define('select2/dropdown/stopPropagation', [

			], function() {
				function StopPropagation() {}

				StopPropagation.prototype.bind = function(decorated, container, $container) {
					decorated.call(this, container, $container);

					var stoppedEvents = [
						'blur',
						'change',
						'click',
						'dblclick',
						'focus',
						'focusin',
						'focusout',
						'input',
						'keydown',
						'keyup',
						'keypress',
						'mousedown',
						'mouseenter',
						'mouseleave',
						'mousemove',
						'mouseover',
						'mouseup',
						'search',
						'touchend',
						'touchstart'
					];

					this.$dropdown.on(stoppedEvents.join(' '), function(evt) {
						evt.stopPropagation();
					});
				};

				return StopPropagation;
			});

			S2.define('select2/selection/stopPropagation', [

			], function() {
				function StopPropagation() {}

				StopPropagation.prototype.bind = function(decorated, container, $container) {
					decorated.call(this, container, $container);

					var stoppedEvents = [
						'blur',
						'change',
						'click',
						'dblclick',
						'focus',
						'focusin',
						'focusout',
						'input',
						'keydown',
						'keyup',
						'keypress',
						'mousedown',
						'mouseenter',
						'mouseleave',
						'mousemove',
						'mouseover',
						'mouseup',
						'search',
						'touchend',
						'touchstart'
					];

					this.$selection.on(stoppedEvents.join(' '), function(evt) {
						evt.stopPropagation();
					});
				};

				return StopPropagation;
			});

			/*!
         * jQuery Mousewheel 3.1.13
         *
         * Copyright jQuery Foundation and other contributors
         * Released under the MIT license
         * http://jquery.org/license
         */

			(function(factory) {
				if (typeof S2.define === 'function' && S2.define.amd) {
					// AMD. Register as an anonymous module.
					S2.define('jquery-mousewheel', ['jquery'], factory);
				} else if (typeof exports === 'object') {
					// Node/CommonJS style for Browserify
					module.exports = factory;
				} else {
					// Browser globals
					factory(jQuery);
				}
			}(function($) {

				var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
					toBind = ('onwheel' in document || document.documentMode >= 9) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
					slice = Array.prototype.slice,
					nullLowestDeltaTimeout, lowestDelta;

				if ($.event.fixHooks) {
					for (var i = toFix.length; i;) {
						$.event.fixHooks[toFix[--i]] = $.event.mouseHooks;
					}
				}

				var special = $.event.special.mousewheel = {
					version: '3.1.12',

					setup: function() {
						if (this.addEventListener) {
							for (var i = toBind.length; i;) {
								this.addEventListener(toBind[--i], handler, false);
							}
						} else {
							this.onmousewheel = handler;
						}
						// Store the line height and page height for this particular element
						$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
						$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
					},

					teardown: function() {
						if (this.removeEventListener) {
							for (var i = toBind.length; i;) {
								this.removeEventListener(toBind[--i], handler, false);
							}
						} else {
							this.onmousewheel = null;
						}
						// Clean up the data we added to the element
						$.removeData(this, 'mousewheel-line-height');
						$.removeData(this, 'mousewheel-page-height');
					},

					getLineHeight: function(elem) {
						var $elem = $(elem),
							$parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
						if (!$parent.length) {
							$parent = $('body');
						}
						return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
					},

					getPageHeight: function(elem) {
						return $(elem).height();
					},

					settings: {
						adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
						normalizeOffset: true // calls getBoundingClientRect for each event
					}
				};

				$.fn.extend({
					mousewheel: function(fn) {
						return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
					},

					unmousewheel: function(fn) {
						return this.unbind('mousewheel', fn);
					}
				});


				function handler(event) {
					var orgEvent = event || window.event,
						args = slice.call(arguments, 1),
						delta = 0,
						deltaX = 0,
						deltaY = 0,
						absDelta = 0,
						offsetX = 0,
						offsetY = 0;
					event = $.event.fix(orgEvent);
					event.type = 'mousewheel';

					// Old school scrollwheel delta
					if ('detail' in orgEvent) {
						deltaY = orgEvent.detail * -1;
					}
					if ('wheelDelta' in orgEvent) {
						deltaY = orgEvent.wheelDelta;
					}
					if ('wheelDeltaY' in orgEvent) {
						deltaY = orgEvent.wheelDeltaY;
					}
					if ('wheelDeltaX' in orgEvent) {
						deltaX = orgEvent.wheelDeltaX * -1;
					}

					// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
					if ('axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
						deltaX = deltaY * -1;
						deltaY = 0;
					}

					// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
					delta = deltaY === 0 ? deltaX : deltaY;

					// New school wheel delta (wheel event)
					if ('deltaY' in orgEvent) {
						deltaY = orgEvent.deltaY * -1;
						delta = deltaY;
					}
					if ('deltaX' in orgEvent) {
						deltaX = orgEvent.deltaX;
						if (deltaY === 0) {
							delta = deltaX * -1;
						}
					}

					// No change actually happened, no reason to go any further
					if (deltaY === 0 && deltaX === 0) {
						return;
					}

					// Need to convert lines and pages to pixels if we aren't already in pixels
					// There are three delta modes:
					//   * deltaMode 0 is by pixels, nothing to do
					//   * deltaMode 1 is by lines
					//   * deltaMode 2 is by pages
					if (orgEvent.deltaMode === 1) {
						var lineHeight = $.data(this, 'mousewheel-line-height');
						delta *= lineHeight;
						deltaY *= lineHeight;
						deltaX *= lineHeight;
					} else if (orgEvent.deltaMode === 2) {
						var pageHeight = $.data(this, 'mousewheel-page-height');
						delta *= pageHeight;
						deltaY *= pageHeight;
						deltaX *= pageHeight;
					}

					// Store lowest absolute delta to normalize the delta values
					absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));

					if (!lowestDelta || absDelta < lowestDelta) {
						lowestDelta = absDelta;

						// Adjust older deltas if necessary
						if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
							lowestDelta /= 40;
						}
					}

					// Adjust older deltas if necessary
					if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
						// Divide all the things by 40!
						delta /= 40;
						deltaX /= 40;
						deltaY /= 40;
					}

					// Get a whole, normalized value for the deltas
					delta = Math[delta >= 1 ? 'floor' : 'ceil'](delta / lowestDelta);
					deltaX = Math[deltaX >= 1 ? 'floor' : 'ceil'](deltaX / lowestDelta);
					deltaY = Math[deltaY >= 1 ? 'floor' : 'ceil'](deltaY / lowestDelta);

					// Normalise offsetX and offsetY properties
					if (special.settings.normalizeOffset && this.getBoundingClientRect) {
						var boundingRect = this.getBoundingClientRect();
						offsetX = event.clientX - boundingRect.left;
						offsetY = event.clientY - boundingRect.top;
					}

					// Add information to the event object
					event.deltaX = deltaX;
					event.deltaY = deltaY;
					event.deltaFactor = lowestDelta;
					event.offsetX = offsetX;
					event.offsetY = offsetY;
					// Go ahead and set deltaMode to 0 since we converted to pixels
					// Although this is a little odd since we overwrite the deltaX/Y
					// properties with normalized deltas.
					event.deltaMode = 0;

					// Add event and delta to the front of the arguments
					args.unshift(event, delta, deltaX, deltaY);

					// Clearout lowestDelta after sometime to better
					// handle multiple device types that give different
					// a different lowestDelta
					// Ex: trackpad = 3 and mouse wheel = 120
					if (nullLowestDeltaTimeout) {
						clearTimeout(nullLowestDeltaTimeout);
					}
					nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);

					return ($.event.dispatch || $.event.handle).apply(this, args);
				}

				function nullLowestDelta() {
					lowestDelta = null;
				}

				function shouldAdjustOldDeltas(orgEvent, absDelta) {
					// If this is an older event and the delta is divisable by 120,
					// then we are assuming that the browser is treating this as an
					// older mouse wheel event and that we should divide the deltas
					// by 40 to try and get a more usable deltaFactor.
					// Side note, this actually impacts the reported scroll distance
					// in older browsers and can cause scrolling to be slower than native.
					// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
					return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
				}

			}));

			S2.define('jquery.select2', [
				'jquery',
				'jquery-mousewheel',

				'./select2/core',
				'./select2/defaults'
			], function($, _, Select2, Defaults) {
				if ($.fn.wpmuiSelect == null) {
					// All methods that should return the element
					var thisMethods = ['open', 'close', 'destroy'];

					$.fn.wpmuiSelect = function(options) {
						options = options || {};

						if (typeof options === 'object') {
							this.each(function() {
								var instanceOptions = $.extend(true, {}, options);

								var instance = new Select2($(this), instanceOptions);
							});

							return this;
						} else if (typeof options === 'string') {
							var ret;
							var args = Array.prototype.slice.call(arguments, 1);

							this.each(function() {
								var instance = $(this).data('select2');

								if (instance == null && window.console && console.error) {
									console.error(
										'The select2(\'' + options + '\') method was called on an ' +
										'element that is not using Select2.'
									);
								}

								ret = instance[options].apply(instance, args);
							});

							// Check if we should be returning `this`
							if ($.inArray(options, thisMethods) > -1) {
								return this;
							}

							return ret;
						} else {
							throw new Error('Invalid arguments for Select2: ' + options);
						}
					};
				}

				if ($.fn.wpmuiSelect.defaults == null) {
					$.fn.wpmuiSelect.defaults = Defaults;
				}

				return Select2;
			});

			// Return the AMD loader configuration so it can be used outside of this file
			return {
				define: S2.define,
				require: S2.require
			};
		}());

	// Autoload the jQuery bindings
	// We know that all of the modules exist above this, so we're safe
	var select2 = S2.require('jquery.select2');

	// Hold the AMD module references on the jQuery function that was just loaded
	// This allows Select2 to use the internal loader outside of this file, such
	// as in the language files.
	jQuery.fn.wpmuiSelect.amd = S2;

	// Return the Select2 instance for anyone who is importing it.
	return select2;
}));