How to find the nearest common ancestors of two or more nodes?

前端 未结 14 1936
-上瘾入骨i
-上瘾入骨i 2020-11-30 04:03

Users selects two or more elements in a HTML page. What i want to accomplish is to find those elements\' common ancestors (so body node would be the common ancestor if none

相关标签:
14条回答
  • 2020-11-30 04:19

    The solutions involving manually going through the ancestor elements are far more complicated than necessary. You don't need to do the loops manually. Get all the ancestor elements of one element with parents(), reduce it to the ones that contain the second element with has(), then get the first ancestor with first().

    var a = $('#a'),
        b = $('#b'),
        closestCommonAncestor = a.parents().has(b).first();
    

    jsFiddle example

    0 讨论(0)
  • 2020-11-30 04:21

    Somewhat late to the party, here's a JavaScript ES6 version that uses Array.prototype.reduce() and Node.contains(), and can take any number of elements as parameters:

    function closestCommonAncestor(...elements) {
        const reducer = (prev, current) => current.parentElement.contains(prev) ? current.parentElement : prev;
        return elements.reduce(reducer, elements[0]);
    }
    
    const element1 = document.getElementById('element1');
    const element2 = document.getElementById('element2');
    const commonAncestor = closestCommonAncestor(element1, element2);
    
    0 讨论(0)
  • 2020-11-30 04:24

    did not liked any of the answers above(want pure javascript and one function). that worked perfectly for me,efficient and also easier to understand:

        const findCommonAncestor = (elem, elem2) => {
          let parent1 = elem.parentElement,parent2 = elem2.parentElement;
          let childrensOfParent1 = [],childrensOfParent2 = [];
          while (parent1 !== null && parent2 !== null) {
            if (parent1 !== !null) {
              childrensOfParent2.push(parent2);
              if (childrensOfParent2.includes(parent1)) return parent1;
            }
            if (parent2 !== !null) {
              childrensOfParent1.push(parent1);
              if (childrensOfParent1.includes(parent2)) return parent2;
            }
            parent1 = parent1.parentElement;
            parent2 = parent1.parentElement;
          }
          return null;
        };
    
    
    0 讨论(0)
  • 2020-11-30 04:25

    PureJS

    function getFirstCommonAncestor(nodeA, nodeB) {
        const parentsOfA = this.getParents(nodeA);
        const parentsOfB = this.getParents(nodeB);
        return parentsOfA.find((item) => parentsOfB.indexOf(item) !== -1);
    }
    
    function getParents(node) {
        const result = [];
        while (node = node.parentElement) {
            result.push(node);
        }
        return result;
    }
    
    0 讨论(0)
  • 2020-11-30 04:26

    Here is a dirtier way of doing this. It's easier to understand but requires dom modification:

    function commonAncestor(node1,node2){
            var tmp1 = node1,tmp2 = node2;
            // find node1's first parent whose nodeType == 1
            while(tmp1.nodeType != 1){
                tmp1 = tmp1.parentNode;
            }
            // insert an invisible span contains a strange character that no one 
            // would use
            // if you need to use this function many times,create the span outside
            // so you can use it without creating every time
            var span = document.createElement('span')
                , strange_char = '\uee99';
            span.style.display='none';
            span.innerHTML = strange_char;
            tmp1.appendChild(span);
            // find node2's first parent which contains that odd character, that 
            // would be the node we are looking for
            while(tmp2.innerHTML.indexOf(strange_char) == -1){
                tmp2 = tmp2.parentNode; 
            }                           
            // remove that dirty span
            tmp1.removeChild(span);
            return tmp2;
        }
    
    0 讨论(0)
  • 2020-11-30 04:27

    Try this:

    function get_common_ancestor(a, b)
    {
        $parentsa = $(a).parents();
        $parentsb = $(b).parents();
    
        var found = null;
    
        $parentsa.each(function() {
            var thisa = this;
    
            $parentsb.each(function() {
                if (thisa == this)
                {
                    found = this;
                    return false;
                }
            });
    
            if (found) return false;
        });
    
        return found;
    }
    

    Use it like this:

    var el = get_common_ancestor("#id_of_one_element", "#id_of_another_element");
    

    That's just rattled out pretty quickly, but it should work. Should be easy to amend if you want something slightly different (e.g. jQuery object returned instead of DOM element, DOM elements as arguments rather than IDs, etc.)

    0 讨论(0)
提交回复
热议问题