jquery-svg-rails 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|