For example , I have a string <i class='highlight'>L</i>olopolo
. And I need to change the letter l
to <i class='highlight'>l</i>
. How to make a regular expression to ignore the tag and everything inside?

- 172,303
- 28
- 230
- 274

- 11
- 3
-
Not sure that i understand you - you want to change uppercase 'L' to lowercase: 'l'? – sinisake Sep 20 '15 at 12:22
-
2Don't use regex to parse HTML... and if you do, don't talk about it on stack overflow... http://stackoverflow.com/a/1732454/665261 – Billy Moon Sep 20 '15 at 12:23
-
i need to wrap another letter – Deodat Teos Sep 20 '15 at 12:26
-
Hm... 'olopolo' -> you need to wrap every occurrence of 'l' with , right? – sinisake Sep 20 '15 at 12:28
-
wrap every occurrence, yes – Deodat Teos Sep 20 '15 at 12:29
4 Answers
Try this:
var string = "<i class='highlight'>L</i>olopolo";
string = string.replace(/l(?![^>]+>)(?![^<]*<\/)/g, "<i class='highlight'>l</i>");
alert(string);
if you want to have arbitrary text then you can use the code below:
var text = "foo";
var re = new RegExp(text + '(?![^>]+>)(?![^<]*</)', 'g');
var string = "<i class='highlight'>foobar</i>foobarfoobar";
string = string.replace(re, "<i class='highlight'>" + text + "</i>");
alert(string);

- 61,973
- 54
- 229
- 402
As mentioned using regular expressions is not the best idea so the next best thing is to loop over text nodes and add the elements.
var charSplit = "l";
var elem = document.querySelector(".x");
var nodes = elem.childNodes;
for(var i=nodes.length-1;i>=0;i--){
var node = nodes[i];
if(node.nodeType === 3) { //this is a text node
var last = node;
var parts = node.nodeValue.split(charSplit); //split of the character we are supposed to match
node.nodeValue = parts[parts.length-1]; //set text node value to last index's value
for (var j=parts.length-2; j>=0;j--){ //loop backwards ingnoring the last index since we already put that text in the textode
var it = document.createElement("i"); //create the new element to add
it.className="highligt";
it.innerHTML = charSplit;
node.parentNode.insertBefore(it,last); //add it before the text node
var tx = document.createTextNode(parts[j]); //create new text node for text that becomes before the element
node.parentNode.insertBefore(tx,it);
last = tx;
}
}
}
<p class="x"><i class='highlight'>L</i>olopolo</p>

- 204,599
- 20
- 195
- 236
I would suggest something like this, with minimal (and not so complicated) regex usage. If your string is initially part of html -> you can get parent(s), and change textContent and innerHTML:
tag=document.getElementsByTagName('p')[0]; /*just as example,can be anything else*/
str=tag.textContent;
reg=/(l)/gi;
tag.innerHTML=str.replace(reg,"<i class='highlight'>"+'$1'+"</i>");
Demo: http://jsfiddle.net/LzbkhLx7/
P.S. Explanation - textContent will give you 'pure' string/text, without HTML tags - and then you can easily wrap every occurrence of l/L.

- 11,240
- 2
- 19
- 27
-
1hopefully there are no other tags in it, but in this case it works fine. :) – epascarello Sep 20 '15 at 13:21
document.getElementsByClassName("highlight")[0].innerHTML = "l";
No need for regex.
Or if you want to change the letter from upper to lower case
var el = document.getElementsByClassName("highlight")[0];
el.innerHTML = el.innerHTML.toLowerCase();
Of course you'll have to make sure you can call toLowerCase (or other method) on the innerHTML before doing it.

- 1,395
- 3
- 15
- 23