views:

834

answers:

2

Hi,

I've been observing some strange behavior with the following code:

$.fn.submit_to_remote = function() {
  // I use .each instead of the .submit directly so I can save
  // the 'submitEnabled' variable separately for each form
  jQuery.each($(this), function() {
    $(this).submit(function() {
      form = $(this);
      if (form.data('submitEnabled') == false) { alert('disabled'); return false; }
      form.data('submitEnabled', false);
      $.ajax({type: 'POST', url: 'url', data: data, dataType: 'script',
        success: function(script) {
          alert('success')
        }
      })
      return false;
    })
  })
}
$('.submit_to_remote').submit_to_remote();

So, basically, upon calling submit_to_remote on a form(s), it will disable it's normal submit and then make an AJAX POST request.

The strange thing is that the form gets posted multiple times, as the 'disabled' alert will show. As you can see, I'm preventing this by using a "variable" saved on the form object, and checking that variable to see if the form has already been submitted.

Upon further testing, it seems that the culprit is the script returned by the AJAX call. Let me explain a bit what I'm doing so it's more clear.

The form gets posted to the server, and a script returned. The script shows the form again, but this time with error messages for some fields. Note that the form is completely replaced.

The script, upon showing the new form, executes this:

$('.submit_to_remote').submit_to_remote();

I have to do that because otherwise, when you click on the submit button again, the form is submitted normally, no AJAX.

So, say a user submits the form and it's returned back with the appropriate errors (the 'disabled' alert is not shown). Then he submits it again; this time the 'disabled' alert is shown once. Now he submits it one more time, and this time the alert is shown twice! And so on...

So it would seem that the .submit callback is being appended again and again with each request, but why?

Could it be that by using .html() the original form is kept as a ghost or something?

Thanks!

PS: In case it's relevant, here's the script returned by the $.ajax call:

replace_content_with = 'the form and other stuff here';
$('.page-content').html(replace_content_with);
$('.submit_to_remote').submit_to_remote();
A: 

Not sure about this strange behavior, but seems that unbinding the submit event will do the trick.

So, before running the script returned by the $.ajax call, run this:

$('.submit_to_remote').unbind("submit");

That should remove previous bindings and leave just the new one.

Seb
I forgot to mention I tried that too, but that weirdly doesn't work because then the new form won't have the AJAX behavior, even do I'm re-binding it with the script...
Ivan
+2  A: 

Yes, I agree with Seb, it's a good practice, in my opinion to always unbind before binding unless you are certain that there aren't currently binds to your element that you want. You can double bind your stuff on accident by simply using the '.submit', '.click', '.mouseover', etc... functions.

Get into the habit of doing this (never fails for me):

$('.some_element').unbind('submit').bind('submit',function() {
    // do stuff here...
});

... instead of:

$('.some_element').submit(function() {
    // do stuff here...
});
KyleFarris