Introduction

SVG (Scalable Vector Graphics) is a modularized language for describing two-dimensional vector and mixed vector/raster graphics in XML. It is a W3C Recommendation currently at version 1.1.

SVG is a language for describing two-dimensional graphics in XML. SVG allows for three types of graphic objects: vector graphic shapes (e.g., paths consisting of straight lines and curves), images and text. Graphical objects can be grouped, styled, transformed and composited into previously rendered objects. The feature set includes nested transformations, clipping paths, alpha masks, filter effects and template objects.

SVG is implemented natively in Firefox from version 1.5, Opera from version 8.5, Safari from version 3.0, and in IE from version 9.0. Not every SVG construct is supported by these implementations.

This plugin allows you to manipulate the SVG from JavaScript. For more details see the reference documentation, or the graphing reference or plotting reference pages.

Download and include the jQuery SVG CSS and JavaScript in the head section of your page.

<link rel="stylesheet" type="text/css" href="css/jquery.svg.css">
<script type="text/javascript" src="js/jquery.svg.js"></script>

Alternatively, you can use the minified version of the code: jquery.svg.min.js (18.7K vs 56.6K, 5.7K when zipped).

Attach an SVG canvas to a <div>.

$('#svgintro').svg({onLoad: drawIntro});

Then respond to the load completion and start working with it.

function drawIntro(svg) {
	svg.circle(75, 75, 50,
		{fill: 'none', stroke: 'red', strokeWidth: 3});
	var g = svg.group({stroke: 'black', strokeWidth: 2});
	svg.line(g, 15, 75, 135, 75);
	svg.line(g, 75, 15, 75, 135);
}

You can remove the SVG functionality if you no longer need it.

$('#remove').click(function() {
	var remove = $(this).text() === 'Remove';
	$(this).text(remove ? 'Re-attach' : 'Remove');
	remove ? $('#svgintro').svg('destroy') : $('#svgintro').svg({onLoad: drawIntro});
});

For IE prior to version 9, you need one of the SVG browser plugins to render the documents (such as the Adobe SVG viewer or the Renesis Player). You also need to use an older version of this plugin (before 1.5.0), and provide a blank SVG document that is initially loaded to register itself with the plugin and allows access to its internal structure. This is the blank.svg document. Because of this requirement, you must wait for the document to be loaded before accessing the SVG instance and using it. Use the onLoad setting to be notified when loading is complete. The callback is not necessary for the other browsers, but its use provides a consistent access pattern for them all.

Processed divisions are marked with a class of hasSVG and are not re-processed if targeted a second time.

Extension Plugins

As well as the basic SVG functionality, the plugin allows for extending its abilities via additional packages. In this way you can avoid loading code that you are not going to use. Most extensions add an entry point object to the SVG manager object, returned by $(selector).svg('get'), from which you can access its functionality.

Currently the following extensions are available:

PackageEntry pointFunctionality
jquery.svganim.js- Support for jQuery animation of SVG attributes. Since 1.1.0.
jquery.svgdom.js- Support for jQuery/SVG DOM compatibility. Since 1.4.0.
jquery.svgfilter.jssvg.filter Support for SVG filter element and filter definitions.
jquery.svggraph.jssvg.graph Support for basic graphing using SVG.
jquery.svgplot.jssvg.plot Support for plotting functions using SVG. Since 1.3.0.

To use these extensions just load them after the main jQuery SVG Javascript in the head section of your page.

<script type="text/javascript" src="jquery.svg.js"></script>
<script type="text/javascript" src="jquery.svggraph.js"></script>

Each extension registers itself with the SVG framework as shown, indicating the name of its entry point and the class (function) that encapsulates its functionality:

$.svg.addExtension('graph', SVGGraph);

Attach an SVG canvas and retrieve the SVG instance as before. Then access the new functionality through its entry point:

$('div selector').svg();
var svg = $('div selector').svg('get');
svg.graph.addSeries('Firefox', [0.00, 4.06, 8.13, 9.95],
	'lightgreen', 'green', 3);
SVG Examples

These examples are taken from the SVG 1.1 specification to show how they might be implemented using this package.

Select one of the examples taken from the SVG specification that demonstrates how the functionality might be produced using this package. Both the original SVG document and the jQuery SVG code are shown below.

 

SVG Source Document

SVG jQuery Code

SVG Load

The SVG component may be updated with inline SVG elements, be cleared of all content, or be loaded with external SVG documents. In the latter case, you may pass additional settings to add to any existing content (addTo: true) or automatically clear it first (addTo: false - the default).

You can also specify a callback function (onLoad: loadDone) to be notified when the external document (loaded asynchronously) has completed. The function receives the current SVG wrapper object as a parameter, and an additional message parameter if there was an error. The this object is the SVG container division.

This came from an inline SVG fragment
<svg id="svginline">
  <g>
    <rect width="350" height="50" x="20" y="90" fill="blue"></rect>
    <text x="40" y="120" fill="white" font-weight="bold">
      This came from an inline SVG fragment</text>
  </g>
</svg>
$('#svgload').svg();

$('#addInline').click(function() {
	var svg = $('#svgload').svg('get');
	svg.add($('#svginline > *'));
	resetSize(svg);
});

$('#clear1').click(function() {
	$('#svgload').svg('get').clear();
});

$('#loadExternal').click(function() {
	var svg = $('#svgload').svg('get');
	svg.load($('#loadURL').val(), {addTo: $('#addTo')[0].checked,
		changeSize: false, onLoad: loadDone});
	resetSize(svg);
});

/* Callback after loading external document */
function loadDone(svg, error) {
	svg.text(10, 20, error || 'Loaded into ' + this.id);
}
SVG Attribute Animations

By adding the jquery.svganim.js extension to your page you can easily animate several of the attributes of the various SVG elements using the standard jQuery animate function.

All attributes must be prefixed by 'svg' to identify them as SVG settings and are written in camelCase, e.g. svgStrokeWidth. Many of the values may be expressed as exact pixels or as percentages. You can also use the '+=' or '-=' prefixes for relative values.

var myrect = svg.rect(25, 25, 150, '25%', 10, 10,
	{fill: 'none', stroke: 'blue', strokeWidth: 3,
	transform: 'rotate(0, 100, 75)'});
$(myrect).animate({svgWidth: 200, svgHeight: '30%',
	svgStroke: 'aqua', svgStrokeWidth: '+=7',
	svgTransform: 'rotate(60, 100, 75)'}, 2000);

Animate

or a combination of effects  

$('#svganim').svg({onLoad: drawAnim});
		
var current = {};

$('#animGo').click(function() {
	var opt = $('#animShape').val();
	$('#animBetween').text(
		'between ' + values[opt][0] + ' and ' + values[opt][1]);
	current[opt] = 1 - (current[opt] || 0);
	var parts = opt.split(':');
	var params = {};
	params['svg' + parts[1]] = values[opt][current[opt]];
	$(shapes[parts[0]]).animate(params, 2000);
});

$('#animCombo').click(function() {
	var go = $(this).text() === 'Go';
	$(this).text(go ? 'Back' : 'Go');
	var rectAnim = go ? {svgWidth: '30%', svgStrokeWidth: 10,
			svgTransform: 'rotate(45 100 75) translate(20 40)'} :
			{svgWidth: '25%', svgStrokeWidth: 3,
			svgTransform: 'rotate(0 100 75) translate(0 0)'};
	var circleAnim = go ? {svgR: 100, svgStroke: 'pink'} : {svgR: 50, svgStroke: 'red'};
	$(shapes['rect']).animate(rectAnim, 2000);
	$(shapes['circle']).animate(circleAnim, 2000);
});

The attributes that can be animated are summarised below. For more information see the documentation reference animation page

SVG AttributeAnimation AttributeTypeElements
xsvgXnumeric svg, rect, text
ysvgYnumeric svg, rect, text
widthsvgWidthnumeric svg, rect
heightsvgHeightnumeric svg, rect
cxsvgCxnumeric circle, ellipse
cysvgCynumeric circle, ellipse
rsvgRnumeric circle
rxsvgRxnumeric rect, ellipse
rysvgRynumeric rect, ellipse
x1svgX1numeric line
y1svgY1numeric line
x2svgX2numeric line
y2svgY2numeric line
opacitysvgOpacitynumeric 0.0-1.0 group, rect, circle, ellipse, line, polyline, polygon, path, text
font-sizesvgFontSizenumeric group, text
font-weightsvgFontWeightnumeric group, text
letter-spacingsvgLetterSpacingnumeric group, text
word-spacingsvgWordSpacingnumeric group, text
fillsvgFillcolour group, rect, circle, ellipse, polygon, path, text
fill-opacitysvgFillOpacitynumeric 0.0-1.0 group, rect, circle, ellipse, polygon, path, text
strokesvgStrokecolour group, rect, circle, ellipse, line, polyline, polygon, path, text
stroke-widthsvgStrokeWidthnumeric group, rect, circle, ellipse, line, polyline, polygon, path, text
stroke-dasharraysvgStrokeDashArraystring group, rect, circle, ellipse, line, polyline, polygon, path, text
stroke-dashoffsetsvgStrokeDashOffsetnumeric group, rect, circle, ellipse, line, polyline, polygon, path, text
stroke-opacitysvgStrokeOpacitynumeric 0.0-1.0 group, rect, circle, ellipse, line, polyline, polygon, path, text
transformsvgTransformstring group, rect, circle, ellipse, line, polyline, polygon, path, text
viewBoxsvgViewBoxstring svg, symbol, marker, pattern
Sketchpad

Select a shape and its appearance and then drag in the panel to create it.

 
Shape Fill
Stroke width Stroke
 
 
var drawNodes = [];
var sketchpad = null;
var start = null;
var outline = null;
var offset = null;

$('#svgsketch').svg({onLoad: function(svg) {
		sketchpad = svg;
		var surface = svg.rect(0, 0, '100%', '100%', {id: 'surface', fill: 'white'});
		$(surface).mousedown(startDrag).mousemove(dragging).mouseup(endDrag);
		resetSize(svg, '100%', '100%');
	}
});

/* Remember where we started */
function startDrag(event) {
	offset = (sketchpad._embedded ? {left: 0, top: 0} : $('#svgsketch').offset());
	if (!sketchpad._embedded) {
		offset.left -= document.documentElement.scrollLeft || document.body.scrollLeft;
		offset.top -= document.documentElement.scrollTop || document.body.scrollTop;
	}
	start = {X: event.clientX - offset.left, Y: event.clientY - offset.top};
	event.preventDefault();
}

/* Provide feedback as we drag */
function dragging(event) {
	if (!start) {
		return;
	}
	if (!outline) {
		outline = sketchpad.rect(0, 0, 0, 0,
			{fill: 'none', stroke: '#c0c0c0', strokeWidth: 1, strokeDashArray: '2,2'});
		$(outline).mouseup(endDrag);
	}
	sketchpad.change(outline, {x: Math.min(event.clientX - offset.left, start.X),
		y: Math.min(event.clientY - offset.top, start.Y),
		width: Math.abs(event.clientX - offset.left - start.X),
		height: Math.abs(event.clientY - offset.top - start.Y)});
	event.preventDefault();
}

/* Draw where we finish */
function endDrag(event) {
	if (!start) {
		return;
	}
	$(outline).remove();
	outline = null;
	drawShape(start.X, start.Y,
		event.clientX - offset.left, event.clientY - offset.top);
	start = null;
	event.preventDefault();
}

/* Draw the selected element on the canvas */
function drawShape(x1, y1, x2, y2) {
	var left = Math.min(x1, x2);
	var top = Math.min(y1, y2);
	var right = Math.max(x1, x2);
	var bottom = Math.max(y1, y2);
	var settings = {fill: $('#fill').val(), stroke: $('#stroke').val(),
		strokeWidth: $('#swidth').val()};
	var shape = $('#shape').val();
	var node = null;
	if (shape == 'rect') {
		node = sketchpad.rect(left, top, right - left, bottom - top, settings);
	}
	else if (shape == 'circle') {
		var r = Math.min(right - left, bottom - top) / 2;
		node = sketchpad.circle(left + r, top + r, r, settings);
	}
	else if (shape == 'ellipse') {
		var rx = (right - left) / 2;
		var ry = (bottom - top) / 2;
		node = sketchpad.ellipse(left + rx, top + ry, rx, ry, settings);
	}
	else if (shape == 'line') {
		node = sketchpad.line(x1, y1, x2, y2, settings);
	}
	else if (shape == 'polyline') {
		node = sketchpad.polyline([[(x1 + x2) / 2, y1], [x2, y2],
			[x1, (y1 + y2) / 2], [x2, (y1 + y2) / 2], [x1, y2],
			[(x1 + x2) / 2, y1]], $.extend(settings, {fill: 'none'}));
	}
	else if (shape == 'polygon') {
		node = sketchpad.polygon([[(x1 + x2) / 2, y1], [x2, y1], [x2, y2],
			[(x1 + x2) / 2, y2], [x1, (y1 + y2) / 2]], settings);
	}
	drawNodes[drawNodes.length] = node;
	$(node).mousedown(startDrag).mousemove(dragging).mouseup(endDrag);
	$('#svgsketch').focus();
};

/* Remove the last drawn element */
$('#undo').click(function() {
	if (!drawNodes.length) {
		return;
	}
	sketchpad.remove(drawNodes[drawNodes.length - 1]);
	drawNodes.splice(drawNodes.length - 1, 1);
});

/* Clear the canvas */
$('#clear2').click(function() {
	while (drawNodes.length) {
		$('#undo').trigger('click');
	}
});

/* Convert to text */
$('#toSVG').click(function() {
	alert(sketchpad.toSVG());
});
Graphing

Use the graphing extension to make it easier to create SVG graphs.

Add the jQuery SVG graphing extension in the head section of your page.

<script type="text/javascript" src="jquery.svggraph.js"></script>

Then access the extra functionality via the graph object within the SVG root. As well as the series and their formatting, you can control the graph title, axes, gridlines, labels, and legend.

with legend and background  

Options:

This is the code behind the graphing.

$('#svggraph').svg(initGraph);
		
var chartAreas = [[0.1, 0.1, 0.95, 0.9], [0.2, 0.1, 0.95, 0.9],
	[0.1, 0.1, 0.8, 0.9], [0.1, 0.25, 0.9, 0.9], [0.1, 0.1, 0.9, 0.8]];
var legendAreas = [[0.0, 0.0, 0.0, 0.0], [0.005, 0.1, 0.125, 0.5],
	[0.85, 0.1, 0.97, 0.5], [0.2, 0.1, 0.8, 0.2], [0.2, 0.9, 0.8, 0.995]];
var fills = [['lightblue', 'url(#fadeBlue)'], ['pink', 'url(#fadeRed)'],
	['lightgreen', 'url(#fadeGreen)']];

function initGraph(svg) {
	var defs = svg.defs();
	svg.linearGradient(defs, 'fadeBlue',
		[[0, 'lightblue'], [1, 'blue']]);
	svg.linearGradient(defs, 'fadeRed', [[0, 'pink'], [1, 'red']]);
	svg.linearGradient(defs, 'fadeGreen',
		[[0, 'lightgreen'], [1, 'green']]);
	svg.graph.noDraw().title('Browser Usage', 'blue').
		addSeries('IE', [95.97, 91.80, 88.16, 86.64],
			'lightblue', 'blue', 3).
		addSeries('Netscape', [3.39, 2.83, 1.61, 0.00],
			'pink', 'red', 3).
		addSeries('Firefox', [0.00, 4.06, 8.13, 9.95],
			'lightgreen', 'green', 3).
		format('ivory', 'gray').
		gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray');
	svg.graph.xAxis.title('Year', 'green').scale(0, 3).
		ticks(1, 0).labels(['2002', '2004', '2005', '2006']);
	svg.graph.yAxis.title('Percentage').ticks(10, 5);
	svg.graph.legend.settings({fill: 'lightgoldenrodyellow',
		stroke: 'gray'});
	svg.graph.status(showGraphStatus);
}

/* Draw a new graph with the selected options */
$('#graphIt').click(function() {
	var chartType = $('#chartType').val();
	var chartLegend = parseInt($('#chartLegend').val(), 10);
	var seriesFill = ($('#seriesFill').val() == 'plain' ? 0 : 1);
	var svg = $('#svggraph').svg('get');
	svg.graph.noDraw().
		legend.show(chartLegend).area(legendAreas[chartLegend]).end().
		series(0).format(fills[0][seriesFill]).end().
		series(1).format(fills[1][seriesFill]).end().
		series(2).format(fills[2][seriesFill]).end().
		area(chartAreas[chartLegend]).
		type(chartType, {explode: 2, explodeDist: 10}).redraw();
	chartType = $.svg.graphing.chartTypes()[chartType];
	$('#graphDesc').text(chartType.description());
	var options = '';
	for (var i = 0; i < chartType.options().length; i++) {
		options += '<li>' + chartType.options()[i] + '</li>';
	}
	$('#graphOptions').html(options || '<li>None</li>');
	resetSize(svg);
});

function showGraphStatus(label, value) {
	$('#svggraph').attr('title', (label ? label + ' ' + value : ''));
}
Plotting

Use the plotting extension to display the plots of numeric functions on a grid.

Add the jQuery SVG plotting extension in the head section of your page.

<script type="text/javascript" src="jquery.svgplot.js"></script>

Then access the extra functionality via the plot object within the SVG root. As well as the functions and their formatting, you can control the plot title, axes, gridlines, labels, and legend.

Zoom with x/y units and legend  

This is the code behind the plotting.

$('#svgplot').svg(initPlot);
		
var plotZooms = [[-2, 2, -1.5, 1.5], [-10, 10, -10, 10]];
var chartAreas = [[0.1, 0.1, 0.95, 0.9], [0.2, 0.1, 0.95, 0.9],
	[0.1, 0.1, 0.8, 0.9], [0.1, 0.25, 0.9, 0.9], [0.1, 0.1, 0.9, 0.8]];
var legendAreas = [[0.0, 0.0, 0.0, 0.0], [0.005, 0.1, 0.125, 0.5],
	[0.85, 0.1, 0.97, 0.5], [0.2, 0.1, 0.8, 0.2], [0.2, 0.9, 0.8, 0.995]];
	
function initPlot(svg) {
	svg.plot.noDraw().title('Functions', 'blue').
		addFunction('Sine', Math.sin, 'blue', 3).
		addFunction('Cosine', Math.cos, [-Math.PI, Math.PI], 20, 'red', 3).
		addFunction('Decaying', decay, 'green', 3).
		format('ivory', 'gray').
		gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray');
	svg.plot.xAxis.scale(-1, 3.5).ticks(1, 0.2);
	svg.plot.yAxis.scale(-1.5, 1.5).ticks(1, 0.2);
	svg.plot.legend.settings({fill: 'lightgoldenrodyellow',
		stroke: 'gray'});
	svg.plot.status(showPlotStatus);
}

/* Plot a new function with the selected options */
$('#plotIt').click(function() {
	var plotZoom = parseInt($('#plotZoom').val(), 10);
	var plotEqual = parseInt($('#plotEqual').val(), 10);
	var plotLegend = parseInt($('#plotLegend').val(), 10);
	var svg = $('#svgplot').svg('get');
	svg.plot.noDraw().
		legend.show(plotLegend).area(legendAreas[plotLegend]).end().
		xAxis.scale(plotZooms[plotZoom][0], plotZooms[plotZoom][1]).end().
		yAxis.scale(plotZooms[plotZoom][2], plotZooms[plotZoom][3]).end().
		area(chartAreas[plotLegend]).equalXY(plotEqual).redraw();
	resetSize(svg);
});

/* Decaying sine wave */
function decay(x) {
	return Math.exp(-0.4 * x) * Math.sin(x);
}

function showPlotStatus(label) {
	$('#svgplot').attr('title', label);
}
Mixture of Graphs/Plots/etc.

You can combine graphs, plots, and other SVG elements in the one document. A default container (embedded <svg>) is created for each of a graph and a plot. You can change the settings for these or specify a new container and size and position it appropriately.

This is the code behind the mixture.

$('#svgmix').svg({onLoad: drawMixture});

function drawMixture(svg) {
	var g = svg.group({'font-weight': 'bold'});
	svg.text(g, 600, 100, 'This graph is in its');
	svg.text(g, 600, 120, 'own <svg> element');
	svg.text(g, 150, 450, 'As is this plot');
	svg.change(svg.graph.container(), /* Graph */
		{width: 600, height: 350, 'font-size': 12});
	svg.graph.noDraw().
		title('Browser Usage').type('column').area([0.1, 0.1, 0.9, 0.8]).
		addSeries('IE', [95.97, 91.80, 88.16, 86.64],
			'lightblue', 'blue', 3).
		addSeries('Netscape', [3.39, 2.83, 1.61, 0.00], 'pink', 'red', 3).
		addSeries('Firefox', [0.00, 4.06, 8.13, 9.95],
			'lightgreen', 'green', 3).
		format('ivory', 'gray').
		gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray').
		xAxis.title('Year', 30).scale(0, 3).
		ticks(1, 0).labels(['2002', '2004', '2005', '2006']).end().
		yAxis.title('Percentage').ticks(10, 5).end().
		legend.show(true).area([0.2, 0.9, 0.8, 0.995]).
		settings({fill: 'lightgoldenrodyellow', stroke: 'gray'}).end().
		redraw();
	svg.plot.noDraw().container(svg.svg(300, 350, 400, 350)). /* Plot */
		title('Functions').area([0.1, 0.1, 0.9, 0.8]).equalXY(true).
		addFunction('Sine', Math.sin, 'blue', 3).
		addFunction('Cosine', Math.cos, [-Math.PI, Math.PI], 20, 'red', 3).
		addFunction('Decaying', decay, 'green', 3).
		format('ivory', 'gray').
		gridlines({stroke: 'gray', strokeDashArray: '2,2'}, 'gray').
		xAxis.scale(-1, 3.5).ticks(1, 0.2).end().
		yAxis.scale(-1.5, 1.5).ticks(1, 0.2).end().
		legend.show(true).area([0.1, 0.9, 0.9, 0.995]).
		settings({fill: 'lightgoldenrodyellow', stroke: 'gray'}).end().
		redraw();
	resetSize(svg, 800, 700);
}

/* Decaying sine wave */
function decay(x) {
	return Math.exp(-0.4 * x) * Math.sin(x);
}
SVG DOM

The SVG DOM is different to the HTML DOM for which jQuery was designed. In particular, any attributes that can be animated are stored as objects instead of plain strings. This includes the class attribute. Thus, jQuery's functions that work with classes don't work on SVG nodes.

To overcome this problem you can use the jQuery SVG DOM extension. Add the extension in the head section of your page.

<script type="text/javascript" src="jquery.svgdom.js"></script>

Then just use jQuery's class and attribute functions on SVG nodes as well: addClass, removeClass, toggleClass, hasClass, attr, and removeAttr.

Use the power of jQuery to select nodes in the SVG document with this extension. Provide the SVG root element as the context for your selections:

$(selector, svg.root())...

Unfortunately, for older versions of IE (before 9.0), there are some small modifications needed to the base jQuery code that cannot be overridden in the extension. These modifications are not needed for IE9+ and plugin 1.5.0+.

A modified jQuery 1.7.2 is available for download, as is a modified jQuery 1.6.2, modified jQuery 1.5.1, and modified jQuery 1.4.2.

In the jQuery.removeData function (line 1881, v1.7.2):

if ( jQuery.support.deleteExpando ) {
	delete elem[ internalKey ];
} else {
	try { // SVG
		elem.removeAttribute( internalKey );
	} catch (e) {
		elem[ internalKey ] = null;
	}
}

In the event.add function (line 2985, v1.7.2):

if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
	// Bind the global event handler to the element
	try { // SVG
		elem.addEventListener( type, eventHandle, false );
	} catch(e) {
		if ( elem.attachEvent ) {
			elem.attachEvent( "on" + type, eventHandle );
		}
	}
}

In the event.remove function (line 3074, v1.7.2):

if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
	try { // SVG
		elem.removeEventListener(type, elemData.handle, false);
	}
	catch (e) {
		if (elem.detachEvent) {
			elem.detachEvent("on" + type, elemData.handle);
		}
	}
}

In the event.fix function (line 3394, v1.7.2):

if (event.target.namespaceURI == 'http://www.w3.org/2000/svg') { // SVG
	event.button = [1, 4, 2][event.button];
}

// Add which for click: 1 === left; 2 === middle; 3 === right
// Note: button is not normalized, so don't use it
if ( !event.which && button !== undefined ) {
	event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
}

In the Sizzle function (line 4083, v1.7.2):

if ( toString.call(checkSet) === "[object Array]" ) {
	if ( !prune ) {
		results.push.apply( results, checkSet );

	} else if ( context && context.nodeType === 1 ) {
		for ( i = 0; checkSet[i] != null; i++ ) {
			if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
				results.push( set[i] || set.item(i) ); // SVG
			}
		}

	} else {
		for ( i = 0; checkSet[i] != null; i++ ) {
			if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
				results.push( set[i] || set.item(i) ); // SVG
			}
		}
	}
} else {...

In the fallback for the Sizzle makeArray function (line 4877, v1.7.2):

if ( toString.call(array) === "[object Array]" ) {
	Array.prototype.push.apply( ret, array );

} else {
	if ( typeof array.length === "number" ) {
		for ( var l = array.length; i < l; i++ ) {
			ret.push( array[i] || array.item(i) ); // SVG
		}

	} else {
		for ( ; array[i]; i++ ) {
			ret.push( array[i] );
		}
	}
}

In the jQuery.cleandata function (line 6538, v1.7.2):

if ( deleteExpando ) {
	delete elem[ jQuery.expando ];

} else {
	try { // SVG
		elem.removeAttribute( jQuery.expando );
	} catch (e) {
		// Ignore
	}
}

In the fallback getComputedStyle function (line 6727, v1.7.2):

defaultView = (elem.ownerDocument ? elem.ownerDocument.defaultView : elem.defaultView); // SVG
if ( defaultView &&
		(computedStyle = defaultView.getComputedStyle( elem, null )) ) {

	ret = computedStyle.getPropertyValue( name );
	...

The structure of the sample SVG document below is as follows:

Select

and fill with  

or or click/mouseover 

$('#svgselect').svg({onLoad: function(svg) {
		svg.rect(10, 20, 150, 100, {id: 'rect1',
			fill: 'red', stroke: 'black', strokeWidth: 3});
		svg.circle(100, 150, 75, {id: 'circle1',
			fill: 'yellow', stroke: 'black', strokeWidth: 3});
		var g = svg.group({transform: 'translate(200,20)'});
		svg.circle(g, 100, 100, 75, {id: 'circle2', class_: 'grouped',
			fill: 'yellow', stroke: 'black', strokeWidth: 3});
		svg.rect(g, 10, 150, 150, 100, {id: 'rect2', class_: 'grouped',
			fill: 'red', stroke: 'black', strokeWidth: 3});
		resetSize(svg, '100%', '100%');
	}
});

$('#selectPath').change(function() {
	$('#selector').val($(this).val());
});

$('#fillButton').click(function() {
	var svg = $('#svgselect').svg('get');
	$($('#selector').val(), svg.root()).attr('fill', $('#selectColour').val());
});

$('#eventButton').click(function() {
	var svg = $('#svgselect').svg('get');
	if ($('#selectEventAdd').is(':checked')) {
		$($('#selector').val(), svg.root()).on('click', svgClicked).
			on('mouseover', svgOver).on('mouseout', svgOut);
	}
	else {
		$($('#selector').val(), svg.root()).
			off('click mouseover mouseout');
	}
});

function svgClicked() {
	alert('This is a ' + $(this).attr('fill') + ' ' + this.nodeName);
}

function svgOver() {
	$(this).attr('stroke', 'lime');
}

function svgOut() {
	$(this).attr('stroke', 'black');
}
Tips and Tricks
In the Wild

This tab highlights examples of this plugin in use "in the wild".

To add another example, please contact me (wood.keith{at}optusnet.com.au) and provide the plugin name, the URL of your site, its title, and a short description of its purpose and where/how the plugin is used.

Quick Reference

A list of available fields and functions. For more detail see the documentation reference page.

$(selector).svg({
	loadURL: '', // External document to load
	onLoad: null, // Callback once loaded
	settings: {}, // Additional settings for SVG element
	initPath: ''}) // Initial path for blank document
$(selector).svg(loadURL)
$(selector).svg(onLoad)
$(selector).svg('get') // Retrieve SVG wrapper
$(selector).svg('destroy') // Remove SVG functionality

$.svg.addExtension(name, extClass) // Extend SVG functionality
$.svg.isSVGElem(node)

svg.width()
svg.height()
svg.root()
svg.configure(node, settings, clear)
svg.getElementById(id)
svg.change(element, settings)
svg.title(parent, text, settings)
svg.describe(parent, text, settings)
svg.defs(parent, id, settings)
svg.symbol(parent, id, x1, y1, width, height, settings)
svg.marker(parent, id, refX, refY, mWidth, mHeight, orient, settings)
svg.style(parent, styles, settings)
svg.script(parent, script, type, settings)
svg.linearGradient(parent, id, stops, x1, y1, x2, y2, settings)
svg.radialGradient(parent, id, stops, cx, cy, r, fx, fy, settings)
svg.pattern(parent, id, x, y, width, height, vx, vy, vwidth, vheight, settings)
svg.clipPath(parent, id, units, settings)
svg.mask(parent, id, x, y, width, height, settings)
svg.createPath()
svg.createText()
svg.svg(parent, x, y, width, height, vx, vy, vwidth, vheight, settings)
svg.group(parent, id, settings)
svg.use(parent, x, y, width, height, ref, settings)
svg.link(parent, ref, settings)
svg.image(parent, x, y, width, height, ref, settings)
svg.path(parent, path, settings)
svg.rect(parent, x, y, width, height, rx, ry, settings)
svg.circle(parent, cx, cy, r, settings)
svg.ellipse(parent, cx, cy, rx, ry, settings)
svg.line(parent, x1, y1, x2, y2, settings)
svg.polyline(parent, points, settings)
svg.polygon(parent, points, settings)
svg.text(parent, x, y, value, settings)
svg.textpath(parent, path, value, settings)
svg.other(parent, name, settings)
svg.add(parent, node)
svg.clone(parent, node)
svg.load(url, settings)
svg.remove(node)
svg.clear(attrsToo)
svg.toSVG(node)

path.reset()
path.move(x, y, relative)
path.line(x, y, relative)
path.horiz(x, relative)
path.vert(y, relative)
path.curveC(x1, y1, x2, y2, x, y, relative)
path.smoothC(x2, y2, x, y, relative)
path.curveQ(x1, y1, x, y, relative)
path.smoothQ(x, y, relative)
path.arc(rx, ry, xRotate, large, clockwise, x, y, relative)
path.close()
path.path()

text.reset()
text.string(value)
text.span(value, settings)
text.ref(id, settings)
text.path(id, value, settings)