Raphael.js event handlers sometimes require closures

I’m playing around with raphael. In the code below, I use a few loops to make a grid of rectangles. I want each rectangle turn from white to gray when clicked. This is a little tricky in raphael, because you can’t use this or evt.target to get a reference to what got clicked on.
var main = function () {
var paper = Raphael("grid", 320, 200);
for (var rownum=0; rownum<3; rownum+=1) { for (var colnum=0; colnum<3; colnum+=1) { var r = paper.rect(10+colnum*50, 10+rownum*50, 50, 50); r.attr({stroke:"gray", fill:"white"}); r.node.onclick = function () { var this_rect = r; return function () { this_rect.attr({fill:"gray"}); } }(); } } }; window.onload = main;

Remember that your typical boring onclick assignments usually look like this:
r.node.onclick = function () {
alert("your mom");

I don't call the function. I just define it.

Study the r.node.onclick assignment in the main code again, and make sure to notice that the r.node.onclick attribute is assigned to the result of the function defined.

That's the first big difference. Now you have to figure what the heck is returned by this function. The answer is. . . another function. That other function is what gets linked up to be fired when a click event happens.

Closures are tricky at first, but they're really useful for situations like this, when you need to pass along references with the functions to operate on them.

Published by


My name is Matt Wilson and I live in Cleveland Heights, Ohio. I love random emails from strangers, so get in touch! matt@tplus1.com.