Debounce clicks when submitting a web form - javascript

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?
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

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
} );
} );
} );
} );

All good suggestions above. If you really want to "debounce" as you say, then I've got a great function for that. More details at unscriptable.com
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
};
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || 100);
};
}

If you've got jQuery handy, attach a click() event that disables the button after the initial submission -
$('input[type="submit"]').click(function(event){
event.preventDefault();
this.click(null);
});
that sort of thing.

You could try setting the "disabled" flag on the input (type=submit) element, rather than just changing the style. That should entirely shut down the from on the browser side.
See: http://www.prototypejs.org/api/form/element#method-disable

Here I have a simple and handy way to prevent duplicate or multiple form submittion.
Give a class "prevent-mult-submit-form" to the desired form and another class to the submit button "disable-mult-click". You can aslo add a font awesome spinner like
<i class="spinner hidden fa fa-spinner fa-spin" style="margin-right: 2px"></i>
Now pest the code below inside script tag. you are good to go.
$('.prevent-mult-submit-form').on('submit', function(){
$('.disable-mult-click').attr('disabled', true)
$('.spinner').removeClass('hidden')
})

Submit the form with AJAX, and the GIF will animate.

Related

Submitting POST Request only once [duplicate]

I have a submit button at the end of the form.
I have added the following condition to the submit button:
onClick="this.disabled=true;
this.value='Sending…';
this.form.submit();"
But when it moves to the next page, the parameters did not pass and null values are passed.
You should first submit your form and then change the value of your submit:
onClick="this.form.submit(); this.disabled=true; this.value='Sending…'; "
Probably you're submitting the form twice.
Remove the this.form.submit() or add return false at the end.
you should end up with onClick="this.disabled=true; this.value='Sending…';"
tested on IE11, FF53, GC58 :
onclick="var e=this;setTimeout(function(){e.disabled=true;},0);return true;"
You need to disable the button in the onsubmit event of the <form>:
<form action='/' method='POST' onsubmit='disableButton()'>
<input name='txt' type='text' required />
<button id='btn' type='submit'>Post</button>
</form>
<script>
function disableButton() {
var btn = document.getElementById('btn');
btn.disabled = true;
btn.innerText = 'Posting...'
}
</script>
Note: this way if you have a form element which has the required attribute will work.
Disabled HTML forms elements aren't sent along with the post/get values when you submit the form. So if you disable your submit button once clicked and that this submit button have the name attribute set, It will not be sent in the post/get values since the element is now disabled. This is normal behavior.
One of the way to overcome this problem is using hidden form elements.
the trick is to delayed the button to be disabled, and submit the form you can use
window.setTimeout('this.disabled=true',0);
yes even with 0 MS is working
Using JQuery, you can do this..
$("#submitbutton").click(
function() {
alert("Sending...");
window.location.replace("path to url");
}
);
If you disable the button, then its name=value pair will indeed not be sent as parameter. But the remnant of the parameters should be sent (as long as their respective input elements and the parent form are not disabled). Likely you're testing the button only or the other input fields or even the form are disabled?
Here's a drop-in example that expands on Andreas Köberle's solution. It uses jQuery for the event handler and the document ready event, but those could be switched to plain JS:
(function(document, $) {
$(function() {
$(document).on('click', '[disable-on-click], .disable-on-click', function() {
var disableText = this.getAttribute("data-disable-text") || 'Processing...';
if(this.form) {
this.form.submit();
}
this.disabled = true;
if(this.tagName === 'BUTTON') {
this.innerHTML = disableText;
} else if(this.tagName === 'INPUT') {
this.value = disableText;
}
});
});
})(document, jQuery);
It can then be used in HTML like this:
<button disable-on-click data-disable-text="Saving...">Click Me</button>
<button class="disable-on-click">Click Me</button>
<input type="submit" disable-on-click value="Click Me" />
I don't think you need this.form.submit(). The disabling code should run, then it will pass on the click which will click the form.
Another solution i´ve used is to move the button instead of disabling it. In that case you don´t have those "disable" problems.
Finally what you really want is people not to press twice, if the button is not there they can´t do it.
You may also replace it with another button.
function xxxx() {
// submit or validate here , disable after that using below
document.getElementById('buttonId').disabled = 'disabled';
document.getElementById('buttonId').disabled = '';
}
Your question is confusing and you really should post some code, but this should work:
onClick="this.disabled=true; this.value='Sending...'; submitForm(); return false;"
I think that when you use this.form.submit() it's doing what happens naturally when you click the submit button. If you want same-page submit, you should look into using AJAX in the submitForm() method (above).
Also, returning false at the end of the onClick attribute value suppresses the default event from firing (in this case submitting the form).
A better trick, so you don't lose the value of the button is
function showwait() {
document.getElementById('WAIT').style['display']='inline';
document.getElementById('BUTTONS').style['display']='none';
}
wrap code to show in a div
id=WAIT style="display:none"> text to display (end div)
wrap code to hide in a div
id=BUTTONS style="display:inline"> ... buttons or whatever to hide with
onclick="showwait();"
(end div)
In my case this was needed.
Disable submit button on form submit
It works fine in Internet Explorer and Firefox without it, but it did not work in Google Chrome.
The problem is that you are disabling the button before it can actually trigger the submit event.
I think easy way to disable button is :data => { disable_with: "Saving.." }
This will submit a form and then make a button disable, Also it won't disable button if you have any validations like required = 'required'.
In this working example, the user confirms in JavaScript that he really wants to abort. If true, the button is disabled to prevent double click and then the code behind which updates the database will run.
<asp:button id="btnAbort" runat="server" OnClick="btnAbort_Click" OnClientClick="if (!abort()) {return false;};" UseSubmitBehavior="false" text="Abort" ></asp:button>
I had issues because .net can change the name of the button
function abort() {
if (confirm('<asp:Literal runat="server" Text="Do you want to abort?" />')) {
var btn = document.getElementById('btnAbort');
btn.disabled = true;
btn.innerText = 'Aborting...'
return true;
}
else {
return false;
}
}
Because you are overriding the OnClick with OnClientClick, even if your validation method succeeds, the code behind wont work. That's why you set UseSubmitBehavior to false to make it work
PS: You don't need the OnClick if your code is in vb.net!
Okay, i did a lot of research on how to make this work perfectly.
So the best option is to create a set timeout for disabling a button onclick.
Now, the problem arise when there is a submit function running on the backend. Then the events become stacked in a queue and whenever the javascript "button.disabled == true"is added to the onclick event, only the first action(i.e. disabling the button) gets triggered and not the submit action which is running in the backend(This backend submit function can comprise of anything such as $.ajax).
For disabling Single button on click :
function() { //i always create annonymous function to avoid polluting global
space
var btn = document.getElementsByClassName("btn");
btn.onclick = function() {
setTimeout(function() {
backButton.disabled = true;
}, 0);
};
}
}();
This code will disable your button and also would run the function on the queue. timeout = 0 actually is used for firing subsequent backend tasks.
For disabling all btns in the screen :
(function() {
let i, element, list, o;
element = document.getElementsByClassName("classx");
if (element) {
element = element[0];
list = element.getElementsByTagName("button");
for (i = 0; i < list.length; i++) {
o = list[i];
o.onclick = function() {
setTimeout(function() {
let i;
for (i = 0; i < list.length; i++) {
list[i].disabled = true;
}
}, 0);
return true;
}
}
}
})();
This would help you disable all of the buttons present in the page. (Just use it according to your usecase.)
Also, this(disabled button) is a good use case for settimeout=0, functionality description as it will "defer" the call until the currently "stacked javascript events" are finished.
Thank you and hope this helps someone's in the future.
I did the trick. When set timeout, it works perfectly and sending all values.
$(document).ready(function () {
document.getElementById('btnSendMail').onclick = function () {
setTimeout(function () {
document.getElementById('btnSendMail').value = 'Sending…';
document.getElementById('btnSendMail').disabled = true;
}, 850);
}
});

Is there any way to auto submit gravity form according to radio button selection

I am setting up a new gravity form, where i need to get auto form submission trigger when someone click on radio button "No".
here is my form - https://wpskillguru.com/test/
I added below code in theme's "function.php" file
add_filter( 'gchoice_22_1_1', 'add_onclick', 10, 2 );
function add_onclick( $button, $form, $radio ) {
jQuery(document).ready(function(){
jQuery('form#gform_22_1_1').trigger('gform_submit_button_22');
});
but don't know how to set "onclick event" in Radio button
Is there anyone who can help me?
You can use .on() method and attach the event handler with it. You can read more about it here
$(".ginput_container_radio").on("click", "input[value='No']", function(){
alert("No select!");
// your code here
});
or
$(".ginput_container_radio").on("change", "input[value='No']", function(){
alert("No select!");
// your code here
});
Note: The ginput_container_radio is taken from the radio buttons at https://wpskillguru.com/test
To submit the form after clicking a Gravity Forms Radio Button you can use the following code:
$( '.ginput_container_radio input' ).on( 'change', function() {
$( '#gform_GFFORMID' ).submit();
} );
The best way to install this code is the free Gravity Forms Custom JavaScript plugin.
If you're looking for a way to auto-submit a form without any code, check out our GF Page Transitions add-on.

Common jQuery to disable submit buttons on all forms after HTML5 validation

Please pardon me if it is a basic thing, because I am a new learner of Javascript/jQuery. I have been trying to disable submit button to disable multiple submits. I have come across multiple solutions here as well, but all those used specific form name. But I wanted to apply a global solution for all forms on all pages so I dont have to write code on each page, so I put this in footer, so all pages have:
$('input:submit').click(function(){
$('input:submit').attr("disabled", true);
});
This code works on all the forms in all pages as I wanted, but if there are HTML5 required fields in form and form is submitted without them, of course notifications are popped but button still gets disabled. So, I tried with this:
$('input:submit').click(function(){
if ($(this).valid()) {
$('input:submit').attr("disabled", true);
$('.button').hide();
});
});
But this does not work. Kindly help me so that jQuery only disables when all HTML5 validation is done. Thanks
Try this and let me know:
$('input:submit').click(function(){
if ($(this).closest("form").checkValidity()) {
$('input:submit').attr("disabled", true);
$('.button').hide();
});
});
Ruprit, thank you for the tip. Your example did not work for me (in Firefox), but it helped me a lot.
Here is my working solution:
$(document).on("click", ".disable-after-click", function() {
var $this = $(this);
if ($this.closest("form")[0].checkValidity()) {
$this.attr("disabled", true);
$this.text("Saving...");
}
});
Since checkValidity() is not a jQuery function but a JavaScript function, you need to access the JavaScript element, not the jQuery object. That's the reason why there has to be [0] behind $this.closest("form").
With this code you only need to add a class="disable-after-click" to the button, input, link or whatever you need...
It is better to attach a handler to the submit event rather than a click event, because the submit event is only fired after validation is successful. (This saves you from having to check validity yourself.)
But note that if a submit button is disabled then any value they may hold is NOT submitted to the server. So we need to disable the inputs after form submission.
The question is compounded by the new HTML5 attribute form which allows associated inputs to be anywhere on the page as long as their form attribute matches a form ID.
This is the JQuery snippet that I use:
$(document).ready( function() {
$("form").on("submit", function(event) {
var $target = $(event.target);
var formId = $target.attr("id");
// let the submit values get submitted before we disable them
window.setTimeout(function() {
// disable all submits inside the form
$target.find("[type=submit]").prop("disabled", true);
// disable all HTML5 submits outside the form
$("[form=" + formId + "][type=submit]").prop("disabled", true);
}, 2); // 2ms
});
});
---[ WARNING ]---
While disabling submit buttons prevents multiple form submissions, the buttons have the unfortunate side effect of staying disabled should the user click the [Back] button.
Think about this scenario, the user edits some text, clicks submit (and get redirected to different page to view the edits), clicks back to edit some more, ... and ... they can't re-submit!
The solution is to (re-)enable the submit button on page load:
// re-enable the submit buttons should the user click back after a "Save & View"
$(document).ready( function() {
$("form").each(function() {
var $target = $(this);
var formId = $target.attr("id");
// enable all submits inside the form
$target.find("[type=submit]").prop("disabled", false);
// enable all HTML5 submits outside the form
$("[form=" + formId + "][type=submit]").prop("disabled", false);
});
});
Try this
`jQuery('input[type=submit]').click(function(){ return true;jQuery(this).prop('disabled','disabled');})`
run this code on successful validation of the form

Submit a form using onclick event, but only allow once

I am both setting a form's action and submitting the form via the onclick event of a div:
<div class="action_button" onclick="document.forms['test'].action='url/to/action';document.forms['test'].submit()">
<span class="action_button_label">Save</span>
</div>
This works fine, but I'm wanting to use some code that conditionally checks for the 'Save' in the action_label_button, and only lets the submit() fire once. I'm trying to prevent multiple saves (which is yielding duplicate data in my app) from occurring.
// disable save buttons onclick (prevent multiple clicks of save buttons)
$('.action_button_label').one('click', function() {
// if the button is a save button
if($(this).html().indexOf('Save') != -1) {
// submit the parent form
$(this).html('<span class="action_button_label" style="color:gray;">Saving...</span>');
$(this).parents('form').submit();
}
});
$('form').bind('submit', function() {
$(this).find('action_button').attr('onclick', '');
});
This code doesn't seem to work as I expected. I'm afraid I'm a bit out of my depth here, any pointers would be great.
Try replacing
$(this).find('action_button').attr('onclick', '');
with
$(this).find('.action_button').attr('onclick', '');
You should always handle multiple submits server side to ENSURE you don't get them. However you can hide the button-label to assist with this client side.
$('.action_button_label').one('click', function() {
// if the button is a save button
if($(this).html().indexOf('Save') != -1) {
// submit the parent form
$('.action_button_label').hide(); //ADD THIS
$(this).html('<span class="action_button_label" style="color:gray;">Saving...</span>');
$(this).parents('form').submit();
}
});
$('form').bind('submit', function() {
$(this).find('action_button').attr('onclick', '');
});

How can I prevent a double submit with jQuery or Javascript?

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, but none of them seem to be sufficient.
How can I prevent these duplicate entries from occurring using javascript or preferably jQuery?
Thanx in advance!
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 should do the trick:
$("form").submit(function() {
$(":submit", this).attr("disabled", "disabled");
});
No JQuery?
Alternatively, you can make a check from db to check if a record already exist and if so, don't insert new one.
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:
button elements
img elements
javascripts
pressing 'enter' while on some text field
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;
});
Here is bit of jQuery that I use to avoid the double click problem. It will only allow one click of the submit button.
$(document).ready(function() {
$("#submit").on('click', function() {
});
});
I'm not sure what language/framework you're working with or if it's just straight HTML. But in a Rails app I wrote I pass a data attribute on the form button disable_with which keeps the button from being clickable more than once while the transaction is in process.
Here's what the ERB looks like.
<%= f.button "Log In", class: 'btn btn-large btn-block btn-primary', data: {disable_with: "<i class='icon-spinner'></i>Logging In..."} %>
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);
});
});
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');
}
});
If you are using client-side validation and want to allow additional submit attempts if the data is invalid, you can disallow submits only when the form content is unchanged:
var submittedFormContent = null;
$('#myForm').submit(function (e) {
var newFormContent = $(this).serialize();
if (submittedFormContent === newFormContent)
e.preventDefault(true);
else
submittedFormContent = newFormContent;
});
Found at How to prevent form resubmission when page is refreshed (F5 / CTRL+R) and solves the problem:
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
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);
});
});

Categories