好的,这就是我所拥有的。我希望在代码注释中解释得足够好:
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
};
}
}
}
}
因此,例如,在问题中描述的 DOM 中获取“距离”#div5
将使用以下内容:#div10
var divOne = document.getElementById('div5'),
divTwo = document.getElementById('div10'),
distance = DOMdistance(divOne, divTwo);
因此distance
将是:
{
up: 1,
across: 3,
down: 2
}
演示:http: //jsfiddle.net/x58Ga/