0

I am creating a stand alone svg. With javascript embedded. I have difficulties accessing the root element "svg". It's easy enough when it's embedded in a HTML page (getElementById), but is it possible to do as standalone?

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id ="testsvg"  width="1000" height="500" viewBox="0 0 1000 500"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example script01 - invoke an ECMAScript function from an onclick event
  </desc>
  <!-- ECMAScript to change the radius with each click -->
  <script type="application/ecmascript"> <![CDATA[
    function circle_click(evt) {
      var circle = evt.target;
      var currentRadius = circle.getAttribute("r");
      if (currentRadius == 100)
        circle.setAttribute("r", currentRadius*2);
      else
        circle.setAttribute("r", currentRadius*0.5);
    }
	
	function make_shape(evt) {
	   
		var svg =                          // <-------------  WHAT TO USE?
		console.log(svg);
		shape = svg.createElement("circle");
		shape.setAttribute("cx", 25);
		shape.setAttribute("cy", 25);
		shape.setAttribute("r",  20);
		shape.setAttribute("style", "fill: green");
		svg.appendChild(shape);
	}
    
  ]]> </script>

  <!-- Outline the drawing area with a blue line -->
  <rect x="1" y="1" width="900" height="498" fill="none" stroke="blue"/>

  <!-- Act on each click event -->
  <circle onclick="circle_click(evt)" cx="300" cy="225" r="50"
          fill="red"/>
	  <!-- Act on each click event -->
  <circle onclick="make_shape(evt)" cx="500" cy="225" r="50"
          fill="yellow"/>	  
  
  <text x="500" y="380" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on red circle to change its size.
  </text> 
  <text x="500" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on yellow circle to add a circle
  </text>
  
</svg>

1
  • Just select your root using document.querySelector('svg'), as regardless of whether it's a document, when viewed in the browser it will be hosted inside a document, even if you don't specify one. Commented Apr 18, 2018 at 15:50

2 Answers 2

1

When your SVG element is displayed as the main document in your browser, it is actually an element of a generated document, so you can simply use techniques already familiar from javascript:

var svg = document.querySelector('svg')

Since the SVG is not a document, you cannot use it to create elements, but you can use the document itself to create new shapes:

var shape = document.createElementNS('http://www.w3.org/2000/svg', 'circle');

And then you can append them to your new-found svg element. I have amended your code for clarity. If this is not working, what exactly are you using to display these SVGs? Since if they have support for 'ecmascript' (aka javascript), they must also support at least the functionality described in the spec.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id ="testsvg"  width="1000" height="500" viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>
    Example script01 - invoke an ECMAScript function from an onclick event
  </desc>
  
  <!-- ECMAScript to change the radius with each click -->
  <script type="text/javascript">
    function circle_click( evt ){
    
      var circle = evt.target;
      var currentRadius = circle.getAttribute("r");
      
      if( currentRadius == 100 ){
      
        circle.setAttribute("r", currentRadius*2);
      
      } else {
      
        circle.setAttribute("r", currentRadius*0.5);
      
      }
      
    }
    
    function make_shape( evt ){
	  
      var svg = document.querySelector('svg');
      var shape = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
      
      shape.setAttribute("cx", 25);
      shape.setAttribute("cy", 25);
      shape.setAttribute("r",  20);
      shape.setAttribute("style", "fill: green");
      
      svg.appendChild( shape );
      
    }
    
  </script>

  <!-- Outline the drawing area with a blue line -->
  <rect x="1" y="1" width="900" height="498" fill="none" stroke="blue"/>

  <!-- Act on each click event -->
  <circle onclick="circle_click(evt)" cx="300" cy="225" r="50" fill="red"/>
  <!-- Act on each click event -->
  <circle onclick="make_shape(evt)" cx="500" cy="225" r="50" fill="yellow"/>	  
  
  <text x="500" y="380" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on red circle to change its size.
  </text> 
  <text x="500" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on yellow circle to add a circle
  </text>
  
</svg>

Sign up to request clarification or add additional context in comments.

Comments

1

The DOM API still works just fine, so you can use document.querySelector('svg'). I assume you could assign a class or id to the svg if you need to select it in another way. The selected svg, however, is still just an element, so rather than svg.createElement(), you'll need document.createElement(). If you do that, the code should work, but nothing will display. This, I've just learned, is because svg elements must be created with document.createElementNS(), which takes two arguments: the xmlns, and the type of element you want to create: document.createElementNS("http://www.w3.org/2000/svg", "circle").

<?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
      "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg id ="testsvg"  width="1000" height="500" viewBox="0 0 1000 500"
         xmlns="http://www.w3.org/2000/svg" version="1.1">
      <desc>Example script01 - invoke an ECMAScript function from an onclick event
      </desc>
      <!-- ECMAScript to change the radius with each click -->
      <script type="application/ecmascript"> <![CDATA[
        function circle_click(evt) {
          var circle = evt.target;
          var currentRadius = circle.getAttribute("r");
          if (currentRadius == 100)
            circle.setAttribute("r", currentRadius*2);
          else
            circle.setAttribute("r", currentRadius*0.5);
        }
        
        function make_shape(evt) {
           
            var svg =     document.querySelector('svg');                    
            
            shape = document.createElementNS( "http://www.w3.org/2000/svg", "circle");
            shape.setAttribute("cx", 25);
            shape.setAttribute("cy", 25);
            shape.setAttribute("r",  20);
            shape.setAttribute("fill", "green");
            svg.appendChild(shape);
        }
        
      ]]> </script>

      <!-- Outline the drawing area with a blue line -->
      <rect x="1" y="1" width="900" height="498" fill="none" stroke="blue"/>

      <!-- Act on each click event -->
      <circle onclick="circle_click(evt)" cx="300" cy="225" r="50"
              fill="red"/>
          <!-- Act on each click event -->
      <circle onclick="make_shape(evt)" cx="500" cy="225" r="50"
              fill="yellow"/>     
      
      <text x="500" y="380" font-family="Verdana" font-size="35" text-anchor="middle">
        Click on red circle to change its size.
      </text> 
      <text x="500" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
        Click on yellow circle to add a circle
      </text>
      
    </svg>

2 Comments

both answers are excellent, and provide a lot of insight. I chose the "first" one. Thanks!
np. I didn't realize the question had been answered by the time I figured out .createElementNS. Glad we could help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.