«Расстояние» между элементами в DOM (глубина генерации и т. Д.)

0

Я искал функцию, которая возвращала бы "расстояние" между элементами в DOM с точки зрения предков, братьев и сестер и потомков. Например, предположим, что у меня было:

<div id="div1">
    <div id="div5"></div>
</div>
<div id="div2">
    <div id="div6">
        <div id="div9"></div>
    </div>
    <div id="div7"></div>
</div>
<div id="div3"></div>
<div id="div4">
    <div id="div8">
        <div id="div10"></div>
    </div>
</div>

то мне нужна функция, которая вернет расстояние между #div5 и #div10 как-то вроде:

{
    up: 1,
    across: 3,
    down: 2
}

Так как для перехода из #div5 в #div10 вам нужно подняться на одно поколение, перейдите 3 брата (до #div4), а затем вниз 2 поколения. Аналогично, #div9 в #div1 вернется:

{
    up: 2,
    across: -1,
    down: 0
}

для восхождения на два поколения, а затем назад одного брата.

У меня уже есть функция, которая делает это (что я буду включать в качестве ответа ниже), поэтому я включаю его здесь, потому что: а) я думал, что кто-то может найти его полезным; и б) может быть, у кого-то есть лучший способ сделать это.

Теги:
dom
dom-traversal

1 ответ

2
Лучший ответ

Хорошо, вот что у меня для этого. Я надеюсь, что он достаточно хорошо объяснил в комментариях кода:

function DOMdistance(elem1,elem2) {

    if (elem1 === elem2) {
        return {
            up: 0,
            across: 0,
            down: 0
        };
    }

    var parents1 = [elem1],
        parents2 = [elem2],
        gens = 1,
        sibs = 0,
        sibElem;

    // searches up the DOM from elem1 to the body, stopping and 
    // returning if it finds elem2 as a direct ancestor
    while (elem1 !== document.body) {
        elem1 = elem1.parentNode;
        if (elem1 === elem2) {
            return {
                up: parents1.length,
                across: 0,
                down: 0
            };
        }
        parents1.unshift(elem1);
    }

    // reset value of elem1 for use in the while loop that follows:
    elem1 = parents1[parents1.length - 1];

    // searches up the DOM from elem2 to the body, stopping and 
    // returning if it finds elem1 as a direct ancestor
    while (elem2 !== document.body) {
        elem2 = elem2.parentNode;
        if (elem2 === elem1) {
            return {
                up: 0,
                across: 0,
                down: parents2.length
            };
        }
        parents2.unshift(elem2);
    }

    // finds generation depth from body of first generation of ancestors 
    // of elem1 and elem2 that aren't common to both
    while (parents1[gens] === parents2[gens]) {
        gens++;
    }

    sibElem = parents1[gens];

    // searches forward across siblings from the earliest non-common ancestor
    // of elem1, looking for earliest non-common ancestor of elem2
    while (sibElem) {
        sibElem = sibElem.nextSibling;
        if (sibElem && sibElem.tagName) {
            sibs++;
            if (sibElem === parents2[gens]) {
                return {
                    up: parents1.length - gens - 1,
                    across: sibs,
                    down: parents2.length - gens - 1
                };
            }
        }
    }

    sibs = 0;
    sibElem = parents1[gens];

    // searches backward across siblings from the earliest non-common ancestor 
    // of elem1, looking for earliest non-common ancestor of elem2
    while (sibElem) {
        sibElem = sibElem.previousSibling;
        if (sibElem && sibElem.tagName) {
            sibs--;
            if (sibElem === parents2[gens]) {
                return {
                    up: parents1.length - gens - 1,
                    across: sibs,
                    down: parents2.length - gens - 1
                };
            }
        }
    }

}

Так, например, получение "расстояния" от #div5 до #div10 в DOM, описанном в вопросе, будет использовать что-то вроде:

var divOne = document.getElementById('div5'),
    divTwo = document.getElementById('div10'),
    distance = DOMdistance(divOne, divTwo);

и поэтому distance было бы:

{
    up: 1,
    across: 3,
    down: 2
}

demo: http://jsfiddle.net/x58Ga/

  • 0
    Не могли бы вы предоставить демо?
  • 0
    @ Zeaklous да, я поставил один в своем ответе

Ещё вопросы

Сообщество Overcoder
Наверх
Меню