|
416 | 416 | return count; |
417 | 417 | } |
418 | 418 |
|
| 419 | + /** |
| 420 | + * Default tokenizer. This function uses breaks the input on substring match of any string from the |
| 421 | + * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those |
| 422 | + * two options have to be defined in order for the tokenizer to work. |
| 423 | + * |
| 424 | + * @param input text user has typed so far or pasted into the search field |
| 425 | + * @param selection currently selected choices |
| 426 | + * @param selectCallback function(choice) callback tho add the choice to selection |
| 427 | + * @param opts select2's opts |
| 428 | + * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value |
| 429 | + */ |
| 430 | + function defaultTokenizer(input, selection, selectCallback, opts) { |
| 431 | + var original = input, // store the original so we can compare and know if we need to tell the search to update its text |
| 432 | + dupe = false, // check for whether a token we extracted represents a duplicate selected choice |
| 433 | + token, // token |
| 434 | + index, // position at which the separator was found |
| 435 | + i, l, // looping variables |
| 436 | + separator; // the matched separator |
| 437 | + |
| 438 | + if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined; |
| 439 | + |
| 440 | + while (true) { |
| 441 | + index = -1; |
| 442 | + |
| 443 | + for (i = 0, l = opts.tokenSeparators.length; i < l; i++) { |
| 444 | + separator = opts.tokenSeparators[i]; |
| 445 | + index = input.indexOf(separator); |
| 446 | + if (index >= 0) break; |
| 447 | + } |
| 448 | + |
| 449 | + if (index < 0) break; // did not find any token separator in the input string, bail |
| 450 | + |
| 451 | + token = input.substring(0, index); |
| 452 | + input = input.substring(index + separator.length); |
| 453 | + |
| 454 | + if (token.length > 0) { |
| 455 | + token = opts.createSearchChoice(token, selection); |
| 456 | + if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) { |
| 457 | + dupe = false; |
| 458 | + for (i = 0, l = selection.length; i < l; i++) { |
| 459 | + if (equal(opts.id(token), opts.id(selection[i]))) { |
| 460 | + dupe = true; break; |
| 461 | + } |
| 462 | + } |
| 463 | + |
| 464 | + if (!dupe) selectCallback(token); |
| 465 | + } |
| 466 | + } |
| 467 | + } |
| 468 | + |
| 469 | + if (original.localeCompare(input) != 0) return input; |
| 470 | + } |
| 471 | + |
419 | 472 | /** |
420 | 473 | * blurs any Select2 container that has focus when an element outside them was clicked or received focus |
421 | 474 | * |
|
599 | 652 | this.select = select = opts.element; |
600 | 653 | } |
601 | 654 |
|
602 | | - //Custom tags separator. |
603 | | - opts.separator = opts.separator || ","; |
604 | | - |
605 | 655 | if (select) { |
606 | 656 | // these options are not allowed when attached to a select because they are picked up off the element itself |
607 | 657 | $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () { |
|
1074 | 1124 | } |
1075 | 1125 | }, |
1076 | 1126 |
|
| 1127 | + /** |
| 1128 | + * Default tokenizer function which does nothing |
| 1129 | + */ |
| 1130 | + tokenize: function() { |
| 1131 | + |
| 1132 | + }, |
| 1133 | + |
1077 | 1134 | /** |
1078 | 1135 | * @param initial whether or not this is the call to this method right after the dropdown has been opened |
1079 | 1136 | */ |
1080 | 1137 | // abstract |
1081 | 1138 | updateResults: function (initial) { |
1082 | | - var search = this.search, results = this.results, opts = this.opts, data, self=this; |
| 1139 | + var search = this.search, results = this.results, opts = this.opts, data, self=this, input; |
1083 | 1140 |
|
1084 | 1141 | // if the search is currently hidden we do not alter the results |
1085 | 1142 | if (initial !== true && (this.showSearchInput === false || !this.opened())) { |
|
1115 | 1172 | render("<li class='select2-searching'>" + opts.formatSearching() + "</li>"); |
1116 | 1173 | } |
1117 | 1174 |
|
| 1175 | + // give the tokenizer a chance to pre-process the input |
| 1176 | + input = this.tokenize(); |
| 1177 | + if (input != undefined && input != null) { |
| 1178 | + search.val(input); |
| 1179 | + } |
| 1180 | + |
1118 | 1181 | this.resultsPage = 1; |
1119 | 1182 | opts.query({ |
1120 | 1183 | term: search.val(), |
|
1889 | 1952 | self.postprocessResults(); |
1890 | 1953 | }, |
1891 | 1954 |
|
| 1955 | + tokenize: function() { |
| 1956 | + var input = this.search.val(); |
| 1957 | + input = this.opts.tokenizer(input, this.data(), this.bind(this.onSelect), this.opts); |
| 1958 | + if (input != null && input != undefined) { |
| 1959 | + this.search.val(input); |
| 1960 | + if (input.length > 0) { |
| 1961 | + this.open(); |
| 1962 | + } |
| 1963 | + } |
| 1964 | + |
| 1965 | + }, |
| 1966 | + |
1892 | 1967 | // multi |
1893 | 1968 | onSelect: function (data) { |
1894 | 1969 | this.addSelectedChoice(data); |
|
1898 | 1973 | this.close(); |
1899 | 1974 | this.search.width(10); |
1900 | 1975 | } else { |
1901 | | - this.search.width(10); |
1902 | | - this.resizeSearch(); |
1903 | | - |
1904 | 1976 | if (this.countSelectableResults()>0) { |
| 1977 | + this.search.width(10); |
| 1978 | + this.resizeSearch(); |
1905 | 1979 | this.positionDropdown(); |
1906 | 1980 | } else { |
1907 | 1981 | // if nothing left to select close |
|
2032 | 2106 | containerLeft = this.selection.offset().left; |
2033 | 2107 |
|
2034 | 2108 | searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding; |
2035 | | - |
2036 | 2109 | if (searchWidth < minimumWidth) { |
2037 | 2110 | searchWidth = maxWidth - sideBorderPadding; |
2038 | 2111 | } |
|
2232 | 2305 | id: function (e) { return e.id; }, |
2233 | 2306 | matcher: function(term, text) { |
2234 | 2307 | return text.toUpperCase().indexOf(term.toUpperCase()) >= 0; |
2235 | | - } |
| 2308 | + }, |
| 2309 | + separator: ",", |
| 2310 | + tokenSeparators: [], |
| 2311 | + tokenizer: defaultTokenizer |
2236 | 2312 | }; |
2237 | 2313 |
|
2238 | 2314 | // exports |
|
0 commit comments