Twitter bootstrap typeahead multiple values?

denislexic picture denislexic · Sep 30, 2012 · Viewed 54.9k times · Source

I'm using Twitter Bootstrap with Jquery. I want to use the TYPEAHEAD function for a textarea, which I got to work super easily. But I also need it to allow multiple selection.

By that I mean, after I selected one word from the autocomplete, it takes me back to textarea with an extra space afterwards and then if I start typing again, it offers me to do it again.

Here is a JS bin: http://jsbin.com/ewubuk/1/edit (Nothing special inside).

Is there an easy solution to allow multiple selection with typeahead? If yes, how?

Thanks in advance.

Answer

Sherbrow picture Sherbrow · Sep 30, 2012

Edit There already was a pull about that : https://github.com/twitter/bootstrap/pull/2007


You can approach the desired behavior by using a proxy for the typeahead : Demo (jsfiddle)

var $myTextarea = $('#myTextarea');

$('.typeahead').typeahead({
    source: source,
    updater: function(item) {
        $myTextarea.append(item, ' ');
        return '';
    }
});

I think the updater method is meant for this kind of thing, you just return what will be displayed.


Or if you really want everything to be in the same input element, you would have to override more methods so that it only matches the currently-typed element : Demo (jsfiddle)

function extractor(query) {
    var result = /([^,]+)$/.exec(query);
    if(result && result[1])
        return result[1].trim();
    return '';
}

$('.typeahead').typeahead({
    source: source,
    updater: function(item) {
        return this.$element.val().replace(/[^,]*$/,'')+item+',';
    },
    matcher: function (item) {
      var tquery = extractor(this.query);
      if(!tquery) return false;
      return ~item.toLowerCase().indexOf(tquery.toLowerCase())
    },
    highlighter: function (item) {
      var query = extractor(this.query).replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
        return '<strong>' + match + '</strong>'
      })
    }
});

This one is not idiot proof, because you have to type at the end, after the special character.