HEX
Server: Apache
System: Linux webm010.cluster127.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: alloesb (202139)
PHP: 8.3.31
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/alloesb/www/wp-content/themes/listable/assets/js/main.js
/*!
Chosen, a Select Box Enhancer for jQuery and Prototype
by Patrick Filler for Harvest, http://getharvest.com

Version 1.8.7
Full source at https://github.com/harvesthq/chosen
Copyright (c) 2011-2018 Harvest http://getharvest.com

MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
This file is generated by `grunt build`, do not edit it by hand.
*/

(function() {
  var $, AbstractChosen, Chosen, SelectParser,
      bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
      extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
      hasProp = {}.hasOwnProperty;

  SelectParser = (function() {
    function SelectParser() {
      this.options_index = 0;
      this.parsed = [];
    }

    SelectParser.prototype.add_node = function(child) {
      if (child.nodeName.toUpperCase() === "OPTGROUP") {
        return this.add_group(child);
      } else {
        return this.add_option(child);
      }
    };

    SelectParser.prototype.add_group = function(group) {
      var group_position, i, len, option, ref, results1;
      group_position = this.parsed.length;
      this.parsed.push({
        array_index: group_position,
        group: true,
        label: group.label,
        title: group.title ? group.title : void 0,
        children: 0,
        disabled: group.disabled,
        classes: group.className
      });
      ref = group.childNodes;
      results1 = [];
      for (i = 0, len = ref.length; i < len; i++) {
        option = ref[i];
        results1.push(this.add_option(option, group_position, group.disabled));
      }
      return results1;
    };

    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
      if (option.nodeName.toUpperCase() === "OPTION") {
        if (option.text !== "") {
          if (group_position != null) {
            this.parsed[group_position].children += 1;
          }
          this.parsed.push({
            array_index: this.parsed.length,
            options_index: this.options_index,
            value: option.value,
            text: option.text,
            html: option.innerHTML,
            title: option.title ? option.title : void 0,
            selected: option.selected,
            disabled: group_disabled === true ? group_disabled : option.disabled,
            group_array_index: group_position,
            group_label: group_position != null ? this.parsed[group_position].label : null,
            classes: option.className,
            style: option.style.cssText
          });
        } else {
          this.parsed.push({
            array_index: this.parsed.length,
            options_index: this.options_index,
            empty: true
          });
        }
        return this.options_index += 1;
      }
    };

    return SelectParser;

  })();

  SelectParser.select_to_array = function(select) {
    var child, i, len, parser, ref;
    parser = new SelectParser();
    ref = select.childNodes;
    for (i = 0, len = ref.length; i < len; i++) {
      child = ref[i];
      parser.add_node(child);
    }
    return parser.parsed;
  };

  AbstractChosen = (function() {
    function AbstractChosen(form_field, options1) {
      this.form_field = form_field;
      this.options = options1 != null ? options1 : {};
      this.label_click_handler = bind(this.label_click_handler, this);
      if (!AbstractChosen.browser_is_supported()) {
        return;
      }
      this.is_multiple = this.form_field.multiple;
      this.set_default_text();
      this.set_default_values();
      this.setup();
      this.set_up_html();
      this.register_observers();
      this.on_ready();
    }

    AbstractChosen.prototype.set_default_values = function() {
      this.click_test_action = (function(_this) {
        return function(evt) {
          return _this.test_active_click(evt);
        };
      })(this);
      this.activate_action = (function(_this) {
        return function(evt) {
          return _this.activate_field(evt);
        };
      })(this);
      this.active_field = false;
      this.mouse_on_container = false;
      this.results_showing = false;
      this.result_highlighted = null;
      this.is_rtl = this.options.rtl || /\bchosen-rtl\b/.test(this.form_field.className);
      this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
      this.disable_search_threshold = this.options.disable_search_threshold || 0;
      this.disable_search = this.options.disable_search || false;
      this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
      this.group_search = this.options.group_search != null ? this.options.group_search : true;
      this.search_contains = this.options.search_contains || false;
      this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
      this.max_selected_options = this.options.max_selected_options || Infinity;
      this.inherit_select_classes = this.options.inherit_select_classes || false;
      this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
      this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
      this.include_group_label_in_selected = this.options.include_group_label_in_selected || false;
      this.max_shown_results = this.options.max_shown_results || Number.POSITIVE_INFINITY;
      this.case_sensitive_search = this.options.case_sensitive_search || false;
      return this.hide_results_on_select = this.options.hide_results_on_select != null ? this.options.hide_results_on_select : true;
    };

    AbstractChosen.prototype.set_default_text = function() {
      if (this.form_field.getAttribute("data-placeholder")) {
        this.default_text = this.form_field.getAttribute("data-placeholder");
      } else if (this.is_multiple) {
        this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
      } else {
        this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
      }
      this.default_text = this.escape_html(this.default_text);
      return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
    };

    AbstractChosen.prototype.choice_label = function(item) {
      if (this.include_group_label_in_selected && (item.group_label != null)) {
        return "<b class='group-name'>" + (this.escape_html(item.group_label)) + "</b>" + item.html;
      } else {
        return item.html;
      }
    };

    AbstractChosen.prototype.mouse_enter = function() {
      return this.mouse_on_container = true;
    };

    AbstractChosen.prototype.mouse_leave = function() {
      return this.mouse_on_container = false;
    };

    AbstractChosen.prototype.input_focus = function(evt) {
      if (this.is_multiple) {
        if (!this.active_field) {
          return setTimeout(((function(_this) {
            return function() {
              return _this.container_mousedown();
            };
          })(this)), 50);
        }
      } else {
        if (!this.active_field) {
          return this.activate_field();
        }
      }
    };

    AbstractChosen.prototype.input_blur = function(evt) {
      if (!this.mouse_on_container) {
        this.active_field = false;
        return setTimeout(((function(_this) {
          return function() {
            return _this.blur_test();
          };
        })(this)), 100);
      }
    };

    AbstractChosen.prototype.label_click_handler = function(evt) {
      if (this.is_multiple) {
        return this.container_mousedown(evt);
      } else {
        return this.activate_field();
      }
    };

    AbstractChosen.prototype.results_option_build = function(options) {
      var content, data, data_content, i, len, ref, shown_results;
      content = '';
      shown_results = 0;
      ref = this.results_data;
      for (i = 0, len = ref.length; i < len; i++) {
        data = ref[i];
        data_content = '';
        if (data.group) {
          data_content = this.result_add_group(data);
        } else {
          data_content = this.result_add_option(data);
        }
        if (data_content !== '') {
          shown_results++;
          content += data_content;
        }
        if (options != null ? options.first : void 0) {
          if (data.selected && this.is_multiple) {
            this.choice_build(data);
          } else if (data.selected && !this.is_multiple) {
            this.single_set_selected_text(this.choice_label(data));
          }
        }
        if (shown_results >= this.max_shown_results) {
          break;
        }
      }
      return content;
    };

    AbstractChosen.prototype.result_add_option = function(option) {
      var classes, option_el;
      if (!option.search_match) {
        return '';
      }
      if (!this.include_option_in_results(option)) {
        return '';
      }
      classes = [];
      if (!option.disabled && !(option.selected && this.is_multiple)) {
        classes.push("active-result");
      }
      if (option.disabled && !(option.selected && this.is_multiple)) {
        classes.push("disabled-result");
      }
      if (option.selected) {
        classes.push("result-selected");
      }
      if (option.group_array_index != null) {
        classes.push("group-option");
      }
      if (option.classes !== "") {
        classes.push(option.classes);
      }
      option_el = document.createElement("li");
      option_el.className = classes.join(" ");
      if (option.style) {
        option_el.style.cssText = option.style;
      }
      option_el.setAttribute("data-option-array-index", option.array_index);
      option_el.innerHTML = option.highlighted_html || option.html;
      if (option.title) {
        option_el.title = option.title;
      }
      return this.outerHTML(option_el);
    };

    AbstractChosen.prototype.result_add_group = function(group) {
      var classes, group_el;
      if (!(group.search_match || group.group_match)) {
        return '';
      }
      if (!(group.active_options > 0)) {
        return '';
      }
      classes = [];
      classes.push("group-result");
      if (group.classes) {
        classes.push(group.classes);
      }
      group_el = document.createElement("li");
      group_el.className = classes.join(" ");
      group_el.innerHTML = group.highlighted_html || this.escape_html(group.label);
      if (group.title) {
        group_el.title = group.title;
      }
      return this.outerHTML(group_el);
    };

    AbstractChosen.prototype.results_update_field = function() {
      this.set_default_text();
      if (!this.is_multiple) {
        this.results_reset_cleanup();
      }
      this.result_clear_highlight();
      this.results_build();
      if (this.results_showing) {
        return this.winnow_results();
      }
    };

    AbstractChosen.prototype.reset_single_select_options = function() {
      var i, len, ref, result, results1;
      ref = this.results_data;
      results1 = [];
      for (i = 0, len = ref.length; i < len; i++) {
        result = ref[i];
        if (result.selected) {
          results1.push(result.selected = false);
        } else {
          results1.push(void 0);
        }
      }
      return results1;
    };

    AbstractChosen.prototype.results_toggle = function() {
      if (this.results_showing) {
        return this.results_hide();
      } else {
        return this.results_show();
      }
    };

    AbstractChosen.prototype.results_search = function(evt) {
      if (this.results_showing) {
        return this.winnow_results();
      } else {
        return this.results_show();
      }
    };

    AbstractChosen.prototype.winnow_results = function(options) {
      var escapedQuery, fix, i, len, option, prefix, query, ref, regex, results, results_group, search_match, startpos, suffix, text;
      this.no_results_clear();
      results = 0;
      query = this.get_search_text();
      escapedQuery = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
      regex = this.get_search_regex(escapedQuery);
      ref = this.results_data;
      for (i = 0, len = ref.length; i < len; i++) {
        option = ref[i];
        option.search_match = false;
        results_group = null;
        search_match = null;
        option.highlighted_html = '';
        if (this.include_option_in_results(option)) {
          if (option.group) {
            option.group_match = false;
            option.active_options = 0;
          }
          if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
            results_group = this.results_data[option.group_array_index];
            if (results_group.active_options === 0 && results_group.search_match) {
              results += 1;
            }
            results_group.active_options += 1;
          }
          text = option.group ? option.label : option.text;
          if (!(option.group && !this.group_search)) {
            search_match = this.search_string_match(text, regex);
            option.search_match = search_match != null;
            if (option.search_match && !option.group) {
              results += 1;
            }
            if (option.search_match) {
              if (query.length) {
                startpos = search_match.index;
                prefix = text.slice(0, startpos);
                fix = text.slice(startpos, startpos + query.length);
                suffix = text.slice(startpos + query.length);
                option.highlighted_html = (this.escape_html(prefix)) + "<em>" + (this.escape_html(fix)) + "</em>" + (this.escape_html(suffix));
              }
              if (results_group != null) {
                results_group.group_match = true;
              }
            } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
              option.search_match = true;
            }
          }
        }
      }
      this.result_clear_highlight();
      if (results < 1 && query.length) {
        this.update_results_content("");
        return this.no_results(query);
      } else {
        this.update_results_content(this.results_option_build());
        if (!(options != null ? options.skip_highlight : void 0)) {
          return this.winnow_results_set_highlight();
        }
      }
    };

    AbstractChosen.prototype.get_search_regex = function(escaped_search_string) {
      var regex_flag, regex_string;
      regex_string = this.search_contains ? escaped_search_string : "(^|\\s|\\b)" + escaped_search_string + "[^\\s]*";
      if (!(this.enable_split_word_search || this.search_contains)) {
        regex_string = "^" + regex_string;
      }
      regex_flag = this.case_sensitive_search ? "" : "i";
      return new RegExp(regex_string, regex_flag);
    };

    AbstractChosen.prototype.search_string_match = function(search_string, regex) {
      var match;
      match = regex.exec(search_string);
      if (!this.search_contains && (match != null ? match[1] : void 0)) {
        match.index += 1;
      }
      return match;
    };

    AbstractChosen.prototype.choices_count = function() {
      var i, len, option, ref;
      if (this.selected_option_count != null) {
        return this.selected_option_count;
      }
      this.selected_option_count = 0;
      ref = this.form_field.options;
      for (i = 0, len = ref.length; i < len; i++) {
        option = ref[i];
        if (option.selected) {
          this.selected_option_count += 1;
        }
      }
      return this.selected_option_count;
    };

    AbstractChosen.prototype.choices_click = function(evt) {
      evt.preventDefault();
      this.activate_field();
      if (!(this.results_showing || this.is_disabled)) {
        return this.results_show();
      }
    };

    AbstractChosen.prototype.keydown_checker = function(evt) {
      var ref, stroke;
      stroke = (ref = evt.which) != null ? ref : evt.keyCode;
      this.search_field_scale();
      if (stroke !== 8 && this.pending_backstroke) {
        this.clear_backstroke();
      }
      switch (stroke) {
        case 8:
          this.backstroke_length = this.get_search_field_value().length;
          break;
        case 9:
          if (this.results_showing && !this.is_multiple) {
            this.result_select(evt);
          }
          this.mouse_on_container = false;
          break;
        case 13:
          if (this.results_showing) {
            evt.preventDefault();
          }
          break;
        case 27:
          if (this.results_showing) {
            evt.preventDefault();
          }
          break;
        case 32:
          if (this.disable_search) {
            evt.preventDefault();
          }
          break;
        case 38:
          evt.preventDefault();
          this.keyup_arrow();
          break;
        case 40:
          evt.preventDefault();
          this.keydown_arrow();
          break;
      }
    };

    AbstractChosen.prototype.keyup_checker = function(evt) {
      var ref, stroke;
      stroke = (ref = evt.which) != null ? ref : evt.keyCode;
      this.search_field_scale();
      switch (stroke) {
        case 8:
          if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
            this.keydown_backstroke();
          } else if (!this.pending_backstroke) {
            this.result_clear_highlight();
            this.results_search();
          }
          break;
        case 13:
          evt.preventDefault();
          if (this.results_showing) {
            this.result_select(evt);
          }
          break;
        case 27:
          if (this.results_showing) {
            this.results_hide();
          }
          break;
        case 9:
        case 16:
        case 17:
        case 18:
        case 38:
        case 40:
        case 91:
          break;
        default:
          this.results_search();
          break;
      }
    };

    AbstractChosen.prototype.clipboard_event_checker = function(evt) {
      if (this.is_disabled) {
        return;
      }
      return setTimeout(((function(_this) {
        return function() {
          return _this.results_search();
        };
      })(this)), 50);
    };

    AbstractChosen.prototype.container_width = function() {
      if (this.options.width != null) {
        return this.options.width;
      } else {
        return this.form_field.offsetWidth + "px";
      }
    };

    AbstractChosen.prototype.include_option_in_results = function(option) {
      if (this.is_multiple && (!this.display_selected_options && option.selected)) {
        return false;
      }
      if (!this.display_disabled_options && option.disabled) {
        return false;
      }
      if (option.empty) {
        return false;
      }
      return true;
    };

    AbstractChosen.prototype.search_results_touchstart = function(evt) {
      this.touch_started = true;
      return this.search_results_mouseover(evt);
    };

    AbstractChosen.prototype.search_results_touchmove = function(evt) {
      this.touch_started = false;
      return this.search_results_mouseout(evt);
    };

    AbstractChosen.prototype.search_results_touchend = function(evt) {
      if (this.touch_started) {
        return this.search_results_mouseup(evt);
      }
    };

    AbstractChosen.prototype.outerHTML = function(element) {
      var tmp;
      if (element.outerHTML) {
        return element.outerHTML;
      }
      tmp = document.createElement("div");
      tmp.appendChild(element);
      return tmp.innerHTML;
    };

    AbstractChosen.prototype.get_single_html = function() {
      return "<a class=\"chosen-single chosen-default\">\n  <span>" + this.default_text + "</span>\n  <div><b></b></div>\n</a>\n<div class=\"chosen-drop\">\n  <div class=\"chosen-search\">\n    <input class=\"chosen-search-input\" type=\"text\" autocomplete=\"off\" />\n  </div>\n  <ul class=\"chosen-results\"></ul>\n</div>";
    };

    AbstractChosen.prototype.get_multi_html = function() {
      return "<ul class=\"chosen-choices\">\n  <li class=\"search-field\">\n    <input class=\"chosen-search-input\" type=\"text\" autocomplete=\"off\" value=\"" + this.default_text + "\" />\n  </li>\n</ul>\n<div class=\"chosen-drop\">\n  <ul class=\"chosen-results\"></ul>\n</div>";
    };

    AbstractChosen.prototype.get_no_results_html = function(terms) {
      return "<li class=\"no-results\">\n  " + this.results_none_found + " <span>" + (this.escape_html(terms)) + "</span>\n</li>";
    };

    AbstractChosen.browser_is_supported = function() {
      if ("Microsoft Internet Explorer" === window.navigator.appName) {
        return document.documentMode >= 8;
      }
      if (/iP(od|hone)/i.test(window.navigator.userAgent) || /IEMobile/i.test(window.navigator.userAgent) || /Windows Phone/i.test(window.navigator.userAgent) || /BlackBerry/i.test(window.navigator.userAgent) || /BB10/i.test(window.navigator.userAgent) || /Android.*Mobile/i.test(window.navigator.userAgent)) {
        return false;
      }
      return true;
    };

    AbstractChosen.default_multiple_text = "Select Some Options";

    AbstractChosen.default_single_text = "Select an Option";

    AbstractChosen.default_no_result_text = "No results match";

    return AbstractChosen;

  })();

  $ = jQuery;

  $.fn.extend({
    chosen: function(options) {
      if (!AbstractChosen.browser_is_supported()) {
        return this;
      }
      return this.each(function(input_field) {
        var $this, chosen;
        $this = $(this);
        chosen = $this.data('chosen');
        if (options === 'destroy') {
          if (chosen instanceof Chosen) {
            chosen.destroy();
          }
          return;
        }
        if (!(chosen instanceof Chosen)) {
          $this.data('chosen', new Chosen(this, options));
        }
      });
    }
  });

  Chosen = (function(superClass) {
    extend(Chosen, superClass);

    function Chosen() {
      return Chosen.__super__.constructor.apply(this, arguments);
    }

    Chosen.prototype.setup = function() {
      this.form_field_jq = $(this.form_field);
      return this.current_selectedIndex = this.form_field.selectedIndex;
    };

    Chosen.prototype.set_up_html = function() {
      var container_classes, container_props;
      container_classes = ["chosen-container"];
      container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
      if (this.inherit_select_classes && this.form_field.className) {
        container_classes.push(this.form_field.className);
      }
      if (this.is_rtl) {
        container_classes.push("chosen-rtl");
      }
      container_props = {
        'class': container_classes.join(' '),
        'title': this.form_field.title
      };
      if (this.form_field.id.length) {
        container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
      }
      this.container = $("<div />", container_props);
      this.container.width(this.container_width());
      if (this.is_multiple) {
        this.container.html(this.get_multi_html());
      } else {
        this.container.html(this.get_single_html());
      }
      this.form_field_jq.hide().after(this.container);
      this.dropdown = this.container.find('div.chosen-drop').first();
      this.search_field = this.container.find('input').first();
      this.search_results = this.container.find('ul.chosen-results').first();
      this.search_field_scale();
      this.search_no_results = this.container.find('li.no-results').first();
      if (this.is_multiple) {
        this.search_choices = this.container.find('ul.chosen-choices').first();
        this.search_container = this.container.find('li.search-field').first();
      } else {
        this.search_container = this.container.find('div.chosen-search').first();
        this.selected_item = this.container.find('.chosen-single').first();
      }
      this.results_build();
      this.set_tab_index();
      return this.set_label_behavior();
    };

    Chosen.prototype.on_ready = function() {
      return this.form_field_jq.trigger("chosen:ready", {
        chosen: this
      });
    };

    Chosen.prototype.register_observers = function() {
      this.container.on('touchstart.chosen', (function(_this) {
        return function(evt) {
          _this.container_mousedown(evt);
        };
      })(this));
      this.container.on('touchend.chosen', (function(_this) {
        return function(evt) {
          _this.container_mouseup(evt);
        };
      })(this));
      this.container.on('mousedown.chosen', (function(_this) {
        return function(evt) {
          _this.container_mousedown(evt);
        };
      })(this));
      this.container.on('mouseup.chosen', (function(_this) {
        return function(evt) {
          _this.container_mouseup(evt);
        };
      })(this));
      this.container.on('mouseenter.chosen', (function(_this) {
        return function(evt) {
          _this.mouse_enter(evt);
        };
      })(this));
      this.container.on('mouseleave.chosen', (function(_this) {
        return function(evt) {
          _this.mouse_leave(evt);
        };
      })(this));
      this.search_results.on('mouseup.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_mouseup(evt);
        };
      })(this));
      this.search_results.on('mouseover.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_mouseover(evt);
        };
      })(this));
      this.search_results.on('mouseout.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_mouseout(evt);
        };
      })(this));
      this.search_results.on('mousewheel.chosen DOMMouseScroll.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_mousewheel(evt);
        };
      })(this));
      this.search_results.on('touchstart.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_touchstart(evt);
        };
      })(this));
      this.search_results.on('touchmove.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_touchmove(evt);
        };
      })(this));
      this.search_results.on('touchend.chosen', (function(_this) {
        return function(evt) {
          _this.search_results_touchend(evt);
        };
      })(this));
      this.form_field_jq.on("chosen:updated.chosen", (function(_this) {
        return function(evt) {
          _this.results_update_field(evt);
        };
      })(this));
      this.form_field_jq.on("chosen:activate.chosen", (function(_this) {
        return function(evt) {
          _this.activate_field(evt);
        };
      })(this));
      this.form_field_jq.on("chosen:open.chosen", (function(_this) {
        return function(evt) {
          _this.container_mousedown(evt);
        };
      })(this));
      this.form_field_jq.on("chosen:close.chosen", (function(_this) {
        return function(evt) {
          _this.close_field(evt);
        };
      })(this));
      this.search_field.on('blur.chosen', (function(_this) {
        return function(evt) {
          _this.input_blur(evt);
        };
      })(this));
      this.search_field.on('keyup.chosen', (function(_this) {
        return function(evt) {
          _this.keyup_checker(evt);
        };
      })(this));
      this.search_field.on('keydown.chosen', (function(_this) {
        return function(evt) {
          _this.keydown_checker(evt);
        };
      })(this));
      this.search_field.on('focus.chosen', (function(_this) {
        return function(evt) {
          _this.input_focus(evt);
        };
      })(this));
      this.search_field.on('cut.chosen', (function(_this) {
        return function(evt) {
          _this.clipboard_event_checker(evt);
        };
      })(this));
      this.search_field.on('paste.chosen', (function(_this) {
        return function(evt) {
          _this.clipboard_event_checker(evt);
        };
      })(this));
      if (this.is_multiple) {
        return this.search_choices.on('click.chosen', (function(_this) {
          return function(evt) {
            _this.choices_click(evt);
          };
        })(this));
      } else {
        return this.container.on('click.chosen', function(evt) {
          evt.preventDefault();
        });
      }
    };

    Chosen.prototype.destroy = function() {
      $(this.container[0].ownerDocument).off('click.chosen', this.click_test_action);
      if (this.form_field_label.length > 0) {
        this.form_field_label.off('click.chosen');
      }
      if (this.search_field[0].tabIndex) {
        this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
      }
      this.container.remove();
      this.form_field_jq.removeData('chosen');
      return this.form_field_jq.show();
    };

    Chosen.prototype.search_field_disabled = function() {
      this.is_disabled = this.form_field.disabled || this.form_field_jq.parents('fieldset').is(':disabled');
      this.container.toggleClass('chosen-disabled', this.is_disabled);
      this.search_field[0].disabled = this.is_disabled;
      if (!this.is_multiple) {
        this.selected_item.off('focus.chosen', this.activate_field);
      }
      if (this.is_disabled) {
        return this.close_field();
      } else if (!this.is_multiple) {
        return this.selected_item.on('focus.chosen', this.activate_field);
      }
    };

    Chosen.prototype.container_mousedown = function(evt) {
      var ref;
      if (this.is_disabled) {
        return;
      }
      if (evt && ((ref = evt.type) === 'mousedown' || ref === 'touchstart') && !this.results_showing) {
        evt.preventDefault();
      }
      if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
        if (!this.active_field) {
          if (this.is_multiple) {
            this.search_field.val("");
          }
          $(this.container[0].ownerDocument).on('click.chosen', this.click_test_action);
          this.results_show();
        } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
          evt.preventDefault();
          this.results_toggle();
        }
        return this.activate_field();
      }
    };

    Chosen.prototype.container_mouseup = function(evt) {
      if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
        return this.results_reset(evt);
      }
    };

    Chosen.prototype.search_results_mousewheel = function(evt) {
      var delta;
      if (evt.originalEvent) {
        delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
      }
      if (delta != null) {
        evt.preventDefault();
        if (evt.type === 'DOMMouseScroll') {
          delta = delta * 40;
        }
        return this.search_results.scrollTop(delta + this.search_results.scrollTop());
      }
    };

    Chosen.prototype.blur_test = function(evt) {
      if (!this.active_field && this.container.hasClass("chosen-container-active")) {
        return this.close_field();
      }
    };

    Chosen.prototype.close_field = function() {
      $(this.container[0].ownerDocument).off("click.chosen", this.click_test_action);
      this.active_field = false;
      this.results_hide();
      this.container.removeClass("chosen-container-active");
      this.clear_backstroke();
      this.show_search_field_default();
      this.search_field_scale();
      return this.search_field.blur();
    };

    Chosen.prototype.activate_field = function() {
      if (this.is_disabled) {
        return;
      }
      this.container.addClass("chosen-container-active");
      this.active_field = true;
      this.search_field.val(this.search_field.val());
      return this.search_field.focus();
    };

    Chosen.prototype.test_active_click = function(evt) {
      var active_container;
      active_container = $(evt.target).closest('.chosen-container');
      if (active_container.length && this.container[0] === active_container[0]) {
        return this.active_field = true;
      } else {
        return this.close_field();
      }
    };

    Chosen.prototype.results_build = function() {
      this.parsing = true;
      this.selected_option_count = null;
      this.results_data = SelectParser.select_to_array(this.form_field);
      if (this.is_multiple) {
        this.search_choices.find("li.search-choice").remove();
      } else {
        this.single_set_selected_text();
        if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
          this.search_field[0].readOnly = true;
          this.container.addClass("chosen-container-single-nosearch");
        } else {
          this.search_field[0].readOnly = false;
          this.container.removeClass("chosen-container-single-nosearch");
        }
      }
      this.update_results_content(this.results_option_build({
        first: true
      }));
      this.search_field_disabled();
      this.show_search_field_default();
      this.search_field_scale();
      return this.parsing = false;
    };

    Chosen.prototype.result_do_highlight = function(el) {
      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
      if (el.length) {
        this.result_clear_highlight();
        this.result_highlight = el;
        this.result_highlight.addClass("highlighted");
        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
        visible_top = this.search_results.scrollTop();
        visible_bottom = maxHeight + visible_top;
        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
        high_bottom = high_top + this.result_highlight.outerHeight();
        if (high_bottom >= visible_bottom) {
          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
        } else if (high_top < visible_top) {
          return this.search_results.scrollTop(high_top);
        }
      }
    };

    Chosen.prototype.result_clear_highlight = function() {
      if (this.result_highlight) {
        this.result_highlight.removeClass("highlighted");
      }
      return this.result_highlight = null;
    };

    Chosen.prototype.results_show = function() {
      if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
        this.form_field_jq.trigger("chosen:maxselected", {
          chosen: this
        });
        return false;
      }
      this.container.addClass("chosen-with-drop");
      this.results_showing = true;
      this.search_field.focus();
      this.search_field.val(this.get_search_field_value());
      this.winnow_results();
      return this.form_field_jq.trigger("chosen:showing_dropdown", {
        chosen: this
      });
    };

    Chosen.prototype.update_results_content = function(content) {
      return this.search_results.html(content);
    };

    Chosen.prototype.results_hide = function() {
      if (this.results_showing) {
        this.result_clear_highlight();
        this.container.removeClass("chosen-with-drop");
        this.form_field_jq.trigger("chosen:hiding_dropdown", {
          chosen: this
        });
      }
      return this.results_showing = false;
    };

    Chosen.prototype.set_tab_index = function(el) {
      var ti;
      if (this.form_field.tabIndex) {
        ti = this.form_field.tabIndex;
        this.form_field.tabIndex = -1;
        return this.search_field[0].tabIndex = ti;
      }
    };

    Chosen.prototype.set_label_behavior = function() {
      this.form_field_label = this.form_field_jq.parents("label");
      if (!this.form_field_label.length && this.form_field.id.length) {
        this.form_field_label = $("label[for='" + this.form_field.id + "']");
      }
      if (this.form_field_label.length > 0) {
        return this.form_field_label.on('click.chosen', this.label_click_handler);
      }
    };

    Chosen.prototype.show_search_field_default = function() {
      if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
        this.search_field.val(this.default_text);
        return this.search_field.addClass("default");
      } else {
        this.search_field.val("");
        return this.search_field.removeClass("default");
      }
    };

    Chosen.prototype.search_results_mouseup = function(evt) {
      var target;
      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
      if (target.length) {
        this.result_highlight = target;
        this.result_select(evt);
        return this.search_field.focus();
      }
    };

    Chosen.prototype.search_results_mouseover = function(evt) {
      var target;
      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
      if (target) {
        return this.result_do_highlight(target);
      }
    };

    Chosen.prototype.search_results_mouseout = function(evt) {
      if ($(evt.target).hasClass("active-result") || $(evt.target).parents('.active-result').first()) {
        return this.result_clear_highlight();
      }
    };

    Chosen.prototype.choice_build = function(item) {
      var choice, close_link;
      choice = $('<li />', {
        "class": "search-choice"
      }).html("<span>" + (this.choice_label(item)) + "</span>");
      if (item.disabled) {
        choice.addClass('search-choice-disabled');
      } else {
        close_link = $('<a />', {
          "class": 'search-choice-close',
          'data-option-array-index': item.array_index
        });
        close_link.on('click.chosen', (function(_this) {
          return function(evt) {
            return _this.choice_destroy_link_click(evt);
          };
        })(this));
        choice.append(close_link);
      }
      return this.search_container.before(choice);
    };

    Chosen.prototype.choice_destroy_link_click = function(evt) {
      evt.preventDefault();
      evt.stopPropagation();
      if (!this.is_disabled) {
        return this.choice_destroy($(evt.target));
      }
    };

    Chosen.prototype.choice_destroy = function(link) {
      if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
        if (this.active_field) {
          this.search_field.focus();
        } else {
          this.show_search_field_default();
        }
        if (this.is_multiple && this.choices_count() > 0 && this.get_search_field_value().length < 1) {
          this.results_hide();
        }
        link.parents('li').first().remove();
        return this.search_field_scale();
      }
    };

    Chosen.prototype.results_reset = function() {
      this.reset_single_select_options();
      this.form_field.options[0].selected = true;
      this.single_set_selected_text();
      this.show_search_field_default();
      this.results_reset_cleanup();
      this.trigger_form_field_change();
      if (this.active_field) {
        return this.results_hide();
      }
    };

    Chosen.prototype.results_reset_cleanup = function() {
      this.current_selectedIndex = this.form_field.selectedIndex;
      return this.selected_item.find("abbr").remove();
    };

    Chosen.prototype.result_select = function(evt) {
      var high, item;
      if (this.result_highlight) {
        high = this.result_highlight;
        this.result_clear_highlight();
        if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
          this.form_field_jq.trigger("chosen:maxselected", {
            chosen: this
          });
          return false;
        }
        if (this.is_multiple) {
          high.removeClass("active-result");
        } else {
          this.reset_single_select_options();
        }
        high.addClass("result-selected");
        item = this.results_data[high[0].getAttribute("data-option-array-index")];
        item.selected = true;
        this.form_field.options[item.options_index].selected = true;
        this.selected_option_count = null;
        if (this.is_multiple) {
          this.choice_build(item);
        } else {
          this.single_set_selected_text(this.choice_label(item));
        }
        if (this.is_multiple && (!this.hide_results_on_select || (evt.metaKey || evt.ctrlKey))) {
          if (evt.metaKey || evt.ctrlKey) {
            this.winnow_results({
              skip_highlight: true
            });
          } else {
            this.search_field.val("");
            this.winnow_results();
          }
        } else {
          this.results_hide();
          this.show_search_field_default();
        }
        if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
          this.trigger_form_field_change({
            selected: this.form_field.options[item.options_index].value
          });
        }
        this.current_selectedIndex = this.form_field.selectedIndex;
        evt.preventDefault();
        return this.search_field_scale();
      }
    };

    Chosen.prototype.single_set_selected_text = function(text) {
      if (text == null) {
        text = this.default_text;
      }
      if (text === this.default_text) {
        this.selected_item.addClass("chosen-default");
      } else {
        this.single_deselect_control_build();
        this.selected_item.removeClass("chosen-default");
      }
      return this.selected_item.find("span").html(text);
    };

    Chosen.prototype.result_deselect = function(pos) {
      var result_data;
      result_data = this.results_data[pos];
      if (!this.form_field.options[result_data.options_index].disabled) {
        result_data.selected = false;
        this.form_field.options[result_data.options_index].selected = false;
        this.selected_option_count = null;
        this.result_clear_highlight();
        if (this.results_showing) {
          this.winnow_results();
        }
        this.trigger_form_field_change({
          deselected: this.form_field.options[result_data.options_index].value
        });
        this.search_field_scale();
        return true;
      } else {
        return false;
      }
    };

    Chosen.prototype.single_deselect_control_build = function() {
      if (!this.allow_single_deselect) {
        return;
      }
      if (!this.selected_item.find("abbr").length) {
        this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
      }
      return this.selected_item.addClass("chosen-single-with-deselect");
    };

    Chosen.prototype.get_search_field_value = function() {
      return this.search_field.val();
    };

    Chosen.prototype.get_search_text = function() {
      return $.trim(this.get_search_field_value());
    };

    Chosen.prototype.escape_html = function(text) {
      return $('<div/>').text(text).html();
    };

    Chosen.prototype.winnow_results_set_highlight = function() {
      var do_high, selected_results;
      selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
      do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
      if (do_high != null) {
        return this.result_do_highlight(do_high);
      }
    };

    Chosen.prototype.no_results = function(terms) {
      var no_results_html;
      no_results_html = this.get_no_results_html(terms);
      this.search_results.append(no_results_html);
      return this.form_field_jq.trigger("chosen:no_results", {
        chosen: this
      });
    };

    Chosen.prototype.no_results_clear = function() {
      return this.search_results.find(".no-results").remove();
    };

    Chosen.prototype.keydown_arrow = function() {
      var next_sib;
      if (this.results_showing && this.result_highlight) {
        next_sib = this.result_highlight.nextAll("li.active-result").first();
        if (next_sib) {
          return this.result_do_highlight(next_sib);
        }
      } else {
        return this.results_show();
      }
    };

    Chosen.prototype.keyup_arrow = function() {
      var prev_sibs;
      if (!this.results_showing && !this.is_multiple) {
        return this.results_show();
      } else if (this.result_highlight) {
        prev_sibs = this.result_highlight.prevAll("li.active-result");
        if (prev_sibs.length) {
          return this.result_do_highlight(prev_sibs.first());
        } else {
          if (this.choices_count() > 0) {
            this.results_hide();
          }
          return this.result_clear_highlight();
        }
      }
    };

    Chosen.prototype.keydown_backstroke = function() {
      var next_available_destroy;
      if (this.pending_backstroke) {
        this.choice_destroy(this.pending_backstroke.find("a").first());
        return this.clear_backstroke();
      } else {
        next_available_destroy = this.search_container.siblings("li.search-choice").last();
        if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
          this.pending_backstroke = next_available_destroy;
          if (this.single_backstroke_delete) {
            return this.keydown_backstroke();
          } else {
            return this.pending_backstroke.addClass("search-choice-focus");
          }
        }
      }
    };

    Chosen.prototype.clear_backstroke = function() {
      if (this.pending_backstroke) {
        this.pending_backstroke.removeClass("search-choice-focus");
      }
      return this.pending_backstroke = null;
    };

    Chosen.prototype.search_field_scale = function() {
      var div, i, len, style, style_block, styles, width;
      if (!this.is_multiple) {
        return;
      }
      style_block = {
        position: 'absolute',
        left: '-1000px',
        top: '-1000px',
        display: 'none',
        whiteSpace: 'pre'
      };
      styles = ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing'];
      for (i = 0, len = styles.length; i < len; i++) {
        style = styles[i];
        style_block[style] = this.search_field.css(style);
      }
      div = $('<div />').css(style_block);
      div.text(this.get_search_field_value());
      $('body').append(div);
      width = div.width() + 25;
      div.remove();
      if (this.container.is(':visible')) {
        width = Math.min(this.container.outerWidth() - 10, width);
      }
      return this.search_field.width(width);
    };

    Chosen.prototype.trigger_form_field_change = function(extra) {
      this.form_field_jq.trigger("input", extra);
      return this.form_field_jq.trigger("change", extra);
    };

    return Chosen;

  })(AbstractChosen);

}).call(this);

/*
 * debouncedresize: special jQuery event that happens once after a window resize
 *
 * latest version and complete README available on Github:
 * https://github.com/louisremi/jquery-smartresize
 *
 * Copyright 2012 @louis_remi
 * Licensed under the MIT license.
 *
 * This saved you an hour of work? 
 * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON
 */
(function($) {

var $event = $.event,
  $special,
  resizeTimeout;

$special = $event.special.debouncedresize = {
  setup: function() {
    $( this ).on( "resize", $special.handler );
  },
  teardown: function() {
    $( this ).off( "resize", $special.handler );
  },
  handler: function( event, execAsap ) {
    // Save the context
    var context = this,
      args = arguments,
      dispatch = function() {
        // set correct event type
        event.type = "debouncedresize";
        $event.dispatch.apply( context, args );
      };

    if ( resizeTimeout ) {
      clearTimeout( resizeTimeout );
    }

    execAsap ?
      dispatch() :
      resizeTimeout = setTimeout( dispatch, $special.threshold ); 
  },
  threshold: 150
};

})(jQuery);
/*!
 * imagesLoaded PACKAGED v3.1.8
 * JavaScript is all like "You images are done yet or what?"
 * MIT License
 */


/*!
 * EventEmitter v4.2.6 - git.io/ee
 * Oliver Caldwell
 * MIT license
 * @preserve
 */

(function () {


    /**
     * Class for managing events.
     * Can be extended to provide event functionality in other classes.
     *
     * @class EventEmitter Manages event registering and emitting.
     */
    function EventEmitter() {}

    // Shortcuts to improve speed and size
    var proto = EventEmitter.prototype;
    var exports = this;
    var originalGlobalValue = exports.EventEmitter;

    /**
     * Finds the index of the listener for the event in it's storage array.
     *
     * @param {Function[]} listeners Array of listeners to search through.
     * @param {Function} listener Method to look for.
     * @return {Number} Index of the specified listener, -1 if not found
     * @api private
     */
    function indexOfListener(listeners, listener) {
        var i = listeners.length;
        while (i--) {
            if (listeners[i].listener === listener) {
                return i;
            }
        }

        return -1;
    }

    /**
     * Alias a method while keeping the context correct, to allow for overwriting of target method.
     *
     * @param {String} name The name of the target method.
     * @return {Function} The aliased method
     * @api private
     */
    function alias(name) {
        return function aliasClosure() {
            return this[name].apply(this, arguments);
        };
    }

    /**
     * Returns the listener array for the specified event.
     * Will initialise the event object and listener arrays if required.
     * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
     * Each property in the object response is an array of listener functions.
     *
     * @param {String|RegExp} evt Name of the event to return the listeners from.
     * @return {Function[]|Object} All listener functions for the event.
     */
    proto.getListeners = function getListeners(evt) {
        var events = this._getEvents();
        var response;
        var key;

        // Return a concatenated array of all matching events if
        // the selector is a regular expression.
        if (typeof evt === 'object') {
            response = {};
            for (key in events) {
                if (events.hasOwnProperty(key) && evt.test(key)) {
                    response[key] = events[key];
                }
            }
        }
        else {
            response = events[evt] || (events[evt] = []);
        }

        return response;
    };

    /**
     * Takes a list of listener objects and flattens it into a list of listener functions.
     *
     * @param {Object[]} listeners Raw listener objects.
     * @return {Function[]} Just the listener functions.
     */
    proto.flattenListeners = function flattenListeners(listeners) {
        var flatListeners = [];
        var i;

        for (i = 0; i < listeners.length; i += 1) {
            flatListeners.push(listeners[i].listener);
        }

        return flatListeners;
    };

    /**
     * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
     *
     * @param {String|RegExp} evt Name of the event to return the listeners from.
     * @return {Object} All listener functions for an event in an object.
     */
    proto.getListenersAsObject = function getListenersAsObject(evt) {
        var listeners = this.getListeners(evt);
        var response;

        if (listeners instanceof Array) {
            response = {};
            response[evt] = listeners;
        }

        return response || listeners;
    };

    /**
     * Adds a listener function to the specified event.
     * The listener will not be added if it is a duplicate.
     * If the listener returns true then it will be removed after it is called.
     * If you pass a regular expression as the event name then the listener will be added to all events that match it.
     *
     * @param {String|RegExp} evt Name of the event to attach the listener to.
     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.addListener = function addListener(evt, listener) {
        var listeners = this.getListenersAsObject(evt);
        var listenerIsWrapped = typeof listener === 'object';
        var key;

        for (key in listeners) {
            if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
                listeners[key].push(listenerIsWrapped ? listener : {
                    listener: listener,
                    once: false
                });
            }
        }

        return this;
    };

    /**
     * Alias of addListener
     */
    proto.on = alias('addListener');

    /**
     * Semi-alias of addListener. It will add a listener that will be
     * automatically removed after it's first execution.
     *
     * @param {String|RegExp} evt Name of the event to attach the listener to.
     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.addOnceListener = function addOnceListener(evt, listener) {
        return this.addListener(evt, {
            listener: listener,
            once: true
        });
    };

    /**
     * Alias of addOnceListener.
     */
    proto.once = alias('addOnceListener');

    /**
     * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
     * You need to tell it what event names should be matched by a regex.
     *
     * @param {String} evt Name of the event to create.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.defineEvent = function defineEvent(evt) {
        this.getListeners(evt);
        return this;
    };

    /**
     * Uses defineEvent to define multiple events.
     *
     * @param {String[]} evts An array of event names to define.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.defineEvents = function defineEvents(evts) {
        for (var i = 0; i < evts.length; i += 1) {
            this.defineEvent(evts[i]);
        }
        return this;
    };

    /**
     * Removes a listener function from the specified event.
     * When passed a regular expression as the event name, it will remove the listener from all events that match it.
     *
     * @param {String|RegExp} evt Name of the event to remove the listener from.
     * @param {Function} listener Method to remove from the event.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.removeListener = function removeListener(evt, listener) {
        var listeners = this.getListenersAsObject(evt);
        var index;
        var key;

        for (key in listeners) {
            if (listeners.hasOwnProperty(key)) {
                index = indexOfListener(listeners[key], listener);

                if (index !== -1) {
                    listeners[key].splice(index, 1);
                }
            }
        }

        return this;
    };

    /**
     * Alias of removeListener
     */
    proto.off = alias('removeListener');

    /**
     * Adds listeners in bulk using the manipulateListeners method.
     * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
     * You can also pass it a regular expression to add the array of listeners to all events that match it.
     * Yeah, this function does quite a bit. That's probably a bad thing.
     *
     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
     * @param {Function[]} [listeners] An optional array of listener functions to add.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.addListeners = function addListeners(evt, listeners) {
        // Pass through to manipulateListeners
        return this.manipulateListeners(false, evt, listeners);
    };

    /**
     * Removes listeners in bulk using the manipulateListeners method.
     * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
     * You can also pass it an event name and an array of listeners to be removed.
     * You can also pass it a regular expression to remove the listeners from all events that match it.
     *
     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
     * @param {Function[]} [listeners] An optional array of listener functions to remove.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.removeListeners = function removeListeners(evt, listeners) {
        // Pass through to manipulateListeners
        return this.manipulateListeners(true, evt, listeners);
    };

    /**
     * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
     * The first argument will determine if the listeners are removed (true) or added (false).
     * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
     * You can also pass it an event name and an array of listeners to be added/removed.
     * You can also pass it a regular expression to manipulate the listeners of all events that match it.
     *
     * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
     * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
        var i;
        var value;
        var single = remove ? this.removeListener : this.addListener;
        var multiple = remove ? this.removeListeners : this.addListeners;

        // If evt is an object then pass each of it's properties to this method
        if (typeof evt === 'object' && !(evt instanceof RegExp)) {
            for (i in evt) {
                if (evt.hasOwnProperty(i) && (value = evt[i])) {
                    // Pass the single listener straight through to the singular method
                    if (typeof value === 'function') {
                        single.call(this, i, value);
                    }
                    else {
                        // Otherwise pass back to the multiple function
                        multiple.call(this, i, value);
                    }
                }
            }
        }
        else {
            // So evt must be a string
            // And listeners must be an array of listeners
            // Loop over it and pass each one to the multiple method
            i = listeners.length;
            while (i--) {
                single.call(this, evt, listeners[i]);
            }
        }

        return this;
    };

    /**
     * Removes all listeners from a specified event.
     * If you do not specify an event then all listeners will be removed.
     * That means every event will be emptied.
     * You can also pass a regex to remove all events that match it.
     *
     * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.removeEvent = function removeEvent(evt) {
        var type = typeof evt;
        var events = this._getEvents();
        var key;

        // Remove different things depending on the state of evt
        if (type === 'string') {
            // Remove all listeners for the specified event
            delete events[evt];
        }
        else if (type === 'object') {
            // Remove all events matching the regex.
            for (key in events) {
                if (events.hasOwnProperty(key) && evt.test(key)) {
                    delete events[key];
                }
            }
        }
        else {
            // Remove all listeners in all events
            delete this._events;
        }

        return this;
    };

    /**
     * Alias of removeEvent.
     *
     * Added to mirror the node API.
     */
    proto.removeAllListeners = alias('removeEvent');

    /**
     * Emits an event of your choice.
     * When emitted, every listener attached to that event will be executed.
     * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
     * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
     * So they will not arrive within the array on the other side, they will be separate.
     * You can also pass a regular expression to emit to all events that match it.
     *
     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
     * @param {Array} [args] Optional array of arguments to be passed to each listener.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.emitEvent = function emitEvent(evt, args) {
        var listeners = this.getListenersAsObject(evt);
        var listener;
        var i;
        var key;
        var response;

        for (key in listeners) {
            if (listeners.hasOwnProperty(key)) {
                i = listeners[key].length;

                while (i--) {
                    // If the listener returns true then it shall be removed from the event
                    // The function is executed either with a basic call or an apply if there is an args array
                    listener = listeners[key][i];

                    if (listener.once === true) {
                        this.removeListener(evt, listener.listener);
                    }

                    response = listener.listener.apply(this, args || []);

                    if (response === this._getOnceReturnValue()) {
                        this.removeListener(evt, listener.listener);
                    }
                }
            }
        }

        return this;
    };

    /**
     * Alias of emitEvent
     */
    proto.trigger = alias('emitEvent');

    /**
     * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
     * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
     *
     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
     * @param {...*} Optional additional arguments to be passed to each listener.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.emit = function emit(evt) {
        var args = Array.prototype.slice.call(arguments, 1);
        return this.emitEvent(evt, args);
    };

    /**
     * Sets the current value to check against when executing listeners. If a
     * listeners return value matches the one set here then it will be removed
     * after execution. This value defaults to true.
     *
     * @param {*} value The new value to check for when executing listeners.
     * @return {Object} Current instance of EventEmitter for chaining.
     */
    proto.setOnceReturnValue = function setOnceReturnValue(value) {
        this._onceReturnValue = value;
        return this;
    };

    /**
     * Fetches the current value to check against when executing listeners. If
     * the listeners return value matches this one then it should be removed
     * automatically. It will return true by default.
     *
     * @return {*|Boolean} The current value to check for or the default, true.
     * @api private
     */
    proto._getOnceReturnValue = function _getOnceReturnValue() {
        if (this.hasOwnProperty('_onceReturnValue')) {
            return this._onceReturnValue;
        }
        else {
            return true;
        }
    };

    /**
     * Fetches the events object and creates one if required.
     *
     * @return {Object} The events storage object.
     * @api private
     */
    proto._getEvents = function _getEvents() {
        return this._events || (this._events = {});
    };

    /**
     * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
     *
     * @return {Function} Non conflicting EventEmitter class.
     */
    EventEmitter.noConflict = function noConflict() {
        exports.EventEmitter = originalGlobalValue;
        return EventEmitter;
    };

    // Expose the class either via AMD, CommonJS or the global object
    if (typeof define === 'function' && define.amd) {
        define('eventEmitter/EventEmitter',[],function () {
            return EventEmitter;
        });
    }
    else if (typeof module === 'object' && module.exports){
        module.exports = EventEmitter;
    }
    else {
        this.EventEmitter = EventEmitter;
    }
}.call(this));

/*!
 * eventie v1.0.4
 * event binding helper
 *   eventie.bind( elem, 'click', myFn )
 *   eventie.unbind( elem, 'click', myFn )
 */

/*jshint browser: true, undef: true, unused: true */
/*global define: false */

( function( window ) {



var docElem = document.documentElement;

var bind = function() {};

function getIEEvent( obj ) {
  var event = window.event;
  // add event.target
  event.target = event.target || event.srcElement || obj;
  return event;
}

if ( docElem.addEventListener ) {
  bind = function( obj, type, fn ) {
    obj.addEventListener( type, fn, false );
  };
} else if ( docElem.attachEvent ) {
  bind = function( obj, type, fn ) {
    obj[ type + fn ] = fn.handleEvent ?
      function() {
        var event = getIEEvent( obj );
        fn.handleEvent.call( fn, event );
      } :
      function() {
        var event = getIEEvent( obj );
        fn.call( obj, event );
      };
    obj.attachEvent( "on" + type, obj[ type + fn ] );
  };
}

var unbind = function() {};

if ( docElem.removeEventListener ) {
  unbind = function( obj, type, fn ) {
    obj.removeEventListener( type, fn, false );
  };
} else if ( docElem.detachEvent ) {
  unbind = function( obj, type, fn ) {
    obj.detachEvent( "on" + type, obj[ type + fn ] );
    try {
      delete obj[ type + fn ];
    } catch ( err ) {
      // can't delete window object properties
      obj[ type + fn ] = undefined;
    }
  };
}

var eventie = {
  bind: bind,
  unbind: unbind
};

// transport
if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( 'eventie/eventie',eventie );
} else {
  // browser global
  window.eventie = eventie;
}

})( this );

/*!
 * imagesLoaded v3.1.8
 * JavaScript is all like "You images are done yet or what?"
 * MIT License
 */

( function( window, factory ) {
  // universal module definition

  /*global define: false, module: false, require: false */

  if ( typeof define === 'function' && define.amd ) {
    // AMD
    define( [
      'eventEmitter/EventEmitter',
      'eventie/eventie'
    ], function( EventEmitter, eventie ) {
      return factory( window, EventEmitter, eventie );
    });
  } else if ( typeof exports === 'object' ) {
    // CommonJS
    module.exports = factory(
      window,
      require('wolfy87-eventemitter'),
      require('eventie')
    );
  } else {
    // browser global
    window.imagesLoaded = factory(
      window,
      window.EventEmitter,
      window.eventie
    );
  }

})( window,

// --------------------------  factory -------------------------- //

function factory( window, EventEmitter, eventie ) {



var $ = window.jQuery;
var console = window.console;
var hasConsole = typeof console !== 'undefined';

// -------------------------- helpers -------------------------- //

// extend objects
function extend( a, b ) {
  for ( var prop in b ) {
    a[ prop ] = b[ prop ];
  }
  return a;
}

var objToString = Object.prototype.toString;
function isArray( obj ) {
  return objToString.call( obj ) === '[object Array]';
}

// turn element or nodeList into an array
function makeArray( obj ) {
  var ary = [];
  if ( isArray( obj ) ) {
    // use object if already an array
    ary = obj;
  } else if ( typeof obj.length === 'number' ) {
    // convert nodeList to array
    for ( var i=0, len = obj.length; i < len; i++ ) {
      ary.push( obj[i] );
    }
  } else {
    // array of single index
    ary.push( obj );
  }
  return ary;
}

  // -------------------------- imagesLoaded -------------------------- //

  /**
   * @param {Array, Element, NodeList, String} elem
   * @param {Object or Function} options - if function, use as callback
   * @param {Function} onAlways - callback function
   */
  function ImagesLoaded( elem, options, onAlways ) {
    // coerce ImagesLoaded() without new, to be new ImagesLoaded()
    if ( !( this instanceof ImagesLoaded ) ) {
      return new ImagesLoaded( elem, options );
    }
    // use elem as selector string
    if ( typeof elem === 'string' ) {
      elem = document.querySelectorAll( elem );
    }

    this.elements = makeArray( elem );
    this.options = extend( {}, this.options );

    if ( typeof options === 'function' ) {
      onAlways = options;
    } else {
      extend( this.options, options );
    }

    if ( onAlways ) {
      this.on( 'always', onAlways );
    }

    this.getImages();

    if ( $ ) {
      // add jQuery Deferred object
      this.jqDeferred = new $.Deferred();
    }

    // HACK check async to allow time to bind listeners
    var _this = this;
    setTimeout( function() {
      _this.check();
    });
  }

  ImagesLoaded.prototype = new EventEmitter();

  ImagesLoaded.prototype.options = {};

  ImagesLoaded.prototype.getImages = function() {
    this.images = [];

    // filter & find items if we have an item selector
    for ( var i=0, len = this.elements.length; i < len; i++ ) {
      var elem = this.elements[i];
      // filter siblings
      if ( elem.nodeName === 'IMG' ) {
        this.addImage( elem );
      }
      // find children
      // no non-element nodes, #143
      var nodeType = elem.nodeType;
      if ( !nodeType || !( nodeType === 1 || nodeType === 9 || nodeType === 11 ) ) {
        continue;
      }
      var childElems = elem.querySelectorAll('img');
      // concat childElems to filterFound array
      for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
        var img = childElems[j];
        this.addImage( img );
      }
    }
  };

  /**
   * @param {Image} img
   */
  ImagesLoaded.prototype.addImage = function( img ) {
    var loadingImage = new LoadingImage( img );
    this.images.push( loadingImage );
  };

  ImagesLoaded.prototype.check = function() {
    var _this = this;
    var checkedCount = 0;
    var length = this.images.length;
    this.hasAnyBroken = false;
    // complete if no images
    if ( !length ) {
      this.complete();
      return;
    }

    function onConfirm( image, message ) {
      if ( _this.options.debug && hasConsole ) {
        console.log( 'confirm', image, message );
      }

      _this.progress( image );
      checkedCount++;
      if ( checkedCount === length ) {
        _this.complete();
      }
      return true; // bind once
    }

    for ( var i=0; i < length; i++ ) {
      var loadingImage = this.images[i];
      loadingImage.on( 'confirm', onConfirm );
      loadingImage.check();
    }
  };

  ImagesLoaded.prototype.progress = function( image ) {
    this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
    // HACK - Chrome triggers event before object properties have changed. #83
    var _this = this;
    setTimeout( function() {
      _this.emit( 'progress', _this, image );
      if ( _this.jqDeferred && _this.jqDeferred.notify ) {
        _this.jqDeferred.notify( _this, image );
      }
    });
  };

  ImagesLoaded.prototype.complete = function() {
    var eventName = this.hasAnyBroken ? 'fail' : 'done';
    this.isComplete = true;
    var _this = this;
    // HACK - another setTimeout so that confirm happens after progress
    setTimeout( function() {
      _this.emit( eventName, _this );
      _this.emit( 'always', _this );
      if ( _this.jqDeferred ) {
        var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
        _this.jqDeferred[ jqMethod ]( _this );
      }
    });
  };

  // -------------------------- jquery -------------------------- //

  if ( $ ) {
    $.fn.imagesLoaded = function( options, callback ) {
      var instance = new ImagesLoaded( this, options, callback );
      return instance.jqDeferred.promise( $(this) );
    };
  }


  // --------------------------  -------------------------- //

  function LoadingImage( img ) {
    this.img = img;
  }

  LoadingImage.prototype = new EventEmitter();

  LoadingImage.prototype.check = function() {
    // first check cached any previous images that have same src
    var resource = cache[ this.img.src ] || new Resource( this.img.src );
    if ( resource.isConfirmed ) {
      this.confirm( resource.isLoaded, 'cached was confirmed' );
      return;
    }

    // If complete is true and browser supports natural sizes,
    // try to check for image status manually.
    if ( this.img.complete && this.img.naturalWidth !== undefined ) {
      // report based on naturalWidth
      this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
      return;
    }

    // If none of the checks above matched, simulate loading on detached element.
    var _this = this;
    resource.on( 'confirm', function( resrc, message ) {
      _this.confirm( resrc.isLoaded, message );
      return true;
    });

    resource.check();
  };

  LoadingImage.prototype.confirm = function( isLoaded, message ) {
    this.isLoaded = isLoaded;
    this.emit( 'confirm', this, message );
  };

  // -------------------------- Resource -------------------------- //

  // Resource checks each src, only once
  // separate class from LoadingImage to prevent memory leaks. See #115

  var cache = {};

  function Resource( src ) {
    this.src = src;
    // add to cache
    cache[ src ] = this;
  }

  Resource.prototype = new EventEmitter();

  Resource.prototype.check = function() {
    // only trigger checking once
    if ( this.isChecked ) {
      return;
    }
    // simulate loading on detached element
    var proxyImage = new Image();
    eventie.bind( proxyImage, 'load', this );
    eventie.bind( proxyImage, 'error', this );
    proxyImage.src = this.src;
    // set flag
    this.isChecked = true;
  };

  // ----- events ----- //

  // trigger specified handler for event type
  Resource.prototype.handleEvent = function( event ) {
    var method = 'on' + event.type;
    if ( this[ method ] ) {
      this[ method ]( event );
    }
  };

  Resource.prototype.onload = function( event ) {
    this.confirm( true, 'onload' );
    this.unbindProxyEvents( event );
  };

  Resource.prototype.onerror = function( event ) {
    this.confirm( false, 'onerror' );
    this.unbindProxyEvents( event );
  };

  // ----- confirm ----- //

  Resource.prototype.confirm = function( isLoaded, message ) {
    this.isConfirmed = true;
    this.isLoaded = isLoaded;
    this.emit( 'confirm', this, message );
  };

  Resource.prototype.unbindProxyEvents = function( event ) {
    eventie.unbind( event.target, 'load', this );
    eventie.unbind( event.target, 'error', this );
  };

  // -----  ----- //

  return ImagesLoaded;

});
/*!
 * JavaScript Cookie v2.2.1
 * https://github.com/js-cookie/js-cookie
 *
 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
 * Released under the MIT license
 */
;(function (factory) {
	var registeredInModuleLoader;
	if (typeof define === 'function' && define.amd) {
		define(factory);
		registeredInModuleLoader = true;
	}
	if (typeof exports === 'object') {
		module.exports = factory();
		registeredInModuleLoader = true;
	}
	if (!registeredInModuleLoader) {
		var OldCookies = window.Cookies;
		var api = window.Cookies = factory();
		api.noConflict = function () {
			window.Cookies = OldCookies;
			return api;
		};
	}
}(function () {
	function extend () {
		var i = 0;
		var result = {};
		for (; i < arguments.length; i++) {
			var attributes = arguments[ i ];
			for (var key in attributes) {
				result[key] = attributes[key];
			}
		}
		return result;
	}

	function decode (s) {
		return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
	}

	function init (converter) {
		function api() {}

		function set (key, value, attributes) {
			if (typeof document === 'undefined') {
				return;
			}

			attributes = extend({
				path: '/'
			}, api.defaults, attributes);

			if (typeof attributes.expires === 'number') {
				attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
			}

			// We're using "expires" because "max-age" is not supported by IE
			attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';

			try {
				var result = JSON.stringify(value);
				if (/^[\{\[]/.test(result)) {
					value = result;
				}
			} catch (e) {}

			value = converter.write ?
				converter.write(value, key) :
				encodeURIComponent(String(value))
				.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);

			key = encodeURIComponent(String(key))
			.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
			.replace(/[\(\)]/g, escape);

			var stringifiedAttributes = '';
			for (var attributeName in attributes) {
				if (!attributes[attributeName]) {
					continue;
				}
				stringifiedAttributes += '; ' + attributeName;
				if (attributes[attributeName] === true) {
					continue;
				}

				// Considers RFC 6265 section 5.2:
				// ...
				// 3.  If the remaining unparsed-attributes contains a %x3B (";")
				//     character:
				// Consume the characters of the unparsed-attributes up to,
				// not including, the first %x3B (";") character.
				// ...
				stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
			}

			return (document.cookie = key + '=' + value + stringifiedAttributes);
		}

		function get (key, json) {
			if (typeof document === 'undefined') {
				return;
			}

			var jar = {};
			// To prevent the for loop in the first place assign an empty array
			// in case there are no cookies at all.
			var cookies = document.cookie ? document.cookie.split('; ') : [];
			var i = 0;

			for (; i < cookies.length; i++) {
				var parts = cookies[i].split('=');
				var cookie = parts.slice(1).join('=');

				if (!json && cookie.charAt(0) === '"') {
					cookie = cookie.slice(1, -1);
				}

				try {
					var name = decode(parts[0]);
					cookie = (converter.read || converter)(cookie, name) ||
					         decode(cookie);

					if (json) {
						try {
							cookie = JSON.parse(cookie);
						} catch (e) {}
					}

					jar[name] = cookie;

					if (key === name) {
						break;
					}
				} catch (e) {}
			}

			return key ? jar[key] : jar;
		}

		api.set = set;
		api.get = function (key) {
			return get(key, false /* read as raw */);
		};
		api.getJSON = function (key) {
			return get(key, true /* read as json */);
		};
		api.remove = function (key, attributes) {
			set(key, '', extend(attributes, {
				expires: -1
			}));
		};

		api.defaults = {};

		api.withConverter = init;

		return api;
	}

	return init(function () {});
}));
/*! Magnific Popup - v1.1.0 - 2016-02-20
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2016 Dmitry Semenov; */
;(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(window.jQuery || window.Zepto);
	}
}(function($) {

	/*>>core*/
	/**
	 *
	 * Magnific Popup Core JS file
	 *
	 */


	/**
	 * Private static constants
	 */
	var CLOSE_EVENT = 'Close',
		BEFORE_CLOSE_EVENT = 'BeforeClose',
		AFTER_CLOSE_EVENT = 'AfterClose',
		BEFORE_APPEND_EVENT = 'BeforeAppend',
		MARKUP_PARSE_EVENT = 'MarkupParse',
		OPEN_EVENT = 'Open',
		CHANGE_EVENT = 'Change',
		NS = 'mfp',
		EVENT_NS = '.' + NS,
		READY_CLASS = 'mfp-ready',
		REMOVING_CLASS = 'mfp-removing',
		PREVENT_CLOSE_CLASS = 'mfp-prevent-close';


	/**
	 * Private vars
	 */
	/*jshint -W079 */
	var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
		MagnificPopup = function(){},
		_isJQ = !!(window.jQuery),
		_prevStatus,
		_window = $(window),
		_document,
		_prevContentType,
		_wrapClasses,
		_currPopupType;


	/**
	 * Private functions
	 */
	var _mfpOn = function(name, f) {
			mfp.ev.on(NS + name + EVENT_NS, f);
		},
		_getEl = function(className, appendTo, html, raw) {
			var el = document.createElement('div');
			el.className = 'mfp-'+className;
			if(html) {
				el.innerHTML = html;
			}
			if(!raw) {
				el = $(el);
				if(appendTo) {
					el.appendTo(appendTo);
				}
			} else if(appendTo) {
				appendTo.appendChild(el);
			}
			return el;
		},
		_mfpTrigger = function(e, data) {
			mfp.ev.triggerHandler(NS + e, data);

			if(mfp.st.callbacks) {
				// converts "mfpEventName" to "eventName" callback and triggers it if it's present
				e = e.charAt(0).toLowerCase() + e.slice(1);
				if(mfp.st.callbacks[e]) {
					mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
				}
			}
		},
		_getCloseBtn = function(type) {
			if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
				mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
				_currPopupType = type;
			}
			return mfp.currTemplate.closeBtn;
		},
		// Initialize Magnific Popup only when called at least once
		_checkInstance = function() {
			if(!$.magnificPopup.instance) {
				/*jshint -W020 */
				mfp = new MagnificPopup();
				mfp.init();
				$.magnificPopup.instance = mfp;
			}
		},
		// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
		supportsTransitions = function() {
			var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
				v = ['ms','O','Moz','Webkit']; // 'v' for vendor

			if( s['transition'] !== undefined ) {
				return true;
			}

			while( v.length ) {
				if( v.pop() + 'Transition' in s ) {
					return true;
				}
			}

			return false;
		};



	/**
	 * Public functions
	 */
	MagnificPopup.prototype = {

		constructor: MagnificPopup,

		/**
		 * Initializes Magnific Popup plugin.
		 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
		 */
		init: function() {
			var appVersion = navigator.appVersion;
			mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener;
			mfp.isAndroid = (/android/gi).test(appVersion);
			mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
			mfp.supportsTransition = supportsTransitions();

			// We disable fixed positioned lightbox on devices that don't handle it nicely.
			// If you know a better way of detecting this - let me know.
			mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
			_document = $(document);

			mfp.popupsCache = {};
		},

		/**
		 * Opens popup
		 * @param  data [description]
		 */
		open: function(data) {

			var i;

			if(data.isObj === false) {
				// convert jQuery collection to array to avoid conflicts later
				mfp.items = data.items.toArray();

				mfp.index = 0;
				var items = data.items,
					item;
				for(i = 0; i < items.length; i++) {
					item = items[i];
					if(item.parsed) {
						item = item.el[0];
					}
					if(item === data.el[0]) {
						mfp.index = i;
						break;
					}
				}
			} else {
				mfp.items = $.isArray(data.items) ? data.items : [data.items];
				mfp.index = data.index || 0;
			}

			// if popup is already opened - we just update the content
			if(mfp.isOpen) {
				mfp.updateItemHTML();
				return;
			}

			mfp.types = [];
			_wrapClasses = '';
			if(data.mainEl && data.mainEl.length) {
				mfp.ev = data.mainEl.eq(0);
			} else {
				mfp.ev = _document;
			}

			if(data.key) {
				if(!mfp.popupsCache[data.key]) {
					mfp.popupsCache[data.key] = {};
				}
				mfp.currTemplate = mfp.popupsCache[data.key];
			} else {
				mfp.currTemplate = {};
			}



			mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
			mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;

			if(mfp.st.modal) {
				mfp.st.closeOnContentClick = false;
				mfp.st.closeOnBgClick = false;
				mfp.st.showCloseBtn = false;
				mfp.st.enableEscapeKey = false;
			}


			// Building markup
			// main containers are created only once
			if(!mfp.bgOverlay) {

				// Dark overlay
				mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
					mfp.close();
				});

				mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
					if(mfp._checkIfClose(e.target)) {
						mfp.close();
					}
				});

				mfp.container = _getEl('container', mfp.wrap);
			}

			mfp.contentContainer = _getEl('content');
			if(mfp.st.preloader) {
				mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
			}


			// Initializing modules
			var modules = $.magnificPopup.modules;
			for(i = 0; i < modules.length; i++) {
				var n = modules[i];
				n = n.charAt(0).toUpperCase() + n.slice(1);
				mfp['init'+n].call(mfp);
			}
			_mfpTrigger('BeforeOpen');


			if(mfp.st.showCloseBtn) {
				// Close button
				if(!mfp.st.closeBtnInside) {
					mfp.wrap.append( _getCloseBtn() );
				} else {
					_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
						values.close_replaceWith = _getCloseBtn(item.type);
					});
					_wrapClasses += ' mfp-close-btn-in';
				}
			}

			if(mfp.st.alignTop) {
				_wrapClasses += ' mfp-align-top';
			}



			if(mfp.fixedContentPos) {
				mfp.wrap.css({
					overflow: mfp.st.overflowY,
					overflowX: 'hidden',
					overflowY: mfp.st.overflowY
				});
			} else {
				mfp.wrap.css({
					top: _window.scrollTop(),
					position: 'absolute'
				});
			}
			if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
				mfp.bgOverlay.css({
					height: _document.height(),
					position: 'absolute'
				});
			}



			if(mfp.st.enableEscapeKey) {
				// Close on ESC key
				_document.on('keyup' + EVENT_NS, function(e) {
					if(e.keyCode === 27) {
						mfp.close();
					}
				});
			}

			_window.on('resize' + EVENT_NS, function() {
				mfp.updateSize();
			});


			if(!mfp.st.closeOnContentClick) {
				_wrapClasses += ' mfp-auto-cursor';
			}

			if(_wrapClasses)
				mfp.wrap.addClass(_wrapClasses);


			// this triggers recalculation of layout, so we get it once to not to trigger twice
			var windowHeight = mfp.wH = _window.height();


			var windowStyles = {};

			if( mfp.fixedContentPos ) {
				if(mfp._hasScrollBar(windowHeight)){
					var s = mfp._getScrollbarSize();
					if(s) {
						windowStyles.marginRight = s;
					}
				}
			}

			if(mfp.fixedContentPos) {
				if(!mfp.isIE7) {
					windowStyles.overflow = 'hidden';
				} else {
					// ie7 double-scroll bug
					$('body, html').css('overflow', 'hidden');
				}
			}



			var classesToadd = mfp.st.mainClass;
			if(mfp.isIE7) {
				classesToadd += ' mfp-ie7';
			}
			if(classesToadd) {
				mfp._addClassToMFP( classesToadd );
			}

			// add content
			mfp.updateItemHTML();

			_mfpTrigger('BuildControls');

			// remove scrollbar, add margin e.t.c
			$('html').css(windowStyles);

			// add everything to DOM
			mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) );

			// Save last focused element
			mfp._lastFocusedEl = document.activeElement;

			// Wait for next cycle to allow CSS transition
			setTimeout(function() {

				if(mfp.content) {
					mfp._addClassToMFP(READY_CLASS);
					mfp._setFocus();
				} else {
					// if content is not defined (not loaded e.t.c) we add class only for BG
					mfp.bgOverlay.addClass(READY_CLASS);
				}

				// Trap the focus in popup
				_document.on('focusin' + EVENT_NS, mfp._onFocusIn);

			}, 16);

			mfp.isOpen = true;
			mfp.updateSize(windowHeight);
			_mfpTrigger(OPEN_EVENT);

			return data;
		},

		/**
		 * Closes the popup
		 */
		close: function() {
			if(!mfp.isOpen) return;
			_mfpTrigger(BEFORE_CLOSE_EVENT);

			mfp.isOpen = false;
			// for CSS3 animation
			if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
				mfp._addClassToMFP(REMOVING_CLASS);
				setTimeout(function() {
					mfp._close();
				}, mfp.st.removalDelay);
			} else {
				mfp._close();
			}
		},

		/**
		 * Helper for close() function
		 */
		_close: function() {
			_mfpTrigger(CLOSE_EVENT);

			var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';

			mfp.bgOverlay.detach();
			mfp.wrap.detach();
			mfp.container.empty();

			if(mfp.st.mainClass) {
				classesToRemove += mfp.st.mainClass + ' ';
			}

			mfp._removeClassFromMFP(classesToRemove);

			if(mfp.fixedContentPos) {
				var windowStyles = {marginRight: ''};
				if(mfp.isIE7) {
					$('body, html').css('overflow', '');
				} else {
					windowStyles.overflow = '';
				}
				$('html').css(windowStyles);
			}

			_document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
			mfp.ev.off(EVENT_NS);

			// clean up DOM elements that aren't removed
			mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
			mfp.bgOverlay.attr('class', 'mfp-bg');
			mfp.container.attr('class', 'mfp-container');

			// remove close button from target element
			if(mfp.st.showCloseBtn &&
			   (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
				if(mfp.currTemplate.closeBtn)
					mfp.currTemplate.closeBtn.detach();
			}


			if(mfp.st.autoFocusLast && mfp._lastFocusedEl) {
				$(mfp._lastFocusedEl).focus(); // put tab focus back
			}
			mfp.currItem = null;
			mfp.content = null;
			mfp.currTemplate = null;
			mfp.prevHeight = 0;

			_mfpTrigger(AFTER_CLOSE_EVENT);
		},

		updateSize: function(winHeight) {

			if(mfp.isIOS) {
				// fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
				var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
				var height = window.innerHeight * zoomLevel;
				mfp.wrap.css('height', height);
				mfp.wH = height;
			} else {
				mfp.wH = winHeight || _window.height();
			}
			// Fixes #84: popup incorrectly positioned with position:relative on body
			if(!mfp.fixedContentPos) {
				mfp.wrap.css('height', mfp.wH);
			}

			_mfpTrigger('Resize');

		},

		/**
		 * Set content of popup based on current index
		 */
		updateItemHTML: function() {
			var item = mfp.items[mfp.index];

			// Detach and perform modifications
			mfp.contentContainer.detach();

			if(mfp.content)
				mfp.content.detach();

			if(!item.parsed) {
				item = mfp.parseEl( mfp.index );
			}

			var type = item.type;

			_mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
			// BeforeChange event works like so:
			// _mfpOn('BeforeChange', function(e, prevType, newType) { });

			mfp.currItem = item;

			if(!mfp.currTemplate[type]) {
				var markup = mfp.st[type] ? mfp.st[type].markup : false;

				// allows to modify markup
				_mfpTrigger('FirstMarkupParse', markup);

				if(markup) {
					mfp.currTemplate[type] = $(markup);
				} else {
					// if there is no markup found we just define that template is parsed
					mfp.currTemplate[type] = true;
				}
			}

			if(_prevContentType && _prevContentType !== item.type) {
				mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
			}

			var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
			mfp.appendContent(newContent, type);

			item.preloaded = true;

			_mfpTrigger(CHANGE_EVENT, item);
			_prevContentType = item.type;

			// Append container back after its content changed
			mfp.container.prepend(mfp.contentContainer);

			_mfpTrigger('AfterChange');
		},


		/**
		 * Set HTML content of popup
		 */
		appendContent: function(newContent, type) {
			mfp.content = newContent;

			if(newContent) {
				if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
				   mfp.currTemplate[type] === true) {
					// if there is no markup, we just append close button element inside
					if(!mfp.content.find('.mfp-close').length) {
						mfp.content.append(_getCloseBtn());
					}
				} else {
					mfp.content = newContent;
				}
			} else {
				mfp.content = '';
			}

			_mfpTrigger(BEFORE_APPEND_EVENT);
			mfp.container.addClass('mfp-'+type+'-holder');

			mfp.contentContainer.append(mfp.content);
		},


		/**
		 * Creates Magnific Popup data object based on given data
		 * @param  {int} index Index of item to parse
		 */
		parseEl: function(index) {
			var item = mfp.items[index],
				type;

			if(item.tagName) {
				item = { el: $(item) };
			} else {
				type = item.type;
				item = { data: item, src: item.src };
			}

			if(item.el) {
				var types = mfp.types;

				// check for 'mfp-TYPE' class
				for(var i = 0; i < types.length; i++) {
					if( item.el.hasClass('mfp-'+types[i]) ) {
						type = types[i];
						break;
					}
				}

				item.src = item.el.attr('data-mfp-src');
				if(!item.src) {
					item.src = item.el.attr('href');
				}
			}

			item.type = type || mfp.st.type || 'inline';
			item.index = index;
			item.parsed = true;
			mfp.items[index] = item;
			_mfpTrigger('ElementParse', item);

			return mfp.items[index];
		},


		/**
		 * Initializes single popup or a group of popups
		 */
		addGroup: function(el, options) {
			var eHandler = function(e) {
				e.mfpEl = this;
				mfp._openClick(e, el, options);
			};

			if(!options) {
				options = {};
			}

			var eName = 'click.magnificPopup';
			options.mainEl = el;

			if(options.items) {
				options.isObj = true;
				el.off(eName).on(eName, eHandler);
			} else {
				options.isObj = false;
				if(options.delegate) {
					el.off(eName).on(eName, options.delegate , eHandler);
				} else {
					options.items = el;
					el.off(eName).on(eName, eHandler);
				}
			}
		},
		_openClick: function(e, el, options) {
			var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;


			if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) {
				return;
			}

			var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;

			if(disableOn) {
				if($.isFunction(disableOn)) {
					if( !disableOn.call(mfp) ) {
						return true;
					}
				} else { // else it's number
					if( _window.width() < disableOn ) {
						return true;
					}
				}
			}

			if(e.type) {
				e.preventDefault();

				// This will prevent popup from closing if element is inside and popup is already opened
				if(mfp.isOpen) {
					e.stopPropagation();
				}
			}

			options.el = $(e.mfpEl);
			if(options.delegate) {
				options.items = el.find(options.delegate);
			}
			mfp.open(options);
		},


		/**
		 * Updates text on preloader
		 */
		updateStatus: function(status, text) {

			if(mfp.preloader) {
				if(_prevStatus !== status) {
					mfp.container.removeClass('mfp-s-'+_prevStatus);
				}

				if(!text && status === 'loading') {
					text = mfp.st.tLoading;
				}

				var data = {
					status: status,
					text: text
				};
				// allows to modify status
				_mfpTrigger('UpdateStatus', data);

				status = data.status;
				text = data.text;

				mfp.preloader.html(text);

				mfp.preloader.find('a').on('click', function(e) {
					e.stopImmediatePropagation();
				});

				mfp.container.addClass('mfp-s-'+status);
				_prevStatus = status;
			}
		},


		/*
			"Private" helpers that aren't private at all
		 */
		// Check to close popup or not
		// "target" is an element that was clicked
		_checkIfClose: function(target) {

			if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
				return;
			}

			var closeOnContent = mfp.st.closeOnContentClick;
			var closeOnBg = mfp.st.closeOnBgClick;

			if(closeOnContent && closeOnBg) {
				return true;
			} else {

				// We close the popup if click is on close button or on preloader. Or if there is no content.
				if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
					return true;
				}

				// if click is outside the content
				if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
					if(closeOnBg) {
						// last check, if the clicked element is in DOM, (in case it's removed onclick)
						if( $.contains(document, target) ) {
							return true;
						}
					}
				} else if(closeOnContent) {
					return true;
				}

			}
			return false;
		},
		_addClassToMFP: function(cName) {
			mfp.bgOverlay.addClass(cName);
			mfp.wrap.addClass(cName);
		},
		_removeClassFromMFP: function(cName) {
			this.bgOverlay.removeClass(cName);
			mfp.wrap.removeClass(cName);
		},
		_hasScrollBar: function(winHeight) {
			return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
		},
		_setFocus: function() {
			(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
		},
		_onFocusIn: function(e) {
			if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
				mfp._setFocus();
				return false;
			}
		},
		_parseMarkup: function(template, values, item) {
			var arr;
			if(item.data) {
				values = $.extend(item.data, values);
			}
			_mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );

			$.each(values, function(key, value) {
				if(value === undefined || value === false) {
					return true;
				}
				arr = key.split('_');
				if(arr.length > 1) {
					var el = template.find(EVENT_NS + '-'+arr[0]);

					if(el.length > 0) {
						var attr = arr[1];
						if(attr === 'replaceWith') {
							if(el[0] !== value[0]) {
								el.replaceWith(value);
							}
						} else if(attr === 'img') {
							if(el.is('img')) {
								el.attr('src', value);
							} else {
								el.replaceWith( $('<img>').attr('src', value).attr('class', el.attr('class')) );
							}
						} else {
							el.attr(arr[1], value);
						}
					}

				} else {
					template.find(EVENT_NS + '-'+key).html(value);
				}
			});
		},

		_getScrollbarSize: function() {
			// thx David
			if(mfp.scrollbarSize === undefined) {
				var scrollDiv = document.createElement("div");
				scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
				document.body.appendChild(scrollDiv);
				mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
				document.body.removeChild(scrollDiv);
			}
			return mfp.scrollbarSize;
		}

	}; /* MagnificPopup core prototype end */




	/**
	 * Public static functions
	 */
	$.magnificPopup = {
		instance: null,
		proto: MagnificPopup.prototype,
		modules: [],

		open: function(options, index) {
			_checkInstance();

			if(!options) {
				options = {};
			} else {
				options = $.extend(true, {}, options);
			}

			options.isObj = true;
			options.index = index || 0;
			return this.instance.open(options);
		},

		close: function() {
			return $.magnificPopup.instance && $.magnificPopup.instance.close();
		},

		registerModule: function(name, module) {
			if(module.options) {
				$.magnificPopup.defaults[name] = module.options;
			}
			$.extend(this.proto, module.proto);
			this.modules.push(name);
		},

		defaults: {

			// Info about options is in docs:
			// http://dimsemenov.com/plugins/magnific-popup/documentation.html#options

			disableOn: 0,

			key: null,

			midClick: false,

			mainClass: '',

			preloader: true,

			focus: '', // CSS selector of input to focus after popup is opened

			closeOnContentClick: false,

			closeOnBgClick: true,

			closeBtnInside: true,

			showCloseBtn: true,

			enableEscapeKey: true,

			modal: false,

			alignTop: false,

			removalDelay: 0,

			prependTo: null,

			fixedContentPos: 'auto',

			fixedBgPos: 'auto',

			overflowY: 'auto',

			closeMarkup: '<button title="%title%" type="button" class="mfp-close">&#215;</button>',

			tClose: 'Close (Esc)',

			tLoading: 'Loading...',

			autoFocusLast: true

		}
	};



	$.fn.magnificPopup = function(options) {
		_checkInstance();

		var jqEl = $(this);

		// We call some API method of first param is a string
		if (typeof options === "string" ) {

			if(options === 'open') {
				var items,
					itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
					index = parseInt(arguments[1], 10) || 0;

				if(itemOpts.items) {
					items = itemOpts.items[index];
				} else {
					items = jqEl;
					if(itemOpts.delegate) {
						items = items.find(itemOpts.delegate);
					}
					items = items.eq( index );
				}
				mfp._openClick({mfpEl:items}, jqEl, itemOpts);
			} else {
				if(mfp.isOpen)
					mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
			}

		} else {
			// clone options obj
			options = $.extend(true, {}, options);

			/*
			 * As Zepto doesn't support .data() method for objects
			 * and it works only in normal browsers
			 * we assign "options" object directly to the DOM element. FTW!
			 */
			if(_isJQ) {
				jqEl.data('magnificPopup', options);
			} else {
				jqEl[0].magnificPopup = options;
			}

			mfp.addGroup(jqEl, options);

		}
		return jqEl;
	};

	/*>>core*/

	/*>>inline*/

	var INLINE_NS = 'inline',
		_hiddenClass,
		_inlinePlaceholder,
		_lastInlineElement,
		_putInlineElementsBack = function() {
			if(_lastInlineElement) {
				_inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
				_lastInlineElement = null;
			}
		};

	$.magnificPopup.registerModule(INLINE_NS, {
		options: {
			hiddenClass: 'hide', // will be appended with `mfp-` prefix
			markup: '',
			tNotFound: 'Content not found'
		},
		proto: {

			initInline: function() {
				mfp.types.push(INLINE_NS);

				_mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
					_putInlineElementsBack();
				});
			},

			getInline: function(item, template) {

				_putInlineElementsBack();

				if(item.src) {
					var inlineSt = mfp.st.inline,
						el = $(item.src);

					if(el.length) {

						// If target element has parent - we replace it with placeholder and put it back after popup is closed
						var parent = el[0].parentNode;
						if(parent && parent.tagName) {
							if(!_inlinePlaceholder) {
								_hiddenClass = inlineSt.hiddenClass;
								_inlinePlaceholder = _getEl(_hiddenClass);
								_hiddenClass = 'mfp-'+_hiddenClass;
							}
							// replace target inline element with placeholder
							_lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
						}

						mfp.updateStatus('ready');
					} else {
						mfp.updateStatus('error', inlineSt.tNotFound);
						el = $('<div>');
					}

					item.inlineElement = el;
					return el;
				}

				mfp.updateStatus('ready');
				mfp._parseMarkup(template, {}, item);
				return template;
			}
		}
	});

	/*>>inline*/

	/*>>ajax*/
	var AJAX_NS = 'ajax',
		_ajaxCur,
		_removeAjaxCursor = function() {
			if(_ajaxCur) {
				$(document.body).removeClass(_ajaxCur);
			}
		},
		_destroyAjaxRequest = function() {
			_removeAjaxCursor();
			if(mfp.req) {
				mfp.req.abort();
			}
		};

	$.magnificPopup.registerModule(AJAX_NS, {

		options: {
			settings: null,
			cursor: 'mfp-ajax-cur',
			tError: '<a href="%url%">The content</a> could not be loaded.'
		},

		proto: {
			initAjax: function() {
				mfp.types.push(AJAX_NS);
				_ajaxCur = mfp.st.ajax.cursor;

				_mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
				_mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
			},
			getAjax: function(item) {

				if(_ajaxCur) {
					$(document.body).addClass(_ajaxCur);
				}

				mfp.updateStatus('loading');

				var opts = $.extend({
					url: item.src,
					success: function(data, textStatus, jqXHR) {
						var temp = {
							data:data,
							xhr:jqXHR
						};

						_mfpTrigger('ParseAjax', temp);

						mfp.appendContent( $(temp.data), AJAX_NS );

						item.finished = true;

						_removeAjaxCursor();

						mfp._setFocus();

						setTimeout(function() {
							mfp.wrap.addClass(READY_CLASS);
						}, 16);

						mfp.updateStatus('ready');

						_mfpTrigger('AjaxContentAdded');
					},
					error: function() {
						_removeAjaxCursor();
						item.finished = item.loadError = true;
						mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
					}
				}, mfp.st.ajax.settings);

				mfp.req = $.ajax(opts);

				return '';
			}
		}
	});

	/*>>ajax*/

	/*>>image*/
	var _imgInterval,
		_getTitle = function(item) {
			if(item.data && item.data.title !== undefined)
				return item.data.title;

			var src = mfp.st.image.titleSrc;

			if(src) {
				if($.isFunction(src)) {
					return src.call(mfp, item);
				} else if(item.el) {
					return item.el.attr(src) || '';
				}
			}
			return '';
		};

	$.magnificPopup.registerModule('image', {

		options: {
			markup: '<div class="mfp-figure">'+
			        '<div class="mfp-close"></div>'+
			        '<figure>'+
			        '<div class="mfp-img"></div>'+
			        '<figcaption>'+
			        '<div class="mfp-bottom-bar">'+
			        '<div class="mfp-title"></div>'+
			        '<div class="mfp-counter"></div>'+
			        '</div>'+
			        '</figcaption>'+
			        '</figure>'+
			        '</div>',
			cursor: 'mfp-zoom-out-cur',
			titleSrc: 'title',
			verticalFit: true,
			tError: '<a href="%url%">The image</a> could not be loaded.'
		},

		proto: {
			initImage: function() {
				var imgSt = mfp.st.image,
					ns = '.image';

				mfp.types.push('image');

				_mfpOn(OPEN_EVENT+ns, function() {
					if(mfp.currItem.type === 'image' && imgSt.cursor) {
						$(document.body).addClass(imgSt.cursor);
					}
				});

				_mfpOn(CLOSE_EVENT+ns, function() {
					if(imgSt.cursor) {
						$(document.body).removeClass(imgSt.cursor);
					}
					_window.off('resize' + EVENT_NS);
				});

				_mfpOn('Resize'+ns, mfp.resizeImage);
				if(mfp.isLowIE) {
					_mfpOn('AfterChange', mfp.resizeImage);
				}
			},
			resizeImage: function() {
				var item = mfp.currItem;
				if(!item || !item.img) return;

				if(mfp.st.image.verticalFit) {
					var decr = 0;
					// fix box-sizing in ie7/8
					if(mfp.isLowIE) {
						decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
					}
					item.img.css('max-height', mfp.wH-decr);
				}
			},
			_onImageHasSize: function(item) {
				if(item.img) {

					item.hasSize = true;

					if(_imgInterval) {
						clearInterval(_imgInterval);
					}

					item.isCheckingImgSize = false;

					_mfpTrigger('ImageHasSize', item);

					if(item.imgHidden) {
						if(mfp.content)
							mfp.content.removeClass('mfp-loading');

						item.imgHidden = false;
					}

				}
			},

			/**
			 * Function that loops until the image has size to display elements that rely on it asap
			 */
			findImageSize: function(item) {

				var counter = 0,
					img = item.img[0],
					mfpSetInterval = function(delay) {

						if(_imgInterval) {
							clearInterval(_imgInterval);
						}
						// decelerating interval that checks for size of an image
						_imgInterval = setInterval(function() {
							if(img.naturalWidth > 0) {
								mfp._onImageHasSize(item);
								return;
							}

							if(counter > 200) {
								clearInterval(_imgInterval);
							}

							counter++;
							if(counter === 3) {
								mfpSetInterval(10);
							} else if(counter === 40) {
								mfpSetInterval(50);
							} else if(counter === 100) {
								mfpSetInterval(500);
							}
						}, delay);
					};

				mfpSetInterval(1);
			},

			getImage: function(item, template) {

				var guard = 0,

					// image load complete handler
					onLoadComplete = function() {
						if(item) {
							if (item.img[0].complete) {
								item.img.off('.mfploader');

								if(item === mfp.currItem){
									mfp._onImageHasSize(item);

									mfp.updateStatus('ready');
								}

								item.hasSize = true;
								item.loaded = true;

								_mfpTrigger('ImageLoadComplete');

							}
							else {
								// if image complete check fails 200 times (20 sec), we assume that there was an error.
								guard++;
								if(guard < 200) {
									setTimeout(onLoadComplete,100);
								} else {
									onLoadError();
								}
							}
						}
					},

					// image error handler
					onLoadError = function() {
						if(item) {
							item.img.off('.mfploader');
							if(item === mfp.currItem){
								mfp._onImageHasSize(item);
								mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
							}

							item.hasSize = true;
							item.loaded = true;
							item.loadError = true;
						}
					},
					imgSt = mfp.st.image;


				var el = template.find('.mfp-img');
				if(el.length) {
					var img = document.createElement('img');
					img.className = 'mfp-img';
					if(item.el && item.el.find('img').length) {
						img.alt = item.el.find('img').attr('alt');
					}
					item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
					img.src = item.src;

					// without clone() "error" event is not firing when IMG is replaced by new IMG
					// TODO: find a way to avoid such cloning
					if(el.is('img')) {
						item.img = item.img.clone();
					}

					img = item.img[0];
					if(img.naturalWidth > 0) {
						item.hasSize = true;
					} else if(!img.width) {
						item.hasSize = false;
					}
				}

				mfp._parseMarkup(template, {
					title: _getTitle(item),
					img_replaceWith: item.img
				}, item);

				mfp.resizeImage();

				if(item.hasSize) {
					if(_imgInterval) clearInterval(_imgInterval);

					if(item.loadError) {
						template.addClass('mfp-loading');
						mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
					} else {
						template.removeClass('mfp-loading');
						mfp.updateStatus('ready');
					}
					return template;
				}

				mfp.updateStatus('loading');
				item.loading = true;

				if(!item.hasSize) {
					item.imgHidden = true;
					template.addClass('mfp-loading');
					mfp.findImageSize(item);
				}

				return template;
			}
		}
	});

	/*>>image*/

	/*>>zoom*/
	var hasMozTransform,
		getHasMozTransform = function() {
			if(hasMozTransform === undefined) {
				hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
			}
			return hasMozTransform;
		};

	$.magnificPopup.registerModule('zoom', {

		options: {
			enabled: false,
			easing: 'ease-in-out',
			duration: 300,
			opener: function(element) {
				return element.is('img') ? element : element.find('img');
			}
		},

		proto: {

			initZoom: function() {
				var zoomSt = mfp.st.zoom,
					ns = '.zoom',
					image;

				if(!zoomSt.enabled || !mfp.supportsTransition) {
					return;
				}

				var duration = zoomSt.duration,
					getElToAnimate = function(image) {
						var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
							transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
							cssObj = {
								position: 'fixed',
								zIndex: 9999,
								left: 0,
								top: 0,
								'-webkit-backface-visibility': 'hidden'
							},
							t = 'transition';

						cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;

						newImg.css(cssObj);
						return newImg;
					},
					showMainContent = function() {
						mfp.content.css('visibility', 'visible');
					},
					openTimeout,
					animatedImg;

				_mfpOn('BuildControls'+ns, function() {
					if(mfp._allowZoom()) {

						clearTimeout(openTimeout);
						mfp.content.css('visibility', 'hidden');

						// Basically, all code below does is clones existing image, puts in on top of the current one and animated it

						image = mfp._getItemToZoom();

						if(!image) {
							showMainContent();
							return;
						}

						animatedImg = getElToAnimate(image);

						animatedImg.css( mfp._getOffset() );

						mfp.wrap.append(animatedImg);

						openTimeout = setTimeout(function() {
							animatedImg.css( mfp._getOffset( true ) );
							openTimeout = setTimeout(function() {

								showMainContent();

								setTimeout(function() {
									animatedImg.remove();
									image = animatedImg = null;
									_mfpTrigger('ZoomAnimationEnded');
								}, 16); // avoid blink when switching images

							}, duration); // this timeout equals animation duration

						}, 16); // by adding this timeout we avoid short glitch at the beginning of animation


						// Lots of timeouts...
					}
				});
				_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
					if(mfp._allowZoom()) {

						clearTimeout(openTimeout);

						mfp.st.removalDelay = duration;

						if(!image) {
							image = mfp._getItemToZoom();
							if(!image) {
								return;
							}
							animatedImg = getElToAnimate(image);
						}

						animatedImg.css( mfp._getOffset(true) );
						mfp.wrap.append(animatedImg);
						mfp.content.css('visibility', 'hidden');

						setTimeout(function() {
							animatedImg.css( mfp._getOffset() );
						}, 16);
					}

				});

				_mfpOn(CLOSE_EVENT+ns, function() {
					if(mfp._allowZoom()) {
						showMainContent();
						if(animatedImg) {
							animatedImg.remove();
						}
						image = null;
					}
				});
			},

			_allowZoom: function() {
				return mfp.currItem.type === 'image';
			},

			_getItemToZoom: function() {
				if(mfp.currItem.hasSize) {
					return mfp.currItem.img;
				} else {
					return false;
				}
			},

			// Get element postion relative to viewport
			_getOffset: function(isLarge) {
				var el;
				if(isLarge) {
					el = mfp.currItem.img;
				} else {
					el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
				}

				var offset = el.offset();
				var paddingTop = parseInt(el.css('padding-top'),10);
				var paddingBottom = parseInt(el.css('padding-bottom'),10);
				offset.top -= ( $(window).scrollTop() - paddingTop );


				/*

				Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.

				 */
				var obj = {
					width: el.width(),
					// fix Zepto height+padding issue
					height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
				};

				// I hate to do this, but there is no another option
				if( getHasMozTransform() ) {
					obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
				} else {
					obj.left = offset.left;
					obj.top = offset.top;
				}
				return obj;
			}

		}
	});



	/*>>zoom*/

	/*>>iframe*/

	var IFRAME_NS = 'iframe',
		_emptyPage = '//about:blank',

		_fixIframeBugs = function(isShowing) {
			if(mfp.currTemplate[IFRAME_NS]) {
				var el = mfp.currTemplate[IFRAME_NS].find('iframe');
				if(el.length) {
					// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
					if(!isShowing) {
						el[0].src = _emptyPage;
					}

					// IE8 black screen bug fix
					if(mfp.isIE8) {
						el.css('display', isShowing ? 'block' : 'none');
					}
				}
			}
		};

	$.magnificPopup.registerModule(IFRAME_NS, {

		options: {
			markup: '<div class="mfp-iframe-scaler">'+
			        '<div class="mfp-close"></div>'+
			        '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
			        '</div>',

			srcAction: 'iframe_src',

			// we don't care and support only one default type of URL by default
			patterns: {
				youtube: {
					index: 'youtube.com',
					id: 'v=',
					src: '//www.youtube.com/embed/%id%?autoplay=1'
				},
				vimeo: {
					index: 'vimeo.com/',
					id: '/',
					src: '//player.vimeo.com/video/%id%?autoplay=1'
				},
				gmaps: {
					index: '//maps.google.',
					src: '%id%&output=embed'
				}
			}
		},

		proto: {
			initIframe: function() {
				mfp.types.push(IFRAME_NS);

				_mfpOn('BeforeChange', function(e, prevType, newType) {
					if(prevType !== newType) {
						if(prevType === IFRAME_NS) {
							_fixIframeBugs(); // iframe if removed
						} else if(newType === IFRAME_NS) {
							_fixIframeBugs(true); // iframe is showing
						}
					}// else {
					// iframe source is switched, don't do anything
					//}
				});

				_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
					_fixIframeBugs();
				});
			},

			getIframe: function(item, template) {
				var embedSrc = item.src;
				var iframeSt = mfp.st.iframe;

				$.each(iframeSt.patterns, function() {
					if(embedSrc.indexOf( this.index ) > -1) {
						if(this.id) {
							if(typeof this.id === 'string') {
								embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
							} else {
								embedSrc = this.id.call( this, embedSrc );
							}
						}
						embedSrc = this.src.replace('%id%', embedSrc );
						return false; // break;
					}
				});

				var dataObj = {};
				if(iframeSt.srcAction) {
					dataObj[iframeSt.srcAction] = embedSrc;
				}
				mfp._parseMarkup(template, dataObj, item);

				mfp.updateStatus('ready');

				return template;
			}
		}
	});



	/*>>iframe*/

	/*>>gallery*/
	/**
	 * Get looped index depending on number of slides
	 */
	var _getLoopedId = function(index) {
			var numSlides = mfp.items.length;
			if(index > numSlides - 1) {
				return index - numSlides;
			} else  if(index < 0) {
				return numSlides + index;
			}
			return index;
		},
		_replaceCurrTotal = function(text, curr, total) {
			return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
		};

	$.magnificPopup.registerModule('gallery', {

		options: {
			enabled: false,
			arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
			preload: [0,2],
			navigateByImgClick: true,
			arrows: true,

			tPrev: 'Previous (Left arrow key)',
			tNext: 'Next (Right arrow key)',
			tCounter: '%curr% of %total%'
		},

		proto: {
			initGallery: function() {

				var gSt = mfp.st.gallery,
					ns = '.mfp-gallery';

				mfp.direction = true; // true - next, false - prev

				if(!gSt || !gSt.enabled ) return false;

				_wrapClasses += ' mfp-gallery';

				_mfpOn(OPEN_EVENT+ns, function() {

					if(gSt.navigateByImgClick) {
						mfp.wrap.on('click'+ns, '.mfp-img', function() {
							if(mfp.items.length > 1) {
								mfp.next();
								return false;
							}
						});
					}

					_document.on('keydown'+ns, function(e) {
						if (e.keyCode === 37) {
							mfp.prev();
						} else if (e.keyCode === 39) {
							mfp.next();
						}
					});
				});

				_mfpOn('UpdateStatus'+ns, function(e, data) {
					if(data.text) {
						data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
					}
				});

				_mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
					var l = mfp.items.length;
					values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
				});

				_mfpOn('BuildControls' + ns, function() {
					if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
						var markup = gSt.arrowMarkup,
							arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
							arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);

						arrowLeft.click(function() {
							mfp.prev();
						});
						arrowRight.click(function() {
							mfp.next();
						});

						mfp.container.append(arrowLeft.add(arrowRight));
					}
				});

				_mfpOn(CHANGE_EVENT+ns, function() {
					if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);

					mfp._preloadTimeout = setTimeout(function() {
						mfp.preloadNearbyImages();
						mfp._preloadTimeout = null;
					}, 16);
				});


				_mfpOn(CLOSE_EVENT+ns, function() {
					_document.off(ns);
					mfp.wrap.off('click'+ns);
					mfp.arrowRight = mfp.arrowLeft = null;
				});

			},
			next: function() {
				mfp.direction = true;
				mfp.index = _getLoopedId(mfp.index + 1);
				mfp.updateItemHTML();
			},
			prev: function() {
				mfp.direction = false;
				mfp.index = _getLoopedId(mfp.index - 1);
				mfp.updateItemHTML();
			},
			goTo: function(newIndex) {
				mfp.direction = (newIndex >= mfp.index);
				mfp.index = newIndex;
				mfp.updateItemHTML();
			},
			preloadNearbyImages: function() {
				var p = mfp.st.gallery.preload,
					preloadBefore = Math.min(p[0], mfp.items.length),
					preloadAfter = Math.min(p[1], mfp.items.length),
					i;

				for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
					mfp._preloadItem(mfp.index+i);
				}
				for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
					mfp._preloadItem(mfp.index-i);
				}
			},
			_preloadItem: function(index) {
				index = _getLoopedId(index);

				if(mfp.items[index].preloaded) {
					return;
				}

				var item = mfp.items[index];
				if(!item.parsed) {
					item = mfp.parseEl( index );
				}

				_mfpTrigger('LazyLoad', item);

				if(item.type === 'image') {
					item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
						item.hasSize = true;
					}).on('error.mfploader', function() {
						item.hasSize = true;
						item.loadError = true;
						_mfpTrigger('LazyLoadError', item);
					}).attr('src', item.src);
				}


				item.preloaded = true;
			}
		}
	});

	/*>>gallery*/

	/*>>retina*/

	var RETINA_NS = 'retina';

	$.magnificPopup.registerModule(RETINA_NS, {
		options: {
			replaceSrc: function(item) {
				return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
			},
			ratio: 1 // Function or number.  Set to 1 to disable.
		},
		proto: {
			initRetina: function() {
				if(window.devicePixelRatio > 1) {

					var st = mfp.st.retina,
						ratio = st.ratio;

					ratio = !isNaN(ratio) ? ratio : ratio();

					if(ratio > 1) {
						_mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
							item.img.css({
								'max-width': item.img[0].naturalWidth / ratio,
								'width': '100%'
							});
						});
						_mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
							item.src = st.replaceSrc(item, ratio);
						});
					}
				}

			}
		}
	});

	/*>>retina*/
	_checkInstance(); }));
/*! modernizr 3.6.0 (Custom Build) | MIT *
 * https://modernizr.com/download/?-flexbox-requestanimationframe-touchevents-setclasses !*/
!function(e,n,t){function r(e,n){return typeof e===n}function o(){var e,n,t,o,i,s,a;for(var l in x)if(x.hasOwnProperty(l)){if(e=[],n=x[l],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t<n.options.aliases.length;t++)e.push(n.options.aliases[t].toLowerCase());for(o=r(n.fn,"function")?n.fn():n.fn,i=0;i<e.length;i++)s=e[i],a=s.split("."),1===a.length?Modernizr[a[0]]=o:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=o),C.push((o?"":"no-")+a.join("-"))}}function i(e){var n=_.className,t=Modernizr._config.classPrefix||"";if(w&&(n=n.baseVal),Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+t+"no-js(\\s|$)");n=n.replace(r,"$1"+t+"js$2")}Modernizr._config.enableClasses&&(n+=" "+t+e.join(" "+t),w?_.className.baseVal=n:_.className=n)}function s(e){return e.replace(/([a-z])-([a-z])/g,function(e,n,t){return n+t.toUpperCase()}).replace(/^-/,"")}function a(){return"function"!=typeof n.createElement?n.createElement(arguments[0]):w?n.createElementNS.call(n,"http://www.w3.org/2000/svg",arguments[0]):n.createElement.apply(n,arguments)}function l(){var e=n.body;return e||(e=a(w?"svg":"body"),e.fake=!0),e}function f(e,t,r,o){var i,s,f,u,c="modernizr",p=a("div"),d=l();if(parseInt(r,10))for(;r--;)f=a("div"),f.id=o?o[r]:c+(r+1),p.appendChild(f);return i=a("style"),i.type="text/css",i.id="s"+c,(d.fake?d:p).appendChild(i),d.appendChild(p),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(n.createTextNode(e)),p.id=c,d.fake&&(d.style.background="",d.style.overflow="hidden",u=_.style.overflow,_.style.overflow="hidden",_.appendChild(d)),s=t(p,e),d.fake?(d.parentNode.removeChild(d),_.style.overflow=u,_.offsetHeight):p.parentNode.removeChild(p),!!s}function u(e,n){return!!~(""+e).indexOf(n)}function c(e,n){return function(){return e.apply(n,arguments)}}function p(e,n,t){var o;for(var i in e)if(e[i]in n)return t===!1?e[i]:(o=n[e[i]],r(o,"function")?c(o,t||n):o);return!1}function d(e){return e.replace(/([A-Z])/g,function(e,n){return"-"+n.toLowerCase()}).replace(/^ms-/,"-ms-")}function m(n,t,r){var o;if("getComputedStyle"in e){o=getComputedStyle.call(e,n,t);var i=e.console;if(null!==o)r&&(o=o.getPropertyValue(r));else if(i){var s=i.error?"error":"log";i[s].call(i,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}}else o=!t&&n.currentStyle&&n.currentStyle[r];return o}function v(n,r){var o=n.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(d(n[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+d(n[o])+":"+r+")");return i=i.join(" or "),f("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"==m(e,null,"position")})}return t}function h(e,n,o,i){function l(){c&&(delete k.style,delete k.modElem)}if(i=r(i,"undefined")?!1:i,!r(o,"undefined")){var f=v(e,o);if(!r(f,"undefined"))return f}for(var c,p,d,m,h,y=["modernizr","tspan","samp"];!k.style&&y.length;)c=!0,k.modElem=a(y.shift()),k.style=k.modElem.style;for(d=e.length,p=0;d>p;p++)if(m=e[p],h=k.style[m],u(m,"-")&&(m=s(m)),k.style[m]!==t){if(i||r(o,"undefined"))return l(),"pfx"==n?m:!0;try{k.style[m]=o}catch(g){}if(k.style[m]!=h)return l(),"pfx"==n?m:!0}return l(),!1}function y(e,n,t,o,i){var s=e.charAt(0).toUpperCase()+e.slice(1),a=(e+" "+P.join(s+" ")+s).split(" ");return r(n,"string")||r(n,"undefined")?h(a,n,o,i):(a=(e+" "+j.join(s+" ")+s).split(" "),p(a,n,t))}function g(e,n,r){return y(e,t,t,n,r)}var C=[],x=[],S={_version:"3.6.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var t=this;setTimeout(function(){n(t[e])},0)},addTest:function(e,n,t){x.push({name:e,fn:n,options:t})},addAsyncTest:function(e){x.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=S,Modernizr=new Modernizr;var _=n.documentElement,w="svg"===_.nodeName.toLowerCase(),b=S._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):["",""];S._prefixes=b;var z=S.testStyles=f;Modernizr.addTest("touchevents",function(){var t;if("ontouchstart"in e||e.DocumentTouch&&n instanceof DocumentTouch)t=!0;else{var r=["@media (",b.join("touch-enabled),("),"heartz",")","{#modernizr{top:9px;position:absolute}}"].join("");z(r,function(e){t=9===e.offsetTop})}return t});var T="Moz O ms Webkit",P=S._config.usePrefixes?T.split(" "):[];S._cssomPrefixes=P;var E=function(n){var r,o=b.length,i=e.CSSRule;if("undefined"==typeof i)return t;if(!n)return!1;if(n=n.replace(/^@/,""),r=n.replace(/-/g,"_").toUpperCase()+"_RULE",r in i)return"@"+n;for(var s=0;o>s;s++){var a=b[s],l=a.toUpperCase()+"_"+r;if(l in i)return"@-"+a.toLowerCase()+"-"+n}return!1};S.atRule=E;var j=S._config.usePrefixes?T.toLowerCase().split(" "):[];S._domPrefixes=j;var N={elem:a("modernizr")};Modernizr._q.push(function(){delete N.elem});var k={style:N.elem.style};Modernizr._q.unshift(function(){delete k.style}),S.testAllProps=y;var q=S.prefixed=function(e,n,t){return 0===e.indexOf("@")?E(e):(-1!=e.indexOf("-")&&(e=s(e)),n?y(e,n,t):y(e,"pfx"))};Modernizr.addTest("requestanimationframe",!!q("requestAnimationFrame",e),{aliases:["raf"]}),S.testAllProps=g,Modernizr.addTest("flexbox",g("flexBasis","1px",!0)),o(),i(C),delete S.addTest,delete S.addAsyncTest;for(var A=0;A<Modernizr._q.length;A++)Modernizr._q[A]();e.Modernizr=Modernizr}(window,document);
// https://github.com/taylorhakes/promise-polyfill
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
		typeof define === 'function' && define.amd ? define(factory) :
			(factory());
}(this, (function () { 'use strict';

	/**
	 * @this {Promise}
	 */
	function finallyConstructor(callback) {
		var constructor = this.constructor;
		return this.then(
			function(value) {
				// @ts-ignore
				return constructor.resolve(callback()).then(function() {
					return value;
				});
			},
			function(reason) {
				// @ts-ignore
				return constructor.resolve(callback()).then(function() {
					// @ts-ignore
					return constructor.reject(reason);
				});
			}
		);
	}

// Store setTimeout reference so promise-polyfill will be unaffected by
// other code modifying setTimeout (like sinon.useFakeTimers())
	var setTimeoutFunc = setTimeout;

	function isArray(x) {
		return Boolean(x && typeof x.length !== 'undefined');
	}

	function noop() {}

// Polyfill for Function.prototype.bind
	function bind(fn, thisArg) {
		return function() {
			fn.apply(thisArg, arguments);
		};
	}

	/**
	 * @constructor
	 * @param {Function} fn
	 */
	function Promise(fn) {
		if (!(this instanceof Promise))
			throw new TypeError('Promises must be constructed via new');
		if (typeof fn !== 'function') throw new TypeError('not a function');
		/** @type {!number} */
		this._state = 0;
		/** @type {!boolean} */
		this._handled = false;
		/** @type {Promise|undefined} */
		this._value = undefined;
		/** @type {!Array<!Function>} */
		this._deferreds = [];

		doResolve(fn, this);
	}

	function handle(self, deferred) {
		while (self._state === 3) {
			self = self._value;
		}
		if (self._state === 0) {
			self._deferreds.push(deferred);
			return;
		}
		self._handled = true;
		Promise._immediateFn(function() {
			var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
			if (cb === null) {
				(self._state === 1 ? resolve : reject)(deferred.promise, self._value);
				return;
			}
			var ret;
			try {
				ret = cb(self._value);
			} catch (e) {
				reject(deferred.promise, e);
				return;
			}
			resolve(deferred.promise, ret);
		});
	}

	function resolve(self, newValue) {
		try {
			// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
			if (newValue === self)
				throw new TypeError('A promise cannot be resolved with itself.');
			if (
				newValue &&
				(typeof newValue === 'object' || typeof newValue === 'function')
			) {
				var then = newValue.then;
				if (newValue instanceof Promise) {
					self._state = 3;
					self._value = newValue;
					finale(self);
					return;
				} else if (typeof then === 'function') {
					doResolve(bind(then, newValue), self);
					return;
				}
			}
			self._state = 1;
			self._value = newValue;
			finale(self);
		} catch (e) {
			reject(self, e);
		}
	}

	function reject(self, newValue) {
		self._state = 2;
		self._value = newValue;
		finale(self);
	}

	function finale(self) {
		if (self._state === 2 && self._deferreds.length === 0) {
			Promise._immediateFn(function() {
				if (!self._handled) {
					Promise._unhandledRejectionFn(self._value);
				}
			});
		}

		for (var i = 0, len = self._deferreds.length; i < len; i++) {
			handle(self, self._deferreds[i]);
		}
		self._deferreds = null;
	}

	/**
	 * @constructor
	 */
	function Handler(onFulfilled, onRejected, promise) {
		this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
		this.onRejected = typeof onRejected === 'function' ? onRejected : null;
		this.promise = promise;
	}

	/**
	 * Take a potentially misbehaving resolver function and make sure
	 * onFulfilled and onRejected are only called once.
	 *
	 * Makes no guarantees about asynchrony.
	 */
	function doResolve(fn, self) {
		var done = false;
		try {
			fn(
				function(value) {
					if (done) return;
					done = true;
					resolve(self, value);
				},
				function(reason) {
					if (done) return;
					done = true;
					reject(self, reason);
				}
			);
		} catch (ex) {
			if (done) return;
			done = true;
			reject(self, ex);
		}
	}

	Promise.prototype['catch'] = function(onRejected) {
		return this.then(null, onRejected);
	};

	Promise.prototype.then = function(onFulfilled, onRejected) {
		// @ts-ignore
		var prom = new this.constructor(noop);

		handle(this, new Handler(onFulfilled, onRejected, prom));
		return prom;
	};

	Promise.prototype['finally'] = finallyConstructor;

	Promise.all = function(arr) {
		return new Promise(function(resolve, reject) {
			if (!isArray(arr)) {
				return reject(new TypeError('Promise.all accepts an array'));
			}

			var args = Array.prototype.slice.call(arr);
			if (args.length === 0) return resolve([]);
			var remaining = args.length;

			function res(i, val) {
				try {
					if (val && (typeof val === 'object' || typeof val === 'function')) {
						var then = val.then;
						if (typeof then === 'function') {
							then.call(
								val,
								function(val) {
									res(i, val);
								},
								reject
							);
							return;
						}
					}
					args[i] = val;
					if (--remaining === 0) {
						resolve(args);
					}
				} catch (ex) {
					reject(ex);
				}
			}

			for (var i = 0; i < args.length; i++) {
				res(i, args[i]);
			}
		});
	};

	Promise.resolve = function(value) {
		if (value && typeof value === 'object' && value.constructor === Promise) {
			return value;
		}

		return new Promise(function(resolve) {
			resolve(value);
		});
	};

	Promise.reject = function(value) {
		return new Promise(function(resolve, reject) {
			reject(value);
		});
	};

	Promise.race = function(arr) {
		return new Promise(function(resolve, reject) {
			if (!isArray(arr)) {
				return reject(new TypeError('Promise.race accepts an array'));
			}

			for (var i = 0, len = arr.length; i < len; i++) {
				Promise.resolve(arr[i]).then(resolve, reject);
			}
		});
	};

// Use polyfill for setImmediate for performance gains
	Promise._immediateFn =
		// @ts-ignore
		(typeof setImmediate === 'function' &&
		 function(fn) {
			 // @ts-ignore
			 setImmediate(fn);
		 }) ||
		function(fn) {
			setTimeoutFunc(fn, 0);
		};

	Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
		if (typeof console !== 'undefined' && console) {
			console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
		}
	};

	/** @suppress {undefinedVars} */
	var globalNS = (function() {
		// the only reliable means to get the global object is
		// `Function('return this')()`
		// However, this causes CSP violations in Chrome apps.
		if (typeof self !== 'undefined') {
			return self;
		}
		if (typeof window !== 'undefined') {
			return window;
		}
		if (typeof global !== 'undefined') {
			return global;
		}
		throw new Error('unable to locate global object');
	})();

	if (!('Promise' in globalNS)) {
		globalNS['Promise'] = Promise;
	} else if (!globalNS.Promise.prototype['finally']) {
		globalNS.Promise.prototype['finally'] = finallyConstructor;
	}

})));
/**
 * requestAnimationFrame polyfill by Erik Möller.
 * Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon
 *
 * MIT license
 */
if (!Date.now)
  Date.now = function() {
    return new Date().getTime();
  };

(function() {
  'use strict';

  var vendors = ['webkit', 'moz'];
  for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
    var vp = vendors[i];
    window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
    window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame']);
  }
  if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
    || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
    var lastTime = 0;
    window.requestAnimationFrame = function(callback) {
      var now = Date.now();
      var nextTime = Math.max(lastTime + 16, now);
      return setTimeout(function() {
          callback(lastTime = nextTime);
        },
        nextTime - now);
    };
    window.cancelAnimationFrame = clearTimeout;
  }
}());
/*!
 * Select2 4.0.11
 * 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 module === 'object' && module.exports) {
		// Node/CommonJS
		module.exports = function (root, jQuery) {
			if (jQuery === undefined) {
				// require('jQuery') returns a factory that requires window to
				// build a jQuery instance, we normalize how we use modules
				// that require this pattern but the window provided is a noop
				// if it's defined (how jquery works)
				if (typeof window !== 'undefined') {
					jQuery = require('jquery');
				}
				else {
					jQuery = require('jquery')(root);
				}
			}
			factory(jQuery);
			return 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.select2 && jQuery.fn.select2.amd) {
			var S2 = jQuery.fn.select2.amd;
		}
		var S2;(function () { if (!S2 || !S2.requirejs) {
			if (!S2) { S2 = {}; } else { require = S2; }
			/**
			 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
			 * Released under MIT license, http://github.com/requirejs/almond/LICENSE
			 */
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
			/*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, normalizedBaseParts,
						baseParts = baseName && baseName.split("/"),
						map = config.map,
						starMap = (map && map['*']) || {};

					//Adjust any relative paths.
					if (name) {
						name = name.split('/');
						lastIndex = name.length - 1;

						// If wanting node ID compatibility, strip .js from end
						// of IDs. Have to do this here, and not in nameToUrl
						// because node allows either .js or non .js to map
						// to same file.
						if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
							name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
						}

						// Starts with a '.' so need the baseName
						if (name[0].charAt(0) === '.' && baseParts) {
							//Convert baseName to array, and lop off the last part,
							//so that . matches that '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.
							normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
							name = normalizedBaseParts.concat(name);
						}

						//start trimDots
						for (i = 0; i < name.length; i++) {
							part = name[i];
							if (part === '.') {
								name.splice(i, 1);
								i -= 1;
							} else if (part === '..') {
								// If at the start, or previous value is still ..,
								// keep them so that when converted to a path it may
								// still work when converted to a path, even though
								// as an ID it is less than ideal. In larger point
								// releases, may be better to just kick out an error.
								if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
									continue;
								} else if (i > 0) {
									name.splice(i - 1, 2);
									i -= 2;
								}
							}
						}
						//end trimDots

						name = name.join('/');
					}

					//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];
				}

				//Creates a parts array for a relName where first part is plugin ID,
				//second part is resource ID. Assumes relName has already been normalized.
				function makeRelParts(relName) {
					return relName ? splitPrefix(relName) : [];
				}

				/**
				 * 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, relParts) {
					var plugin,
						parts = splitPrefix(name),
						prefix = parts[0],
						relResourceName = relParts[1];

					name = parts[1];

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

					//Normalize according
					if (prefix) {
						if (plugin && plugin.normalize) {
							name = plugin.normalize(name, makeNormalize(relResourceName));
						} else {
							name = normalize(name, relResourceName);
						}
					} else {
						name = normalize(name, relResourceName);
						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, relParts,
						args = [],
						callbackType = typeof callback,
						usingExports;

					//Use name if no relName
					relName = relName || name;
					relParts = makeRelParts(relName);

					//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], relParts);
							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, makeRelParts(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);
			};

			// Cache objects in Utils.__cache instead of $.data (see #4346)
			Utils.__cache = {};

			var id = 0;
			Utils.GetUniqueElementId = function (element) {
				// Get a unique element Id. If element has no id,
				// creates a new unique number, stores it in the id
				// attribute and returns the new id.
				// If an id already exists, it simply returns it.

				var select2Id = element.getAttribute('data-select2-id');
				if (select2Id == null) {
					// If element has id, use it.
					if (element.id) {
						select2Id = element.id;
						element.setAttribute('data-select2-id', select2Id);
					} else {
						element.setAttribute('data-select2-id', ++id);
						select2Id = id.toString();
					}
				}
				return select2Id;
			};

			Utils.StoreData = function (element, name, value) {
				// Stores an item in the cache for a specified element.
				// name is the cache key.
				var id = Utils.GetUniqueElementId(element);
				if (!Utils.__cache[id]) {
					Utils.__cache[id] = {};
				}

				Utils.__cache[id][name] = value;
			};

			Utils.GetData = function (element, name) {
				// Retrieves a value from the cache by its key (name)
				// name is optional. If no name specified, return
				// all cache items for the specified element.
				// and for a specified element.
				var id = Utils.GetUniqueElementId(element);
				if (name) {
					if (Utils.__cache[id]) {
						if (Utils.__cache[id][name] != null) {
							return Utils.__cache[id][name];
						}
						return $(element).data(name); // Fallback to HTML5 data attribs.
					}
					return $(element).data(name); // Fallback to HTML5 data attribs.
				} else {
					return Utils.__cache[id];
				}
			};

			Utils.RemoveData = function (element) {
				// Removes all cached items for a specified element.
				var id = Utils.GetUniqueElementId(element);
				if (Utils.__cache[id] != null) {
					delete Utils.__cache[id];
				}

				element.removeAttribute('data-select2-id');
			};

			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="listbox"></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="alert" 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 = Utils.GetData(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': 'option',
					'aria-selected': 'false'
				};

				var matches = window.Element.prototype.matches ||
				              window.Element.prototype.msMatchesSelector ||
				              window.Element.prototype.webkitMatchesSelector;

				if ((data.element != null && matches.call(data.element, ':disabled')) ||
				    (data.element == null && 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);
				}

				Utils.StoreData(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();

					if (self.options.get('scrollAfterSelect')) {
						self.highlightFirstItem();
					}
				});

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

					self.setClasses();

					if (self.options.get('scrollAfterSelect')) {
						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 = Utils.GetData($highlighted[0], '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 the top, don't move further
					// If no options, currentIndex will be -1
					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 = Utils.GetData(this, '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 = Utils.GetData(this, '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 (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
					this._tabindex = Utils.GetData(this.$element[0], '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);
				$selection.attr('aria-disabled', 'false');

				this.$selection = $selection;

				return $selection;
			};

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

				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.trigger('focus');

					self._detachCloseHandler(container);
				});

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

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

			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) {

				$(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 () {
						if (this == $select[0]) {
							return;
						}

						var $element = Utils.GetData(this, 'element');

						$element.select2('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)
				    .attr('role', 'textbox')
				    .attr('aria-readonly', 'true');
				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.trigger('focus');
					}
				});
			};

			SingleSelection.prototype.clear = function () {
				var $rendered = this.$selection.find('.select2-selection__rendered');
				$rendered.empty();
				$rendered.removeAttr('title'); // clear tooltip on 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);

				var title = selection.title || selection.text;

				if (title) {
					$rendered.attr('title', title);
				} else {
					$rendered.removeAttr('title');
				}
			};

			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 = Utils.GetData($selection[0], 'data');

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

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

			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);

					var title = selection.title || selection.text;

					if (title) {
						$selection.attr('title', title);
					}

					Utils.StoreData($selection[0], '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',
			'../utils'
		], function ($, KEYS, Utils) {
			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 = Utils.GetData($clear[0], 'data');

				var previousVal = this.$element.val();
				this.$element.val(this.placeholder.id);

				var unselectData = {
					data: data
				};
				this.trigger('clear', unselectData);
				if (unselectData.prevented) {
					this.$element.val(previousVal);
					return;
				}

				for (var d = 0; d < data.length; d++) {
					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) {
						this.$element.val(previousVal);
						return;
					}
				}

				this.$element.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 removeAll = this.options.get('translations').get('removeAllItems');

				var $remove = $(
					'<span class="select2-selection__clear" title="' + removeAll() +'">' +
					'&times;' +
					'</span>'
				);
				Utils.StoreData($remove[0], '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="none"' +
					' spellcheck="false" role="searchbox" 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;

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

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

				container.on('open', function () {
					self.$search.attr('aria-controls', resultsId);
					self.$search.trigger('focus');
				});

				container.on('close', function () {
					self.$search.val('');
					self.$search.removeAttr('aria-controls');
					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) {
					if (params.data._resultId) {
						self.$search.attr('aria-activedescendant', params.data._resultId);
					} else {
						self.$search.removeAttr('aria-activedescendant');
					}
				});

				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 = Utils.GetData($previousChoice[0], 'data');

							self.searchRemoveChoice(item);

							evt.preventDefault();
						}
					}
				});

				this.$selection.on('click', '.select2-search--inline', function (evt) {
					if (self.$search.val()) {
						evt.stopPropagation();
					}
				});

				// 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.trigger('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').width();
				} 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',
					'clear', 'clearing'
				];

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

				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',
				'\u0152': 'OE',
				'\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',
				'\u0153': 'oe',
				'\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',
				'\u03CE': '\u03C9',
				'\u03C2': '\u03C3',
				'\u2019': '\''
			};

			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
					Utils.RemoveData(this);
				});
			};

			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 !== undefined) {
					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
				Utils.StoreData(option, 'data', normalizedData);

				return $option;
			};

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

				data = Utils.GetData($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];

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

				return data;
			};

			SelectAdapter.prototype._normalizeItem = function (item) {
				if (item !== Object(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) {
				this._dataToConvert = options.get('data') || [];

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

			Utils.Extend(ArrayAdapter, SelectAdapter);

			ArrayAdapter.prototype.bind = function (container, $container) {
				ArrayAdapter.__super__.bind.call(this, container, $container);

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

			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 ('status' in $request &&
						    ($request.status === 0 || $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 optionText = (option.text || '').toUpperCase();
						var paramsTerm = (params.term || '').toUpperCase();

						var checkText = optionText === paramsTerm;

						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 $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.trigger('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.bind =
				function (decorated, container, $container) {
					var self = this;

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

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

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

					this._checkIfMaximumSelected(function () {
						decorated.call(self, params, callback);
					});
				};

			MaximumSelectionLength.prototype._checkIfMaximumSelected =
				function (_, successCallback) {
					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;
						}

						if (successCallback) {
							successCallback();
						}
					});
				};

			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 implemented 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="none"' +
					' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
					'</span>'
				);

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

				$rendered.prepend($search);

				return $rendered;
			};

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

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

				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.attr('aria-controls', resultsId);

					self.$search.trigger('focus');

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

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

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

				container.on('focus', function () {
					if (!container.isOpen()) {
						self.$search.trigger('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');
						}
					}
				});

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

			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);
					this.loadMoreIfNeeded();
				}
			};

			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', this.loadMoreIfNeeded.bind(this));
			};

			InfiniteScroll.prototype.loadMoreIfNeeded = function () {
				var isLoadMoreVisible = $.contains(
					document.documentElement,
					this.$loadingMore[0]
				);

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

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

				if (currentOffset + 50 >= loadingMoreOffset) {
					this.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="option" 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;

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

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

					// Must bind after the results handlers to ensure correct sizing
					self._bindContainerResultHandlers(container);
				});

				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._bindContainerResultHandlers =
				function (decorated, container) {

					// These should only be bound once
					if (this._containerResultsHandlersBound) {
						return;
					}

					var self = this;

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

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

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

					container.on('select', function () {
						self._positionDropdown();
						self._resizeDropdown();
					});

					container.on('unselect', function () {
						self._positionDropdown();
						self._resizeDropdown();
					});

					this._containerResultsHandlersBound = true;
				};

			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 () {
						Utils.StoreData(this, 'select2-scroll-position', {
							x: $(this).scrollLeft(),
							y: $(this).scrollTop()
						});
					});

					$watchers.on(scrollEvent, function (ev) {
						var position = Utils.GetData(this, '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 calculating the offset
				var $offsetParent = this.$dropdownParent;

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

				var parentOffset = {
					top: 0,
					left: 0
				};

				if ($.contains(document.body, $offsetParent[0])) {
					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',[
			'../utils'
		], function (Utils) {
			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 = Utils.GetData($highlightedResults[0], '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 || originalEvent.metaKey)) {
					return;
				}

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

			return CloseOnSelect;
		});

		S2.define('select2/i18n/en',[],function () {
			// English
			return {
				errorLoading: function () {
					return 'The results could not be loaded.';
				},
				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 'Loading more results…';
				},
				maximumSelected: function (args) {
					var message = 'You can only select ' + args.maximum + ' item';

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

					return message;
				},
				noResults: function () {
					return 'No results found';
				},
				searching: function () {
					return 'Searching…';
				},
				removeAllItems: function () {
					return 'Remove all items';
				}
			};
		});

		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 the defaults were not previously applied from an element, it is
				// possible for the language option to have not been resolved
				options.language = this._resolveLanguage(options.language);

				// Always fall back to English since it will always be complete
				options.language.push('en');

				var uniqueLanguages = [];

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

					if (uniqueLanguages.indexOf(language) === -1) {
						uniqueLanguages.push(language);
					}
				}

				options.language = uniqueLanguages;

				options.translations = this._processTranslations(
					options.language,
					options.debug
				);

				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: false,
					escapeMarkup: Utils.escapeMarkup,
					language: {},
					matcher: matcher,
					minimumInputLength: 0,
					maximumInputLength: 0,
					maximumSelectionLength: 0,
					minimumResultsForSearch: 0,
					selectOnClose: false,
					scrollAfterSelect: false,
					sorter: function (data) {
						return data;
					},
					templateResult: function (result) {
						return result.text;
					},
					templateSelection: function (selection) {
						return selection.text;
					},
					theme: 'default',
					width: 'resolve'
				};
			};

			Defaults.prototype.applyFromElement = function (options, $element) {
				var optionLanguage = options.language;
				var defaultLanguage = this.defaults.language;
				var elementLanguage = $element.prop('lang');
				var parentLanguage = $element.closest('[lang]').prop('lang');

				var languages = Array.prototype.concat.call(
					this._resolveLanguage(elementLanguage),
					this._resolveLanguage(optionLanguage),
					this._resolveLanguage(defaultLanguage),
					this._resolveLanguage(parentLanguage)
				);

				options.language = languages;

				return options;
			};

			Defaults.prototype._resolveLanguage = function (language) {
				if (!language) {
					return [];
				}

				if ($.isEmptyObject(language)) {
					return [];
				}

				if ($.isPlainObject(language)) {
					return [language];
				}

				var languages;

				if (!$.isArray(language)) {
					languages = [language];
				} else {
					languages = language;
				}

				var resolvedLanguages = [];

				for (var l = 0; l < languages.length; l++) {
					resolvedLanguages.push(languages[l]);

					if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
						// Extract the region information if it is included
						var languageParts = languages[l].split('-');
						var baseLanguage = languageParts[0];

						resolvedLanguages.push(baseLanguage);
					}
				}

				return resolvedLanguages;
			};

			Defaults.prototype._processTranslations = function (languages, debug) {
				var translations = new Translation();

				for (var l = 0; l < languages.length; l++) {
					var languageData = new Translation();

					var language = languages[l];

					if (typeof language === 'string') {
						try {
							// Try to load it with the original name
							languageData = Translation.loadPath(language);
						} catch (e) {
							try {
								// If we couldn't load it, check if it wasn't the full path
								language = this.defaults.amdLanguageBase + language;
								languageData = Translation.loadPath(language);
							} 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 (debug && window.console && console.warn) {
									console.warn(
										'Select2: The language file for "' + language + '" could ' +
										'not be automatically loaded. A fallback will be used instead.'
									);
								}
							}
						}
					} else if ($.isPlainObject(language)) {
						languageData = new Translation(language);
					} else {
						languageData = language;
					}

					translations.extend(languageData);
				}

				return translations;
			};

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

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

				var convertedData = Utils._convertData(data);

				$.extend(true, 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);
				}

				if ($element != null) {
					this.options = Defaults.applyFromElement(this.options, $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.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 (Utils.GetData($e[0], '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.'
						);
					}

					Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
					Utils.StoreData($e[0], 'tags', true);
				}

				if (Utils.GetData($e[0], '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', Utils.GetData($e[0], 'ajaxUrl'));
					Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
				}

				var dataset = {};

				function upperCaseLetter(_, letter) {
					return letter.toUpperCase();
				}

				// Pre-load all of the attributes which are prefixed with `data-`
				for (var attr = 0; attr < $e[0].attributes.length; attr++) {
					var attributeName = $e[0].attributes[attr].name;
					var prefix = 'data-';

					if (attributeName.substr(0, prefix.length) == prefix) {
						// Get the contents of the attribute after `data-`
						var dataName = attributeName.substring(prefix.length);

						// Get the data contents from the consistent source
						// This is more than likely the jQuery data helper
						var dataValue = Utils.GetData($e[0], dataName);

						// camelCase the attribute name to match the spec
						var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);

						// Store the data attribute contents into the dataset since
						dataset[camelDataName] = dataValue;
					}
				}

				// 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, dataset);
				}

				// Prefer our internal data cache if it exists
				var data = $.extend(true, {}, Utils.GetData($e[0]), 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 (Utils.GetData($element[0], 'select2') != null) {
					Utils.GetData($element[0], '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;
				Utils.StoreData($element[0], '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();

				Utils.StoreData($element[0], 'select2', this);

				// Ensure backwards compatibility with $element.data('select2').
				$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;
				}

				if (method == 'computedstyle') {
					var computedStyle = window.getComputedStyle($element[0]);

					return computedStyle.width;
				}

				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',
					'clear': 'clearing'
				};

				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',
					Utils.GetData(this.$element[0], 'old-tabindex'));

				this.$element.removeClass('select2-hidden-accessible');
				this.$element.attr('aria-hidden', 'false');
				Utils.RemoveData(this.$element[0]);
				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'));

				Utils.StoreData($container[0], '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',
			'../utils'
		], function ($, Utils) {
			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 Utils.GetData($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',
			'./select2/utils'
		], function ($, _, Select2, Defaults, Utils) {
			if ($.fn.select2 == null) {
				// All methods that should return the element
				var thisMethods = ['open', 'close', 'destroy'];

				$.fn.select2 = 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 = Utils.GetData(this, '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.select2.defaults == null) {
				$.fn.select2.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.select2.amd = S2;

	// Return the Select2 instance for anyone who is importing it.
	return select2;
}));
(function($, undefined) {
	"use strict";
/**
 * Shared variables
 */
var ua                  = navigator.userAgent.toLowerCase(),
    platform            = navigator.platform.toLowerCase(),
    $window             = $(window),
    $document           = $(document),
    $html               = $('html'),
    $body               = $('body'),

    android_ancient     = (ua.indexOf('mozilla/5.0') !== -1 && ua.indexOf('android') !== -1 && ua.indexOf('applewebKit') !== -1) && ua.indexOf('chrome') === -1,
    apple               = ua.match(/(iPad|iPhone|iPod|Macintosh)/i),
    webkit              = ua.indexOf('webkit') != -1,

    isiPhone            = false,
    isiPod              = false,
    isAndroidPhone      = false,
    android             = false,
    iOS                 = false,
    isIE                = false,
    ieMobile            = false,
    isSafari            = false,
    isMac               = false,
    isWindows           = false,
    isiele10            = false,

    firefox             = ua.indexOf('gecko') != -1,
    safari              = ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1,

    is_small            = $('.js-nav-trigger').is(':visible'),

    windowHeight        = $window.height(),
    windowWidth         = $window.width(),
    documentHeight      = $document.height(),
    orientation         = windowWidth > windowHeight ? 'portrait' : 'landscape',

    filmWidth,
    contentWidth,
    sidebarWidth,

    latestKnownScrollY  = window.scrollY,
    latestKnownScrollX  = window.scrollX,

    latestKnownMouseX   = 0,
    latestKnownMouseY   = 0,

    latestDeviceAlpha   = 0,
    latestDeviceBeta    = 0,
    latestDeviceGamma   = 0,

    horToVertScroll     = false,

    globalDebug         = false,
    $reviewsParent      = null;


var Carousel = (function() {

	var offset, $container, $images, $prev, $next, lastScroll, totalWidth, $arrow, $currentImg;

	function init() {

		if ( ! $('.entry-featured-gallery').length ) {
			return;
		}

		offset 		= $('.entry-header').offset().left;
		$container 	= $('.entry-featured-gallery');
		$arrow 		= $('.arrow-icon-svg');
		$prev 		= $('<div class="gallery-arrow gallery-arrow-prev">' + $arrow.html() + '</div>');
		$next 		= $('<div class="gallery-arrow gallery-arrow-next">' + $arrow.html() + '</div>');
		lastScroll 	= 0;
		totalWidth  = 0;

		var isRtl = $body.hasClass( 'rtl' );

		if ( isRtl ) {
			$container.children().each( function( i, obj ) {
				$container.prepend( obj )
			} );
		}

		$images = $container.find('.entry-featured-image');

		if ( $container.length && $images.length ) {

			$prev.add($next).appendTo($container.parent());

			var zeroWidth = $images.last().width();

			$currentImg = $images.first();

			$images.each(function(i, obj) {
				var $item 		= $(obj),
					itemWidth 	= $item.width(),
					itemOffset 	= $item.offset().left,
					marginRight = parseInt($item.css('marginRight'), 10);

				totalWidth = totalWidth + itemWidth + marginRight;

				$item.data('index', i);
				$item.data('offset', itemOffset);
				$item.data('width', itemWidth);
			});

			if ( totalWidth < windowWidth ) {
				$container.parent().addClass('is--at-start is--at-end').addClass('carousel-center');
			}

			lastScroll 	= zeroWidth - offset;
			$images 	= $container.children();

			onScroll();
			$container.on('scroll', onScroll);
			$('.gallery-arrow-prev').on('click', goToPrev);
			$('.gallery-arrow-next').on('click', goToNext);
			$prev.add($next).addClass('is--ready');
		}

		if ( isRtl ) {
			$container.scrollLeft( $container[0].scrollWidth );
		}
	}

	function onScroll() {
		lastScroll = $container.scrollLeft();
		$container.parent()
			.toggleClass('is--at-start', lastScroll <= 10)
			.toggleClass('is--at-end', lastScroll >= totalWidth - windowWidth - 10);
	}

	function goToPrev() {
		var $to;
		$images.each(function(i, obj) {
			var $image = $(obj);
			if ($image.data('offset') < lastScroll) {
				$to = $image;
			}
		});

		if (typeof $to !== "undefined") {
			setCurrent($to);
		}
	}

	function goToNext() {
		var $to;
		$images.each(function(i, obj) {
			var $image = $(obj);

			if ($image.data('offset') + $image.data('width') > lastScroll + windowWidth) {

				if ( $image.attr('src') == $currentImg.attr('src') ) {
					$image = $image.next();
				}

				$to = $image;
				return false;
			}
		});

		if (typeof $to !== "undefined") {
			setCurrent($to);
		}
	}

	function setCurrent($current) {
		$currentImg = $current;

		TweenLite.to($container, .3, {
			scrollTo: {
				x: $current.data('offset') - offset
			},
			ease: Power2.easeOut
		});
	}

	return {
		init: init
	}
})();

$('.js-widget-gallery').magnificPopup({
	delegate: '.listing-gallery__item', // child items selector, by clicking on it popup will open
	type: 'image',
	image: {
		titleSrc: function (item) {
			var output = '';

			output += item.el.find('img').attr('caption');
			output += '<span class="mfp-description">' + item.el.find('img').attr('description') + '</span>';

			return output;
		}
	},
	gallery: {
		enabled: true,
		tCounter: '<span class="mfp-counter">%curr%/%total%</span>',
		arrowMarkup: '<div class="gallery-arrow  gallery-arrow-%dir%  is--ready">' + $('.arrow-icon-svg').html() + '</div>'
	}
});

$('.listing-gallery__all').on( 'click', function(e) {
	e.preventDefault();
	$('.js-widget-gallery').magnificPopup('open');
} );

if ( typeof listable_params.login_url !== "undefined" && listable_params.login_url.indexOf( 'action=logout' ) === -1 ) {
	$('a.iframe-login-link').magnificPopup({
		mainClass: "mfp-bg-transparent  mfp-login-modal",
		type: 'iframe',
		src: listable_params.login_url,
		iframe: {
			markup: '<div class="mfp-iframe-scaler  mfp-wp-login">'+
			'<div class="mfp-close"></div>'+
			'<iframe class="mfp-iframe" frameborder="0" allowfullscreen></iframe>'+
			'</div>' // HTML markup of popup, `mfp-close` will be replaced by the close button
		},
		callbacks: {
			open: function() {
				if ( ! listableDocumentCookies.hasItem('listable_login_modal') )  {
					listableDocumentCookies.setItem('listable_login_modal', 'opened', null, '/');
				}

				closeMenu();

				$('body').addClass('overlay-is-open');
				$('body').width($('body').width());
				$('body').css('overflow', 'hidden');
			},
			close: function() {
				listableDocumentCookies.removeItem('listable_login_modal', '/');

				$('body').removeClass('overlay-is-open');
				$('body').removeAttr('style');
			}
		}
	});
}
if ( $( '#map' ).length && typeof L === "object" ) {
	// set Leaflet's default path for images
	L.Icon.Default.imagePath = 'wp-content/themes/listable/assets/img/';
}

// Map module
var Map = (
	function () {
		// create a custom icon class that can be extended for each listing category

		var map, markers, CustomHtmlIcon;

		// initialization - check wether we are on the archive page or on a single listing
		function init() {

			if ( $( '.no_job_listings_found' ).length ) {
				$( '<div class="results">' + listable_params.strings['no_job_listings_found'] + '</div>' ).prependTo( '.showing_jobs, .search-query' );
			}

			if ( ! $( '#map' ).length ) {
				$( '#main .job_listings' ).on( 'updated_results', function ( e, result ) {
					updateCards( result.total_found );
				} );
				return;
			}

			if ( typeof L !== "object" || ! L.hasOwnProperty( 'map' ) ) {
				return;
			}

			map = L.map( 'map', {scrollWheelZoom: false} );
			markers = new L.MarkerClusterGroup( {showCoverageOnHover: false} );
			CustomHtmlIcon = L.HtmlIcon.extend( {
				options: {
					html: "<div class='pin'></div>",
					iconSize: [48, 59], // size of the icon
					iconAnchor: [24, 59], // point of the icon which will correspond to marker's location
					popupAnchor: [0, - 59] 	// point from which the popup should open relative to the iconAnchor
				}
			} );

			$window.on( 'pxg:refreshmap', function () {
				map._onResize();
			} );

			var tileLayer,
				mapboxToken = $( 'body' ).data( 'mapbox-token' ),
				mapboxStyle = $( 'body' ).data( 'mapbox-style' );

			if ( ! empty( mapboxToken ) ) {
				tileLayer = L.tileLayer( 'https://api.mapbox.com/styles/v1/pixelgrade/' + mapboxStyle + '/tiles/{z}/{x}/{y}?access_token=' + mapboxToken, {
					tileSize: 512,
					zoomOffset: -1,
					maxZoom: listable_params.mapbox.maxZoom,
					attribution: '&copy; <a href="http://mapbox.com">Mapbox</a> | &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>',
				} )
			} else {
				tileLayer = L.gridLayer.googleMutant( {
					type: 'roadmap'
				} );
				$( '#map' ).addClass( 'map--google' );
			}

			map.addLayer( tileLayer );

			// if we are on the archive page (#map is not a single listing's map) :D
			// @todo do do doom
			if ( ! $( '#map' ).is( '.listing-map' ) ) {
				$( '#main .job_listings' ).on( 'updated_results', function ( e, result ) {
					updateCards( result.total_found );
				} );

				//This one is for FacetWP
				$( document ).on( 'facetwp-loaded', function ( e, result ) {
					updateCards();
				} );
			} else {
				var $item = $( '.single_job_listing' );
				// add only one marker if we're on the single listing page
				if ( typeof $item.data( 'latitude' ) !== "undefined" && typeof $item.data( 'longitude' ) !== "undefined" ) {

					var zoom = (
						typeof MapWidgetZoom !== "undefined"
					) ? MapWidgetZoom : 13;

					addPinToMap( $item );
					map.addLayer( markers );
					map.setActiveArea( 'active-area' );
					map.setView( [$item.data( 'latitude' ), $item.data( 'longitude' )], zoom );
					$( window ).on( 'update:map', function () {
						map.setView( [$item.data( 'latitude' ), $item.data( 'longitude' )], zoom );
					} );
				} else {
					$( '#map' ).hide();
					$( '.listing-address' ).css( 'marginTop', 0 );
				}
			}

			$( '.js-find-me' ).on( 'click', function ( e ) {
				e.preventDefault();
				e.stopPropagation();
				map.locate( {setView: true, maxZoom: listable_params.mapbox.maxZoom} );
			} );
		}

		function updateCards( $total_found ) {

			var $cards = $( '#main .card' );
			var cardsWithLocation = 0;
			var clusterMarkup = document.querySelector('.cluster-icon-svg' ).innerHTML;

			if ( ! $cards.length ) {
				$( 'body' ).addClass( 'has-no-listings' );
				defaultMapView();
				return;
			}

			//first some cleanup to avoid multiple results being shown - it happens
			$( '.showing_jobs .results' ).remove();

			if ( typeof $total_found !== 'undefined' ) {
				//someone must have blessed us with higher knowledge
				//let's not let it go to waste
				$( '<div class="results"><span class="results-no">' + $total_found + '</span> ' + listable_params.strings['results-no'] + '</div>' ).prependTo( '.showing_jobs, .search-query' );
			} else {
				$( '<div class="results"><span class="results-no">' + $cards.length + '</span> ' + listable_params.strings['results-no'] + '</div>' ).prependTo( '.showing_jobs, .search-query' );
			}

			if ( $( '.map' ).length && typeof map !== "undefined" ) {
				map.removeLayer( markers );
				markers = new L.MarkerClusterGroup( {
					showCoverageOnHover: false,
					spiderfyDistanceMultiplier: 3,
					spiderLegPolylineOptions: { weight: 0 },
					iconCreateFunction: function( cluster ) {
						return new L.DivIcon( {
							html: clusterMarkup + '<span>' + cluster.getChildCount() + '</span>',
							className: 'marker-cluster',
							iconSize: new L.Point(40, 40) });
					}
				} );
				$cards.each( function ( i, obj ) {
					var cardHasLocation = addPinToMap( $( obj ), true );
					if ( cardHasLocation ) {
						cardsWithLocation += 1;
					}
				} );

				if (cardsWithLocation != 0) {
					map.fitBounds(markers.getBounds(), {padding: [50, 50]});
					map.addLayer(markers);

					var mapZoom = map.getZoom();
					var bounds = markers.getBounds();
					var lat = ( bounds._northEast.lat + bounds._southWest.lat ) / 2;
					var lng = ( bounds._northEast.lng + bounds._southWest.lng ) / 2;
					bounds = [lat, lng];

					Cookies.set('pxg-listable-bounds', JSON.stringify(bounds));
					Cookies.set('pxg-listable-mapZoom', mapZoom);
				} else {
					defaultMapView();
				}
			}
		}

		function addPinToMap( $item, archive ) {
			var categories = $item.data( 'categories' ),
				iconClass, m;

			if ( empty( $item.data( 'latitude' ) ) || empty( $item.data( 'longitude' ) ) ) {
				return false;
			}

			if ( typeof categories !== "undefined" && ! categories.length ) {
				iconClass = 'pin pin--empty';
			} else {
				iconClass = 'pin';
			}

			var $icon = $( '.selected-icon-svg' ),
				$tags = $item.find( '.card__tag' ),
				$categories = $item.find( '.category-icon' ),
				$tag, iconHTML = "<div class='" + iconClass + "'>" + $( '.empty-icon-svg' ).html() + "</div>";

			if ( $body.is( '.single-job_listing' ) ) {
				// If we are on a single listing
				if ( $( '.single-listing-map-category-icon' ).length ) {
					iconHTML = "<div class='" + iconClass + "'>" + $icon.html() + "<div class='pin__icon'>" + $( '.single-listing-map-category-icon' ).html() + "</div></div>";
				}
			} else if ( $tags.length ) {
				$tag = $tags.first();
				iconHTML = "<div class='" + iconClass + "'>" + $icon.html() + $tag.html() + "</div>";
			} else if ( $categories.length ) {
				iconHTML = "<div class='" + iconClass + "'>" + $icon.html() + "<div class='pin__icon'>" + $categories.html() + "</div></div>";
			}

			m = L.marker( [$item.data( 'latitude' ), $item.data( 'longitude' )], {
				icon: new CustomHtmlIcon( {
					html: iconHTML
				} )
			} );

			if ( typeof archive !== "undefined" ) {

				$item.hover( function () {
					$( m._icon ).find( '.pin' ).addClass( 'pin--selected' );
				}, function () {
					$( m._icon ).find( '.pin' ).removeClass( 'pin--selected' );
				} );

				var rating = $item.find( '.js-average-rating' ).text(),
					ratingHTML = rating.length ? "<div class='popup__rating'><span>" + rating + "</span></div>" : "",
					address = $item.find( '.card__address' ).text();

				m.bindPopup(
					"<a class='popup' href='" + $item.data( 'permalink' ) + "'>" +
					"<div class='popup__image' style='background-image: url(" + $item.data( 'img' ) + ");'></div>" +
					"<div class='popup__content'>" +
					"<h3 class='popup__title'>" + $item.find( '.card__title' ).html() + "</h3>" +
					"<div class='popup__footer'>" +
					ratingHTML +
					"<div class='popup__address'>" + $item.find( '.card__address' ).html() + "</div>" +
					"</div>" +
					"</div>" +
					"</a>" ).openPopup();
			}

			markers.addLayer( m );

			return true;
		}

		function defaultMapView() {
			var defaultLocation = $( 'body' ).data( 'map-default-location' ),
				defaultCoordinates = [51.5073509, -0.12775829999998223];

			if ( typeof defaultLocation !== "undefined" ) {
				defaultCoordinates = defaultLocation.split( ',' );
				defaultCoordinates = defaultCoordinates.map( function callback( currentValue ) {
					return parseFloat( currentValue );
				} );
			}

			map.removeLayer( markers );
			map.setView( defaultCoordinates, 9 );
		}

		return {
			init: init,
			updateResults: updateCards
        }
	}
)();

function platformDetect() {

	var	isIE = typeof (is_ie) !== "undefined" || (!(window.ActiveXObject) && "ActiveXObject" in window),
		isiele10 = ua.match(/msie (9|([1-9][0-9]))/i),
		isie9 = ua.match(/msie (9)/i);

	iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

	if (isIE) {
		$html.addClass('is--ie');
	}

	if (isiele10) {
		$html.addClass('is--iele10');
	}

	if (isie9) {
		$html.addClass('is--ie9');
	}

	if (/Edge\/12./i.test(navigator.userAgent)){
		$html.addClass('is--edge');
	}

	if( iOS ) {
		$html.addClass('is--ios');
	}
}
// /* ====== ON DOCUMENT READY ====== */
$( document ).ready( function () {
	init();

	$( '.job_filters' ).bindFirst( 'click', '.reset', function () {
		$( '.active-tags' ).empty();
		$( '.tags-select' ).find( ':selected' ).each( function ( i, obj ) {
			$( obj ).attr( 'selected', false );
		} );
		$( '.tags-select' ).trigger( "chosen:updated" );

		$( 'input[name="search_keywords"]' ).each( function ( i, obj ) {
			$( obj ).val( '' ).trigger( 'chosen:updated' );
		} );
	} );

    $('.wc-social-login').attr('data-string', listable_params.strings.social_login_string);
} );

// [name] is the name of the event "click", "mouseover", ..
// same as you'd pass it to bind()
// [fn] is the handler function
$.fn.bindFirst = function ( name, selector, fn ) {
	// bind as you normally would
	// don't want to miss out on any jQuery magic
	this.on( name, selector, fn );

	// Thanks to a comment by @Martin, adding support for
	// namespaced events too.
	this.each( function () {
		var handlers = $._data( this, 'events' )[name.split( '.' )[0]];
		// take out the handler we just inserted from the end
		var handler = handlers.pop();
		// move it at the beginning
		handlers.splice( 0, 0, handler );
	} );
};

function customizerOptionsPadding() {
    var $updatable = $( '.page-listings .js-header-height-padding-top' ),
        $map = $( '.map' ),
        $jobFilters = $( ' .job_filters .search_jobs div.search_location' ),
        $findMeButton = $( '.findme' ),
        headerHeight = $( '.site-header' ).outerHeight();

    // set padding top to certain elements which is equal to the header height

    $updatable.css( 'paddingTop', '' );
    $updatable.css( 'paddingTop', headerHeight );

    if ( $( '#wpadminbar' ).length ) {
        headerHeight += $( '#wpadminbar' ).outerHeight();
    }

    $map.css( 'top', headerHeight );
    $jobFilters.css( 'top', headerHeight );
    $findMeButton.css( 'top', headerHeight + 70);
}

function init() {
	platformDetect();
	browserSupport();
	browserSize();

	eventHandlers();

    customizerOptionsPadding();
    handleHiddenFacetFieldsOnMobile();
	handleSearchFunctionality();

	$( 'html' ).addClass( 'is--ready' );

    var $body = $( 'body' );
    var withChosen = isChosenEnabled();

    $body.toggleClass( 'with-chosen', withChosen );
    $body.toggleClass( 'without-chosen', ! withChosen );

	var $email = $( 'input#account_email' ),
		$target = $( '.field.account-sign-in' ),
		$fieldset;

	if ( $email.length && $target.length ) {
		$fieldset = $email.closest( 'fieldset' );
		$email.insertAfter( $target );
		$fieldset.remove();
	}

	var $uploader = $( '.wp-job-manager-file-upload' );

	$uploader.each( function ( i, obj ) {
		var $input = $( obj ),
			id = $( obj ).attr( 'id' ),
			$label = $( 'label[for="' + id + '"]' ),
			$btn = $( '<div class="uploader-btn"><div class="spacer"><div class="text">' + listable_params.strings['wp-job-manager-file-upload'] + '</div></div></div>' ).insertAfter( $input );

		$btn.on( 'click', function () {
			$label.trigger( 'click' );
		} );
	} );

	$( '#main_image' ).on( 'change', function ( e ) {
		var self = this;
		var this_logo = $( '#company_logo' ).val();

		if ( this_logo === '' ) {
			var url = self.value;
		}
	} );

	if ( $( '#job_preview_wrapper' ).length ) {
		$body.addClass( 'single-job_listing single-job_listing_preview' ).removeClass( 'page-add-listing' );
		$( '.page' ).removeClass( 'page' );
		$( '.listing-map' ).css( {
			display: '',
			height: ''
		} );
		singleListingMapHeight();
		$window.trigger( 'pxg:refreshmap' );
		$( '#job_preview_wrapper' ).css( 'opacity', 1 );
	}

	$( '.btn--filter' ).on( 'click', function ( e ) {
		e.preventDefault();
		e.stopPropagation();

		if ( $body.hasClass( 'show-filters' ) ) {
			$window.scrollTop( 0 );
		}
		$body.toggleClass( 'show-filters' );
	} );

	$( '.btn--view' ).on( 'click', function ( e ) {
		e.preventDefault();
		e.stopPropagation();
		$body.toggleClass( 'show-map' );
		$( 'html, body' ).scrollTop( 0 );
		setTimeout( function () {
			$window.trigger( 'pxg:refreshmap' );
		} );
	} );

	if ( $( '#job_package_selection' ).length ) {
		$body.addClass( 'page-package-selection' );

		var $nopackages = $( '.no-packages' );

		if ( $nopackages.length ) {
			var $form = $nopackages.closest( '#job_package_selection' );

			if ( $form.length ) {
				$nopackages.insertAfter( $form );
				$form.remove();
			}
		}
	}

	Map.init();

	detectLongMenu();
	moveListingStickySidebar();
	singleListingMapHeight();
	moveSingleListingReviews();
	moveSingleListingClaimWidget();

	if ( $( '.search-field-wrapper.has--menu' ).length ) {
		searchSuggestionsTrigger();
	}

	$reviewsParent = $( '.widget_listing_comments' ).parent();

	$( '.showlogin' ).off( 'click' ).on( 'click', function () {
		$( '.login-container' ).slideToggle();
	} );
}

// /* ====== ON WINDOW LOAD ====== */
$window.on('load', function () {

	$( 'html' ).addClass( 'is--loaded' );

	Carousel.init();

	// if we're on the listings archive do this shit
	// @todo do do doom
	if ( $( '.tags-select' ).length && ! $( '.listing-map' ).length ) {
		var $tags = $( '.tags-select' ).chosen(),
			updateTags = function () {
				$( '.active-tags' ).empty();
				$tags.find( ':selected' ).each( function ( i, obj ) {
					if ( empty( obj.value ) ) {
						return;
					}

					$( '<div class="active-tag">' + obj.value + '<div class="remove-tag"></div></div>' ).appendTo( '.active-tags' ).on( 'click', function () {
						$( this ).remove();
						$( obj ).attr( 'selected', false );
						$tags.trigger( "chosen:updated" );
						$( '.active-tags input[value="' + obj.value + '"]' ).remove();
						$( '.job_listings' ).triggerHandler( 'update_results', [1, false] );
					} );

					$( '<input type="hidden" name="job_tag[]" value="' + obj.value + '" />' ).appendTo( '.active-tags' );
				} );
				$( '.job_listings' ).triggerHandler( 'update_results', [1, false] );
			};

		$tags.on( 'change', updateTags );

		var $categories = $( '#search_categories' ),
			updateCategories = function () {
				$( '.active-categories' ).empty();
				$categories.find( ':selected' ).each( function ( i, obj ) {
					$( '<div class="active-category">' + $( obj ).text() + '<div class="remove-tag"></div></div>' ).appendTo( '.active-categories' ).on( 'click', function () {
						$( obj ).attr( 'selected', false );
						$categories.trigger( "chosen:updated" );
						$( this ).remove();
						$( '.job_listings' ).triggerHandler( 'update_results', [1, false] );
					} );
				} );
				updateTags();
			};

		// updateCategories();
		$categories.on( 'change', updateCategories );
	}

	if ( $().chosen ) {
		$( '.search_jobs--frontpage .job-manager-category-dropdown' ).chosen();
	}

	tooltipTrigger();
	keepSubmenusInViewport();

	$( '.js-menu-trigger' ).on( 'touchstart click', toggleMenu );

	HandleSubmenusOnTouch.unbind();
	if ( windowWidth < 900 ) {
		HandleSubmenusOnTouch.initSidebarMenu();
	} else {
		if ( Modernizr.touchevents ) {
			HandleSubmenusOnTouch.initHorizontalMenu();
		}
	}

	if ( $( '.site-header .search-form' ).is( ':visible' ) ) {
		handleMobileHeaderSearch();
	}

	frontpageVideoInit();

	loginWithAjaxHandlers();

	$window.trigger( 'pxg:refreshmap' );
} );

//for search listings we need to make some magic to make it behave like the categories and tags archives
function handleSearchFunctionality() {

	var $searchField = $( '#search_keywords' ),
		$searchFieldPlaceholder = $( '#search_keywords_placeholder' ),
		$form = $searchFieldPlaceholder.closest( 'form' ),
		$jobListings = $( '.job_listings' );

	if ( $body.is('.page-listings' ) ) {

		$jobListings.data( 'disable-form-state-storage', true );
		$jobListings.on( 'updated_results', function() {
			$jobListings.data( 'disable-form-state-storage', '' );
		} );

		$searchFieldPlaceholder.on( 'input', function() {
			$searchField.val( $searchFieldPlaceholder.val() );
		} );

		$form.on( 'submit', function(e) {
			e.preventDefault();
			$('.job_listings').triggerHandler( 'update_results', [ 1, false ] );
		} );
	}
}

function eventHandlers() {

	$window.on( 'debouncedresize', function () {
		browserSize();
		detectLongMenu();
		moveListingStickySidebar();
		singleListingMapHeight();
		moveSingleListingReviews();
		handleHiddenFacetFieldsOnMobile();
        customizerOptionsPadding();

		setTimeout( function () {
			$window.trigger( 'update:map' );
			$window.trigger( 'pxg:refreshmap' );
		} );

		if ( windowWidth < 900 ) {
			$( '.site-header' ).css( 'paddingBottom', '' );
		} else {
			var headerPaddingBottom = parseInt( $( '.site-header' ).css( 'paddingTop' ) ) + $( '.secondary-menu' ).outerHeight();
			$( '.site-header' ).css( 'paddingBottom', headerPaddingBottom );
		}

		HandleSubmenusOnTouch.unbind();
		if ( windowWidth < 900 ) {
			HandleSubmenusOnTouch.initSidebarMenu();
		} else {
			if ( Modernizr.touchevents ) {
				HandleSubmenusOnTouch.initHorizontalMenu();
			}
		}
	} );

	$window.on( 'scroll', function () {
		latestKnownScrollY = $window.scrollTop();
		latestKnownScrollX = $window.scrollLeft();
	} );

	$( window ).on( 'mousemove', function ( e ) {
		latestKnownMouseX = e.clientX;
		latestKnownMouseY = e.clientY;
	} );

	$( window ).on( 'deviceorientation', function ( e ) {
		latestDeviceAlpha = e.originalEvent.alpha;
		latestDeviceBeta = e.originalEvent.beta;
		latestDeviceGamma = e.originalEvent.gamma;
	} );

	handleHiddenFacets();
	handleLongSubMenus();
	hideCategoryDescription();

	// After FacetWP fetches new items,
	// scroll listings page to top to see
	// all new loaded items.
	if ( $body.is( '.page-listings' ) ) {

		var $facetWpLoadMore = $( '.fwp-load-more' ).first();
		$facetWpLoadMore.insertAfter( '.facetwp-template' );
		$facetWpLoadMore.wrap( '<div class="fwp-load-more-wrapper">' );

		$facetWpLoadMore.on( 'click', function() {

			$( document ).one( 'facetwp-loaded', function() {
				// hacking starts here
				var $lists = $( '.job_listings.list' );

				if ( $lists.length <= 1 ) {
					TweenLite.to( window, 1, {scrollTo: 0} );
					console.log('here');
				} else {
					var $firstList = $lists.first();
					var $otherLists = $lists.not( $firstList );

					$otherLists.children().appendTo( $firstList );
					$otherLists.remove();
				}
			} );

		} );
	}
}

/* ====== HELPER FUNCTIONS ====== */


/**
 * Detect what platform are we on (browser, mobile, etc)
 */

function browserSupport() {
	$.support.touch = 'ontouchend' in document;
	$.support.svg = document.implementation.hasFeature( "http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1" );
	$.support.transform = getSupportedTransform();

	$html
		.addClass( $.support.touch ? 'touch' : 'no-touch' )
		.addClass( $.support.svg ? 'svg' : 'no-svg' )
		.addClass( ! ! $.support.transform ? 'transform' : 'no-transform' );
}

function browserSize() {
	windowHeight = $window.height();
	windowWidth = $window.width();
	documentHeight = $document.height();
	orientation = windowWidth > windowHeight ? 'portrait' : 'landscape';
}

function getSupportedTransform() {
	var prefixes = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'];
	for ( var i = 0; i < prefixes.length; i ++ ) {
		if ( document.createElement( 'div' ).style[prefixes[i]] !== undefined ) {
			return prefixes[i];
		}
	}
	return false;
}

/**
 * Handler for the back to top button
 */
function scrollToTop() {
	$( 'a[href="#top"]' ).click( function ( event ) {
		event.preventDefault();
		event.stopPropagation();

		TweenMax.to( $( window ), 1, {
			scrollTo: {
				y: 0,
				autoKill: true
			},
			ease: Power3.easeOut
		} );
	} );
}

/**
 * function similar to PHP's empty function
 */

function empty( data ) {
	if ( typeof( data ) === 'number' || typeof( data ) === 'boolean' ) {
		return false;
	}
	if ( typeof( data ) === 'undefined' || data === null ) {
		return true;
	}
	if ( typeof( data.length ) !== 'undefined' ) {
		return data.length === 0;
	}
	var count = 0;
	for ( var i in data ) {
		// if(data.hasOwnProperty(i))
		//
		// This doesn't work in ie8/ie9 due the fact that hasOwnProperty works only on native objects.
		// http://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8
		//
		// for hosts objects we do this
		if ( Object.prototype.hasOwnProperty.call( data, i ) ) {
			count ++;
		}
	}
	return count === 0;
}

function toggleMenu( e ) {
	if ( e ) {
		e.preventDefault();
		e.stopPropagation();
	}

	$( 'body' ).toggleClass( 'nav-is-open' );

	$( 'body' ).toggleClass( 'overlay-is-open' );

	if ( $( 'body' ).hasClass( 'overlay-is-open' ) ) {
		$( 'body' ).width( $( 'body' ).width() );
		$( 'body' ).css( 'overflow', 'hidden' );
	} else {
		$( 'body' ).removeAttr( 'style' );
	}
}

function closeMenu() {
	$( 'body' ).removeClass( 'nav-is-open' );
	$( 'body' ).removeClass( 'overlay-is-open' );
	$( 'body' ).removeAttr( 'style' );
}

// Set the height of the single listing map
function singleListingMapHeight() {
	if ( windowWidth > 900 ) {
		var $listingMap = $( '.listing-sidebar--top .widget_listing_sidebar_map:first-child .listing-map' );

		if ( $( '.entry-featured-image' ).length && $listingMap.length ) {
			var featuredTop = $( '.entry-featured-image' ).offset().top;
			var featuredHeight = $( '.entry-featured-image' ).height();
			var featuredBottom = featuredTop + featuredHeight;
			var mapFeaturedDistance = $listingMap.offset().top - featuredBottom + 1;
			var headerHeight = $( '.single_job_listing .entry-header' ).outerHeight();
			var mapComputedHeight = headerHeight - mapFeaturedDistance;
			$listingMap.height( mapComputedHeight );

			$window.trigger( 'pxg:refreshmap' );
		}
	}
}


// Move listing sticky sidebar under header on mobile
function moveListingStickySidebar() {

	var $sidebarTop = $( '.listing-sidebar--top' ),
		$sidebarBottom = $( '.listing-sidebar--bottom' ),
		isTop = $sidebarTop.data( 'isTop' );

	if ( ! $sidebarTop.length ) {
		return;
	}

	if ( windowWidth < 900 ) {
		if ( isTop !== true ) {
			$sidebarTop.insertAfter( $( '.entry-header' ) );
			isTop = true;
		}
	} else {
		if ( isTop !== false ) {
			$sidebarTop.insertBefore( $sidebarBottom );
			isTop = false;
		}
	}

	$sidebarTop.data( 'isTop', isTop );
}

// When there's a long menu, prevent it from breaking on two lines
function detectLongMenu() {
	if ( windowWidth > 900 ) {
		var $menuWrapper = $( '.menu-wrapper' );

		if ( $menuWrapper.find( 'ul:first-of-type' ).height() > $menuWrapper.height() ) {
			$menuWrapper.addClass( 'has--long-menu' );
		}

		if ( $menuWrapper.find( 'ul:first-of-type' ).width() < $menuWrapper.width() ) {
			$menuWrapper.removeClass( 'has--long-menu' );
		}
	}
}

function tooltipTrigger() {
	$( '.js-tooltip-trigger' ).on( 'click', function ( e ) {
		e.preventDefault();
		e.stopPropagation();

		$( this ).parent().toggleClass( 'active' );

	} );
}

function searchSuggestionsTrigger() {
	var $searchField = $( '.js-search-suggestions-field' );
	var $searchForm = $( '.js-search-form' );

	function makeActive() {
		$searchForm.addClass( 'is--active' );
	}

	function makeInactive() {
		$searchForm.removeClass( 'is--active' );
	}

	function toggleActive() {
		$searchForm.toggleClass( 'is--active' );
	}

	$searchField.on( 'blur', function () {
		setTimeout( makeInactive, 150 );
	} );

	$searchField.on( 'click', function(e) {
		e.stopPropagation();
		toggleActive();
	} );

	$( '#page' ).on( 'click', function (e) {
		if ( $searchField.is( ':focus' ) ) {
			$searchField.blur();
		}
	} );
}

function handleMobileHeaderSearch() {
	// When clicking on search icon, show the search input
	$( '.js-search-trigger-mobile' ).on( 'click', toggleHeaderSearch );

	// When the search input loses focus, hide the input
	$( '.js-search-mobile-field' ).on( 'blur', function ( e ) {
		setTimeout( function closeMobileSearch() {
			$( '.js-search-form' ).removeClass( 'is--active' );
		}, 150 );
	} );

	function toggleHeaderSearch( e ) {
		e.preventDefault();
		e.stopPropagation();

		if ( ! $( '.js-search-form' ).hasClass( 'is--active' ) ) {
			$( '.js-search-form' ).addClass( 'is--active' );
			$( '.js-search-mobile-field' ).focus();
		}
	}
}

// Detect the submenus that exceed the viewport
// and add a class to make them open vertically
function keepSubmenusInViewport() {
	if ( $( '.primary-menu' ).length ) {
		var headerRightmost = $( '.site-header' ).outerWidth();

		$( '.sub-menu' ).each( function () {
			var submenuRightmost = $( this ).offset().left + $( this ).width();

			// if the sub menu exceeds primary menu's rightmost edge
			if ( submenuRightmost > headerRightmost ) {
				$( this ).addClass( 'is--forced-placed' );

				$( this ).find( '.sub-menu' ).addClass( 'is--forced-placed' );
			}
		} );
	}
}

function moveSingleListingReviews() {
	// On mobile, when focusing on a review field, the keyboard appears thus
	// triggering a resize. When a resize is triggered, trying to move the
	// reviews causes fields to lose focus, hiding the keyboard. Prevent that.
	if ( Modernizr.touchevents && $( 'input, textarea' ).is( ':focus' ) ) {
		return;
	}

	if ( $( '.widget_listing_comments' ).length ) {
		if ( windowWidth < 900 ) {
			if ( $( '.widget_listing_comments' ).parent().hasClass( 'column-sidebar' ) ) {
				return;
			}

			$( '.widget_listing_comments' ).appendTo( $( '.column-sidebar' ) );
		} else {
			$( '.widget_listing_comments' ).appendTo( $reviewsParent );
		}
	}
}

function moveSingleListingClaimWidget() {
	var $claimWidget = $( '.listing-sidebar--bottom .widget_listing_sidebar_claim_listing' );

	if ( $claimWidget.length ) {
		var $parentSidebar = $claimWidget.parent();

		$claimWidget.each( function () {
			if ( $( this ).is( ':first-of-type' ) ) {
				$( this ).insertBefore( $parentSidebar ).addClass( 'is--independent' );
			} else if ( $( this ).is( ':last-of-type' ) ) {
				$( this ).insertAfter( $parentSidebar ).addClass( 'is--independent' );
			}
		} );
	}
}

var listableDocumentCookies = {
	getItem: function ( sKey ) {
		if ( ! sKey ) {
			return null;
		}
		return decodeURIComponent( document.cookie.replace( new RegExp( "(?:(?:^|.*;)\\s*" + encodeURIComponent( sKey ).replace( /[\-\.\+\*]/g, "\\$&" ) + "\\s*\\=\\s*([^;]*).*$)|^.*$" ), "$1" ) ) || null;
	},
	setItem: function ( sKey, sValue, vEnd, sPath, sDomain, bSecure ) {
		if ( ! sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test( sKey ) ) {
			return false;
		}
		var sExpires = "";
		if ( vEnd ) {
			switch ( vEnd.constructor ) {
				case Number:
					sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
					break;
				case String:
					sExpires = "; expires=" + vEnd;
					break;
				case Date:
					sExpires = "; expires=" + vEnd.toUTCString();
					break;
			}
		}
		document.cookie = encodeURIComponent( sKey ) + "=" + encodeURIComponent( sValue ) + sExpires + (
				sDomain ? "; domain=" + sDomain : ""
			) + (
			                  sPath ? "; path=" + sPath : ""
		                  ) + (
			                  bSecure ? "; secure" : ""
		                  );
		return true;
	},
	removeItem: function ( sKey, sPath, sDomain ) {
		if ( ! this.hasItem( sKey ) ) {
			return false;
		}
		document.cookie = encodeURIComponent( sKey ) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (
				sDomain ? "; domain=" + sDomain : ""
			) + (
			                  sPath ? "; path=" + sPath : ""
		                  );
		return true;
	},
	hasItem: function ( sKey ) {
		if ( ! sKey ) {
			return false;
		}
		return (
			new RegExp( "(?:^|;\\s*)" + encodeURIComponent( sKey ).replace( /[\-\.\+\*]/g, "\\$&" ) + "\\s*\\=" )
		).test( document.cookie );
	},
	keys: function () {
		var aKeys = document.cookie.replace( /((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "" ).split( /\s*(?:\=[^;]*)?;\s*/ );
		for ( var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx ++ ) {
			aKeys[nIdx] = decodeURIComponent( aKeys[nIdx] );
		}
		return aKeys;
	}
};

function frontpageVideoInit() {
	// video resizing
	var $wrapper = $( '.page-template-front_page .entry-header .wp-video' ),
		$video = $( '.page-template-front_page .entry-header .mejs-video' ),
		$header,
		$featured,
		videoWidth,
		videoHeight,
		headerWidth,
		headerHeight,
		newWidth,
		newHeight;

	function stretch() {

		if ( (
		     videoWidth / videoHeight
		     ) > (
		     headerWidth / headerHeight
		     ) ) {
			newHeight = headerHeight;
			newWidth = newHeight * videoWidth / videoHeight;
		} else {
			newWidth = headerWidth;
			newHeight = newWidth * videoHeight / videoWidth;
		}

		$wrapper.css( {
			width: newWidth,
			height: newHeight
		} );
	}

	if ( $wrapper.length ) {
		$header = $( '.page-template-front_page .entry-header' );
		$featured = $( '.page-template-front_page .entry-featured' );
		videoWidth = $video.outerWidth();
		videoHeight = $video.outerHeight();
		headerWidth = $header.outerWidth();
		headerHeight = $header.outerHeight();

		$wrapper.find( 'video' ).prop( 'muted', true )

		stretch();
		$wrapper.addClass( 'is--stretched' ).data( 'ar', newWidth / newHeight );

		$window.on( 'debouncedresize', function () {
			headerWidth = $header.outerWidth();
			headerHeight = $header.outerHeight();
			stretch();
		} );

	}
}

// iOS Multiple Select Bug Fix
if ( navigator.userAgent.match( /iPhone/i ) ) {
	$( 'select[multiple]' ).each( function () {
		var select = $( this ).on( {
			"focusout": function () {
				var values = select.val() || [];
				setTimeout( function () {
					select.val( values.length ? values : [''] ).change();
				}, 1000 );
			}
		} );
		var firstOption = '<option value="" disabled="disabled"';
		firstOption += (
		               select.val() || []
		               ).length > 0 ? '' : ' selected="selected"';
		firstOption += '>' + select.attr( 'data-placeholder' );
		firstOption += '</option>';
		select.prepend( firstOption );
	} );
}

function loginWithAjaxHandlers() {
	if ( $( '.lwa-modal' ).length ) {

		$( '.js-lwa-open-remember-form' ).on( 'click', function ( e ) {
			e.stopPropagation();
			e.preventDefault();

			$( '.js-lwa-login, .js-lwa-remember' ).toggleClass( 'form-visible' );
		} );

		$( '.js-lwa-close-remember-form' ).on( 'click', function () {
			$( '.js-lwa-login, .js-lwa-remember' ).toggleClass( 'form-visible' );
		} );

		$( '.js-lwa-open-register-form' ).on( 'click', function ( e ) {
			e.stopPropagation();
			e.preventDefault();

			$( '.js-lwa-login, .js-lwa-register' ).toggleClass( 'form-visible' );
		} );

		$( '.js-lwa-close-register-form' ).on( 'click', function () {
			$( '.js-lwa-login, .js-lwa-register' ).toggleClass( 'form-visible' );
		} );

		$( '.lwa-login-link' ).on( 'touchstart', function () {
			closeMenu();
		} );
	}
}

var HandleSubmenusOnTouch = (
	function () {

		var $theUsualSuspects,
			$theUsualAnchors,
			initialInit = false,
			isHorizontalInitiated = false,
			isSidebarInitiated = false;

		function init() {
			if ( initialInit ) {
				return;
			}

			$theUsualSuspects = $( 'li[class*=children]' );
			$theUsualAnchors = $theUsualSuspects.find( '> a' );

			bindOuterNavClick();

			initialInit = true;
		}

		// Sub menus will be opened with a click on the parent
		// The second click on the parent will follow parent's link
		function initHorizontalMenu() {
			if ( isHorizontalInitiated ) {
				return;
			}

			init();
			unbind();

			// Make sure there are no open menu items
			$theUsualSuspects.removeClass( 'hover' );

			$theUsualAnchors.on( 'click', function ( e ) {

				if ( ! $( this ).hasClass( 'active' ) ) {
					e.preventDefault();
					e.stopPropagation();

					return;
				}

				$theUsualAnchors.removeClass( 'active' );
				$( this ).addClass( 'active' );

				// When a parent menu item is activated,
				// close other menu items on the same level
				$( this ).parent().siblings().removeClass( 'hover' );

				// Open the sub menu of this parent item
				$( this ).parent().addClass( 'hover' );
			} );

			isHorizontalInitiated = true;
		}

		// Sub menus will be opened on arrow click
		function initSidebarMenu() {
			if ( isSidebarInitiated ) {
				return;
			}

			init();
			unbind();

			$theUsualAnchors.on( 'touchstart click', function ( e ) {
				var posX = e.originalEvent.touches ? e.originalEvent.touches[0].pageX : e.pageX,
					width = $( this ).outerWidth(),
					isRtl = $( 'body' ).is( '.rtl' ),
					ltrTrigger = ! isRtl && ( width - posX < 60 ),
					rtlPos = posX - ( windowWidth - width ),
					rtlTrigger = isRtl && rtlPos < 60 && rtlPos > 0;

				if ( ltrTrigger || rtlTrigger ) {

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

					if ( $( this ).parent().hasClass( 'hover' ) ) {
						$( this ).parent().removeClass( 'hover' );
					} else {
						$( this ).parent().addClass( 'hover' );
						$( this ).parent().siblings().removeClass( 'hover' );
					}
				}
			} );

			isSidebarInitiated = true;
		}

		function unbind() {
			if ( ! initialInit ) {
				return;
			}
			$theUsualAnchors.unbind();
			isHorizontalInitiated = false;
			isSidebarInitiated = false;
		}

		// When a sub menu is open, close it by a touch on
		// any other part of the viewport than navigation.
		// use case: normal, horizontal menu, touch events,
		// sub menus are not visible.
		function bindOuterNavClick() {
			$( 'body' ).on( 'touchstart', function ( e ) {
				var container = $( '.menu-wrapper' );

				if ( ! container.is( e.target ) // if the target of the click isn't the container...
				     && container.has( e.target ).length === 0 ) // ... nor a descendant of the container
				{
					$theUsualSuspects.removeClass( 'hover' ).removeClass( 'active' );
				}
			} );
		}

		return {
			initHorizontalMenu: initHorizontalMenu,
			initSidebarMenu: initSidebarMenu,
			unbind: unbind
		}
	}()
);

function handleHiddenFacets() {
	if ( ! $body.hasClass( 'is--using-facetwp' ) ) {
		return;
	}

	$( '.js-toggle-hidden-facets' ).on( 'click', function () {
		$body.toggleClass( 'is--showing-hidden-facets' );
		$( '.hidden_facets' ).slideToggle( 300 );
	} )
}

// Check if a sub menu's height is bigger that windows's width
function handleLongSubMenus() {
	if ( Modernizr.touchevents ) {
		return;
	}

	$( 'li[class*="children"] > a' ).on( 'hover', function () {
		var $subMenu = $( this ).siblings( '.sub-menu' );

		var remainingHeight = windowHeight - this.getBoundingClientRect().top;
		if ( remainingHeight < $subMenu.height() ) {
			$subMenu.addClass( 'big-one' );
		}
	} );
}

// Hide the category description after a FacetWP filtering
function hideCategoryDescription() {
	if ( $body.hasClass( 'is--using-facetwp' ) ) {

		checkAndHideForFacet();

		$( document ).on( 'facetwp-refresh', function () {
			setTimeout( function () {
				checkAndHideForFacet();
			}, 1 );
		} );

	} else {
		$( '.job_listings' ).on( 'update_results', function () {
			$( '.listing_category_description.do-hide' ).hide();

			// An 'update_results' event is triggered on page load;
			// hide it only after it gets the class do-hide;
			// (only after the initial 'update_results' event is triggered)
			$( '.listing_category_description' ).addClass( 'do-hide' );
		} );
	}
}

function checkAndHideForFacet() {
	var windowPath = window.location.href;

	if ( windowPath.indexOf( "fwp" ) > - 1 ) {
		$( '.listing_category_description' ).hide();
	} else {
		$( '.listing_category_description' ).show();
	}
}

var handleHiddenFacetFieldsOnMobile = (function() {
	var $container = $( '.header-facet-wrapper' );
	var $target = $( '.search_jobs' );
	var $fields = $container.children().not( '.search-submit' );

	return function() {
		if ( ! $container.length ) {
			return;
		}
		if ( $container.is( ':visible' ) ) {
			if ( $fields.parent().is( $target ) ) {
				$fields.prependTo( $container );
			}
		} else {
			if ( $fields.parent().is( $container ) ) {
				$fields.prependTo( $target );
			}
		}
	}
})();

// as chosen doesn't initialize on most (if not all) mobile devices
// we test if it is enabled by actually trying to initialize it on a dummy select
// instead of duplicating the function used to disable it on mobile devices
// which can always change
function isChosenEnabled() {
	var isEnabled = false;

	if ( ! $.fn.chosen ) {
		return false;
	}

	var $container = $( '<div>' );
	var $select = $( '<select>' );

	$select.appendTo( $container );
	$select.chosen();

	if ( $container.find( '.chosen-container' ).length ) {
		isEnabled = true;

		$select.chosen( "destroy" );
	}

	$container.remove();

	return isEnabled;
}

})(jQuery);