There has been much trumpeting by Macromedia about the ability in the new Flash tools for dynamic updating of pages with reloading/redrawing (see maxify). There's nothing unique to flash in this (or indeed anything new.) this document hopes to describe some techniques you can use in SVG. If you want to update HTML webpages using javascript, my examples on the XML HTTP Request Object will hopefully be useful.
I originally created a simple updating graph to demonstrate the technique. This uses a simple graphing library to draw a graph, with the data for each point coming from the server - This is supported by both Adobe SVG Viewer 3.0 and Batik 1.5b2, support for Mozilla SVG can be added.
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)"> <script type="text/ecmascript" xlink:href="/svg/drawing.js"/> <script type="text/ecmascript"><![CDATA[ SVGDoc=null L1=null count=0 function init(evt) { SVGDoc = evt.getTarget().getOwnerDocument(); LG=new LineGraph(100,100,0,0,30,1000,300,600,"Live updating graph from server data.") L1=LG.AddLine('red',0,0) setTimeout('go()',5000) } function go() { getURL('/2002/4/rnd.1',fn) } function fn(obj) { L1.AddData(++count,+obj.content) if (count<30) setTimeout('go()',5000) } ]]></script> </svg>
Most of this is just standard SVG stuff /svg/drawing.js is my library of
functions. LG=new LineGraph(100,100,0,0,30,1000,300,600,"Live
updating graph from server data.")
and
L1=LG.AddLine('red',0,0)
set up the graph - the interesting
part is the go()
function. This uses Adobes
getURL
method, which is not part of any standard so this
is limited to Adobes SVG viewer and Batik who have implemented it as
an extension - when Mozilla SVG becomes more widespread a simple
wrapper to the XMLHTTPRequest Object can be created to support
Mozilla.
getURL
takes two parameters, the URL to
retrieve and a function to call when the request completes. The URL, is just a URL, a simple text file, or anything can be there, so if you want to "call a function on the server", all you do is give your script a url (i.e. "http://jibbering.com/2002/4/rnd.1") which then executes any script and returns data back simply by writing text. When using postURL
it's the same, however there's a complication because the posted data is not URI Encoded as it is when forms are submitted in HTML webpages. This means that convenience methods like PHP's $elementname
do not work, so you have to parse the data direct from the PHP global variable $HTTP_RAW_POST_DATA
. Other server side technologies have similar methods.
In my example, the url is /2002/4/rnd.1 this is a simple script, which
returns a text/plain document containing a random number. When the
resource is loaded the viewer will call the function that is the
second parameter of getURL - fn
in my example. This
function recieves an object as a parameter with 2 properties,
contentType
and content
.
L1.AddData(++count,+obj.content)
AddData is a method from
my drawing.js library which adds a point to the graph with x,y
parameters, count is a simple counter for the X values and
+obj.content
is the data returned converted to a number
by the unary + operator. setTimeout
then kicks it all
of again if the count is still below 30.
The actual updating of the SVG is done in javascript using DOM methods (see http://www.kevlindev.com/dom/ )
Instead of have the server send just numbers, you can use more
structured data,XML, RDF or something else. An approach used by RO IT Systems is to send SVG
fragments which the client then parses (using the Adobe extension parseXML
method ). This has the effect of simplfying the client code and
keeping all logic on the server - upgrading the capability of the
system is simply a job of upgrading the server. An example of this
technique from RO IT Systems - Live
Financial Data Graphic.
The cost of sending SVG is in re-using the server side resource in other enviroments. Another example similar to the above is the Stock exchange feed example which draws graphs of the current stock market indices, and updates over time (30 second intervals) The same server side script is used to provide information to an HTML stock exchange feed demonstration. That still only sends simply structured data, rather than something more structured.
Adobes SVG viewer has no ability to set HTTP headers, so whilst it
can post (with the postURL()
method) it cannot add the
required headers. This is not too limiting as you can only talk to
your own server so simply not using XML-RPC SOAP/RPC is easy to
implement. REST is probably
a better model than SOAP in any case so the lack of XML-RPC
SOAP/RPC support is not onerous.
Mozilla has some SVG support, but does not include getURL
or postURL
however it does have the xmlhttprequest
object which can be used to provide them easily.
<script type="text/javascript"> function HTTP() { var xmlhttp /*@cc_on @*/ /*@if (@_jscript_version >= 5) try { xmlhttp=new ActiveXObject("Msxml2.XMLHTTP") } catch (e) { try { xmlhttp=new ActiveXObject("Microsoft.XMLHTTP") } catch (E) { xmlhttp=false } } @else xmlhttp=false @end @*/ if (!xmlhttp) { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp=false } } return xmlhttp } if (typeof getURL=='undefined') { getURL=function(url,fn) { var xmlhttp=new HTTP(); if (xmlhttp) { xmlhttp.open("GET",url,true); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { fn({status:xmlhttp.status,content:xmlhttp.responseText, contentType:xmlhttp.getResponseHeader("Content-Type")}) } } xmlhttp.send() } else { //Some Appropriate Fallback... } } } if (typeof postURL=='undefined') { postURL=function(url,txt,fn,type,enc) { var xmlhttp=new HTTP(); if (xmlhttp) { xmlhttp.open("POST",url,true); if (enc) xmlhttp.setRequestHeader("Content-Encoding",enc) if (type) xmlhttp.setRequestHeader("Content-Type",type) xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4) { fn({status:xmlhttp.status,content:xmlhttp.responseText, contentType:xmlhttp.getResponseHeader("Content-Type")}) } } xmlhttp.send(txt) } else { //Some Appropriate Fallback... } } } </script>
Above script in javascript file - getURL-postURL.js