javascripthtmldomhtml-selectinnerhtml

How to dynamically retrieve the content text of a HTML tag and its child tags?


I would like to know how to dynamically retrieve the content text of a HTML tag and its child tags?

Here is my HTML code, for example:

<p><code>C:\<select>
        <option value="test1\">test1\</option>
        <option value="test2\">test2\</option>
    </select>test3\<select>
        <option value="test4\">test4\</option>
        <option value="test5\">test5\</option>
    </select>test6\<select>
        <option value="test7\">test7\</option>
        <option value="test8\">test8\</option>
        <option value="test9\">test9\</option>
    </select>test10.txt</code></p>

I would like to create a button after this code, and when it is clicked, I would like to write the content directly within the console.

For example:

C:\test2\test3\test4\test6\test8\test10.txt

or

C:\test1\test3\test5\test6\test9\test10.txt

...

It might be possible that another paragraph of code only contains 1 or 2 <select> tags. So, I don't want a code that only works for 3 <select> tags, like in the previous example.

Thank you very much in advance


Solution

  • The best property to use if you want all the text (ie. both inside and outside the <select> elements) is .textContent:

    p.textContent; // C:\ test1\ test2\ test3\ test4\ test5\ test6\ test7\ test8\ test9\ test10.txt
    

    Working Example:

    let firstParagraph = document.querySelector('p');
    let button = document.querySelector('button');
    let outputParagraph = document.querySelector('.output');
    let selectElements = document.querySelectorAll('select');
    
    const showOutput = () => {
      let outputText = '';
    
      // GET *ALL* PATH SEGMENTS
      let pathSegmentsArray = firstParagraph.textContent.split(' ').filter((pathSegment) => pathSegment !== '');
    
      // GET PATH SEGMENTS INSIDE <select> ELEMENTS
      let selectedOptions = [];
      selectElements.forEach((select) => selectedOptions.push(select.selectedOptions[0].textContent));
    
      // BUILD OUTPUT
      pathSegmentsArray.forEach((pathSegment) => {
        let includePathSegment = false;
        
        if (firstParagraph.innerText.includes(pathSegment.trim())) {
          includePathSegment = true;
        }
        
        if (selectedOptions.includes(pathSegment.trim())) {
          includePathSegment = true;
        }
        
        if (includePathSegment) {
          outputText += pathSegment;
        }
      });
      
      outputParagraph.textContent = outputText;
    }
    
    button.addEventListener('click', showOutput);
    <p><code>C:\<select>
            <option value="test1\">test1\</option>
            <option value="test2\">test2\</option>
        </select>test3\<select>
            <option value="test4\">test4\</option>
            <option value="test5\">test5\</option>
        </select>test6\<select>
            <option value="test7\">test7\</option>
            <option value="test8\">test8\</option>
            <option value="test9\">test9\</option>
        </select>test10.txt</code></p>
        
    <button type="button">Show Output</button>
    <p class="output"></p>


    Further Reading on textContent vs innerText:

    The source above states:

    Differences from innerText

    Don't get confused by the differences between Node.textContent and > HTMLElement.innerText. Although the names seem similar, there are > important differences:

    • textContent gets the content of all elements, including <script> and <style> elements. In contrast, innerText only shows "human-readable" elements.
    • textContent returns every element in the node. In contrast, innerText is aware of styling and won't return the text of "hidden" elements.

    Moreover, since innerText takes CSS styles into account, reading the value of innerText triggers a reflow to ensure up-to-date computed styles. (Reflows can be computationally expensive, and thus > should be avoided when possible.)


    Further Reading on selectedOptions: