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>
Adding 'click' event listener using 'for' loop
This is because your event handler will be called later (by user action), and that time, i
isn't what you want. You have to use closure to keep it internal.
var links = ['https://www.facebook.com/', 'https://twitter.com', 'https://soundcloud.com'];
function openURL(link) { console.log(link);};
window.onload = function () {
var listElement = document.getElementsByTagName('li');
for (i=0;i<listElement.length;i++) { listElement[i].addEventListener('click',(function (i) { return function () { openURL(links[i]); }; }(i))); }
}
<li>Facebook</li><li>Twitter</li><li>Souncloud</li>
Adding Click Event Listeners During Iteration?
So a few things crosses my mind:
Firstly, edit_entry.bind(this, key);
: Are you certain this
is pointing to what you want? It should be pointing to the window
object. Also, is there any reason to bind context for that particular function?
Secondly innerHTML
: Generally it's discouraged to use innerHTML
directly. I don't know how/when the browser layouts changes to innerHTML
, the div
might not be on the page when you call getElementById
. As an alternative, you could try document.createElement("div")
, set its properties accordingly and finally append it to lex_body
.
Edit
From mdn:
Please note that using innerHTML to append html elements (e.g. el.innerHTML += "link") will result in the removal of any previously set event listeners. That is, after you append any HTML element that way you won't be able to listen to the previously set event listeners.
Adding addEventListener() in loop only works for last button
The main problem is that you redefine the HTML of adiv
completely every time you iterate. This means that any event handler you had already bound to a child element of adiv
is lost the moment you do adviv.innerHTML = ...
. Although you assign the same HTML plus some new one, you don't assign the event handlers that were previously defined. So they are lost.
Only the event handler you assign at the last iteration is not destroyed in this way.
Solution
A quick solution would be to first loop to create all the HTML, and then do a separate loop to assign the event handlers:
// First add all the new content:
var html = adiv.innerHTML;
for (var i = 0; i < array_length; ++i) {
var obj = data.Items[i];
html += "<div class='row'><div class='center-div six columns'>" + obj.Event + ", " + obj.Location + "</div></div>";
html += "<div class='row'><div class='center-div six columns'>" + obj.Date + ", " + obj.Time + "</div></div>";
html += "<div class='row'><div class='center-div six columns'><button id='yay_button_" + i + "' class='button-primary'>Deltag</button></div></div>";
}
adiv.innerHTML = html;
// Now bind the event handlers
// By using "let" instead of "var" the right value is retained
// in the handlers
for (let i = 0; i < array_length; ++i) {
var elem = document.getElementById('yay_button_' + i);
elem.addEventListener('click', function() {
alert('id: ' + i);
});
}
If your browser does not support ES2015 (for let
), then you can use bind
:
for (var i = 0; i < array_length; ++i) {
var elem = document.getElementById('yay_button_' + i);
elem.addEventListener('click', function(i) {
alert('id: ' + i);
}.bind(null, i));
}
adding 'click' event listeners in loop
You need to wrap the assignment of the event listener in a closure, something like:
var td;
for (var t = 1; t < 8; t++){
td = document.getElementById('td'+t);
if (typeof window.addEventListener === 'function'){
(function (_td) {
td.addEventListener('click', function(){
console.log(_td);
});
})(td);
}
}
Using addEventListener() in a for loop with various listeners
There are 3 issues with your code:
- In your for loop, you are essentially attaching strings as eventlisteners. You need to access your event listeners from the string you have.
Since you eventlisteners are declared in the global scopre, you can use window
to access them:
button.addEventListener("click", window[listenerName]);
You are attaching the event listeners before declaring them. You need to declare
listener1
and so on before your for loopinnerHtml
does not exist. The right syntax isinnerHTML
Here is a working example:
<!DOCTYPE html>
<html>
<body>
<button id="button-listener1">Try 1</button>
<button id="button-listener2">Try 2</button>
<button id="button-listener3">Try 3</button>
<button id="button-listener4">Try 4</button>
<p id="demo"></p>
<script>
var listener1 = function() {
document.getElementById('demo').innerHTML = "1";
}
var listener2 = function() {
document.getElementById('demo').innerHTML = "2";
}
var listener3 = function() {
document.getElementById('demo').innerHTML = "3";
}
var listener4 = function() {
document.getElementById('demo').innerHTML = "4";
}
var selector = "[id^=button]";
var allButtons = document.querySelectorAll(selector);
for (var button of allButtons) {
var listenerName = button.id.slice(button.id.lastIndexOf("-")+1);
button.addEventListener("click", window[listenerName]);
}
</script>
</body>
</html>
Loop through array and add event listener click to each
You should use addEventListener()
as :
target.addEventListener(type, listener[, options]);
You could also get the index from forEach
:
arr.forEach(function ( element_value,element_index ){ })
Hope this helps.
var sliders = [].slice.call(document.getElementsByClassName("sliderControlLi"));
sliders.forEach(function (element, index){ element.addEventListener("click", function(){ console.log("you clicked slider controler " +index + "!"); });});
<div class="sliderControlLi">slider 1</div><div class="sliderControlLi">slider 2</div><div class="sliderControlLi">slider 3</div><div class="sliderControlLi">slider 4</div>
How to loop through all the buttons to a click event listener
Adding a large number of event listeners will hinder your application's performance. Hence in such cases you can use the Event Delegation technique.
If you want to read more about this, I found this link very resourceful. In case you have any queries hit me up in the comments.
const input = document.querySelector("#user-input");
const table = document.querySelector("table");
table.addEventListener('click', (e) => {
//Since we only want to register button clicks inside the table and not any clicks on the blank space between the buttons.
if(e.target.tagName === "BUTTON") {
if(e.target.id === "clear") {
input.value = "";
} else {
input.value += e.target.value;
}
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Async JS</title>
<script src="promises.js" defer></script>
<style>
input {
margin-top: 10px;
}
table {
margin-bottom: 10px;
width: auto;
margin-top: 10px;
}
</style>
</head>
<body>
<main>
<input id="user-input">
<table>
<tr>
<td><button type="button" value="1" class="calc">1</button></td>
<td><button type="button" value="2" class="calc">2</button></td>
<td><button type="button" value="3" class="calc">3</button></td>
</tr>
<tr>
<td><button type="button" value="4" class="calc">4</button></td>
<td><button type="button" value="5" class="calc">5</button></td>
<td><button type="button" value="6" class="calc">6</button></td>
</tr>
<tr>
<td><button type="button" value="7" class="calc">7</button></td>
<td><button type="button" value="8" class="calc">8</button></td>
<td><button type="button" value="9" class="calc">9</button></td>
</tr>
<tr>
<td><button type="button" value="0" class="calc">0</button></td>
<td colspan="2"><button type="button" value="CLEAR" id="clear" class="calc">CLEAR</button></td>
</tr>
</table>
</main>
</body>
</html>
Related Topics
Ajax Mailchimp Signup Form Integration
Detecting iOS/Android Operating System
How to Limit Google Autocomplete Results to City and Country Only
Multiple Left-Hand Assignment with JavaScript
Angularjs 1.2 $Injector:Modulerr
String.Replace' Weird Behavior When Using Dollar Sign ($) as Replacement
Unexpected Behavior Using Array Map on an Array Initialized with Array Fill
How to Remove All the Options of a Select Box and Then Add One Option and Select It with Jquery
Prototype Based VS. Class Based Inheritance
Get Viewport/Window Height in Reactjs
How to Get Selected HTML Text with JavaScript
Javascript: Formatting a Rounded Number to N Decimals
Using Address Instead of Longitude and Latitude with Google Maps API
Are Es6 Classes Just Syntactic Sugar for the Prototypal Pattern in JavaScript
Merge Multiple Objects Inside the Same Array into One Object