dmcshehan
dmcshehan

Reputation: 1259

How to get a text Node from a DOM node?

I'm trying to crate a Range Object by using

let range = document.createRange();

As you all know we must call

range.setStart(startNode,startOffset) ;

and

range.setEnd(endNode,endOffset);

I want to pass text nodes for both startNode and endNode, because if you pass a DOM node, you cannot specify custom offsets. My question is how can i get the text node of an element.

I just dont want just text as String, i want the text node.

suppose i have a paragraph

<p id="para">This is a paragraph</p>

i can get the DOM node by calling

let para = document.getElementById('para');

But how can i get the text node which is inside paragraph?

I want it as a text node, not like just a string. Please help.

jsfiddle

Upvotes: 0

Views: 823

Answers (3)

Kaiido
Kaiido

Reputation: 136627

To get the TextNode from

 <p id="para">This is a paragraph</p>

you just need para.childNodes[0].

console.log(para.childNodes[0].nodeName, para.childNodes[0].textContent);
<p id="para">This is a paragraph</p>

However beware, if you actually had

<p id="para"><!--some comment-->
This is a paragraph
</p>

then this would return the CommentNode:

console.log(para.childNodes[0].nodeName, para.childNodes[0].textContent);
<p id="para"><!--some comment-->
This is a paragraph
</p>

And even, depending on how your element has been populated, you may very well have different TextNodes in the same element:

para.append('This ', 'is ', 'a ', 'paragraph');
console.log(para.childNodes[0].nodeName, para.childNodes[0].textContent);
<p id="para"></p>

So you'd probably want to iterate over each Nodes of the childNodes NodeList, or simply call setStart on your Element since it's also allowed:

const range = document.createRange();
range.setStart(para,0);
range.setEnd(para, para.childNodes.length);
// which is actually the same as range.selectNode(para)

getSelection().addRange(range);
<p id="para">This is a paragraph</p>


And if you really need to walk along the TextNodes of your element, then consider using a TreeWalker with the NodeFilter.SHOW_TEXT filter:

para.append('This ', 'is ', 'a ', 'paragraph');
function getNodeAtTextIndex(elem, index) {
  const treeWalker = document.createTreeWalker(
    elem,
    NodeFilter.SHOW_TEXT,
    null,
    false
  );
  let str = '';
  while(treeWalker.nextNode()) {
    const node = treeWalker.currentNode;
    str += node.textContent;
    if(str.length >= index) return {
      node: node,
      index: node.length - (str.length - index)
    };
  }
  return null;
}

const start = getNodeAtTextIndex(para, 2);
const end = getNodeAtTextIndex(para, 9);
const range = document.createRange();
range.setStart(start.node, start.index);
range.setEnd(end.node, end.index);
getSelection().addRange(range);
<p id="para"></p>

Upvotes: 3

sminutoli
sminutoli

Reputation: 841

Every DOMElement has a childNodes array-like object that you can access. Try changing the textNode value with

const textNode = document.querySelector('#para').childNodes[0];

Upvotes: 0

mike.k
mike.k

Reputation: 3427

You can use para.innerText to get the value This is a paragraph out.

Update: this should work for you.

const textNode = document.querySelector('#para').childNodes[0];

Upvotes: 0

Related Questions