How to find all Siblings of the currently selected DOM object
I'll assume that this takes place inside an event handler where this
is a reference to the targeted element whose siblings you want to affect.
If not, adjustments will be needed.
var result = [],
node = this.parentNode.firstChild;
while ( node ) {
if ( node !== this && node.nodeType === Node.ELEMENT_NODE )
result.push( node );
node = node.nextElementSibling || node.nextSibling;
}
// result will contain all type 1 siblings of "this"
Here is a very short and simple way to do it with ES6:
function getAllSiblings(element, parent) {
const children = [...parent.children];
return children.filter(child => child !== element);
}
This will return all children of the parent node that are not the element.
This is a bit more winded of a solution but allows you to create a filter on how you get siblings.
There are three functions to get only previous, only next, or all. This could be improved but decent starting point if you need more control on what types of siblings you want to collect. Thought it might be worth adding.
Working Example
get all next siblings
//this will start from the current element and get all of the next siblings
function getNextSiblings(elem, filter) {
var sibs = [];
while (elem = elem.nextSibling) {
if (elem.nodeType === 3) continue; // text node
if (!filter || filter(elem)) sibs.push(elem);
}
return sibs;
}
get all previous siblings
//this will start from the current element and get all the previous siblings
function getPreviousSiblings(elem, filter) {
var sibs = [];
while (elem = elem.previousSibling) {
if (elem.nodeType === 3) continue; // text node
if (!filter || filter(elem)) sibs.push(elem);
}
return sibs;
}
get all siblings
//this will start from the first child of the current element's parent and get all the siblings
function getAllSiblings(elem, filter) {
var sibs = [];
elem = elem.parentNode.firstChild;
do {
if (elem.nodeType === 3) continue; // text node
if (!filter || filter(elem)) sibs.push(elem);
} while (elem = elem.nextSibling)
return sibs;
}
example filter to apply to above functions
// Example filter only counts divs and spans but could be made more complex
function exampleFilter(elem) {
switch (elem.nodeName.toUpperCase()) {
case 'DIV':
return true;
case 'SPAN':
return true;
default:
return false;
}
}
HTML and testing output
HTML
<div id='test'>
<div id='test2'>asdf</div>
<br /> sdf
<div>asdfasdf<span>asdf</span></div>
<div>a</div>
<span>a</span>
<br />
<div>d</div>
<hr/>
</div>
JavaScript
var elem;
elem = document.getElementById('test2');
//with filter alerts 4
alert( getNextSiblings( elem, exampleFilter ).length );
// no filter, alerts 7
elem = document.getElementById('test2');// put elem back to what it was
alert( getNextSiblings( elem ).length );
// alerts 0
elem = document.getElementById('test2');// put elem back to what it was
alert( getPreviousSiblings( elem, exampleFilter ).length );
// alerts 5
elem = document.getElementById('test2');// put elem back to what it was
alert( getAllSiblings( elem, exampleFilter ).length );
This is an update to @subhaze's answer.
This code uses the matches
DOM method which is supported in modern browsers:
Demo
function matches(elem, filter) {
if (elem && elem.nodeType === 1) {
if (filter) {
return elem.matches(filter);
}
return true;
}
return false;
}
// this will start from the current element and get all of
// the next siblings
function getNextSiblings(elem, filter) {
var sibs = [];
while (elem = elem.nextSibling) {
if (matches(elem, filter)) {
sibs.push(elem);
}
}
return sibs;
}
// this will start from the current element and get all the
// previous siblings
function getPreviousSiblings(elem, filter) {
var sibs = [];
while (elem = elem.previousSibling) {
if (matches(elem, filter)) {
sibs.push(elem);
}
}
return sibs;
}
// this will start from the first child of the current element's
// parent and get all the siblings
function getAllSiblings(elem, filter) {
var sibs = [];
elem = elem.parentNode.firstChild;
while (elem = elem.nextSibling) {
if (matches(elem, filter)) {
sibs.push(elem);
}
}
return sibs;
}
Use these functions as follows:
var elem = document.querySelector('#test');
// find all the "div" and "span" siblings
var after = getNextSiblings(elem, 'div, span');
// find previous siblings with ".list-item" class
var index = getPreviousSiblings(elem, '.list-item');
// get all siblings with a title attribute
var allSibs = getAllSiblings(elem, '[title]');