diff --git a/select2.js b/select2.js index bc5eadc1..af4a1993 100755 --- a/select2.js +++ b/select2.js @@ -416,6 +416,59 @@ return count; } + /** + * Default tokenizer. This function uses breaks the input on substring match of any string from the + * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those + * two options have to be defined in order for the tokenizer to work. + * + * @param input text user has typed so far or pasted into the search field + * @param selection currently selected choices + * @param selectCallback function(choice) callback tho add the choice to selection + * @param opts select2's opts + * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value + */ + function defaultTokenizer(input, selection, selectCallback, opts) { + var original = input, // store the original so we can compare and know if we need to tell the search to update its text + dupe = false, // check for whether a token we extracted represents a duplicate selected choice + token, // token + index, // position at which the separator was found + i, l, // looping variables + separator; // the matched separator + + if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined; + + while (true) { + index = -1; + + for (i = 0, l = opts.tokenSeparators.length; i < l; i++) { + separator = opts.tokenSeparators[i]; + index = input.indexOf(separator); + if (index >= 0) break; + } + + if (index < 0) break; // did not find any token separator in the input string, bail + + token = input.substring(0, index); + input = input.substring(index + separator.length); + + if (token.length > 0) { + token = opts.createSearchChoice(token, selection); + if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) { + dupe = false; + for (i = 0, l = selection.length; i < l; i++) { + if (equal(opts.id(token), opts.id(selection[i]))) { + dupe = true; break; + } + } + + if (!dupe) selectCallback(token); + } + } + } + + if (original.localeCompare(input) != 0) return input; + } + /** * blurs any Select2 container that has focus when an element outside them was clicked or received focus * @@ -599,9 +652,6 @@ this.select = select = opts.element; } - //Custom tags separator. - opts.separator = opts.separator || ","; - if (select) { // these options are not allowed when attached to a select because they are picked up off the element itself $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () { @@ -1074,12 +1124,19 @@ } }, + /** + * Default tokenizer function which does nothing + */ + tokenize: function() { + + }, + /** * @param initial whether or not this is the call to this method right after the dropdown has been opened */ // abstract updateResults: function (initial) { - var search = this.search, results = this.results, opts = this.opts, data, self=this; + var search = this.search, results = this.results, opts = this.opts, data, self=this, input; // if the search is currently hidden we do not alter the results if (initial !== true && (this.showSearchInput === false || !this.opened())) { @@ -1115,6 +1172,12 @@ render("