Making a Wizard with JavaScript

By Curtis Dicken

Introduction to Creating Wizards

Good web design is not just about making your website beautiful; it’s also about being user-friendly. One of the most common tools for a user-friendly website is the Wizard. In this installment we’ll create a wizard for subscribing to some websites. We’ll use JavaScript to manipulate display and styles to make it slick and easy to use without having to post anything to the server until we are finished.

Parts of a Wizard

Most of the time you encounter a wizard it will have the same general makeup:
  1. Getting Started
  2. Individual Steps
  3. Final Review
  4. Submission Confirmation
Getting Started – This step gives the user the basic info on what your wizard will do and what information the user may need in order to complete the wizard. If the wizard is rather lengthy it can also provide an estimate on how long it will take to complete.

Individual Steps – This is the main part of your wizard. Here you basically break down all of the data that you want to collect into logical steps. In our example below we have just 3 steps: Name, Account Access, and Select Subscriptions.

Final Review – This is a very important step if you want to ensure that incoming data is as accurate as possible. Display the data that you have collected with your wizard in an organized fashion. If you have a lengthy wizard you may want to do a periodic review throughout the process so that the user isn’t inundated with too much to review at the end. If there is too much to review at the end users are likely to skip the review altogether.

Submission Confirmation – This final step lets the user know that their submission has been processed and usually thanks them for their efforts. Since this step happens after the form data is processed on the server we will not cover it in our example.

JavaScript Wizard Example

<html>

<head>

    <title>JavaScript Subscription Wizard Example</title>

    <script type="text/javascript">

    

        // This function handles style and display changes for each next button click

        function handleWizardNext()

        {

            if (document.getElementById('ButtonNext').name == 'Step2')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step3';

                document.getElementById('ButtonPrevious').name = 'Step1';

                // Disable/enable buttons when reach reach start and review steps

                document.getElementById('ButtonPrevious').disabled = '';

                // Set new step to display and turn off display of current step

                document.getElementById('Step1').style.display = 'none';

                document.getElementById('Step2').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep2').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep1').style.backgroundColor = 'Silver';

            }

            else if (document.getElementById('ButtonNext').name == 'Step3')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step4';

                document.getElementById('ButtonPrevious').name = 'Step2';

                document.getElementById('Step2').style.display = 'none';

                document.getElementById('Step3').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep3').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep2').style.backgroundColor = 'Silver';

            }

            else if (document.getElementById('ButtonNext').name == 'Step4')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step5';

                document.getElementById('ButtonPrevious').name = 'Step3';

                // Set new step to display and turn off display of current step

                document.getElementById('Step3').style.display = 'none';

                document.getElementById('Step4').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep4').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep3').style.backgroundColor = 'Silver';

            }

            else if (document.getElementById('ButtonNext').name == 'Step5')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = '';

                document.getElementById('ButtonPrevious').name = 'Step4';

                // Disable/enable buttons when reach reach start and review steps

                document.getElementById('ButtonNext').disabled = 'disabled';

                document.getElementById('SubmitFinal').disabled = '';

                // Set new step to display and turn off display of current step

                document.getElementById('Step4').style.display = 'none';

                document.getElementById('Step5').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep5').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep4').style.backgroundColor = 'Silver';

                // Load table elements for final review step

                loadStep5Review();

            }

        }

        

        // This function handles style and display changes for each previous button click

        function handleWizardPrevious()

        {

            if (document.getElementById('ButtonPrevious').name == 'Step1')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step2';

                document.getElementById('ButtonPrevious').name = '';

                // Disable/enable buttons when reach reach start and review steps

                document.getElementById('ButtonPrevious').disabled = 'disabled';

                // Set new step to display and turn off display of current step

                document.getElementById('Step2').style.display = 'none';

                document.getElementById('Step1').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep1').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep2').style.backgroundColor = 'Silver';

            }

            else if (document.getElementById('ButtonPrevious').name == 'Step2')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step3';

                document.getElementById('ButtonPrevious').name = 'Step1';

                // Set new step to display and turn off display of current step

                document.getElementById('Step3').style.display = 'none';

                document.getElementById('Step2').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep2').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep3').style.backgroundColor = 'Silver';

            }

            else if (document.getElementById('ButtonPrevious').name == 'Step3')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step4';

                document.getElementById('ButtonPrevious').name = 'Step2';

                // Set new step to display and turn off display of current step

                document.getElementById('Step4').style.display = 'none';

                document.getElementById('Step3').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep3').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep4').style.backgroundColor = 'Silver';

            }

            else if (document.getElementById('ButtonPrevious').name == 'Step4')

            {

                // Change the button name - we use this to keep track of which step to display on a click

                document.getElementById('ButtonNext').name = 'Step5';

                document.getElementById('ButtonPrevious').name = 'Step3';

                // Disable/enable buttons when reach reach start and review steps

                document.getElementById('ButtonNext').disabled = '';

                document.getElementById('SubmitFinal').disabled = 'disabled';

                // Set new step to display and turn off display of current step

                document.getElementById('Step5').style.display = 'none';

                document.getElementById('Step4').style.display = '';

                // Change background color on header to highlight new step

                document.getElementById('HeaderTableStep4').style.backgroundColor = 'Yellow';

                document.getElementById('HeaderTableStep5').style.backgroundColor = 'Silver';

            }

        }

        

        // This function handles loading the review table innerHTML for the user to review before final submission

        function loadStep5Review()

        {

            // Assign values to appropriate cells in review table

            document.getElementById('ReviewFirstName').innerHTML = document.getElementById('TextFirstName').value;

            document.getElementById('ReviewMiddleName').innerHTML = document.getElementById('TextMiddleName').value;

            document.getElementById('ReviewLastName').innerHTML = document.getElementById('TextLastName').value;

            document.getElementById('ReviewEmail').innerHTML = document.getElementById('TextEmail').value;

            // Indicate Yes or No based on subscription checkbox checked

            if (document.getElementById('CheckboxHtmlGoodies').checked == 1)

            {

                document.getElementById('ReviewHtmlGoodies').innerHTML = 'Yes';

            }

            else

            {

                document.getElementById('ReviewHtmlGoodies').innerHTML = 'No';

            }

            if (document.getElementById('CheckboxJavaScript').checked == 1)

            {

                document.getElementById('ReviewJavaScript').innerHTML = 'Yes';

            }

            else

            {

                document.getElementById('ReviewJavaScript').innerHTML = 'No';

            }

            if (document.getElementById('CheckboxWdvl').checked == 1)

            {

                document.getElementById('ReviewWdvl').innerHTML = 'Yes';

            }

            else

            {

                document.getElementById('ReviewWdvl').innerHTML = 'No';

            }

            // Special case to display password as asterisks

            var iCounter = 1;

            var iCharacterCount = document.getElementById('TextPassword').value.length;

            var passwordMasked = '';

            for (iCounter = 1; iCounter <= iCharacterCount; iCounter++)

            {

                passwordMasked = passwordMasked + '*';

            }

            document.getElementById('ReviewPassword').innerHTML = passwordMasked;

        }

    </script>

</head>

<body>

<form id="SubscriptionWizard" action="" method="post">

    <table border="1" cellpadding="5" cellspacing="0" id="HeaderTable">

        <tr>

            <td id="HeaderTableStep1" style="background-color:Yellow">

                Step 1: Getting Started</td>

            <td id="HeaderTableStep2" style="background-color:Silver">

                Step 2: Name</td>

            <td id="HeaderTableStep3" style="background-color:Silver">

                Step 3:&nbsp; Account Access</td>

            <td id="HeaderTableStep4" style="background-color:Silver">

                Step 4: Select subscriptions</td>

            <td id="HeaderTableStep5" style="background-color:Silver">

                Step:5 Finalize &amp; Submit</td>

        </tr>

    </table>

    <br />

<span id="Step1"><strong>

    Welcome to our Subscription Wizard!<br />

    </strong>

        <br />

    This wizard simulates subscribing for access to website content. Each step is highlighted in the header. 

    <br />

    This step is intended to provide the user with everything they need to know to get started.

    <br />

</span>

<span id="Step2" style="display:none">

    <table border="0" cellpadding="5" cellspacing="0">

        <tr>

            <td align="right">

                First name:</td>

            <td>

                <input id="TextFirstName" name="FirstName" type="text" /></td>

        </tr>

        <tr>

            <td align="right">

                Middle name:</td>

            <td>

                <input id="TextMiddleName" name="MiddleName" type="text" /></td>

        </tr>

        <tr>

            <td align="right">

                Last name:</td>

            <td>

                <input id="TextLastName" name="LastName" type="text" /></td>

        </tr>

    </table>

</span>

<span id="Step3" style="display:none">

    <table border="0" cellpadding="5" cellspacing="0">

        <tr>

            <td align="right">

                Email:</td>

            <td>

                <input id="TextEmail" name="Email" type="text" /></td>

        </tr>

        <tr>

            <td align="right">

                Password:</td>

            <td>

                <input id="TextPassword" name="Password" type="password" /></td>

        </tr>

    </table>

</span>

<span id="Step4" style="display:none">

    <table border="0" cellpadding="5" cellspacing="0">

        <tr>

            <td align="left" colspan="2">

                <strong>

                Select your subscription:</strong></td>

        </tr>

        <tr>

            <td align="right">

                HtmlGoodies.com:</td>

            <td>

                <input id="CheckboxHtmlGoodies" name="CheckboxHtmlGoodies" type="checkbox" value="Yes" /></td>

        </tr>

        <tr>

            <td align="right">

                JavaScript.com:</td>

            <td>

                <input id="CheckboxJavaScript" name="CheckboxJavaScript" type="checkbox" value="Yes" /></td>

        </tr>

        <tr>

            <td align="right">

                wdvl.com</td>

            <td>

                <input id="CheckboxWdvl" name="CheckboxWdvl" type="checkbox" value="Yes" /></td>

        </tr>

    </table>

</span>

<span id="Step5" style="display:none">

    <table border="0" cellpadding="5" cellspacing="0">

        <tr>

            <td colspan="2">

                <strong>Final Review:</strong></td>

        </tr>

        <tr>

            <td align="right">

                First name:</td>

            <td id="ReviewFirstName">

                </td>

        </tr>

        <tr>

            <td align="right">

                Middle name:</td>

            <td id="ReviewMiddleName">

                </td>

        </tr>

        <tr>

            <td align="right">

                Last name:</td>

            <td id="ReviewLastName">

                </td>

        </tr>

        <tr>

            <td align="right">

                Email:</td>

            <td id="ReviewEmail">

            </td>

        </tr>

        <tr>

            <td align="right">

                Password:</td>

            <td id="ReviewPassword">

            </td>

        </tr>

        <tr>

            <td align="left">

                <strong>

                Subscribed to:</strong></td>

            <td>

            </td>

        </tr>

        <tr>

            <td align="right">

                HtmlGoodies.com:</td>

            <td id="ReviewHtmlGoodies">

            </td>

        </tr>

        <tr>

            <td align="right">

                JavaScript.com:</td>

            <td id="ReviewJavaScript">

            </td>

        </tr>

        <tr>

            <td align="right">

                wdvl.com:</td>

            <td id="ReviewWdvl">

            </td>

        </tr>

    </table>

</span>

<br />    

<table border="0" cellpadding="5" cellspacing="0">

    <tr>

        <td>

            <input id="ButtonPrevious" type="button" value="Previous" disabled="disabled" name="" onclick="handleWizardPrevious()" /></td>

        <td>

            <input id="ButtonNext" type="button" value="Next" name="Step2" onclick="handleWizardNext()" /></td>

        <td>

            <input id="SubmitFinal" type="submit" value="Finish" disabled="disabled" /></td>

    </tr>

</table>

</form>

</body>

</html>

Breaking Down the Wizard

The first step in designing a wizard is to break down your form into logical steps. In our example I made 3 simple steps: Name, Account Access, and Select Subscription. For each step I made several “mini-forms” with tables that held my input elements and descriptive text. I next created my review table for my final step. The final table should only have descriptive text for each item to review and an empty cell for each item that we will populate using JavaScript innerHTML. Lastly, I wrote a bit of descriptive text for my Getting Started first step so that the user would know what to expect.

Once I had my steps laid out I brought it all together by adding a header table, placing a span tag around each step, and adding a footer for my Previous, Next and Finish buttons. The header table has 5 columns with the step number and a title for each step. The background color for each cell was set to silver except for the starting step which I highlighted with yellow. The footer holds my 3 buttons of which Previous and Finish are disabled when the page loads as neither Previous or Finish are applicable for step 1.

The next step of the process was to create JavaScript functions to handle the button clicks for Previous and Next. I titled those functions handleWizardPrevious and handleWizardNext. In order to know how to handle each Previous and Next click I decided to use the name attribute for each button to keep track of what step to move to next. You should notice that name for the Next button starts off with a value of Step2 and it calls the handleWizardNext for the onclick event.

Now if you take a look at the handleWizardNext function you will notice our first order of business is to look at the button and determine which step to display next. Once we have made that determination we perform the following operations where applicable:

  1. Change the name value for both the Next and Previous buttons to reflect their new step values.
  2. Make visible the new step that needs to be completed and make invisible the current step. We do this by changing the style.display of the span tag that surrounds each step. Changing the display value to None causes the browser to not show the contents of the span tag while changing the value to an empty string causes the browser to show the contents.
  3. Enable and disable buttons as necessary. For example, the Previous button should be disabled for step one and the Finish button remains disabled until we are on the final review step.
  4. Lastly we manipulate the background color in the step header table to turn the highlight on for the new step and off for the current step. We do this by changing the table cell style.backgroundColor value.
The handleWizardPrevious function contains the same general operations as the handleWizardNext function. There is also one more function that I needed to create in order to compile the review step. The loadStep5Review function takes values straight from the input elements and writes those values into the appropriate table cells using innerHTML. For added password security, we created a special bit of code to render the correct number of asterisks instead of the actual password the user entered. Lastly we do a quick check on the check boxes and render a Yes or No depending on whether the check box has been checked.

The last thing you will note is the Finish button which actually posts the form. Our Previous and Next buttons are of type Button so we can use them for navigation while the Finish button is of type Submit so that the page posts when clicked. From there you should set the form action to process the page data and forward the user to an appropriate completion or thank you page. Put all the pieces together and you have a simple quick wizard that your users will appreciate.

Conclusion

Wizards are easy for both the user and the developer. As you can see from the example above it’s not too difficult to put together a wizard. With just a few changes to styles and display you can put together a very slick wizard interface. You can also add validation, images, graphical buttons and any number of other finishing touches to make your wizard even better.

Happy scripting!

Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •