Avoid double submissions on HTML forms

Some users still live in era of Windows 95 where you had to do double-click to make something happen. And this double-clicking goes with them when they go online. So they double-click on links, double click on submit buttons… Wait? did you just double-clicked that button? submitted the form twice? OOPS!

There are a lot of advice online how to stop this happening, but I have not found a complete solution. Here is my stub at this (using jQuery):

$(':submit').click(function () {
    var $button = this;
    var oldValue = $button.value;
    var oldHtml = $button.innerHTML;
    setTimeout(function () {
        $button.disabled = true;
        if (oldValue) {
            $button.value = 'One moment...';
        }
        if (oldHtml) {
            $button.innerHTML = 'One moment...';
        }
        setTimeout(function () {
            $button.disabled = false;
            if (oldValue) {
                $button.value = oldValue;
            }
            if (oldHtml) {
                $button.innerHTML = oldHtml;
            }
        }, 3000);
    }, 0);
});

What are we doing here? seems like too much code for a simple task. A lot of advice goes to e.preventDefault() but that stops the form submission. Some people recommend adding form.submit() after the preventing default action. That smells. What if I did not want to submit the form, but some other event was triggered on click? If you just disable the button on click – your form will not be submitted because disabled html elements are not submitted.

In this snippet I’m delaying button disabling. This gives a chance to other events to fire – I don’t need to submit the form manually. And inside that timeout I’m setting another delayed function to re-activate the function. Because in era where JavaScript is executed on servers (node.js, I’m looking at you!), it is just plain wrong not to do a validation on a client. So in case when the validation has failed, I re-enable the button again so user can re-submit.

I’ve tried that in latest (17 Dec 2014) Chrome and in IE9 in both cases works as expected. Let me know how this can be improved!

UPDATE 29 Feb 2016

Added support for button html elements along with existing input elements. Made the code quite ugly, but we don’t want to set innerHTML for input element because it should not have one.