Search code examples
jqueryreplacefindhrefsrc

jQuery: Find & replace string in html; avoid src and href values


Say I have this:

<div>
    People say <a href="apples.html">apples</a> are nice. 
    It's true, apples are nice. You go, <b>apples</b>!
    <img src="apples.jpg" />
</div>

How would I go about replacing every occurrence of "apples" (with "oranges", for example) within that div (including any tag's element content and plain text) WHILE avoiding replacing such occurrences in the href and src attributes, or any attribute for that matter.

So the end result would be:

<div>
    People say <a href="apples.html">oranges</a> are nice.
    It's true, oranges are nice. You go, <b>oranges</b>!
    <img src="apples.jpg" />
</div>

Should note, while text() would do me a good job in this example, I will be replacing with html elements so it's not particularly helpful in the actual case.

Thanks!


Solution

  • The :contains selector will help you here. Given that the div is the root of you search & replace, the following will allow you to replace apples with oranges:

    $("div").find(":contains('apples')").each(function(){
        $this = $(this);
    
        //Example replacement using HTML, but can also just us text() for simple changes
        $this.html($("<i>").text("oranges"));
    });
    

    Based on your comments, I've shown it replacing apples with a little html ... italic oranges.

    See the JSFiddle for a working example.

    Update - altering source html

    The comments pointed out that this missed out the "apples" in the body of the div. If you have control of the Html (I assume you do), then it makes everything easier if you can change the Html to wrap the problem "apples" in a span, so <span>apples</span>. This makes the html:

    <div>
        People say <a href="apples.html">apples</a> are nice. 
        It's true, <span>apples</span> are nice. You go, <b>apples</b>!
        <img src="apples.jpg" />
    </div>
    

    Basically, markup needs to be in place to help you here. See the updated JSFiddle.

    If that isn't possible, an additional Regex to catch this would be needed.

    Update - can't update source html, use Regex

    Ok, so altering the source html is not possible. The following solution, just uses a Regex over the html, which matches all "apples" that are followed by a "<" or a space:

    $("div:contains('apples')").each(function(){
        $this = $(this);
        $this.html($this.html().replace(/apples(?=<|\s)/gi, "oranges"));
    });
    

    Working version shown in the JSFiddle