It’s been awhile now since the W3C proposed the XHTML + SVG + MAthML document type declaration and a certain level of support has been available for a while. I’ve been testing XHTML + MathML lately (see http://www.metonymie.com/apuntes/2008/05/14/probabilidad-formulas-basicas.html). Now Firefox 3 is out, and supposedly it has support not only for embedded SVG but also for Dom manipulation the SVG nodes ( Correction: Jeff Schiller has pointed out that SVG support has been available in Firefox since version 1.5 ). So this is a series of tests of the basics of working with SVG from Javascript.

Getting the content to be recognized by the browser.

While testing this on my machine, I found out that for the svg to be accepted inside the html I had to name the file with an .xhtml extension. Since the same document with a .html extension just wasn´t recognized by firefox (IE 7 didn´t recognize the embedded SVG one way or the other). An example: SVG embedded inline inside XHTML.

So that was fine for local tests, but what about a dynamically generated document?.

Well first we need to define the type declaration, and the appropiate namespaces:

<?xml version="1.0"?><!DOCTYPE html PUBLIC    “-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN”“http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd”><html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en”><html xmlns=”http://www.w3.org/1999/xhtml”      xmlns:svg=”http://www.w3.org/2000/svg”      xmlns:xlink=”http://www.w3.org/1999/xlink”  xmlns:mathml=”http://www.w3.org/1998/Math/MathML”>

Note: Declaring the namespace on the document level saves us from having to declare it in each and every instance of an SVG element. So out of laziness, I prefer to do it on the top of the document.

But this is not enough if we want the document to be recognized as XHTML, we need to either use the .xhtml extension or to use a header when serving the document with content type=”text/xml”. In php we can do it like this:

header("content-type:text/xml");

An example: SVG embedded inline inside XHTML in a file with a non .xhtml extension.

You can also set the content type to a more specific definition, for example (inside the head of the document):

<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>

Using SVG inside XHTML

Now we’ll get into a little (just a little) more complex svg example that we’ll use for the rest of the post: Dom Manipulations of SVG Inside XHTML Examples

Defining the SVG elements

First we´ll create some basic SVG elements inside our document. Basically a Rectangle and a Circle inside a div.

<div id="svg-content"><svg:svg height="300" width="700" is="svg-container"><svg:rect fill="#ff5500" height="50" width="200" y="100" x="300" stroke="#000000" stroke-width="2px"/>    <svg:circle cx="150px" cy="100px" r="50px" fill="#ff0000" stroke="#000000" stroke-width="5px" id="circle"/></svg:svg></div>

Accesing the SVG Objects Properties with Javascript

Getting the value of an SVG Object attribute

It is as simple as retrieving the element by ID and getting the attribute as we would for any other DOM object. In the example page, this is the code on the first button:

alert( document.getElementById('circle').getAttribute('fill') );

Changing the value of an SVG Object Attribute

Again this is done as we would normally do with any other DOM Object.

document.getElementById('circle').setAttribute('fill', '#ffdd22');

Creating and adding a new SVG Object

This is a little more complex since we have to create a document node with the SVG Namespace defined.

function add_new_rectangle () {var atts = {"stroke-width":"1", "stroke":"blue", "fill":"yellow", "height":"20", "width":"40", "y":"100", "x":"220"};//Defining the SVG Namespacevar svgNS = "http://www.w3.org/2000/svg";//Creating a Document by Namespacevar node = document.createElementNS(svgNS, "rect");//Setting attributes by namespacenode.setAttributeNS(null, "id", "new-rect");for(name in atts) {node.setAttributeNS(null, name, atts[name]);}var cont = document.getElementById(”svg-container”);//Appending the new nodecont.appendChild(node);}

Using innerHTML with SVG

Now, a very simple way to deal with elements in HTML with the dom, is to use the innerHTML property. Luckily we can do the same with Divs containing SVG. Code for the fourth button in the example:

alert(document.getElementById('svg-content').innerHTML);

And of course we can manipulate and change it with a new SVG element declaration. The function that calls the fifth button:

function change_innerHTML_to_a_new_SVG() {var svg_str='‘;for(var x=1; x<10; x++) {svg_str += '<svg:circle cx="' + (x*30) + 'px" cy="100" r="' + (x*5) + 'px" fill="#ff' + (x*10) +  '00" stroke="#000000" stroke-width="3px"/>';}svg_str += '</svg:svg>';var cont = document.getElementById("svg-content");cont.innerHTML = svg_str;}