Reputation: 1024
I have a cat constructor and I want to add eventListener to all my cat objects, so when I click on them, the counter increases. I don't want to add events one by one by hand. Is there any way to add event to all new objects? Thanks
var counter = document.getElementById("counter").innerHTML;
var Cat = function(name , source , width) {
this.name = name;
this.image = new Image(width);
this.image.src = source;
document.body.appendChild(this.image);
}
var poplinre = new Cat("Poplinre" , "images/poplinre.jpg" , 500);
var chewie = new Cat("Chewie" , "images/chewie.jpg" , 500);
Upvotes: 1
Views: 54
Reputation: 541
See Event Delegation.
Event delegation allows you to avoid adding event listeners to specific nodes; instead, the event listener is added to one parent.
How JavaScript Event Delegation Works
Upvotes: 0
Reputation: 3611
You can listen for click events globally and target only the images you want to. This way is called Event Delegation, this article gives you some explanation.
To be short, you listen the click
event on a common parent node and targets only the wanted elements. In your situation you have to implement something like :
document.body.addEventListener('click', e => {
if (e.target && e.target.nodeName === 'IMG' && e.target.classList.contains('cat')) {
//only the image is targeted
}
});
var Cat = function(name , source , width) {
this.name = name;
this.image = new Image(width);
this.image.src = source;
this.image.classList.add('cat');
document.body.appendChild(this.image);
}
Upvotes: 1
Reputation: 1074038
You basically have two choices:
Add the handler individually, within the Cat
constructor
function incrementCounter() {
document.getElementById("counter").innerHTML = ++counter;
}
var Cat = function(name , source , width) {
this.name = name;
this.image = new Image(width);
this.image.src = source;
this.addEventListener("click", incrementCounter);
document.body.appendChild(this.image);
}
Use event delegation: Give your cat images some identifying characteristic (such as a class name) and have a single handler on the container they're being added to (body
in this case), and put the handler on body
, but have it do the increment only when the event passed through one your cat images:
document.body.addEventListener("click", function(e) {
if (e.target.closest(".cat")) {
document.getElementById("counter").innerHTML = ++counter;
}
});
var Cat = function(name , source , width) {
this.name = name;
this.image = new Image(width);
this.image.src = source;
this.className = "cat";
document.body.appendChild(this.image);
}
#2 above uses Element#closest
, which is vaguely new, but can be polyfilled for older environments.
Actually, in your specific case, you don't need Element#closest
since img
elements can't have descendant elements, so you could just look at e.target.className
directly. closest
is a more general solution (which also works here).
Upvotes: 1