How to Change an Element'S Text Without Changing Its Child Elements

How can I change an element's text without changing its child elements?

Mark’s got a better solution using jQuery, but you might be able to do this in regular JavaScript too.

In Javascript, the childNodes property gives you all the child nodes of an element, including text nodes.

So, if you knew the text you wanted to change was always going to be the first thing in the element, then given e.g. this HTML:

<div id="your_div">
**text to change**
<p>
text that should not change
</p>
<p>
text that should not change
</p>
</div>

You could do this:

var your_div = document.getElementById('your_div');

var text_to_change = your_div.childNodes[0];

text_to_change.nodeValue = 'new text';

Of course, you can still use jQuery to select the <div> in the first place (i.e. var your_div = $('your_div').get(0);).

How do you change an element innerText without changing its children

Try this:

document.getElementById("el1").childNodes[0].textContent = "changed";
<div id="el1">Change only me<div>but not me</div></div>

change text of an element without changing child elements

In order to access the text part, you need to use .contents()

See this answer and comments for more info.

$("#x").append("<b> pressed</b>")       .contents().filter(function(){return this.nodeType == 3;}).first()       .replaceWith("well done");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div id='x'>Press</div>

How do you remove text without affecting child elements?

Whit Javascript you can just get all the childNodes of the element with id=parent and then traverse these childs to .remove() those that have nodeType equal to Node.TEXT_NODE:

let childs = document.getElementById("parent").childNodes;childs.forEach(c => c.nodeType === Node.TEXT_NODE && c.remove());
<div id="parent">  <div>keep this</div>  <div>keep this</div>  Some random text that can't be predicted (to be removed)  <div>keep this</div></div>

Proper way to change a SVG text without changing its children tspan

"Is there a property or any other method to specifically change the text content only?"

No, probably not. In fact, I think it might be for the better that such a method doesn't exist. Say for example that your <text> node looked like this:

<text>
Foo
<tspan>Bar</tspan>
Baz
</text>

And now we would call the unknown method to change the text into Hello world. What would the desired outcome be?

<text>
Hello world
<tspan>Bar</tspan>
</text>
<text>
<tspan>Bar</tspan>
Hello world
</text>

or even

<text>
Hello
<tspan>Bar</tspan>
world
</text>

Looking at it like this, it becomes clear that the "text content" can't be seen as a special case that exists apart from the node tree: just like the <tspan> in your example, there can be multiple text nodes in any order and quantity. It's therefore hard to justify a special method that only changes text nodes, without introducing method to only change all the <tspan>, <div> and so on as well.

Solutions

If you regard all the text nodes as some kind of typeless elements like this:

<text>
<text>Foo</text>
<tspan>Bar</tspan>
<text>Baz</text>
</text>

there is little question about how you would approach targeting and changing your desired element. Options include:

  • Grab it by index (like you already did). Judging from the fictional snippet above, it would be pretty safe to assume that Foo will indeed always be the first element. But just like with the :first selector in CSS, you might rather not want to depend so rigidly on a specific structure.
  • A class="text" attribute would be very clear, but then you'd need to wrap your text in an actual element (which might be the best solution, but I'm following your specs here).
  • Grab the first element that is of the right type, just like you would with any other element.

The snippet below would therefore be a perfectly valid way to alter the first text node in a list of children (written in a functional manner to keep it concise).

Array.from(document.querySelector("text").childNodes)
.find(e => e.nodeType === Node.TEXT_NODE)
.textContent = "New Foo";
<svg>
<text x="10" y="30">
Foo Bar Baz
<tspan x="30" dy="30">FooBar</tspan>
<tspan x="30" dy="30">FooBaz</tspan>
</text>
</svg>

Update text of HTMLElement without affecting child elements

You could wrap the text in its own container, which is probably the best pattern here.

$('.text-content').text('Something else')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><span class="js-my-parent-span">    <span class="text-content">Hello, World!</span>    <span class="js-my-child-span">Other content</span></span>

How to change text inside a div without changing any other element in the div

With element.innerText() you're essentially overwriting the whole content of your div - including other html elements such as the anchor tag.

There's a child attached to your div that actually holds your text.
You can reference it via document.getElementById("title").firstChild along with it's .data property.