I'm trying to do in vanilla js what the siblings() does in jQuery. I've seen a lot of helpful explanations here but I'm having trouble implementing them on my code.
I have a div that has 4 buttons inside it. Every time i click on a button a class (.btn-anim) is added to that button (this works ok so far). What I want to do is when I click on one of the buttons (that doesn't have the class already) to remove the class of any other button and add it to the clicked one.
My Html markup:
<div id="js-colors-div">
<button class="yellow"></button>
<button class="green"></button>
<button class="blue"></button>
<button class="pink"></button>
</div>
And Js:
var colorsDiv = document.getElementById('js-colors-div');
var colors = colorsDiv.getElementsByTagName("button");
for (var i = 0; i < colors.length; i++) {
colors[i].onclick = function(e) {
var highlight = e.target;
//trying to achieve this
$(this).addClass('btn-anim').siblings().removeClass('btn-anim');
}
};
And this is my code for adding the class
highlight.classList.add('btn-anim'); //
Siblings are "brothers" and "sisters". Siblings are nodes with the same parent (in the same childNodes list). Element Siblings are elements with the same parent (in the same children list).
Vanilla JavaScript refers to using plain Javascript without any additional libraries or frameworks. The term became popular when Eric Wastl created the Vanilla JS site in 2012 as a joke. The site tries to bring attention to the fact that you can use just plain Javascript in many cases.
To select all sibling elements of an element, we will use siblings() method. The siblings() method is used to find all sibling elements of the selected element. The siblings are those having the same parent element in DOM Tree.
In vanilla JS you could loop over the parent's children and just skip the element itself. You can use classList
methods for adding/removing the class:
this.classList.add('btn-anim');
for (let sibling of this.parentNode.children) {
if (sibling !== this) sibling.classList.remove('btn-anim');
}
Note however that you can (also in jQuery) simplify a bit: just remove the class from all buttons, and then add it to the current one:
for (let sibling of this.parentNode.children) {
sibling.classList.remove('btn-anim');
}
this.classList.add('btn-anim');
.siblings() in jQuery also allows you to use a selector argument to target specific siblings and I don't think that's been addressed.
const getSiblings = (el, sel) => {
const siblings = [];
let targets;
if (sel)
targets = el.parentNode.querySelectorAll(':scope > ' + sel)
else
targets = el.parentNode.children;
for (const target of targets) {
if (target !== el)
siblings.push(target);
}
return siblings;
};
Then this could be used like so for the OP's use case...
const removeAnimClass = (ev) => {
const siblings = getSiblings(ev.currentTarget, '.btn-anim');
for (const sibling of siblings) {
sibling.classList.remove('btn-anim');
};
const colorsDiv = document.getElementById('js-colors-div');
const colorBtns = colorsDiv.getElementsByTagName("button");
for (const colorBtn of colorBtns) {
colorBtn.onclick = removeAnimClass;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With