text: define([
    './base',
    '../utils',
    'jquery'
  ], function (BaseAdapter, Utils, $) {
    function SelectAdapter ($element, options) {
      this.$element = $element;
      this.options = options;
  
      SelectAdapter.__super__.constructor.call(this);
    }
  
    Utils.Extend(SelectAdapter, BaseAdapter);
  
    SelectAdapter.prototype.current = function (callback) {
      var data = [];
      var self = this;
  
      this.$element.find(':selected').each(function () {
        var $option = $(this);
  
        var option = self.item($option);
  
        data.push(option);
      });
  
      callback(data);
    };
  
    SelectAdapter.prototype.select = function (data) {
      var self = this;
  
      data.selected = true;
  
      // If data.element is a DOM node, use it instead
      if ($(data.element).is('option')) {
        data.element.selected = true;
  
        this.$element.trigger('change');
  
        return;
      }
  
      if (this.$element.prop('multiple')) {
        this.current(function (currentData) {
          var val = [];
  
          data = [data];
          data.push.apply(data, currentData);
  
          for (var d = 0; d < data.length; d++) {
            var id = data[d].id;
  
            if ($.inArray(id, val) === -1) {
              val.push(id);
            }
          }
  
          self.$element.val(val);
          self.$element.trigger('change');
        });
      } else {
        var val = data.id;
  
        this.$element.val(val);
        this.$element.trigger('change');
      }
    };
  
    SelectAdapter.prototype.unselect = function (data) {
      var self = this;
  
      if (!this.$element.prop('multiple')) {
        return;
      }
  
      data.selected = false;
  
      if ($(data.element).is('option')) {
        data.element.selected = false;
  
        this.$element.trigger('change');
  
        return;
      }
  
      this.current(function (currentData) {
        var val = [];
  
        for (var d = 0; d < currentData.length; d++) {
          var id = currentData[d].id;
  
          if (id !== data.id && $.inArray(id, val) === -1) {
            val.push(id);
          }
        }
  
        self.$element.val(val);
  
        self.$element.trigger('change');
      });
    };
  
    SelectAdapter.prototype.bind = function (container, $container) {
      var self = this;
  
      this.container = container;
  
      container.on('select', function (params) {
        self.select(params.data);
      });
  
      container.on('unselect', function (params) {
        self.unselect(params.data);
      });
    };
  
    SelectAdapter.prototype.destroy = function () {
      // Remove anything added to child elements
      this.$element.find('*').each(function () {
        // Remove any custom data set by Select2
        $.removeData(this, 'data');
      });
    };
  
    SelectAdapter.prototype.query = function (params, callback) {
      var data = [];
      var self = this;
  
      var $options = this.$element.children();
  
      $options.each(function () {
        var $option = $(this);
  
        if (!$option.is('option') && !$option.is('optgroup')) {
          return;
        }
  
        var option = self.item($option);
  
        var matches = self.matches(params, option);
  
        if (matches !== null) {
          data.push(matches);
        }
      });
  
      callback({
        results: data
      });
    };
  
    SelectAdapter.prototype.addOptions = function ($options) {
      Utils.appendMany(this.$element, $options);
    };
  
    SelectAdapter.prototype.option = function (data) {
      var option;
  
      if (data.children) {
        option = document.createElement('optgroup');
        option.label = data.text;
      } else {
        option = document.createElement('option');
  
        if (option.textContent !== undefined) {
          option.textContent = data.text;
        } else {
          option.innerText = data.text;
        }
      }
  
      if (data.id !== 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
      $.data(option, 'data', normalizedData);
  
      return $option;
    };
  
    SelectAdapter.prototype.item = function ($option) {
      var data = {};
  
      data = $.data($option[0], 'data');
  
      if (data != null) {
        return data;
      }
  
      if ($option.is('option')) {
        data = {
          id: $option.val(),
          text: $option.text(),
          disabled: $option.prop('disabled'),
          selected: $option.prop('selected'),
          title: $option.prop('title')
        };
      } else if ($option.is('optgroup')) {
        data = {
          text: $option.prop('label'),
          children: [],
          title: $option.prop('title')
        };
  
        var $children = $option.children('option');
        var children = [];
  
        for (var c = 0; c < $children.length; c++) {
          var $child = $($children[c]);
  
          var child = this.item($child);
  
          children.push(child);
        }
  
        data.children = children;
      }
  
      data = this._normalizeItem(data);
      data.element = $option[0];
  
      $.data($option[0], 'data', data);
  
      return data;
    };
  
    SelectAdapter.prototype._normalizeItem = function (item) {
      if (!$.isPlainObject(item)) {
        item = {
          id: item,
          text: item
        };
      }
  
      item = $.extend({}, {
        text: ''
      }, item);
  
      var defaults = {
        selected: false,
        disabled: false
      };
  
      if (item.id != null) {
        item.id = item.id.toString();
      }
  
      if (item.text != null) {
        item.text = item.text.toString();
      }
  
      if (item._resultId == null && item.id) {
        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;
  });
  