Reputation: 335
I'm trying to get the child elements of a div to toggle a class 'active'
JS
const dots = document.querySelectorAll('[data-dots]');
dots.forEach(dot => dot.addEventListener('click', handleClick));
function handleClick(e) {
e.target.getElementsByClassName('tb-drop').classList.toggle('active');
console.log(e.target.getElementsByClassName('tb-drop'))
}
HTML
<div class="dots" data-dots>
<i class="fas fa-ellipsis-v dots"></i>
<div class="tb-drop">
<i class="far fa-edit icon-grid"></i>
<i class="fas fa-link icon-grid"></i>
</div>
</div>
So i'm selecting all the divs with the data-dots attribute and then select the child of that div and add the class active. I tried with e.target.children but didnt work.
Thanks, I'm just trying to learn :)
Upvotes: 2
Views: 17892
Reputation: 509
You can also try this code.
var dots = document.querySelectorAll('[data-dots]');
for (var i = 0; i < dots.length; i++) {
dots[i].addEventListener('click', function () {
handleClick(this);
}, false);
}
function handleClick(object) {
var container = object.getElementsByClassName('tb-drop')[0];
if (container != undefined) {
if (container.classList.contains('active')) {
container.classList.remove('active')
}else{
container.classList.add('active')
}
}
}
Upvotes: 0
Reputation: 253368
In order to identify the first child, the easiest option is simply to use Element.querySelector()
in place of Element.getElementsByClassName()
:
const dots = document.querySelectorAll('[data-dots]');
dots.forEach(dot => dot.addEventListener('click', handleClick));
function handleClick(e) {
// Element.querySelector() returns the first - if any -
// element matching the supplied CSS selector (element,
// elements):
e.target.querySelector('.tb-drop').classList.add('active');
}
The problem is, of course, that if no matching element is found by Element.querySelector()
then it returns null
; which is where your script will raise an error. So, with that in mind, it makes sense to check that the element exists before you try to modify it:
const dots = document.querySelectorAll('[data-dots]');
dots.forEach(dot => dot.addEventListener('click', handleClick));
function handleClick(e) {
let el = e.target.querySelector('.tb-drop');
if (el) {
el.classList.add('active');
}
}
It's also worth noting that EventTarget.addEventListener()
passes the this
element into the function, so rather than using:
e.target.querySelector(...)
it's entirely possible to simply write:
this.querySelector(...)
Unless, of course, handleClick()
is rewritten as an Arrow function.
Demo:
const dots = document.querySelectorAll('[data-dots]');
dots.forEach(dot => dot.addEventListener('click', handleClick));
function handleClick(e) {
let el = e.target.querySelector('.tb-drop');
if (el) {
el.classList.add('active');
}
}
div {
display: block;
border: 2px solid #000;
padding: 0.5em;
}
i {
display: inline-block;
height: 1em;
}
::before {
content: attr(class);
}
.active {
color: limegreen;
}
<div class="dots" data-dots>
<i class="fas fa-ellipsis-v dots"></i>
<div class="tb-drop">
<i class="far fa-edit icon-grid"></i>
<i class="fas fa-link icon-grid"></i>
</div>
</div>
Or, if you wish to toggle the 'active' class you could, instead, use toggle()
in place of add
:
const dots = document.querySelectorAll('[data-dots]');
dots.forEach(dot => dot.addEventListener('click', handleClick));
function handleClick(e) {
let el = e.target.querySelector('.tb-drop');
if (el) {
el.classList.toggle('active');
}
}
div {
display: block;
border: 2px solid #000;
padding: 0.5em;
}
i {
display: inline-block;
height: 1em;
}
::before {
content: attr(class);
}
.active {
color: limegreen;
}
<div class="dots" data-dots>
<i class="fas fa-ellipsis-v dots"></i>
<div class="tb-drop">
<i class="far fa-edit icon-grid"></i>
<i class="fas fa-link icon-grid"></i>
</div>
</div>
References:
Upvotes: 10
Reputation: 664886
e.target
already is the clicked child of the element that you installed the listener on. You probably want to use e.currentTarget
or this
instead.
Then you can go using .getElementsByClassName()
, .querySelector[All]()
or .children
from there.
Upvotes: 1