tags:

views:

345

answers:

2

I'm kind of new to this so please bear with me...

Let's say I have this javascript code

$(document).ready(function() {
    $("a").click(function() {
        alert("Hello world!");
    });
});

The way I understand it, this code will "capture" any link selection and post an alert box. Normally this works fine.

Now, on the same page I also have a table, and on submit, I'm capturing the form submit and using JQuery to add the row to the users display while the data is sent to the server.

Here's the code to intercept the post request (mostly taken from Railscasts #136)

jQuery.ajaxSetup({
    'beforeSend': function(xhr) {
        xhr.setRequestHeader("Accept", "text/javascript")
    }
})

jQuery.fn.submitWithAjax = function() {
    this.submit(function() {
        $.post(this.action, $(this).serialize(), null, "script");
        return false;
    })
    return this;
};

$(document).ready(function() {
    $("#new_ride_form").submitWithAjax();
})

Here's the code to render the partial...

$("#add_new_ride").before("<%= escape_javascript(render(:partial => @ride)) %>");
$("#ride_<%[email protected] %>").effect("highlight", {color: '#aaffaa'}, 2000);
$("#new_ride_form")[0].reset();

Here's the code to create a link in one of the table cells generated by the partial

<td><%= link_to  'remove', ride_url(ride),
   :id => :destroy_ride,
   :method => :delete,
   :href => delete_ride_url(ride) %>
</td>

Now when I submit the form, then click on the 'remove' link in the newly created table row, it simply submits the delete request. The javascript to create the 'Hello World' alert box is not executed.

If however, I submit the form, create the new table row, then manually refresh the page, before clicking the 'remove' link in the newly created table row, the the 'Hello World' alert box appears as expected.

What's going on here where I need to manually refresh before getting the expected behavior?

Is there a "document.ready" event or something I need to trigger after using AJAX to add the table row in order to tell the code that "hey, there's some new stuff over here you need to watch for".

Thanks!

By the way, I'm coding in Rails and JQuery, but I'm not really sure it matters.

+4  A: 

It sounds like you want to use jQuery.live instead of jQuery.click. The difference is that jQuery.click will bind the click event for all current <a> elements, and jQuery.live will bind all of the current and future elements.

$(document).ready(function() {
    $("a").live("click", function() {
        alert("Hello world!");
    });
});
William Brendel
beat me to it by 22 seconds! :-(
Kip
jQuery.live is a great answer but since it functions differently than a traditional bind and not all events are supported it's important to read up on it and ensure it satisfies your needs.
Doomspork
Thanks! This was exactly what I needed.
Vinnie
A: 

The first code in your example gets called first so links created by your AJAX call are not bound. The easiest way to fix that is wrap the bind in a function. Call it on document.ready and then call it again after your AJAX loads.

Like this:

$(document).ready(function() { bind_links(); });

function bind_links() {
    $("a").click(function() {
        alert("Hello world!");
    });
}

Then in your AJAX add a call back to bind the link that gets created:

jQuery.fn.submitWithAjax = function() {
    this.submit(function() {
        $.post(this.action, $(this).serialize(), function() { bind_links(); }, "script");
        return false;
    })
    return this;
};
Cfreak
This is kind of wasteful since each bind_links() call will have to transverse the DOM for element it has previously found. You could bind to the new link in your callback.
Doomspork