getElementsByTagName() equivalent for textNodesFind all text nodes in HTML pageHow do I get all the text nodes in a HTML document?Best approach to traverse the DOM and replace textget all html elements with text node to custom javascript objectFind and replace specific text characters across a document with JSJavascript Contenteditable - set Cursor / Caret to indexHighlight each word on a webpage, one at a time, with JavaScriptFirefox addon SDK and DOM manipulation problemsUsing a TreeWalker to retrieve non-Javascript text nodesRegex to search html return, but not actual html jQueryjQuery document.createElement equivalent?JavaScript equivalent to printf/String.Format$(document).ready equivalent without jQueryHow do I find the DOM node that is at a given (X,Y) position? (Hit test)Is there a replaceWholeText Equivalent in jQuery? - How to replace TextNodeEfficiently removing textnodes from the DOMHow to implement arbitrary textnode selection in jQueryIs there an alternative to jQuery / sizzle that supports textNodes as first class citizens in selectors?How to Implement DOM Data Binding in JavaScriptTreeWalker, textNodes and RTL ordering in natural language web pages
How long does it take to type this?
Do Phineas and Ferb ever actually get busted in real time?
If I cast Expeditious Retreat, can I Dash as a bonus action on the same turn?
How to make payment on the internet without leaving a money trail?
Accidentally leaked the solution to an assignment, what to do now? (I'm the prof)
How does one intimidate enemies without having the capacity for violence?
How can bays and straits be determined in a procedurally generated map?
Can I make popcorn with any corn?
What are these boxed doors outside store fronts in New York?
A function which translates a sentence to title-case
What typically incentivizes a professor to change jobs to a lower ranking university?
Python: Add Submenu
The magic money tree problem
Email Account under attack (really) - anything I can do?
TGV timetables / schedules?
Why did the Germans forbid the possession of pet pigeons in Rostov-on-Don in 1941?
Why is "Reports" in sentence down without "The"
How is this relation reflexive?
How can I fix this gap between bookcases I made?
Why are 150k or 200k jobs considered good when there are 300k+ births a month?
Why can't I see bouncing of a switch on an oscilloscope?
How did the USSR manage to innovate in an environment characterized by government censorship and high bureaucracy?
Suffixes -unt and -ut-
Possibly bubble sort algorithm
getElementsByTagName() equivalent for textNodes
Find all text nodes in HTML pageHow do I get all the text nodes in a HTML document?Best approach to traverse the DOM and replace textget all html elements with text node to custom javascript objectFind and replace specific text characters across a document with JSJavascript Contenteditable - set Cursor / Caret to indexHighlight each word on a webpage, one at a time, with JavaScriptFirefox addon SDK and DOM manipulation problemsUsing a TreeWalker to retrieve non-Javascript text nodesRegex to search html return, but not actual html jQueryjQuery document.createElement equivalent?JavaScript equivalent to printf/String.Format$(document).ready equivalent without jQueryHow do I find the DOM node that is at a given (X,Y) position? (Hit test)Is there a replaceWholeText Equivalent in jQuery? - How to replace TextNodeEfficiently removing textnodes from the DOMHow to implement arbitrary textnode selection in jQueryIs there an alternative to jQuery / sizzle that supports textNodes as first class citizens in selectors?How to Implement DOM Data Binding in JavaScriptTreeWalker, textNodes and RTL ordering in natural language web pages
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
Is there any way to get the collection of all textNode
objects within a document?
getElementsByTagName()
works great for Elements, but textNode
s are not Elements.
Update: I realize this can be accomplished by walking the DOM - as many below suggest. I know how to write a DOM-walker function that looks at every node in the document. I was hoping there was some browser-native way to do it. After all it's a little strange that I can get all the <input>
s with a single built-in call, but not all textNode
s.
javascript dom dhtml textnode
add a comment |
Is there any way to get the collection of all textNode
objects within a document?
getElementsByTagName()
works great for Elements, but textNode
s are not Elements.
Update: I realize this can be accomplished by walking the DOM - as many below suggest. I know how to write a DOM-walker function that looks at every node in the document. I was hoping there was some browser-native way to do it. After all it's a little strange that I can get all the <input>
s with a single built-in call, but not all textNode
s.
javascript dom dhtml textnode
add a comment |
Is there any way to get the collection of all textNode
objects within a document?
getElementsByTagName()
works great for Elements, but textNode
s are not Elements.
Update: I realize this can be accomplished by walking the DOM - as many below suggest. I know how to write a DOM-walker function that looks at every node in the document. I was hoping there was some browser-native way to do it. After all it's a little strange that I can get all the <input>
s with a single built-in call, but not all textNode
s.
javascript dom dhtml textnode
Is there any way to get the collection of all textNode
objects within a document?
getElementsByTagName()
works great for Elements, but textNode
s are not Elements.
Update: I realize this can be accomplished by walking the DOM - as many below suggest. I know how to write a DOM-walker function that looks at every node in the document. I was hoping there was some browser-native way to do it. After all it's a little strange that I can get all the <input>
s with a single built-in call, but not all textNode
s.
javascript dom dhtml textnode
javascript dom dhtml textnode
edited Apr 5 '10 at 21:57
levik
asked Apr 5 '10 at 16:58
leviklevik
74k236689
74k236689
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
Update:
I have outlined some basic performance tests for each of these 6 methods over 1000 runs. getElementsByTagName
is the fastest but it does a half-assed job, as it does not select all elements, but only one particular type of tag ( i think p
) and blindly assumes that its firstChild is a text element. It might be little flawed but its there for demonstration purpose and comparing its performance to TreeWalker
. Run the tests yourselves on jsfiddle to see the results.
- Using a TreeWalker
- Custom Iterative Traversal
- Custom Recursive Traversal
- Xpath query
- querySelectorAll
- getElementsByTagName
Let's assume for a moment that there is a method that allows you to get all Text
nodes natively. You would still have to traverse each resulting text node and call node.nodeValue
to get the actual text as you would do with any DOM Node. So the issue of performance is not with iterating through text nodes, but iterating through all nodes that are not text and checking their type. I would argue (based on the results) that TreeWalker
performs just as fast as getElementsByTagName
, if not faster (even with getElementsByTagName playing handicapped).
Ran each test 1000 times.
Method Total ms Average ms
--------------------------------------------------
document.TreeWalker 301 0.301
Iterative Traverser 769 0.769
Recursive Traverser 7352 7.352
XPath query 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212
Source for each method:
TreeWalker
function nativeTreeWalker()
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode())
textNodes.push(node.nodeValue);
Recursive Tree Traversal
function customRecursiveTreeWalker()
var result = [];
(function findTextNodes(current)
for(var i = 0; i < current.childNodes.length; i++)
var child = current.childNodes[i];
if(child.nodeType == 3)
result.push(child.nodeValue);
else
findTextNodes(child);
)(document.body);
Iterative Tree Traversal
function customIterativeTreeWalker()
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null)
if(node.nodeType == 3) /* Fixed a bug here. Thanks @theazureshadow */
result.push(node.nodeValue);
if(node.hasChildNodes())
node = node.firstChild;
else
while(node.nextSibling == null && node != root)
node = node.parentNode;
node = node.nextSibling;
querySelectorAll
function nativeSelector()
var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
var results = [];
var child;
for(var i = 0; i < elements.length; i++)
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3)
results.push(child.nodeValue);
getElementsByTagName (handicap)
function getElementsByTagName()
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++)
results.push(elements[i].childNodes[0].nodeValue);
XPath
function xpathSelector()
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext())
results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */
Also, you might find this discussion helpful - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
Interesting... DoescreateTreeWalker()
work on IE?
– levik
Apr 6 '10 at 22:43
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
1
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Changenode.nodeType = 3
tonode.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
5
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
1
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
|
show 11 more comments
I know you specifically asked for a collection, but if you just meant that informally and didn't care if they were all joined together into one big string, you can use:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
...with the first item being the DOM3 standard approach. Note however that innerText
appears to exclude script or style tag contents in implementations that support it (at least IE and Chrome) while textContent
includes them (in Firefox and Chrome).
1
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
add a comment |
Here's a modern Iterator
version of the fastest TreeWalker method:
function getTextNodesIterator(el) // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const next = () =>
const value = walker.nextNode();
return
value,
done: !value
;
;
walker[Symbol.iterator] = () => (next);
return walker;
Usage:
for (const textNode of getTextNodesIterator(document.body))
console.log(textNode)
But the loop might get stuck if you move the nodes around while looping.
This is safer:
function getTextNodes(el) // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode())
nodes.push(walker.currentNode);
return nodes;
add a comment |
document.deepText= function(hoo, fun)
var A= [], tem;
if(hoo)
hoo= hoo.firstChild;
while(hoo!= null)
if(hoo.nodeType== 3)
if(typeof fun== 'function')
tem= fun(hoo);
if(tem!= undefined) A[A.length]= tem;
else A[A.length]= hoo;
else A= A.concat(document.deepText(hoo, fun));
hoo= hoo.nextSibling;
return A;
/*
You can return an array of all the descendant text nodes of some parent element,
or you can pass it some function and do something (find or replace or whatever)
to the text in place.
This example returns the text of the non-whitespace textnodes in the body:
var A= document.deepText(document.body, function(t)
var tem= t.data;
return /S/.test(tem)? tem: undefined;
);
alert(A.join('n'))
*/
Handy for search and replace, highlighting and so on
add a comment |
var el1 = document.childNodes[0]
function get(node,ob)
ob = ob
var o = get(el1)
console.log(o)
add a comment |
Here's an alternative that's a bit more idiomatic and (hopefully) easier to understand.
function getText(node)
// recurse into each child node
if (node.hasChildNodes())
node.childNodes.forEach(getText);
// get content of each non-empty text node
else if (node.nodeType === Node.TEXT_NODE)
const text = node.textContent.trim();
if (text)
console.log(text); // do something
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2579666%2fgetelementsbytagname-equivalent-for-textnodes%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
Update:
I have outlined some basic performance tests for each of these 6 methods over 1000 runs. getElementsByTagName
is the fastest but it does a half-assed job, as it does not select all elements, but only one particular type of tag ( i think p
) and blindly assumes that its firstChild is a text element. It might be little flawed but its there for demonstration purpose and comparing its performance to TreeWalker
. Run the tests yourselves on jsfiddle to see the results.
- Using a TreeWalker
- Custom Iterative Traversal
- Custom Recursive Traversal
- Xpath query
- querySelectorAll
- getElementsByTagName
Let's assume for a moment that there is a method that allows you to get all Text
nodes natively. You would still have to traverse each resulting text node and call node.nodeValue
to get the actual text as you would do with any DOM Node. So the issue of performance is not with iterating through text nodes, but iterating through all nodes that are not text and checking their type. I would argue (based on the results) that TreeWalker
performs just as fast as getElementsByTagName
, if not faster (even with getElementsByTagName playing handicapped).
Ran each test 1000 times.
Method Total ms Average ms
--------------------------------------------------
document.TreeWalker 301 0.301
Iterative Traverser 769 0.769
Recursive Traverser 7352 7.352
XPath query 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212
Source for each method:
TreeWalker
function nativeTreeWalker()
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode())
textNodes.push(node.nodeValue);
Recursive Tree Traversal
function customRecursiveTreeWalker()
var result = [];
(function findTextNodes(current)
for(var i = 0; i < current.childNodes.length; i++)
var child = current.childNodes[i];
if(child.nodeType == 3)
result.push(child.nodeValue);
else
findTextNodes(child);
)(document.body);
Iterative Tree Traversal
function customIterativeTreeWalker()
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null)
if(node.nodeType == 3) /* Fixed a bug here. Thanks @theazureshadow */
result.push(node.nodeValue);
if(node.hasChildNodes())
node = node.firstChild;
else
while(node.nextSibling == null && node != root)
node = node.parentNode;
node = node.nextSibling;
querySelectorAll
function nativeSelector()
var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
var results = [];
var child;
for(var i = 0; i < elements.length; i++)
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3)
results.push(child.nodeValue);
getElementsByTagName (handicap)
function getElementsByTagName()
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++)
results.push(elements[i].childNodes[0].nodeValue);
XPath
function xpathSelector()
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext())
results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */
Also, you might find this discussion helpful - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
Interesting... DoescreateTreeWalker()
work on IE?
– levik
Apr 6 '10 at 22:43
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
1
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Changenode.nodeType = 3
tonode.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
5
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
1
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
|
show 11 more comments
Update:
I have outlined some basic performance tests for each of these 6 methods over 1000 runs. getElementsByTagName
is the fastest but it does a half-assed job, as it does not select all elements, but only one particular type of tag ( i think p
) and blindly assumes that its firstChild is a text element. It might be little flawed but its there for demonstration purpose and comparing its performance to TreeWalker
. Run the tests yourselves on jsfiddle to see the results.
- Using a TreeWalker
- Custom Iterative Traversal
- Custom Recursive Traversal
- Xpath query
- querySelectorAll
- getElementsByTagName
Let's assume for a moment that there is a method that allows you to get all Text
nodes natively. You would still have to traverse each resulting text node and call node.nodeValue
to get the actual text as you would do with any DOM Node. So the issue of performance is not with iterating through text nodes, but iterating through all nodes that are not text and checking their type. I would argue (based on the results) that TreeWalker
performs just as fast as getElementsByTagName
, if not faster (even with getElementsByTagName playing handicapped).
Ran each test 1000 times.
Method Total ms Average ms
--------------------------------------------------
document.TreeWalker 301 0.301
Iterative Traverser 769 0.769
Recursive Traverser 7352 7.352
XPath query 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212
Source for each method:
TreeWalker
function nativeTreeWalker()
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode())
textNodes.push(node.nodeValue);
Recursive Tree Traversal
function customRecursiveTreeWalker()
var result = [];
(function findTextNodes(current)
for(var i = 0; i < current.childNodes.length; i++)
var child = current.childNodes[i];
if(child.nodeType == 3)
result.push(child.nodeValue);
else
findTextNodes(child);
)(document.body);
Iterative Tree Traversal
function customIterativeTreeWalker()
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null)
if(node.nodeType == 3) /* Fixed a bug here. Thanks @theazureshadow */
result.push(node.nodeValue);
if(node.hasChildNodes())
node = node.firstChild;
else
while(node.nextSibling == null && node != root)
node = node.parentNode;
node = node.nextSibling;
querySelectorAll
function nativeSelector()
var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
var results = [];
var child;
for(var i = 0; i < elements.length; i++)
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3)
results.push(child.nodeValue);
getElementsByTagName (handicap)
function getElementsByTagName()
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++)
results.push(elements[i].childNodes[0].nodeValue);
XPath
function xpathSelector()
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext())
results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */
Also, you might find this discussion helpful - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
Interesting... DoescreateTreeWalker()
work on IE?
– levik
Apr 6 '10 at 22:43
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
1
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Changenode.nodeType = 3
tonode.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
5
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
1
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
|
show 11 more comments
Update:
I have outlined some basic performance tests for each of these 6 methods over 1000 runs. getElementsByTagName
is the fastest but it does a half-assed job, as it does not select all elements, but only one particular type of tag ( i think p
) and blindly assumes that its firstChild is a text element. It might be little flawed but its there for demonstration purpose and comparing its performance to TreeWalker
. Run the tests yourselves on jsfiddle to see the results.
- Using a TreeWalker
- Custom Iterative Traversal
- Custom Recursive Traversal
- Xpath query
- querySelectorAll
- getElementsByTagName
Let's assume for a moment that there is a method that allows you to get all Text
nodes natively. You would still have to traverse each resulting text node and call node.nodeValue
to get the actual text as you would do with any DOM Node. So the issue of performance is not with iterating through text nodes, but iterating through all nodes that are not text and checking their type. I would argue (based on the results) that TreeWalker
performs just as fast as getElementsByTagName
, if not faster (even with getElementsByTagName playing handicapped).
Ran each test 1000 times.
Method Total ms Average ms
--------------------------------------------------
document.TreeWalker 301 0.301
Iterative Traverser 769 0.769
Recursive Traverser 7352 7.352
XPath query 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212
Source for each method:
TreeWalker
function nativeTreeWalker()
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode())
textNodes.push(node.nodeValue);
Recursive Tree Traversal
function customRecursiveTreeWalker()
var result = [];
(function findTextNodes(current)
for(var i = 0; i < current.childNodes.length; i++)
var child = current.childNodes[i];
if(child.nodeType == 3)
result.push(child.nodeValue);
else
findTextNodes(child);
)(document.body);
Iterative Tree Traversal
function customIterativeTreeWalker()
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null)
if(node.nodeType == 3) /* Fixed a bug here. Thanks @theazureshadow */
result.push(node.nodeValue);
if(node.hasChildNodes())
node = node.firstChild;
else
while(node.nextSibling == null && node != root)
node = node.parentNode;
node = node.nextSibling;
querySelectorAll
function nativeSelector()
var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
var results = [];
var child;
for(var i = 0; i < elements.length; i++)
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3)
results.push(child.nodeValue);
getElementsByTagName (handicap)
function getElementsByTagName()
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++)
results.push(elements[i].childNodes[0].nodeValue);
XPath
function xpathSelector()
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext())
results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */
Also, you might find this discussion helpful - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
Update:
I have outlined some basic performance tests for each of these 6 methods over 1000 runs. getElementsByTagName
is the fastest but it does a half-assed job, as it does not select all elements, but only one particular type of tag ( i think p
) and blindly assumes that its firstChild is a text element. It might be little flawed but its there for demonstration purpose and comparing its performance to TreeWalker
. Run the tests yourselves on jsfiddle to see the results.
- Using a TreeWalker
- Custom Iterative Traversal
- Custom Recursive Traversal
- Xpath query
- querySelectorAll
- getElementsByTagName
Let's assume for a moment that there is a method that allows you to get all Text
nodes natively. You would still have to traverse each resulting text node and call node.nodeValue
to get the actual text as you would do with any DOM Node. So the issue of performance is not with iterating through text nodes, but iterating through all nodes that are not text and checking their type. I would argue (based on the results) that TreeWalker
performs just as fast as getElementsByTagName
, if not faster (even with getElementsByTagName playing handicapped).
Ran each test 1000 times.
Method Total ms Average ms
--------------------------------------------------
document.TreeWalker 301 0.301
Iterative Traverser 769 0.769
Recursive Traverser 7352 7.352
XPath query 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212
Source for each method:
TreeWalker
function nativeTreeWalker()
var walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
var textNodes = [];
while(node = walker.nextNode())
textNodes.push(node.nodeValue);
Recursive Tree Traversal
function customRecursiveTreeWalker()
var result = [];
(function findTextNodes(current)
for(var i = 0; i < current.childNodes.length; i++)
var child = current.childNodes[i];
if(child.nodeType == 3)
result.push(child.nodeValue);
else
findTextNodes(child);
)(document.body);
Iterative Tree Traversal
function customIterativeTreeWalker()
var result = [];
var root = document.body;
var node = root.childNodes[0];
while(node != null)
if(node.nodeType == 3) /* Fixed a bug here. Thanks @theazureshadow */
result.push(node.nodeValue);
if(node.hasChildNodes())
node = node.firstChild;
else
while(node.nextSibling == null && node != root)
node = node.parentNode;
node = node.nextSibling;
querySelectorAll
function nativeSelector()
var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
var results = [];
var child;
for(var i = 0; i < elements.length; i++)
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3)
results.push(child.nodeValue);
getElementsByTagName (handicap)
function getElementsByTagName()
var elements = document.getElementsByTagName("p");
var results = [];
for(var i = 0; i < elements.length; i++)
results.push(elements[i].childNodes[0].nodeValue);
XPath
function xpathSelector()
var xpathResult = document.evaluate(
"//*/text()",
document,
null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
var results = [], res;
while(res = xpathResult.iterateNext())
results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */
Also, you might find this discussion helpful - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
edited Jul 7 '12 at 0:19
answered Apr 5 '10 at 17:31
AnuragAnurag
119k30199250
119k30199250
Interesting... DoescreateTreeWalker()
work on IE?
– levik
Apr 6 '10 at 22:43
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
1
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Changenode.nodeType = 3
tonode.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
5
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
1
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
|
show 11 more comments
Interesting... DoescreateTreeWalker()
work on IE?
– levik
Apr 6 '10 at 22:43
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
1
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Changenode.nodeType = 3
tonode.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
5
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
1
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
Interesting... Does
createTreeWalker()
work on IE?– levik
Apr 6 '10 at 22:43
Interesting... Does
createTreeWalker()
work on IE?– levik
Apr 6 '10 at 22:43
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
I have gotten mixed results for each of the methods above in different browser - these results above are for Chrome. Firefox and Safari behave very differently. I don't have have access to IE unfortunately, but you could test these yourselves on IE to see if it works. As for browser optimization, I wouldn't worry about picking a different method for each browser as long as the differences are in order of tens of milliseconds or maybe even the low hundreds.
– Anurag
Apr 7 '10 at 0:29
1
1
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Change
node.nodeType = 3
to node.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
This is a really useful answer, but beware that the different methods return very different things. Many of them only get text nodes if they're the first child of their parent. Some of them can only get the text, while others can return actual text nodes with minor modifications. There is an error in Iterative Tree Traversal that may affect its performance. Change
node.nodeType = 3
to node.nodeType == 3
– theazureshadow
Jul 5 '12 at 17:40
5
5
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
I've made the tests equivalent and made a jsPerf: jsperf.com/text-node-traversal
– Tim Down
Apr 19 '13 at 10:02
1
1
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
Nice work @TimDown - that handicapped test was an eye-sore for a long time :) You should add it as an answer..
– Anurag
Apr 19 '13 at 19:02
|
show 11 more comments
I know you specifically asked for a collection, but if you just meant that informally and didn't care if they were all joined together into one big string, you can use:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
...with the first item being the DOM3 standard approach. Note however that innerText
appears to exclude script or style tag contents in implementations that support it (at least IE and Chrome) while textContent
includes them (in Firefox and Chrome).
1
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
add a comment |
I know you specifically asked for a collection, but if you just meant that informally and didn't care if they were all joined together into one big string, you can use:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
...with the first item being the DOM3 standard approach. Note however that innerText
appears to exclude script or style tag contents in implementations that support it (at least IE and Chrome) while textContent
includes them (in Firefox and Chrome).
1
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
add a comment |
I know you specifically asked for a collection, but if you just meant that informally and didn't care if they were all joined together into one big string, you can use:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
...with the first item being the DOM3 standard approach. Note however that innerText
appears to exclude script or style tag contents in implementations that support it (at least IE and Chrome) while textContent
includes them (in Firefox and Chrome).
I know you specifically asked for a collection, but if you just meant that informally and didn't care if they were all joined together into one big string, you can use:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
...with the first item being the DOM3 standard approach. Note however that innerText
appears to exclude script or style tag contents in implementations that support it (at least IE and Chrome) while textContent
includes them (in Firefox and Chrome).
answered Apr 1 '11 at 14:06
Brett ZamirBrett Zamir
9,67033055
9,67033055
1
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
add a comment |
1
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
1
1
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
Thanks - that's not what I wanted though. My needs call for being able to inspect them in-place as DOM objects (like finding their parents, etc)
– levik
Apr 21 '11 at 1:32
add a comment |
Here's a modern Iterator
version of the fastest TreeWalker method:
function getTextNodesIterator(el) // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const next = () =>
const value = walker.nextNode();
return
value,
done: !value
;
;
walker[Symbol.iterator] = () => (next);
return walker;
Usage:
for (const textNode of getTextNodesIterator(document.body))
console.log(textNode)
But the loop might get stuck if you move the nodes around while looping.
This is safer:
function getTextNodes(el) // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode())
nodes.push(walker.currentNode);
return nodes;
add a comment |
Here's a modern Iterator
version of the fastest TreeWalker method:
function getTextNodesIterator(el) // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const next = () =>
const value = walker.nextNode();
return
value,
done: !value
;
;
walker[Symbol.iterator] = () => (next);
return walker;
Usage:
for (const textNode of getTextNodesIterator(document.body))
console.log(textNode)
But the loop might get stuck if you move the nodes around while looping.
This is safer:
function getTextNodes(el) // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode())
nodes.push(walker.currentNode);
return nodes;
add a comment |
Here's a modern Iterator
version of the fastest TreeWalker method:
function getTextNodesIterator(el) // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const next = () =>
const value = walker.nextNode();
return
value,
done: !value
;
;
walker[Symbol.iterator] = () => (next);
return walker;
Usage:
for (const textNode of getTextNodesIterator(document.body))
console.log(textNode)
But the loop might get stuck if you move the nodes around while looping.
This is safer:
function getTextNodes(el) // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode())
nodes.push(walker.currentNode);
return nodes;
Here's a modern Iterator
version of the fastest TreeWalker method:
function getTextNodesIterator(el) // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const next = () =>
const value = walker.nextNode();
return
value,
done: !value
;
;
walker[Symbol.iterator] = () => (next);
return walker;
Usage:
for (const textNode of getTextNodesIterator(document.body))
console.log(textNode)
But the loop might get stuck if you move the nodes around while looping.
This is safer:
function getTextNodes(el) // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode())
nodes.push(walker.currentNode);
return nodes;
edited Sep 13 '18 at 3:16
answered Jun 13 '17 at 8:22
bfred.itbfred.it
15.1k66996
15.1k66996
add a comment |
add a comment |
document.deepText= function(hoo, fun)
var A= [], tem;
if(hoo)
hoo= hoo.firstChild;
while(hoo!= null)
if(hoo.nodeType== 3)
if(typeof fun== 'function')
tem= fun(hoo);
if(tem!= undefined) A[A.length]= tem;
else A[A.length]= hoo;
else A= A.concat(document.deepText(hoo, fun));
hoo= hoo.nextSibling;
return A;
/*
You can return an array of all the descendant text nodes of some parent element,
or you can pass it some function and do something (find or replace or whatever)
to the text in place.
This example returns the text of the non-whitespace textnodes in the body:
var A= document.deepText(document.body, function(t)
var tem= t.data;
return /S/.test(tem)? tem: undefined;
);
alert(A.join('n'))
*/
Handy for search and replace, highlighting and so on
add a comment |
document.deepText= function(hoo, fun)
var A= [], tem;
if(hoo)
hoo= hoo.firstChild;
while(hoo!= null)
if(hoo.nodeType== 3)
if(typeof fun== 'function')
tem= fun(hoo);
if(tem!= undefined) A[A.length]= tem;
else A[A.length]= hoo;
else A= A.concat(document.deepText(hoo, fun));
hoo= hoo.nextSibling;
return A;
/*
You can return an array of all the descendant text nodes of some parent element,
or you can pass it some function and do something (find or replace or whatever)
to the text in place.
This example returns the text of the non-whitespace textnodes in the body:
var A= document.deepText(document.body, function(t)
var tem= t.data;
return /S/.test(tem)? tem: undefined;
);
alert(A.join('n'))
*/
Handy for search and replace, highlighting and so on
add a comment |
document.deepText= function(hoo, fun)
var A= [], tem;
if(hoo)
hoo= hoo.firstChild;
while(hoo!= null)
if(hoo.nodeType== 3)
if(typeof fun== 'function')
tem= fun(hoo);
if(tem!= undefined) A[A.length]= tem;
else A[A.length]= hoo;
else A= A.concat(document.deepText(hoo, fun));
hoo= hoo.nextSibling;
return A;
/*
You can return an array of all the descendant text nodes of some parent element,
or you can pass it some function and do something (find or replace or whatever)
to the text in place.
This example returns the text of the non-whitespace textnodes in the body:
var A= document.deepText(document.body, function(t)
var tem= t.data;
return /S/.test(tem)? tem: undefined;
);
alert(A.join('n'))
*/
Handy for search and replace, highlighting and so on
document.deepText= function(hoo, fun)
var A= [], tem;
if(hoo)
hoo= hoo.firstChild;
while(hoo!= null)
if(hoo.nodeType== 3)
if(typeof fun== 'function')
tem= fun(hoo);
if(tem!= undefined) A[A.length]= tem;
else A[A.length]= hoo;
else A= A.concat(document.deepText(hoo, fun));
hoo= hoo.nextSibling;
return A;
/*
You can return an array of all the descendant text nodes of some parent element,
or you can pass it some function and do something (find or replace or whatever)
to the text in place.
This example returns the text of the non-whitespace textnodes in the body:
var A= document.deepText(document.body, function(t)
var tem= t.data;
return /S/.test(tem)? tem: undefined;
);
alert(A.join('n'))
*/
Handy for search and replace, highlighting and so on
edited Jan 14 '17 at 7:36
user663031
answered Apr 5 '10 at 17:59
kennebeckennebec
80.2k2387117
80.2k2387117
add a comment |
add a comment |
var el1 = document.childNodes[0]
function get(node,ob)
ob = ob
var o = get(el1)
console.log(o)
add a comment |
var el1 = document.childNodes[0]
function get(node,ob)
ob = ob
var o = get(el1)
console.log(o)
add a comment |
var el1 = document.childNodes[0]
function get(node,ob)
ob = ob
var o = get(el1)
console.log(o)
var el1 = document.childNodes[0]
function get(node,ob)
ob = ob
var o = get(el1)
console.log(o)
answered Oct 31 '16 at 22:51
Mankament GraMankament Gra
656
656
add a comment |
add a comment |
Here's an alternative that's a bit more idiomatic and (hopefully) easier to understand.
function getText(node)
// recurse into each child node
if (node.hasChildNodes())
node.childNodes.forEach(getText);
// get content of each non-empty text node
else if (node.nodeType === Node.TEXT_NODE)
const text = node.textContent.trim();
if (text)
console.log(text); // do something
add a comment |
Here's an alternative that's a bit more idiomatic and (hopefully) easier to understand.
function getText(node)
// recurse into each child node
if (node.hasChildNodes())
node.childNodes.forEach(getText);
// get content of each non-empty text node
else if (node.nodeType === Node.TEXT_NODE)
const text = node.textContent.trim();
if (text)
console.log(text); // do something
add a comment |
Here's an alternative that's a bit more idiomatic and (hopefully) easier to understand.
function getText(node)
// recurse into each child node
if (node.hasChildNodes())
node.childNodes.forEach(getText);
// get content of each non-empty text node
else if (node.nodeType === Node.TEXT_NODE)
const text = node.textContent.trim();
if (text)
console.log(text); // do something
Here's an alternative that's a bit more idiomatic and (hopefully) easier to understand.
function getText(node)
// recurse into each child node
if (node.hasChildNodes())
node.childNodes.forEach(getText);
// get content of each non-empty text node
else if (node.nodeType === Node.TEXT_NODE)
const text = node.textContent.trim();
if (text)
console.log(text); // do something
answered Mar 9 at 3:16
jtschoonhovenjtschoonhoven
4671411
4671411
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2579666%2fgetelementsbytagname-equivalent-for-textnodes%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown