javascriptjqueryjquery-callback

jquery 'on' not working


I've a statically created table:

<table id="table" style="width:100%">
    <tbody id="tbody">
    </tbody>
</table>

I've dinamically created some elements:

var tbody = document.getElementById('tbody');   

for (var i = 0; i < 8; i++) {
    var tr = document.createElement('tr');
    for (var j = 0; j < 8; j++) {
        var td = document.createElement('td');
        td.appendChild( createDiv(i,j)); // div id is = i + ' ' + j
        tr.appendChild(td);
    }
    tbody.appendChild(tr);
}

But now I'm trying to add a callback function for each div, but this is not working. I think that the problem is with the jquery on function but I don't know how to solve it.

for(var x=0;x<8;x++){
    for(var y=0;y<8;y++){
        $(document.body).on('mousedown', '#' + x + ' ' + y, function(){
            var audio = document.getElementById('audio');

            audio.currentTime = 0;
            audio.play(); 
        });
    }
}

When I try to do the same with static elements it works fine, does anybody know what is happening? Thanks


Solution

  • There are other answers here that are correct in their answer, but I wanted to add a bit more clarification.

    The purpose of jQuery's on() is to attach event handlers to selected elements. The purpose of the selector parameter is to create a delegated handler. From the jQuery documentation:

    The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector.

    In addition:

    Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.

    (I would recommend you read the whole section on Direct and delegated events by the way.)

    In any case, for your particular example, you want to build your DOM in such a way that there is a top-level element that is guaranteed to exist at the time the delegated event is attached. It may be your table, or a div element above your table. You could also attach to the body or the document, but, it is better to attach the event to the closest element that will be guaranteed to exist per this documentation:

    Attaching many delegated event handlers near the top of the document tree can degrade performance. Each time the event occurs, jQuery must compare all selectors of all attached events of that type to every element in the path from the event target up to the top of the document. For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.

    In your particular case, it appears that the table is a guaranteed element. Because of that, you can attach to that and delegate the divs that are inside. (Of course, appropriate adjust your selectors to get the correct divs.) Assuming you want all divs to bubble up, then your attachment would be something like this:

    $('#table').on('mousedown', 'div', function(e) {
      console.log('Do some stuff here.');
    });
    

    Of course, you'll want to do this inside the document ready handler to ensure that your elements are present.

    Also, be aware that IDs cannot start with a number in the HTML 4 spec. If you are developing HTML 5, however, IDs can basically be anything as long as they are unique, don't contain any spaces, and are at least a single character.