2

Using javascript, I need to parse the HTML of a page and replace all occurrences of ABC with ABC that occur within a content block such as <p>ABC Company lorem ipsum</p> would be changed to <p><span class="abc">ABC</span> Company lorem ipsum</p> but mailto:[email protected] would stay the same.

So pretty much replace ABC anywhere that is preceded by a space or quote, but obviously I would like to make it a little more generic. Perhaps the expression would say when it is not preceded/followed by [a-zA-z].

What I have so far:

<script type="text/javascript">
    $(document).ready(function() {
        $('body').find('div').each(function(i, v) {
            h = $(v).html();

            if (h.indexOf('abc') > 0) {
                h = h.replace('abc', '<span class="abc">abc</span>');
                $(v).html(h);
            }
        });
    });
</script>
4
  • 3
    Just in case it wasn't obvious, doing the replace this way will cause all stored data and bound events on elments inside of those divs to be lost. Commented May 20, 2013 at 20:44
  • ah, I figured there was something horribly wrong with this implementation since it took 5 minutes to come up. Commented May 20, 2013 at 20:50
  • This should get you part of the way there: jsfiddle.net/hrEyC actually going to have to navigate from the node to it's closest parent element and modify that element's text content. Commented May 20, 2013 at 20:57
  • If I'm not mistaken, your code will cause <div><div>abc</div></div> to become <div><div><span class="<span class="abc">abc</span>">abc</span></div></div> Commented May 20, 2013 at 21:14

2 Answers 2

1

I suggest going about it a different way that preserves data and events on the elements and doesn't interfere with attributes on said elements.

 $("body div").find("*").addBack().contents().filter(function(){
     return this.nodeType === 3;
 }).each(function() {
     $(this).parent().html(this.nodeValue.replace(/abc/g, '<span  class="abc">abc</span>'));
 })

http://jsfiddle.net/hrEyC/1/

Note, requires jQuery 1.9+ due to use of .addBack(), for older versions replace with .andSelf()

Sign up to request clarification or add additional context in comments.

3 Comments

That replace logic is much more solid, but the regex replaces all. I need to exclude instances that would be in email addresses (or similar situations).
Do you also want it to replace fooabcbar with foo<span>abc</span>bar? that makes it very difficult if you also want to ensure that it doesn't replace inside an email address.
If abc is surrounded by other letters, it's more than likely not getting replaced. Most situations are just <p>Blah abc</p> or <p>Blah "abc blah"</p>
1

This is not a very efficient thing to do (loop through all div tags in the DOM and apply a regex to each one) but since I don't know what constraints you have or what situation you are using this code in, I'll just assume there's a good reason you're doing this client-side in this way.

Anyway, this regex seems to match your requirements (albeit not very well defined requirements):

h = h.replace(/([^A-Z])(ABC)([^A-Z])/gi, '$1<span style="color: red">$2</span>$3');

Fiddle here: http://jsfiddle.net/czJFG/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.