我试图访问给定元素内的所有文本节点,以便我可以隔离单词并将它们包装在跨度中。
TreeWalker
似乎是这项工作的 API,但我发现它非常不直观。既没有spec http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html也不MDN 参考 https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker(通常非常擅长解释神秘的 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 protected] /cdn-cgi/l/email-protection">[email protected] /cdn-cgi/l/email-protection</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 protected] /cdn-cgi/l/email-protection">[email protected] /cdn-cgi/l/email-protection</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 protected] /cdn-cgi/l/email-protection">[email protected] /cdn-cgi/l/email-protection</a> for submissions & other enquiries.
我缺少什么?
我缺少什么?
node.parentNode.removeChild(node)
问题是 - 你正在从 DOM 中删除当前节点,所以 walker 会发现没有.nextNode()
从那里。
您应该在删除节点之前推进步行器,或者只是不删除它而是缩小其内容(到移出所有单词后剩下的内容)。
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 protected] /cdn-cgi/l/email-protection">email @ example.com</a> for submissions & other enquiries.
Notice that the correct filter is NodeFilter.SHOW_TEXT
, not .TEXT_NODE
, and that in older browser the four arguments are not optional.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)