我正在尝试获取范围对象中的所有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*/;
我一直在考虑过去几个小时的方法,并想出了这个:
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; };
但是,当结束节点是起始节点的父节点时,它将返回页面上的所有内容.我敢肯定我忽略了一些明显的东西?或者可能以完全错误的方式进行.
MDC/DOM /范围
如果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); };
并在声明中:
while (startNode = getNextNode(startNode, false , endNode));
这是我想出来解决这个问题的一个实现:
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; }