2

Please take a look at this fiddle: http://jsfiddle.net/arasbm/Tyxea/14/

As you can see I want to transform SVG elements when an event is triggered on them. You can click on arrow and it should work, because it uses the JavaScript code embeded inside the SVG scope:

<svg id="my-svg" width="20cm" height="20cm" viewBox="0 0 600 600"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example showing how to transform svg elements 
        using SVGTransform objects</desc>
  <script type="application/ecmascript"> <![CDATA[
    function transformMe(evt) {
      // svg root element to access the createSVGTransform() function
      var svgroot = evt.target.parentNode;

      // SVGTransformList of the element that has been clicked on
      var tfmList = evt.target.transform.baseVal;

      // Create a seperate transform object for each transform
      var translate = svgroot.createSVGTransform();
      translate.setTranslate(50,5);

      var rotate = svgroot.createSVGTransform();
      rotate.setRotate(10,0,0);

      var scale = svgroot.createSVGTransform();
      scale.setScale(0.8,0.8);

      // apply the transformations by appending the SVGTranform objects 
      // to the SVGTransformList associated with the element
      tfmList.appendItem(translate);
      tfmList.appendItem(rotate);
      tfmList.appendItem(scale);
    }
  ]]> </script>

  <polygon fill="orange" stroke="black" 
    stroke-width="5" 
    points="100,225 100,115 130,115 70,15 70,15 10,115 40,115 40,225"
    onclick="transformMe(evt)"/>
  ...
</svg>

This works, but I would like to have my JavaScript code separate from SVG element. According to this W3C document I should be able to have call a javascript function by refering to it using top scope. That is what I have done for the rectangle:

  <rect x="200" y="100" width="100" height="100" 
    fill="yellow" stroke="black" stroke-width="5"  
    onclick="top.transformMe(evt)"/>

However clicking on the rectangle gives the following error in console:

  Error: Permission denied to access property 'transformMe' @ http://fiddle.jshell.net/arasbm/Tyxea/14/show/:1

Can someone tell me how to solve this problem. The real question I have that is demonstrated in this example is: what is the proper way to handle events on SVG elements with JavaScript code that is outside those elements?

Aras
  • 5,878
  • 9
  • 49
  • 76

1 Answers1

1

The problem in the fiddle code is the way JSFiddle arranges your code.

First, the Javascript is evaluated in a function body and thus your method transformMe does not become a global function. Add

window.transformMe = transformMe 

at the end of your Javascript so that the function becomes a global.

Then again in the fiddle the code runs in an iframe (maybe your page is different) and "top" refers to the top document and in the case of jsfiddle.net you are thus trying to make a cross-domain JS call. You can see this if you run the fiddle with the developer tools turned on: the console gives the right hints.

Last but not least in the current browser implementations I don't believe you need the "top" reference at all. Instead you can simply call global functions (just tested it with IE, Chrome, and FF and it worked for me).

Sebastian
  • 7,729
  • 2
  • 37
  • 69
  • thanks for the quick reply. However, I think the issue is still present in your fiddle. Could you remove the script tag embeded in the SVG and use only the outside function. It still gives the same error. – Aras May 02 '13 at 06:38
  • @Aras I changed the fiddle (you could have done that, too, that's the idea of JSFiddle) and it still worked in all browsers I tested. – Sebastian May 03 '13 at 09:21
  • I did try to change the jsFiddle and test it but for some reason I was still getting the error, must have been a different issue. Sorry about that. Your solution works great. Thanks! – Aras May 04 '13 at 07:53