'Select element by text and change text with jQuery

It only works correctly in the first case. How can I modify the code so that it works in the various possible cases?

$(".person")
    .find(".name")
    .filter(function () {
        return $(this).text() === "Steve";
    })
    .text("Tim");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>.name a {color: red;} .name span {color: green;}</style>
<div class="person">
    <a class="name">Steve</a>
</div>

<div class="person">
    <div class="name">
        <a>Steve</a>
    </div>
</div>

<div class="person">
    <div class="name">
        <div>My name is <span>Steve</span></div>
    </div>
</div>


Solution 1:[1]

This is the solution to my problem that I found:

const rename = (selector, oldName, newName) => {
  $(selector)
    .addBack()
    .find('*')
    .filter((index, node) => $(node).text() === oldName)
    .text(newName)
}

rename('.name', 'Steve', 'Tim')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>.name a {color: red;} .name span {color: green;}</style>
<div class="person">
  <a class="name">Steve</a><br>
  <a class="name">James</a><br>
  <a class="name">John</a>
</div>

<div class="person">
  <div class="name">
    <a>Steve</a>
  </div>
  <div class="name">
    <a>James</a>
  </div>
  <div class="name">
    <a>John</a>
  </div>
</div>

<div class="person">
  <div class="name">
    <div>My name is <span>Steve</span></div>
  </div>
  <div class="name">
    <div>My name is <span>James</span></div>
  </div>
  <div class="name">
    <div>My name is <span>John</span></div>
  </div>
</div>

Solution 2:[2]

Here's a reusable function with 3 parameters:

  1. selector ==> ".person"
  2. target ===> "Steve"
  3. substitute => "Tim"

It uses JavaScript String method .replaceAll(). Some jQuery and JavaScript methods can destroy HTML. Extracting the text, changing it, and inserting it back in is safer.

BTW, I added a few more examples to demonstrate it's capability. The first example will always have black text, .name span {color: green;} doesn't work because the <span> is .name not a <span> inside .name.

.name span {color: green;} // Works for last example
span.name {color: green;}  //? Works for first example

const switchNames = (selector, target, substitute) =>
$(selector).text().replaceAll(target, substitute);

switchNames('.person', 'Steve', 'Tim');
 
<style>.name b {color: red;} .name span {color: green;}</style>
<div class="person">
  <span class="name">Steve</span>
</div>

<div class="person">
  <div class="name">
    <b>Steve</b>
  </div>
</div>
<div class="person">
  <b class="name">Jim</b>
</div>

<div class="person">
  <div class="name">
    <i>Jim</i>
  </div>
</div>

<div class="person">
  <div class="name">
    <div><span>Steve is in this sentence</span></div>
  </div>
</div>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2