window.$ = window.$ || {};(function() { if ($ && $.fn && $.fn.select2 && $.fn.select2.amd) { define = $.fn.select2.amd.define; require = $.fn.select2.amd.require; }define('select2/utils',[], 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; } 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; this.listeners = this.listeners || {}; 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; }; return Utils; }); define('select2/results',[ './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 = $( '' ); 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) { this.clear(); var $message = $('
  • '); var message = this.options.get('translations').get(params.message); $message.text(message(params.args)); this.$results.append($message); }; Results.prototype.append = function (data) { var $options = []; if (data.length === 0) { if (this.$results.children().length === 0) { this.trigger('results:message', { message: 'noResults' }); } return; } data = this.sort(data); for (var d = 0; d < data.length; d++) { var item = data[d]; var $option = this.option(item); $options.push($option); } this.$results.append($options); }; Results.prototype.sort = function (data) { return data; }; 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('.option[aria-selected]'); $options.each(function () { var $option = $(this); var item = $.data(this, 'data'); if (item.id != null && selectedIds.indexOf(item.id.toString()) > -1) { $option.attr('aria-selected', 'true'); } else { $option.attr('aria-selected', 'false'); } }); 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'); } }); }; Results.prototype.option = function (data) { var option = document.createElement('li'); option.className = '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.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 = 'group-label'; 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 = $(''); $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(); } }); container.on('results:append', function (params) { self.append(params.data); if (container.isOpen()) { self.setClasses(); } }); container.on('select', function () { if (!container.isOpen()) { return; } self.setClasses(); }); container.on('unselect', function () { if (!container.isOpen()) { return; } self.setClasses(); }); 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:select', function () { var $highlighted = self.$results.find('.highlighted'); if ($highlighted.length === 0) { return; } var data = $highlighted.data('data'); if ($highlighted.attr('aria-selected') == 'true') { self.trigger('unselected', { data: data }); } else { self.trigger('selected', { data: data }); } }); container.on('results:previous', function () { var $highlighted = self.$results.find('.highlighted'); 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.$results.find('.highlighted'); 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('highlighted'); }); container.on('results:message', function (params) { self.trigger('results:message', params); }); this.on('results:message', function (params) { self.displayMessage(params); }); this.$results.on('mouseup', '.option[aria-selected]', function (evt) { var $this = $(this); var data = $this.data('data'); if ($this.attr('aria-selected') === 'true') { self.trigger('unselected', { originalEvent: evt, data: data }); return; } self.trigger('selected', { originalEvent: evt, data: data }); }); this.$results.on('mouseenter', '.option[aria-selected]', function (evt) { var data = $(this).data('data'); self.$results.find('.option.highlighted').removeClass('highlighted'); self.trigger('results:focus', { data: data, element: $(this) }); }); this.$results.on('mouseleave', '.option', function (evt) { if ($(this).hasClass('highlighted')) { $(this).removeClass('highlighted'); self.$results.removeAttr('aria-activedescendant'); } }); }; Results.prototype.destroy = function () { this.$results.remove(); }; Results.prototype.ensureHighlightVisible = function () { var $highlighted = this.$results.find('.highlighted'); 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'); container.innerHTML = template(result); }; return Results; }); define('select2/selection/base',[ '../utils' ], function (Utils) { function BaseSelection ($element, options) { this.$element = $element; this.options = options; BaseSelection.__super__.constructor.call(this); } Utils.Extend(BaseSelection, Utils.Observable); BaseSelection.prototype.render = function () { throw new Error('The `render` method must be defined in child classes.'); }; BaseSelection.prototype.bind = function (container, $container) { var self = this; container.on('selection:update', function (params) { self.update(params.data); }); container.on('open', function () { $(document.body).on('mousedown.select2.' + container.id, function (e) { var $target = $(e.target); var $select = $target.closest('.select2'); var $all = $('.select2.open'); $all.each(function () { var $this = $(this); if (this == $select[0]) { return; } var $element = $this.data('element'); $element.select2('close'); }); }); container.on('close', function () { $(document.body).off('mousedown.select2.' + container.id); }); }); }; BaseSelection.prototype.destroy = function () { // Unbind the dropdown click handler if it exists $(document.body).off('.select2.' + container.id); }; BaseSelection.prototype.update = function (data) { throw new Error('The `update` method must be defined in child classes.'); }; return BaseSelection; }); 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, isArrow: function (k) { k = k.which ? k.which : k; switch (k) { case KEY.LEFT: case KEY.RIGHT: case KEY.UP: case KEY.DOWN: return true; } return false; } }; return KEYS; }); define('select2/selection/single',[ './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 = $( '' ); $selection.attr('title', this.$element.attr('title')); this.$selection = $selection; return $selection; }; SingleSelection.prototype.bind = function (container, $container) { var self = this; SingleSelection.__super__.bind.apply(this, arguments); var id = container.id + '-container'; var resultsId = container.id + '-results'; this.$selection.find('.rendered-selection').attr('id', id); this.$selection.attr('aria-labelledby', id); this.$selection.attr('aria-owns', resultsId); this.$selection.on('mousedown', function (evt) { // Only respond to left clicks if (evt.which !== 1) { return; } self.trigger('toggle', { originalEvent: evt }); }); container.on('open', function () { // When the dropdown is open, aria-expanded="true" self.$selection.attr('aria-expanded', 'true'); }); 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.focus(); }); this.$selection.on('focus', function (evt) { // User focuses on the container }); this.$selection.on('blur', function (evt) { // User exits the container }); 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); }); }; SingleSelection.prototype.clear = function () { this.$selection.find('.rendered-selection').empty(); }; SingleSelection.prototype.display = function (data) { var template = this.options.get('templateSelection'); return template(data); }; SingleSelection.prototype.selectionContainer = function () { return $(''); }; SingleSelection.prototype.update = function (data) { if (data.length === 0) { this.clear(); return; } var selection = data[0]; var formatted = this.display(selection); this.$selection.find('.rendered-selection').html(formatted); }; return SingleSelection; }); define('select2/selection/multiple',[ './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 = $( '' + '' + '' ); this.$selection = $selection; 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', '.remove', function (evt) { var $remove = $(this); var $selection = $remove.parent(); var data = $selection.data('data'); self.trigger('unselected', { originalEvent: evt, data: data }); }); }; MultipleSelection.prototype.clear = function () { this.$selection.find('.rendered-selection').empty(); }; MultipleSelection.prototype.display = function (data) { var template = this.options.get('templateSelection'); return template(data); }; MultipleSelection.prototype.selectionContainer = function () { var $container = $( '
  • ' + '×' + '
  • ' ); 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 formatted = this.display(selection); var $selection = this.selectionContainer(); $selection.append(formatted); $selection.data('data', selection); $selections.push($selection); } this.$selection.find('.rendered-selection').append($selections); }; return MultipleSelection; }); 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.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.selectionContainer(); $placeholder.html(this.display(this.placeholder)); $placeholder.addClass('placeholder').removeClass('choice'); this.$selection.find('.rendered-selection').append($placeholder); }; return Placeholder; }); define('select2/translation',[ ], function () { 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; }); 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; }); 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; 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++) { id = data[d].id; if (val.indexOf(id) === -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; } this.current(function (currentData) { var val = []; for (var d = 0; d < currentData.length; d++) { id = currentData[d].id; if (id !== data.id && val.indexOf(id) === -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(data); }; SelectAdapter.prototype.option = function (data) { var option = document.createElement('option'); option.value = data.id; if (data.disabled) { option.disabled = true; } if (data.selected) { option.selected = true; } option.innerText = data.text; var $option = $(option); var normalizedData = this._normalizeItem(data); // 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.html(), disabled: $option.prop('disabled'), selected: $option.prop('selected') }; } else if ($option.is('optgroup')) { data = { text: $option.attr('label'), children: [] }; 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($option[0], 'data', data); return data; }; SelectAdapter.prototype._normalizeItem = function (item) { if (item.text == null) { item = { id: item, 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; }); 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.convertToOptions(data); } Utils.Extend(ArrayAdapter, SelectAdapter); ArrayAdapter.prototype.select = function (data) { var $option = this.$element.find('option[value="' + data.id + '"]'); if ($option.length === 0) { $option = this.option(data); this.$element.append($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(); // 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 = data[d]; item.id = item.id.toString(); // Skip items which were pre-loaded, only merge the data if (existingIds.indexOf(item.id) >= 0) { var $existingOption = $existing.filter(onlyItem(item)); var existingData = this.item($existingOption); var newData = $.extend(true, {}, existingData, item); var $newOption = this.option(existingData); $existingOption.replaceWith($newOption); continue; } var $option = this.option(item); this.$element.append($option); } }; return ArrayAdapter; }); define('select2/data/ajax',[ './array', '../utils', 'jquery' ], function (ArrayAdapter, Utils, $) { function AjaxAdapter ($element, options) { this.ajaxOptions = options.get('ajax'); if (this.ajaxOptions.processResults != null) { this.processResults = this.ajaxOptions.processResults; } ArrayAdapter.__super__.constructor.call(this, $element, options); } Utils.Extend(AjaxAdapter, ArrayAdapter); AjaxAdapter.prototype.processResults = function (results) { return results; }; AjaxAdapter.prototype.query = function (params, callback) { var matches = []; var self = this; var options = $.extend({ type: 'GET' }, this.ajaxOptions); if (typeof options.url === 'function') { options.url = options.url(params); } if (typeof options.data === 'function') { options.data = options.data(params); } function request () { var $request = $.ajax(options); $request.success(function (data) { var results = self.processResults(data); callback(results); }); } if (this.ajaxOptions.delay && params.term !== '') { if (this._queryTimeout) { window.clearTimeout(this._queryTimeout); } this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay); } else { request(); } }; return AjaxAdapter; }); define('select2/data/tags',[ ], function () { function Tags (decorated, $element, options) { var tags = options.get('tags'); 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.term === '' || params.page != null) { decorated.call(this, params, callback); return; } function wrapper (data, child) { for (var i = 0; i < data.length; i++) { var option = data[i]; var checkChildren = ( option.children != null && !wrapper(option.children, true) ); var checkText = option.text === params.term; if (checkText || checkChildren) { if (child) { return false; } callback(data); return; } } if (child) { return true; } var tag = self.createTag(params); var $option = self.option(tag); $option.attr('data-select2-tag', true); self.$element.append($option); self.insertTag(data, tag); callback(data); } decorated.call(this, params, wrapper); }; Tags.prototype.createTag = function (decorated, params) { return { id: params.term, text: params.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; }); 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; }); define('select2/dropdown',[ './utils' ], function (Utils) { function Dropdown ($element, options) { this.$element = $element; } Utils.Extend(Dropdown, Utils.Observable); Dropdown.prototype.render = function () { var $dropdown = $( '' + '' + '' ); this.$dropdown = $dropdown; return $dropdown; }; Dropdown.prototype.destroy = function () { // Remove the dropdown from the DOM this.$dropdown.remove(); }; Dropdown.prototype.bind = function (container, $container) { // Can be implemented in subclasses }; return Dropdown; }); define('select2/dropdown/search',[ '../utils' ], function (Utils) { function Search () { } Search.prototype.render = function (decorated) { var $rendered = decorated.call(this); var $search = $( '' + '' + '' ); 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(); }); this.$search.on('keyup', function (evt) { self.handleSearch(evt); }); container.on('open', function () { self.$search.attr('tabindex', 0); self.$search.focus(); }); container.on('close', function () { self.$search.attr('tabindex', -1); self.$search.val(''); }); container.on('results:all', function (params) { if (params.query.term == null || params.query.term === '') { var showSearch = self.showSearch(params); if (showSearch) { self.$searchContainer.show(); } else { self.$searchContainer.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; }); 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 = this.removePlaceholder(data); 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; }); 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(); decorated.call(this, data); if (data.length > 0) { this.$results.append(this.$loadingMore); } this.loading = false; }; 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 loadMoreVisible = $.contains( document.documentElement, self.$loadingMore[0] ); if (self.loading || !loadMoreVisible) { 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.createLoadingMore = function () { var $option = $( '
  • ' ); var message = this.options.get('translations').get('loadingMore'); $option.html(message(this.lastParams)); return $option; }; return InfiniteScroll; }); define('select2/i18n/en',[],function () { return { inputTooShort: function (args) { var remainingChars = args.minimum - args.input.length; var message = 'Please enter ' + remainingChars + ' or more character'; if (remainingChars != 1) { message += 's'; } return message; }, loadingMore: function () { return 'Loading more results…'; }, noResults: function () { return 'No results found'; } }; }); define('select2/defaults',[ 'jquery', './results', './selection/single', './selection/multiple', './selection/placeholder', './utils', './translation', './data/select', './data/array', './data/ajax', './data/tags', './data/minimumInputLength', './dropdown', './dropdown/search', './dropdown/hidePlaceholder', './dropdown/infiniteScroll', './i18n/en' ], function ($, ResultsList, SingleSelection, MultipleSelection, Placeholder, Utils, Translation, SelectData, ArrayData, AjaxData, Tags, MinimumInputLength, Dropdown, Search, HidePlaceholder, InfiniteScroll, EnglishTranslation) { function Defaults () { this.reset(); } Defaults.prototype.apply = function (options) { options = $.extend({}, 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.tags != null) { options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags); } 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.dropdownAdapter == null) { var SearchableDropdown = Utils.Decorate(Dropdown, Search); options.dropdownAdapter = SearchableDropdown; } 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 (typeof options.language === 'string') { options.language = [options.language]; } if ($.isArray(options.language)) { var languages = new Translation(); var languageNames = options.language.concat(this.defaults.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) { // If we couldn't load it, check if it wasn't the full path name = 'select2/i18n/' + name; language = Translation.loadPath(name); } languages.extend(language); } options.translations = languages; } else { options.translations = new Translations(options.language); } return options; }; Defaults.prototype.reset = function () { 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); } // Check if the text contains the term if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) > -1) { return data; } // If it doesn't contain the term, don't return anything return null; } this.defaults = { language: ['select2/i18n/en'], matcher: matcher, minimumInputLength: 0, templateResult: function (result) { return result.text; }, templateSelection: function (selection) { return selection.text; } }; }; var defaults = new Defaults(); return defaults; }); define('select2/options',[ './defaults' ], function (Defaults) { function Options (options, $element) { this.options = options; if ($element != null) { this.fromElement($element); } this.options = Defaults.apply(this.options); } Options.prototype.fromElement = function ($e) { if (this.options.multiple == null) { this.options.multiple = $e.prop('multiple'); } return this; }; Options.prototype.get = function (key) { return this.options[key]; }; Options.prototype.set = function (key, val) { this.options[key] = val; }; return Options; }); define('select2/core',[ 'jquery', './options', './utils', './keys' ], function ($, Options, Utils, KEYS) { var Select2 = function ($element, options) { if ($element.data('select2') != null) { return; } this.$element = $element; this.id = this._generateId($element); options = options || {}; this.options = new Options(options, $element); Select2.__super__.constructor.call(this); // Set up containers and adapters var DataAdapter = this.options.get('dataAdapter'); this.data = 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); var $selection = this.selection.render(); this._placeSelection($selection); var DropdownAdapter = this.options.get('dropdownAdapter'); this.dropdown = new DropdownAdapter($element, this.options); var $dropdown = this.dropdown.render(); this._placeDropdown($dropdown); var ResultsAdapter = this.options.get('resultsAdapter'); this.results = new ResultsAdapter($element, this.options, this.data); var $results = this.results.render(); this._placeResults($results); // 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.data.current(function (initialData) { self.trigger('selection:update', { data: initialData }); }); // Hide the original select $element.hide(); this._tabindex = $element.attr('tabindex') || 0; $element.attr('tabindex', '-1'); $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 = 'select2-' + id; return id; }; Select2.prototype._placeContainer = function ($container) { $container.insertAfter(this.$element); $container.width(this.$element.outerWidth(false)); }; Select2.prototype._placeSelection = function ($selection) { var $selectionContainer = this.$container.find('.selection'); $selectionContainer.append($selection); }; Select2.prototype._placeDropdown = function ($dropdown) { this.$dropdown = $dropdown; var $dropdownContainer = this.$container.find('.dropdown-wrapper'); $dropdownContainer.append($dropdown); }; Select2.prototype._placeResults = function ($results) { var $resultsContainer = this.$dropdown.find('.results'); $resultsContainer.append($results); }; Select2.prototype._bindAdapters = function () { this.data.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.data.current(function (data) { self.trigger('selection:update', { data: data }); }); }); }; Select2.prototype._registerDataEvents = function () { var self = this; this.data.on('results:message', function (params) { self.trigger('results:message', params); }); }; Select2.prototype._registerSelectionEvents = function () { var self = this; this.selection.on('open', function () { self.open(); }); this.selection.on('close', function () { self.close(); }); this.selection.on('toggle', function () { self.toggleDropdown(); }); this.selection.on('results:select', function () { self.trigger('results:select'); }); this.selection.on('results:previous', function () { self.trigger('results:previous'); }); this.selection.on('results:next', function () { self.trigger('results:next'); }); this.selection.on('unselected', function (params) { self.trigger('unselect', params); self.close(); }); this.selection.on('keypress', function (e) { self.trigger('keypress', e); }); }; Select2.prototype._registerDropdownEvents = function () { var self = this; this.dropdown.on('query', function (params) { self.trigger('query', params); }); this.dropdown.on('keypress', function (e) { self.trigger('keypress', e); }); }; Select2.prototype._registerResultsEvents = function () { var self = this; this.results.on('query:append', function (params) { self.trigger('query:append', params); }); this.results.on('selected', function (params) { self.trigger('select', params); self.close(); }); this.results.on('unselected', function (params) { self.trigger('unselect', params); self.close(); }); this.results.on('results:focus', function (params) { self.trigger('results:focus', params); }); }; Select2.prototype._registerEvents = function () { var self = this; this.on('open', function () { self.$container.addClass('open'); }); this.on('close', function () { self.$container.removeClass('open'); }); this.on('query', function (params) { this.data.query(params, function (data) { self.trigger('results:all', { data: data, query: params }); }); }); this.on('query:append', function (params) { this.data.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.ENTER) { self.trigger('results:select'); 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.ESC || key === KEYS.TAB) { self.close(); evt.preventDefault(); } } else { if (key === KEYS.ENTER || key === KEYS.SPACE) { self.open(); evt.preventDefault(); } } }); }; Select2.prototype.toggleDropdown = function () { if (this.isOpen()) { this.close(); } else { this.open(); } }; Select2.prototype.open = function () { if (this.isOpen()) { return; } this.trigger('query', {}); this.trigger('open'); }; Select2.prototype.close = function () { if (!this.isOpen()) { return; } this.trigger('close'); }; Select2.prototype.isOpen = function () { return this.$container.hasClass('open'); }; Select2.prototype.destroy = function () { this.$container.remove(); this.$element.off('.select2'); this.$element.attr('tabindex', this._tabindex); this.$element.show(); this.$element.removeData('select2'); this.data.destroy(); this.selection.destroy(); this.dropdown.destroy(); this.results.destroy(); this.data = null; this.selection = null; this.dropdown = null; this.results = null; }; Select2.prototype.render = function () { var $container = $( '' + '' + '' + '' ); this.$container = $container; $container.data('element', this.$element); return $container; }; return Select2; }); define('jquery.select2',[ 'jquery', 'select2/core' ], function ($, Select2) { if ($.fn.select2 == null) { $.fn.select2 = function (options) { options = options || {}; if (typeof options === 'object') { this.each(function () { var instance = new Select2($(this), options); }); } else if (typeof options === 'string') { var instance = this.data('select2'); var args = Array.prototype.slice.call(arguments, 1); instance[options](args); } else { throw new Error('Invalid arguments for Select2: ' + options); } }; } return Select2; }); require('jquery.select2'); $.fn.select2.amd = { define: define, require: require };}());