Selectize.js: Resume Typing on Focus

Created on 1 Nov 2013  路  7Comments  路  Source: selectize/selectize.js

We're using selectize.js for a search autocomplete menu and it works amazing! (w/ optgroups and 'recent searches'!). The only problem is when the user want to change the search, the selected 'item' has to be removed to search again. With the restore_on_backspace option - it works a little better, but the user is expecting backspace to delete a letter on the first press (instead of the second) and if they start typing w/o hitting backspace, it's not responsive.

Ex. User searches for "Milk" and that is 'created' as a new item in the recent searches optgroup. The "Milk" item stays in the search bar. User clicks back on the bar to refine the search to "Milk Organic" - but typing doesn't work.

Is there anyway to have the search input stay persistant and add items so that its simple to edit the search query?

Thanks for the great work!

(side note - using selectize.js with backbone.stickit and its pretty slick - https://gist.github.com/chiplay/7272109)

enhancement

Most helpful comment

Selectize.define('continue_editing', function(options) {
  if (this.settings.mode != 'single') return;

  var self = this;

  options.text = options.text || function(option) {
    return option[this.settings.labelField];
  };

  this.onFocus = (function(e) {
    var original = self.onFocus;

    return function(e) {
      original.apply(this, arguments);

      var index = this.caretPos - 1;
      if (index >= 0 && index < this.items.length) {
        var option = this.options[this.items[index]];
        var currentValue = options.text.apply(this, [option]);
        if (this.deleteSelection({keyCode: KEY_BACKSPACE})) {
          this.removeItem(currentValue);
          this.setTextboxValue(currentValue);
        }
      }
    };
  })();
});

All 7 comments

Hey @chiplay it's old now, but I wrote #43 to solve this exact problem, I think

Thanks @bradleypriest - I was able to solve this issue by hooking into the Selectize events and wire it up manually:

var _this = this,
    selectize,
    $select,
    options,
    queryVal,
    queryText;

// Get view options
var getDefaultOptions = function(options) {
  options = options || {};
  return _.defaults(options, {
    highlight: false,
    sortField: 'text'
  });
};

options = getDefaultOptions(_.result(_this, 'selectize'));

// Create a 'recent searches' optgroup for new items
var recentSearches = _.once(function() {
  selectize.addOptionGroup('Recent Searches', {label: 'Recent Searches', value: 'Recent Searches'});
});

// Refresh after adding a new optgroup
var refresh = function() {
  selectize.refreshOptions(false);
};

var reset = function() {
  if (selectize.items.length) {
    queryVal = selectize.items[0];
    queryText = selectize.options[queryVal].text;
  }
  selectize.clear();
  selectize.setTextboxValue(queryText);
  selectize.refreshOptions(false);
};

// Call back when observed model attributes change
// Only need to initialize selectize once
var up = function(m, v, o) {
  if (!selectize) {
    $select = $el.selectize(options);
    selectize = $select[0].selectize;

    selectize.on('option_add', recentSearches);
    selectize.on('option_add', selectize.blur);
    selectize.on('optgroup_add', refresh);
    selectize.on('item_add', reset);
  }
};

// Add listeners for each observable
_.each(_.flatten([opt.observe]), function(attr) {
  var e = 'change:' + attr;
  this.listenTo(model, e, up);
  this.listenTo(model, 'stickit:unstuck', function() {
    _this.stopListening(model, e, up);
  });
}, this);
Selectize.define('continue_editing', function(options) {
  if (this.settings.mode != 'single') return;

  var self = this;

  options.text = options.text || function(option) {
    return option[this.settings.labelField];
  };

  this.onFocus = (function(e) {
    var original = self.onFocus;

    return function(e) {
      original.apply(this, arguments);

      var index = this.caretPos - 1;
      if (index >= 0 && index < this.items.length) {
        var option = this.options[this.items[index]];
        var currentValue = options.text.apply(this, [option]);
        if (this.deleteSelection({keyCode: KEY_BACKSPACE})) {
          this.removeItem(currentValue);
          this.setTextboxValue(currentValue);
        }
      }
    };
  })();
});

@christopherdupont Thanks a ton! I was just about to write my own handling for this, but this plugin works great.

@christopherdupont This has been on our backlog for a while to fix. Thank you!

Thanks @christopherdupont -- this almost worked for me. For anybody else borrowing this hack: I had to replace '{keyCode: KEY_BACKSPACE}' with '{keyCode: 8}' to make it work properly.

closing stale issues older than one year.
If this issue was closed in error please message the maintainers.
All issues must include a proper title, description, and examples.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

notflip picture notflip  路  15Comments

eliashdezr picture eliashdezr  路  41Comments

andriijas picture andriijas  路  21Comments

nesl247 picture nesl247  路  37Comments

nepsdotin picture nepsdotin  路  15Comments