Feb 5, 2012
Posted on Feb 5, 2012 in Hints and Tips | 10 comments
Creating little browser extensions is a great way to learn JavaScript. You don’t need to worry about cross-browser compatibility, you can make the project as small or large as you like, and you can fix problems in other people’s websites that bug you, specifically. In this post, we’ll create a short script that automatically rearranges Tumblr archive pages to read in chronological order – and we’ll learn about NodeList on the way.
The Problem
This week, Ryan North started a new Tumblr, in which he’s going through the novelization of the first Back to the Future movie, one page at a time. This is a thing I wish to read.

Click to read.
However, Tumblr displays its posts in reverse chronological order – that is, with the most recent posts first. This makes sense for a lot of sites on Tumblr, but in this instance, I really want to read them in the order they were written. The current site layout means that, to do that, I have to scroll down to the top of the first (first written) post, scroll down as I read it, and then scroll up to the top of the second post, and scroll down through that…
This is a tiny, tiny first world problem – totally trivial and almost embarrassing to mention. But that doesn’t mean I don’t want to fix it.
By the end of this tutorial, you’ll make this Tumblr – or any Tumblr you choose – display its posts in chronological order on the page, automatically.
How Can We Do This?
We don’t have control over the BtotheF site design; it offers no options to us, so we can’t change the order in which the posts are displayed on the page server-side.
But once the HTML is sent to the browser, it’s ours. We can manipulate it however we want. And, of course, the language with which we can do this is JavaScript.
I’ll give a quick demo. I’ll be using Chrome, and recommend that you do, too – if you can’t, or don’t want to, then grab a copy of Firebug.
Browse to http://btothef.tumblr.com/ and open the JavaScript console (Tools > JavaScript Console, in Chrome). Type:
alert("Hi");
…and hit Enter.
Wow! … Okay, fine, that didn’t prove much. Try this:
document.body.appendChild(document.createTextNode("Hi"));
This will take the HTML document’s <body> element, and append a new text node – a piece of text, basically – containing the word “Hi”. If you didn’t follow any of that, get up to speed with HTML.
To see the result, scroll right down to the bottom of the Tumblr:
Slightly more impressive, since we’ve actually changed the contents of the page. The new text node is right at the bottom because we’ve used appendChild() – which adds the specified node after everything else inside the <body>. As far as our browser is concerned, the last few lines of HTML now look like this:
<!-- END TUMBLR CODE -->
Hi
</body>
</html>
So! Now we have two issues:
- How do we use JavaScript to rearrange all the posts in the page?
- How do we make this happen automatically, without having to mess around in the console every time we read the Tumblr?
We’ll address these in order.
Rearranging the Posts
First, let’s figure out how to “find” all of the posts in the HTML. In Chrome, right-click somewhere in the top post, and select “Inspect element”. (Firebug should add the same shortcut to Firefox; for other browsers, try the magnifying glass icon.)
The Elements tab of the Developer Tools will appear, with the element you selected highlighted:
As you hover over different elements in this HTML view, you’ll see them highlighted in the page itself. Eventually, you’ll find that the entire post is contained in a div with a class of post. As you can see from the screenshot above, there are several other such div elements, and they are all contained in a master div with an id of contents.
We can select all of these post elements at once with a single line of code; type this into the JavaScript console:
document.getElementById("contents").getElementsByClassName("post");
(Technically, we could have just written document.getElementsByClassName("post"), but who cares?)
You’ll see – again, in Chrome – some feedback:
Great! This indicates that it worked. If you click the arrows, you’ll see the contents of each div.
We might as well assign this to a variable, to save us having to type it out over and over:
var posts = document.getElementById("contents").getElementsByClassName("post");
(This time, the console will return undefined; you can check that it assigned the variable correctly by just typing the word posts in the console.)
We can loop through all of the elements in posts as if it were an array:
for (var i=0; i < posts.length; i++) {
console.log(posts[i]);
}
Hit Shift-Enter to add a new line to your code without running it, in the JavaScript console. console.log() just traces its contents to the console, which is far less annoying than an alert() and far less disruptive than adding text to the HTML DOM.
The result of this simple loop will just be a list of all the div elements. Cool. So presumably we can do something like this…
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
posts.push(posts[i]);
}
Try it out! You’ll see this:
TypeError: Object #<NodeList> has no method 'push'
Rats.
A NodeList Is Not an Array
When we use getElementsByClassName(), we don’t retrieve a simple array of elements, we retrieve a NodeList. Like an array, this is a collection of elements; unlike an array, the collection is updated in real time. If the HTML DOM is modified, the contents of posts gets modified to match.
For example, let’s create a new div with a class of post and append it to the contents div:
var newPostDiv = document.createElement("div");
newPostDiv.setAttribute("class", "post");
document.getElementById("contents").appendChild(newPostDiv);
Run that, then type posts and hit Enter. You’ll see an extra div in the list – even though we haven’t touched the posts variable.
Since a NodeList is not an array, it doesn’t have most of the methods and properties of Array, such as push() In fact, we’ve already used the only property: length. The only method is .item(n), which just gets the nth item in the list.
However, our earlier demonstration with appendChild() does suggest an alternative solution: what if, instead of trying to rearrange the elements of the NodeList within the NodeList, we rearranged them within the page?
First, we’ll run through the list in reverse order, and append each element in turn to the contents div; then, we’ll remove the original posts.
Refresh the Tumblr page to clear out all the extra rubbish we’ve added to the DOM, then do the first step, of adding the elements in reverse order:
//have to define posts again, since we lost it when we refreshed
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
Okay, now we… wait, what?
The (chronological) first post is already at the top, and the last post is at the bottom, with no posts repeated. This may seem surprising, but it makes sense: we didn’t clone any elements of the NodeList, we just appended them to the contents div, in reverse order. Since the NodeList always reflects the contents of the HTML DOM, we just moved each of the 11 elements to a new position – the 11th element got added to the end (no change in position); then the 10th got moved to be after that; the 9th after that, and so on, until the 1st element was right at the end.
So, problem solved, in five simple lines of code. Now let’s automate it.
Turning It Into a Browser Extension
Three of the top four browsers allow you to create browser extensions – installable add-ons – using JavaScript. (It will not surprise you to learn that Internet Explorer is the exception.) Here are the instructions for Chrome, the instructions for Firefox, and the instructions for Safari.
But we’re not going to use any of those. Instead, we’ll use a great add-on called Greasemonkey, which allows you to install little JS scripts without needing to package them up as full-blown browser extensions. Essentially, it injects snippets of JavaScript into the page, once it’s loaded.
Chrome already has Greasemonkey support baked in. Opera has something very similar to Greasemonkey baked in: UserJS. For Firefox, you’ll need to install the Greasemonkey extension. For Safari, install SIMBL, and then GreaseKit. For IE, install IE7Pro or Trixie.
Writing the Greasemonkey Script
Create a new text file, and name it ChronologicalTumblr.user.js. Make sure you remove the default .txt extension, and that you use .user.js, rather than just .js – this is the extension for a Greasemonkey script.
Copy our post rearrangement code into the file:
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
Now, we need to add some extra metadata at the top of the script – details about the script itself. All these details should go in comments, starting with ==UserScript== and ending with ==/UserScript==:
// ==UserScript==
//
// ==/UserScript==
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
First, we’ll add a name and a description:
// ==UserScript==
// @name Chronological Tumblr
// @description Displays Tumblr posts in chronological order
// ==/UserScript==
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
Then, we’ll specify a namespace. The combination of the name and the namespace is what uniquely identifies the script; if you try to install another Greasemonkey script with the same name and namespace as an existing script, it will overwrite the old one – if only the name or the namespace match, it’ll just install the new one alongside the old.
It’s common to use a URL here, so I’ll use Activetuts+’s. You should use your own, since you’re in control of it:
// ==UserScript==
// @name Chronological Tumblr
// @description Displays Tumblr posts in chronological order
// @namespace http://active.tutsplus.com/
// ==/UserScript==
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
Now we need to specify which URLs this script should affect – that is, on which web pages the JavaScript should automatically be injected into. I want this script to work on the BtotheF homepage, plus the other archive pages, like http://btothef.tumblr.com/page/2:
// ==UserScript==
// @name Chronological Tumblr
// @description Displays Tumblr posts in chronological order
// @namespace http://active.tutsplus.com/
// @include http://btothef.tumblr.com/
// @include http://btothef.tumblr.com/page/*
// ==/UserScript==
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
The * is a wildcard; it ensures that the script will be inserted into every single archive page of the BtotheF Tumblr.
We could use a wildcard to make every single Tumblr’s archive pages display in chronological order:
// ==UserScript==
// @name Chronological Tumblr
// @description Displays Tumblr posts in chronological order
// @namespace http://active.tutsplus.com/
// @include http://*.tumblr.com/
// @include http://*.tumblr.com/page/*
// ==/UserScript==
var posts = document.getElementById("contents").getElementsByClassName("post");
var numPosts = posts.length;
for (var i=numPosts - 1; i >= 0; i--) {
document.getElementById("contents").appendChild(posts[i]);
}
In this case, it might be a good idea to improve your script to insert a button or link into the page that rearranges the posts when clicked. That way, you can use it when appropriate, without having to manually add every single Tumblr’s URL as an @include parameter.
There are other metadata parameters you could add, but this is all we need for now.
Finishing Off
Installing the script in Chrome is easy: just drag and drop it from your hard drive into a browser window. It’ll warn you that scripts could potentially be dangerous (just click Continue), and then check again that you want to install this specific one:
Hit Install. If you’re using another browser, refer to the relevant Greasemonkey script’s manual – in any case, it’ll be simple.
Once it’s installed, you can see it in your list of extensions:
Head back to http://btothef.tumblr.com/, or hit refresh if you still have it open.
The posts are now automatically displaying in chronological order!
It’s not perfect: you may have noticed that the navigation buttons have been moved to the top of the page, since they are contained in a div with a class of post. But hey – if that bugs you, you have the tools to fix it now.



View full post on Activetuts+
Feb 3, 2012
Posted on Feb 3, 2012 in Hints and Tips | 10 comments
In this Quick Tip, we’ll discuss the confusing AS3 error 1203, “no constructor found”, which crops up without provocation and is rather unfortunately worded. We’ll examine the scenario in which it will appear, and how to fix it.
Step 1: An Obligatory But Somewhat Useless Description of Error 1203
First, here is the language of the error:
1203: No default constructor found in base class flash.display:BitmapData.
It’s difficult to break this down into plain English. So let’s next move on to a scenario that produces this error.
Step 2: A Busted Project
You can find this project in the download package, in the folder “busted“. It consists of the following (which you can use to re-create this project if you prefer a hands-on approach):
- A FLA named Busted.fla. It is empty, but is linked to the document class described next.
-
A document class named Busted.as. This extends Sprite and simply creates an instance of the class described next, and adds it to the stage.
The contents of the class are as follows:
package {
import flash.display.*;
public class Busted extends Sprite {
public function Busted() {
var bmp:Bitmap = new Bitmap(new BustedBitmap());
addChild(bmp);
}
}
}
The BustedBitmap class extends BitmapData, and so we use it to feed a Bitmap object, which is then added to the stage.
-
Another class file named BustedBitmap.as. As mentioned previously, this extends BitmapData, and its purpose is to be a BitmapData that automatically supplies itself with some Perlin noise. Its contents are:
package {
import flash.display.*;
public class BustedBitmap extends BitmapData {
public function BustedBitmap() {
perlinNoise(100, 100, 2, 1024, false, false, 7, true);
}
}
}
So, in the BustedBitmap constructor, we call perlinNoise() and thus we automatically have something interesting in the pixel data, so we can see something right away when displaying on the stage.
Now, go ahead and test the movie. You will get Error 1203, pointed at line 4 of BustedBitmap.as. And line 4 is…
public function BustedBitmap() {
Step 3: What’s All This, Then?
So what happened? The big thing to keep in mind is that we’re writing a class that is a subclass of another class (BitmapData in this case). Also keep in mind that when a class is instantiated, the constructor is called as part of the “new” process.
If you do not actually write a constructor, ActionScript will imply one for you. It will look like this:
public function [NameOfClass]() {
}
Where “[NameOfClass]” will match the name of your class.
Similarly, if you write a subclass, and don’t call super() in it, then ActionScript will imply that call for you, as well. It will look like this:
public function [NameOfSubclass]() {
super();
// Other explicit code in subclass constructor
}
Note that it happens on the first line, and is simply a call to super with no arguments.
Finally, we get to the root of the problem. If your subclass omits an explicit call to super, and your superclass’s constructor has required parameters, then your implicit call to super does not supply the required parameters. You’d think that an argument mismatch error could catch this, but consider that since there isn’t any code actually written to make the mismatch, ActionScript can only complain that the lack of a default constructor.
In our example, BustedBitmap extend BitmapData, which has a constructor defined in the documentation as so:
BitmapData(width:int, height:int, transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF)
The first two parameters are required, and we’re not supplying them.
Step 4: It’s as Simple As…
The solution is, once you understand the problem, extremely simple. You need to explicitly call the super constructor, at least if there are required parameters. In other words, in our BustedBitmap class, this following highlighted line will fix the problem:
package {
import flash.display.*;
public class BustedBitmap extends BitmapData {
public function BustedBitmap() {
super(600, 400);
perlinNoise(100, 100, 2, 1024, false, false, 7, true);
}
}
}
And that will do it.
As a teachable moment, I’d like to add that, when extending another class, it’s generally a good idea to include the explicit call to super. Even if there are no parameters at all, required or otherwise (as in Sprite or MovieClip), an explicit call can declare intention and awareness of the nature of the subclass. More practically, explicit calls give you an opportunity to run some code prior to the call to super, which may be helpful in certain situations.
Step 5: …And That Is All
Yet another error demystified; the challenge for this one is that the real cause of the error is quite buried. Once you become handy with a shovel, though, the fix is easy enough.
Thanks for reading, and be ready for more debugging tips.



View full post on Activetuts+
Feb 1, 2012
Posted on Feb 1, 2012 in Hints and Tips | 10 comments
Commando is a Flash debugger that lets you change variables at runtime and run your own custom commands. It will allow you to try out whatever tweaks you want, without the hassle of changing your code and recompiling every time. This debugger also comes with its own memory monitor, and an output panel that is similar to the output dialog in the Flash IDE.
See Commando in Action
Why Use Commando?
Using Commando you can change your code at runtime. Let’s pretend you are making a platformer game. You have a jumpPower variable, but when testing your game you feel that the player can’t jump high enough. So instead of going back and changing your code, you can just type set jumpPower(25) in Commando and you can try out the new value.
Of course, this is just a simple demonstration; Commando can be extended even more. Just continue reading…
Configuration
First, download the ZIP file included with this article. Then, add the SWC file to your project’s library path.
Once you have added the SWC to your project’s library path, all you need are three lines of code to add an instance of Commando on the stage:
import com.pxlcoder.debug.Commando;
var commando:Commando = new Commando(flash.ui.Keyboard.ENTER, this);
addChild(commando);
Now press CTRL+ENTER (CMD+ENTER on a Mac), and you will see Commando up and running in your Flash project!
Explore
Commando comes with eight built-in functions. In this section I will explain what they are and how to use them.
Math
Using the Math function you can do addition, subtraction, multiplication and division between two numbers. The Math function can also calculate the square root of a number. For example, type math 1+1 or math sqrt(144) in the Commando dialog. The answer will show up in the output dialog.
Hide
You can use the Hide function to hide objects. You can type hide monitor or hide output to hide the two panels at the bottom. You can also use the Hide function with movieclips or buttons by simply typing hide myInstanceName.
View
You can use the View function to view hidden objects. You can type view monitor or view output to show the two panels at the bottom. You can also use the View function with movieclips or buttons by simply typing view myInstanceName. If any of your objects have their visible property set to false, typing view myInstanceName will set it to true.
Set
Using the Set function you can set values of your variables or you can set properties of your objects. To use the Set function on variables type set myVariable(myValue). To use the Set function on objects, type set myInstanceName(myPropertyName,myValue).
Get
Using the Get function you can get the values of your variables and properties. To use the Get function type get myVariable. You can also get properties by typing get myInstanceName.myPropertyName.The values will show up in the output dialog.
Probe
Using the Rrobe function you can get the probe all of the properties of an object. To use the Probe function type: probe myObjectInstanceName. The properties will be traced in the Flash IDE, rather than in the Commando output dialog.
Remove
You can use the Remove function to remove objects from the stage. To use the Remove function type remove myInstanceName.
Add
You can use the Add function to add objects back on to the stage. To use the Add function type add myInstanceName.
Note: Commando’s built-in functions each evaluate a single string, so after you type your function name and press space, make sure to type your arguments without any spaces. Instead, type your arguments as one continuous word, with commas if necessary.
Extend
While Commando has many great built-in functions, you may want something more. To solve this problem, Commando comes with a function to add your own custom commands.
Here is a quick code example of how you can create your own custom commands:
import com.pxlcoder.debug.Commando;
var commando:Commando = new Commando(flash.ui.Keyboard.ENTER, this);
addChild(commando);
commando.addCommand("output", outputFunction); //Sets the command keyword to "output" and calls the outputFunction below
public function outputFunction(s:String):void {
commando.output(s); //A call to Commando's built-in output dialog
}
Now press CTRL+ENTER (CMD+ENTER on a Mac), to run your code. In the Commando dialog, type output hello, and press Enter. The output dialog will now say hello!
You can also remove commands from Commando by using the removeCommand() function.
import com.pxlcoder.debug.Commando;
var commando:Commando = new Commando(flash.ui.Keyboard.ENTER, this);
addChild(commando);
commando.removeCommand("output");
Recap: Commando has three functions that you can access; addCommand(), output() and removeCommand().
Conclusion
At the end of the day, debugging is the most important part in the development process. Commando has everything you could ever ask for in a debugger. You can use it for anything and everything.
If you’re a Tuts+ Premium member, you can download the source files for Commando – just log in and head to the Source File page.
Any questions, comments or concerns? Feel free to get in touch in the comments.
Take control of your Flash projects!



View full post on Activetuts+
Jan 31, 2012
Posted on Jan 31, 2012 in Hints and Tips | 10 comments
In this tutorial we will be working with the HTML5 canvas and Javascript to create a dynamic tile swapping game. The result will be a puzzle that works with any given image, and has flexible difficulty levels that are easily adjusted.
The Complete HTML5 Canvas Puzzle
Here is a quick shot of the puzzle we will be building:
Click to play
A couple of notes:
- Cross-browser compatibility: This puzzle was tested and works in all versions of Safari, Firefox, and Chrome that support the
canvas element.
- Mobile: The code provide here works in the above-mentioned desktop browser and is not optimised for mobile. The puzzle will load and render just fine, but because of the touch and drag behaviors in mobile browsers, optimization is required for it to function correctly. Optimizing this puzzle for mobile will be covered in a future tutorial.
- Adjustable Difficulty: The code contains a constant,
PUZZLE_DIFFICULTY, that determines the number of pieces. In the demo above, this is set to 4, giving a 4×4 puzzle. We can easily change this – for example, this version has a PUZZLE_DIFFICULTY of 10.
Getting Started
To get started, create a directory for the project. Place an image in the directory that you want to use as your puzzle. Any web friendly image will do, and it can be any size your heart desires – just make sure it fits within the fold of your browser’s window.
Step 1: Creating the HTML Template
Open a new file using your favorite text editor and save it inside your project directory, next to your image. Next, fill out this basic HTML template.
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Puzzle</title>
<script>
</script>
</head>
<body onload="init();">
<canvas id="canvas"></canvas>
</body>
</html>
All we need to do here is create a standard HTML5 template containing one canvas tag with the id of “canvas”. We’ll write an onload listener in the body tag which will call our init() function when fired.
Now place by placing your cursor inside the script tag. From here on out it’s all javascript. With the exception of the initial variables, I’ll be organising the sections by function. First showing you the code and then explaining the logic.
Ready? Let’s get right to it!
Step 2: Setting Up Our Variables
Let’s set up our variables and take a look at each one.
const PUZZLE_DIFFICULTY = 4;
const PUZZLE_HOVER_TINT = '#009900';
var _canvas;
var _stage;
var _img;
var _pieces;
var _puzzleWidth;
var _puzzleHeight;
var _pieceWidth;
var _pieceHeight;
var _currentPiece;
var _currentDropPiece;
var _mouse;
First we have a couple of constants: PUZZLE_DIFFICULTY and PUZZLE_HOVER_TINT. The PUZZLE_DIFFICULTY constant holds the number of pieces in our puzzle. In this application, the rows and columns always match, so by setting PUZZLE_DIFFICULTY to 4, we get 16 puzzle pieces in total. Increasing this increases the difficulty of the puzzle.
Next is a series of variables:
_canvas and _stage will hold a reference to the canvas and to its drawing context, respectively. We do this so we don’t have to write out the entire query each time we use them. And we’ll be using them a lot!
_img will be a reference to the loaded image, which we will be copying pixels from throughout the application.
_puzzleWidth, _puzzleHeight, _pieceWidth, and _pieceHeight will be used to store the dimensions of both the entire puzzle and each individual puzzle piece. We set these once to prevent calculating them over and over again each time we need them.
_currentPiece holds a reference to the piece currently being dragged.
_currentDropPiece holds a reference to the piece currently in position to be dropped on. (In the demo, this piece is highlighted green.)
_mouse is a reference that will hold the mouse’s current x and y position. This gets updated when the puzzle is clicked to determine which piece is touched, and when a piece is being dragged to determine what piece it’s hovering over.
Now, on to our functions.
Step 3: The init() Function
function init(){
_img = new Image();
_img.addEventListener('load',onImage,false);
_img.src = "mke.jpg";
}
The first thing we want to do in our application is to load the image for the puzzle. The image object is first instantiated and set to our _img variable. Next, we listen for the load event which will then fire our onImage() function when the image has finished loading. Lastly we set the source of the image, which triggers the load.
Step 4: The onImage() Function
function onImage(e){
_pieceWidth = Math.floor(_img.width / PUZZLE_DIFFICULTY)
_pieceHeight = Math.floor(_img.height / PUZZLE_DIFFICULTY)
_puzzleWidth = _pieceWidth * PUZZLE_DIFFICULTY;
_puzzleHeight = _pieceHeight * PUZZLE_DIFFICULTY;
setCanvas();
initPuzzle();
}
Now that the image is successfully loaded, we can set the majority of the variables declared earlier. We do this here because we now have information about the image and can set our values appropriately.
The first thing we do is calculate the size of each puzzle piece. We do this by dividing the PUZZLE_DIFFICULTY value by the width and height of the loaded image. We also trim the fat off of the edges to give us some nice even numbers to work with and assure that each piece can appropriately swap ‘slots’ with others.
Next we use our new puzzle piece values to determine the total size of the puzzle and set these values to _puzzleWidth and _puzzleHeight.
Lastly, we call off a few functions – setCanvas() and initPuzzle().
Step 5: The setCanvas() Function
function setCanvas(){
_canvas = document.getElementById('canvas');
_stage = _canvas.getContext('2d');
_canvas.width = _puzzleWidth;
_canvas.height = _puzzleHeight;
_canvas.style.border = "1px solid black";
}
Now that our puzzle values are complete, we want to set up our canvas element. First we set our _canvas variable to reference our canvas element, and _stage to reference its context.
Now we set the width and height of our canvas to match the size of our trimmed image, followed by applying some simple styles to create a black border around our canvas to display the bounds of our puzzle.
Step 6: The initPuzzle() Function
function initPuzzle(){
_pieces = [];
_mouse = {x:0,y:0};
_currentPiece = null;
_currentDropPiece = null;
_stage.drawImage(_img, 0, 0, _puzzleWidth, _puzzleHeight, 0, 0, _puzzleWidth, _puzzleHeight);
createTitle("Click to Start Puzzle");
buildPieces();
}
Here we initialize the puzzle. We set this function up in such a way that we can call it again later when we want to replay the puzzle. Anything else that needed to be set prior to playing will not need to be set again.
First we set _pieces as an empty array and create the _mouse object, which will hold our mouse position throughout the application. Next we set the _currentPiece and _currentPieceDrop to null. (On the first play these values would already be null, but we want to make sure they get reset when replaying the puzzle.)
Finally, it’s time to draw! First we draw the entire image to display to the player what they will be creating. After that we create some simple instructions by calling our createTitle() function.
Step 7: The createTitle() Function
function createTitle(msg){
_stage.fillStyle = "#000000";
_stage.globalAlpha = .4;
_stage.fillRect(100,_puzzleHeight - 40,_puzzleWidth - 200,40);
_stage.fillStyle = "#FFFFFF";
_stage.globalAlpha = 1;
_stage.textAlign = "center";
_stage.textBaseline = "middle";
_stage.font = "20px Arial";
_stage.fillText(msg,_puzzleWidth / 2,_puzzleHeight - 20);
}
Here we create a fairly simple message that instructs the user to click the puzzle to begin.
Our message will be a semi-transparent rectangle that will serve as the background of our text. This allows the user to see the image behind it and also assures our white text will be legible on any image
We simply set fillStyle to black and globalAlpha to .4, before filling in a short black rectangle at the bottom of the image.
Since globalAlpha affects the entire canvas, we need to set it back to 1 (opaque) before drawing the text. To set up our title, we set the textAlign to ‘center’ and the textBaseline to 'middle'. We can also apply some font properties.
To draw the text, we use the fillText() method. We pass in the msg variable and place it at the horizontal center of the canvas, and the vertical center of the rectangle.
Step 8: The buildPieces() Function
function buildPieces(){
var i;
var piece;
var xPos = 0;
var yPos = 0;
for(i = 0;i < PUZZLE_DIFFICULTY * PUZZLE_DIFFICULTY;i++){
piece = {};
piece.sx = xPos;
piece.sy = yPos;
_pieces.push(piece);
xPos += _pieceWidth;
if(xPos >= _puzzleWidth){
xPos = 0;
yPos += _pieceHeight;
}
}
document.onmousedown = shufflePuzzle;
}
Finally it’s time to build the puzzle!
We do this by building an object for each piece. These objects will not be responsible for rendering to the canvas, but rather to merely hold references on what to draw and where. That being said, let’s get to it.
First off, let’s declare a few variables that we’ll be reusing through the loop. We want to set up the loop to iterate through the number of puzzle pieces we need. We get this value by multiplying PUZZLE_DIFFICULTY by itself – so in this case we get 16.
In the loop:
for(i = 0;i < PUZZLE_DIFFICULTY * PUZZLE_DIFFICULTY;i++){
piece = {};
piece.sx = xPos;
piece.sy = yPos;
_pieces.push(piece);
xPos += _pieceWidth;
if(xPos >= _puzzleWidth){
xPos = 0;
yPos += _pieceHeight;
}
}
Start by creating an empty piece object. Next add the sx and sy properties to the object. In the first iteration, these values are 0 and represent the point in our image where we will begin to draw from. Now push it to the _pieces[] array. This object will also contain the properties xPos and yPos, which will tell us the current position in the puzzle where the piece should be drawn. We’ll be shuffling the objects before its playable so these values don’t need to be set quite yet.
The last thing we do in each loop is increase the local variable xPos by _pieceWidth. Before continuing on with the loop, we determine if we need to step down to the next row of pieces by checking whether xPos is beyond the width of the puzzle. If so, we reset xPos back to 0 and increase yPos by _puzzleHeight.
Now we have our puzzle pieces all stored away nicely in our _pieces array. At this point the code finally stops executing and waits for the user to interact. We set a click listener to the document to fire the shufflePuzzle() function when triggered, which will begin the game.
Step 9: The shufflePuzzle() Function
function shufflePuzzle(){
_pieces = shuffleArray(_pieces);
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
var i;
var piece;
var xPos = 0;
var yPos = 0;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
piece.xPos = xPos;
piece.yPos = yPos;
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, xPos, yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(xPos, yPos, _pieceWidth,_pieceHeight);
xPos += _pieceWidth;
if(xPos >= _puzzleWidth){
xPos = 0;
yPos += _pieceHeight;
}
}
document.onmousedown = onPuzzleClick;
}
function shuffleArray(o){
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
First things first: shuffle the _pieces[] array. I’m using a nice utility function here that will shuffle the indices of the array passed into it. The explanation of this function is beyond the topic of this tutorial so we’ll move on, knowing that we have successfully shuffled our pieces. (For a basic introduction to shuffling, take a look at this tutorial.)
Let’s first clear all graphics drawn to the canvas to make way for drawing our pieces. Next, set up the array similar to how we did when first creating our piece objects.
In the loop:
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
piece.xPos = xPos;
piece.yPos = yPos;
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, xPos, yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(xPos, yPos, _pieceWidth,_pieceHeight);
xPos += _pieceWidth;
if(xPos >= _puzzleWidth){
xPos = 0;
yPos += _pieceHeight;
}
}
First of all, use the i variable to set up our reference to the current piece object in the loop. Now we populate the xPos and yPos properties I mentioned earlier, which will be 0 in our first iteration.
Now, at long last, we draw our pieces.
The first parameter of drawImage() assigns the source of the image we want to draw from. Then use the piece objects sx and sy properties, along with _pieceWidth and _pieceHeight, to populate the parameters that declare the area of the image in which to draw from. The last four parameters set the area of the canvas where we want to draw. We use the xPos and yPos values that we are both building in the loop and assigning to the object.
Immediately after this we draw a quick stroke around the piece to give it a border, which will separate it nicely from the other pieces.
Now we wait for the user to grab a piece by setting another click listener. This time it will fire an onPuzzleClick() function.
Step 10: The onPuzzleClick() Function
function onPuzzleClick(e){
if(e.layerX || e.layerX == 0){
_mouse.x = e.layerX - _canvas.offsetLeft;
_mouse.y = e.layerY - _canvas.offsetTop;
}
else if(e.offsetX || e.offsetX == 0){
_mouse.x = e.offsetX - _canvas.offsetLeft;
_mouse.y = e.offsetY - _canvas.offsetTop;
}
_currentPiece = checkPieceClicked();
if(_currentPiece != null){
_stage.clearRect(_currentPiece.xPos,_currentPiece.yPos,_pieceWidth,_pieceHeight);
_stage.save();
_stage.globalAlpha = .9;
_stage.drawImage(_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight);
_stage.restore();
document.onmousemove = updatePuzzle;
document.onmouseup = pieceDropped;
}
}
We know that the puzzle was clicked; now we need to determine what piece was clicked on. This simple conditional will get us our mouse position on all modern desktop browsers that support canvas, using either e.layerX and e.layerY or e.offsetX and e.offsetY. Use these values to update our _mouse object by assigning it an x and a y property to hold the current mouse position – in this case, the position where it was clicked.
In line 112 we then immediately set _currentPiece to the returned value from our checkPieceClicked() function. We separate this code because we want to use it later when dragging the puzzle piece. I’ll explain this function in the next step.
If the value returned was null, we simply do nothing, as this implies that the user didn’t actually click on a puzzle piece. However, if we do retrieve a puzzle piece, we want to attach it to the mouse and fade it out a bit to reveal the pieces underneath. So how do we do this?
First we clear the canvas area where the piece sat before we clicked it. We use clearRect() once again, but in this case we pass in only the area obtained from the _currentPiece object. Before we redraw it, we want to save() the context of the canvas before proceeding. This will assure that anything we draw after saving will not simply draw over anything in its way. We do this because we’ll be slightly fading the dragged piece and want to see the pieces under it. If we didn’t call save(), we’d just draw over any graphics in the way – faded or not.
Now we draw the image so its center is positioned at the mouse pointer. The first 5 parameters of drawImage will always be the same throughout the application. When clicking, the next two parameters will be updated to center itself to the pointer of the mouse. The last two parameters, the width and height to draw, will also never change.
Lastly we call the restore() method. This essentially means we are done using the new alpha value and want to restore all properties back to where they were. To wrap up this function we add two more listeners. One for when we move the mouse (dragging the puzzle piece), and one for when we let go (drop the puzzle piece).
Step 11: The checkPieceClicked() Function
function checkPieceClicked(){
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)){
//PIECE NOT HIT
}
else{
return piece;
}
}
return null;
}
Now we need to backtrack a bit. We were able to determine what piece was clicked, but how did we do it? It’s pretty simple actually. What we need to do is loop through all of the puzzle pieces and determine if the click was within the bounds of any of our objects. If we find one, we return the matched object and end the function. If we find nothing, we return null.
Step 12: The updatePuzzle() Function
function updatePuzzle(e){
_currentDropPiece = null;
if(e.layerX || e.layerX == 0){
_mouse.x = e.layerX - _canvas.offsetLeft;
_mouse.y = e.layerY - _canvas.offsetTop;
}
else if(e.offsetX || e.offsetX == 0){
_mouse.x = e.offsetX - _canvas.offsetLeft;
_mouse.y = e.offsetY - _canvas.offsetTop;
}
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
if(piece == _currentPiece){
continue;
}
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight);
if(_currentDropPiece == null){
if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)){
//NOT OVER
}
else{
_currentDropPiece = piece;
_stage.save();
_stage.globalAlpha = .4;
_stage.fillStyle = PUZZLE_HOVER_TINT;
_stage.fillRect(_currentDropPiece.xPos,_currentDropPiece.yPos,_pieceWidth, _pieceHeight);
_stage.restore();
}
}
}
_stage.save();
_stage.globalAlpha = .6;
_stage.drawImage(_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight);
_stage.restore();
_stage.strokeRect( _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth,_pieceHeight);
}
Now back to the dragging. We call this function when the user moves the mouse. This is the biggest function of the application as it’s doing several things. Let’s begin. I’ll break it down as we go.
_currentDropPiece = null;
if(e.layerX || e.layerX == 0){
_mouse.x = e.layerX - _canvas.offsetLeft;
_mouse.y = e.layerY - _canvas.offsetTop;
}
else if(e.offsetX || e.offsetX == 0){
_mouse.x = e.offsetX - _canvas.offsetLeft;
_mouse.y = e.offsetY - _canvas.offsetTop;
}
Start by setting _currentDropPiece to null. We need to reset this back to null on update because of the chance that our piece was dragged back to its home. We don’t want the previous _currentDropPiece value hanging around. Next we set the _mouse object the same way we did on click.
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
Here we need to do clear all graphics on the canvas. We essentially need to redraw the puzzle pieces because the object being dragged on top will effect their appearance. If we didn’t do this, we’d see some very strange results following the path of our dragged puzzle piece.
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
Begin by setting up our usual pieces loop.
In the Loop:
piece = _pieces[i];
if(piece == _currentPiece){
continue;
}
Create our piece reference as usual. Next check if the piece we are currently referencing is the same as piece we are dragging. If so, continue the loop. This will keep the dragged piece’s home slot empty.
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight);
Moving on, redraw the puzzle piece using its properties exactly the same way we did when first drew them. You’ll need to draw the border as well.
if(_currentDropPiece == null){
if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)){
//NOT OVER
}
else{
_currentDropPiece = piece;
_stage.save();
_stage.globalAlpha = .4;
_stage.fillStyle = PUZZLE_HOVER_TINT;
_stage.fillRect(_currentDropPiece.xPos,_currentDropPiece.yPos,_pieceWidth, _pieceHeight);
_stage.restore();
}
}
Since we have a reference to each object in the loop, we can also use this opportunity to check if the dragged piece is on top of it. We do this because we want to give the user feedback on what piece it can be dropped on. Let’s dig into that code now.
First we want to see if this loop has already produced a drop target. If so, we don’t need to bother since only one drop target can be possible and any given mouse move. If not, _currentDropPiece will be null and we can proceed into the logic. Since our mouse is in the middle of the dragged piece, all we really need to do is determine what other piece our mouse is over.
Next, use our handy checkPieceClicked() function to determine whether the mouse is hovering over the current piece object in the loop. If so, we set the _currentDropPiece variable and draw a tinted box over the puzzle piece, indicating that it is now the drop target.
Remember to save() and restore(). Otherwise you’d get the tinted box and not the image underneath.
Out of the Loop:
_stage.save();
_stage.globalAlpha = .6;
_stage.drawImage(_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight);
_stage.restore();
_stage.strokeRect( _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth,_pieceHeight);
Last but not least we need to redraw the dragged piece. The code is the same as when we first clicked it, but the mouse has moved so its position will be updated.
Step 13: The pieceDropped() Function
function pieceDropped(e){
document.onmousemove = null;
document.onmouseup = null;
if(_currentDropPiece != null){
var tmp = {xPos:_currentPiece.xPos,yPos:_currentPiece.yPos};
_currentPiece.xPos = _currentDropPiece.xPos;
_currentPiece.yPos = _currentDropPiece.yPos;
_currentDropPiece.xPos = tmp.xPos;
_currentDropPiece.yPos = tmp.yPos;
}
resetPuzzleAndCheckWin();
}
OK, the worst is behind us. We are now successfully dragging a puzzle piece and even getting visual feedback on where it will be dropped. Now all that is left is to drop the piece. Let’s first remove the listeners right away since nothing is being dragged.
Next, check that _currentDropPiece is not null. If it is, this means that we dragged it back to the piece’s home area and not over another slot. If it’s not null, we continue with the function.
What we do now is simply swap the xPos and yPos of each piece. We make a quick temp object as a buffer to hold one of the object’s values in the swapping process. At this point, the two pieces both have new xPos and yPos values, and will snap into their new homes on the next draw. That’s what we’ll do now, simultaneously checking whether the game has been won.
Step 14: The resetPuzzleAndCheckWin() Function
function resetPuzzleAndCheckWin(){
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
var gameWin = true;
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight);
if(piece.xPos != piece.sx || piece.yPos != piece.sy){
gameWin = false;
}
}
if(gameWin){
setTimeout(gameOver,500);
}
}
Once again, clear the canvas and set up a gameWin variable, setting it to true by default. Now proceed with our all-too-familiar pieces loop.
The code here should look familiar so we won’t go over it. It simply draws the pieces back into their original or new slots. Within this loop, we want to see if each piece is being drawn in its winning position. This is simple: we check to see if our sx and sy properties match up with xPos and yPos. If not, we know we couldn’t possibly win the puzzle and set gameWin to false. If we made it through the loop with everyone in their winning places, we set up a quick timeout to call our gameOver() method. (We set a timeout so the screen doesn’t change so drastically upon dropping the puzzle piece.)
Step 15: The gameOver() Function
function gameOver(){
document.onmousedown = null;
document.onmousemove = null;
document.onmouseup = null;
initPuzzle();
}
This is our last function! Here we just remove all listeners and call initPuzzle(), which resets all necessary values and waits for the user to play again.
Conclusion
Click here to see the final result.
As you can see, you can do a lot of new creative things in HTML5 using selected bitmap areas of loaded images and drawing. You can easily extend this application by adding scoring and perhaps even a timer to give it more gameplay. Another idea would be to increase the difficulty and select a different image in the gameOver() function, giving the game levels.



View full post on Activetuts+