Cory O'Daniel – These are just words Software development, thoughts, and randomness

22Aug/0878

BabySteps – jQuery Step-by-Step Forms

Just finished up my first jQuery plugin 'BabySteps' (yes, its Bill Murray reference). BabySteps helps in breaking up long or complicated web forms into smaller steps without multiple page requests. In the past when doing a multi-step form I'd generally have two or three pages that a user would have to go through, or I'd chalk up a bunch of javascript to shuffle divs around.

BabySteps takes the thinking out of breaking up forms. Simply break your steps up into divs (or your container of choice) and hide them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<style type="text/css">
  .step{display: none;}
</style>
<script type="text/javascript" language="javascript">
  var step1 = $('#step1');
  var step2 = $('#step2');
  var step3 = $('#step3');
 
  step1.bindStep(step2);
  step2.bindStep(step3);
 
  $('#step1').show();
</script>
}
</style>
<form method="post" action="http://example.com/some/far/away/place">
  <div id="step1" class="step">
    <!-- STEP 1 stuff here -->
  </div>
  <div id="step2" class="step">
    <!-- STEP 2 stuff here. -->
  </div>
  <div id="step3" class="step">
    <!-- STEP 3 stuff here. -->
    <input type="submit" id="frm_submit_btn" />
  </div>
</form>

And thats it. When your page loads 'step 1' will show. At the bottom a 'next' button will be appended. Click the next button and 'step 2' appears with a 'next' and 'previous' button.

Ok maybe you are thinking, well that's great, but I'd really like to customize what my form transitions look like.

Ok, cool. I can deal with that. BabySteps has a number of configurable parameters (globally or individually configurable):

  • nextBtn - path to your next button
  • prevBtn - path to your previous button
  • bindPrev - Do you want a previous button on the next page?
  • transition - how you want to transition from one step to the next
  • layoutButton - how you want to lay your button out over/in your step
  • generateMarkup - the markup you want to use to create your button
  • nextValidator - callback that runs a validator on next buttons 'onclick' should return boolean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//These are each globally or individually configurable... :)
$.fn.bindStep.default.nextBtn = '/images/path/to/my/next.gif';
$.fn.bindStep.default.prevBtn = '/images/path/to/my/prev.gif';
 
var step1 = $('#step1');
var step2 = $('#step2');
 
//Dont like the default hide/show?
step1.bindStep(step2,{
  transition: function(currStep,nextStep){
    currStep.slideUp();
    nextStep.slideDown();
  }
});
 
//Dont like the <img> wrapped in <div>?
$.fn.bindStep.defaults.generateMarkup = function(id1,id2,img){
  //id1 is the id the events are bound to (default DIV)
  //id2 is an extra id for the inner element (default img), if you dont have an inner, just ignore it
  return(
  [
    '<img ',
      'src="' + img + '" ',
      'id="' + id1 + '" ',
    '/>'
  ].join('');
  );
}

Woot, pretty much everything is a callback, so you can modify the way the buttons are laid out, how their markup is generated and even how they transition. Of course there are also defaults, so now, it's up to you whether or not you want to just do the bare minimum. Well, like Brian, for example, has 37 cool transitions.

Here is a SIMPLE example of using the nextValidator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$(function(){
  //get references to my 4 steps
  var s1 = $('#step1');
  var s2 = $('#step2');
  var s3 = $('#step3');
  var s4 = $('#step4');
 
  s1.bindStep(s2,{
    nextValidator: step1_validator
  });
 
  s2.bindStep(s3);
  s3.bindStep(s4);
});
 
/* The nextValidator doesn't care what goes on
 * inside the validation method/closure as long
 * as it returns true|false.  If it gets true, the
 * next button works, if it gets false, it doesn't
 * All error reporting/validation is up to you or
 * your validation plugin.
 *
 * Simple example of validation that a username,
 * password, and password confirmation are entered
 * before moving on to the rest of the sign up form.
 *
**/
function step1_validator(){
  if(!$('#username').val()) return false;
  if(!$('#password').val()) return false;
  if(!$('#password_confirm').val()) return false;
 
  return true;
}

You may be saying, 'where can I get this swell tool?' Well from jQuery's plugins page of course.

UPDATE:
Here's a demo!

Post to Twitter Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

Comments (78) Trackbacks (3)
  1. Hi everyone!
    Question: can anyone explain to me how can I change the way the buttons (next and prev) are displayed? I’m not a specialist on js nor css… I want to center the to buttons in my form.

  2. @Ricardo, I assume something like this would work:
    $.fn.bindStep.defaults.generateMarkup = function(id1,id2,img){
    return([
    ''
    ].join(”));
    }

  3. Hi all!
    I want to do the bindstep dynamical, eg: binding is depending on dropdown-content.
    Can I do this with a callback? Can someone help me?

    greetz,
    AL

  4. Hi I am having trouble getting the buttons to appear. Are they meant to be automatically appended from the plugin Or do i have to specify a div that they will be attached to? I am so confused right now. Its not very clear how your buttons are working. Any help would be appreciated

  5. This is doing my head in! Ok I have placed this code in:

    # var step1 = $(‘#step1′);
    # var step2 = $(‘#step2′);
    # var step3 = $(‘#step3′);
    #
    # step1.bindStep(step2);
    # step2.bindStep(step3);
    #
    # $(‘#step1′).show();

    and my divs are setup and it seems to be hiding my steps except for #step1 which is fine.

    Now what I dont quite get is this part where it reads:

    “At the bottom a ‘next’ button will be appended. Click the next button and ’step 2′ appears with a ‘next’ and ‘previous’ button.”

    No buttons are showing up. I have checked my code in firebug and there is no sign of anything being appended to my original source code.

    I have tried the other ways, even ripped all the other code out to see if anything is conflicting.

    I Dont think its a browser issue as the demo seems to be running fine. (im using firefox 3.0.10 on OS X)

    Anyone else have the same trouble?

    Please someone give me some insight into what is occurring!

    Many thanks in advance…

  6. Ok I have figured out that when the div.class of div.id”step1″ is appended. it changes to “step jQueryBabyStep” when i noticed the demo has only “jQueryBabyStep” as its class. Is there a way to change this?

  7. Ahh!! this is probably the most stressful jquery script/plug I have come across. I just tested it in safari and it decided to show not even the first step. I think its very buggy still. Im just gonna give this one a miss. Nice concept though! Good luck with fixing the bugs. Would be nice if you could post a downloadable zip file with better documentation. Anyways…

  8. Steve, if you don’t have your first div displayed it won’t show it. It only hides/unhides when buttons are clicked if you decide not to show your first step, then it won’t show.

  9. Steve/Cory I am having the same problem. I do not see any buttons showing up in my version or the demo that Cory posted. Is this a browser limitation?

    I have my first div displayed, but nothing is showing up still. I have no buttons!

  10. Hi,

    I am using a synchronous ajax call to do some server side validation:

    $(document).ajaxStart(function() { $.blockUI({ message: ‘hello’, overlayCSS: { backgroundColor: ‘green’} }); })
    $(document).ajaxStop(function() { $.unblockUI(); })

    function step1_validator() {

    $.ajax({
    url: “../BlaValidationStep1″,
    type: “POST”,
    dataType: “text”,
    data: { …},
    async: false,
    error: function(XMLHttpRequest, textStatus, errorThrown) {
    $(‘#error_message_step1′).text(“Server error ” + textStatus + ” ” + errorThrown);
    },
    success: function(data) {
    var x = JSON.parse(data);
    $(‘#error_message_step1′).html(x.message);
    }
    });

    if (!$(‘#error_message_step1′).text() ) {
    return true;
    }
    else {
    return false;
    }
    }

    This works fine in Firefox but not in IE. Here ajaxStart is not invoked immediately. Is there any way to do server side validation better – even with an async ajax call?

    Thanks.

    Christian

  11. Thanks for the plugin !

    This works great with jQuery Validate except when I click next step image button, there’s only one error message display at a time, the next error message will not displayed until you correct first. I would like to display all error messages at once when step button is clicked. Is there any way I can do that ?

    Any help would be appreciated !

    Jack

  12. Awesome plugin.
    Thanks a lot.

  13. Hi. I’m trying it, but all fields insite “step n” divs ARE NOT SENT to the server.

    I tryed to use your demo and insert two fields:
    one at beggining of the form (before <step1>)

    and another one just before the end of form.

    these two fields are sent, but all fields inside step divs are not sent.

  14. Quite new to jQuery. Is this supposed to be able to work as a basic “plugin” without any config? I am having difficulty understanding your instructions in the latest version of the script while looking at your example form. Should I be able to link to the plugin script:

    Then add the following to the head of the page after the plugin?

    var step1 = $(‘#step1′);
    var step2 = $(‘#step2′);
    var step3 = $(‘#step3′);
    var step4 = $(‘#step4′);
    step1.bindStep(step2);
    step2.bindStep(step3);
    $(‘#step1′).show();

    I have labeled all my divs correctly, I am sure of that. Nothing displays at all due to the css.

    I suppose all I am asking is, do I need to edit the plugin script at all to make it function in its basic format? Should adding my steps as above be enough to spark some action?

    Thanks in advance for your help.

    Jack

  15. Hi Jackson … I’m in the same position as you!

    I have a link to jquery.js and to babysteps.js in the head.

    I added the following in the body, just before the step1 div

    var step1 = $(‘#step1′);
    var step2 = $(‘#step2′);
    var step3 = $(‘#step3′);

    step1.bindStep(step2);
    step2.bindStep(step3);

    $(‘#step1′).show();

    but like you it all remains hidden, presumably by the
    .step{display: none;}
    which I’m guessing should be over-writen by the
    $(‘#step1′).show();
    but isn’t!

  16. Dont know if anyone still uses or reads this, but I had the same issues as above, and since no-one posted a solution, I worked out looking at the source of the example that the link to babysteps.js has to go after the form. That makes the buttons appear.

    Hope that helps a fellow newbie like myself.

  17. Is it possible to pass a parameter into the validation function like:
    step1.bindStep(‘#step2′,{
    nextValidator: custom_validator(’step1′)
    });

    My form is quite complex so I wanted to create my own validation function but its having problems when I try to do this.

  18. Just wanted to add: It could be something to do with the plugin line 133 where it says:
    nextValidator : function(){return true;},
    Hope you can help.

  19. When you set nextValidator it overrides the ‘return true’. I’d venture to say your problem is:

    nextValidator: custom_validator(’step1′)

    This expects a method… you are passing it the RESULT of the method.

  20. Hello Cory O’Daniel,
    plugin is very nice and useful!!!
    I have a question:
    can I disable all animation effetcs?
    I tried with “jQuery.Fx.off = true” into “click(function()” but it doesn’t work.
    Thank you

  21. You can create whatever effect transition you want by overriding the transition method. Check the source to see the method signature so you know what arguments to expect.

  22. Does this impact switch functions, when the switch is being triggered from the visible part but the actual change occurs in the next step (that’s hidden)? I have a form where several times, your choice in a radio/checkbox will turn on/off a later question, but it’s my understanding that when part of a page is set as “hidden”, that part’s contents don’t load until the part is unhidden. Seems to me this means that any triggers would get lost, because they’d be triggering something that isn’t even loaded. Have you run into this before? Thanks!

  23. Disregard! After a bit of wrangling, managed to do up a dummy w/in the BabySteps setup, and switch-on/off triggers work across the hidden/unhidden parts. Yay!

  24. aha .. this is plugin i’m looking for :)

    Thanks

  25. If anyone is still wondering why the buttons aren’t showing it’s because you must update the javascript tag at the bottom of the code to the full url for his .js file. Provided it’s…

    script type=”text/javascript” src=”/stuff/examples/babysteps/babysteps.0.2.2.js”

    but it needs to be

    script type=”text/javascript” src=”http://coryodaniel.com/stuff/examples/babysteps/babysteps.0.2.2.js”

  26. Hello,

    I want to use BabySteps plugin for my multiparts form but I want to use the jquery validator plugin to check each step of my form.
    It’s ok to check the complete form but I didn’t find how to check each single steps as it is done in the demo (nextValidator: step1_validator).
    Your help and advices will be welcome. Thanks

  27. Hi,
    1. does it submit all the information that was checked in the field like regular form?
    2. Can it be integrated with wordPress contact form?
    3. Can I integrate it with a calc price plugin at the last step?

    Thanks


Leave a comment