| <?xml version="1.0"?> |
| |
| <!-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| --> |
| |
| <!-- ========================================================================= --> |
| <!-- author cjolif@ilog.fr --> |
| <!-- version $Id: scriptIntro.xml 201374 2004-08-18 07:17:26Z vhardy $ --> |
| <!-- ========================================================================= --> |
| |
| <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd"> |
| <document> |
| <header> |
| <title>Scripting with ECMAScript</title> |
| </header> |
| |
| <body> |
| <p> |
| This page is a brief introduction to scripting SVG documents with |
| ECMAScript, and how Batik’s ECMAScript environment can be extended. |
| </p> |
| |
| <section id="scriptingBasics"> |
| <title>Scripting basics</title> |
| <p> |
| As the ECMAScript language (the standardised version of JavaScript) |
| is one of the most popular scripting languages, and as the SVG |
| specification states that an SVG conforming implementation must |
| support it, SVG documents processed by Batik support scripting |
| with ECMAScript using Mozilla’s ECMAScript interpreter, |
| <a href="http://www.mozilla.org/rhino/">Rhino</a>. |
| </p> |
| <p> |
| There are two places in an SVG file where you can put scripts. |
| </p> |
| <p> |
| The first one is in the <code>script</code> |
| element, where you can place any code, including function |
| definitions, to be executed just before the document |
| <code>SVGLoad</code> event is fired. |
| </p> |
| <source><![CDATA[<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"> |
| <script type="text/ecmascript"> |
| // ECMAScript code to be executed |
| </script> |
| |
| <!-- Remainder of the document... --> |
| </svg>]]></source> |
| <p> |
| You can also attach script to respond to user or document |
| events using attributes on SVG elements. As shown in the |
| previous example, the scripting language must be set on |
| the <code>script</code> element. However, for event handling |
| the default language type <code>text/ecmascript</code> |
| is assumed. If you want to change it you can use |
| the <code>contentScriptType</code> attribute on the |
| <code>svg</code> element. |
| </p> |
| <p> |
| The event attribute can contain any script code to execute when the |
| event reaches the element (as described by the |
| <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow">DOM event flow</a>) |
| in either the bubbling or at-target phases. The following example |
| will change the <code>rect</code> to be filled in blue when it is |
| clicked. |
| </p> |
| <source><![CDATA[<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"> |
| <rect x="0" y="0" width="10" height="10" |
| onclick="evt.target.setAttribute('fill', 'blue')"/> |
| </svg>]]></source> |
| <p> |
| Note that inside the event attribute script, there is a variable |
| called <code>evt</code> that is a reference to the |
| <a class="class" href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event">Event</a> |
| object that represents the event that is being handled. |
| </p> |
| <p> |
| For more information on using scripting in SVG you can have a look at: |
| </p> |
| <ul> |
| <li> |
| the <a href="http://www.w3.org/TR/SVG11/script.html">scripting |
| chapter of the SVG specification</a>, for advanced information on |
| scripting in SVG, and |
| </li> |
| <li> |
| the <a href="http://www.ecma.ch/ecma1/stand/ecma-262.htm">ECMAScript |
| specification</a>, for advanced information on the ECMAScript |
| language. |
| </li> |
| </ul> |
| </section> |
| |
| <section id="rhinoFeatures"> |
| <title>Using Rhino features</title> |
| |
| <p> |
| Rhino has a number of features beyond those supported by standard |
| ECMAScript interpreters, and these can be used with Batik. One |
| useful feature is that ECMAScript code can use Java classes and |
| objects, and not just the standard ECMAScript primitive types and |
| host objects exposed by Batik. |
| </p> |
| <p> |
| To create an instance of a Java class from ECMAScript, you first need |
| to import the package in which it resides. This is done using the |
| <code>importPackage</code> global function that Rhino provides. |
| For example, to import the <code>javax.swing.JFrame</code> class, |
| you use: |
| </p> |
| <source>importPackage(Packages.javax.swing);</source> |
| <p> |
| This then exposes a global property for each class in the |
| <code>javax.swing</code> package that you can use to create a new |
| object of this class, similar to a <code>import javax.swing.*;</code> |
| statement in Java. We can use the exposed <code>JFrame</code> |
| property to create a new instance of this class: |
| </p> |
| <source>var frame = new JFrame("My test frame");</source> |
| <p> |
| Note how an ECMAScript string value is passed as the parameter to |
| <code>JFrame</code>’s constructor. Rhino will attempt to convert |
| ECMAScript values into appropriate Java primitive types or objects |
| to make underlying constructor or method calls. In this instance, |
| the ECMAScript string value is converted into a |
| <code>java.lang.String</code> object to be passed to the constructor. |
| </p> |
| <p> |
| Now that we have a reference to this Java object, we can call any |
| method on it as we usually would from Java code. The following |
| complete example demonstrates this, where clicking the green |
| circle will pop up a frame: |
| </p> |
| <source><![CDATA[<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"> |
| <circle cx="50" cy="50" r="50" fill="green" onclick="showFrame()"/> |
| <script type="text/ecmascript"> |
| importPackage(Packages.javax.swing); |
| |
| function showFrame() { |
| var frame = new JFrame("My test frame"); |
| var label = new JLabel("Hello from Java objects created in ECMAScript!"); |
| label.setHorizontalAlignment(SwingConstants.CENTER); |
| frame.getContentPane().add(label); |
| frame.setSize(400, 100); |
| frame.setVisible(true); |
| frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); |
| } |
| </script> |
| </svg>]]></source> |
| |
| <p> |
| For more information on scripting Java classes from ECMAScript code, |
| see Rhino's |
| <a href="http://www.mozilla.org/rhino/ScriptingJava.html">Scripting |
| Java</a> document. |
| </p> |
| </section> |
| |
| <section id="customizingRhino"> |
| <title>Customizing the Rhino interpreter</title> |
| |
| <p> |
| A useful example of customization of the Rhino interpreter comes from |
| the fact that the ECMAScript specification doesn’t provide any |
| predefined I/O facilities to interact with the console. However, it is |
| very common for ECMAScript compatible languages to provide a function |
| named <code>print</code> to output messages to the console. We will |
| describe here an example of cutomization of the Batik Rhino |
| interpreter to add such functionality to it. |
| </p> |
| <p> |
| You should first subclass the default Batik ECMAScript interpreter to |
| add the functionality to it as below. |
| </p> |
| <source>import org.apache.batik.script.rhino.RhinoInterpreter; |
| |
| import java.net.URL; |
| |
| import org.mozilla.javascript.Context; |
| import org.mozilla.javascript.Function; |
| import org.mozilla.javascript.Scriptable; |
| import org.mozilla.javascript.ScriptableObject; |
| import org.mozilla.javascript.PropertyException; |
| |
| public class ExtendedRhinoInterpreter extends RhinoInterpreter { |
| |
| public ExtendedRhinoInterpreter(URL documentURL) { |
| super(documentURL); |
| |
| // Array of functions to put in the global object. |
| final String[] names = { "print" } |
| try { |
| // Add the functions to the global object. |
| getGlobalObject().defineFunctionProperties |
| (names, ExtendedRhinoInterpreter.class, |
| ScriptableObject.DONTENUM); |
| } catch (PropertyException e) { |
| throw new Error(e); |
| } |
| } |
| |
| public static void print(Context cx, Scriptable thisObj, |
| Object[] args, Function funObj) { |
| for (int i = 0; i < args.length; i++) { |
| if (i > 0) { |
| System.out.print(" "); |
| } |
| |
| // Convert the ECMAScript value into a string form. |
| String s = Context.toString(args[i]); |
| System.out.print(s); |
| } |
| System.out.println(); |
| } |
| }</source> |
| <p> |
| Now, you need to tell to Batik to use this interpreter instead of the |
| default one. For that, you must first define a factory to create |
| instances of your interpreter. |
| </p> |
| <source>import org.apache.batik.script.Interpreter; |
| import org.apache.batik.script.rhino.RhinoInterpreterFactory; |
| |
| public class ExtendedRhinoInterpreterFactory extends RhinoInterpreterFactory { |
| |
| public Interpreter createInterpreter(URL documentURL, boolean isSVG12) { |
| return new ExtendedRhinoInterpreter(documentURL); |
| } |
| }</source> |
| <p> |
| Then, you must build an |
| <a class="class" href="../../javadoc/org/apache/batik/script/InterpreterPool.html">IntepreterPool</a> |
| that will use this factory, and then set the pool on the |
| <a class="class" href="../../javadoc/org/apache/batik/bridge/BridgeContext.html">BridgeContext</a> |
| of your application. |
| </p> |
| <source>org.apache.batik.bridge.BridgeContext ctx = ...; |
| org.apache.batik.script.InterpreterPool pool = |
| new org.apache.batik.script.InterpreterPool(); |
| InterpreterFactory f = new ExtendedRhinoInterpreterFactory(); |
| |
| // Register the interpreter factory for all four MIME types that |
| // Batik normally supports for ECMAScript. |
| pool.putInterpreterFactory("text/ecmascript", f); |
| pool.putInterpreterFactory("text/javascript", f); |
| pool.putInterpreterFactory("application/ecmascript", f); |
| pool.putInterpreterFactory("application/javascript", f); |
| ctx.setIntepreterPool(pool);</source> |
| <p> |
| For example if you are using the Batik SVG browser application you |
| should be able to use the previous piece of code on a subclass of the |
| <a class="class" href="../../javadoc/org/apache/batik/swing/JSVGCanvas.html">JSVGCanvas</a> |
| class in the <code>createBridgeContext()</code> method. |
| </p> |
| <p> |
| For further information on working with Rhino, consult the |
| <a href="http://www.mozilla.org/rhino/">Rhino website</a>. |
| </p> |
| </section> |
| </body> |
| </document> |