views:

124

answers:

3

Having discovered that IE does not handle javascript onmouseout, I determined to use jQuery instead so the cross-browser compatibility would be taken care of automatically. I am making an area defined by an svg path light up when the mouse hovers over it, and I adapted the code provided on the Raphael website from the Australia example: http://raphaeljs.com/australia.html.

In this code, each state of Australia is defined by a Raphael path, for example Tasmania:

 aus.tas = R.path("...").attr(attr);

This path ('st') is then passed to the function:

st[0].onmouseover = function () {
    ...
};

Contrary to what I would have expected, the code is st[0].onmouseover as opposed to merely st.onmouseover. Thus, the path must actually be an array, and st[0], what ever that is, is the thing that is hovered over.

In order to replace onmouseover with the jQuery equivalent (which I believe is .mouseout()), I need to assign a class to st[0] so I can refer to it with jQuery. My question is, how do I do that?? If the code was st.onmouseover it would be straightforward, but why is the path (st) an array?? What exactly is st[0]? And how the heck do I get to it?

+4  A: 

You don't need to assign a class to it in order to expose it to jQuery. Certainly not. You can simply pass your DOM element to jQuery and it will do the magic for you...

$(st[0]).mouseout(function() {
  alert("That mouse is outta here!");
};

You are seeing the array syntax because that is generally how Javascript libraries maintain a reference to the original element (essentially just "wrapping" it and adding functionality). Pseudo-code explanation...

st == Raphael element
st[0] == DOM element
Josh Stodola
Note that you can also get the reference to associated DOM Object of a Raphael Object using the [ **`.node`** ](http://raphaeljs.com/reference.html#node) property. So `st[0]` and `st.node` are equivalent.
Peter Ajtai
@Peter Good point. By the same token, jQuery has the [`get()`](http://api.jquery.com/get/) method.
Josh Stodola
Also, it seems like the Raphael [ **`.mouseover()` and `.hover()`** ](http://raphaeljs.com/reference.html#events) methods are cross browser, just like the jQuery ones. I think this demo was written before those methods or `node` were introduced. ---------- Anyway, +1 for the `st[0]` explanation.
Peter Ajtai
Good point Peter, need to update the demo code.
Dmitry Baranovskiy
+1  A: 

This is a bit of javascript trickery, st is passed in. Look at the JS code in the australia example.

(function (st, state) {
                    .. some code referring to st[0] in here .. 
                })(aus[state], state);

So st[0] in this code refers to the path DOM node from aus[state].

Try it yourself with this simple example in a Firebug console:

(function(a,b) {alert(a); })("hello", "b");

hth

Francis Shanahan
+3  A: 

Note: That demo was made with an old version of Raphael. Now Raphael has its own custom event handlers including .mouseover() and .hover().


The short of it:

Simply wrap the DOM Object to make a jQuery Object out of it, or use the Raphael built in custom event handlers:

$(st[0]).mouseover( ... );            // This uses the jQuery .mouseover() method

Or, probably more convenient, and IE supported:

$(st[0]).hover( ... );                //     This uses the jQuery .hover() method

Or, using a Raphael built in event handler method:

st.mouseover( ... );                 // This uses the Raphael .mouseover() method
st.hover( ... );                     //     This uses the Raphael .hover() method

The long of it:

You can get the reference to the DOM object to work on using node or [0], since RaphaelObject[0] is always the reference to the DOM element:

aus.tas = R.path("...").attr(attr);

// aus.tas is a Raphael object
// aus.tas[0] is aus.tas.node is the reference to the DOM Object

$(aus.tas[0]).mouseover(function() {          // Could have also use aus.tas.node
    ...
});

// Raphael now has custom event handlers
aus.tas.mouseover(function() {
    ...
});
aus.tas.hover(function() {
    ...
}, function() {
    ...
});

So, with you function:

(function (st, state) {
      // st is a Raphael Object
      // st[0] is st.node is the reference to the DOM Object

      // This is now using jQuery for mouseover!
    $(st[0]).mouseover(function() {
        ...
    });
    ...
})(aus[state], state);

Additionally, I would suggest looking into the jQuery .hover() function, which does handle IE quite nicely:

(function (st, state) {
      // This is now using jQuery not Raphael for hover!
    $(st[0]).hover(function() {
        ... // the mouseenter function
    }, function() {
        ... // the mouseleave function
    });
    ...
})(aus[state], state);

As a simplified demonstration, here is how to bind mouseenter and mouseout using .hover() to a Raphael element (tested in IE 8):

​$(function() {
    var elie, paper = Raphael("canvas", 500, 500); 

      // Create Raphael element
    elie = paper.rect(0,0,100,100).attr("fill","#000");

      // Get reference to DOM object using .node and bind
      //     mouseover and mouseout to it:
    $(elie[0]).hover(function() {
        elie.attr("fill","#FFF");
    },function() {
        elie.attr("fill","#000");    
    });
});​

Try it out with this jsFiddle

Additionally, the Raphael .hover() method seem to work in IE too.

Peter Ajtai
+1 For research and demo. Nicely done!
Josh Stodola
Thanks to all of you, awesome answers! Got it completely sorted now!
Bazley