9 July 2003

9 Expressions


Contents


 

9.1 Introduction

The dSVG expression syntax was created to allow the attribute values of dSVG elements to be dynamic. With dSVG expressions, attribute values can be dependent on the real-time values of other attributes in the DOM. This syntax was intended to be simpler to use than XPath and ECMAScript, and to provide a subset of their most commonly used features.

dSVG expressions are denoted by the %% characters. Whatever is contained with the % characters gets evaluated. The basic unit of reference is elementID@attributeName. For example, %myRectangle@width% would be resolved to the numeric value of the width attribute of the element //.[ @id = "myRectangle"] (as denoted with the XPath expression). This syntax is therefore intended to be used in documents where elements have unique ID's. Note that the attributeName can have a namespace prefix for any namespace declared in the document.

9.2 Required Unit Pattern

elementID@attributeName | elementID@nameSpace:attributeName

9.3 Extended Pattern

Some dSVG behaviors, like 'loadXML', can create document fragments. These are named at the time of creation and can be referred to within %% expressions like so:

docID.elementID@nameSpace:attributeName

9.4 Special Attribute Extensions

9.4.1 Bounding Box

elementID@bbox.x : returns the x-coordinate of the element's bounding box (i.e. the left)
elementID@bbox.y : returns the y-coordinate of the element's bounding box (i.e. the top)
elementID@bbox.width : returns the width of the element's bounding box
elementID@bbox.height : returns the height of the element's bounding box

9.4.2 CDATA

elementID@cdata : returns the text content of the element

9.4.3 Event Attributes

@event.type: returns the type of event that triggered the behavior (e.g. 'mouseover', 'SVGResize', 'keypress', etc.)
@event.targetNodeName: returns the nodeName of the element that was the target of the event that triggered the behavior
@event.targetID: returns the 'id' attribute of the element that was the target of the event that triggered the behavior
@event.currentTargetNodeName: returns the nodeName of the element that observed the event that triggered the behavior
@event.currentTargetID: returns the 'id' attribute of the element that observed the event that triggered the behavior
@event.shiftKey: returns 'true' if the Shift-key is pressed, 'false' otherwise.
@event.ctrlKey: returns 'true' if the Ctrl-key is pressed, 'false' otherwise.
@event.keyCode: returns the keyCode attribute of the 'keydown' or 'keyup' event that triggered the behavior.
@event.keyID: returns the key identifier--a string representation of the keyCode attribute of the 'keydown' or 'keyup' event that triggered the behavior (e.g. 'Space', 'Enter', 'a').
@event.charCode: returns the charCode attribute of the 'keypress' event that triggered the behavior.
@event.char: returns the string representation of the charCode attribute of the 'keypress' event that triggered the behavior (e.g. 'A' or 'a').

Note: The real event object has 'target' and 'currentTarget' attributes, which are node objects. Since these would only be useful in a scripting environment, dSVG instead offers the "virtual" event attributes 'targetNodeName', 'targetID', 'currentTargetNodeName' and 'currentTargetID'.

9.4.3.1 Key Identifiers

A keyCode event attribute is automatically generated in response to the 'keydown' and 'keyup' events. For ease of authoring, dSVG offers a "virtual" event attribute called 'keyID', which is a string identifier for the various keys. These keyID's resemble, as closely as possible, the key identifiers listed in the W3C Working Draft of the DOM Level 3 Events Specification (http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/keyset.html). The mapping between the keyCodes and their corresponding keyID's are listed below.

keyCode keyID keyCode keyID keyCode keyID keyCode keyID keyCode keyID
8 Backspace 48 0 75 K 97 NumPad1 118 F7
9 Tab 49 1 76 L 98 NumPad2 119 F8
12 Center 50 2 77 M 99 NumPad3 120 F9
13 Enter 51 3 78 N 100 NumPad4 121 F10
16 Shift 52 4 79 O 101 NumPad5 122 F11
17 Control 53 5 80 P 102 NumPad6 123 F12
19 Pause 54 6 81 Q 103 NumPad7 127 Delete
20 CapsLock 55 7 82 R 104 NumPad8 144 NumLock
27 Escape 56 8 83 S 105 NumPad9 146 Scroll
32 Space 57 9 84 T 106 Multiply 186 Semicolon
33 PageUp 65 A 85 U 107 Add 187 Equals
34 PageDown 66 B 86 V 109 Subtract 188 Comma
35 End 67 C 87 W 110 Decimal 189 Hyphen
36 Home 68 D 88 X 111 Divide 190 Period
37 Left 69 E 89 Y 112 F1 191 Slash
38 Up 70 F 90 z 113 F2 192 GraveAccent
39 Right 71 G 91 WinLeft 114 F3 219 LeftSquareBracket
40 Down 72 H 92 WinRight 115 F4 220 Blackslash
44 PrintScreen 73 I 93 Apps 116 F5 221 RightSquareBracket
45 Insert 74 J 96 NumPad0 117 F6 222 Apostrophe

Note: In some SVG viewers, the 'keyCode' event attribute for some keys may be inconsistent with the DOM Level 3 Events Specification, which is currently in the Working Draft phase.

9.5 Processing

An attribute consists of constant string data concatenated with evaluated expressions delimited by % symbols (a double %% acts as an escape). For example:

attribute="constant_one% expression_one %constant_two% expression_two %constant_three"

Each resolution expects an expression of the form:

% complex_expression %

where complex_expression can be of the form:

% simple_expression %

or:

% simple_expression ( complex_expression ) simple_expression %

9.5.1 Use of Parentheses

Parentheses are resolved from innermost to outermost. Note that open parentheses require leading whitespace to distinguish them from functions.

9.5.2 Simple Expressions

simple_expression = [ string, Unit_Pattern, function, variable ] ( OpCode [ string, Unit_Pattern, function, variable ] )*

9.5.3 Strings

string = 'some string data' resolves to some string data

9.5.4 Functions

function = functionName( params ) : resolves to a function return value

The following ECMA math functions are available:

Other available functions are:

9.5.5 Variables

variable ( form: $variableName ) = % expression %

Variables refer to dSVG 'variable' elements and are intended as a convenient way of building and (re)using complex expressions, or simply for storage. It is the author's responsibility to not create self referential variables or circular variable references.

9.5.6 OpCodes

+  : addition
-  : subtraction
*  : multiplication
/  : division
,  : list separator (ie. for parameters)
== : boolean equals
>= : boolean greater than or equal to
<= : boolean less than or equal to
!= : boolean not equal to

Expressions using opcodes resolve any Unit_Patterns, functions, variables and strings and then follow standard ecma expression rules.

9.6 Example #1

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg SYSTEM "../SVGdSVG.dtd">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dsvg="http://www.corel.com/schemas/2002/dSVG" height="410px" width="744px" onload="init(evt)" viewBox="0 0 744 410">
	<script type="text/ecmascript" xlink:href="dsvg/dSVG.js"/>
	<script type="text/ecmascript" xlink:href="dsvg/baseUI.js"/>
	<script type="text/ecmascript" xlink:href="dsvg/constraint.js"/>
	<script type="text/ecmascript" xlink:href="dsvg/focus.js"/>
	<script type="text/ecmascript" xlink:href="dsvg/setAttribute.js"/>
	<script type="text/ecmascript" xlink:href="dsvg/setStyle.js"/>
	<script type="text/ecmascript" xlink:href="dsvg/setTransform.js"/>
	
	<!-- template -->
	<rect height="40" width="744" y="0" x="0" fill="#5f86B1" id="title_rect"/>
	<text y="25" x="20" font-weight="bold" font-size="18" fill="white" id="text_1">dSVG sample behavior: focus - with added attributes focusGroup and focus</text>
	<text y="365" x="20" font-size="12" id="content">Content of file:  dsvg:focus, dsvg:setTransform, dsvg:setAttribute, dsvg:setStyle, (added attributes dsvg:focus, dsvg:focusGroup)</text>
	<text y="380" x="20" font-size="12" id="expected">The dsvg:focusGroup attribute adds the ability to store the ID of similar type elements that are assigned to that group.</text>
	<text y="395" x="20" font-size="12" id="depend">Default focus can be given to an element (red circle above) by adding the dsvg:focus attribute to that element.</text>
	<line y2="340" x2="744" y1="340" x1="0" stroke-width="2" stroke="#5f86B1" fill="#5f86B1" id="bottom_line"/>
	
	<!-- adding behavior -->
	<text y="250" x="20" font-size="12" id="desc">The red, blue, green circles are part of the focusGroup. The orange circle is not.</text>
	<text y="150" x="200" font-size="12" id="desc_2">Click on the red, green and blue circles to set focus.</text>
	<text y="170" x="200" font-size="12" id="desc_3">Hover over the 'red', 'green' and 'blue' text elements to set focus.</text>
	<dsvg:focus elementID="redCircle" event="onclick" id="circleGroup">
		<dsvg:setTransform scale="1.2" vAlign="middle" hAlign="middle" absolute="true" elementID="%circleGroup@elementID%"/>
		<dsvg:setTransform scale="1" vAlign="middle" hAlign="middle" absolute="true" elementID="%circleGroup@previousID%"/>
		<dsvg:setAttribute value="%(circleGroup@elementID)@fill%Text" attribute="elementID" elementID="textGroup"/>
	</dsvg:focus>
	<dsvg:focus event="onmouseover" id="textGroup">
		<dsvg:setStyle value="%(textGroup@elementID)@cdata%" property="fill" elementID="%textGroup@elementID%"/>
		<dsvg:setStyle value="black" property="fill" elementID="%textGroup@previousID%"/>
		<dsvg:setAttribute value="%(textGroup@elementID)@cdata%Circle" attribute="elementID" elementID="circleGroup"/>
	</dsvg:focus>
	<circle dsvg:focus="true" dsvg:focusGroup="circleGroup" r="30" cy="100" cx="50" fill="red" id="redCircle"/>
	<circle dsvg:focusGroup="circleGroup" r="30" cy="200" cx="50" fill="blue" id="blueCircle"/>
	<circle dsvg:focusGroup="circleGroup" r="30" cy="100" cx="150" fill="green" id="greenCircle"/>
	<circle r="30" cy="200" cx="150" fill="orange" id="orangeCircle"/>
	<text dsvg:focus="true" dsvg:focusGroup="textGroup" y="80" x="200" id="redText">red</text>
	<text dsvg:focusGroup="textGroup" y="80" x="250" id="blueText">blue</text>
	<text dsvg:focusGroup="textGroup" y="80" x="300" id="greenText">green</text>
	<text y="80" x="350">orange</text>
</svg>

Hovering the mouse over the 'text' element with id="blueText causes the behaviors within the second 'focus' element to be run. When the first 'setStyle' behavior is run, its 'value' attribute, which is equal to:

%(textGroup@elementID)@cdata%

resolves to:

%blueText@cdata%

which then further resolves to:

blue

9.7 Example #2

<dsvg:button xlink:href="dsvg/skinButton_Windows.svg#skinButton" autoScale="true" disabled="false" selected="false" toggle="false" height="18" 
							width="100" y="70" x="80" label="Evaluate" id="button1">
  <dsvg:alert message="%button1@label == 'false' , 'is selected', 'is not selected') %"/>
</dsvg:button>

Pushing the button will run the 'alert' behavior. Its 'message' attribute, which is equal to:

message= "%button1@label	+ ' button ' + if(button1@selected == 'false' , 'is selected', 'is not selected')

which resolves to:

"button1@label + ' button ' + if( false , 'is selected', 'is not selected')

which further resolves to:

Evaluate button is selected