From 82f6162b9ac69ea3b87c1b4533c15060f427cdd6 Mon Sep 17 00:00:00 2001 From: Keith Wood Date: Sun, 2 Nov 2014 17:14:35 +1100 Subject: [PATCH] Release 1.5.0 --- blank.svg | 3 - jquery.svg.css | 9 +- jquery.svg.js | 1236 ++++++++++++++++++-------------------- jquery.svg.min.js | 9 +- jquery.svg.pack.js | 7 - jquery.svganim.js | 98 ++- jquery.svganim.min.js | 9 +- jquery.svganim.pack.js | 7 - jquery.svgdom.js | 379 ++++-------- jquery.svgdom.min.js | 9 +- jquery.svgdom.pack.js | 7 - jquery.svgfilter.js | 464 +++++++------- jquery.svgfilter.min.js | 9 +- jquery.svgfilter.pack.js | 7 - jquery.svggraph.js | 933 ++++++++++++++-------------- jquery.svggraph.min.js | 9 +- jquery.svggraph.pack.js | 7 - jquery.svgplot.js | 554 +++++++++-------- jquery.svgplot.min.js | 9 +- jquery.svgplot.pack.js | 7 - kbw.svg.jquery.json | 39 ++ svgBasic.html | 28 +- 22 files changed, 1813 insertions(+), 2026 deletions(-) delete mode 100644 blank.svg delete mode 100644 jquery.svg.pack.js delete mode 100644 jquery.svganim.pack.js delete mode 100644 jquery.svgdom.pack.js delete mode 100644 jquery.svgfilter.pack.js delete mode 100644 jquery.svggraph.pack.js delete mode 100644 jquery.svgplot.pack.js create mode 100644 kbw.svg.jquery.json diff --git a/blank.svg b/blank.svg deleted file mode 100644 index 81783d3..0000000 --- a/blank.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/jquery.svg.css b/jquery.svg.css index 9430c62..a9e3867 100644 --- a/jquery.svg.css +++ b/jquery.svg.css @@ -1,14 +1,9 @@ /* http://keith-wood.name/svg.html - SVG for jQuery v1.4.5. - 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. - Please attribute the author if you use it. */ - + SVG for jQuery v1.5.0. + Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.*/ svg\:svg { display: none; } - .svg_error { color: red; font-weight: bold; diff --git a/jquery.svg.js b/jquery.svg.js index 6a6a9b3..acb4db1 100644 --- a/jquery.svg.js +++ b/jquery.svg.js @@ -1,52 +1,41 @@ /* http://keith-wood.name/svg.html - SVG for jQuery v1.4.5. + SVG for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ (function($) { // Hide scope, no $ conflict -/* SVG manager. - Use the singleton instance of this class, $.svg, - to interact with the SVG functionality. */ +/** The SVG manager. +

Use the singleton instance of this class, $.svg, + to interact with the SVG functionality.

+

Expects HTML like:

+
<div></div>
+ @module SVGManager */ function SVGManager() { this._settings = []; // Settings to be remembered per SVG object this._extensions = []; // List of SVG extensions added to SVGWrapper // for each entry [0] is extension name, [1] is extension class (function) // the function takes one parameter - the SVGWrapper instance this.regional = []; // Localisations, indexed by language, '' for default (English) - this.regional[''] = {errorLoadingText: 'Error loading', - notSupportedText: 'This browser does not support SVG'}; + this.regional[''] = {errorLoadingText: 'Error loading'}; this.local = this.regional['']; // Current localisation this._uuid = new Date().getTime(); - this._renesis = detectActiveX('RenesisX.RenesisCtrl'); + this._ie = !!window.ActiveXObject; } -/* Determine whether a given ActiveX control is available. - @param classId (string) the ID for the ActiveX control - @return (boolean) true if found, false if not */ -function detectActiveX(classId) { - try { - return !!(window.ActiveXObject && new ActiveXObject(classId)); - } - catch (e) { - return false; - } -} - -var PROP_NAME = 'svgwrapper'; - $.extend(SVGManager.prototype, { - /* Class name added to elements to indicate already configured with SVG. */ + /** Class name added to elements to indicate already configured with SVG. */ markerClassName: 'hasSVG', + /** Name of the data property for instance settings. */ + propertyName: 'svgwrapper', - /* SVG namespace. */ + /** SVG namespace. */ svgNS: 'http://www.w3.org/2000/svg', - /* XLink namespace. */ + /** XLink namespace. */ xlinkNS: 'http://www.w3.org/1999/xlink', - /* SVG wrapper class. */ + /** SVG wrapper class. */ _wrapperClass: SVGWrapper, /* Camel-case versions of attribute names containing dashes or are reserved words. */ @@ -82,15 +71,15 @@ $.extend(SVGManager.prototype, { /* Add the SVG object to its container. */ _attachSVG: function(container, settings) { - var svg = (container.namespaceURI == this.svgNS ? container : null); + var svg = (container.namespaceURI === this.svgNS ? container : null); var container = (svg ? null : container); if ($(container || svg).hasClass(this.markerClassName)) { return; } - if (typeof settings == 'string') { + if (typeof settings === 'string') { settings = {loadURL: settings}; } - else if (typeof settings == 'function') { + else if (typeof settings === 'function') { settings = {onLoad: settings}; } $(container || svg).addClass(this.markerClassName); @@ -109,42 +98,7 @@ $.extend(SVGManager.prototype, { this._afterLoad(container, svg, settings || {}); } catch (e) { - if ($.browser.msie) { - if (!container.id) { - container.id = 'svg' + (this._uuid++); - } - this._settings[container.id] = settings; - container.innerHTML = ''; - } - else { - container.innerHTML = '

' + - this.local.notSupportedText + '

'; - } - } - }, - - /* SVG callback after loading - register SVG root. */ - _registerSVG: function() { - for (var i = 0; i < document.embeds.length; i++) { // Check all - var container = document.embeds[i].parentNode; - if (!$(container).hasClass($.svg.markerClassName) || // Not SVG - $.data(container, PROP_NAME)) { // Already done - continue; - } - var svg = null; - try { - svg = document.embeds[i].getSVGDocument(); - } - catch(e) { - setTimeout($.svg._registerSVG, 250); // Renesis takes longer to load - return; - } - svg = (svg ? svg.documentElement : null); - if (svg) { - $.svg._afterLoad(container, svg); - } + $(container).html('

SVG is not supported natively on this browser

'); } }, @@ -153,7 +107,7 @@ $.extend(SVGManager.prototype, { var settings = settings || this._settings[container.id]; this._settings[container ? container.id : ''] = null; var wrapper = new this._wrapperClass(svg, container); - $.data(container || svg, PROP_NAME, wrapper); + $.data(container || svg, $.svg.propertyName, wrapper); try { if (settings.loadURL) { // Load URL wrapper.load(settings.loadURL, settings); @@ -170,51 +124,48 @@ $.extend(SVGManager.prototype, { } }, - /* Return the SVG wrapper created for a given container. - @param container (string) selector for the container or - (element) the container for the SVG object or - jQuery collection - first entry is the container - @return (SVGWrapper) the corresponding SVG wrapper element, or null if not attached */ + /** Return the SVG wrapper created for a given container. + @param container {string|Element|jQuery} Selector for the container or + the container for the SVG object or jQuery collection where first entry is the container. + @return {SVGWrapper} The corresponding SVG wrapper element, or null if not attached. */ _getSVG: function(container) { - container = (typeof container == 'string' ? $(container)[0] : - (container.jquery ? container[0] : container)); - return $.data(container, PROP_NAME); + return $(container).data(this.propertyName); }, - /* Remove the SVG functionality from a div. - @param container (element) the container for the SVG object */ + /** Remove the SVG functionality from a div. + @param container {Element} The container for the SVG object. */ _destroySVG: function(container) { - var $container = $(container); - if (!$container.hasClass(this.markerClassName)) { + container = $(container); + if (!container.hasClass(this.markerClassName)) { return; } - $container.removeClass(this.markerClassName); - if (container.namespaceURI != this.svgNS) { - $container.empty(); + container.removeClass(this.markerClassName).removeData(this.propertyName); + if (container[0].namespaceURI !== this.svgNS) { + container.empty(); } - $.removeData(container, PROP_NAME); }, - /* Extend the SVGWrapper object with an embedded class. - The constructor function must take a single parameter that is + /** Extend the SVGWrapper object with an embedded class. +

The constructor function must take a single parameter that is a reference to the owning SVG root object. This allows the - extension to access the basic SVG functionality. - @param name (string) the name of the SVGWrapper attribute to access the new class - @param extClass (function) the extension class constructor */ + extension to access the basic SVG functionality.

+ @param name {string} The name of the SVGWrapper attribute to access the new class. + @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 */ + /** 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); + return (node.nodeType === 1 && node.namespaceURI === $.svg.svgNS); } }); -/* The main SVG interface, which encapsulates the SVG element. - Obtain a reference from $().svg('get') */ +/** The main SVG interface, which encapsulates the SVG element. +

Obtain a reference from $().svg('get')

+ @module SVGWrapper */ function SVGWrapper(svg, container) { this._svg = svg; // The SVG root node this._container = container; // The containing div @@ -226,28 +177,30 @@ function SVGWrapper(svg, container) { $.extend(SVGWrapper.prototype, { - /* Retrieve the width of the SVG object. */ - _width: function() { + /** Retrieve the width of the SVG object. + @return {number} The width of the SVG canvas. */ + width: function() { return (this._container ? this._container.clientWidth : this._svg.width); }, - /* Retrieve the height of the SVG object. */ - _height: function() { + /** Retrieve the height of the SVG object. + @return {number} The height of the SVG canvas. */ + height: function() { return (this._container ? this._container.clientHeight : this._svg.height); }, - /* Retrieve the root SVG element. - @return the top-level SVG element */ + /** Retrieve the root SVG element. + @return {SVGElement} The top-level SVG element. */ root: function() { return this._svg; }, - /* 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 a SVG node. + @param [node] {SVGElement} The node to configure, or the SVG root if not specified. + @param settings {object} Additional settings for the root. + @param [clear=false] {boolean} true to remove existing attributes first, + false to add to what is already there. + @return {SVGWrapper} This wrapper. */ configure: function(node, settings, clear) { if (!node.nodeName) { clear = settings; @@ -257,8 +210,8 @@ $.extend(SVGWrapper.prototype, { if (clear) { 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')) { + if (!(attr.nodeName === 'onload' || attr.nodeName === 'version' || + attr.nodeName.substring(0, 5) === 'xmlns')) { node.attributes.removeNamedItem(attr.nodeName); } } @@ -269,17 +222,17 @@ $.extend(SVGWrapper.prototype, { return this; }, - /* Locate a specific element in the SVG document. - @param id (string) the element's identifier - @return (element) the element reference, or null if not found */ + /** Locate a specific element in the SVG document. + @param id {string} The element's identifier. + @return {SVGElement} The element reference, or null if not found. */ getElementById: function(id) { return this._svg.ownerDocument.getElementById(id); }, - /* Change the attributes for a SVG node. - @param element (SVG element) the node to change - @param settings (object) the new settings - @return (SVGWrapper) this root */ + /** Change the attributes for a SVG node. + @param element {SVGElement} The node to change. + @param settings {object} The new settings. + @return {SVGWrapper} This wrapper. */ change: function(element, settings) { if (element) { for (var name in settings) { @@ -294,7 +247,12 @@ $.extend(SVGWrapper.prototype, { return this; }, - /* Check for parent being absent and adjust arguments accordingly. */ + /** Check for parent being absent and adjust arguments accordingly. + @private + @param values {string[]} The given parameters. + @param names {string[]} The names of the parameters in order. + @param optSettings {string[]} The names of optional parameters. + @return {object} An object representing the named parameters. */ _args: function(values, names, optSettings) { names.splice(0, 0, 'parent'); names.splice(names.length, 0, 'settings'); @@ -303,7 +261,7 @@ $.extend(SVGWrapper.prototype, { if (values[0] != null && values[0].jquery) { values[0] = values[0][0]; } - if (values[0] != null && !(typeof values[0] == 'object' && values[0].nodeName)) { + if (values[0] != null && !(typeof values[0] === 'object' && values[0].nodeName)) { args['parent'] = null; offset = 1; } @@ -312,7 +270,7 @@ $.extend(SVGWrapper.prototype, { } if (optSettings) { $.each(optSettings, function(i, value) { - if (typeof args[value] == 'object') { + if (typeof args[value] === 'object') { args.settings = args[value]; args[value] = null; } @@ -321,11 +279,11 @@ $.extend(SVGWrapper.prototype, { return args; }, - /* Add a title. - @param parent (element or jQuery) the parent node for the new title (optional) - @param text (string) the text of the title - @param settings (object) additional settings for the title (optional) - @return (element) the new title node */ + /** Add a title. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param text {string} The text of the title. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new title node. */ title: function(parent, text, settings) { var args = this._args(arguments, ['text']); var node = this._makeNode(args.parent, 'title', args.settings || {}); @@ -333,11 +291,11 @@ $.extend(SVGWrapper.prototype, { return node; }, - /* Add a description. - @param parent (element or jQuery) the parent node for the new description (optional) - @param text (string) the text of the description - @param settings (object) additional settings for the description (optional) - @return (element) the new description node */ + /** Add a description. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param text {string} The text of the description. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new description node. */ describe: function(parent, text, settings) { var args = this._args(arguments, ['text']); var node = this._makeNode(args.parent, 'desc', args.settings || {}); @@ -345,168 +303,162 @@ $.extend(SVGWrapper.prototype, { return node; }, - /* Add a definitions node. - @param parent (element or jQuery) the parent node for the new definitions (optional) - @param id (string) the ID of this definitions (optional) - @param settings (object) additional settings for the definitions (optional) - @return (element) the new definitions node */ + /** Add a definitions node. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param [id] {string} The ID of this definitions (optional). + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new definitions node. */ defs: function(parent, id, settings) { var args = this._args(arguments, ['id'], ['id']); - return this._makeNode(args.parent, 'defs', $.extend( - (args.id ? {id: args.id} : {}), args.settings || {})); - }, - - /* Add a symbol definition. - @param parent (element or jQuery) the parent node for the new symbol (optional) - @param id (string) the ID of this symbol - @param x1 (number) the left coordinate for this symbol - @param y1 (number) the top coordinate for this symbol - @param width (number) the width of this symbol - @param height (number) the height of this symbol - @param settings (object) additional settings for the symbol (optional) - @return (element) the new symbol node */ + return this._makeNode(args.parent, 'defs', $.extend((args.id ? {id: args.id} : {}), args.settings || {})); + }, + + /** Add a symbol definition. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID of this symbol. + @param x1 {number} The left coordinate for this symbol. + @param y1 {number} The top coordinate for this symbol. + @param width {number} The width of this symbol. + @param height {number} The height of this symbol. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new symbol node. */ symbol: function(parent, id, x1, y1, width, height, settings) { var args = this._args(arguments, ['id', 'x1', 'y1', 'width', 'height']); return this._makeNode(args.parent, 'symbol', $.extend({id: args.id, - viewBox: args.x1 + ' ' + args.y1 + ' ' + args.width + ' ' + args.height}, - args.settings || {})); - }, - - /* Add a marker definition. - @param parent (element or jQuery) the parent node for the new marker (optional) - @param id (string) the ID of this marker - @param refX (number) the x-coordinate for the reference point - @param refY (number) the y-coordinate for the reference point - @param mWidth (number) the marker viewport width - @param mHeight (number) the marker viewport height - @param orient (string or int) 'auto' or angle (degrees) (optional) - @param settings (object) additional settings for the marker (optional) - @return (element) the new marker node */ + viewBox: args.x1 + ' ' + args.y1 + ' ' + args.width + ' ' + args.height}, args.settings || {})); + }, + + /** Add a marker definition. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID of this marker. + @param refX {number} The x-coordinate for the reference point. + @param refY {number} The y-coordinate for the reference point. + @param mWidth {number} The marker viewport width. + @param mHeight {number} The marker viewport height. + @param [orient] {string|number} 'auto' or angle (degrees). + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new marker node. */ marker: function(parent, id, refX, refY, mWidth, mHeight, orient, settings) { - var args = this._args(arguments, ['id', 'refX', 'refY', - 'mWidth', 'mHeight', 'orient'], ['orient']); + var args = this._args(arguments, ['id', 'refX', 'refY', 'mWidth', 'mHeight', 'orient'], ['orient']); return this._makeNode(args.parent, 'marker', $.extend( {id: args.id, refX: args.refX, refY: args.refY, markerWidth: args.mWidth, markerHeight: args.mHeight, orient: args.orient || 'auto'}, args.settings || {})); }, - /* Add a style node. - @param parent (element or jQuery) the parent node for the new node (optional) - @param styles (string) the CSS styles - @param settings (object) additional settings for the node (optional) - @return (element) the new style node */ + /** Add a style node. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param styles {string} The CSS styles. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new style node. */ style: function(parent, styles, settings) { var args = this._args(arguments, ['styles']); - var node = this._makeNode(args.parent, 'style', $.extend( - {type: 'text/css'}, args.settings || {})); + var node = this._makeNode(args.parent, 'style', $.extend({type: 'text/css'}, args.settings || {})); node.appendChild(this._svg.ownerDocument.createTextNode(args.styles)); - if ($.browser.opera) { - $('head').append(''); - } return node; }, - /* Add a script node. - @param parent (element or jQuery) the parent node for the new node (optional) - @param script (string) the JavaScript code - @param type (string) the MIME type for the code (optional, default 'text/javascript') - @param settings (object) additional settings for the node (optional) - @return (element) the new script node */ + /** Add a script node. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param script {string} The JavaScript code. + @param [type='text/javascript'] {string} The MIME type for the code. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new script node. */ script: function(parent, script, type, settings) { 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(args.script)); - if (!$.browser.mozilla) { + if ($.svg._ie) { $.globalEval(args.script); } return node; }, - /* Add a linear gradient definition. - Specify all of x1, y1, x2, y2 or none of them. - @param parent (element or jQuery) the parent node for the new gradient (optional) - @param id (string) the ID for this gradient - @param stops (string[][]) the gradient stops, each entry is - [0] is offset (0.0-1.0 or 0%-100%), [1] is colour, - [2] is opacity (optional) - @param x1 (number) the x-coordinate of the gradient start (optional) - @param y1 (number) the y-coordinate of the gradient start (optional) - @param x2 (number) the x-coordinate of the gradient end (optional) - @param y2 (number) the y-coordinate of the gradient end (optional) - @param settings (object) additional settings for the gradient (optional) - @return (element) the new gradient node */ + /** Add a linear gradient definition. +

Specify all of x1, y1, x2, y2 or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID for this gradient. + @param stops {string[][]} The gradient stops, each entry is [0] is offset (0.0-1.0 or 0%-100%), + [1] is colour, [2] is opacity (optional). + @param [x1] {number} The x-coordinate of the gradient start. + @param [y1] {number} The y-coordinate of the gradient start. + @param [x2] {number} The x-coordinate of the gradient end. + @param [y2] {number} The y-coordinate of the gradient end. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new linear gradient node. */ linearGradient: function(parent, id, stops, x1, y1, x2, y2, settings) { - var args = this._args(arguments, - ['id', 'stops', 'x1', 'y1', 'x2', 'y2'], ['x1']); - var sets = $.extend({id: args.id}, - (args.x1 != null ? {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2} : {})); - return this._gradient(args.parent, 'linearGradient', - $.extend(sets, args.settings || {}), args.stops); - }, - - /* Add a radial gradient definition. - Specify all of cx, cy, r, fx, fy or none of them. - @param parent (element or jQuery) the parent node for the new gradient (optional) - @param id (string) the ID for this gradient - @param stops (string[][]) the gradient stops, each entry - [0] is offset, [1] is colour, [2] is opacity (optional) - @param cx (number) the x-coordinate of the largest circle centre (optional) - @param cy (number) the y-coordinate of the largest circle centre (optional) - @param r (number) the radius of the largest circle (optional) - @param fx (number) the x-coordinate of the gradient focus (optional) - @param fy (number) the y-coordinate of the gradient focus (optional) - @param settings (object) additional settings for the gradient (optional) - @return (element) the new gradient node */ + var args = this._args(arguments, ['id', 'stops', 'x1', 'y1', 'x2', 'y2'], ['x1']); + var sets = $.extend({id: args.id}, + (args.x1 != null ? {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2} : {})); + return this._gradient(args.parent, 'linearGradient', $.extend(sets, args.settings || {}), args.stops); + }, + + /** Add a radial gradient definition. +

Specify all of cx, cy, r, + fx, fy or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID for this gradient. + @param stops {string[][]} The gradient stops, each entry [0] is offset (0.0-1.0 or 0%-100%), + [1] is colour, [2] is opacity (optional). + @param [cx] {number} The x-coordinate of the largest circle centre. + @param [cy] {number} The y-coordinate of the largest circle centre. + @param [r] {number} The radius of the largest circle. + @param [fx] {number} The x-coordinate of the gradient focus. + @param [fy] {number} The y-coordinate of the gradient focus. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new radial gradient node. */ radialGradient: function(parent, id, stops, cx, cy, r, fx, fy, settings) { - var args = this._args(arguments, - ['id', 'stops', 'cx', 'cy', 'r', 'fx', 'fy'], ['cx']); - var sets = $.extend({id: args.id}, (args.cx != null ? - {cx: args.cx, cy: args.cy, r: args.r, fx: args.fx, fy: args.fy} : {})); - return this._gradient(args.parent, 'radialGradient', - $.extend(sets, args.settings || {}), args.stops); - }, - - /* Add a gradient node. */ + var args = this._args(arguments, ['id', 'stops', 'cx', 'cy', 'r', 'fx', 'fy'], ['cx']); + var sets = $.extend({id: args.id}, + (args.cx != null ? {cx: args.cx, cy: args.cy, r: args.r, fx: args.fx, fy: args.fy} : {})); + return this._gradient(args.parent, 'radialGradient', $.extend(sets, args.settings || {}), args.stops); + }, + + /** Add a gradient node. + @private + @param parent {SVGElement|jQuery} The parent node for the new node. + @param name {string} The type of gradient node to create. + @param settings {object} The settings for this node. + @param stops {string[][]} The gradient stops. + @return {SVGElement} The new gradient node. */ _gradient: function(parent, name, settings, stops) { var node = this._makeNode(parent, name, settings); for (var i = 0; i < stops.length; i++) { var stop = stops[i]; - this._makeNode(node, 'stop', $.extend( - {offset: stop[0], stopColor: stop[1]}, + this._makeNode(node, 'stop', $.extend({offset: stop[0], stopColor: stop[1]}, (stop[2] != null ? {stopOpacity: stop[2]} : {}))); } return node; }, - /* Add a pattern definition. - Specify all of vx, vy, xwidth, vheight or none of them. - @param parent (element or jQuery) the parent node for the new pattern (optional) - @param id (string) the ID for this pattern - @param x (number) the x-coordinate for the left edge of the pattern - @param y (number) the y-coordinate for the top edge of the pattern - @param width (number) the width of the pattern - @param height (number) the height of the pattern - @param vx (number) the minimum x-coordinate for view box (optional) - @param vy (number) the minimum y-coordinate for the view box (optional) - @param vwidth (number) the width of the view box (optional) - @param vheight (number) the height of the view box (optional) - @param settings (object) additional settings for the pattern (optional) - @return (element) the new pattern node */ + /** Add a pattern definition. +

Specify all of vx, vy, xwidth, + vheight or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID for this pattern. + @param x {number} The x-coordinate for the left edge of the pattern. + @param y {number} The y-coordinate for the top edge of the pattern. + @param width {number} The width of the pattern. + @param height {number} The height of the pattern. + @param [vx] {number} The minimum x-coordinate for view box. + @param [vy] {number} The minimum y-coordinate for the view box. + @param [vwidth] {number} The width of the view box. + @param [vheight] {number} The height of the view box. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new pattern definition node. */ pattern: function(parent, id, x, y, width, height, vx, vy, vwidth, vheight, settings) { - var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height', - 'vx', 'vy', 'vwidth', 'vheight'], ['vx']); - var sets = $.extend({id: args.id, x: args.x, y: args.y, - width: args.width, height: args.height}, (args.vx != null ? - {viewBox: args.vx + ' ' + args.vy + ' ' + args.vwidth + ' ' + args.vheight} : {})); + var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height', 'vx', 'vy', 'vwidth', 'vheight'], ['vx']); + var sets = $.extend({id: args.id, x: args.x, y: args.y, width: args.width, height: args.height}, + (args.vx != null ? {viewBox: args.vx + ' ' + args.vy + ' ' + args.vwidth + ' ' + args.vheight} : {})); 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 */ + /** Add a clip path definition. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID for this path. + @param [units='userSpaceOnUse'] {string} Either 'userSpaceOnUse' or 'objectBoundingBox'. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new clip path definition node. */ clipPath: function(parent, id, units, settings) { var args = this._args(arguments, ['id', 'units']); args.units = args.units || 'userSpaceOnUse'; @@ -514,95 +466,92 @@ $.extend(SVGWrapper.prototype, { {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 - @param x (number) the x-coordinate for the left edge of the mask - @param y (number) the y-coordinate for the top edge of the mask - @param width (number) the width of the mask - @param height (number) the height of the mask - @param settings (object) additional settings for the mask (optional) - @return (element) the new mask node */ + /** Add a mask definition. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID for this mask. + @param x {number} The x-coordinate for the left edge of the mask. + @param y {number} The y-coordinate for the top edge of the mask. + @param width {number} The width of the mask. + @param height {number} The height of the mask. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new mask definition node. */ mask: function(parent, id, x, y, width, height, settings) { var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height']); return this._makeNode(args.parent, 'mask', $.extend( - {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height}, - args.settings || {})); + {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height}, args.settings || {})); }, - /* Create a new path object. - @return (SVGPath) a new path object */ + /** Create a new path object. + @return {SVGPath} A new path object. */ createPath: function() { return new SVGPath(); }, - /* Create a new text object. - @return (SVGText) a new text object */ + /** Create a new text object. + @return {SVGText} A new text object. */ createText: function() { return new SVGText(); }, - /* Add an embedded SVG element. - Specify all of vx, vy, vwidth, vheight or none of them. - @param parent (element or jQuery) the parent node for the new node (optional) - @param x (number) the x-coordinate for the left edge of the node - @param y (number) the y-coordinate for the top edge of the node - @param width (number) the width of the node - @param height (number) the height of the node - @param vx (number) the minimum x-coordinate for view box (optional) - @param vy (number) the minimum y-coordinate for the view box (optional) - @param vwidth (number) the width of the view box (optional) - @param vheight (number) the height of the view box (optional) - @param settings (object) additional settings for the node (optional) - @return (element) the new node */ + /** Add an embedded SVG element. +

Specify all of vx, vy, + vwidth, vheight or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param x {number} The x-coordinate for the left edge of the node. + @param y {number} The y-coordinate for the top edge of the node. + @param width {number} The width of the node. + @param height {number} The height of the node. + @param [vx] {number} The minimum x-coordinate for view box. + @param [vy] {number} The minimum y-coordinate for the view box. + @param [vwidth] {number} The width of the view box. + @param [vheight] {number} The height of the view box. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new svg node. */ svg: function(parent, x, y, width, height, vx, vy, vwidth, vheight, settings) { - var args = this._args(arguments, ['x', 'y', 'width', 'height', - 'vx', 'vy', 'vwidth', 'vheight'], ['vx']); + var args = this._args(arguments, ['x', 'y', 'width', 'height', 'vx', 'vy', 'vwidth', 'vheight'], ['vx']); var sets = $.extend({x: args.x, y: args.y, width: args.width, height: args.height}, - (args.vx != null ? {viewBox: args.vx + ' ' + args.vy + ' ' + - args.vwidth + ' ' + args.vheight} : {})); + (args.vx != null ? {viewBox: args.vx + ' ' + args.vy + ' ' + args.vwidth + ' ' + args.vheight} : {})); return this._makeNode(args.parent, 'svg', $.extend(sets, args.settings || {})); }, - /* Create a group. - @param parent (element or jQuery) the parent node for the new group (optional) - @param id (string) the ID of this group (optional) - @param settings (object) additional settings for the group (optional) - @return (element) the new group node */ + /** Create a group. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param [id] {string} The ID of this group. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new group node. */ group: function(parent, id, settings) { var args = this._args(arguments, ['id'], ['id']); return this._makeNode(args.parent, 'g', $.extend({id: args.id}, args.settings || {})); }, - /* Add a usage reference. - Specify all of x, y, width, height or none of them. - @param parent (element or jQuery) the parent node for the new node (optional) - @param x (number) the x-coordinate for the left edge of the node (optional) - @param y (number) the y-coordinate for the top edge of the node (optional) - @param width (number) the width of the node (optional) - @param height (number) the height of the node (optional) - @param ref (string) the ID of the definition node - @param settings (object) additional settings for the node (optional) - @return (element) the new node */ + /** Add a usage reference. +

Specify all of x, y, width, height or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param [x] {number} The x-coordinate for the left edge of the node. + @param [y] {number} The y-coordinate for the top edge of the node. + @param [width] {number} The width of the node. + @param [height] {number} The height of the node. + @param ref {string} The ID of the definition node. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new usage reference node. */ use: function(parent, x, y, width, height, ref, settings) { var args = this._args(arguments, ['x', 'y', 'width', 'height', 'ref']); - if (typeof args.x == 'string') { + if (typeof args.x === 'string') { args.ref = args.x; args.settings = args.y; args.x = args.y = args.width = args.height = null; } var node = this._makeNode(args.parent, 'use', $.extend( - {x: args.x, y: args.y, width: args.width, height: args.height}, - args.settings || {})); + {x: args.x, y: args.y, width: args.width, height: args.height}, args.settings || {})); node.setAttributeNS($.svg.xlinkNS, 'href', args.ref); return node; }, - /* Add a link, which applies to all child elements. - @param parent (element or jQuery) the parent node for the new link (optional) - @param ref (string) the target URL - @param settings (object) additional settings for the link (optional) - @return (element) the new link node */ + /** Add a link, which applies to all child elements. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param ref {string} The target URL. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new link node. */ link: function(parent, ref, settings) { var args = this._args(arguments, ['ref']); var node = this._makeNode(args.parent, 'a', args.settings); @@ -610,46 +559,45 @@ $.extend(SVGWrapper.prototype, { return node; }, - /* Add an image. - @param parent (element or jQuery) the parent node for the new image (optional) - @param x (number) the x-coordinate for the left edge of the image - @param y (number) the y-coordinate for the top edge of the image - @param width (number) the width of the image - @param height (number) the height of the image - @param ref (string) the path to the image - @param settings (object) additional settings for the image (optional) - @return (element) the new image node */ + /** Add an image. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param x {number} The x-coordinate for the left edge of the image. + @param y {number} The y-coordinate for the top edge of the image. + @param width {number} The width of the image. + @param height {number} The height of the image. + @param ref {string} The path to the image. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new image node. */ image: function(parent, x, y, width, height, ref, settings) { var args = this._args(arguments, ['x', 'y', 'width', 'height', 'ref']); var node = this._makeNode(args.parent, 'image', $.extend( - {x: args.x, y: args.y, width: args.width, height: args.height}, - args.settings || {})); + {x: args.x, y: args.y, width: args.width, height: args.height}, args.settings || {})); node.setAttributeNS($.svg.xlinkNS, 'href', args.ref); return node; }, - /* Draw a path. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param path (string or SVGPath) the path to draw - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw a path. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param path {string|SVGPath} The path to draw. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new path node. */ path: function(parent, path, settings) { var args = this._args(arguments, ['path']); return this._makeNode(args.parent, 'path', $.extend( {d: (args.path.path ? args.path.path() : args.path)}, args.settings || {})); }, - /* Draw a rectangle. - Specify both of rx and ry or neither. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param x (number) the x-coordinate for the left edge of the rectangle - @param y (number) the y-coordinate for the top edge of the rectangle - @param width (number) the width of the rectangle - @param height (number) the height of the rectangle - @param rx (number) the x-radius of the ellipse for the rounded corners (optional) - @param ry (number) the y-radius of the ellipse for the rounded corners (optional) - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw a rectangle. +

Specify both of rx and ry or neither.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param x {number} The x-coordinate for the left edge of the rectangle. + @param y {number} The y-coordinate for the top edge of the rectangle. + @param width {number} The width of the rectangle. + @param height {number} The height of the rectangle. + @param [rx] {number} The x-radius of the ellipse for the rounded corners. + @param [ry] {number} The y-radius of the ellipse for the rounded corners. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new rectangle node. */ rect: function(parent, x, y, width, height, rx, ry, settings) { var args = this._args(arguments, ['x', 'y', 'width', 'height', 'rx', 'ry'], ['rx']); return this._makeNode(args.parent, 'rect', $.extend( @@ -657,106 +605,108 @@ $.extend(SVGWrapper.prototype, { (args.rx ? {rx: args.rx, ry: args.ry} : {}), args.settings || {})); }, - /* Draw a circle. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param cx (number) the x-coordinate for the centre of the circle - @param cy (number) the y-coordinate for the centre of the circle - @param r (number) the radius of the circle - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw a circle. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param cx {number} The x-coordinate for the centre of the circle. + @param cy {number} The y-coordinate for the centre of the circle. + @param r {number} The radius of the circle. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new circle node. */ circle: function(parent, cx, cy, r, settings) { var args = this._args(arguments, ['cx', 'cy', 'r']); return this._makeNode(args.parent, 'circle', $.extend( {cx: args.cx, cy: args.cy, r: args.r}, args.settings || {})); }, - /* Draw an ellipse. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param cx (number) the x-coordinate for the centre of the ellipse - @param cy (number) the y-coordinate for the centre of the ellipse - @param rx (number) the x-radius of the ellipse - @param ry (number) the y-radius of the ellipse - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw an ellipse. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param cx {number} The x-coordinate for the centre of the ellipse. + @param cy {number} The y-coordinate for the centre of the ellipse. + @param rx {number} The x-radius of the ellipse. + @param ry {number} The y-radius of the ellipse. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new ellipse node. */ ellipse: function(parent, cx, cy, rx, ry, settings) { var args = this._args(arguments, ['cx', 'cy', 'rx', 'ry']); return this._makeNode(args.parent, 'ellipse', $.extend( {cx: args.cx, cy: args.cy, rx: args.rx, ry: args.ry}, args.settings || {})); }, - /* Draw a line. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param x1 (number) the x-coordinate for the start of the line - @param y1 (number) the y-coordinate for the start of the line - @param x2 (number) the x-coordinate for the end of the line - @param y2 (number) the y-coordinate for the end of the line - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw a line. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param x1 {number} The x-coordinate for the start of the line. + @param y1 {number} The y-coordinate for the start of the line. + @param x2 {number} The x-coordinate for the end of the line. + @param y2 {number} The y-coordinate for the end of the line. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new line node. */ line: function(parent, x1, y1, x2, y2, settings) { var args = this._args(arguments, ['x1', 'y1', 'x2', 'y2']); return this._makeNode(args.parent, 'line', $.extend( {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2}, args.settings || {})); }, - /* Draw a polygonal line. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param points (number[][]) the x-/y-coordinates for the points on the line - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw a polygonal line. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param points {number[][]} The x-/y-coordinates for the points on the line. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new polygonal line node. */ polyline: function(parent, points, settings) { var args = this._args(arguments, ['points']); return this._poly(args.parent, 'polyline', args.points, args.settings); }, - /* Draw a polygonal shape. - @param parent (element or jQuery) the parent node for the new shape (optional) - @param points (number[][]) the x-/y-coordinates for the points on the shape - @param settings (object) additional settings for the shape (optional) - @return (element) the new shape node */ + /** Draw a polygonal shape. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param points {number[][]} The x-/y-coordinates for the points on the shape. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new polygonal shape node. */ polygon: function(parent, points, settings) { var args = this._args(arguments, ['points']); return this._poly(args.parent, 'polygon', args.points, args.settings); }, - /* Draw a polygonal line or shape. */ + /** Draw a polygonal line or shape. + @private + @param parent {SVGElement|jQuery} The parent node for the new node. + @param name {string} The type of polygon to create. + @param points {number[][]} The x-/y-coordinates for the points on the shape. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new polygon node. */ _poly: function(parent, name, points, settings) { var ps = ''; for (var i = 0; i < points.length; i++) { ps += points[i].join() + ' '; } - return this._makeNode(parent, name, $.extend( - {points: $.trim(ps)}, settings || {})); - }, - - /* Draw text. - Specify both of x and y or neither of them. - @param parent (element or jQuery) the parent node for the text (optional) - @param x (number or number[]) the x-coordinate(s) for the text (optional) - @param y (number or number[]) the y-coordinate(s) for the text (optional) - @param value (string) the text content or - (SVGText) text with spans and references - @param settings (object) additional settings for the text (optional) - @return (element) the new text node */ + return this._makeNode(parent, name, $.extend({points: $.trim(ps)}, settings || {})); + }, + + /** Draw text. +

Specify both of x and y or neither of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param [x] {number|number[]} The x-coordinate(s) for the text. + @param [y] {number|number[]} The y-coordinate(s) for the text. + @param value {string|SVGText} The text content or text with spans and references. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new text node. */ text: function(parent, x, y, value, settings) { var args = this._args(arguments, ['x', 'y', 'value']); - if (typeof args.x == 'string' && arguments.length < 4) { + if (typeof args.x === 'string' && arguments.length < 4) { args.value = args.x; args.settings = args.y; args.x = args.y = null; } return this._text(args.parent, 'text', args.value, $.extend( - {x: (args.x && isArray(args.x) ? args.x.join(' ') : args.x), - y: (args.y && isArray(args.y) ? args.y.join(' ') : args.y)}, - args.settings || {})); - }, - - /* Draw text along a path. - @param parent (element or jQuery) the parent node for the text (optional) - @param path (string) the ID of the path - @param value (string) the text content or - (SVGText) text with spans and references - @param settings (object) additional settings for the text (optional) - @return (element) the new text node */ + {x: (args.x && $.isArray(args.x) ? args.x.join(' ') : args.x), + y: (args.y && $.isArray(args.y) ? args.y.join(' ') : args.y)}, args.settings || {})); + }, + + /** Draw text along a path. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param path {string} The ID of the path. + @param value {string|SVGText} The text content or text with spans and references. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new textpath node. */ textpath: function(parent, path, value, settings) { var args = this._args(arguments, ['path', 'value']); var node = this._text(args.parent, 'textPath', args.value, args.settings || {}); @@ -764,26 +714,32 @@ $.extend(SVGWrapper.prototype, { return node; }, - /* Draw text. */ + /** Draw text. + @private + @param parent {SVGElement|jQuery} The parent node for the new node. + @param name {string} The type of text to create. + @param value {string|SVGText} The text content or text with spans and references. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new text node. */ _text: function(parent, name, value, settings) { var node = this._makeNode(parent, name, settings); - if (typeof value == 'string') { + if (typeof value === 'string') { node.appendChild(node.ownerDocument.createTextNode(value)); } else { for (var i = 0; i < value._parts.length; i++) { var part = value._parts[i]; - if (part[0] == 'tspan') { + if (part[0] === 'tspan') { var child = this._makeNode(node, part[0], part[2]); child.appendChild(node.ownerDocument.createTextNode(part[1])); node.appendChild(child); } - else if (part[0] == 'tref') { + else if (part[0] === 'tref') { var child = this._makeNode(node, part[0], part[2]); child.setAttributeNS($.svg.xlinkNS, 'href', part[1]); node.appendChild(child); } - else if (part[0] == 'textpath') { + else if (part[0] === 'textpath') { var set = $.extend({}, part[2]); set.href = null; var child = this._makeNode(node, part[0], set); @@ -799,24 +755,28 @@ $.extend(SVGWrapper.prototype, { return node; }, - /* Add a custom SVG element. - @param parent (element or jQuery) the parent node for the new element (optional) - @param name (string) the name of the element - @param settings (object) additional settings for the element (optional) - @return (element) the new custom node */ + /** Add a custom SVG element. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param name {string} The name of the element. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new custom node. */ other: function(parent, name, settings) { var args = this._args(arguments, ['name']); return this._makeNode(args.parent, args.name, args.settings || {}); }, - /* Create a shape node with the given settings. */ + /** Create a SVG node with the given settings. + @private + @param parent {SVGElement|jQuery} The parent node for the new node, or SVG root if null. + @param name {string} The name of the element. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new node. */ _makeNode: function(parent, name, settings) { parent = parent || this._svg; var node = this._svg.ownerDocument.createElementNS($.svg.svgNS, name); for (var name in settings) { var value = settings[name]; - if (value != null && value != null && - (typeof value != 'string' || value != '')) { + if (value != null && (typeof value !== 'string' || value !== '')) { node.setAttribute($.svg._attrNames[name] || name, value); } } @@ -824,21 +784,17 @@ $.extend(SVGWrapper.prototype, { return node; }, - /* Add an existing SVG node 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 (SVGWrapper) this wrapper */ + /** Add an existing SVG node to the document. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param node {SVGElement|string|jQuery} The new node to add or + the jQuery selector for the node or the set of nodes to add. + @return {SVGWrapper} This wrapper. */ add: function(parent, node) { - var args = this._args((arguments.length == 1 ? [null, parent] : arguments), ['node']); + 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'; - } args.parent.appendChild(args.node.cloneNode(true)); } catch (e) { @@ -852,15 +808,14 @@ $.extend(SVGWrapper.prototype, { return this; }, - /* 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 an existing SVG node and add it to the document. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param node {SVGEelement|string|jQuery} The new node to add or + the jQuery selector for the node or the set of nodes to clone. + @return {SVGElement[]} The collection of new nodes. */ clone: function(parent, node) { var svg = this; - var args = this._args((arguments.length == 1 ? [null, parent] : arguments), ['node']); + 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 = []; @@ -875,20 +830,19 @@ $.extend(SVGWrapper.prototype, { 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 */ + /** SVG nodes must belong to the SVG namespace, so clone and ensure this is so. + @private + @param node {SVGElement} The SVG node to clone. + @return {SVGElement} The cloned node. */ _cloneAsSVG: function(node) { var newNode = null; - if (node.nodeType == 1) { // element - newNode = this._svg.ownerDocument.createElementNS( - $.svg.svgNS, this._checkName(node.nodeName)); + if (node.nodeType === 1) { // element + newNode = this._svg.ownerDocument.createElementNS($.svg.svgNS, this._checkName(node.nodeName)); for (var i = 0; i < node.attributes.length; i++) { var attr = node.attributes.item(i); - if (attr.nodeName != 'xmlns' && attr.nodeValue) { - if (attr.prefix == 'xlink') { - newNode.setAttributeNS($.svg.xlinkNS, - attr.localName || attr.baseName, attr.nodeValue); + if (attr.nodeName !== 'xmlns' && attr.nodeValue) { + if (attr.prefix === 'xlink') { + newNode.setAttributeNS($.svg.xlinkNS, attr.localName || attr.baseName, attr.nodeValue); } else { newNode.setAttribute(this._checkName(attr.nodeName), attr.nodeValue); @@ -902,56 +856,54 @@ $.extend(SVGWrapper.prototype, { } } } - else if (node.nodeType == 3) { // text + else if (node.nodeType === 3) { // text if ($.trim(node.nodeValue)) { newNode = this._svg.ownerDocument.createTextNode(node.nodeValue); } } - else if (node.nodeType == 4) { // CDATA + else if (node.nodeType === 4) { // CDATA if ($.trim(node.nodeValue)) { try { newNode = this._svg.ownerDocument.createCDATASection(node.nodeValue); } catch (e) { newNode = this._svg.ownerDocument.createTextNode( - node.nodeValue.replace(/&/g, '&'). - replace(//g, '>')); + node.nodeValue.replace(/&/g, '&').replace(//g, '>')); } } } return newNode; }, - /* Node names must be lower case and without SVG namespace prefix. */ + /** Node names must be lower case and without SVG namespace prefix. + @private + @param name {string} The name to check. + @return {string} The corrected name. */ _checkName: function(name) { - name = (name.substring(0, 1) >= 'A' && name.substring(0, 1) <= 'Z' ? - name.toLowerCase() : name); - return (name.substring(0, 4) == 'svg:' ? name.substring(4) : name); - }, - - /* Load an external SVG document. - @param url (string) the location of the SVG document or - the actual SVG content - @param settings (boolean) see addTo below or - (function) see onLoad below or - (object) additional settings for the load with attributes below: - addTo (boolean) true to add to what's already there, - or false to clear the canvas first - changeSize (boolean) true to allow the canvas size to change, - or false to retain the original - 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 */ + name = (name.substring(0, 1) >= 'A' && name.substring(0, 1) <= 'Z' ? name.toLowerCase() : name); + return (name.substring(0, 4) === 'svg:' ? name.substring(4) : name); + }, + + /** Load an external SVG document. + @param url {string} The location of the SVG document or + the actual SVG content (starting with '<svg'. + @param settings {boolean|function|object} Either addTo below or onLoad below or + additional settings for the load with attributes below: + addTo {boolean} true to add to what's already there, + or false to clear the canvas first, + changeSize {boolean} true to allow the canvas size to change, + or false to retain the original, + onLoad {function} callback after the document has loaded, + 'this' is the container, receives SVG object and optional error message as a parameter, + parent {string|SVGElement|jQuery} the parent to load into, + defaults to top-level svg element. + @return {SVGWrapper} This wrapper. */ load: function(url, settings) { - 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 || {}))))); + 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); } @@ -974,7 +926,7 @@ $.extend(SVGWrapper.prototype, { xml.resolveExternals = false; xml.async = false; xml.loadXML(data); - if (xml.parseError.errorCode != 0) { + if (xml.parseError.errorCode !== 0) { reportError(xml.parseError.reason); return null; } @@ -985,18 +937,17 @@ $.extend(SVGWrapper.prototype, { if (!data) { return; } - if (data.documentElement.nodeName != 'svg') { + if (data.documentElement.nodeName !== 'svg') { var errors = data.getElementsByTagName('parsererror'); var messages = (errors.length ? errors[0].getElementsByTagName('div') : []); // Safari - reportError(!errors.length ? '???' : - (messages.length ? messages[0] : errors[0]).firstChild.nodeValue); + reportError(!errors.length ? '???' : (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); - if (!(attr.nodeName == 'version' || attr.nodeName.substring(0, 5) == 'xmlns')) { + if (!(attr.nodeName === 'version' || attr.nodeName.substring(0, 5) === 'xmlns')) { attrs[attr.nodeName] = attr.nodeValue; } } @@ -1004,11 +955,8 @@ $.extend(SVGWrapper.prototype, { var nodes = data.documentElement.childNodes; for (var i = 0; i < nodes.length; i++) { try { - if ($.svg._renesis) { - throw 'Force traversal'; - } parent.appendChild(wrapper._svg.ownerDocument.importNode(nodes[i], true)); - if (nodes[i].nodeName == 'script') { + if (nodes[i].nodeName === 'script') { $.globalEval(nodes[i].textContent); } } @@ -1016,6 +964,15 @@ $.extend(SVGWrapper.prototype, { wrapper.add(parent, nodes[i]); } } + if (!settings.keepRelativeLinks && url.match('/')) { + var base = url.replace(/\/[^\/]*$/, '/'); + $('*', parent).each(function() { + var href = $(this).attr('xlink:href'); + if (href && !href.match(/(^[a-z][-a-z0-9+.]*:.*$)|(^\/.*$)|(^#.*$)/i)) { + $(this).attr('xlink:href', base + href); + } + }); + } if (!settings.changeSize) { wrapper.configure(parent, {width: size[0], height: size[1]}); } @@ -1024,13 +981,16 @@ $.extend(SVGWrapper.prototype, { } }; if (url.match('true to clear any root attributes as well, + false to leave them. + @return {SVGWrapper} This wrapper. */ clear: function(attrsToo) { if (attrsToo) { this.configure({}, true); @@ -1061,25 +1021,27 @@ $.extend(SVGWrapper.prototype, { return this; }, - /* Serialise the current diagram into an SVG text document. - @param node (SVG element) the starting node (optional) - @return (string) the SVG as text */ + /** Serialise the current diagram into an SVG text document. + @param [node] {SVGElement} The starting node, or SVG root if not specified . + @return {string} The SVG as text. */ toSVG: function(node) { node = node || this._svg; - return (typeof XMLSerializer == 'undefined' ? this._toSVG(node) : - new XMLSerializer().serializeToString(node)); + return (typeof XMLSerializer === 'undefined' ? this._toSVG(node) : new XMLSerializer().serializeToString(node)); }, - /* Serialise one node in the SVG hierarchy. */ + /** Serialise one node in the SVG hierarchy. + @private + @param node {SVGElement} The current node to serialise. + @return {string} The serialised SVG. */ _toSVG: function(node) { var svgDoc = ''; if (!node) { return svgDoc; } - if (node.nodeType == 3) { // Text + if (node.nodeType === 3) { // Text svgDoc = node.nodeValue; } - else if (node.nodeType == 4) { // CDATA + else if (node.nodeType === 4) { // CDATA svgDoc = ''; } else { // Element @@ -1087,9 +1049,9 @@ $.extend(SVGWrapper.prototype, { if (node.attributes) { for (var i = 0; i < node.attributes.length; i++) { var attr = node.attributes.item(i); - if (!($.trim(attr.nodeValue) == '' || attr.nodeValue.match(/^\[object/) || + if (!($.trim(attr.nodeValue) === '' || attr.nodeValue.match(/^\[object/) || attr.nodeValue.match(/^function/))) { - svgDoc += ' ' + (attr.namespaceURI == $.svg.xlinkNS ? 'xlink:' : '') + + svgDoc += ' ' + (attr.namespaceURI === $.svg.xlinkNS ? 'xlink:' : '') + attr.nodeName + '="' + attr.nodeValue + '"'; } } @@ -1111,170 +1073,171 @@ $.extend(SVGWrapper.prototype, { } }); -/* Helper to generate an SVG path. - Obtain an instance from the SVGWrapper object. - String calls together to generate the path and use its value: - var path = root.createPath(); +/** Helper to generate an SVG path. +

Obtain an instance from the SVGWrapper object.

+

String calls together to generate the path and use its value:

+ @module SVGPath + @example var path = root.createPath(); root.path(null, path.move(100, 100).line(300, 100).line(200, 300).close(), {fill: 'red'}); - or + // or root.path(null, path.move(100, 100).line([[300, 100], [200, 300]]).close(), {fill: 'red'}); */ function SVGPath() { this._path = ''; } $.extend(SVGPath.prototype, { - /* Prepare to create a new path. - @return (SVGPath) this path */ + /** Prepare to create a new path. + @return {SVGPath} This path. */ reset: function() { this._path = ''; return this; }, - /* Move the pointer to a position. - @param x (number) x-coordinate to move to or - (number[][]) x-/y-coordinates to move to - @param y (number) y-coordinate to move to (omitted if x is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Move the pointer to a position. + @param x {number|number[][]} x-coordinate to move to or x-/y-coordinates to move to. + @param [y] {number} y-coordinate to move to (omitted if x is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ move: function(x, y, relative) { - relative = (isArray(x) ? y : relative); + relative = ($.isArray(x) ? y : relative); return this._coords((relative ? 'm' : 'M'), x, y); }, - /* Draw a line to a position. - @param x (number) x-coordinate to move to or - (number[][]) x-/y-coordinates to move to - @param y (number) y-coordinate to move to (omitted if x is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Draw a line to a position. + @param x {number|number[][]} x-coordinate to move to or x-/y-coordinates to move to. + @param [y] {number} y-coordinate to move to (omitted if x is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ line: function(x, y, relative) { - relative = (isArray(x) ? y : relative); + relative = ($.isArray(x) ? y : relative); return this._coords((relative ? 'l' : 'L'), x, y); }, - /* Draw a horizontal line to a position. - @param x (number) x-coordinate to draw to or - (number[]) x-coordinates to draw to - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Draw a horizontal line to a position. + @param x {number|number[]} x-coordinate to draw to or x-coordinates to draw to. + @param relative {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ horiz: function(x, relative) { - this._path += (relative ? 'h' : 'H') + (isArray(x) ? x.join(' ') : x); + this._path += (relative ? 'h' : 'H') + ($.isArray(x) ? x.join(' ') : x); return this; }, - /* Draw a vertical line to a position. - @param y (number) y-coordinate to draw to or - (number[]) y-coordinates to draw to - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Draw a vertical line to a position. + @param y {number|number[]} y-coordinate to draw to or y-coordinates to draw to. + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ vert: function(y, relative) { - this._path += (relative ? 'v' : 'V') + (isArray(y) ? y.join(' ') : y); + this._path += (relative ? 'v' : 'V') + ($.isArray(y) ? y.join(' ') : y); return this; }, - /* Draw a cubic Bézier curve. - @param x1 (number) x-coordinate of beginning control point or - (number[][]) x-/y-coordinates of control and end points to draw to - @param y1 (number) y-coordinate of beginning control point (omitted if x1 is array) - @param x2 (number) x-coordinate of ending control point (omitted if x1 is array) - @param y2 (number) y-coordinate of ending control point (omitted if x1 is array) - @param x (number) x-coordinate of curve end (omitted if x1 is array) - @param y (number) y-coordinate of curve end (omitted if x1 is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Draw a cubic Bézier curve. + @param x1 {number|number[][]} x-coordinate of beginning control point or + x-/y-coordinates of control and end points to draw to. + @param [y1] {number} y-coordinate of beginning control point (omitted if x1 is array). + @param [x2] {number} x-coordinate of ending control point (omitted if x1 is array). + @param [y2] {number} y-coordinate of ending control point (omitted if x1 is array). + @param [x] {number} x-coordinate of curve end (omitted if x1 is array). + @param [y] {number} y-coordinate of curve end (omitted if x1 is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ curveC: function(x1, y1, x2, y2, x, y, relative) { - relative = (isArray(x1) ? y1 : relative); + relative = ($.isArray(x1) ? y1 : relative); return this._coords((relative ? 'c' : 'C'), x1, y1, x2, y2, x, y); }, - /* Continue a cubic Bézier curve. - Starting control point is the reflection of the previous end control point. - @param x2 (number) x-coordinate of ending control point or - (number[][]) x-/y-coordinates of control and end points to draw to - @param y2 (number) y-coordinate of ending control point (omitted if x2 is array) - @param x (number) x-coordinate of curve end (omitted if x2 is array) - @param y (number) y-coordinate of curve end (omitted if x2 is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Continue a cubic Bézier curve. +

Starting control point is the reflection of the previous end control point.

+ @param x2 {number|number[][]} x-coordinate of ending control point or + x-/y-coordinates of control and end points to draw to. + @param [y2] {number} y-coordinate of ending control point (omitted if x2 is array). + @param [x] {number} x-coordinate of curve end (omitted if x2 is array). + @param [y] {number} y-coordinate of curve end (omitted if x2 is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ smoothC: function(x2, y2, x, y, relative) { - relative = (isArray(x2) ? y2 : relative); + relative = ($.isArray(x2) ? y2 : relative); return this._coords((relative ? 's' : 'S'), x2, y2, x, y); }, - /* Draw a quadratic Bézier curve. - @param x1 (number) x-coordinate of control point or - (number[][]) x-/y-coordinates of control and end points to draw to - @param y1 (number) y-coordinate of control point (omitted if x1 is array) - @param x (number) x-coordinate of curve end (omitted if x1 is array) - @param y (number) y-coordinate of curve end (omitted if x1 is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Draw a quadratic Bézier curve. + @param x1 {number|number[][]} x-coordinate of control point or + x-/y-coordinates of control and end points to draw to. + @param [y1] {number} y-coordinate of control point (omitted if x1 is array). + @param [x] {number} x-coordinate of curve end (omitted if x1 is array). + @param [y] {number} y-coordinate of curve end (omitted if x1 is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ curveQ: function(x1, y1, x, y, relative) { - relative = (isArray(x1) ? y1 : relative); + relative = ($.isArray(x1) ? y1 : relative); return this._coords((relative ? 'q' : 'Q'), x1, y1, x, y); }, - /* Continue a quadratic Bézier curve. - Control point is the reflection of the previous control point. - @param x (number) x-coordinate of curve end or - (number[][]) x-/y-coordinates of points to draw to - @param y (number) y-coordinate of curve end (omitted if x is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Continue a quadratic Bézier curve. +

Control point is the reflection of the previous control point.

+ @param x {number|number[][]} x-coordinate of curve end or x-/y-coordinates of points to draw to. + @param [y] {number} y-coordinate of curve end (omitted if x is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ smoothQ: function(x, y, relative) { - relative = (isArray(x) ? y : relative); + relative = ($.isArray(x) ? y : relative); return this._coords((relative ? 't' : 'T'), x, y); }, - /* Generate a path command with (a list of) coordinates. */ + /** Generate a path command with (a list of) coordinates. + @private + @param cmd {string} The command for the path element. + @param x1 {number} The first x-coordinate. + @param y1 {number} The first y-coordinate. + @param [x2] {number} The second x-coordinate. + @param [y2] {number} The second y-coordinate. + @param [x3] {number} The third x-coordinate. + @param [y3] {number} The third y-coordinate. + @return {SVGPath} This path. */ _coords: function(cmd, x1, y1, x2, y2, x3, y3) { - if (isArray(x1)) { + if ($.isArray(x1)) { for (var i = 0; i < x1.length; i++) { var cs = x1[i]; - this._path += (i == 0 ? cmd : ' ') + cs[0] + ',' + cs[1] + - (cs.length < 4 ? '' : ' ' + cs[2] + ',' + cs[3] + - (cs.length < 6 ? '': ' ' + cs[4] + ',' + cs[5])); + this._path += (i === 0 ? cmd : ' ') + cs[0] + ',' + cs[1] + (cs.length < 4 ? '' : + ' ' + cs[2] + ',' + cs[3] + (cs.length < 6 ? '': ' ' + cs[4] + ',' + cs[5])); } } else { this._path += cmd + x1 + ',' + y1 + - (x2 == null ? '' : ' ' + x2 + ',' + y2 + - (x3 == null ? '' : ' ' + x3 + ',' + y3)); + (x2 == null ? '' : ' ' + x2 + ',' + y2 + (x3 == null ? '' : ' ' + x3 + ',' + y3)); } return this; }, - /* Draw an arc to a position. - @param rx (number) x-radius of arc or - (number/boolean[][]) x-/y-coordinates and flags for points to draw to - @param ry (number) y-radius of arc (omitted if rx is array) - @param xRotate (number) x-axis rotation (degrees, clockwise) (omitted if rx is array) - @param large (boolean) true to draw the large part of the arc, - false to draw the small part (omitted if rx is array) - @param clockwise (boolean) true to draw the clockwise arc, - false to draw the anti-clockwise arc (omitted if rx is array) - @param x (number) x-coordinate of arc end (omitted if rx is array) - @param y (number) y-coordinate of arc end (omitted if rx is array) - @param relative (boolean) true for coordinates relative to the current point, - false for coordinates being absolute - @return (SVGPath) this path */ + /** Draw an arc to a position. + @param rx {number|any[][]} x-radius of arc or x-/y-coordinates and flags for points to draw to. + @param [ry] {number} y-radius of arc (omitted if rx is array). + @param [xRotate] {number} x-axis rotation (degrees, clockwise) (omitted if rx is array). + @param [large] {boolean} true to draw the large part of the arc, + false to draw the small part (omitted if rx is array). + @param [clockwise] {boolean} true to draw the clockwise arc, + false to draw the anti-clockwise arc (omitted if rx is array). + @param [x] {number} x-coordinate of arc end (omitted if rx is array). + @param [y] {number} y-coordinate of arc end (omitted if rx is array). + @param [relative=false] {boolean} true for coordinates relative to the current point, + false for coordinates being absolute. + @return {SVGPath} This path. */ arc: function(rx, ry, xRotate, large, clockwise, x, y, relative) { - relative = (isArray(rx) ? ry : relative); + relative = ($.isArray(rx) ? ry : relative); this._path += (relative ? 'a' : 'A'); - if (isArray(rx)) { + if ($.isArray(rx)) { for (var i = 0; i < rx.length; i++) { var cs = rx[i]; - this._path += (i == 0 ? '' : ' ') + cs[0] + ',' + cs[1] + ' ' + - cs[2] + ' ' + (cs[3] ? '1' : '0') + ',' + - (cs[4] ? '1' : '0') + ' ' + cs[5] + ',' + cs[6]; + this._path += (i === 0 ? '' : ' ') + cs[0] + ',' + cs[1] + ' ' + + cs[2] + ' ' + (cs[3] ? '1' : '0') + ',' + (cs[4] ? '1' : '0') + ' ' + cs[5] + ',' + cs[6]; } } else { @@ -1284,15 +1247,15 @@ $.extend(SVGPath.prototype, { return this; }, - /* Close the current path. - @return (SVGPath) this path */ + /** Close the current path. + @return {SVGPath} This path. */ close: function() { this._path += 'z'; return this; }, - /* Return the string rendering of the specified path. - @return (string) stringified path */ + /** Return the string rendering of the specified path. + @return {string} The stringified path. */ path: function() { return this._path; } @@ -1308,10 +1271,11 @@ SVGPath.prototype.curveQTo = SVGPath.prototype.curveQ; SVGPath.prototype.smoothQTo = SVGPath.prototype.smoothQ; SVGPath.prototype.arcTo = SVGPath.prototype.arc; -/* Helper to generate an SVG text object. - Obtain an instance from the SVGWrapper object. - String calls together to generate the text and use its value: - var text = root.createText(); +/** Helper to generate an SVG text object. +

Obtain an instance from the SVGWrapper object.

+

String calls together to generate the text and use its value:

+ @module SVGText + @example var text = root.createText(); root.text(null, x, y, text.string('This is '). span('red', {fill: 'red'}).string('!'), {fill: 'blue'}); */ function SVGText() { @@ -1319,62 +1283,61 @@ function SVGText() { } $.extend(SVGText.prototype, { - /* Prepare to create a new text object. - @return (SVGText) this text */ + /** Prepare to create a new text object. + @return {SVGText} This text object. */ reset: function() { this._parts = []; return this; }, - /* Add a straight string value. - @param value (string) the actual text - @return (SVGText) this text object */ + /** Add a straight string value. + @param value {string} The actual text. + @return {SVGText} This text object. */ string: function(value) { - this._parts[this._parts.length] = ['text', value]; + this._parts.push(['text', value]); return this; }, - /* Add a separate text span that has its own settings. - @param value (string) the actual text - @param settings (object) the settings for this text - @return (SVGText) this text object */ + /** Add a separate text span that has its own settings. + @param value {string} The actual text. + @param settings {object} The settings for this text. + @return {SVGText} This text object. */ span: function(value, settings) { - this._parts[this._parts.length] = ['tspan', value, settings]; + this._parts.push(['tspan', value, settings]); return this; }, - /* Add a reference to a previously defined text string. - @param id (string) the ID of the actual text - @param settings (object) the settings for this text - @return (SVGText) this text object */ + /** Add a reference to a previously defined text string. + @param id {string} The ID of the actual text. + @param settings {object} The settings for this text. + @return {SVGText} This text object. */ ref: function(id, settings) { - this._parts[this._parts.length] = ['tref', id, settings]; + this._parts.push(['tref', id, settings]); return this; }, - /* Add text drawn along a path. - @param id (string) the ID of the path - @param value (string) the actual text - @param settings (object) the settings for this text - @return (SVGText) this text object */ + /** Add text drawn along a path. + @param id {string} The ID of the path. + @param value {string} The actual text. + @param settings {object} The settings for this text. + @return {SVGText} This text object. */ path: function(id, value, settings) { - this._parts[this._parts.length] = ['textpath', value, - $.extend({href: id}, settings || {})]; + this._parts.push(['textpath', value, $.extend({href: id}, settings || {})]); return this; } }); -/* Attach the SVG functionality to a jQuery selection. - @param command (string) the command to run (optional, default 'attach') - @param options (object) the new settings to use for these SVG instances - @return jQuery (object) for chaining further calls */ +/** Attach the SVG functionality to a jQuery selection. + @param [command] {string} The command to run. + @param [options] {object} The new settings to use for these SVG instances. + @return {jQuery} For chaining further calls. */ $.fn.svg = function(options) { var otherArgs = Array.prototype.slice.call(arguments, 1); - if (typeof options == 'string' && options == 'get') { + if (typeof options === 'string' && options === 'get') { return $.svg['_' + options + 'SVG'].apply($.svg, [this[0]].concat(otherArgs)); } return this.each(function() { - if (typeof options == 'string') { + if (typeof options === 'string') { $.svg['_' + options + 'SVG'].apply($.svg, [this].concat(otherArgs)); } else { @@ -1383,11 +1346,6 @@ $.fn.svg = function(options) { }); }; -/* Determine whether an object is an array. */ -function isArray(a) { - return (a && a.constructor == Array); -} - // Singleton primary SVG interface $.svg = new SVGManager(); diff --git a/jquery.svg.min.js b/jquery.svg.min.js index b193b9e..7c99985 100644 --- a/jquery.svg.min.js +++ b/jquery.svg.min.js @@ -1,7 +1,6 @@ -/* http://keith-wood.name/svg.html - SVG for jQuery v1.4.5. +/* http://keith-wood.name/svg.html + SVG for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ -(function($){function SVGManager(){this._settings=[];this._extensions=[];this.regional=[];this.regional['']={errorLoadingText:'Error loading',notSupportedText:'This browser does not support SVG'};this.local=this.regional[''];this._uuid=new Date().getTime();this._renesis=detectActiveX('RenesisX.RenesisCtrl')}function detectActiveX(a){try{return!!(window.ActiveXObject&&new ActiveXObject(a))}catch(e){return false}}var q='svgwrapper';$.extend(SVGManager.prototype,{markerClassName:'hasSVG',svgNS:'http://www.w3.org/2000/svg',xlinkNS:'http://www.w3.org/1999/xlink',_wrapperClass:SVGWrapper,_attrNames:{class_:'class',in_:'in',alignmentBaseline:'alignment-baseline',baselineShift:'baseline-shift',clipPath:'clip-path',clipRule:'clip-rule',colorInterpolation:'color-interpolation',colorInterpolationFilters:'color-interpolation-filters',colorRendering:'color-rendering',dominantBaseline:'dominant-baseline',enableBackground:'enable-background',fillOpacity:'fill-opacity',fillRule:'fill-rule',floodColor:'flood-color',floodOpacity:'flood-opacity',fontFamily:'font-family',fontSize:'font-size',fontSizeAdjust:'font-size-adjust',fontStretch:'font-stretch',fontStyle:'font-style',fontVariant:'font-variant',fontWeight:'font-weight',glyphOrientationHorizontal:'glyph-orientation-horizontal',glyphOrientationVertical:'glyph-orientation-vertical',horizAdvX:'horiz-adv-x',horizOriginX:'horiz-origin-x',imageRendering:'image-rendering',letterSpacing:'letter-spacing',lightingColor:'lighting-color',markerEnd:'marker-end',markerMid:'marker-mid',markerStart:'marker-start',stopColor:'stop-color',stopOpacity:'stop-opacity',strikethroughPosition:'strikethrough-position',strikethroughThickness:'strikethrough-thickness',strokeDashArray:'stroke-dasharray',strokeDashOffset:'stroke-dashoffset',strokeLineCap:'stroke-linecap',strokeLineJoin:'stroke-linejoin',strokeMiterLimit:'stroke-miterlimit',strokeOpacity:'stroke-opacity',strokeWidth:'stroke-width',textAnchor:'text-anchor',textDecoration:'text-decoration',textRendering:'text-rendering',underlinePosition:'underline-position',underlineThickness:'underline-thickness',vertAdvY:'vert-adv-y',vertOriginY:'vert-origin-y',wordSpacing:'word-spacing',writingMode:'writing-mode'},_attachSVG:function(a,b){var c=(a.namespaceURI==this.svgNS?a:null);var a=(c?null:a);if($(a||c).hasClass(this.markerClassName)){return}if(typeof b=='string'){b={loadURL:b}}else if(typeof b=='function'){b={onLoad:b}}$(a||c).addClass(this.markerClassName);try{if(!c){c=document.createElementNS(this.svgNS,'svg');c.setAttribute('version','1.1');if(a.clientWidth>0){c.setAttribute('width',a.clientWidth)}if(a.clientHeight>0){c.setAttribute('height',a.clientHeight)}a.appendChild(c)}this._afterLoad(a,c,b||{})}catch(e){if($.browser.msie){if(!a.id){a.id='svg'+(this._uuid++)}this._settings[a.id]=b;a.innerHTML=''}else{a.innerHTML='

'+this.local.notSupportedText+'

'}}},_registerSVG:function(){for(var i=0;i=0;i--){var d=a.attributes.item(i);if(!(d.nodeName=='onload'||d.nodeName=='version'||d.nodeName.substring(0,5)=='xmlns')){a.attributes.removeNamedItem(d.nodeName)}}}for(var e in b){a.setAttribute($.svg._attrNames[e]||e,b[e])}return this},getElementById:function(a){return this._svg.ownerDocument.getElementById(a)},change:function(a,b){if(a){for(var c in b){if(b[c]==null){a.removeAttribute($.svg._attrNames[c]||c)}else{a.setAttribute($.svg._attrNames[c]||c,b[c])}}}return this},_args:function(b,c,d){c.splice(0,0,'parent');c.splice(c.length,0,'settings');var e={};var f=0;if(b[0]!=null&&b[0].jquery){b[0]=b[0][0]}if(b[0]!=null&&!(typeof b[0]=='object'&&b[0].nodeName)){e['parent']=null;f=1}for(var i=0;i'+d.styles+'')}return e},script:function(a,b,c,d){var e=this._args(arguments,['script','type'],['type']);var f=this._makeNode(e.parent,'script',$.extend({type:e.type||'text/javascript'},e.settings||{}));f.appendChild(this._svg.ownerDocument.createTextNode(e.script));if(!$.browser.mozilla){$.globalEval(e.script)}return f},linearGradient:function(a,b,c,d,e,f,g,h){var i=this._args(arguments,['id','stops','x1','y1','x2','y2'],['x1']);var j=$.extend({id:i.id},(i.x1!=null?{x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2}:{}));return this._gradient(i.parent,'linearGradient',$.extend(j,i.settings||{}),i.stops)},radialGradient:function(a,b,c,d,e,r,f,g,h){var i=this._args(arguments,['id','stops','cx','cy','r','fx','fy'],['cx']);var j=$.extend({id:i.id},(i.cx!=null?{cx:i.cx,cy:i.cy,r:i.r,fx:i.fx,fy:i.fy}:{}));return this._gradient(i.parent,'radialGradient',$.extend(j,i.settings||{}),i.stops)},_gradient:function(a,b,c,d){var e=this._makeNode(a,b,c);for(var i=0;i/g,'>'))}}}return b},_checkName:function(a){a=(a.substring(0,1)>='A'&&a.substring(0,1)<='Z'?a.toLowerCase():a);return(a.substring(0,4)=='svg:'?a.substring(4):a)},load:function(j,k){k=(typeof k=='boolean'?{addTo:k}:(typeof k=='function'?{onLoad:k}:(typeof k=='string'?{parent:k}:(typeof k=='object'&&k.nodeName?{parent:k}:(typeof k=='object'&&k.jquery?{parent:k}:k||{})))));if(!k.parent&&!k.addTo){this.clear(false)}var l=[this._svg.getAttribute('width'),this._svg.getAttribute('height')];var m=this;var n=function(a){a=$.svg.local.errorLoadingText+': '+a;if(k.onLoad){k.onLoad.apply(m._container||m._svg,[m,a])}else{m.text(null,10,20,a)}};var o=function(a){var b=new ActiveXObject('Microsoft.XMLDOM');b.validateOnParse=false;b.resolveExternals=false;b.async=false;b.loadXML(a);if(b.parseError.errorCode!=0){n(b.parseError.reason);return null}return b};var p=function(a){if(!a){return}if(a.documentElement.nodeName!='svg'){var b=a.getElementsByTagName('parsererror');var c=(b.length?b[0].getElementsByTagName('div'):[]);n(!b.length?'???':(c.length?c[0]:b[0]).firstChild.nodeValue);return}var d=(k.parent?$(k.parent)[0]:m._svg);var f={};for(var i=0;i'}else{b='<'+a.nodeName;if(a.attributes){for(var i=0;i';var d=a.firstChild;while(d){b+=this._toSVG(d);d=d.nextSibling}b+=''}else{b+='/>'}}return b}});function SVGPath(){this._path=''}$.extend(SVGPath.prototype,{reset:function(){this._path='';return this},move:function(x,y,a){a=(isArray(x)?y:a);return this._coords((a?'m':'M'),x,y)},line:function(x,y,a){a=(isArray(x)?y:a);return this._coords((a?'l':'L'),x,y)},horiz:function(x,a){this._path+=(a?'h':'H')+(isArray(x)?x.join(' '):x);return this},vert:function(y,a){this._path+=(a?'v':'V')+(isArray(y)?y.join(' '):y);return this},curveC:function(a,b,c,d,x,y,e){e=(isArray(a)?b:e);return this._coords((e?'c':'C'),a,b,c,d,x,y)},smoothC:function(a,b,x,y,c){c=(isArray(a)?b:c);return this._coords((c?'s':'S'),a,b,x,y)},curveQ:function(a,b,x,y,c){c=(isArray(a)?b:c);return this._coords((c?'q':'Q'),a,b,x,y)},smoothQ:function(x,y,a){a=(isArray(x)?y:a);return this._coords((a?'t':'T'),x,y)},_coords:function(a,b,c,d,e,f,g){if(isArray(b)){for(var i=0;i0){c.setAttribute('width',a.clientWidth)}if(a.clientHeight>0){c.setAttribute('height',a.clientHeight)}a.appendChild(c)}this._afterLoad(a,c,b||{})}catch(e){$(a).html('

SVG is not supported natively on this browser

')}},_afterLoad:function(a,b,c){var c=c||this._settings[a.id];this._settings[a?a.id:'']=null;var d=new this._wrapperClass(b,a);$.data(a||b,$.svg.propertyName,d);try{if(c.loadURL){d.load(c.loadURL,c)}if(c.settings){d.configure(c.settings)}if(c.onLoad&&!c.loadURL){c.onLoad.apply(a||b,[d])}}catch(e){alert(e)}},_getSVG:function(a){return $(a).data(this.propertyName)},_destroySVG:function(a){a=$(a);if(!a.hasClass(this.markerClassName)){return}a.removeClass(this.markerClassName).removeData(this.propertyName);if(a[0].namespaceURI!==this.svgNS){a.empty()}},addExtension:function(a,b){this._extensions.push([a,b])},isSVGElem:function(a){return(a.nodeType===1&&a.namespaceURI===$.svg.svgNS)}});function SVGWrapper(a,b){this._svg=a;this._container=b;for(var i=0;i<$.svg._extensions.length;i++){var c=$.svg._extensions[i];this[c[0]]=new c[1](this)}}$.extend(SVGWrapper.prototype,{width:function(){return(this._container?this._container.clientWidth:this._svg.width)},height:function(){return(this._container?this._container.clientHeight:this._svg.height)},root:function(){return this._svg},configure:function(a,b,c){if(!a.nodeName){c=b;b=a;a=this._svg}if(c){for(var i=a.attributes.length-1;i>=0;i--){var d=a.attributes.item(i);if(!(d.nodeName==='onload'||d.nodeName==='version'||d.nodeName.substring(0,5)==='xmlns')){a.attributes.removeNamedItem(d.nodeName)}}}for(var e in b){a.setAttribute($.svg._attrNames[e]||e,b[e])}return this},getElementById:function(a){return this._svg.ownerDocument.getElementById(a)},change:function(a,b){if(a){for(var c in b){if(b[c]==null){a.removeAttribute($.svg._attrNames[c]||c)}else{a.setAttribute($.svg._attrNames[c]||c,b[c])}}}return this},_args:function(b,c,d){c.splice(0,0,'parent');c.splice(c.length,0,'settings');var e={};var f=0;if(b[0]!=null&&b[0].jquery){b[0]=b[0][0]}if(b[0]!=null&&!(typeof b[0]==='object'&&b[0].nodeName)){e['parent']=null;f=1}for(var i=0;i/g,'>'))}}}return b},_checkName:function(a){a=(a.substring(0,1)>='A'&&a.substring(0,1)<='Z'?a.toLowerCase():a);return(a.substring(0,4)==='svg:'?a.substring(4):a)},load:function(l,m){m=(typeof m==='boolean'?{addTo:m}:(typeof m==='function'?{onLoad:m}:(typeof m==='string'?{parent:m}:(typeof m==='object'&&m.nodeName?{parent:m}:(typeof m==='object'&&m.jquery?{parent:m}:m||{})))));if(!m.parent&&!m.addTo){this.clear(false)}var n=[this._svg.getAttribute('width'),this._svg.getAttribute('height')];var o=this;var p=function(a){a=$.svg.local.errorLoadingText+': '+a;if(m.onLoad){m.onLoad.apply(o._container||o._svg,[o,a])}else{o.text(null,10,20,a)}};var q=function(a){var b=new ActiveXObject('Microsoft.XMLDOM');b.validateOnParse=false;b.resolveExternals=false;b.async=false;b.loadXML(a);if(b.parseError.errorCode!==0){p(b.parseError.reason);return null}return b};var r=function(b){if(!b){return}if(b.documentElement.nodeName!=='svg'){var c=b.getElementsByTagName('parsererror');var d=(c.length?c[0].getElementsByTagName('div'):[]);p(!c.length?'???':(d.length?d[0]:c[0]).firstChild.nodeValue);return}var f=(m.parent?$(m.parent)[0]:o._svg);var g={};for(var i=0;i'}else{b='<'+a.nodeName;if(a.attributes){for(var i=0;i';var d=a.firstChild;while(d){b+=this._toSVG(d);d=d.nextSibling}b+=''}else{b+='/>'}}return b}});function SVGPath(){this._path=''}$.extend(SVGPath.prototype,{reset:function(){this._path='';return this},move:function(x,y,a){a=($.isArray(x)?y:a);return this._coords((a?'m':'M'),x,y)},line:function(x,y,a){a=($.isArray(x)?y:a);return this._coords((a?'l':'L'),x,y)},horiz:function(x,a){this._path+=(a?'h':'H')+($.isArray(x)?x.join(' '):x);return this},vert:function(y,a){this._path+=(a?'v':'V')+($.isArray(y)?y.join(' '):y);return this},curveC:function(a,b,c,d,x,y,e){e=($.isArray(a)?b:e);return this._coords((e?'c':'C'),a,b,c,d,x,y)},smoothC:function(a,b,x,y,c){c=($.isArray(a)?b:c);return this._coords((c?'s':'S'),a,b,x,y)},curveQ:function(a,b,x,y,c){c=($.isArray(a)?b:c);return this._coords((c?'q':'Q'),a,b,x,y)},smoothQ:function(x,y,a){a=($.isArray(x)?y:a);return this._coords((a?'t':'T'),x,y)},_coords:function(a,b,c,d,e,f,g){if($.isArray(b)){for(var i=0;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(9($){9 2k(){7.1X=[];7.1Y=[];7.2l=[];7.2l[\'\']={2Z:\'4d 4e\',30:\'4f 1r 4g 4h 4i 2m\'};7.2n=7.2l[\'\'];7.31=1e 4j().4k();7.2o=32(\'4l.4m\')}9 32(a){1s{u!!(4n.2p&&1e 2p(a))}1t(e){u 1L}}8 q=\'4o\';$.I(2k.W,{1C:\'4p\',1u:\'2q://2r.33.34/4q/D\',1j:\'2q://2r.33.34/4r/2s\',35:2t,1M:{4s:\'36\',4t:\'1Z\',4u:\'4v-2u\',4w:\'2u-4x\',2v:\'37-19\',4y:\'37-38\',4z:\'1D-39\',4A:\'1D-39-4B\',4C:\'1D-2w\',4D:\'4E-2u\',4F:\'4G-4H\',4I:\'3a-21\',4J:\'3a-38\',4K:\'3b-1D\',4L:\'3b-21\',4M:\'1v-4N\',4O:\'1v-3c\',4P:\'1v-3c-4Q\',4R:\'1v-4S\',4T:\'1v-1N\',4U:\'1v-4V\',4W:\'1v-4X\',4Y:\'3d-3e-4Z\',50:\'3d-3e-51\',52:\'22-3f-x\',53:\'22-3g-x\',54:\'23-2w\',55:\'56-3h\',57:\'58-1D\',59:\'1O-5a\',5b:\'1O-5c\',5d:\'1O-5e\',3i:\'2x-1D\',3j:\'2x-21\',5f:\'3k-3l\',5g:\'3k-3m\',5h:\'1w-5i\',5j:\'1w-5k\',5l:\'1w-5m\',5n:\'1w-5o\',5p:\'1w-5q\',5r:\'1w-21\',5s:\'1w-O\',5t:\'15-5u\',5v:\'15-5w\',5x:\'15-2w\',5y:\'3n-3l\',5z:\'3n-3m\',5A:\'24-3f-y\',5B:\'24-3g-y\',5C:\'5D-3h\',5E:\'5F-5G\'},3o:9(a,b){8 c=(a.25==7.1u?a:P);8 a=(c?P:a);w($(a||c).2y(7.1C)){u}w(13 b==\'1f\'){b={26:b}}Y w(13 b==\'9\'){b={1m:b}}$(a||c).5H(7.1C);1s{w(!c){c=27.2z(7.1u,\'D\');c.1x(\'2A\',\'1.1\');w(a.2B>0){c.1x(\'O\',a.2B)}w(a.2C>0){c.1x(\'U\',a.2C)}a.11(c)}7.2D(a,c,b||{})}1t(e){w($.1r.28){w(!a.E){a.E=\'D\'+(7.31++)}7.1X[a.E]=b;a.3p=\'<5I 1y="23/D+2E" O="3q%" \'+\'U="3q%" 5J="\'+(b.5K||\'\')+\'5L.D" \'+\'5M="2q://2r.5N.5O/D/5P/5Q/5R.5S"/>\'}Y{a.3p=\'

\'+7.2n.30+\'

\'}}},3r:9(){14(8 i=0;i<27.2F.R;i++){8 a=27.2F[i].3s;w(!$(a).2y($.D.1C)||$.2G(a,q)){5U}8 b=P;1s{b=27.2F[i].5V()}1t(e){5W($.D.3r,5X);u}b=(b?b.1P:P);w(b){$.D.2D(a,b)}}},2D:9(a,b,c){8 c=c||7.1X[a.E];7.1X[a?a.E:\'\']=P;8 d=1e 7.35(b,a);$.2G(a||b,q,d);1s{w(c.26){d.3t(c.26,c)}w(c.F){d.1Q(c.F)}w(c.1m&&!c.26){c.1m.1R(a||b,[d])}}1t(e){5Y(e)}},5Z:9(a){a=(13 a==\'1f\'?$(a)[0]:(a.1E?a[0]:a));u $.2G(a,q)},60:9(a){8 b=$(a);w(!b.2y(7.1C)){u}b.61(7.1C);w(a.25!=7.1u){b.62()}$.63(a,q)},64:9(a,b){7.1Y.3u([a,b])},65:9(a){u(a.1F==1&&a.25==$.D.1u)}});9 2t(a,b){7.N=a;7.1z=b;14(8 i=0;i<$.D.1Y.R;i++){8 c=$.D.1Y[i];7[c[0]]=1e c[1](7)}}$.I(2t.W,{66:9(){u(7.1z?7.1z.2B:7.N.O)},67:9(){u(7.1z?7.1z.2C:7.N.U)},68:9(){u 7.N},1Q:9(a,b,c){w(!a.12){c=b;b=a;a=7.N}w(c){14(8 i=a.1g.R-1;i>=0;i--){8 d=a.1g.29(i);w(!(d.12==\'69\'||d.12==\'2A\'||d.12.1G(0,5)==\'2H\')){a.1g.6a(d.12)}}}14(8 e 1Z b){a.1x($.D.1M[e]||e,b[e])}u 7},3v:9(a){u 7.N.17.3v(a)},6b:9(a,b){w(a){14(8 c 1Z b){w(b[c]==P){a.6c($.D.1M[c]||c)}Y{a.1x($.D.1M[c]||c,b[c])}}}u 7},J:9(b,c,d){c.3w(0,0,\'B\');c.3w(c.R,0,\'F\');8 e={};8 f=0;w(b[0]!=P&&b[0].1E){b[0]=b[0][0]}w(b[0]!=P&&!(13 b[0]==\'1S\'&&b[0].12)){e[\'B\']=P;f=1}14(8 i=0;i\'+d.2L+\'\')}u e},1H:9(a,b,c,d){8 e=7.J(G,[\'1H\',\'1y\'],[\'1y\']);8 f=7.K(e.B,\'1H\',$.I({1y:e.1y||\'15/6l\'},e.F||{}));f.11(7.N.17.1h(e.1H));w(!$.1r.6m){$.3D(e.1H)}u f},3E:9(a,b,c,d,e,f,g,h){8 i=7.J(G,[\'E\',\'2c\',\'1i\',\'1n\',\'1I\',\'1J\'],[\'1i\']);8 j=$.I({E:i.E},(i.1i!=P?{1i:i.1i,1n:i.1n,1I:i.1I,1J:i.1J}:{}));u 7.2M(i.B,\'3E\',$.I(j,i.F||{}),i.2c)},3F:9(a,b,c,d,e,r,f,g,h){8 i=7.J(G,[\'E\',\'2c\',\'1c\',\'1k\',\'r\',\'2N\',\'2O\'],[\'1c\']);8 j=$.I({E:i.E},(i.1c!=P?{1c:i.1c,1k:i.1k,r:i.r,2N:i.2N,2O:i.2O}:{}));u 7.2M(i.B,\'3F\',$.I(j,i.F||{}),i.2c)},2M:9(a,b,c,d){8 e=7.K(a,b,c);14(8 i=0;i/g,\'&6E;\'))}}}u b},2U:9(a){a=(a.1G(0,1)>=\'A\'&&a.1G(0,1)<=\'Z\'?a.6F():a);u(a.1G(0,4)==\'D:\'?a.1G(4):a)},3t:9(j,k){k=(13 k==\'6G\'?{3V:k}:(13 k==\'9\'?{1m:k}:(13 k==\'1f\'?{B:k}:(13 k==\'1S\'&&k.12?{B:k}:(13 k==\'1S\'&&k.1E?{B:k}:k||{})))));w(!k.B&&!k.3V){7.3W(1L)}8 l=[7.N.3X(\'O\'),7.N.3X(\'U\')];8 m=7;8 n=9(a){a=$.D.2n.2Z+\': \'+a;w(k.1m){k.1m.1R(m.1z||m.N,[m,a])}Y{m.15(P,10,20,a)}};8 o=9(a){8 b=1e 2p(\'6H.6I\');b.6J=1L;b.6K=1L;b.6L=1L;b.6M(a);w(b.3Y.6N!=0){n(b.3Y.6O);u P}u b};8 p=9(a){w(!a){u}w(a.1P.12!=\'D\'){8 b=a.3Z(\'6P\');8 c=(b.R?b[0].3Z(\'6Q\'):[]);n(!b.R?\'???\':(c.R?c[0]:b[0]).1W.16);u}8 d=(k.B?$(k.B)[0]:m.N);8 f={};14(8 i=0;i\'}Y{b=\'<\'+a.12;w(a.1g){14(8 i=0;i\';8 d=a.1W;41(d){b+=7.2Y(d);d=d.77}b+=\'\'}Y{b+=\'/>\'}}u b}});9 X(){7.1d=\'\'}$.I(X.W,{43:9(){7.1d=\'\';u 7},44:9(x,y,a){a=(18(x)?y:a);u 7.1B((a?\'m\':\'M\'),x,y)},2h:9(x,y,a){a=(18(x)?y:a);u 7.1B((a?\'l\':\'L\'),x,y)},22:9(x,a){7.1d+=(a?\'h\':\'H\')+(18(x)?x.1U(\' \'):x);u 7},24:9(y,a){7.1d+=(a?\'v\':\'V\')+(18(y)?y.1U(\' \'):y);u 7},45:9(a,b,c,d,x,y,e){e=(18(a)?b:e);u 7.1B((e?\'c\':\'C\'),a,b,c,d,x,y)},46:9(a,b,x,y,c){c=(18(a)?b:c);u 7.1B((c?\'s\':\'S\'),a,b,x,y)},47:9(a,b,x,y,c){c=(18(a)?b:c);u 7.1B((c?\'q\':\'Q\'),a,b,x,y)},48:9(x,y,a){a=(18(x)?y:a);u 7.1B((a?\'t\':\'T\'),x,y)},1B:9(a,b,c,d,e,f,g){w(18(b)){14(8 i=0;i 1 || parseInt($.fn.jquery.substring(2), 10) > 5; + // Enable animation for all of these SVG numeric attributes - // named as svg-* or svg* (with first character upper case) $.each(['x', 'y', 'width', 'height', 'rx', 'ry', 'cx', 'cy', 'r', 'x1', 'y1', 'x2', 'y2', @@ -24,7 +25,7 @@ $.each(['x', 'y', 'width', 'height', 'rx', 'ry', 'cx', 'cy', 'r', 'x1', 'y1', 'x var attr = fx.elem.attributes.getNamedItem(realAttrName); if (!fx.set) { fx.start = (attr ? parseFloat(attr.nodeValue) : 0); - var offset = ($.fn.jquery >= '1.6' ? '' : + var offset = (jQueryNew ? '' : fx.options.curAnim['svg' + ccName] || fx.options.curAnim['svg-' + attrName]); if (/^[+-]=/.exec(offset)) { fx.end = fx.start + parseFloat(offset.replace(/=/, '')); @@ -32,7 +33,7 @@ $.each(['x', 'y', 'width', 'height', 'rx', 'ry', 'cx', 'cy', 'r', 'x1', 'y1', 'x $(fx.elem).css(realAttrName, ''); fx.set = true; } - var value = (fx.pos * (fx.end - fx.start) + fx.start) + (fx.unit == '%' ? '%' : ''); + var value = (fx.pos * (fx.end - fx.start) + fx.start) + (fx.unit === '%' ? '%' : ''); (attr ? attr.nodeValue = value : fx.elem.setAttribute(realAttrName, value)); }; } @@ -44,13 +45,13 @@ $.fx.step['svgStroke-dasharray'] = $.fx.step['svg-stroke-dasharray'] = function( 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 : + var offset = (jQueryNew ? 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 + 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]); @@ -70,9 +71,10 @@ $.fx.step['svgStroke-dasharray'] = $.fx.step['svg-stroke-dasharray'] = function( (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 */ +/** Parse a strokeDashArray definition: dash, gap, ... + @private + @param value {string} The definition. + @return {number[]} The extracted values. */ function parseDashArray(value) { var dashArray = value.split(/[, ]+/); for (var i = 0; i < dashArray.length; i++) { @@ -81,7 +83,7 @@ function parseDashArray(value) { dashArray[i] = 0; } } - if (dashArray.length % 2 == 1) { // Must have an even number + 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]); @@ -95,8 +97,7 @@ $.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 = ($.fn.jquery >= '1.6' ? fx.end : - fx.options.curAnim['svgViewBox'] || fx.options.curAnim['svg-viewBox']); + var offset = (jQueryNew ? fx.end : fx.options.curAnim['svgViewBox'] || fx.options.curAnim['svg-viewBox']); fx.end = parseViewBox(offset); if (/^[+-]=/.exec(offset)) { offset = offset.split(/[, ]+/); @@ -117,9 +118,10 @@ $.fx.step['svgViewBox'] = $.fx.step['svg-viewBox'] = function(fx) { (attr ? attr.nodeValue = value : fx.elem.setAttribute('viewBox', value)); }; -/* Parse a viewBox definition: x, y, width, height. - @param value (string) the definition - @return (number[4]) the extracted values */ +/** Parse a viewBox definition: x, y, width, height. + @private + @param value {string} The definition. + @return {number[]} The extracted values. */ function parseViewBox(value) { var viewBox = value.split(/[, ]+/); for (var i = 0; i < viewBox.length; i++) { @@ -151,22 +153,18 @@ $.fx.step['svgTransform'] = $.fx.step['svg-transform'] = function(fx) { (fx.pos * (fx.end.translateY - fx.start.translateY) + fx.start.translateY) + ')'; break; case 's': - transform += ' scale(' + - (fx.pos * (fx.end.scaleX - fx.start.scaleX) + fx.start.scaleX) + ',' + + 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 += ' 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) + ')'; break; case 'x': - transform += ' 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 += ' 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 = ''; @@ -180,18 +178,18 @@ $.fx.step['svgTransform'] = $.fx.step['svg-transform'] = function(fx) { (attr ? attr.nodeValue = transform : fx.elem.setAttribute('transform', transform)); }; -/* Decode a transform string and extract component values. - @param value (string) the transform string to parse - @param original (object) the settings from the original node - @return (object) the combined transformation attributes */ +/** Decode a transform string and extract component values. + @private + @param value {string} The transform string to parse. + @param original {object} The settings from the original node. + @return {object} The combined transformation attributes. */ function parseTransform(value, original) { value = value || ''; - if (typeof value == 'object') { + 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 || {}); + rotateA: 0, rotateX: 0, rotateY: 0, skewX: 0, skewY: 0, matrix: [0, 0, 0, 0, 0, 0]}, original || {}); transform.order = ''; var pattern = /([a-zA-Z]+)\(\s*([+-]?[\d\.]+)\s*(?:[\s,]\s*([+-]?[\d\.]+)\s*(?:[\s,]\s*([+-]?[\d\.]+)\s*(?:[\s,]\s*([+-]?[\d\.]+)\s*[\s,]\s*([+-]?[\d\.]+)\s*[\s,]\s*([+-]?[\d\.]+)\s*)?)?)?\)/g; var result = pattern.exec(value); @@ -224,14 +222,13 @@ function parseTransform(value, original) { case 'matrix': transform.order += 'm'; transform.matrix = [parseFloat(result[2]), parseFloat(result[3]), - parseFloat(result[4]), parseFloat(result[5]), - parseFloat(result[6]), parseFloat(result[7])]; + parseFloat(result[4]), parseFloat(result[5]), parseFloat(result[6]), parseFloat(result[7])]; 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])) { + 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); @@ -251,49 +248,51 @@ $.each(['fill', 'stroke'], $.fx.step['svg' + ccName] = $.fx.step['svg-' + attrName] = function(fx) { if (!fx.set) { fx.start = $.svg._getColour(fx.elem, attrName); - var toNone = (fx.end == 'none'); + var toNone = (fx.end === 'none'); fx.end = (toNone ? $.svg._getColour(fx.elem.parentNode, attrName) : $.svg._getRGB(fx.end)); fx.end[3] = toNone; $(fx.elem).css(attrName, ''); fx.set = true; } - var attr = fx.elem.attributes.getNamedItem(attrName); var colour = 'rgb(' + [ Math.min(Math.max(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 0), 255), Math.min(Math.max(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 0), 255), Math.min(Math.max(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 0), 255) ].join(',') + ')'; - colour = (fx.end[3] && fx.state == 1 ? 'none' : colour); + colour = (fx.end[3] && fx.state === 1 ? 'none' : colour); + var attr = fx.elem.attributes.getNamedItem(attrName); (attr ? attr.nodeValue = colour : fx.elem.setAttribute(attrName, colour)); } } ); -/* Find this attribute value somewhere up the node hierarchy. - @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 */ +/** Find this attribute value somewhere up the node hierarchy. + @private + @param elem {SVGElement} The starting element to find the attribute. + @param attr {string} The attribute name. + @return {number[]} RGB components for the attribute colour. */ $.svg._getColour = function(elem, attr) { elem = $(elem); var colour; do { 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($.svg.markerClassName)) { + if ((colour !== '' && colour !== 'none') || elem.hasClass($.svg.markerClassName)) { break; } } 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 */ +/** Parse strings looking for common colour formats. + @private + @param colour {string} Colour description to parse. + @return {number[]} RGB components of this colour. */ $.svg._getRGB = function(colour) { var result; // Check if we're already dealing with an array of colors - if (colour && colour.constructor == Array) { - return (colour.length == 3 || colour.length == 4 ? colour : colours['none']); + 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)) { @@ -301,8 +300,7 @@ $.svg._getRGB = function(colour) { } // 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)) { - return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, - parseFloat(result[3]) * 2.55]; + 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)) { diff --git a/jquery.svganim.min.js b/jquery.svganim.min.js index 8b0eca8..d9a9ac4 100644 --- a/jquery.svganim.min.js +++ b/jquery.svganim.min.js @@ -1,7 +1,6 @@ -/* http://keith-wood.name/svg.html - SVG attribute animations for jQuery v1.4.5. +/* http://keith-wood.name/svg.html + SVG attribute animations for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ -(function($){$.each(['x','y','width','height','rx','ry','cx','cy','r','x1','y1','x2','y2','stroke-width','strokeWidth','opacity','fill-opacity','fillOpacity','stroke-opacity','strokeOpacity','stroke-dashoffset','strokeDashOffset','font-size','fontSize','font-weight','fontWeight','letter-spacing','letterSpacing','word-spacing','wordSpacing'],function(i,f){var g=f.charAt(0).toUpperCase()+f.substr(1);if($.cssProps){$.cssProps['svg'+g]=$.cssProps['svg-'+f]=f}$.fx.step['svg'+g]=$.fx.step['svg-'+f]=function(a){var b=$.svg._attrNames[f]||f;var c=a.elem.attributes.getNamedItem(b);if(!a.set){a.start=(c?parseFloat(c.nodeValue):0);var d=($.fn.jquery>='1.6'?'':a.options.curAnim['svg'+g]||a.options.curAnim['svg-'+f]);if(/^[+-]=/.exec(d)){a.end=a.start+parseFloat(d.replace(/=/,''))}$(a.elem).css(b,'');a.set=true}var e=(a.pos*(a.end-a.start)+a.start)+(a.unit=='%'?'%':'');(c?c.nodeValue=e:a.elem.setAttribute(b,e))}});$.fx.step['svgStrokeDashArray']=$.fx.step['svg-strokeDashArray']=$.fx.step['svgStroke-dasharray']=$.fx.step['svg-stroke-dasharray']=function(a){var b=a.elem.attributes.getNamedItem('stroke-dasharray');if(!a.set){a.start=parseDashArray(b?b.nodeValue:'');var c=($.fn.jquery>='1.6'?a.end:a.options.curAnim['svgStrokeDashArray']||a.options.curAnim['svg-strokeDashArray']||a.options.curAnim['svgStroke-dasharray']||a.options.curAnim['svg-stroke-dasharray']);a.end=parseDashArray(c);if(/^[+-]=/.exec(c)){c=c.split(/[, ]+/);if(c.length%2==1){var d=c.length;for(var i=0;i='1.6'?a.end:a.options.curAnim['svgViewBox']||a.options.curAnim['svg-viewBox']);a.end=parseViewBox(c);if(/^[+-]=/.exec(c)){c=c.split(/[, ]+/);while(c.length<4){c.push('0')}for(var i=0;i<4;i++){if(/^[+-]=/.exec(c[i])){a.end[i]=a.start[i]+parseFloat(c[i].replace(/=/,''))}}}a.set=true}var d=$.map(a.start,function(n,i){return(a.pos*(a.end[i]-n)+n)}).join(' ');(b?b.nodeValue=d:a.elem.setAttribute('viewBox',d))};function parseViewBox(a){var b=a.split(/[, ]+/);for(var i=0;i1||parseInt($.fn.jquery.substring(2),10)>5;$.each(['x','y','width','height','rx','ry','cx','cy','r','x1','y1','x2','y2','stroke-width','strokeWidth','opacity','fill-opacity','fillOpacity','stroke-opacity','strokeOpacity','stroke-dashoffset','strokeDashOffset','font-size','fontSize','font-weight','fontWeight','letter-spacing','letterSpacing','word-spacing','wordSpacing'],function(i,f){var g=f.charAt(0).toUpperCase()+f.substr(1);if($.cssProps){$.cssProps['svg'+g]=$.cssProps['svg-'+f]=f}$.fx.step['svg'+g]=$.fx.step['svg-'+f]=function(a){var b=$.svg._attrNames[f]||f;var c=a.elem.attributes.getNamedItem(b);if(!a.set){a.start=(c?parseFloat(c.nodeValue):0);var d=(h?'':a.options.curAnim['svg'+g]||a.options.curAnim['svg-'+f]);if(/^[+-]=/.exec(d)){a.end=a.start+parseFloat(d.replace(/=/,''))}$(a.elem).css(b,'');a.set=true}var e=(a.pos*(a.end-a.start)+a.start)+(a.unit==='%'?'%':'');(c?c.nodeValue=e:a.elem.setAttribute(b,e))}});$.fx.step['svgStrokeDashArray']=$.fx.step['svg-strokeDashArray']=$.fx.step['svgStroke-dasharray']=$.fx.step['svg-stroke-dasharray']=function(a){var b=a.elem.attributes.getNamedItem('stroke-dasharray');if(!a.set){a.start=parseDashArray(b?b.nodeValue:'');var c=(h?a.end:a.options.curAnim['svgStrokeDashArray']||a.options.curAnim['svg-strokeDashArray']||a.options.curAnim['svgStroke-dasharray']||a.options.curAnim['svg-stroke-dasharray']);a.end=parseDashArray(c);if(/^[+-]=/.exec(c)){c=c.split(/[, ]+/);if(c.length%2===1){var d=c.length;for(var i=0;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(A($){$.2f([\'x\',\'y\',\'2g\',\'2S\',\'2T\',\'2U\',\'2V\',\'2W\',\'r\',\'2X\',\'2Y\',\'2Z\',\'31\',\'U-2g\',\'33\',\'1F\',\'2h-1F\',\'36\',\'U-1F\',\'37\',\'U-38\',\'39\',\'2i-3a\',\'3b\',\'2i-3c\',\'3d\',\'3e-2j\',\'3f\',\'3g-2j\',\'3h\'],A(i,f){l g=f.1G(0).2k()+f.1H(1);q($.1I){$.1I[\'u\'+g]=$.1I[\'u-\'+f]=f}$.D.E[\'u\'+g]=$.D.E[\'u-\'+f]=A(a){l b=$.u.3i[f]||f;l c=a.B.1l.1m(b);q(!a.N){a.k=(c?p(c.O):0);l d=($.1J.1K>=\'1.6\'?\'\':a.V.W[\'u\'+g]||a.V.W[\'u-\'+f]);q(/^[+-]=/.L(d)){a.o=a.k+p(d.1L(/=/,\'\'))}$(a.B).1M(b,\'\');a.N=1n}l e=(a.w*(a.o-a.k)+a.k)+(a.3j==\'%\'?\'%\':\'\');(c?c.O=e:a.B.1o(b,e))}});$.D.E[\'2l\']=$.D.E[\'u-2m\']=$.D.E[\'2n-17\']=$.D.E[\'u-U-17\']=A(a){l b=a.B.1l.1m(\'U-17\');q(!a.N){a.k=1N(b?b.O:\'\');l c=($.1J.1K>=\'1.6\'?a.o:a.V.W[\'2l\']||a.V.W[\'u-2m\']||a.V.W[\'2n-17\']||a.V.W[\'u-U-17\']);a.o=1N(c);q(/^[+-]=/.L(c)){c=c.1r(/[, ]+/);q(c.F%2==1){l d=c.F;X(l i=0;i=\'1.6\'?a.o:a.V.W[\'2q\']||a.V.W[\'u-1t\']);a.o=1P(c);q(/^[+-]=/.L(c)){c=c.1r(/[, ]+/);1u(c.F<4){c.1s(\'0\')}X(l i=0;i<4;i++){q(/^[+-]=/.L(c[i])){a.o[i]=a.k[i]+p(c[i].1L(/=/,\'\'))}}}a.N=1n}l d=$.2o(a.k,A(n,i){G(a.w*(a.o[i]-n)+n)}).1O(\' \');(b?b.O=d:a.B.1o(\'1t\',d))};A 1P(a){l b=a.1r(/[, ]+/);X(l i=0;itrue if this class is present, false if not. */ $.fn.hasClass = function(origHasClass) { return function(className) { className = className || ''; var found = false; this.each(function() { if ($.svg.isSVGElem(this)) { - var classes = (this.className ? this.className.baseVal : - this.getAttribute('class')).split(/\s+/); - found = ($.inArray(className, classes) > -1); + found = ($.inArray(className, getClassNames(this).split(/\s+/)) > -1); } else { found = (origHasClass.apply($(this), [className])); @@ -89,15 +140,19 @@ $.fn.hasClass = function(origHasClass) { }; }($.fn.hasClass); -/* Support attributes on SVG nodes. */ +/** Support attributes on SVG nodes. + @param name {string} The attribute name. + @param [value] {any} The new attribute value. + @param type {boolean} Internal flag. + @return {any} If an attribute value is requested. */ $.fn.attr = function(origAttr) { return function(name, value, type) { - if (typeof name === 'string' && value === undefined) { - var val = origAttr.apply(this, [name]); + if (typeof name === 'string' && value === undefined) { // Return attribute value + var val = origAttr.apply(this, arguments); if (val && val.baseVal && val.baseVal.numberOfItems != null) { // Multiple values value = ''; val = val.baseVal; - if (name == 'transform') { + if (name === 'transform') { for (var i = 0; i < val.numberOfItems; i++) { var item = val.getItem(i); switch (item.type) { @@ -126,30 +181,39 @@ $.fn.attr = function(origAttr) { options = {}; options[name] = value; } - return this.each(function() { + if ($.isFunction(value)) { + return $(this).each(function(i) { + $(this).attr(name, value.call(this, i, $(this).attr(name))); + }); + } + var origArgs = arguments; + return $(this).each(function() { 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)); + (type ? this.style[n] = options[n] : this.setAttribute(n, options[n])); } } else { - origAttr.apply($(this), [name, value, type]); + origAttr.apply($(this), origArgs); } }); }; }($.fn.attr); -/* Support removing attributes on SVG nodes. */ +/** Support removing attributes on SVG nodes. + @param names {string} The names of the attributes to remove. */ $.fn.removeAttr = function(origRemoveAttr) { - return function(name) { + return function(names) { + var origArgs = arguments; return this.each(function() { if ($.svg.isSVGElem(this)) { - (this[name] && this[name].baseVal ? this[name].baseVal.value = '' : - this.setAttribute(name, '')); + var node = this; + $.each(names.split(/\s+/), function(i, name) { + (node[name] && node[name].baseVal ? node[name].baseVal.value = null : node.removeAttribute(name)); + }); } else { - origRemoveAttr.apply($(this), [name]); + origRemoveAttr.apply($(this), origArgs); } }); }; @@ -165,242 +229,11 @@ $.extend($.cssNumber, { /* Support retrieving CSS/attribute values on SVG nodes. */ if ($.cssProps) { $.css = function(origCSS) { - return function(elem, name, extra) { + return function(elem, name, numeric, extra) { var value = (name.match(/^svg.*/) ? $(elem).attr($.cssProps[name] || name) : ''); - return value || origCSS(elem, name, extra); + return value || origCSS(elem, name, numeric, extra); }; }($.css); } - -/* Determine if any nodes are SVG nodes. */ -function anySVG(checkSet) { - for (var i = 0; i < checkSet.length; i++) { - if (checkSet[i].nodeType == 1 && checkSet[i].namespaceURI == $.svg.svgNS) { - return true; - } - } - return false; -} - -/* Update Sizzle selectors. */ - -$.expr.relative['+'] = function(origRelativeNext) { - return function(checkSet, part, isXML) { - origRelativeNext(checkSet, part, isXML || anySVG(checkSet)); - }; -}($.expr.relative['+']); - -$.expr.relative['>'] = function(origRelativeChild) { - return function(checkSet, part, isXML) { - origRelativeChild(checkSet, part, isXML || anySVG(checkSet)); - }; -}($.expr.relative['>']); - -$.expr.relative[''] = function(origRelativeDescendant) { - return function(checkSet, part, isXML) { - origRelativeDescendant(checkSet, part, isXML || anySVG(checkSet)); - }; -}($.expr.relative['']); - -$.expr.relative['~'] = function(origRelativeSiblings) { - return function(checkSet, part, isXML) { - origRelativeSiblings(checkSet, part, isXML || anySVG(checkSet)); - }; -}($.expr.relative['~']); - -$.expr.find.ID = function(origFindId) { - return function(match, context, isXML) { - return ($.svg.isSVGElem(context) ? - [context.ownerDocument.getElementById(match[1])] : - origFindId(match, context, isXML)); - }; -}($.expr.find.ID); - -var div = document.createElement('div'); -div.appendChild(document.createComment('')); -if (div.getElementsByTagName('*').length > 0) { // Make sure no comments are found - $.expr.find.TAG = function(match, context) { - var results = context.getElementsByTagName(match[1]); - if (match[1] === '*') { // Filter out possible comments - var tmp = []; - for (var i = 0; results[i] || results.item(i); i++) { - if ((results[i] || results.item(i)).nodeType === 1) { - tmp.push(results[i] || results.item(i)); - } - } - results = tmp; - } - return results; - }; -} - -$.expr.preFilter.CLASS = function(match, curLoop, inplace, result, not, isXML) { - match = ' ' + match[1].replace(/\\/g, '') + ' '; - if (isXML) { - return match; - } - for (var i = 0, elem = {}; elem != null; i++) { - elem = curLoop[i]; - if (!elem) { - try { - elem = curLoop.item(i); - } - catch (e) { - // Ignore - } - } - if (elem) { - var className = (!$.svg.isSVGElem(elem) ? elem.className : - (elem.className ? elem.className.baseVal : '') || elem.getAttribute('class')); - if (not ^ (className && (' ' + className + ' ').indexOf(match) > -1)) { - if (!inplace) - result.push(elem); - } - else if (inplace) { - curLoop[i] = false; - } - } - } - return false; -}; - -$.expr.filter.CLASS = function(elem, match) { - var className = (!$.svg.isSVGElem(elem) ? elem.className : - (elem.className ? elem.className.baseVal : elem.getAttribute('class'))); - return (' ' + className + ' ').indexOf(match) > -1; -}; - -$.expr.filter.ATTR = function(origFilterAttr) { - return function(elem, match) { - var handler = null; - if ($.svg.isSVGElem(elem)) { - handler = match[1]; - $.expr.attrHandle[handler] = function(elem){ - var attr = elem.getAttribute(handler); - return attr && attr.baseVal || attr; - }; - } - var filter = origFilterAttr(elem, match); - if (handler) { - $.expr.attrHandle[handler] = null; - } - return filter; - }; -}($.expr.filter.ATTR); - -/* - In the 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 ); - ... - -*/ })(jQuery); diff --git a/jquery.svgdom.min.js b/jquery.svgdom.min.js index 5c76168..3def35f 100644 --- a/jquery.svgdom.min.js +++ b/jquery.svgdom.min.js @@ -1,7 +1,6 @@ -/* http://keith-wood.name/svg.html - jQuery DOM compatibility for jQuery SVG v1.4.5. +/* http://keith-wood.name/svg.html + jQuery DOM compatibility for jQuery SVG v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ -(function($){$.fn.addClass=function(e){return function(d){d=d||'';return this.each(function(){if($.svg.isSVGElem(this)){var c=this;$.each(d.split(/\s+/),function(i,a){var b=(c.className?c.className.baseVal:c.getAttribute('class'));if($.inArray(a,b.split(/\s+/))==-1){b+=(b?' ':'')+a;(c.className?c.className.baseVal=b:c.setAttribute('class',b))}})}else{e.apply($(this),[d])}})}}($.fn.addClass);$.fn.removeClass=function(e){return function(d){d=d||'';return this.each(function(){if($.svg.isSVGElem(this)){var c=this;$.each(d.split(/\s+/),function(i,a){var b=(c.className?c.className.baseVal:c.getAttribute('class'));b=$.grep(b.split(/\s+/),function(n,i){return n!=a}).join(' ');(c.className?c.className.baseVal=b:c.setAttribute('class',b))})}else{e.apply($(this),[d])}})}}($.fn.removeClass);$.fn.toggleClass=function(c){return function(a,b){return this.each(function(){if($.svg.isSVGElem(this)){if(typeof b!=='boolean'){b=!$(this).hasClass(a)}$(this)[(b?'add':'remove')+'Class'](a)}else{c.apply($(this),[a,b])}})}}($.fn.toggleClass);$.fn.hasClass=function(d){return function(b){b=b||'';var c=false;this.each(function(){if($.svg.isSVGElem(this)){var a=(this.className?this.className.baseVal:this.getAttribute('class')).split(/\s+/);c=($.inArray(b,a)>-1)}else{c=(d.apply($(this),[b]))}return!c});return c}}($.fn.hasClass);$.fn.attr=function(h){return function(b,c,d){if(typeof b==='string'&&c===undefined){var e=h.apply(this,[b]);if(e&&e.baseVal&&e.baseVal.numberOfItems!=null){c='';e=e.baseVal;if(b=='transform'){for(var i=0;i']=function(d){return function(a,b,c){d(a,b,c||anySVG(a))}}($.expr.relative['>']);$.expr.relative['']=function(d){return function(a,b,c){d(a,b,c||anySVG(a))}}($.expr.relative['']);$.expr.relative['~']=function(d){return function(a,b,c){d(a,b,c||anySVG(a))}}($.expr.relative['~']);$.expr.find.ID=function(d){return function(a,b,c){return($.svg.isSVGElem(b)?[b.ownerDocument.getElementById(a[1])]:d(a,b,c))}}($.expr.find.ID);var j=document.createElement('div');j.appendChild(document.createComment(''));if(j.getElementsByTagName('*').length>0){$.expr.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==='*'){var d=[];for(var i=0;c[i]||c.item(i);i++){if((c[i]||c.item(i)).nodeType===1){d.push(c[i]||c.item(i))}}c=d}return c}}$.expr.preFilter.CLASS=function(a,b,c,d,f,g){a=' '+a[1].replace(/\\/g,'')+' ';if(g){return a}for(var i=0,elem={};elem!=null;i++){elem=b[i];if(!elem){try{elem=b.item(i)}catch(e){}}if(elem){var h=(!$.svg.isSVGElem(elem)?elem.className:(elem.className?elem.className.baseVal:'')||elem.getAttribute('class'));if(f^(h&&(' '+h+' ').indexOf(a)>-1)){if(!c)d.push(elem)}else if(c){b[i]=false}}}return false};$.expr.filter.CLASS=function(a,b){var c=(!$.svg.isSVGElem(a)?a.className:(a.className?a.className.baseVal:a.getAttribute('class')));return(' '+c+' ').indexOf(b)>-1};$.expr.filter.ATTR=function(g){return function(c,d){var e=null;if($.svg.isSVGElem(c)){e=d[1];$.expr.attrHandle[e]=function(a){var b=a.getAttribute(e);return b&&b.baseVal||b}}var f=g(c,d);if(e){$.expr.attrHandle[e]=null}return f}}($.expr.filter.ATTR)})(jQuery); \ No newline at end of file +(function($){var j=/[\t\r\n]/g,rspace=/\s+/,rwhitespace="[\\x20\\t\\r\\n\\f]";function getClassNames(a){return(!$.svg.isSVGElem(a)?a.className:(a.className?a.className.baseVal:a.getAttribute('class')))||''}function setClassNames(a,b){(a.className?a.className.baseVal=b:a.setAttribute('class',b))}$.fn.addClass=function(f){return function(d){if($.isFunction(d)){return this.each(function(i){$(this).addClass(d.call(this,i,getClassNames(this)))})}var e=arguments;d=d||'';return this.each(function(){if($.svg.isSVGElem(this)){var c=this;$.each(d.split(/\s+/),function(i,a){var b=getClassNames(c);if($.inArray(a,b.split(/\s+/))===-1){setClassNames(c,b+=(b?' ':'')+a)}})}else{f.apply($(this),e)}})}}($.fn.addClass);$.fn.removeClass=function(f){return function(d){if($.isFunction(d)){return this.each(function(i){$(this).removeClass(d.call(this,i,getClassNames(this)))})}var e=arguments;d=d||'';return this.each(function(){if($.svg.isSVGElem(this)){var c=this;$.each(d.split(/\s+/),function(i,a){var b=getClassNames(c);b=$.grep(b.split(/\s+/),function(n,i){return n!==a}).join(' ');setClassNames(c,b)})}else{f.apply($(this),e)}})}}($.fn.removeClass);$.fn.toggleClass=function(h){return function(d,e){if($.isFunction(d)){return this.each(function(i){$(this).toggleClass(d.call(this,i,getClassNames(this),e),e)})}var f=arguments;var g=(typeof e==='boolean');return this.each(function(){if($.svg.isSVGElem(this)){if(typeof d==='string'){var b=$(this);$.each(d.split(/\s+/),function(i,a){if(!g){e=!b.hasClass(a)}b[(e?'add':'remove')+'Class'](a)})}else{var c=getClassNames(this);if(c){$._data(this,'__className__',c)}setClassNames(this,c||d===false?'':$._data(this,'__className__')||'')}}else{h.apply($(this),f)}})}}($.fn.toggleClass);$.fn.hasClass=function(c){return function(a){a=a||'';var b=false;this.each(function(){if($.svg.isSVGElem(this)){b=($.inArray(a,getClassNames(this).split(/\s+/))>-1)}else{b=(c.apply($(this),[a]))}return!b});return b}}($.fn.hasClass);$.fn.attr=function(h){return function(a,b,c){if(typeof a==='string'&&b===undefined){var d=h.apply(this,arguments);if(d&&d.baseVal&&d.baseVal.numberOfItems!=null){b='';d=d.baseVal;if(a==='transform'){for(var i=0;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.q.S=7(e){8 7(d){d=d||\'\';8 9.w(7(){k($.r.v(9)){l c=9;$.w(d.E(/\\s+/),7(i,a){l b=(c.o?c.o.p:c.B(\'z\'));k($.T(a,b.E(/\\s+/))==-1){b+=(b?\' \':\'\')+a;(c.o?c.o.p=b:c.H(\'z\',b))}})}x{e.A($(9),[d])}})}}($.q.S);$.q.U=7(e){8 7(d){d=d||\'\';8 9.w(7(){k($.r.v(9)){l c=9;$.w(d.E(/\\s+/),7(i,a){l b=(c.o?c.o.p:c.B(\'z\'));b=$.1d(b.E(/\\s+/),7(n,i){8 n!=a}).1e(\' \');(c.o?c.o.p=b:c.H(\'z\',b))})}x{e.A($(9),[d])}})}}($.q.U);$.q.V=7(c){8 7(a,b){8 9.w(7(){k($.r.v(9)){k(M b!==\'1f\'){b=!$(9).N(a)}$(9)[(b?\'1g\':\'1h\')+\'1i\'](a)}x{c.A($(9),[a,b])}})}}($.q.V);$.q.N=7(d){8 7(b){b=b||\'\';l c=I;9.w(7(){k($.r.v(9)){l a=(9.o?9.o.p:9.B(\'z\')).E(/\\s+/);c=($.T(b,a)>-1)}x{c=(d.A($(9),[b]))}8!c});8 c}}($.q.N);$.q.O=7(h){8 7(b,c,d){k(M b===\'W\'&&c===1j){l e=h.A(9,[b]);k(e&&e.p&&e.p.X!=J){c=\'\';e=e.p;k(b==\'1k\'){F(l i=0;i\']=7(d){8 7(a,b,c){d(a,b,c||G(a))}}($.m.y[\'>\']);$.m.y[\'\']=7(d){8 7(a,b,c){d(a,b,c||G(a))}}($.m.y[\'\']);$.m.y[\'~\']=7(d){8 7(a,b,c){d(a,b,c||G(a))}}($.m.y[\'~\']);$.m.Q.15=7(d){8 7(a,b,c){8($.r.v(b)?[b.1F.1G(a[1])]:d(a,b,c))}}($.m.Q.15);l j=16.1H(\'1I\');j.1J(16.1K(\'\'));k(j.17(\'*\').13>0){$.m.Q.1L=7(a,b){l c=b.17(a[1]);k(a[1]===\'*\'){l d=[];F(l i=0;c[i]||c.L(i);i++){k((c[i]||c.L(i)).14===1){d.18(c[i]||c.L(i))}}c=d}8 c}}$.m.1M.19=7(a,b,c,d,f,g){a=\' \'+a[1].1N(/\\\\/g,\'\')+\' \';k(g){8 a}F(l i=0,t={};t!=J;i++){t=b[i];k(!t){1O{t=b.L(i)}1P(e){}}k(t){l h=(!$.r.v(t)?t.o:(t.o?t.o.p:\'\')||t.B(\'z\'));k(f^(h&&(\' \'+h+\' \').1a(a)>-1)){k(!c)d.18(t)}x k(c){b[i]=I}}}8 I};$.m.R.19=7(a,b){l c=(!$.r.v(a)?a.o:(a.o?a.o.p:a.B(\'z\')));8(\' \'+c+\' \').1a(b)>-1};$.m.R.1b=7(g){8 7(c,d){l e=J;k($.r.v(c)){e=d[1];$.m.1c[e]=7(a){l b=a.B(e);8 b&&b.p||b}}l f=g(c,d);k(e){$.m.1c[e]=J}8 f}}($.m.R.1b)})(1Q);',62,115,'|||||||function|return|this|||||||||||if|var|expr||className|baseVal|fn|svg||elem|matrix|isSVGElem|each|else|relative|class|apply|getAttribute|case|break|split|for|anySVG|setAttribute|false|null|true|item|typeof|hasClass|attr|angle|find|filter|addClass|inArray|removeClass|toggleClass|string|numberOfItems|getItem|valueAsString|removeAttr|cssProps|css|length|nodeType|ID|document|getElementsByTagName|push|CLASS|indexOf|ATTR|attrHandle|grep|join|boolean|add|remove|Class|undefined|transform|switch|type|translate|scale|rotate|skewX|skewY|substring|in|isFunction|style|value|extend|cssNumber|stopOpacity|strokeMitrelimit|strokeOpacity|match|namespaceURI|svgNS|ownerDocument|getElementById|createElement|div|appendChild|createComment|TAG|preFilter|replace|try|catch|jQuery'.split('|'),0,{})) \ No newline at end of file diff --git a/jquery.svgfilter.js b/jquery.svgfilter.js index 7e5466e..e36d30c 100644 --- a/jquery.svgfilter.js +++ b/jquery.svgfilter.js @@ -1,8 +1,7 @@ /* http://keith-wood.name/svg.html - SVG filters for jQuery v1.4.5. + SVG filters for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ (function($) { // Hide scope, no $ conflict @@ -11,139 +10,130 @@ $.svg.addExtension('filters', SVGFilter); $.extend($.svg._wrapperClass.prototype, { - /* Add a filter definition. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param id (string) the ID for this filter - @param x (number) the x-coordinate for the left edge of the filter - @param y (number) the y-coordinate for the top edge of the filter - @param width (number) the width of the filter - @param height (number) the height of the filter - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a filter definition. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param id {string} The ID for this filter. + @param x {number} The x-coordinate for the left edge of the filter. + @param y {number} The y-coordinate for the top edge of the filter. + @param width {number} The width of the filter. + @param height {number} The height of the filter. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ filter: function(parent, id, x, y, width, height, settings) { var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height']); return this._makeNode(args.parent, 'filter', $.extend( - {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height}, - args.settings || {})); + {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height}, args.settings || {})); } }); -/* Extension point for SVG filters. - Access through svg.filters. */ +/** The SVG filters manager. +

Use the singleton instance of this class, $.svg.filters, + to interact with the SVG filters functionality.

+ @module SVGFilter */ function SVGFilter(wrapper) { this._wrapper = wrapper; // The attached SVG wrapper object } $.extend(SVGFilter.prototype, { - /* Add a distant light filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param azimuth (number) the angle (degrees) in the XY plane for the light source - @param elevation (number) the angle (degrees) in the YZ plane for the light source - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a distant light filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param azimuth {number} The angle (degrees) in the XY plane for the light source. + @param elevation {number} The angle (degrees) in the YZ plane for the light source. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ distantLight: function(parent, result, azimuth, elevation, settings) { var args = this._wrapper._args(arguments, ['result', 'azimuth', 'elevation']); return this._wrapper._makeNode(args.parent, 'feDistantLight', $.extend( - {result: args.result, azimuth: args.azimuth, elevation: args.elevation}, - args.settings || {})); + {result: args.result, azimuth: args.azimuth, elevation: args.elevation}, args.settings || {})); }, - /* Add a point light filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param x (number) the x-coordinate for the light source - @param y (number) the y-coordinate for the light source - @param z (number) the z-coordinate for the light source - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a point light filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param x {number} The x-coordinate for the light source. + @param y {number} The y-coordinate for the light source. + @param z {number} The z-coordinate for the light source. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ pointLight: function(parent, result, x, y, z, settings) { var args = this._wrapper._args(arguments, ['result', 'x', 'y', 'z']); return this._wrapper._makeNode(args.parent, 'fePointLight', $.extend( {result: args.result, x: args.x, y: args.y, z: args.z}, args.settings || {})); }, - /* Add a spot light filter. - Specify all of toX, toY, toZ or none of them. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param x (number) the x-coordinate for the light source - @param y (number) the y-coordinate for the light source - @param z (number) the z-coordinate for the light source - @param toX (number) the x-coordinate for where the light is pointing (optional) - @param toY (number) the y-coordinate for where the light is pointing (optional) - @param toZ (number) the z-coordinate for where the light is pointing (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a spot light filter. +

Specify all of toX, toY, toZ or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param x {number} The x-coordinate for the light source. + @param y {number} The y-coordinate for the light source. + @param z {number} The z-coordinate for the light source. + @param [toX] {number} The x-coordinate for where the light is pointing. + @param [toY] {number} The y-coordinate for where the light is pointing. + @param [toZ] {number} The z-coordinate for where the light is pointing. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ spotLight: function(parent, result, x, y, z, toX, toY, toZ, settings) { - var args = this._wrapper._args(arguments, - ['result', 'x', 'y', 'z', 'toX', 'toY', 'toZ'], ['toX']); + var args = this._wrapper._args(arguments, ['result', 'x', 'y', 'z', 'toX', 'toY', 'toZ'], ['toX']); var sets = $.extend({result: args.result, x: args.x, y: args.y, z: args.z}, - (args.toX != null ? {pointsAtX: args.toX, pointsAtY: args.toY, - pointsAtZ: args.toZ} : {})); - return this._wrapper._makeNode(args.parent, 'feSpotLight', - $.extend(sets, args.settings || {})); + (args.toX != null ? {pointsAtX: args.toX, pointsAtY: args.toY, pointsAtZ: args.toZ} : {})); + return this._wrapper._makeNode(args.parent, 'feSpotLight', $.extend(sets, args.settings || {})); }, - /* Add a blend filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param mode (string) normal | multiply | screen | darken | lighten - @param in1 (string) the first image to blend - @param in2 (string) the second image to blend - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a blend filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param mode {string} One of 'normal', 'multiply', 'screen', 'darken', 'lighten'. + @param in1 {string} The first image to blend. + @param in2 {string} The second image to blend. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ blend: function(parent, result, mode, in1, in2, settings) { var args = this._wrapper._args(arguments, ['result', 'mode', 'in1', 'in2']); return this._wrapper._makeNode(args.parent, 'feBlend', $.extend( - {result: args.result, mode: args.mode, in_: args.in1, in2: args.in2}, - args.settings || {})); + {result: args.result, mode: args.mode, in_: args.in1, in2: args.in2}, args.settings || {})); }, - /* Add a colour matrix filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source to colour - @param type (string) matrix | saturate | hueRotate | luminanceToAlpha - @param values (number[][]) for 'matrix' the matrix (5x4) values to apply - (number) for 'saturate' 0.0 to 1.0 - (number) for 'hueRotate' degrees - (void) for 'luminanceToAlpha' - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a colour matrix filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param in1 {string} The source to colour. + @param type {string} One of 'matrix', 'saturate', 'hueRotate', 'luminanceToAlpha'. + @param values {number[][]|number} For 'matrix' the matrix (5x4) values to apply, for 'saturate' 0.0 to 1.0, + for 'hueRotate' degrees, for 'luminanceToAlpha' nothing. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ colorMatrix: function(parent, result, in1, type, values, settings) { var args = this._wrapper._args(arguments, ['result', 'in1', 'type', 'values']); - if (isArray(args.values)) { + if ($.isArray(args.values)) { var vs = ''; for (var i = 0; i < args.values.length; i++) { - vs += (i == 0 ? '' : ' ') + args.values[i].join(' '); + vs += (i === 0 ? '' : ' ') + args.values[i].join(' '); } args.values = vs; } - else if (typeof args.values == 'object') { + else if (typeof args.values === 'object') { args.settings = args.values; args.values = null; } var sets = $.extend({result: args.result, in_: args.in1, type: args.type}, (args.values != null ? {values: args.values} : {})); - return this._wrapper._makeNode(args.parent, 'feColorMatrix', - $.extend(sets, args.settings || {})); + return this._wrapper._makeNode(args.parent, 'feColorMatrix', $.extend(sets, args.settings || {})); }, - /* Add a component transfer filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param functions (object[]) one for each of RGB and A (alpha, optional) - for each entry: - [0] is (string) identity | table | discrete | linear | gamma - [1] is (number[]) for 'table' or 'discrete' the list of - interpolation or step values OR - (number) for 'linear' the slope, for 'gamma' the amplitude, - [2] is (number) for 'linear' the intercept, for 'gamma' the exponent, - [3] is (number) for 'gamma' the offset - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a component transfer filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param functions {object[]} One for each of RGB and A (alpha, optional), for each entry: + [0] {string} one of 'identity', 'table', 'discrete', 'linear', 'gamma', + [1] {number[]|number} for 'table' or 'discrete' the list of interpolation or step values OR + for 'linear' the slope, for 'gamma' the amplitude, + [2] {number} for 'linear' the intercept, for 'gamma' the exponent, + [3] {number} for 'gamma' the offset. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ componentTransfer: function(parent, result, functions, settings) { var args = this._wrapper._args(arguments, ['result', 'functions']); var node = this._wrapper._makeNode(args.parent, 'feComponentTransfer', @@ -152,99 +142,92 @@ $.extend(SVGFilter.prototype, { for (var i = 0; i < Math.min(4, args.functions.length); i++) { var props = args.functions[i]; var sets = $.extend({type: props[0]}, - (props[0] == 'table' || props[0] == 'discrete' ? {tableValues: props[1].join(' ')} : - (props[0] == 'linear' ? {slope: props[1], intercept: props[2]} : - (props[0] == 'gamma' ? {amplitude: props[1], - exponent: props[2], offset: props[3]} : {})))); + (props[0] === 'table' || props[0] === 'discrete' ? {tableValues: props[1].join(' ')} : + (props[0] === 'linear' ? {slope: props[1], intercept: props[2]} : + (props[0] === 'gamma' ? {amplitude: props[1], exponent: props[2], offset: props[3]} : {})))); this._wrapper._makeNode(node, 'feFunc' + rgba[i], sets); } return node; }, - /* Add a composite filter. - Specify all of k1, k2, k3, k4 or none of them. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param operator (string) over | in | out | atop | xor | arithmetic - @param in1 (string) the first filter to compose - @param in2 (string) the second filter to compose - @param k1 (number) for 'arithmetic' (optional) - @param k2 (number) for 'arithmetic' (optional) - @param k3 (number) for 'arithmetic' (optional) - @param k4 (number) for 'arithmetic' (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a composite filter. +

Specify all of k1, k2, k3, k4 or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param operator {string} One of 'over', 'in', 'out', 'atop', 'xor', 'arithmetic'. + @param in1 {string} The first filter to compose. + @param in2 {string} The second filter to compose. + @param [k1] {number} For 'arithmetic'. + @param [k2] {number} For 'arithmetic'. + @param [k3] {number} For 'arithmetic'. + @param [k4] {number} For 'arithmetic'. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ composite: function(parent, result, operator, in1, in2, k1, k2, k3, k4, settings) { - var args = this._wrapper._args(arguments, ['result', 'operator', - 'in1', 'in2', 'k1', 'k2', 'k3', 'k4'], ['k1']); - var sets = $.extend({result: args.result, operator: args.operator, - 'in': args.in1, in2: args.in2}, + var args = this._wrapper._args(arguments, ['result', 'operator', 'in1', 'in2', 'k1', 'k2', 'k3', 'k4'], ['k1']); + var sets = $.extend({result: args.result, operator: args.operator, 'in': args.in1, in2: args.in2}, (args.k1 != null ? {k1: args.k1, k2: args.k2, k3: args.k3, k4: args.k4} : {})); - return this._wrapper._makeNode(args.parent, 'feComposite', - $.extend(sets, args.settings || {})); + return this._wrapper._makeNode(args.parent, 'feComposite', $.extend(sets, args.settings || {})); }, - /* Add a convolve matrix filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param order (int or 'int int') the size(s) of the matrix - @param matrix (number[][]) the kernel matrix for the convolution - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a convolve matrix filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter + @param order {number|string} The size(s) of the matrix + optionally separated into x- and y-components ('number number'). + @param matrix {number[][]} The kernel matrix for the convolution. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ convolveMatrix: function(parent, result, order, matrix, settings) { var args = this._wrapper._args(arguments, ['result', 'order', 'matrix']); var mx = ''; for (var i = 0; i < args.matrix.length; i++) { - mx += (i == 0 ? '' : ' ') + args.matrix[i].join(' '); + mx += (i === 0 ? '' : ' ') + args.matrix[i].join(' '); } args.matrix = mx; return this._wrapper._makeNode(args.parent, 'feConvolveMatrix', $.extend( - {result: args.result, order: args.order, kernelMatrix: args.matrix}, - args.settings || {})); + {result: args.result, order: args.order, kernelMatrix: args.matrix}, args.settings || {})); }, - /* Add a diffuse lighting filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param colour (string) the lighting colour (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a diffuse lighting filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param [colour] {string} The lighting colour. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ diffuseLighting: function(parent, result, colour, settings) { var args = this._wrapper._args(arguments, ['result', 'colour'], ['colour']); - return this._wrapper._makeNode(args.parent, 'feDiffuseLighting', - $.extend($.extend({result: args.result}, + return this._wrapper._makeNode(args.parent, 'feDiffuseLighting', $.extend($.extend({result: args.result}, (args.colour ? {lightingColor: args.colour} : {})), args.settings || {})); }, - /* Add a displacement map filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source image - @param in2 (string) the displacement image - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a displacement map filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param in1 {string} The source image. + @param in2 {string} The displacement image. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ displacementMap: function(parent, result, in1, in2, settings) { var args = this._wrapper._args(arguments, ['result', 'in1', 'in2']); return this._wrapper._makeNode(args.parent, 'feDisplacementMap', - $.extend({result: args.result, in_: args.in1, in2: args.in2}, - args.settings || {})); + $.extend({result: args.result, in_: args.in1, in2: args.in2}, args.settings || {})); }, - /* Add a flood filter. - Specify all of x, y, width, height or none of them. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param x (number) the left coordinate of the rectangle (optional) - @param y (number) the top coordinate of the rectangle (optional) - @param width (number) the width of the rectangle (optional) - @param height (number) the height of the rectangle (optional) - @param colour (string) the colour to fill with - @param opacity (number) the opacity 0.0-1.0 - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a flood filter. +

Specify all of x, y, width, height or none of them.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param [x] {number} The left coordinate of the rectangle. + @param [y] {number} The top coordinate of the rectangle. + @param [width] {number} The width of the rectangle. + @param [height] {number} The height of the rectangle. + @param colour {string} The colour to fill with. + @param opacity {number} The opacity 0.0-1.0. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ flood: function(parent, result, x, y, width, height, colour, opacity, settings) { - var args = this._wrapper._args(arguments, - ['result', 'x', 'y', 'width', 'height', 'colour', 'opacity']); + var args = this._wrapper._args(arguments, ['result', 'x', 'y', 'width', 'height', 'colour', 'opacity']); if (arguments.length < 6) { args.colour = args.x; args.opacity = args.y; @@ -254,149 +237,132 @@ $.extend(SVGFilter.prototype, { var sets = $.extend({result: args.result, floodColor: args.colour, floodOpacity: args.opacity}, (args.x != null ? {x: args.x, y: args.y, width: args.width, height: args.height} : {})); - return this._wrapper._makeNode(args.parent, 'feFlood', - $.extend(sets, args.settings || {})); + return this._wrapper._makeNode(args.parent, 'feFlood', $.extend(sets, args.settings || {})); }, - /* Add a Gaussian blur filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source filter - @param stdDevX (number) the standard deviation along the x-axis - @param stdDevY (number) the standard deviation along the y-axis (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a Gaussian blur filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param in1 {string} The source filter. + @param stdDevX {number} The standard deviation along the x-axis. + @param [stdDevY] {number} The standard deviation along the y-axis. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ gaussianBlur: function(parent, result, in1, stdDevX, stdDevY, settings) { - var args = this._wrapper._args(arguments, - ['result', 'in1', 'stdDevX', 'stdDevY'], ['stdDevY']); + var args = this._wrapper._args(arguments, ['result', 'in1', 'stdDevX', 'stdDevY'], ['stdDevY']); return this._wrapper._makeNode(args.parent, 'feGaussianBlur', $.extend( {result: args.result, in_: args.in1, stdDeviation: args.stdDevX + (args.stdDevY ? ' ' + args.stdDevY : '')}, args.settings || {})); }, - /* Add an image filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param href (string) the URL of the image - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add an image filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} the ID of this filter. + @param href {string} The URL of the image. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ image: function(parent, result, href, settings) { var args = this._wrapper._args(arguments, ['result', 'href']); - var node = this._wrapper._makeNode(args.parent, 'feImage', $.extend( - {result: args.result}, args.settings || {})); + var node = this._wrapper._makeNode(args.parent, 'feImage', $.extend({result: args.result}, args.settings || {})); node.setAttributeNS($.svg.xlinkNS, 'href', args.href); return node; }, - /* Add a merge filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param refs (string[]) the IDs of the filters to merge - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a merge filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param refs {string[])} The IDs of the filters to merge. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ merge: function(parent, result, refs, settings) { var args = this._wrapper._args(arguments, ['result', 'refs']); - var node = this._wrapper._makeNode(args.parent, 'feMerge', $.extend( - {result: args.result}, args.settings || {})); + var node = this._wrapper._makeNode(args.parent, 'feMerge', $.extend({result: args.result}, args.settings || {})); for (var i = 0; i < args.refs.length; i++) { this._wrapper._makeNode(node, 'feMergeNode', {in_: args.refs[i]}); } return node; }, - /* Add a morphology filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source filter - @param operator (string) erode | dilate - @param radiusX (number) the size of the operation in the x-axis - @param radiusY (number) the size of the operation in the y-axis (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a morphology filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param in1 {string} The source filter. + @param operator {string} One of 'erode', 'dilate'. + @param radiusX {number} The size of the operation in the x-axis. + @param [radiusY] {number} The size of the operation in the y-axis. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ morphology: function(parent, result, in1, operator, radiusX, radiusY, settings) { - var args = this._wrapper._args(arguments, ['result', 'in1', - 'operator', 'radiusX', 'radiusY'], ['radiusY']); + var args = this._wrapper._args(arguments, ['result', 'in1', 'operator', 'radiusX', 'radiusY'], ['radiusY']); return this._wrapper._makeNode(args.parent, 'feMorphology', $.extend( {result: args.result, in_: args.in1, operator: args.operator, - radius: args.radiusX + (args.radiusY ? ' ' + args.radiusY : '')}, - args.settings || {})); + radius: args.radiusX + (args.radiusY ? ' ' + args.radiusY : '')}, args.settings || {})); }, - /* Add an offset filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source filter - @param dX (number) the offset in the x-axis - @param dY (number) the offset in the y-axis - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add an offset filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param in1 {string} The source filter. + @param dX {number} The offset in the x-axis. + @param dY {number} The offset in the y-axis. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ offset: function(parent, result, in1, dx, dy, settings) { var args = this._wrapper._args(arguments, ['result', 'in1', 'dx', 'dy']); return this._wrapper._makeNode(args.parent, 'feOffset', $.extend( - {result: args.result, in_: args.in1, dx: args.dx, dy: args.dy}, - args.settings || {})); + {result: args.result, in_: args.in1, dx: args.dx, dy: args.dy}, args.settings || {})); }, - /* Add a specular lighting filter. - Numeric params are only optional if following numeric params are also omitted. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source filter - @param surfaceScale (number) the surface height when Ain = 1 (optional) - @param specularConstant (number) the ks in Phong lighting model (optional) - @param specularExponent (number) the shininess 1.0-128.0 (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ - specularLighting: function(parent, result, in1, surfaceScale, - specularConstant, specularExponent, settings) { - var args = this._wrapper._args(arguments, ['result', 'in1', - 'surfaceScale', 'specularConstant', 'specularExponent'], + /** Add a specular lighting filter. +

Numeric params are only optional if following numeric params are also omitted.

+ @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string}The ID of this filter. + @param in1 {string} The source filter. + @param [surfaceScale] {number} The surface height when Ain = 1. + @param [specularConstant] {number} The ks in Phong lighting model. + @param [specularExponent] {number} The shininess 1.0-128.0. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ + specularLighting: function(parent, result, in1, surfaceScale, specularConstant, specularExponent, settings) { + var args = this._wrapper._args(arguments, ['result', 'in1', 'surfaceScale', 'specularConstant', 'specularExponent'], ['surfaceScale', 'specularConstant', 'specularExponent']); return this._wrapper._makeNode(args.parent, 'feSpecularLighting', $.extend( {result: args.result, in_: args.in1, surfaceScale: args.surfaceScale, - specularConstant: args.specularConstant, specularExponent: args.specularExponent}, - args.settings || {})); + specularConstant: args.specularConstant, specularExponent: args.specularExponent}, args.settings || {})); }, - /* Add a tile filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param in1 (string) the source filter - @param x (number) the left coordinate of the rectangle - @param y (number) the top coordinate of the rectangle - @param width (number) the width of the rectangle - @param height (number) the height of the rectangle - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a tile filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param in1 {string} The source filter. + @param x {number} The left coordinate of the rectangle. + @param y {number} The top coordinate of the rectangle. + @param width {number} The width of the rectangle. + @param height {number} The height of the rectangle. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ tile: function(parent, result, in1, x, y, width, height, settings) { - var args = this._wrapper._args(arguments, - ['result', 'in1', 'x', 'y', 'width', 'height']); + var args = this._wrapper._args(arguments, ['result', 'in1', 'x', 'y', 'width', 'height']); return this._wrapper._makeNode(args.parent, 'feTile', $.extend( {result: args.result, in_: args.in1, x: args.x, y: args.y, width: args.width, height: args.height}, args.settings || {})); }, - /* Add a turbulence filter. - @param parent (element or jQuery) the parent node for the new filter (optional) - @param result (string) the ID of this filter - @param type (string) fractalNoise | turbulence - @param baseFreq (number or 'number number') the base frequency, - optionally separated into x- and y-components - @param octaves (number) the amount of turbulence (optional) - @param settings (object) additional settings for the filter (optional) - @return (element) the new filter node */ + /** Add a turbulence filter. + @param [parent] {SVGElement|jQuery} The parent node for the new node, or SVG root if not specified. + @param result {string} The ID of this filter. + @param type {string} One of 'fractalNoise', 'turbulence'. + @param [baseFreq] {number|string} The base frequency, + optionally separated into x- and y-components ('number number'). + @param [octaves] {number} The amount of turbulence. + @param [settings] {object} Additional settings for this node. + @return {SVGElement} The new filter node. */ turbulence: function(parent, result, type, baseFreq, octaves, settings) { - var args = this._wrapper._args(arguments, ['result', 'type', - 'baseFreq', 'octaves'], ['octaves']); + var args = this._wrapper._args(arguments, ['result', 'type', 'baseFreq', 'octaves'], ['octaves']); return this._wrapper._makeNode(args.parent, 'feTurbulence', $.extend( {result: args.result, type: args.type, baseFrequency: args.baseFreq, numOctaves: args.octaves}, args.settings || {})); } }); -/* Determine whether an object is an array. */ -function isArray(a) { - return (a && a.constructor == Array); -} - })(jQuery) diff --git a/jquery.svgfilter.min.js b/jquery.svgfilter.min.js index 65cfae2..d29a0b8 100644 --- a/jquery.svgfilter.min.js +++ b/jquery.svgfilter.min.js @@ -1,7 +1,6 @@ -/* http://keith-wood.name/svg.html - SVG filters for jQuery v1.4.5. +/* http://keith-wood.name/svg.html + SVG filters for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ -(function($){$.svg.addExtension('filters',SVGFilter);$.extend($.svg._wrapperClass.prototype,{filter:function(a,b,x,y,c,d,e){var f=this._args(arguments,['id','x','y','width','height']);return this._makeNode(f.parent,'filter',$.extend({id:f.id,x:f.x,y:f.y,width:f.width,height:f.height},f.settings||{}))}});function SVGFilter(a){this._wrapper=a}$.extend(SVGFilter.prototype,{distantLight:function(a,b,c,d,e){var f=this._wrapper._args(arguments,['result','azimuth','elevation']);return this._wrapper._makeNode(f.parent,'feDistantLight',$.extend({result:f.result,azimuth:f.azimuth,elevation:f.elevation},f.settings||{}))},pointLight:function(a,b,x,y,z,c){var d=this._wrapper._args(arguments,['result','x','y','z']);return this._wrapper._makeNode(d.parent,'fePointLight',$.extend({result:d.result,x:d.x,y:d.y,z:d.z},d.settings||{}))},spotLight:function(a,b,x,y,z,c,d,e,f){var g=this._wrapper._args(arguments,['result','x','y','z','toX','toY','toZ'],['toX']);var h=$.extend({result:g.result,x:g.x,y:g.y,z:g.z},(g.toX!=null?{pointsAtX:g.toX,pointsAtY:g.toY,pointsAtZ:g.toZ}:{}));return this._wrapper._makeNode(g.parent,'feSpotLight',$.extend(h,g.settings||{}))},blend:function(a,b,c,d,e,f){var g=this._wrapper._args(arguments,['result','mode','in1','in2']);return this._wrapper._makeNode(g.parent,'feBlend',$.extend({result:g.result,mode:g.mode,in_:g.in1,in2:g.in2},g.settings||{}))},colorMatrix:function(a,b,c,d,e,f){var g=this._wrapper._args(arguments,['result','in1','type','values']);if(isArray(g.values)){var h='';for(var i=0;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(n($){$.V.1n(\'1o\',W);$.m($.V.1p.1e,{1f:n(a,b,x,y,c,d,e){9 f=7.s(q,[\'X\',\'x\',\'y\',\'w\',\'C\']);r 7.o(f.t,\'1f\',$.m({X:f.X,x:f.x,y:f.y,w:f.w,C:f.C},f.p||{}))}});n W(a){7.8=a}$.m(W.1e,{1q:n(a,b,c,d,e){9 f=7.8.s(q,[\'5\',\'Y\',\'Z\']);r 7.8.o(f.t,\'1r\',$.m({5:f.5,Y:f.Y,Z:f.Z},f.p||{}))},1s:n(a,b,x,y,z,c){9 d=7.8.s(q,[\'5\',\'x\',\'y\',\'z\']);r 7.8.o(d.t,\'1t\',$.m({5:d.5,x:d.x,y:d.y,z:d.z},d.p||{}))},1u:n(a,b,x,y,z,c,d,e,f){9 g=7.8.s(q,[\'5\',\'x\',\'y\',\'z\',\'N\',\'1g\',\'1h\'],[\'N\']);9 h=$.m({5:g.5,x:g.x,y:g.y,z:g.z},(g.N!=I?{1v:g.N,1w:g.1g,1x:g.1h}:{}));r 7.8.o(g.t,\'1y\',$.m(h,g.p||{}))},1z:n(a,b,c,d,e,f){9 g=7.8.s(q,[\'5\',\'10\',\'u\',\'D\']);r 7.8.o(g.t,\'1A\',$.m({5:g.5,10:g.10,E:g.u,D:g.D},g.p||{}))},1B:n(a,b,c,d,e,f){9 g=7.8.s(q,[\'5\',\'u\',\'F\',\'v\']);11(1i(g.v)){9 h=\'\';O(9 i=0;iUse the singleton instance of this class, $.svg.graphing, + to interact with the SVG graphing functionality.

+ @module SVGGraphing */ function SVGGraphing() { this.regional = []; this.regional[''] = {percentageText: 'Percentage'}; @@ -21,24 +23,26 @@ function SVGGraphing() { $.extend(SVGGraphing.prototype, { _chartTypes: [], - /* Add a new chart rendering type to the package. - The rendering object must implement the following functions: - getTitle(), getDescription(), getOptions(), drawChart(graph). - @param id (string) the ID of this graph renderer - @param chartType (object) the object implementing this chart type */ + /** Add a new chart rendering type to the package. +

The rendering object must implement the following functions: getTitle(), + getDescription(), getOptions(), drawChart(graph).

+ @param id {string} The ID of this graph renderer. + @param chartType {object} The object implementing this chart type. */ addChartType: function(id, chartType) { this._chartTypes[id] = chartType; }, - /* Retrieve the list of chart types. - @return (object[string]) the array of chart types indexed by ID */ + /** Retrieve the list of chart types. + @return {object[]} The array of chart types indexed by ID */ chartTypes: function() { return this._chartTypes; } }); -/* Extension point for SVG graphing. - Access through svg.graph. */ +/** The SVG graph manager. +

Use the singleton instance of this class, $.svg.graph, + to interact with the SVG graph functionality.

+ @module SVGGraph */ function SVGGraph(wrapper) { this._wrapper = wrapper; // The attached SVG wrapper object this._drawNow = false; // True for immediate update, false to wait for redraw call @@ -49,8 +53,7 @@ function SVGGraph(wrapper) { this._chartOptions = {}; // Extra options for the graph type // The graph title and settings this._title = {value: '', offset: 25, settings: {textAnchor: 'middle'}}; - this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom, - // > 1 in pixels, <= 1 as proportion + this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom, > 1 in pixels, <= 1 as proportion this._chartFormat = {fill: 'none', stroke: 'black'}; // The formatting for the chart area this._gridlines = []; // The formatting of the x- and y-gridlines this._series = []; // The series to be plotted, each is an object @@ -70,49 +73,54 @@ function SVGGraph(wrapper) { $.extend(SVGGraph.prototype, { /* Useful indexes. */ + /** Index in a dimensions array for x-coordinate. */ X: 0, + /** Index in a dimensions array for y-coordinate. */ Y: 1, + /** Index in a dimensions array for width. */ W: 2, + /** Index in a dimensions array for height. */ H: 3, + /** Index in an area array for left x-coordinate. */ L: 0, + /** Index in an area array for top y-coordinate. */ T: 1, + /** Index in an area array for right x-coordinate. */ R: 2, + /** Index in an area array for bottom y-coordinate. */ B: 3, /* Standard percentage axis. */ _percentageAxis: new SVGGraphAxis(this, $.svg.graphing.region.percentageText, 0, 100, 10, 0), - /* Set or retrieve the container for the graph. - @param cont (SVG element) the container for the graph - @return (SVGGraph) this graph object or - (SVG element) the current container (if no parameters) */ + /** Set or retrieve the container for the graph. + @param cont {SVGElement} The container for the graph. + @return {SVGGraph|SVGElement} This graph object or the current container (if no parameters). */ container: function(cont) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._chartCont; } this._chartCont = cont; return this; }, - /* Set or retrieve the type of chart to be rendered. - See $.svg.graphing.getChartTypes() for the list of available types. - @param id (string) the ID of the chart type - @param options (object) additional settings for this chart type (optional) - @return (SVGGraph) this graph object or - (string) the chart type (if no parameters) - @deprecated use type() */ + /** Set or retrieve the type of chart to be rendered. +

See $.svg.graphing.getChartTypes() for the list of available types.

+ @param id {string} The ID of the chart type. + @param [options] {object} Additional settings for this chart type. + @return {SVGGraph|string} This graph object or the chart type (if no parameters). + @deprecated Use type(). */ chartType: function(id, options) { - return (arguments.length == 0 ? this.type() : this.type(id, options)); + return (arguments.length === 0 ? this.type() : this.type(id, options)); }, - /* Set or retrieve the type of chart to be rendered. - See $.svg.graphing.getChartTypes() for the list of available types. - @param id (string) the ID of the chart type - @param options (object) additional settings for this chart type (optional) - @return (SVGGraph) this graph object or - (string) the chart type (if no parameters) */ + /** Set or retrieve the type of chart to be rendered. +

See $.svg.graphing.getChartTypes() for the list of available types.

+ @param id {string} The ID of the chart type. + @param [options] {object} Additional settings for this chart type. + @return {SVGGraph|string} This graph object or the chart type (if no parameters). */ type: function(id, options) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._chartType; } var chartType = $.svg.graphing._chartTypes[id]; @@ -124,21 +132,19 @@ $.extend(SVGGraph.prototype, { return this; }, - /* Set or retrieve additional options for the particular chart type. - @param options (object) the extra options - @return (SVGGraph) this graph object or - (object) the chart options (if no parameters) - @deprecated use options() */ + /** Set or retrieve additional options for the particular chart type. + @param options {object} The extra options. + @return {SVGGraph|object} This graph object or the chart options (if no parameters). + @deprecated Use options(). */ chartOptions: function(options) { - return(arguments.length == 0 ? this.options() : this.options(options)); + return(arguments.length === 0 ? this.options() : this.options(options)); }, - /* Set or retrieve additional options for the particular chart type. - @param options (object) the extra options - @return (SVGGraph) this graph object or - (object) the chart options (if no parameters) */ + /** Set or retrieve additional options for the particular chart type. + @param options {object} The extra options. + @return {SVGGraph|object} This graph object or the chart options (if no parameters). */ options: function(options) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._chartOptions; } this._chartOptions = $.extend({}, options); @@ -146,82 +152,72 @@ $.extend(SVGGraph.prototype, { return this; }, - /* Set or retrieve the background of the graph chart. - @param fill (string) how to fill the chart background - @param stroke (string) the colour of the outline (optional) - @param settings (object) additional formatting for the chart background (optional) - @return (SVGGraph) this graph object or - (object) the chart format (if no parameters) - @deprecated use format() */ + /** Set or retrieve the background of the graph chart. + @param fill {string} How to fill the chart background. + @param [stroke] {string} The colour of the outline. + @param [settings] {object} Additional formatting for the chart background. + @return {SVGGraph|object} This graph object or the chart format (if no parameters). + @deprecated Use format(). */ chartFormat: function(fill, stroke, settings) { - return (arguments.length == 0 ? this.format() : this.format(fill, stroke, settings)); + return (arguments.length === 0 ? this.format() : this.format(fill, stroke, settings)); }, - /* Set or retrieve the background of the graph chart. - @param fill (string) how to fill the chart background - @param stroke (string) the colour of the outline (optional) - @param settings (object) additional formatting for the chart background (optional) - @return (SVGGraph) this graph object or - (object) the chart format (if no parameters) */ + /** Set or retrieve the background of the graph chart. + @param fill {string} How to fill the chart background. + @param [stroke] {string} The colour of the outline. + @param [settings] {object} Additional formatting for the chart background. + @return {SVGGraph|object} This graph object or the chart format (if no parameters). */ format: function(fill, stroke, settings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._chartFormat; } - if (typeof stroke == 'object') { + if (typeof stroke === 'object') { settings = stroke; stroke = null; } - this._chartFormat = $.extend({fill: fill}, - (stroke ? {stroke: stroke} : {}), settings || {}); + this._chartFormat = $.extend({fill: fill}, (stroke ? {stroke: stroke} : {}), settings || {}); this._drawGraph(); return this; }, - /* Set or retrieve the main chart area. - @param left (number) > 1 is pixels, <= 1 is proportion of width or - (number[4]) for left, top, right, bottom - @param top (number) > 1 is pixels, <= 1 is proportion of height - @param right (number) > 1 is pixels, <= 1 is proportion of width - @param bottom (number) > 1 is pixels, <= 1 is proportion of height - @return (SVGGraph) this graph object or - (number[4]) the chart area: left, top, right, bottom (if no parameters) - @deprecated use area() */ + /** Set or retrieve the main chart area. + @param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom. + @param [top] {number} > 1 is pixels, <= 1 is proportion of height. + @param [right] {number} > 1 is pixels, <= 1 is proportion of width. + @param [bottom] {number} > 1 is pixels, <= 1 is proportion of height. + @return {SVGGraph|number[]} This graph object or the chart area: left, top, right, bottom (if no parameters). + @deprecated Use area(). */ chartArea: function(left, top, right, bottom) { - return (arguments.length == 0 ? this.area() : this.area(left, top, right, bottom)); + return (arguments.length === 0 ? this.area() : this.area(left, top, right, bottom)); }, - /* Set or retrieve the main chart area. - @param left (number) > 1 is pixels, <= 1 is proportion of width or - (number[4]) for left, top, right, bottom - @param top (number) > 1 is pixels, <= 1 is proportion of height - @param right (number) > 1 is pixels, <= 1 is proportion of width - @param bottom (number) > 1 is pixels, <= 1 is proportion of height - @return (SVGGraph) this graph object or - (number[4]) the chart area: left, top, right, bottom (if no parameters) */ + /** Set or retrieve the main chart area. + @param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom. + @param [top] {number} > 1 is pixels, <= 1 is proportion of height. + @param [right] {number} > 1 is pixels, <= 1 is proportion of width. + @param [bottom] {number} > 1 is pixels, <= 1 is proportion of height. + @return {SVGGraph|number[]} This graph object or the chart area: left, top, right, bottom (if no parameters). */ area: function(left, top, right, bottom) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._area; } - this._area = (isArray(left) ? left : [left, top, right, bottom]); + this._area = ($.isArray(left) ? left : [left, top, right, bottom]); this._drawGraph(); return this; }, - /* Set or retrieve the gridlines formatting for the graph chart. - @param xSettings (string) the colour of the gridlines along the x-axis, or - (object) formatting for the gridlines along the x-axis, or - null for none - @param ySettings (string) the colour of the gridlines along the y-axis, or - (object) formatting for the gridlines along the y-axis, or - null for none - @return (SVGGraph) this graph object or - (object[2]) the gridlines formatting (if no parameters) */ + /** Set or retrieve the gridlines formatting for the graph chart. + @param xSettings {string|object} The colour of the gridlines along the x-axis, + or formatting for the gridlines along the x-axis, or null for none. + @param ySettings {string|object} The colour of the gridlines along the y-axis, + or formatting for the gridlines along the y-axis, or null for none. + @return {SVGGraph|object[]} This graph object or the gridlines formatting (if no parameters) */ gridlines: function(xSettings, ySettings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._gridlines; } - this._gridlines = [(typeof xSettings == 'string' ? {stroke: xSettings} : xSettings), - (typeof ySettings == 'string' ? {stroke: ySettings} : ySettings)]; + this._gridlines = [(typeof xSettings === 'string' ? {stroke: xSettings} : xSettings), + (typeof ySettings === 'string' ? {stroke: ySettings} : ySettings)]; if (this._gridlines[0] == null && this._gridlines[1] == null) { this._gridlines = []; } @@ -229,81 +225,77 @@ $.extend(SVGGraph.prototype, { return this; }, - /* Set or retrieve the title of the graph and its formatting. - @param value (string) the title - @param offset (number) the vertical positioning of the title - > 1 is pixels, <= 1 is proportion of width (optional) - @param colour (string) the colour of the title (optional) - @param settings (object) formatting for the title (optional) - @return (SVGGraph) this graph object or - (object) value, offset, and settings for the title (if no parameters) */ + /** Set or retrieve the title of the graph and its formatting. + @param value {string} The title. + @param [offset] {number} The vertical positioning of the title > 1 is pixels, <= 1 is proportion of width. + @param [colour] {string} The colour of the title. + @param [settings] {object} Formatting for the title. + @return {SVGGraph|object} This graph object or value, offset, and settings for the title (if no parameters). */ title: function(value, offset, colour, settings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._title; } - if (typeof offset != 'number') { + if (typeof offset !== 'number') { settings = colour; colour = offset; offset = null; } - if (typeof colour != 'string') { + if (typeof colour !== 'string') { settings = colour; colour = null; } this._title = {value: value, offset: offset || this._title.offset, - settings: $.extend({textAnchor: 'middle'}, - (colour ? {fill: colour} : {}), settings || {})}; + settings: $.extend({textAnchor: 'middle'}, (colour ? {fill: colour} : {}), settings || {})}; this._drawGraph(); return this; }, - /* Add a series of values to be plotted on the graph. - @param name (string) the name of this series (optional) - @param values (number[]) the values to be plotted - @param fill (string) how the plotted values are filled - @param stroke (string) the colour of the plotted lines (optional) - @param strokeWidth (number) the width of the plotted lines (optional) - @param settings (object) additional settings for the plotted values (optional) - @return (SVGGraph) this graph object */ + /** Add a series of values to be plotted on the graph. + @param [name] {string} The name of this series. + @param values {number[]} The values to be plotted. + @param fill {string} How the plotted values are filled. + @param [stroke] {string} The colour of the plotted lines. + @param [strokeWidth] {number} The width of the plotted lines. + @param [settings] {object} Additional settings for the plotted values. + @return {SVGGraph} This graph object. */ addSeries: function(name, values, fill, stroke, strokeWidth, settings) { - this._series.push(new SVGGraphSeries( - this, name, values, fill, stroke, strokeWidth, settings)); + this._series.push(new SVGGraphSeries(this, name, values, fill, stroke, strokeWidth, settings)); this._drawGraph(); return this; }, - /* Retrieve the series wrappers. - @param i (number) the series index (optional) - @return (SVGGraphSeries) the specified series or - (SVGGraphSeries[]) the list of series */ + /** Retrieve the series wrappers. + @param [i] {number} The series index. + @return {SVGGraphSeries|SVGGraphSeries[]} The specified series or the list of series. */ series: function(i) { return (arguments.length > 0 ? this._series[i] : null) || this._series; }, - /* Suppress drawing of the graph until redraw() is called. - @return (SVGGraph) this graph object */ + /** Suppress drawing of the graph until redraw() is called. + @return {SVGGraph} This graph object. */ noDraw: function() { this._drawNow = false; return this; }, - /* Redraw the entire graph with the current settings and values. - @return (SVGGraph) this graph object */ + /** Redraw the entire graph with the current settings and values. + @return {SVGGraph} This graph object. */ redraw: function() { this._drawNow = true; this._drawGraph(); return this; }, - /* Set the callback function for status updates. - @param onstatus (function) the callback function - @return (SVGGraph) this graph object */ + /** Set the callback function for status updates. + @param onstatus {function} The callback function. + @return {SVGGraph} This graph object. */ status: function(onstatus) { this._onstatus = onstatus; return this; }, - /* Actually draw the graph (if allowed) based on the graph type set. */ + /** Actually draw the graph (if allowed) based on the graph type set. + @private */ _drawGraph: function() { if (!this._drawNow) { return; @@ -317,47 +309,48 @@ $.extend(SVGGraph.prototype, { // Set sizes if not already there if (!this._chartCont.width) { this._chartCont.setAttribute('width', - parseInt(this._chartCont.getAttribute('width'), 10) || this._wrapper._width()); + parseInt(this._chartCont.getAttribute('width'), 10) || this._wrapper.width()); } else if (this._chartCont.width.baseVal) { - this._chartCont.width.baseVal.value = - this._chartCont.width.baseVal.value || this._wrapper._width(); + this._chartCont.width.baseVal.value = this._chartCont.width.baseVal.value || this._wrapper.width(); } else { - this._chartCont.width = this._chartCont.width || this._wrapper._width(); + this._chartCont.width = this._chartCont.width || this._wrapper.width(); } if (!this._chartCont.height) { this._chartCont.setAttribute('height', - parseInt(this._chartCont.getAttribute('height'), 10) || this._wrapper._height()); + parseInt(this._chartCont.getAttribute('height'), 10) || this._wrapper.height()); } else if (this._chartCont.height.baseVal) { - this._chartCont.height.baseVal.value = - this._chartCont.height.baseVal.value || this._wrapper._height(); + this._chartCont.height.baseVal.value = this._chartCont.height.baseVal.value || this._wrapper.height(); } else { - this._chartCont.height = this._chartCont.height || this._wrapper._height(); + this._chartCont.height = this._chartCont.height || this._wrapper.height(); } this._chartType.drawGraph(this); }, - /* Decode an attribute value. - @param node the node to examine - @param name the attribute name - @return the actual value */ + /** Decode an attribute value. + @private + @param node {SVGElement} The node to examine. + @param name {string} The attribute name. + @return {string} The actual value. */ _getValue: function(node, name) { return (!node[name] ? parseInt(node.getAttribute(name), 10) : (node[name].baseVal ? node[name].baseVal.value : node[name])); }, - /* Draw the graph title - centred. */ + /** Draw the graph title - centred. + @private */ _drawTitle: function() { this._wrapper.text(this._chartCont, this._getValue(this._chartCont, 'width') / 2, this._title.offset, this._title.value, this._title.settings); }, - /* Calculate the actual dimensions of the chart area. - @param area (number[4]) the area values to evaluate (optional) - @return (number[4]) an array of dimension values: left, top, width, height */ + /** Calculate the actual dimensions of the chart area. + @private + @param [area] {number[]} The area values to evaluate, defaulting to the current ones. + @return {number[]} An array of dimension values: left, top, width, height. */ _getDims: function(area) { area = area || this._area; var availWidth = this._getValue(this._chartCont, 'width'); @@ -369,10 +362,11 @@ $.extend(SVGGraph.prototype, { return [left, top, width, height]; }, - /* Draw the chart background, including gridlines. - @param noXGrid (boolean) true to suppress the x-gridlines, false to draw them (optional) - @param noYGrid (boolean) true to suppress the y-gridlines, false to draw them (optional) - @return (element) the background group element */ + /** Draw the chart background, including gridlines. + @private + @param [noXGrid=false] {boolean} true to suppress the x-gridlines, false to draw them. + @param [noYGrid=false] {boolean} true to suppress the y-gridlines, false to draw them. + @return {SVGEelement} The background group element */ _drawChartBackground: function(noXGrid, noYGrid) { var bg = this._wrapper.group(this._chartCont, {class_: 'background'}); var dims = this._getDims(); @@ -386,12 +380,13 @@ $.extend(SVGGraph.prototype, { return bg; }, - /* Draw one set of gridlines. - @param bg (element) the background group element - @param axis (SVGGraphAxis) the axis definition - @param horiz (boolean) true if horizontal, false if vertical - @param dims (number[]) the left, top, width, height of the chart area - @param format (object) additional settings for the gridlines */ + /** Draw one set of gridlines. + @private + @param bg {SVGElement} The background group element. + @param axis {SVGGraphAxis} The axis definition. + @param horiz {boolean} true if horizontal, false if vertical. + @param dims {number[]} The left, top, width, height of the chart area. + @param format {object} Additional settings for the gridlines. */ _drawGridlines: function(bg, axis, horiz, dims, format) { var g = this._wrapper.group(bg, format); var scale = (horiz ? dims[this.H] : dims[this.W]) / (axis._scale.max - axis._scale.min); @@ -406,15 +401,15 @@ $.extend(SVGGraph.prototype, { } }, - /* Draw the axes in their standard configuration. - @param noX (boolean) true to suppress the x-axes, false to draw it (optional) */ + /** Draw the axes in their standard configuration. + @private + @param [noX=false] {boolean} true to suppress the x-axes, false to draw it. */ _drawAxes: function(noX) { var dims = this._getDims(); if (this.xAxis && !noX) { if (this.xAxis._title) { this._wrapper.text(this._chartCont, dims[this.X] + dims[this.W] / 2, - dims[this.Y] + dims[this.H] + this.xAxis._titleOffset, - this.xAxis._title, this.xAxis._titleFormat); + dims[this.Y] + dims[this.H] + this.xAxis._titleOffset, this.xAxis._title, this.xAxis._titleFormat); } this._drawAxis(this.xAxis, 'xAxis', dims[this.X], dims[this.Y] + dims[this.H], dims[this.X] + dims[this.W], dims[this.Y] + dims[this.H]); @@ -425,37 +420,36 @@ $.extend(SVGGraph.prototype, { transform: 'translate(' + (dims[this.X] - this.yAxis._titleOffset) + ',' + (dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.yAxis._titleFormat || {})); } - this._drawAxis(this.yAxis, 'yAxis', dims[this.X], dims[this.Y], - dims[this.X], dims[this.Y] + dims[this.H]); + this._drawAxis(this.yAxis, 'yAxis', dims[this.X], dims[this.Y], dims[this.X], dims[this.Y] + dims[this.H]); } if (this.x2Axis && !noX) { if (this.x2Axis._title) { this._wrapper.text(this._chartCont, dims[this.X] + dims[this.W] / 2, dims[this.X] - this.x2Axis._titleOffset, this.x2Axis._title, this.x2Axis._titleFormat); } - this._drawAxis(this.x2Axis, 'x2Axis', dims[this.X], dims[this.Y], - dims[this.X] + dims[this.W], dims[this.Y]); + this._drawAxis(this.x2Axis, 'x2Axis', dims[this.X], dims[this.Y], dims[this.X] + dims[this.W], dims[this.Y]); } if (this.y2Axis) { if (this.y2Axis._title) { this._wrapper.text(this._chartCont, 0, 0, this.y2Axis._title, $.extend({textAnchor: 'middle', - transform: 'translate(' + (dims[this.X] + dims[this.W] + this.y2Axis._titleOffset) + - ',' + (dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.y2Axis._titleFormat || {})); + transform: 'translate(' + (dims[this.X] + dims[this.W] + this.y2Axis._titleOffset) + ',' + + (dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.y2Axis._titleFormat || {})); } this._drawAxis(this.y2Axis, 'y2Axis', dims[this.X] + dims[this.W], dims[this.Y], dims[this.X] + dims[this.W], dims[this.Y] + dims[this.H]); } }, - /* Draw an axis and its tick marks. - @param axis (SVGGraphAxis) the axis definition - @param id (string) the identifier for the axis group element - @param x1 (number) starting x-coodinate for the axis - @param y1 (number) starting y-coodinate for the axis - @param x2 (number) ending x-coodinate for the axis - @param y2 (number) ending y-coodinate for the axis */ + /** Draw an axis and its tick marks. + @private + @param axis {SVGGraphAxis} The axis definition. + @param id {string} The identifier for the axis group element. + @param x1 {number} Starting x-coodinate for the axis. + @param y1 {number} Starting y-coodinate for the axis. + @param x2 {number} Ending x-coodinate for the axis. + @param y2 {number} Ending y-coodinate for the axis. */ _drawAxis: function(axis, id, x1, y1, x2, y2) { - var horiz = (y1 == y2); + var horiz = (y1 === y2); var gl = this._wrapper.group(this._chartCont, $.extend({class_: id}, axis._lineFormat)); var gt = this._wrapper.group(this._chartCont, $.extend({class_: id + 'Labels', textAnchor: (horiz ? 'middle' : 'end')}, axis._labelFormat)); @@ -474,43 +468,42 @@ $.extend(SVGGraph.prototype, { var count = 0; while (major <= axis._scale.max || minor <= axis._scale.max) { var cur = Math.min(major, minor); - var len = (cur == major ? size : size / 2); - var v = (horiz ? x1 : y1) + - (horiz ? cur - axis._scale.min : axis._scale.max - cur) * scale; - this._wrapper.line(gl, (horiz ? v : x1 + len * offsets[0]), - (horiz ? y1 + len * offsets[0] : v), - (horiz ? v : x1 + len * offsets[1]), - (horiz ? y1 + len * offsets[1] : v)); - if (cur == major) { + var len = (cur === major ? size : size / 2); + var v = (horiz ? x1 : y1) + (horiz ? cur - axis._scale.min : axis._scale.max - cur) * scale; + this._wrapper.line(gl, (horiz ? v : x1 + len * offsets[0]), (horiz ? y1 + len * offsets[0] : v), + (horiz ? v : x1 + len * offsets[1]), (horiz ? y1 + len * offsets[1] : v)); + if (cur === major) { this._wrapper.text(gt, (horiz ? v : x1 - size), (horiz ? y1 + 2 * size : v), (axis._labels ? axis._labels[count++] : '' + cur)); } - major += (cur == major ? axis._ticks.major : 0); - minor += (cur == minor ? axis._ticks.minor : 0); + major += (cur === major ? axis._ticks.major : 0); + minor += (cur === minor ? axis._ticks.minor : 0); } } }, - /* Calculate offsets based on axis and tick positions. - @param axis (SVGGraphAxis) the axis definition - @param bottomRight (boolean) true if this axis is appearing on the bottom or - right of the chart area, false if to the top or left - @return (number[2]) the array of offset multipliers (-1..+1) */ + /** Calculate offsets based on axis and tick positions. + @private + @param axis {SVGGraphAxis} The axis definition. + @param bottomRight {boolean} true if this axis is appearing on the bottom or + right of the chart area, false if to the top or left. + @return {number[]} The array of offset multipliers (-1..+1). */ _getTickOffsets: function(axis, bottomRight) { - return [(axis._ticks.position == (bottomRight ? 'in' : 'out') || - axis._ticks.position == 'both' ? -1 : 0), - (axis._ticks.position == (bottomRight ? 'out' : 'in') || - axis._ticks.position == 'both' ? +1 : 0), ]; + return [(axis._ticks.position === (bottomRight ? 'in' : 'out') || axis._ticks.position === 'both' ? -1 : 0), + (axis._ticks.position === (bottomRight ? 'out' : 'in') || axis._ticks.position === 'both' ? +1 : 0), ]; }, - /* Retrieve the standard percentage axis. - @return (SVGGraphAxis) percentage axis */ + /** Retrieve the standard percentage axis. + @private + @return {SVGGraphAxis} Percentage axis. */ _getPercentageAxis: function() { this._percentageAxis._title = $.svg.graphing.region.percentageText; return this._percentageAxis; }, - /* Calculate the column totals across all the series. */ + /** Calculate the column totals across all the series. + @private + @return {number[]} The column totals. */ _getTotals: function() { var totals = []; var numVal = (this._series.length ? this._series[0]._values.length : 0); @@ -523,15 +516,15 @@ $.extend(SVGGraph.prototype, { return totals; }, - /* Draw the chart legend. */ + /** Draw the chart legend. + @private */ _drawLegend: function() { if (!this.legend._show) { return; } var g = this._wrapper.group(this._chartCont, {class_: 'legend'}); var dims = this._getDims(this.legend._area); - this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], - this.legend._bgSettings); + this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], this.legend._bgSettings); var horiz = dims[this.W] > dims[this.H]; var numSer = this._series.length; var offset = (horiz ? dims[this.W] : dims[this.H]) / numSer; @@ -548,7 +541,11 @@ $.extend(SVGGraph.prototype, { } }, - /* Show the current value status on hover. */ + /** Show the current value status on hover. + @private + @param elem {string|SVGElement} The selector or SVG element to show the status in. + @param label {string} The current label. + @param value {number} The current value. */ _showStatus: function(elem, label, value) { var status = this._onstatus; if (this._onstatus) { @@ -558,17 +555,21 @@ $.extend(SVGGraph.prototype, { } }); -/* Details about each graph series. - @param graph (SVGGraph) the owning graph - @param name (string) the name of this series (optional) - @param values (number[]) the list of values to be plotted - @param fill (string) how the series should be displayed - @param stroke (string) the colour of the (out)line for the series (optional) - @param strokeWidth (number) the width of the (out)line for the series (optional) - @param settings (object) additional formatting settings (optional) - @return (SVGGraphSeries) the new series object */ +/** A graph series definition. + @module SVGGraphSeries */ + +/** Details about each graph series. +

Created through graph.addSeries().

+ @param graph {SVGGraph} The owning graph. + @param [name] {string} The name of this series. + @param values {number[]} The values to be plotted. + @param fill {string} How the plotted values are filled. + @param [stroke] {string} The colour of the plotted lines. + @param [strokeWidth] {number} The width of the plotted lines. + @param [settings] {object} Additional settings for the plotted values. + @return {SVGGraphSeries} The new series object. */ function SVGGraphSeries(graph, name, values, fill, stroke, strokeWidth, settings) { - if (typeof name != 'string') { + if (typeof name !== 'string') { settings = strokeWidth; strokeWidth = stroke; stroke = fill; @@ -576,12 +577,12 @@ function SVGGraphSeries(graph, name, values, fill, stroke, strokeWidth, settings values = name; name = null; } - if (typeof stroke != 'string') { + if (typeof stroke !== 'string') { settings = strokeWidth; strokeWidth = stroke; stroke = null; } - if (typeof strokeWidth != 'number') { + if (typeof strokeWidth !== 'number') { settings = strokeWidth; strokeWidth = null; } @@ -597,12 +598,11 @@ function SVGGraphSeries(graph, name, values, fill, stroke, strokeWidth, settings $.extend(SVGGraphSeries.prototype, { - /* Set or retrieve the name for this series. - @param name (string) the series' name - @return (SVGGraphSeries) this series object or - (string) the series name (if no parameters) */ + /** Set or retrieve the name for this series. + @param name {string} The series' name. + @return {SVGGraphSeries|string} This series object or the series name (if no parameters). */ name: function(name) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._name; } this._name = name; @@ -610,16 +610,15 @@ $.extend(SVGGraphSeries.prototype, { return this; }, - /* Set or retrieve the values for this series. - @param name (string) the series' name (optional) - @param values (number[]) the values to be graphed - @return (SVGGraphSeries) this series object or - (number[]) the series values (if no parameters) */ + /** Set or retrieve the values for this series. + @param [name] {string} The series' name. + @param values {number[]} The values to be graphed. + @return {SVGGraphSeries|number[]} This series object or the series values (if no parameters). */ values: function(name, values) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._values; } - if (isArray(name)) { + if ($.isArray(name)) { values = name; name = null; } @@ -629,24 +628,22 @@ $.extend(SVGGraphSeries.prototype, { return this; }, - /* Set or retrieve the formatting for this series. - @param fill (string) how the values are filled when plotted - @param stroke (string) the (out)line colour (optional) - @param strokeWidth (number) the line's width (optional) - @param settings (object) additional formatting settings for the series (optional) - @return (SVGGraphSeries) this series object or - (object) formatting settings (if no parameters) */ + /** Set or retrieve the formatting for this series. + @param fill {string} How the values are filled when plotted. + @param [stroke] {string} The (out)line colour. + @param [strokeWidth] {number} The line's width. + @param [settings] {object} Additional formatting settings for the series. + @return {SVGGraphSeries|object} This series object or formatting settings (if no parameters). */ format: function(fill, stroke, strokeWidth, settings) { - if (arguments.length == 0) { - return $.extend({fill: this._fill, stroke: this._stroke, - strokeWidth: this._strokeWidth}, this._settings); + if (arguments.length === 0) { + return $.extend({fill: this._fill, stroke: this._stroke, strokeWidth: this._strokeWidth}, this._settings); } - if (typeof stroke != 'string') { + if (typeof stroke !== 'string') { settings = strokeWidth; strokeWidth = stroke; stroke = null; } - if (typeof strokeWidth != 'number') { + if (typeof strokeWidth !== 'number') { settings = strokeWidth; strokeWidth = null; } @@ -658,20 +655,24 @@ $.extend(SVGGraphSeries.prototype, { return this; }, - /* Return to the parent graph. */ + /** Return to the parent graph. + @return {SVGGraph} The parent graph. */ end: function() { return this._graph; } }); -/* Details about each graph axis. - @param graph (SVGGraph) the owning graph - @param title (string) the title of the axis - @param min (number) the minimum value displayed on this axis - @param max (number) the maximum value displayed on this axis - @param major (number) the distance between major ticks - @param minor (number) the distance between minor ticks (optional) - @return (SVGGraphAxis) the new axis object */ +/** A graph axis definition. + @module SVGGraphAxis */ + +/** Details about each graph axis. + @param graph {SVGGraph} The owning graph. + @param title {string} The title of the axis. + @param min [number} The minimum value displayed on this axis. + @param max {number} The maximum value displayed on this axis. + @param major {number} The distance between major ticks. + @param [minor] {number} The distance between minor ticks. + @return {SVGGraphAxis} The new axis object. */ function SVGGraphAxis(graph, title, min, max, major, minor) { this._graph = graph; // The owning graph this._title = title || ''; // Title of this axis @@ -687,13 +688,12 @@ function SVGGraphAxis(graph, title, min, max, major, minor) { $.extend(SVGGraphAxis.prototype, { - /* Set or retrieve the scale for this axis. - @param min (number) the minimum value shown - @param max (number) the maximum value shown - @return (SVGGraphAxis) this axis object or - (object) min and max values (if no parameters) */ + /** Set or retrieve the scale for this axis. + @param min {number} The minimum value shown. + @param max {number} The maximum value shown. + @return {SVGGraphAxis|object} This axis object or min and max values (if no parameters). */ scale: function(min, max) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._scale; } this._scale.min = min; @@ -702,19 +702,17 @@ $.extend(SVGGraphAxis.prototype, { return this; }, - /* Set or retrieve the ticks for this axis. - @param major (number) the distance between major ticks - @param minor (number) the distance between minor ticks - @param size (number) the length of the major ticks (minor are half) (optional) - @param position (string) the location of the ticks: - 'in', 'out', 'both' (optional) - @return (SVGGraphAxis) this axis object or - (object) major, minor, size, and position values (if no parameters) */ + /** Set or retrieve the ticks for this axis. + @param major {number} The distance between major ticks. + @param minor {number} The distance between minor ticks. + @param [size] {number} The length of the major ticks (minor are half). + @param [position] {string} The location of the ticks: 'in', 'out', 'both'. + @return {SVGGraphAxis|object} This axis object or major, minor, size, and position values (if no parameters). */ ticks: function(major, minor, size, position) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._ticks; } - if (typeof size == 'string') { + if (typeof size === 'string') { position = size; size = null; } @@ -726,23 +724,22 @@ $.extend(SVGGraphAxis.prototype, { return this; }, - /* Set or retrieve the title for this axis. - @param title (string) the title text - @param offset (number) the distance to offset the title position (optional) - @param colour (string) how to colour the title (optional) - @param format (object) formatting settings for the title (optional) - @return (SVGGraphAxis) this axis object or - (object) title, offset, and format values (if no parameters) */ + /** Set or retrieve the title for this axis. + @param title {string} The title text + @param [offset] {number} The distance to offset the title position. + @param [colour] {string} How to colour the title. + @param [format] {object} Formatting settings for the title. + @return {SVGGraphAxis|object} This axis object or title, offset, and format values (if no parameters). */ title: function(title, offset, colour, format) { - if (arguments.length == 0) { + if (arguments.length === 0) { return {title: this._title, offset: this._titleOffset, format: this._titleFormat}; } - if (typeof offset != 'number') { + if (typeof offset !== 'number') { format = colour; colour = offset; offset = null; } - if (typeof colour != 'string') { + if (typeof colour !== 'string') { format = colour; colour = null; } @@ -755,17 +752,16 @@ $.extend(SVGGraphAxis.prototype, { return this; }, - /* Set or retrieve the labels for this axis. - @param labels (string[]) the text for each entry - @param colour (string) how to colour the labels (optional) - @param format (object) formatting settings for the labels (optional) - @return (SVGGraphAxis) this axis object or - (object) labels and format values (if no parameters) */ + /** Set or retrieve the labels for this axis. + @param labels {string[]} The text for each entry. + @param [colour] {string} How to colour the labels. + @param [format] {object} Formatting settings for the labels. + @return {SVGGraphAxis|object} This axis object or labels and format values (if no parameters). */ labels: function(labels, colour, format) { - if (arguments.length == 0) { + if (arguments.length === 0) { return {labels: this._labels, format: this._labelFormat}; } - if (typeof colour != 'string') { + if (typeof colour !== 'string') { format = colour; colour = null; } @@ -777,42 +773,43 @@ $.extend(SVGGraphAxis.prototype, { return this; }, - /* Set or retrieve the line formatting for this axis. - @param colour (string) the line's colour - @param width (number) the line's width (optional) - @param settings (object) additional formatting settings for the line (optional) - @return (SVGGraphAxis) this axis object or - (object) line formatting values (if no parameters) */ + /** Set or retrieve the line formatting for this axis. + @param colour {string} The line's colour + @param [width] {number} The line's width. + @param [settings] {object} Additional formatting settings for the line. + @return {SVGGraphAxis|object} This axis object or line formatting values (if no parameters). */ line: function(colour, width, settings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._lineFormat; } - if (typeof width == 'object') { + if (typeof width === 'object') { settings = width; width = null; } - $.extend(this._lineFormat, {stroke: colour}, - (width ? {strokeWidth: width} : {}), settings || {}); + $.extend(this._lineFormat, {stroke: colour}, (width ? {strokeWidth: width} : {}), settings || {}); this._graph._drawGraph(); return this; }, - /* Return to the parent graph. */ + /** Return to the parent graph. + @return {SVGGraph} The parent graph. */ end: function() { return this._graph; } }); -/* Details about the graph legend. - @param graph (SVGGraph) the owning graph - @param bgSettings (object) additional formatting settings for the legend background (optional) - @param textSettings (object) additional formatting settings for the legend text (optional) - @return (SVGGraphLegend) the new legend object */ +/** A graph legend definition. + @module SVGGraphLegend */ + +/** Details about each graph legend. + @param graph {SVGGraph} The owning graph. + @param [bgSettings] {object} Additional formatting settings for the legend background. + @param [textSettings] {object} Additional formatting settings for the legend text. + @return {SVGGraphLegend} The new legend object. */ function SVGGraphLegend(graph, bgSettings, textSettings) { this._graph = graph; // The owning graph this._show = true; // Show the legend? - this._area = [0.9, 0.1, 1.0, 0.9]; // The legend area: left, top, right, bottom, - // > 1 in pixels, <= 1 as proportion + this._area = [0.9, 0.1, 1.0, 0.9]; // The legend area: left, top, right, bottom, > 1 in pixels, <= 1 as proportion this._sampleSize = 15; // Size of sample box this._bgSettings = bgSettings || {stroke: 'gray'}; // Additional formatting settings for the legend background this._textSettings = textSettings || {}; // Additional formatting settings for the text @@ -820,12 +817,11 @@ function SVGGraphLegend(graph, bgSettings, textSettings) { $.extend(SVGGraphLegend.prototype, { - /* Set or retrieve whether the legend should be shown. - @param show (boolean) true to display it, false to hide it - @return (SVGGraphLegend) this legend object or - (boolean) show the legend? (if no parameters) */ + /** Set or retrieve whether the legend should be shown. + @param show {boolean} true to display it, false to hide it. + @return {SVGGraphLegend|boolean} This legend object or show the legend? (if no parameters) */ show: function(show) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._show; } this._show = show; @@ -833,35 +829,33 @@ $.extend(SVGGraphLegend.prototype, { return this; }, - /* Set or retrieve the legend area. - @param left (number) > 1 is pixels, <= 1 is proportion of width or - (number[4]) for left, top, right, bottom - @param top (number) > 1 is pixels, <= 1 is proportion of height - @param right (number) > 1 is pixels, <= 1 is proportion of width - @param bottom (number) > 1 is pixels, <= 1 is proportion of height - @return (SVGGraphLegend) this legend object or - (number[4]) the legend area: left, top, right, bottom (if no parameters) */ + /** Set or retrieve the legend area. + @param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom. + @param [top] {number) > 1 is pixels, <= 1 is proportion of height. + @param [right] {number) > 1 is pixels, <= 1 is proportion of width. + @param [bottom] {number) > 1 is pixels, <= 1 is proportion of height. + @return {SVGGraphLegend|number[]} This legend object or the legend area: + left, top, right, bottom (if no parameters). */ area: function(left, top, right, bottom) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._area; } - this._area = (isArray(left) ? left : [left, top, right, bottom]); + this._area = ($.isArray(left) ? left : [left, top, right, bottom]); this._graph._drawGraph(); return this; }, - /* Set or retrieve additional settings for the legend area. - @param sampleSize (number) the size of the sample box to display (optional) - @param bgSettings (object) additional formatting settings for the legend background - @param textSettings (object) additional formatting settings for the legend text (optional) - @return (SVGGraphLegend) this legend object or - (object) bgSettings and textSettings for the legend (if no parameters) */ + /** Set or retrieve additional settings for the legend area. + @param [sampleSize] {number} The size of the sample box to display. + @param bgSettings {object} Additional formatting settings for the legend background. + @param [textSettings] {object} Additional formatting settings for the legend text. + @return {SVGGraphLegend|object} This legend object or + bgSettings and textSettings for the legend (if no parameters). */ settings: function(sampleSize, bgSettings, textSettings) { - if (arguments.length == 0) { - return {sampleSize: this._sampleSize, bgSettings: this._bgSettings, - textSettings: this._textSettings}; + if (arguments.length === 0) { + return {sampleSize: this._sampleSize, bgSettings: this._bgSettings, textSettings: this._textSettings}; } - if (typeof sampleSize != 'number') { + if (typeof sampleSize !== 'number') { textSettings = bgSettings; bgSettings = sampleSize; sampleSize = null; @@ -873,7 +867,8 @@ $.extend(SVGGraphLegend.prototype, { return this; }, - /* Return to the parent graph. */ + /** Return to the parent graph. + @return {SVGGraph} The parent graph. */ end: function() { return this._graph; } @@ -881,42 +876,46 @@ $.extend(SVGGraphLegend.prototype, { //============================================================================== -/* Round a number to a given number of decimal points. */ +/** Round a number to a given number of decimal points. + @private + @param num {number} The original value. + @param dec {number} The number of decimal points to retain. + @return {number} The rounded number. */ function roundNumber(num, dec) { return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec); } -var barOptions = ['barWidth (number) - the width of each bar', - 'barGap (number) - the gap between sets of bars']; +var barOptions = ['barWidth (number) - the width of each bar', 'barGap (number) - the gap between sets of bars']; //------------------------------------------------------------------------------ -/* Draw a standard grouped column bar chart. */ +/** Draw a standard grouped column bar chart. + @module SVGColumnChart */ function SVGColumnChart() { } $.extend(SVGColumnChart.prototype, { - /* Retrieve the display title for this chart type. - @return the title */ + /** Retrieve the display title for this chart type. + @return {string} Its title. */ title: function() { return 'Basic column chart'; }, - /* Retrieve a description of this chart type. - @return its description */ + /** Retrieve a description of this chart type. + @return {string} Its description. */ description: function() { return 'Compare sets of values as vertical bars with grouped categories.'; }, - /* Retrieve a list of the options that may be set for this chart type. - @return options list */ + /** Retrieve a list of the options that may be set for this chart type. + @return {string[]} Its options list. */ options: function() { return barOptions; }, - /* Actually draw the graph in this type's style. - @param graph (object) the SVGGraph object */ + /** Actually draw the graph in this type's style. + @param graph {SVGGraph} The graph object. */ drawGraph: function(graph) { graph._drawChartBackground(true); var barWidth = graph._chartOptions.barWidth || 10; @@ -936,7 +935,16 @@ $.extend(SVGColumnChart.prototype, { graph._drawLegend(); }, - /* Plot an individual series. */ + /** Plot an individual series. + @private + @param graph {SVGGraph} The graph object. + @param cur {number} The current series index. + @param numSer {number} The number of points in this series. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. + @param yScale {number} The scaling factor in the vertical direction. */ _drawSeries: function(graph, cur, numSer, barWidth, barGap, dims, xScale, yScale) { var series = graph._series[cur]; var g = graph._wrapper.group(this._chart, @@ -951,7 +959,15 @@ $.extend(SVGColumnChart.prototype, { } }, - /* Draw the x-axis and its ticks. */ + /** Draw the x-axis and its ticks. + @private + @param graph {SVGGraph} The graph object. + @param numSer {number} The number of points in this series. + @param numVal {number} The current value index. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. */ _drawXAxis: function(graph, numSer, numVal, barWidth, barGap, dims, xScale) { var axis = graph.xAxis; if (axis._title) { @@ -982,33 +998,34 @@ $.extend(SVGColumnChart.prototype, { //------------------------------------------------------------------------------ -/* Draw a stacked column bar chart. */ +/** Draw a stacked column bar chart. + @module SVGStackedColumnChart */ function SVGStackedColumnChart() { } $.extend(SVGStackedColumnChart.prototype, { - /* Retrieve the display title for this chart type. - @return the title */ + /** Retrieve the display title for this chart type. + @return {string} Its title. */ title: function() { return 'Stacked column chart'; }, - /* Retrieve a description of this chart type. - @return its description */ + /** Retrieve a description of this chart type. + @return {string} Its description. */ description: function() { return 'Compare sets of values as vertical bars showing ' + 'relative contributions to the whole for each category.'; }, - /* Retrieve a list of the options that may be set for this chart type. - @return options list */ + /** Retrieve a list of the options that may be set for this chart type. + @return {string[]} Its options list. */ options: function() { return barOptions; }, - /* Actually draw the graph in this type's style. - @param graph (object) the SVGGraph object */ + /** Actually draw the graph in this type's style. + @param graph {SVGGraph} The graph object. */ drawGraph: function(graph) { var bg = graph._drawChartBackground(true, true); var dims = graph._getDims(); @@ -1030,13 +1047,21 @@ $.extend(SVGStackedColumnChart.prototype, { (dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, graph.yAxis._titleFormat || {})); var pAxis = $.extend({}, graph._getPercentageAxis()); $.extend(pAxis._labelFormat, graph.yAxis._labelFormat || {}); - graph._drawAxis(pAxis, 'yAxis', dims[graph.X], dims[graph.Y], - dims[graph.X], dims[graph.Y] + dims[graph.H]); + graph._drawAxis(pAxis, 'yAxis', dims[graph.X], dims[graph.Y], dims[graph.X], dims[graph.Y] + dims[graph.H]); this._drawXAxis(graph, numVal, barWidth, barGap, dims, xScale); graph._drawLegend(); }, - /* Plot all of the columns. */ + /** Plot all of the columns. + @private + @param graph {SVGGraph} The graph object. + @param numSer {number} The number of points in this series. + @param numVal {number} The current value index. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. + @param yScale {number} The scaling factor in the vertical direction. */ _drawColumns: function(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale) { var totals = graph._getTotals(); var accum = []; @@ -1045,23 +1070,26 @@ $.extend(SVGStackedColumnChart.prototype, { } for (var s = 0; s < numSer; s++) { var series = graph._series[s]; - var g = graph._wrapper.group(this._chart, - $.extend({class_: 'series' + s, fill: series._fill, - stroke: series._stroke, strokeWidth: series._strokeWidth}, - series._settings || {})); + var g = graph._wrapper.group(this._chart, $.extend({class_: 'series' + s, fill: series._fill, + stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {})); for (var i = 0; i < series._values.length; i++) { accum[i] += series._values[i]; - var r = graph._wrapper.rect(g, - dims[graph.X] + xScale * (barGap + i * (barWidth + barGap)), + var r = graph._wrapper.rect(g, dims[graph.X] + xScale * (barGap + i * (barWidth + barGap)), dims[graph.Y] + yScale * (totals[i] - accum[i]) / totals[i], xScale * barWidth, yScale * series._values[i] / totals[i]); - graph._showStatus(r, series._name, - roundNumber(series._values[i] / totals[i] * 100, 2)); + graph._showStatus(r, series._name, roundNumber(series._values[i] / totals[i] * 100, 2)); } } }, - /* Draw the x-axis and its ticks. */ + /** Draw the x-axis and its ticks. + @private + @param graph {SVGGraph} The graph object. + @param numVal {number} The current value index. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. */ _drawXAxis: function(graph, numVal, barWidth, barGap, dims, xScale) { var axis = graph.xAxis; if (axis._title) { @@ -1092,32 +1120,33 @@ $.extend(SVGStackedColumnChart.prototype, { //------------------------------------------------------------------------------ -/* Draw a standard grouped row bar chart. */ +/** Draw a standard grouped row bar chart. + @module SVGRowChart */ function SVGRowChart() { } $.extend(SVGRowChart.prototype, { - /* Retrieve the display title for this chart type. - @return the title */ + /** Retrieve the display title for this chart type. + @return {string} Its title. */ title: function() { return 'Basic row chart'; }, - /* Retrieve a description of this chart type. - @return its description */ + /** Retrieve a description of this chart type. + @return {string} Its description. */ description: function() { return 'Compare sets of values as horizontal rows with grouped categories.'; }, - /* Retrieve a list of the options that may be set for this chart type. - @return options list */ + /** Retrieve a list of the options that may be set for this chart type. + @return {string[]} Its options list. */ options: function() { return barOptions; }, - /* Actually draw the graph in this type's style. - @param graph (object) the SVGGraph object */ + /** Actually draw the graph in this type's style. + @param graph {SVGGraph} The graph object. */ drawGraph: function(graph) { var bg = graph._drawChartBackground(true, true); var dims = graph._getDims(); @@ -1137,23 +1166,37 @@ $.extend(SVGRowChart.prototype, { graph._drawLegend(); }, - /* Plot an individual series. */ + /** Plot an individual series. + @private + @param graph {SVGGraph} The graph object. + @param cur {number} The current series index. + @param numSer {number} The number of points in this series. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. + @param yScale {number} The scaling factor in the vertical direction. */ _drawSeries: function(graph, cur, numSer, barWidth, barGap, dims, xScale, yScale) { var series = graph._series[cur]; - var g = graph._wrapper.group(this._chart, - $.extend({class_: 'series' + cur, fill: series._fill, - stroke: series._stroke, strokeWidth: series._strokeWidth}, - series._settings || {})); + var g = graph._wrapper.group(this._chart, $.extend({class_: 'series' + cur, fill: series._fill, + stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {})); for (var i = 0; i < series._values.length; i++) { - var r = graph._wrapper.rect(g, - dims[graph.X] + xScale * (0 - graph.yAxis._scale.min), + var r = graph._wrapper.rect(g, dims[graph.X] + xScale * (0 - graph.yAxis._scale.min), dims[graph.Y] + yScale * (barGap + i * (numSer * barWidth + barGap) + (cur * barWidth)), xScale * series._values[i], yScale * barWidth); graph._showStatus(r, series._name, series._values[i]); } }, - /* Draw the axes for this graph. */ + /** Draw the axes for this graph. + @private + @param graph {SVGGraph} The graph object. + @param numSer {number} The number of points in this series. + @param numVal {number} The current value index. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param yScale {number} The scaling factor in the vertical direction. */ _drawAxes: function(graph, numSer, numVal, barWidth, barGap, dims, yScale) { // X-axis var axis = graph.yAxis; @@ -1194,33 +1237,34 @@ $.extend(SVGRowChart.prototype, { //------------------------------------------------------------------------------ -/* Draw a stacked row bar chart. */ +/** Draw a stacked row bar chart. + @module SVGStackedRowChart */ function SVGStackedRowChart() { } $.extend(SVGStackedRowChart.prototype, { - /* Retrieve the display title for this chart type. - @return the title */ + /** Retrieve the display title for this chart type. + @return {string} Its title. */ title: function() { return 'Stacked row chart'; }, - /* Retrieve a description of this chart type. - @return its description */ + /** Retrieve a description of this chart type. + @return {string} Its description. */ description: function() { return 'Compare sets of values as horizontal bars showing ' + 'relative contributions to the whole for each category.'; }, - /* Retrieve a list of the options that may be set for this chart type. - @return options list */ + /** Retrieve a list of the options that may be set for this chart type. + @return {string[]} Its options list. */ options: function() { return barOptions; }, - /* Actually draw the graph in this type's style. - @param graph (object) the SVGGraph object */ + /** Actually draw the graph in this type's style. + @param graph {SVGGraph} The graph object. */ drawGraph: function(graph) { var bg = graph._drawChartBackground(true, true); var dims = graph._getDims(); @@ -1237,8 +1281,7 @@ $.extend(SVGStackedRowChart.prototype, { this._drawRows(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale); graph._drawTitle(); graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2, - dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset, - $.svg.graphing.region.percentageText, + dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset, $.svg.graphing.region.percentageText, $.extend({textAnchor: 'middle'}, graph.yAxis._titleFormat || {})); var pAxis = $.extend({}, graph._getPercentageAxis()); $.extend(pAxis._labelFormat, graph.yAxis._labelFormat || {}); @@ -1248,7 +1291,16 @@ $.extend(SVGStackedRowChart.prototype, { graph._drawLegend(); }, - /* Plot all of the rows. */ + /** Plot all of the rows. + @private + @param graph {SVGGraph} The graph object. + @param numSer {number} The number of points in this series. + @param numVal {number} The current value index. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. + @param yScale {number} The scaling factor in the vertical direction. */ _drawRows: function(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale) { var totals = graph._getTotals(); var accum = []; @@ -1257,23 +1309,26 @@ $.extend(SVGStackedRowChart.prototype, { } for (var s = 0; s < numSer; s++) { var series = graph._series[s]; - var g = graph._wrapper.group(this._chart, - $.extend({class_: 'series' + s, fill: series._fill, - stroke: series._stroke, strokeWidth: series._strokeWidth}, - series._settings || {})); + var g = graph._wrapper.group(this._chart, $.extend({class_: 'series' + s, fill: series._fill, + stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {})); for (var i = 0; i < series._values.length; i++) { - var r = graph._wrapper.rect(g, - dims[graph.X] + xScale * accum[i] / totals[i], + var r = graph._wrapper.rect(g, dims[graph.X] + xScale * accum[i] / totals[i], dims[graph.Y] + yScale * (barGap + i * (barWidth + barGap)), xScale * series._values[i] / totals[i], yScale * barWidth); - graph._showStatus(r, series._name, - roundNumber(series._values[i] / totals[i] * 100, 2)); + graph._showStatus(r, series._name, roundNumber(series._values[i] / totals[i] * 100, 2)); accum[i] += series._values[i]; } } }, - /* Draw the y-axis and its ticks. */ + /** Draw the y-axis and its ticks. + @private + @param graph {SVGGraph} The graph object. + @param numVal {number} The current value index. + @param barWidth {number} The width of each bar. + @param barGap {number} The space between bars. + @param dims {number[]} The dimensions of the drawing area. + @param yScale {number} The scaling factor in the vertical direction. */ _drawYAxis: function(graph, numVal, barWidth, barGap, dims, yScale) { var axis = graph.xAxis; if (axis._title) { @@ -1281,12 +1336,10 @@ $.extend(SVGStackedRowChart.prototype, { transform: 'translate(' + (dims[graph.X] - axis._titleOffset) + ',' + (dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, axis._titleFormat || {})); } - var gl = graph._wrapper.group(graph._chartCont, - $.extend({class_: 'yAxis'}, axis._lineFormat)); + var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'yAxis'}, axis._lineFormat)); var gt = graph._wrapper.group(graph._chartCont, $.extend({class_: 'yAxisLabels', textAnchor: 'end'}, axis._labelFormat)); - graph._wrapper.line(gl, dims[graph.X], dims[graph.Y], - dims[graph.X], dims[graph.Y] + dims[graph.H]); + graph._wrapper.line(gl, dims[graph.X], dims[graph.Y], dims[graph.X], dims[graph.Y] + dims[graph.H]); if (axis._ticks.major) { var offsets = graph._getTickOffsets(axis, false); for (var i = 1; i < numVal; i++) { @@ -1305,32 +1358,33 @@ $.extend(SVGStackedRowChart.prototype, { //------------------------------------------------------------------------------ -/* Draw a standard line chart. */ +/** Draw a standard line chart. + @module SVGLineChart */ function SVGLineChart() { } $.extend(SVGLineChart.prototype, { - /* Retrieve the display title for this chart type. - @return the title */ + /** Retrieve the display title for this chart type. + @return {string} Its title. */ title: function() { return 'Basic line chart'; }, - /* Retrieve a description of this chart type. - @return its description */ + /** Retrieve a description of this chart type. + @return {string} Its description. */ description: function() { return 'Compare sets of values as continuous lines.'; }, - /* Retrieve a list of the options that may be set for this chart type. - @return options list */ + /** Retrieve a list of the options that may be set for this chart type. + @return {string[]} Its options list. */ options: function() { return []; }, - /* Actually draw the graph in this type's style. - @param graph (object) the SVGGraph object */ + /** Actually draw the graph in this type's style. + @param graph {SVGGraph} The graph object. */ drawGraph: function(graph) { graph._drawChartBackground(); var dims = graph._getDims(); @@ -1345,30 +1399,36 @@ $.extend(SVGLineChart.prototype, { graph._drawLegend(); }, - /* Plot an individual series. */ + /** Plot an individual series. + @private + @param graph {SVGGraph} The graph object. + @param cur {number} The current series index. + @param dims {number[]} The dimensions of the drawing area. + @param xScale {number} The scaling factor in the horizontal direction. + @param yScale {number} The scaling factor in the vertical direction. */ _drawSeries: function(graph, cur, dims, xScale, yScale) { var series = graph._series[cur]; var path = graph._wrapper.createPath(); for (var i = 0; i < series._values.length; i++) { var x = dims[graph.X] + i * xScale; var y = dims[graph.Y] + (graph.yAxis._scale.max - series._values[i]) * yScale; - if (i == 0) { + if (i === 0) { path.move(x, y); } else { path.line(x, y); } } - var p = graph._wrapper.path(this._chart, path, - $.extend({id: 'series' + cur, fill: 'none', stroke: series._stroke, - strokeWidth: series._strokeWidth}, series._settings || {})); + var p = graph._wrapper.path(this._chart, path, $.extend({id: 'series' + cur, fill: 'none', + stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {})); graph._showStatus(p, series._name, 0); } }); //------------------------------------------------------------------------------ -/* Draw a standard pie chart. */ +/** Draw a standard pie chart. + @module SVGPieChart */ function SVGPieChart() { } @@ -1378,26 +1438,26 @@ $.extend(SVGPieChart.prototype, { 'explodeDist (number) - the distance to move an exploded section', 'pieGap (number) - the distance between pies for multiple values'], - /* Retrieve the display title for this chart type. - @return the title */ + /** Retrieve the display title for this chart type. + @return {string} Its title. */ title: function() { return 'Pie chart'; }, - /* Retrieve a description of this chart type. - @return its description */ + /** Retrieve a description of this chart type. + @return {string} Its description. */ description: function() { return 'Compare relative sizes of values as contributions to the whole.'; }, - /* Retrieve a list of the options that may be set for this chart type. - @return options list */ + /** Retrieve a list of the options that may be set for this chart type. + @return {string[]} Its options list. */ options: function() { return this._options; }, - /* Actually draw the graph in this type's style. - @param graph (object) the SVGGraph object */ + /** Actually draw the graph in this type's style. + @param graph {SVGGraph} The graph object. */ drawGraph: function(graph) { graph._drawChartBackground(true, true); this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'}); @@ -1407,14 +1467,17 @@ $.extend(SVGPieChart.prototype, { graph._drawLegend(); }, - /* Plot all the series. */ + /** Plot all the series. + @private + @param graph {SVGGraph} The graph object. + @param dims {number[]} The dimensions of the drawing area. */ _drawSeries: function(graph, dims) { var totals = graph._getTotals(); var numSer = graph._series.length; var numVal = (numSer ? (graph._series[0])._values.length : 0); var path = graph._wrapper.createPath(); var explode = graph._chartOptions.explode || []; - explode = (isArray(explode) ? explode : [explode]); + explode = ($.isArray(explode) ? explode : [explode]); var explodeDist = graph._chartOptions.explodeDist || 10; var pieGap = (numVal <= 1 ? 0 : graph._chartOptions.pieGap || 10); var xBase = (dims[graph.W] - (numVal * pieGap) - pieGap) / numVal / 2; @@ -1429,12 +1492,12 @@ $.extend(SVGPieChart.prototype, { var curTotal = 0; for (var j = 0; j < numSer; j++) { var series = graph._series[j]; - if (i == 0) { - gl[j] = graph._wrapper.group(this._chart, $.extend({class_: 'series' + j, - fill: series._fill, stroke: series._stroke, + if (i === 0) { + gl[j] = graph._wrapper.group(this._chart, + $.extend({class_: 'series' + j, fill: series._fill, stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {})); } - if (series._values[i] == 0) { + if (series._values[i] === 0) { continue; } var start = (curTotal / totals[i]) * 2 * Math.PI; @@ -1442,7 +1505,7 @@ $.extend(SVGPieChart.prototype, { var end = (curTotal / totals[i]) * 2 * Math.PI; var exploding = false; for (var k = 0; k < explode.length; k++) { - if (explode[k] == j) { + if (explode[k] === j) { exploding = true; break; } @@ -1453,8 +1516,7 @@ $.extend(SVGPieChart.prototype, { line(x + radius * Math.cos(start), y + radius * Math.sin(start)). arc(radius, radius, 0, (end - start < Math.PI ? 0 : 1), 1, x + radius * Math.cos(end), y + radius * Math.sin(end)).close()); - graph._showStatus(p, series._name, - roundNumber((end - start) / 2 / Math.PI * 100, 2)); + graph._showStatus(p, series._name, roundNumber((end - start) / 2 / Math.PI * 100, 2)); } if (graph.xAxis) { graph._wrapper.text(gt, cx, dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset, @@ -1466,11 +1528,6 @@ $.extend(SVGPieChart.prototype, { //------------------------------------------------------------------------------ -/* Determine whether an object is an array. */ -function isArray(a) { - return (a && a.constructor == Array); -} - // Basic chart types $.svg.graphing.addChartType('column', new SVGColumnChart()); $.svg.graphing.addChartType('stackedColumn', new SVGStackedColumnChart()); diff --git a/jquery.svggraph.min.js b/jquery.svggraph.min.js index f693148..84a5285 100644 --- a/jquery.svggraph.min.js +++ b/jquery.svggraph.min.js @@ -1,7 +1,6 @@ -/* http://keith-wood.name/svg.html - SVG graphing extension for jQuery v1.4.5. +/* http://keith-wood.name/svg.html + SVG graphing extension for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ -(function($){$.svg.addExtension('graph',SVGGraph);$.svg.graphing=new SVGGraphing();function SVGGraphing(){this.regional=[];this.regional['']={percentageText:'Percentage'};this.region=this.regional['']}$.extend(SVGGraphing.prototype,{_chartTypes:[],addChartType:function(a,b){this._chartTypes[a]=b},chartTypes:function(){return this._chartTypes}});function SVGGraph(a){this._wrapper=a;this._drawNow=false;for(var b in $.svg.graphing._chartTypes){this._chartType=$.svg.graphing._chartTypes[b];break}this._chartOptions={};this._title={value:'',offset:25,settings:{textAnchor:'middle'}};this._area=[0.1,0.1,0.8,0.9];this._chartFormat={fill:'none',stroke:'black'};this._gridlines=[];this._series=[];this._onstatus=null;this._chartCont=this._wrapper.svg(0,0,0,0,{class_:'svg-graph'});this.xAxis=new SVGGraphAxis(this);this.xAxis.title('',40);this.yAxis=new SVGGraphAxis(this);this.yAxis.title('',40);this.x2Axis=null;this.y2Axis=null;this.legend=new SVGGraphLegend(this);this._drawNow=true}$.extend(SVGGraph.prototype,{X:0,Y:1,W:2,H:3,L:0,T:1,R:2,B:3,_percentageAxis:new SVGGraphAxis(this,$.svg.graphing.region.percentageText,0,100,10,0),container:function(a){if(arguments.length==0){return this._chartCont}this._chartCont=a;return this},chartType:function(a,b){return(arguments.length==0?this.type():this.type(a,b))},type:function(a,b){if(arguments.length==0){return this._chartType}var c=$.svg.graphing._chartTypes[a];if(c){this._chartType=c;this._chartOptions=$.extend({},b||{})}this._drawGraph();return this},chartOptions:function(a){return(arguments.length==0?this.options():this.options(a))},options:function(a){if(arguments.length==0){return this._chartOptions}this._chartOptions=$.extend({},a);this._drawGraph();return this},chartFormat:function(a,b,c){return(arguments.length==0?this.format():this.format(a,b,c))},format:function(a,b,c){if(arguments.length==0){return this._chartFormat}if(typeof b=='object'){c=b;b=null}this._chartFormat=$.extend({fill:a},(b?{stroke:b}:{}),c||{});this._drawGraph();return this},chartArea:function(a,b,c,d){return(arguments.length==0?this.area():this.area(a,b,c,d))},area:function(a,b,c,d){if(arguments.length==0){return this._area}this._area=(isArray(a)?a:[a,b,c,d]);this._drawGraph();return this},gridlines:function(a,b){if(arguments.length==0){return this._gridlines}this._gridlines=[(typeof a=='string'?{stroke:a}:a),(typeof b=='string'?{stroke:b}:b)];if(this._gridlines[0]==null&&this._gridlines[1]==null){this._gridlines=[]}this._drawGraph();return this},title:function(a,b,c,d){if(arguments.length==0){return this._title}if(typeof b!='number'){d=c;c=b;b=null}if(typeof c!='string'){d=c;c=null}this._title={value:a,offset:b||this._title.offset,settings:$.extend({textAnchor:'middle'},(c?{fill:c}:{}),d||{})};this._drawGraph();return this},addSeries:function(a,b,c,d,e,f){this._series.push(new SVGGraphSeries(this,a,b,c,d,e,f));this._drawGraph();return this},series:function(i){return(arguments.length>0?this._series[i]:null)||this._series},noDraw:function(){this._drawNow=false;return this},redraw:function(){this._drawNow=true;this._drawGraph();return this},status:function(a){this._onstatus=a;return this},_drawGraph:function(){if(!this._drawNow){return}while(this._chartCont.firstChild){this._chartCont.removeChild(this._chartCont.firstChild)}if(!this._chartCont.parent){this._wrapper._svg.appendChild(this._chartCont)}if(!this._chartCont.width){this._chartCont.setAttribute('width',parseInt(this._chartCont.getAttribute('width'),10)||this._wrapper._width())}else if(this._chartCont.width.baseVal){this._chartCont.width.baseVal.value=this._chartCont.width.baseVal.value||this._wrapper._width()}else{this._chartCont.width=this._chartCont.width||this._wrapper._width()}if(!this._chartCont.height){this._chartCont.setAttribute('height',parseInt(this._chartCont.getAttribute('height'),10)||this._wrapper._height())}else if(this._chartCont.height.baseVal){this._chartCont.height.baseVal.value=this._chartCont.height.baseVal.value||this._wrapper._height()}else{this._chartCont.height=this._chartCont.height||this._wrapper._height()}this._chartType.drawGraph(this)},_getValue:function(a,b){return(!a[b]?parseInt(a.getAttribute(b),10):(a[b].baseVal?a[b].baseVal.value:a[b]))},_drawTitle:function(){this._wrapper.text(this._chartCont,this._getValue(this._chartCont,'width')/2,this._title.offset,this._title.value,this._title.settings)},_getDims:function(a){a=a||this._area;var b=this._getValue(this._chartCont,'width');var c=this._getValue(this._chartCont,'height');var d=(a[this.L]>1?a[this.L]:b*a[this.L]);var e=(a[this.T]>1?a[this.T]:c*a[this.T]);var f=(a[this.R]>1?a[this.R]:b*a[this.R])-d;var g=(a[this.B]>1?a[this.B]:c*a[this.B])-e;return[d,e,f,g]},_drawChartBackground:function(a,b){var c=this._wrapper.group(this._chartCont,{class_:'background'});var d=this._getDims();this._wrapper.rect(c,d[this.X],d[this.Y],d[this.W],d[this.H],this._chartFormat);if(this._gridlines[0]&&this.yAxis._ticks.major&&!b){this._drawGridlines(c,this.yAxis,true,d,this._gridlines[0])}if(this._gridlines[1]&&this.xAxis._ticks.major&&!a){this._drawGridlines(c,this.xAxis,false,d,this._gridlines[1])}return c},_drawGridlines:function(a,b,c,d,e){var g=this._wrapper.group(a,e);var f=(c?d[this.H]:d[this.W])/(b._scale.max-b._scale.min);var h=Math.floor(b._scale.min/b._ticks.major)*b._ticks.major;h=(h(this._getValue(this._chartCont,'width')/2)&&f>(this._getValue(this._chartCont,'height')/2));var k=(g?e-c:f-d)/(a._scale.max-a._scale.min);var l=a._ticks.size;var m=Math.floor(a._scale.min/a._ticks.major)*a._ticks.major;m=(ma[this.H];var c=this._series.length;var d=(b?a[this.W]:a[this.H])/c;var e=a[this.X]+5;var f=a[this.Y]+((b?a[this.H]:d)+this.legend._sampleSize)/2;for(var i=0;i0?h:0);var q=a._wrapper.group(a._chartCont,$.extend({class_:'xAxisLabels',textAnchor:'middle'},a.xAxis._labelFormat));var r=[];for(var i=0;i0?this._series[i]:null)||this._series},noDraw:function(){this._drawNow=false;return this},redraw:function(){this._drawNow=true;this._drawGraph();return this},status:function(a){this._onstatus=a;return this},_drawGraph:function(){if(!this._drawNow){return}while(this._chartCont.firstChild){this._chartCont.removeChild(this._chartCont.firstChild)}if(!this._chartCont.parent){this._wrapper._svg.appendChild(this._chartCont)}if(!this._chartCont.width){this._chartCont.setAttribute('width',parseInt(this._chartCont.getAttribute('width'),10)||this._wrapper.width())}else if(this._chartCont.width.baseVal){this._chartCont.width.baseVal.value=this._chartCont.width.baseVal.value||this._wrapper.width()}else{this._chartCont.width=this._chartCont.width||this._wrapper.width()}if(!this._chartCont.height){this._chartCont.setAttribute('height',parseInt(this._chartCont.getAttribute('height'),10)||this._wrapper.height())}else if(this._chartCont.height.baseVal){this._chartCont.height.baseVal.value=this._chartCont.height.baseVal.value||this._wrapper.height()}else{this._chartCont.height=this._chartCont.height||this._wrapper.height()}this._chartType.drawGraph(this)},_getValue:function(a,b){return(!a[b]?parseInt(a.getAttribute(b),10):(a[b].baseVal?a[b].baseVal.value:a[b]))},_drawTitle:function(){this._wrapper.text(this._chartCont,this._getValue(this._chartCont,'width')/2,this._title.offset,this._title.value,this._title.settings)},_getDims:function(a){a=a||this._area;var b=this._getValue(this._chartCont,'width');var c=this._getValue(this._chartCont,'height');var d=(a[this.L]>1?a[this.L]:b*a[this.L]);var e=(a[this.T]>1?a[this.T]:c*a[this.T]);var f=(a[this.R]>1?a[this.R]:b*a[this.R])-d;var g=(a[this.B]>1?a[this.B]:c*a[this.B])-e;return[d,e,f,g]},_drawChartBackground:function(a,b){var c=this._wrapper.group(this._chartCont,{class_:'background'});var d=this._getDims();this._wrapper.rect(c,d[this.X],d[this.Y],d[this.W],d[this.H],this._chartFormat);if(this._gridlines[0]&&this.yAxis._ticks.major&&!b){this._drawGridlines(c,this.yAxis,true,d,this._gridlines[0])}if(this._gridlines[1]&&this.xAxis._ticks.major&&!a){this._drawGridlines(c,this.xAxis,false,d,this._gridlines[1])}return c},_drawGridlines:function(a,b,c,d,e){var g=this._wrapper.group(a,e);var f=(c?d[this.H]:d[this.W])/(b._scale.max-b._scale.min);var h=Math.floor(b._scale.min/b._ticks.major)*b._ticks.major;h=(h(this._getValue(this._chartCont,'width')/2)&&f>(this._getValue(this._chartCont,'height')/2));var k=(g?e-c:f-d)/(a._scale.max-a._scale.min);var l=a._ticks.size;var m=Math.floor(a._scale.min/a._ticks.major)*a._ticks.major;m=(ma[this.H];var c=this._series.length;var d=(b?a[this.W]:a[this.H])/c;var e=a[this.X]+5;var f=a[this.Y]+((b?a[this.H]:d)+this.legend._sampleSize)/2;for(var i=0;i0?h:0);var q=a._wrapper.group(a._chartCont,$.extend({class_:'xAxisLabels',textAnchor:'middle'},a.xAxis._labelFormat));var r=[];for(var i=0;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.19.3M(\'3i\',2L);$.19.1k=1q 2M();7 2M(){4.2N=[];4.2N[\'\']={2g:\'3N\'};4.2h=4.2N[\'\']}$.G(2M.1v,{26:[],1V:7(a,b){4.26[a]=b},3O:7(){C 4.26}});7 2L(a){4.D=a;4.2i=1K;M(6 b 2O $.19.1k.26){4.2y=$.19.1k.26[b];3j}4.1h={};4.O={1L:\'\',2j:25,2z:{1b:\'1l\'}};4.1M=[0.1,0.1,0.8,0.9];4.2A={1o:\'3k\',1i:\'2P\'};4.1j=[];4.S=[];4.2B=Z;4.F=4.D.19(0,0,0,0,{U:\'19-3i\'});4.Q=1q 2k(4);4.Q.1w(\'\',40);4.N=1q 2k(4);4.N.1w(\'\',40);4.1N=Z;4.1O=Z;4.1x=1q 2Q(4);4.2i=18}$.G(2L.1v,{X:0,Y:1,W:2,H:3,L:0,T:1,R:2,B:3,2R:1q 2k(4,$.19.1k.2h.2g,0,2l,10,0),3P:7(a){E(11.J==0){C 4.F}4.F=a;C 4},3Q:7(a,b){C(11.J==0?4.2S():4.2S(a,b))},2S:7(a,b){E(11.J==0){C 4.2y}6 c=$.19.1k.26[a];E(c){4.2y=c;4.1h=$.G({},b||{})}4.12();C 4},3R:7(a){C(11.J==0?4.1G():4.1G(a))},1G:7(a){E(11.J==0){C 4.1h}4.1h=$.G({},a);4.12();C 4},3S:7(a,b,c){C(11.J==0?4.27():4.27(a,b,c))},27:7(a,b,c){E(11.J==0){C 4.2A}E(1c b==\'3l\'){c=b;b=Z}4.2A=$.G({1o:a},(b?{1i:b}:{}),c||{});4.12();C 4},3T:7(a,b,c,d){C(11.J==0?4.2C():4.2C(a,b,c,d))},2C:7(a,b,c,d){E(11.J==0){C 4.1M}4.1M=(2m(a)?a:[a,b,c,d]);4.12();C 4},3U:7(a,b){E(11.J==0){C 4.1j}4.1j=[(1c a==\'1H\'?{1i:a}:a),(1c b==\'1H\'?{1i:b}:b)];E(4.1j[0]==Z&&4.1j[1]==Z){4.1j=[]}4.12();C 4},1w:7(a,b,c,d){E(11.J==0){C 4.O}E(1c b!=\'1y\'){d=c;c=b;b=Z}E(1c c!=\'1H\'){d=c;c=Z}4.O={1L:a,2j:b||4.O.2j,2z:$.G({1b:\'1l\'},(c?{1o:c}:{}),d||{})};4.12();C 4},3V:7(a,b,c,d,e,f){4.S.3W(1q 2T(4,a,b,c,d,e,f));4.12();C 4},1W:7(i){C(11.J>0?4.S[i]:Z)||4.S},3X:7(){4.2i=1K;C 4},3Y:7(){4.2i=18;4.12();C 4},3Z:7(a){4.2B=a;C 4},12:7(){E(!4.2i){C}2U(4.F.3m){4.F.41(4.F.3m)}E(!4.F.42){4.D.43.44(4.F)}E(!4.F.1r){4.F.3n(\'1r\',2V(4.F.2W(\'1r\'),10)||4.D.2X())}2n E(4.F.1r.1P){4.F.1r.1P.1L=4.F.1r.1P.1L||4.D.2X()}2n{4.F.1r=4.F.1r||4.D.2X()}E(!4.F.1A){4.F.3n(\'1A\',2V(4.F.2W(\'1A\'),10)||4.D.2Y())}2n E(4.F.1A.1P){4.F.1A.1P.1L=4.F.1A.1P.1L||4.D.2Y()}2n{4.F.1A=4.F.1A||4.D.2Y()}4.2y.1X(4)},28:7(a,b){C(!a[b]?2V(a.2W(b),10):(a[b].1P?a[b].1P.1L:a[b]))},1Y:7(){4.D.14(4.F,4.28(4.F,\'1r\')/2,4.O.2j,4.O.1L,4.O.2z)},1B:7(a){a=a||4.1M;6 b=4.28(4.F,\'1r\');6 c=4.28(4.F,\'1A\');6 d=(a[4.L]>1?a[4.L]:b*a[4.L]);6 e=(a[4.T]>1?a[4.T]:c*a[4.T]);6 f=(a[4.R]>1?a[4.R]:b*a[4.R])-d;6 g=(a[4.B]>1?a[4.B]:c*a[4.B])-e;C[d,e,f,g]},1Z:7(a,b){6 c=4.D.V(4.F,{U:\'45\'});6 d=4.1B();4.D.20(c,d[4.X],d[4.Y],d[4.W],d[4.H],4.2A);E(4.1j[0]&&4.N.I.16&&!b){4.29(c,4.N,18,d,4.1j[0])}E(4.1j[1]&&4.Q.I.16&&!a){4.29(c,4.Q,1K,d,4.1j[1])}C c},29:7(a,b,c,d,e){6 g=4.D.V(a,e);6 f=(c?d[4.H]:d[4.W])/(b.K.1d-b.K.13);6 h=17.2Z(b.K.13/b.I.16)*b.I.16;h=(h(4.28(4.F,\'1r\')/2)&&f>(4.28(4.F,\'1A\')/2));6 k=(g?e-c:f-d)/(a.K.1d-a.K.13);6 l=a.I.1g;6 m=17.2Z(a.K.13/a.I.16)*a.I.16;m=(ma[4.H];6 c=4.S.J;6 d=(b?a[4.W]:a[4.H])/c;6 e=a[4.X]+5;6 f=a[4.Y]+((b?a[4.H]:d)+4.1x.1I)/2;M(6 i=0;i0?h:0);6 q=a.D.V(a.F,$.G({U:\'34\',1b:\'1l\'},a.Q.1p));6 r=[];M(6 i=0;iUse the singleton instance of this class, $.svg.plot, + to interact with the SVG plotting functionality.

+ @module SVGPlot */ function SVGPlot(wrapper) { this._wrapper = wrapper; // The attached SVG wrapper object this._drawNow = false; // True for immediate update, false to wait for redraw call // The plot title and settings this._title = {value: '', offset: 25, settings: {textAnchor: 'middle'}}; - this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom, - // > 1 in pixels, <= 1 as proportion + this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom, > 1 in pixels, <= 1 as proportion this._areaFormat = {fill: 'none', stroke: 'black'}; // The formatting for the plot area this._gridlines = []; // The formatting of the x- and y-gridlines this._equalXY = true; // True for equal-sized x- and y-units, false to fill available space @@ -25,91 +25,94 @@ function SVGPlot(wrapper) { this._onstatus = null; // The callback function for status updates this._uuid = new Date().getTime(); this._plotCont = this._wrapper.svg(0, 0, 0, 0, {class_: 'svg-plot'}); // The main container for the plot - - this.xAxis = new SVGPlotAxis(this); // The main x-axis + + /** The main x-axis for this plot. */ + this.xAxis = new SVGPlotAxis(this); this.xAxis.title('X', 20); - this.yAxis = new SVGPlotAxis(this); // The main y-axis + /** The main y-axis for this plot. */ + this.yAxis = new SVGPlotAxis(this); this.yAxis.title('Y', 20); - this.legend = new SVGPlotLegend(this); // The plot legend + /** The legend for this plot. */ + this.legend = new SVGPlotLegend(this); this._drawNow = true; } $.extend(SVGPlot.prototype, { /* Useful indexes. */ + /** Index in a dimensions array for x-coordinate. */ X: 0, + /** Index in a dimensions array for y-coordinate. */ Y: 1, + /** Index in a dimensions array for width. */ W: 2, + /** Index in a dimensions array for height. */ H: 3, + /** Index in an area array for left x-coordinate. */ L: 0, + /** Index in an area array for top y-coordinate. */ T: 1, + /** Index in an area array for right x-coordinate. */ R: 2, + /** Index in an area array for bottom y-coordinate. */ B: 3, - /* Set or retrieve the container for the plot. - @param cont (SVG element) the container for the plot - @return (SVGPlot) this plot object or - (SVG element) the current container (if no parameters) */ + /** Set or retrieve the container for the plot. + @param cont {SVGElement} The container for the plot. + @return {SVGPlot|SVGElement} This plot object or the current container (if no parameters). */ container: function(cont) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._plotCont; } this._plotCont = cont; return this; }, - /* Set or retrieve the main plotting area. - @param left (number) > 1 is pixels, <= 1 is proportion of width or - (number[4]) for left, top, right, bottom - @param top (number) > 1 is pixels, <= 1 is proportion of height - @param right (number) > 1 is pixels, <= 1 is proportion of width - @param bottom (number) > 1 is pixels, <= 1 is proportion of height - @return (SVGPlot) this plot object or - (number[4]) the plotting area: left, top, right, bottom (if no parameters) */ + /** Set or retrieve the main plotting area. + @param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom. + @param [top] {number) > 1 is pixels, <= 1 is proportion of height. + @param [right] {number) > 1 is pixels, <= 1 is proportion of width. + @param [bottom] {number) > 1 is pixels, <= 1 is proportion of height. + @return {SVGPlot|number[]} This plot object or the plotting area: left, top, right, bottom (if no parameters). */ area: function(left, top, right, bottom) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._area; } - this._area = (isArray(left) ? left : [left, top, right, bottom]); + this._area = ($.isArray(left) ? left : [left, top, right, bottom]); this._drawPlot(); return this; }, - /* Set or retrieve the background of the plot area. - @param fill (string) how to fill the area background - @param stroke (string) the colour of the outline (optional) - @param settings (object) additional formatting for the area background (optional) - @return (SVGPlot) this plot object or - (object) the area format (if no parameters) */ + /** Set or retrieve the background of the plot area. + @param fill {string} How to fill the area background. + @param [stroke] {string} The colour of the outline. + @param [settings] {object} Additional formatting for the area background. + @return {SVGPlot|object} This plot object or the area format (if no parameters). */ format: function(fill, stroke, settings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._areaFormat; } - if (typeof stroke == 'object') { + if (typeof stroke === 'object') { settings = stroke; stroke = null; } - this._areaFormat = $.extend({fill: fill}, - (stroke ? {stroke: stroke} : {}), settings || {}); + this._areaFormat = $.extend({fill: fill}, (stroke ? {stroke: stroke} : {}), settings || {}); this._drawPlot(); return this; }, - /* Set or retrieve the gridlines formatting for the plot area. - @param xSettings (string) the colour of the gridlines along the x-axis, or - (object) formatting for the gridlines along the x-axis, or - null for none - @param ySettings (string) the colour of the gridlines along the y-axis, or - (object) formatting for the gridlines along the y-axis, or - null for none - @return (SVGPlot) this plot object or - (object[2]) the gridlines formatting (if no parameters) */ + /** Set or retrieve the gridlines formatting for the plot area. + @param xSettings {string|object} The colour of the gridlines along the x-axis, + or formatting for the gridlines along the x-axis, or null for none. + @param ySettings {string|object} The colour of the gridlines along the y-axis, + or formatting for the gridlines along the y-axis, or null for none. + @return {SVGPlot|object[]} This plot object or the gridlines formatting (if no parameters). */ gridlines: function(xSettings, ySettings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._gridlines; } - this._gridlines = [(typeof xSettings == 'string' ? {stroke: xSettings} : xSettings), - (typeof ySettings == 'string' ? {stroke: ySettings} : ySettings)]; + this._gridlines = [(typeof xSettings === 'string' ? {stroke: xSettings} : xSettings), + (typeof ySettings === 'string' ? {stroke: ySettings} : ySettings)]; if (this._gridlines[0] == null && this._gridlines[1] == null) { this._gridlines = []; } @@ -117,94 +120,90 @@ $.extend(SVGPlot.prototype, { return this; }, - /* Set or retrieve the equality of the x- and y-axes. - @param value (boolean) true for equal x- and y-units, false to fill the available space - @return (SVGPlot) this plot object or - (boolean) the current setting (if no parameters) */ + /** Set or retrieve the equality of the x- and y-axes. + @param value {boolean} true for equal x- and y-units, + false to fill the available space. + @return {SVGPlot|boolean} This plot object or the current setting (if no parameters). */ equalXY: function(value) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._equalXY; } this._equalXY = value; return this; }, - /* Set or retrieve the title of the plot and its formatting. - @param value (string) the title - @param offset (number) the vertical positioning of the title - > 1 is pixels, <= 1 is proportion of width (optional) - @param colour (string) the colour of the title (optional) - @param settings (object) formatting for the title (optional) - @return (SVGPlot) this plot object or - (object) value, offset, and settings for the title (if no parameters) */ + /** Set or retrieve the title of the plot and its formatting. + @param value {string} The title. + @param [offset] {number} The vertical positioning of the title, > 1 is pixels, <= 1 is proportion of width. + @param [colour] {string} The colour of the title. + @param [settings] {object} Formatting for the title. + @return {SVGPlot|object} This plot object or value, offset, and settings for the title (if no parameters). */ title: function(value, offset, colour, settings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._title; } - if (typeof offset != 'number') { + if (typeof offset !== 'number') { settings = colour; colour = offset; offset = null; } - if (typeof colour != 'string') { + if (typeof colour !== 'string') { settings = colour; colour = null; } this._title = {value: value, offset: offset || this._title.offset, - settings: $.extend({textAnchor: 'middle'}, - (colour ? {fill: colour} : {}), settings || {})}; + settings: $.extend({textAnchor: 'middle'}, (colour ? {fill: colour} : {}), settings || {})}; this._drawPlot(); return this; }, - /* Add a function to be plotted on the plot. - @param name (string) the name of this series (optional) - @param fn (function) the function to be plotted - @param range (number[2]) the range of values to plot (optional) - @param points (number) the number of points to plot within this range (optional) - @param stroke (string) the colour of the plotted lines (optional) - @param strokeWidth (number) the width of the plotted lines (optional) - @param settings (object) additional settings for the plotted values (optional) - @return (SVGPlot) this plot object */ + /** Add a function to be plotted on the plot. + @param [name] {string} The name of this series. + @param fn {function} The function to be plotted. + @param [range] {number[]} The range of values to plot. + @param [points] {number} The number of points to plot within this range. + @param [stroke] {string} The colour of the plotted lines. + @param [strokeWidth] {number} The width of the plotted lines. + @param [settings] {object} Additional settings for the plotted values. + @return {SVGPlot} This plot object. */ addFunction: function(name, fn, range, points, stroke, strokeWidth, settings) { - this._functions.push(new SVGPlotFunction( - this, name, fn, range, points, stroke, strokeWidth, settings)); + this._functions.push(new SVGPlotFunction(this, name, fn, range, points, stroke, strokeWidth, settings)); this._drawPlot(); return this; }, - /* Retrieve the function wrappers. - @param i (number) the function index (optional) - @return (SVGPlotFunction) the specified function or - (SVGPlotFunction[]) the list of functions */ + /** Retrieve the function wrappers. + @param [i] {number} the function index. + @return {SVGPlotFunction|SVGPlotFunction[]} the specified function or the list of functions. */ functions: function(i) { return (arguments.length > 0 ? this._functions[i] : null) || this._functions; }, - /* Suppress drawing of the plot until redraw() is called. - @return (SVGPlot) this plot object */ + /** Suppress drawing of the plot until redraw() is called. + @return {SVGPlot} this plot object. */ noDraw: function() { this._drawNow = false; return this; }, - /* Redraw the entire plot with the current settings and values. - @return (SVGPlot) this plot object */ + /** Redraw the entire plot with the current settings and values. + @return {SVGPlot} This plot object. */ redraw: function() { this._drawNow = true; this._drawPlot(); return this; }, - /* Set the callback function for status updates. - @param onstatus (function) the callback function - @return (SVGPlot) this plot object */ + /** Set the callback function for status updates. + @param onstatus {function} The callback function. + @return {SVGPlot} This plot object. */ status: function(onstatus) { this._onstatus = onstatus; return this; }, - /* Actually draw the plot (if allowed). */ + /** Actually draw the plot (if allowed). + @private */ _drawPlot: function() { if (!this._drawNow) { return; @@ -218,25 +217,23 @@ $.extend(SVGPlot.prototype, { // Set sizes if not already there if (!this._plotCont.width) { this._plotCont.setAttribute('width', - parseInt(this._plotCont.getAttribute('width'), 10) || this._wrapper._width()); + parseInt(this._plotCont.getAttribute('width'), 10) || this._wrapper.width()); } else if (this._plotCont.width.baseVal) { - this._plotCont.width.baseVal.value = - this._plotCont.width.baseVal.value || this._wrapper._width(); + this._plotCont.width.baseVal.value = this._plotCont.width.baseVal.value || this._wrapper.width(); } else { - this._plotCont.width = this._plotCont.width || this._wrapper._width(); + this._plotCont.width = this._plotCont.width || this._wrapper.width(); } if (!this._plotCont.height) { this._plotCont.setAttribute('height', - parseInt(this._plotCont.getAttribute('height'), 10) || this._wrapper._height()); + parseInt(this._plotCont.getAttribute('height'), 10) || this._wrapper.height()); } else if (this._plotCont.height.baseVal) { - this._plotCont.height.baseVal.value = - this._plotCont.height.baseVal.value || this._wrapper._height(); + this._plotCont.height.baseVal.value = this._plotCont.height.baseVal.value || this._wrapper.height(); } else { - this._plotCont.height = this._plotCont.height || this._wrapper._height(); + this._plotCont.height = this._plotCont.height || this._wrapper.height(); } this._drawChartBackground(); var dims = this._getDims(); @@ -253,18 +250,20 @@ $.extend(SVGPlot.prototype, { this._drawLegend(); }, - /* Decode an attribute value. - @param node the node to examine - @param name the attribute name - @return the actual value */ + /** Decode an attribute value. + @private + @param node {SVGElement} The node to examine. + @param name {string} The attribute name. + @return {string} The actual value. */ _getValue: function(node, name) { return (!node[name] ? parseInt(node.getAttribute(name), 10) : (node[name].baseVal ? node[name].baseVal.value : node[name])); }, - /* Calculate the actual dimensions of the plot area. - @param area (number[4]) the area values to evaluate (optional) - @return (number[4]) an array of dimension values: left, top, width, height */ + /** Calculate the actual dimensions of the plot area. + @private + @param [area] {number[]} The area values to evaluate, or the current area if not specified. + @return {number[]} An array of dimension values: left, top, width, height. */ _getDims: function(area) { var otherArea = (area != null); area = area || this._area; @@ -283,18 +282,20 @@ $.extend(SVGPlot.prototype, { return [left, top, width, height]; }, - /* Calculate the scaling factors for the plot area. - @return (number[2]) the x- and y-scaling factors */ + /** Calculate the scaling factors for the plot area. + @private + @return {number[]} The x- and y-scaling factors. */ _getScales: function() { var dims = this._getDims(); return [dims[this.W] / (this.xAxis._scale.max - this.xAxis._scale.min), dims[this.H] / (this.yAxis._scale.max - this.yAxis._scale.min)]; }, - /* Draw the chart background, including gridlines. - @param noXGrid (boolean) true to suppress the x-gridlines, false to draw them (optional) - @param noYGrid (boolean) true to suppress the y-gridlines, false to draw them (optional) - @return (element) the background group element */ + /** Draw the chart background, including gridlines. + @private + @param [noXGrid] {boolean} true to suppress the x-gridlines, false to draw them. + @param [noYGrid] {boolean} true to suppress the y-gridlines, false to draw them. + @return {SVGElement} The background group element. */ _drawChartBackground: function(noXGrid, noYGrid) { var bg = this._wrapper.group(this._plotCont, {class_: 'background'}); var dims = this._getDims(); @@ -308,10 +309,11 @@ $.extend(SVGPlot.prototype, { return bg; }, - /* Draw one set of gridlines. - @param bg (element) the background group element - @param horiz (boolean) true if horizontal, false if vertical - @param format (object) additional settings for the gridlines */ + /** Draw one set of gridlines. + @private + @param bg {SVGElement} The background group element. + @param horiz {boolean} true if horizontal, false if vertical. + @param format {object} Additional settings for the gridlines. */ _drawGridlines: function(bg, horiz, format, dims) { var g = this._wrapper.group(bg, format); var axis = (horiz ? this.yAxis : this.xAxis); @@ -327,8 +329,9 @@ $.extend(SVGPlot.prototype, { } }, - /* Draw an axis, its tick marks, and title. - @param horiz (boolean) true for x-axis, false for y-axis */ + /** Draw an axis, its tick marks, and title. + @private + @param horiz {boolean} true for x-axis, false for y-axis. */ _drawAxis: function(horiz) { var id = (horiz ? 'x' : 'y') + 'Axis'; var axis = (horiz ? this.xAxis : this.yAxis); @@ -341,8 +344,7 @@ $.extend(SVGPlot.prototype, { var zero = (horiz ? axis2._scale.max : -axis2._scale.min) * scales[horiz ? 1 : 0] + (horiz ? dims[this.Y] : dims[this.X]); this._wrapper.line(gl, (horiz ? dims[this.X] : zero), (horiz ? zero : dims[this.Y]), - (horiz ? dims[this.X] + dims[this.W] : zero), - (horiz ? zero : dims[this.Y] + dims[this.H])); + (horiz ? dims[this.X] + dims[this.W] : zero), (horiz ? zero : dims[this.Y] + dims[this.H])); if (axis._ticks.major) { var size = axis._ticks.size; var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major; @@ -350,23 +352,20 @@ $.extend(SVGPlot.prototype, { var minor = (!axis._ticks.minor ? axis._scale.max + 1 : Math.floor(axis._scale.min / axis._ticks.minor) * axis._ticks.minor); minor = (minor < axis._scale.min ? minor + axis._ticks.minor : minor); - var offsets = [(axis._ticks.position == 'nw' || axis._ticks.position == 'both' ? -1 : 0), - (axis._ticks.position == 'se' || axis._ticks.position == 'both' ? +1 : 0)]; + var offsets = [(axis._ticks.position === 'nw' || axis._ticks.position === 'both' ? -1 : 0), + (axis._ticks.position === 'se' || axis._ticks.position === 'both' ? +1 : 0)]; while (major <= axis._scale.max || minor <= axis._scale.max) { var cur = Math.min(major, minor); - var len = (cur == major ? size : size / 2); + var len = (cur === major ? size : size / 2); var xy = (horiz ? cur - axis._scale.min : axis._scale.max - cur) * scales[horiz ? 0 : 1] + (horiz ? dims[this.X] : dims[this.Y]); - this._wrapper.line(gl, (horiz ? xy : zero + len * offsets[0]), - (horiz ? zero + len * offsets[0] : xy), - (horiz ? xy : zero + len * offsets[1]), - (horiz ? zero + len * offsets[1] : xy)); - if (cur == major && cur != 0) { - this._wrapper.text(gt, (horiz ? xy : zero - size), - (horiz ? zero - size : xy), '' + cur); + this._wrapper.line(gl, (horiz ? xy : zero + len * offsets[0]), (horiz ? zero + len * offsets[0] : xy), + (horiz ? xy : zero + len * offsets[1]), (horiz ? zero + len * offsets[1] : xy)); + if (cur === major && cur !== 0) { + this._wrapper.text(gt, (horiz ? xy : zero - size), (horiz ? zero - size : xy), '' + cur); } - major += (cur == major ? axis._ticks.major : 0); - minor += (cur == minor ? axis._ticks.minor : 0); + major += (cur === major ? axis._ticks.major : 0); + minor += (cur === minor ? axis._ticks.minor : 0); } } if (axis._title) { @@ -375,14 +374,16 @@ $.extend(SVGPlot.prototype, { zero, axis._title, $.extend({textAnchor: 'end'}, axis._titleFormat || {})); } else { - this._wrapper.text(this._plotCont, zero, - dims[this.Y] + dims[this.H] + axis._titleOffset, + this._wrapper.text(this._plotCont, zero, dims[this.Y] + dims[this.H] + axis._titleOffset, axis._title, $.extend({textAnchor : 'middle'}, axis._titleFormat || {})); } } }, - /* Plot an individual function. */ + /** Plot an individual function. + @private + @param fn {function} The function to plot. + @param cur {number} The current function index. */ _plotFunction: function(fn, cur) { var dims = this._getDims(); var scales = this._getScales(); @@ -403,27 +404,27 @@ $.extend(SVGPlot.prototype, { path[(first ? 'move' : 'line') + 'To'](px, py); first = false; } - var p = this._wrapper.path(this._plot, path, - $.extend({class_: 'fn' + cur, fill: 'none', stroke: fn._stroke, + var p = this._wrapper.path(this._plot, path, $.extend({class_: 'fn' + cur, fill: 'none', stroke: fn._stroke, strokeWidth: fn._strokeWidth}, fn._settings || {})); this._showStatus(p, fn._name); }, - /* Draw the plot title - centred. */ + /** Draw the plot title - centred + @private */ _drawTitle: function() { this._wrapper.text(this._plotCont, this._getValue(this._plotCont, 'width') / 2, this._title.offset, this._title.value, this._title.settings); }, - /* Draw the chart legend. */ + /** Draw the chart legend. + @private */ _drawLegend: function() { if (!this.legend._show) { return; } var g = this._wrapper.group(this._plotCont, {class_: 'legend'}); var dims = this._getDims(this.legend._area); - this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], - this.legend._bgSettings); + this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], this.legend._bgSettings); var horiz = dims[this.W] > dims[this.H]; var numFn = this._functions.length; var offset = (horiz ? dims[this.W] : dims[this.H]) / numFn; @@ -439,7 +440,10 @@ $.extend(SVGPlot.prototype, { } }, - /* Show the current value status on hover. */ + /** Show the current value status on hover. + @private + @param elem {SVGElement} The current plot element. + @param label {string} The current status label. */ _showStatus: function(elem, label) { var status = this._onstatus; if (this._onstatus) { @@ -449,18 +453,22 @@ $.extend(SVGPlot.prototype, { } }); -/* Details about each plot function. - @param plot (SVGPlot) the owning plot - @param name (string) the name of this function (optional) - @param fn (function) the function to be plotted - @param range (number[2]) the range of values to be plotted (optional) - @param points (number) the number of points to plot within this range (optional) - @param stroke (string) the colour of the (out)line for the plot (optional) - @param strokeWidth (number) the width of the (out)line for the plot (optional) - @param settings (object) additional formatting settings (optional) - @return (SVGPlotFunction) the new plot function object */ +/** A plot function definition. + @module SVGPlotFunction */ + +/** Details about each plot function. +

Created through plot.addFunction().

+ @param plot {SVGPlot} The owning plot. + @param [name] {string} The name of this function. + @param fn {function} The function to be plotted. + @param [range] {number[]} The range of values to be plotted. + @param [points] {number} The number of points to plot within this range. + @param [stroke] {string} The colour of the (out)line for the plot. + @param [strokeWidth] {number} The width of the (out)line for the plot. + @param [settings] {object} Additional settings for the plotted values. + @return {SVGPlotFunction} The new plot function object. */ function SVGPlotFunction(plot, name, fn, range, points, stroke, strokeWidth, settings) { - if (typeof name != 'string') { + if (typeof name !== 'string') { settings = strokeWidth; strokeWidth = stroke; stroke = points; @@ -469,25 +477,25 @@ function SVGPlotFunction(plot, name, fn, range, points, stroke, strokeWidth, set fn = name; name = null; } - if (!isArray(range)) { + if (!$.isArray(range)) { settings = strokeWidth; strokeWidth = stroke; stroke = points; points = range; range = null; } - if (typeof points != 'number') { + if (typeof points !== 'number') { settings = strokeWidth; strokeWidth = stroke; stroke = points; points = null; } - if (typeof stroke != 'string') { + if (typeof stroke !== 'string') { settings = strokeWidth; strokeWidth = stroke; stroke = null; } - if (typeof strokeWidth != 'number') { + if (typeof strokeWidth !== 'number') { settings = strokeWidth; strokeWidth = null; } @@ -503,12 +511,11 @@ function SVGPlotFunction(plot, name, fn, range, points, stroke, strokeWidth, set $.extend(SVGPlotFunction.prototype, { - /* Set or retrieve the name for this function. - @param name (string) the function's name - @return (SVGPlotFunction) this plot function object or - (string) the function name (if no parameters) */ + /** Set or retrieve the name for this function. + @param name {string} The function's name. + @return {SVGPlotFunction|string} This plot function object or the function name (if no parameters). */ name: function(name) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._name; } this._name = name; @@ -516,16 +523,15 @@ $.extend(SVGPlotFunction.prototype, { return this; }, - /* Set or retrieve the function to be plotted. - @param name (string) the function's name (optional) - @param fn (function) the function to be ploted - @return (SVGPlotFunction) this plot function object or - (function) the actual function (if no parameters) */ + /** Set or retrieve the function to be plotted. + @param [name] {string} The function's name. + @param fn {function} The function to be ploted. + @return {SVGPlotFunction|function} This plot function object or the actual function (if no parameters). */ fn: function(name, fn) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._fn; } - if (typeof name == 'function') { + if (typeof name === 'function') { fn = name; name = null; } @@ -535,13 +541,12 @@ $.extend(SVGPlotFunction.prototype, { return this; }, - /* Set or retrieve the range of values to be plotted. - @param min (number) the minimum value to be plotted - @param max (number) the maximum value to be plotted - @return (SVGPlotFunction) this plot function object or - (number[2]) the value range (if no parameters) */ + /** Set or retrieve the range of values to be plotted. + @param min {number} The minimum value to be plotted. + @param max {number} The maximum value to be plotted. + @return {SVGPlotFunction|number[]} This plot function object or the value range (if no parameters). */ range: function(min, max) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._range; } this._range = (min == null ? null : [min, max]); @@ -549,12 +554,11 @@ $.extend(SVGPlotFunction.prototype, { return this; }, - /* Set or retrieve the number of points to be plotted. - @param value (number) the number of points to plot - @return (SVGPlotFunction) this plot function object or - (number) the number of points (if no parameters) */ + /** Set or retrieve the number of points to be plotted. + @param value {number} The number of points to plot. + @return {SVGPlotFunction|number} This plot function object or the number of points (if no parameters). */ points: function(value) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._points; } this._points = value; @@ -562,18 +566,16 @@ $.extend(SVGPlotFunction.prototype, { return this; }, - /* Set or retrieve the formatting for this function. - @param stroke (string) the (out)line colour - @param strokeWidth (number) the line's width (optional) - @param settings (object) additional formatting settings for the function (optional) - @return (SVGPlotFunction) this plot function object or - (object) formatting settings (if no parameters) */ + /** Set or retrieve the formatting for this function. + @param stroke {string} The (out)line colour. + @param [strokeWidth] {number} The line's width. + @param [settings] {object} Additional formatting settings for the function. + @return {SVGPlotFunction|object} This plot function object or formatting settings (if no parameters). */ format: function(stroke, strokeWidth, settings) { - if (arguments.length == 0) { - return $.extend({stroke: this._stroke, - strokeWidth: this._strokeWidth}, this._settings); + if (arguments.length === 0) { + return $.extend({stroke: this._stroke, strokeWidth: this._strokeWidth}, this._settings); } - if (typeof strokeWidth != 'number') { + if (typeof strokeWidth !== 'number') { settings = strokeWidth; strokeWidth = null; } @@ -584,7 +586,8 @@ $.extend(SVGPlotFunction.prototype, { return this; }, - /* Return to the parent plot. */ + /** Return to the parent plot. + @return {SVGPlot} The parent plot. */ end: function() { return this._plot; } @@ -597,14 +600,18 @@ function identity(x) { return x; } -/* Details about each plot axis. - @param plot (SVGPlot) the owning plot - @param title (string) the title of the axis - @param min (number) the minimum value displayed on this axis - @param max (number) the maximum value displayed on this axis - @param major (number) the distance between major ticks - @param minor (number) the distance between minor ticks (optional) - @return (SVGPlotAxis) the new axis object */ +/** A plot axis definition. + @module SVGPlotAxis */ + +/** Details about each plot axis. +

Accessed through plot.xAxis or plot.yAxis.

+ @param plot {SVGPlot} The owning plot. + @param title {string} The title of the axis. + @param min {number} The minimum value displayed on this axis. + @param max {number} The maximum value displayed on this axis. + @param major {number} The distance between major ticks. + @param [minor] {number} The distance between minor ticks. + @return {SVGPlotAxis} The new plot axis object. */ function SVGPlotAxis(plot, title, min, max, major, minor) { this._plot = plot; // The owning plot this._title = title || ''; // The plot's title @@ -619,13 +626,12 @@ function SVGPlotAxis(plot, title, min, max, major, minor) { $.extend(SVGPlotAxis.prototype, { - /* Set or retrieve the scale for this axis. - @param min (number) the minimum value shown - @param max (number) the maximum value shown - @return (SVGPlotAxis) this axis object or - (object) min and max values (if no parameters) */ + /** Set or retrieve the scale for this axis. + @param min {number} The minimum value shown. + @param max {number} The maximum value shown. + @return {SVGPlotAxis|object} This axis object or min and max values (if no parameters). */ scale: function(min, max) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._scale; } this._scale.min = min; @@ -634,19 +640,17 @@ $.extend(SVGPlotAxis.prototype, { return this; }, - /* Set or retrieve the ticks for this axis. - @param major (number) the distance between major ticks - @param minor (number) the distance between minor ticks - @param size (number) the length of the major ticks (minor are half) (optional) - @param position (string) the location of the ticks: - 'nw', 'se', 'both' (optional) - @return (SVGPlotAxis) this axis object or - (object) major, minor, size, and position values (if no parameters) */ + /** Set or retrieve the ticks for this axis. + @param major {number} The distance between major ticks. + @param minor {number} The distance between minor ticks. + @param [size] {number} The length of the major ticks (minor are half). + @param [position] {string} The location of the ticks: 'nw', 'se', 'both'. + @return {SVGPlotAxis|object} This axis object or major, minor, size, and position values (if no parameters). */ ticks: function(major, minor, size, position) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._ticks; } - if (typeof size == 'string') { + if (typeof size === 'string') { position = size; size = null; } @@ -658,23 +662,22 @@ $.extend(SVGPlotAxis.prototype, { return this; }, - /* Set or retrieve the title for this axis. - @param title (string) the title text - @param offset (number) the distance to offset the title position (optional) - @param colour (string) how to colour the title (optional) - @param format (object) formatting settings for the title (optional) - @return (SVGPlotAxis) this axis object or - (object) title, offset, and format values (if no parameters) */ + /** Set or retrieve the title for this axis. + @param title {string} The title text + @param [offset] {number} The distance to offset the title position. + @param [colour] {string} How to colour the title. + @param [format] {object} Formatting settings for the title. + @return {SVGPlotAxis|object} This axis object or title, offset, and format values (if no parameters). */ title: function(title, offset, colour, format) { - if (arguments.length == 0) { + if (arguments.length === 0) { return {title: this._title, offset: this._titleOffset, format: this._titleFormat}; } - if (typeof offset != 'number') { + if (typeof offset !== 'number') { format = colour; colour = offset; offset = null; } - if (typeof colour != 'string') { + if (typeof colour !== 'string') { format = colour; colour = null; } @@ -687,16 +690,15 @@ $.extend(SVGPlotAxis.prototype, { return this; }, - /* Set or retrieve the label format for this axis. - @param colour (string) how to colour the labels (optional) - @param format (object) formatting settings for the labels (optional) - @return (SVGPlotAxis) this axis object or - (object) format values (if no parameters) */ + /** Set or retrieve the label format for this axis. + @param [colour] {string} How to colour the labels. + @param [format] {object} Formatting settings for the labels. + @return {SVGPlotAxis|object} This axis object or format values (if no parameters). */ format: function(colour, format) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._labelFormat; } - if (typeof colour != 'string') { + if (typeof colour !== 'string') { format = colour; colour = null; } @@ -705,37 +707,40 @@ $.extend(SVGPlotAxis.prototype, { return this; }, - /* Set or retrieve the line formatting for this axis. - @param colour (string) the line's colour - @param width (number) the line's width (optional) - @param settings (object) additional formatting settings for the line (optional) - @return (SVGPlotAxis) this axis object or - (object) line formatting values (if no parameters) */ + /** Set or retrieve the line formatting for this axis. + @param colour {string} The line's colour. + @param [width] {number} The line's width. + @param [settings] {object} Additional formatting settings for the line. + @return {SVGPlotAxis|object} This axis object or line formatting values (if no parameters). */ line: function(colour, width, settings) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._lineFormat; } - if (typeof width != 'number') { + if (typeof width !== 'number') { settings = width; width = null; } - $.extend(this._lineFormat, {stroke: colour, strokeWidth: - width || this._lineFormat.strokeWidth}, settings || {}); + $.extend(this._lineFormat, {stroke: colour, strokeWidth: width || this._lineFormat.strokeWidth}, settings || {}); this._plot._drawPlot(); return this; }, - /* Return to the parent plot. */ + /** Return to the parent plot. + @return {SVGPlot} The parent plot. */ end: function() { return this._plot; } }); -/* Details about the plot legend. - @param plot (SVGPlot) the owning plot - @param bgSettings (object) additional formatting settings for the legend background (optional) - @param textSettings (object) additional formatting settings for the legend text (optional) - @return (SVGPlotLegend) the new legend object */ +/** A plot legend definition. + @module SVGPlotLegend */ + +/** Details about each plot legend. +

Accessed through plot.legend.

+ @param plot {SVGPlot} The owning plot. + @param [bgSettings] {object} Additional formatting settings for the legend background. + @param [textSettings] {object} Additional formatting settings for the legend text. + @return {SVGPlotLegend} The new plot legend object. */ function SVGPlotLegend(plot, bgSettings, textSettings) { this._plot = plot; // The owning plot this._show = true; // Show the legend? @@ -748,12 +753,11 @@ function SVGPlotLegend(plot, bgSettings, textSettings) { $.extend(SVGPlotLegend.prototype, { - /* Set or retrieve whether the legend should be shown. - @param show (boolean) true to display it, false to hide it - @return (SVGPlotLegend) this legend object or - (boolean) show the legend? (if no parameters) */ + /** Set or retrieve whether the legend should be shown. + @param show {boolean} true to display it, false to hide it. + @return {SVGPlotLegend|boolean} This legend object or show the legend? (if no parameters) */ show: function(show) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._show; } this._show = show; @@ -761,35 +765,33 @@ $.extend(SVGPlotLegend.prototype, { return this; }, - /* Set or retrieve the legend area. - @param left (number) > 1 is pixels, <= 1 is proportion of width or - (number[4]) for left, top, right, bottom - @param top (number) > 1 is pixels, <= 1 is proportion of height - @param right (number) > 1 is pixels, <= 1 is proportion of width - @param bottom (number) > 1 is pixels, <= 1 is proportion of height - @return (SVGPlotLegend) this legend object or - (number[4]) the legend area: left, top, right, bottom (if no parameters) */ + /** Set or retrieve the legend area. + @param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom. + @param [top] {number} > 1 is pixels, <= 1 is proportion of height. + @param [right] {number} > 1 is pixels, <= 1 is proportion of width. + @param [bottom] {number} > 1 is pixels, <= 1 is proportion of height. + @return {SVGPlotLegend|number[]} This legend object or the legend area: + left, top, right, bottom (if no parameters). */ area: function(left, top, right, bottom) { - if (arguments.length == 0) { + if (arguments.length === 0) { return this._area; } - this._area = (isArray(left) ? left : [left, top, right, bottom]); + this._area = ($.isArray(left) ? left : [left, top, right, bottom]); this._plot._drawPlot(); return this; }, - /* Set or retrieve additional settings for the legend area. - @param sampleSize (number) the size of the sample box to display (optional) - @param bgSettings (object) additional formatting settings for the legend background - @param textSettings (object) additional formatting settings for the legend text (optional) - @return (SVGPlotLegend) this legend object or - (object) bgSettings and textSettings for the legend (if no parameters) */ + /** Set or retrieve additional settings for the legend area. + @param [sampleSize] {number} The size of the sample box to display. + @param bgSettings {object} Additional formatting settings for the legend background. + @param [textSettings] {object} Additional formatting settings for the legend text. + @return {SVGPlotLegend|object} This legend object or + bgSettings and textSettings for the legend (if no parameters). */ settings: function(sampleSize, bgSettings, textSettings) { - if (arguments.length == 0) { - return {sampleSize: this._sampleSize, bgSettings: this._bgSettings, - textSettings: this._textSettings}; + if (arguments.length === 0) { + return {sampleSize: this._sampleSize, bgSettings: this._bgSettings, textSettings: this._textSettings}; } - if (typeof sampleSize == 'object') { + if (typeof sampleSize === 'object') { textSettings = bgSettings; bgSettings = sampleSize; sampleSize = null; @@ -801,17 +803,11 @@ $.extend(SVGPlotLegend.prototype, { return this; }, - /* Return to the parent plot. */ + /** Return to the parent plot. + @return {SVGPlot} The parent plot. */ end: function() { return this._plot; } }); -//============================================================================== - -/* Determine whether an object is an array. */ -function isArray(a) { - return (a && a.constructor == Array); -} - })(jQuery) diff --git a/jquery.svgplot.min.js b/jquery.svgplot.min.js index 78d9f39..dc47017 100644 --- a/jquery.svgplot.min.js +++ b/jquery.svgplot.min.js @@ -1,7 +1,6 @@ -/* http://keith-wood.name/svg.html - SVG plotting extension for jQuery v1.4.5. +/* http://keith-wood.name/svg.html + SVG plotting extension for jQuery v1.5.0. 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. + Available under the MIT (http://keith-wood.name/licence.html) license. Please attribute the author if you use it. */ -(function($){$.svg.addExtension('plot',SVGPlot);function SVGPlot(a){this._wrapper=a;this._drawNow=false;this._title={value:'',offset:25,settings:{textAnchor:'middle'}};this._area=[0.1,0.1,0.8,0.9];this._areaFormat={fill:'none',stroke:'black'};this._gridlines=[];this._equalXY=true;this._functions=[];this._onstatus=null;this._uuid=new Date().getTime();this._plotCont=this._wrapper.svg(0,0,0,0,{class_:'svg-plot'});this.xAxis=new SVGPlotAxis(this);this.xAxis.title('X',20);this.yAxis=new SVGPlotAxis(this);this.yAxis.title('Y',20);this.legend=new SVGPlotLegend(this);this._drawNow=true}$.extend(SVGPlot.prototype,{X:0,Y:1,W:2,H:3,L:0,T:1,R:2,B:3,container:function(a){if(arguments.length==0){return this._plotCont}this._plotCont=a;return this},area:function(a,b,c,d){if(arguments.length==0){return this._area}this._area=(isArray(a)?a:[a,b,c,d]);this._drawPlot();return this},format:function(a,b,c){if(arguments.length==0){return this._areaFormat}if(typeof b=='object'){c=b;b=null}this._areaFormat=$.extend({fill:a},(b?{stroke:b}:{}),c||{});this._drawPlot();return this},gridlines:function(a,b){if(arguments.length==0){return this._gridlines}this._gridlines=[(typeof a=='string'?{stroke:a}:a),(typeof b=='string'?{stroke:b}:b)];if(this._gridlines[0]==null&&this._gridlines[1]==null){this._gridlines=[]}this._drawPlot();return this},equalXY:function(a){if(arguments.length==0){return this._equalXY}this._equalXY=a;return this},title:function(a,b,c,d){if(arguments.length==0){return this._title}if(typeof b!='number'){d=c;c=b;b=null}if(typeof c!='string'){d=c;c=null}this._title={value:a,offset:b||this._title.offset,settings:$.extend({textAnchor:'middle'},(c?{fill:c}:{}),d||{})};this._drawPlot();return this},addFunction:function(a,b,c,d,e,f,g){this._functions.push(new SVGPlotFunction(this,a,b,c,d,e,f,g));this._drawPlot();return this},functions:function(i){return(arguments.length>0?this._functions[i]:null)||this._functions},noDraw:function(){this._drawNow=false;return this},redraw:function(){this._drawNow=true;this._drawPlot();return this},status:function(a){this._onstatus=a;return this},_drawPlot:function(){if(!this._drawNow){return}while(this._plotCont.firstChild){this._plotCont.removeChild(this._plotCont.firstChild)}if(!this._plotCont.parent){this._wrapper._svg.appendChild(this._plotCont)}if(!this._plotCont.width){this._plotCont.setAttribute('width',parseInt(this._plotCont.getAttribute('width'),10)||this._wrapper._width())}else if(this._plotCont.width.baseVal){this._plotCont.width.baseVal.value=this._plotCont.width.baseVal.value||this._wrapper._width()}else{this._plotCont.width=this._plotCont.width||this._wrapper._width()}if(!this._plotCont.height){this._plotCont.setAttribute('height',parseInt(this._plotCont.getAttribute('height'),10)||this._wrapper._height())}else if(this._plotCont.height.baseVal){this._plotCont.height.baseVal.value=this._plotCont.height.baseVal.value||this._wrapper._height()}else{this._plotCont.height=this._plotCont.height||this._wrapper._height()}this._drawChartBackground();var a=this._getDims();var b=this._wrapper.other(this._plotCont,'clipPath',{id:'clip'+this._uuid});this._wrapper.rect(b,a[this.X],a[this.Y],a[this.W],a[this.H]);this._plot=this._wrapper.group(this._plotCont,{class_:'foreground',clipPath:'url(#clip'+this._uuid+')'});this._drawAxis(true);this._drawAxis(false);for(var i=0;i1?a[this.L]:c*a[this.L]);var f=(a[this.T]>1?a[this.T]:d*a[this.T]);var g=(a[this.R]>1?a[this.R]:c*a[this.R])-e;var h=(a[this.B]>1?a[this.B]:d*a[this.B])-f;if(this._equalXY&&!b){var i=Math.min(g/(this.xAxis._scale.max-this.xAxis._scale.min),h/(this.yAxis._scale.max-this.yAxis._scale.min));g=i*(this.xAxis._scale.max-this.xAxis._scale.min);h=i*(this.yAxis._scale.max-this.yAxis._scale.min)}return[e,f,g,h]},_getScales:function(){var a=this._getDims();return[a[this.W]/(this.xAxis._scale.max-this.xAxis._scale.min),a[this.H]/(this.yAxis._scale.max-this.yAxis._scale.min)]},_drawChartBackground:function(a,b){var c=this._wrapper.group(this._plotCont,{class_:'background'});var d=this._getDims();this._wrapper.rect(c,d[this.X],d[this.Y],d[this.W],d[this.H],this._areaFormat);if(this._gridlines[0]&&this.yAxis._ticks.major&&!b){this._drawGridlines(c,true,this._gridlines[0],d)}if(this._gridlines[1]&&this.xAxis._ticks.major&&!a){this._drawGridlines(c,false,this._gridlines[1],d)}return c},_drawGridlines:function(a,b,c,d){var g=this._wrapper.group(a,c);var e=(b?this.yAxis:this.xAxis);var f=this._getScales();var h=Math.floor(e._scale.min/e._ticks.major)*e._ticks.major;h+=(h<=e._scale.min?e._ticks.major:0);while(hthis.xAxis._scale.max+g){break}if(xa[this.H];var c=this._functions.length;var d=(b?a[this.W]:a[this.H])/c;var e=a[this.X]+5;var f=a[this.Y]+((b?a[this.H]:d)+this.legend._sampleSize)/2;for(var i=0;i0?this._functions[i]:null)||this._functions},noDraw:function(){this._drawNow=false;return this},redraw:function(){this._drawNow=true;this._drawPlot();return this},status:function(a){this._onstatus=a;return this},_drawPlot:function(){if(!this._drawNow){return}while(this._plotCont.firstChild){this._plotCont.removeChild(this._plotCont.firstChild)}if(!this._plotCont.parent){this._wrapper._svg.appendChild(this._plotCont)}if(!this._plotCont.width){this._plotCont.setAttribute('width',parseInt(this._plotCont.getAttribute('width'),10)||this._wrapper.width())}else if(this._plotCont.width.baseVal){this._plotCont.width.baseVal.value=this._plotCont.width.baseVal.value||this._wrapper.width()}else{this._plotCont.width=this._plotCont.width||this._wrapper.width()}if(!this._plotCont.height){this._plotCont.setAttribute('height',parseInt(this._plotCont.getAttribute('height'),10)||this._wrapper.height())}else if(this._plotCont.height.baseVal){this._plotCont.height.baseVal.value=this._plotCont.height.baseVal.value||this._wrapper.height()}else{this._plotCont.height=this._plotCont.height||this._wrapper.height()}this._drawChartBackground();var a=this._getDims();var b=this._wrapper.other(this._plotCont,'clipPath',{id:'clip'+this._uuid});this._wrapper.rect(b,a[this.X],a[this.Y],a[this.W],a[this.H]);this._plot=this._wrapper.group(this._plotCont,{class_:'foreground',clipPath:'url(#clip'+this._uuid+')'});this._drawAxis(true);this._drawAxis(false);for(var i=0;i1?a[this.L]:c*a[this.L]);var f=(a[this.T]>1?a[this.T]:d*a[this.T]);var g=(a[this.R]>1?a[this.R]:c*a[this.R])-e;var h=(a[this.B]>1?a[this.B]:d*a[this.B])-f;if(this._equalXY&&!b){var i=Math.min(g/(this.xAxis._scale.max-this.xAxis._scale.min),h/(this.yAxis._scale.max-this.yAxis._scale.min));g=i*(this.xAxis._scale.max-this.xAxis._scale.min);h=i*(this.yAxis._scale.max-this.yAxis._scale.min)}return[e,f,g,h]},_getScales:function(){var a=this._getDims();return[a[this.W]/(this.xAxis._scale.max-this.xAxis._scale.min),a[this.H]/(this.yAxis._scale.max-this.yAxis._scale.min)]},_drawChartBackground:function(a,b){var c=this._wrapper.group(this._plotCont,{class_:'background'});var d=this._getDims();this._wrapper.rect(c,d[this.X],d[this.Y],d[this.W],d[this.H],this._areaFormat);if(this._gridlines[0]&&this.yAxis._ticks.major&&!b){this._drawGridlines(c,true,this._gridlines[0],d)}if(this._gridlines[1]&&this.xAxis._ticks.major&&!a){this._drawGridlines(c,false,this._gridlines[1],d)}return c},_drawGridlines:function(a,b,c,d){var g=this._wrapper.group(a,c);var e=(b?this.yAxis:this.xAxis);var f=this._getScales();var h=Math.floor(e._scale.min/e._ticks.major)*e._ticks.major;h+=(h<=e._scale.min?e._ticks.major:0);while(hthis.xAxis._scale.max+g){break}if(xa[this.H];var c=this._functions.length;var d=(b?a[this.W]:a[this.H])/c;var e=a[this.X]+5;var f=a[this.Y]+((b?a[this.H]:d)+this.legend._sampleSize)/2;for(var i=0;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(r($){$.1S.2r(\'2a\',1T);r 1T(a){4.u=a;4.1i=1j;4.M={11:\'\',1k:25,1z:{1l:\'1A\'}};4.12=[0.1,0.1,0.8,0.9];4.1B={17:\'2b\',U:\'1U\'};4.Q=[];4.1C=18;4.13=[];4.1D=z;4.1V=1m 2s().2t();4.t=4.u.1S(0,0,0,0,{19:\'1S-2a\'});4.G=1m 1E(4);4.G.1n(\'X\',20);4.N=1m 1E(4);4.N.1n(\'Y\',20);4.P=1m 1W(4);4.1i=18}$.K(1T.1F,{X:0,Y:1,W:2,H:3,L:0,T:1,R:2,B:3,2u:r(a){7(E.D==0){q 4.t}4.t=a;q 4},2c:r(a,b,c,d){7(E.D==0){q 4.12}4.12=(1G(a)?a:[a,b,c,d]);4.F();q 4},1H:r(a,b,c){7(E.D==0){q 4.1B}7(I b==\'2d\'){c=b;b=z}4.1B=$.K({17:a},(b?{U:b}:{}),c||{});4.F();q 4},2v:r(a,b){7(E.D==0){q 4.Q}4.Q=[(I a==\'14\'?{U:a}:a),(I b==\'14\'?{U:b}:b)];7(4.Q[0]==z&&4.Q[1]==z){4.Q=[]}4.F();q 4},2w:r(a){7(E.D==0){q 4.1C}4.1C=a;q 4},1n:r(a,b,c,d){7(E.D==0){q 4.M}7(I b!=\'1e\'){d=c;c=b;b=z}7(I c!=\'14\'){d=c;c=z}4.M={11:a,1k:b||4.M.1k,1z:$.K({1l:\'1A\'},(c?{17:c}:{}),d||{})};4.F();q 4},2x:r(a,b,c,d,e,f,g){4.13.2y(1m 1X(4,a,b,c,d,e,f,g));4.F();q 4},2z:r(i){q(E.D>0?4.13[i]:z)||4.13},2A:r(){4.1i=1j;q 4},2B:r(){4.1i=18;4.F();q 4},2C:r(a){4.1D=a;q 4},F:r(){7(!4.1i){q}1Y(4.t.2e){4.t.2D(4.t.2e)}7(!4.t.2E){4.u.2F.2G(4.t)}7(!4.t.S){4.t.2f(\'S\',1Z(4.t.21(\'S\'),10)||4.u.22())}1o 7(4.t.S.16){4.t.S.16.11=4.t.S.16.11||4.u.22()}1o{4.t.S=4.t.S||4.u.22()}7(!4.t.V){4.t.2f(\'V\',1Z(4.t.21(\'V\'),10)||4.u.23())}1o 7(4.t.V.16){4.t.V.16.11=4.t.V.16.11||4.u.23()}1o{4.t.V=4.t.V||4.u.23()}4.2g();6 a=4.1a();6 b=4.u.2H(4.t,\'2h\',{2I:\'2i\'+4.1V});4.u.1I(b,a[4.X],a[4.Y],a[4.W],a[4.H]);4.A=4.u.1f(4.t,{19:\'2J\',2h:\'2K(#2i\'+4.1V+\')\'});4.24(18);4.24(1j);26(6 i=0;i<4.13.D;i++){4.2j(4.13[i],i)}4.2k();4.2l()},1J:r(a,b){q(!a[b]?1Z(a.21(b),10):(a[b].16?a[b].16.11:a[b]))},1a:r(a){6 b=(a!=z);a=a||4.12;6 c=4.1J(4.t,\'S\');6 d=4.1J(4.t,\'V\');6 e=(a[4.L]>1?a[4.L]:c*a[4.L]);6 f=(a[4.T]>1?a[4.T]:d*a[4.T]);6 g=(a[4.R]>1?a[4.R]:c*a[4.R])-e;6 h=(a[4.B]>1?a[4.B]:d*a[4.B])-f;7(4.1C&&!b){6 i=1p.C(g/(4.G.s.J-4.G.s.C),h/(4.N.s.J-4.N.s.C));g=i*(4.G.s.J-4.G.s.C);h=i*(4.N.s.J-4.N.s.C)}q[e,f,g,h]},1K:r(){6 a=4.1a();q[a[4.W]/(4.G.s.J-4.G.s.C),a[4.H]/(4.N.s.J-4.N.s.C)]},2g:r(a,b){6 c=4.u.1f(4.t,{19:\'2L\'});6 d=4.1a();4.u.1I(c,d[4.X],d[4.Y],d[4.W],d[4.H],4.1B);7(4.Q[0]&&4.N.w.O&&!b){4.27(c,18,4.Q[0],d)}7(4.Q[1]&&4.G.w.O&&!a){4.27(c,1j,4.Q[1],d)}q c},27:r(a,b,c,d){6 g=4.u.1f(a,c);6 e=(b?4.N:4.G);6 f=4.1K();6 h=1p.28(e.s.C/e.w.O)*e.w.O;h+=(h<=e.s.C?e.w.O:0);1Y(h4.G.s.J+g){2R}7(x<4.G.s.C-g){2S}6 j=(x-4.G.s.C)*d[0]+c[4.X];6 k=c[4.H]-((a.1O(x)-4.N.s.C)*d[1])+c[4.Y];e[(h?\'2T\':\'1q\')+\'2U\'](j,k);h=1j}6 p=4.u.2V(4.A,e,$.K({19:\'2m\'+b,17:\'2b\',U:a.1h,1w:a.1x},a.1P||{}));4.2n(p,a.1d)},2k:r(){4.u.1t(4.t,4.1J(4.t,\'S\')/2,4.M.1k,4.M.11,4.M.1z)},2l:r(){7(!4.P.1Q){q}6 g=4.u.1f(4.t,{19:\'P\'});6 a=4.1a(4.P.12);4.u.1I(g,a[4.X],a[4.Y],a[4.W],a[4.H],4.P.1R);6 b=a[4.W]>a[4.H];6 c=4.13.D;6 d=(b?a[4.W]:a[4.H])/c;6 e=a[4.X]+5;6 f=a[4.Y]+((b?a[4.H]:d)+4.P.Z)/2;26(6 i=0;i=1.7" + } +} \ No newline at end of file diff --git a/svgBasic.html b/svgBasic.html index e57edca..9f5e866 100644 --- a/svgBasic.html +++ b/svgBasic.html @@ -1,16 +1,15 @@ - + jQuery SVG Basics - - - - + +