I need to locate words for more than 4 characters that are written between <p> </p> in uppercase and add them a style (ex. italic).
I know about the function isUpperCase() but don't know how to apply it to check if the string is more than 4 characters.
function isUpperCase( string ) {
(?)
}
Thanks.
var ps = [].slice.call(document.getElementsByTagName("p"))
ps.forEach(function (p) {
p.textContent.split(" ").forEach(function (word) {
if (word.length > 4 && word.toUpperCase() === word) {
// 4character UPPERCASE word
}
})
})
You could use a regex to replace any uppercase text longer than four characters in the innerHTML of every <p> element with that text surrounded by the markup you're trying to insert:
$('p').each(function(){
var pattern = /([-A-Z0-9]{4,})/g;
var before = '<span style="color: red;">';
var after = '</span>';
$(this).html($(this).html().replace(pattern, before+"$1"+after));
});
http://jsfiddle.net/eHPVg/
Yeah, like Rob said, I don't think Raynos's answer will work cross-browser and it also won't let you modify the matches within the paragraph.
Here's a slightly modified version:
var i = 0, ps = document.getElementsByTagName("p");
for(len = ps.length; i<len; i++)
{
var p = ps[i];
p.innerHTML = p.innerHTML.replace(/\b([A-Z]{4,})\b/g, "<span style='font-style:italic'>$1</span>";
}
You can change the span code to be whatever style you want to add. Just make sure to leave the $1, which refers the original uppercase word.
Related
I'm trying to highlight all the words that have more than 5 characters within a <p> element. I was able to select those words, but I failed on highlighting those words on the screen. I'd appreciate any help. Please see the complete code JavaScript exercise
let pElement = document.getElementById("text");
function highlightLongWords(element){
let paragraph = pElement.textContent;
let textInsideP = pElement.innerHTML = paragraph;
// use String.split(" ") to split the paragraph into an array of words
let words = paragraph.split(" ");
console.log(words);
let longestWord = "abcde";
//use Array.length to get the length of the array.
for(let word of words) {
if (word.length > longestWord.length) {
//console.log(word);
let longWords = word;
pElement.style.backgroundColor = "yellow"
console.log(longWords);
}
}
return;
}
highlightLongWords(pElement);
You can use a regex to replace the text content of the p element such that every text segment which matches your criteria is replaced with that same content, but wrapped within a <span> element:
let wrapTextInSpans = (elem, regex) => {
// Takes an element, and a regex. The regex should have the "g" flag set
elem.innerHTML = elem.innerHTML.replace(regex, '<span>$&</span>');
};
wrapTextInSpans(document.querySelector('p'), /[a-zA-Z]{5,}/g);
.highlight > span {
background-color: rgba(255, 0, 0, 0.2);
}
<p class="highlight">
Hello, this is some sample text I have written for the illustrative purpose of detecting all
linguistic words whose length is equal to or longer than five characters. I hope that this
sample text combined with the accompanying javascript and css code is sufficient to solve
your problem.
</p>
The regex used is very simple:
[a-zA-Z] -> Any alpha character
{5,} -> Repeat minimum 5 times
If you want multiple consecutive words which match your criteria to share the same highlighting, you can simply extend the regex used for wrapTextInSpans:
let wrapTextInSpans = (elem, regex) => {
// Takes an element, and a regex. The regex should have the "g" flag set
elem.innerHTML = elem.innerHTML.replace(regex, '<span>$&</span>');
};
wrapTextInSpans(document.querySelector('p'), /[a-zA-Z]{5,}([^a-zA-Z]*[a-zA-Z]{5,})*/g);
.highlight > span {
background-color: rgba(255, 0, 0, 0.2);
}
<p class="highlight">
Hello, this is some sample text I have written for the illustrative purpose of detecting all
linguistic words whose length is equal to or longer than five characters. I hope that this
sample text combined with the accompanying javascript and css code is sufficient to solve
your problem.
</p>
The regex used is a bit more complicated:
[a-zA-Z] -> Alpha character
{5,} -> Repeat minimum 5 times
( )* -> Repeat any number of times (including 0)
[^a-zA-Z]* -> Any number of non-alpha characters (allowing punctuation to break up matching words)
[a-zA-Z]{5,} -> 5 or more alpha characters
Here I wrote small helper function for your case, check it and read comments
// Highlight function
const hl = (s, e) => {
// Shortcut <p>
const p = document.getElementById("myText");
// Get content of target <p>
let text = p.textContent;
// Write custom replace function
text = text.replace(new RegExp('(\\w+)', 'g'), (m) => {
// Check if word is equal or greater or
// has maximum parameter
if(m.length >= s && (e && m.length <= e || !e)) return `<span class="yellow">${m}</span>`;
else return m;
});
// Replace <p> with altered text
p.innerHTML = text;
}
// Test by providing target length+
// BONUS: as second parameter you can pass
// maximum length, i.e: hl(6, 9);
hl(6);
.yellow {
background-color: yellow;
}
<p id="myText">
JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions. While it is most well-known as the scripting language for Web pages, many non-browser environments also use it, such as Node.js, Apache CouchDB and Adobe Acrobat.
</p>
everyone. Thank you for taking the time to reply to my question. It's been very valuable to see different solutions.
My solution was a bit simple since I was not familiar with regex. I used the .split() method to convert the text into an array, and I went with a for loop to identify the long words and wrap those with mark elements to highlight them.
let pElement = document.getElementById("text");
function highlightLongWords(element){
let longestWord = "abcde";
const words = element.textContent.split(" ");
for(let i = 0 ; i < words.length; i++){
if(words[i].length > longestWord.length){
element.innerHTML = element.innerHTML.replace(words[i],`<mark>${words[i]}</mark>`)
}
}
return;
}
highlightLongWords(pElement);
<p id="text">
This sample text has highlighted words. Why are some words highlighted and others are not? Well, the highlighted words are 5 characters long, or longer. The non-highlighted words are shorter than 5 characters long.
</p>
This question already has answers here:
How can I change an element's text without changing its child elements?
(16 answers)
Closed 5 years ago.
I need to write a second RegExp to find variable d inside sentence that is not in tags. So variable in tags should be skipped.
Regex '(?:^|\\b)('+d+')(?=\\b|$)' will find d variable but i need to exclude <span> tag with class="description".
New sentence is wrapped in a new tag.
sentence = "This is some word. <span class='description'>word</span> in tag should be skipped"
d = 'word'
re = new RegExp('(?:^|\\b)('+d+')(?=\\b|$)', 'gi')
sentence = sentence.replace(re, "<span>$1</span>")
Result I'm trying to achieve is:
"This is some <span>word</span>. <span class='description'>word</span> in tag should be skipped"
I'm using coffeescript, thanks for the help.
Try this one: (word)(?![^<>]*<\/)
Full code:
var sentence = "This is some word. <span class='description'>word</span> in tag should be skipped"
var d = 'word'
var re = new RegExp('('+d+')(?![^<>]*<\/)', 'gi')
sentence = sentence.replace(re, "<span>$1</span>")
I based this answer on this snippet: https://regex101.com/library/gN4vI6
Trying to manipulate HTML with regular expressions is not a good idea: sooner or later you'll bump into some boundary condition where it fails. Maybe some < or > occur inside attribute values, or even inside text nodes, while the searched term may also occur at unexpected places, like in HTML comments, attribute values, or script tags, ... The list of boundary cases is long.
Furthermore, your search term may contain characters that have a special meaning in regular expression syntax, so you should at least escape those.
Here is a solution that interprets the string as HTML, using the DOM capabilities, and only replaces text in text nodes:
function escapeRegExp(str) {
return str.replace(/[\[\]\/{}()*+?.\\^$|-]/g, "\\$&");
}
function wrapText(sentence, word) {
const re = new RegExp("\\b(" + escapeRegExp(word) + ")\\b", "gi"),
span = document.createElement('span');
span.innerHTML = sentence;
Array.from(span.childNodes, function (node) {
if (node.nodeType !== 3) return;
node.nodeValue.split(re).forEach(function (part, i) {
let add;
if (i%2) {
add = document.createElement('span');
add.textContent = part;
add.className = 'someClass';
} else {
add = document.createTextNode(part);
}
span.insertBefore(add, node);
});
span.removeChild(node);
});
return span.innerHTML;
}
const html = 'This is some word. <span class="word">word</span> should stay',
result = wrapText(html, 'word');
console.log(result);
Recursing into elements
In comments you mentioned that you would now also like to have the replacements happening within some tags, like p.
I'll assume that you want this to happen for all elements, except those that have a certain class, e.g. the class that you use for the wrapping span elements, but you can of course customise the condition to your needs (like only recursing into p, or ...).
The code needs only a few modifications:
function escapeRegExp(str) {
return str.replace(/[\[\]\/{}()*+?.\\^$|-]/g, "\\$&");
}
function wrapText(sentence, word) {
const re = new RegExp("\\b(" + escapeRegExp(word) + ")\\b", "gi"),
doc = document.createElement('span');
doc.innerHTML = sentence;
(function recurse(elem) {
Array.from(elem.childNodes, function (node) {
// Customise this condition as needed:
if (node.classList && !node.classList.contains('someClass')) recurse(node);
if (node.nodeType !== 3) return;
node.nodeValue.split(re).forEach(function (part, i) {
let add;
if (i%2) {
add = document.createElement('span');
add.textContent = part;
add.className = 'someClass';
} else {
add = document.createTextNode(part);
}
elem.insertBefore(add, node);
});
elem.removeChild(node);
});
})(doc);
return doc.innerHTML;
}
const html = '<p><b>Some word</b></p>. <span class="someClass">word</span> should stay',
result = wrapText(html, 'word');
console.log(result);
I've written a live filter in javascript that takes a value from a field and hides the rows in a table that do not match.
The RegEx I use for this is very simple: /inputValue/i
Although this works great it only matches characters that are in order. For example:
inputValue = test
string to match = this is a test sentence
This example would match, but if I tried:
inputValue = this sentence
string to match = this is a test sentence
This won't match because the input value is out of order.
How would I go about writing a RegEx that is in order but can skip words?
Here is the loop I currently use:
for (var i=0; i < liveFilterDataArray.length; i++) {
var comparisonString = liveFilterDataArray[i],
comparisonString = comparisonString.replace(/['";:,.\/?\\-]/g, '');
RE = eval("/" + liveFilterValue + "/i");
if (comparisonString.match(RE)) {
rowsToShow.push(currentRow);
}
if(currentRow < liveFilterGridRows.length - 1) {
currentRow++;
} else {
currentRow = 0;
}
}
Many thanks for your time.
Chris
It is recommended to Use RegExp instead of eval.
DEMO
var words = liveFilterValue.split(" ");
var searchArg = (words.length==1)?words:words.join(".*")+'|'+words.reverse().join(".*")
var RE = new RegExp(searchArg,"i");
It will create this.*sentence|sentence.*this/i
remove +'|'+words.reverse().join(".*") if you only want to find this.....sentence and not sentence....this
You could split the input string on spaces and then run the filter sequentially for each word.
I need a way to replace all appearances of <br class=""> with just <br>
I'm a complete novice with regex, but I tried:
str = str.replace(/<br\sclass=\"\"\s>/g, "<br>");
and it didn't work.
What's a proper regex to do this?
I would not use a regex to do this, but rather actually parse the html and remove the classes.
This is untested, but probably works.
// Dummy <div> to hold the HTML string contents
var d = document.createElement("div");
d.innerHTML = yourHTMLString;
// Find all the <br> tags inside the dummy <div>
var brs = d.getElementsByTagName("br");
// Loop over the <br> tags and remove the class
for (var i=0; i<brs.length; i++) {
if (brs[i].hasAttribute("class")) {
brs[i].removeAttribute("class");
}
}
// Return it to a string
var yourNewHTMLString = d.innerHTML;
One way is with the following
var s = '<br class="">';
var n = s.replace(/(.*)(\s.*)(>)/,"$1$3");
console.log(n)
\s matches exactly one whitespace character. You probably want \s*, which will match any number (including zero) of whitespace characters, and \s+, which will match at least one.
str = str.replace(/'<br\s+class=\"\"\s*>/g, "<br>");
On my web pages I have source that looks like this:
<div id="opt_3" >A)</div>
<div id="opt_2" >B)</div>
<div id="opt_4" >C)</div>
<div id="opt_5" >D)</div>
<div id="opt_1" >E)</div>
What I need is to create a javascript that when running takes something like this as an input var:
Text 1 word word word this is a text 3 word word.
and changes it to
<strong>E</strong> word word word this is a <strong>A</strong> word word.
or
abc text 4 word
and changes it to
abc <strong>C</strong> word
The job of my javascript will be to taken the number inside of the string "Text X" or "text X", look at the first character of the id field that matches the value of X and substitute that character for "Text X".
I have jQuery loaded. Can that help by giving me some suggestioins? Do I need to use javascript as well as jQuery?
Can someone give me some advice on how I could do this. I am not very familiar with javascript or with jQuery.
You should this
var myText = 'Lorem {0} Dolor {1} Amet is a {2} text.';
var textReplace = function(txt) {
for (var i = 0, ii = arguments.length - 1; i < ii; i++) {
txt = txt.replace('{' + i + '}', arguments[i + 1]);
}
return txt;
}
textReplace(myText, 'ipsum', 'sit', 'dummy');
This function requires arguments. The first one is the text that you want to replace in a way. Other arguments will be replaced in your text. I suggest you to use wrapper texts with curly braces instead Text 4 or whatever.
I hope this will help.
The following code should do exactly as you describe:
var input = "Text 1 word word word this is a text 3 word word.";
input = input.toLowerCase();
var split = input.split(" ");
for(var i = 0; i < split.length; i++) {
if(split[i].toLowerCase() == "text") {
var num = split[i+1];
var val = $("#opt_" + num).text();
input = input.replace("text " + num, "<strong>" + val + "</strong>");
}
}
alert(input);
You can see it working here. It splits your string on spaces, then loops through the resulting array, looking for occurences of the word "text". When it finds one, it replaces that word and the next word (which will be a number according to your instructions) with the value of the corresponding element, wrapped in strong tags.
You could do a case-insensitive RegExp replace with a callback function, like this:
function textReplace(v){
return v.replace(/text ([0-9])/gi,function(i,e){
return "<strong>"+$("#opt_"+e).text().substring(0,1)+"</strong>";
});
}
example: http://jsfiddle.net/niklasvh/pLpxN/
For this you will need jQuery
//get the original text
txt = $('#text-container').text();
//split the whole text by the words "Text"
// this way each string in the array arr will contain as its first member the number
// without the splitting text
arr = txt.split('Text');
answerText = '';
for(i=0; i < arr.size(); i++){
words=arr[i].split(' '); //split by spaces
//the first word will be the number
nr = words[0];
//then we look up the corresponding option, and substitute the number
words[0] = $('#opt_'+nr).text();
//and rebuild the original text
answerText += words.join(' ');
}