7

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.

Roman C
  • 49,761
  • 33
  • 66
  • 176
meg
  • 151
  • 2
  • 10
  • Is there anything else involved? Are there any "click" handlers that explicitly invoke "submit()" on the form, for example? – Pointy Jul 06 '10 at 12:55
  • Thanks, Pointy. No, it is perfectly bare bones at the moment, with no other handlers bound to the form or its buttons. – meg Jul 06 '10 at 12:58
  • Do you have an example page or post the contents of your page somewhere (all HTML and JS), so we can have a look? – Marcel Korpel Jul 06 '10 at 13:06
  • OK, well hmm. OK now my next question is this: What is it that has convinced you that the form has been submitted twice? (I'm not trying to deny what you're seeing, but the thing is that code all looks more-or-less OK to me, so I'm just trying to get more of the complete picture.) – Pointy Jul 06 '10 at 13:07
  • 1
    The more I think about this the weirder it seems. I don't know how I'd make a form get posted twice if I *wanted* it to happen (well without wiring up the form to an AJAX submission mechanism). – Pointy Jul 06 '10 at 13:19
  • @Marcel The live site is www.braineos.com. You'd need to log in (with OpenId) to create a new deck of flashcards. The form is on your profile page, though its code is slightly different as it is using the onsubmit attr (I'm 'fixing' this bug in Chrome and Safari today so the live code isn't the same as my dev stuff posted here) – meg Jul 06 '10 at 13:29
  • @Pointy I know the form is submitted twice because I can see the url being hit twice in my dev console and I can also see a phantom deck is created on dev (and live) apps when deck create is done through Chrome/Safari. My AJAX forms run pretty sweet especially as I'm moving over to jQuery form plugin this week, it is just this particular form that is killing me. – meg Jul 06 '10 at 13:31
  • Could it be that the enter key needs to be blocked from submitting? – Mottie Jul 06 '10 at 13:52
  • 1
    @meg is it possible that some Javascript file that the page is importing might be attaching something to the form or to the buttons, or whatever? Could you (experimentally) try omitting some of the script files to see if that makes a difference? Of course, it's not clear why that'd cause different behavior between Chrome and FF, but this is a weird issue anyway. – Pointy Jul 06 '10 at 13:58
  • @fudgey Thanks! I'm not doing any keypress management JS/jQuery at the moment on this form and simply using the browser's default behaviour for input type='submit'. I have been wondering if submit inputs are fundamentally 'weird' in Chrome/Safari, but w3C says that submit inputs are supported in those browsers and Googling around the issue hasn't shown me that there are known probs in that regard. What gets me is that the most basic post doesn't behave right! It must be something so ridiculous that I'm just not seeing. – meg Jul 06 '10 at 14:00
  • @Pointy, my JS is concatenated and minified but I have confirmed that there are no other handlers associated with the form or any of its elements. – meg Jul 06 '10 at 14:02
  • Well you've apparently drifted off into the Twilight Zone somehow. I hope you find a solution. – Pointy Jul 06 '10 at 14:06
  • 1
    @Pointy! I tore out all the concatenated JS and something, somewhere is doing something to my form, unbidden! I'll let you know when it is rolling. I just *know* it is something deeply stupid ;) – meg Jul 06 '10 at 14:08
  • That's good news. Isn't there a Sherlock Holmes quote about how the answer to a mystery is never that something impossible has happened? :-) – Pointy Jul 06 '10 at 14:30
  • Hmmm, ok did you try disabling the submit button after the validation clears it? (e.g. http://stackoverflow.com/questions/903550/properly-disabling-the-submit-button/903563#903563) – Mottie Jul 06 '10 at 16:49
  • Thanks for that link @fudgey, could come in handy, unhappily this is not a case of multiple invocations of the submit input. @Pointy after a break at the gym and a shot of Mount Gay I have found the root of all evil. The page that is loaded by the server after the submission includes a button which opens a facebox. When the facebox initialisation happens onload ($("#megs-button").facebox();) a second request posts to the url which is pointing at my deck-creation server (I'm sorry if this lacks context and doesn't make sense). Removed all JS and worked backwards to here - thanks for your help! – meg Jul 06 '10 at 19:19

4 Answers4

3

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
  • 151
  • 2
  • 10
  • 1
    I seem to have the same problem, do you have the code (or a global description) of your solution, how did you redirect the get after the post? – michel.iamit Aug 19 '11 at 09:09
1

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
  • 231,737
  • 57
  • 305
  • 359
  • Yep pretty sure you need to return false to stop the browser default event happening as well – Tom Jul 06 '10 at 13:06
  • 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 Jul 06 '10 at 13:11
  • @meg: not exactly, returning `false` from an event handler triggers both, `preventDefault` plus `stopPropagation`. – jAndy Jul 06 '10 at 13:14
  • @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 Jul 06 '10 at 13:20
0

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
  • 3,626
  • 1
  • 34
  • 55
  • 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 Jul 06 '10 at 13:08
  • Have you tried using a non-anonymous method (defining it with a name) and using it as an attribute, e.g.:
    . If that also posts twice, the problem is elsewhere in your code...
    – Koen Jul 06 '10 at 13:42
  • Sure did @Koen, thanks. Wasn't the form submission that cause the problem, just where the freakiness could be started from. – meg Jul 08 '10 at 06:50
0

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
  • 3,127
  • 1
  • 21
  • 19
  • 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 Jul 07 '10 at 08:13
  • 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 Jul 07 '10 at 14:50
  • 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 Jul 08 '10 at 06:49