An easy solution would be to simply replace the innerHTML
property of your element by a new html string that would have wrapped the words in a span
. However, it's not a very flexible solution, since by replacing the innerHTML
property, all the elements would be renewed and that might give unexpected results, unless you target elements that only holds text nodes.
Lets suppose the body
contains this text:
this is some text and I want to replace the word cool
You could have:
var $body = $(document.body);
$body.html($body.html().replace(/(cool)/g, '<span style="color: red;">$1</span>'));
Here the /(cool)/g
regex will match every cool words and create a capturing group on them, allowing us to reference it in the replacement expression as $1
.
However, a most advanced solution could probably be implemented like:
- Loop over text nodes not contained within a
span
that has a data-styled-text
attribute. (you could check the textNode.parentNode
property)
- Sourround the words that you want by a
<span data-styled-text>
tag. Have a look at https://developer.mozilla.org/fr/docs/DOM/Text.splitText
- Query all the
<span data-styled-text>
elements and do whatever manipulation you want with them.
I have toyed around with that concept and I have create a fiddle for you that shows how you could manipulate text in any ways you want using a regex
to target specific text. I have created 2 main functions wrapText
and styleText
that will allow you to do whatever you want with text on the page. It could be further optimzed, but you will get the idea.
Have a look at http://jsfiddle.net/scarsick/tX4Ge/1/
The following function allows you to wrap any text in a text node.
function wrapText(textNode, textRx, wrapFn) {
var global = textRx.global,
wrapEl,
result,
rightTextNode,
matchedText,
index;
while (result = textRx.exec(textNode.nodeValue)) {
rightTextNode = textNode.splitText(index = result.index);
rightTextNode.nodeValue = rightTextNode.nodeValue.substring((matchedText = result[0]).length);
wrapEl = wrapFn(matchedText, index);
wrapEl.appendChild(document.createTextNode(matchedText));
rightTextNode.parentNode.insertBefore(wrapEl, rightTextNode);
if (!global) {
break;
}
textNode = rightTextNode;
textRx.lastIndex = 0;
}
}
The following function allow you to style any text contained within an element.
function styleText(el, textRx, styleFn) {
var wrapEl = document.createElement('span'),
slice = [].slice;
wrapEl.setAttribute('data-styled-text', 'true');
styleText = function(el, textRx, styleFn) {
var childNodes = slice.call(el.childNodes, 0),
i = 0,
len = childNodes.length,
node;
for (; i < len; i++) {
node = childNodes[i];
switch (node.nodeType) {
case 3:
if (!node.parentNode.getAttribute('data-styled-text')) {
wrapText(node, textRx, function (text, index) {
var el = wrapEl.cloneNode();
styleFn(el, text, index);
return el;
});
continue;
}
styleFn(node.parentNode);
break;
case 1:
styleText(node, textRx, styleFn);
break;
}
}
};
styleText(el, textRx, styleFn);
}