Reputation: 15
I have multiple buttons with the ids "especifica-i-pj"
, where i goes from 1 to 4 and j goes from 1 to 3. The idea is to assign an onclick
event to each one of them, without having to declare 12 functions. I thought this would solve my problem:
for ( i = 1; i <= 4; i++ ) {
for ( j = 1; j <= 3; j++ ) {
dom_id = "especifica-"+i.toString()+"-p"+j.toString();
document.getElementById(dom_id).onclick = function() {
console.log("you clicked ",dom_id)
ponder[i-1] = 0.1 + 0.05*(j-1);
console.log("ponder:",i,ponder[i-1])
$("#"+dom_id).addClass("active");
for ( k = 1; k <= 3 && k != j; k++ )
$("#especifica-"+i.toString()+"-p"+k.toString()).removeClass("active");
}
}
}
However each time I click any of the buttons, my console outputs that I clicked especifica-4-p3
, the last one, and outputs ponder: 5 0.25
, when i==5
should not be possible, as the outer for gets to i==4
.
What can I do to make this work? I have been searching online but I have not found anything about this, or even declaring functions inside for loops. Thanks.
Upvotes: 0
Views: 1358
Reputation: 4425
Here's a fix by using data-*
attributes:
for (var i = 1; i <= 2; i++) {
for (var j = 1; j <= 3; j++) {
var buttonId = "especifica-" + i + "-p" + j;
var button = document.getElementById(buttonId);
button.setAttribute("data-i", i);
button.setAttribute("data-j", j);
button.addEventListener("click", function(event) {
console.log("i", event.target.getAttribute("data-i"));
console.log("j", event.target.getAttribute("data-j"));
console.log("button with id of", event.target.id, "was clicked!");
});
}
}
<div><button id="especifica-1-p1" type="button">especifica-1-p1</button></div>
<div><button id="especifica-1-p2" type="button">especifica-1-p2</button></div>
<div><button id="especifica-1-p3" type="button">especifica-1-p3</button></div>
<div><button id="especifica-2-p1" type="button">especifica-2-p1</button></div>
<div><button id="especifica-2-p2" type="button">especifica-2-p2</button></div>
<div><button id="especifica-2-p3" type="button">especifica-2-p3</button></div>
Learn more about data-*
attributes here:
Alternatively, you could take advantage of the concept of closures
, like in the following example:
for (var i = 1; i <= 2; i++) {
for (var j = 1; j <= 3; j++) {
var buttonId = "especifica-" + i + "-p" + j;
var button = document.getElementById(buttonId);
var createEventListener = function (iValue, jValue) {
return function (event) {
console.log("i:", iValue, "j:", jValue);
console.log("button with id of", event.target.id, "was clicked!");
}
};
button.addEventListener("click", createEventListener(i, j));
}
}
<div><button id="especifica-1-p1" type="button">especifica-1-p1</button></div>
<div><button id="especifica-1-p2" type="button">especifica-1-p2</button></div>
<div><button id="especifica-1-p3" type="button">especifica-1-p3</button></div>
<div><button id="especifica-2-p1" type="button">especifica-2-p1</button></div>
<div><button id="especifica-2-p2" type="button">especifica-2-p2</button></div>
<div><button id="especifica-2-p3" type="button">especifica-2-p3</button></div>
Read more about closures
here:
Also, use the element.addEventListener
method instead of element.onclick
. Have a look at here why it's better to use addEventListener('click', ...)
instead of onclick
:
Upvotes: 1
Reputation: 4054
The best way is to capture on click for the first level parent which is the parent for all the buttons,
Only for that you create on click,
inside the event function detect event.target
which will tell from which button the click is happening
function buttonClick(event) {
alert(event.target.getAttribute("id"));
}
<div id="parent" onclick="buttonClick(event)">
<button id="especifica-1-p1">b11</button>
<button id="especifica-1-p2">b12</button>
<button id="especifica-1-p3">b13</button>
<button id="especifica-2-p1">b21</button>
<button id="especifica-2-p2">b22</button>
<button id="especifica-2-p3">b23</button>
</div>
If you want to maintain the data 1,1
1,2
... etc , you can do like this
In each button you can introduce dummy data attributes with your own name assumption
Example
<button id="especifica-1-p1" data-row="1" data-column="1">b11</button>
<button id="especifica-1-p2" data-row="1" data-column="2">b12</button>
Then you can use JavaScript
event.target.getAttribute("data-row");
event.target.getAttribute("data-column");
Upvotes: 1
Reputation: 21487
The easy way would be to do one of the following:
Method 1:
for(i=1; i<=4; i++) {
for(j=1; j<=3; j++) {
dom_id = "especifica-"+i.toString()+"-p"+j.toString();
element = document.getElementById(dom_id);
element.i = i;
element.j = j;
element.onclick = function() {
console.log("you clicked ",dom_id)
ponder[this.i-1] = 0.1 + 0.05*(this.j-1);
console.log("ponder:",this.i,ponder[this.i-1])
$("#"+dom_id).addClass("active");
for(k=1; k<=3 && k!=j; k++)
$("#especifica-"+this.i.toString()+"-p"+k.toString()).removeClass("active");
}
}
}
Method 2:
for(i=1; i<=4; i++) {
for(j=1; j<=3; j++) {
dom_id = "especifica-"+i.toString()+"-p"+j.toString();
document.getElementById(dom_id).onclick = function() {
i = dom_id.substring(11,12);
j = dom_id.substring(14,15);
console.log("you clicked ",dom_id)
ponder[i-1] = 0.1 + 0.05*(j-1);
console.log("ponder:",i,ponder[i-1])
$("#"+dom_id).addClass("active");
for(k=1; k<=3 && k!=j; k++)
$("#especifica-"+i.toString()+"-p"+k.toString()).removeClass("active");
}
}
}
Method 3:
for(i=1; i<=4; i++) {
let i1 = i;
for(j=1; j<=3; j++) {
let j1 = j;
dom_id = "especifica-"+i.toString()+"-p"+j.toString();
document.getElementById(dom_id).onclick = function() {
console.log("you clicked ",dom_id)
ponder[i1-1] = 0.1 + 0.05*(j1-1);
console.log("ponder:",i,ponder[i1-1])
$("#"+dom_id).addClass("active");
for(k=1; k<=3 && k!=j; k++)
$("#especifica-"+i1.toString()+"-p"+k.toString()).removeClass("active");
}
}
}
Upvotes: 2