在 JavaScript 中查找两个 DOM 节点的第一个公共父节点的最佳方法是什么?

发布于 2024-08-25 16:28:38 字数 249 浏览 11 评论 0 原文

我的问题正是如此,但在上下文中我想检查选择对象,比较锚节点和焦点节点,如果它们不同,则找到第一个公共父元素。

var selected = window.getSelection();
var anchor = selection.anchorNode;
var focus = selection.focusNode;

if ( anchor != focus ) {
   // find common parent...
}

My question is exactly that but in context I want to examine the selection object, compare the anchorNode and focusNode and if they are different then find the first common parent element.

var selected = window.getSelection();
var anchor = selection.anchorNode;
var focus = selection.focusNode;

if ( anchor != focus ) {
   // find common parent...
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

徒留西风 2024-09-01 16:28:38

由于这个问题和接受的答案非常过时,我建议使用更现代的 DOM API,范围

function findFirstCommonAncestor(nodeA, nodeB) {
    let range = new Range();
    range.setStart(nodeA, 0);
    range.setEnd(nodeB, 0);
    // There's a compilication, if nodeA is positioned after
    // nodeB in the document, we created a collapsed range.
    // That means the start and end of the range are at the
    // same position. In that case `range.commonAncestorContainer`
    // would likely just be `nodeB.parentNode`.
    if(range.collapsed) {
        // The old switcheroo does the trick.
        range.setStart(nodeB, 0);
        range.setEnd(nodeA, 0);
    }
    return range.commonAncestorContainer;
}

Since this question and accepted answer are very dated, I'd like to suggest using a more modern DOM API, Range:

function findFirstCommonAncestor(nodeA, nodeB) {
    let range = new Range();
    range.setStart(nodeA, 0);
    range.setEnd(nodeB, 0);
    // There's a compilication, if nodeA is positioned after
    // nodeB in the document, we created a collapsed range.
    // That means the start and end of the range are at the
    // same position. In that case `range.commonAncestorContainer`
    // would likely just be `nodeB.parentNode`.
    if(range.collapsed) {
        // The old switcheroo does the trick.
        range.setStart(nodeB, 0);
        range.setEnd(nodeA, 0);
    }
    return range.commonAncestorContainer;
}
宣告ˉ结束 2024-09-01 16:28:38

我会尝试这样的事情,假设没有 JS 库:

function findFirstCommonAncestor(nodeA, nodeB, ancestorsB) {
    var ancestorsB = ancestorsB || getAncestors(nodeB);
    if(ancestorsB.length == 0) return null;
    else if(ancestorsB.indexOf(nodeA) > -1) return nodeA;
    else if(nodeA == document) return null;
    else return findFirstCommonAncestor(nodeA.parentNode, nodeB, ancestorsB);
}

使用这个实用程序:

function getAncestors(node) {
    if(node != document) return [node].concat(getAncestors(node.parentNode));
    else return [node];
}

if(Array.prototype.indexOf === undefined) {
    Array.prototype.indexOf = function(element) {
        for(var i=0, l=this.length; i<l; i++) {
            if(this[i] == element) return i;
        }
        return -1;
    };
}

然后你可以调用findFirstCommonAncestor(myElementA,myElementB)。

I would try something like this, assuming no JS library:

function findFirstCommonAncestor(nodeA, nodeB, ancestorsB) {
    var ancestorsB = ancestorsB || getAncestors(nodeB);
    if(ancestorsB.length == 0) return null;
    else if(ancestorsB.indexOf(nodeA) > -1) return nodeA;
    else if(nodeA == document) return null;
    else return findFirstCommonAncestor(nodeA.parentNode, nodeB, ancestorsB);
}

using this utilities:

function getAncestors(node) {
    if(node != document) return [node].concat(getAncestors(node.parentNode));
    else return [node];
}

if(Array.prototype.indexOf === undefined) {
    Array.prototype.indexOf = function(element) {
        for(var i=0, l=this.length; i<l; i++) {
            if(this[i] == element) return i;
        }
        return -1;
    };
}

Then you can call findFirstCommonAncestor(myElementA, myElementB).

抱猫软卧 2024-09-01 16:28:38

这种方式相当简单:

var fp = $(focus).parents();
var ap = $(anchor).parents();
for (var i=0; i<ap.length; i++) {
  if (fp.index(ap[i]) != -1) {
    // common parent
  }
}

循环遍历一个的 parents()元素并使用 parents() 中>index() 直到找到匹配项(或未找到匹配项)。

This way is fairly straightforward:

var fp = $(focus).parents();
var ap = $(anchor).parents();
for (var i=0; i<ap.length; i++) {
  if (fp.index(ap[i]) != -1) {
    // common parent
  }
}

Loop through the parents() of one element and see if they are contained in the parents() of the other using index() until you find a match (or not).

肤浅与狂妄 2024-09-01 16:28:38

// 看起来应该相当简单,即使没有库或indexOf

document.commonParent= function(a, b){
 var pa= [], L;
 while(a){
  pa[pa.length]=a;
  a= a.parentNode;
 }
 L=pa.length;
 while(b){  
  for(var i=0; i<L; i++){
   if(pa[i]==b) return b;
  }
  b= b.parentNode;
 }
}

// It seems like it should be fairly simple, even without a library or indexOf

document.commonParent= function(a, b){
 var pa= [], L;
 while(a){
  pa[pa.length]=a;
  a= a.parentNode;
 }
 L=pa.length;
 while(b){  
  for(var i=0; i<L; i++){
   if(pa[i]==b) return b;
  }
  b= b.parentNode;
 }
}
煮酒 2024-09-01 16:28:38

有一个很好的 DOM API 可以做到这一点: compareDocumentPosition

事情是这样的:

    /**
     * Returns closest parent element for both nodes.
     */
    function getCommonParent(one, two){
        let parent = one.parentElement;
        if(one === two) { //both nodes are the same node.
            return parent;
        }
        const contained = Node.DOCUMENT_POSITION_CONTAINED_BY;
        let docpos = parent.compareDocumentPosition(two);

        while(parent && !(docpos & contained)) {
            parent = parent.parentElement;
            docpos = parent.compareDocumentPosition(two);
        }
        return parent;
    }

There is a a good bit of DOM API for that: compareDocumentPosition

This is how it goes:

    /**
     * Returns closest parent element for both nodes.
     */
    function getCommonParent(one, two){
        let parent = one.parentElement;
        if(one === two) { //both nodes are the same node.
            return parent;
        }
        const contained = Node.DOCUMENT_POSITION_CONTAINED_BY;
        let docpos = parent.compareDocumentPosition(two);

        while(parent && !(docpos & contained)) {
            parent = parent.parentElement;
            docpos = parent.compareDocumentPosition(two);
        }
        return parent;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文