views:

122

answers:

4

Dear Stackoverflow,

I am seeking to perform a basic form post, but the following submits to the server twice in Chrome and Safari (but behaves as expected in Firefox):

<form id="create-deck-form" action="/decks/create" method="post">
  <fieldset>
    <legend>Create new deck</legend>
    <label for="deck-name-field">Name</label>
    <input id="deck-name-field" name="deck-name-field" type="text" value="" maxlength="140" />

    <label for="tag-field">Tags</label>
    <input id="tag-field" name="tag-field" type="text" value="" maxlength="140" />

    <input class="add-button" type="submit" value="Create" />
  </fieldset>
</form>

I would like to use the onsubmit attribute to perform validation on the fields before submission, but wherever the return value is true, the form is submitted twice.

I have sought to bind a jQuery handler to the form, but here too, where the default behaviour is not prevented, the form is submitted twice, e.g.:

<script type="text/javascript">
 $(document).ready(function() {
     $("#create-deck-form").submit(function(event){
          if($("#deck-name-field").val() == "") {
            event.preventDefault();
            alert("deck name required");
          }
        });
 });
</script>

While I suppose there is something blindingly obvious wrong here to a fresh pair of eyes, I am deeply confused why submission, with or without validation, makes a duplicate post to the server in Chrome and Safari. I'd be grateful for any insight.

A: 

Can you try return false; after your alert and remove event.preventDefault();. Maybe you also need return true; in your else-clause. I believe I have that working somewhere.

Koen
Thank you, Koen. Where validation fails, the behaviour is all good (and yes, either event.preventDefault(); or return false; perform as expected). Wherever validation passes the form is submitted twice. This is the case where the default behaviour is explicitly called (using an else-clause to return true) or implicitly called by not preventing the default/returning false (as in the code snippets above).
meg
Have you tried using a non-anonymous method (defining it with a name) and using it as an attribute, e.g.: <form ... onsubmit="return validationMethod();">. If that also posts twice, the problem is elsewhere in your code...
Koen
Sure did @Koen, thanks. Wasn't the form submission that cause the problem, just where the freakiness could be started from.
meg
+1  A: 

I'm not 100% sure, but please try this one:

<script type="text/javascript">
   $(document).ready(function() {
      $("#create-deck-form").submit(function(event){
         if(!$("#deck-name-field").val().length) {
           return false;
         }
       });
   });
</script>

if that does not work, please have a look at

for(e in $("#create-deck-form").data('events'))
    alert(e);

This will alert you all events which are bound to your form. Maybe there are more event handlers? Otherwise also alert/log

$("#create-deck-form").attr('onclick')

and

$("#create-deck-form").attr('onsubmit')

just in case.

jAndy
Yep pretty sure you need to return false to stop the browser default event happening as well
Tom
Thanks Andy and Tom. I think I may have confused the issue by mentioning the validation. Where validation fails I'm fine (event.preventDefault is equivalent to return false and both are fine) it is when the form submits with no validation issues that I get trouble. So, as I show above in the first code snippet, the basic form submission with no validation or JS involvement submits to the server twice.Great idea about checking for any rogue handlers associated with the form, Andy, I'll have a try.
meg
@meg: not exactly, returning `false` from an event handler triggers both, `preventDefault` plus `stopPropagation`.
jAndy
@Andy, I can confirm that there are no unexpected handlers bound to the form. @jAndy, I see! Thanks very much. Not sure how that helps with my current problem though. In my case I'm getting the unexpected behaviour when validation passes and therefore neither code preventing default behaviour nor returning false is hit.
meg
A: 

Ok, not sure how much this will help, but try removing the submit input and submitting the form via javascript. So for instance

<input id="submit-button" class="add-button" type="button" value="Create" />

Then instead of listening to the onsubmit, you can try

$('#submit-button').click(function(evt) {
    if(validationSuccess(...)) {
        $("#create-deck-form").submit();
    } else {
        //display whatever
    }
});

Now you're way should work too... but this way you can debug where you're problem is.... This should only submit once... good luck!

Java Drinker
Thanks JavaDrinker, I have indeed attempted this approach to no avail. I've been digging and it may be something much deeper in my app. I hope to resolve today and post the resolution.
meg
This maybe a dumb question but: how are you determining that your form is being submitted twice? I mean, what is the result of this "double submit"?
Java Drinker
@JavaDrinker I can see in my console print out that there are two requests to the server and there is a second deck visible in the datastore. Turns out wasn't the form submission, but that's where the behaviour could be kicked off - red herring!
meg
+2  A: 

This issue is actually associated with Facebox (http://defunkt.github.com/facebox/). Facebox initialization causes a second set of requests after your page loads. So, if you post to /myaction/create, Facebox will start a second set of requests with the base URL set to /myaction/create. A fix is to redirect to a URL which handles get requests after doing a post, so you don't end up performing the post twice. Thanks very much for your help.

meg