Invoke the onclick method using addEventListener

I am attempting to create a basic function that increments a counter when one of my list items is clicked on. However, I keep encountering an error message that says addEventListener is not a function.

This is how the HTML looks:

  <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>

The JavaScript portion is as follows:

     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);

Does anyone have any suggestions on how to fix this issue?

Answer №1

    function CounterFunction(group){
      this.count = 0;
    
      this.addClickEvent = function() {
        this.count++;
        console.log(this.count);
      };
    
      // Revised code:
      //el.addEventListener('click', this.addClick(), false);
      // Explanation of changes needed for the addEventListener method
      for (var i = 0; i < group.length; i++) {
        group[i].addEventListener('click', this.addClickEvent.bind(this), false);
      }
    }
    
    var elements = document.getElementsByClassName('box');
    var instance = new CounterFunction(elements);
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>

Answer №2

The function getElementsByClassName
provides an array-like collection of elements instead of a single element.

Updated syntax:

let squares = document.getElementsByClassName('box')[index];

Loop through each class element:

document.querySelectorAll('.box').forEach((element) => {
  ...
  element.addEventListener(...)
});

Answer №3

An issue arises when attempting to add an event listener to a group of elements. The correct approach is to iterate through them and attach the listener individually:

function MyCounter(links) {
    var turn = 0;

    function addClick() {
        turn++;
        console.log(turn);
    }

    for (var i=0; i<links.length; i++) {
        links[i].addEventListener('click', addClick(), false);
    }
}

By following this method, a single function serves as a global counter.

Answer №4

function CounterBoxes(squares){
    this.count = 0;

    this.incrementCount = function() {
        this.count ++;
        console.log(this.count);
    };

    var self = this;
    for(var i = 0; i < squares.length; i++){
        squares[i].addEventListener('click', function(){
        self.incrementCount();
        }, false);
    }
}

var squares = document.getElementsByClassName('box');
var boxCounter = new CounterBoxes(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>

Answer №5

If the boxes are filling the size of the ul element, you can use this method instead of creating multiple 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to target a form in jQuery without using a class selector

Within my project, there exists a form, <form id="form3" name="form3"> <input type="text" id="number" name="number" value="" >Number</input> <button type="button" onclick="submit();">Submit</button> </form> When at ...

JQGrid is a unique event grid that triggers only once for the inaugural loading, allowing users to apply a default filter upon first loading

I am currently using JQGrid (jQuery jQgrid not Gurrido) version 4.6.0 and I am in need of an event that occurs only once the grid has completed loading for the first time. I have attempted to use loadComplete and gridComplete, but it seems they both perfor ...

The authorization process for uploading data to Azure Data Lake Gen2

Currently, I am working on generating a Shared Access Signature (SAS) client-side within my Node.js application. The primary goal is to allow users to directly upload files to my Azure Data Lake Gen2 Blob Storage container without streaming them through th ...

What is the proper way to provide parameters in a GET request using Axios?

Recently, I have been attempting to include the api_key in the get request parameter using axios Below is the snippet of my code: const instance = axios.create({ baseURL: "https://api.themoviedb.org/3" }); export function crudify(path) { function get ...

Is there a way for the React select component to adjust its width automatically based on the label size?

After defining a React select component, it looks like this: <FormControl> <InputLabel id="demo-simple-select-label">Age</InputLabel> <Select labelId="demo-simple-select-label" id=&quo ...

Using Bootstrap Multiselect and making AJAX GET requests with nested objects

I'm having difficulties with retrieving nested objects using $.ajax and dynamically populating Bootstrap Multiselect dropdown select options. This issue is similar to the ones discussed in the following Stack Overflow threads: Issue with Data returnin ...

Should I use the item-text property or another property in v-autocomplete for Vuetify search?

I have a to-do list that consists of an array of objects with properties (id, title, description). I want to display the title in the v-autocomplete, but when I search for a word, it works fine. However, what I actually want is to search for either the des ...

RxJS and asynchronous operations - Mastering the flow of execution

Exploring the concepts of async with RxJS is my current goal; I created this example to dive into how async function calls interact within RxJS observables. The outcome looks like this: func1 --- 10 func1 --- 20 func1 --- 40 func1 --- 30 switch ...

Expanding the ul height with animation when the page loads

Hi there, I am a beginner looking to create a ul list that increases its height with animation when the page loads. Can this be achieved with CSS? Any assistance would be greatly appreciated. <ul> <li><a href="/">title 1</a>& ...

Interfacing Contact Form Data from Vue Application to Magento Using API - A Step-by-Step Guide

Introduction A custom vue-component has been implemented on the application, serving as a contact form. This component is imported into the header component and enclosed within a modal container. The primary function of this contact form is to trigger an ...

Ways to merge several getServerSideProps functions

Within my project, I have two important pages: index.js and other.js. In index.js, there exists a crucial method known as getServerSideProps: export async function getServerSideProps(context) { //code here } The challenge arises when I realize that I ...

"Learn the process of setting a variable in ng-model within an input field based on a specific condition

I need to dynamically assign an ng-model variable based on a condition. For instance: <input type="text" ng-model="item.model[multilang]" > The $scope.multilang variable can be set to either "ENG", "JP" (languages) or false. So, when multilang = "E ...

Develop a segmented control-style component with a draggable feature

In my project, I have set up 2 divs that are positioned alongside each other, with a background div referred to as the "bg div". Upon selecting one of the divs, the bg div transitions on top of the selected one, creating a segmented controller effect. Now ...

Encase the event handler within JQuery

Here's an example of inputs with OnBlur event handlers: <input name="abc" tabIndex="5" class="datetime" onblur="if (CheckMode(this))__doPostBack('abc',''); else return false;" /> Now, in JQuery Form ready function, I want ...

Issues with background image slideshow functionality

For one of my websites, I am using a theme that originally came with a single background image. I modified it to have multiple background images for the 'section' tag <section id="intro" class="intro"></section> U ...

Utilize ThreeJS to incorporate a positional offset into a Matrix4 as part of a series of

I need to handle a ThreeJS Matrix4 that holds the position of an element, along with another Matrix4 containing an offset. I want to add this offset to the position in my first Matrix4. Currently, I'm doing it like this: baseMatrix4.setPosition(new TH ...

what is preventing me from receiving the props effectively

It's important to note that this question is specifically related to next.js. Understanding Next.js is crucial for grasping the interaction between the getStaticProps and Home functions as shown in the code snippet below. export async function getStat ...

WebPack Error: When calling __webpack_modules__[moduleId], a TypeError occurs, indicating that it is not a function during development. In production, an Invalid hook call error

Encountering a WebPack error when utilizing my custom library hosted as a package and streamed with NPM Link. Interestingly, the production version functions flawlessly. Below are my scripts: "scripts": { "dev": "rm -rf build ...

Utilizing Several Pop-up Windows on a Single Page

I am currently working on a website feature where users can click on an image to open a modal window with menu items inside. However, while the first modal functions properly, subsequent modals do not. Here is the JavaScript code I am using: <script&g ...

Transform a bit of JavaScript to jQuery

I'm working with some JavaScript code that sets a link's URL using specified parameters. The code looks like this: link.NavigateUrl = string.Format("javascript:MyFunction({0}, {1});", ID1, ID2); This means that when the link is clicked, MyFunct ...