3

Update:

Seems like the problem has nothing to do with my code. I've been running the webpage over browser-sync and that's where the problem appears. When I open the static webpage in Chrome directly, everything seems to be working fine. Thank you to everyone for your help!

I'm working on my personal website and want to make a way to filter through my list of projects using buttons.

<div class="filters">
  <button class="btn btn-filter">Android</button>
  <button class="btn btn-filter">iOS</button>
  <button class="btn btn-filter">Web Dev</button>
  <button class="btn btn-filter">Data Science</button>
</div>

I'm trying to attach event listeners to the buttons by doing this, but it seems like the event listeners are being attached multiple times:

$(".btn-filter").each(function() {
  console.log(this); // #1
  $(this).click(function(e) {
      e.preventDefault();
      e.stopPropagation();
      console.log(this); // #2
  })
  debugger;
})

I have also tried using the class selector. It doesn't work, I switched to .each() and $(this) to be sure the elements were being assigned event handlers only once.

$('.btn-filter').click(...)

Logs show that each button is selected once to be assigned a click listener, but when I actually click the buttons, only some fire once, and some fire 3 times. I use some because it doesn't always behave the same way each time the page is run.

I have tried the solutions described in this post(off(), unbind(), stopPropagation()), but none have worked.

Using Google Chrome's debugger tools, it seems like at the breakpoint, this refers to the HTML element twice for every iteration of each, despite some clicks firing once and some three times.

I suppose I could just assign IDs and wire each button individually, but I want to know what I'm doing wrong here. Could anyone explain?

9
  • 1
    with ".btn-filter" you already select all the buttons (with that class) and can bind one handler to all of them. Commented Oct 2, 2018 at 22:19
  • I've tried the class selector to assign a listener to each element in the class, but the result is the same. I switched to each() and this to debug Commented Oct 2, 2018 at 22:28
  • Is this code accidentally being called more than once, meaning is the $(".btn-filter").each() being called multiple times, for instance inside another event handler? Commented Oct 2, 2018 at 22:30
  • 1
    You'll need to provide a minimal reproducible example as the code shown by itself shouldn't cause what you are seeing Commented Oct 2, 2018 at 22:33
  • 1
    I cannot reproduce: jsfiddle.net/2h1ygLzo/1 - only fires once on each click. The problem must be somewhere else. Commented Oct 2, 2018 at 22:40

3 Answers 3

6

You are running a for each loop on the class, so it will create a new event handler for each element with the class. If you want just one event handler you need to write it like this:

$(".btn-filter").click(function() {
  console.log($(this).text());
});

Buttons that show or hide specific content are best described with a data value or id

Edit: after learning you had this before I will add that nothing you supplied is causing the error you are receiving.

Sign up to request clarification or add additional context in comments.

6 Comments

Sorry I didn't clarify in the post; I have also tried that with the same result. I switched to the .each() to try to get to the bottom of whether the event handlers were actually being registered multiple times.
Note this is effectively the same as OP's code. Both use a loop to put the event listener on each element. $(".btn-filter").click() is just going to do the loop internally
Also, I'm a bit of a newbie when JS, so I want to be certain, I am using .each() on the class, but within the scope of that call, I'm using $(this) to assign the clicks, so that should just do the one element in the class, right?
You will still need to have a way to specify the action you wish to take when clicking on the button. usually this is done with an id or a data value. Otherwise the exact same code will run if you click any of the buttons
Though I was on the same track as you, Daniel, I made a simple test with the original code. The described behaviour cannot be reproduced: jsfiddle.net/2h1ygLzo/1
|
0

The problem with your code is is here

$(".btn-filter")**.each**(function() {

You should simplify it by simply doing something like this

$(".btn-filter").click(function(e) {
      e.preventDefault();
      e.stopPropagation();
      console.log(e); 
  debugger;
})

Since you are already selecting via the class name $(".btn-filter") the function should be added to all the elements.

3 Comments

I've updated the post to clarify that this was my initial code, which didn't work and lead me to do .each() and $(this) to make sure I'm not re-registering event handlers.
Are you sure you are not initializing/declaring the function from multiple locations? T
The code is wrapped by a function and the function is called once on document ready. Also, some buttons were firing once as intended, but others 3 times, so while I had considered that, there's no problem the way I'm using it. This is looking like a browser-sync problem.
0

Call click event using class and get clicked value using .html()

$(document).ready(function () {
        $(".btn-filter").click(function() {
                    alert($(this).html());
                })
    });

JSFiddler

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.