I’ve had some trouble with the SVG versions of CompendiumLD maps I’m (still) developing this week. The problem was occurring when I tried extracting data from a mouse click event, for mouse clicks on a CompendiumLD icon. It seems that because the icon is defined as a SVG group element (<g>) that the target of the event (i.e the click) is interpreted by some browser’s Javascript engine as being the group as a whole, and by others as being the specific SVG element within the group upon which the click actually occurred.
In my code, the ‘onclick’ attribute is attached to a <use> element, so I naiively assumed it would pick up any clicks on whatever the the <use> referred to as a whole. In this case, the <use> referred to the CompendiumLD icon definition. This is a SVG group <g> containing lots of other SVG elements
Teg Lansdell (and Jonathan Fine) helped me solve the problem by pointing me towards the ‘evt.target and evt.currentTarget‘ section in the ‘Dynamic SVG and JavaScript‘ of W3C’s working draft ‘An SVG Primer for Today’s Browsers‘. Here are the relevant paragraphs (the …. indicates that I’ve cut some text out):
“Likewise, we may assign an event handler to the entire group as in <g onclick=”doIt()”>. This generally works well, unless we try to identify the group itself that was clicked on. That is because even though an event handler is assigned to the group, the target of the event ends up being the specific element within the group that actually received the event”.
“The answer to the above issue lies with evt.currentTarget. Its purpose,…….. is to find the superordinate object containing evt.target, specifically the group or other container to which the event listener has been assigned”.
I ran into problems because I used Firefox 9.0.1 for my initial tests, and it returns the <use> element for both currentTarget and target However, Chrome (and Safari) return the <use> element for currentTarget, but an ‘SVGElementInstance’ for ‘target’. Now in the ‘Document Structure‘ section of the SVG 1.1 (Second Edition)’ W3C recommendation it says “For each ‘use’ element, the SVG DOM maintains a shadow tree (the “instance tree”) of objects of type SVGElementInstance“. In then goes on to explain how group elements are handled, using this example
“If the ‘use’ element references a ‘g’ which contains two ‘rect’ elements, then the instance tree contains three SVGElementInstance objects, a root SVGElementInstance object whose correspondingElement is the SVGGElement object for the ‘g’, and then two child SVGElementInstance objects, each of which has its correspondingElement that is an SVGRectElement object”.
To get the ‘real’ element related to a SVGElementinstance, use the ‘correspondingElement’ property, eg.
actualElement = svgElementInstance.correspondingElement;
In conclusion, I’m going to use the ‘currentTarget’ for this particular bit of code in the expectation (and hope) that it will work across most modrn browsers. A quick check of Safari, Chrome, Firefox and IE9 shows that it appears to for those browsers.
However, I’m perturbed that Firefox seems to be processing the SVG and Javascript differently, and incorrectly?
