Bootstrap Application Wizard

Screenshot

General

Author

Special Thanks

Update bootstrap v3.x

Contributors

Dependencies

  • jQuery 2.x
  • Bootstrap 3.x

Installation

CSS

<link href="bootstrap-wizard/bootstrap-wizard.css" rel="stylesheet" />

Javascript

<script src="bootstrap-wizard/bootstrap-wizard.js" type="text/javascript"></script>

Usage

1) Create wizard

<div class="wizard" id="some-wizard" data-title="Wizard Title"></div>

To set the title of the application wizard use the data-title attribute

2) Create wizard cards

Each .wizard-card will be its own step in the Application Wizard, and the h3 tag will be used for its navigation name on the left. Also notice the data-cardname attribute on each card. While not required, this can be used to access the cards by a specific name.

Card Setup

<div class="wizard-card" data-cardname="card1">
    <h3>Card 1</h3>
    Some content
</div>

Basic Wizard Setup

<div class="wizard" id="some-wizard" data-title="Wizard Title">
    <div class="wizard-card" data-cardname="card1">
        <h3>Card 1</h3>
        Some content
    </div>
    
    <div class="wizard-card" data-cardname="card2">
        <h3>Card 2</h3>
        Some content
    </div>
</div>

3) Initialize Wizard

After setting up the wizard with it's cards you can initilize it.

$(function() {
    var options = {};
    var wizard = $("#some-wizard").wizard(options);
});

Wizard

Wizard Options

Name Type Default Description
keyboard boolean true Closes the modal when escape key is pressed.
backdrop boolean or string `static` true Includes a modal-backdrop element. Alternatively, specify `static` for a backdrop which doesn't close the modal on click.
show boolean false Shows the modal when initialized.
showCancel boolean false Show cancel button when initialized.
showClose boolean true Show close button when initialized
progressBarCurrent boolean false
submitUrl string '' Default submit url
increateHeight integer 0 Deprecated
contentHeight integer 300 Default height of content view
contentWidth integer 580 Default width of wizard dialog, includes step navigation, which takes 28%.
buttons array cancelText: "Cancel"
nextText: "Next"
backText: "Back"
submitText: "Submit"
submittingText: "Submitting..."
formClass string form-horizontal Allows the configuration of the class(es) of the form. Default `form-horizontal` is set. Multiple classes are allow by separation of space.

Logging can be turned on by setting logging before wizard initialization

$.fn.wizard.logging = true;

Wizard Methods

Usage:

var wizard = $("#some-wizard").wizard({});

wizard.methodName(arguments);
Method Description
show() Displays the wizard
hide() Alias for close()
close() Closes the wizard
serialize() Returns all inputs from the wizard as serialized string, see [jQuery serialize()] (http://api.jquery.com/serialize/). Add-on: standard disabled inputs are not serialized. This function will will also serialize disabled inputs which have a attribute `data-serialize="1"`.
serializeArray() Returns all inputs from the wizard as array object, can be used for sending a JSON object to the server. See [jQuery serializeArray()] (http://api.jquery.com/serializeArray/) Add-on: standard disabled inputs are not serialized. This function will will also serialize disabled inputs which have a attribute `data-serialize="1"`.
getActiveCard Returns a wizardCard object for the active card
setTitle(title) Set the title of the wizard
setSubtitle(subTitle) Sets the secondary, less pronounced title in the wizard header
errorPopover(element, msg, allowHtml) This creates an error popup on element, with content msg. This is useful being called from a card-level validator, where you might want to pick specific elements on a card on which to show an error tooltip. allowHtml (default:false) allows html content as msg argument.
changeNextButton(text, [class]) Changes the “next” button (used to advance steps in the wizard) to have text text and optionally css class cls. This is used internally by the wizard when the last step is reached, to display a green “submit” button, but it may be useful elsewhere.
updateProgressBar(percent) Sets the progress bar in the lower right to percent complete. This typically shouldn’t be touched by user code, but it can be useful to call updateProgressBar(0) after a submit handler returns. [See Submitting Data].
hideButtons() Hides the next and previous buttons. This is only really useful after a submission handler returns. [See Submitting Data].
showButtons() Shows the next and previous buttons. This is only really useful after a submission handler returns. [See Submitting Data].
submitSuccess() Shows the special submit cards. This is only really useful after a submission handler returns. [See Submitting Data].
submitError() Shows the special submit cards. This is only really useful after a submission handler returns. [See Submitting Data].
submitFailure() Shows the special submit cards. This is only really useful after a submission handler returns. [See Submitting Data].
reset() Resets the wizard to its original state. This only resets wizard internals, and does not affect your form elements. If you want to reset those, listen for the `reset` event, and write some code to reset your elements manually.
find(selector) Search for the given selector within the modal. And returns the same result as jQuery.find(selector) function.

Wizard Events

You can register on the follwing wizard events with jQuery's on(eventName, callback) function.

Example registering on the reset event

var wizard = $("#some-wizard").wizard({});

wizard.on("reset", function() {
    // Some reset actions
});
<tr>
    <td>submitError</td>
    <td>Triggers when submit encounters an error</td>
</tr>
<tr>
    <td>loading</td>
    <td>Triggers after the submit event</td>
</tr>
<tr>
    <td>readySubmit</td>
    <td>Triggers when the wizard has reached its final card</td>
</tr>
Event Description
reset Reset event is called when the dialog is either closed or when submit is done
submit Triggers when the submit button is clicked on the final card
closed Triggers when the wizard is closed
incrementCard Triggers when the next card becomes the current card
decrementCard Triggers when the previous card becomes the current card
progressBar Triggers when the progress bar is incremented. The first argument passed to the callback is the new progress percent from 0 to 100.
submitSuccess Trigger when submit was succesfull
submitFailure Trigger when submit failed

Submitting Wizard

The easiest way to submit data to the wizard is to pass in a submitUrl on construction.

var wizard = $("#some-wizard").wizard({submitUrl: "/some_url"});

When the wizard reaches its last step and the user clicks the submit button, all of the inputs from all of the wizard cards will be aggregated together and POSTed to your submitUrl.

If you wish to implement your own submit listener, take a look at the source of the Wizard._defaultSubmit method, which is the default submit listener.

function(wizard) {
    $.ajax({
        type: "POST",
        url: wizard.args.submitUrl,
        data: wizard.serialize(),
        dataType: "json"
    }).done(function(response) {
        wizard.submitSuccess();
        wizard.hideButtons();
        wizard.updateProgressBar(0);
    }).fail(function() {
        wizard.submitFailure();
        wizard.hideButtons();
    });
}

The wizard class implements the serialize() and serializeArray() methods of jQuery form elements. These methods will scan through all the form input elements in your wizard cards, aggregate the names and values, and return a data structure for submitting via an ajax call.

After your submission, depending on whether your submission succeeded, failed, or had an error, you can display a specific hidden card to reflect the submission status. These submission cards must first be defined in the html.

<div class="wizard" id="some-wizard">
    <!-- normal wizard cards: -->
 
    <div class="wizard-card" data-cardname="card1">
        <h3>Card 1</h3>
        <div>...</div>
    </div>
 
    <!-- begin special status cards below: -->
 
    <div class="wizard-success">
        submission succeeded!
    </div>
 
    <div class="wizard-error">
        submission had an error
    </div>
 
    <div class="wizard-failure">
        submission failed
    </div>
</div>

These 3 cards are hidden by default and only appear when you specifically activate them. Typically, these cards will be activated by status of an ajax post.

wizard.on("submit", function(wizard) {
    $.ajax({
        url: "/wizard_submit_url",
        type: "POST",
        url: wizard.args.submitUrl,
        data: wizard.serialize(),
        dataType: "json"
    }).done(function(response) {
        wizard.submitSuccess();         // displays the success card
        wizard.hideButtons();           // hides the next and back buttons
        wizard.updateProgressBar(0);    // sets the progress meter to 0
    }).fail(function() {
        wizard.submitError();           // display the error card
        wizard.hideButtons();           // hides the next and back buttons
    });
}

By activating these cards in the ajax request handlers, you can display information relevant to the status of the submit request

After submission, you may wish to reset the wizard to some default state. See the [reset()] method in the wizard class for details on this.

Wizard Cards

Access

Cards can be accessed through the cards attribute on the wizard object. By default, this is an object whose keys are the text from the h3 tags, and whose values are instances of the WizardCard class. So for example, with the following markup:

<div class="wizard" id="some-wizard">
    <div class="wizard-card">
        <h3>Card 1</h3>
        <div>...</div>
    </div>
</div>

You could access this card the following way:

var wizard = $("#some-wizard").wizard();
var card = wizard.cards["Card 1"];

From this card object, you can call any of the card methods. You can also set a card’s name specifically by using the data-cardname attribute

<div class="wizard" id="some-wizard">
    <div class="wizard-card" data-cardname="card1">
        <h3>Card 1</h3>
        <div>...</div>
    </div>
</div>

Now you can access the card by the name “card1″:

var wizard = $("#some-wizard").wizard();
var card = wizard.cards["card1"];

Validation

Most wizard cards will require some kind of validation of the input before proceeding to the next card. This validation is not intended to sanitize malicious data to be trustworthy (this should be done server-side), merely to catch any obvious common problems with the data.

Validation can be attached inline to form elements by using the attribute data-validate on the input.

<div class="wizard-card">
    <h3>Card 1</h3>
    Name <input type="text" name="name" data-validate="validateName" />
</div>

When the Next button is clicked for the card, validateName will be called with the element as its first argument. Here’s an example validation function:

function validateName(el) {
    var name = el.val();
    var retValue = {};
 
    if (name == "") {
        retValue.status = false;
        retValue.msg = "Please enter a name";
    }
    else {
        retValue.status = true;
    }
 
    return retValue;
}

If the validator returns with an object with .status == false, then an error popup will display on the element and the wizard will not be allowed to progress to the next step. The wizard will only progress when all of the validators on the page return with a status of true.

Entire cards may be assigned a validation function by using the data-validate attribute on the card.

<div class="wizard-card" data-validate="someFunction">
    <h3>Card 1</h3>
    Some content
</div>

someFunction() will receive a WizardCard object on which you can manually search for the inputs on that card and validate them. This is useful for validating complex interdependencies between many inputs, for example, if a name field can only be empty if another field is populated.

The final method for validating entire cards is to subscribe to the the “validate” event and provide a validation function.

wizard.cards["Card 1"].on("validate", function(card) {
    var input = card.el.find("input");
    var name = input.val();
    if (name == "") {
        card.wizard.errorPopover(input, "Name cannot be empty");
        return false;
    }
    return true;
});

A card-level validation function is slightly different from an input-level validation function. In a card-level function, you are required to display any error popovers, using the wizard object’s errorPopover() method, as well as returning true or false to tell the wizard whether or not it should advance to the next step.

Validation Error Popup

Input with adjacent button

Bootstrap has the possibility to have button adjacent to an input. This causes the error-popover to be misplaced. To correct this the error-popover has to be placed on the span of the adjacent button.

To accomplish this the application wizard has smart detection for this. When creating an adjacent button to an input an additionial id has to be set on the adjacent <span> of the button. The id name of the span has to be btn-(ID OF INPUT).

For example within the following card setup. The card uses standard bootstrap v3.x code for an input with adjacent button. The id of the input is fqdn. The id of the adjacent span becomes btn-fqdn.

This will cause the error-popop to be correctly displayed when there is an validation error.

<div class="wizard-card" data-cardname="address">
    <h3>Address</h3>

    <div class="wizard-input-section">
        <p>Full Qualified Domain Name</p>
    
        <div class="form-group">
            <div class="col-sm-8">
                <div class="input-group">
                    <input type="text" class="form-control" id="fqdn" name="fqdn" placeholder="FQDN" data-validate="validateFQDN" data-is-valid="0" data-lookup="0" />
                    <span class="input-group-btn" id="btn-fqdn">
                        <button class="btn btn-default" type="button" onclick='lookup();'>Lookup</button>
                    </span>
                </div>
            </div>
        </div>
    </div>
</div>

Card CSS

If you require to display an selection box overlayed over wizard, like is done within the demo for some of the selects. You have to add the following class to your wizard-card element. wizard-card-overlay.

Card Methods

Method Description

Card Events

Registering event on cards can be done with the jQuery on(event, callback) function on the wizardCard object.

Event Description
loaded Triggers when the card is first loaded (when the card is selected but has never been selected before). This is useful for lazy-loading content.
validate when the card is being validated. The callback assigned to this can itself be used as a validator if it returns a boolean.
selected Triggers when this card is selected as the active wizard card
deselect Triggers when this card is changed from. The new card will receive the select event, and the old card will receive the deselect event.
enabled
disabled
reload Triggers when the card is first loaded or when the reload() function is called.
validate Called when the card is being validated. The callback assigned to this can serve as a validator itself, if it returns a boolean.
validated Triggers when validation is done
invalid Triggers when validation failed
markVisited Triggers when this card is marked as visited, meaning, typically, that the user can go back to it from a different step
unmarkVisited Triggers removing this card as a visited card