views:

516

answers:

4

I am very new at jQuery ... I've used Javascript many times and am quite familiar with DOM manipulation but simply not the API or gears of jQuery.

I am dynamically adding DOM elements via a JSON call like so:

$(document).ready(function() {
        var url = "jsonMenuItems.js";
        $.getJSON(url, null, function(data) {
            var html = "";
            //alert(data.items);
            data = data.items;
            for (var key in data) {      
                html += "<td class=\"menuItem\"><span>" + data[key].name + "</span></td>";
            };
            $("#menuTR").html(html);
        });

        var lZeroArray = $("#menu td");
        lZeroArray.click(function() {
            $("#submenu").slideDown("fast");
        });
    });

If the TD items are on the page manually the click function slideDown works perfectly ... if I use the above code to dynamically add the TD items then the click function slideDown does not fire.

jQuery cannot find it's own added items or am I doing something wrong?

+3  A: 

Take a look at jQuery live. This will let you bind events to dynamically added items.

$("#menu td").live("click", function(){
    $("#submenu").slideDown("fast");
});
tribus
+1 live() available in 1.3 onwards. Or there is a plugin if using 1.2 like I do.
Wayne Khan
Thank you very much ... this worked. There was another live answer but yours is dated first so you get the answered check.
webwires
+1  A: 

It looks like you're adding the click event to the wrong elements. You're adding the dynamically added TDs to an element with id="menuTR", but you're setting the click event on TD elements that are descendants of id="menu"

To test, try changing $("#menu td") to $("#menuTR td"), or vice versa. Alternately, you could try selecting the elements with $("td.menuItem"), which selects all TD elements with a class of menuItem.

Sean Nyman
-1 No, webwires has stated that the selector works correctly -- the click function slideDown works perfectly.
Wayne Khan
Ah, but when he tested the click function he put the TDs on the page manually, so he wouldn't have changed the existing enclosing element (with an id of "menu", presumably).
Sean Nyman
I reverse my vote. He used #menuTR append(), but then the event handler is binded to #menu td.
Wayne Khan
+5  A: 

the problem is: your event handler is bound to $('#menu td'), but at the time that this is done, there are no tds in the #menu!

using live() makes sure that jquery adds event handlers to objects added later on to the DOM.

Alternatively, a solution used in older jquery versions would be:

    var url = "jsonMenuItems.js";
    $.getJSON(url, null, function(data) {
        var html = "";
        //alert(data.items);
        data = data.items;
        for (var key in data) {
                  html += "<td class=\"menuItem\"><span>" + data[key].name + "</span></td>";
        };
        $("#menuTR").html(html);
        $("#menu td").click(function() { 
           $("#submenu").slideDown("fast");
        });
    });
    var lZeroArray = $("#menu td");
    lZeroArray.click(function() { 
       $("#submenu").slideDown("fast");
    });
Here Be Wolves
+1 for actually explaining why the posted code does not work
matt b
Grrr... 'A new answer has appeard (that is the same as yous)'
SeanJA
A: 

That is because you have to reapply the click functionality to them after they are created:

$.getJSON(url, null, function(data) {
        var html = "";
        //alert(data.items);
        data = data.items;
        for (var key in data) {      
            html += "<td class=\"menuItem\"><span>" + data[key].name + "</span></td>";
        };
        $("#menuTR").html(html);

        $("#menu td").click(function() {
            $("#submenu").slideDown("fast");
        });

    });
SeanJA