I need to wrap each asterisks on a page with <span class="red"></span>
. The few things I've tried don't work. I think what this boils down to is that I need to search the page for a specific character, and I can't figure out how to do that.

- 17,318
- 25
- 95
- 158
-
1Why would you want to do that? I am sure there are better ways to achieve what you are trying to do. – Selvakumar Arumugam Apr 26 '13 at 14:52
-
I second Vega's comment, in that, this would be resource intensive being as you would have to check the entire page for a specific character. – user1477388 Apr 26 '13 at 14:53
-
It's a bit hard to explain, but basically it's just easier to do this than to rework an entire script I've written for a page. – JacobTheDev Apr 26 '13 at 14:54
-
2@Blazemonger: That's incorrect, `$("*")` will return a collection of *all* elements. – MMM Apr 26 '13 at 14:57
-
I realized the problem with the `*`, but that still doesn't help me figure out how to do this. – JacobTheDev Apr 26 '13 at 14:58
-
@Rev So what do you want to do? – VisioN Apr 26 '13 at 14:58
-
Are we looking for text or elements here? – Blake Plumb Apr 26 '13 at 14:59
-
duplicate of http://stackoverflow.com/questions/926580/find-text-string-using-jquery – David Apr 26 '13 at 15:02
-
@Dave: Not really, that question is about searching for a string, not handling the replacement of all occurrences of that string. – MMM Apr 26 '13 at 15:15
-
@MMM The answer http://stackoverflow.com/a/926964/21909 would at least be a good starting point. – David Apr 26 '13 at 15:33
-
True, you're right, however it's not a _duplicate_ – MMM Apr 26 '13 at 15:35
5 Answers
For not replacing the entire HTML (really bad attitude), we can do fast manipulation with elements:
var specialTags = ["script", "style"].join("|"),
re = new RegExp("^(?:" + specialTags + ")$", "i");
for (var els = document.getElementsByTagName("*"), i = els.length; i--;) {
var el = els[i];
if (re.test(el.tagName))
continue;
for (var j = 0, childs = el.childNodes, lj = childs.length; j < lj; j++) {
var child = childs[j];
if (child.nodeType === 3 && child.nodeValue.indexOf("*") > -1) {
var segments = child.nodeValue.split("*");
for (var k = 0, lk = segments.length; k < lk; k++) {
el.insertBefore(document.createTextNode(segments[k]), child);
if (k < lk - 1) {
var span = document.createElement("span");
span.className = "red";
span.appendChild(document.createTextNode("*"));
el.insertBefore(span, child);
}
}
el.removeChild(child);
}
}
}
This is pure JavaScript which does not require jQuery, that can't really help here.

- 143,310
- 32
- 282
- 281
-
1
-
The ***REAL SPEED*** of this approach is demonstrated here: http://jsperf.com/replace-text-with-tag. – VisioN Apr 26 '13 at 15:32
-
+1 Remember to add the `*` to the contents of the tag (that's what the OP wanted) – MMM Apr 26 '13 at 15:34
-
-
-
-
@VisioN: How about `
My ** website `? Never heard that the spec does not allow that. – MMM Apr 26 '13 at 16:40 -
@MMM Then it is `
` and not ``. Just add `title` to `specialTags` array, and the script will skip it. – VisioN Apr 26 '13 at 16:41 -
@MMM Of course if you need to remove entire `` from operating queue, it is better to use `querySelectorAll("body, body *")` instead of `getElementsByTagName("*")`. However `querySelector` is available only in modern browsers. – VisioN Apr 26 '13 at 16:46
-
Yes, yes, all you're saying is true and known to me, I've merely stated that if anything in the head has an asterisk, it will get replaced too ;) No need to explain yourself! – MMM Apr 26 '13 at 16:51
How about this?...
$("body:contains(*)").contents().each(function() {
if(this.nodeType == 1)
{
$(this).html($(this).html().replace(/\*/g, "<span class=\"red\">*</span>"))
}
});

- 123,204
- 21
- 253
- 243
-
You would want to do this on nodeType == 3 so as not to replace * in html – Daniel Moses Apr 26 '13 at 15:20
-
I was initially trying that but then it doesnt replace the text in the html so i needed to get that particular text's parent node.. hence tried use Nodetype element. Probably i was doing something wrong... – PSL Apr 26 '13 at 15:21
This is a bit dirty and risky (explained below), but you could try the following:
var allHTML = $("body").html();
allHTML = allHTML.replace(/\*/g, "<span class=\"red\">*</span>");
$("body").html(allHTML);
Note: As Dogbert pointed out this might replace *
characters that are within HTML tags, e.g. node attributes.
EDIT: Bear in mind that this might reattach all the scripts you have in your body though! Try replacing body
with your main container.
EDIT2: VisioN posted a more elaborate but a lot safer solution.

- 7,221
- 2
- 24
- 42
-
-
@Dogbert: That's true, however I don't think you use such characters in attributes often? I'll add this to the answer though. – MMM Apr 26 '13 at 15:05
-
ugh. Unfortunately the things that I'm trying to edit do have * in the attributes. Thanks, though, this would solve the problem otherwise. I'll just have to do this statically, which is going to take much longer. – JacobTheDev Apr 26 '13 at 15:09
-
@Rev Never never never replace entire markup in a way like this. Please see [my answer](http://stackoverflow.com/a/16239900/1249581) as the way how it *should* be done. – VisioN Apr 26 '13 at 15:34
-
@VisioN: I agree, that's why I wrote it's dirty and risky, your answer is brilliant though. – MMM Apr 26 '13 at 15:36
Without using jQuery so it might be a little faster, and definitely not dependent on libs:
(function(str,e){
var regex = new RegExp(str, 'gi');
e.innerHTML = e.innerHTML.replace(regex, '<span class="red">*</span>');
})('*',document.body);

- 3,615
- 1
- 26
- 32
This will work and not replace * in tags it shouldn't.
var text = $("body").find(":contains(*)").contents().filter(function() {
//Don't include css or script tags, all other text nodes are fine.
return this.nodeType == 3
&& ($(this).parent().get(0).tagName.toUpperCase() !== "SCRIPT")
&& ($(this).parent().get(0).tagName.toUpperCase() !== "STYLE");
}).replaceWith(function() {
return this.textContent.replace(/\*/g, "<span class=\"red\">*</span>");
You can test the others code in this jsfiddle to see if they keep the "hi" blue or not. If it doesn't stay blue they have a bug.

- 5,872
- 26
- 39