Reputation: 11755
I have an autocomplete (jQuery) in which I want to highlight any words in the dropdown that occur in the user input. User enters: "holy water" then both holy and water should be highlighted even if they're not next to each other. So entering multiple words should highlight multiple words if present
I'm trying to do this with just making text bold using a regular expression
_renderItem: function( ul, item ) {
var termWords = this.term.trim().split(" ").join("|"); //if multiple words, split into parts, join back with ors to use in regexp
var regex = new RegExp("({"+termWords+"[s]?}*)([\s\.,])","gi"); // convert to regex, make global and case insensitive
var currentLabel = item.label;
var currentLabel = currentLabel.replace(regex, "<b>$1</b>$2");
var itemHtml = '<a>'+ currentLabel + '</a>';
return $( "<li></li>" )
.data( "item.autocomplete", item )
.html(itemHtml)
.appendTo( ul );
}
Trying this out if I enter "is language", the output expression becomes
/({is|language[s]?}*)([s.,])/gi
But the problem is, none of the text I enter matches and hence isn't highlighted.
Here is a jsfiddle of what I'm trying: http://jsfiddle.net/8tD49/5/ , just note that it's not exactly the same as my own ajax function returns results as seen in the image.
Edit:
Final answer to highlight multiple strings:
_renderItem: function( ul, item ) {
var termWords = this.term.trim().split(" ").join("|"); //if multiple words, split into parts, join back with ors
"(?:"+termWords+"[s]?)*"
var regex = new RegExp("((?:"+termWords+")s?)([\s.,])?","gi");
var currentLabel = item.label;
var currentLabel = currentLabel.replace(regex, "<b>$1</b>$2");
var itemHtml = '<a>'+ currentLabel + '</a>';
return $( "<li></li>" )
.data( "item.autocomplete", item )
.html(itemHtml)
.appendTo( ul );
}
Upvotes: 1
Views: 551
Reputation: 9644
I believe you mixed up {}
and simple parenthesis. For matching either something OR another, the syntax is something|other
. If you need to enclose in non-selective parenthesis, the syntax is
(?:is|language[s]?)*
But here, I don't think the *
is necessary. You want to match all occurrences of a few words: all you have to do is do a regex that would match any of these words. The g
flag will take care of repeating the task.
Your complete regex should then become:
"/((?:"+termWords+")s?)([\s.,])?/gi"
...
/((?:is|language)s?))([s.,])?/gi
The ([.,]?)
part (why did you put an s there, btw?) seems a little restrictive too. You could use (\W?)
instead for english language (\W
is short for non alphanumerical character, ie [^a-zA-Z0-9]
, which means it would catch any punctuation but mess up words like journée
).
And you may wanna be careful when you try to catch plural, in this example iss
would also be catched... This part probably needs a bit more thinking !
Upvotes: 1
Reputation: 104
You'll need to use word boundaries (\b)
(\bis\b|\blanguage\b)
is this the correct language. The above regex matches is and language.
Upvotes: 1