Associate buttons and click actions in a loop - javascript

I am trying to associate several click actions to several buttons, in jQuery. I am using a for loop to browse all the buttons.
I tried something like that :
var realThis = $(this);
// ...
for (var i = 0; i < buttons.length; i++) {
if (typeof(buttons[i].callback) !== 'undefined')
$('#' + buttons[i].id).click(function(){
buttons[i].callback(realThis.getFormValues());
});
}
I got a warning from my editing software :
Mutable variable is accessible from closure
I tried several things without any success.
Any help here ?

I would change the structure of your HTML so that you know which handler will be attached. Data attributes might help you:
<button id="button-1" data-button-id="1" class="button-action">
Do action 1
</button>
<button id="button-2" data-button-id="2" class="button-action">
Do action 2
</button>
You can then attach your handlers to all buttons, and work out which function you want to call on click, instead of in advance:
$('.button-action').on('click', function (e) {
// get the button index from the data attribute
var buttonId = $(e.currentTarget).data('buttonId');
// if there's a callback then execute it
if (buttons[buttonId].callback) {
buttons[buttonId].callback(realThis.getFormValues());
}
});

Finally found an answer to my problem :
for(var i = 0; i < buttons.length; i++)
{
(function()
{
if(buttons[i].callback)
{
var callbackTemp = buttons[i].callback;
$('#' + buttons[i].id).click(function(){ callbackTemp(realThis.getFormValues()); });
}
})();
}
Thanks for you help ;)

Related

How to get value from button after it has been clicked

I'm struggling with this assignment: Pin an event listener to the buttons.
Create a function that gets called when one of the buttons is clicked. Check this with a console.log. Make sure the click event is passed to this function.
Make sure you have access to the value of the button clicked in this function. Check this with console.log. The outcome you want to see in the console when you click is: Leopard / Lion / Elephant / Rhino or Buffalo.
fiveButtons = document.getElementsByClassName("big-five-button");
for (var i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function () {
Array.from(fiveButtons).forEach(function (nameButton) {
console.log(nameButton.innerHTML);
})
});
}
This is what I wrote so far. When I'm clicking the button now, the outcome is the text from all the buttons. While I want the outcome to only be "Lion" after the button lion has been clicked.
<h1>The Big Five</h1>
<ul class="big-five-list">
<li class="big-five-list-item">
<button class="big-five-button">Lion</button>
</li> etc.
when creating an addEventListener you can use the event object to target the element clicked, like this:
fiveButtons[i].addEventListener("click", function (event) {
console.log(event.target.innerHTML);
});
You can change the button to include an onclick function like the below:
https://www.w3schools.com/jsref/event_onclick.asp
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction('Lion')">Lion</button>
<input type="text" value="" id="getValue">
<p id="demo"></p>
<script>
function myFunction(value) {
document.getElementById("getValue").value = value;
}
</script>
</body>
</html>
The onclick function will then have a value inside the () for the function name. This will pass the value you want across to the function and it can be called whatever you want. The above snippet shows an example of how it can be used
Try this solution!
fiveButtons = document.getElementsByClassName("big-five-button");
for (var i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function (item) {
console.log(item.target.innerHTML);
});
}
The function you pass to addEventListener gives an event argument:
fiveButtons = document.getElementsByClassName("big-five-button");
for (var i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function (event) { // use the first argument
console.log('element value:', event.target.value); // log the 'value' of the event target;
// I suspect you want the innerHTML or innerText
console.log('element innerText:', event.target.innerText);
});
}
You can then get the required information from the DOM node in event.target
You don't need the Array.from inside the for loop. You can just do that:
fiveButtons = document.getElementsByClassName("big-five-button");
for (let i = 0; i < fiveButtons.length; i++) {
fiveButtons[i].addEventListener("click", function () {
console.log(fiveButtons[i].innerText);
});
}
EDITED
// Get all the buttons
const fiveButtons = document.getElementsByClassName("big-five-button");
// Iterate through the collection of buttons
// Here is let i = 0 instead of var i = 0, since var has functional scope and let has block scope
// If we used var i = 0 it would not work implicitly because i would exist in the scope of a function,
// and all the event handlers (for each button) would share the same value of i
for (let i = 0; i < fiveButtons.length; i++) {
// For each button register event handler
fiveButtons[i].addEventListener("click", _ => {
// When button is clicked this part of a code is being called
// Because of javascript CLOSURE, it remembers the i value
console.log(fiveButtons[i].innerHTML)
});
}
If this is not understandable please read about closures in javascript.

How to get value of a list item that is generated automatically on click

I am populating an unordered list item with javascript as follows:
for(var i = 0; i < ourData.length; i++){
$('#searchTeamResultView').append(`<li> <Button class="ui-btn" value=${ourData[i]}> ${ourData[i]["team_long_name"]} </Button> </li>`)
}
The ourData is an array of json objects. I want to get log the value of whatever the button user clicks. I am detecting the click using the following code
$("#searchTeamResultView").on("click", "li", function(){
console.log("FML"); // I don't understand what to put inside the log
})
I am unsure on how to log the value of list item on which the user clicks. It would be great if someone could assist me with it. Sorry if this is a noob question. I was unable to figure it out on my own.
If you attach the event handler to the button element instead of the li, which makes more sense semantically, then you can simply use this.value within the event handler. Try this:
let ourData = ['lorem', 'ipsum', 'dolor'];
for (var i = 0; i < ourData.length; i++) {
$('#searchTeamResultView').append(`<li><button class="ui-btn" value="${ourData[i]}">${ourData[i]}</button></li>`);
}
$("#searchTeamResultView").on("click", "button", function() {
console.log(this.value);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="searchTeamResultView"></ul>
Once added onclick event, you can get exact element by "this" value.
For example.
$( document ).ready(function() {
let $elementsDiv = $('.elements');
for(let i = 0; i < 5; i++) {
//Creating new div with on click handler and adding attr subIndex
let $newOnclickElement = $('<div></div>')
.on('click', function() {
handleOnClick(this);
})
.attr('subIndex', i)
.html('element ' + i);
$elementsDiv.append($newOnclickElement);
}
});
function handleOnClick(subElement) {
console.log(subElement);
//To get its attr for example some new index we gonna add;
let $subElemenet = $(subElement);
//Console log subIndex
console.log($subElemenet.attr('subIndex'));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='elements'>
</div>
Someone beat me to it :(

Onclick event for "li" in a for loop when using createElement

I'm trying to add an event listener (onclick) onto every li element that gets created in a specific for loop - using JavaScript.
First I tried using tempLi.onclick (see code below for context), but it wouldn't run the function. After that I searched for the issue here on Stackoverflow, and I read that this method I'm using below should work - but it doesn't (not in my case at least).
if (users.length !== 0) {
for (let i = 0; i < users.length; i++) {
let tempLi = d.createElement('li');
tempLi.className = 'btn btn-primary knappur'
tempLi.innerHTML = users[i];
getId('usersUl').appendChild(tempLi);
(function(value) {
tempLi.addEventListener("click", function() {
alert(value);
}, false);
})(users[i]);
getId('usersUl').innerHTML += '<br>';
}
}
The code is in a function called loginPrepare:
let loginPrepare = () => { ... }
How can I execute code when I click on the generated li (tempLi)?
EDIT: The code that I'd like to run when clicked on the "li" is login(users[i])
I would put the event handler on your ul and rely on event bubbling instead of attaching an event handler to each. It would look something like this.
document.getElementById('usersUl')
.addEventListener('click', function(e) {
if (e.target.hasClass('knappur') {
// Do your work
}
});
You are creating a function inside a loop, referencing the ever-changing index i, which, when the loop is done might be a completely different value than what you think it is.
Also, I think this way you are attaching the event-listener before the tempLi has had time to be properly integrated into the dom.
Third: you don't need to create a new event-listener for each list item. One is enough.//
Try this instead:
if (users.length !== 0) {
const list = getId('usersUl')
for (let i = 0; i < users.length; i++) {
let tempLi = d.createElement('li');
tempLi.className = 'btn btn-primary knappur';
tempLi.innerHTML = users[i];
tempLi.setAttribute('data-user', users[i])
list.appendChild(tempLi);
//list.innerHTML += '<br>'; don't do this btw, <br />s aren't valid children of lists!
}
list.addEventListener("click", event => {
const user = event.target.getAttribute('data-user');
alert(user);
});
}
We can achieve event binding to HTML in very simple way using JQuery like below:
$("#usersUl").on('click',function(e){
//what we do
});

addEventListener firing automatically within loop - or only last element works

I have a loop, and I am creating a button within each iteration. I am attaching an event listener to each newly created button, and I need to pass unique parameters through. Please see the code below (in this case, just passing the index from the loop through the event listener)
for (i = 0; i <= worklog.worklogs.length; i++) {
if (worklog.total > 0) {
var theButton = document.createElement("button");
theButton.addEventListener("click", alertButton(i));
theButton.innerHTML = "Add";
mySpan.appendChild(theButton);
}
}
function alertButton(arg) {
return function () {
alert(arg);
};
}
Currently, the event listener fires on only the button implemented on the very last iteration. If I remove the "return function(){}" within my alertButton function, then the event listener is fired on each iteration without the user clicking on the button.
If you have any ideas I would be extremely appreciative. I am finding other people who have had this problem, yet the solutions provided don't seem to work so well for me. Hopefully I am overlooking something simple.
Thanks!
Issue is in the way you are assigning listener:
theButton.addEventListener("click", alertButton(i));
in above code, alertButton(i) will call function and not assign to it. If you want to pass a value to a function assignment, you should bind value.
theButton.addEventListener("click", alertButton.bind(this,i));
As pointed by #Andreas, a working example.
function createButtons() {
for (var i = 0; i < 5; i++) {
var theButton = document.createElement("button");
theButton.addEventListener("click", alertButton.bind(this, i));
theButton.innerHTML = "Add";
content.appendChild(theButton);
}
}
function alertButton(arg) {
console.log(arg)
}
createButtons();
<div id="content"></div>

How to trigger an event after clicking two different button in Javascript

I was wondering how I can trigger an event after two different buttons being clicked. Specifically I have some buttons with different ids and I want when I click two specific buttons from them to trigger an event. I thought that this can be happen If I call some function in the first on click event and inside this function I can call another function if the second button being clicked. It does not seem to work, so I need your help. (If anyone needs more code please comment to upload the whole code)
function someKindOfFunction(){
//there is some other code here
var ob = document.getElementById(idTable[0]);
var ob1 = document.getElementById(idTable[1]);
var ob2 = document.getElementById(idTable[2]);
var ob3 = document.getElementById(idTable[3]);
ob.addEventListener("click",function() {onCl1(idTable[0],idTable)});
ob1.addEventListener("click",function() {onCl1(idTable[1],idTable)});
ob2.addEventListener("click",function() {onCl1(idTable[2],idTable)});
ob3.addEventListener("click",function() {onCl1(idTable[3],idTable)});
}
function onCl1(id1,idTable){
var obj1 = document.getElementById(id1);
obj1.disabled=true;
var obj2,v,obj3,obj4;
v=0;
var temp = ["0","0","0"];
for(var i =0 ; i<4 ; i++){
if( id1 != idTable[i]){
temp[v] = idTable[i];
v=v+1;
}
}
ob=document.getElementById(temp[0]);
ob1=document.getElementById(temp[1]);
ob2=document.getElementById(temp[2]);
ob.addEventListener("click",function() {onCl2(id1,temp[0])});
ob1.addEventListener("click",function() {onCl2(id1,temp[1])});
ob2.addEventListener("click",function() {onCl2(id1,temp[2])});
}
function onCl2(id1,id2){
//some kind of actions
alert("it wokrs");
}
Just pass some sort of value whenever the button you want is clicked. For instance:
ob.addEventListener("click",function() {onCl1(1)});
ob1.addEventListener("click",function() {onCl1(1)});
var i;
function onCl1(value){
i += value;
if(i == 2){
//do this
}
}
So basically once these two buttons are clicked the value will equal 2 and trigger whatever you want.

Categories

Resources