Existe-t-il un moyen de sélectionner des nœuds frères?


104

Pour certaines raisons de performances, j'essaie de trouver un moyen de sélectionner uniquement les nœuds frères du nœud sélectionné.

Par exemple,

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

Si j'ai sélectionné le nœud inner1, y a-t-il un moyen pour moi d'accéder à ses frères et sœurs, inner2-4nœuds?

Réponses:


141

Eh bien ... bien sûr ... accédez simplement au parent, puis aux enfants.

 node.parentNode.childNodes[]

ou ... en utilisant jQuery:

$('#innerId').siblings()

Edit: Cletus, comme toujours, est inspirant. J'ai creusé plus loin. Voici comment jQuery obtient essentiellement des frères et sœurs:

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
Notez que jquery.siblings () exclut le nœud actuel de l'ensemble de résultats.
cletus

3
Ce qui est une fonctionnalité très intéressante!
cgp

1
En fait, l'équivalent de node.parentNode.childNodes [] dans jquery est en réalité $ (node) .parent (). Children () et non $ (node) .siblings (). Cela peut être une fonctionnalité intéressante mais cela peut aussi être ennuyeux. Cela dépend de ce que vous voulez.
cletus

1
Vous voudrez vérifier les nœuds ELEMENT_NODE avec node.parentNode.childNodes, car cela vous donnera également des nœuds de texte en espace blanc.
seanmonstar

Rien, je pense que c'était une gaffe - désolé pour ça (supprimé)
cgp

100
var sibling = node.nextSibling;

Cela renverra le frère immédiatement après, ou null plus aucun frère n'est disponible. De même, vous pouvez utiliser previousSibling.

[Edit] Après réflexion, cela ne donnera pas la divbalise suivante , mais l'espace blanc après le nœud. Mieux semble être

var sibling = node.nextElementSibling;

Il existe également un fichier previousElementSibling.


1
suivant / précédentElementSibling n'est pas pris en charge dans IE8
Vadim

1
À partir d'IE9, c'est le cas. Voir aussi stackoverflow.com/questions/5197825/…
parvus

14

Rapide:

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

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

Récupérez les enfants du parent sous forme de tableau, filtrez cet élément.

Éditer:

Et pour filtrer les nœuds de texte (Merci pmrotule ):

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

2
Belle solution. Bien que, je vérifie que nodeType supprime le nœud de texte[ ...n.parentNode.children ].filter(c => c.nodeType == 1 && c != n)
pmrotule

Comment modifieriez-vous cela pour dactylographié?
Nic Scozzaro

10

À partir de 2017:
réponse simple: element.nextElementSiblingpour obtenir le bon frère d'élément. aussi tu as element.previousElementSiblingpour le précédent

à partir d'ici, c'est assez simple d'avoir toutes les prochaines sibiling

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

Il devrait renvoyer tous les frères et sœurs, pas seulement nextou previous. Spécifier exactement le recul ou l’avant n’aide pas beaucoup dans ce cas.
dvlden le

4
pourquoi pas. si vous prenez le suivant et le précédent, vous pouvez avoir une vue d'ensemble. cette réponse vient montrer une nouvelle façon de faire les choses. et apportez quelque chose aux lecteurs. juste pour devenir parent et aller à chaque élément et filtrer celui que tout le monde peut faire actuel
pery mimon

6

avez-vous vérifié la méthode "Sibling" dans jQuery?

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

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

        return r;
    }

le n.nodeType == 1 vérifie si l'élément est un nœud html et n! == exclut l'élément courant.

Je pense que vous pouvez utiliser la même fonction, tout ce code semble être du javascript vanille.


6

Il y a plusieurs façons de le faire.

L'une ou l'autre des solutions suivantes devrait faire l'affaire.

// 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 code jQuery est une excellente ressource pour observer le Javascript de grade A.

Voici un excellent outil qui révèle la base de code jQuery d'une manière très simplifiée. http://james.padolsey.com/jquery/


3

Voici comment vous pouvez obtenir les frères précédents, suivants et tous les frères et sœurs (des deux côtés):

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

Utilisez document.querySelectorAll () et Loops et itération

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();

Natif - dernier, Edge13 +

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

Natif (alternative) - le plus récent, Edge13 +

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

Natif - IE10 +

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


0

1) Ajouter la classe sélectionnée à l'élément cible
2) Rechercher tous les enfants de l'élément parent à l'exclusion de l'élément cible
3) Supprimer la classe de l'élément cible

 <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 fonction suivante retournera un tableau contenant tous les frères et sœurs de l'élément donné.

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

Passez simplement l'élément sélectionné dans la getSiblings()fonction car ce n'est qu'un paramètre.


-2
x1 = document.getElementById('outer')[0]
      .getElementsByTagName('ul')[1]
      .getElementsByTagName('li')[2];
x1.setAttribute("id", "buyOnlineLocationFix");
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.