Confirm form before submitting using Twitter Bootstrap in a Modal window [Snippet]

Tags

Idea

Have you ever wanted to create a way to confirm input before actually submitting the form. Automatically.

My snippet's goal is exactly for that purpose. The idea is that it reads the form inputs and labels, and generates a modal window (like a lightbox) and asks confirmation. This project is a contribution I do to Twitter Bootstrap and jQuery-bootstrap-scripting ("dialog2") to add on any form using Twitter Bootstrap form markup convention the capability to create a confirmation modal window.

The concept is that some forms needs to have some confirmation and requires more than "are you sure", but also what you are submitting.

How it works

When the pages load, it executes in this order the following:

  • Whether there is a form[data-behavior=confirm], and modify the form default submit button to replace it with a link (idea being that if there is no javascript enabled, you can still submit!)
  • on a Click action on the newly created a.confirm-toggle, it fires up some html manipulation and creates a modal window using jQuery Bootstrap Scriptin's Dialog2 plugin

Word of advice

I have to warn you though. The solution is not yet complete. It works well with input[type=text] and some select. But I need to add more field types as time goes. That's why I created this Fiddle to give room for improvement. Feel free to collaborate. When the solution will be strong enough, i'll contribute it to both projects in their respective syntax (dialog2 doesnt initialize the same way as Bootstrap's modal()

Known limitations

  • Works only with select and input[type=text], and breaks bad with radio and checkbox
  • Works only with ONE form in the page, for now.
  • ¨

The code

You can play with this Fiddle in the meantime i make it ready-er

The javascript

    /**
     * Use form's content into a confirmation modal
     *
     * Using: http://nikku.github.com/jquery-bootstrap-scripting/
     * Requires: Twitter Bootstrap, dialog2
     *
     * @author: Renoir Boulanger
     */
    if ($('form[data-behavior=confirm]').length >= 1) {

        console.log('run.js: document ready : Applying confirmation, ' + $('form[data-behavior=confirm]').length + ' times');

        $('form[data-behavior=confirm] select').click(function() {
            var dataValue = $(this).find(':selected').text();
            $(this).attr('data-value', dataValue);

            // Debug console
            console.log('Adding data-value at: ' + dataValue);
        });

        $('form[data-behavior=confirm] .confirm-toggle').replaceWith('' + 'Continue');

        /**
         *  Since we know javascript is executed so far, lets handle it with the confirmation.
         *
         *  That way, no javascript-enabled browsing user will be able to use the form. #progressiveEnhancement
         *
         *  Do the work.
         */
        $('form[data-behavior=confirm] .confirm-toggle').click(function(event) {
            event.preventDefault();

            // Get form content
            var form = $('form[data-behavior=confirm]').clone().attr('id', 'cloned'); //.appendTo('body');
            var i = 0;
            form.find(':input:not([type=hidden])').each(function() {
                var field = $(this);


                if (field.is('select')) {
                    fieldValue = $(this).attr('data-value');
                    if (fieldValue === undefined) {
                        fieldValue = field.find(':selected').html();

                        // Debug console
                        console.log('fieldValue was undefined, setting to : ' + fieldValue);
                    }

                    // Debug console
                    console.log('fieldValue is : ' + fieldValue);
                } else {
                    fieldValue = field.val();
                }

                // Remove undefined field (they are useless)
                if (fieldValue === '') {
                    field.parent().parent().addClass('empty-field-resolved');
                }

                // Debug console
                console.log('Field ' + i + ' :' + fieldValue + ' for #' + field.attr('id'));

                // Wrap fieldValue in a tag, Tested in IE7!!
                field.after($('' + fieldValue + ''));

                // Remove the field itself, we only want to see the resulting
                field.remove();

                i++;
            });

            // Work stuff out for modal window, copying content, and building modal into the DOM
            var decorate = $("
"); var buildup = decorate.find(".modal-builder").html(form); buildup.appendTo('body'); // Debug console console.log('Appending #modal-placeholder in body, ready to call dialog2()'); // Remove not needed anymore stuff $('.modal-builder .help-block, .modal-builder .input-append, .modal-builder .form-actions').remove(); $('.modal-builder').dialog2({ title: "Are you sure?", id: "confirm-modal", modalClass: "modal-wide fade in", closeOnOverlayClick: false, closeOnEscape: false, initialLoadText: "Loading in progress...", buttons: { Confirm: { primary: true, click: function() { // Debug console.log('Inside dialog2() clicked Confirm'); $('#confirm-submit').click(); } }, "Forgot something": { click: function() { // Debug console.log('Inside dialog2() clicked cancel'); $(this).dialog2("close"); $('.modal').remove(); return false; } } } }); // Do my own cleanup. Remove potentially bogus nodes $('#modal-placeholder, .modal-header .close, .control-group.empty-field-resolved').remove(); }); }

The CSS

Minimally...

.modal-wide {
  overflow:visible;
  width: 650px;
}

.modal-builder .control-label {
      padding:0 !important;
      font-weight:bold;
}

 /* In case you use a span.required-star
  * with title="required field", I don't want to
  * have them in modal
  **/
.modal-builder  .required-star {
    display:none;
}

.modal-builder .hide-in-confirm {
  display:none !important;
}

Tell me in the comments if you want the LESS block I created

The Form

Always using Twitter Bootstrap markup, A form minimally needs

What is really required here is

  • Form tag has data-behavior="confirm" attribute
  • Form submit button has at least the class name confirm-toggle

Just use any combination of Twitter Bootstrap Form patterns

In addition to freeform text, any HTML5 text-based input appears like so.

Possible enhancements paths

My solution fit for what I needed. A two parameters to add confirm in a modal using the project's markup. Sadly I read after doing it that there is some plugins I could have considered such as the Form plugin

.

End word

I am going to prepare this post and propose a pull request to the jQuery Bootstrap Scripting AND Bootstrap project in a day or two.

Ressources

  • http://nikku.github.com/jquery-bootstrap-scripting/#
  • http://twitter.github.com/bootstrap/base-css.html#forms