Javascript – Debounce clicks when submitting a web form

htmljavascriptprototypejs

A poorly-written back-end system we interface with is having trouble with handling the load we're producing. While they fix their load problems, we're trying to reduce any additional load we're generating, one of which is that the back-end system continues to try and service a form submission even if another submission has come from the same user.

One thing we've noticed is users double-clicking the form submission button. I need to de-bounce these clicks, and prevent a second form submission.
My approach (using Prototype) places an onSubmit on the form that calls the following function which hides the form submission button and displays a "loading…" div.

function disableSubmit(id1, id2) {
    $(id1).style.display = 'none';
    $(id2).style.display = 'inline';
}

The problem I've found with this approach is that if I use an animated gif in the "loading…" div, it loads fine but doesn't animate while the form is submitting.

Is there a better way to do this de-bouncing and continue to show animation on the page while waiting for the form result to (finally) load?
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

Best Solution

Using Prototype, you can use this code to watch if any form has been submitted and disable all submit buttons when it does:

document.observe( 'dom:loaded', function() { // when document is loaded
    $$( 'form' ).each( function( form ) { // find all FORM elements in the document
        form.observe( 'submit', function() {  // when any form is submitted
            $$( 'input[type="submit"]' ).invoke( 'disable' );  // disable all submit buttons
        } );
    } );
} );

This should help with users that double-click on submit buttons. However, it will still be possible to submit the form any other way (e.g. pressing Enter on text field). To prevent this, you have to start watching for any form submission after the first one and stop it:

document.observe( 'dom:loaded', function() {
    $$( 'form' ).each( function( form ) {
        form.observe( 'submit', function() {
            $$( 'input[type="submit"]' ).invoke( 'disable' );
            $$( 'form' ).observe( 'submit', function( evt ) { // once any form is submitted
                evt.stop(); // prevent any other form submission
            } );
        } );
    } );
} );