I keep getting duplicate entries in my database because of impatient users clicking the submit button multiple times.
I googled and googled and found a few scripts,
One technique I've seen used is to assign a unique ID to every form that's opened, and only accept one submission per form based on the ID.
It also means you can check how many times people aren't bothering to submit at all, and you can check if the submission genuinely came from your form by checking if it's got an ID that your server created.
I know you asked for a javascript solution, but personally I'd do both if I needed the robustness.
Preventing the double posting is not so simple as disabling the submit button. There are other elements that may submit it:
Using jQuery data container would be my choice. Here's an example:
$('#someForm').submit(function(){
$this = $(this);
/** prevent double posting */
if ($this.data().isSubmitted) {
return false;
}
/** do some processing */
/** mark the form as processed, so we will not process it again */
$this.data().isSubmitted = true;
return true;
});
The problem with the method described here is that if you're using a javascript validation framework and the validation fails, you won't be able to correct and re-submit the form without refreshing the page.
To solve this, you need to plug into the success event of your validation framework and only then, set the submit control to disabled. With Parsley, you can plug into the form validated event with the following code:
$.listen('parsley:form:validated', function(e){
if (e.validationResult) {
/* Validation has passed, prevent double form submissions */
$('button[type=submit]').attr('disabled', 'disabled');
}
});
That is what I did to solve the problem.
I disabled the button for a second with adding setTimeout twice:
- the 1st time is to let the JS form fields verification work;
- the 2nd time is to enable the button in case if you have any verification on your back end, that may return an error, and hence the user will want to try to submit the form again after editing his data.
$(document).ready(function(){
$('button[type=submit]').on("click", function(){
setTimeout(function () {
$('button[type=submit]').prop('disabled', true);
}, 0);
setTimeout(function () {
$('button[type=submit]').prop('disabled', false);
}, 1000);
});
});
How about disabling the button on submit? That's what I do. It works fine.
$('form').submit(function(){
$('input[type=submit]', this).attr('disabled', 'disabled');
});
Disclaimer:
This only works when javascript is enabled on the user's browser. If the data that's being submitted is critical (like a credit card purchase), then consider my solution as only the first line of defense. For many use cases though, disabling the submit button will provide enough prevention.
I would implement this javascript-only solution first. Then track how many duplicate records are still getting created. If it's zero (or low enough to not care), then you're done. If it's too high for you, then implement a back-end database check for an existing record.
This is what I came up with in https://github.com/liberapay/liberapay.com/pull/875:
$('form').on('submit', function (e) {
var $form = $(this);
// Check that the form hasn't already been submitted
if ($form.data('js-submit-disable')) {
e.preventDefault();
return false;
}
// Prevent submitting again
$form.data('js-submit-disable', true);
// Set a timer to disable inputs for visual feedback
var $inputs = $form.find(':not(:disabled)');
setTimeout(function () { $inputs.prop('disabled', true); }, 100);
// Unlock if the user comes back to the page
$(window).on('focus pageshow', function () {
$form.data('js-submit-disable', false);
$inputs.prop('disabled', false);
});
});