SVG Tiny 1.2 - 20050413

15 Scripting

Contents

15.1 Specifying the scripting language

15.1.1 Specifying the default scripting language

The 'contentScriptType' attribute on the 'svg' element specifies the default scripting language for the given document fragment.

15.1.2 Local declaration of a scripting language

It is also possible to specify the scripting language for each individual 'script' or 'handler' elements by specifying a type attribute on the 'script'/'handler' elements.

15.2 The 'script' element

A script element may either contain or point to executable content (e.g., ECMAScript or Java JAR file). Executable content can come either in the form of a script (textual code) or in the form of compiled code. If the code is textual, it can either be placed inline in the script element (as character data) or as an external resource, referenced through xlink:href attribute. Compiled code must be an external resource.

Scripting languages (such as ECMAScript) that have a notion of a "global scope" or a "global object" must have a single global object associated with the document (unique for each DOM Document node). This object is shared by all elements. Thus, an ECMAScript function defined within any script is in the "global" scope of the entire document in which the script occured. The global object must have all the methods and attributes from the SVGGlobal interface. It can be obtained from an SVG document through the SVGDocument::global attribute. Event listeners attached through event attributes and handler elements are also evaluated using the global scope of the document in which such a listener is defined.

For compiled languages (such as Java) that don't have a notion of "global scope", each script element, in effect, provides a separate scope object per script element. This scope object performs an initialization and serves as event listener factory for the handler element.

Script execution happens only at load time. Removing, inserting or altering script elements once the document has been loaded has no effect.

Exact details on how this element works depend on the executable content's type (either the resource MIME type or specified as an attribute). SVG does not require the support of any particular scripting language. However, SVG defines the behavior for two specific script types in the case where an implementation supports the type:

application/ecmascript

This type of executable content must be source code for the ECMAScript programming language (either of ECMA-262 3rd Edition, ECMA-327, or ECMA-357). This code is executed in the context of this element's owner document's global scope as explained above.

Also, the script global object must implement the EventListenerInitializer2 interface by providing an initializeEventListeners function that is called for every script element in the document and a createEventListener function that is called for every handler element that has a script content type of "application/ecmascript".

SVG implementations that load external resources through protocols such as HTTP that support content coding must accept external script files that have been encoded using gzip compression (flagged using "Content-Encoding: gzip" for HTTP).

application/java-archive

This type of executable content must be an external resource that contains a Java JAR. The manifest file in the JAR archive must have an entry named SVG-Handler-Class. The entry's value must be a fully-qualified Java class name for a class contained in this archive. The user agent must instantiate the class from the JAR file and cast it to the EventListenerInitializer2 interface. Then the initializeEventListeners method must be called with the script element itself as a parameter. If a class listed in SVG-Handler-Class do not implement EventListenerInitializer2, it is an error.

Note that the user agent may reuse classes loaded from the same URL, so the code must not assume that every script element or every document will create its own separate class object. Thus, one cannot assume, for instance, that static fields in the class are private to a document.

Implementations may also accept the script type "text/ecmascript" for backwards compatibility with SVG 1.1. However, this type is deprecated and should not be used by content authors.

Other language bindings are encouraged to adopt a similar approach to either of the two described above.

Example 18_01 defines a function circle_click which is called when the 'circle' element is being clicked. The drawing below on the left is the initial image. The drawing below on the right shows the result after clicking on the circle. The example uses the 'handler' element which is described further down in this chapter.

Note that this example demonstrates the use of the 'click' event for explanatory purposes. The example presupposes the presence of an input device with the same behavioral characteristics as a mouse, which will not always be the case. To support the widest range of users, the 'activate' event attribute should be used instead of the 'click' event attribute.

Example: 18_01.svg
<?xml version="1.0" standalone="no"?>
<svg width="6cm" height="5cm" viewBox="0 0 600 500"
     xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny"
     xmlns:ev="http://www.w3.org/2001/xml-events">
  <desc>Example: invoke an ECMAScript function from an click 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.getFloatTrait("r");
      if (currentRadius == 100)
        circle.setFloatTrait("r", currentRadius*2);
      else
        circle.setFloatTrait("r", currentRadius*0.5);
    }
  ]]> </script>
  
  <!-- Outline the drawing area with a blue line -->
  <rect x="1" y="1" width="598" height="498" fill="none" stroke="blue"/>
  <!-- Act on each click event -->
  <circle onclick="circle_click(evt)" cx="300" cy="225" r="100" fill="red">
  <handler type="application/ecmascript" ev:event="click"> 
        circle_click(evt);
    </handler>
  </circle>  
  
  <text x="300" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on circle to change its size
  </text>
</svg>
    
Example 18_01 - invoke an ECMAScript function from an onclick event - before first click Example 18_01 - invoke an ECMAScript function from an onclick event - after first click
Schema: script
  <define name='script'>
    <element name='script'>
      <ref name='script.AT'/>
      <ref name='script.CM'/>
    </element>
  </define>

  <define name='script.AT' combine='interleave'>
    <ref name='svg.CorePreserve.attr'/>
    <ref name='svg.External.attr'/>
    <ref name='svg.ContentType.attr'/>
  </define>

  <define name='script.CM'>
    <choice>
      <group>
        <ref name='svg.XLinkRequired.attr'/>
      </group>
      <text/>
    </choice>
  </define>
    

Attribute definitions:

type = "content-type"
Identifies the scripting language for the given 'script' element. The value content-type specifies a media type, per [RFC2045]. If a 'type' is not provided, the value of 'contentScriptType' on the 'svg' element shall be used.

Animatable: no.


15.3 XML Events

XML Events is an XML syntax for integrating event listeners and handlers with DOM 2 or DOM 3 Event interfaces. Declarative event handling in SVG 1.1 was hardwired into the language, in that the developer was required to embed the event handler in the element syntax (e.g. an element has an onclick attribute). SVG Tiny does not support the event attributes (onload, onclick, onactivate, etc.). Instead SVG Tiny uses XML Events to provide the ability to listen to custom events, as well as specifying the event listener separately from the graphical content.

SVG Tiny 1.2 makes the following modifications to XML Events:

  1. Namespaced events: As SVG 1.2 supports DOM Level 3 Events, which are namespaced, XML Events in SVG 1.2 must allow namespaced events.
  2. IRIREFs instead of IDREFs: the observer and target attributes from XML Events are currently IDREFs. Since SVG 1.2 requires a declarative syntax for event handling in more than one document, it uses IRIREFs for those attributes, with the following restriction: only documents that are declaratively referenced as part of the current document, via the 'use' and 'animation' elements, can be referred to. Referring to any other arbitrary external document is an error.
  3. No capture phase: SVG Tiny does not have an event capture phase, only a bubble phase.

The list of events supported by SVG Tiny 1.2 is given in the Interactivity chapter.

The following is an example of an SVG file using XML Events:

Example: handler.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny"
     xmlns:ev="http://www.w3.org/2001/xml-events">
     
  <desc>An example of the handler element.</desc>

  <rect id="myRect" x="10" y="20" width="200" height="300"
        fill="red"/>

  <!-- register a listener for a myRect.click event -->
  <ev:listener ev:event="click" ev:observer="myRect"
               ev:handler="#myClickHandler" />

  <handler id="myClickHandler" type="application/ecmascript">
    var myRect = document.getElementById("myRect");
    var width = myRect.getFloatTrait("width"));
    myRect.setFloatTrait("width", (width+10));
  </handler>

</svg>
    

In the above example, the ev:listener element registers that the myClickHandler element should be invoked whenever a "click" event happens on "myRect".

The combination of the XML Events syntax and the new handler element allows event handling to be more easily processed in a compiled language. Below is an example of an event handler using the Java language:

Example: javahandler.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny"
     xmlns:ev="http://www.w3.org/2001/xml-events"
     xmlns:foo="http://www.example.com/foo">
     
  <desc>Example of a Java handler</desc>

  <rect id="myRect" x="10" y="20" width="200" height="300"
        fill="red"/>

  <!-- reference a jar containing an EventListenerInitializer2 object -->
  <script type="application/java-archive" id="init" xlink:href="http://example.com/myJar.jar"/>
  
  <!-- register a listener for a myRect.click event -->
  <ev:listener ev:event="click" ev:observer="myRect"
                      ev:handler="#myClickHandler" />

  <handler id="myClickHandler" type="application/java-archive" xlink:href="#init" foo:offset="10"/>      

</svg>
    

In this case, the 'handler' element specifies a reference to the script element that specificies the location of compiled code that conforms to the EventListenerInitializer2 interface. The user agent invokes the createEventListener method within the targeted interface.

In this case, the MyEventListenerInitializer2 referenced by the SVG-Handler-Class entry of the myJar.jar manifest has the following definition:

MyEventListenerInitializer2
package com.example;

import org.w3c.svg.EventListenerInitializer2;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;

public class MyEventListenerInitializer2 implements EventListenerInitializer2 {

   Document document;

    public void initializeEventListeners(Element scriptElement) {
        document = scriptElement.getOwnerDocument();
    }

    public EventListener createEventListener(final Element handlerElement) {
        return new EventListener() {
            public void handleEvent(Event event) {
                Element myRect = document.getElementById("myRect");
                float width = Float.parseFloat(myRect.getAttribute("width"));
                float offest = Float.parseFloat(handlerElement.getAttributeNS("http://www.example.com/foo", "offset");
                myRect.setAttribute(width, "" + (width + 10));
            }
        };
    }
}

The EventListenerInitializer2 interface is currently defined in the SVG package/namespace. Future specifications may move this package.

15.4 The handler element

The 'handler' element is similar to the script element: its contents, either included inline or referenced, are code that is to be executed by the scripting engine(s) used by user agent.

However, where the script element evaluates its contents when the document is loaded, the 'handler' element evaluates its contents in response to an event. This means that SVGT1.2 use 'handler' to get the equivalent functionality as the SVG Full event attributes.

For example, consider the following SVG 1.1 document:

Example: SVG 1.1 scripting
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">

<rect id="myRect" x="10" y="20" width="200" height="300" fill="red"

onclick="var width = parseFloat(

document.getElementById('myRect').getAttribute('width'));

document.setAttribute('myRect', 'width', (width+10));"/>

</svg>

The above example should be rewritten to use the 'handler' element and XML Events (described below) as shown:

Example: handler2.svg
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.2"
     xmlns:ev="http://www.w3.org/2001/xml-events">
  <desc>handler element example</desc>
  <rect id="myRect" x="10" y="20" width="200" height="300" fill="red">

    <handler type="application/ecmascript" ev:event="click">
        var myRect = evt.target;
        var width = myRect.getFloatTrait("width"));
        myRect.setFloatTrait("width", (width+10));
    </handler>

  </rect>

</svg> 
    

In ECMAScript, the contents of the 'handler' element behave as if they are the contents of a new function object, created as shown:

function(evt) {

//contents of handler

}

Other interpreted languages should behave in a similar manner.

The 'evt' parameter shown above is an Event object corresponding to the event that has triggered the handler.

Schema: handler
  <define name='handler'>
    <element name='handler'>
      <ref name='handler.AT'/>
      <ref name='handler.CM'/>
    </element>
  </define>

  <define name='handler.AT' combine='interleave'>
    <ref name='svg.CorePreserve.attr'/>
    <ref name='svg.External.attr'/>
    <attribute name='ev:event' svg:animatable='false' svg:inheritable='false'>
      <ref name='XSLT-QName.datatype'/>
    </attribute>
    <ref name='svg.ContentType.attr'/>
  </define>

  <define name='handler.CM'>
    <choice>
      <group>
        <ref name='svg.XLinkRequired.attr'/>
      </group>
      <text/>
    </choice>
  </define>
    

Attribute definitions:

type = "content-type"
Identifies the language used for the handler element. The value specifies a media type, per RFC2045. If a 'type' is not provided, the value of 'contentScriptType' on the 'svg' element shall be used.

Animatable: no.
xlink:href = "<iri>"
If this attribute is present, then the script content of the handler element should be loaded from this resource.

Animatable: no.
ev:event = "<string>"
The name of the event to handle. See event list for a list of all supported events.

Animatable: no.

For compiled languages, the xlink:href attribute must reference a script element that itself reference a jar file with a manifest with an SVG-Handler-Class entry pointing to an EventListenerInitializer2 implementation.

15.4.1 Parameters to handler elements

In many situations, the script author uses the 'handler' as a template for calling other functions, using the content of the 'handler' element to pass parameters. However, for compiled languages the 'handler' element does not have any executable content.

In this case, the author should embed the parameters into the 'handler' as custom content. The execution of the 'handler' code retrieves the contents of the parameters using the DOM.

Below is an example of using parameters on the 'handler' element:

Example: handlerparam.svg
<svg xmlns="http://www.w3.org/2000/svg" version="1.2"
     xmlns:ev="http://www.w3.org/2001/xml-events"
     xmlns:foo="http://www.example.com/foo">
  <desc>An example of parameters on the handler element.</desc>

  <rect id="myRect" x="10" y="20" width="200" height="300"
        fill="red"/>               

  <!-- reference a jar containing an EventListenerInitializer2 object -->
  <script type="application/java-archive" id="init" xlink:href="http://example.com/myJar.jar"/>

  <!-- register a listener for a myRect.click event -->
  <ev:listener ev:event="click" ev:observer="myRect"
               ev:handler="#myClickHandler" />

  <handler id="myClickHandler" type="application/java-archive"
           xlink:href="#init">
      <foo:offset value="10"/>
      <foo:person>
         <foo:name>Victor Vector</foo:name>
         <foo:age>42</foo:age>
      </foo:person>
  </handler>

</svg>
    

In this case, the object referenced by the SVG-Handler-Class entry of the myJar.jar manifest has its createEventListener method called and the returning EventListener registered. Whenever a 'click' event on the 'myRect' object is observed, the handleEvent method of the listener is called. The object can then retrieve the children of the 'handler' element in order to obtain the contents of the elements from the "foo" namespace.

15.5 Event handling

Events can cause scripts to execute when either of the following has occurred:

Related sections of the spec:

15.6 Script Module

The Script Module contains the following element:

15.7 Handler Module

The Handler Module contains the following element: