changeset 1050:301ef9bf1965

update jquery.svg.js
author hertzhaft
date Mon, 26 Mar 2012 08:18:40 +0200
parents 32096eff13c7
children ad769aaea759
files webapp/src/main/webapp/jquery/svg/jquery.svg.js webapp/src/main/webapp/jquery/svg/jquery.svganim.js webapp/src/main/webapp/jquery/svg/jquery.svgdom.js webapp/src/main/webapp/jquery/svg/jquery.svgfilter.js webapp/src/main/webapp/jquery/svg/jquery.svggraph.js webapp/src/main/webapp/jquery/svg/jquery.svgplot.js
diffstat 6 files changed, 361 insertions(+), 178 deletions(-) [+]
line wrap: on
line diff
--- a/webapp/src/main/webapp/jquery/svg/jquery.svg.js	Mon Mar 26 01:01:09 2012 +0200
+++ b/webapp/src/main/webapp/jquery/svg/jquery.svg.js	Mon Mar 26 08:18:40 2012 +0200
@@ -1,5 +1,5 @@
 /* http://keith-wood.name/svg.html
-   SVG for jQuery v1.4.3.
+   SVG for jQuery v1.4.4.
    Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 
@@ -98,8 +98,12 @@
 			if (!svg) {
 				svg = document.createElementNS(this.svgNS, 'svg');
 				svg.setAttribute('version', '1.1');
-				svg.setAttribute('width', container.clientWidth);
-				svg.setAttribute('height', container.clientHeight);
+				if (container.clientWidth > 0) {
+					svg.setAttribute('width', container.clientWidth);
+				}
+				if (container.clientHeight > 0) {
+					svg.setAttribute('height', container.clientHeight);
+				}
 				container.appendChild(svg);
 			}
 			this._afterLoad(container, svg, settings || {});
@@ -111,7 +115,8 @@
 				}
 				this._settings[container.id] = settings;
 				container.innerHTML = '<embed type="image/svg+xml" width="100%" ' +
-					'height="100%" src="' + (settings.initPath || '') + 'blank.svg"/>';
+					'height="100%" src="' + (settings.initPath || '') + 'blank.svg" ' +
+					'pluginspage="http://www.adobe.com/svg/viewer/install/main.html"/>';
 			}
 			else {
 				container.innerHTML = '<p class="svg_error">' +
@@ -198,6 +203,13 @@
 	   @param  extClass  (function) the extension class constructor */
 	addExtension: function(name, extClass) {
 		this._extensions.push([name, extClass]);
+	},
+
+	/* Does this node belong to SVG?
+	   @param  node  (element) the node to be tested
+	   @return  (boolean) true if an SVG node, false if not */
+	isSVGElem: function(node) {
+		return (node.nodeType == 1 && node.namespaceURI == $.svg.svgNS);
 	}
 });
 
@@ -230,23 +242,29 @@
 		return this._svg;
 	},
 
-	/* Configure the SVG root.
+	/* Configure a SVG node.
+	   @param  node      (element, optional) the node to configure
 	   @param  settings  (object) additional settings for the root
 	   @param  clear     (boolean) true to remove existing attributes first,
 	                     false to add to what is already there (optional)
 	   @return  (SVGWrapper) this root */
-	configure: function(settings, clear) {
+	configure: function(node, settings, clear) {
+		if (!node.nodeName) {
+			clear = settings;
+			settings = node;
+			node = this._svg;
+		}
 		if (clear) {
-			for (var i = this._svg.attributes.length - 1; i >= 0; i--) {
-				var attr = this._svg.attributes.item(i);
+			for (var i = node.attributes.length - 1; i >= 0; i--) {
+				var attr = node.attributes.item(i);
 				if (!(attr.nodeName == 'onload' || attr.nodeName == 'version' || 
 						attr.nodeName.substring(0, 5) == 'xmlns')) {
-					this._svg.attributes.removeNamedItem(attr.nodeName);
+					node.attributes.removeNamedItem(attr.nodeName);
 				}
 			}
 		}
 		for (var attrName in settings) {
-			this._svg.setAttribute(attrName, settings[attrName]);
+			node.setAttribute($.svg._attrNames[attrName] || attrName, settings[attrName]);
 		}
 		return this;
 	},
@@ -266,10 +284,10 @@
 		if (element) {
 			for (var name in settings) {
 				if (settings[name] == null) {
-					element.removeAttribute(name);
+					element.removeAttribute($.svg._attrNames[name] || name);
 				}
 				else {
-					element.setAttribute(name, settings[name]);
+					element.setAttribute($.svg._attrNames[name] || name, settings[name]);
 				}
 			}
 		}
@@ -398,7 +416,7 @@
 		var args = this._args(arguments, ['script', 'type'], ['type']);
 		var node = this._makeNode(args.parent, 'script', $.extend(
 			{type: args.type || 'text/javascript'}, args.settings || {}));
-		node.appendChild(this._svg.ownerDocument.createTextNode(this._escapeXML(args.script)));
+		node.appendChild(this._svg.ownerDocument.createTextNode(args.script));
 		if (!$.browser.mozilla) {
 			$.globalEval(args.script);
 		}
@@ -484,6 +502,18 @@
 		return this._makeNode(args.parent, 'pattern', $.extend(sets, args.settings || {}));
 	},
 
+	/* Add a clip path definition.
+	   @param  parent  (element) the parent node for the new element (optional)
+	   @param  id      (string) the ID for this path
+	   @param  units   (string) either 'userSpaceOnUse' (default) or 'objectBoundingBox' (optional)
+	   @return  (element) the new clipPath node */
+	clipPath: function(parent, id, units, settings) {
+		var args = this._args(arguments, ['id', 'units']);
+		args.units = args.units || 'userSpaceOnUse';
+		return this._makeNode(args.parent, 'clipPath', $.extend(
+			{id: args.id, clipPathUnits: args.units}, args.settings || {}));
+	},
+
 	/* Add a mask definition.
 	   @param  parent    (element or jQuery) the parent node for the new mask (optional)
 	   @param  id        (string) the ID for this mask
@@ -804,6 +834,7 @@
 		var args = this._args((arguments.length == 1 ? [null, parent] : arguments), ['node']);
 		var svg = this;
 		args.parent = args.parent || this._svg;
+		args.node = (args.node.jquery ? args.node : $(args.node));
 		try {
 			if ($.svg._renesis) {
 				throw 'Force traversal';
@@ -811,7 +842,6 @@
 			args.parent.appendChild(args.node.cloneNode(true));
 		}
 		catch (e) {
-			args.node = (args.node.jquery ? args.node : $(args.node));
 			args.node.each(function() {
 				var child = svg._cloneAsSVG(this);
 				if (child) {
@@ -822,7 +852,32 @@
 		return this;
 	},
 
-	/* SVG nodes must belong to the SVG namespace, so clone and ensure this is so. */
+	/* Clone an existing SVG node and add it to the diagram.
+	   @param  parent  (element or jQuery) the parent node for the new node (optional)
+	   @param  node    (element) the new node to add or
+	                   (string) the jQuery selector for the node or
+	                   (jQuery collection) set of nodes to add
+	   @return  (element[]) collection of new nodes */
+	clone: function(parent, node) {
+		var svg = this;
+		var args = this._args((arguments.length == 1 ? [null, parent] : arguments), ['node']);
+		args.parent = args.parent || this._svg;
+		args.node = (args.node.jquery ? args.node : $(args.node));
+		var newNodes = [];
+		args.node.each(function() {
+			var child = svg._cloneAsSVG(this);
+			if (child) {
+				child.id = '';
+				args.parent.appendChild(child);
+				newNodes.push(child);
+			}
+		});
+		return newNodes;
+	},
+
+	/* SVG nodes must belong to the SVG namespace, so clone and ensure this is so.
+	   @param  node  (element) the SVG node to clone
+	   @return  (element) the cloned node */
 	_cloneAsSVG: function(node) {
 		var newNode = null;
 		if (node.nodeType == 1) { // element
@@ -832,7 +887,8 @@
 				var attr = node.attributes.item(i);
 				if (attr.nodeName != 'xmlns' && attr.nodeValue) {
 					if (attr.prefix == 'xlink') {
-						newNode.setAttributeNS($.svg.xlinkNS, attr.localName, attr.nodeValue);
+						newNode.setAttributeNS($.svg.xlinkNS,
+							attr.localName || attr.baseName, attr.nodeValue);
 					}
 					else {
 						newNode.setAttribute(this._checkName(attr.nodeName), attr.nodeValue);
@@ -886,11 +942,17 @@
 	                       onLoad      (function) callback after the document has loaded,
 	                                   'this' is the container, receives SVG object and
 	                                   optional error message as a parameter
+	                       parent      (string or element or jQuery) the parent to load
+	                                   into, defaults to top-level svg element
 	   @return  (SVGWrapper) this root */
 	load: function(url, settings) {
-		settings = (typeof settings == 'boolean'? {addTo: settings} :
-			(typeof settings == 'function'? {onLoad: settings} : settings || {}));
-		if (!settings.addTo) {
+		settings = (typeof settings == 'boolean' ? {addTo: settings} :
+			(typeof settings == 'function' ? {onLoad: settings} :
+			(typeof settings == 'string' ? {parent: settings} : 
+			(typeof settings == 'object' && settings.nodeName ? {parent: settings} :
+			(typeof settings == 'object' && settings.jquery ? {parent: settings} :
+			settings || {})))));
+		if (!settings.parent && !settings.addTo) {
 			this.clear(false);
 		}
 		var size = [this._svg.getAttribute('width'), this._svg.getAttribute('height')];
@@ -930,6 +992,7 @@
 					(messages.length ? messages[0] : errors[0]).firstChild.nodeValue);
 				return;
 			}
+			var parent = (settings.parent ? $(settings.parent)[0] : wrapper._svg);
 			var attrs = {};
 			for (var i = 0; i < data.documentElement.attributes.length; i++) {
 				var attr = data.documentElement.attributes.item(i);
@@ -937,24 +1000,24 @@
 					attrs[attr.nodeName] = attr.nodeValue;
 				}
 			}
-			wrapper.configure(attrs, true);
+			wrapper.configure(parent, attrs, !settings.parent);
 			var nodes = data.documentElement.childNodes;
 			for (var i = 0; i < nodes.length; i++) {
 				try {
 					if ($.svg._renesis) {
 						throw 'Force traversal';
 					}
-					wrapper._svg.appendChild(nodes[i].cloneNode(true));
+					parent.appendChild(wrapper._svg.ownerDocument.importNode(nodes[i], true));
 					if (nodes[i].nodeName == 'script') {
 						$.globalEval(nodes[i].textContent);
 					}
 				}
 				catch (e) {
-					wrapper.add(null, nodes[i]);
+					wrapper.add(parent, nodes[i]);
 				}
 			}
 			if (!settings.changeSize) {
-				wrapper.configure({width: size[0], height: size[1]});
+				wrapper.configure(parent, {width: size[0], height: size[1]});
 			}
 			if (settings.onLoad) {
 				settings.onLoad.apply(wrapper._container || wrapper._svg, [wrapper]);
@@ -1045,14 +1108,6 @@
 			}
 		}
 		return svgDoc;
-	},
-	
-	/* Escape reserved characters in XML. */
-	_escapeXML: function(text) {
-		text = text.replace(/&/g, '&amp;');
-		text = text.replace(/</g, '&lt;');
-		text = text.replace(/>/g, '&gt;');
-		return text;
 	}
 });
 
--- a/webapp/src/main/webapp/jquery/svg/jquery.svganim.js	Mon Mar 26 01:01:09 2012 +0200
+++ b/webapp/src/main/webapp/jquery/svg/jquery.svganim.js	Mon Mar 26 08:18:40 2012 +0200
@@ -1,5 +1,5 @@
 /* http://keith-wood.name/svg.html
-   SVG attribute animations for jQuery v1.4.3.
+   SVG attribute animations for jQuery v1.4.4.
    Written by Keith Wood (kbwood{at}iinet.com.au) June 2008.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 
@@ -11,18 +11,23 @@
 // named as svg-* or svg* (with first character upper case)
 $.each(['x', 'y', 'width', 'height', 'rx', 'ry', 'cx', 'cy', 'r', 'x1', 'y1', 'x2', 'y2',
 		'stroke-width', 'strokeWidth', 'opacity', 'fill-opacity', 'fillOpacity',
-		'stroke-opacity', 'strokeOpacity', 'font-size', 'fontSize'],
+		'stroke-opacity', 'strokeOpacity', 'stroke-dashoffset', 'strokeDashOffset',
+		'font-size', 'fontSize', 'font-weight', 'fontWeight',
+		'letter-spacing', 'letterSpacing', 'word-spacing', 'wordSpacing'],
 	function(i, attrName) {
 		var ccName = attrName.charAt(0).toUpperCase() + attrName.substr(1);
+		if ($.cssProps) {
+			$.cssProps['svg' + ccName] = $.cssProps['svg-' + attrName] = attrName;
+		}
 		$.fx.step['svg' + ccName] = $.fx.step['svg-' + attrName] = function(fx) {
 			var realAttrName = $.svg._attrNames[attrName] || attrName;
 			var attr = fx.elem.attributes.getNamedItem(realAttrName);
 			if (!fx.set) {
 				fx.start = (attr ? parseFloat(attr.nodeValue) : 0);
-				var offset = fx.options.curAnim['svg-' + attrName] ||
-					fx.options.curAnim['svg' + ccName];
+				var offset = ($.fn.jquery >= '1.6' ? '' :
+					fx.options.curAnim['svg' + ccName] || fx.options.curAnim['svg-' + attrName]);
 				if (/^[+-]=/.exec(offset)) {
-					fx.end = fx.start + parseFloat(offset.replace(/=/, ''));
+					fx.end = fx.start + parseFloat(offset.replace(/=/, ''));
 				}
 				$(fx.elem).css(realAttrName, '');
 				fx.set = true;
@@ -32,16 +37,69 @@
 		};
 	}
 );
+
+// Enable animation for the SVG strokeDashArray attribute
+$.fx.step['svgStrokeDashArray'] = $.fx.step['svg-strokeDashArray'] =
+$.fx.step['svgStroke-dasharray'] = $.fx.step['svg-stroke-dasharray'] = function(fx) {
+	var attr = fx.elem.attributes.getNamedItem('stroke-dasharray');
+	if (!fx.set) {
+		fx.start = parseDashArray(attr ? attr.nodeValue : '');
+		var offset = ($.fn.jquery >= '1.6' ? fx.end :
+			fx.options.curAnim['svgStrokeDashArray'] || fx.options.curAnim['svg-strokeDashArray'] ||
+			fx.options.curAnim['svgStroke-dasharray'] || fx.options.curAnim['svg-stroke-dasharray']);
+		fx.end = parseDashArray(offset);
+		if (/^[+-]=/.exec(offset)) {
+			offset = offset.split(/[, ]+/);
+			if (offset.length % 2 == 1) { // Must have an even number
+				var len = offset.length;
+				for (var i = 0; i < len; i++) { // So repeat
+					offset.push(offset[i]);
+				}
+			}
+			for (var i = 0; i < offset.length; i++) {
+				if (/^[+-]=/.exec(offset[i])) {
+					fx.end[i] = fx.start[i] + parseFloat(offset[i].replace(/=/, ''));
+				}
+			}
+		}
+		fx.set = true;
+	}
+	var value = $.map(fx.start, function(n, i) {
+		return (fx.pos * (fx.end[i] - n) + n);
+	}).join(',');
+	(attr ? attr.nodeValue = value : fx.elem.setAttribute('stroke-dasharray', value));
+};
+
+/* Parse a strokeDashArray definition: dash, gap, ...
+   @param  value  (string) the definition
+   @return  (number[2n]) the extracted values */
+function parseDashArray(value) {
+	var dashArray = value.split(/[, ]+/);
+	for (var i = 0; i < dashArray.length; i++) {
+		dashArray[i] = parseFloat(dashArray[i]);
+		if (isNaN(dashArray[i])) {
+			dashArray[i] = 0;
+		}
+	}
+	if (dashArray.length % 2 == 1) { // Must have an even number
+		var len = dashArray.length;
+		for (var i = 0; i < len; i++) { // So repeat
+			dashArray.push(dashArray[i]);
+		}
+	}
+	return dashArray;
+}
 
 // Enable animation for the SVG viewBox attribute
 $.fx.step['svgViewBox'] = $.fx.step['svg-viewBox'] = function(fx) {
 	var attr = fx.elem.attributes.getNamedItem('viewBox');
 	if (!fx.set) {
 		fx.start = parseViewBox(attr ? attr.nodeValue : '');
-		var offset = fx.options.curAnim['svg-viewBox'] || fx.options.curAnim['svgViewBox'];
+		var offset = ($.fn.jquery >= '1.6' ? fx.end :
+			fx.options.curAnim['svgViewBox'] || fx.options.curAnim['svg-viewBox']);
 		fx.end = parseViewBox(offset);
 		if (/^[+-]=/.exec(offset)) {
-			offset = offset.split(' ');
+			offset = offset.split(/[, ]+/);
 			while (offset.length < 4) {
 				offset.push('0');
 			}
@@ -63,7 +121,7 @@
    @param  value  (string) the definition
    @return  (number[4]) the extracted values */
 function parseViewBox(value) {
-	var viewBox = value.split(' ');
+	var viewBox = value.split(/[, ]+/);
 	for (var i = 0; i < viewBox.length; i++) {
 		viewBox[i] = parseFloat(viewBox[i]);
 		if (isNaN(viewBox[i])) {
@@ -84,32 +142,31 @@
 		fx.end = parseTransform(fx.end, fx.start);
 		fx.set = true;
 	}
-	var transform = '';
+	var transform = '';
 	for (var i = 0; i < fx.end.order.length; i++) {
 		switch (fx.end.order.charAt(i)) {
 			case 't':
-				transform += (fx.start.translateX != fx.end.translateX || fx.start.translateY != fx.end.translateY ?
-					' translate(' + (fx.pos * (fx.end.translateX - fx.start.translateX) + fx.start.translateX) + ',' +
-					(fx.pos * (fx.end.translateY - fx.start.translateY) + fx.start.translateY) + ')' : '');
+				transform += ' translate(' +
+					(fx.pos * (fx.end.translateX - fx.start.translateX) + fx.start.translateX) + ',' +
+					(fx.pos * (fx.end.translateY - fx.start.translateY) + fx.start.translateY) + ')';
 				break;
 			case 's':
-				transform += (fx.start.scaleX != fx.end.scaleX || fx.start.scaleY != fx.end.scaleY ? 
-					' scale(' + (fx.pos * (fx.end.scaleX - fx.start.scaleX) + fx.start.scaleX) + ',' +
-					(fx.pos * (fx.end.scaleY - fx.start.scaleY) + fx.start.scaleY) + ')' : '');
+				transform += ' scale(' +
+					(fx.pos * (fx.end.scaleX - fx.start.scaleX) + fx.start.scaleX) + ',' +
+					(fx.pos * (fx.end.scaleY - fx.start.scaleY) + fx.start.scaleY) + ')';
 				break;
 			case 'r':
-				transform += (fx.start.rotateA != fx.end.rotateA ||
-					fx.start.rotateX != fx.end.rotateX || fx.start.rotateY != fx.end.rotateY ?
-					' rotate(' + (fx.pos * (fx.end.rotateA - fx.start.rotateA) + fx.start.rotateA) + ',' +
+				transform += ' rotate(' +
+					(fx.pos * (fx.end.rotateA - fx.start.rotateA) + fx.start.rotateA) + ',' +
 					(fx.pos * (fx.end.rotateX - fx.start.rotateX) + fx.start.rotateX) + ',' +
-					(fx.pos * (fx.end.rotateY - fx.start.rotateY) + fx.start.rotateY) + ')' : '');
+					(fx.pos * (fx.end.rotateY - fx.start.rotateY) + fx.start.rotateY) + ')';
 				break;
 			case 'x':
-				transform += (fx.start.skewX != fx.end.skewX ?
-					' skewX(' + (fx.pos * (fx.end.skewX - fx.start.skewX) + fx.start.skewX) + ')' : '');
+				transform += ' skewX(' +
+					(fx.pos * (fx.end.skewX - fx.start.skewX) + fx.start.skewX) + ')';
 			case 'y':
-				transform += (fx.start.skewY != fx.end.skewY ?
-					' skewY(' + (fx.pos * (fx.end.skewY - fx.start.skewY) + fx.start.skewY) + ')' : '');
+				transform += ' skewY(' +
+					(fx.pos * (fx.end.skewY - fx.start.skewY) + fx.start.skewY) + ')';
 				break;
 			case 'm':
 				var matrix = '';
@@ -131,7 +188,7 @@
 	value = value || '';
 	if (typeof value == 'object') {
 		value = value.nodeValue;
-	}
+	}
 	var transform = $.extend({translateX: 0, translateY: 0, scaleX: 0, scaleY: 0,
 		rotateA: 0, rotateX: 0, rotateY: 0, skewX: 0, skewY: 0,
 		matrix: [0, 0, 0, 0, 0, 0]}, original || {});
@@ -172,7 +229,18 @@
 				break;
 		}
 		result = pattern.exec(value);
-	}
+	}
+	if (transform.order == 'm' && Math.abs(transform.matrix[0]) == Math.abs(transform.matrix[3]) &&
+			transform.matrix[1] != 0 && Math.abs(transform.matrix[1]) == Math.abs(transform.matrix[2])) {
+		// Simple rotate about origin and translate
+		var angle = Math.acos(transform.matrix[0]) * 180 / Math.PI;
+		angle = (transform.matrix[1] < 0 ? 360 - angle : angle);
+		transform.order = 'rt';
+		transform.rotateA = angle;
+		transform.rotateX = transform.rotateY = 0;
+		transform.translateX = transform.matrix[4];
+		transform.translateY = transform.matrix[5];
+	}
 	return transform;
 }
 
@@ -182,9 +250,9 @@
 		var ccName = attrName.charAt(0).toUpperCase() + attrName.substr(1);
 		$.fx.step['svg' + ccName] = $.fx.step['svg-' + attrName] = function(fx) {
 			if (!fx.set) {
-				fx.start = getColour(fx.elem, attrName);
+				fx.start = $.svg._getColour(fx.elem, attrName);
 				var toNone = (fx.end == 'none');
-				fx.end = (toNone ? getColour(fx.elem.parentNode, attrName) : getRGB(fx.end));
+				fx.end = (toNone ? $.svg._getColour(fx.elem.parentNode, attrName) : $.svg._getRGB(fx.end));
 				fx.end[3] = toNone;
 				$(fx.elem).css(attrName, '');
 				fx.set = true;
@@ -205,49 +273,49 @@
    @param  elem  (element) the starting element to find the attribute
    @param  attr  (string) the attribute name
    @return  (number[3]) RGB components for the attribute colour */
-function getColour(elem, attr) {
+$.svg._getColour = function(elem, attr) {
+	elem = $(elem);
 	var colour;
 	do {
-		colour = (elem.attributes && elem.attributes.getNamedItem(attr) ?
-			elem.attributes.getNamedItem(attr).nodeValue : '');
+		colour = elem.attr(attr) || elem.css(attr);
 		// Keep going until we find an element that has colour, or exit SVG
-		if ((colour != '' && colour != 'none') || $(elem).hasClass('hasSVG')) {
+		if ((colour != '' && colour != 'none') || elem.hasClass('hasSVG')) {
 			break; 
 		}
-	} while (elem = elem.parentNode);
-	return getRGB(colour);
-}
+	} while (elem = elem.parent());
+	return $.svg._getRGB(colour);
+};
 
 /* Parse strings looking for common colour formats.
    @param  colour  (string) colour description to parse
    @return  (number[3]) RGB components of this colour */
-function getRGB(colour) {
+$.svg._getRGB = function(colour) {
 	var result;
 	// Check if we're already dealing with an array of colors
-	if (colour && colour.constructor == Array && (colour.length == 3 || colour.length == 4)) {
-		return colour;
+	if (colour && colour.constructor == Array) {
+		return (colour.length == 3 || colour.length == 4 ? colour : colours['none']);
 	}
 	// Look for rgb(num,num,num)
-	if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(colour)) {
+	if (result = /^rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)$/.exec(colour)) {
 		return [parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)];
 	}
 	// Look for rgb(num%,num%,num%)
-	if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(colour)) {
+	if (result = /^rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)$/.exec(colour)) {
 		return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55,
 			parseFloat(result[3]) * 2.55];
 	}
 	// Look for #a0b1c2
-	if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(colour)) {
+	if (result = /^#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})$/.exec(colour)) {
 		return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)];
 	}
 	// Look for #abc
-	if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(colour)) {
+	if (result = /^#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])$/.exec(colour)) {
 		return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16),
 			parseInt(result[3] + result[3], 16)];
 	}
 	// Otherwise, we're most likely dealing with a named color
 	return colours[$.trim(colour).toLowerCase()] || colours['none'];
-}
+};
 
 // The SVG named colours
 var colours = {
@@ -255,52 +323,52 @@
 	none:					[255, 255, 255, 1],
 	aliceblue:				[240, 248, 255],
 	antiquewhite:			[250, 235, 215],
-	aqua:					[ 0, 255, 255],
+	aqua:					[0, 255, 255],
 	aquamarine:				[127, 255, 212],
 	azure:					[240, 255, 255],
 	beige:					[245, 245, 220],
 	bisque:					[255, 228, 196],
-	black:					[ 0, 0, 0],
+	black:					[0, 0, 0],
 	blanchedalmond:			[255, 235, 205],
-	blue:					[ 0, 0, 255],
+	blue:					[0, 0, 255],
 	blueviolet:				[138, 43, 226],
 	brown:					[165, 42, 42],
 	burlywood:				[222, 184, 135],
-	cadetblue:				[ 95, 158, 160],
+	cadetblue:				[95, 158, 160],
 	chartreuse:				[127, 255, 0],
 	chocolate:				[210, 105, 30],
 	coral:					[255, 127, 80],
 	cornflowerblue:			[100, 149, 237],
 	cornsilk:				[255, 248, 220],
 	crimson:				[220, 20, 60],
-	cyan:					[ 0, 255, 255],
-	darkblue:				[ 0, 0, 139],
-	darkcyan:				[ 0, 139, 139],
+	cyan:					[0, 255, 255],
+	darkblue:				[0, 0, 139],
+	darkcyan:				[0, 139, 139],
 	darkgoldenrod:			[184, 134, 11],
 	darkgray:				[169, 169, 169],
-	darkgreen:				[ 0, 100, 0],
+	darkgreen:				[0, 100, 0],
 	darkgrey:				[169, 169, 169],
 	darkkhaki:				[189, 183, 107],
 	darkmagenta:			[139, 0, 139],
-	darkolivegreen:			[ 85, 107, 47],
+	darkolivegreen:			[85, 107, 47],
 	darkorange:				[255, 140, 0],
 	darkorchid:				[153, 50, 204],
 	darkred:				[139, 0, 0],
 	darksalmon:				[233, 150, 122],
 	darkseagreen:			[143, 188, 143],
-	darkslateblue:			[ 72, 61, 139],
-	darkslategray:			[ 47, 79, 79],
-	darkslategrey:			[ 47, 79, 79],
-	darkturquoise:			[ 0, 206, 209],
+	darkslateblue:			[72, 61, 139],
+	darkslategray:			[47, 79, 79],
+	darkslategrey:			[47, 79, 79],
+	darkturquoise:			[0, 206, 209],
 	darkviolet:				[148, 0, 211],
 	deeppink:				[255, 20, 147],
-	deepskyblue:			[ 0, 191, 255],
+	deepskyblue:			[0, 191, 255],
 	dimgray:				[105, 105, 105],
 	dimgrey:				[105, 105, 105],
-	dodgerblue:				[ 30, 144, 255],
+	dodgerblue:				[30, 144, 255],
 	firebrick:				[178, 34, 34],
 	floralwhite:			[255, 250, 240],
-	forestgreen:			[ 34, 139, 34],
+	forestgreen:			[34, 139, 34],
 	fuchsia:				[255, 0, 255],
 	gainsboro:				[220, 220, 220],
 	ghostwhite:				[248, 248, 255],
@@ -308,12 +376,12 @@
 	goldenrod:				[218, 165, 32],
 	gray:					[128, 128, 128],
 	grey:					[128, 128, 128],
-	green:					[ 0, 128, 0],
+	green:					[0, 128, 0],
 	greenyellow:			[173, 255, 47],
 	honeydew:				[240, 255, 240],
 	hotpink:				[255, 105, 180],
 	indianred:				[205, 92, 92],
-	indigo:					[ 75, 0, 130],
+	indigo:					[75, 0, 130],
 	ivory:					[255, 255, 240],
 	khaki:					[240, 230, 140],
 	lavender:				[230, 230, 250],
@@ -329,32 +397,32 @@
 	lightgrey:				[211, 211, 211],
 	lightpink:				[255, 182, 193],
 	lightsalmon:			[255, 160, 122],
-	lightseagreen:			[ 32, 178, 170],
+	lightseagreen:			[32, 178, 170],
 	lightskyblue:			[135, 206, 250],
 	lightslategray:			[119, 136, 153],
 	lightslategrey:			[119, 136, 153],
 	lightsteelblue:			[176, 196, 222],
 	lightyellow:			[255, 255, 224],
-	lime:					[ 0, 255, 0],
-	limegreen:				[ 50, 205, 50],
+	lime:					[0, 255, 0],
+	limegreen:				[50, 205, 50],
 	linen:					[250, 240, 230],
 	magenta:				[255, 0, 255],
 	maroon:					[128, 0, 0],
 	mediumaquamarine:		[102, 205, 170],
-	mediumblue:				[ 0, 0, 205],
+	mediumblue:				[0, 0, 205],
 	mediumorchid:			[186, 85, 211],
 	mediumpurple:			[147, 112, 219],
-	mediumseagreen:			[ 60, 179, 113],
+	mediumseagreen:			[60, 179, 113],
 	mediumslateblue:		[123, 104, 238],
-	mediumspringgreen:		[ 0, 250, 154],
-	mediumturquoise:		[ 72, 209, 204],
+	mediumspringgreen:		[0, 250, 154],
+	mediumturquoise:		[72, 209, 204],
 	mediumvioletred:		[199, 21, 133],
-	midnightblue:			[ 25, 25, 112],
+	midnightblue:			[25, 25, 112],
 	mintcream:				[245, 255, 250],
 	mistyrose:				[255, 228, 225],
 	moccasin:				[255, 228, 181],
 	navajowhite:			[255, 222, 173],
-	navy:					[ 0, 0, 128],
+	navy:					[0, 0, 128],
 	oldlace:				[253, 245, 230],
 	olive:					[128, 128, 0],
 	olivedrab:				[107, 142, 35],
@@ -374,11 +442,11 @@
 	purple:					[128, 0, 128],
 	red:					[255, 0, 0],
 	rosybrown:				[188, 143, 143],
-	royalblue:				[ 65, 105, 225],
+	royalblue:				[65, 105, 225],
 	saddlebrown:			[139, 69, 19],
 	salmon:					[250, 128, 114],
 	sandybrown:				[244, 164, 96],
-	seagreen:				[ 46, 139, 87],
+	seagreen:				[46, 139, 87],
 	seashell:				[255, 245, 238],
 	sienna:					[160, 82, 45],
 	silver:					[192, 192, 192],
@@ -387,13 +455,13 @@
 	slategray:				[112, 128, 144],
 	slategrey:				[112, 128, 144],
 	snow:					[255, 250, 250],
-	springgreen:			[ 0, 255, 127],
-	steelblue:				[ 70, 130, 180],
+	springgreen:			[0, 255, 127],
+	steelblue:				[70, 130, 180],
 	tan:					[210, 180, 140],
-	teal:					[ 0, 128, 128],
+	teal:					[0, 128, 128],
 	thistle:				[216, 191, 216],
 	tomato:					[255, 99, 71],
-	turquoise:				[ 64, 224, 208],
+	turquoise:				[64, 224, 208],
 	violet:					[238, 130, 238],
 	wheat:					[245, 222, 179],
 	white:					[255, 255, 255],
--- a/webapp/src/main/webapp/jquery/svg/jquery.svgdom.js	Mon Mar 26 01:01:09 2012 +0200
+++ b/webapp/src/main/webapp/jquery/svg/jquery.svgdom.js	Mon Mar 26 08:18:40 2012 +0200
@@ -1,5 +1,5 @@
-/* http://keith-wood.name/svg.html
-   SVG/jQuery DOM compatibility for jQuery v1.4.3.
+/* http://keith-wood.name/svg.html
+   jQuery DOM compatibility for jQuery SVG v1.4.4.
    Written by Keith Wood (kbwood{at}iinet.com.au) April 2009.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 
@@ -12,7 +12,7 @@
 	return function(classNames) {
 		classNames = classNames || '';
 		return this.each(function() {
-			if (isSVGElem(this)) {
+			if ($.svg.isSVGElem(this)) {
 				var node = this;
 				$.each(classNames.split(/\s+/), function(i, className) {
 					var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));
@@ -35,7 +35,7 @@
 	return function(classNames) {
 		classNames = classNames || '';
 		return this.each(function() {
-			if (isSVGElem(this)) {
+			if ($.svg.isSVGElem(this)) {
 				var node = this;
 				$.each(classNames.split(/\s+/), function(i, className) {
 					var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));
@@ -56,7 +56,7 @@
 $.fn.toggleClass = function(origToggleClass) {
 	return function(className, state) {
 		return this.each(function() {
-			if (isSVGElem(this)) {
+			if ($.svg.isSVGElem(this)) {
 				if (typeof state !== 'boolean') {
 					state = !$(this).hasClass(className);
 				}
@@ -75,7 +75,7 @@
 		className = className || '';
 		var found = false;
 		this.each(function() {
-			if (isSVGElem(this)) {
+			if ($.svg.isSVGElem(this)) {
 				var classes = (this.className ? this.className.baseVal :
 					this.getAttribute('class')).split(/\s+/);
 				found = ($.inArray(className, classes) > -1);
@@ -94,34 +94,40 @@
 	return function(name, value, type) {
 		if (typeof name === 'string' && value === undefined) {
 			var val = origAttr.apply(this, [name, value, type]);
-			if (val && val.baseVal && val.baseVal.numberOfItems != null) { // Transform
+			if (val && val.baseVal && val.baseVal.numberOfItems != null) { // Multiple values
 				value = '';
 				val = val.baseVal;
-				for (var i = 0; i < val.numberOfItems; i++) {
-					var item = val.getItem(i);
-					switch (item.type) {
-						case 1: value += ' matrix(' + item.matrix.a + ',' + item.matrix.b + ',' +
-									item.matrix.c + ',' + item.matrix.d + ',' +
-									item.matrix.e + ',' + item.matrix.f + ')';
-								break;
-						case 2: value += ' translate(' + item.matrix.e + ',' + item.matrix.f + ')'; break;
-						case 3: value += ' scale(' + item.matrix.a + ',' + item.matrix.d + ')'; break;
-						case 4: value += ' rotate(' + item.angle + ')'; break; // Doesn't handle new origin
-						case 5: value += ' skewX(' + item.angle + ')'; break;
-						case 6: value += ' skewY(' + item.angle + ')'; break;
+				if (name == 'transform') {
+					for (var i = 0; i < val.numberOfItems; i++) {
+						var item = val.getItem(i);
+						switch (item.type) {
+							case 1: value += ' matrix(' + item.matrix.a + ',' + item.matrix.b + ',' +
+										item.matrix.c + ',' + item.matrix.d + ',' +
+										item.matrix.e + ',' + item.matrix.f + ')';
+									break;
+							case 2: value += ' translate(' + item.matrix.e + ',' + item.matrix.f + ')'; break;
+							case 3: value += ' scale(' + item.matrix.a + ',' + item.matrix.d + ')'; break;
+							case 4: value += ' rotate(' + item.angle + ')'; break; // Doesn't handle new origin
+							case 5: value += ' skewX(' + item.angle + ')'; break;
+							case 6: value += ' skewY(' + item.angle + ')'; break;
+						}
 					}
+					val = value.substring(1);
 				}
-				val = value.substring(1);
+				else {
+					val = val.getItem(0).valueAsString;
+				}
 			}
 			return (val && val.baseVal ? val.baseVal.valueAsString : val);
 		}
+
 		var options = name;
 		if (typeof name === 'string') {
 			options = {};
 			options[name] = value;
 		}
 		return this.each(function() {
-			if (isSVGElem(this)) {
+			if ($.svg.isSVGElem(this)) {
 				for (var n in options) {
 					var val = ($.isFunction(options[n]) ? options[n]() : options[n]);
 					(type ? this.style[n] = val : this.setAttribute(n, val));
@@ -138,7 +144,7 @@
 $.fn.removeAttr = function(origRemoveAttr) {
 	return function(name) {
 		return this.each(function() {
-			if (isSVGElem(this)) {
+			if ($.svg.isSVGElem(this)) {
 				(this[name] && this[name].baseVal ? this[name].baseVal.value = '' :
 					this.setAttribute(name, ''));
 			}
@@ -149,6 +155,23 @@
 	};
 }($.fn.removeAttr);
 
+/* Add numeric only properties. */
+$.extend($.cssNumber, {
+	'stopOpacity': true,
+	'strokeMitrelimit': true,
+	'strokeOpacity': true
+});
+
+/* Support retrieving CSS/attribute values on SVG nodes. */
+if ($.cssProps) {
+	$.css = function(origCSS) {
+		return function(elem, name) {
+			var value = (name.match(/^svg.*/) ? $(elem).attr($.cssProps[name] || name) : '');
+			return value || origCSS(elem, name);
+		};
+	}($.css);
+}
+  
 /* Determine if any nodes are SVG nodes. */
 function anySVG(checkSet) {
 	for (var i = 0; i < checkSet.length; i++) {
@@ -187,7 +210,7 @@
 
 $.expr.find.ID = function(origFindId) {
 	return function(match, context, isXML) {
-		return (isSVGElem(context) ?
+		return ($.svg.isSVGElem(context) ?
 			[context.ownerDocument.getElementById(match[1])] :
 			origFindId(match, context, isXML));
 	};
@@ -227,7 +250,7 @@
 			}
 		}
 		if (elem) {
-			var className = (!isSVGElem(elem) ? elem.className :
+			var className = (!$.svg.isSVGElem(elem) ? elem.className :
 				(elem.className ? elem.className.baseVal : '') || elem.getAttribute('class'));
 			if (not ^ (className && (' ' + className + ' ').indexOf(match) > -1)) {
 				if (!inplace)
@@ -242,7 +265,7 @@
 };
 
 $.expr.filter.CLASS = function(elem, match) {
-	var className = (!isSVGElem(elem) ? elem.className :
+	var className = (!$.svg.isSVGElem(elem) ? elem.className :
 		(elem.className ? elem.className.baseVal : elem.getAttribute('class')));
 	return (' ' + className + ' ').indexOf(match) > -1;
 };
@@ -250,7 +273,7 @@
 $.expr.filter.ATTR = function(origFilterAttr) {
 	return function(elem, match) {
 		var handler = null;
-		if (isSVGElem(elem)) {
+		if ($.svg.isSVGElem(elem)) {
 			handler = match[1];
 			$.expr.attrHandle[handler] = function(elem){
 				var attr = elem.getAttribute(handler);
@@ -266,67 +289,104 @@
 }($.expr.filter.ATTR);
 
 /*
-	Change Sizzle initialisation (line 1425) in jQuery v1.3.2 base code...
-	
+	In the event.add function (line 2646, v1.6.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 2776, v1.6.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 3036, v.1.6.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 && event.button !== undefined ) {
+			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+		}
+
+	In the Sizzle function (line 3873, v1.6.2):
+
 	if ( toString.call(checkSet) === "[object Array]" ) {
 		if ( !prune ) {
 			results.push.apply( results, checkSet );
-		} else if ( context.nodeType === 1 ) {
-			for ( var i = 0; checkSet[i] != null; i++ ) {
-				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
-					results.push( set[i] || set.item(i) ); // Here
+
+		} 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 ( var i = 0; checkSet[i] != null; i++ ) {
+			for ( i = 0; checkSet[i] != null; i++ ) {
 				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
-					results.push( set[i] || set.item(i) ); // Here
+					results.push( set[i] || set.item(i) ); // SVG
 				}
 			}
 		}
-	}
-	
-	Change fallback makeArray (line 2076) implementation in jQuery Sizzle...
-	
+
+	} else {
+
+	In the fallback for the Sizzle makeArray function (line 4617, v1.6.2):
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+
+		} else {
 			if ( typeof array.length === "number" ) {
-				for ( var i = 0, l = array.length; i < l; i++ ) {
-					ret.push( array[i] || array.item(i) ); // Here
+				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] );
 				}
 			}
-*/
+		}
 
-/*
-	Events management requires changes to jQuery v1.3.2 base code...
+	In the jQuery.cleanData function (line 6220, v1.6.2)
 
-	In $.event.add (line 2437)...
-	
-				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
-					// Bind the global event handler to the element
-					try { // Here
-						elem.addEventListener(type, handle, false);
-					}
-					catch(e) {
-						if (elem.attachEvent)
-							elem.attachEvent("on" + type, handle);
+				if ( deleteExpando ) {
+					delete elem[ jQuery.expando ];
+
+				} else {
+					try { // SVG
+						elem.removeAttribute( jQuery.expando );
+					} catch (e) {
+						// Ignore
 					}
 				}
 
-	In $.event.remove (line 2521)...
-	
-							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
-								try { // Here
-									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
-								}
-								catch (e) {
-									if (elem.detachEvent)
-										elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
-								}
-							}
+	In the fallback getComputedStyle function (line 6509, v.1.6.2)
+
+		defaultView = (elem.ownerDocument ? elem.ownerDocument.defaultView : elem.defaultView); // SVG
+		if ( !defaultView ) {
+			return undefined;
+		}
+
 */
 
-/* Does this node belong to SVG? */
-function isSVGElem(node) {
-	return (node.nodeType == 1 && node.namespaceURI == $.svg.svgNS);
-}
-
 })(jQuery);
--- a/webapp/src/main/webapp/jquery/svg/jquery.svgfilter.js	Mon Mar 26 01:01:09 2012 +0200
+++ b/webapp/src/main/webapp/jquery/svg/jquery.svgfilter.js	Mon Mar 26 08:18:40 2012 +0200
@@ -1,5 +1,5 @@
 /* http://keith-wood.name/svg.html
-   SVG filters for jQuery v1.4.3.
+   SVG filters for jQuery v1.4.4.
    Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
--- a/webapp/src/main/webapp/jquery/svg/jquery.svggraph.js	Mon Mar 26 01:01:09 2012 +0200
+++ b/webapp/src/main/webapp/jquery/svg/jquery.svggraph.js	Mon Mar 26 08:18:40 2012 +0200
@@ -1,5 +1,5 @@
 /* http://keith-wood.name/svg.html
-   SVG graphing extension for jQuery v1.4.3.
+   SVG graphing extension for jQuery v1.4.4.
    Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
--- a/webapp/src/main/webapp/jquery/svg/jquery.svgplot.js	Mon Mar 26 01:01:09 2012 +0200
+++ b/webapp/src/main/webapp/jquery/svg/jquery.svgplot.js	Mon Mar 26 08:18:40 2012 +0200
@@ -1,5 +1,5 @@
 /* http://keith-wood.name/svg.html
-   SVG plotting extension for jQuery v1.4.3.
+   SVG plotting extension for jQuery v1.4.4.
    Written by Keith Wood (kbwood{at}iinet.com.au) December 2008.
    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.