2013-10-05 1 views
0

Je cherchais une fonction qui retournerait la 'distance' entre les éléments du DOM en termes d'ancêtres, de frères et sœurs et de descendants. Par exemple, supposons que j'avais:'Distance' entre les éléments dans DOM (profondeur de génération, etc.)

<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> 

alors je veux une fonction qui retournerait la distance entre #div5 et #div10 quelque chose comme:

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

Depuis obtenir #div5-#div10 vous avoir à remonter d'une génération, avancer 3 frères et sœurs (à #div4) puis 2 générations. De même, #div9 à #div1 renverrait:

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

pour aller jusqu'à deux générations, puis de nouveau un frère.

J'ai déjà une fonction qui fait cela (que je vais inclure comme réponse ci-dessous) donc je l'inclue ici parce que: a) je pensais que quelqu'un d'autre pourrait trouver cela utile; et b) peut-être que quelqu'un d'autre a une meilleure façon de le faire.

Répondre

2

Ok, voici ce que j'ai pour cela. Je l'ai expliqué, espérons assez bien dans les commentaires de code:

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 
       }; 
      } 
     } 
    } 

} 

Ainsi, par exemple, obtenir la « distance » #div5-#div10 dans les DOM décrite dans la question utiliserait quelque chose comme:

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

et donc distance serait:

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

démo: http://jsfiddle.net/x58Ga/

+0

Pourriez-vous fournir une démo? –

+0

@Zeaklous ouais, j'en ai mis un dans ma réponse – BYossarian

Questions connexes