DOM TreeWalker返回所有文本节点
DOM TreeWalker to return all text nodes
我试图访问给定元素中的所有文本节点,以便我可以隔离单词并将它们包装在span中。
TreeWalker
似乎是这项工作的API,但我发现它非常不直观。在我看来,规范和MDN参考(通常很擅长解释神秘的DOM api)都是不证自明的。
我的第一个假设是,所有我需要传递的是正确的过滤器作为第二个参数-像document.createTreeWalker( element, NodeFilter.TEXT_NODE )
。但这似乎在遇到非文本节点时就会停止:
wordWrap( document.body )
function wordWrap( element ){
var nodes = document.createTreeWalker( element, NodeFilter.TEXT_NODE )
var node
var text
var word
while( node = nodes.nextNode() ){
text = node.nodeValue.replace( /(^'s+|'s+$)/, '' ).split( /'s+/g )
while( text.length ){
word = document.createElement( 'span' )
word.className = 'word'
word.innerText = text.shift()
node.parentNode.insertBefore( word, node )
if( text.length )
node.parentNode.insertBefore( document.createTextNode( ' ' ), node )
}
node.parentNode.removeChild( node )
}
}
.word {
background: #fee;
padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email@example.com</a> for submissions & other enquiries.
所以我认为这是一个使用TreeWalker
的第三个过滤器参数的机会,以及NodeFilter
上的额外属性。如果一个过滤器方法的有效返回值是FILTER_ACCEPT
, FILTER_REJECT
&FILTER_SKIP
,那么我推断,通过在第二个参数中接受元素节点和文本节点,我可以指定应该接受文本节点,而跳过其他节点。但这似乎给出了相同的结果-锚内或锚后没有文本节点:
wordWrap( document.body )
function wordWrap( element ){
var nodes = document.createTreeWalker(
element,
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,
{ acceptNode : function( node ){
if( node.nodeType === node.TEXT_NODE )
return NodeFilter.FILTER_ACCEPT
else
return NodeFilter.FILTER_SKIP
} }
)
var node
var text
var word
while( node = nodes.nextNode() ){
text = node.nodeValue.replace( /(^'s+|'s+$)/, '' ).split( /'s+/g )
while( text.length ){
word = document.createElement( 'span' )
word.className = 'word'
word.innerText = text.shift()
node.parentNode.insertBefore( word, node )
if( text.length )
node.parentNode.insertBefore( document.createTextNode( ' ' ), node )
}
node.parentNode.removeChild( node )
}
}
.word {
background: #fee;
padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email@example.com</a> for submissions & other enquiries.
至此,我确信使用DOM1方法递归地遍历树会更容易,如以下代码片段所示:
wordWrap( document.body )
function wordWrap( element ){
textNodes( element ).forEach( function( node ){
var text = node.nodeValue.split( /'s+/g )
var word
while( text.length ){
word = document.createElement( 'span' )
word.className = 'word'
word.innerText = text.shift()
node.parentNode.insertBefore( word, node )
if( text.length )
node.parentNode.insertBefore( document.createTextNode( ' ' ), node )
}
node.parentNode.removeChild( node )
} )
}
function textNodes( element ){
var nodes = []
Array.prototype.forEach.call( element.childNodes, function( child ){
if( child.nodeType === child.TEXT_NODE )
nodes = nodes.concat( child )
else if( child.nodeType === child.ELEMENT_NODE )
nodes = nodes.concat( textNodes( child ) )
} )
return nodes
}
.word {
background: #fee;
padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email@example.com</a> for submissions & other enquiries.
我错过了什么?
我错过了什么?
node.parentNode.removeChild(node)
是问题所在-您正在从DOM中删除当前节点,因此walker将从那里找不到.nextNode()
。
您应该在删除节点之前推进walker,或者只是不删除它,而是缩小其内容(当您移出所有单词时剩下的内容)。
wordWrap(document.body);
function wordWrap( element ){
var nodes = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, null);
var node;
while (node = nodes.nextNode()) {
var p = node.parentNode;
var text = node.nodeValue;
var m;
while(m = text.match(/^('s*)('S+)/)) {
text = text.slice(m[0].length);
p.insertBefore(document.createTextNode(m[1]), node);
var word = p.insertBefore(document.createElement('span'), node);
word.appendChild(document.createTextNode(m[2]));
word.className = 'word';
}
node.nodeValue = text;
}
}
.word {
background: #faa;
padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email @ example.com</a> for submissions & other enquiries.
注意,正确的过滤器是NodeFilter.SHOW_TEXT
,而不是.TEXT_NODE
,并且在较旧的浏览器中,这四个参数不是可选的。
相关文章:
- Javascript,将文本添加到具有现有文本节点的元素中
- 拆分文本节点
- 使用TreeWalker检索非Javascript文本节点
- jquery在元素中查找文本节点,并使用标记进行连接和包装
- JavaScript 文本节点属性
- 获取文本节点的宽度
- 如何将由
分隔的文本节点与它们自己的标记包装起来
- 如何返回jQuery对象中的文本节点
- 包装和打开jquery后合并文本节点
- 有没有一种方法可以在javascript中为文本节点添加属性
- 使用文本节点打印段落
- 计算文本节点中的字母数
- 正则表达式:仅在标记中匹配文本节点
- "“错误”;导致故障的文本节点
- 正在创建文本节点
- jQuery,如何测试一个变量是一个文本节点,不包含任何标记
- 使用 casperjs 抓取文本节点的最快方法
- 如何在文本节点中保留空格
- 如何获取文档片段中的所有文本节点
- 选择“相邻同级”而不干预文本节点