[javascript] Is there a way to select sibling nodes?

For some performance reasons, I am trying to find a way to select only sibling nodes of the selected node.

For example,

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

If I selected inner1 node, is there a way for me to access its siblings, inner2-4 nodes?

This question is related to javascript dom siblings

The answer is


1) Add selected class to target element
2) Find all children of parent element excluding target element
3) Remove class from target element

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

From 2017:
straightforward answer: element.nextElementSibling for get the right element sibling. also you have element.previousElementSibling for previous one

from here is pretty simple to got all next sibiling

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

The following function will return an array containing all the siblings of the given element.

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

Just pass the selected element into the getSiblings() function as it's only parameter.


jQuery

$el.siblings();

Native - latest, Edge13+

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

Native (alternative) - latest, Edge13+

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

Native - IE10+

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

Here's how you could get previous, next and all siblings (both sides):

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

Use document.querySelectorAll() and Loops and iteration

_x000D_
_x000D_
function sibblingOf(children,targetChild){_x000D_
  var children = document.querySelectorAll(children);_x000D_
  for(var i=0; i< children.length; i++){_x000D_
    children[i].addEventListener("click", function(){_x000D_
      for(var y=0; y<children.length;y++){children[y].classList.remove("target")}_x000D_
      this.classList.add("target")_x000D_
    }, false)_x000D_
  }_x000D_
}_x000D_
_x000D_
sibblingOf("#outer >div","#inner2");
_x000D_
#outer >div:not(.target){color:red}
_x000D_
<div id="outer">_x000D_
      <div id="inner1">Div 1 </div>_x000D_
      <div id="inner2">Div 2 </div>_x000D_
      <div id="inner3">Div 3 </div>_x000D_
      <div id="inner4">Div 4 </div>_x000D_
 </div>
_x000D_
_x000D_
_x000D_


Quick:

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

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

Get the parent's children as an array, filter out this element.

Edit:

And to filter out text nodes (Thanks pmrotule):

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

There are a few ways to do it.

Either one of the following should do the trick.

// 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: The jQuery code-base is a great resource for observing Grade A Javascript.

Here is an excellent tool that reveals the jQuery code-base in a very streamlined way. http://james.padolsey.com/jquery/


var sibling = node.nextSibling;

This will return the sibling immediately after it, or null no more siblings are available. Likewise, you can use previousSibling.

[Edit] On second thought, this will not give the next div tag, but the whitespace after the node. Better seems to be

var sibling = node.nextElementSibling;

There also exists a previousElementSibling.


var childNodeArray = document.getElementById('somethingOtherThanid').childNodes;

x1 = document.getElementById('outer')[0]
      .getElementsByTagName('ul')[1]
      .getElementsByTagName('li')[2];
x1.setAttribute("id", "buyOnlineLocationFix");

have you checked the "Sibling" method in jQuery?

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

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

        return r;
    }

the n.nodeType == 1 check if the element is a html node and n!== exclude the current element.

I think you can use the same function, all that code seems to be vanilla javascript.