views:

32

answers:

1

Hi, using Raphael, I'm trying to get a shape to appear when you hover over an invisible area near the shape. The following code does not work - where am I going wrong? Each shape has two Raphael paths associated with it: one for the visible shape, and the other for the invisible area.

<script type="text/javascript" charset="utf-8">
 $("document").ready(function() {
        var RM  = Raphael("canvas", 1000, 500);

        var attr = {     // for the visible shapes
            fill: "#bbb",      "fill-opacity": 1,
            stroke: "#222",    "stroke-width": 0.3,
        };
        var attr2 = {    // for the invisible hovering areas
            fill: "green",     "fill-opacity": 0.0,
            stroke: "red",     "stroke-width": 0,
        };
        var things = {};

        /* Square */    things.square     = [ RM.path("m 154.21525,71.431259 74.32805,0 0,70.496711 -74.32805,0 0,-70.496711 z").attr(attr),
                                              RM.path("m 271.25132,77.933263 58.07304,0 0,56.409037 -58.07304,0 0,-56.409037 z").attr(attr2)   ];
        /* Triangle */  things.triangle   = [ RM.path("m 154.02932,222.44063 36.78089,-58.23641 34.48208,58.2364 -71.26297,1e-5").attr(attr),
                                              RM.path("m 271.25132,165.71032 58.07304,0 0,56.40903 -58.07304,0 0,-56.40903 z").attr(attr2)   ];
        for (var shape in things) {
            shape[0].color = Raphael.getColor();

shape[1].onmouseover = function () {
 shape[0].animate({fill:shape[0].color, stroke:"#ccc"}, 500);
 document.getElementById(shape)[0].style.display = "block";
 shape[0].toFront();   R.safari();
};
shape[1].onmouseout = function () {
 shape[0].animate({fill:"#bbb", stroke:"#222"}, 500);
 document.getElementById(shape)[0].style.display = "none";
 shape[0].toFront();   R.safari();
};
        } // end for every member of things
    }); // end the document ready function
</script>

The example on the Raphael website uses more complicated javascript: http://raphaeljs.com/australia.html

I didn't use this code because I don't understand the function syntax they use:

(function (a, b) {
    ----
})(c, d);

But I still don't see what's wrong with my version! Thanks for any help!

+2  A: 
for (var shape in things) { ...

This does not behave like foreach, instead it behaves more like Perls:

foreach my $shape (keys $things) { ...

So your code should be:

for (var shape in things) {
    things[shape][0].color = Raphael.getColor();
    ...

Additional answer

As for the function syntax, it's rather simple and is very common in modern js code so you should familiarize yourself with it. Let's construct that function step by step.

We know:

function foo (x,y) {};

declares a function, but in javascript functions can be anonymous:

function (x,y) {};

is a function with no name. Now, in a declaration, this is rather useless but if we do this in an expression it yields a reference to that function. So how do we make it an expression? just put an = sign to the left of it:

var foo = function (x,y) {}

is a function expression assigning the function to variable foo.

Apart from being to the right of the = sign, there are other places where code is considered expressions. One of them is when code happens inside braces. It comes from math really:

var x = a * (b + c);

everything to the right hand side of the = sign is an expression but (b+c) is special because it is a sub-expression that is evaluated first. It's the () syntax that makes b+c an expression in their own right. Similarly:

(function (x,y) {})

forces what initially looks like a function declaration to become a function expression. The rule comes from the math expression earlier.

As I mentioned earlier, a function expression evaluates to a function reference. And one of the things you can do with a function reference is to use it to call the function:

var foo = function (x,y) {};
foo();

here, the () after foo means something different: it is used to make a function call. Since we can make a function call using a function reference and since a function expression evaluates to a function reference we can call the function without assigning it to any variable:

(function (x,y) {})();  // think of it as foo() where foo=(function(x,y){})
slebetman