jquery-svg-rails 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/CODE_OF_CONDUCT.md +28 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +55 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/jquery-svg-rails.gemspec +26 -0
- data/lib/jquery/svg/rails.rb +9 -0
- data/lib/jquery/svg/rails/engine.rb +8 -0
- data/lib/jquery/svg/rails/version.rb +7 -0
- data/vendor/assets/javascripts/jquery.svg.js +1352 -0
- data/vendor/assets/javascripts/jquery.svg.min.js +6 -0
- data/vendor/assets/javascripts/jquery.svganim.js +471 -0
- data/vendor/assets/javascripts/jquery.svganim.min.js +6 -0
- data/vendor/assets/javascripts/jquery.svgdom.js +239 -0
- data/vendor/assets/javascripts/jquery.svgdom.min.js +6 -0
- data/vendor/assets/javascripts/jquery.svgfilter.js +368 -0
- data/vendor/assets/javascripts/jquery.svgfilter.min.js +6 -0
- data/vendor/assets/javascripts/jquery.svggraph.js +1539 -0
- data/vendor/assets/javascripts/jquery.svggraph.min.js +6 -0
- data/vendor/assets/javascripts/jquery.svgplot.js +813 -0
- data/vendor/assets/javascripts/jquery.svgplot.min.js +6 -0
- data/vendor/assets/stylesheets/jquery.svg.css +10 -0
- metadata +134 -0
@@ -0,0 +1,6 @@
|
|
1
|
+
/* http://keith-wood.name/svg.html
|
2
|
+
SVG filters for jQuery v1.5.0.
|
3
|
+
Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
|
4
|
+
Available under the MIT (http://keith-wood.name/licence.html) license.
|
5
|
+
Please attribute the author if you use it. */
|
6
|
+
(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;i<g.values.length;i++){h+=(i===0?'':' ')+g.values[i].join(' ')}g.values=h}else if(typeof g.values==='object'){g.settings=g.values;g.values=null}var j=$.extend({result:g.result,in_:g.in1,type:g.type},(g.values!=null?{values:g.values}:{}));return this._wrapper._makeNode(g.parent,'feColorMatrix',$.extend(j,g.settings||{}))},componentTransfer:function(a,b,c,d){var e=this._wrapper._args(arguments,['result','functions']);var f=this._wrapper._makeNode(e.parent,'feComponentTransfer',$.extend({result:e.result},e.settings||{}));var g=['R','G','B','A'];for(var i=0;i<Math.min(4,e.functions.length);i++){var h=e.functions[i];var j=$.extend({type:h[0]},(h[0]==='table'||h[0]==='discrete'?{tableValues:h[1].join(' ')}:(h[0]==='linear'?{slope:h[1],intercept:h[2]}:(h[0]==='gamma'?{amplitude:h[1],exponent:h[2],offset:h[3]}:{}))));this._wrapper._makeNode(f,'feFunc'+g[i],j)}return f},composite:function(a,b,c,d,e,f,g,h,i,j){var k=this._wrapper._args(arguments,['result','operator','in1','in2','k1','k2','k3','k4'],['k1']);var l=$.extend({result:k.result,operator:k.operator,'in':k.in1,in2:k.in2},(k.k1!=null?{k1:k.k1,k2:k.k2,k3:k.k3,k4:k.k4}:{}));return this._wrapper._makeNode(k.parent,'feComposite',$.extend(l,k.settings||{}))},convolveMatrix:function(a,b,c,d,e){var f=this._wrapper._args(arguments,['result','order','matrix']);var g='';for(var i=0;i<f.matrix.length;i++){g+=(i===0?'':' ')+f.matrix[i].join(' ')}f.matrix=g;return this._wrapper._makeNode(f.parent,'feConvolveMatrix',$.extend({result:f.result,order:f.order,kernelMatrix:f.matrix},f.settings||{}))},diffuseLighting:function(a,b,c,d){var e=this._wrapper._args(arguments,['result','colour'],['colour']);return this._wrapper._makeNode(e.parent,'feDiffuseLighting',$.extend($.extend({result:e.result},(e.colour?{lightingColor:e.colour}:{})),e.settings||{}))},displacementMap:function(a,b,c,d,e){var f=this._wrapper._args(arguments,['result','in1','in2']);return this._wrapper._makeNode(f.parent,'feDisplacementMap',$.extend({result:f.result,in_:f.in1,in2:f.in2},f.settings||{}))},flood:function(a,b,x,y,c,d,e,f,g){var h=this._wrapper._args(arguments,['result','x','y','width','height','colour','opacity']);if(arguments.length<6){h.colour=h.x;h.opacity=h.y;h.settings=h.width;h.x=null}var i=$.extend({result:h.result,floodColor:h.colour,floodOpacity:h.opacity},(h.x!=null?{x:h.x,y:h.y,width:h.width,height:h.height}:{}));return this._wrapper._makeNode(h.parent,'feFlood',$.extend(i,h.settings||{}))},gaussianBlur:function(a,b,c,d,e,f){var g=this._wrapper._args(arguments,['result','in1','stdDevX','stdDevY'],['stdDevY']);return this._wrapper._makeNode(g.parent,'feGaussianBlur',$.extend({result:g.result,in_:g.in1,stdDeviation:g.stdDevX+(g.stdDevY?' '+g.stdDevY:'')},g.settings||{}))},image:function(a,b,c,d){var e=this._wrapper._args(arguments,['result','href']);var f=this._wrapper._makeNode(e.parent,'feImage',$.extend({result:e.result},e.settings||{}));f.setAttributeNS($.svg.xlinkNS,'href',e.href);return f},merge:function(a,b,c,d){var e=this._wrapper._args(arguments,['result','refs']);var f=this._wrapper._makeNode(e.parent,'feMerge',$.extend({result:e.result},e.settings||{}));for(var i=0;i<e.refs.length;i++){this._wrapper._makeNode(f,'feMergeNode',{in_:e.refs[i]})}return f},morphology:function(a,b,c,d,e,f,g){var h=this._wrapper._args(arguments,['result','in1','operator','radiusX','radiusY'],['radiusY']);return this._wrapper._makeNode(h.parent,'feMorphology',$.extend({result:h.result,in_:h.in1,operator:h.operator,radius:h.radiusX+(h.radiusY?' '+h.radiusY:'')},h.settings||{}))},offset:function(a,b,c,d,e,f){var g=this._wrapper._args(arguments,['result','in1','dx','dy']);return this._wrapper._makeNode(g.parent,'feOffset',$.extend({result:g.result,in_:g.in1,dx:g.dx,dy:g.dy},g.settings||{}))},specularLighting:function(a,b,c,d,e,f,g){var h=this._wrapper._args(arguments,['result','in1','surfaceScale','specularConstant','specularExponent'],['surfaceScale','specularConstant','specularExponent']);return this._wrapper._makeNode(h.parent,'feSpecularLighting',$.extend({result:h.result,in_:h.in1,surfaceScale:h.surfaceScale,specularConstant:h.specularConstant,specularExponent:h.specularExponent},h.settings||{}))},tile:function(a,b,c,x,y,d,e,f){var g=this._wrapper._args(arguments,['result','in1','x','y','width','height']);return this._wrapper._makeNode(g.parent,'feTile',$.extend({result:g.result,in_:g.in1,x:g.x,y:g.y,width:g.width,height:g.height},g.settings||{}))},turbulence:function(a,b,c,d,e,f){var g=this._wrapper._args(arguments,['result','type','baseFreq','octaves'],['octaves']);return this._wrapper._makeNode(g.parent,'feTurbulence',$.extend({result:g.result,type:g.type,baseFrequency:g.baseFreq,numOctaves:g.octaves},g.settings||{}))}})})(jQuery)
|
@@ -0,0 +1,1539 @@
|
|
1
|
+
/* http://keith-wood.name/svg.html
|
2
|
+
SVG graphing extension for jQuery v1.5.0.
|
3
|
+
Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
|
4
|
+
Available under the MIT (http://keith-wood.name/licence.html) license.
|
5
|
+
Please attribute the author if you use it. */
|
6
|
+
|
7
|
+
(function($) { // Hide scope, no $ conflict
|
8
|
+
|
9
|
+
$.svg.addExtension('graph', SVGGraph);
|
10
|
+
|
11
|
+
$.svg.graphing = new SVGGraphing();
|
12
|
+
|
13
|
+
/** The SVG graphing manager.
|
14
|
+
<p>Use the singleton instance of this class, $.svg.graphing,
|
15
|
+
to interact with the SVG graphing functionality.</p>
|
16
|
+
@module SVGGraphing */
|
17
|
+
function SVGGraphing() {
|
18
|
+
this.regional = [];
|
19
|
+
this.regional[''] = {percentageText: 'Percentage'};
|
20
|
+
this.region = this.regional[''];
|
21
|
+
}
|
22
|
+
|
23
|
+
$.extend(SVGGraphing.prototype, {
|
24
|
+
_chartTypes: [],
|
25
|
+
|
26
|
+
/** Add a new chart rendering type to the package.
|
27
|
+
<p>The rendering object must implement the following functions: <code>getTitle()</code>,
|
28
|
+
<code>getDescription()</code>, <code>getOptions()</code>, <code>drawChart(graph)</code>.</p>
|
29
|
+
@param id {string} The ID of this graph renderer.
|
30
|
+
@param chartType {object} The object implementing this chart type. */
|
31
|
+
addChartType: function(id, chartType) {
|
32
|
+
this._chartTypes[id] = chartType;
|
33
|
+
},
|
34
|
+
|
35
|
+
/** Retrieve the list of chart types.
|
36
|
+
@return {object[]} The array of chart types indexed by ID */
|
37
|
+
chartTypes: function() {
|
38
|
+
return this._chartTypes;
|
39
|
+
}
|
40
|
+
});
|
41
|
+
|
42
|
+
/** The SVG graph manager.
|
43
|
+
<p>Use the singleton instance of this class, $.svg.graph,
|
44
|
+
to interact with the SVG graph functionality.</p>
|
45
|
+
@module SVGGraph */
|
46
|
+
function SVGGraph(wrapper) {
|
47
|
+
this._wrapper = wrapper; // The attached SVG wrapper object
|
48
|
+
this._drawNow = false; // True for immediate update, false to wait for redraw call
|
49
|
+
for (var id in $.svg.graphing._chartTypes) {
|
50
|
+
this._chartType = $.svg.graphing._chartTypes[id]; // Use first graph renderer
|
51
|
+
break;
|
52
|
+
}
|
53
|
+
this._chartOptions = {}; // Extra options for the graph type
|
54
|
+
// The graph title and settings
|
55
|
+
this._title = {value: '', offset: 25, settings: {textAnchor: 'middle'}};
|
56
|
+
this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom, > 1 in pixels, <= 1 as proportion
|
57
|
+
this._chartFormat = {fill: 'none', stroke: 'black'}; // The formatting for the chart area
|
58
|
+
this._gridlines = []; // The formatting of the x- and y-gridlines
|
59
|
+
this._series = []; // The series to be plotted, each is an object
|
60
|
+
this._onstatus = null; // The callback function for status updates
|
61
|
+
this._chartCont = this._wrapper.svg(0, 0, 0, 0, {class_: 'svg-graph'}); // The main container for the graph
|
62
|
+
|
63
|
+
this.xAxis = new SVGGraphAxis(this); // The main x-axis
|
64
|
+
this.xAxis.title('', 40);
|
65
|
+
this.yAxis = new SVGGraphAxis(this); // The main y-axis
|
66
|
+
this.yAxis.title('', 40);
|
67
|
+
this.x2Axis = null; // The secondary x-axis
|
68
|
+
this.y2Axis = null; // The secondary y-axis
|
69
|
+
this.legend = new SVGGraphLegend(this); // The chart legend
|
70
|
+
this._drawNow = true;
|
71
|
+
}
|
72
|
+
|
73
|
+
$.extend(SVGGraph.prototype, {
|
74
|
+
|
75
|
+
/* Useful indexes. */
|
76
|
+
/** Index in a dimensions array for x-coordinate. */
|
77
|
+
X: 0,
|
78
|
+
/** Index in a dimensions array for y-coordinate. */
|
79
|
+
Y: 1,
|
80
|
+
/** Index in a dimensions array for width. */
|
81
|
+
W: 2,
|
82
|
+
/** Index in a dimensions array for height. */
|
83
|
+
H: 3,
|
84
|
+
/** Index in an area array for left x-coordinate. */
|
85
|
+
L: 0,
|
86
|
+
/** Index in an area array for top y-coordinate. */
|
87
|
+
T: 1,
|
88
|
+
/** Index in an area array for right x-coordinate. */
|
89
|
+
R: 2,
|
90
|
+
/** Index in an area array for bottom y-coordinate. */
|
91
|
+
B: 3,
|
92
|
+
|
93
|
+
/* Standard percentage axis. */
|
94
|
+
_percentageAxis: new SVGGraphAxis(this, $.svg.graphing.region.percentageText, 0, 100, 10, 0),
|
95
|
+
|
96
|
+
/** Set or retrieve the container for the graph.
|
97
|
+
@param cont {SVGElement} The container for the graph.
|
98
|
+
@return {SVGGraph|SVGElement} This graph object or the current container (if no parameters). */
|
99
|
+
container: function(cont) {
|
100
|
+
if (arguments.length === 0) {
|
101
|
+
return this._chartCont;
|
102
|
+
}
|
103
|
+
this._chartCont = cont;
|
104
|
+
return this;
|
105
|
+
},
|
106
|
+
|
107
|
+
/** Set or retrieve the type of chart to be rendered.
|
108
|
+
<p>See <code>$.svg.graphing.getChartTypes()</code> for the list of available types.</p>
|
109
|
+
@param id {string} The ID of the chart type.
|
110
|
+
@param [options] {object} Additional settings for this chart type.
|
111
|
+
@return {SVGGraph|string} This graph object or the chart type (if no parameters).
|
112
|
+
@deprecated Use <code>type()</code>. */
|
113
|
+
chartType: function(id, options) {
|
114
|
+
return (arguments.length === 0 ? this.type() : this.type(id, options));
|
115
|
+
},
|
116
|
+
|
117
|
+
/** Set or retrieve the type of chart to be rendered.
|
118
|
+
<p>See <code>$.svg.graphing.getChartTypes()</code> for the list of available types.</p>
|
119
|
+
@param id {string} The ID of the chart type.
|
120
|
+
@param [options] {object} Additional settings for this chart type.
|
121
|
+
@return {SVGGraph|string} This graph object or the chart type (if no parameters). */
|
122
|
+
type: function(id, options) {
|
123
|
+
if (arguments.length === 0) {
|
124
|
+
return this._chartType;
|
125
|
+
}
|
126
|
+
var chartType = $.svg.graphing._chartTypes[id];
|
127
|
+
if (chartType) {
|
128
|
+
this._chartType = chartType;
|
129
|
+
this._chartOptions = $.extend({}, options || {});
|
130
|
+
}
|
131
|
+
this._drawGraph();
|
132
|
+
return this;
|
133
|
+
},
|
134
|
+
|
135
|
+
/** Set or retrieve additional options for the particular chart type.
|
136
|
+
@param options {object} The extra options.
|
137
|
+
@return {SVGGraph|object} This graph object or the chart options (if no parameters).
|
138
|
+
@deprecated Use <code>options()</code>. */
|
139
|
+
chartOptions: function(options) {
|
140
|
+
return(arguments.length === 0 ? this.options() : this.options(options));
|
141
|
+
},
|
142
|
+
|
143
|
+
/** Set or retrieve additional options for the particular chart type.
|
144
|
+
@param options {object} The extra options.
|
145
|
+
@return {SVGGraph|object} This graph object or the chart options (if no parameters). */
|
146
|
+
options: function(options) {
|
147
|
+
if (arguments.length === 0) {
|
148
|
+
return this._chartOptions;
|
149
|
+
}
|
150
|
+
this._chartOptions = $.extend({}, options);
|
151
|
+
this._drawGraph();
|
152
|
+
return this;
|
153
|
+
},
|
154
|
+
|
155
|
+
/** Set or retrieve the background of the graph chart.
|
156
|
+
@param fill {string} How to fill the chart background.
|
157
|
+
@param [stroke] {string} The colour of the outline.
|
158
|
+
@param [settings] {object} Additional formatting for the chart background.
|
159
|
+
@return {SVGGraph|object} This graph object or the chart format (if no parameters).
|
160
|
+
@deprecated Use <code>format()</code>. */
|
161
|
+
chartFormat: function(fill, stroke, settings) {
|
162
|
+
return (arguments.length === 0 ? this.format() : this.format(fill, stroke, settings));
|
163
|
+
},
|
164
|
+
|
165
|
+
/** Set or retrieve the background of the graph chart.
|
166
|
+
@param fill {string} How to fill the chart background.
|
167
|
+
@param [stroke] {string} The colour of the outline.
|
168
|
+
@param [settings] {object} Additional formatting for the chart background.
|
169
|
+
@return {SVGGraph|object} This graph object or the chart format (if no parameters). */
|
170
|
+
format: function(fill, stroke, settings) {
|
171
|
+
if (arguments.length === 0) {
|
172
|
+
return this._chartFormat;
|
173
|
+
}
|
174
|
+
if (typeof stroke === 'object') {
|
175
|
+
settings = stroke;
|
176
|
+
stroke = null;
|
177
|
+
}
|
178
|
+
this._chartFormat = $.extend({fill: fill}, (stroke ? {stroke: stroke} : {}), settings || {});
|
179
|
+
this._drawGraph();
|
180
|
+
return this;
|
181
|
+
},
|
182
|
+
|
183
|
+
/** Set or retrieve the main chart area.
|
184
|
+
@param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom.
|
185
|
+
@param [top] {number} > 1 is pixels, <= 1 is proportion of height.
|
186
|
+
@param [right] {number} > 1 is pixels, <= 1 is proportion of width.
|
187
|
+
@param [bottom] {number} > 1 is pixels, <= 1 is proportion of height.
|
188
|
+
@return {SVGGraph|number[]} This graph object or the chart area: left, top, right, bottom (if no parameters).
|
189
|
+
@deprecated Use <code>area()</code>. */
|
190
|
+
chartArea: function(left, top, right, bottom) {
|
191
|
+
return (arguments.length === 0 ? this.area() : this.area(left, top, right, bottom));
|
192
|
+
},
|
193
|
+
|
194
|
+
/** Set or retrieve the main chart area.
|
195
|
+
@param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom.
|
196
|
+
@param [top] {number} > 1 is pixels, <= 1 is proportion of height.
|
197
|
+
@param [right] {number} > 1 is pixels, <= 1 is proportion of width.
|
198
|
+
@param [bottom] {number} > 1 is pixels, <= 1 is proportion of height.
|
199
|
+
@return {SVGGraph|number[]} This graph object or the chart area: left, top, right, bottom (if no parameters). */
|
200
|
+
area: function(left, top, right, bottom) {
|
201
|
+
if (arguments.length === 0) {
|
202
|
+
return this._area;
|
203
|
+
}
|
204
|
+
this._area = ($.isArray(left) ? left : [left, top, right, bottom]);
|
205
|
+
this._drawGraph();
|
206
|
+
return this;
|
207
|
+
},
|
208
|
+
|
209
|
+
/** Set or retrieve the gridlines formatting for the graph chart.
|
210
|
+
@param xSettings {string|object} The colour of the gridlines along the x-axis,
|
211
|
+
or formatting for the gridlines along the x-axis, or <code>null</code> for none.
|
212
|
+
@param ySettings {string|object} The colour of the gridlines along the y-axis,
|
213
|
+
or formatting for the gridlines along the y-axis, or <code>null</code> for none.
|
214
|
+
@return {SVGGraph|object[]} This graph object or the gridlines formatting (if no parameters) */
|
215
|
+
gridlines: function(xSettings, ySettings) {
|
216
|
+
if (arguments.length === 0) {
|
217
|
+
return this._gridlines;
|
218
|
+
}
|
219
|
+
this._gridlines = [(typeof xSettings === 'string' ? {stroke: xSettings} : xSettings),
|
220
|
+
(typeof ySettings === 'string' ? {stroke: ySettings} : ySettings)];
|
221
|
+
if (this._gridlines[0] == null && this._gridlines[1] == null) {
|
222
|
+
this._gridlines = [];
|
223
|
+
}
|
224
|
+
this._drawGraph();
|
225
|
+
return this;
|
226
|
+
},
|
227
|
+
|
228
|
+
/** Set or retrieve the title of the graph and its formatting.
|
229
|
+
@param value {string} The title.
|
230
|
+
@param [offset] {number} The vertical positioning of the title > 1 is pixels, <= 1 is proportion of width.
|
231
|
+
@param [colour] {string} The colour of the title.
|
232
|
+
@param [settings] {object} Formatting for the title.
|
233
|
+
@return {SVGGraph|object} This graph object or value, offset, and settings for the title (if no parameters). */
|
234
|
+
title: function(value, offset, colour, settings) {
|
235
|
+
if (arguments.length === 0) {
|
236
|
+
return this._title;
|
237
|
+
}
|
238
|
+
if (typeof offset !== 'number') {
|
239
|
+
settings = colour;
|
240
|
+
colour = offset;
|
241
|
+
offset = null;
|
242
|
+
}
|
243
|
+
if (typeof colour !== 'string') {
|
244
|
+
settings = colour;
|
245
|
+
colour = null;
|
246
|
+
}
|
247
|
+
this._title = {value: value, offset: offset || this._title.offset,
|
248
|
+
settings: $.extend({textAnchor: 'middle'}, (colour ? {fill: colour} : {}), settings || {})};
|
249
|
+
this._drawGraph();
|
250
|
+
return this;
|
251
|
+
},
|
252
|
+
|
253
|
+
/** Add a series of values to be plotted on the graph.
|
254
|
+
@param [name] {string} The name of this series.
|
255
|
+
@param values {number[]} The values to be plotted.
|
256
|
+
@param fill {string} How the plotted values are filled.
|
257
|
+
@param [stroke] {string} The colour of the plotted lines.
|
258
|
+
@param [strokeWidth] {number} The width of the plotted lines.
|
259
|
+
@param [settings] {object} Additional settings for the plotted values.
|
260
|
+
@return {SVGGraph} This graph object. */
|
261
|
+
addSeries: function(name, values, fill, stroke, strokeWidth, settings) {
|
262
|
+
this._series.push(new SVGGraphSeries(this, name, values, fill, stroke, strokeWidth, settings));
|
263
|
+
this._drawGraph();
|
264
|
+
return this;
|
265
|
+
},
|
266
|
+
|
267
|
+
/** Retrieve the series wrappers.
|
268
|
+
@param [i] {number} The series index.
|
269
|
+
@return {SVGGraphSeries|SVGGraphSeries[]} The specified series or the list of series. */
|
270
|
+
series: function(i) {
|
271
|
+
return (arguments.length > 0 ? this._series[i] : null) || this._series;
|
272
|
+
},
|
273
|
+
|
274
|
+
/** Suppress drawing of the graph until redraw() is called.
|
275
|
+
@return {SVGGraph} This graph object. */
|
276
|
+
noDraw: function() {
|
277
|
+
this._drawNow = false;
|
278
|
+
return this;
|
279
|
+
},
|
280
|
+
|
281
|
+
/** Redraw the entire graph with the current settings and values.
|
282
|
+
@return {SVGGraph} This graph object. */
|
283
|
+
redraw: function() {
|
284
|
+
this._drawNow = true;
|
285
|
+
this._drawGraph();
|
286
|
+
return this;
|
287
|
+
},
|
288
|
+
|
289
|
+
/** Set the callback function for status updates.
|
290
|
+
@param onstatus {function} The callback function.
|
291
|
+
@return {SVGGraph} This graph object. */
|
292
|
+
status: function(onstatus) {
|
293
|
+
this._onstatus = onstatus;
|
294
|
+
return this;
|
295
|
+
},
|
296
|
+
|
297
|
+
/** Actually draw the graph (if allowed) based on the graph type set.
|
298
|
+
@private */
|
299
|
+
_drawGraph: function() {
|
300
|
+
if (!this._drawNow) {
|
301
|
+
return;
|
302
|
+
}
|
303
|
+
while (this._chartCont.firstChild) {
|
304
|
+
this._chartCont.removeChild(this._chartCont.firstChild);
|
305
|
+
}
|
306
|
+
if (!this._chartCont.parent) {
|
307
|
+
this._wrapper._svg.appendChild(this._chartCont);
|
308
|
+
}
|
309
|
+
// Set sizes if not already there
|
310
|
+
if (!this._chartCont.width) {
|
311
|
+
this._chartCont.setAttribute('width',
|
312
|
+
parseInt(this._chartCont.getAttribute('width'), 10) || this._wrapper.width());
|
313
|
+
}
|
314
|
+
else if (this._chartCont.width.baseVal) {
|
315
|
+
this._chartCont.width.baseVal.value = this._chartCont.width.baseVal.value || this._wrapper.width();
|
316
|
+
}
|
317
|
+
else {
|
318
|
+
this._chartCont.width = this._chartCont.width || this._wrapper.width();
|
319
|
+
}
|
320
|
+
if (!this._chartCont.height) {
|
321
|
+
this._chartCont.setAttribute('height',
|
322
|
+
parseInt(this._chartCont.getAttribute('height'), 10) || this._wrapper.height());
|
323
|
+
}
|
324
|
+
else if (this._chartCont.height.baseVal) {
|
325
|
+
this._chartCont.height.baseVal.value = this._chartCont.height.baseVal.value || this._wrapper.height();
|
326
|
+
}
|
327
|
+
else {
|
328
|
+
this._chartCont.height = this._chartCont.height || this._wrapper.height();
|
329
|
+
}
|
330
|
+
this._chartType.drawGraph(this);
|
331
|
+
},
|
332
|
+
|
333
|
+
/** Decode an attribute value.
|
334
|
+
@private
|
335
|
+
@param node {SVGElement} The node to examine.
|
336
|
+
@param name {string} The attribute name.
|
337
|
+
@return {string} The actual value. */
|
338
|
+
_getValue: function(node, name) {
|
339
|
+
return (!node[name] ? parseInt(node.getAttribute(name), 10) :
|
340
|
+
(node[name].baseVal ? node[name].baseVal.value : node[name]));
|
341
|
+
},
|
342
|
+
|
343
|
+
/** Draw the graph title - centred.
|
344
|
+
@private */
|
345
|
+
_drawTitle: function() {
|
346
|
+
this._wrapper.text(this._chartCont, this._getValue(this._chartCont, 'width') / 2,
|
347
|
+
this._title.offset, this._title.value, this._title.settings);
|
348
|
+
},
|
349
|
+
|
350
|
+
/** Calculate the actual dimensions of the chart area.
|
351
|
+
@private
|
352
|
+
@param [area] {number[]} The area values to evaluate, defaulting to the current ones.
|
353
|
+
@return {number[]} An array of dimension values: left, top, width, height. */
|
354
|
+
_getDims: function(area) {
|
355
|
+
area = area || this._area;
|
356
|
+
var availWidth = this._getValue(this._chartCont, 'width');
|
357
|
+
var availHeight = this._getValue(this._chartCont, 'height');
|
358
|
+
var left = (area[this.L] > 1 ? area[this.L] : availWidth * area[this.L]);
|
359
|
+
var top = (area[this.T] > 1 ? area[this.T] : availHeight * area[this.T]);
|
360
|
+
var width = (area[this.R] > 1 ? area[this.R] : availWidth * area[this.R]) - left;
|
361
|
+
var height = (area[this.B] > 1 ? area[this.B] : availHeight * area[this.B]) - top;
|
362
|
+
return [left, top, width, height];
|
363
|
+
},
|
364
|
+
|
365
|
+
/** Draw the chart background, including gridlines.
|
366
|
+
@private
|
367
|
+
@param [noXGrid=false] {boolean} <code>true</code> to suppress the x-gridlines, <code>false</code> to draw them.
|
368
|
+
@param [noYGrid=false] {boolean} <code>true</code> to suppress the y-gridlines, <code>false</code> to draw them.
|
369
|
+
@return {SVGEelement} The background group element */
|
370
|
+
_drawChartBackground: function(noXGrid, noYGrid) {
|
371
|
+
var bg = this._wrapper.group(this._chartCont, {class_: 'background'});
|
372
|
+
var dims = this._getDims();
|
373
|
+
this._wrapper.rect(bg, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], this._chartFormat);
|
374
|
+
if (this._gridlines[0] && this.yAxis._ticks.major && !noYGrid) {
|
375
|
+
this._drawGridlines(bg, this.yAxis, true, dims, this._gridlines[0]);
|
376
|
+
}
|
377
|
+
if (this._gridlines[1] && this.xAxis._ticks.major && !noXGrid) {
|
378
|
+
this._drawGridlines(bg, this.xAxis, false, dims, this._gridlines[1]);
|
379
|
+
}
|
380
|
+
return bg;
|
381
|
+
},
|
382
|
+
|
383
|
+
/** Draw one set of gridlines.
|
384
|
+
@private
|
385
|
+
@param bg {SVGElement} The background group element.
|
386
|
+
@param axis {SVGGraphAxis} The axis definition.
|
387
|
+
@param horiz {boolean} <code>true</code> if horizontal, <code>false</code> if vertical.
|
388
|
+
@param dims {number[]} The left, top, width, height of the chart area.
|
389
|
+
@param format {object} Additional settings for the gridlines. */
|
390
|
+
_drawGridlines: function(bg, axis, horiz, dims, format) {
|
391
|
+
var g = this._wrapper.group(bg, format);
|
392
|
+
var scale = (horiz ? dims[this.H] : dims[this.W]) / (axis._scale.max - axis._scale.min);
|
393
|
+
var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major;
|
394
|
+
major = (major < axis._scale.min ? major + axis._ticks.major : major);
|
395
|
+
while (major <= axis._scale.max) {
|
396
|
+
var v = (horiz ? axis._scale.max - major : major - axis._scale.min) * scale +
|
397
|
+
(horiz ? dims[this.Y] : dims[this.X]);
|
398
|
+
this._wrapper.line(g, (horiz ? dims[this.X] : v), (horiz ? v : dims[this.Y]),
|
399
|
+
(horiz ? dims[this.X] + dims[this.W] : v), (horiz ? v : dims[this.Y] + dims[this.H]));
|
400
|
+
major += axis._ticks.major;
|
401
|
+
}
|
402
|
+
},
|
403
|
+
|
404
|
+
/** Draw the axes in their standard configuration.
|
405
|
+
@private
|
406
|
+
@param [noX=false] {boolean} <code>true</code> to suppress the x-axes, <code>false</code> to draw it. */
|
407
|
+
_drawAxes: function(noX) {
|
408
|
+
var dims = this._getDims();
|
409
|
+
if (this.xAxis && !noX) {
|
410
|
+
if (this.xAxis._title) {
|
411
|
+
this._wrapper.text(this._chartCont, dims[this.X] + dims[this.W] / 2,
|
412
|
+
dims[this.Y] + dims[this.H] + this.xAxis._titleOffset, this.xAxis._title, this.xAxis._titleFormat);
|
413
|
+
}
|
414
|
+
this._drawAxis(this.xAxis, 'xAxis', dims[this.X], dims[this.Y] + dims[this.H],
|
415
|
+
dims[this.X] + dims[this.W], dims[this.Y] + dims[this.H]);
|
416
|
+
}
|
417
|
+
if (this.yAxis) {
|
418
|
+
if (this.yAxis._title) {
|
419
|
+
this._wrapper.text(this._chartCont, 0, 0, this.yAxis._title, $.extend({textAnchor: 'middle',
|
420
|
+
transform: 'translate(' + (dims[this.X] - this.yAxis._titleOffset) + ',' +
|
421
|
+
(dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.yAxis._titleFormat || {}));
|
422
|
+
}
|
423
|
+
this._drawAxis(this.yAxis, 'yAxis', dims[this.X], dims[this.Y], dims[this.X], dims[this.Y] + dims[this.H]);
|
424
|
+
}
|
425
|
+
if (this.x2Axis && !noX) {
|
426
|
+
if (this.x2Axis._title) {
|
427
|
+
this._wrapper.text(this._chartCont, dims[this.X] + dims[this.W] / 2,
|
428
|
+
dims[this.X] - this.x2Axis._titleOffset, this.x2Axis._title, this.x2Axis._titleFormat);
|
429
|
+
}
|
430
|
+
this._drawAxis(this.x2Axis, 'x2Axis', dims[this.X], dims[this.Y], dims[this.X] + dims[this.W], dims[this.Y]);
|
431
|
+
}
|
432
|
+
if (this.y2Axis) {
|
433
|
+
if (this.y2Axis._title) {
|
434
|
+
this._wrapper.text(this._chartCont, 0, 0, this.y2Axis._title, $.extend({textAnchor: 'middle',
|
435
|
+
transform: 'translate(' + (dims[this.X] + dims[this.W] + this.y2Axis._titleOffset) + ',' +
|
436
|
+
(dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.y2Axis._titleFormat || {}));
|
437
|
+
}
|
438
|
+
this._drawAxis(this.y2Axis, 'y2Axis', dims[this.X] + dims[this.W], dims[this.Y],
|
439
|
+
dims[this.X] + dims[this.W], dims[this.Y] + dims[this.H]);
|
440
|
+
}
|
441
|
+
},
|
442
|
+
|
443
|
+
/** Draw an axis and its tick marks.
|
444
|
+
@private
|
445
|
+
@param axis {SVGGraphAxis} The axis definition.
|
446
|
+
@param id {string} The identifier for the axis group element.
|
447
|
+
@param x1 {number} Starting x-coodinate for the axis.
|
448
|
+
@param y1 {number} Starting y-coodinate for the axis.
|
449
|
+
@param x2 {number} Ending x-coodinate for the axis.
|
450
|
+
@param y2 {number} Ending y-coodinate for the axis. */
|
451
|
+
_drawAxis: function(axis, id, x1, y1, x2, y2) {
|
452
|
+
var horiz = (y1 === y2);
|
453
|
+
var gl = this._wrapper.group(this._chartCont, $.extend({class_: id}, axis._lineFormat));
|
454
|
+
var gt = this._wrapper.group(this._chartCont, $.extend({class_: id + 'Labels',
|
455
|
+
textAnchor: (horiz ? 'middle' : 'end')}, axis._labelFormat));
|
456
|
+
this._wrapper.line(gl, x1, y1, x2, y2);
|
457
|
+
if (axis._ticks.major) {
|
458
|
+
var bottomRight = (x2 > (this._getValue(this._chartCont, 'width') / 2) &&
|
459
|
+
y2 > (this._getValue(this._chartCont, 'height') / 2));
|
460
|
+
var scale = (horiz ? x2 - x1 : y2 - y1) / (axis._scale.max - axis._scale.min);
|
461
|
+
var size = axis._ticks.size;
|
462
|
+
var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major;
|
463
|
+
major = (major < axis._scale.min ? major + axis._ticks.major : major);
|
464
|
+
var minor = (!axis._ticks.minor ? axis._scale.max + 1 :
|
465
|
+
Math.floor(axis._scale.min / axis._ticks.minor) * axis._ticks.minor);
|
466
|
+
minor = (minor < axis._scale.min ? minor + axis._ticks.minor : minor);
|
467
|
+
var offsets = this._getTickOffsets(axis, bottomRight);
|
468
|
+
var count = 0;
|
469
|
+
while (major <= axis._scale.max || minor <= axis._scale.max) {
|
470
|
+
var cur = Math.min(major, minor);
|
471
|
+
var len = (cur === major ? size : size / 2);
|
472
|
+
var v = (horiz ? x1 : y1) + (horiz ? cur - axis._scale.min : axis._scale.max - cur) * scale;
|
473
|
+
this._wrapper.line(gl, (horiz ? v : x1 + len * offsets[0]), (horiz ? y1 + len * offsets[0] : v),
|
474
|
+
(horiz ? v : x1 + len * offsets[1]), (horiz ? y1 + len * offsets[1] : v));
|
475
|
+
if (cur === major) {
|
476
|
+
this._wrapper.text(gt, (horiz ? v : x1 - size), (horiz ? y1 + 2 * size : v),
|
477
|
+
(axis._labels ? axis._labels[count++] : '' + cur));
|
478
|
+
}
|
479
|
+
major += (cur === major ? axis._ticks.major : 0);
|
480
|
+
minor += (cur === minor ? axis._ticks.minor : 0);
|
481
|
+
}
|
482
|
+
}
|
483
|
+
},
|
484
|
+
|
485
|
+
/** Calculate offsets based on axis and tick positions.
|
486
|
+
@private
|
487
|
+
@param axis {SVGGraphAxis} The axis definition.
|
488
|
+
@param bottomRight {boolean} <code>true</code> if this axis is appearing on the bottom or
|
489
|
+
right of the chart area, <code>false</code> if to the top or left.
|
490
|
+
@return {number[]} The array of offset multipliers (-1..+1). */
|
491
|
+
_getTickOffsets: function(axis, bottomRight) {
|
492
|
+
return [(axis._ticks.position === (bottomRight ? 'in' : 'out') || axis._ticks.position === 'both' ? -1 : 0),
|
493
|
+
(axis._ticks.position === (bottomRight ? 'out' : 'in') || axis._ticks.position === 'both' ? +1 : 0), ];
|
494
|
+
},
|
495
|
+
|
496
|
+
/** Retrieve the standard percentage axis.
|
497
|
+
@private
|
498
|
+
@return {SVGGraphAxis} Percentage axis. */
|
499
|
+
_getPercentageAxis: function() {
|
500
|
+
this._percentageAxis._title = $.svg.graphing.region.percentageText;
|
501
|
+
return this._percentageAxis;
|
502
|
+
},
|
503
|
+
|
504
|
+
/** Calculate the column totals across all the series.
|
505
|
+
@private
|
506
|
+
@return {number[]} The column totals. */
|
507
|
+
_getTotals: function() {
|
508
|
+
var totals = [];
|
509
|
+
var numVal = (this._series.length ? this._series[0]._values.length : 0);
|
510
|
+
for (var i = 0; i < numVal; i++) {
|
511
|
+
totals[i] = 0;
|
512
|
+
for (var j = 0; j < this._series.length; j++) {
|
513
|
+
totals[i] += this._series[j]._values[i];
|
514
|
+
}
|
515
|
+
}
|
516
|
+
return totals;
|
517
|
+
},
|
518
|
+
|
519
|
+
/** Draw the chart legend.
|
520
|
+
@private */
|
521
|
+
_drawLegend: function() {
|
522
|
+
if (!this.legend._show) {
|
523
|
+
return;
|
524
|
+
}
|
525
|
+
var g = this._wrapper.group(this._chartCont, {class_: 'legend'});
|
526
|
+
var dims = this._getDims(this.legend._area);
|
527
|
+
this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], this.legend._bgSettings);
|
528
|
+
var horiz = dims[this.W] > dims[this.H];
|
529
|
+
var numSer = this._series.length;
|
530
|
+
var offset = (horiz ? dims[this.W] : dims[this.H]) / numSer;
|
531
|
+
var xBase = dims[this.X] + 5;
|
532
|
+
var yBase = dims[this.Y] + ((horiz ? dims[this.H] : offset) + this.legend._sampleSize) / 2;
|
533
|
+
for (var i = 0; i < numSer; i++) {
|
534
|
+
var series = this._series[i];
|
535
|
+
this._wrapper.rect(g, xBase + (horiz ? i * offset : 0),
|
536
|
+
yBase + (horiz ? 0 : i * offset) - this.legend._sampleSize,
|
537
|
+
this.legend._sampleSize, this.legend._sampleSize,
|
538
|
+
{fill: series._fill, stroke: series._stroke, strokeWidth: 1});
|
539
|
+
this._wrapper.text(g, xBase + (horiz ? i * offset : 0) + this.legend._sampleSize + 5,
|
540
|
+
yBase + (horiz ? 0 : i * offset), series._name, this.legend._textSettings);
|
541
|
+
}
|
542
|
+
},
|
543
|
+
|
544
|
+
/** Show the current value status on hover.
|
545
|
+
@private
|
546
|
+
@param elem {string|SVGElement} The selector or SVG element to show the status in.
|
547
|
+
@param label {string} The current label.
|
548
|
+
@param value {number} The current value. */
|
549
|
+
_showStatus: function(elem, label, value) {
|
550
|
+
var status = this._onstatus;
|
551
|
+
if (this._onstatus) {
|
552
|
+
$(elem).hover(function() { status.apply(this, [label, value]); },
|
553
|
+
function() { status.apply(this, ['', 0]); });
|
554
|
+
}
|
555
|
+
}
|
556
|
+
});
|
557
|
+
|
558
|
+
/** A graph series definition.
|
559
|
+
@module SVGGraphSeries */
|
560
|
+
|
561
|
+
/** Details about each graph series.
|
562
|
+
<p>Created through <code>graph.addSeries()</code>.</p>
|
563
|
+
@param graph {SVGGraph} The owning graph.
|
564
|
+
@param [name] {string} The name of this series.
|
565
|
+
@param values {number[]} The values to be plotted.
|
566
|
+
@param fill {string} How the plotted values are filled.
|
567
|
+
@param [stroke] {string} The colour of the plotted lines.
|
568
|
+
@param [strokeWidth] {number} The width of the plotted lines.
|
569
|
+
@param [settings] {object} Additional settings for the plotted values.
|
570
|
+
@return {SVGGraphSeries} The new series object. */
|
571
|
+
function SVGGraphSeries(graph, name, values, fill, stroke, strokeWidth, settings) {
|
572
|
+
if (typeof name !== 'string') {
|
573
|
+
settings = strokeWidth;
|
574
|
+
strokeWidth = stroke;
|
575
|
+
stroke = fill;
|
576
|
+
fill = values;
|
577
|
+
values = name;
|
578
|
+
name = null;
|
579
|
+
}
|
580
|
+
if (typeof stroke !== 'string') {
|
581
|
+
settings = strokeWidth;
|
582
|
+
strokeWidth = stroke;
|
583
|
+
stroke = null;
|
584
|
+
}
|
585
|
+
if (typeof strokeWidth !== 'number') {
|
586
|
+
settings = strokeWidth;
|
587
|
+
strokeWidth = null;
|
588
|
+
}
|
589
|
+
this._graph = graph; // The owning graph
|
590
|
+
this._name = name || ''; // The name of this series
|
591
|
+
this._values = values || []; // The list of values for this series
|
592
|
+
this._axis = 1; // Which axis this series applies to: 1 = primary, 2 = secondary
|
593
|
+
this._fill = fill || 'green'; // How the series is plotted
|
594
|
+
this._stroke = stroke || 'black'; // The colour for the (out)line
|
595
|
+
this._strokeWidth = strokeWidth || 1; // The (out)line width
|
596
|
+
this._settings = settings || {}; // Additional formatting settings for the series
|
597
|
+
}
|
598
|
+
|
599
|
+
$.extend(SVGGraphSeries.prototype, {
|
600
|
+
|
601
|
+
/** Set or retrieve the name for this series.
|
602
|
+
@param name {string} The series' name.
|
603
|
+
@return {SVGGraphSeries|string} This series object or the series name (if no parameters). */
|
604
|
+
name: function(name) {
|
605
|
+
if (arguments.length === 0) {
|
606
|
+
return this._name;
|
607
|
+
}
|
608
|
+
this._name = name;
|
609
|
+
this._graph._drawGraph();
|
610
|
+
return this;
|
611
|
+
},
|
612
|
+
|
613
|
+
/** Set or retrieve the values for this series.
|
614
|
+
@param [name] {string} The series' name.
|
615
|
+
@param values {number[]} The values to be graphed.
|
616
|
+
@return {SVGGraphSeries|number[]} This series object or the series values (if no parameters). */
|
617
|
+
values: function(name, values) {
|
618
|
+
if (arguments.length === 0) {
|
619
|
+
return this._values;
|
620
|
+
}
|
621
|
+
if ($.isArray(name)) {
|
622
|
+
values = name;
|
623
|
+
name = null;
|
624
|
+
}
|
625
|
+
this._name = name || this._name;
|
626
|
+
this._values = values;
|
627
|
+
this._graph._drawGraph();
|
628
|
+
return this;
|
629
|
+
},
|
630
|
+
|
631
|
+
/** Set or retrieve the formatting for this series.
|
632
|
+
@param fill {string} How the values are filled when plotted.
|
633
|
+
@param [stroke] {string} The (out)line colour.
|
634
|
+
@param [strokeWidth] {number} The line's width.
|
635
|
+
@param [settings] {object} Additional formatting settings for the series.
|
636
|
+
@return {SVGGraphSeries|object} This series object or formatting settings (if no parameters). */
|
637
|
+
format: function(fill, stroke, strokeWidth, settings) {
|
638
|
+
if (arguments.length === 0) {
|
639
|
+
return $.extend({fill: this._fill, stroke: this._stroke, strokeWidth: this._strokeWidth}, this._settings);
|
640
|
+
}
|
641
|
+
if (typeof stroke !== 'string') {
|
642
|
+
settings = strokeWidth;
|
643
|
+
strokeWidth = stroke;
|
644
|
+
stroke = null;
|
645
|
+
}
|
646
|
+
if (typeof strokeWidth !== 'number') {
|
647
|
+
settings = strokeWidth;
|
648
|
+
strokeWidth = null;
|
649
|
+
}
|
650
|
+
this._fill = fill || this._fill;
|
651
|
+
this._stroke = stroke || this._stroke;
|
652
|
+
this._strokeWidth = strokeWidth || this._strokeWidth;
|
653
|
+
$.extend(this._settings, settings || {});
|
654
|
+
this._graph._drawGraph();
|
655
|
+
return this;
|
656
|
+
},
|
657
|
+
|
658
|
+
/** Return to the parent graph.
|
659
|
+
@return {SVGGraph} The parent graph. */
|
660
|
+
end: function() {
|
661
|
+
return this._graph;
|
662
|
+
}
|
663
|
+
});
|
664
|
+
|
665
|
+
/** A graph axis definition.
|
666
|
+
@module SVGGraphAxis */
|
667
|
+
|
668
|
+
/** Details about each graph axis.
|
669
|
+
@param graph {SVGGraph} The owning graph.
|
670
|
+
@param title {string} The title of the axis.
|
671
|
+
@param min [number} The minimum value displayed on this axis.
|
672
|
+
@param max {number} The maximum value displayed on this axis.
|
673
|
+
@param major {number} The distance between major ticks.
|
674
|
+
@param [minor] {number} The distance between minor ticks.
|
675
|
+
@return {SVGGraphAxis} The new axis object. */
|
676
|
+
function SVGGraphAxis(graph, title, min, max, major, minor) {
|
677
|
+
this._graph = graph; // The owning graph
|
678
|
+
this._title = title || ''; // Title of this axis
|
679
|
+
this._titleFormat = {}; // Formatting settings for the title
|
680
|
+
this._titleOffset = 0; // The offset for positioning the title
|
681
|
+
this._labels = null; // List of labels for this axis - one per possible value across all series
|
682
|
+
this._labelFormat = {}; // Formatting settings for the labels
|
683
|
+
this._lineFormat = {stroke: 'black', strokeWidth: 1}; // Formatting settings for the axis lines
|
684
|
+
this._ticks = {major: major || 10, minor: minor || 0, size: 10, position: 'out'}; // Tick mark options
|
685
|
+
this._scale = {min: min || 0, max: max || 100}; // Axis scale settings
|
686
|
+
this._crossAt = 0; // Where this axis crosses the other one
|
687
|
+
}
|
688
|
+
|
689
|
+
$.extend(SVGGraphAxis.prototype, {
|
690
|
+
|
691
|
+
/** Set or retrieve the scale for this axis.
|
692
|
+
@param min {number} The minimum value shown.
|
693
|
+
@param max {number} The maximum value shown.
|
694
|
+
@return {SVGGraphAxis|object} This axis object or min and max values (if no parameters). */
|
695
|
+
scale: function(min, max) {
|
696
|
+
if (arguments.length === 0) {
|
697
|
+
return this._scale;
|
698
|
+
}
|
699
|
+
this._scale.min = min;
|
700
|
+
this._scale.max = max;
|
701
|
+
this._graph._drawGraph();
|
702
|
+
return this;
|
703
|
+
},
|
704
|
+
|
705
|
+
/** Set or retrieve the ticks for this axis.
|
706
|
+
@param major {number} The distance between major ticks.
|
707
|
+
@param minor {number} The distance between minor ticks.
|
708
|
+
@param [size] {number} The length of the major ticks (minor are half).
|
709
|
+
@param [position] {string} The location of the ticks: 'in', 'out', 'both'.
|
710
|
+
@return {SVGGraphAxis|object} This axis object or major, minor, size, and position values (if no parameters). */
|
711
|
+
ticks: function(major, minor, size, position) {
|
712
|
+
if (arguments.length === 0) {
|
713
|
+
return this._ticks;
|
714
|
+
}
|
715
|
+
if (typeof size === 'string') {
|
716
|
+
position = size;
|
717
|
+
size = null;
|
718
|
+
}
|
719
|
+
this._ticks.major = major;
|
720
|
+
this._ticks.minor = minor;
|
721
|
+
this._ticks.size = size || this._ticks.size;
|
722
|
+
this._ticks.position = position || this._ticks.position;
|
723
|
+
this._graph._drawGraph();
|
724
|
+
return this;
|
725
|
+
},
|
726
|
+
|
727
|
+
/** Set or retrieve the title for this axis.
|
728
|
+
@param title {string} The title text
|
729
|
+
@param [offset] {number} The distance to offset the title position.
|
730
|
+
@param [colour] {string} How to colour the title.
|
731
|
+
@param [format] {object} Formatting settings for the title.
|
732
|
+
@return {SVGGraphAxis|object} This axis object or title, offset, and format values (if no parameters). */
|
733
|
+
title: function(title, offset, colour, format) {
|
734
|
+
if (arguments.length === 0) {
|
735
|
+
return {title: this._title, offset: this._titleOffset, format: this._titleFormat};
|
736
|
+
}
|
737
|
+
if (typeof offset !== 'number') {
|
738
|
+
format = colour;
|
739
|
+
colour = offset;
|
740
|
+
offset = null;
|
741
|
+
}
|
742
|
+
if (typeof colour !== 'string') {
|
743
|
+
format = colour;
|
744
|
+
colour = null;
|
745
|
+
}
|
746
|
+
this._title = title;
|
747
|
+
this._titleOffset = (offset != null ? offset : this._titleOffset);
|
748
|
+
if (colour || format) {
|
749
|
+
this._titleFormat = $.extend(format || {}, (colour ? {fill: colour} : {}));
|
750
|
+
}
|
751
|
+
this._graph._drawGraph();
|
752
|
+
return this;
|
753
|
+
},
|
754
|
+
|
755
|
+
/** Set or retrieve the labels for this axis.
|
756
|
+
@param labels {string[]} The text for each entry.
|
757
|
+
@param [colour] {string} How to colour the labels.
|
758
|
+
@param [format] {object} Formatting settings for the labels.
|
759
|
+
@return {SVGGraphAxis|object} This axis object or labels and format values (if no parameters). */
|
760
|
+
labels: function(labels, colour, format) {
|
761
|
+
if (arguments.length === 0) {
|
762
|
+
return {labels: this._labels, format: this._labelFormat};
|
763
|
+
}
|
764
|
+
if (typeof colour !== 'string') {
|
765
|
+
format = colour;
|
766
|
+
colour = null;
|
767
|
+
}
|
768
|
+
this._labels = labels;
|
769
|
+
if (colour || format) {
|
770
|
+
this._labelFormat = $.extend(format || {}, (colour ? {fill: colour} : {}));
|
771
|
+
}
|
772
|
+
this._graph._drawGraph();
|
773
|
+
return this;
|
774
|
+
},
|
775
|
+
|
776
|
+
/** Set or retrieve the line formatting for this axis.
|
777
|
+
@param colour {string} The line's colour
|
778
|
+
@param [width] {number} The line's width.
|
779
|
+
@param [settings] {object} Additional formatting settings for the line.
|
780
|
+
@return {SVGGraphAxis|object} This axis object or line formatting values (if no parameters). */
|
781
|
+
line: function(colour, width, settings) {
|
782
|
+
if (arguments.length === 0) {
|
783
|
+
return this._lineFormat;
|
784
|
+
}
|
785
|
+
if (typeof width === 'object') {
|
786
|
+
settings = width;
|
787
|
+
width = null;
|
788
|
+
}
|
789
|
+
$.extend(this._lineFormat, {stroke: colour}, (width ? {strokeWidth: width} : {}), settings || {});
|
790
|
+
this._graph._drawGraph();
|
791
|
+
return this;
|
792
|
+
},
|
793
|
+
|
794
|
+
/** Return to the parent graph.
|
795
|
+
@return {SVGGraph} The parent graph. */
|
796
|
+
end: function() {
|
797
|
+
return this._graph;
|
798
|
+
}
|
799
|
+
});
|
800
|
+
|
801
|
+
/** A graph legend definition.
|
802
|
+
@module SVGGraphLegend */
|
803
|
+
|
804
|
+
/** Details about each graph legend.
|
805
|
+
@param graph {SVGGraph} The owning graph.
|
806
|
+
@param [bgSettings] {object} Additional formatting settings for the legend background.
|
807
|
+
@param [textSettings] {object} Additional formatting settings for the legend text.
|
808
|
+
@return {SVGGraphLegend} The new legend object. */
|
809
|
+
function SVGGraphLegend(graph, bgSettings, textSettings) {
|
810
|
+
this._graph = graph; // The owning graph
|
811
|
+
this._show = true; // Show the legend?
|
812
|
+
this._area = [0.9, 0.1, 1.0, 0.9]; // The legend area: left, top, right, bottom, > 1 in pixels, <= 1 as proportion
|
813
|
+
this._sampleSize = 15; // Size of sample box
|
814
|
+
this._bgSettings = bgSettings || {stroke: 'gray'}; // Additional formatting settings for the legend background
|
815
|
+
this._textSettings = textSettings || {}; // Additional formatting settings for the text
|
816
|
+
}
|
817
|
+
|
818
|
+
$.extend(SVGGraphLegend.prototype, {
|
819
|
+
|
820
|
+
/** Set or retrieve whether the legend should be shown.
|
821
|
+
@param show {boolean} <code>true</code> to display it, <code>false</code> to hide it.
|
822
|
+
@return {SVGGraphLegend|boolean} This legend object or show the legend? (if no parameters) */
|
823
|
+
show: function(show) {
|
824
|
+
if (arguments.length === 0) {
|
825
|
+
return this._show;
|
826
|
+
}
|
827
|
+
this._show = show;
|
828
|
+
this._graph._drawGraph();
|
829
|
+
return this;
|
830
|
+
},
|
831
|
+
|
832
|
+
/** Set or retrieve the legend area.
|
833
|
+
@param left {number|number[]} > 1 is pixels, <= 1 is proportion of width or array for left, top, right, bottom.
|
834
|
+
@param [top] {number) > 1 is pixels, <= 1 is proportion of height.
|
835
|
+
@param [right] {number) > 1 is pixels, <= 1 is proportion of width.
|
836
|
+
@param [bottom] {number) > 1 is pixels, <= 1 is proportion of height.
|
837
|
+
@return {SVGGraphLegend|number[]} This legend object or the legend area:
|
838
|
+
left, top, right, bottom (if no parameters). */
|
839
|
+
area: function(left, top, right, bottom) {
|
840
|
+
if (arguments.length === 0) {
|
841
|
+
return this._area;
|
842
|
+
}
|
843
|
+
this._area = ($.isArray(left) ? left : [left, top, right, bottom]);
|
844
|
+
this._graph._drawGraph();
|
845
|
+
return this;
|
846
|
+
},
|
847
|
+
|
848
|
+
/** Set or retrieve additional settings for the legend area.
|
849
|
+
@param [sampleSize] {number} The size of the sample box to display.
|
850
|
+
@param bgSettings {object} Additional formatting settings for the legend background.
|
851
|
+
@param [textSettings] {object} Additional formatting settings for the legend text.
|
852
|
+
@return {SVGGraphLegend|object} This legend object or
|
853
|
+
bgSettings and textSettings for the legend (if no parameters). */
|
854
|
+
settings: function(sampleSize, bgSettings, textSettings) {
|
855
|
+
if (arguments.length === 0) {
|
856
|
+
return {sampleSize: this._sampleSize, bgSettings: this._bgSettings, textSettings: this._textSettings};
|
857
|
+
}
|
858
|
+
if (typeof sampleSize !== 'number') {
|
859
|
+
textSettings = bgSettings;
|
860
|
+
bgSettings = sampleSize;
|
861
|
+
sampleSize = null;
|
862
|
+
}
|
863
|
+
this._sampleSize = sampleSize || this._sampleSize;
|
864
|
+
this._bgSettings = bgSettings;
|
865
|
+
this._textSettings = textSettings || this._textSettings;
|
866
|
+
this._graph._drawGraph();
|
867
|
+
return this;
|
868
|
+
},
|
869
|
+
|
870
|
+
/** Return to the parent graph.
|
871
|
+
@return {SVGGraph} The parent graph. */
|
872
|
+
end: function() {
|
873
|
+
return this._graph;
|
874
|
+
}
|
875
|
+
});
|
876
|
+
|
877
|
+
//==============================================================================
|
878
|
+
|
879
|
+
/** Round a number to a given number of decimal points.
|
880
|
+
@private
|
881
|
+
@param num {number} The original value.
|
882
|
+
@param dec {number} The number of decimal points to retain.
|
883
|
+
@return {number} The rounded number. */
|
884
|
+
function roundNumber(num, dec) {
|
885
|
+
return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
|
886
|
+
}
|
887
|
+
|
888
|
+
var barOptions = ['barWidth (number) - the width of each bar', 'barGap (number) - the gap between sets of bars'];
|
889
|
+
|
890
|
+
//------------------------------------------------------------------------------
|
891
|
+
|
892
|
+
/** Draw a standard grouped column bar chart.
|
893
|
+
@module SVGColumnChart */
|
894
|
+
function SVGColumnChart() {
|
895
|
+
}
|
896
|
+
|
897
|
+
$.extend(SVGColumnChart.prototype, {
|
898
|
+
|
899
|
+
/** Retrieve the display title for this chart type.
|
900
|
+
@return {string} Its title. */
|
901
|
+
title: function() {
|
902
|
+
return 'Basic column chart';
|
903
|
+
},
|
904
|
+
|
905
|
+
/** Retrieve a description of this chart type.
|
906
|
+
@return {string} Its description. */
|
907
|
+
description: function() {
|
908
|
+
return 'Compare sets of values as vertical bars with grouped categories.';
|
909
|
+
},
|
910
|
+
|
911
|
+
/** Retrieve a list of the options that may be set for this chart type.
|
912
|
+
@return {string[]} Its options list. */
|
913
|
+
options: function() {
|
914
|
+
return barOptions;
|
915
|
+
},
|
916
|
+
|
917
|
+
/** Actually draw the graph in this type's style.
|
918
|
+
@param graph {SVGGraph} The graph object. */
|
919
|
+
drawGraph: function(graph) {
|
920
|
+
graph._drawChartBackground(true);
|
921
|
+
var barWidth = graph._chartOptions.barWidth || 10;
|
922
|
+
var barGap = graph._chartOptions.barGap || 10;
|
923
|
+
var numSer = graph._series.length;
|
924
|
+
var numVal = (numSer ? (graph._series[0])._values.length : 0);
|
925
|
+
var dims = graph._getDims();
|
926
|
+
var xScale = dims[graph.W] / ((numSer * barWidth + barGap) * numVal + barGap);
|
927
|
+
var yScale = dims[graph.H] / (graph.yAxis._scale.max - graph.yAxis._scale.min);
|
928
|
+
this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
|
929
|
+
for (var i = 0; i < numSer; i++) {
|
930
|
+
this._drawSeries(graph, i, numSer, barWidth, barGap, dims, xScale, yScale);
|
931
|
+
}
|
932
|
+
graph._drawTitle();
|
933
|
+
graph._drawAxes(true);
|
934
|
+
this._drawXAxis(graph, numSer, numVal, barWidth, barGap, dims, xScale);
|
935
|
+
graph._drawLegend();
|
936
|
+
},
|
937
|
+
|
938
|
+
/** Plot an individual series.
|
939
|
+
@private
|
940
|
+
@param graph {SVGGraph} The graph object.
|
941
|
+
@param cur {number} The current series index.
|
942
|
+
@param numSer {number} The number of points in this series.
|
943
|
+
@param barWidth {number} The width of each bar.
|
944
|
+
@param barGap {number} The space between bars.
|
945
|
+
@param dims {number[]} The dimensions of the drawing area.
|
946
|
+
@param xScale {number} The scaling factor in the horizontal direction.
|
947
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
948
|
+
_drawSeries: function(graph, cur, numSer, barWidth, barGap, dims, xScale, yScale) {
|
949
|
+
var series = graph._series[cur];
|
950
|
+
var g = graph._wrapper.group(this._chart,
|
951
|
+
$.extend({class_: 'series' + cur, fill: series._fill, stroke: series._stroke,
|
952
|
+
strokeWidth: series._strokeWidth}, series._settings || {}));
|
953
|
+
for (var i = 0; i < series._values.length; i++) {
|
954
|
+
var r = graph._wrapper.rect(g,
|
955
|
+
dims[graph.X] + xScale * (barGap + i * (numSer * barWidth + barGap) + (cur * barWidth)),
|
956
|
+
dims[graph.Y] + yScale * (graph.yAxis._scale.max - series._values[i]),
|
957
|
+
xScale * barWidth, yScale * series._values[i]);
|
958
|
+
graph._showStatus(r, series._name, series._values[i]);
|
959
|
+
}
|
960
|
+
},
|
961
|
+
|
962
|
+
/** Draw the x-axis and its ticks.
|
963
|
+
@private
|
964
|
+
@param graph {SVGGraph} The graph object.
|
965
|
+
@param numSer {number} The number of points in this series.
|
966
|
+
@param numVal {number} The current value index.
|
967
|
+
@param barWidth {number} The width of each bar.
|
968
|
+
@param barGap {number} The space between bars.
|
969
|
+
@param dims {number[]} The dimensions of the drawing area.
|
970
|
+
@param xScale {number} The scaling factor in the horizontal direction. */
|
971
|
+
_drawXAxis: function(graph, numSer, numVal, barWidth, barGap, dims, xScale) {
|
972
|
+
var axis = graph.xAxis;
|
973
|
+
if (axis._title) {
|
974
|
+
graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
|
975
|
+
dims[graph.Y] + dims[graph.H] + axis._titleOffset,
|
976
|
+
axis._title, $.extend({textAnchor: 'middle'}, axis._titleFormat || {}));
|
977
|
+
}
|
978
|
+
var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxis'}, axis._lineFormat));
|
979
|
+
var gt = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxisLabels',
|
980
|
+
textAnchor: 'middle'}, axis._labelFormat));
|
981
|
+
graph._wrapper.line(gl, dims[graph.X], dims[graph.Y] + dims[graph.H],
|
982
|
+
dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
|
983
|
+
if (axis._ticks.major) {
|
984
|
+
var offsets = graph._getTickOffsets(axis, true);
|
985
|
+
for (var i = 1; i < numVal; i++) {
|
986
|
+
var x = dims[graph.X] + xScale * (barGap / 2 + i * (numSer * barWidth + barGap));
|
987
|
+
graph._wrapper.line(gl, x, dims[graph.Y] + dims[graph.H] + offsets[0] * axis._ticks.size,
|
988
|
+
x, dims[graph.Y] + dims[graph.H] + offsets[1] * axis._ticks.size);
|
989
|
+
}
|
990
|
+
for (var i = 0; i < numVal; i++) {
|
991
|
+
var x = dims[graph.X] + xScale * (barGap / 2 + (i + 0.5) * (numSer * barWidth + barGap));
|
992
|
+
graph._wrapper.text(gt, x, dims[graph.Y] + dims[graph.H] + 2 * axis._ticks.size,
|
993
|
+
(axis._labels ? axis._labels[i] : '' + i));
|
994
|
+
}
|
995
|
+
}
|
996
|
+
}
|
997
|
+
});
|
998
|
+
|
999
|
+
//------------------------------------------------------------------------------
|
1000
|
+
|
1001
|
+
/** Draw a stacked column bar chart.
|
1002
|
+
@module SVGStackedColumnChart */
|
1003
|
+
function SVGStackedColumnChart() {
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
$.extend(SVGStackedColumnChart.prototype, {
|
1007
|
+
|
1008
|
+
/** Retrieve the display title for this chart type.
|
1009
|
+
@return {string} Its title. */
|
1010
|
+
title: function() {
|
1011
|
+
return 'Stacked column chart';
|
1012
|
+
},
|
1013
|
+
|
1014
|
+
/** Retrieve a description of this chart type.
|
1015
|
+
@return {string} Its description. */
|
1016
|
+
description: function() {
|
1017
|
+
return 'Compare sets of values as vertical bars showing ' +
|
1018
|
+
'relative contributions to the whole for each category.';
|
1019
|
+
},
|
1020
|
+
|
1021
|
+
/** Retrieve a list of the options that may be set for this chart type.
|
1022
|
+
@return {string[]} Its options list. */
|
1023
|
+
options: function() {
|
1024
|
+
return barOptions;
|
1025
|
+
},
|
1026
|
+
|
1027
|
+
/** Actually draw the graph in this type's style.
|
1028
|
+
@param graph {SVGGraph} The graph object. */
|
1029
|
+
drawGraph: function(graph) {
|
1030
|
+
var bg = graph._drawChartBackground(true, true);
|
1031
|
+
var dims = graph._getDims();
|
1032
|
+
if (graph._gridlines[0] && graph.xAxis._ticks.major) {
|
1033
|
+
graph._drawGridlines(bg, graph._getPercentageAxis(), true, dims, graph._gridlines[0]);
|
1034
|
+
}
|
1035
|
+
var barWidth = graph._chartOptions.barWidth || 10;
|
1036
|
+
var barGap = graph._chartOptions.barGap || 10;
|
1037
|
+
var numSer = graph._series.length;
|
1038
|
+
var numVal = (numSer ? (graph._series[0])._values.length : 0);
|
1039
|
+
var xScale = dims[graph.W] / ((barWidth + barGap) * numVal + barGap);
|
1040
|
+
var yScale = dims[graph.H];
|
1041
|
+
this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
|
1042
|
+
this._drawColumns(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale);
|
1043
|
+
graph._drawTitle();
|
1044
|
+
graph._wrapper.text(graph._chartCont, 0, 0, $.svg.graphing.region.percentageText,
|
1045
|
+
$.extend({textAnchor: 'middle', transform: 'translate(' +
|
1046
|
+
(dims[graph.X] - graph.yAxis._titleOffset) + ',' +
|
1047
|
+
(dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, graph.yAxis._titleFormat || {}));
|
1048
|
+
var pAxis = $.extend({}, graph._getPercentageAxis());
|
1049
|
+
$.extend(pAxis._labelFormat, graph.yAxis._labelFormat || {});
|
1050
|
+
graph._drawAxis(pAxis, 'yAxis', dims[graph.X], dims[graph.Y], dims[graph.X], dims[graph.Y] + dims[graph.H]);
|
1051
|
+
this._drawXAxis(graph, numVal, barWidth, barGap, dims, xScale);
|
1052
|
+
graph._drawLegend();
|
1053
|
+
},
|
1054
|
+
|
1055
|
+
/** Plot all of the columns.
|
1056
|
+
@private
|
1057
|
+
@param graph {SVGGraph} The graph object.
|
1058
|
+
@param numSer {number} The number of points in this series.
|
1059
|
+
@param numVal {number} The current value index.
|
1060
|
+
@param barWidth {number} The width of each bar.
|
1061
|
+
@param barGap {number} The space between bars.
|
1062
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1063
|
+
@param xScale {number} The scaling factor in the horizontal direction.
|
1064
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
1065
|
+
_drawColumns: function(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale) {
|
1066
|
+
var totals = graph._getTotals();
|
1067
|
+
var accum = [];
|
1068
|
+
for (var i = 0; i < numVal; i++) {
|
1069
|
+
accum[i] = 0;
|
1070
|
+
}
|
1071
|
+
for (var s = 0; s < numSer; s++) {
|
1072
|
+
var series = graph._series[s];
|
1073
|
+
var g = graph._wrapper.group(this._chart, $.extend({class_: 'series' + s, fill: series._fill,
|
1074
|
+
stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {}));
|
1075
|
+
for (var i = 0; i < series._values.length; i++) {
|
1076
|
+
accum[i] += series._values[i];
|
1077
|
+
var r = graph._wrapper.rect(g, dims[graph.X] + xScale * (barGap + i * (barWidth + barGap)),
|
1078
|
+
dims[graph.Y] + yScale * (totals[i] - accum[i]) / totals[i],
|
1079
|
+
xScale * barWidth, yScale * series._values[i] / totals[i]);
|
1080
|
+
graph._showStatus(r, series._name, roundNumber(series._values[i] / totals[i] * 100, 2));
|
1081
|
+
}
|
1082
|
+
}
|
1083
|
+
},
|
1084
|
+
|
1085
|
+
/** Draw the x-axis and its ticks.
|
1086
|
+
@private
|
1087
|
+
@param graph {SVGGraph} The graph object.
|
1088
|
+
@param numVal {number} The current value index.
|
1089
|
+
@param barWidth {number} The width of each bar.
|
1090
|
+
@param barGap {number} The space between bars.
|
1091
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1092
|
+
@param xScale {number} The scaling factor in the horizontal direction. */
|
1093
|
+
_drawXAxis: function(graph, numVal, barWidth, barGap, dims, xScale) {
|
1094
|
+
var axis = graph.xAxis;
|
1095
|
+
if (axis._title) {
|
1096
|
+
graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
|
1097
|
+
dims[graph.Y] + dims[graph.H] + axis._titleOffset,
|
1098
|
+
axis._title, $.extend({textAnchor: 'middle'}, axis._titleFormat || {}));
|
1099
|
+
}
|
1100
|
+
var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxis'}, axis._lineFormat));
|
1101
|
+
var gt = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxisLabels',
|
1102
|
+
textAnchor: 'middle'}, axis._labelFormat));
|
1103
|
+
graph._wrapper.line(gl, dims[graph.X], dims[graph.Y] + dims[graph.H],
|
1104
|
+
dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
|
1105
|
+
if (axis._ticks.major) {
|
1106
|
+
var offsets = graph._getTickOffsets(axis, true);
|
1107
|
+
for (var i = 1; i < numVal; i++) {
|
1108
|
+
var x = dims[graph.X] + xScale * (barGap / 2 + i * (barWidth + barGap));
|
1109
|
+
graph._wrapper.line(gl, x, dims[graph.Y] + dims[graph.H] + offsets[0] * axis._ticks.size,
|
1110
|
+
x, dims[graph.Y] + dims[graph.H] + offsets[1] * axis._ticks.size);
|
1111
|
+
}
|
1112
|
+
for (var i = 0; i < numVal; i++) {
|
1113
|
+
var x = dims[graph.X] + xScale * (barGap / 2 + (i + 0.5) * (barWidth + barGap));
|
1114
|
+
graph._wrapper.text(gt, x, dims[graph.Y] + dims[graph.H] + 2 * axis._ticks.size,
|
1115
|
+
(axis._labels ? axis._labels[i] : '' + i));
|
1116
|
+
}
|
1117
|
+
}
|
1118
|
+
}
|
1119
|
+
});
|
1120
|
+
|
1121
|
+
//------------------------------------------------------------------------------
|
1122
|
+
|
1123
|
+
/** Draw a standard grouped row bar chart.
|
1124
|
+
@module SVGRowChart */
|
1125
|
+
function SVGRowChart() {
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
$.extend(SVGRowChart.prototype, {
|
1129
|
+
|
1130
|
+
/** Retrieve the display title for this chart type.
|
1131
|
+
@return {string} Its title. */
|
1132
|
+
title: function() {
|
1133
|
+
return 'Basic row chart';
|
1134
|
+
},
|
1135
|
+
|
1136
|
+
/** Retrieve a description of this chart type.
|
1137
|
+
@return {string} Its description. */
|
1138
|
+
description: function() {
|
1139
|
+
return 'Compare sets of values as horizontal rows with grouped categories.';
|
1140
|
+
},
|
1141
|
+
|
1142
|
+
/** Retrieve a list of the options that may be set for this chart type.
|
1143
|
+
@return {string[]} Its options list. */
|
1144
|
+
options: function() {
|
1145
|
+
return barOptions;
|
1146
|
+
},
|
1147
|
+
|
1148
|
+
/** Actually draw the graph in this type's style.
|
1149
|
+
@param graph {SVGGraph} The graph object. */
|
1150
|
+
drawGraph: function(graph) {
|
1151
|
+
var bg = graph._drawChartBackground(true, true);
|
1152
|
+
var dims = graph._getDims();
|
1153
|
+
graph._drawGridlines(bg, graph.yAxis, false, dims, graph._gridlines[0]);
|
1154
|
+
var barWidth = graph._chartOptions.barWidth || 10;
|
1155
|
+
var barGap = graph._chartOptions.barGap || 10;
|
1156
|
+
var numSer = graph._series.length;
|
1157
|
+
var numVal = (numSer ? (graph._series[0])._values.length : 0);
|
1158
|
+
var xScale = dims[graph.W] / (graph.yAxis._scale.max - graph.yAxis._scale.min);
|
1159
|
+
var yScale = dims[graph.H] / ((numSer * barWidth + barGap) * numVal + barGap);
|
1160
|
+
this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
|
1161
|
+
for (var i = 0; i < numSer; i++) {
|
1162
|
+
this._drawSeries(graph, i, numSer, barWidth, barGap, dims, xScale, yScale);
|
1163
|
+
}
|
1164
|
+
graph._drawTitle();
|
1165
|
+
this._drawAxes(graph, numSer, numVal, barWidth, barGap, dims, yScale);
|
1166
|
+
graph._drawLegend();
|
1167
|
+
},
|
1168
|
+
|
1169
|
+
/** Plot an individual series.
|
1170
|
+
@private
|
1171
|
+
@param graph {SVGGraph} The graph object.
|
1172
|
+
@param cur {number} The current series index.
|
1173
|
+
@param numSer {number} The number of points in this series.
|
1174
|
+
@param barWidth {number} The width of each bar.
|
1175
|
+
@param barGap {number} The space between bars.
|
1176
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1177
|
+
@param xScale {number} The scaling factor in the horizontal direction.
|
1178
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
1179
|
+
_drawSeries: function(graph, cur, numSer, barWidth, barGap, dims, xScale, yScale) {
|
1180
|
+
var series = graph._series[cur];
|
1181
|
+
var g = graph._wrapper.group(this._chart, $.extend({class_: 'series' + cur, fill: series._fill,
|
1182
|
+
stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {}));
|
1183
|
+
for (var i = 0; i < series._values.length; i++) {
|
1184
|
+
var r = graph._wrapper.rect(g, dims[graph.X] + xScale * (0 - graph.yAxis._scale.min),
|
1185
|
+
dims[graph.Y] + yScale * (barGap + i * (numSer * barWidth + barGap) + (cur * barWidth)),
|
1186
|
+
xScale * series._values[i], yScale * barWidth);
|
1187
|
+
graph._showStatus(r, series._name, series._values[i]);
|
1188
|
+
}
|
1189
|
+
},
|
1190
|
+
|
1191
|
+
/** Draw the axes for this graph.
|
1192
|
+
@private
|
1193
|
+
@param graph {SVGGraph} The graph object.
|
1194
|
+
@param numSer {number} The number of points in this series.
|
1195
|
+
@param numVal {number} The current value index.
|
1196
|
+
@param barWidth {number} The width of each bar.
|
1197
|
+
@param barGap {number} The space between bars.
|
1198
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1199
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
1200
|
+
_drawAxes: function(graph, numSer, numVal, barWidth, barGap, dims, yScale) {
|
1201
|
+
// X-axis
|
1202
|
+
var axis = graph.yAxis;
|
1203
|
+
if (axis) {
|
1204
|
+
if (axis._title) {
|
1205
|
+
graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
|
1206
|
+
dims[graph.Y] + dims[graph.H] + axis._titleOffset, axis._title, axis._titleFormat);
|
1207
|
+
}
|
1208
|
+
graph._drawAxis(axis, 'xAxis', dims[graph.X], dims[graph.Y] + dims[graph.H],
|
1209
|
+
dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
|
1210
|
+
}
|
1211
|
+
// Y-axis
|
1212
|
+
var axis = graph.xAxis;
|
1213
|
+
if (axis._title) {
|
1214
|
+
graph._wrapper.text(graph._chartCont, 0, 0, axis._title, $.extend({textAnchor: 'middle',
|
1215
|
+
transform: 'translate(' + (dims[graph.X] - axis._titleOffset) + ',' +
|
1216
|
+
(dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, axis._titleFormat || {}));
|
1217
|
+
}
|
1218
|
+
var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'yAxis'}, axis._lineFormat));
|
1219
|
+
var gt = graph._wrapper.group(graph._chartCont, $.extend(
|
1220
|
+
{class_: 'yAxisLabels', textAnchor: 'end'}, axis._labelFormat));
|
1221
|
+
graph._wrapper.line(gl, dims[graph.X], dims[graph.Y], dims[graph.X], dims[graph.Y] + dims[graph.H]);
|
1222
|
+
if (axis._ticks.major) {
|
1223
|
+
var offsets = graph._getTickOffsets(axis, false);
|
1224
|
+
for (var i = 1; i < numVal; i++) {
|
1225
|
+
var y = dims[graph.Y] + yScale * (barGap / 2 + i * (numSer * barWidth + barGap));
|
1226
|
+
graph._wrapper.line(gl, dims[graph.X] + offsets[0] * axis._ticks.size, y,
|
1227
|
+
dims[graph.X] + offsets[1] * axis._ticks.size, y);
|
1228
|
+
}
|
1229
|
+
for (var i = 0; i < numVal; i++) {
|
1230
|
+
var y = dims[graph.Y] + yScale * (barGap / 2 + (i + 0.5) * (numSer * barWidth + barGap));
|
1231
|
+
graph._wrapper.text(gt, dims[graph.X] - axis._ticks.size, y,
|
1232
|
+
(axis._labels ? axis._labels[i] : '' + i));
|
1233
|
+
}
|
1234
|
+
}
|
1235
|
+
}
|
1236
|
+
});
|
1237
|
+
|
1238
|
+
//------------------------------------------------------------------------------
|
1239
|
+
|
1240
|
+
/** Draw a stacked row bar chart.
|
1241
|
+
@module SVGStackedRowChart */
|
1242
|
+
function SVGStackedRowChart() {
|
1243
|
+
}
|
1244
|
+
|
1245
|
+
$.extend(SVGStackedRowChart.prototype, {
|
1246
|
+
|
1247
|
+
/** Retrieve the display title for this chart type.
|
1248
|
+
@return {string} Its title. */
|
1249
|
+
title: function() {
|
1250
|
+
return 'Stacked row chart';
|
1251
|
+
},
|
1252
|
+
|
1253
|
+
/** Retrieve a description of this chart type.
|
1254
|
+
@return {string} Its description. */
|
1255
|
+
description: function() {
|
1256
|
+
return 'Compare sets of values as horizontal bars showing ' +
|
1257
|
+
'relative contributions to the whole for each category.';
|
1258
|
+
},
|
1259
|
+
|
1260
|
+
/** Retrieve a list of the options that may be set for this chart type.
|
1261
|
+
@return {string[]} Its options list. */
|
1262
|
+
options: function() {
|
1263
|
+
return barOptions;
|
1264
|
+
},
|
1265
|
+
|
1266
|
+
/** Actually draw the graph in this type's style.
|
1267
|
+
@param graph {SVGGraph} The graph object. */
|
1268
|
+
drawGraph: function(graph) {
|
1269
|
+
var bg = graph._drawChartBackground(true, true);
|
1270
|
+
var dims = graph._getDims();
|
1271
|
+
if (graph._gridlines[0] && graph.xAxis._ticks.major) {
|
1272
|
+
graph._drawGridlines(bg, graph._getPercentageAxis(), false, dims, graph._gridlines[0]);
|
1273
|
+
}
|
1274
|
+
var barWidth = graph._chartOptions.barWidth || 10;
|
1275
|
+
var barGap = graph._chartOptions.barGap || 10;
|
1276
|
+
var numSer = graph._series.length;
|
1277
|
+
var numVal = (numSer ? (graph._series[0])._values.length : 0);
|
1278
|
+
var xScale = dims[graph.W];
|
1279
|
+
var yScale = dims[graph.H] / ((barWidth + barGap) * numVal + barGap);
|
1280
|
+
this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
|
1281
|
+
this._drawRows(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale);
|
1282
|
+
graph._drawTitle();
|
1283
|
+
graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
|
1284
|
+
dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset, $.svg.graphing.region.percentageText,
|
1285
|
+
$.extend({textAnchor: 'middle'}, graph.yAxis._titleFormat || {}));
|
1286
|
+
var pAxis = $.extend({}, graph._getPercentageAxis());
|
1287
|
+
$.extend(pAxis._labelFormat, graph.yAxis._labelFormat || {});
|
1288
|
+
graph._drawAxis(pAxis, 'xAxis', dims[graph.X], dims[graph.Y] + dims[graph.H],
|
1289
|
+
dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
|
1290
|
+
this._drawYAxis(graph, numVal, barWidth, barGap, dims, yScale);
|
1291
|
+
graph._drawLegend();
|
1292
|
+
},
|
1293
|
+
|
1294
|
+
/** Plot all of the rows.
|
1295
|
+
@private
|
1296
|
+
@param graph {SVGGraph} The graph object.
|
1297
|
+
@param numSer {number} The number of points in this series.
|
1298
|
+
@param numVal {number} The current value index.
|
1299
|
+
@param barWidth {number} The width of each bar.
|
1300
|
+
@param barGap {number} The space between bars.
|
1301
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1302
|
+
@param xScale {number} The scaling factor in the horizontal direction.
|
1303
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
1304
|
+
_drawRows: function(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale) {
|
1305
|
+
var totals = graph._getTotals();
|
1306
|
+
var accum = [];
|
1307
|
+
for (var i = 0; i < numVal; i++) {
|
1308
|
+
accum[i] = 0;
|
1309
|
+
}
|
1310
|
+
for (var s = 0; s < numSer; s++) {
|
1311
|
+
var series = graph._series[s];
|
1312
|
+
var g = graph._wrapper.group(this._chart, $.extend({class_: 'series' + s, fill: series._fill,
|
1313
|
+
stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {}));
|
1314
|
+
for (var i = 0; i < series._values.length; i++) {
|
1315
|
+
var r = graph._wrapper.rect(g, dims[graph.X] + xScale * accum[i] / totals[i],
|
1316
|
+
dims[graph.Y] + yScale * (barGap + i * (barWidth + barGap)),
|
1317
|
+
xScale * series._values[i] / totals[i], yScale * barWidth);
|
1318
|
+
graph._showStatus(r, series._name, roundNumber(series._values[i] / totals[i] * 100, 2));
|
1319
|
+
accum[i] += series._values[i];
|
1320
|
+
}
|
1321
|
+
}
|
1322
|
+
},
|
1323
|
+
|
1324
|
+
/** Draw the y-axis and its ticks.
|
1325
|
+
@private
|
1326
|
+
@param graph {SVGGraph} The graph object.
|
1327
|
+
@param numVal {number} The current value index.
|
1328
|
+
@param barWidth {number} The width of each bar.
|
1329
|
+
@param barGap {number} The space between bars.
|
1330
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1331
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
1332
|
+
_drawYAxis: function(graph, numVal, barWidth, barGap, dims, yScale) {
|
1333
|
+
var axis = graph.xAxis;
|
1334
|
+
if (axis._title) {
|
1335
|
+
graph._wrapper.text(graph._chartCont, 0, 0, axis._title, $.extend({textAnchor: 'middle',
|
1336
|
+
transform: 'translate(' + (dims[graph.X] - axis._titleOffset) + ',' +
|
1337
|
+
(dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, axis._titleFormat || {}));
|
1338
|
+
}
|
1339
|
+
var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'yAxis'}, axis._lineFormat));
|
1340
|
+
var gt = graph._wrapper.group(graph._chartCont,
|
1341
|
+
$.extend({class_: 'yAxisLabels', textAnchor: 'end'}, axis._labelFormat));
|
1342
|
+
graph._wrapper.line(gl, dims[graph.X], dims[graph.Y], dims[graph.X], dims[graph.Y] + dims[graph.H]);
|
1343
|
+
if (axis._ticks.major) {
|
1344
|
+
var offsets = graph._getTickOffsets(axis, false);
|
1345
|
+
for (var i = 1; i < numVal; i++) {
|
1346
|
+
var y = dims[graph.Y] + yScale * (barGap / 2 + i * (barWidth + barGap));
|
1347
|
+
graph._wrapper.line(gl, dims[graph.X] + offsets[0] * axis._ticks.size, y,
|
1348
|
+
dims[graph.X] + offsets[1] * axis._ticks.size, y);
|
1349
|
+
}
|
1350
|
+
for (var i = 0; i < numVal; i++) {
|
1351
|
+
var y = dims[graph.Y] + yScale * (barGap / 2 + (i + 0.5) * (barWidth + barGap));
|
1352
|
+
graph._wrapper.text(gt, dims[graph.X] - axis._ticks.size, y,
|
1353
|
+
(axis._labels ? axis._labels[i] : '' + i));
|
1354
|
+
}
|
1355
|
+
}
|
1356
|
+
}
|
1357
|
+
});
|
1358
|
+
|
1359
|
+
//------------------------------------------------------------------------------
|
1360
|
+
|
1361
|
+
/** Draw a standard line chart.
|
1362
|
+
@module SVGLineChart */
|
1363
|
+
function SVGLineChart() {
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
$.extend(SVGLineChart.prototype, {
|
1367
|
+
|
1368
|
+
/** Retrieve the display title for this chart type.
|
1369
|
+
@return {string} Its title. */
|
1370
|
+
title: function() {
|
1371
|
+
return 'Basic line chart';
|
1372
|
+
},
|
1373
|
+
|
1374
|
+
/** Retrieve a description of this chart type.
|
1375
|
+
@return {string} Its description. */
|
1376
|
+
description: function() {
|
1377
|
+
return 'Compare sets of values as continuous lines.';
|
1378
|
+
},
|
1379
|
+
|
1380
|
+
/** Retrieve a list of the options that may be set for this chart type.
|
1381
|
+
@return {string[]} Its options list. */
|
1382
|
+
options: function() {
|
1383
|
+
return [];
|
1384
|
+
},
|
1385
|
+
|
1386
|
+
/** Actually draw the graph in this type's style.
|
1387
|
+
@param graph {SVGGraph} The graph object. */
|
1388
|
+
drawGraph: function(graph) {
|
1389
|
+
graph._drawChartBackground();
|
1390
|
+
var dims = graph._getDims();
|
1391
|
+
var xScale = dims[graph.W] / (graph.xAxis._scale.max - graph.xAxis._scale.min);
|
1392
|
+
var yScale = dims[graph.H] / (graph.yAxis._scale.max - graph.yAxis._scale.min);
|
1393
|
+
this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
|
1394
|
+
for (var i = 0; i < graph._series.length; i++) {
|
1395
|
+
this._drawSeries(graph, i, dims, xScale, yScale);
|
1396
|
+
}
|
1397
|
+
graph._drawTitle();
|
1398
|
+
graph._drawAxes();
|
1399
|
+
graph._drawLegend();
|
1400
|
+
},
|
1401
|
+
|
1402
|
+
/** Plot an individual series.
|
1403
|
+
@private
|
1404
|
+
@param graph {SVGGraph} The graph object.
|
1405
|
+
@param cur {number} The current series index.
|
1406
|
+
@param dims {number[]} The dimensions of the drawing area.
|
1407
|
+
@param xScale {number} The scaling factor in the horizontal direction.
|
1408
|
+
@param yScale {number} The scaling factor in the vertical direction. */
|
1409
|
+
_drawSeries: function(graph, cur, dims, xScale, yScale) {
|
1410
|
+
var series = graph._series[cur];
|
1411
|
+
var path = graph._wrapper.createPath();
|
1412
|
+
for (var i = 0; i < series._values.length; i++) {
|
1413
|
+
var x = dims[graph.X] + i * xScale;
|
1414
|
+
var y = dims[graph.Y] + (graph.yAxis._scale.max - series._values[i]) * yScale;
|
1415
|
+
if (i === 0) {
|
1416
|
+
path.move(x, y);
|
1417
|
+
}
|
1418
|
+
else {
|
1419
|
+
path.line(x, y);
|
1420
|
+
}
|
1421
|
+
}
|
1422
|
+
var p = graph._wrapper.path(this._chart, path, $.extend({id: 'series' + cur, fill: 'none',
|
1423
|
+
stroke: series._stroke, strokeWidth: series._strokeWidth}, series._settings || {}));
|
1424
|
+
graph._showStatus(p, series._name, 0);
|
1425
|
+
}
|
1426
|
+
});
|
1427
|
+
|
1428
|
+
//------------------------------------------------------------------------------
|
1429
|
+
|
1430
|
+
/** Draw a standard pie chart.
|
1431
|
+
@module SVGPieChart */
|
1432
|
+
function SVGPieChart() {
|
1433
|
+
}
|
1434
|
+
|
1435
|
+
$.extend(SVGPieChart.prototype, {
|
1436
|
+
|
1437
|
+
_options: ['explode (number or number[]) - indexes of sections to explode out of the pie',
|
1438
|
+
'explodeDist (number) - the distance to move an exploded section',
|
1439
|
+
'pieGap (number) - the distance between pies for multiple values'],
|
1440
|
+
|
1441
|
+
/** Retrieve the display title for this chart type.
|
1442
|
+
@return {string} Its title. */
|
1443
|
+
title: function() {
|
1444
|
+
return 'Pie chart';
|
1445
|
+
},
|
1446
|
+
|
1447
|
+
/** Retrieve a description of this chart type.
|
1448
|
+
@return {string} Its description. */
|
1449
|
+
description: function() {
|
1450
|
+
return 'Compare relative sizes of values as contributions to the whole.';
|
1451
|
+
},
|
1452
|
+
|
1453
|
+
/** Retrieve a list of the options that may be set for this chart type.
|
1454
|
+
@return {string[]} Its options list. */
|
1455
|
+
options: function() {
|
1456
|
+
return this._options;
|
1457
|
+
},
|
1458
|
+
|
1459
|
+
/** Actually draw the graph in this type's style.
|
1460
|
+
@param graph {SVGGraph} The graph object. */
|
1461
|
+
drawGraph: function(graph) {
|
1462
|
+
graph._drawChartBackground(true, true);
|
1463
|
+
this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
|
1464
|
+
var dims = graph._getDims();
|
1465
|
+
this._drawSeries(graph, dims);
|
1466
|
+
graph._drawTitle();
|
1467
|
+
graph._drawLegend();
|
1468
|
+
},
|
1469
|
+
|
1470
|
+
/** Plot all the series.
|
1471
|
+
@private
|
1472
|
+
@param graph {SVGGraph} The graph object.
|
1473
|
+
@param dims {number[]} The dimensions of the drawing area. */
|
1474
|
+
_drawSeries: function(graph, dims) {
|
1475
|
+
var totals = graph._getTotals();
|
1476
|
+
var numSer = graph._series.length;
|
1477
|
+
var numVal = (numSer ? (graph._series[0])._values.length : 0);
|
1478
|
+
var path = graph._wrapper.createPath();
|
1479
|
+
var explode = graph._chartOptions.explode || [];
|
1480
|
+
explode = ($.isArray(explode) ? explode : [explode]);
|
1481
|
+
var explodeDist = graph._chartOptions.explodeDist || 10;
|
1482
|
+
var pieGap = (numVal <= 1 ? 0 : graph._chartOptions.pieGap || 10);
|
1483
|
+
var xBase = (dims[graph.W] - (numVal * pieGap) - pieGap) / numVal / 2;
|
1484
|
+
var yBase = dims[graph.H] / 2;
|
1485
|
+
var radius = Math.min(xBase, yBase) - (explode.length > 0 ? explodeDist : 0);
|
1486
|
+
var gt = graph._wrapper.group(graph._chartCont, $.extend(
|
1487
|
+
{class_: 'xAxisLabels', textAnchor: 'middle'}, graph.xAxis._labelFormat));
|
1488
|
+
var gl = [];
|
1489
|
+
for (var i = 0; i < numVal; i++) {
|
1490
|
+
var cx = dims[graph.X] + xBase + (i * (2 * Math.min(xBase, yBase) + pieGap)) + pieGap;
|
1491
|
+
var cy = dims[graph.Y] + yBase;
|
1492
|
+
var curTotal = 0;
|
1493
|
+
for (var j = 0; j < numSer; j++) {
|
1494
|
+
var series = graph._series[j];
|
1495
|
+
if (i === 0) {
|
1496
|
+
gl[j] = graph._wrapper.group(this._chart,
|
1497
|
+
$.extend({class_: 'series' + j, fill: series._fill, stroke: series._stroke,
|
1498
|
+
strokeWidth: series._strokeWidth}, series._settings || {}));
|
1499
|
+
}
|
1500
|
+
if (series._values[i] === 0) {
|
1501
|
+
continue;
|
1502
|
+
}
|
1503
|
+
var start = (curTotal / totals[i]) * 2 * Math.PI;
|
1504
|
+
curTotal += series._values[i];
|
1505
|
+
var end = (curTotal / totals[i]) * 2 * Math.PI;
|
1506
|
+
var exploding = false;
|
1507
|
+
for (var k = 0; k < explode.length; k++) {
|
1508
|
+
if (explode[k] === j) {
|
1509
|
+
exploding = true;
|
1510
|
+
break;
|
1511
|
+
}
|
1512
|
+
}
|
1513
|
+
var x = cx + (exploding ? explodeDist * Math.cos((start + end) / 2) : 0);
|
1514
|
+
var y = cy + (exploding ? explodeDist * Math.sin((start + end) / 2) : 0);
|
1515
|
+
var p = graph._wrapper.path(gl[j], path.reset().move(x, y).
|
1516
|
+
line(x + radius * Math.cos(start), y + radius * Math.sin(start)).
|
1517
|
+
arc(radius, radius, 0, (end - start < Math.PI ? 0 : 1), 1,
|
1518
|
+
x + radius * Math.cos(end), y + radius * Math.sin(end)).close());
|
1519
|
+
graph._showStatus(p, series._name, roundNumber((end - start) / 2 / Math.PI * 100, 2));
|
1520
|
+
}
|
1521
|
+
if (graph.xAxis) {
|
1522
|
+
graph._wrapper.text(gt, cx, dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset,
|
1523
|
+
graph.xAxis._labels[i])
|
1524
|
+
}
|
1525
|
+
}
|
1526
|
+
}
|
1527
|
+
});
|
1528
|
+
|
1529
|
+
//------------------------------------------------------------------------------
|
1530
|
+
|
1531
|
+
// Basic chart types
|
1532
|
+
$.svg.graphing.addChartType('column', new SVGColumnChart());
|
1533
|
+
$.svg.graphing.addChartType('stackedColumn', new SVGStackedColumnChart());
|
1534
|
+
$.svg.graphing.addChartType('row', new SVGRowChart());
|
1535
|
+
$.svg.graphing.addChartType('stackedRow', new SVGStackedRowChart());
|
1536
|
+
$.svg.graphing.addChartType('line', new SVGLineChart());
|
1537
|
+
$.svg.graphing.addChartType('pie', new SVGPieChart());
|
1538
|
+
|
1539
|
+
})(jQuery)
|