EML
EML

Reputation: 10261

Can't pass a function as a value to setAttribute

I have some working SVG code that handles mouse events by setting attributes on a shape:

function plot() {
  ...
  shape.setAttributeNS(null, "onmouseover", "popup_on (evt,"+sindex+","+month+")");
  shape.setAttributeNS(null, "onmouseout",  "popup_off(evt,"+sindex+")");
}

However, I need to change this code, because popup_on and popup_off are no longer static functions, and need lots of context depending on where they're called from. I'm handling this by defining a closure, and passing a function name as the attribute value:

function plot(popup_on, popup_off) {
  ...
  shape.setAttributeNS(null, "onmouseover", popup_on  + "(evt,"+sindex+","+month+")");
  shape.setAttributeNS(null, "onmouseout",  popup_off + "(evt,"+sindex+")");
}

However, this doesn't work - the popup code is never fired. If I check the 'shape' attributes in Firebug or Dragonfly they seem to be correct. 'shape' has 'onmouseover' and 'onmouseout' attributes, and the value of the attribute is the complete source text of the popup_on and popup_off functions:

onmouseover=function popup_on(evt, sindex, month) {
  ...
} 

but the functions aren't actually run. Any idea what I'm doing wrong? Thanks.

UPDATE

Thanks for all the feedback. Marc's answer doesn't work; 'function' is flagged as a syntax error. 'popup_on' and 'popup_off' aren't strings - they're actually functions in the closure. Both Sime's and Erik's answers did work, though, but with one problem.

If I change the code to this:

shape.addEventListener("mouseover", function() {popup_on (evt, sindex, month);}, false);

then firebug complains that 'evt' is undefined when it tries to execute popup_on (when the mouse hits). If I change evt to either window.evt or evt || window.evt, then I don't get this error, but I still don't have access to the event in the popup handler:

   // popup handler in closure
   o["popup_on"] = function(evt, sindex, month) {
      // both evt and window.evt are undefined on entry
      evt = evt || window.evt;
      // so evt is still undefined, but...
      ...
      // I need to do this
      var upright = (evt.clientY >= cy);

Any idea why? Thanks.

UPDATE2

Ok - fixed. The answer is:

shape.addEventListener("mouseover", function(evt) {popup_on (evt, sindex, month);}, false);
shape.addEventListener("mouseout",  function(evt) {popup_off(evt, sindex);}, false);

Upvotes: 0

Views: 397

Answers (2)

Erik Dahlström
Erik Dahlström

Reputation: 60966

Why don't you use shape.addEventListener("mouseout", function() {...}, false) instead? See here for some examples.

If you want the event object to be named 'evt' in your function you can name it (you can give it any name you want), like this: shape.addEventListener("mouseout", function(evt) {...}, false)

Otherwise the event variable is by default named 'event' inside the listener function, not 'evt'. This is a source of some confusion.

Upvotes: 1

Marc B
Marc B

Reputation: 360572

popup_on  + "(evt,"+sindex+","+month+")"

is see as "the function popup_on plus the string '(evt,' plus the value of sindex plus ..."

It's not interpreted as building a function call.

If you need to dynamically build its parameters, you should do something more like

shape.setAttributeNS(null, "onmouseout",  function() {
    popup_off(evt,sindex);
});

Upvotes: 1

Related Questions