2011-09-08 24 views
9

¿Cómo puedo buscar hermanos "hacia arriba" usando JavaScript? Básicamente, necesito una función prevUntil() similar a la presente en jQuery.Obtener hermanos en JavaScript, sin bibliotecas

Tengo un montón de <div> elementos, todos en el mismo nivel, tales como:

<div></div> 
<div></div> 
<div></div> 
<div></div> 
<div></div> 
<div></div> 

quiero empezar en un elemento de clic, y trabajar mi camino hasta el árbol hermanos hasta que uno que coincide con una clase se alcanza el criterio de nombre, luego se detiene.

¿Cómo puedo hacer esto, por favor?

+1

@glowcoder: Personalmente, me parece interesante saber lo que jQuery realmente * está haciendo *. – pimvdb

+2

@pimvdb, jQuery es de código abierto, no dude en consultar su código fuente si está interesado en lo que realmente está haciendo y lo más importante * cómo * lo está haciendo. –

+1

@Darin Dimitrov: Lo sé, quiero decir que no hay nada de malo en preguntar qué sucede detrás de escena. – pimvdb

Respuesta

9

Esta respuesta ha sido publicada previamente here en respuesta a una pregunta similar.

Hay algunas formas de hacerlo.

Cualquiera de los siguientes debe hacer el truco.

// METHOD A (ARRAY.FILTER, STRING.INDEXOF) 
var siblings = function(node, children) { 
    siblingList = children.filter(function(val) { 
     return [node].indexOf(val) != -1; 
    }); 
    return siblingList; 
} 

// METHOD B (FOR LOOP, IF STATEMENT, ARRAY.PUSH) 
var siblings = function(node, children) { 
    var siblingList = []; 
    for (var n = children.length - 1; n >= 0; n--) { 
     if (children[n] != node) { 
      siblingList.push(children[n]); 
     } 
    } 
    return siblingList; 
} 

// METHOD C (STRING.INDEXOF, ARRAY.SPLICE) 
var siblings = function(node, children) { 
    siblingList = children; 
    index = siblingList.indexOf(node); 
    if(index != -1) { 
     siblingList.splice(index, 1); 
    } 
    return siblingList; 
} 

FYI: La base de código jQuery es un gran recurso para la observación de grado A Javascript.

Aquí se encuentra una herramienta excelente que revela la base de código jQuery de una manera muy simplificada. http://james.padolsey.com/jquery/

1

Hay una propiedad previousSibling en el DOM HTML

Aquí es alguna referencia

http://reference.sitepoint.com/javascript/Node/previousSibling

+0

La propiedad 'previousSibling' es una referencia a un nodo DOM, no a una función. –

+0

Lo entiendo completamente. Pero con algunas iteraciones simples puedes usar esto para encontrar el elemento anterior que coincida con sus condiciones. –

1

Basta con echar un vistazo a how jQuery does it.

prevUntil: function(elem, i, until) { 
    return jQuery.dir(elem, "previousSibling", until); 
}, 

Que usa una función while/looping caled dir(). El previoHasta que continúa hasta que previousSibling sea el mismo que el elemento until.

dir: function(elem, dir, until) { 
    var matched = [], 
     cur = elem[ dir ]; 

    while (cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery(cur).is(until))) { 
     if (cur.nodeType === 1) { 
      matched.push(cur); 
     } 
     cur = cur[dir]; 
    } 
    return matched; 
}, 
4

uso en combinación con .children.parentNode. Luego filtre el NodeList, luego de convertirlo en una matriz: http://jsfiddle.net/pimvdb/DYSAm/.

var div = document.getElementsByTagName('div')[0]; 
var siblings = [].slice.call(div.parentNode.children) // convert to array 
       .filter(function(v) { return v !== div }); // remove element itself 
console.log(siblings); 
+0

NodeList para organizar el casting con '[] .slice.call (nl)'? Niza ':)' –

+0

¡Gran solución, gracias! – Kholiavko

7

Example Usando previousSibling:

var className = "needle"; 
    var element = clickedElement; 
    while(element.previousSibling && element.previousSibling.className != className) { 
     element = element.previousSibling; 
    } 
    element.previousSibling; // the element or null 
+0

Este 'element.previousSibling.className' es problemático. Si ningún hermano anterior tiene la clase deseada, 'element.previousSibling' eventualmente devolverá' null', por lo que 'element.previousSibling.className' lanzará un error. –

+2

¡Eso fue para evitar un ciclo infinito! Es una broma. He actualizado – Joe

+0

Gracias, chico con nombre largo. – Francisc

2

¿Qué tal esto:

while (node = node.previousElementSibling) { 
    if ((' ' + node.className + ' ').indexOf('foo') !== -1) { 
     // found; do your thing 
     break; 
    } 
} 

No se moleste que me dice que esto no funciona en IE8 ...

+0

¿Te gustaría ser engañado? Como no te engañaré, no puedo responder a tu pregunta porque me pediste que no lo haga. – Wayne

+0

@Wayne No, no me gusta que me engañen. No te pedí que no respondieras mi pregunta. ¡Por favor respóndeme! ¿Y qué pregunté? Creí haber respondido una pregunta, no una pregunta. –

+0

Lo siento malentendido de mi parte. Pensé que tu no me digas que no funciona en IE8 literalmente ... no es que ya lo sepas. – Wayne

0

Básicamente tienes getlementsByTagName y getElementsByName devuelven matrices y puede usar comodines. Si quieres previenen hasta que necesites hacer una función o utilizas algo que ya existe como una biblioteca.

function getElements() 
    { 
    var x=document.getElementsByName("*"); 
    alert(x.length); 
    } 

actualización

GetElementByID devuelve sólo un elemento.

Cuestiones relacionadas