如何遍历javascript中选定范围内的每个节点?
How to iterate over every node in a selected range in javascript?
在 javascript 中实现富文本编辑器时,我需要对选定范围内的每个文本节点应用一些更改。 Range 对象提供了获取所选范围的 startContainer
、endContainer
、startOffset
、endOffset
的接口。我如何遍历中间的每个 DOM 节点?
var selection = window.getSelection();
var range = selection.getRange(0);
// How can I iterate over every node within the range?
range.commonAncestorContainer
将为您提供包含该范围的节点。如果它给你一个文本节点,那么这是你范围内的唯一节点。
如果它给你一个元素,你可以使用NodeIterator
,或el.querySelectorAll('*')
来获取其中的节点。
并非所有这些都在您的范围内,因此请使用 range.intersectsNode(el)
进行确认。
根据提示,您可以使用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. If you know what you are selecting, you can check this reference 以正确选择 NodeFilter
。
编辑:我也想指出document.createTreeWalker()。
主要区别在于 document.createTreeWalker()
允许您的 acceptNode
过滤器 return NodeFilter.FILTER_REJECT
和 NodeFilter.FILTER_SKIP
具有真正的区别。
FILTER_REJECT:
Value to be returned by the NodeFilter.acceptNode() method when a node should be rejected. For TreeWalker, child nodes are also rejected. For NodeIterator, this flag is synonymous with FILTER_SKIP.
Ps: NodeFilter.FILTER_REJECT
的 NodeFilter.acceptNode() 文档不正确。
在 javascript 中实现富文本编辑器时,我需要对选定范围内的每个文本节点应用一些更改。 Range 对象提供了获取所选范围的 startContainer
、endContainer
、startOffset
、endOffset
的接口。我如何遍历中间的每个 DOM 节点?
var selection = window.getSelection();
var range = selection.getRange(0);
// How can I iterate over every node within the range?
range.commonAncestorContainer
将为您提供包含该范围的节点。如果它给你一个文本节点,那么这是你范围内的唯一节点。
如果它给你一个元素,你可以使用NodeIterator
,或el.querySelectorAll('*')
来获取其中的节点。
并非所有这些都在您的范围内,因此请使用 range.intersectsNode(el)
进行确认。
根据提示,您可以使用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. If you know what you are selecting, you can check this reference 以正确选择 NodeFilter
。
编辑:我也想指出document.createTreeWalker()。
主要区别在于 document.createTreeWalker()
允许您的 acceptNode
过滤器 return NodeFilter.FILTER_REJECT
和 NodeFilter.FILTER_SKIP
具有真正的区别。
FILTER_REJECT:
Value to be returned by the NodeFilter.acceptNode() method when a node should be rejected. For TreeWalker, child nodes are also rejected. For NodeIterator, this flag is synonymous with FILTER_SKIP.
Ps: NodeFilter.FILTER_REJECT
的 NodeFilter.acceptNode() 文档不正确。