0

我正在编写一个模块,它应该允许用户选择 HTML 文档的一部分。为了让内部工作正常,我将Range选择扩展为有效的 HTML 片段。

对于 B 是 AI 的后代的情况,找到 B 的祖先,它是 A 的孩子,并希望使用 setEndAfter 将范围设置为在该节点之后结束。这就是我现在所拥有的:

var closestChild = function (node, descendant) {
    var parent;
    if (descendant.parentElement) {
        parent = descendant.parentElement;
        if ( node === parent ) {
            return descendant;
        }
        return closestChild(node, parent);
    }
    return false;
}

var legalRange = function (range) {
        var newRange = range.cloneRange(),
            child;
        if (range.startContainer === range.endContainer) {
            return newRange;
        }
        child = closestChild(range.startContainer.parentElement, range.endContainer.parentElement);
        if (child) {
            newRange.setEndAfter(child);
            return newRange;
        } 
        return null;
};

INVALID_NODE_TYPE_ERR: DOM Range Exception 2但是当我尝试设置终点时,这会引发 。我也尝试使用 parentNode 而不是 parentElement 并引发相同的异常。如果我使用 setEnd(),这不是问题。我应该传递什么类型的节点来执行此操作。

PS:事实证明,代码在 FireFox 中有效,所以我现在的问题是 Safari 和 Chrome。

4

2 回答 2

1

我找到了解决方案。当我设置我的测试用例时,我没有将元素添加到文档中。如果节点不是文档的一部分,Chrome 和 Safari 在使用 setEndAfter 时似乎将节点视为无效。

于 2012-09-06T09:23:30.190 回答
0

正如 Eivind 所回答的,问题在于用于设置范围位置的节点未附加到文档。因此,一种解决方案是在设置范围位置之前附加它。

如果由于某种原因无法将节点附加到 DOM,另一种解决方案是使用setStart()andsetEnd()代替。

// Instead of `range.setStartBefore(node)`
var parent = node.parent;
range.setStart(parent, Array.from(parent.childNodes).indexOf(node))

// Instead of `range.setStartAfter(node)`
var parent = node.parent;
range.setStart(parent, Array.from(parent.childNodes).indexOf(node) + 1)

// Instead of `range.setEndBefore(node)`
var parent = node.parent;
range.setEnd(parent, Array.from(parent.childNodes).indexOf(node))

// Instead of `range.setEndAfter(node)`
var parent = node.parent;
range.setEnd(parent, Array.from(parent.childNodes).indexOf(node) + 1)

注意:Array.from(arrayLike)在 Internet Explorer <= 11 中不支持。使用Array.prototype.slice.call(arrayLike)而不是您需要 IE 支持。

于 2016-04-01T15:00:48.027 回答