Based on a variety of user inputs, we put an array of words in a hidden div (#words) and then perform functions using that info.
What I would like to do is check the div for the existing words, i.e.:
terms = $("#words").html();
And then, in a visible and separate div elsewhere on the page (.ocrText), wrap only those words in a strong tag.
$('.ocrText').each(function() {
$(this).html($(this).html().replace(/term/g, "<strong>term</strong>"));
});
So, if they'd searched for "Tallant France" and we stored that, then the following sentence:
"Mark Tallant served in France."
Would become:
"Mark <strong>Tallant</strong> served in <strong>France</strong>."
But I don't know how to inject that variable in to .replace()
///
EDIT: The terms are inserted in to the #words div in this format:
["Tallant","France","War"] ... and so on.
$('.ocrText').each(function() {
var term = 'term'
var pattern = RegExp(term, 'g')
$(this).html($(this).html().replace(pattern, "<strong>" + term + "</strong>"));
});
Assuming your words contain only alphnumeric characters you can construct a single regexp to search of all of them at once as follows:
html = html.replace (
new RegExp(terms.split(/\s*,\s*|\s+/).join('|'), 'g'), '<strong>$&</strong>');
The split should convert the terms string into an array containing the individual words, in the example I have coded it to split on commas optionally surround by whitespace or just whitespace.
Related
I have a sentence stored in a variable.That sentence I need to extract into 3 parts which I have mentioned in other 3 variable in my code,for now I have hard coded in the variable. Then I need to console those variable separately.I have already tried with slice for first one,is there any better way to do it.Here is the code below.Can anyone please help me.
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
SCRIPT
$(document).ready(function(){
var maintext = "Welcome to project,are you (1. Existing user or 2. new user)" ;
var text_split1 = maintext.split(' ').slice(0,4).join(' ');
//var text_split1 = "Welcome to project,are you" ; /*this text should come from maintext after extraction*/
var text_split2 = "1. Existing user" ; /*this text should come from maintext after extraction*/
var text_split3 = "2. new user" ; /*this text should come from maintext after extraction*/
console.log(text_split1);
console.log(text_split2);
console.log(text_split3);
});
The best option in this case is to create a regular expression.
In your case (if I got it right) you have a sentence consisting of:
Some text
Open parenthesis '('
More text
The word 'or'
More text
Close parenthesis ')'
So you want a regex to match the format above and you want to capture the items 1, 3 and 5.
Here, I made the regex for you: /^(.*) ?\((.*) or (.*)\)$/
Now, using the function exec(string) you can match the desired string and capture the desired sections from it.
regex = /^(.*) ?\((.*) or (.*)\)$/;
maintext = "Welcome to project,are you (1. Existing user or 2. new user)";
matches = regex.exec(maintext);
text_split1 = matches[1];
text_split2 = matches[2];
text_split3 = matches[3];
Notice that I didn't use matches[0]. That's because this is the full match from the regex, which, in this case, would be the full string you had at first.
Also, notice that the regex may fail with any of the texts inside the parenthesis contain the full word 'or', which is being used to separate the two portions of the string. You must secure this won't happen, or maybe use some special character to separate the two texts instead of the word.
I suggest you take a look at the Split, Substring and IndexOf methods.
For example if you wanted to grab what's inside the parenthesis you could do
var inside_split = maintext.substring(maintext.indexOf( "(" ) + 1, maintext.indexOf( ")" ) )
and then whats outside of it
var outside_split = maintext.substring(0, maintext.indexOf("(") - 1)
or with Split
var split_Text = maintext.split("(")
Careful with Split here because it'll result in the last parenthesis being included in.
Array [ "Welcome to project,are you ", "1. Existing user or 2. new user)" ]
and from that you can Split the two options with
split_Text[1].split("or")
which results in
Array [ "1. Existing user ", " 2. new user)" ]
and then manipulate the remaining closing parenthesis
I am currently looking for a way to turn matching text into a bold html line. I have it partially working except for special characters giving me problems because I desire to maintain the original string, but not compare the original string.
Example:
Given the original string:
Taco John's is my favorite place to eat.
And wanting to match:
is my 'favorite'
To get the desired result:
Taco John's <b>is my favorite</b> place to eat.
The way I'm currently getting around the extra quotes in the matching string is by replacing them
let regex = new RegExp('('+escapeRegexCharacters(matching_text.replace(/[^a-z 0-9]/gi,''))+')',"gi")
let html= full_text.replace(/[^a-z 0-9]/gi,'').replace(regex, "<b>$1</b>")}}></span>
This almost works, except that I lose all punctuation:
Taco Johns <b>is my favorite</b> place to eat
Is there any way to use regex, or another method, to add tags surrounding a matching phrase while ignoring both case and special characters during the matching process?
UPDATE #1:
It seems that I am being unclear. I need the original string's puncuation to remain in the end result's html. And I need the matching text logic to ignore all special characters and capitalization. So is my favorite is My favorite and is my 'favorite' should all trigger a match.
Instead of removing the special characters from the string being searched, you could inject in your regular expression a pattern between each character-to-match that will skip any special characters that might occur. That way you build a regular expression that can be applied directly to the string being searched, and the replacing operation will thus not touch the special characters outside of the matches:
let escapeRegexCharacters =
s => s.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
full_text = "Taco John's is My favorite place to eat.";
matching_text = "is my 'favorite'";
regex = new RegExp(matching_text.replace(/[^a-z\s\d]/gi, '')
.split().map(escapeRegexCharacters).join('[^a-z\s\d]*'), "gi"),
html = full_text.replace(regex, "<b>$&</b>");
console.log(html);
Regexps are useful where there is a pattern, but, in this case you have a direct match, so, the good approach is using a String.prototype.replace:
function wrap(source, part, tagName) {
return source
.replace(part,
`<${tagName}>${part}</${tagName}>`
)
;
}
At least, if there is a pattern, you should edit your question and provide it.
As an option, for single occurrence case - use String.split
Example replacing '###' with '###' :
let inputString = '1234###5678'
const chunks = inputString.split('###')
inputString = `${chunks[0]}###${chunks[1]}`
It's possible to avoid using a capture group with the $& replacement string, which means "entire matched substring":
var phrase = "Taco John's is my favorite place to eat."
var matchingText = "is my favorite"
var re = new RegExp(escapeRegexCharacters(matchingText), "ig");
phrase.replace(re, "<b>$&</b>");
(Code based on obarakon's answer.)
Generalizing, the regex you could use is my /w+. You can use that in a replacer function so that you can javascript manipulate the resultant text:
var str = "Taco John's is my favorite place to eat.";
var html = str.replace(/is my \w*/, function (x) {
return "<b>" + x + "</b>";
} );
console.log(html);
I am looking for a way to highlight words in a textbox (or some other way to tag or make the word noticeable) if they are on a list (likely an array list with Javascript).
I don't expect this to be real time, a button that checks the words in the textbox will work perfectly fine. Basically an "If Word is (Word1, Word2, etc.) then Insert change here to Word."
I am also fine with it just making the word all caps to signify change. Whatever is easy. I'm new to Javascript and only understand the very basic concept on how to do this and would like to learn how to make it interact with a textbox.
You could make it bold <b>Word</b> or emphasize according to some style with <em>Word</em> See this https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em for more info on the em tag.
Here is a quick javascript example working off the contenteditable property referenced in the comments of gabesoft's answer. You can define a list of words, specify the textbox, and then use a button to do the highlights.
JSFiddle Example
HTML:
<p contenteditable="true">This is a test of the word highlight system.</p>
<button onClick="highlightWords()">highlight</button>
JS:
//define words you want highlighted
var arr = ['test', 'system'];
//locate the element on the page to do the word operations
//this will find the first <p> tag
var textbox = document.getElementsByTagName('p')[0];
var highlightWords = function() {
//foreach word, perform highlighting actions
arr.forEach(function(word) {
//build regular expression to match against each variable (word) in our list
var regex = new RegExp("(" + word + ")", "gi");
//g = can find multiple instances (global)
//i = case insenstive
//replace predefined textbox HTML with 'highlighted' version
//the regex will find matching words and wrap them in <strong> tags
//the $1 represents the matched word
textbox.innerHTML = textbox.innerHTML.replace(regex, "<strong>$1</strong>");
});
}
I have an autocomplete form and when showing the results matching the user's search string, I want to highlight the search string itself. I plan to do this by wrapping any occurrence of the search string within a tag such as , or a with a given class. Now, the problem is that when using regEx I have problems if the pattern occurs within a html tag.
For instance
var searchPattern = 'pa';
var originalString = 'The pattern to <span class="something">be replaced is pa but only outside the html tag</span>';
var regEx = new RegExp(searchPattern, "gi")
var output = originalString.replace(regEx, "<strong>" + searchPattern + "</strong>");
alert(output);
(Demo: http://jsfiddle.net/cumufLm3/7/ )
This is going to replace also the occurrence of "pa" within the tag
<span class="something">
breaking the code. I'm not sure how to deal with this. I've been checking various similar questions, and I've understood that in general I shouldn't use regular expressions to parse html. But I'm not sure if there is any quick way to parse smoothly the html string, alter the text of each node, and "rebuild" the string with the text altered?
Of course I suppose I could use $.parseHTML(), iterate over each node, and somehow rewrite the string, but this seems to me to be too complex and prone to errors.
Is there a smart way to parse the html string somehow to tell "do this only outside of html tags"?
Please notice that the content of the tag itself must be handled. So, in my example above, the replace() should act also on the part "be replaced is pa but only outside the html tag".
Any idea of either a regular expression solid enough to deal with this, or (better, I suppose) to elegantly handle the text parts within the html string?
Your code should look like this:
var searchWord = 'pa';
var originalString = 'The pattern to <span class="something">be replaced is pa but only outside the html tag</span>';
var regEx = new RegExp("(" + searchWord + ")(?!([^<]+)?>)", "gi");
var output = originalString.replace(regEx, "<strong>$1</strong>");
alert(output);
Source: http://pureform.wordpress.com/2008/01/04/matching-a-word-characters-outside-of-html-tags/
Parse the HTML and find all text nodes in it, doing the replace in all of them. If you are using jQuery you can do this by just passing the snippet to $() which parses it in a Document Fragment, which you can then query or step over all elements and find all the .text() to replace.
I have made a javascript function to replace some words with other words in a text area, but it doesn't work. I have made this:
function wordCheck() {
var text = document.getElementById("eC").value;
var newText = text.replace(/hello/g, '<b>hello</b>');
document.getElementById("eC").innerText = newText;
}
When I alert the variable newText, the console says that the variable doesn't exist.
Can anyone help me?
Edit:
Now it replace the words, but it replaces it with <b>hello</b>, but I want to have it bold. Is there a solution?
Update:
In response to your edit, about your wanting to see the word "hello" show up in bold. The short answer to that is: it can't be done. Not in a simple textarea, at least. You're probably looking for something more like an online WYSIWYG editor, or at least a RTE (Richt Text Editor). There are a couple of them out there, like tinyMCE, for example, which is a decent WYSIWYG editor. A list of RTE's and HTML editors can be found here.
First off: As others have already pointed out: a textarea element's contents is available through its value property, not the innerText. You get the contents alright, but you're trying to update it through the wrong property: use value in both cases.
If you want to replace all occurrences of a string/word/substring, you'll have to resort to using a regular expression, using the g modifier. I'd also recommend making the matching case-insensitive, to replace "hello", "Hello" and "HELLO" all the same:
var txtArea = document.querySelector('#eC');
txtArea.value = txtArea.value.replace(/(hello)/gi, '<b>$1</b>');
As you can see: I captured the match, and used it in the replacement string, to preserve the caps the user might have used.
But wait, there's more:
What if, for some reason, the input already contains <b>Hello</b>, or contains a word containing the string "hello" like "The company is called hellonearth?" Enter conditional matches (aka lookaround assertions) and word boundaries:
txtArea.value = txtArea.value.replace(x.value.replace(/(?!>)\b(hello)\b(?!<)/gi, '<b>$1</b>');
fiddle
How it works:
(?!>): Only match the rest if it isn't preceded by a > char (be more specific, if you want to and use (?!<b>). This is called a negative look-ahead
\b: a word boundary, to make sure we're not matching part of a word
(hello): match and capture the string literal, provided (as explained above) it is not preceded by a > and there is a word boundary
(?!<): same as above, only now we don't want to find a matching </b>, so you can replace this with the more specific (?!<\/b>)
/gi: modifiers, or flags, that affect the entire pattern: g for global (meaning this pattern will be applied to the entire string, not just a single match). The i tells the regex engine the pattern is case-insensitive, ie: h matches both the upper and lowercase character.
The replacement string <b>$1</b>: when the replacement string contains $n substrings, where n is a number, they are treated as backreferences. A regex can group matches into various parts, each group has a number, starting with 1, depending on how many groups you have. We're only grouping one part of the pattern, but suppose we wrote:
'foobar hello foobar'.replace(/(hel)(lo)/g, '<b>$1-$2</b>');
The output would be "foobar <b>hel-lo</b> foobar", because we've split the match up into 2 parts, and added a dash in the replacement string.
I think I'll leave the introduction to RegExp at that... even though we've only scratched the surface, I think it's quite clear now just how powerful regex's can be. Put some time and effort into learning more about this fantastic tool, it is well worth it.
If <textarea>, then you need to use .value property.
document.getElementById("eC").value = newText;
And, as mentioned Barmar, replace() replaces only first word. To replace all word, you need to use simple regex. Note that I removed quotes. /g means global replace.
var newText = text.replace(/hello/g, '<b>hello</b>');
But if you want to really bold your text, you need to use content editable div, not text area:
<div id="eC" contenteditable></div>
So then you need to access innerHTML:
function wordCheck() {
var text = document.getElementById("eC").innerHTML;
var newText = text.replace(/hello/g, '<b>hello</b>');
newText = newText.replace(/<b><b>/g,"<b>");//These two lines are there to prevent <b><b>hello</b></b>
newText = newText.replace(/<\/b><\/b>/g,"</b>");
document.getElementById("eC").innerHTML = newText;
}