Turn any webform into a powerful wizard with jQuery (FormToWizard plugin)

September 28, 2009

This detailed tutorial will show you how to turn long webform into a wizard with “steps left” information. A plugin is also available for download.

Download plugin with example  View demo

What is our task?

If you would, for whatever reason, have a large webform all fields shoud be semantically divided into fieldsets. Each fieldset would clearly describe each group of fields. Although many examples on the web today look different, this is how it should be.

 

So, we can say that each group of fields represent a sub task of a larger task – filling the entire web form. Thus, each sub task can become a step with a description, input fields and navigation that is common for wizard forms – back and next.The entire process can be done in several simple steps.

1. Create “steps”

The code should look like the example below.

<form id="SignupForm" action="">
    <fieldset>
        <-- input fields -->
    </fieldset>
    <fieldset>
        <-- input fields -->
    </fieldset>
    <fieldset>
        <-- input fields -->
    </fieldset>
</form> 

Let’s explain the following code. In order to determine how much steps there will be, we need to select all fieldsets and get the size of this wrapped set. Next, we iterate through this wrapped set (that returned all fieldsets), wrap each fieldset into a div and append a paragraph that will hold “back” and “next” buttons.

Now comes the funny part. If this is a first fieldset in wrapped set, we’ll create “next” button only and make this step visible. If it is the last fieldset in wrapped set, we’ll create only “back” button. In all other cases we’ll create both buttons. Methods for creating buttons will be explained later in this tutorial.

var steps = $("#SignupForm fieldset");
var count = steps.size();
steps.each(function(i) {     $(this).wrap("<div id='step" + i + "'></div>");     $(this).append("<p id='step" + i + "commands'></p>");
    if (i == 0) {         createNextButton(i);        // to do         selectStep(i);                  // to do     }     else if (i == count - 1) {         $("#step" + i).hide();         createPrevButton(i);       // to do     }     else {         $("#step" + i).hide();         createPrevButton(i);       // to do         createNextButton(i);       // to do } }

Now let’s explain how to create buttons and how users will actually move through the wizard.

2. Create next and back buttons and add interatcion

Creating the buttons isn’t that hard. Each button will have a unique name (e.g. step1next, or step3prev) and will be appended to their panels created in previous step. In order to add some interaction, and that is to enable moving between steps, we need to bind click event to each button. This is how they will work:

function createPrevButton(i) {
    var stepName = "step" + i;
    $("#" + stepName + "commands").append("<a href='#' id='" + stepName + "Prev' class='prev'>< Back</a>");
    $("#" + stepName + "Prev").bind("click", function(e) {         $("#" + stepName).hide();         $("#step" + (i - 1)).show();         selectStep(i - 1);     }); }
function createNextButton(i) {     var stepName = "step" + i;     $("#" + stepName + "commands").append("<a href='#' id='" + stepName + "Next' class='next'>Next ></a>");     $("#" + stepName + "Next").bind("click", function(e) {         $("#" + stepName).hide();         $("#step" + (i + 1)).show();         selectStep(i + 1);     }); }

Function selectStep() that I mentioned before removes CSS class “current” from all steps and assign it only to the currently selected.

function selectStep(i) {
    $("#steps li").removeClass("current");
    $("#stepDesc" + i).addClass("current");
}

At this moment wizard is functional. But that’s not all. Let’s apply Steps left UI design pattern here.

3. Create “steps left” information

This is easier than it might look like at the first sight. At the very beginning of our code we have to add unordered list that will be a container for steps left information. In addition to this we will hide signup button. We want it to be visible only in the last step.

var steps = $("#SignupForm fieldset");
var count = steps.size();
           
$("#SaveAccount").hide();
$("#SignupForm").before("<ul id='steps'></ul>");

We also need to extend each() function and add information about steps for each fieldset in wrapped set. Each step will have it’s natural number, starting with 1. Below the step number we’ll add a description that is extracted from <legend> element.

steps.each(function(i) {
    var name = $(this).find("legend").html();
    $("#steps").append("<li id='stepDesc" + i + "'>Step " + (i + 1) + "<span>" + name + "</span></li>");
    ...
});

Let’s do just one more thing. Since submit button should be visible only in the last step, we’ll hide it every time user presses next. Only if user comes to the last step, it should be visible.

$("#" + stepName + "Prev").bind("click", function(e) {
    $("#SaveAccount").hide();
});
$("#" + stepName + "Next").bind("click", function(e) {
    if (i + 2 == count)
        $("#SaveAccount").show();
});

If you want to see the full source code, download it or check out the demo.

Plugin for easier use

It would be a pity not to create a plugin that will enable all of this in just one line of code. I called it FormToWizard. I guess it’s clear what it does :) In order to apply the plugin you will have to add a reference to script file and apply it to y <form> element.

<script type="text/javascript" src="formToWizard.js"></script>
$("#SignupForm").formToWizard();

If you want to hide a submit button (or placeholder for multiple buttons) you can add a parameter sumbitButton with the name of element you wish to be hidden.

$("#SignupForm").formToWizard({ submitButton: 'SaveAccount' }) 

Lightweight and Cross Browser compatible

This plugin has only 2,3KB and with compression it can be even smaller. It is compatible with all major browsers: FireFox, Google Chrome, Safari, Opera, Internet Explorer 8, 7 and 6. The latter is collateral, I was surprised it actually works there :)

If you, however, find any bug or have some suggestion on how to improve this or extend it, please share!

This work is published under Creative Commons Attribution 3.0 Unported License.

Let's discuss this on twitter.

102 Comments

  • Marco (September 29, 2009)

    Just like your "Generate a table of contents" example, this one is very, VERY cool (and useful)! Can’t understand why nobody else came up with this before.

    Also, thanks for converting this into a plugin – it makes it even more usable.

    Keep up the great work Janko!

  • webmasterdubai (September 29, 2009)

    really nice work it will make life easy to end user to fill lengthy forms in steps is there possibility to add validation with steps.

  • sky_mender (September 29, 2009)

    Really nice work, very essential and useful! Thanks for sharing it.
    The demo does not work in IE 7.

  • Denis Ivanov (September 29, 2009)

    Interesting indeed! My love for gracefully degrading frontend sugar just keeps increasing…

  • Kornelije Sajler (September 29, 2009)

    Great tutorial and great idea also, I will try to it implement in my ASP.NET MVC2 Project.
    Great job, Janko!

  • grimen (September 29, 2009)

    Very useful and cool – thanks!

  • Masoud (September 29, 2009)

    nice job.

    real use full.

    i think its better see this in a plugin.

    ;)

  • Peter (September 29, 2009)

    You just saved me loads of time! Thanks for all your hard work too.

  • Soh Tanaka (September 29, 2009)

    Awesome job Janko :-) This will def come in handy~

  • Yigit Ozdamar (September 29, 2009)

    Great work! Thanx mate!

  • Janko (September 29, 2009)

    Thanks everyone! Yes, I forgot to mention that it degrades gracefully if JavaScript is disabled :)

  • Nanda (September 30, 2009)

    Thanks Janko, I can put it use right away. :)

  • Steffen Jørgensen (September 30, 2009)

    Hi Janko!
    A very nice post, with a very useful method of making large forms easier to consume.

    Keep up the great work!

  • Fredrik (September 30, 2009)

    Thanks for a very good articel!

    Love your blog.

  • Yasser El-Sherif (September 30, 2009)

    Awsome ..

  • Max (September 30, 2009)

    Very nice tutorial, like a lot of your tutorials!!!
    Thanks

  • Tigrish (September 30, 2009)

    Hey Janko, some great stuff here!

    Do you have any suggestion on how to add validation to the form? I suppose each fieldset would need to be validated every time the "next" button is clicked so that users can’t move on to the following step if they have entered incorrect data.

  • mDesign (September 30, 2009)

    This is simply awesome, well done! And thanks for sharing.

    @ Tigrish, someone else wrote a great script for that. http://bassistance.de/jquery-plugins/jquery-plugin-validation/ Implenting this script shouldn’t be that hard. Good luck :)

  • Andrea (September 30, 2009)

    Is it possible to have the "step X" text to be clickable to go directly to that section?

  • Sarah (September 30, 2009)

    Hi mDesign, thanks for the heads up on bassistance validation implementation. i have tried integrating with this great execution for forms created by janko but there seems to be a conflict. the next buttons fail to trigger a validation per ‘form’ basis. has anyone managed to successfully integrate this? i will carry on trying and post back if i get it working :)

  • mDesign (September 30, 2009)

    If I got some spare time tomorrow at work I’ll take a quick look at it :)

  • Janko (September 30, 2009)

    Thanks everyone!

    mDesign: yep, bassistance can do the work.

    Tigrish, Sarah: If you have problems with bassistance, why don’t use inline validation? http://livevalidation.com/ and http://code.google.com/p/javascriptformvalidation/

    Andrea: You can do it simply by wrapping each step info into the same link as buttons.

  • Erwin Heiser (October 1, 2009)

    Nice one this! Would also like to add jquery-tinyvalidate by Karl Swedberg from learningjquery.com as a possible form validation script. It’s on github http://github.com/kswedberg/jquery-tinyvalidate

  • William (October 1, 2009)

    Wow..impressive!! great trick, simple and powerful..

    thanks for sharing

  • Jahufar (October 1, 2009)

    Nice job!

    However, this breaks the browser’s back button – any way to avoid that – .i.e. clicking the browser’s back button takes you the the previous step and vice versa?

  • FoO Iskandar (October 1, 2009)

    Nice job!

    Thank’s for sharing

  • Yoosuf (October 1, 2009)

    Awesome work,

    its seems like not working in Apple Safari Browser

  • Janko (October 1, 2009)

    Thanks, everyone!

    Erwin: I guess Karl’s plugin would also be great solution, thanks!

    Jahufar: Excellent point, I didn’t think of that at all. I guess the good solution would be to add step number in anchors, so you’d have:

    http://www.mysite.com/signup/#1 for Step 1 and so on. Thanks for this suggestion!

    Yoosuf: Can you give me some details, what bug do you get? I just tested it again and works for me.

  • noel (October 1, 2009)

    chhers, great work, great tutorial

  • Roberto Xite Studio Magazine (October 1, 2009)

    Very cool! Thanks!

  • Jason (October 1, 2009)

    Very nice, I’m going to check this out and try it later tonight!

  • James (October 1, 2009)

    First off, thanks for the (hopefully) awesome script – I too am running into an error with Safari 4 (WinXP), latest version, and JQuery 1.3.2 (I have tried 1.2.6 as well):

    In Safari 4, nothing happens – the fieldset tags don’t get processed into a Wizard, and using the JS debugger in Safari (if the Develop menu is enabled) tells me:

    syntax error, unrecognized expression: #

    And stepping through the functions, it hits on where the script initiates the formToWizard function where the hash sign (#) is used to reference the ID of the form.

    Any help/advice is appreciated. I’d really like to get this working as it’s a great way to save screen real estate on large multipart forms.

  • James (October 1, 2009)

    Oh, and I should add that your demo DOES work, so i’m guessing it’s my code (obviously, lol) – do I have to have the elements the script creates styled out in an inline CSS style tag for it to work? I don’t have that currently (just figured getting it working first, then style it afterwards).

  • James (October 1, 2009)

    IE6/WinXP (I know, I know…) JS debugger says that the "Object doesn’t support this property or method". Hope the info I supply helps.

  • Jack (October 2, 2009)

    Your CSS forces the labels on radio buttons and check boxes to show above or below the actual checkboxes. Any suggestions/solutions for getting the text to preced or follow the checkboxes instead?

  • Janko (October 2, 2009)

    Jahufar, James: I will try that idea with URLs as soon as I find some free time. Adding step numbers can help you show the right step if users want to come to a specific step by tying URL, but not sure it will work for back button. Have to check it.

    Jack: You have a plenty of choices. For instance, wrap label and input field in, let’s say, paragraph and float them to left.

  • James (October 2, 2009)

    @Jack:

    I can help there with that – after the content of the label tag (the readable part that shows as the label’s text), put a br tag followed by the radio input, and make sure your labels are set to display inline rather than block. this will force the label’s text to line up before the input on the same line.

  • Bobby (October 2, 2009)

    There is one jquery plugin that does this quite well already, it’s called form wizard plugin. See http://plugins.jquery.com/project/formwizard or http://home.aland.net/sundman/ . Just a heads up.

  • Janko (October 2, 2009)

    Bobby: Looks very similar, but I’ll check that one thoroughly. Thanks!

  • Martin (October 3, 2009)

    Love it. Simple and straightforward.

    This encourages me to start writing my own JQ plugins.

  • Janko (October 3, 2009)

    Martin: Then do it! The best thing about this is that it is really fun to experiment and write about it .

  • Nikola (October 5, 2009)

    Odlichno!

  • Micael Estrázulas (October 5, 2009)

    Hi,

    Im changed your plugin to more accessible for other languages.

    I added 3 new options: title, prevLabel, nextLabel.

    [code]
    /* Created by jankoatwarpspeed.com */

    (function($) {
    $.fn.formToWizard = function(options) {
    options = $.extend({
    submitButton: ”,
    title: "Step",
    nextLabel: "Next",
    prevLabel: "Back"
    }, options);

    var element = this;

    var steps = $(element).find("fieldset");
    var count = steps.size();
    var submmitButtonName = "#" + options.submitButton;
    $(submmitButtonName).hide();

    // 2
    $(element).before("<ul id=’steps’></ul>");

    steps.each(function(i) {
    $(this).wrap("<div id=’step" + i + "’></div>");
    $(this).append("<p id=’step" + i + "commands’></p>");

    // 2
    var name = $(this).find("legend").html();
    $("#steps").append("<li id=’stepDesc" + i + "’>"+options.title+" " + (i + 1) + "<span>" + name + "</span></li>");

    if (i == 0) {
    createNextButton(i);
    selectStep(i);
    }
    else if (i == count – 1) {
    $("#step" + i).hide();
    createPrevButton(i);
    }
    else {
    $("#step" + i).hide();
    createPrevButton(i);
    createNextButton(i);
    }
    });

    function createPrevButton(i) {
    var stepName = "step" + i;
    $("#" + stepName + "commands").append("<a href=’#’ id=’" + stepName + "Prev’ class=’prev’>< "+options.prevLabel+"</a>");

    $("#" + stepName + "Prev").bind("click", function(e) {
    $("#" + stepName).hide();
    $("#step" + (i – 1)).show();
    $(submmitButtonName).hide();
    selectStep(i – 1);
    });
    }

    function createNextButton(i) {
    var stepName = "step" + i;
    $("#" + stepName + "commands").append("<a href=’#’ id=’" + stepName + "Next’ class=’next’>"+options.nextLabel+" ></a>");

    $("#" + stepName + "Next").bind("click", function(e) {
    $("#" + stepName).hide();
    $("#step" + (i + 1)).show();
    if (i + 2 == count)
    $(submmitButtonName).show();
    selectStep(i + 1);
    });
    }

    function selectStep(i) {
    $("#steps li").removeClass("current");
    $("#stepDesc" + i).addClass("current");
    }

    }
    })(jQuery);
    [/code]

    Thanks for your plugin

  • Janko (October 5, 2009)

    Micael: Good ideas, thanks for extending and sharing it!

  • Derek Pennycuff (October 6, 2009)

    I’ll have to experiment with this one to see if it plays nice with PEAR.HTML.QuickForms.Renderer.Tableless. If not, I’ve been considering trying to write my own renderer anyway.

    My biggest fear with this one is I’ve put so much energy into arguing for streamlined, simple forms this could encourage people to request more and more fields.

    I also wonder about impact on completion rates. From my observations with using SurveyMonkey (which is sorta like a big form, right?) lots of people complete the first page with significant losses on each subsequent page. Putting it all on a single long page seems to get a higher return rate, or at lest cut down on the partial submissions. That’s far from scientific, and could be a topic ripe for some A/B testing.

  • Janko (October 6, 2009)

    Derek: Thanks for mentioning this! As far as I am concerned adding additional fields should be something that brings value to customers and should be agreed with them. This should be the same for both cases.

    Regarding completion rates, I think it depends on context, but it would be really interesting to see the results from A/B testing.

  • killy (October 6, 2009)

    wow, great script. thanks :D

  • Louis (October 8, 2009)

    Hi great code

  • Russell (October 15, 2009)

    Hi,
    Great piece of script, quite simple to use and works really well. One question, i’ve added in the livevalidation code as suggested above but how can i stop the user going to step 2 if the fields don’t validate?

  • File Horse (October 16, 2009)

    Great work! Thanx mate! CHEARS!

  • Daniel (October 18, 2009)

    Odlican plugin :)

  • Greg (October 21, 2009)

    Thanks for the code. this can be very useful especially if the wizard can be turned on and off much like in Google Adsense.

  • Mohamed Amine (October 22, 2009)

    Really interesting. I was wondering for awhile how to do this. Thanks.

  • Mónica Baquerizo (October 24, 2009)

    Good job, Excellent !. I will do in my thesis
    Thanks

  • Andy Walpole (October 24, 2009)

    Excellent tutorial. Bookmarked. I’m going to use this on a forthcoming project….

  • Andrew (October 25, 2009)

    Hey.. love the code, except it breaks in IE7 for me! :-(

  • Dirty Bird (October 27, 2009)

    Great plug in, works so easy in FF, Opera and Safari. I keep getting the "Object doesn’t support this property or method" error in IE. I see some others had this issue as well, is there a fix? Please help!
    thanks!

  • Dirty Bird (October 27, 2009)

    Here is what Im using to call the Wizard, it works in all browsers but IE
    <script type="text/javascript">
    $(document).ready(function() {
    $("#signUp").formToWizard({ submitButton: ‘submitButton’ });
    });
    </script>

    I changed it from the demo, as it needs to fire on page load not an onclick.
    Please help!

  • Janko (October 27, 2009)

    The reason why this won’t work in IE is a comma character that has been left by my mistake. Remove it from this line at the very beginning of the plugin.

    options = $.extend({
    submitButton: "" [i]< this line should be without comma character at the end[/i]
    }, options);

    Thanks everyone who noticed this!

  • josemrb (October 29, 2009)

    Hi, nice plugin, I’ve added some functionality and want to share my changes but I don’t know under what license You’ve published the code, thanks.

  • Karl (October 29, 2009)

    Nice plugin, I like the design pattern used.

    Somewhere on my HDD I think I was working on similar using tabs (divs) instead which got me around a problem I experienced with this plugin – if you nest fieldsets it all goes horribly wrong… maybe if it looks for a user-defined class on a fieldset to act upon that would solve it?

    Thanks for sharing :-)

  • Dirty Bird (October 29, 2009)

    Thanks for that Janko. I had to copy your script through your url to get it to work. Phew! Very glad to be able to use it. Very nice.
    Thanks again.

  • Josh (October 31, 2009)

    Thanks for the awesome plugin, I have successfully got it working. I do have a question though, is there a way to go to a specific page… I need to apply some validation server side, and would like it to return to one of the pages.

  • Jesse (November 12, 2009)

    Hi! Love this plugin – I have a long, long form (over 300 fields) and this thing is a godsend. I’d also love to use it with the jQuery validation plugin – does anyone know how to validate one fieldset at a time using the Next buttons, instead of waiting at the end for the Submit button? Thanks for any assistance you can provide.

  • Maicon Sobczak (November 17, 2009)

    Great solution for extensive forms! An create a plugin from it turn our work much better. Thank you.

  • Jasper (November 18, 2009)

    I would also be interested in combining this with steps validation.

  • José Alfredo (November 19, 2009)

    primo, dejame decirte que esta vaina esta la verga!!, now in english, dude this shit is wack!!, great job and pretty efficient

  • awake (November 19, 2009)

    Janko… ur a mad man! Luv This!

  • Dave Blencowe (December 4, 2009)

    Hi there Janko,

    Firstly I would like to say great plugin,
    Unfortunately when using the latest version of the jQuery javascript library your plugin dies with the following error:
    [quote]uncaught exception: Syntax error, unrecognized expression: #
    anonymous()js.js (line 11)
    anonymous()jquery-1….2.min.js (line 19)
    anonymous([function(), function(), function(), 1 more…], function(), Object name=F)jquery-1….2.min.js (line 12)
    anonymous()jquery-1….2.min.js (line 19)
    anonymous()[/quote]

    I hope you have some ideas on how this can be fixed and I’ll take a look myself now.
    Dave,

  • sabbir (December 6, 2009)

    Nice work ! thanks !

  • Themba Ntleki (December 8, 2009)

    Thank for a great plugin, I really love this, but I have noticed that someone mentioned that , this does not work on IE7, can this be fixed please please and is there way to write into a cookie which step you are currently on…so that when you refresh the page, you are not back to step1?

    Thank you.

  • Janko (December 9, 2009)

    Dave: I’m not sure why this happens, I couldn’t get that error

  • Dave (December 10, 2009)

    Hi Janko,

    I really like your plug-in. I’m pretty new with jquery and gather I am doing something wrong. I have your plug-in working with a bunch of validation I created. For my validation I added a var required = 1 if the validation failed or 0 if it passes. What I am trying to do is have a message next to the Next > button that says Oops! You need to fix some fields. I also want the next button to be disabled until the user has made the required changes. What I attempted to do is the following…

    $(a.next).bind(click, (function(){
    if((required) == 1){
    $(a.next).prepend("<span>Oops!</span>");
    }
    else{

    };

    }));

    Basically this just broke the functionality of your plug-in. Could you please give me a hand?

    Thanks!

    Dave

  • Menno (December 15, 2009)

    Hey janko,

    Just wanted to say i stumbled upon your plugin, used it, and i find it really satisfying.
    You posted it, its expandable, it isnt hard to read, easy to style with css, no problem to use in combination with php (or any language for that matter, as far as i can see)

    So yeah, thanks, and keep up the good work (:

    Menno

  • Joe (December 15, 2009)

    Hey Janko, nice work!! Keep it up!!

  • Michael (December 18, 2009)

    Wow that is very nice. Let’s see if someone is porting this to go MOO ;)

  • Brian Wangila (December 25, 2009)

    Hey Janko

    Thanks for the great script. I am currently integrating this into my PHP Web Application. I will post how successful it is.

  • Tommy (December 25, 2009)

    Hi, Janko this is great concept and plugin.

    I’ve added bassistance support, these are two simple snippets to add:

    [i]options[/i] reading:

    options = $.extend( {
    submitButton : "submit",
    [b]validationEnabled : true[/b]
    }, options);

    [i]createNextButton[/i] function:

    $("#" + stepName + "Next").bind("click", function(e) {
    [b] if (options.validationEnabled) {
    if (!element.valid()) {
    element.validate().focusInvalid();
    return false;
    }
    };[/b]
    $("#" + stepName).hide();

    Hope it helps someone.

  • Tommy (December 25, 2009)

    Fix for my prevoius comment. This is the correct version of [i]createNextButton[/i] snippet:

    if (options.validationEnabled) {
    var stepIsValid = true;
    $("#" + stepName + " :input").each( function(index) {
    stepIsValid = !element.validate().element($(this)) && stepIsValid;
    });
    if (!stepIsValid) {
    return false;
    }
    }

    … still experimenting with code formatting on your blog

  • Dave (December 28, 2009)

    As a follow up to my earlier problem. I was able to disable the button when my validation did not pass.

    It’s not pretty but it works…

    function createNextButton(i) {
    var stepName = "step" + i;
    $("#" + stepName + "commands").append("<a href=’#’ id=’" + stepName + "Next’ class=’next’>Next ></a>");
    $("#" + stepName + "Next").bind("click", function(e) {
    if ($("#reqValue").val() == 0 && $("#req1Value").val() == 0 && $("#req2Value").val() == 0 && $("#req3Value").val() == 0 && $("#req4Value").val() == 0){
    $("#" + stepName).hide();
    $("#step" + (i + 1)).show();
    if (i + 2 == count)
    $(submmitButtonName).show();
    selectStep(i + 1);
    } else {};
    });
    }

  • seman (December 30, 2009)

    wow, great script. thanks

  • huge (January 6, 2010)

    I don’t understand why the submit button doesn’t work?
    have set post on the form, but still will not submit.
    Trying to send the form detail off for processing to database, obviously missing something obvious.

  • huge (January 6, 2010)

    Also.. are name=" " and id=" " interchangeable?
    will be sending variables via php to a database, will this work?
    thanks

  • huge (January 6, 2010)

    soooory, got it, it has been 5 years since i touched this stuff!
    thanks a mil!

  • Sasha (January 9, 2010)

    Hi Janko, this plugin is great, thanks.

    I modified your code for allowing ‘StepName’ can be clicked, as user may need go back to step2 from step 8.

    Code is simply and is working. code below add in steps.each(function(i)

    $("#steps").append("<li id=’stepDesc" + i + "’ Class=’Stepsname’>Step " + (i + 1) + "<span>" + name + "</span></li>");

    //add Class to <li> for CSS

    $("#stepDesc" + i).bind("click", function(e) {
    for (var f=0;f<=count;f++){
    $("#step" + f).hide();
    }
    $("#step" + i).show();
    if (i + 1 == count)
    $(submmitButtonName).show();
    selectStep(i);
    });

  • Alfrek (January 11, 2010)

    Thanks for your script, it has helped me so much, btw I trasnlated it to spanish and added a Link to each step, for accesing a given step without having to go back and forward. I hope you like it!

    /* Created by jankoatwarpspeed.com */

    (function($) {
    $.fn.formToWizard = function(options) {
    options = $.extend({
    submitButton: ”
    }, options);

    var element = this;

    var steps = $(element).find("fieldset");
    var actual = 0;
    var count = steps.size();
    var submmitButtonName = "#" + options.submitButton;
    $(submmitButtonName).hide();

    // 2
    $(element).before("<ul id=’steps’></ul>");

    steps.each(function(i) {
    $(this).wrap("<div id=’step" + i + "’></div>");
    $(this).append("<p id=’step" + i + "commands’></p>");

    // 2
    var name = $(this).find("legend").html();
    $("#steps").append("<li id=’stepDesc" + i + "’><a href=’#’ id=’goto"+i+"’>Paso " + (i + 1) + "<span>" + name + "</span></a></li>");

    $("#goto" + i).bind("click", function(e) {
    $("#step" + actual).hide();
    $("#step" + (i)).show();
    $(submmitButtonName).hide();
    selectStep(i);
    actual = i;
    });

    if (i == 0) {
    createNextButton(i);
    selectStep(i);
    }
    else if (i == count – 1) {
    $("#step" + i).hide();
    createPrevButton(i);
    }
    else {
    $("#step" + i).hide();
    createPrevButton(i);
    createNextButton(i);
    }
    });

    function createPrevButton(i) {
    var stepName = "step" + i;
    $("#" + stepName + "commands").append("<a href=’#’ id=’" + stepName + "Prev’ class=’prev’>< Atras</a>");

    $("#" + stepName + "Prev").bind("click", function(e) {
    $("#" + stepName).hide();
    $("#step" + (i – 1)).show();
    $(submmitButtonName).hide();
    selectStep(i – 1);
    actual = i-1;
    });
    }

    function createNextButton(i) {
    var stepName = "step" + i;
    $("#" + stepName + "commands").append("<a href=’#’ id=’" + stepName + "Next’ class=’next’>Siguiente ></a>");

    $("#" + stepName + "Next").bind("click", function(e) {
    $("#" + stepName).hide();
    $("#step" + (i + 1)).show();
    if (i + 2 == count)
    $(submmitButtonName).show();
    selectStep(i + 1);
    actual = i+1;
    });
    }

    function selectStep(i) {
    $("#steps li").removeClass("current");
    $("#stepDesc" + i).addClass("current");
    }

    }
    })(jQuery);

  • Alfrek (January 11, 2010)

    And here is the css rules, for the <a>’s

    #steps li a
    {
    color: #999;
    }

    #steps li.current a
    {
    color: #036;
    }

  • Leanne (January 12, 2010)

    @Tommy, I’m trying to implement the bassistance validation plugin, using your code, which shows the fields which are required, BUT the next button dies (you click on it and nothing happens at all whether all fields are filled in or not)..

    Did anyone get it working with bassistance?

    Great script by the way!! :)

  • Kyle Fox (January 12, 2010)

    Nice script. You should post it on Github so that people can report issues and submit patches without having to litter your blog with ugly, unformatted code in the comments.

  • isbkch (January 26, 2010)

    Nice work man…
    This plugin display just 5 steps, and i want to go above this, is it possible ?

  • isbkch (January 26, 2010)

    I wrote the comment above, because im fetching the questions and the fields from a mysql DB and it displays me only the five first questions…

  • Paolo (February 4, 2010)

    Thank for this nice script!

    @Tommy: Based on you code I was able to integrate jQuery’s validation plugin to have a step-by-step validation, but I needed to change the condition you’re using to check if each single input is valid

    from
    [b]stepIsValid = !element.validate().element($(this)) && stepIsValid;[/b]

    to
    [b]stepIsValid = element.validate().element($(this)) && stepIsValid;[/b]

    Now it seems to work as expected

  • Draw (February 4, 2010)

    Hey Janko, great code.
    I’m wondering if I can get rid of the "steps" part and just show the legends.

    Thanks for you time.

  • jagang (February 18, 2010)

    @Tommy and Paolo

    Sometimes you could get an undefined instead of true or false! I don´t know why but this code should fix the problem and now the formToWizard combined with jQuey´s Validation plugin should work in every case!

    if (options.validationEnabled) {
    var stepIsValid = true;
    $("#" + stepName + " :input").each( function(index) {
    var xy = element.validate().element($(this));
    if(xy == undefined) xy = true;
    stepIsValid = xy && stepIsValid;
    });
    if (!stepIsValid) {
    return false;
    };
    };

  • Tommy (February 18, 2010)

    Paolo, thanx for the correction. It was my mistake of course. I fixed my local code and didn’t fixed post I wrote

  • Tommy (February 19, 2010)

    Hi Leanne, check messages posted by me and/or Paolo. There is some mistake in my code.

  • Richard (February 19, 2010)

    Hey Janko,

    This is a great plugin that I’ve used several times. I did run into this problem a couple of times, mainly through typos and being an idiot:

    [quote]uncaught exception: Syntax error, unrecognized expression: #[/quote]

    There’s no other information available – no line number or anything (which is amazingly unhelpful). However, it boils down to not having fieldsets or legends in place (or in my case have not spelt them correctly). This might help other people out :)

  • Sam Sweeney (February 26, 2010)

    Nice plugin, Janko.

    I did change a few things though:

    1) The next > and < Back buttons text was changed to make the symbols html character codes.
    2) The link is #, this can potentially still follow the link(this was the case for me). so I replaced ‘#’ with ‘javascript:void(0);’.
    3) I added a live event to the steps, so if a user clicks on a step it will take them there.

    Thanks!

  • Paolo (February 26, 2010)

    @jagang

    Thanks for your piece of advice.
    I never got ‘undefined’ as value so far, but if I will I’ll apply your code.

  • ilyas bakouch (February 26, 2010)

    this plugin helped me to create my quizz on http://www.isbkch.com/quiz
    just want to say thank you :)

  • fb (March 6, 2010)

    I second this, please post on github, give your work the honor it deserves, share it on a broader spectrum, just my 2 cents

  • Glenn Coomans (March 9, 2010)

    Hi all

    I’m new into JQuery, but when I use this script and I add other JQuery UI (datepicker or slider), then the FormWizard is not working: the form is displayed on one ‘page’, not in ‘steps’. It must be something with the references to the other JS libraries.
    A hint?

    THX