Samuel Fyckes
Samuel Fyckes

Reputation: 125

How to reuse a JS function on different HTML elements

I have 2 squares in a <table> and I want that when I click one, it become black and the other don't.

My current code is working but I gave them the same function and id, so when I click the first, it work well, but when I click the second, it's the first one that changes.
I know whats wrong, but I don't know how to correct it without having to create a function for each id.

Let's say I want 100 squares, I won't write one function to each one, so what can I do?

function myFunc() {
  var element = document.getElementById("cc");
  element.classList.toggle("th");
}
table,
th,
td {
  border: solid black 1px;
  width: 100px;
  height: 100px;
}

.th {
  background-color: black;
}
<table>
  <tr>
    <th onclick="myFunc(this)" id="cc"></th>
    <th onclick="myFunc(this)" id="cc"></th>
  </tr>
</table>

Upvotes: 2

Views: 825

Answers (3)

Calvin Nunes
Calvin Nunes

Reputation: 6516

First of all, and more important: id must be unique, thats why it is called id (identifier).

Said that, I will show you two options to solve your question:

1. The better option:
Don't add any inline (direct in HTML) onclick listener. Add a common class to all <th>, then in Javascript add a single listener to each element that has the class, and use this inside the function, since this scope will be the clicked element.

Example:

let allTh = document.querySelectorAll(".clickableTh").forEach(x => x.onclick = myFunc)


function myFunc() {
   this.classList.toggle("th");
}
table, th, td {
   border:solid black 1px;     
   width:100px;
   height:100px;
}
.th {
  background-color:black;
}
<table>
  <tr>
    <th class="clickableTh"></th>
    <th class="clickableTh"></th>
    <th class="clickableTh"></th>
    <th class="clickableTh"></th>
    <th class="clickableTh"></th>
    <th id="cc" class="notClickableTh"></th>
  </tr>
</table>

2. Keeping your current structure:
As said in the comments, you pass this as parameter (onclick="myFunc(this)"), then inside myFunc you don't need to find the element, you'll already have it in as parameter.

Click below to see the snippet code of example

function myFunc(elem) {
   elem.classList.toggle("th");
}
table, th, td {
   border:solid black 1px;     
   width:100px;
   height:100px;
}
.th {
  background-color:black;
}
<table>
  <tr>
    <th onclick="myFunc(this)"></th>
    <th onclick="myFunc(this)"></th>
    <th onclick="myFunc(this)"></th>
    <th onclick="myFunc(this)"></th>
    <th onclick="myFunc(this)"></th>
    <th id="cc"></th>
  </tr>
</table>

Upvotes: 2

Bhuwan
Bhuwan

Reputation: 16855

For less markup you can bind the click event on all th

var th = document.getElementsByTagName("th");
for (var i = 0; i < th.length; i++) {
  th[i].addEventListener("click", function() {
    this.classList.toggle("th");
  });
}
th,
td {
  border: solid black 1px;
  width: 100px;
  height: 100px;
}

.th {
  background-color: black;
}
<table>
  <tr>
    <th></th>
    <th></th>
    <th></th>
    <th></th>
  </tr>
</table>

Upvotes: 1

Your function is storing the first square in a variable with the cc identifier.

Instead, you should pass a reference of the element clicked and store that element in the variable. That way, the element clicked will be toggled.

function myFunc(ref) {
   var element = document.getElementById(ref.id).innerHTML;
   element.classList.toggle("th");
}

Notice that must also add this to the call of the function.

Upvotes: 0

Related Questions