W3C home > Mailing lists > Public > www-svg@w3.org > May 2010

SVG DOM 2 : JS createFragment

From: Hans Schmucker <hansschmucker@gmail.com>
Date: Sun, 30 May 2010 22:14:08 +0200
Message-ID: <AANLkTinjoDC0Dl8lQBOJ-qQ1t9WwQJyS56LPCsYXGenc@mail.gmail.com>
To: www-svg@w3.org
I've created what is essentially a wish list for SVG DOM 2's node
creation facility. The target was to create something that's fit for a
wide range of scenarios and uses while making simple use possible with
a minimum amount of overhead. For example using this you can create
template JS-objects, include whatever namespaces you want, import the
response from an XMLHttpRequest as SVG and lots more.
But if you just want to create a g node, it's still as easy as saying
createFragment("g")
Is this an approach that you'd think could work or is it too hackish?

=========  function createFragment  =========
	createFragment is intended to create SVG fragments that are detached
from the document. There are four basic ways it can be called:
	
	SVGElement createFragment( SVGElement )
	SVGElement createFragment( XML )
	SVGElement createFragment( XMLString )
	SVGElement|SVGElementMap createFragment( Array/ArrayContent )
	
	createFragment can be either called on any node or on the document
element, in which case its behaviour is identical to a call on the
root element of the document,
	
	Note that namespaces are interpreted as if the resulting SVG had been
written into the document at that point. Additional namespaces may be
given using
	the xmlns: constructs on the root node. There is no special variant
createFragmentNS since createFragment always resolves namespace
prefixes.
	
	
	===== createFragment( SVGElement ) =====
		Will create a new fragment that is identical to the given SVGElement
(and its child nodes). Specifically node types and attributes are
copied. Event Listeners and
		other complex properties are not.
		
		var svg=document.createFragment(existing_SVGElement);
		
		
	===== createFragment( XML ) =====
		In E4X enabled useragents, an XML snippet can be provided, which
will be interpreted according to the namespaces at the current node.
		The point is that any form of XML should be able to serve as
template, no matter if its a responseXML, an E4X snippet or whatever.
		
		var svg=document.createFragment(
			<g transform="rotate(45)" id="container">
				<image xlink:href="foo.png">
					<image xlink:href=" foo.png" />
					Hello World
				</image>
			</g>
		);
	
	
	===== createFragment( XMLString ) =====
		This is identical to createFragment( XML ), however the XML is not
specified via E4X, but as a String instead. It is primarily intended
for
		backwards compatibility with browsers that do not support E4X. An
XMLString is required to have "<" as its first character after
trimming
		
		var svg=document.createFragment(
'			<g transform="rotate(45)" id="container">'+
'				<image xlink:href="foo.png">'+
'					<image xlink:href=" foo.png" />'+
'					Hello World'+
'				</image>'+
'			</g>'
		);
		
	
	===== createFragment( Array/ArrayContent ) =====
		JSON-like notation for insertion of a dynamic SVG snippet. This mode
is used if argument 1 is either an Array or a String not starting with
"\s*<".
		Each element (except text nodes) is represented by an Array that at
least contains a string with the tag name.
		
		There are three different types of elements in this tree:	
		1. Arrays
			Arrays are interpreted as element templates.
		2. Strings
			Strings are interpreted as textnode templates, except at the top
level (createFragment is not meant for the creation of simple text
nodes)
		3. SVGElements
			Passing in an existing SVG element will create a copy at this point
in the document fragment

		== Array element templates ==
			Each Array element template must at the very least contain a string
with its tagname (including namespace prefixes if required).
			Note that namespaces are interpreted as if this element were
attached directly to the document. The tag name may not include
whitespace.
			["svg:g"]
			
			The list of arguments passed to createFragment is treated
automatically as an Array unless the first element is itself an Array.
So
			createFragment(["g"])
			is equivalent to
			createFragment("g")
			
			This string can optionally include attributes, seperated by
whitespace. There may be any amount of whitespace between name, "="
and value. Leading and trailing
			whitespace is trimmed
			["g foo  =   bar"]
			
			Attribute values that contain whitespace must be enclosed in either
single or double quotes. Attribute name may likewise be enclosed:
			["g 'foo'=\" Hello World \" "]
			
			["g 'foo'=Hello World"]
			is invalid and should throw and error.
			
			For class and id definition a shorthand notation is allowed.
Multiple class defintions add up to a space seperated string, while
multiple
			id definitions will discard every but the last one. Neither one can
contain whitespace.
			["g #foo #foo2 .bar .bar2"]
			is equivalent to
			["g id=foo2 class='bar bar2'"]
			
			Additionally, nodes can contain a special shorthand property that
will not change the node itself, but cause a change in return value
behavior: $
			["g $identity"]
			If any such such identity node templates are encountered,
createFragment returns an object where for each $... marked node there
is a property pointing
			to that node, or if multiple nodes with the same $... marker were
encountered an Array containing them. The root element will
automatically be marked $root.
			
			A tree containing
			["g"] as root element and ["g $ident1"], ["g $ident2"], ["g
$ident2"] somwhere inside the tree will return (# meaning references
to these nodes)
			{ "root": #1, "ident1": #2, "ident2": [ #3, #4 ] }
			
			= Attribute Collections =
				An array element template may contain any number of objects that
contain attribute maps. If an attribute is declared in multiple maps,
the last occurence takes
				precedence. This is so that developers can create seperate objects
for rarely changing attributes. Any object that is not an Array is
interpreted as attribute map.
				["g" {"id":"foo","class":bar"},{"class":"bar2"}]
			
			= Child nodes =
				Child nodes are specified as one or more Arrays:
				["g",[
					["image"],
					["g",[
						["image"]
					]]
				]]
				
				Allowing multiple childNode lists is primarily intended for reusing of parts
				var seperator=[
					["rect"],
					["image"]
				];
				
				createFragment(
					"g",
					[
						["image"],
					],
					seperator,
					[
						["image"],
					],
					seperator,
					[
						["image"],
					],
				]


-- 
Hans Schmucker
Mannheim
Germany
hansschmucker@gmail.com
http://www.tapper-ware.net
Received on Sunday, 30 May 2010 23:44:56 GMT

This archive was generated by hypermail 2.3.1 : Friday, 8 March 2013 15:54:45 GMT