4

在Javascript中,我想确定一个元素,比如一个A元素,是否存在于给定的范围/文本范围内。目的是确定用户的当前选择是否包含链接。我正在构建一个富文本编辑器控件。

范围对象有一个 commonAncestorContainer (W3C) 或 parentElement() (Microsoft) 方法,它返回范围内所有元素的最接近的公共祖先。但是,在此元素内部查找元素是A行不通的,因为这个共同的祖先也可能包含不在范围内的元素,因为范围可以通过父级开始或结束。

您将如何实现这一目标?

4

5 回答 5

5

selection.containsNode 怎么样? https://developer.mozilla.org/en/DOM/Selection/containsNode

就像是:

var selection = window.getSelection();
var range = selection.getRangeAt(0);
var result = $('a', range.commonAncestorContainer).filter(function() {
  return selection.containsNode(this);
});
console.log(result);
于 2011-05-19T08:12:17.350 回答
3

我最终采用了这样的解决方案:

        var findinselection = function(tagname, container) {
            var
                i, len, el,
                rng = getrange(),
                comprng,
                selparent;
            if (rng) {
                selparent = rng.commonAncestorContainer || rng.parentElement();
                // Look for an element *around* the selected range
                for (el = selparent; el !== container; el = el.parentNode) {
                    if (el.tagName && el.tagName.toLowerCase() === tagname) {
                        return el;
                    }
                }
                // Look for an element *within* the selected range
                if (!rng.collapsed && (rng.text === undefined || rng.text) &&
                    selparent.getElementsByTagName) {
                    el = selparent.getElementsByTagName(tagname);
                    comprng = document.createRange ?
                        document.createRange() : document.body.createTextRange();
                    for (i = 0, len = el.length; i < len; i++) {

                        // determine if element el[i] is within the range
                        if (document.createRange) { // w3c
                            comprng.selectNodeContents(el[i]);
                            if (rng.compareBoundaryPoints(Range.END_TO_START, comprng) < 0 &&
                                rng.compareBoundaryPoints(Range.START_TO_END, comprng) > 0) {
                                return el[i];
                            }
                        }
                        else { // microsoft
                            comprng.moveToElementText(el[i]);
                            if (rng.compareEndPoints("StartToEnd", comprng) < 0 &&
                                rng.compareEndPoints("EndToStart", comprng) > 0) {
                                return el[i];
                            }
                        }
                    }
                }
            }
        };

其中 getrange() 是我的另一个函数,用于获取当前选择作为范围对象。

要使用,请像这样称呼它

var link = findselection('a', editor);

其中 editor 是 contenteditable 元素,或设计模式 iframe 中的主体。

于 2011-05-25T04:13:46.940 回答
2

这对跨浏览器来说有点痛苦。你可以使用我的Rangy库,这对于这个任务来说可能有点过头了,但它确实使它更直接并且适用于所有主要浏览器。以下代码假设只选择了一个 Range:

var sel = rangy.getSelection();
if (sel.rangeCount) {
    var range = sel.getRangeAt(0);
    var links = range.getNodes([1], function(node) {
        return node.tagName.toLowerCase() == "a" && range.containsNode(node);
    });
}
于 2011-05-19T09:45:39.063 回答
0

我正在使用适用于 IE / Chrome / FF 的代码:(我正在使用它来选择表中的行 <tr>)

// yourLink is the DOM element you want to check
var selection = window.getSelection().getRangeAt(0)
var node = document.createRange()
node.selectNode(yourLink)
var s2s = selection.compareBoundaryPoints(Range.START_TO_END, node)
var s2e = selection.compareBoundaryPoints(Range.START_TO_START, node)
var e2s = selection.compareBoundaryPoints(Range.END_TO_START, node)
var e2e = selection.compareBoundaryPoints(Range.END_TO_END, node)
if ((s2s != s2e) || (e2s != e2e) || (s2s!=e2e))
    console.log("your node is inside selection")
于 2015-05-07T14:07:52.360 回答
0

对于搜索元素的范围,我写的内容很有用。(但仅适用于这种情况!)

首先,我编写了一个函数,它返回在范围内找到的节点:getNodeFromRange(rangeObject)。使用这个函数,编写返回所需节点的函数已经很容易了:findTagInRange(tagName)。

function getNodeFromRange(range) {
    if(range.endContainer.nodeType==Node.ELEMENT_NODE) {
        return range.endContainer;
    }
    if(range.endContainer.nodeType==Node.TEXT_NODE) {
        return range.endContainer.parentNode;
    }
    else {
        // the 'startContainer' it isn't on an Element (<p>, <div>, etc...)
        return;
    }
}

function findTagInRange(tagName, range) {
    var node = getNodeFromRange(range);
    if(node && typeof(node.tagName)!='undefiend' && node.tagName.toLowerCase()==tagName.toLowerCase()) {
        return $(node);
    }
    return;
}

然后我可以按如下方式使用它:

var link = findTagInRange('A', range);

我看到了你已经解决的范围的确定。:)

于 2019-06-14T08:00:49.937 回答