views:

1028

answers:

4

I asked a similar question earlier http://stackoverflow.com/questions/1610752/how-can-i-have-jquery-attach-behavior-to-an-element-after-inserting-it, but still have not found an answer. To keep things clear I am asking a new question with a different example.

Here is my code that doesn't work.

$(document).ready(function() {  
 $('form.edit_color').live('submit',  function(){
 var form = $(this).closest('form');
 var colorRow = $(this).closest('tr');
    var action = $(form).attr('action');
    var formData = $(form).serialize();
 $(colorRow).fadeOut();
   $.post(action, formData,
    function(data) {
        $(form).replaceWith(data);
  $(colorRow).fadeIn();   
    });
    return false;
  });
});

What happens is this, for each of my forms I can submit them through ajax and replace it with the updated form. But, then nothing happens when I click the new submit button.

+1  A: 

As answered in your original question, live simply does not work with the submit event.

Note also the $(colorRow).fadeIn(); in your callback function can't possibly work as it is referring to the colorRow that existed in the form at the time submit occurred. But you have completely removed and replaced that colorRow with a new one in the preceding replaceWith call. After the replace, the form and colorRow variables don't point to anything useful.

live is a bit of a hack that doesn't quite mesh with how events actually work in HTML. Try to avoid having to use it. Replacing large parts of your page with new markup is often a bad move. If you can update the content of existing elements in the form from a JSON return value rather than passing back a katamari of HTML: then you won't need to worry about rebinding events or keeping references to now-dead DOM objects.

(If you must pass back HTML, at least return only the contents of the form, and not the form tag itself. Then you can use html() to set the form content; by not replacing the form tag itself, you don't have to worry about re-binding the submit event on it.)

bobince
but I am not replacing the colorRow, just the Form inside it, and it's a small form
ToreyHeinz
Also I just implemented the same code elsewhere and it worked... I think the difference was that in this case my form is improperly contained some table elements.
ToreyHeinz
Ah, OK, cool. Yeah, that will happen: you can't set `innerHTML` on a table in IE, so jQuery has a workaround but because it only triggers when the element you're creating is a table-child like `tr` or `tbody`. jQuery is assuming that you'll only be nesting in an HTML-valid way, which is probably fair enough.
bobince
+1  A: 

To add to bobince, live uses event delegation technique to 'attach' events. It works on a basis that all events eventually propagate to the highest parent in DOM (window.document) so if you attach just a single event handler to document and then run different event handlers based on the original target of the event.

Some events however, do not propagate. submit is one of them. So you can't use event delegation there.

Chetan Sastry
A: 

I was thinking livequery did handle submit events, but when I was having problems with that as well, I figured I would just live() as well.

I was also having problems finding the form, when I tried to bind to the click event of the submit button.

As I was inspecting my submit button in firebug I realized the it was not being shown as a child of my form. That got me thinking that if firebug couldn't figure out that my submit button was a child element of my form, what kind of trouble was jQuery having (and maybe the W3C validator was complaining for a reason).

So I tried the same code as above on a different form that I had inside a div tag instead, and it worked, so I quickly removed the table tags from form for this question and amazingly it worked too.

My solution will be to take the extra time to make my html valid, and to go with what is not suppose to work until jQuery 1.3.3, http://docs.jquery.com/Release%3AjQuery_1.3.2.

Below is my current code, I will need to figure out to properly markup the form.

$('form.edit_color').live('submit', function(){ var form = $(this); var colorRow = $(this).closest('div.color_form'); var action = $(form).attr('action'); var formData = $(form).serialize(); $(colorRow).fadeOut(); $.post(action, formData, function(data) { $(form).replaceWith(data); $(colorRow).fadeIn();
}); return false; });

<div class="color_form">
<% form_for color, :url => admin_color_path(color) do |f| -%>
 <div style="background: #<%= color.value %>"></div>
  <div><%= f.text_field :title %></div>
   <div><input type="text" size="30" name="color[value]" class="colorpickerfield" value="<%= color.value %>" /></div>
    <div style="text-align:left">
     <% Color.types.each do |type, name| %>
      <div>
       <%= color_types_checkbox(color, type) %>
       <%= name %>
      </div> 
     <% end %>
    </div>
   <div>
  <%= f.submit "Update", :class => 'submit' %>
 </div>
<% end %>
</div>
ToreyHeinz
A: 

$('form').live('submit', function(e) { alert(e.type); e.preventDefault(); });

$('form :submit').live('click', function(e) { $(this.form).submit(); e.preventDefault(); });

한국인