Looping result last index of array [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I have the following code, to add each element an event using addeventlistener:
var x, y, z;
elm = elm.normalize();
if(!isobj(elm) && iselm(elm)) {
elm = new Array(elm);
}
for(x in elm) {
(function() {
elm[x].addEventListener('click', function() {
alert(x);
});
})();
}
but when I click any element that added an event by the loop it always show the last index example, like when I click the element it show an alert with example text inside the alert box.
Here was the result of console.log(elm) after elm = elm.normalize():
[sample: input.sample.fld, example: input.example.fld]
isobj(elm) is a function to check if variable is an object, same like
iselm(elm) is a function to check if variable is an element.
Due to fix this, I'm trying to use, (function() { /* I put the addEventListener as above */ })(); inside the loop, but still not work.
I already make sure that x is always showing it index, but I didn't know why it always showing the last index in the event.
Please help.

By the time that line of the code is executed, the for-loop has finished.
For explanation:https://dzone.com/articles/why-does-javascript-loop-only-use-last-value
You can use let if your browser supports it. (See article for explanation and alternatives)
var x, y, z;
elm = elm.normalize();
if(!isobj(elm) && iselm(elm)) {
elm = new Array(elm);
}
for(x in elm) {
(function() {
let myX = x;
elm[myX].addEventListener('click', function() {
alert(myX);
});
})();
}

Related

Index based argument in for loop of addEventListener [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 2 years ago.
I am adding some JS to an HTML, and I have a fragment of code similar to this:
<script>
function ButtonAction(index){
alert("My index is: "+index);
if(window_big){
// Use index to do something
}
else{
// Use index to do something else
}
}
function WindowResize(){
if(window.innerWidth > 1200){
window_big = true;
}
else{
window_big = false;
}
}
var window_big;
if(window.innerWidth > 1200){
window_big = true;
}
else{
window_big = false;
}
buttons = document.getElementsByClassName('MyButtons')
var i;
for (i = 0; i < buttons.length; i++) {
alert(i);
buttons[i].addEventListener("click",function(){ButtonAction(i);},false);
}
window.onresize = WindowResize;
</script>
The idea can be summarized like this:
There is a series of buttons in the page, stored in buttons[].
If the window is bigger than a certain size, those buttons should do one action, and if not, do another one.
To do said actions, I need the button[x].id. In fact, the initial intention was to set the listener to:
buttons[i].addEventListener("click",function(){ButtonAction(i);},false);
The problem is that I cannot retrieve the id, because the argument passed in the event listener seems to be always the last value i was set to.
May I ask for some help, please?

How to create functions with dynamic content and store them in an object? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I want to create multiple functions that do different things depending on what's written in a data-table and store them in an object for later use.
Let's look at this simple example:
var arrayPl = [];
function myFunction() {
var carNames = ["Volvo", "Nissan"];
var counter = 0;
for (var i in carNames) {
arrayPl[counter] = function() {
alert(carNames[i]);
};
counter++;
}
}
myFunction();
arrayPl[0]();
Here I wanted to create as many functions as there are car names and save them in an object arrayPl that I could call these functions from later.
Now obviously this example doesn't explain why I would need to do this - but at least it shows my problem, because the first function arrayPl[0](); gives me the second car name instead of the first.
Explaining the reason behind this is too complicated for me now and not that important (Dialogs in Adobe LiveCycle) - I just want to know if what I'm asking is possible in general and if so how.
I prefere this syntax :
var arrayPl = [];
function myFunction() {
var carNames = ["Volvo", "Nissan"];
carNames.forEach( function(element, i) {
arrayPl[i] = function() {
alert(carNames[i]);
}
})
}
myFunction();
arrayPl[0]();

Javascript onclick getvalue is undefined [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
my problem has 2 sides to it.
I am trying to send a simple get value that is generated via a loop like so:
for(var x=0; x<del.length; x++) {
del[x].onclick = function () {
WORK(x);
}
}
Here is my frustrated WORK function
function WORK (x) {
var y = ids[x];
var url = "Delete.php?val=" + y;
window.location = url;
}
I know i just have to pass the value to the function...but if i set it up like that the page executes the function on load and doesn't wait for my click and as is it is now it will always pass an undefined value...what is going on here?
Variable hoisting + non-scoped variables in for loops.
Use .forEach:
Array.prototype.slice.call(del).forEach(function(elem, index) {
elem.onclick = ...
});
Or if you can't, use an immediately-invoked anonymous function:
for (var x = 0; x < del.length; x++) {
(function() {
var elem = del[x];
...
})();
}
When you iterate through the loop, there is only ever one x variable. It is not scoped to the for loop, and changes on each iteration (x++). When you trigger a click, the event handler is called, which in turn calls WORK with the value of x as an argument, which would've already been del.length by the time it runs.

Having issues preserving variable contents in closure [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
(This question is related to this and this but answers there haven't helped me figure out what's wrong in my case.)
I am trying to create an array of clickable elements where each element is bound to a separate instance of some object.
I've simplified the real code I'm working on as much as possible for this question here:
//----------
// Setup part
// SomeObject just holds a number
var SomeObject = function(number) {
this.number = number;
this.getNumber = function() {
return this.number;
};
};
// contains SomeObject(1) through SomeObject(9)
var someArrayContainingObjects = [];
for(var i=1; i<=9; i++)
{
someArrayContainingObjects.push(new SomeObject(i));
}
//----------
// Problem part
for(var y=0; y<3; y++)
{
for(var x=0; x<3; x++)
{
var obj = someArrayContainingObjects[y*3 + x]; // Creating new variable in the loop every time explicitly with var statement?
$("body").append(
$("<button />")
.text("Should output ("+obj.getNumber()+")")
.click(function() {
alert(obj.getNumber()); // Will always be 9
})
);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I thought by explicitly using var obj = ... inside the loop I would create a new context/scope/however it's called for each anonymous click() callback function I'm creating – so that when I click one of the objects, the appropriate number of the respective SomeObject is alert()ed and not always the number of the last SomeObject the loop takes from the array.
Could someone please explain to me why this code snippet does not work as expected, and what to change to have the code function correctly?
To create closure scope in JavaScript you need to invoke a function. In JavaScript we can also invoke functions as soon as you declare them. They are called immediately invoked function expressions
This way you can preserve your x and y values in the scope of the IIFE.
for(var y=0; y<3; y++) {
for(var x=0; x<3; x++) {
(function (x, y) {
var obj = someArrayContainingObjects[y * 3 + x]
$("body").append(
$("<button />")
.text("Should output ("+obj.getNumber()+")")
.click(function() {
alert(obj.getNumber())
})
)
}(x, y))
}
}
Working codepen
Also, this is a big problem that people encounter when they try to write JavaScript as if it was a class based language. I would try to look into writing JS from a more functional perspective

When creating .on() elements in a for loop, how can I make the .on(function) call the current index? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
JavaScript Puzzle: Scope
(6 answers)
Closed 7 years ago.
I hope the title makes sense.
I am using a for loop to create one or more $(document).on() elements. Inside each $(document).on() element created, I need it to call a function foo(currentIndex) where the currentIndex is the value of the index at the time of the .on() definition.
Fiddle: https://jsfiddle.net/xLbses7w/
JavaScript/jQuery:
var event = ['click', 'click'];
var element = ['#someId', '#someId2'];
for (i = 0; i < event.length; i++)
{
$(document).on(event[i], element[i], function ()
{
foo(i); // would like this to be the value of i when the function was created
});
}
function foo(arg)
{
alert(arg);
}
HTML:
<div id="someId">div1</div> <br/>
<div id="someId2">div2</div>
The problem: When I click on the element using the .on() function I have created, it uses the latest value of i (which in this case is 2).
Desired Behavior: When I click on div1, it should alert 0, and when I click on div2 it should alert 1 (the current indexes at the time of .on() definition.)
You can use .data() to store the index value
$(element[i]).data('index', i);
$(document).on(event[i], element[i], function () {
foo($(this).data('index'));
});
DEMO
You can create a closure:
for (i = 0; i < event.length; i++) {
(function (i) {
$(document).on(event[i], element[i], function () {
foo(i); // would like this to be the value of i when the function was created
});
})(i);
}
-DEMO-

Categories