Require Steps Be Done In Order
When a web page has several steps that need to be completed by the user, how does one ensure the steps are done in order?
This article describes how to put each step into an undisplayed div tag. The divs are locked so each step must be completed before the next div can be displayed. A cookie remembers the last step completed so the user can come back later to finish the steps.
The system is implemented with JavaScript and CSS. If the browser is JavaScript-disabled, none of the divs containing the steps can be opened.
Here is a demonstration of three steps to be completed in order. The source code for the demonstration is further below.
Implementing the Step By Step Requirement
Implementation is in two parts.
-
The JavaScript — The JavaScript monitors the steps completed and which steps may be displayed.
-
The div tags containing the steps — Each step has its own div tag to be displayed in its turn.
The JavaScript
Here is the JavaScript code. It is the same code used in the earlier example. See below for customization notes.
<!-- The JavaScript. Can be anywhere on the page or imported from an external file. --> <script type="text/javascript"><!-- /* Require Steps Be Done In Order Version 1.1 March 5, 2012 Will Bontrager Software, LLC https://www.willmaster.com/ Copyright 2012 Will Bontrager Software, LLC This software is provided "AS IS," without any warranty of any kind, without even any implied warranty such as merchantability or fitness for a particular purpose. Will Bontrager Software, LLC grants you a royalty free license to use or modify this software provided this notice appears on all copies. */ /////////////////// // Customization // // Three places to customize. // Place 1 -- // Specify the message to display in an alert box // when the user tries to skip a level. var CheaterMessage = "The previous level must be completed first."; // Place 2 -- // Specify the cookie name (blank for no cookie functionality). var RevealLockCookieName = "StepByStep"; // Place 3 -- // Specify how many days the cookie shall live (decimal number is OK). var CookieLifeDays = 1.5; // End of customization section // ////////////////////////////////// var LastLevelCompleted = GetCookie(); function GetCookie() { var cookiecontent = 0; if( ! RevealLockCookieName.length ) { return cookiecontent; } if(document.cookie.length > 0) { var cookiename = RevealLockCookieName + '='; var cookiebegin = document.cookie.indexOf(cookiename); var cookieend = 0; if(cookiebegin > -1) { cookiebegin += cookiename.length; cookieend = document.cookie.indexOf(";",cookiebegin); if(cookieend < cookiebegin) { cookieend = document.cookie.length; } cookiecontent = document.cookie.substring(cookiebegin,cookieend); } } return parseInt(cookiecontent); } function PutCookie(v) { if( ! RevealLockCookieName.length ) { return; } var exp = ''; if(CookieLifeDays > 0) { var now = new Date(); now.setTime(now.getTime() + parseInt(CookieLifeDays * 24 * 60 * 60 * 1000)); exp = '; expires=' + now.toGMTString(); } document.cookie = RevealLockCookieName + "=" + v + exp; } function DoOpenAndClose(open,close) { document.getElementById(open).style.display = ""; document.getElementById(close).style.display = "none"; } function DisplayLevel(level,open,close) { if( level > (LastLevelCompleted+1) ) { alert(CheaterMessage); } else { DoOpenAndClose(open,close); } } function DoneWithLevel(level,open,close) { if( level > LastLevelCompleted ) { LastLevelCompleted = level; PutCookie(level); } DoOpenAndClose(open,close); } function HideLevel(open,close) { DoOpenAndClose(open,close); } //--></script>
Customization notes:
The JavaScript has three places to customize. Each is marked in the JavaScript source code, with instructions.
-
At variable CheaterMessage — Between the quotation marks, specify the message to display in an alert box when the user tries to skip a level. If the message itself contains any quotation marks, they need to be escaped with a backward-slash character, like: \"
-
At variable RevealLockCookieName — Between the quotation marks, specify the cookie name. To omit using a cookie, put nothing between the quotation marks.
-
At variable CookieLifeDays — Specify how many days the cookie shall live. To specify a fraction of a day, use a decimal number.
Put the JavaScript anywhere on the page, in the HEAD or BODY area. The JavaScript may be imported from an external file.
The Div Tags Containing The Steps
Here are the div tags containing the steps used in the earlier example. Notes follow.
<!-- The divs are assigned steps 1, 2, etc, in numerical order. It's the way the JavaScript keeps track of which have been completed and which may be opened. --> <!-- Only the first div is commented. --> <!-- The div for step 1 --> <!-- The link to open the first div is assigned id="levelAlink". It can be assigned any unique value. --> <div id="levelAlink"> <!-- The DisplayLevel() function needs three parameters: the div level number, and the div id to open, and the div id to close. --> <a href="javascript:DisplayLevel(1,'levelA','levelAlink')">Open Step One</a> </div> <!-- The first div is assigned id="levelA". It can be assigned any unique id value. --> <div id="levelA" style="display:none; border:1px solid black; padding:15px;"> <!-- The X's in the corners to close box without clicking the "done with this step link." Optional, of course. --> <!-- The HideLevel() function needs two parameters: the div id to open and the div id to close. --> <div style="float:left; font-size:18px;"><a href="javascript:HideLevel('levelAlink','levelA')">[X]</a></div> <div style="float:right; font-size:18px;"><a href="javascript:HideLevel('levelAlink','levelA')">[X]</a></div> <div style="clear:both;"></div> <!-- The content for the step. --> <p>Instructions go here for step one.</p> <!-- The "done with this step" link. --> <!-- The DoneWithLevel() function needs three parameters: the div level number, the div id to open, and the div id to close. --> <div style="text-align:right; font-size:14px; font-weight:bold;"><a href="javascript:DoneWithLevel(1,'levelAlink','levelA')">[click when step has been completed]</a></div> <!-- End of div. --> </div> <hr style="margin:15px 0 15px 0;"> <!-- The div for step 2 --> <div id="levelBlink"> <a href="javascript:DisplayLevel(2,'levelB','levelBlink')">Open Step Two</a> </div> <div id="levelB" style="display:none; border:1px solid black; padding:15px;"> <div style="float:left; font-size:18px;"><a href="javascript:HideLevel('levelBlink','levelB')">[X]</a></div> <div style="float:right; font-size:18px;"><a href="javascript:HideLevel('levelBlink','levelB')">[X]</a></div> <div style="clear:both;"></div> <p>Instructions go here for step two.</p> <div style="text-align:right; font-size:14px; font-weight:bold;"><a href="javascript:DoneWithLevel(2,'levelBlink','levelB')">[click when step has been completed]</a></div> </div> <hr style="margin:15px 0 15px 0;"> <!-- The div for step 3 --> <div id="levelClink"> <a href="javascript:DisplayLevel(3,'levelC','levelClink')">Open Step Three</a> </div> <div id="levelC" style="display:none; border:1px solid black; padding:15px;"> <div style="float:left; font-size:18px;"><a href="javascript:HideLevel('levelClink','levelC')">[X]</a></div> <div style="float:right; font-size:18px;"><a href="javascript:HideLevel('levelClink','levelC')">[X]</a></div> <div style="clear:both;"></div> <p>Instructions go here for step three.</p> <div style="text-align:right; font-size:14px; font-weight:bold;"><a href="javascript:DoneWithLevel(3,'levelClink','levelC')">[click when step has been completed]</a></div> </div>
Notes:
Two id values are associated with each step. One id valus is associated with a link to open the div with the step and the other is associated with the div containing the step itself. The JavaScript keeps track of which steps have been completed and which step is next in order.
The above code is well commented with instructions at the point where the instructions apply.
Only the first step div is commented. Each div with a step is constructed similarly. The significant changes are the step numbers and the id values at each step. For your convenience, the step numbers are printed in red and id values are printed in blue.
Implementing the System
It may be prudent to implement the system by first implementing the example. Here is a complete web page with the example.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <title>Require Step By Step Example</title> <style type="text/css"> body { font-family:sans-serif; margin:100px 100px 0 150px; } p { font-size:14px; } </style> </head> <body> <script type="text/javascript"><!-- /* Require Steps Be Done In Order Version 1.1 March 5, 2012 Will Bontrager Software, LLC https://www.willmaster.com/ Copyright 2012 Will Bontrager Software, LLC This software is provided "AS IS," without any warranty of any kind, without even any implied warranty such as merchantability or fitness for a particular purpose. Will Bontrager Software, LLC grants you a royalty free license to use or modify this software provided this notice appears on all copies. */ /////////////////// // Customization // // Three places to customize. // Place 1 -- // Specify the message to display in an alert box // when the user tries to skip a level. var CheaterMessage = "The previous level must be completed first."; // Place 2 -- // Specify the cookie name (blank for no cookie functionality). var RevealLockCookieName = "StepByStep"; // Place 3 -- // Specify how many days the cookie shall live (decimal number is OK). var CookieLifeDays = 1.5; // End of customization section // ////////////////////////////////// var LastLevelCompleted = GetCookie(); function GetCookie() { var cookiecontent = 0; if( ! RevealLockCookieName.length ) { return cookiecontent; } if(document.cookie.length > 0) { var cookiename = RevealLockCookieName + '='; var cookiebegin = document.cookie.indexOf(cookiename); var cookieend = 0; if(cookiebegin > -1) { cookiebegin += cookiename.length; cookieend = document.cookie.indexOf(";",cookiebegin); if(cookieend < cookiebegin) { cookieend = document.cookie.length; } cookiecontent = document.cookie.substring(cookiebegin,cookieend); } } return parseInt(cookiecontent); } function PutCookie(v) { if( ! RevealLockCookieName.length ) { return; } var exp = ''; if(CookieLifeDays > 0) { var now = new Date(); now.setTime(now.getTime() + parseInt(CookieLifeDays * 24 * 60 * 60 * 1000)); exp = '; expires=' + now.toGMTString(); } document.cookie = RevealLockCookieName + "=" + v + exp; } function DoOpenAndClose(open,close) { document.getElementById(open).style.display = ""; document.getElementById(close).style.display = "none"; } function DisplayLevel(level,open,close) { if( level > (LastLevelCompleted+1) ) { alert(CheaterMessage); } else { DoOpenAndClose(open,close); } } function DoneWithLevel(level,open,close) { if( level > LastLevelCompleted ) { LastLevelCompleted = level; PutCookie(level); } DoOpenAndClose(open,close); } function HideLevel(open,close) { DoOpenAndClose(open,close); } //--></script> <div id="levelAlink"> <a href="javascript:DisplayLevel(1,'levelA','levelAlink')">Open Step One</a> </div> <div id="levelA" style="display:none; border:1px solid black; padding:15px;"> <div style="float:left; font-size:18px;"><a href="javascript:HideLevel('levelAlink','levelA')">[X]</a></div> <div style="float:right; font-size:18px;"><a href="javascript:HideLevel('levelAlink','levelA')">[X]</a></div> <div style="clear:both;"></div> <p>Instructions go here for step one.</p> <div style="text-align:right; font-size:14px; font-weight:bold;"><a href="javascript:DoneWithLevel(1,'levelAlink','levelA')">[click when step has been completed]</a></div> </div> <hr style="margin:15px 0 15px 0;"> <div id="levelBlink"> <a href="javascript:DisplayLevel(2,'levelB','levelBlink')">Open Step Two</a> </div> <div id="levelB" style="display:none; border:1px solid black; padding:15px;"> <div style="float:left; font-size:18px;"><a href="javascript:HideLevel('levelBlink','levelB')">[X]</a></div> <div style="float:right; font-size:18px;"><a href="javascript:HideLevel('levelBlink','levelB')">[X]</a></div> <div style="clear:both;"></div> <p>Instructions go here for step two.</p> <div style="text-align:right; font-size:14px; font-weight:bold;"><a href="javascript:DoneWithLevel(2,'levelBlink','levelB')">[click when step has been completed]</a></div> </div> <hr style="margin:15px 0 15px 0;"> <div id="levelClink"> <a href="javascript:DisplayLevel(3,'levelC','levelClink')">Open Step Three</a> </div> <div id="levelC" style="display:none; border:1px solid black; padding:15px;"> <div style="float:left; font-size:18px;"><a href="javascript:HideLevel('levelClink','levelC')">[X]</a></div> <div style="float:right; font-size:18px;"><a href="javascript:HideLevel('levelClink','levelC')">[X]</a></div> <div style="clear:both;"></div> <p>Instructions go here for step three.</p> <div style="text-align:right; font-size:14px; font-weight:bold;"><a href="javascript:DoneWithLevel(3,'levelClink','levelC')">[click when step has been completed]</a></div> </div> </body> </html>
Make incremental changes to the example, testing each change, until it is fully transformed into what is required for your implementation.
The steps now are done in order.
Will Bontrager