I'm trying to make a simple function that will increase a counter when a click occurs on one of my lis. When I run this, I get an error addEventListener is not a function.
HTML:
<ul class="boxes">
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
</ul>
JS:
var squares = document.getElementsByClassName('box');
function MyCounter(el){
this.turn = 0;
this.addClick = function() {
this.turn ++;
console.log(this.turn);
};
el.addEventListener('click', this.addClick(), false);
}
var c = new MyCounter(squares);
Any suggestions?
getElementsByClassName
returns an array-like of elements, not a single element.
It should be:
var squares = document.getElementsByClassName('box')[index];
For each class element loop :
document.querySelectorAll('.box').forEach((e) => {
...
e.addEventListener(...)
});
function MyCounter(els){ this.turn = 0; this.addClick = function() { this.turn++; console.log(this.turn); }; // old code: //el.addEventListener('click', this.addClick(), false); // 1. parameter el is a collection of DOM elements, not a single element // 2. this.addClick() - calls addClick, resulting in undefined to be passed to addEventListener // 3. context inside addClick (if its reference is passed to addEventListener) would be DOM element, not instance of MyCounter for (var i = 0; i < els.length; i++) { els[i].addEventListener('click', this.addClick.bind(this), false); } } var squares = document.getElementsByClassName('box'); var c = new MyCounter(squares);
div.box { display:block; width:100px; height:100px; margin-right:10px; margin-bottom:10px; background: green; }
<div class="box">A</div> <div class="box">B</div>
The problem is you are trying to add an event listener to a list of elements. Instead you need to loop though them and apply the listener to each single one:
function MyCounter(links) {
var turn = 0;
function addClick = function() {
turn ++;
console.log(turn);
};
for (var i=0; i<links.length; i++) {
links[i].addEventListener('click', addClick(), false);
}
}
This way you have one function that acts as a global counter.
function MyCounter(squares){ this.turn = 0; this.addClick = function() { this.turn ++; console.log(this.turn); }; var that = this; for(var i = 0; i < squares.length; i++){ squares[i].addEventListener('click', function(){ that.addClick(); }, false); } } var squares = document.getElementsByClassName('box'); var c = new MyCounter(squares);
<ul class="boxes"> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> <li class="box">box</li> </ul>
You can always use this method, if the boxes are filling the size of the ul element (instead of creating several listeners)
<ul id="boxes" class="boxes">
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
<li class="box"></li>
</ul>
<script>
var squares = document.getElementById("boxes");
squares.addEventListener('click', function (el) {
if ("HTMLLIElement" === el.target.constructor.name) {
//counter++
}
}, true);
</script>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.