1

I have something like that :

<h3 id="plop">I want to change this text <span id="trololo">bla bla bla</span> </h3>

Generaly, I use js to change text on my html elements :

document.getElementById("plop").innerHTML = "I change the text";

But do something like this remove my span element on title. Then, is it possible to change only the text on h3 ?

I know, i can do something like that:

document.getElementById("plop").innerHTML = "I change the text <span id=\"trololo\">bla bla bla</span>";

But is not my goal.

KasaiJo
  • 130
  • 1
  • 12
  • Have you tried wrapping your text with another span and target that span by id instead? – lefanous Nov 18 '20 at 11:17
  • 1
    Create another span between `h3` and the other `span`, that contains `I want to change this text` and simpy change that `span`'s text. – nagyl Nov 18 '20 at 11:17

3 Answers3

3

You can try this:

document.querySelector('#plop').firstChild.nodeValue = "I change the text "
rensothearin
  • 670
  • 1
  • 5
  • 24
1

With a RegExp you can preserve the element as it is:

document.getElementById("plop").innerHTML = document.getElementById("plop").innerHTML.replace(/.*(<span.*<\/span>)/,"I change the text $1")
console.log(document.getElementById("plop").innerHTML)
<h3 id="plop">I want to change this text <span id="trololo">bla bla bla</span> </h3>

Note: Don't go much beyond that with regexp and HTML: https://stackoverflow.com/a/1732454/2729605

malarres
  • 2,941
  • 1
  • 21
  • 35
1

While you've already accepted an answer to your question, I thought I'd take the time to post an alternative — functional — approach:

// declaring the function changeText() as a constant, using
// Arrow function syntax (since we don't use 'this' within
// the function); this takes two arguments:
// elem: a reference to the node whose text we're changing, and
// ...text: which combines all supplied Strings into an Array,
// using rest parameters:
const changeText = (elem, ...text) => {

  // initialises a counter:
  let counter = 0,

    // in the event that only one String is provided we make the
    // assumption that the supplied String should replace all
    // text-nodes:
    repeat = text.length === 1,
    // declared, but uninitialised, variables for later use:
    cache,
    _temp,
    beginsWithSpace,
    endsWithSpace;

  // retrieves the child-nodes of the given element-node, and we then
  // use NodeList.prototype.forEach() to iterate over those nodes:
  elem.childNodes.forEach(
    // n is a reference to the current Node of the NodeList:
    (n) => {
      // if the Node has a nodeType, and that nodeType is 3 it is
      // a textNode:
      if (n.nodeType && n.nodeType === 3) {
        // we cache the current nodeValue in the 'cache' variable:
        cache = n.nodeValue;
        // we use RegExp.prototype.test() which returns a Boolean
        // to see if the current nodeValue starts with a space:
        beginsWithSpace = (/^\s+/).test(cache);
        // ...or ends with a whitespace:
        endsWithSpace = (/\s+$/).test(cache);

        // here we assign the text - from the supplied argument -
        // to the _temp variable; if only one argument exists
        // (hence repeat is true) we use the first element of the
        // Array, otherwise - if repeat is false - we use the
        // String from the text Array at the index of counter, and
        // then increment the counter variable:
        _temp = repeat ? text[0] : [text[counter++]];

        // here we assign a new value to the current Node, using
        // a template-literal; if beginsWithSpace evaluates to true
        // a single white-space is inserted, otherwise an empty
        // String is inserted, followed immediately by the cached
        // text to be inserted, followed again by either another
        // white-space character or empty string depending on
        // the value of endsWithSpace:
        n.nodeValue = `${beginsWithSpace ? ' ':''}${ _temp }${endsWithSpace ? ' ' : ''}`;
      }
    });
}

// calling the function:
changeText(document.getElementById('plop'), "some new text in here");
changeText(document.querySelector('li'), "Node content", "amazing");
changeText(document.querySelector('li:last-child'), "redacted");
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

q::before,
q::after {
  content: '"';
  color: #777;
}

ul li {
  margin: 0.2em 0 0 1.5em;
}

ul li::marker {
  content: "\00BB";
  color: #f90;
}
<h3 id="plop">I want to change this text <span id="trololo">bla bla bla</span> </h3>

<ul>
  <li>This text <em>should be</em> removed</li>
  <li>This <em>element</em> has <em>multiple</em> <q>HTML child-nodes</q> which should <em>not</em> be changed<strong>.</strong></li>
</ul>

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410