4

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
        });
    }
1
  • I don't find any button over here. Commented May 25, 2018 at 6:39

5 Answers 5

7

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.

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

Comments

3

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>

1 Comment

I shall look into this for sure. Thanks for the link and the snippet
1

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>

Comments

1

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.