XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

SVG Tips and Tricks: Adobe's SVG Viewer

SVG Tips and Tricks: Adobe's SVG Viewer

July 03, 2002


Introduction

Since Adobe's SVG Viewer is the main SVG implementation, with 160 million deployed units and counting, I thought it would be a good idea to take a look at some special features that only the Adobe SVG Viewer offers to its users. Want to see what we can do with it? Grab a copy of version 3.0 of the viewer and we'll be off.

Using Adobe's Scripting Engine

With version 3.0, Adobe has added a significant feature to its SVG Viewer: a conformant JavaScript engine. Before version 3.0, when you were using the Adobe SVG Viewer within your Web page as viewed in Internet Explorer or Netscape Navigator, you were relying on the browser's scripting engine to evaluate and run your SVG scripting. Using Adobe's embedded scripting engine offers a few significant advantages. First and foremost it is a rock-solid, compliant implementation of the ECMA specification, and Adobe has used Mozilla's acclaimed SeaMonkey engine, opting for proven reliability. So, you can make sure that all your scripting code runs the same whether it's viewed on IE or Netscape, and whether on a Mac or a Windows box. IE and Netscape have diverging views and implementations for some of the core JavaScript functionalities (for example, the String.split() method), and they don't allow JavaScript communications between the browser and a plug-in in the same way. All of which results in cases where SVG authors had to do some browser-sniffing to serve either IE- or Netscape-specific script libraries.

Although the Adobe SVG Viewer 3.0 has its own scripting engine, you can still use your browser's engine if you want. You might actually want to author SVG content for use in a specific browser, which would allow you to take full advantage of the browser's engine. Also, the Adobe engine is not turned on by default, so existing content authored prior to version 3.0 will not break. Turning Adobe's scripting engine on is fairly easy and can be done in a clean way using an attribute in Adobe's namespace. This scripting-ready SVG template demonstrates the use of the Adobe scriptImplementation attribute:

<?xml version="1.0"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
 "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg  xmlns="http://www.w3.org/2000/svg"
      xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
      a3:scriptImplementation="Adobe">

  <script a3:scriptImplementation="Adobe" type="text/ecmascript">
    <![CDATA[

      // EcmaScript code

    ]]>
  </script>

  <!-- SVG contents -->

</svg>

Download this file.

   Related Reading
SVG Essentials

SVG Essentials
By J. David Eisenberg
Full Description
Index
Table of Contents

To use the browser scripting engine, omit all Adobe-specific declarations, or have the scriptImplementation attribute in the Adobe namespace set to either browser, Microsoft, or Netscape. Also, using the Adobe scripting engine will not prevent you from calling some scripts in the browser environment, since Adobe also offers a custom method, browserEval() located on its Window object, to do exactly this.

Customizing the Context Menu

Every time I talk about SVG in a conference, I give a few use cases. I never forget to mention SVG's capabilities as a UI rendering layer. People often relate their experiences hacking UI stuff with SVG, and they often say how nice it is. Sometimes, when creating an SVG-based UI, you want certain things to look exactly the same as they would in your system's own look and feel. Adobe allows you to change the contents of its contextual menu, rendered using native UI code, and you can do so by specifying an XML representation of its contextual menu. The default menu XML is:

<menu>

	<header>Adobe SVG Viewer</header>

	<item action="Open" id="Open">Open</item>
	<item action="OpenNew" id="OpenNew">Open in New Window</item>

	<separator/>

	<item action="ZoomIn" id="ZoomIn">Zoom In</item>
	<item action="ZoomOut" id="ZoomOut">Zoom Out</item>
	<item action="OriginalView" id="OriginalView">Original View</item>

	<separator/>

	<item action="Quality" id="Quality">Higher Quality</item>
	<item action="Pause" id="Pause">Pause</item>
	<item action="Mute" id="Mute">Mute</item>

	<separator/>

	<item action="Find" id="Find">Find...</item>
	<item action="FindAgain" id="FindAgain">Find Again</item>

	<separator/>

	<item action="Copy" id="Copy">Copy Selected Text</item>
	<item action="CopySVG" id="CopySVG">Copy SVG</item>
	<item action="ViewSVG" id="ViewSVG">View SVG</item>
	<item action="ViewSource" id="ViewSource">View Source</item>
	<item action="SaveAs" id="SaveAs">Save SVG As...</item>

	<separator/>

	<item action="Help" id="Help">Help</item>
	<item action="About" id="About">About Adobe SVG Viewer...</item>

</menu>			

Download this file.

Like any other XML fragment loaded in the Adobe SVG Viewer, you can script this using the standard XML DOM interfaces. The contextual menu XML representation is actually another DOM Document instance, and Adobe has an accessor field, contextMenu, for it on its Window object. Once you access the contextMenu you can modify the contextual menu any way you want, using the standard DOM scripting methods. As you can see, <item> elements can have an action attribute that specifies the built-in Adobe Viewer function it should fire upon user activation. If built-in functions don't suffice, you can use the onactivate attribute to call a custom-made JavaScript function. Further menu customization also includes submenus with nested <menu> elements. For more information, browse the SVG Wiki, especially its contextual menu page.

Server Connections

One thing that the Flash Player prides itself on is server-connection facilities, which enable Flash developers to open XML sockets to load external data sources. But no SVG or DOM recommendations from the W3C specify any kind of load-and-save mechanisms. The DOM Level 3 Load and Save Working Draft aims to do just that. Adobe has actually anticipated a little bit, offering SVG content creators the means to do what the Flash Player can do, and a little more.

The relevant methods are getURL() and postURL(), both defined on the Window object. These two methods allow you to retrieve data from, or post data to, a URL. Both getURL() and postURL() require a callback method to be passed as a parameter. The callback method is automatically passed to an AsyncURLStatus object, which gives some information on the status of the request and the data you received. Let's see how we can call for data from a remote URL:

function loadFile (fileName) {
	getURL(fileName, fileLoaded);
}
		
function fileLoaded (data) {
	var msg = '';
	if(data.success) {
		msg = data.content;
	} else {
		msg = 'Loading has failed';
	}
	alert(msg);
}

The Adobe implementation handles data reception quite nicely. It will take care of any necessary encoding and compression. If you want to receive gzipped XML or SVG data, the viewer will decompress it before sending it back to you. The same goes for ASCII and UTF-8 or UTF-16 encodings. You won't be able to pass any URL outside of your SVG's document-originating server for security reasons. To see a nice usage of these two methods, check out Kevin Lindsey's implementation of a loading progress bar; it should give you a fair idea of how to integrate it within your own applications. I have come up with a quick and dirty example myself: a minimal object inspector and hide mechanism. Also, taking our previous discussions on customizing the contextual menu further, you could use getURL() to load a context-menu, XML-description file straight from a server rather than build one on the client with some perhaps clumsy DOM code. One last notable point: the SVG Working Group has received strong feedback from the SVG community to make these methods available in a W3C standard. The Group is looking into that and SVG 1.2 looks like a great candidate to have those two methods defined (probably as convenient shorthands for DOM Level 3 Load and Save methods).

Also in Sacré SVG

Big Lists in Small Spaces

SVG At the Movies

Mobile SVG

SVG and Typography: Animation

Going Mobile With SVG: Standards

Simplified XML Parsing and Serialization

Since it is only strings that can be sent or received with the methods above, you might well face two problems. If you receive SVG content from the server, and you want to append it to your existing SVG tree, you'll need a Document Fragment rather than a plain string. Or maybe you're sending SVG code generated on the client to the server so it can be archived in a database, in which case you will have to convert your Document Fragment into a string.

Rather than using getURL() or postURL(), you can use parseXML() and printNode(). These are exactly what you will need for your XML parsing and serialization needs. printNode() takes a node as a parameter and returns a formatted string with the XML data. printNode() will most likely throw out some empty text nodes and normalize contiguous text nodes. For example,

function printContextualMenu () {
	var string = printNode(contextMenu);
	alert(string);
}

The inverse operation, parsing, is done in a simple way, too. The parseXML() method takes two parameters. The first one is the string you want to have returned as a Document Fragment. The second argument, which is optional, specifies the context document used for parsing. If you don't care to provide a context, a new document will be created. If you want to parse SVG in order to append it to an existing SVG DOM tree, you will want to parse your string in the document, another field in the helpful Window object that refers to your existing SVG document. Here's how you would parse a string with SVG content and then append your new graphics to the document:

function parseAndAddData (string) {
	var node = parseXML(string, document);
	document.documentElement.appendChild(node);
}

Again, the SVG Working Group has received many requests to include these two handy methods in an upcoming SVG recommendation. Similar to the getURL() and postURL() methods, there's a good chance you will see these two appear in SVG 1.2 as convenience shorthands to DOM Level 3 Load and Save methods.

Wrapping It All Up

You should now know how to get the best out of the most widely deployed SVG implementation out there. If you want to know more, look at the set of pages devoted to ASV3 on the SVG Wiki, which is maintained by Niklas Gustavsson. Think of Adobe's work as an anticipation of what's next with SVG. And don't hesitate to voice your concerns to the W3C or to Adobe.