2

I have 512 buttons, that when each is clicked, I want to update the state to either 1, 2, 3, or 4. Is there a way to create a function that will update the array when each button is clicked? As a sample, I am able to make 5 buttons, 5 different EventListeners,5 functions. Obviously, can't do that when I have 512 buttons. How can I update my function to take in a button that is clicked?

<!DOCTYPE html>
<html>
<body>

<button id="b1"> 1</button>
<button id="b2"> 2</button>
<button id="b3"> 3</button>
<button id="b4"> 4</button>
<button id="b5"> 5</button>

<script>

var items = [0,0,0,0,0]

button1 = document.querySelector("#b1");
button2 = document.querySelector("#b2");
button3 = document.querySelector("#b3");
button4 = document.querySelector("#b4");
button5 = document.querySelector("#b5");

button1.addEventListener("click",updateArray1);
button2.addEventListener("click",updateArray2);
button3.addEventListener("click",updateArray3);
button4.addEventListener("click",updateArray4);
button5.addEventListener("click",updateArray5);

function updateArray1() {items[0]=1; console.log(items)}
function updateArray2() {items[1]=1; console.log(items)}
function updateArray3() {items[2]=1; console.log(items)}
function updateArray4() {items[3]=1; console.log(items)}
function updateArray5() {items[4]=1; console.log(items)}

</script>

</body>

I am able to update the array by writing a function. How can I loop over the event listeners?

Pippo
  • 2,173
  • 2
  • 3
  • 16
tetra1
  • 41
  • 3
  • 1
    What determines whether the button's number is 1, 2, 3, or 4? – Andy May 07 '23 at 20:40
  • 2
    Does this answer your question? [What is DOM Event delegation?](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation) – pilchard May 07 '23 at 20:41
  • Let me rephrase: at the moment all of the five buttons in your example update each slot in the array with 1. If you have 22 buttons what is the procedure for updating the array? Do the first 5 update all the slots with 1, the next 5 with 2...? How about 512? How do they each update the array? – Andy May 07 '23 at 20:48
  • Hi. Thanks for all the comments. Well I simplified it a bit as a first pass. Each button is supposed to be a pixel, and there are 512 pixels (which can be each set to 1 of 4 values). It's for an electronics testing experiment. My end goal is an array that I'll pass to a script that will interface with some other stuff. With a click, I have to be able to set each pixel to one of 4 numbers, so in fact I will need 512*4 buttons. I thought I would start with 512. Any other suggestions are welcome as I new at JS. Thanks! – tetra1 May 07 '23 at 22:28
  • So the user wants to be able to go to this web interface, click on some buttons (setting each of 1 of 512 pixels to a certain value), and get the end result, which is an array. It has to be just a 1-D array of 512 numbers in order of pixels. I will also need functions later that set groups, e.g, larger blocks of pixels to a certain value (so the user doesn't have to click 512 times!). But I thought I'd start with a simple case. – tetra1 May 07 '23 at 22:30

3 Answers3

1

You can use querySelectorAll to get all buttons, and then you can use for of Loop to bind event Listener to all buttons. Lastly you can use event.target inside the event listener callback function to get the target button. Here is a sample code:-

let buttons = document.querySelectorAll('.buttons');

for (const button of buttons) {
    button.addEventListener('click', updateFunction);
}

function updateFunction(e){
    const target = e.currentTarget;
    // Update the target button here
}
Developer
  • 1,297
  • 1
  • 4
  • 15
  • `querySelectorAll` returns a NodeList that has a `forEach` prototype. `buttons.forEach(btn => {` makes a better code smell than using `for (const button of buttons) {` I think – Roko C. Buljan May 07 '23 at 21:28
  • Nope! For using foreach loop, we have to convert it into array first. – Developer May 07 '23 at 21:32
  • 2
    @MuneebShoukat the [`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) interface *also* has the [`forEach`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach) method. But I don't agree with Roko: `NodeList` has the iterator method, so using `for...of` is a valid way of looping over it. – Emiel Zuurbier May 07 '23 at 21:54
  • Yes you are right. NodeList has foreach method. Thanks – Developer May 07 '23 at 21:55
  • @EmielZuurbier I did not say it's *invalid*. `for..of` is even faster, but that was not my point. Just personal preference: functional approach being more developer friendly. – Roko C. Buljan May 07 '23 at 22:11
1

var items = [0,0,0,0,0]

// use a query selector to get all the buttons at once
// using the name you gave them 

let buttons = document.body.querySelectorAll("button[name='myBtn']");
//what this "button[name='myBtn']" says is get all buttons with that have the name 'myBtn'

//the querySelectorAll returns an array
// use a forEach loop to set the event Listeners
buttons.forEach(button => {

  /*  button before the "=>" is perimiter being passed to the for each callback
      it represents each element in the array, in this case the button element 
      returned by querySelectorAll
   */

  button.addEventListener("click",(event) => {
    //get the button that was pressed
    let pressedButton = event.target;

    // get the number that you passed into the data-num attribute
    // and use the Number() function to convert it into an INT
    let buttonNumber = Number(pressedButton.dataset.num);

    //udate your array
    items[buttonNumber] = 1;

    console.log(items)
  })

})
<!DOCTYPE html>
<html lang="en">

  <body>

    <!-- give your elements the same name -->
    <!-- give your elements a data attribute "num" -->
    <button name="myBtn" data-num="0" id="b1"> 1</button>
    <button name="myBtn" data-num="1" id="b2"> 2</button>
    <button name="myBtn" data-num="2" id="b3"> 3</button>
    <button name="myBtn" data-num="3" id="b4"> 4</button>
    <button name="myBtn" data-num="4" id="b5"> 5</button>
  </body>
</html>
0

I'm not sure what are you trying to do by adding 512 buttons but I hope this helps you

// This function create dynamic count of buttons based on `num_of_btns` variable
function appendButtons(num_of_btns) {
    const container = document.querySelector('#btns-container');
    for (let i = 1; i <= num_of_btns; i++) {
        const button = document.createElement('button');
        button.innerText = i;
        button.classList.add('custom-btn-class');
        button.setAttribute('data-btn_id', i)
        container.appendChild(button);
    }
}

// Set number of buttons you need and fill array of zeros
const num_of_btns = 512;
let items = new Array(num_of_btns).fill(0);
appendButtons(num_of_btns);

// Event listener for all buttons with the class 'custom-btn-class'
let btns = document.querySelectorAll('.custom-btn-class');
btns.forEach((btn) => {
    btn.addEventListener('click', () => {
        let btn_id = parseInt(btn.getAttribute('data-btn_id'));
        items[btn_id - 1] = 1;
        console.log(items)
    });
});
<!DOCTYPE html>
<html>
<body>
    <div id="btns-container"></div>
</body>

</html>
Mohamed EL-Gendy
  • 566
  • 4
  • 11