JS: Lock form when submitting and unlock it when done

Background:

When a form is submitting, it should be locked – not be editable, all input elements and buttons should be disabled. And it should be unlocked or enabled after the submitting is complete (success or fail).

But make sure not to lock it if validation fails, in which case users can’t correct their errors. To ensure this, you should do an extra unlock/enable action when validation failing event occurs. Because in some browsers the validation just comes before submitting, which might happen just after your locking action.

Note:

This is all about client side effect, not a solution for preventing duplicate form submission. You should always do idempotency check at the server side if duplicate form submission is a problem in your specific scenario.

Code:

Put the following formLocker.js file just prior to your </body> tag, and note it is dependent on jQuery.js (must) and jquery.validate.js (optional).

;
(function($) {
    // Lock form during submitting and unlock it after
    function lockForm($form, $elements) {
        $form.data('locked', true);
        $elements.prop('disabled', true).addClass('submitting');
    }

    function unlockForm($form, $elements) {
        if ($form.data('locked') === true) {
            if (!$elements) {
                $elements = $form.find('.submitting:disabled');
            }

            if ($elements.length > 0) {
                $elements.each(function(index, element) {
                    if ($(element).hasClass('submitting')) {
                        $(element).removeClass('submitting').prop('disabled', false);
                    }
                });
            }

            $form.data('locked', false);
        }
    }

    $(document).on("submit", "form", function (event) {
        var $form = $(event.currentTarget);
        var $elements = $form.find('input, textarea, select, button');
        // Lock form
        if ((typeof $form.valid !== 'function' || $form.valid())
            && $form[0].method
            && $form[0].method.toLowerCase() === 'post') {
            lockForm($form, $elements);
        }

        $(document).ajaxComplete(function (event, jqXHR, options) {
            if (options.url === $form[0].action) {
                // Only handle the same form's ajax response. (This suppose different forms have
                // different action urls, which would be most cases.)

                // Unlock form
                unlockForm($form, $elements);
            }
        });
    });

    $(document).ready(function (event, validator) {
        $("form").bind("invalid-form.validate", function () {
            unlockForm($(this));
        });
    });
})(jQuery);

Add comment

Loading