0

i have a table with 90 buttons, that has different ids, and i want to keep that way, i also have buttons outside the table.

    <button type="button" onclick="resetState()">reset state</button>

    <div>
        <table>
            <tr>
                <td><button type="button" onclick="step('1,1')" id="1,1"></button></td>
                <td><button type="button" onclick="step('1,2')" id="1,2"></button></td>
                <td><button type="button" onclick="step('1,3')" id="1,3"></button></td>
                <!-- etc -->
                <!-- etc -->
                <td><button type="button" onclick="step('9,7')" id="9,7"></button></td>
                <td><button type="button" onclick="step('9,8')" id="9,8"></button></td>
                <td><button type="button" onclick="step('9,9')" id="9,9"></button></td>
            </tr>
    </div>

I want to access all of them from a function, when i right click one of the 90 buttons i want something specific to happen

    <script>
        document.getElementById('1,1').addEventListener('contextmenu', (event) => {
            event.preventDefault()
            console.log("6");
        })
    </script>

the problem is that i cant find something in common between them other than the tagname, but obviously there are other buttons so i cant use it, i want to give the table or the div something that defines all the buttons inside it, also going over them and giving them the same class is unrealistic, unless it is? thanks in advance.

2 Answers2

1

Add a click listener to the <tr>. If the listener sees that a button is the target, check its ID.

    <div>
        <table class="button-table">
            <tr>
document.querySelector('.button-table tr').addEventListener('contextmenu', (e) => {
  if (!e.target.matches('button')) return;
  event.preventDefault()
  console.log(e.target.id);
});

i want to give the table or the div something that defines all the buttons inside it, also going over them and giving them the same class is unrealistic, unless it is?

It wouldn't be unrealistic if you're creating all these elements with a template engine (which I'd recommend if feasible) - typing them all out manually is tedious and error-prone.

You can also remove all of the inline click handlers if you want. (They're horrible practice.)

document.querySelector('.button-table tr').addEventListener('contextmenu', (e) => {
  if (!e.target.matches('button')) return;
  event.preventDefault()
  step(...e.target.id.split(',').map(Number));
});
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • could you explain what this line does exactly ```if (!e.target.matches('button')) return``` – Mohammad Abu Qaoud Mar 17 '22 at 22:41
  • It means that the rest of the function will only run if the clicked element is a button. – CertainPerformance Mar 17 '22 at 22:42
  • CP is talking about [event delegation](https://dmitripavlutin.com/javascript-event-delegation/). Instead attaching listeners to _all the buttons_ have one listener attached to the parent that captures the event from the clicked elements as they bubble up the DOM. But, because all child elements of that parent are clickable, you need to check that the element is a button before proceeding. @MohammadAbuQaoud. – Andy Mar 17 '22 at 22:57
  • Thank you CP, Also for the record, i changed the ```querySelector``` parameter to '.button-table' since i have multiple 'tr's inside the table, and put ```e.target.id``` in a variable because for some reason it would only pass first character to the javaScript function and that fixed it, also thank you Andy that was very clarifying – Mohammad Abu Qaoud Mar 17 '22 at 23:34
0

Traditionally you'd give them all the same class and then use something like document.getElementsByClassName() to iterate over them.

jQuery makes it even easier, if you wanted to go down that route.

Eddie Parker
  • 4,770
  • 3
  • 35
  • 43