To begin with, we will design a simple quiz application where users have to match country names to their corresponding capital names by dragging a country name over its correct capital. A correct match will result in one point, and drag and drop will be disabled for both the country and its capital.
The display will contain two columns, the first one will have country names and the second one will have the names of the capitals of those countries. Both the columns will be shuffled randomly. Once the user has matched all the names successfully, a modal dialog will appear. Users will also be given the option to reset the quiz. Resetting will restart the game and shuffle the lists again.
We will need the jQuery and jQuery UI libraries before going ahead. Throughout this book, we'll use jQuery Version 1.10.2 and jQuery UI Version 1.10.4 with the UI lightness
theme . Note that the jQuery UI files also contain a copy of the jQuery source file.
To download jQuery, visit the download page on the jQuery website at http://jquery.com/download/.
For jQuery UI, visit the download page at http://jqueryui.com/download/ to download the jQuery UI library.
You might be aware that Content Delivery Networks (CDN) host many popular libraries. Since the browsers cache JavaScript files, your page will not have to load a JavaScript file again if it is referenced from a CDN and already cached in browser. You can link jQuery and jQuery UI among CDN's many other libraries.
Tip
Make sure that you are connected to the Internet if you have referenced the libraries from the CDN in your pages.
Google, Microsoft, and some other companies provide CDN for jQuery, jQuery UI, and other libraries. Here are the links to pages for downloading these libraries:
Google CDN can be downloaded from https://developers.google.com/speed/libraries/devguide#jquery.
Microsoft CDN can be downloaded from http://www.asp.net/ajaxlibrary/cdn.ashx#Using_jQuery_from_the_CDN_21.
CDNJS can be downloaded from https://cdnjs.com/. It is a helpful site where you can find many libraries and their different versions.
We will now set up the folder structure that we will use for all the chapters in this book. The steps are as follows:
In your document root, create a folder named
MasteringjQueryUI
. Then, create a folder for each chapter inside it.For this chapter, create a new folder named
Chapter1
insideMasteringjQueryUI
and two more folders namedjs
andcss
inside theChapter1
folder.Now extract the jQuery UI files into a separate folder and go to its
js
folder. You will see three files: jQuery source file and full and minified versions of jQuery UI.Copy the jQuery source file and any one version of jQuery UI source files and place them inside the
js
folder that you created insideChapter1
of theMasteringjQueryUI
folder.Also, copy the
ui-lightness
folder from thecss
folder from the downloaded jQuery UI to thecss
folder ofChapter1
.
Now we are ready to experiment with jQuery UI and create some informative and fun examples. Let's start our journey by creating the quiz application.
In the newly created folder Chapter1
, create a file named index.html
and another .js
file named quiz.js
inside the js
folder of Chapter1
. The quiz.js
file will contain all the code that we need to make the quiz functional.
Open the index.html
file for editing using your favorite text editor, and write the following code in it:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Designing a simple quiz application</title> <link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.10.4.custom.min.css"> </head> <body> <div class="container"> <span id="score"></span> <button id="reset" type="button">Reset</button> <div class="clear"></div> <hr/> <div id="leftCol"> <ul id="source"> </ul> </div> <div id="rightCol"> <ul id="target"> </ul> </div> </div> <div id="dialog-complete" title="Well Done!"> <p><span class="ui-icon ui-icon-check"></span> Well done. You have completed the quiz successfully.</p> </div> <script src="js/jquery-1.10.2.js"></script> <script src="js/jquery-ui-1.10.4.custom.min.js"></script> <script src="js/quiz.js"></script> </body> </html>
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
In the preceding code, inside the head
section, we referenced the jQuery UI .css
file. If you have placed the .css
file elsewhere, make sure to correct the path accordingly. The path can either be an absolute path or a relative path.
Inside the body, we have a div
element named container
that wraps our entire markup. Inside container
, we have created two span
elements. The first span
has the id
value score
and it will be used to show the score of the user. The second span
has the id
value reset
and it will be used to reset the quiz to its initial state.
After this, we have to create two more div
elements having the id
value leftCol
and rightCol
, respectively. leftCol
has an ul
element with the id
value source
inside it. This ul
element will contain the names of countries as list items. Similarly, rightCol
has another ul
element with the id
value target
inside it. It will have the names of capitals as list items.
After the container
element, we have created yet another div
element with the id
value dialog-complete
, which will be displayed once the user has completed the quiz successfully. Inside the dialog-complete
element, we have placed a success message.
Finally, at the bottom of the page, reference the jQuery, jQuery UI, and quiz.js
files.
We will also need some CSS styling to make the elements look good. In the head
section of the index.html
file, write the following code:
<style type="text/css"> body{ font-family:arial,verdana; font-size:12px; margin: 0px auto; width: 600px; } div.container{ border: 1px solid #000; float:left; margin:0 auto; padding:10px; width: 100%; } #leftCol{ float:left; } #rightCol{ float:right; } ul{ list-style:none; margin:0; padding:0; width:50%; } li{ border:1px solid #000; font-weight:bold; margin:5px 0; padding:10px 0; text-align:center; width:175px; } #source li{ cursor:move; } #score{ font-weight:bold; float:left; color:#ff0000; } #reset{ color:#ff0000; cursor:pointer; font-weight:bold; text-align:right; text-decoration:underline; float:right; } .clear{ clear:both; } #dialog-complete{ display:none; } #dialog-complete span{ float:left; margin:0 7px 20px 0; } </style>
In the preceding code, first we defined some basic styles for the body
and the container
elements. After that, the styles were defined for the ul
element and its li
items. These styles will display the list items in the form of individual boxes. CSS for the score
and reset
items follow next and finally some basic styling for the dialog elements.
Our UI part is now complete and we can proceed to make the quiz functional. We will do this in a few steps. First of all, we will display the data on the page in two columns. Then, we will make the country names draggable. Finally, the list items with the capital names will be made droppable so that we can drop a country name inside a capital. We will also have to ensure that a droppable capital name accepts only the correct country name. Finally, the resetting logic will be built.
Open the quiz.js
file for editing and write the following code:
$(document).ready(function() { createQuizLayout(); });
On the document ready event we call a function named createQuizLayout
which we need to define now.
function createQuizLayout() { //declare arrays of countries and their capitals. var countries = ["USA", "UK", "India", "Germany", "Turkey", "France", "Nepal", "Japan", "South Africa", "Maldives"]; var capitals = ["Washington", "London", "Delhi", "Berlin", "Istanbul", "Paris", "Kathmandu", "Tokyo", "Capetown", "Male"]; var arrCountry = []; for(var i=0; i<countries.length; i++) { arrCountry.push('<li data-index="' + (i+1) + '">' + countries[i] +'</li>'); } var arrCapital = []; for(var i=0; i<capitals.length; i++) { arrCapital.push('<li data-index="' + (i+1) + '">' + capitals[i] +'</li>'); } //shuffle the arrays arrCountry = shuffle(arrCountry); arrCapital = shuffle(arrCapital); // once country and capital items are ready, we insert them into DOM $('#source').html(arrCountry.join('')); $('#target').html(arrCapital.join('')); }
Here is what the preceding code does:
We have defined two arrays named
countries
andcapitals
.The
countries
array contains names of 10 countries and thecapitals
array contains names of the capitals of the countries defined in the countries array. The names of capitals must be in the same order as their respective countries.Since we want to display the names of countries and capitals in a random order, we will create two arrays and fill them with list items and shuffle them.
We started with country first. We declared an array named
arrCountry
. Then, we loop in thecountries
array and create a list item with the country name and push it into thearrCountry
array.The same process is repeated for the
capitals
array.
An important point to note here is that we are giving a data attribute named index
to each list item having a value from 1 to 10. Since we have both the countries and capital names in the same order, index
will be used to match which country belongs to which capital.
After both arrays are populated, we will shuffle them so that the order of countries and capitals becomes random. For this, we will use a simple shuffle
function from the website http://jsfromhell.com/array/shuffle. The shuffle
function is defined as follows:
function shuffle(o) { for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); return o; };
After calling the shuffle
function on both arrays arrCountry
and arrCapital
, the array elements are inserted in DOM after combining them into a single string using the JavaScript join
function. The elements in the array arrCountry
are inserted in ul
with the id
value source
and those in the array arrCapital
are inserted in ul
with the id value target
.
Open your browser and point it to the index.html
file of the Chapter1
folder now. You will see a page similar to the one shown in the following screenshot:

If you reload the page, you will see that the order of countries and capitals changes each time. This is because shuffling creates a new order for items of both lists.
To make the country names draggable, we will use the draggable
component of jQuery UI. As the name suggests, the draggable
component allows DOM components to be moved around using a mouse. To do this, go to the $(document).ready()
section of our quiz.js
file and call another function named initQuiz
. The $(document).ready()
callback function should look like this now:
$(document).ready(function() { createQuizLayout(); initQuiz(); });
Now define the initQuiz
function outside document ready handler as follows:
function initQuiz() { $('#source li').draggable( { revert : true, revertDuration: 200, cursor: "move" }); }
The preceding code calls the draggable
method of the jQuery UI library. It is being called upon the li
elements of the ul
source, which means it will make all the list items draggable inside the source ul
. Further, we are also giving the draggable
method three options that we need for our application: revert
, revertDuration
, and cursor
. Let's look at these in more detail:
revert
: This decides whether the element being dragged should revert to its original position or not. In our case, we will set it totrue
. We will drag a country name onto a capital name and revert it to its original position, that is, the country list. Another possible value forrevert
isfalse
, which means it will stay at the place where it is when dragging stops. The values,valid
andinvalid
, can also be provided (as strings) for therevert
option. The valuevalid
means the draggable object will revert only if the draggable object has been dropped on a droppable element. The valueinvalid
means thedraggable
fuction will revert if the draggable object has not been dropped. Alternatively, a function can also be provided to revert. This is required in complex cases where we need to perform any manipulations. Thereturn
value for this function will decide if it will revert or not. Iftrue
is returned, the element will revert.revertDuration
: This defines the duration for therevert
option in milliseconds. The lower the value, the faster it will revert. This value is not considered if the revert option is set tofalse
.cursor
: This is the style of cursor while an element is being dragged.
Our draggable elements are ready now, and so it is time to make the capital names droppable and build the logic to match countries to their correct capitals.
In the previous section, we created an initQuiz
function where we made our countries draggable. After the draggable code, write the following code to make the capitals droppable:
var totalScore = 0; $('#score').text(totalScore + ' points.'); $('#target li').droppable( { accept : function(draggable) { if(parseInt(draggable.data('index'), 10) === parseInt($(this).data('index'), 10)) { return true; } else { return false; } }, drop: function( event, ui ) { var that = $(this); that.addClass( "ui-state-highlight" ).html( 'Correct!' ).effect('bounce'); that.droppable('disable'); ui.draggable.addClass('correct ui-state-error'); (ui.draggable).draggable('disable'); totalScore++; $('#score').text(totalScore + ' points.'); if($('li.correct').length == 10) { $( "#dialog-complete" ).dialog({ resizable: false, modal: true }); } } });
Now save the quiz.js
file and refresh your browser. You will be able to drag the country names now. Drag a country name to its correct capital and you will see that the country will revert to its original position. The capital list item will show a bounce effect and its text will change to Correct!. Both the country and capital names will be disabled now. You will not be able to drag the country name as well. On the top left hand side, the page will show the score as 1 points.
The screen will look like the following screenshot:

Try the drag and drop for all countries in the left-hand side list. When you have matched all countries correctly, you will see a dialog box and the page will look like the following screenshot:

So, a lot is happening in the preceding code. We will look at it step by step.
We defined a variable named totalScore
and set it to 0
. We also inserted the score inside the HTML element with the id
value score
. Each time the quiz starts, the score will be reset as well. After this, we call the droppable
method of jQuery UI on the list items of ul
with the id
value target
to make them ready to accept the draggable country elements.
We are using the accept
option of the jQuery UI draggable
method to check for the correct matches of country and capital, and we are using the drop
event to change the UI and scoring.
The accept
option of a droppable
method defines which draggable element will be accepted by the droppable
method when a draggable element is over it; either a jQuery selector or a function can be provided for this purpose. If a selector is given, only the draggable element matching that selector will be accepted by the droppable
method. Since we want to match an individual country to its capital, it is better for us to use a function instead. The function will receive the current draggable element that is being dragged as a parameter. Inside the function, $(this)
will refer to the current droppable element. The code is as follows:
if(parseInt(draggable.data('index'), 10) == parseInt($(this).data('index'), 10)) { return true; } return false;
Since we have already defined data attributes for both countries and capitals, we can match those to check if the current draggable-droppable pair is a correct country-capital pair or not. If the indexes match, we return true
; otherwise, we return false
.
A return value true
means the droppable
method will accept the draggable element, and will allow the draggable element to be dropped in it.
The drop
event will receive a draggable element once it has been passed from the accept
option. If the accept
option returns false
for any draggable element, then the drop
event will not be called. In our case, this means we will only receive a country's draggable element and its corresponding capital's droppable element.
The callback function for the drop
event receives two parameters: event
and ui
. Of these two, we are interested in the ui
object. Among other values, it provides us with a reference to the draggable element that was dropped. To refer to the current droppable element where the draggable element is dropped, we have $(this)
variable with us. The code is as follows:
$( this ).addClass( "ui-state-highlight" ).html( 'Correct!' ).effect('bounce'); $( this ).droppable('disable');
In the preceding code, we added the jQuery UI framework's CSS class ui-state-highlight
to the current droppable element and then changed that list item's HTML content to Correct! and added the bounce
effect to the droppable capital.
Since the droppable capital has been matched successfully with its country, we no longer need it as a droppable element. Hence, the preceding code uses the disable
method of the droppable component to disable the droppable functionality.
The next two lines add CSS classes named correct
and ui-state-error
to the draggable
method and then disable it. The code is as follows:
ui.draggable.addClass('correct ui-state-error'); (ui.draggable).draggable('disable');
The correct
class will be used to determine how many successful countries have been matched. The class ui-state-error
is just for presentation purposes to make the successfully matched country name highlighted. Using the draggable disable
method, we disable the specific draggable element as well, because it has been matched and we do not want it to be dragged again.
Since the drop
event receives only the accepted draggable elements, we can safely increase the variable totalScore
by 1
and insert the new value back to the DOM in the element score
. This shows us the latest score each time a new match is made.
Finally, we count the number of list items in the countries' column that have the CSS class named correct
associated with them. Since we have 10 elements, if all the 10 list items have the CSS class correct
attached to them, it means the quiz is complete. We then show a jQuery UI dialog component that we kept hidden in our HTML page initially.
If you were wondering why we created the functions createQuizLayout
and initQuiz
when we wrote the code without them, the answer is that we need to call them again. It is better not to repeat yourself. We can now reset the quiz without having to reload the page.
We have already created an element with id reset
. Visit the $(document).ready()
callback again and write the following code after those two function calls. The section will now look like this:
$(document).ready(function() { createQuizLayout(); initQuiz(); $('#reset').on('click', function() { $('#source li').draggable('destroy'); $('#target li').droppable('destroy'); createQuizLayout(); initQuiz(); }); });
We have an event handler registered at the click of the reset
button. It is using the destroy
method of jQuery UI on the draggable and droppable elements. The destroy
method will remove the complete draggable and droppable functionality from respective elements. It will also remove any special CSS classes that jQuery UI might have applied earlier.
After bringing the page to its initial state, we call the createQuizLayout
and initQuiz
functions again, which will initialize our quiz once more.
The draggable
and droppable
methods are important components of jQuery UI in order to make interactive applications. We explored a few options presented by these two components and created a simple quiz application in this process. We will see more options presented by these two components in the following chapters as well, where we will create a jigsaw puzzle game.