uurann
uurann

Reputation: 21

jQuery: replace text inside link but not in tags

I've got a html:

<div class="sth-key">
    <p>
        key here <span class="keyify">and here a key</span>
        <a href="/key-anything" title="dont change that key">and a key</a>
    </p>
    <p>
        and the final <strong>key</strong>
    </p>
</div>

and I want to replace word 'key' that is not inside attributes, with 'pencil', so the output would look like this:

<div class="sth-key">
    <p>
        pencil here <span class="keyify">and here a pencil</span>
        <a href="/key-anything" title="dont change that key">and a pencil</a>
    </p>
    <p>
        and the final <strong>pencil</strong>
    </p>
</div>

I've tried to do this with

$('.sth-key p').each(function(){
    $(this).html($(this).html().replace('key','pencil'));
});

or with text()... but it doesn't work.

Upvotes: 2

Views: 1950

Answers (7)

MaxZoom
MaxZoom

Reputation: 7753

Below code iterates over all text nodes and replaces key word with pencil

$('.sth-key p').each(keyToPencil);

function keyToPencil() {
  var iter = document.createNodeIterator(this, NodeFilter.SHOW_TEXT);
  while (node = iter.nextNode()) {
    node.data = node.data.replace(/key/g, 'pencil');
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="sth-key">
  <p>
    key here <span class="keyify">and here a key</span>
    <a href="/key-anything" title="dont change that key">and a key</a>
  </p>
  <p>
    and the final <strong>key</strong>
  </p>
</div>

Upvotes: 0

jonathanGB
jonathanGB

Reputation: 1540

I replaced "key" with /key/g, which is a regular expression that will search globally. If you use replace like you did, it will stop at the first occasion.

$(function() {
  $('.sth-key p').each(function() {
    $(this).html($(this).html().replace(/key/g, 'pencil'));
  });
})
<div class="sth-key">
  <p>
    key here <span class="keyify">and here a key</span>
    <a href="/key-anything" title="dont change that key">and a key</a>
  </p>
  <p>
    and the final <strong>key</strong>
  </p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Here's more information: String.prototype.replace

Upvotes: 1

Kasia
Kasia

Reputation: 1725

$('.sth-key p').each(function(i,elem){
    let html = $(elem).html().replace(/key/g,'pencil');
    $(this).html(html);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sth-key">
<p>
    key here <span class="keyify">and here a key</span>
    <a href="/key-anything" title="dont change that key">and a key</a>
</p>
<p>
    and the final <strong>key</strong>
</p>
</div>

Upvotes: 1

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48367

You have to use .contents() method in order to search through the immediate children of these elements in the DOM tree.

Also, you have to use replace method in order to replace your text.

I used each() function in order to go through all childrens of the p element.

The nodeType property returns the node type, as a number, of the specified node.

Here are main node types:

If the node is an element node, the nodeType property will return 1.

If the node is an attribute node, the nodeType property will return 2.

If the node is a text node, the nodeType property will return 3.

$('.sth-key p').each(function(){
	$(this).contents().each(function () {
            if (this.nodeType === 3) 
                this.nodeValue=$(this).text().replace("key", "pencil")
            if(this.nodeType===1)
                $(this).html( $(this).html().replace("key", "pencil") )
        });   
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sth-key">
    <p>
        key here <span class="keyify">and here a key</span>
        <a href="/key-anything" title="dont change that key">and a key</a>
    </p>
    <p>
        and the final <strong>key</strong>
    </p>
</div>

Upvotes: 3

gaetanoM
gaetanoM

Reputation: 42054

According to contents:

Get the children of each element in the set of matched elements, including text and comment nodes.

You can :

$('.sth-key p').contents().each(function(idx, ele) {
  // get only TEXT_NODE or ELEMENT_NODE 
  if (ele.nodeType === 3 || ele.nodeType === 1) {
    ele.textContent = ele.textContent.replace('key','pencil');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div class="sth-key">
    <p>
        key here <span class="keyify">and here a key</span>
        <a href="/key-anything" title="dont change that key">and a key</a>
    </p>
    <p>
        and the final <strong>key</strong>
    </p>
</div>

Upvotes: 0

Ajay
Ajay

Reputation: 196

This code only replace when text only in p. if text in span inside of p this does not replace

$(".sth-key p").text(function (_, ctx) {
    return ctx.replace("key", "pencil");
});

Upvotes: -1

mrhallak
mrhallak

Reputation: 1178

Just use the text method and pass a function to replace all 'key' with 'pencil'.

​$(".sth-key").text(function () {
    return $(this).text().replace("key", "pencil"); 
});​​​​​

I didn't test this yet but I think it works.

Upvotes: 1

Related Questions