How to Generate Event Handlers With Loop in JavaScript

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



Leave a reply



Submit