text: define([
    '../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"' +
            ' role="textbox" />' +
        '</li>'
      );
  
      this.$searchContainer = $search;
      this.$search = $search.find('input');
  
      var $rendered = decorated.call(this);
  
      return $rendered;
    };
  
    Search.prototype.bind = function (decorated, container, $container) {
      var self = this;
  
      decorated.call(this, container, $container);
  
      container.on('open', function () {
        self.$search.attr('tabindex', 0);
  
        self.$search.focus();
      });
  
      container.on('close', function () {
        self.$search.attr('tabindex', -1);
  
        self.$search.val('');
      });
  
      container.on('enable', function () {
        self.$search.prop('disabled', false);
      });
  
      container.on('disable', function () {
        self.$search.prop('disabled', true);
      });
  
      this.$selection.on('keydown', '.select2-search--inline', function (evt) {
        evt.stopPropagation();
  
        self.trigger('keypress', evt);
  
        self._keyUpPrevented = evt.isDefaultPrevented();
  
        var key = evt.which;
  
        if (key === KEYS.BACKSPACE && self.$search.val() === '') {
          var $previousChoice = self.$searchContainer
            .prev('.select2-selection__choice');
  
          if ($previousChoice.length > 0) {
            var item = $previousChoice.data('data');
  
            self.searchRemoveChoice(item);
          }
        }
      });
  
      this.$selection.on('keyup', '.select2-search--inline', function (evt) {
        self.handleSearch(evt);
      });
    };
  
    Search.prototype.createPlaceholder = function (decorated, placeholder) {
      this.$search.attr('placeholder', placeholder.text);
    };
  
    Search.prototype.update = function (decorated, data) {
      this.$search.attr('placeholder', '');
  
      decorated.call(this, data);
  
      this.$selection.find('.select2-selection__rendered')
                     .append(this.$searchContainer);
  
      this.resizeSearch();
    };
  
    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('unselected', {
        data: item
      });
  
      this.trigger('open');
  
      this.$search.val(item.text + ' ');
    };
  
    Search.prototype.resizeSearch = function () {
      this.$search.css('width', '25px');
  
      var width = '';
  
      if (this.$search.attr('placeholder') !== '') {
        width = this.$selection.innerWidth();
        width -= this.$selection.find('.select2-selection__rendered')
                                .innerWidth();
  
        width = width + 'px';
      } else {
        var minimumWidth = this.$search.val().length + 1;
  
        width = (minimumWidth * 0.75) + 'em';
      }
  
      this.$search.css('width', width);
    };
  
    return Search;
  });
  