Often, users may wish to create a single resource, and reuse it several times with specified variations. This is is currently possible by the use of script access to URL parameters or the <param> element in the HTML <object> element.
Using the <object> element, you can pass parameters by the use of child <param> elements. Each <param> element should have name/value pairs with the 'name' and 'value' attributes; these will be exposed to the embedded SVG document via script.
HTML:
<object type="image/svg+xml" data="button.svg">
<param name="param1" value="value1" />
<param name="param2" value="value2" />
</object>
SVG Javascript:
// get param elements from referencing object element
var params = document.defaultView.frameElement.getElementsByTagName("param");
// get attribute values of param @name and @value
...
// find elements that need to be changed, then set values to to param @value
...
With the <object>, <iframe>, and <embed> elements, you can pass parameters via the URL. The URL query syntax allows you to pass sets of name/value pairs separated by an ampersand (&); as with object params, these will be exposed to the embedded SVG document via script.
HTML:
<object type="image/svg+xml" data="button.svg?param1=value1¶m2=value2">
</object>
SVG Javascript:
// get param elements from referencing object element
var params = document.defaultView.location.href.split("?")[1].split("&");
// split name/value pairs
...
// find elements that need to be changed, then set values to to parameter value
...
The script-based approach is useful, but has several drawbacks:
To overcome these issues, this document examines some of the requirements and use cases involved in this issue, and proposes a solution for a declarative extension to SVG to fulfill these requirements. (Note: This issue is orthogonal to the CSS Variables proposal.)
For the sake of simplicity in this document, referenced parameter variables will be called variables in the general case, or <ref> elements in the specific case of a proposed solution.
The proposed solution is to specify a new SVG element, the <ref> element. This element would have a 'param' attribute which matches the parameter name, a 'default' attribute which provides a default value, and which is referenced by its 'id' attribute like any paint server. This differs from a paint server in that it can also be used to provide text content for a <tref> element.
My current proposal is to add a new element, the <ref> element. This would have three main attributes, 'param' (for matching incoming parameters from either the <param> element or URL query string), 'default' (an optional value for setting a default value if there is no parameter provided), and 'id' (for referencing with an IDREF attribute like 'xlink:href' or the 'url(#foo)' syntax). Additionally, the element could have child element content, which acts as a default value if there is no 'default' attribute. This element would act much as the various paint servers in SVG (<linearGradient>, <radialGradient>, <solidColor>, etc.), in that it can be referenced to provide a value to an element's attribute. It would also serve as the target for a <tref> reference, for text values.
The various values in the code examples are color-coded as follows:
HTML:
<object type="image/svg+xml" data="button.svg">
<param name="color" value="red" />
<param name="text-label" value="stop" />
</object>
SVG:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 110 40" width="100%" height="100%">
<title>Reusable Button</title>
<desc>Takes parameters from parent document's embedding element.</desc>
<defs>
<ref id="paramFill" param="color" default="blue"/>
<ref id="paramText" param="text-label">button</ref>
<ref id="paramStroke" param="outline" default="navy"/>
</defs>
<g>
<rect id="button_rect" x="5" y="5" width="100" height="30" rx="15" ry="15"
fill="url(#paramFill)" stroke="url(#paramStroke)" />
<text id="button_label" x="55" y="30" text-anchor="middle"
font-size="25" fill="black" font-family="Verdana">
<tref xlink:href="#paramText" />
</text>
</g>
</svg>
These examples show how this proposal would work in practice, by use of a prototyping script, ref.js. Obviously, this wouldn't be needed in a working native implementation.
Note that the text parameter aspects of these examples don't quite work in Firefox, since it doesn't support the <tref> element yet (14-04-2009). They could be made to work with only a little extra script, by directly inserting the text strings into the relevant text element, but the whole point is that it makes use of SVG's IDREF architecture. All other aspects should work in Opera, Firefox, and Safari, and maybe others (Chrome? Plugins?).
<object type="image/svg+xml" data="button.svg">
</object>
<object type="image/svg+xml" data="button.svg">
<param name="color" value="red" />
<param name="text-label" value="stop" />
</object>
<object type="image/svg+xml" data="button.svg?color=cornflowerblue&text-label=fnord">
</object>
<object type="image/svg+xml" data="button.svg?color=cornflowerblue&text-label=fnord">
<param name="color" value="purple" />
<param name="text-label" value="override" />
</object>
<object type="image/svg+xml" data="map.svg">
<param name="x" value="125" />
<param name="y" value="108" />
</object>
<object type="image/svg+xml" data="map.svg?y=103&x=523">
</object>
<ref id="paramX" param="x" default="-10"/>
<ref id="paramY" param="y" default="-10"/>
<circle id="coord" cx="url(#paramX)" cy="url(#paramY)" r="5" fill="tan" stroke="brown" stroke-width="3" />
<object type="image/svg+xml" data="ad.svg">
<param name="buylink" value="http://example.com/shop" />
</object>
<object type="image/svg+xml" data="ad.svg?buylink=http%3A%2F%2Fexample.com%2Fbargains">
</object>
<ref id="targetURL" param="buylink" default="/"/>
<a xlink:href="url(#targetURL)" target="_new">...</>
Comments and questions may be sent to schepers@w3.org. Some open questions and details are:
params
property on the Window object, which would be a list that reflects the names and values from URL query strings and object params)params
property?