C'è un modo per selezionare i nodi di pari livello?


104

Per alcuni motivi di prestazioni, sto cercando di trovare un modo per selezionare solo i nodi di pari livello del nodo selezionato.

Per esempio,

<div id="outer">
  <div id="inner1"></div>
  <div id="inner2"></div>
  <div id="inner3"></div>
  <div id="inner4"></div>
</div>

Se ho selezionato il nodo inner1, c'è un modo per accedere ai suoi fratelli, inner2-4nodi?

Risposte:


141

Bene ... certo ... accedi al genitore e poi ai bambini.

 node.parentNode.childNodes[]

oppure ... usando jQuery:

$('#innerId').siblings()

Modifica: Cletus come sempre è stimolante. Ho scavato oltre. Ecco come jQuery ottiene essenzialmente i fratelli:

function getChildren(n, skipMe){
    var r = [];
    for ( ; n; n = n.nextSibling ) 
       if ( n.nodeType == 1 && n != skipMe)
          r.push( n );        
    return r;
};

function getSiblings(n) {
    return getChildren(n.parentNode.firstChild, n);
}

23
Notare che jquery.siblings () esclude il nodo corrente dal set di risultati.
cletus

3
Che è una caratteristica molto bella!
cgp

1
In realtà l'equivalente di node.parentNode.childNodes [] in jquery è in realtà $ (node) .parent (). Children () e non $ (node) .siblings (). Può essere una caratteristica carina ma può anche essere fastidiosa. Dipende da cosa vuoi.
cletus

1
Dovrai controllare i nodi ELEMENT_NODE con node.parentNode.childNodes, perché ti darà anche nodi di testo con spazi bianchi.
seanmonstar

Niente, penso sia stato uno scherzo - scusate (rimosso)
cgp

100
var sibling = node.nextSibling;

Ciò restituirà il fratello immediatamente dopo di esso, oppure null non sono più disponibili fratelli. Allo stesso modo, puoi usare previousSibling.

[Modifica] A pensarci bene, questo non darà il divtag successivo , ma lo spazio dopo il nodo. Sembra che sia meglio

var sibling = node.nextElementSibling;

Esiste anche un file previousElementSibling.


1
next / previousElementSibling non è supportato in IE8
Vadim

1
A partire da IE9 lo è. Vedi anche stackoverflow.com/questions/5197825/…
parvus

14

Presto:

var siblings = n => [...n.parentElement.children].filter(c=>c!=n)

https://codepen.io/anon/pen/LLoyrP?editors=1011

Ottieni i figli del genitore come un array, filtra questo elemento.

Modificare:

E per filtrare i nodi di testo (grazie pmrotule ):

var siblings = n => [...n.parentElement.children].filter(c=>c.nodeType == 1 && c!=n)

2
Bella soluzione. Tuttavia, controllerei che nodeType scarti il ​​nodo di testo[ ...n.parentNode.children ].filter(c => c.nodeType == 1 && c != n)
pmrotule

Come modificheresti questo per il dattiloscritto?
Nic Scozzaro

10

Dal 2017:
risposta semplice: element.nextElementSiblingper ottenere il fratello dell'elemento giusto. anche tu hai element.previousElementSiblingper quello precedente

da qui è abbastanza semplice ottenere tutti i prossimi fratelli

var n = element, ret = [];
while (n = n.nextElementSibling){
  ret.push(n)
}
return ret;

Dovrebbe restituire tutti i fratelli, non solo nexto previous. Specificare esattamente l'andare indietro o in avanti non aiuta molto in questo caso.
dvlden

4
perchè no. se prendi il successivo e il precedente puoi ottenere l'intera immagine. questa risposta viene a mostrare un nuovo modo di fare le cose. e contribuire con qualcosa ai lettori. solo per diventare genitore e andare su ogni elemento e filtrare quello attuale che tutti possono fare
pery mimon,

6

hai controllato il metodo "Sibling" in jQuery?

    sibling: function( n, elem ) {
        var r = [];

        for ( ; n; n = n.nextSibling ) {
            if ( n.nodeType === 1 && n !== elem ) {
                r.push( n );
            }
        }

        return r;
    }

il n.nodeType == 1 controlla se l'elemento è un nodo html e n! == esclude l'elemento corrente.

Penso che tu possa usare la stessa funzione, tutto quel codice sembra essere javascript vaniglia.


6

Ci sono alcuni modi per farlo.

Uno dei seguenti dovrebbe fare il trucco.

// 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 di codice jQuery è un'ottima risorsa per osservare Javascript di grado A.

Ecco uno strumento eccellente che rivela la base di codice jQuery in un modo molto semplificato. http://james.padolsey.com/jquery/


3

Ecco come puoi ottenere precedenti, successivi e tutti i fratelli (entrambi i lati):

function prevSiblings(target) {
   var siblings = [], n = target;
   while(n = n.previousElementSibling) siblings.push(n);
   return siblings;
}

function nextSiblings(target) {
   var siblings = [], n = target;
   while(n = n.nextElementSibling) siblings.push(n);
   return siblings;
}

function siblings(target) {
    var prev = prevSiblings(target) || [],
        next = nexSiblings(target) || [];
    return prev.concat(next);
}

2

Usa document.querySelectorAll () e Loops e iterazione

function sibblingOf(children,targetChild){
  var children = document.querySelectorAll(children);
  for(var i=0; i< children.length; i++){
    children[i].addEventListener("click", function(){
      for(var y=0; y<children.length;y++){children[y].classList.remove("target")}
      this.classList.add("target")
    }, false)
  }
}

sibblingOf("#outer >div","#inner2");
#outer >div:not(.target){color:red}
<div id="outer">
      <div id="inner1">Div 1 </div>
      <div id="inner2">Div 2 </div>
      <div id="inner3">Div 3 </div>
      <div id="inner4">Div 4 </div>
 </div>


1

jQuery

$el.siblings();

Nativo - ultimo, Edge13 +

[...el.parentNode.children].filter((child) =>
  child !== el
);

Native (alternativa) - più recente, Edge13 +

Array.from(el.parentNode.children).filter((child) =>
  child !== el
);

Nativo - IE10 +

Array.prototype.filter.call(el.parentNode.children, (child) =>
  child !== el
);


0

1) Aggiungi la classe selezionata all'elemento di destinazione
2) Trova tutti i figli dell'elemento padre escluso l'elemento di destinazione
3) Rimuovi la classe dall'elemento di destinazione

 <div id = "outer">
            <div class="item" id="inner1">Div 1 </div>
            <div class="item" id="inner2">Div 2 </div>
            <div class="item" id="inner3">Div 3 </div>
            <div class="item" id="inner4">Div 4 </div>
           </div>



function getSiblings(target) {
    target.classList.add('selected');
    let siblings = document.querySelecttorAll('#outer .item:not(.currentlySelected)')
    target.classList.remove('selected'); 
return siblings
    }

-1

La funzione seguente restituirà un array contenente tutti i fratelli dell'elemento specificato.

function getSiblings(elem) {
    return [...elem.parentNode.children].filter(item => item !== elem);
}

Basta passare l'elemento selezionato nella getSiblings()funzione poiché è l'unico parametro.


-2
x1 = document.getElementById('outer')[0]
      .getElementsByTagName('ul')[1]
      .getElementsByTagName('li')[2];
x1.setAttribute("id", "buyOnlineLocationFix");
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.