addEventListener isn't working properly - javascript

I want to move some elements between two div's. Everything works normal with onclick event, but when i swicth to addEventListener it lets me switch just a few times the elements.
Here is a previev http://jsfiddle.net/2u6nyxp4/1/ .
Can someone explain why is that ? Thank you.
HTML
<div id="one">
<span>One</span>
<span>Two</span>
</div>
<div id="two"><span>One</span></div>
JAVASCRIPT
var one = document.getElementById('one');
var two = document.getElementById('two');
var movetoOne = function () {
one.appendChild(this);
bindEvents (this,movetoTwo);
}
var movetoTwo = function () {
two.appendChild(this);
bindEvents (this,movetoOne);
}
var bindEvents = function (childList, moveEvent) {
childList.onclick = moveEvent;
}
for (i=0; i < one.children.length ; i+=1 ) {
bindEvents(one.children[i], movetoTwo);
}
for (i=0; i < two.children.length ; i+=1 ) {
bindEvents(two.children[i], movetoOne);
}

If you use oncklick there is only one event-handler for the event at a time. Each time you call bindEvents the old one becomes overwritten by the new one.
If you use addEventListener, each time you call bindEvents a new handler is added to the existing. After ten clicks there are five handlers movetoOne and five movetoTwo attached to the same element and the browser is totally confused.
The way out: remove the existing handler before adding a new one like so:
var bindEvents = function (childList, moveEvent) {
var old = movetoOne;
if (old === moveEvent) old = movetoTwo;
childList.removeEventListener('click', old);
childList.addEventListener('click', moveEvent);
}
Working DEMO here. - - - Reference: removeEventListener().

Related

addEventListener null, onclick works (onload did not work and js is in separate document)

I can use onClick in my HTML file to call upon functions created in my JavaScript file, however, attempting to use addEventListener does not work and I am not sure why. Error in console.log says that the addEventListner is null.
I am attempting to change the display of my web page via a click event.
I understand that addEventListener does not cancel out the previous event called, but even the first event called in my code does not trigger the change which is confusing.
After looking this up I tried the following:
Using window.onload = function(){} and placing the below code within the function.
document.getElementById('begin_game').addEventListener('click', beginGame);
document.getElementById('select_category').addEventListener('click', selectCategory);
Using this code independent of the window.onload function but the addEventListener still returned as null.
The beginGame and selectCategory functions reference the following code in the js file:
function Hide(x) {
const hidden = document.getElementsByClassName(x);
for (var i=0, length= hidden.length; i < length; i++) {
if ( hidden[i].style.display != 'none') {
hidden[i].style.display = 'none';
}
}
}
function Display(x) {
const show = document.getElementsByClassName(x);
for (var i = 0, length = show.length; i < length; i++) {
if (show[i].style.display != 'flex') {
show[i].style.display = 'flex';
}
}
}
//Below is how the functions are referenced
function beginGame() {
document.getElementById('welcome').style.display = 'flex';
Hide('start');
}
function selectCategory () {
Hide('welcome-content');
Display('category');
}
// Where I would place the event listeners I mentioned above
// document.getElementById('begin_game').addEventListener('click', beginGame);
// document.getElementById('select_category').addEventListener('click', selectCategory);
// When I used the window.onload function, I placed it at the bottom of the js page
Buttons from HTML file
<button type='submit' class='welcome-content' id='select_category'>
Categories
</button>
</div>
<h1 class= 'start'>
Math Maniacs
</h1>
<button type='submit' class='start' id='begin_button'>
START
</button>
Using window.onload was the correct solution, I realized that I was not enveloping all of the relevant js code with the onload function.
Before I did this
window.onload = function() {
document.getElementById('begin_game').addEventListener('click', beginGame);
document.getElementById('select_category').addEventListener('click', selectCategory);
}
However, I believe that didn't work because I did not place the functions the event listeners were referencing into the window.onload function.
Once I wrote the below
window.onload = function() {
function beginGame() {
document.getElementById('welcome').style.display = 'flex';
Hide('start');
}
document.getElementById('begin_button').addEventListener('click', beginGame);
function selectCategory() = {
Hide('welcome-content');
Display('category');
}
document.getElementById('select_category').addEventListener('click', selectCategory);
}
The code worked as intended

Onclick event for "li" in a for loop when using createElement

I'm trying to add an event listener (onclick) onto every li element that gets created in a specific for loop - using JavaScript.
First I tried using tempLi.onclick (see code below for context), but it wouldn't run the function. After that I searched for the issue here on Stackoverflow, and I read that this method I'm using below should work - but it doesn't (not in my case at least).
if (users.length !== 0) {
for (let i = 0; i < users.length; i++) {
let tempLi = d.createElement('li');
tempLi.className = 'btn btn-primary knappur'
tempLi.innerHTML = users[i];
getId('usersUl').appendChild(tempLi);
(function(value) {
tempLi.addEventListener("click", function() {
alert(value);
}, false);
})(users[i]);
getId('usersUl').innerHTML += '<br>';
}
}
The code is in a function called loginPrepare:
let loginPrepare = () => { ... }
How can I execute code when I click on the generated li (tempLi)?
EDIT: The code that I'd like to run when clicked on the "li" is login(users[i])
I would put the event handler on your ul and rely on event bubbling instead of attaching an event handler to each. It would look something like this.
document.getElementById('usersUl')
.addEventListener('click', function(e) {
if (e.target.hasClass('knappur') {
// Do your work
}
});
You are creating a function inside a loop, referencing the ever-changing index i, which, when the loop is done might be a completely different value than what you think it is.
Also, I think this way you are attaching the event-listener before the tempLi has had time to be properly integrated into the dom.
Third: you don't need to create a new event-listener for each list item. One is enough.//
Try this instead:
if (users.length !== 0) {
const list = getId('usersUl')
for (let i = 0; i < users.length; i++) {
let tempLi = d.createElement('li');
tempLi.className = 'btn btn-primary knappur';
tempLi.innerHTML = users[i];
tempLi.setAttribute('data-user', users[i])
list.appendChild(tempLi);
//list.innerHTML += '<br>'; don't do this btw, <br />s aren't valid children of lists!
}
list.addEventListener("click", event => {
const user = event.target.getAttribute('data-user');
alert(user);
});
}
We can achieve event binding to HTML in very simple way using JQuery like below:
$("#usersUl").on('click',function(e){
//what we do
});

addEventListener firing automatically within loop - or only last element works

I have a loop, and I am creating a button within each iteration. I am attaching an event listener to each newly created button, and I need to pass unique parameters through. Please see the code below (in this case, just passing the index from the loop through the event listener)
for (i = 0; i <= worklog.worklogs.length; i++) {
if (worklog.total > 0) {
var theButton = document.createElement("button");
theButton.addEventListener("click", alertButton(i));
theButton.innerHTML = "Add";
mySpan.appendChild(theButton);
}
}
function alertButton(arg) {
return function () {
alert(arg);
};
}
Currently, the event listener fires on only the button implemented on the very last iteration. If I remove the "return function(){}" within my alertButton function, then the event listener is fired on each iteration without the user clicking on the button.
If you have any ideas I would be extremely appreciative. I am finding other people who have had this problem, yet the solutions provided don't seem to work so well for me. Hopefully I am overlooking something simple.
Thanks!
Issue is in the way you are assigning listener:
theButton.addEventListener("click", alertButton(i));
in above code, alertButton(i) will call function and not assign to it. If you want to pass a value to a function assignment, you should bind value.
theButton.addEventListener("click", alertButton.bind(this,i));
As pointed by #Andreas, a working example.
function createButtons() {
for (var i = 0; i < 5; i++) {
var theButton = document.createElement("button");
theButton.addEventListener("click", alertButton.bind(this, i));
theButton.innerHTML = "Add";
content.appendChild(theButton);
}
}
function alertButton(arg) {
console.log(arg)
}
createButtons();
<div id="content"></div>

onclick() automatic firing on loading but failing afterwards

I understand that onclick() in html with parenthesis calls automatically. But in my situation, I want to pass a parameter into the onclick function(specifically, the element clicked). So how do I manage this without having onclick fired when the page loads? In addition, the onclick method does not fire after its automatically firing upon loading. My code is below:
for (i = 0; i < returnPostPhotoSrcs().length; i++) {
// var photosArray=returnPhotoNames()
// var imgName=photosArray[i]
var imgSrcArray=returnPostPhotoSrcs();
var imgSrc=imgSrcArray[i]
var postNamesArray=returnPostNamesArray();
var postName=returnPostNamesArray[i]
var img=img_create(imgSrc,postName,'')
img.style.width=returnPostHeight();
img.style.height=returnPostWidth();
img.className="postImage";
img.onmousedown=playShout(img);
var postNamesArray=returnPostNames();
var innerSpan = document.createElement('span');
innerSpan.onmousedown=playShout(innerSpan); //problem line
var text = postNamesArray[i];
innerSpan.innerHTML = text; // clear existing, dont actually know what this does
var outerSpan = document.createElement('span');
outerSpan.className="text-content";
outerSpan.onmousedown=playShout(outerSpan); //another problem line, also doesnt call onclick
var li = document.createElement('li');
var imgSpacer=img_create('spacerSource',"spacer",'')
imgSpacer.style.width="25px";
imgSpacer.style.height=returnPostWidth();
li.appendChild(img)
outerSpan.appendChild(innerSpan)
li.appendChild(imgSpacer)
imgSpacer.style.opacity="0"
// if (i>0 && i<returnPostPhotoSrcs().length-1) {
// hackey
var imgSpacer=img_create('spacerSource',"spacer",'')
imgSpacer.style.width="25px";
imgSpacer.style.height=returnPostWidth();
li.appendChild(imgSpacer)
li.appendChild(outerSpan)
imgSpacer.style.opacity="0"
// }
var outerDiv = document.getElementById("postDivOuter");
outerDiv.appendChild(li)
}
Adding onto this you could also do:
img.onmousedown= function(e) { playShout(e) };
//for playshout
playshout = function(e) {
var element = e.target; //this contains the element that was clicked
};
The function fires because you are calling it. You need to use a closure
img.onmousedown= function() { playShout(img) };
As others have shown, you can create an anonymous function, or another option is to use .bind():
innerSpan.onmousedown = playShout.bind(null, innerSpan);

How to add onclick event to exist element by Javascript? (document.getElementbyID)

I have a button in my project that when you click over it a function call and add onclick event to all certain elements in my project and show my hidden popup element container.
I have a function that search all exist element in my page and add onclick event to some of elements that they have certain class.
My element is stored in a list array. in each cell of this array (array name is list) stored an element like below:
list[0] = document.getElementById("my_div_id");
list[1] = document.getElementById("my_div_id_1");
list[2] = document.getElementById("my_div_id_2");
...
list[n] = document.getElementById("my_div_id_n");
and I have a function like below in top of my Javascript code:
function say_hello(e, msg) {
if (e == null) e = window.event;
//now e handler mouse event in all browser !!!
alert (e + "::" + msg);
}
I have a function to add onclick event to each element in array. I add onclick event in type of below (separated with (*) comment) but doesn't work any of them:
function search_and_add_events_to_all_dragable_elements (list) {
for (var z = 0; z < list.length; z++) {
list[z].href = "javascript:;";
var e;
var test_msg = "VAYYYYYYYYYY";
/**************
element.onclick = new Function { alert ('hi'); };
element.onclick = new Function () { alert ('hi'); };
element.onclick = new function { alert ('hi'); };
element.onclick = new function () { alert ('hi'); };
element.onclick = new function () { return alert ('hi'); };
element.onclick = function () { return alert ('hi'); };
element.onclick = alert ('hi');
element.onclick = "alert ('hi');";
element.onclick = say_hello(e, test_msg);
element.onclick = "say_hello();";
element.onclick = (function (e, test_msg) { return function(e) { sib(e, test_msg); };
element.onclick = (function () { return function() { alert("ahaaay"); };
**************/
list[z].style["padding"] = "20px";
list[z].style["border"] = "solid 10px";
list[z].style["backgroundColor"] = "#CCC";
}
}
I change style in end of my code to perform my code is work and end truly. style change every time but onclick event doesn't add to my div.
only one way add onclick to my project. that is same as below:
list[z].setAttribute("onclick", "alert(\"hi\");");
but are there better ways?
There is a better way. My first mistake was using JavaScript before my all element load on my page. to solve it you must call element in end of page load or put your javascript code in end of your project. then your code execute exactly when your elements are exist in your page.
for more details about it see links below:
JavaScript that executes after page load
http://www.w3schools.com/jsref/event_onload.asp
My second mistake was hurt :(
I has a div that hold all of my other elements in itself. it was styled display: none; on load. when I call my function it was displayed none and all thins work well (like my new styling) but onclick event didn't work :(( and I spent two days to solve this :((
only be careful your element should not be display: none styled when you are adding your onclick event to it.
then you can use this type of creation onclick event dynamically to your project:
list[z].onclick = (function (e, test_msg) {
return function(e) {
sib(e, test_msg);
};
})(e, test_msg);
this is best way that I know. you can manage event handler and send your arguments also to your function.
I use several time another way of dynamically add onclick event in my project.

Categories

Resources