I'm continuing work on a search term suggestion tool using Jquery UI. I am now working on displaying the results with the search term pattern in bold. I have implemented this functionality through patching the Autocomplete's _renderItem method. The problem I have now is that the replaced characters have the same case as those typed by the user in the input (e.g. if the user typed an "A" and the returned result was "America", the replaced text would be AmericA. Here's the code:
var exp = new RegExp(this.term, "gi") ;
var rep = item.label.replace( exp, "<span style='font-weight:bold;color:Black;'>"
+ this.term + "</span>");
As always, thanks in advance for any help.
You can use:
var rep = item.label.replace(exp,
"<span style='font-weight:bold;color:Black;'>$&</span>");
When replacing a string, $& means "the whole match", so you don't have to repeat the search term (in some cases you don't know it). In other flavors, you may use $0 or \0.
Also, remember to escape special characters in this.term.
You can add your expression in a group by encapsulating them in parentheses
var exp = new RegExp("(" + this.term + ")", "gi") ;
var rep = item.label.replace( exp, "<span style='font-weight:bold'>$1</span>");
You can the refere to that group using $1.
See here for more details about backreferences.
Related
here's my code
replaced.replace(new RegExp(item, 'i'), "<span class='has-background-primary'>$&</span>");
it's highlighting searched term. But if I run it second time and serach for eg. "back", it will do stupid things like replacing string in the tag class. What can I do to prevent it?
I'm not sure if what you're looking for is somewhere along the lines of the following modified code:
replaced.replace(new RegExp(item, 'i'), "$&".indexOf(">"));
This should ensure the html tag is not impacted
The "literal" solution is to match the tag you want to skip and then match a keyword in any other context, and, upon a match, check if your term or the tag was matched, and replace accordingly:
var regex = new RegExp("(<span class='has-background-primary'>[^]*?</span>)|"+item.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi');
var result = replaced.replace(regex, function ($0, $1) {
return $1 ? $0 : "<span class='has-background-primary'>" + $0 + "</span>";
});
Say, your item is house. So, the regex will look like /(<span class='has-background-primary'>[^]*?</span>)|house/gi. It will match and capture <span class='has-background-primary'>, 0+ chars as few as possible (with [^]*?) and then </span>, else, the key word is matched. If Group 1 matched, the match is pasted back as is, else, it is wrapped with new span tags.
Note that it is advised to escape your literal strings to be used as RegExp patterns, hence, .replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') is added.
Another idea is to build a pattern from the search terms dynamically, like
var search = ['abc', 'abcde', 'xyz'];
search.sort(function(a, b){
return b.length - a.length;
});
var rx = new RegExp(search.map(function(m) {
return m.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');}
).join("|"), "gi"); // => /abcde|abc|xyz/gi
var result = replaced.replace(rx, "<span class='has-background-primary'>$&</span>"));
Since your alternation group is unanchored and a search word may represent a subset of another term, you should sort the search words by length in the descending order.
Then, build the alternation while escaping each value, do not forget the g modifier here.
I'm trying to figure out how to do a RegEx search on a string that ignores case, but when it does a replacement it should preserve the original case.
i.e.
Searching for "adv" should match "Adv", but the replacement should match "Adv" not "adv"
The purpose is to 'highlight' text in a string. Obviously if there is something easier I'm all ears.
Current code...
$("#SearchResults").append(appendString.replace(
new RegExp($("#SearchInput").val(), "g"), "<strong>" +
$("#SearchInput").val() + "</strong>")
);
You need to encapsulate the value with parenthesis, this will create a group and you will be able the get that group in the replacement string with $n where n is the number of the group. The index start to 1.
So use that :
appendString.replace(new RegExp('(' + $("#SearchInput").val() + ')', "gi"), "<strong>$1</strong>");
Note that using regexp like that is dangerous, for instance, if I write (hello in the input, it will throw an error : invalid regexp.
Karl's approach is right, although you might also need to escape special characters:
var value = $("#SearchInput").val();
var escaped = value.replace(/([\[\]\(\)\/\.\*\+])/g, "\\$1");
// Regex: new RegExp(escaped, "gi");
// Replace with: "<strong>" + value + "</strong>");
Edit for typo.
This is my string converted into javascript object.
{"text" : "Must consist of alphabetical characters and spaces only", regexp:"/^[a-z\\s]+$/i"}
I need regexp to use it for validation but it won’t work because of the double quotes and \s escape sequence.
To make it work the value of regexp must be {"text" : "Must consist of alphabetical characters and spaces only", regexp : /^[a-z\s]+$/i}.
I also used this new RegExp(object.regexp) and any other way I can possibly think but with no luck at all.
Any help is appreciated!
Try split-ing out the part that you want, before putting it into the new RegExp constructor:
var regexVariable = new RegExp(object.regexp.split("/")[1]);
That will trim off the string representation of the regex "boundaries", as well as the "i" flag, and leave you with just the "guts" of the regex.
Pushing the result of that to the console results in the following regex: /^[a-z\s]+$/
Edit:
Not sure if you want to "read" the case insensitivity from the value in the object or not, but, if you do, you can expand the use of the split a little more to get any flags included automatically:
var aRegexParts = object.regexp.split("/");
var regexVariable = new RegExp(aRegexParts[1], aRegexParts[2]);
Logging that in the console results in the first regex that I posted, but with the addition of the "i" flag: /^[a-z\s]+$/i
Borrowing the example #RoryMcCrossan made, you can use a regular expression to parse your regular expression.
var object = {
"text": "Must consist of alphabetical characters and spaces only",
"regexp": "/^[a-z\\s]+$/i"
}
// parse out the main regex and any additional flags.
var extracted_regex = object.regexp.match(/\/(.*?)\/([ig]+)?/);
var re = new RegExp(extracted_regex[1], extracted_regex[2]);
// don't use document.write in production! this is just so that it's
// easier to see the values in stackoverflow's editor.
document.write('<b>regular expression:</b> ' + re + '<br>');
document.write('<b>string:</b> ' + object.text + '<br>');
document.write('<b>evaluation:</b> ' + re.test(object.text));
not used regex in Java but the regular expression itself should look something like :
"^([aA-zZ] | \s)*$"
If Java uses regular expression as I am used to them [a-z] will only capture lowercase characters
Hope this helps even if it's just a little (would add this as a comment instead of answer but need 50 rep)
I was trying to change color to some text in a document, and I required regexp.
So, I tried the function findText to search where my text is in the selected text, but I am having some troubles matching the regexps.
Look at this sample script
function onOpen() {
DocumentApp.getUi().createMenu('Test')
.addItem('Find regex in sel', 'findRegex'))
.addToUi();
}
function findRegex() {
var ui = DocumentApp.getUi();
var selection = DocumentApp.getActiveDocument().getSelection();
var txt = selection.getSelectedElements()[0].getElement().asText();
var inp = ui.prompt('Regex to search:').getResponseText();
var regex = new RegExp(inp);
ui.alert('Found in "' + txt.getText()
+ '"\n Re: ' + txt.findText(regex)
+ '\n In: ' + txt.findText(inp));
}
This prompts for something to search, then builds a regex out of it. Then both the regex and the original string are used to search in the selected text.
Well, I do not know what to do to get the regex matching: I am always getting null: if the text to be searched is "foobarbaz", and I input foo, only the plain string matches.
If instead I input /foo/, clearly nothing matches.
How should I use regexps to search using findText?
Consider that I have to "compose" regex, like /foobar/ + /\d+/, where foobar is the user-entered pattern.
Ok, I think to have found the crux: the regexp passed to findText is always a String object, even if it have a regexp inside.
I tried searching "fo+" in the text "fooo" and it matched correctly.
I'm working on an autocomplete component that highlights all ocurrences of searched text. What I do is explode the input text by words, and wrap every ocurrence of those words into a
My code looks like this
inputText = 'marriott st';
text = "Marriott east side";
textSearch = inputText.split(' ');
for (var i in textSearch) {
var regexSearch = new RegExp('(?!<\/?strong>)' + textSearch[i]), "i");
var textReplaced = regexSearch.exec(text);
text = text.replace(regexSearch, '< strong>' + textReplaced + '< /strong>');
}
For example, given the result: "marriott east side"
And the input text: "marriott st"
I should get
<strong>marriot< /strong > ea < strong >st < /strong > side
And i'm getting
<<strong>st</strong>rong>marriot</<strong>st </strong>rong>ea<<strong>st</strong> rong>s</strong> side
Any ideas how can I improve my regex, in order to avoid ocurrences inside the html tags? Thanks
/(?!<\/?strong>)st/
I would process the string in one pass. You can create one regular expression out of the search string:
var search_pattern = '(' + inputText.replace(/\s+/g, '|') + ')';
// `search_pattern` is now `(marriot|st)`
text = text.replace(RegExp(search_pattern, 'gi'), '<strong>$1</strong>');
DEMO
You could even split the search string first, sort the words by length and combine them, to give a higher precedence to longer matches.
You definitely should escape special regex characters inside the string: How to escape regular expression special characters using javascript?.
Before each search, I suggest getting (or saving) the original search string to work on each time. For example, in your current case that means you could replace all '<strong>' and '</strong>' tags with ''. This will help keep your regEx simple, especially if you decide to add other html tags and formatting in the future.