Book Image

jQuery HOTSHOT

By : Dan Wellman
Book Image

jQuery HOTSHOT

By: Dan Wellman

Overview of this book

jQuery is used by millions of people to write JavaScript more easily and more quickly. It has become the standard tool for web developers and designers to add dynamic, interactive elements to their sites, smoothing out browser inconsistencies and reducing costly development time.jQuery Hotshot walks you step by step through 10 projects designed to familiarise you with the jQuery library and related technologies. Each project focuses on a particular subject or section of the API, but also looks at something related, like jQuery's official templates, or an HTML5 feature like localStorage. Build your knowledge of jQuery and related technologies.Learn a large swathe of the API, up to and including jQuery 1.9, by completing the ten individual projects covered in the book. Some of the projects that we'll work through over the course of this book include a drag-and-drop puzzle game, a browser extension, a multi-file drag-and-drop uploader, an infinite scroller, a sortable table, and a heat map. Learn which jQuery methods and techniques to use in which situations with jQuery Hotshots.
Table of Contents (18 chapters)
jQuery HOTSHOT
Credits
Foreword
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Shuffling the puzzle pieces


In this step we need to randomly shuffle the pieces to make it a puzzle so that the visitor can unscramble them. We can also remove the original image as it's no longer required, and remove the first piece to create an empty space so that the other pieces can be moved around.

Prepare for Lift Off

The steps we'll cover in this task are:

  • Removing the original image from the page

  • Removing the first piece of the puzzle

  • Removing the first item in the positions array

  • Shuffling the pieces randomly

Engage Thrusters

Completing the first step requires just the following line of code, which should be added directly after the closing curly-bracket of the outer for loop we added to sliding-puzzle.js in the last task:

img.remove();

The second step is equally as simple; the following can be added directly after the previous line of code:

container.find("#0").remove();

We can also use a single line of code for the next step. Add the following directly after the previous line of code:

positions.shift();

Shuffling the pieces will be slightly more complex; you'll remember from the first part of the project when we added the underlying HTML that one of the elements was a start button. We'll use this button to trigger the shuffle. Add the following code directly after the first two lines we just added (make sure they are still within the outer function wrapper):

$("#start").on("click", function (e) {
    var pieces = imgContainer.children();

    function shuffle(array) {
        var i = array.length;
    
        if (i === 0) { 
            return false;
        }
        while (--i) {
            var j = Math.floor(Math.random() * (i + 1)),
                tempi = array[i],
                tempj = array[j];

                array[i] = tempj;
                array[j] = tempi;
        }
    }

    shuffle(pieces);

    $.each(pieces, function (i) {
        pieces.eq(i).css(positions[i]);
    });

    pieces.appendTo(imgContainer);

    empty.top = 0;
    empty.left = 0;

    container.find("#ui").find("p").not("#time").remove();

});

Objective Complete - Mini Debriefing

jQuery's remove() method is used to remove the original image element from the page, which we already selected when we declared our variables at the start of the script. We use the same method to remove the first puzzle piece, which we should do before the pieces are shuffled to avoid removing a key piece, such as a face. As with the image used in this example, an image where the main item of interest is not in the top-left corner is beneficial.

As we've removed the first piece from the board, we should also remove the first item in the positions array. We'll use this array when we come to check whether the puzzle has been unscrambled and as there won't be a piece at the first position, we don't need to store its position. We use JavaScript's unshift() method to do this, which simply removes the first item in the array it is called on.

Adding an event handler to the button using on()

We added a click event handler for the button by selecting it and calling the jQuery on() method. The on() method takes two arguments in this example (although it can take three when event delegation is required).

The first argument is the event to listen for and the second is the handler function to be executed each time the event is detected. We are listening for the click event in this case.

Tip

The all-encompassing on() method

jQuery's on() method, introduced in version 1.7, replaces the bind(), live(), and delegate() methods, which are now deprecated. Using on() is now the recommended way of attaching event handlers in jQuery.

Within the handler function we first define a variable which stores the children of the <figure> element. Although we need to select the pieces from the page again, we can still use our cached imgContainer variable to avoid creating a new jQuery object.

Shuffling the pieces

Next we define a function called shuffle(), which accepts the array to shuffle as an argument. This function performs a Fisher-Yates shuffle, which is an established pattern for creating a random ordering of a given set of values.

Within the function, we first get the length of the array that was passed in, and return false (exiting the function) if the array is empty. We then use a while loop to cycle through the array. A while loop in JavaScript is similar to a for loop but executes while the condition specified in brackets has a truthy value (or while it evaluates to true), instead of executing a specified number of times. A pre-decrementing loop condition is used to avoid an unnecessary iteration of the loop once the items have all been shuffled.

Note

In JavaScript, as well as the true or false Boolean values, other types of variables can be said to be truthy or falsey. The following values are all considered falsey:

  • The Boolean value false

  • The number 0

  • An empty string

  • null

  • undefined

  • NaN

All other values are considered truthy. This is so that non-Boolean values can be used as conditionals. The similarities between the terms falsey and false may lead to confusion; just remember that false is an actual value, and falsey is an aspect of a value, which values other than false also have.

For more information on this subject, see http://james.padolsey.com/javascript/truthy-falsey/.

Within the loop, which will be executed once for each item in the array except the first item, we want to pick a random item from the array and swap its position in the array with another item. To generate a random number to use as the index of the item to swap, we first generate a random number using JavaScript's Math.random() function and multiply the random number (which will be between 0 and 1) by the length of the array plus 1. This will give us a random number, between 0 and the length of the array.

We then pull the item with the current index out of the array, along with the item at the randomly generated index, and swap them. It may seem complex but this is almost universally regarded as the most efficient way to randomly shuffle the items in the array. It gives us the most random result for the least amount of processing.

Once we have defined the function, we then invoke it, passing in the pieces array as the array to shuffle.

Note

For more information on the JavaScript implementation of the Fisher-Yates shuffle, see http://sedition.com/perl/javascript-fy.html.

Positioning the pieces

Once the array of elements has been shuffled, we iterate it using jQuery's each() method. This method is passed the array to iterate over, which in this case is the pieces array we have just shuffled. The second argument is an iterator function that will be called for each item in the array.

Within this function we use our positions array to put the shuffled elements in the right place on the page. If we didn't do this, the elements would be shuffled, but would still appear in the same place on the page because of their absolute positioning. We can use the positions array that we updated when creating the new elements to get the correct top and left positions for each of the shuffled elements.

Once the collection of elements have been iterated and their positions set, we then append them back to the page using jQuery's appendTo() method. Again we can specify our imgContainer variable as the argument to appendTo() in order to avoid selecting the container from the page once more.

Positioning the empty space

Lastly we should make sure that the empty space is definitely at 0 top and 0 left, that is the top-left square of the board. If the button is clicked, some pieces are moved and then the button is clicked again, we have to ensure that the empty space is in the right place. We do this by setting both the top and left properties of the empty object to 0.

We can also remove any previous messages that may be displayed in the UI area (we'll cover adding these messages towards the end of this project). We don't want to remove the timer though, so we filter this element out of the selection using jQuery's not() method, which accepts a selector for which matching elements are discarded and therefore not removed from the page.

At this point we should be able to run the page in a browser and shuffle the pieces by clicking on the Start! button: