As I slowly rewrite NJTheater.com, one task that I was trying to move from a MSAccess application to a webpage would be made much easier if put in a wizard form, with the user being led through the steps. Since I was using jQuery throughout the site, I figured I could find a plug-in for the job, and I did - sorta.
After rejecting a couple, I found formwizard by Jan Sundman, which mostly fit my needs. I would need to make a small change - but, I never can stop at just one small change. In the end, I’ve got a plugin which has at it’s core Jan’s code, but is nevertheless quite different. The revision, with docs and examples can be found here: Wizard.
The executive summary of it’s use: You have one form. It is divided up into several <div>
s, each marked with the class “step”. You call $("#theForm").Wizard()
. Each <div>
is displayed to the user individually, and they can click Next or Back buttons to move between the page. When the users clicks Next on the final page, the form is submitted. There are a lot of options, and you could choose to make it much more complicated.
The first thing you’ll note about it, if you are familiar with the original, is that it, to the best of my abilities, now confirms to the jQuery UI standard for interface and CSS theming. I also added a new callback, several new methods, and a couple new options. Comparing the new code to Jan’s code is a bit tricky because the jQuery UI framework wants methods as tag properties of an object (i.e. SomeFunc : function() {.....}
rather than function SomeFunc() {....}
), but the major source code difference really had nothing to to with that nor had any good code-quality reason: I made some unnamed functions into named function, and alphabetized the methods, just because it made it easier for me to navigate through the code. However, this does make doing a DIFF between the two source file difficult.
So what were the more functional changes between the two versions? Mostly they reflect a somewhat different view of the use of wizards. In Jan’s code it seems, he largely viewed the wizard as just one big form, divided up into pages with one submit at the end. There was some infrastructure to alter the flow through the wizard, but it was limited. (I’m still not quite sure of the utility of the “linkClass” in Jan’s code in real-world situations)
I see a wizard as guiding the users through a multi-step process, where what you see on step 3 depends on ajax calls based on what you entered in Step 2, and your choices there affects the options in step 4. So, you’d need more control as the user moved from step to step. Jan’s apparently saw this need as well, and added the afterBack and afterNext callbacks, but they pass no parameters - you are told that the user has click “next”, but are left to your own devices to know where he is. I figured a developer would be more concerned about where the user was in the wizard, than how he got there. So I added the “Show” callback (also wired as an event by the framework). It tells you what step the user has just moved to, by it’s index number and by a jQuery object of the div itself. It also says if the user got there by moving forward or backward.</p>
Also, Jan added validation by means of the standard jquery.validate.js plugin. In that scenario, the user would click “Next” and then the plugin would tell him to fix things. That’s not the way Wizards normally work, where the “Next” button is disabled upon the step is complete. So, I added an option autoDisabledNext
which always displays the Next button grayed initially when moving to a new step, and waits for the script to re-enable it in response to some action by the user. The “enableNext” method handles that (with “disableNext”, “enableBack” and “disableBack” also added to give the developer complete control in this area).
In Jan’s original, the formwizard() method took three parameters, each js objects, the first for the wizard itself while the other two were passed to the forms plugin and the validation plugin respectively, which are optional — the plugins, not the parameters. So if you weren’t using those plugins, you had to pass empty objects. I moved them to named parameters in with the other wizard options, where they could be defaulted. Similarly, the boolean flags which had to be explicitly set, now derive their settings from the environment. You can still explicitly set them if you need to overrule that determination.
A few other changes just seemed to make more sense to me. formwizard expected the form to have a Submit and Reset buttons, which it converted into the Next and Back respectively. Submit for Next wasn’t too bad, but Reset for Back just seemed wrong. If you are going to have a button controlled strictly by Javascript, it should be a <button> element. So, they are indicated, by default, by the classes “wizard_next” and “wizard_back”. Another one just seems like fun and I wondered how difficult it would be: You can specify the effect used to display each page, via the “animate” option. The default is “FadeIn”.
Finally, I included a “old-school” jQuery plugin called “formwizard” which sets all the defaults I changed back to the way they were in Jan’s original, and then calls Wizard(), so we should have full backward compatibility.
Note: Despite my best effort to make the docs page look just like one of those for actual jQuery UI widgets, it is not part of the official jQuery UI package, and although submitted to them for review, probably will not be part of the official release any time soon (“not any time soon” == “a few years at least”).
Now, how can you help Wizard become part of the official jQuery UI package. Well, I guess you could mention in your blogs, tweets, forum message (particularly on the jQuery UI Google Group) that “wouldn’t it be great if jQuery UI included a Wizard widget — just like that one James stolen from Jan”.