
Making the tour functional
Now that the layout of our page is complete, let's discuss in brief how we are going to implement the tour functionality. We have already created a tour.js
file that we will use for writing all the JavaScript code.
We will initialize the accordion for which we have already written the markup, and we will also initialize the tooltip that will appear on hovering over the Contact Us link.
After that, we will define a jQuery UI dialog
component with some basic settings and buttons for navigating the tour. Next, we will define a JavaScript array that will contain all the steps of the tour. Finally, we will create a tour object, and we will write the functions that will initialize the tour, display a tour step, and handle the Previous, Next, and End Tour buttons.
Let's write the code for the aforementioned steps and discuss them in detail.
Initializing accordion and tooltips
The best practice when writing JavaScript is to start by writing a jQuery $(document).ready()
handler that ensures the related jQuery or JavaScript code is executed after the page has loaded. Open the tour.js
file and start by writing the following code in it:
$(document).ready(function(){ $('#accordion').accordion({animate : false}); $(document).tooltip( { items : '#contact', content : function() { var strContact = '<img src="http://maps.googleapis.com/maps/api/staticmap?center=New+Delhi,India&zoom=13&size=300x200&sensor=false"/>'; strContact+= '<hr/>In case of any issues, here is the address of our new office in Central Delhi which is well connected to all the places.Feel free to visit us anytime.'; strContact+= '<hr><span class="ui-icon ui-icon-home" style="float: left; margin-right: 5px;"></span>#23, Rachna Building, Karol Bagh -110005'; strContact+= '<hr><span class="ui-icon ui-icon-mail-closed" style="float: left; margin-right: 5px;"></span><a href="mailto:awesomecompany@ourlocation.com">awesomecompany@ourlocation.com</a>'; return strContact; } }); });
In our markup, we assigned the id
value accordion
to the div
that contains the markup for the accordion
. Inside the $(document).ready()
handler, the first line initializes the accordion
with the animate
option set to false
. We also want a tooltip to appear on the Contact Us link. To achieve this, we initialize the tooltip
component of jQuery UI.
If the tooltip
component is initialized without providing any options, it displays the value of the title
attribute in a tooltip. Since we want to display custom HTML, we have used two options, items
and content
, for it. The items
option decides which elements will display the tooltip, and in the content
option, we can provide any text or HTML to be displayed inside the tooltip. The value of items
option has been set to #contact
. To set the value of the content
option, we created a string
. This string contains an image and some information text. The source for image is a static image tile from Google Maps that shows the location of a place. You can set the value from center to any place of your choice.
Now, we can check the progress so far. Save the file and refresh the index.html
page in the browser. You will find that jQuery UI's accordion has been styled using jQuery UI's theme and has also become active. Hovering your mouse over the Contact Us link will show the tooltip with an image and the text we defined in the content
option while initializing the tooltip
.

Defining the dialog
It's time to initialize the dialog box. We already defined a div
with id
dialog
in the markup. We will convert the said div
to jQuery UI dialog box. For this, we need to define settings for the dialog and also the buttons that will appear in it. We will add the following code outside the $(document).ready()
event handler to create the dialog:
var tourDialog = $('#dialog').dialog( { minWidth : 315, draggable : false, buttons: [ { id : 'buttonPrevious', text: 'Previous', click: function() { }, icons: { primary: 'ui-icon-carat-1-w' } }, { id : 'buttonNext', text: 'Next', click: function(event) { }, icons: { secondary: 'ui-icon-carat-1-e' } }, { text: 'End Tour', click: function() { }, icons: { secondary: 'ui-icon-close' } } ], show : 'fold', hide : 'fold' });
In the preceding code, we defined five options while creating the dialog. Let's look at all of these one by one:
minWidth
: This option defines the minimum width the dialog must take. For our purposes, we have set it to315
.draggable
: Since the dialog box will appear at specific places denoting respective steps of the tour, we do not want users to drag the dialog. Hence, we have set this option tofalse
.buttons
: A dialog box can have one or more buttons that can be defined using thebuttons
option. We need to provide an array of objects for buttons. Each object in the array represents a button that will be displayed at the bottom of the dialog. We have defined three buttons, each having anid
, a displaytext
, aclick
event handler, and an icon. The first button has theid
buttonPrevious
and displaytext
is Previous; we have also provided a primary icon for this button. The second button hasid
buttonNext
and the displaytext
is Next. Note that we have provided a secondary icon here. The difference between the primary and secondary icons is that the primary icon appears on the left of the text and the secondary icon appears to the right of the text. The third button has no id but has the displaytext
End Tour and a secondary icon. We have left the click event handlers for all three buttons empty for now. We will go back to these event handlers later in the chapter.show
: We can decide which effect will be used when the dialog is displayed. Any value mentioned in jQuery UI effects can be provided.hide
: This is used to define the effect that will be used when the dialog closes.
After writing the preceding code, if you reload the index.html
page in your browser, you will see that an empty dialog box with three buttons appears at the centre of the page as soon as the page finishes loading.

We definitely do not want this to happen; the dialog must be displayed at the appropriate position only when the Start Tour button is clicked. Hence, we will add another option to the dialog, which will initialize the dialog but will not display it automatically. Add another option to the dialog initialization code with the following code:
autoOpen : false
You can check again by reloading the page; the dialog box will not appear now.
Another important thing to note is that we used the variable tourDialog
to keep a reference to the initialized dialog. This tourDialog
variable will be used henceforth in the code to access the dialog.
Defining the tour steps
For the home page we have designed, our tour will have 12 steps. Each of these steps will be represented by a JavaScript object that has the following structure:
{ element : '#logo', title : 'We have changed the logo !', content : 'Did you notice that we have made some changes to our logo as well. ', sequence : 1 }
Let's see what each property does:
element
: This indicates the HTML element where the tour dialog box will appeartitle
: This is the title that will be displayed in the dialog boxcontent
: This is the HTML content displayed in the dialog boxsequence
: This is a number indicating the step of the tour. We will start with1
and proceed with 2, 3, and so on
Since we plan to display the tour steps on accordion
as well, we will need two more properties:
isAccordion
: The value for this property will be set totrue
if theelement
property is part of an accordion.accordionIndex
: This is the 0-based index of accordion panels where the tour step will be displayed. Using this property value, we will be able to open a specific panel of accordion before displaying a tour step.
Here is the full structure of steps of the tour for our example home page in this chapter:
var steps = [ { element : '#logo', title : 'We have changed the logo !', content : 'Did you notice that we have made some changes to our logo as well. ', sequence : 1 }, { element : '#menu', title : 'Menu On Left', content : 'We have placed all the menu items on left hand side for quick access.', sequence : 2 }, { element : '#orders', title : 'Your Orders', content : 'Orders menu has a submenu which links to different pages.', sequence : 3 }, { element : '#profile', title : 'Your Profile', content : 'This link will take you to your profile page where you will be able to edit your profile and change password among other things', sequence : 4 }, { element : '#help', title : 'Get Help', content : 'Use this link to get help related to any issues', sequence : 5 }, { element : '#lastLink', title : 'Last Menu Link', content : 'This is last link of menu', sequence : 6 }, { element : '#section1', title : 'Buy Cat Posters', content : 'We have introduced a new category where you can buy posters of cute cats ', isAccordion : true, accordionIndex : 0, sequence : 7 }, { element : '#section2', title : 'Buy Dog Posters', content : 'Dog lovers also welcome.', isAccordion : true, accordionIndex : 1, sequence : 8 }, { element : '#section3', title : 'Watch videos', content : 'We have collected some of the best videos from web and you can see them here', isAccordion : true, accordionIndex : 2, sequence : 9 }, { element : '#cart', title : 'Your Cart', content : 'This is your shopping cart where all the products you have selected will be displayed.', sequence : 10 }, { element : '#contact', title : 'Contact Us', content : function() { var strContact = '<img src="http://maps.googleapis.com/maps/api/staticmap?center=New+Delhi,India&zoom=13&size=280x200&sensor=false"/>'; strContact+= '<hr/>In case of any issues, here is the address of our new office in Central Delhi which is well connected to all the places.Feel free to visit us anytime.'; strContact+= '<hr><span class="ui-icon ui-icon-home" style="float: left; margin-right: 5px;"></span>#23, Rachna Building, Karol Bagh -110005'; strContact+= '<hr><span class="ui-icon ui-icon-mail-closed" style="float: left; margin-right: 5px;"></span>awesomecompany@ourlocation.com'; strContact+= '<hr>You can take your mouse over Contact Us link if you want to see this information later.'; return strContact; }, sequence : 11 }, { element : '#startTour', title : 'Thank You!', content : 'Thank you for going through through the tour.', sequence : 12 } ];
We defined an array named steps
with 12 objects. On going through each of these objects, you will see that we are starting with the logo
, then proceeding to the menu, and so on. For quick reference, here are the id
values of all the HTML elements where tour
will be displayed one step at a time:
logo
menu
orders
profile
help
lastLink
section1
section2
section3
cart
contact
startTour
Initializing the tour
We have prepared the entire markup and JavaScript required to build the tour. Let's dive in and write some awesome JavaScript code. But before that, I would like to introduce you to a JavaScript best coding practice.
Since the code size will grow in this chapter, as well as in following chapters, we will use a JavaScript pattern called object literal to organize our code. Simply put, an object literal pattern implies defining a single JavaScript object with a set of comma-separated key-value pairs. Keys can be strings or identifiers and values can be strings, identifiers, or functions. The advantage of this pattern is that it does not pollute the global namespace. Keys that are defined inside the object will not be accessible directly outside that object. You will see this in practice in a moment.
First of all, visit the $(document).ready()
event handler and add the following line of code in the end:
tour.init();
The preceding line calls the init
function of a JavaScript object named tour
. Outside the $(document).ready()
event handler, let's define the tour
object and its init
function with the following code:
var tour = { triggerElement : '#startTour', tourStep : 0, tourSteps : steps, defaultTitle : 'Welcome to the tour !', defaultContent: 'This tour will show you the new changes we have made to our site layout. <br> Please use next previous buttons to proceed. Click the End Tour button whenever you want to finish the tour.', init : function() { if(this.tourSteps == undefined || this.tourSteps.length == 0) { alert('Cannot start tour'); return; } $(this.triggerElement).on('click', function(event) { tour.showStep(tour.defaultTitle, tour.defaultContent, $(this)); return false; }); } };
The value of the triggerElement
property is the id
of the element, by clicking on which the tour will start. You can set it to any element. In our example page, we have created an element with the id
startTour
for this purpose. The tourStep
property will keep track of the current step of the tour. Then, the tourSteps
property to which we have assigned the variable steps
. This variable is the array of twelve steps of the tour that we declared earlier. After this, there are two more properties named, defaultTitle
and defaultContent
. The defaultTitle
property contains some text that will be displayed as the title of the dialog box when the triggerElement
is clicked. Similarly, tourContent
will serve as the content of dialog box.
The init
property declares a closure. Inside this closure, we check to make sure whether the tourSteps
variable has been defined and is actually an array. After this, a click
event handler is added to the triggerElement
. This event handler will be responsible for opening the dialog initially. From here, the user will start navigating the tour using the Previous and Next buttons. The event handler calls the showStep
function. The showStep
function will be responsible for displaying the dialog box and positioning it correctly next to the element, as defined in the element
property of the tourSteps
array. Three parameters are passed to the showStep
function. Since this is the first time dialog opens, we pass defaultTitle
, defaultContent
, and the current trigger element startElement
. We need to display the dialog box for the first time now. This will all be explained in the next section.
Displaying a tour step
The showStep
function is responsible for displaying the dialog box and enabling or disabling the Previous and Next buttons. After the init
function, write the following code to define the showStep
function and another function named prevNextButtons
:
showStep : function(tourStepTitle, tourStepContent, whichElement) { this.prevNextButtons(); $('body').animate( { scrollTop: $(whichElement).offset().top }, 500, function() { $('.ui-state-highlight').removeClass('ui-state-highlight'); $(whichElement).addClass('ui-state-highlight'); tourDialog.dialog('option', 'title', tourStepTitle); tourDialog.html(tourStepContent); tourDialog.dialog('option', 'position', { my: 'left top', at: 'right top', of: whichElement, collision : 'flipfit' }); tourDialog.dialog('open'); }); }, prevNextButtons : function() { $('#buttonNext').button('enable'); $('#buttonPrevious').button('enable'); if(this.tourStep == 0 || this.tourStep == 1) { $('#buttonPrevious').button('disable'); } if(this.tourStep == this.tourSteps.length) { $('#buttonNext').button('disable'); } return; }
Inside the showStep
function, we receive three function arguments: the title text, content HTML, and the target element where a step of the tour will be displayed.
In the first line of showStep
, we have called another function called prevNextButtons
. Since the showStep
function will display and position a tour step, we need to enable or disable the Previous and Next buttons. The prevNextButtons
function is used to achieve this. If the user is on the first step of the tour, the Previous button will be disabled; if the user is on the last step of the tour, the Next button will be disabled.
First, we enable both the Next and Previous buttons. Then, we check the tourStep
property to determine which step is being displayed currently. If it is the welcome dialog that is shown after clicking on the Start Tour link or the first step of the tour, we disable the Previous button. In the next line, we disable the Next button. If the value of the tourStep
variable equals the length of all the steps in the array, it means the user is on the last step of the tour and hence we disable the Next button.
The End Tour button need not be handled, since the user can choose to end the tour during any step.
With the Next and Previous buttons taken care of, the control now returns to the showStep
function.
Inside the showStep
function, we used jQuery's animate
function to scroll the page first so that the target element (whichElement
received as a function argument) scrolls to the top of the viewport in 500 milliseconds. After scrolling is done, the callback function for animate
fires. We remove the CSS class ui-state-highlight
if it has been applied to any element. This is to ensure that there is no highlighted element in the page. In the very next line, the same class is applied to the current element (represented by whichElement
) to highlight it. The ui-state-highlight
class from jQuery UI's theme framework applies a yellowish background color to an element to make it look highlighted.
We have already initialized the dialog
component inside the $(document).ready()
event handler earlier. We now set the title of dialog box using jQuery UI's option
method. Then, we set its inner HTML.
Now, we are left with one most important thing, that is, positioning the dialog. Remember that target elements can be in any corner of the web page, so we need to position the dialog so that its maximum area is available. To position the dialog, we have used the position
option of jQuery UI. To properly position the dialog, we have set four properties of the position
option. The name of the first property is my
. We have set it to left top
. Another property is at
, which we have set to right top
. Setting it to right top
will align the dialog to the right top of the target element. The third property is of
, where we provide the element that we want to position the dialog against. Since we want the dialog to be positioned against the target element, we provide it as a value of the of
parameter. The last property is collision
, which is used to ensure that the maximum part of the dialog
is visible. We supplied the value flip
. This property checks to either side of the element and positions it to the side where more space is available. With this, our positioning is done. We can now display the dialog.
In the last line of showStep
, we called the open
method of the jQuery UI dialog
which displays the dialog. We can now check the result of our hard work so far in the browser. Reload the index.html
page and click on the Take a Tour link. Windows will scroll a little and then the dialog will open with a fold
effect. It will have the Previous button disabled.

Making the Previous and Next buttons functional
We have successfully started the tour by showing a welcome dialog. Now, we need to make use of the Previous and Next buttons, and the tourSteps
array to navigate them.
If you recall, while we created the dialog earlier in the chapter, we created the Previous and Next buttons and their event handlers. We will now make these buttons functional by calling appropriate code for moving forward or backward in the tour. Visit the code where buttons have been defined, and write the following code inside the click
handler for the Previous button:
tour.navigate('previous');
Similarly, go to the click
handler for the Next button and write the following code:
tour.navigate('next');
With this done, we will now define the navigate
method. The navigate
method will be defined inside the tour
object after the code for the prevNextButtons
function. Though you can define the function anywhere inside the tour
object, writing the methods in sequence makes the code more readable:
navigate : function(previousOrNext) { if(previousOrNext == 'previous') { (this.tourStep) = (this.tourStep) - 1; } else { this.tourStep = this.tourStep + 1; } for(var i = 0; i<this.tourSteps.length; i++) { if(this.tourSteps[i].sequence == this.tourStep) { if(this.tourSteps[i].isAccordion) { $("#accordion" ).accordion("option", "active" , this.tourSteps[i].accordionIndex); } this.showStep(this.tourSteps[i].title, this.tourSteps[i].content, this.tourSteps[i].element); return; } } }
A single function will be used for handling both the Previous and Next buttons. The navigate
function has an previousOrNext
argument, based on which we can decide if the tour has to be moved forward or backward. If its value is previous
, we increment the tourStep
property of the tour
object by one. Otherwise, we decrement its value by one. The increment or decrement in value ensures that we will pick the correct element
, title
, and content
properties from the tourSteps
object while moving forward or backward.
A for
loop is used to iterate in the tourSteps
array. When we find that the sequence
value of a tourSteps
object matches the tourStep
value, we call the showStep
function and send the corresponding object's values for element
, title
, and content
. There is another check that we place here for accordion
. We have already defined the isAccordion
and accordionIndex
properties for the tour steps. So, if we find that the isAccordion
value is true
, we activate the corresponding accordion
panel.
We can now check whether the Previous and Next buttons are working by reloading the page in our browser. A typical screen when the tour is on an accordion
panel will look like this:

Ending the tour
Ending the tour is very simple compared to the complex code we have written so far. Just visit the event handler for the End Tour button and use the following code:
tour.endTour();
We called the endTour
method of the tour
object. Let's define it as well. Add the following code inside the tour
object:
endTour : function() { this.tourStep = 1; $('.ui-state-highlight').removeClass('ui-state-highlight'); tourDialog.dialog( 'close' ); }
The preceding code simply resets the tourStep
to 1
so that the correct data is displayed when the tour is started again. The CSS class ui-state-highlight
is also removed from any elements in the page.
Finally, the close
method of dialog component is called, which hides the tour dialog with the fold animation.