问题
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?
回答1:
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.com/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;
}
});
回答2:
this 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.
回答3:
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
回答4:
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;
}
});
来源:https://stackoverflow.com/questions/24980403/select2-custom-matcher-for-non-adjacent-keywords