在JavaScript中实现富文本编辑器时,我需要对选定范围内的每个文本节点进行一些更改。 Range对象提供了用于获取选定范围的startContainer
,endContainer
,startOffset
和endOffset
的接口(interface)。如何遍历之间的每个DOM节点?
var selection = window.getSelection();
var range = selection.getRange(0);
// How can I iterate over every node within the range?
最佳答案
如建议的那样,您可以使用NodeIterator
进入range.commonAncestorContainer
。
这是一个片段:
var _iterator = document.createNodeIterator(
range.commonAncestorContainer,
NodeFilter.SHOW_ALL, // pre-filter
{
// custom filter
acceptNode: function (node) {
return NodeFilter.FILTER_ACCEPT;
}
}
);
var _nodes = [];
while (_iterator.nextNode()) {
if (_nodes.length === 0 && _iterator.referenceNode !== range.startContainer) continue;
_nodes.push(_iterator.referenceNode);
if (_iterator.referenceNode === range.endContainer) break;
}
您应该使用
NodeFilter.SHOW_ALL
,因为您的范围可以包含多个nodeTypes。如果知道选择的内容,则可以检查this reference以正确选择NodeFilter
。编辑:我也想指出document.createTreeWalker()。
关键区别在于
document.createTreeWalker()
允许您的acceptNode
过滤器返回具有真正差异的NodeFilter.FILTER_REJECT
和NodeFilter.FILTER_SKIP
。从NodeFilter docs引用:
PS:的
NodeFilter.FILTER_REJECT
的NodeFilter.acceptNode()文档不正确。