Liam
Liam

Reputation: 111

Javascript on click event for multiple buttons with same class

I have a few buttons across a site I am building, certain buttons have one class while others have another. What I am trying to do is find the best way to find the clicked button without having an event listener for each individual button. I have come up with the below 2 for loops to find all the buttons with class button-1 and class button-2. Being fairly new to javascript i just don't want to get into bad habits so would appreciate any advice on the best way to achieve this.

<section>
  <div class="button--1"></div>
  <div class="button--1"></div>
  <div class="button--2"></div>
</section>

<section>
  <div class="button--2"></div>
  <div class="button--1"></div>
  <div class="button--2"></div>
</section>

 var button1 = document.querySelectorAll('.button--1');
    var button2 = document.querySelectorAll('.button--2');

    for (var a = 0; a < button1.length; a++) {    
        button1[a].addEventListener('click',function(){
            //do something
        });
    }

    for (var b = 0; b < button2.length; b++) {
        button1[b].addEventListener('click',function(){
            //do something
        });
    }

Upvotes: 4

Views: 29699

Answers (5)

KooiInc
KooiInc

Reputation: 122906

Try using event delegation

(function() {
  document.body.addEventListener("click", clickButtons);
  // ^ one handler for all clicks

  function clickButtons(evt) {
    const from = evt.target;
    console.clear();
    if (!from.className || !/button--\d/i.test(from.className)) { return; }
    // ^check if the element clicked is one of the elements you want to handle 
    //  if it's not one of the 'buttons', do nothing
    console.log("you clicked " + from.classList);
  }
}())
.button--1:before,
.button--2:before {
  content: 'BTTN['attr(class)']';
}

.button--1,
.button--2 {
  border: 1px solid #999;
  background: #eee;
  width: 220px;
  padding: 3px;
  text-align: center;
}
<section>
  <div class="b1 button--1 section1"></div>
  <div class="b2 button--1 section1"></div>
  <div class="b3 button--2 section1"></div>
</section>

<section>
  <div class="b4 button--2 section2"></div>
  <div class="b5 button--1 section2"></div>
  <div class="b6 button--2 section2"></div>
</section>

Upvotes: 3

Takit Isy
Takit Isy

Reputation: 10081

If you plan to have multiple other classes like button--3, …4…15,
You must want to target all div elements which class starts (^=) with "button":

(Note that you can do it in the CSS too!)

var allButtons = document.querySelectorAll('div[class^=button]');
console.log("Found", allButtons.length, "div which class starts with “button”.");

for (var i = 0; i < allButtons.length; i++) {
  allButtons[i].addEventListener('click', function() {
    console.clear();
    console.log("You clicked:", this.innerHTML);
  });
}
/* Some styling */

section {
  margin: 8px 0;
  border: 1px solid gray;
}

section div {
  border: 1px solid lightgray;
  display: inline-block;
  margin-left: 8px;
  padding: 4px 8px;
  width: 30px;
}

section div[class^=button] {
  background: lightgray;
  cursor: pointer;
}
<span>You can click on the buttons:</span>
<section>
  <div class="button--1">s1-1</div>
  <div class="button--2">s1-2</div>
  <div class="button--3">s1-3</div>
  <div class="button--4">s1-4</div>
</section>
<section>
  <div class="button--1">s2-1</div>
  <div class="button--2">s2-2</div>
  <div class="button--3">s2-3</div>
  <div class="button--4">s2-4</div>
</section>
<section>
  <div class="not-a-button">not1</div>
  <div class="not-a-button">not2</div>
  <div class="not-a-button">not3</div>
  <div class="not-a-button">not4</div>
</section>

Hope it helps.

Upvotes: 7

onecompileman
onecompileman

Reputation: 940

My suggestion is to use jQuery so that you can do it something like this:

$(document).on('click', '.button--1', function() {
   // Do something
});

$(document).on('click', '.button--1', function() {
   // Do something
})

But a clean approach for pure Javascript is to create a function that binds a callback for the event.

function bindEvent(callback, eventType, targets) {
   targets.forEach(function(target) {
     target.addEventListener(eventType, callback);
   });
};


var button1 = document.querySelectorAll('.button--1');
var button2 = document.querySelectorAll('.button--2');

bindEvent(function() {
   // do something
}, 'click', button1);

bindEvent(function() {
   // do something
}, 'click', button2);

Upvotes: 1

Benoit Chassignol
Benoit Chassignol

Reputation: 289

The click event is fired when a pointing device button (usually a mouse's primary button) is pressed and released on a single element.

This documentation will help you to understand how it works MDN - Click event

Upvotes: 0

flx
flx

Reputation: 1578

You can use multiple selectors in the string of querySelctorAll() by separating them with a ,

var button1 = document.querySelectorAll('.button--1');
var button2 = document.querySelectorAll('.button--2');
var allButtons = document.querySelectorAll('.button--1, .button--2');

console.log(button1.length);
console.log(button2.length);
console.log(allButtons.length);
<section>
  <div class="button--1"></div>
  <div class="button--1"></div>
  <div class="button--2"></div>
</section>

<section>
  <div class="button--2"></div>
  <div class="button--1"></div>
  <div class="button--2"></div>
</section>

Upvotes: 1

Related Questions