Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Show a progress bar when a form is submitted (and prevent more than one submission per document).
/*
Show a progress element for any form submission via POST.
Prevent the form element from being submitted twice.
*/
(function (win, doc) {
'use strict';
if (!doc.querySelectorAll || !win.addEventListener) {
// doesn't cut the mustard.
return;
}
var forms = doc.querySelectorAll('form[method="post"]'),
formcount = forms.length,
i,
submitting = false,
checkForm = function (ev) {
if (submitting) {
ev.preventDefault();
} else {
submitting = true;
this.appendChild(doc.createElement('progress'));
}
};
for (i = 0; i < formcount; i = i + 1) {
forms[i].addEventListener('submit', checkForm, false);
}
}(this, this.document));
@wjaspers

This comment has been minimized.

Show comment Hide comment
@wjaspers

wjaspers Mar 7, 2014

If I'm not mistaken, your "submitting" property is global to all forms on the document.
This means once 1 form is submitted, all are locked.

Wouldn't you want to lock only the form that called it?

wjaspers commented Mar 7, 2014

If I'm not mistaken, your "submitting" property is global to all forms on the document.
This means once 1 form is submitted, all are locked.

Wouldn't you want to lock only the form that called it?

@Zegnat

This comment has been minimized.

Show comment Hide comment
@Zegnat

Zegnat Mar 7, 2014

@wjaspers, when would you want users to submit several forms at the same time? I don’t think there is any harm in “locking” all forms when you are waiting for the server to respond to the first one that was submitted.

Zegnat commented Mar 7, 2014

@wjaspers, when would you want users to submit several forms at the same time? I don’t think there is any harm in “locking” all forms when you are waiting for the server to respond to the first one that was submitted.

@decodedigital

This comment has been minimized.

Show comment Hide comment
@decodedigital

decodedigital Mar 7, 2014

Why not remove the dependency on querySelectorAll by using the more widely-supported getElementsByTagName('form') and checking the form's method in the for loop?

Why not remove the dependency on querySelectorAll by using the more widely-supported getElementsByTagName('form') and checking the form's method in the for loop?

@stryju

This comment has been minimized.

Show comment Hide comment
@stryju

stryju Mar 7, 2014

@Zegnat what if I, as a user, want to submit the OTHER form, after i submitted the 1st one?
It's not an isolated use-case AFAIK

stryju commented Mar 7, 2014

@Zegnat what if I, as a user, want to submit the OTHER form, after i submitted the 1st one?
It's not an isolated use-case AFAIK

@decodedigital

This comment has been minimized.

Show comment Hide comment
@decodedigital

decodedigital Mar 7, 2014

@stryju then you'd potentially lose all data submitted in the first form. Not a good thing!

@stryju then you'd potentially lose all data submitted in the first form. Not a good thing!

@Zegnat

This comment has been minimized.

Show comment Hide comment
@Zegnat

Zegnat Mar 7, 2014

@stryju, @decodedigital, then it depends completely on the timing what is going to happen. Either you cut off submitting the original data and it is lost between the browser and the receiving server. Or the data has actually been received by the server and something is (being) done with it and you cut the browser of from receiving any feedback on the first form. I do not see how this second scenario is – in anyway – a good thing for the user.

Actually, I do not see how wanting to submit the other form is a good use-case unless you accidentally tapped the wrong submit button. But that feels like a design problem of the website.

Why not remove the dependency on querySelectorAll by using the more widely-supported getElementsByTagName('form') and checking the form's method in the for loop?

I wonder if document.forms would trump that, speed wise.

Zegnat commented Mar 7, 2014

@stryju, @decodedigital, then it depends completely on the timing what is going to happen. Either you cut off submitting the original data and it is lost between the browser and the receiving server. Or the data has actually been received by the server and something is (being) done with it and you cut the browser of from receiving any feedback on the first form. I do not see how this second scenario is – in anyway – a good thing for the user.

Actually, I do not see how wanting to submit the other form is a good use-case unless you accidentally tapped the wrong submit button. But that feels like a design problem of the website.

Why not remove the dependency on querySelectorAll by using the more widely-supported getElementsByTagName('form') and checking the form's method in the for loop?

I wonder if document.forms would trump that, speed wise.

@sjorsrijsdam

This comment has been minimized.

Show comment Hide comment
@sjorsrijsdam

sjorsrijsdam Mar 8, 2014

I would do away with the submitting variable and change the checkForm function to this:

checkForm = function (ev) {
    var submitBtns = this.querySelectorAll('[type="submit"]'),
         amountSubmitBtns = submitBtns.length,
         i;

    for (i=0; i<amountSubmitBtns; i++) {
        submitBtns[i].disabled = true;
    }

    this.appendChild(doc.createElement('progress'));
};

I would do away with the submitting variable and change the checkForm function to this:

checkForm = function (ev) {
    var submitBtns = this.querySelectorAll('[type="submit"]'),
         amountSubmitBtns = submitBtns.length,
         i;

    for (i=0; i<amountSubmitBtns; i++) {
        submitBtns[i].disabled = true;
    }

    this.appendChild(doc.createElement('progress'));
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment