Copyright Doug Schepers 2004-2005.
We are investigating the range of possibilities for purely declarative authoring to include in SVG/XHTML Web Applications certain functionality that can only be done, at the present time, by the use of script. While the use of script is unavoidable for complex applications, simple applications can be created wholly through the use of declarative syntax, and even complex applications can rely upon this core functionality and only use scripting where needed. This is desirable from the perspective of the author (who will not need to cater to unreliable script functionality), from a security and efficiency stance, and from the viewpoint of UA implementations on limited devices, such as mobile phones. In addition, we propose an alternative appearance mechanism, to supplement or replace CSS, that is more internally consistent with XML, and which requires less work on the part of UA implementors with little or no loss of practical functionality to the author. This new styling syntax would leverage existing mechanisms in the SVG Specification, and provide syntactic and functional consistency. The primary focus of this document is SVG, but many of the ideas are directly applicable to XHTML as well. In this document, we itemize requirements for SVG-specific features, propose several possible extensions to SVG, and provide use cases, examples, and EcmaScript simulations for proposed BAM features. We also intend to provide corresponding examples for XHML where applicable.
This document is a private investigation and proposal, and not in any way affiliated with the W3C, other than by reference to existing W3C Specifications.
This document is an informal proposal for the SVG Working Group to improve declarative programming options in the SVG Specification. Enhancing declarative programming capabilities in SVG is expected to increase adoption of SVG by means of ease of authoring, and enhance the capabilities of computationally limited devices that access the Web.
This document is a work in progress and may be updated, replaced, or rendered obsolete by other documents at any time.
To make suggestions, comments, or criticisms, please contact Doug Schepers, at doug.schepers@vectoreal.com or doug@schepers.cc
SMIL and CSS are both examples of declarative enhancements to SVG; they do not rely on script, but are instead static instructions attached to an element that tell the User Agent how those elements behave, whether for animation or user interaction, as if that element were an object. Authors should be able to define certain commonly-needed behaviors declaratively, and reuse those behaviors throughout a document.
In terms of appearance, most of the functions of Cascading Style Sheets can be done without the need for a non-XML syntax. This would be easier to author, use a consistent syntax with the rest of the language, and would be better for scripting, making it more versatile.
Throughout this document, we give concrete examples of how such proposed syntax would look and act. Unless otherwise noted, these examples are emulated using EcmaScript which adds the functionality of the syntax to SVG. Ultimately, there would not be a need to use script for any of these examples; they would simply work using the syntax extensions. Technical note: these are not valid SVG documents, since they use custom elements and attributes without proper namespace prefixes; they are for illustrative purposes only.
Appearance is the essence of SVG. Almost all of the semantics of SVG are 'physical' semantics, the descriptions of visual representations. This is unlike HTML, where there is semantic content, structural content, and styling information; the initial goal of CSS was to split off the styling aspect into another specification, so that the structure and content of HTML could be repurposed and made more accessible. In this role as arbiter of style, CSS was included in SVG. Robin Berjon [Berjon] proposed that an XML-based syntax could replace parts of CSS. The essential aspects of this notion are simple:
<defs> <classDef id='redBlue' fill='red' stroke='blue' /> </defs> <rect x='5' y='5' width='40' height='40' class='url(#redBlue)' stroke-width='3'/>
Simple Inheritance is defined and allowed in SVG and SVG-Tiny, and would continue to serve the same function in BAM:
<g id='parentGroup' fill='none' stroke='black'> <!-- this rectangle and this circle have a black border and no fill --> <rect id='rect' width='15' height='15' /> <circle cx='100' cy='75' r='30' /> <!-- this ellipse has a black border, but a yellow fill --> <ellipse cx='65' cy='25' rx='20' ry='10' fill='yellow' /> </g>
With such a scheme there is the opportunity (which is not to say necessity) for the inheritance of geometry (that is, non-style) attributes, such as radius or corner-rounding.
With some addtional syntax, authors could define priority overrides:
<defs> <classDef id='redBlue' fill='red' stroke='blue' > <priority high='stroke' /> </classDef> </defs> <rect x='5' y='5' width='40' height='40' class='url(#redBlue)' stroke-width='3'/>
For an example of simple inheritance and 'classDef' references, see classDef.svg.
For an example of external 'classDef' references and reused SMIL references, see externalReferencing.svg, which draws on the files externalDef1.svg and externalDef2.svg to define the referenced elements.
Constrained tagName selectors, where all elements of a certain type (circle, rect, etc.) can be given the same appearance, or where a subset of that type with attributes of a certain value can be affected. When combined with formal constraints, this can lead to complex styling. Alternately, the use of the switch element could choose between a varied set of appearances.
For an example of tagName selectors, including a simple example of constraints, see tagDef.svg.
The 'class' attribute should be animatable, with changes to the class immediately reflected in the element appearance. Currently, if the CSS 'class' attribute is updated, the DOM is not affected. By doing so, however, large differences in appearance could be effected, rather than forcing the author to update each of the individual attributes of fill, stroke, et cetera. This would lead to more modular, smaller code.
For an example of changing the class of an element, see changeClass.svg. This example uses a script interface to choose the desired class, but it can also be done with a SMIL statement, to change several appearance properties at once, simplifying the code and requiring fewer SMIL statements. To see an example of this, see animateClass.svg.
In addition, just as in CSS, there should be a way to apply multiple appearance class definitions to a single element. The order in which the styles are referenced in the class attribute determines the initial priority of each attribute, but this can be overridden by the use of the 'priority' element. A 'classDef' with any 'priority' value for a given attribute will supercede that of a posterior 'classDef' with no such 'priority' attribute value. An attribute marked 'high' will prevent the application of one marked 'medium' or 'low'; an attribute marked 'medium' will prevent the application of one marked 'low', but will not take precedence over an attribute marked 'high'. In this initial proposal, an attribute marked 'high' will override even a local definition of the attribute in the element where applied, while those marked 'medium' or 'low' will not; in the example below, the rectangle will have a lime fill, and a blue stroke of 5 pixels:
<defs> <classDef id='allOrange' fill='orange' stroke='orange' stroke-width='5' > <priority stroke-width='high' /> </classDef> <classDef id='redBlue' fill='red' stroke='blue' stroke-width='7' > <priority stroke='high' fill='medium'/> </classDef> </defs> <rect x='5' y='5' width='40' height='40' class='url(#allOrange); url(#redBlue)' fill='lime' stroke='green' stroke-width='3'/>
Alternate to the named values in the 'priority' element attributes, an indexical integer scheme would allow a finer degree of control over the degree to which a given attribute assumes priority, with the higher number taking priority. This is not necessarily intuitive, as an author might think that '1' has the highest priority (when compared with nav-index, where the lowest number is first in the navigation order), but having the higher number take precedence allows for user control over styling with custom definitions, for accessibility purposes. This scheme might use integers from '1'- '100', with any value over '50' overriding the local element definition of an attribute.
A working example of multiple appearance class definition references is forthcoming.
As is demonstrated later, CSS pseudo-selectors can be more eloquently replaced by semantic-neutral, event-driven declarative behaviors.
An implication of the conversion of a subset of CSS to XML syntax is that XML is inherently extensible, so authors could define their own style or geometry tags and attributes, and define what effect they have. This would work well with the upcoming Vector-Effects and sXBL.
New value for SMIL attributes, to compensate for the fact that a single declaration might serve for several elements: 'baseValue'. Use case: an author might want any element to have a gold 5px stroke when moused over, but revert to whatever its original stroke value was on mouseout. Is this covered adequately by the 'end' attribute? Does this work also with the 'animate' element? Perhaps there should be another value for the SMIL 'fill' attribute, 'reverse', which would reverse the animation back to the original value; this could be used to easily bounce an item back and forth, or cycle colors in the same way.
When creating an abstracted appearance or, especially, behavior, it is often crucial that allowances be made for variable but predictable aspects. For example, if an author wished to create a behavior that would set the 'xlink:href' attribute of a 'tspan' element to the 'title' of whatever element used that behavior, it would have to automatically adjust to the variable 'id' of each element. Some sort of XPath syntax may be useful here, to get the 'title' of the current or parent element.
Some way to navigate to a parent or sibling element to have the SMIL affect that in addition to/instead of the current element (so it might affect the group or another sibling, in addition to itself). [for some reason, this strikes me as useful, but need a use case... might be muddled thinking] Perhaps this is dealt with via the 'xlink:href' attribute? Or was I thinking more of event bubbling?
Should there be tagName selectors as constraints within 'classDef' elements? Use case: if an author want all highlighted elements to have a gold 2-pixel stroke, and an author makes a generic 'classDef' to do this, it won't work as well with 'line' as with 'circle'; also, an author doesn't need fill-rules with non-path, non-poly elements. Could this be implemented using multiple sequential prioritized 'classDef's? That seems like a kluge.
Currently, if an author wants an animation or interaction statement to apply to more than one element, the author must put each of the recipient elements into a group, and animate the group. This has several problems:
If declarative behaviors and animations were predefined by the author in a generic way, and simply reused by reference, there would be several benefits:
<defs> <g id='hi-lo-light'> <set attributeName='stroke' to='gold' begin='mouseover'/> <set attributeName='stroke' to='black' begin='mouseout'/> </g> </defs> <a id='button1' xlink:href='someplace.com#number1'> <rect x='10' y='10' width='90' height='90' fill='black' stroke='black' stroke-width='10' behavior='url(#hi-lo-light)' /> </a> <a id='button2' xlink:href='someplace.com#number2'> <rect x='10' y='110' width='90' height='90' fill='black' stroke='black' stroke-width='10' behavior='url(#hi-lo-light)' /> </a> <a id='button3' xlink:href='someplace.com#number3'> <rect x='10' y='120' width='90' height='90' fill='black' stroke='black' stroke-width='10' behavior='url(#hi-lo-light)' /> </a>
For an example of reusing predefined SMIL elements, see reuseSMIL.svg. Compare this to a SMIL-only version of the same functionality at reuseSMIL_diff.svg.
On the subjects of file size and ease of authoring, it makes sense to bundle multiple animation elements under the same event triggers. This would be useful when the author wishes the same event to begin (or end) multiple effects. This could take a similar form to the 'classDef' element, where the reused attributes are all bundled into the parent.
<circle cx='200' cy='140' r='45' fill='crimson' /> <animateDef attributeType='XML' begin='mouseover' end='mouseout' fill='remove'> <set attributeName='fill' to='dodgerblue' /> <set attributeName='stroke' to='blue' /> <set attributeName='stroke-width' to='3' /> <set attributeName='stroke-dasharray' to='2 4' /> <set attributeName='stroke-linecap' to='round' /> <animate attributeName='r' from='45' to='65' dur='6s' /> <animateTransform attributeName='transform' type='rotate' from='0,200,140' to='-360,200,140' dur='3s' repeatCount='indefinite' /> </animateDef> </circle>
In the example above, seven different actions are controlled by one event; the actions are of different types, but the common factors are moved into the 'animateDef' element. In this way, the author can maintain the code much more easily, even more so than with the existing 'prev' attribute value keyword. This may seem like an unusual case, but if authors were to rely more upon declarative programming, large numbers of linked actions may become commonplace. Additionally, UAs may be optimized to improve their performance under such conditions. As a side note, were CSS replaced with an XML model, further performance gains would be realized, since currently, if an 'attributeType' is not specified, the processor first searches for a CSS property, then for the XML attribute, drastically increasing the processing needs; without CSS, the need to specify an 'attributeType' attribute would no longer be relevant, decreasing file size to some degree, but more importantly, clarifying authoring and optimizing performance.
The addition of constraints on reused SMIL elements shows how generic behaviors can be applied to multiple elements, and constraints on a SMIL-defined actions and states can create complex and adaptable behaviors. Emergent combinatorial properties will hopefully arise from mixing behaviors, such that relatively few behaviors will have to be included in order to meet a variety of situations and user interactions.
<defs> <classDef id='faveColors' fill='cornflowerblue' stroke='peru' stroke-width='5' stroke-linecap='round' stroke-linejoin='round' /> <g id='active'> <set attributeType='XML' attributeName='fill' to='deepskyblue' begin='mouseover'> <constraint selected='false' /> </set> <set attributeType='XML' attributeName='fill' to='cornflowerblue' begin='mouseout'> <constraint selected='false' /> </set> <set attributeType='XML' attributeName='selected' to='true' begin='click'> <constraint selected='false' /> </set> <set attributeType='XML' attributeName='selected' to='false' begin='click'> <constraint selected='true' /> </set> <set attributeType='XML' attributeName='fill' to='darkorchid' begin='click'> <constraint selected='false' /> </set> <set attributeType='XML' attributeName='fill' to='deepskyblue' begin='click'> <constraint selected='true' /> </set> </g> </defs> <ellipse id='e1' cx='155' cy='35' rx='25' ry='15' class='url(#faveColors)' behavior='url(#active)' selected='false'/> <rect id='r1' x='75' y='15' width='40' height='40' rx='5' ry='5' class='url(#faveColors)' behavior='url(#active)' selected='false'/> <polyline id='p1' points='10,10 55,55 10,55 55,10' class='url(#faveColors)' behavior='url(#active)' selected='false'/>
For an example of reusing constrained SMIL elements, see constrainSMIL.svg. Compare this to a SMIL-only version of the same functionality at constrainSMIL_diff.svg. A more extensive example of reuse shows that files sizes can be significantly smaller: compare constrainSMIL2.svg to a SMIL-only version of the same functionality at constrainSMIL_diff.svg; the file size on even this simple example was three times less on the reuse example.
The above example uses a 'selected' attribute, to detect and indicate stative variables associated with that element that cannot be inferred from environment (unlike enclosure in a shape, or inclusion in a group). There may be other appropriate stative attributes. These need not be defined in the SVG Specification; they may be custom attributes in a different namespace. Root-level 'global' variable elements or attributes may also be useful as reference points or as containers for potentially referenced values, such as a zoom level or alternate viewBox.
Constraints can also be used to serve as selectors in CSS do now. The following example would select only 'circle' elements that are in a group, where the group has an 'id' attribute value of 'apples'.
<defs> <classDef fill='red' > <constraint tagName='circle' /> <constraint target='parentNode' tagName='d' id='apples' /> </classDef> </defs> <circle cx='25' cy='25' r='20' stroke='crimson'/> <g id='apples'> <!-- These circles will be red --> <circle cx='50' cy='50' r='20' stroke='crimson'/> <circle cx='100' cy='100' r='20' stroke='crimson'/> </g> <circle cx='75' cy='75' r='20' stroke='crimson'/>
This is not a particularly pragmatic example, since in this simple case, it would have been more efficient to set the fill on the group to the proper color. It merely illustrates the specificity that can be controlled. The keyword 'parentNode' is introduced as the target of the contraint; another might be 'ancestor' for any level of nesting, or 'descendant' for any nested child node. Allowing non-hierarchical relationships might also be useful, such as providing an XLink reference to the constraint target, which would establish stative changes based on the status of a key element.
Element state and variables raise the issue of flow control. Some form of conditionals exist in SMIL already, in that mouse, keyboard, or timer-driven events must be triggered for the SMIL element to be applied, if not conditions satisfied. Whether further flow control mechanisms should be introduced is questionable, from a more explicit or extensive conditional route (some extension of the declarative 'switch' element, perhaps), to a looping control. A related concept is that an author might define many different behaviors, and 'cascade' them sequentially on an active element or on other elements, according to some criteria (perhaps constraints), which would allow fairly complex behavior-based interactivity, with or without flow controls.
Along similar lines, and particularly pertinent to constraints, is the issue of relational and logical operators. Should there be some way of demanding conditions other than that of simple value matching, such that conditions would obtain if numerical values are greater or less than a specified value? If so, should this issue be complicated by NOT, AND, OR, and XOR statements?
At this point, there may be some danger of defining a full-fledged scripting language, which may not suit the purpose of ease of authoring and small implementation footprint. This is an open question, and use case will have to be consider to resolve it.
A problem exists with repetition of SMIL elements in that they do not easily revert to a previous condition (that is, the 'baseValue') from an animated value. Also, currently, when a new event is triggered, the element being acted upon first reverts to its 'native' attribute values for that animation before starting the new sequence; sometimes this is desired, but usually not. This is a circumstance where having a distinction between 'baseValue' and 'animValue', that can be used in sequential animations or interactions, would be useful.
SMIL-triggered non-visual cues and effects, such as sounds when a focus event occurs. Could be controlled by the profile of the user, roughly equivalent to Aural Stylesheets.
Both the 'class' and 'behavior' attributes should be animatable, so that appearance, animation, and interactions can change based on user interaction and element state. An example of this might be the movement of a game piece that, once placed on a square, cannot be moved again that turn; this could be indicated by changing the 'draggable' attribute to false, and the 'behavior' element to a new reference that longer shows highlights. In a slightly more complicated version of this example, where landing on a specific square triggered a particular action on any element that did so, it might be helpful if there were a behavior on the square (the event 'relatedTarget') that could modify the behavior of the game piece (the event target); this is not currently possible in SMIL (the SMIL statement can only effect its parent, or another predefined element with an 'id', not an arbitrary element selected dynamically), but there are many cases where such potential would be useful, and not too expensive if only a limited set of targets (target, relatedTarget, possibly some others) were available to receive these events. Currently, you can use the 'xlink:href' attribute on a SMIL animation element to define the target of the animation, but it can only take a qname as its argument, not an event target.
In addition, the 'classDef' itself should be animatable, be it through event or timing SMIL, or script. When a 'classDef' is changed, all elements using it should be updated. 'classDef' should be a container element for SMIL statements (to clarify, it should not be only a container, but should have that ability).
Some type of “variable” element might be defined, as well, which could serve as a placeholder for the target of an event or animation, and which can intercept an event and apply any active animation to the current target of that event:
<defs> <listener id='myVariable' type='mouseover' /> <set attributeName='stroke-width' to='5' xlink:href='#myVariable' begin='mouseover'/> </defs> <circle cx='25' cy='25' r='20' stroke='crimson'/> <circle cx='125' cy='25' r='20' stroke='blue'/> <circle cx='225' cy='25' r='20' stroke='lime'/>
As with the 'classDef' element, there may be multiple behavior definitions applied to a single element, with the same syntax and priority scheme. The priority aspect allows even more complex behaviors, without unnecessarily complicating the individual element or behavior definition, and allows for user control over behavior with custom definitions, for accessibility purposes. The 'priority' element attributes should be animatable.
A common request of authors, and equally common use of script, is to enable the user to drag an element or group of elements by moving the mouse, or more rarely by using the keyboard. This is such a common piece of functionality, and so basic to user interaction, that it is an obvious inclusion for declarative syntax. Any other author requirements to be performed while a drag occurs can be synchronously triggered off the 'mousemove' (or possibly 'drag') event, so nothing is lost from scripting. An intuitive implementation of declarative drag-and-drop (DnD) would anchor the pointer at the 'grab point' (that is, if a 'rect' is grabbed at the top-right corner, that is where the mouse would stay while dragging), and would take into account zooming, panning, and transformations. Preferably, rather than using transforms to move the dragged element, the locative attributes themselves would be update while dragging (or, depending on how costly that is, updated upon drop). An advantage to having this functionality built into the UA is that it could also automatically define keyboard shortcuts (for instance, the arrow keys) rather than relying on the mouse, which may not be available to movement-impaired users or those on phones; this fills a frequent neglect on the part of authors. See below for detail on keyboard mapping.
<circle id='ball' cx='25' cy='25' r='18' fill='steelblue' draggable='true' drop='url(#blanket1) url(#blanket2) url(#blanket3)' dragArea='url(#islandBeach)' />
For an example of drag and drop, including a simple use of constraints, see DragAndDrop.svg. For a simple game based on this principle, see DragAndDropIntersection.svg.
Drag and drop brings up the interesting point of intersection and enclosure. In order to allow complex interactions between elements, in addition to a SMIL-accessible 'relatedTarget' property on the 'mouseover' and 'mouseout' events, there should be new events for 'intersection' (for collision) and 'enclosure', subject to a parameterized list or to all instances. While SVG has some simple script APIs for these, they should be extended to include non-rectangular elements. The sample above shows the limitations of doing so easily in script: it is possible for the ball to get stuck, and for the boat to be pulled onto the island. Fine control of intersection and enclosure would make this simple, declaratively. There may even be the equivalent of 'mouseover' and 'mouseout' for elements interaction, 'elementover', 'elementout', 'elementintersect' and 'elementenclosure'.
A precedent for a dragging mechanism exists already in SVG, in the 'animateMotion' element; the chief difference is that in the case of 'animateMotion', the path or direction to be followed is hard coded, where in the case of 'draggable', the direction is determined by the mouse position and whether it is moving or static.
While remaining much lower level than any widget, this would greatly aid in creating fast and responsive widgets. Scrollbars and sliders would simply be a draggable shape constrained to whatever path the author requires, and only scripting then needed would be to interpret the new value and do whatever is needed with that value, not worry about the repositioning of the thumb and its bounding min and max positions. Even circular sliders could be created by either constraining the movement to the shape's stroke, or to a very narrow concentric circle shape. The creation of many other widget types would be aided by a declarative drag, as well, making RCC/sXBL components robust.
Often, authors wish to bind attributes of different elements together, either to keep them in relative position to one another, or more often to attach a line between two elements to show some sort of relationship to one another. In his SVG Constraints browser [CSVG], Cameron McCormack uses XPath expressions to define and resolve such relationships. Rather than demand that all of XPath is implemented in a UA, and in keeping with SMIL syntax, I propose a slightly simpler derivative of his work:
<line id='edge1' x1='0' y1='0' x2='0' y2='0' stroke='ghostwhite' stroke-width='1.5'> <bind attributeName='x1' source='#node1' to='cx'/> <bind attributeName='y1' source='#node1' to='cy'/> <bind attributeName='x2' source='#node2' to='cx'/> <bind attributeName='y2' source='#node2' to='cy'/> </line>
Here, a line will be drawn between two other elements, with the 'id' values 'node1' and 'node2'.
For an example of attribute binding, see animatedAttributeBinding.svg. In this example, the lines are bound to animated circles, and the ends of the lines are dynamically updated as the SMIL animation progresses. [Note: this example works only in ASV6pr1, not ASV3; it may work in Batik.]
For another example of attribute binding, see draggableAttributeBinding.svg. In this example, the lines are bound to draggable circles, with the lines dynamically updated as the circle are dragged. (This which raises the issue of which should have precedence, declared animation or declared draggability).
It is worth noting that in addition to achieving a visual correlation between shapes, a 'bind' element imparts a formal semantic relationship, which can be leveraged by script or by a UA.
In addition to a strict binding of attribute values, McCormack allows mathematical operations on those values, again using XPath syntax. I would propose using an attribute to store any mathematical modifiers:
<rect id='firstRect' x='5' y='5' width='40' height='40' fill='orange' /> <rect x='5' y='5' width='40' height='40' fill='green' > <bind attributeName='x' source='#firstRect' to='x' mod='*2'/> </rect>
In this example, although both rectangles are defined with the same attribute values, the green rectangle would always have an 'x' value twice that of the orange rectangle, due to its 'bind' child element with a 'mod' value. This would persist even if the orange rectangle were moved. This would not move the orange rectangle if the green rectangle were moved, however; instead, the binding would not allow the 'x' value of the green rectangle to change (unless the bind were changed by a SMIL statement). In order to prevent an “infinite loop,” or computationally expensive two-way constraints, only the last binding for the same attribute of two elements will be enforced; that is, if the first rectangle binds its 'x' attribute to that of the second rectangle, which in turn binds its 'x' attribute to that of the first rectangle, only the second binding would be used. Whichever statement was declared last in the document order is applied. That conflicting bindings are legal is important, since the document order can change, thus triggering a new set of binding behaviors. Another way to solve the “infinite loop” problem, especially in the case of a deep interconnectedness of elements, is to allow the prime element (the source of constrained values) to always be that which is directly receiving events; thus, if a set of rectangles are all placed in relation to one another using bindings, and one rectangle is moved by the user, that rectangle becomes the focus for all the related movements of its siblings, while receiving none of the reciprocal updates itself. Of course, you could still constrain it with an area, etc.
Expand on this idea: Allow use of prev and next values, referring to order in document. Also, allow bbox (or top, bottom, left', right') value, so you have a generic reference, instead of cx/cy for circles, and some inaccessible value for paths and polys, etc.
Note that 'mod' can also take an attribute name instead of a number as a parameter, so that an author could say:
<bind attributeName='x' source='#firstRect' to='x' mod='+width'/>
A note on polygon and path nodes: because individual coordinates are parameterized, and not held as discrete attributes on these elements, there may have to be some way of specifying which command or coordinate pair is to be used, perhaps by a numbered array. Other sensible bindings might be the center point or centroid of a shape, as accessed via x or y members (e.g. centroid.x). Additionally, an offset might be declared to bind the endpoint to a certain relative location.
In the above examples, the attribute values were bound directly to the values of another attribute (either one of another element, or of its own element, such as the 'width' of a rectangle being constrained by its own 'height'. Another type of attribute binding that would be useful would be the ability to bind an attribute value to another, unrelated value. A simple example would be a rectangle (an ersatz button) that toggles the visibility of another element [insert example]:
<bind attributeName='x' source='#firstRect' to='x' mod='+width'/>
Declarative server interaction can be useful for many applications. Such interaction already has a precendent in HTML with the 'form' element, and in a limited fashion in SVG with the 'a' element. This proposal differs in three substantial ways. First, the UA would not replace the current document, but would operate on it to alter its state. Second, unlike 'form' or 'a' elements, the server-interaction element would be a child element for the activating element, not a container element, and would send the target server resource a set of name-value pairs indicated by a parameterized list. Third, there would be no explicit submission procedure such as submit button activation or mouseclick on a link, but could be activated by any named event.
The syntax for such a server-interaction element might look like:
<circle id='orangeBall' cx='25' cy='25' r='20' fill='orange' draggable='true' > <report id='myServerReport' action='/cgi-bin/post-position' method='post' begin='drop' values='cx cy' /> <!-- when this circle is dropped, it sends 2 name-value pairs, cx and cy, back to the server to be processed by the server-side script '/cgi-bin/post-position' --> </circle>
Optionally, any DOM data, not just that of the parent, could be indicated, via custom syntax or an XPath selector. Under some circumstances, hardcoded names and values might also be desirable. Here is possible syntax:
<report id='myServerReport' action='/cgi-bin/post-position' method='post' begin='click' values='cx cy' /> <!-- custom syntax to get the width of a particular element --> <value xlink:href='#myRect' attributeName='width' /> <!-- the same value, using XPath syntax --> <value xpath:node='id(myRect)[@width]' /> <!-- arbitrary values might also be passed, such as metadata --> <value parameterName='level' parameterValue='6th' /> </report>
Often an author wants to update a document without reloading and re-rendering the entire thing, incrementally changing the current SVG document. Whether this is accomplished by polling, by maintaining an open socket, or by some more advanced means is left up to the UA. The end result should be that existing elements should be subject to alteration, and new elements should be able to be inserted. In the most straightforward case, a known and specific graphical element would be subject to being updated by the server:
<text id='ticker' x='0' y='13' font-size='18px' > Latest football scores... <update to='serverReturn.nodeValue' begin='serverReturn' /> </text>
In some cases, however, the identity of the element to be updated, or the nature of the material to be inserted, may not be known beforehand. Thus, the mechanism and syntax are unclear, as it may be best that such instructions not be part of an existing graphical element, but serve somewhat independently, perhaps as part of container elements like a 'g' or the root 'svg'. Here, the author may wish to specify what type of actions should be taken upon receiving a 'serverReturn' event, such as inserting all of the new material, or updating those elements (game pieces, perhaps) that are contained in the resulting:
<svg id='orangeBall' cx='25' cy='25' r='20' fill='orange' draggable='true' > <update begin='serverReturn' target='serverReturn.eachId' to='serverReturn.eachNode'> <constraint target='serverReturn.eachId' selected='false' /> </update> <!-- this root-level update element will change all those elements it finds that share an id with elements contained in the XML returned from the server, as long as that element in the current document has the 'selected' attribute value of 'false' --> </svg>
It may be most prudent, for the sake of security, that only certain types of content are allowed as server results for a declarative call. Obviously, most XML files themselves are almost certainly safe (a possible exception may be transformative XML files that could, conceivably, transform normal XML into a malicious script). Script elements should be disallowed, as this would bypass one of the key benefits of declarative programming. Allowing only SVG, however, seems too restrictive, as a user or author may wish to import RDF (or other metadata) or arbitrary XML that will rendered as SVG using sXBL.
One concern about this functionality is that of security and privacy. While the majority of this functionality is already existent, new challenges are introduced by the fact that the user need not explicitly submit data. This might allow a malicious document to monitor and report pointer movements, key inputs, and other interactions. User Agents might overcome this privacy concern by indicating to the user that such a risk exists, either onload or upon the first server access, giving them an opportunity to allow or deny this.
Use cases for such functionality are interactive maps and diagrams (where increased detail is available server-side, or where locations or sections can be annotated or otherwise indicated, with the new data added to a database), declarative chat clients, and games.
Future Notes:
Incremental loading of data.
Elements can be triggered by serverUpdate/serverReturn ('id'-driven) event.
Need for 4-way (directional) navigation, not just 2-way
For an example of nav-index and directional navigation, see focusNavigation.svg. To 'tab' through the focusable elements in order of nav-index, press 'q'; 'shift'+'q' will tab backwards. the keys 'w', 's', 'a', and 'd' will navigate in the cardinal directions. Using the arrow keys, as well as dragging with the mouse, allows the focused element to be moved around.
The need for hierarchical navigation, not just nav-index or directional navigation, was posited by Jan-Klaas Kollhof [Kollhof]. He anticipated that for accessibility reasons, and in order to create modal dialogs in SVG, there should be a concept of nested levels of nav-index focus control. A possible syntax to allow this hierarchical navigation could be to extend nav-index, using a parameterized list syntax rather than a simple integer. For example:
One disadvantage to this scheme is that it is overly complex, and not necessarily intuitive, but I couldn't think of anything better. Hopefully someone else has a more elegant syntax, that would be more clear to authors.
For an example of hierarchical navigation using this scheme, see hierarchicalNavigation.svg. To step through each focusable item in the same group and level, press 'q' for forward and 'shift'+'q' for backward; to go down a level, press 'ctrl'+'q', and to go upwards, press 'shift'+'ctrl'+'q'. Style coding of the focused element options is as follows: solid black stroke if no parents or children are available; gold stroke if a parent is available; and dashed stroke if children are available.
Another possibility is to use a Logical Group [LG] to define a hierarchical ordering outside of the element itself, but this may prove problematic for code upkeep and readability.
Various viewports
Focusable
Selectable
A frequent request is that certain details of a map or drawing be hidden until zoomed-in upon to a specified level. This is referred to as Level of Detail, or LOD, and serves two purposes:
This could easily be done using declarative syntax, by specifying a numerical level that represents the required zoom level before an element renders. A minimum and maximum value might be specified, so that at a default view, simple undetailed 'placeholders' are shown (picture a set of gray rectangles that stand in for columns of text on a zoomed-out newspaper, but which are hidden when zoomed-in, to be replaced by actual text only visible at that level).
Since authors cannot control or be sure of what environment or user ability their content will be used with, it may aid them in designing an effective UI if they can specify keyboard equivalents for triggering certain events. This has been proposed, but dropped from, the most recent version of the CSS Specification. Please see http://www.w3.org/TR/2003/WD-css3-ui-20030703/#key-equivalent. I will soon propose more details and specific syntax to deal with this issue.
SMIL already allows use of the 'accessKey' trigger to begin (or end?) events, but it should also be allowed on the 'a' element to activate links.
The ability for an author, or for a user, to map keys to specific events would help SVG in a number of ways. First, for authors, it would allow the simple inclusion of 'hotkeys,' which are prevalent in applications and which would allow Web Apps to become first-class applications. Users might have a default key-mapping that corresponds to their needs, and which could be applied to any given SVG document; in this way, a 'mouseover' event might be temporarily mapped to the spacebar, for that user, much as 'click' or 'activate' is mapped to the 'enter' key by default in most UAs. The syntax might look something like this:
<keyMap begin='mouseover' accessKey='space'/>
An interesting suggestion was made by Jonathan Chetwynd [Chetwynd] to enable 'mousekeys' in SVG. While this is normally dealt with on a operating-system level, the ability to control the cursor using mapped keys may have merit.
Time is a very important to animation. It would be nice to have declarative access to system variables such as the current time, in order to facilitate such applications as clocks and things which use timestamps. Discrete controls over the flow of time would be helpful, such as reversing the timestream, slowing or speeding the rate of time, stopping and starting all timing, or going back to kill Hitler or my great-grandfather. Note: The current SVG 1.2 LC draft does include timing control, in section 13.5 Time Manipulation; however, it does not explicitly indicate pausing and resuming all timing. Presumably, you could set the 'speed' attribute to '0' to pause the animation, and to '100%' to resume it.
Currently in the DOM, you can set the time on the root element using the methods 'setCurrentTime(currentSeconds)', and there should be a way to set this declaratively, or in response to a restored or notated state (see 8.8.2. Deep Links).
The inclusion of a 'resizeable' attribute would be a boon. This would work similarly to 'draggable', but would 'drag' the nearest vertex or combination of vertices: grabbing a corner of a rectangle would pull that corner in the appropriate direction (up/down/left/right), grabbing the side would allow only vertical or horizontal size change, as applicable; circles could be pulled in any direction to resize; paths and polys would have the individual parameterized coordinate adjusted. This would help in many layout managers. It would throw a 'resize' event.
(Based in part on conversations with Lisa Koonts [Koonts], which will need to be written up in greater detail.)
This is also known as stacking order, z-order, and layering. In SVG's Painter's Model, there is no way to easily implement a z-index. Since this is a DOM 'problem,' there must be a declarative solution. The first thing that springs to mind is some sort of virtual placement, a 'use'-like solution, where the element has all the properties of its locality (group transforms and style, etc.), but is referenced elsewhere in the DOM for the sake of rendering. I do not yet have any proposed syntax for this, nor any profound insights.
There are some features of SVG that are only realizable by manipulating the DOM, such as inserting new elements, removing existing elements, cloning elements, and changing the location in the document of an element. There should be declarative ways to do these common tasks, allowing authors to simply and easily accomplish this without needing to resort to scripting.
<circle cx='25' cy='25' r='20' fill='orange' > <copyElement begin='select'/> </circle>or
<circle cx='25' cy='25' r='20' fill='red' > <alterDOM type='copy' begin='select'/> </circle>or
<circle cx='25' cy='25' r='20' fill='orange' >
<cloneNode deep='false' begin='select'/>
</circle>
<g id='parentGroup'>
<!-- when selected, this entire group will be cloned and inserted into
the document, just after the original. if the target were 'target',
only the selected element would be cloned -->
<cloneNode deep='true' begin='select' target='currentTarget' />
<rect id='rect' width='15' height='15' />
<circle cx='100' cy='75' r='30' />
</g>
Replace Element
<replaceElement to='newId' begin='serverReturn' />
<circle cx='25' cy='25' r='20' fill='orange' > <alterDOM type='remove' begin='click'/> </circle>
There may be times when an author wishes a user to be able to move an element from one location in the DOM to another. Use cases are:
To be continued...
One of the most powerful features of the Internet, the ability to bookmark and send links to specific content, is often broken in SVG when the SVG contains animation or user interactivity, or serves as an application framework. The use of script to alter the document also causes problems in this regard, not only in SVG but in (X)HTML as well. When a user wishes to create a link to a certain view or state of a dynamic document, and access it using a standard UA, there is currently no way to do so outside of often-ineffective script.
The syntax requirements for indicating what might be included or omitted, and the circumstances under which a saved state or link are possible in such a scheme are still being investigated. Perhaps there might be no need for explicit declarative statements to achieve the desired result, relying instead on default UA behavior (see UA Requirements/Features). But there are several use cases as to what functionality might be desired.
When a user wishes to save the current state of the document or application, there are three main types of functionality that may accomplish this:
With any approach, privacy issues would usually dictate that the file is saved to the local computer, although sometimes there will be cause to save it to a server.
This functionality would enable an SVG UA to fulfill the XForms Suspend and Resume feature.
Deep links refer to links to a specified state of an interface, progression of an animation, or section of a document. This might be treated as the Suspend and Resume feature, with the additional requirement that the state in question be available to be sent to another user. Unfortunately, this would not normally be as simple as sending a parameterized string, as generated by a 'get' method, since the data involved will usually be too many; it bears more resemblance to what might be generated by a 'post' method. Two ways of dealing with this are readily apparent:
Neither is ideal, but no other method is yet apparent.
In the process of recording the history of DOM state and mutations for undo/redo functionality, an SVG application could sustain and serialize this history as part of the save process, and thus could give other users access to the initial user's application or file history. This would be a potentially powerful tool.
As mentioned in 6. Server Interaction, one potential way out of the security conundrum of allowing local file-save access to a Web application or document is to restrict the data formats that can be saved. I would suggest two file formats that should balance out utility and safety: XML (with no script elements or transformative aspects such as XSL), and plain text. XML files should have any available extension (besides '.exe'), but text elements should be limited to '.txt' and '.csv' (Comma Separated Values), and such files should be saved with read-only or read-write only permissions, not executable permissions, where the local system permits. Text seems be the more dangerous of the two formats, but short of the user explicitly allowing executable permissions on the file, it should be safe. The CSV format would suffice for the name-value pairs suggested as data storage by XForms. Of course, if these restrictions do not allow the author the needed or desired control, they may feel free to develop a script-based alternative using whatever file-access mechanism is allowed on their target system, such as the Windows-IE-specific FileSystemObject, but this is outside the scope of a declarative approach that seeks to ensure the greatest possible security.
Other considerations for the sake of security lie with some of XML's automatic processing, specifically entity expansion, PIs, and DOCTYPE URIs. While these are important aspects of XML 1.0, the potential risks involved in exploitation of these instructions might be dealt with by disabling them in the serialization process when writing to disk; this may seem extreme, but is reasonable for the kinds of files that would be commonly written from an SVG WebApp, such as static SVG graphics, SMIL animations, diagram and graph descriptions, RDF, and a variety of other XML formats which are not necessarily dependant upon such things. Writing out XSLT, for example, would seem to be a corner case.
Speculation: Currently, you can only access the originating server using getURL, postURL, SVG1.2 sockets, and tref. Perhaps there could be some sort of permissions file (on the remote server) that might let you directly access another server's content, akin to a WebService; if I had a tref that referenced an SVG on another server, the UA would first check that same directory for an explicit XML "config permissions" file, and only allow that tref to follow through if it found an entry. For complete transparency, the UA might also require explicit confirmation from the user, as well. A particular webapp from a particular originating site might allow content from, say, an SVG file on another server, if the other server had explicit permissions for that webapp from that server. Example: User goes to domain A, which has a webapp that references a resource on domain B; the UA first alerts the user of the reference with a popup dialog, asking permission to access the remote server; then the UA checks domain B for an explicit permission file, with the domain and IP of domain A, and if it finds it, it completes the reference. The remote server could even keep a running tally on access instances, so that if there were a charge, it could be assessed that way.
Sometimes a user will have a link to an application, but the application may have been altered to have more or less functionality, to use a different API; similarly, a link to a dynamic document might no longer have access to certain of the data that had been displayed at the time of linking. For this reason, it may be efficacious to save time-sensitive data as part of the serialization process, even if all other saved information is stative only, and so authors might mark such data accordingly. Authors should also take care not to change an application so much that former links no longer work, or should provide a failsafe if they must do so.
In addition to reusable referencing abilities for SMIL elements, and the various SMIL-influenced declarative elements and attributes I describe throughout this document, I would propose several new attributes and elements to enhance SMIL. As it was conceived, SMIL was meant to control and coordinate multimedia content, but not dynamic user interaction.
There are several ways in which existing SMIL elements could be enhanced to allow more versatility:
All declarative elements should themselves be animatable, so that the duration and other attributes can be altered by a child declarative element. This is often desirable in order to create concise and sophisticated animations.
There should be a declarative way to access and change the value of an element's text node, in order to set it to another value. This can already be done in a limited way by animating the 'xlink:href' attribute of a 'tref' element, but only if the 'tref' already exists. To go along with this, there might be a way to perform specific string functions, such as changing case for strings, or animating the incementing/decrementing of numbers, such as might be useful for a clock.
For the purposes of games and artistic applications, a degree of unpredictability is often a useful enhancement. There should be an attribute value of '{random(min, max, precision)}', where min is the smallest value possible, max is the largest value possible, and precision is the number of decimals allowed.
A somewhat hidden feature of SVG is the ability to reverse an element on the x- or y-axis using the 'scale(-1,1)' or 'scale(1,-1)' transformation. However, the point of reversal is the coordinate origin, necessitating the addition of a 'translate()' transformation, which needs to be calculated. An optional parameter that preserves the shape within its original coordinate bounding-box would make for much easier usage of this feature. A simple boolean value would suffice, such as transform='scale(-1,1, true)'. This would also be useful for other types of scale transformations, where the relative position of the growing or shrinking element would be centered in the same location, relieving the author of tedious calculations in circumstances where they element is not supposed to move, only change size.
Concerns have been raised about accessibility issues using declarative syntax. While I believe that declarative syntax will aid accessibility greatly, it is certainly worth considering what implications any given feature will have on accessibility. The ability to create custom styling by users should be no more hampered than in CSS, and extended further if possible. User control over details of declarative functionality, such as the speed of a draggable element as used in a control, and the ability to toggle on or off declarative behaviors, have been raised as issues. I think that the this is largely a UA issue, allowing fine-grain control over features, in much the way that a user can zoom and pan by UA standard controls, or control the multimedia and animation playback, even when the author has not included such controls (see 9. UA Requirements/Features). Also relevant is the concept of key mapping (see 7.3. Key Mapping). In addition to accessibility features formalized in the Specification, and implemented in the UA, there would be great benefit for all authors to consistently use the same 'id' across files for the same appearance and appearance, so that a set of well-designed definition reference classes could be used which profile various disabilities; there is, of course, no way to mandate this, but it is strongly encouraged, and may well be an emergent authoring technique, in the same way that best practices are propagated.
In order to facilitate smooth integration with script, all animated values should be accessible through API, as distinct from 'baseVal'... I think this is the case already, but want to make sure. Perhaps other animated information should be available as well? What else would be needed/useful?
'selectable' attribute - use with/instead of DnD?
More declarative transforms -- needs to be defined in SVG. Non-Affine transform
(set theory - db info - use case... explain more about this)
Possibility of using BAM in conjunction with sXBL
Much called-for: selective restyling of 'use' sub-elements... maybe use xpath selection of child elements
Temporary container for random BAM attributes, to serve as child elements of SVG element
An animation that displays a progressive path, such as on a circuit diagram; akin to motionpath, but "grows" the element along the path, rather than moving it; similar to animatePath, but would not require the paths to have identical command sequences from the outset (animated path would likely start out empty). rate would be controlled by dur attribute.
<bam:node someAttribute='someValue' />
Declarative keyboard mapping, possibly superseding default UA shortcuts. Perhaps a method to trigger those key-events declaratively?
Various options available on context (right-click) menu, in UA?
Save to system clipboard, with options to specify format (SVG code or rasterized) and document section to be saved.
In this document we have performed a preliminary investigation of the possibility of an extension module to static presentation layers, specifically SVG, to allow declarative enhancement of complex behaviors and appearance.
SMIL and CSS are both examples of declarative enhancements to SVG. But there are currently too many limitations with these approaches to allow complex style and behavior. Client-side scripting allows a much greater range of functionality, but there are four main problems with it: it is more difficult for authors unused to programming; it is slower than the language in which the User Agent is written; it is computationally expensive and so may not be available on more limited platforms; and it yields many security concerns. Among the advantages of a dedicated declarative language are that it can operate within a more well-defined set of operations, ensuring security, interoperability across platforms, and ease of implementation. This can be desirable for implementing an alternative for WebCGM, whose users can be distrustful of languages that require extensions via scripting. As regards interactivity and animation, script languages such as ECMAScript (currently the most well-supported scripting language for SVG) allow discrete and pervasive control over the DOM, where SMIL allows rather a smaller range of control. But the needs of most users of SVG are far more limited than the full potential of scripting, and would be well met by an object-based interactivity model, where elements or groups of elements have specific properties and interactions as regards each other and user interactions. The SVG authoring community has a perennial list of desired functionality, containing such things as drag-and-drop, layering (z-index), and user interface widgets, all of which can only be supplied by scripted manipulation of the DOM. Widget controls are addressed by the proposed SVG1.2 extensions of RCC/sXBL, though only in a scripted fashion that limits their applicability. Another factor favoring a declarative solution is accessibility: an appropriate UA can interpret the intent of predefined tags such as 'draggable' in a way that is opaque when using custom script to do the same thing. Thus, UAs that compensate for visual impairment are given a good opportunity to present functionality information in an appropriate manner, and automation is rendered possible. It is worth noting that the inclusion of declarative functionality in a User Agent does not preclude in any way the inclusion of a scripting engine, or prevent an author from using script to accomplish any of the functionality, when the default behavior does not meet their needs.
In terms of appearance, Cascading Style Sheets are not ideally suited for SVG, having been explicitly and implicitly designed to enhance (X)HTML. Most of the presentation aspects that are carried over from print into the (X)HTML world do not have analogies to the graphical and illustrative aspects of SVG, and strain the semantic relationship. For instance, the 'block' and 'margin' style properties, tied into the box model of CSS, are ill-suited to the shape semantics of SVG. The intent of CSS intersects and contradicts SVG's functionality, which is also presentational (rather than logical or structural) in nature. More critical, however, is the fact the entirety of CSS is far more complex to implement than necessary, for the purposes of affecting the appearance of SVG; there is much that is simply not needed. This hampers UA implementors in their desire for conformance.
In addition to the details above, an added benefit to this proposal is the inherent ease with which such consistent, dynamic, well-styled documents could be generated, by authoring tools, by specialized server-side libaries using such languages as Perl or Python, or by XSL-FO and XSLT. It also removes a point of confusion for authors, should they try to set a style attribute that is unknowingly overridden by the equivalent style property.
Finally, while this is intended primarily for SVG, it need not be limited to SVG. Many of the concepts are directly applicable to (X)HTML, such as the appearance syntax and the server interaction. Other mechanisms only make sense in the context of building Web Applications, and SMIL is not currently mandated for (X)HTML, but if deemed applicable, these concepts could be applied to any presentation language, especially in the context of Compound Documents.
In several cases above, I have provided ECMAScript emulations of proposed features, for clarification and proof-of-concept. I have also begun looking into adding animation support into the native Mozilla SVG code, in order to extend it and provide C++ implementations of my proposals.
In addition to personal investigations, the author has received numerous suggestions and valuable insight from the individuals on the Internet Relay Chat channel '#svg' [SVG-IRC]. Specific thanks go to Robin Berjon for his insights into limitations of CSS and inspiring me to formalize my thoughts into this document, Cameron McCormack for his investigations into constraints and help with XPath, Lisa Koonts for insightful perspective on the needs and options for layout in SVG (among other issues), Jan-Klaas Kollhof for his ideas about hierarchical navigation, Kevin Lindsey for hours of brainstorming sessions, Jonathan Chetwynd for his informed advocacy of accessibility, and Jim Ley for his unflagging support of declarative programming. Moreover, I was recently shown a page by the talented Tobias Reif that discusses many of the ideas discussed here, which he anticipated 4 years ago; please see the relevant link in the references section [Reif] for his fascinating ideas.
"Young writers often suppose that style is a garnish for the meat of prose, a sauce by which a dull dish is made palatable. Style has no such separate entity; it is nondetachable, unfilterable. The beginner should approach style warily, realizing that it is himself he is approaching, no other; and he should begin by turning resolutely away from all devices that are popularly believed to indicate style - all mannerisms, tricks, adornments. The approach to style is by way of plainness, simplicity, orderliness, sincerity."
-Strunk and White, "The Elements of Style"