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('input').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('input').trigger('change');
      });
    } else {
      var val = data.id;
      this.$element.val(val);
      this.$element.trigger('input').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('input').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('input').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;
});
 
  |