Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does addEventListener fire before the event if at all? [duplicate]

I was experimenting [in jsfiddle] w/a function created to append a newly created TextNode to the <p> in the HTML below:

    <button onclick="addTextNode('YES! ');">YES!</button>
    <button onclick="addTextNode('NO! ');">NO!</button>
    <button onclick="addTextNode('WE CAN! ');">WE CAN!</button>
    <hr />
    <p id="p1">First line of paragraph.</p>

Here is my javascript as well:

    function addTextNode(text) {
        var newtext = document.createTextNode(text),
            p1 = document.getElementById("p1");

        p1.appendChild(newtext);
    }

This works fine. However, the crux reveals itself when I attempt to make my javascript 'unobtrusive' by removing the behavior from the markup...

    <button>YES!</button>
    <button>NO!</button>
    <button>WE CAN!</button>
    <hr />
    <p id="p1">First line of paragraph.</p>

then utilizing a loop to attach addEventListener to each <button> element, which in turn uses the child TextNode to call addTextNode:

    function addTextNode(text) {
        var newtext = document.createTextNode(text),
            p1 = document.getElementById("p1");

        p1.appendChild(newtext);
    }

    var btns = document.getElementsByTagName("button");

    for(i = 0; i < btns.length; i++){
        var button = btns[i]; 
        button.addEventListener("click", addTextNode(button.innerHTML));
    }

Two strange things happen with my code:
When [jsfiddle's] Code Wrap is set to 'no wrap - in head', nothing happens.

However, When Code Wrap is set to 'onLoad', 'onDomReady' or 'no wrap - in body' the function runs before the click and I get this.

Could someone tell me what I'm missing?

like image 575
Wilhelm Avatar asked May 22 '14 19:05

Wilhelm


People also ask

Why is event listener firing multiple times?

This symptom is indicative that you've registered the same listener more than once. You must remember to deregister events when your component unloads to prevent his problem.

What happens if you call addEventListener multiple times?

If you call addEventListener() twice on the same element, the listener will run twice.

What happens if you add the same event listener twice?

If the same event listener function is registered twice on the same node with the same type and useCapture arguments, the second registration is simply ignored. ...

Can you have multiple event listeners for the same event?

The addEventListener() methodYou can add many event handlers to one element. You can add many event handlers of the same type to one element, i.e two "click" events. You can add event listeners to any DOM object not only HTML elements.


2 Answers

The root of your problem is here:

button.addEventListener("click", addTextNode(button.innerHTML))

You're executing the function rather than passing it to the event listener. Instead, pass the function by reference, then get the innerHTML inside the function.

function addTextNode() {
    var newtext = document.createTextNode(this.innerHTML),
        p1 = document.getElementById("p1");

    p1.appendChild(newtext);
}

var btns = document.getElementsByTagName("button");

for(i = 0; i < btns.length; i++){
    var button = btns[i]; 
    button.addEventListener("click", addTextNode);
}

http://jsfiddle.net/bn85J/

like image 178
Kevin B Avatar answered Oct 18 '22 21:10

Kevin B


First, your usage of Add Event listener is wrong. add event listener is expecting a function reference in the second parameter not a function call.

The following is a function reference:

var myfunctionreference = addTextNode;

This is a function call and will execute the function

var myfunctioncall = addTextNode();

In your code you are actually calling the function to use as the event handler instead of referencing it. Here is some Reference for .addEventListener()

You should be binding the event like this:

button.addEventListener("click", addTextNode);

Second, the event knows the element and knows the event. Your function call should be created to accept the event and not an arbitrary string. Then utilizing the event or "this" will allow you to get your hands on the text your looking for.

function addTextNode(evt) {
    var newtext = document.createTextNode(this.innerHTML),
        p1 = document.getElementById("p1");

    p1.appendChild(newtext);
}
like image 1
John Hartsock Avatar answered Oct 18 '22 20:10

John Hartsock