Ajax form submission with facebox
Mon Sep 08 20:02:00 UTC 2008
So you want a facebox that shows a form which does an asynchronous submission and updates the facebox with the results of the submission showing error or success messages.
Setting up the facebox.
Grab the files from famspam and install all the images, css and javascript.
Create a link that when clicked will display the facebox and set its rel attribute to 'facebox'. Create a div that contains what you want to show in the facebox and hide the div. Now set the href of that link you created to the id of the div.
link_to("Request an invitation", '#invitation_request', :rel => 'facebox')
<div id='invitation_request' style='display: none;'>
<form action='do/something' id='invitation_request_form'>
...
</form>
</div>
Add the javascript to tie it all together.
$('a[rel*=facebox]').facebox()
Asynchronize the form
At this point you have a facebox that works when the link is clicked. The form is still going to do a regular form submission. To make it an XHR post, grab the jquery.form plugin.
To hook it up to the form, you need the id of the form, which thanks to the way facebox works, is not unique within the dom. Facebox clones the div you created and places the clone within another generated div with the id facebox. If you follow the jquery.form instructions and do something like
$('#invitation_request_form').ajaxForm({
success: function(html){
$('#invitation_request').html(html);
}
});
your form submission will still not be asynchronous. That’s because the jQuery selector '#invitation_request_form' is ambiguous within the dom. Make it more specific by using the generated facebox div to ensure the ajaxForm function binds to the correct form.
$('#facebox #invitation_request_form').ajaxForm({
success: function(html){
$('#facebox #invitation_request').html(html);
}
});
Attack of the clones
Let’s say you want to insert the response from the form submission back into the facebox. This way you can redisplay the form with any appropriate error messages or maybe a success message. You’ll run into the same clone issue when specifying the div whose html is to be replaced. Be sure to focus the jQuery selector syntax using the facebox div the same way you did for the form.
That second form submission
Now the form will submit asynchronously and the response will render within the correct div. If you submit the form a second time, however, the request will not be asynchronous. This is because the form is replaced by the first ajax call and the new form does not have the ajaxForm function bound to it. The jQuery livequery plugin solves this final problem by ensuring that even when the form is dynamically inserted into the dom, the ajaxForm function gets bound to it.
$('#facebox #invitation_request_form').livequery(function() {
$(this).ajaxForm({
success: function(html){
$('#facebox #invitation_request').html(html);
}
});
});