The goal of today's mini-lab is to create an interactive puzzle. The player will attempt to unscramble a tiled image with one missing tile. Every time an image is clicked, that image will swap places with the missing tile. You will be provided with a static HTML page, and it will be your job to add the required JavaScript.
First, download the file puzzle.zip to your laptop or M:\ drive. This is a zip file that contains the starting puzzle page, along with all of the required image files. You can extract the contents of this file on the Lab machines by right clicking it and selecting "7-Zip" -> "Extract Here".
If you are using Aptana you will need to import these files into your Aptana project (don't forget to switch into your workspace). Create a new folder named "puzzle" by Right-clicking on your project and select "New"->"Folder". Now, right click on your newly created folder and select "Import..." -> "General" -> "File System", then click "Next >". Click the "Browse..." button and select the "puzzle" directory that was created by unzipping puzzle.zip. Click the checkbox next to the "puzzle" directory and then click "Finish". Your Aptana project should now contain all of the files necessary to complete this mini-lab.
Open puzzle.html, and take a few minutes to look over the HTML. Notice that the image file names look like "01.jpg" or "32.jpg". Those names correspond to the correct locations of those images in the completed puzzle: "01.jpg" belongs in row 0 and column 1. The image "blank.jpg" is an all-white rectangle that will represent the missing tile.
In this exercise you will add code that will allow any image to be resized by clicking on it. This will not be a feature of the finished puzzle; it just gives us a chance to practice working with parameterized functions and the "this" keyword.
<head>
of your puzzle web page.
<script>
//===========================================================
// makeBigger
// This method enlarges an image element by 25%.
// Parameters:
// imgElement - The image element to be enlarged.
function makeBigger(imgElement)
{
imgElement.height = imgElement.height * 1.25;
imgElement.width = imgElement.width * 1.25;
}
</script>
Take a minute to read this function over until you have a feel for what it does and how it works.
The nice thing about this function is that it can be used to
enlarge any image element. If we have twenty image elements
on our page, we won't need to write twenty copies of this code.
Instead, we will use the imgElement
parameter to
determine which element should be enlarged.
onclick
event
of a button makes it possible to run JavaScript commands in response
to user clicks. It turns out that almost any HTML element can respond
to mouse clicks in the same way. Add an onclick
attribute to the first image element in your page as follows:
<td> <img src="00.jpg" onclick="makeBigger(this);"> </td>
In this case the javascript keyword this
will be
interpreted to mean "the element that was just clicked".
Test your code by reloading the page and clicking on the top-left
image you just modified.
onclick
attribute to every image in the page. (Copy and paste could be helpful
here!) You should now be able to enlarge any image by clicking on it.
Test this.
Since the blank picture will move around as you play the puzzle, you will need to keep track of where it currently is. We'll do that with a global variable, a variable that is defined outside any particular function and therefore available to all of them. (A variable that is defined inside a function, and is only accessible inside that function, is called a local variable.)
Add the following global variable declaration right after your
begin-script tag (<script>
, before any of
your functions:
// Global variables go here, outside of (and before) any function.
var currentBlank; // keep track of which image element is currently blank
As the comment suggests, the purpose of this variable is to keep track
of which
image element currently contains the blank image. Initially,
this should be the image with the id of 'blank'
at row 3, column 1 (counting from 0).
Unfortunately, we can't set it to that value here, where we're creating
the variable, because the script
section in the
<head>
section
is executed before the body of the page is loaded by the browser.
When this variable is declared, there are no image elements;
they haven't been loaded yet. We can solve this problem by
creating an initializeGlobalVars
function and calling it
using
the body element's onload
event. In the same way
that onclick
is an event that occurs when an element is
clicked, onload
is an event that occurs when an element
loads.
Add the following function to your script
section,
right after the declaration of the currentBlank
variable:
//===========================================================
// initializeGlobalVars
// This method gives initial values to any global variables on this page.
function initializeGlobalVars()
{
currentBlank = document.getElementById('blank');
}
Then modify your body tag as follows:
<body onload="initializeGlobalVars();" >
Notice that we are not using the var
keyword here.
That's because we are not creating a new variable, we are just
assigning a value to the variable we created above.
We don't have a way to test the new variable yet, but we will in the next exercise.
In this exercise, you will start to write the code that will eventually allow the user to solve the puzzle. You will be writing this function in steps, testing each step as you go. The first step will just "blank out" any image when the user clicks on it.
//===========================================================
// swapWithBlank
// This method swaps the picture in the given element with
// the current blank. (NOT YET IT DOESN'T!)
// Parameters:
// imgElement - the image element to move
function swapWithBlank(imgElement)
{
imgElement.src = currentBlank.src;
}
Note that this function "blanks out" the picture that was clicked on
by replacing its src
attribute (the one that says what
image file to use) with the one that your new currentBlank
variable refers to.
Take a minute to read this function over until you have a feel for
what it does and how it works.
makeBigger
with calls to swapWithBlank
.
So far, you've copied the blank image to the element you clicked on; the next step is to copy the image you clicked on back to the blank image.
As a first experiment, try copying the line you have and reversing it:
imgElement.src = currentBlank.src; currentBlank.src = imgElement.src;
Test your code by reloading the page and clicking on various images.
Do you see any change from before? What is happening here? More
specifically, What is the value of imgElement.src
when it is being copied back to currentBlank.src
?
Is it the picture you clicked on? Or is it the blank picture that you
just copied into imgElement.src
?
Next Step:
A swap
function generally needs a third variable, in
addition to the two variables or parameters it is going to swap. The
standard form for this is:
// Generic swap for understanding. DO NOT TYPE THIS IN!
function swap(a, b)
{
var temp = a;
a = b;
b = temp;
}
In this case, instead of a
you have
imgElement.src
, and instead of b
you have
currentBlank.src
. Modify your swapWithBlank
function to introduce a temporary variable, then change your last line
to copy the temporary variable into currentBlank.src
.
Test your code again; now what do you see? Is the image you click on being swapped with the blank picture, or is it always swapping with the second picture in row 4 (where the blank picture started out)?
Last Step (for this function):
If you've done everything correctly up to now,
the latest problem is that the image you click on is being swapped with
the image referred to by currentBlank
, but
currentBlank
is not being changed to refer to the new blank
image. This is a problem:
currentBlank
needs to be updated after every click.
Add a new line to your function that modifies
currentBlank
to be the imgElement
you passed
in as a parameter. (Note: you want to modify
currentBlank
here, not
currentBlank.src
.)
Test your code again; does it work as expected? Make sure that it works correctly for all images, including those along the edges and in the corners. (Testing for "boundary conditions" is an important part of testing.)
Before publishing your page to the web server, add comments to your JavaScript containing the following information: