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?

codingbear
la source

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);
}
cgp
la source
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.

parvus
la source
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)
rond
la source
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;
pery mimon
la source
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.

Nicolas Rojo
la source
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/

Abbotto
la source
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);
}
Maciej Sitko
la source
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>

Gildas.Tambo
la source
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
);
Humoyun Ahmad
la source
0
var childNodeArray = document.getElementById('somethingOtherThanid').childNodes;
Thunderboltz
la source
window.document.documentElement.childNodes [1] .childNodes [4] récupéré sur howtocreate.co.uk/tutorials/javascript/dombasics
Thunderboltz
est-ce une solution à la question?
zahid9i
Cela ne résout pas le problème, ou du moins pas assez clairement pour être utile.
cdeszaq
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
    }
Manoj Yadav
la source
-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.

Saabbir
la source
-2
x1 = document.getElementById('outer')[0]
      .getElementsByTagName('ul')[1]
      .getElementsByTagName('li')[2];
x1.setAttribute("id", "buyOnlineLocationFix");
andre paradis
la source