Entry
How do I assign an event handler to an object?
How do I attach an object's method as an event handler?
Nov 10th, 2003 06:05
Gavin Kistner,
Most SVG elements inherit from the DOM 2 Events EventTarget interface,
which enables you to dynamically assign one or more event handlers to
the object (for each event type).
This entry shows first how to attach a simple global function as an
event handler, then how to attach an object's method (so that the
method still has proper object scope, with 'this' referring to the
object in question).
All examples assume that you have an object in your SVG file with an
ID of 'myObjID', e.g.
<g id="myObjID">...</g>
and a reference to the global SVG document called 'document'.
ATTACHING A GLOBAL FUNCTION
===========================
<script type="text/ecmascript"><![CDATA[
function SayHello(){
alert('hello world');
}
var myObj = document.getElementById('myObjID');
myObj.addEventListener('click',SayHello,false);
]]></script>
In the above, note that:
* the event type is 'click', not 'onclick'
* the function name is used without parentheses
* the third parameter is false
(this is almost always what you'll want)
Other event types of interest to the fledgling SVG developer are
'mouseover','mouseout','mousedown','mouseup'...but that's not a
complete list. For a complete list, see
http://www.w3.org/TR/SVG11/interact.html#SVGEvents
ATTACHING AN OBJECT'S METHOD
============================
If you used the above to attach the method of an object instance, you
would not get what you expect. For example:
<script type="text/ecmascript"><![CDATA[
function MyClass(name){
this.name=name;
}
MyClass.prototype.sayMyName=function(){
alert(this.name+' says "Hello"');
}
var bob = new MyClass('Bob Villa');
var myObj = document.getElementById('myObjID');
myObj.addEventListener('click',bob.sayMyName,false);
//THE ABOVE WON'T DO WHAT YOU WANT
]]></script>
In the above, the sayMyName() function will be run in global scope,
and 'this' will refer to the global window object, not 'bob'.
There are two ways to do what you want properly:
1) Define a handleEvent method of your object
---------------------------------------------
<script type="text/ecmascript"><![CDATA[
function MyClass(name){
this.name=name;
}
MyClass.prototype.handleEvent=function(evt){
switch(evt.type){
case 'click':
this.sayMyName(evt);
break;
}
}
MyClass.prototype.sayMyName=function(){
alert(this.name+' says "Hello"');
}
var bob = new MyClass('Bob Villa');
var myObj = document.getElementById('myObjID');
myObj.addEventListener('click',bob,false);
//NOTE THAT THE OBJECT ITSELF IS PASSED
]]></script>
Unfortunately the above does not work with Corel's SVG Viewer v2.1;
the alternative method (below) may cause memory leaks in some SVG UAs,
and also may not work all the time, as some UAs will (under
circumstance I don't fully understand) 'clean' up the SVG element and
destroy the custom 'ownerJSObj' property we use to associate the
element with its JS object.
2) Assign a custom property on the SVG element
----------------------------------------------
<script type="text/ecmascript"><![CDATA[
function HandleEventWithObject(evt){
var svgEl = evt.currentTarget;
var jsObj = svgEl.ownerJSObj;
if (jsObj!=null) jsObj.handleEvent(evt);
}
function MyClass(name){
alert(this.name+' says "Hello"');
}
MyClass.prototype.handleEvent=function(evt){
switch(evt.type){
case 'click':
this.sayMyName(evt);
break;
}
}
MyClass.prototype.sayMyName=function(){
alert(this.name);
}
var bob = new MyClass('Bob Villa');
var myObj = document.getElementById('myObjID');
myObj.ownerJSObj = bob;
myObj.addEventListener('click',HandleEventWithObject,false);
]]></script>