Ann*_*nan 16 javascript dom traversal range
我正在尝试获取范围对象中的所有DOM节点,这样做的最佳方法是什么?
var selection = window.getSelection(); //what the user has selected
var range = selection.getRangeAt(0); //the first range of the selection
var startNode = range.startContainer;
var endNode = range.endContainer;
var allNodes = /*insert magic*/;
Run Code Online (Sandbox Code Playgroud)
我一直在考虑过去几个小时的方法,并想出了这个:
var getNextNode = function(node, skipChildren){
//if there are child nodes and we didn't come from a child node
if (node.firstChild && !skipChildren) {
return node.firstChild;
}
if (!node.parentNode){
return null;
}
return node.nextSibling
|| getNextNode(node.parentNode, true);
};
var getNodesInRange = function(range){
var startNode = range.startContainer.childNodes[range.startOffset]
|| range.startContainer;//it's a text node
var endNode = range.endContainer.childNodes[range.endOffset]
|| range.endContainer;
if (startNode == endNode && startNode.childNodes.length === 0) {
return [startNode];
};
var nodes = [];
do {
nodes.push(startNode);
}
while ((startNode = getNextNode(startNode))
&& (startNode != endNode));
return nodes;
};
Run Code Online (Sandbox Code Playgroud)
但是,当结束节点是起始节点的父节点时,它将返回页面上的所有内容.我敢肯定我忽略了一些明显的东西?或者可能以完全错误的方式进行.
Ste*_*röm 11
如果getNextNode是父节点,则它将以递归方式跳过所需的endNode.
改为在getNextNode中执行条件中断检查:
var getNextNode = function(node, skipChildren, endNode){
//if there are child nodes and we didn't come from a child node
if (endNode == node) {
return null;
}
if (node.firstChild && !skipChildren) {
return node.firstChild;
}
if (!node.parentNode){
return null;
}
return node.nextSibling
|| getNextNode(node.parentNode, true, endNode);
};
Run Code Online (Sandbox Code Playgroud)
并在声明中:
while (startNode = getNextNode(startNode, false , endNode));
Run Code Online (Sandbox Code Playgroud)
小智 11
这是我想出来解决这个问题的一个实现:
function getNextNode(node)
{
if (node.firstChild)
return node.firstChild;
while (node)
{
if (node.nextSibling)
return node.nextSibling;
node = node.parentNode;
}
}
function getNodesInRange(range)
{
var start = range.startContainer;
var end = range.endContainer;
var commonAncestor = range.commonAncestorContainer;
var nodes = [];
var node;
// walk parent nodes from start to common ancestor
for (node = start.parentNode; node; node = node.parentNode)
{
nodes.push(node);
if (node == commonAncestor)
break;
}
nodes.reverse();
// walk children and siblings from start until end is found
for (node = start; node; node = getNextNode(node))
{
nodes.push(node);
if (node == end)
break;
}
return nodes;
}
Run Code Online (Sandbox Code Playgroud)