I use Select2 in my app to allow for searching a dropdown with about 1200 options.
I am currently making use of the default implementation of Select2's matcher, which works well as long as keywords are adjacent in the search results:
function(term, text) { return text.toUpperCase().indexOf(term.toUpperCase())>=0; }
For example, a search for 'stackoverflow question' returns option 'Stackoverflow question about Select2'
I would however else like the matcher to return results based on non-adjacent keywords. For instance, I would also like it to return the above option when searching for 'stackoverflow select2'.
Would anyone have an idea how to create a custom matcher to allow for this behavior?
I use Select2 in my app to allow for searching a dropdown with about 1200 options.
I am currently making use of the default implementation of Select2's matcher, which works well as long as keywords are adjacent in the search results:
function(term, text) { return text.toUpperCase().indexOf(term.toUpperCase())>=0; }
For example, a search for 'stackoverflow question' returns option 'Stackoverflow question about Select2'
I would however else like the matcher to return results based on non-adjacent keywords. For instance, I would also like it to return the above option when searching for 'stackoverflow select2'.
Would anyone have an idea how to create a custom matcher to allow for this behavior?
Share Improve this question edited Jul 28, 2014 at 15:42 Charles 51.4k13 gold badges106 silver badges144 bronze badges asked Jul 27, 2014 at 11:21 ACDSLACDSL 872 silver badges7 bronze badges 2- Please note that tags are not keywords. Stuffing the tag list full of the same words that are in your question (search, keyword, mapper) will not help categorize it. Always be sure to read the descriptions that appear when selecting tags! – Charles Commented Jul 28, 2014 at 15:56
- Thanks for the notice Charles, will do so in future posts! – ACDSL Commented Jul 28, 2014 at 16:11
4 Answers
Reset to default 11this is what i did in Select2 4. i wanted matcher to return only options that contains all of keywords entered (assuming keywords are search term splitted by " "). Matching is case insesitive.
matcher: function (params, data) {
// If there are no search terms, return all of the data
if ($.trim(params.term) === '') {
return data;
}
// `params.term` should be the term that is used for searching
// split by " " to get keywords
keywords=(params.term).split(" ");
// `data.text` is the text that is displayed for the data object
// check if data.text contains all of keywords, if some is missing, return null
for (var i = 0; i < keywords.length; i++) {
if (((data.text).toUpperCase()).indexOf((keywords[i]).toUpperCase()) == -1)
// Return `null` if the term should not be displayed
return null;
}
// If here, data.text contains all keywords, so return it.
return data;
}
i know this is old topic, but maybe someone find this usefull.
If you have large amount of data or nested data then the permutation will take lot of time.
Try instead this for searching using Non-Adjacent Keywords.
Just put this function in your document.ready before initializing select2.
$(function () {
var keywords;
$.fn.select2.defaults = $.extend($.fn.select2.defaults, {
placeholder: 'Select...',
matcher: function(term, text, option) {
if ($.trim(term) === '') {
return true;
}
keywords = (term).split(" ");
for (var i = 0; i < keywords.length; i++) {
if ((text.toUpperCase()).indexOf((keywords[i]).toUpperCase()) == -1 )
{
return false;
}
}
return true;
}
});
$("#DropdownID").select2();
});
The Working example is here : http://makmilan.blogspot.in/2015/11/select2-custom-matcher-for-non-adjacent.html
Try this:
search Stackoverflow question, stackoverflow select2, select2 stackoverflow, about stackoverflow select2 question, question select2 about
<select id="e17_2" style="width:300px">
<option alt="Stackoverflow question about Select2">Stackoverflow question about Select2</option>
<option alt="Stackoverflow Other line ...">Stackoverflow Other line ...</option>
</select>
Copied from: https://stackoverflow./a/21745151/3710490
function permute(input, permArr, usedChars) {
var i, ch;
for (i = 0; i < input.length; i++) {
ch = input.splice(i, 1)[0];
usedChars.push(ch);
if (input.length == 0) {
permArr.push(usedChars.slice());
}
permute(input, permArr, usedChars);
input.splice(i, 0, ch);
usedChars.pop();
}
return permArr
};
$("#e17_2").select2({
matcher: function(term, text) {
if (term.length == 0) return true;
texts = text.split(" ");
allCombinations = permute(texts, [], []);
for(i in allCombinations){
if( allCombinations[i].join(" ").toUpperCase().indexOf(term.toUpperCase())==0 ){
return true;
}
}
return false;
}
});
Look for all or part of imperativements words :
element.select2({
matcher: function(term, text){
if (term.length < 3) { return true }
var terms = term.split(" ");
var count = 0;
var nbterm = terms.length;
for(i in terms) {
if (text.toUpperCase().match(new RegExp(terms[i], "i"))) { count++ }
if(nbterm == count){
return true;
}
}
return false;
}
});