0

I want to replace only the text of a given element and it should be it's own function.

For example, something like this:

<div id="thisDivIsGettingTargeted">
    <span>
        Edit me!
        <i class="fas fa-edit"></i>
    </span>
</div>

should be replaced to this:

<div id="thisDivIsGettingTargeted">
    <span>
        Oh yeah
        <i class="fas fa-edit"></i>
    </span>
</div>

It's not always the first child, so I can't use firstChild.

I really don't have any idea, how to achieve this. I have to search for the lowest element and have to change it's text, but in this example, it always finds the i tag.

That's the function I wrote.

const get_object = element => {
    if (!element.hasAttribute("data-liner-stop-search") && element.childElementCount === 1){
        return get_object(element.firstElementChild)
    }
    return element
};

Here's another example:

<span class="text-one-liner">
    <span class="name">
        Username
        <span data-tooltip="A tooltip">
            <i class="fas fa-crown"></i>
        </span>
    </span>
</span>

.text-one-liner is targeted and "Username" should be changed.

1
  • You can check this question. But I also think that many of the answers there are outdated/JQuery, so I won't flag it as duplicate Commented Jan 1, 2020 at 14:24

2 Answers 2

1

You can do this by filtering on the nodeType property. Note that whitespace used to format the code also appears as child nodes. You might want to filter on those too as in my example below (node.nodeValue.trim() !== "").

document.querySelector('#thisDivIsGettingTargeted span').childNodes.forEach((node) => {
  if(node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() !== "") {
    node.nodeValue = "new text";
  }
});
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<div id="thisDivIsGettingTargeted">
    <span>
        Edit me!
        <i class="fas fa-edit"></i>
    </span>
</div>

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

3 Comments

Thank you, but this is again a specifiec solution. I would like to have a function, where I pass my #thisDivIsGettingTargeted as (for example) element and a new text and that function automaticayll searchs for this text node and replaces it.
@Myzel394 You can easily wrap this logic in a function that does this for you. Maybe you only need to build in some logic to look for "grandchildren" and other descendant as well.
I thought I did. I tried it in my function I posted in my question but it didn't work. Do you have an idea?
0

If (and only if) your function always returns the i tag element (as you said) and your text node is just before that i, try this

const get_object = element => {
    if (!element.hasAttribute("data-liner-stop-search") && element.childElementCount === 1){
        return get_object(element.firstElementChild)
    }
    return element.previousSibling;
};

Or you can loop through all the child elements of your targeted element (using .getElementsByTagName("*")) and check for the nodeType of the element. nodeType of a text node is 3. If there's only one text node among all the children, the following (generic) condition inside a loop will work

(updated as per @josh.trow's suggestion)

if (element[i].nodeType === 3 && !element[i].innerText.trim().length)
    return element[i]

You can find a reference for nodeType here.

3 Comments

Works only on this specifiec example, but I want a generic solution. The text could also be after a tag or between multiple tags.
I suspect you will hit many false flags on this by virtue of the HTML whitespace counting as a text node (unless the content is compressed) - you will need to as well verify the content is not empty (if (element[i].nodeType === 3 && element[i].innerText.trim().length) or something like that
@josh.trow I edited the answer and added !element[i].innerText.trim().length as the second check

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.