Search code examples
javascriptevent-handlingdelegation

Are multiple elements each with an addEventListener allowed?


I would like the specified function to be called only if the correct button is clicked on.

function callback(func){
func();
}

The main function(s) and their results:

Attempt A:

document.addEventListener('DOMContentLoaded', function () {

document.getElementById('num1').addEventListener('click', callback(function1));
document.getElementById('num2').addEventListener('click', callback(function2));

});

Result: Opening the page and clicking any of the buttons will run function1

Attempt B:

document.addEventListener('click', function () {

document.getElementById('num1').addEventListener('click', callback(function1));
document.getElementById('num2').addEventListener('click', callback(function2));

});

Result: Clicking anywhere on the page will run function1

Attempt C:

document.getElementById('num1').addEventListener('click', callback(function1));
document.getElementById('num2').addEventListener('click', callback(function2));

Result: Opening the page and clicking on the buttons will run function1 and reload the page

Attempt D:

document.addEventListener('click', function () {

//The first ID doesn't exist
document.getElementById('imaginaryNum1').addEventListener('click', callback(function1));
document.getElementById('num1').addEventListener('click', callback(function1));
document.getElementById('num2').addEventListener('click', callback(function2));

});

Result: Clicking anywhere on the page will run function1

Attempt E:

//The first ID doesn't exist
document.getElementById('imaginaryNum1').addEventListener('click', callback(function1));
document.getElementById('num1').addEventListener('click', callback(function1));
document.getElementById('num2').addEventListener('click', callback(function2));

Result: Opening the page and clicking on the buttons will run function1 and reload the page


Solution

  • Sure, why wouldn't it be. Looking at your code, though, you might be better of delegating the event: it's not that hard. Basically, listen for the event you need on a level in the dom that contains each of the individual elements, and write your handler in such a way that you check if the element that fired the event is of interest, if so: handle the event, if not, just return.
    You're also missing the third argument, that addEventListener expects: a boolean, indicating weather you want to handle the event during the capturing phase, or the bubbling phase, read a couple of articles on quirksmode, in particular on the distinct phases

    I've also noticed that you're doing weird things with your handler function, you're going to have some issues with that. Basically, what addEventListener expects as a second argument is a reference to a function, you're passing the return value of a function (which is undefined in your case).

    function clickHandler(e)//accept event argument
    {
        e = e || window.event;
        var target = e.target || e.srcElement;
        if (!target.id.match(/num[0-9]/))
        {//the clicked element doesn't have num1, num2, num3... as id, no need to handle this event
            return e;
        }
        //handle event. target is a reference to the clicked element
    }
    document.body.addEventListener('click',clickHandler,false);//<-- just the function name, no parentheses
    

    That's all you need, one listener that'll handle all click events.

    Here are a couple of JS questions that I've posted that deal with event delegation, take a look at the code, read the articles I linked to, you'll soon work it out.
    delegating the change event in IE -- tricky
    avoid mem-leaks in IE<9 with onload listener: my answer to the question
    Augmenting the event prototype in IE<9 using delegation