Make buttons which call same event handler using standard DOM manipulations - javascript

What am I essentially trying to do is to produce container with buttons, which have the same handler but get different arguments like this:
<div id="container">
<button onclick="onclick_handler(1)">1</button>
<button onclick="onclick_handler(2)">2</button>
<button onclick="onclick_handler(3)">3</button>
</div>
Using this:
function onload_handler() {
var container = document.getElementById("container");
var i;
for (i = 0; i < 3; i++) {
var button = document.createElement('button');
button.innerHTML = i;
button.addEventListener('click', function() {
onclick_handler(i);
});
container.appendChild(button);
}
}
function onclik_handler(val) {
console.log(val);
}
And when I click buttons I get 4 in my console. What am I doing wrong?
Could it also be done without usage of anonymous functions?

Try to resolve the problem created by closure, by creating a scope per iteration,
function(i){
button.addEventListener('click', function() {
onclick_handler(i);
});
})(i);
And your full code would be,
function onload_handler() {
var container = document.getElementById("container");
var i;
for (i = 0; i < 3; i++) {
var button = document.createElement('button');
button.innerHTML = i;
(function(i){
button.addEventListener('click', function() {
onclick_handler(i);
});
})(i)
container.appendChild(button);
}
}
function onclik_handler(val) {
console.log(val);
}

Related

Cant get element using template literals

Im injecting some number of buttons in my DOM using a for loop
function injectBtn () {
var output = '';
for(var i = 0 ; i < someNumber ; i++){
output += `<button id="button${i}">`;
}
document.getElementById('list').innerHTML = output;
}
Further I want to add event listeners to them like this, but nothing happens when I click them.
function addEvents () {
for (var i=0 ; i < someNumber ; i++) {
var btn = document.getElementById(`button${i}`);
btn.addEventListener('click', function () {
console.log('click');
}
}
}
I checked in my console, and I'm sure the buttons have been added to the DOM. What am i doing wrong?

Hide / show buttons with javascript

I have this function which hides some buttons and create another button, when I click on the button created it should make again visible those who were hidden before , but it doesn't really work.
function hideButtons(){
var buttons=document.getElementsByTagName("input");
for(var i=0;i<buttons.length;i++) {
if(buttons[i].type=="button"){
buttons[i].style.display="none";}
}
var back=document.createElement("input");
back.setAttribute("type", "button");
back.setAttribute("value","BACK");
back.setAttribute("id","btnBack");
back.onclick=showButtons();
document.body.appendChild(back);
}
function showButtons(){
var buttons=document.getElementsByTagName("input");
for(var i=0;i<buttons.length;i++) {
buttons[i].style.display="initial";
}
}
You must not call the listener function when you attach the event listener:
function hideButtons () {
var buttons = document.querySelectorAll("input[type=button]");
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.display = "none";
if (buttons[i].getAttribute("id") === "btnBack") {
// remove the id from the current "back" button
buttons[i].removeAttribute("id");
}
}
var back = document.createElement("input");
back.setAttribute("type", "button");
back.setAttribute("value","BACK");
back.setAttribute("id","btnBack");
back.onclick = showButtons; // important!
document.body.appendChild(back);
}
function showButtons () {
var buttons = document.querySelectorAll("input[type=button]");
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.display = "initial";
}
}
Like PeterMader said the problem is that you're calling the showButtons() function in the event listener. You want to call a reference to the function like Peter suggested, or another way is to wrap showButtons() in a function.
function hideButtons() {
var buttons = document.getElementsByTagName("input");
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].type == "button") {
buttons[i].style.display = "none";
}
}
var back = document.createElement("input");
back.setAttribute("type", "button");
back.setAttribute("value", "BACK");
back.setAttribute("id", "btnBack");
back.onclick = function() {
showButtons();
}
document.body.appendChild(back);
}
function showButtons() {
var buttons = document.getElementsByTagName("input");
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.display = "initial";
}
}
hideButtons();
<input type="button">
<input type="button">
<input type="button">
<input>

JavaScript onclick event fired without any click

I'm trying to clean the URLs of elements and every thing is working, but the onclick event fired directly on the page load but not when I click. How can I fix this?
HTML:
<a class="button" href="http://192.168.1.99:8888/propertyturkey/admin/clients/index/today_calls/?status=3&sales=70&tagged=1&clientName=turkey&nextCall=turkey&clientEmail=sdfgsdfg">Today call list</a>
<input type="reset" class="reset" id="reset" value="Reset">
JS:
var buttons = document.querySelectorAll('.button');
var reset = document.querySelector('.reset');
function forEach(array, action) {
for (var i = 0; i < array.length; i++) {
action(array[i])
};
}
function clear_url_parameters(element) {
if (!element)
return false;
var element_url = element.getAttribute('href');
var split_url = element_url.split("?");
var queries = split_url[1].split("&");
var new_queries = [];
for (var i = 0; i < queries.length; i++) {
query = queries[i].split("=");
new_queries.push(query[0] + "=");
}
cleared_url = split_url[0] + new_queries.join('');
element.setAttribute('href', cleared_url);
}
reset.addEventListener('click', forEach(buttons, clear_url_parameters));
Demo on jsfiddle
You are passing the result of executing the function forEach to your event listener.
Try this:
reset.addEventListener('click', function () { forEach(buttons, clear_url_parameters); } );
change
reset.addEventListener('click', forEach(buttons, clear_url_parameters));
to
reset.addEventListener('click', function(){
forEach(buttons, clear_url_parameters)
});
Because the parameter you passed to addEventListener has already been called.

Setting onclick function to <li> element

I am trying to dynamically add onclick function to "li" tagged elements.
But the event does not fires.
Here is my code:
var arrSideNavButtons = [];
var sideNavLi = document.getElementsByClassName('side-nav')[0].getElementsByTagName('li');
var arrayOfSceneAudios = [scene1Audio, scene2Audio,...];
for (var i = 0; i < sideNavLi.length; i++) {
sideNavLi[i].onclick = function() {
arrayOfSceneAudios[i].play();
}
arrSideNavButtons.push(sideNavLi[i]);
}
Is it possible to code it this way?
If yes, what is my mistake?
Thanks a lot.
Wrap your onclick handler in a closure, else it only get assigned to the last elem in the loop:
for (var i = 0; i < sideNavLi.length; i++) {
(function(i) {
sideNavLi[i].onclick = function() {
arrayOfSceneAudios[i].play();
}
arrSideNavButtons.push(sideNavLi[i]);
})(i)
}
I think it's better to reuse one single function, instead of creating a new one at each iteration:
var arrSideNavButtons = [],
sideNavLi = document.getElementsByClassName('side-nav')[0].getElementsByTagName('li'),
arrayOfSceneAudios = [scene1Audio, scene2Audio,...],
handler = function() {
this.sceneAudio.play();
};
for (var i = 0; i < sideNavLi.length; i++) {
sideNavLi[i].sceneAudio = arrayOfSceneAudios[i];
sideNavLi[i].onclick = handler;
arrSideNavButtons.push(sideNavLi[i]);
}

Javascript for loop and alert

I am looping through a list of links. I can correctly get the title attribute, and want it displayed onclick. When the page is loaded and when I click on a link, all of the link titles are alerted one by one. What am I doing wrong?
function prepareShowElement () {
var nav = document.getElementById('nav');
var links = nav.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].onclick = alert(links[i].title);
}
}
What you were doing was actually running the alert function.
enclosing the whole thing in an anonymous function will only run it when it is clicked
for (var i = 0; i < links.length; i++) {
links[i].onclick = function () {
alert(this.title);
}
}
You are assigning the onclick to the return value of alert(links[i].title); which doesn't make any sense, since onclick is supposed to be a function.
What you want instead is somethig like onclick = function(){ alert('Hi'); };
But
Since you are using a variable i in that loop you need to create a local copy of it
onclick = function(){ alert(links[i].title); }; would just use the outer scope i and all your links would alert the same message.
To fix this you need to write a function that localizes i and returns a new function specific to each link's own onclick:
onclick = (function(i){ return function(e){ alert(links[i].title); }; })(i);
Final result:
function prepareShowElement () {
var nav = document.getElementById('nav');
var links = nav.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].onclick = (function(i){ return function(e){ alert(links[i].title); }; })(i);
}
}
You can use jquery. To display title of the link on click.
$("#nav a").click(function() {
var title = $(this).attr('title');
alert(title);
});
links.forEach(function(link) {
link.onclick = function(event) {
alert(link.title);
};
}
Also note that your original solution suffered from this problem:
JavaScript closure inside loops – simple practical example
By passing in our iteration variable into a closure, we get to keep it. If we wrote the above using a for-loop, it would look like this:
// machinery needed to get the same effect as above
for (var i = 0; i < links.length; i++) {
(function(link){
link.onclick = function(event) {
alert(link.title);
}
})(links[i])
}
or
// machinery needed to get the same effect as above (version 2)
for (var i = 0; i < links.length; i++) {
(function(i){
links[i].onclick = function(event) {
alert(links[i].title);
}
})(i)
}
You need change .onclick for a eventlistener same:
function prepareShowElement () {
var nav = document.getElementById('nav');
var links = nav.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click',function() {
alert(links[i].title);
},false);
}
}

Categories

Resources