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

advertisement

Extending SVG for XForms

Extending SVG for XForms

May 22, 2002

Introduction

If you've read my previous columns, it should be clear that SVG provides what programmers and designers need to create interactive 2D graphics. What makes SVG a little special is the versatility it inherits from XML. XML vocabularies are meant to be extended and intermixed with one another. But despite some noteworthy efforts to create XML-aware browsers, like XSmiles, Amaya, and Mozilla, rock-solid SVG-centric browser applications are not quite ready. But it may be possible to start implementing XForms UI controls in SVG.

In previous columns we looked at SVG DOM in simple drag and drop or event handling and remote animation control. This month we're going to implement the XForms <button> element with CSS support, which will serve as an applied study on extending SVG's semantics with foreign elements and attributes.

The Task at Hand

Our task has three parts: parsing, instantiating objects, and interacting with them. Parsing is the part where we are going to look up XForms content in our document and try to make some sense of it. We will then use the gathered information to build an internal EcmaScript object model and draw the form controls. Interaction is the part where we use event handlers to create the different states of the button and allow for callbacks to be registered when it is pressed. This month, we'll take care of the XForms <button> element alone, concentrating on the process of integrating a new namespace with SVG; we'll look at the the interactivity and object modeling next month. So our first task is to read an SVG+XForms document and draw a static button. Consider this simple document:

<?xml version="1.0"?>
<svg  xmlns="http://www.w3.org/2000/svg"
      xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
      xmlns:forms="http://www.w3.org/2002/01/forms"
      a3:scriptImplementation="Adobe"
      xml:space="preserve"
      onload="XForms.init(evt)">

  <title>Simple implementation of the XForms <button> element</title>
  <script a3:scriptImplementation="Adobe" type="text/ecmascript"
          xlink:href="XFormsButton.es" />

  <g transform="translate(50,50)">
    <forms:button style=" color: blue;
                          border-color: red;
                          border-width: 1px;
                          background-color: pink;">
      <forms:caption>This is a test</forms:caption>
    </forms:button>
  </g>

</svg>
      

View this example as (static) SVG


O'Reilly Open Source Convention
Antoine Quint will give 2 presentations at the upcoming O'Reilly Open Source Convention, this July 22-26, in San Diego.

In addition to the Adobe-specific attributes, you'll notice the declaration of the XForms namespace on the <svg> element and the <forms:button> element in that namespace. You will also notice the use of CSS properties straight out of the CSS 2 Box Model. These are all things that we will need to parse to draw a pink button.

Parsing XForms elements with the DOM

To get started, we have to navigate through the XML tree looking for <forms:button> elements, which hold the data we need. The fact that these elements are described in a separate namespace make this easy. In fact, getting a data structure (here, a NodeList) holding all the buttons is done in a single line of code:

var buttonElements = root.getElementsByTagNameNS(XForms.ns, 'button');
      

If you look at the small EcmaScript library I've built, you'll see that I've referenced the XForms namespace in an object, so it is easy to reference. This line of code was taken from the Button.init() function, called by the XForms.init() that we call when loading the SVG document is done. The rest of this function will recurse through all the nodes in our NodeList and call further initialization code on each element:

for (var i=0; i<buttonElements.length; i++) {
  var elem = buttonElements.item(i);
  var button = new Button(elem);
  button._draw();
}
      

   Related Reading
SVG Essentials

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

We have built a custom Button EcmaScript object that can be constructed with a pointer to a <forms:button> element as an argument. Looking at that object we can see it has the following methods defined: generateSVGStyle() and generateSVG(). Both these methods will be called from Button._draw(), which renders the button as SVG.

In order to parse XML with the DOM we read the caption's text from the <forms:caption> element. Text in XML is a bit tricky to handle. We have something called text nodes, but unfortunately, a text node might not be exactly what you expect. Even though you printed out a nicely-formatted line of text, you might end up with a heap of text nodes that will be a pain to process. Here's how we took a crack at it in the Caption.getText() method:

Caption.prototype.getText = function () {
  this.element.normalize();
  return this.element.firstChild.data;
}
      

The normalize() method (from the mother-of-all Node interfaces) is a great help here, since calling it on our <forms:caption> element will ensure we will encounter only one text node for the whole string. After calling it, we can safely return our first and only child's data.

Pages: 1, 2

Next Pagearrow