我正在尝试编写一个辅助函数,将选择范围扩展到range.canSurroundContents() === true
的最小可能范围。
在开始这个之前,Rangy库中是否有任何方法可以解决这个问题?
答案 0 :(得分:2)
这是问题中指定的问题:
我正在尝试编写一个辅助函数,将选择范围扩展到range.canSurroundContents()=== true的最小可能范围。
这是一个解决方案:
// Provides the depth of ``descendant`` relative to ``ancestor``
function getDepth(ancestor, descendant) {
var ret = 0;
while (descendant !== ancestor) {
ret++;
descendant = descendant.parentNode;
if (!descendant)
throw new Error("not a descendant of ancestor!");
}
return ret;
}
function smallestExpansion() {
var range = rangy.getSelection().getRangeAt(0);
if (range.canSurroundContents()) return;
var common = range.commonAncestorContainer;
var start_depth = getDepth(common, range.startContainer);
var end_depth = getDepth(common, range.endContainer);
while(!range.canSurroundContents()) {
// In the following branches, we cannot just decrement the depth variables because the setStartBefore/setEndAfter may move the start or end of the range more than one level relative to ``common``. So we need to recompute the depth.
if (start_depth > end_depth) {
range.setStartBefore(range.startContainer.parentNode);
start_depth = getDepth(common, range.startContainer);
}
else {
range.setEndAfter(range.endContainer.parentNode);
end_depth = getDepth(common, range.endContainer);
}
}
}
这是一个fiddle来说明。我忽略了选择可能有多个范围的情况。
更新:我发布的第一个代码在方法上是悲观的,因为它过快地用于共同的祖先。更新的代码逐渐将范围的末尾移动到父元素,直到选择使得节点可以包围范围的内容(即range.canSurroundContents()
是true
)。所以在这样的情况下:
<p>This i|s a <strong>te|st</strong> for selecting text.</p>
其中|
符号标记初始区域的开头和结尾。更新的代码将以覆盖s a <strong>test</strong>
的区域结束,这足以满足要求(如果您愿意,可以将区域包装在<span>
元素中)。旧版本将用于选择所有段落。
我相信通过考虑getDepth
和setStartBefore
如何移动范围的结尾,我可以避免在每次迭代时调用setEndAfter
,但我并没有对此优化感到困扰。
答案 1 :(得分:0)
工作解决方案找到最小共同祖先,并向后工作以尝试使其变小。
var sel = rangy.getSelection(),
range = sel.getRangeAt(0),
startNode = range.startContainer,
endNode = range.endContainer,
commonAncestor = getCommonAncestor(range);
range = getSmallestPossibleExpansion(range, commonAncestor, startNode, endNode);
function getRangeContainerElement(range) {
var container = range.commonAncestorContainer;
if (container.nodeType == 3) {
container = container.parentNode;
}
return container;
}
function getChildOfAncestor(node, ancestor) {
if (node.parentNode === ancestor) return node;
return getChildOfAncestor(node.parentNode, ancestor);
}
function getSmallestPossibleExpansion(range, commonAncestor, startNode, endNode) {
if (startNode === endNode) {
if (!range.canSurroundContents()) {
throw new Error("Sanity Check: startNode = endNOde. This should mean canSurroundContents() == true!");
}
} else {
if (commonAncestor !== endNode) {
//expand range of endpoint (to right) by including the 'anscestorOrSelf' from endNode that is the child of commonAncestor
range.setEndAfter(getChildOfAncestor(endNode, commonAncestor));
}
if (commonAncestor !== startNode) { //NOTE: NOT ELSE IF!
//expand range of startNode (to left) by including the 'anscestorOrSelf' from startNode that is the child of commonAncestor
range.setStartBefore(getChildOfAncestor(startNode, commonAncestor));
}
}
return range;
}
甜。