Where has little Timmy's ball gotten to? Quick, he's about to cry! Click on the image where you think the ball is.
If you didn't get it, don't feel too bad. (I didn't have a prize anyway.) If you did, well done! Hope you didn't cheat by looking at the code.
This is one of my favourite discoveries in HTML since I began learning it. You might expect a whopping amount of Javascript lurking behind the 'toy' on this page, but in fact the hard work is done by a humble HTML element attribute. The 'sending' code is as simple as this:
<a href="img_ismap.htm"><img src="images/spottheball.jpg" border="0" ismap="ismap"
/></a>
The link on the image, and the ismap
attribute,
mean that wherever you click on the image, those coordinates are sent to
the destination page as URL parameters. That page (or this page, in my drive
to keep things simple) can easily extract and process them either server-side
or client-side.
Obviously, with server-side scripting and a database to play with, there's the potential for some very sophisticated image-mappery. As I've only got JavaScript to play with, this is a simple object-lesson in how to utilise this method and perform a simple visual interaction with it.
The link's format, as you'll see if you mouseover the image,
has the format targetpage.htm?x,y
so it's a little simpler than
the contents of a GET-method form submission - for JavaScript at least. Server-side
languages like PHP are equipped to automatically parse a URLencoded string
like targetpage.htm?var1=x&var2=y
into an associative array.
You could access these variables quite easily like so:
x = $_GET['var1']; y = $_GET['var2'];
The limitation of JavaScript is it treats the whole parameter
segment of the address as one string (accessed as location.search
),
so some more complex scripting is needed to access the variables in
GET format. NOTE: this code is slightly sub-optimal for the sake of transparency.
var str = location.search.substr(1); //lose the question-mark
str = unescape(str); //translate any URLencoded characters
allParams = str.split('&'); //create an array of variable-value
pairs
var keys = new Array(allParams.length); //initialise 2 arrays
var values = new Array(allParams.length);
for (i=0; i<allParams.length; i++)
{
var j = allParams[i].split('='); //separate the variable and value
keys[i] = j[0]; //fill the arrays with keys and values
values[i] = j[1];
}
// Now we'll use our two arrays to display
// a list of variables and values.
document.write('<h3>URL Parameters Received</h3>\n');
document.write('<ul>\n');
for (t=0; t<keys.length; t++)
document.write('<li>'+keys[t]+' = '+values[t]+'</li>\n');
document.write('</ul>\n');
I've seen bigger scripts, but it's quite a lot of work just to make some form data available for use. Thankfully, in our particular setup there's slightly less work to do:
var str = unescape(location.search.substr(1))
;
var allParams = str.split(',');
document.write('<h3>Coordinates Clicked by You:</h3>\n');
document.write('<ul>\n');
document.write('<li>X-coordinate = '+allParams[0]+'</li>\n');
document.write('<li>Y-coordinate = '+allParams[1]+'</li>\n');
document.write('</ul>\n');
Delightfully minimal. Let's continue by looking at how I used these values for the game above. Just imagine this is being processed server-side so you can't just cheat by reading the code!
The 'hotspot' area on the image is a rectangle defined by maximum and minimum values for X and Y. If the destination page is a different page, there's nothing on the source page to give away this definition. The destination page evaluates whether you clicked within that rectangle, but it also displays a visual indicator to show where you clicked.
The visual resides in an absolutely-positioned DIV which
is empty unless the location.search
string is non-empty. The DIV,
which I've called 'spot' below, has to have its position assigned relative
to both the received values and the position of the image on the
page, and its image defined by whether or not you hit the target. Note that
this
is a case
of
writing an HTML <img>
tag within the DIV, because there is
no cross-browser DOM object for the background-image.
if(location.search !== '')
{
var str = unescape(self.location.search.substr(1));
var allParams = str.split(',');
//set DIV's position by adding parameters to image's position
//note: shave off 15px so spot appears under cursor
var x = parseInt(allParams[0]);
var theX = x + document.getElementById('spottheball').offsetLeft -15;
var y = parseInt(allParams[1]);
var theY = y + document.getElementById('spottheball').offsetTop -15;
//check whether click falls within rectangle
if ((x < 270) && (y < 30) && (x > 260) && (y > 20))
var res = 'right';
else
var res = 'wrong';
var theSpot = document.getElementById('spot');
theSpot.style.left = theX+'px';
theSpot.style.top = theY+'px';
theSpot.innerHTML = '<img src="images/'+res+'.gif" border="0" />';
}
For all-round success with this script, placing it inside
a function is a good idea. That means it can be called by body onload
and
onresize
, which will ensure that the render-time dimension values
I've used are defined before execution. My image is centred, so that's important
to keep the spot matching the same position on the image.
The one downside of this design is that once you've clicked once, the spot obscures part of the image so you can't click within that area. But hey, maybe you only want to give your contestants one try...