How to generate event handlers with loop in Javascript?
All of your handlers are sharing the same i
variable.
You need to put each handler into a separate function that takes i
as a parameter so that each one gets its own variable:
function handleElement(i) {
document.getElementById("b"+i).onclick=function() {
alert(i);
};
}
for(i=1; i<11; i++)
handleElement(i);
Setting event handlers using a for loop
i
will not contain the "current index" like you are intending, but rather the last value i
was, ie arr.length
One quick n dirty solution would be to do something like this
for(var i = 0; i < arr.length; i++) {
(function(_i){
arr[_i].onclick = function() { alert(arr[_i].innerHTML); };
})(i);
}
what this does is captures the current value of i
in a new variable _i
within the closure of the statement you're executing, so it'll stay around and be the value you'd expect every time your onclick handler is called.
Generate event handlers in a loop
The manner you're attempting to do this by - incremental id
attributes - is an anti pattern.
A much better solution would be to use common classes on all the elements to group them within a single event handler. You can then use DOM traversal to find the related elements. Try this:
var $p = jQuery;var html = [ { sector_name: 'foo' }, { sector_name: 'bar' }, { sector_name: 'fizz' }];
for (i = 0; i < html.length; i++) { $p("#panel").append('<div class="flip_sector">' + html[i].sector_name + '</div><div class="panel_sector">sectors</div>');}
$p(".flip_sector").click(function() { $p(this).next('.panel_sector').slideToggle("slow");});
.flip_sector { padding: 5px; text-align: left; background-color: white;}
.panel_sector { padding: 5px; text-align: left; background-color: white; display: none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div id="panel"></div>
addEventListener using for loop and passing values
Closures! :D
This fixed code works as you intended:
// Function to run on click:function makeItHappen(elem, elem2) { var el = document.getElementById(elem); el.style.backgroundColor = "red"; var el2 = document.getElementById(elem2); el2.style.backgroundColor = "blue";}
// Autoloading function to add the listeners:var elem = document.getElementsByClassName("triggerClass");
for (var i = 0; i < elem.length; i += 2) { (function () { var k = i + 1; var boxa = elem[i].parentNode.id; var boxb = elem[k].parentNode.id; elem[i].addEventListener("click", function() { makeItHappen(boxa,boxb); }, false); elem[k].addEventListener("click", function() { makeItHappen(boxb,boxa); }, false); }()); // immediate invocation}
<div class="container"> <div class="one" id="box1"> <p class="triggerClass">some text</p> </div> <div class="two" id="box2"> <p class="triggerClass">some text</p> </div></div>
<div class="container"> <div class="one" id="box3"> <p class="triggerClass">some text</p> </div> <div class="two" id="box4"> <p class="triggerClass">some text</p> </div></div>
How do event handlers in JavaScript get processed by the event loop?
Yes. The order of event handlers executed is guaranteed, and in practice they will not overlap.
This is the beauty of the event loop as a concurrency model. You don't have to think about threading issues like deadlocks, livelocks and race conditions most of the time (though not always).
Order of execution is simple and JavaScript in the browser is single threaded most of the time and in practice you do not have to worry about order of execution of things.
However the fact order of mouse events is guaranteed has hardly anything has to do with JavaScript. This is not a part of the JavaScript language but a part of something called the DOM API, the DOM (document object model) is how JavaScript interacts with your browser and the HTML you write.
Things called Host Objects are defined in the JavaScript specification as external objects JS in the browser works with, and their behavior in this case is specified in the DOM API.
Whether or not the order DOM events are registered is guaranteed is not a part of JavaScript but a part of that API. More specifically, it is defined right here. So to your question: Yes, order of event execution is certain except for control keys (like (control alt delete)) which can mess order of evaluation up.
Why doesn't an event handler inside a for loop work for all iterations?
All you need to do is get that element reference in your changeBackground
function
function changeBackground(e){
var div = e.target; // the current div you want to change
// do your stuff
div.style.backgroundColor = 'red';
}
I put together a quick example do demonstrate the element references. It gets passed to your mouseover
function automatically (I used button
but it works for any element) and I called it e
. Then you need to pull out the current element using e.target
.
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) { btns[i].addEventListener('mouseover', whichButton);}
function whichButton(e) { var btn = e.target; // <- This is your current element (in your case, div2) console.log(btn); var span = document.getElementById('spanMO'); span.textContent = btn.textContent;}
<button>First</button><br/><button>Second</button><br/><button>Third</button><br/>
<p>Mouseover: <span id="spanMO"></span></p>
Event handler for loop with dynamic jQuery selectors
The reason that only the last item gets affected is because the loop has completed before any event fires. Therefore n
holds the last value in the loop. To fix this you need to use a closure:
for (n = 1; n <= total; n++) {
(function(n) {
$('#bt-' + n).on('click', function() {
$('#target-' + n).toggleClass('yellow');
});
})(n);
}
That said, a much better approach would be avoid the loop and to use DOM traversal to find the .target
related to the clicked .button
, like this:
$('.button').click(function() { $(this).next('.target').toggleClass('yellow');});
.wrapper { display: flex; text-align: center;}.button,.target { padding: 20px; margin: 10px;}.button { background: gray;}#target-1 { background: red;}#target-2 { background: green;}#target-3 { background: blue;}.yellow { background: yellow !important;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="wrapper"> <div id="bt-1" class="button"> <h1>Button 1</h1> </div> <div id="target-1" class="target"> <h1>Target 1</h1> </div></div><div class="wrapper"> <div id="bt-2" class="button"> <h1>Button 2</h1> </div> <div id="target-2" class="target"> <h1>Target 2</h1> </div></div><div class="wrapper"> <div id="bt-3" class="button"> <h1>Button 3</h1> </div> <div id="target-3" class="target"> <h1>Target 3</h1> </div></div>
Related Topics
How to Get Input Value Dynamically Using Jquery
Clicking a Button Within a Form Causes Page Refresh
How to Include a JavaScript in a Jsp Page
How to Check If a Background Image Is Loaded
React History.Push() Not Rendering New Component
Validate Phone Number With JavaScript
What Is the Max Size of Localstorage Values
Javascript Loop Wait Until API Call Finished
Google Firestore - How to Get Several Documents by Multiple Ids in One Round-Trip
Change Td Background Colour Based on the Value
Does JavaScript Guarantee Object Property Order
How to Conditionally Include Script Element in Angular
How to Load a Font File in Vuejs and Webpack
How to Convert Utf8 String to Byte Array
Single Quotes in String With Jquery Ajax