rgraph-rails 1.0.8 → 4.62
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 +4 -4
- data/README.md +3 -3
- data/lib/rgraph-rails/version.rb +1 -1
- data/vendor/assets/javascripts/RGraph.bar.js +16 -8
- data/vendor/assets/javascripts/RGraph.bipolar.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.annotate.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.context.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.core.js +84 -7
- data/vendor/assets/javascripts/RGraph.common.csv.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.deprecated.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.dynamic.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.effects.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.key.js +3 -3
- data/vendor/assets/javascripts/RGraph.common.resizing.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.sheets.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.tooltips.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.zoom.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.background.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.circle.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.image.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.marker1.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.marker2.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.marker3.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.poly.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.rect.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.text.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +1 -1
- data/vendor/assets/javascripts/RGraph.fuel.js +1 -1
- data/vendor/assets/javascripts/RGraph.funnel.js +1 -1
- data/vendor/assets/javascripts/RGraph.gantt.js +1 -1
- data/vendor/assets/javascripts/RGraph.gauge.js +1 -1
- data/vendor/assets/javascripts/RGraph.hbar.js +228 -2
- data/vendor/assets/javascripts/RGraph.hprogress.js +1 -1
- data/vendor/assets/javascripts/RGraph.line.js +27 -5
- data/vendor/assets/javascripts/RGraph.meter.js +1 -1
- data/vendor/assets/javascripts/RGraph.modaldialog.js +1 -1
- data/vendor/assets/javascripts/RGraph.odo.js +1 -1
- data/vendor/assets/javascripts/RGraph.pie.js +1 -1
- data/vendor/assets/javascripts/RGraph.radar.js +1 -1
- data/vendor/assets/javascripts/RGraph.rose.js +1 -1
- data/vendor/assets/javascripts/RGraph.rscatter.js +1 -1
- data/vendor/assets/javascripts/RGraph.scatter.js +161 -34
- data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.bar.js +772 -103
- data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.common.core.js +806 -231
- data/vendor/assets/javascripts/RGraph.svg.common.csv.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.common.fx.js +24 -24
- data/vendor/assets/javascripts/RGraph.svg.common.key.js +206 -0
- data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +63 -22
- data/vendor/assets/javascripts/RGraph.svg.hbar.js +351 -91
- data/vendor/assets/javascripts/RGraph.svg.line.js +159 -64
- data/vendor/assets/javascripts/RGraph.svg.pie.js +402 -51
- data/vendor/assets/javascripts/RGraph.svg.radar.js +320 -143
- data/vendor/assets/javascripts/RGraph.svg.rose.js +1818 -0
- data/vendor/assets/javascripts/RGraph.svg.scatter.js +1262 -0
- data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +106 -57
- data/vendor/assets/javascripts/RGraph.svg.waterfall.js +1253 -0
- data/vendor/assets/javascripts/RGraph.thermometer.js +7 -6
- data/vendor/assets/javascripts/RGraph.vprogress.js +1 -1
- data/vendor/assets/javascripts/RGraph.waterfall.js +1 -1
- data/vendor/assets/javascripts/financial-data.js +1067 -0
- metadata +8 -5
- data/vendor/assets/javascripts/RGraph.cornergauge.js +0 -71
- data/vendor/assets/javascripts/RGraph.thermometer.old.js +0 -68
@@ -0,0 +1,1818 @@
|
|
1
|
+
// version: 2017-05-08
|
2
|
+
/**
|
3
|
+
* o--------------------------------------------------------------------------------o
|
4
|
+
* | This file is part of the RGraph package - you can learn more at: |
|
5
|
+
* | |
|
6
|
+
* | http://www.rgraph.net |
|
7
|
+
* | |
|
8
|
+
* | RGraph is licensed under the Open Source MIT license. That means that it's |
|
9
|
+
* | totally free to use! |
|
10
|
+
* o--------------------------------------------------------------------------------o
|
11
|
+
*/
|
12
|
+
|
13
|
+
RGraph = window.RGraph || {isRGraph: true};
|
14
|
+
RGraph.SVG = RGraph.SVG || {};
|
15
|
+
|
16
|
+
// Module pattern
|
17
|
+
(function (win, doc, undefined)
|
18
|
+
{
|
19
|
+
var RG = RGraph,
|
20
|
+
ua = navigator.userAgent,
|
21
|
+
ma = Math,
|
22
|
+
win = window,
|
23
|
+
doc = document;
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
RG.SVG.Rose = function (conf)
|
28
|
+
{
|
29
|
+
//
|
30
|
+
// A setter that the constructor uses (at the end)
|
31
|
+
// to set all of the properties
|
32
|
+
//
|
33
|
+
// @param string name The name of the property to set
|
34
|
+
// @param string value The value to set the property to
|
35
|
+
//
|
36
|
+
this.set = function (name, value)
|
37
|
+
{
|
38
|
+
if (arguments.length === 1 && typeof name === 'object') {
|
39
|
+
for (i in arguments[0]) {
|
40
|
+
if (typeof i === 'string') {
|
41
|
+
|
42
|
+
var ret = RG.SVG.commonSetter({
|
43
|
+
object: this,
|
44
|
+
name: i,
|
45
|
+
value: arguments[0][i]
|
46
|
+
});
|
47
|
+
|
48
|
+
name = ret.name;
|
49
|
+
value = ret.value;
|
50
|
+
|
51
|
+
this.set(name, value);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
} else {
|
56
|
+
|
57
|
+
var ret = RG.SVG.commonSetter({
|
58
|
+
object: this,
|
59
|
+
name: name,
|
60
|
+
value: value
|
61
|
+
});
|
62
|
+
|
63
|
+
name = ret.name;
|
64
|
+
value = ret.value;
|
65
|
+
|
66
|
+
this.properties[name] = value;
|
67
|
+
}
|
68
|
+
|
69
|
+
return this;
|
70
|
+
};
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
this.id = conf.id;
|
80
|
+
this.uid = RG.SVG.createUID();
|
81
|
+
this.container = document.getElementById(this.id);
|
82
|
+
this.svg = RG.SVG.createSVG({container: this.container});
|
83
|
+
this.isRGraph = true;
|
84
|
+
this.width = Number(this.svg.getAttribute('width'));
|
85
|
+
this.height = Number(this.svg.getAttribute('height'));
|
86
|
+
this.data = RG.SVG.arrayClone(conf.data);
|
87
|
+
this.originalData = RG.SVG.arrayClone(conf.data);
|
88
|
+
this.type = 'rose';
|
89
|
+
this.angles = [];
|
90
|
+
this.angles2 = [];
|
91
|
+
this.colorsParsed = false;
|
92
|
+
this.originalColors = {};
|
93
|
+
this.gradientCounter = 1;
|
94
|
+
this.nodes = [];
|
95
|
+
this.shadowNodes = [];
|
96
|
+
this.max = 0;
|
97
|
+
this.redraw = false;
|
98
|
+
this.highlight_node = null;
|
99
|
+
|
100
|
+
// Add this object to the ObjectRegistry
|
101
|
+
RG.SVG.OR.add(this);
|
102
|
+
|
103
|
+
// Set the DIV container to be inline-block
|
104
|
+
this.container.style.display = 'inline-block';
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
this.properties =
|
113
|
+
{
|
114
|
+
centerx: null,
|
115
|
+
centery: null,
|
116
|
+
radius: null,
|
117
|
+
|
118
|
+
gutterLeft: 35,
|
119
|
+
gutterRight: 35,
|
120
|
+
gutterTop: 35,
|
121
|
+
gutterBottom: 35,
|
122
|
+
|
123
|
+
backgroundGrid: true,
|
124
|
+
backgroundGridColor: '#ddd',
|
125
|
+
backgroundGridRadialsCount: null,
|
126
|
+
backgroundGridRadialsAngleOffset: 0,
|
127
|
+
backgroundGridConcentricsCount: 5,
|
128
|
+
backgroundGridLinewidth: 1,
|
129
|
+
|
130
|
+
strokestyle: 'white',
|
131
|
+
colors: [
|
132
|
+
'red', 'black', 'orange', 'green', '#6ff', '#ccc',
|
133
|
+
'pink', 'orange', 'cyan', 'maroon', 'olive', 'teal'
|
134
|
+
],
|
135
|
+
colorsOpacity: 1,
|
136
|
+
|
137
|
+
textColor: 'black',
|
138
|
+
textFont: 'sans-serif',
|
139
|
+
textSize: 12,
|
140
|
+
textBold: false,
|
141
|
+
textItalic: false,
|
142
|
+
|
143
|
+
labels: [],
|
144
|
+
labelsFont: null,
|
145
|
+
labelsSize: null,
|
146
|
+
labelsColor: null,
|
147
|
+
labelsBold: null,
|
148
|
+
labelsItalic: null,
|
149
|
+
labelsRadialMargin: 10,
|
150
|
+
labelsAngleOffset: 0,
|
151
|
+
|
152
|
+
scaleVisible: true,
|
153
|
+
scaleUnitsPre: '',
|
154
|
+
scaleUnitsPost: '',
|
155
|
+
scaleMax: null,
|
156
|
+
scaleMin: 0,
|
157
|
+
scalePoint: '.',
|
158
|
+
scaleThousand: ',',
|
159
|
+
scaleRound: false,
|
160
|
+
scaleDecimals: 0,
|
161
|
+
scaleFormatter: null,
|
162
|
+
scaleBold: null,
|
163
|
+
scaleItalic: null,
|
164
|
+
scaleColor: null,
|
165
|
+
scaleSize: null,
|
166
|
+
scaleFont: null,
|
167
|
+
scaleLabelsCount: 5,
|
168
|
+
|
169
|
+
linewidth: 1,
|
170
|
+
|
171
|
+
tooltips: null,
|
172
|
+
tooltipsOverride: null,
|
173
|
+
tooltipsEffect: 'fade',
|
174
|
+
tooltipsCssClass: 'RGraph_tooltip',
|
175
|
+
tooltipsEvent: 'click',
|
176
|
+
|
177
|
+
highlightStroke: 'rgba(0,0,0,0)',
|
178
|
+
highlightFill: 'rgba(255,255,255,0.7)',
|
179
|
+
highlightLinewidth: 1,
|
180
|
+
|
181
|
+
title: '',
|
182
|
+
titleSize: 16,
|
183
|
+
titleX: null,
|
184
|
+
titleY: null,
|
185
|
+
titleHalign: 'center',
|
186
|
+
titleValign: null,
|
187
|
+
titleColor: 'black',
|
188
|
+
titleFont: null,
|
189
|
+
titleBold: false,
|
190
|
+
titleItalic: false,
|
191
|
+
|
192
|
+
titleSubtitle: '',
|
193
|
+
titleSubtitleSize: 10,
|
194
|
+
titleSubtitleX: null,
|
195
|
+
titleSubtitleY: null,
|
196
|
+
titleSubtitleHalign: 'center',
|
197
|
+
titleSubtitleValign: null,
|
198
|
+
titleSubtitleColor: '#aaa',
|
199
|
+
titleSubtitleFont: null,
|
200
|
+
titleSubtitleBold: false,
|
201
|
+
titleSubtitleItalic: false,
|
202
|
+
|
203
|
+
shadow: false,
|
204
|
+
shadowOffsetx: 2,
|
205
|
+
shadowOffsety: 2,
|
206
|
+
shadowBlur: 2,
|
207
|
+
shadowOpacity: 0.25,
|
208
|
+
|
209
|
+
margin: 0,
|
210
|
+
exploded: 0,
|
211
|
+
|
212
|
+
|
213
|
+
key: null,
|
214
|
+
keyColors: null,
|
215
|
+
keyOffsetx: 0,
|
216
|
+
keyOffsety: 0,
|
217
|
+
keyTextOffsetx: 0,
|
218
|
+
keyTextOffsety: -1,
|
219
|
+
keyTextSize: null,
|
220
|
+
keyTextBold: null,
|
221
|
+
keyTextItalic: null,
|
222
|
+
|
223
|
+
attribution: true,
|
224
|
+
attributionX: null,
|
225
|
+
attributionY: null,
|
226
|
+
attributionHref: null,// Default is set in RGraph.svg.common.core.js
|
227
|
+
attributionHalign: 'right',
|
228
|
+
attributionValign: 'bottom',
|
229
|
+
attributionSize: 7,
|
230
|
+
attributionColor: 'gray',
|
231
|
+
attributionFont: 'sans-serif',
|
232
|
+
attributionItalic: false,
|
233
|
+
attributionBold: false,
|
234
|
+
|
235
|
+
segmentsAngleOffset: 0,
|
236
|
+
variant: 'normal'
|
237
|
+
};
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
|
244
|
+
/**
|
245
|
+
* "Decorate" the object with the generic effects if the effects library has been included
|
246
|
+
*/
|
247
|
+
if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
|
248
|
+
RG.SVG.FX.decorate(this);
|
249
|
+
}
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
var prop = this.properties;
|
255
|
+
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
//
|
264
|
+
// The draw method draws the Bar chart
|
265
|
+
//
|
266
|
+
this.draw = function ()
|
267
|
+
{
|
268
|
+
// Fire the beforedraw event
|
269
|
+
RG.SVG.fireCustomEvent(this, 'onbeforedraw');
|
270
|
+
|
271
|
+
|
272
|
+
|
273
|
+
// Reset the data back to the original values
|
274
|
+
this.data = RG.SVG.arrayClone(this.originalData);
|
275
|
+
|
276
|
+
|
277
|
+
|
278
|
+
// Reset the angles array to stop it growing
|
279
|
+
this.angles = [];
|
280
|
+
|
281
|
+
|
282
|
+
// Create the arrays in the angles2 array based on
|
283
|
+
// the data that we've been passed
|
284
|
+
for (var i=0; i<this.data.length; ++i) {
|
285
|
+
this.angles2[i] = [];
|
286
|
+
}
|
287
|
+
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
// Create the defs tag if necessary
|
293
|
+
RG.SVG.createDefs(this);
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
|
299
|
+
this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
// Work out the center point
|
304
|
+
this.centerx = (this.graphWidth / 2) + prop.gutterLeft;
|
305
|
+
this.centery = (this.graphHeight / 2) + prop.gutterTop;
|
306
|
+
this.radius = ma.min(this.graphWidth, this.graphHeight) / 2;
|
307
|
+
|
308
|
+
|
309
|
+
|
310
|
+
// Allow the user to override the calculated centerx/y/radius
|
311
|
+
this.centerx = typeof prop.centerx === 'number' ? prop.centerx : this.centerx;
|
312
|
+
this.centery = typeof prop.centery === 'number' ? prop.centery : this.centery;
|
313
|
+
this.radius = typeof prop.radius === 'number' ? prop.radius : this.radius;
|
314
|
+
|
315
|
+
//
|
316
|
+
// Allow the centerx/centery/radius to be a plus/minus
|
317
|
+
//
|
318
|
+
if (typeof prop.radius === 'string' && prop.radius.match(/^\+|-\d+$/) ) this.radius += parseFloat(prop.radius);
|
319
|
+
if (typeof prop.centerx === 'string' && prop.centerx.match(/^\+|-\d+$/) ) this.centery += parseFloat(prop.centerx);
|
320
|
+
if (typeof prop.centery === 'string' && prop.centery.match(/^\+|-\d+$/) ) this.centerx += parseFloat(prop.centery);
|
321
|
+
|
322
|
+
|
323
|
+
|
324
|
+
|
325
|
+
|
326
|
+
//
|
327
|
+
// Convert the nargin from strings to a number
|
328
|
+
//
|
329
|
+
if (typeof prop.margin === 'string' && prop.margin.match(/([0-9.]+)deg/)) {
|
330
|
+
prop.margin = RegExp.$1 / (180 / ma.PI);
|
331
|
+
}
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
|
336
|
+
/**
|
337
|
+
* Add the data to the .originalData array and work out the max value
|
338
|
+
*
|
339
|
+
* 2/5/14 Now also use this loop to ensure that the data pieces
|
340
|
+
* are numbers
|
341
|
+
*
|
342
|
+
* **Is this necessary **
|
343
|
+
*/
|
344
|
+
//if (RG.SVG.isArray(this.data) && (typeof this.data[0] === 'number' || typeof this.data[0] === 'string')) {
|
345
|
+
// this.data = [this.data];
|
346
|
+
//}
|
347
|
+
|
348
|
+
// Convert strings to numbers
|
349
|
+
for (var i=0; i<this.data.length; ++i) {
|
350
|
+
if (typeof this.data[i] === 'object') {
|
351
|
+
for (var j=0; j<this.data[i].length; ++j) {
|
352
|
+
if (typeof this.data[i][j] === 'string') {
|
353
|
+
this.data[i][j] = RG.SVG.stringsToNumbers(this.data[i][j]);
|
354
|
+
}
|
355
|
+
}
|
356
|
+
} else if (typeof this.data[i] === 'string') {
|
357
|
+
this.data[i] = RG.SVG.stringsToNumbers(this.data[i]);
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
|
362
|
+
|
363
|
+
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
|
368
|
+
|
369
|
+
// Get the max value. This sets the maximum value on the
|
370
|
+
// this.max variable
|
371
|
+
this.getMaxValue();
|
372
|
+
|
373
|
+
|
374
|
+
|
375
|
+
|
376
|
+
|
377
|
+
|
378
|
+
|
379
|
+
// Parse the colors for gradients
|
380
|
+
RG.SVG.resetColorsToOriginalValues({object:this});
|
381
|
+
this.parseColors();
|
382
|
+
|
383
|
+
//
|
384
|
+
// Get the scale
|
385
|
+
//
|
386
|
+
|
387
|
+
this.scale = RG.SVG.getScale({
|
388
|
+
object: this,
|
389
|
+
numlabels: typeof prop.scaleLabelsCount === 'number' ? prop.scaleLabelsCount : prop.backgroundGridConcentricCount,
|
390
|
+
unitsPre: prop.scaleUnitsPre,
|
391
|
+
unitsPost: prop.scaleUnitsPost,
|
392
|
+
max: typeof prop.scaleMax === 'number' ? prop.scaleMax : this.max,
|
393
|
+
min: prop.scaleMin,
|
394
|
+
point: prop.scalePoint,
|
395
|
+
round: prop.scaleRound,
|
396
|
+
thousand: prop.scaleThousand,
|
397
|
+
decimals: prop.scaleDecimals,
|
398
|
+
strict: typeof prop.scaleMax === 'number',
|
399
|
+
formatter: prop.scaleFormatter
|
400
|
+
});
|
401
|
+
|
402
|
+
this.max = this.scale.max;
|
403
|
+
|
404
|
+
|
405
|
+
|
406
|
+
// Draw the background 'grid'
|
407
|
+
this.drawBackground();
|
408
|
+
|
409
|
+
|
410
|
+
|
411
|
+
// Draw the chart
|
412
|
+
this.drawRose();
|
413
|
+
|
414
|
+
|
415
|
+
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
// Draw the labels
|
420
|
+
this.drawLabels();
|
421
|
+
|
422
|
+
|
423
|
+
|
424
|
+
// Draw the title and subtitle
|
425
|
+
RG.SVG.drawTitle(this);
|
426
|
+
|
427
|
+
|
428
|
+
|
429
|
+
|
430
|
+
|
431
|
+
|
432
|
+
// Draw the key
|
433
|
+
if (typeof prop.key !== null && RG.SVG.drawKey) {
|
434
|
+
RG.SVG.drawKey(this);
|
435
|
+
} else if (!RGraph.SVG.isNull(prop.key)) {
|
436
|
+
alert('The drawKey() function does not exist - have you forgotten to include the key library?');
|
437
|
+
}
|
438
|
+
|
439
|
+
|
440
|
+
|
441
|
+
|
442
|
+
|
443
|
+
// Add the attribution link. If you're adding this elsewhere on your page/site
|
444
|
+
// and you don't want it displayed then there are options available to not
|
445
|
+
// show it.
|
446
|
+
RG.SVG.attribution(this);
|
447
|
+
|
448
|
+
// Create the shadow definition if needed
|
449
|
+
if (prop.shadow) {
|
450
|
+
RG.SVG.setShadow({
|
451
|
+
object: this,
|
452
|
+
offsetx: prop.shadowOffsetx,
|
453
|
+
offsety: prop.shadowOffsety,
|
454
|
+
blur: prop.shadowBlur,
|
455
|
+
opacity: prop.shadowOpacity,
|
456
|
+
id: 'dropShadow'
|
457
|
+
});
|
458
|
+
}
|
459
|
+
|
460
|
+
|
461
|
+
|
462
|
+
// Add the event listener that clears the highlight if
|
463
|
+
// there is any. Must be MOUSEDOWN (ie before the click event)
|
464
|
+
var obj = this;
|
465
|
+
doc.body.addEventListener('mousedown', function (e)
|
466
|
+
{
|
467
|
+
obj.hideHighlight(obj);
|
468
|
+
}, false);
|
469
|
+
|
470
|
+
|
471
|
+
|
472
|
+
// Fire the draw event
|
473
|
+
RG.SVG.fireCustomEvent(this, 'ondraw');
|
474
|
+
|
475
|
+
|
476
|
+
|
477
|
+
return this;
|
478
|
+
};
|
479
|
+
|
480
|
+
|
481
|
+
|
482
|
+
|
483
|
+
|
484
|
+
|
485
|
+
|
486
|
+
|
487
|
+
//
|
488
|
+
// Draw the background grid
|
489
|
+
//
|
490
|
+
this.drawBackground = function ()
|
491
|
+
{
|
492
|
+
if (prop.backgroundGrid) {
|
493
|
+
|
494
|
+
// Create the background grid group tag
|
495
|
+
var grid = RG.SVG.create({
|
496
|
+
svg: this.svg,
|
497
|
+
parent: this.svg.all,
|
498
|
+
type: 'g',
|
499
|
+
attr: {
|
500
|
+
className: 'rgraph_radar_grid',
|
501
|
+
fill: 'rgba(0,0,0,0)',
|
502
|
+
stroke: prop.backgroundGridColor
|
503
|
+
}
|
504
|
+
});
|
505
|
+
|
506
|
+
// Draw the concentric "rings" grid lines that are
|
507
|
+
// arranged around the centerx/centery along with
|
508
|
+
// the radials that eminate from the center outwards
|
509
|
+
|
510
|
+
var origin = 0 - (RG.SVG.TRIG.PI / 2),
|
511
|
+
radials = (typeof prop.backgroundGridRadialsCount === 'number' ? prop.backgroundGridRadialsCount : this.data.length),
|
512
|
+
concentrics = prop.backgroundGridConcentricsCount,
|
513
|
+
step = RG.SVG.TRIG.TWOPI / radials;
|
514
|
+
|
515
|
+
|
516
|
+
|
517
|
+
|
518
|
+
|
519
|
+
// First draw the radial lines that emanate from the
|
520
|
+
// center outwards
|
521
|
+
if (radials > 0) {
|
522
|
+
// This draws the radials for the non-equi-angular ONLY
|
523
|
+
if (prop.variant === 'non-equi-angular') {
|
524
|
+
|
525
|
+
|
526
|
+
|
527
|
+
|
528
|
+
|
529
|
+
|
530
|
+
|
531
|
+
|
532
|
+
|
533
|
+
|
534
|
+
|
535
|
+
|
536
|
+
|
537
|
+
|
538
|
+
// Number of radials always matches the number of data pieces
|
539
|
+
var radials = this.data.length;
|
540
|
+
|
541
|
+
// Work out the total of the second part of each data bit
|
542
|
+
for (var i=0,total=0; i<this.data.length; ++i) {
|
543
|
+
total += this.data[i][1];
|
544
|
+
}
|
545
|
+
|
546
|
+
for (var i=0,sum=0; i<this.data.length; ++i) {
|
547
|
+
|
548
|
+
var coords = RG.SVG.TRIG.toCartesian({
|
549
|
+
cx: this.centerx,
|
550
|
+
cy: this.centery,
|
551
|
+
r: this.radius,
|
552
|
+
angle: origin + ( (sum / total) * RG.SVG.TRIG.TWOPI) + prop.backgroundGridRadialsAngleOffset
|
553
|
+
});
|
554
|
+
|
555
|
+
var str = 'M {1} {2} L {3} {4}'.format(
|
556
|
+
this.centerx,
|
557
|
+
this.centery,
|
558
|
+
coords.x,
|
559
|
+
coords.y
|
560
|
+
);
|
561
|
+
|
562
|
+
RG.SVG.create({
|
563
|
+
svg: this.svg,
|
564
|
+
type: 'path',
|
565
|
+
parent: grid,
|
566
|
+
attr: {
|
567
|
+
d: str,
|
568
|
+
stroke: prop.backgroundGridColor,
|
569
|
+
'stroke-width': prop.backgroundGridLinewidth
|
570
|
+
}
|
571
|
+
});
|
572
|
+
|
573
|
+
sum += this.data[i][1];
|
574
|
+
}
|
575
|
+
|
576
|
+
|
577
|
+
|
578
|
+
|
579
|
+
|
580
|
+
|
581
|
+
|
582
|
+
|
583
|
+
|
584
|
+
|
585
|
+
|
586
|
+
|
587
|
+
// This draws the radials for normal and STACKED Rose charts
|
588
|
+
} else {
|
589
|
+
for (var i=0,len=radials; i<len; ++i) {
|
590
|
+
|
591
|
+
var coords = RG.SVG.TRIG.toCartesian({
|
592
|
+
cx: this.centerx,
|
593
|
+
cy: this.centery,
|
594
|
+
r: this.radius,
|
595
|
+
angle: origin + (i * step) + prop.backgroundGridRadialsAngleOffset
|
596
|
+
});
|
597
|
+
|
598
|
+
var str = 'M {1} {2} L {3} {4}'.format(
|
599
|
+
this.centerx,
|
600
|
+
this.centery,
|
601
|
+
coords.x,
|
602
|
+
coords.y
|
603
|
+
);
|
604
|
+
|
605
|
+
RG.SVG.create({
|
606
|
+
svg: this.svg,
|
607
|
+
type: 'path',
|
608
|
+
parent: grid,
|
609
|
+
attr: {
|
610
|
+
d: str,
|
611
|
+
stroke: prop.backgroundGridColor,
|
612
|
+
'stroke-width': prop.backgroundGridLinewidth
|
613
|
+
}
|
614
|
+
});
|
615
|
+
}
|
616
|
+
}
|
617
|
+
}
|
618
|
+
|
619
|
+
|
620
|
+
|
621
|
+
|
622
|
+
|
623
|
+
// Draw the concentrics
|
624
|
+
if (concentrics > 0) {
|
625
|
+
|
626
|
+
for (var j=1; j<=concentrics; j++) {
|
627
|
+
|
628
|
+
// Add circle to the scene
|
629
|
+
RG.SVG.create({
|
630
|
+
svg: this.svg,
|
631
|
+
type: 'circle',
|
632
|
+
parent: grid,
|
633
|
+
attr: {
|
634
|
+
cx: this.centerx,
|
635
|
+
cy: this.centery,
|
636
|
+
r: this.radius * (j/concentrics),
|
637
|
+
fill: 'transparent',
|
638
|
+
stroke: prop.backgroundGridColor,
|
639
|
+
'stroke-width': prop.backgroundGridLinewidth
|
640
|
+
}
|
641
|
+
});
|
642
|
+
}
|
643
|
+
}
|
644
|
+
}
|
645
|
+
};
|
646
|
+
|
647
|
+
|
648
|
+
|
649
|
+
|
650
|
+
|
651
|
+
|
652
|
+
|
653
|
+
|
654
|
+
//
|
655
|
+
// Draws the radar
|
656
|
+
//
|
657
|
+
this.drawRose = function (opt)
|
658
|
+
{
|
659
|
+
// Jump to another function if we're drawing a non-equi-angular chart
|
660
|
+
if (prop.variant === 'non-equi-angular') {
|
661
|
+
return this.drawRoseNonEquiAngular(opt);
|
662
|
+
}
|
663
|
+
|
664
|
+
|
665
|
+
|
666
|
+
|
667
|
+
|
668
|
+
|
669
|
+
var radians = RG.SVG.TRIG.TWOPI / this.data.length;
|
670
|
+
|
671
|
+
var group = RG.SVG.create({
|
672
|
+
svg: this.svg,
|
673
|
+
type:'g',
|
674
|
+
parent: this.svg.all,
|
675
|
+
attr: {
|
676
|
+
id: 'rgraph_rose_segments_' + this.id
|
677
|
+
}
|
678
|
+
});
|
679
|
+
|
680
|
+
|
681
|
+
// Now loop thru the data
|
682
|
+
for (var i=0,seq=0; i<this.data.length; ++i,++seq) {
|
683
|
+
|
684
|
+
var radius = (this.data[i] / this.scale.max) * this.radius,
|
685
|
+
start = (i / this.data.length) * RG.SVG.TRIG.TWOPI,
|
686
|
+
end = ((i / this.data.length) * RG.SVG.TRIG.TWOPI) + radians;
|
687
|
+
|
688
|
+
// Get the exploded distance
|
689
|
+
var explosion = this.getExploded({
|
690
|
+
index: i,
|
691
|
+
start: start - RG.SVG.TRIG.HALFPI,
|
692
|
+
end: end - RG.SVG.TRIG.HALFPI
|
693
|
+
});
|
694
|
+
|
695
|
+
|
696
|
+
|
697
|
+
|
698
|
+
|
699
|
+
|
700
|
+
|
701
|
+
|
702
|
+
|
703
|
+
|
704
|
+
|
705
|
+
|
706
|
+
|
707
|
+
|
708
|
+
|
709
|
+
|
710
|
+
|
711
|
+
|
712
|
+
|
713
|
+
// Is the data piece an array or a number?
|
714
|
+
if (typeof this.data[i] === 'object' && !RG.SVG.isNull(this.data[i])) {
|
715
|
+
|
716
|
+
// Create a group for the parts of this segment
|
717
|
+
var segment_group = RG.SVG.create({
|
718
|
+
svg: this.svg,
|
719
|
+
type: 'g',
|
720
|
+
parent: group,
|
721
|
+
attr: {
|
722
|
+
id: 'rose_' + this.id + '_segment_group_' + i
|
723
|
+
}
|
724
|
+
});
|
725
|
+
|
726
|
+
for (var j=0,sum=0,accRadius=0; j<this.data[i].length; ++j,++seq) {
|
727
|
+
|
728
|
+
sum += this.data[i][j];
|
729
|
+
|
730
|
+
var radius = (sum / this.scale.max) * this.radius;
|
731
|
+
|
732
|
+
// This (I think is the OUTER curve in the segment
|
733
|
+
var arcPath = RG.SVG.TRIG.getArcPath2({
|
734
|
+
cx: this.centerx + explosion[0],
|
735
|
+
cy: this.centery + explosion[1],
|
736
|
+
r: radius,
|
737
|
+
start: start + prop.margin + prop.segmentsAngleOffset,
|
738
|
+
end: end - prop.margin + prop.segmentsAngleOffset,
|
739
|
+
anticlockwise: false
|
740
|
+
});
|
741
|
+
|
742
|
+
// The inner most segment
|
743
|
+
if (j === 0) {
|
744
|
+
arcPath = '{1} z'.format(
|
745
|
+
arcPath
|
746
|
+
);
|
747
|
+
} else {
|
748
|
+
|
749
|
+
var arcPath2 = RG.SVG.TRIG.getArcPath2({
|
750
|
+
cx: this.centerx + explosion[0],
|
751
|
+
cy: this.centery + explosion[1],
|
752
|
+
r: prevRadius,
|
753
|
+
start: end - prop.margin + prop.segmentsAngleOffset,
|
754
|
+
end: start + prop.margin + prop.segmentsAngleOffset,
|
755
|
+
anticlockwise: true
|
756
|
+
});
|
757
|
+
arcPath = '{1} L {2} {3} {4}'.format(
|
758
|
+
arcPath,
|
759
|
+
this.centerx + explosion[0],
|
760
|
+
this.centery + explosion[1],
|
761
|
+
arcPath2
|
762
|
+
);
|
763
|
+
}
|
764
|
+
|
765
|
+
var path = RG.SVG.create({
|
766
|
+
svg: this.svg,
|
767
|
+
type: 'path',
|
768
|
+
parent: segment_group,
|
769
|
+
attr: {
|
770
|
+
d: arcPath,
|
771
|
+
fill: prop.colorsSequential ? prop.colors[seq] : prop.colors[j],
|
772
|
+
'fill-opacity': prop.colorsOpacity,
|
773
|
+
stroke: prop.strokestyle,
|
774
|
+
'stroke-width': prop.linewidth,
|
775
|
+
|
776
|
+
'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[seq] : '',
|
777
|
+
'data-index': i,
|
778
|
+
'data-centerx': this.centerx + explosion[0],
|
779
|
+
'data-centery': this.centery + explosion[1],
|
780
|
+
'data-group': i,
|
781
|
+
'data-subindex': j,
|
782
|
+
'data-value': this.data[i][j],
|
783
|
+
'data-start-angle': start,
|
784
|
+
'data-end-angle': end,
|
785
|
+
'data-radius': radius,
|
786
|
+
'data-radius-inner': typeof prevRadius === 'number' ? prevRadius : 0,
|
787
|
+
'data-sequential-index': seq
|
788
|
+
}
|
789
|
+
});
|
790
|
+
|
791
|
+
|
792
|
+
// Install the tooltip listener
|
793
|
+
if (prop.tooltips && prop.tooltips[seq]) {
|
794
|
+
|
795
|
+
// Make the tooltipsEvent default to click
|
796
|
+
if (prop.tooltipsEvent !== 'mousemove') {
|
797
|
+
prop.tooltipsEvent = 'click';
|
798
|
+
}
|
799
|
+
|
800
|
+
(function (index, group, seq, obj)
|
801
|
+
{
|
802
|
+
path.addEventListener(prop.tooltipsEvent, function (e)
|
803
|
+
{
|
804
|
+
obj.removeHighlight();
|
805
|
+
|
806
|
+
// Show the tooltip
|
807
|
+
RG.SVG.tooltip({
|
808
|
+
object: obj,
|
809
|
+
group: group,
|
810
|
+
index: index,
|
811
|
+
sequentialIndex: seq,
|
812
|
+
text: prop.tooltips[seq],
|
813
|
+
event: e
|
814
|
+
});
|
815
|
+
|
816
|
+
// Highlight the rect that has been clicked on
|
817
|
+
obj.highlight(e.target);
|
818
|
+
|
819
|
+
var highlight = RG.SVG.REG.get('highlight');
|
820
|
+
|
821
|
+
if (prop.tooltipsEvent === 'mousemove') {
|
822
|
+
highlight.style.cursor = 'pointer';
|
823
|
+
}
|
824
|
+
|
825
|
+
}, false);
|
826
|
+
|
827
|
+
// Install the event listener that changes the
|
828
|
+
// cursor if necessary
|
829
|
+
if (prop.tooltipsEvent === 'click') {
|
830
|
+
path.addEventListener('mousemove', function (e)
|
831
|
+
{
|
832
|
+
e.target.style.cursor = 'pointer';
|
833
|
+
}, false);
|
834
|
+
}
|
835
|
+
|
836
|
+
}(j, i, seq, this));
|
837
|
+
}
|
838
|
+
|
839
|
+
// Add the segment to the angles and angles2 array
|
840
|
+
this.angles.push({
|
841
|
+
object: path,
|
842
|
+
index: seq,
|
843
|
+
cx: this.centerx + explosion[0],
|
844
|
+
cy: this.centery + explosion[1],
|
845
|
+
start: start,
|
846
|
+
end: end,
|
847
|
+
radius: radius,
|
848
|
+
'radius-inner': prevRadius,
|
849
|
+
value: this.data[i][j]
|
850
|
+
});
|
851
|
+
|
852
|
+
this.angles2[i].push({
|
853
|
+
object: path,
|
854
|
+
index: seq,
|
855
|
+
cx: this.centerx + explosion[0],
|
856
|
+
cy: this.centery + explosion[1],
|
857
|
+
start: start,
|
858
|
+
end: end,
|
859
|
+
radius: radius,
|
860
|
+
'radius-inner': prevRadius,
|
861
|
+
value: this.data[i][j]
|
862
|
+
});
|
863
|
+
|
864
|
+
var prevRadius = radius;
|
865
|
+
}
|
866
|
+
|
867
|
+
|
868
|
+
|
869
|
+
|
870
|
+
|
871
|
+
|
872
|
+
|
873
|
+
|
874
|
+
|
875
|
+
|
876
|
+
seq--;
|
877
|
+
|
878
|
+
|
879
|
+
|
880
|
+
|
881
|
+
|
882
|
+
|
883
|
+
|
884
|
+
|
885
|
+
|
886
|
+
|
887
|
+
|
888
|
+
|
889
|
+
|
890
|
+
// A regular number
|
891
|
+
} else {
|
892
|
+
|
893
|
+
var arcPath = RG.SVG.TRIG.getArcPath2({
|
894
|
+
cx: this.centerx + explosion[0],
|
895
|
+
cy: this.centery + explosion[1],
|
896
|
+
r: radius,
|
897
|
+
start: start + prop.margin + prop.segmentsAngleOffset,
|
898
|
+
end: end - prop.margin + prop.segmentsAngleOffset,
|
899
|
+
anticlockwise: false
|
900
|
+
});
|
901
|
+
|
902
|
+
var path = RG.SVG.create({
|
903
|
+
svg: this.svg,
|
904
|
+
type: 'path',
|
905
|
+
parent: group,
|
906
|
+
attr: {
|
907
|
+
d: '{1} z'.format(
|
908
|
+
arcPath
|
909
|
+
),
|
910
|
+
fill: prop.colorsSequential ? prop.colors[i] : prop.colors[0],
|
911
|
+
'fill-opacity': prop.colorsOpacity,
|
912
|
+
stroke: prop.strokestyle,
|
913
|
+
'stroke-width': prop.linewidth,
|
914
|
+
|
915
|
+
'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
|
916
|
+
'data-index': i,
|
917
|
+
'data-centerx': this.centerx + explosion[0],
|
918
|
+
'data-centery': this.centery + explosion[1],
|
919
|
+
'data-value': this.data[i],
|
920
|
+
'data-start-angle': start,
|
921
|
+
'data-end-angle': end,
|
922
|
+
'data-radius': radius,
|
923
|
+
'data-sequential': seq
|
924
|
+
}
|
925
|
+
});
|
926
|
+
|
927
|
+
// Add the segment to the angles array
|
928
|
+
this.angles.push({
|
929
|
+
object: path,
|
930
|
+
index: i,
|
931
|
+
cx: this.centerx + explosion[0],
|
932
|
+
cy: this.centery + explosion[1],
|
933
|
+
start: start,
|
934
|
+
end: end,
|
935
|
+
radius: radius,
|
936
|
+
value: this.data[i]
|
937
|
+
});
|
938
|
+
|
939
|
+
this.angles2[i].push({
|
940
|
+
object: path,
|
941
|
+
index: seq,
|
942
|
+
cx: this.centerx + explosion[0],
|
943
|
+
cy: this.centery + explosion[1],
|
944
|
+
start: start,
|
945
|
+
end: end,
|
946
|
+
radius: radius,
|
947
|
+
'radius-inner': prevRadius,
|
948
|
+
value: this.data[i][j]
|
949
|
+
});
|
950
|
+
|
951
|
+
|
952
|
+
|
953
|
+
|
954
|
+
if (prop.tooltips && prop.tooltips[i]) {
|
955
|
+
|
956
|
+
// Make the tooltipsEvent default to click
|
957
|
+
if (prop.tooltipsEvent !== 'mousemove') {
|
958
|
+
prop.tooltipsEvent = 'click';
|
959
|
+
}
|
960
|
+
|
961
|
+
(function (index, obj)
|
962
|
+
{
|
963
|
+
path.addEventListener(prop.tooltipsEvent, function (e)
|
964
|
+
{
|
965
|
+
obj.removeHighlight();
|
966
|
+
|
967
|
+
// Show the tooltip
|
968
|
+
RG.SVG.tooltip({
|
969
|
+
object: obj,
|
970
|
+
index: index,
|
971
|
+
group: index,
|
972
|
+
sequentialIndex: index,
|
973
|
+
text: prop.tooltips[index],
|
974
|
+
event: e
|
975
|
+
});
|
976
|
+
|
977
|
+
// Highlight the rect that has been clicked on
|
978
|
+
obj.highlight(e.target);
|
979
|
+
|
980
|
+
var highlight = RG.SVG.REG.get('highlight');
|
981
|
+
|
982
|
+
if (prop.tooltipsEvent === 'mousemove') {
|
983
|
+
highlight.style.cursor = 'pointer';
|
984
|
+
}
|
985
|
+
|
986
|
+
}, false);
|
987
|
+
|
988
|
+
// Install the event listener that changes the
|
989
|
+
// cursor if necessary
|
990
|
+
if (prop.tooltipsEvent === 'click') {
|
991
|
+
path.addEventListener('mousemove', function (e)
|
992
|
+
{
|
993
|
+
e.target.style.cursor = 'pointer';
|
994
|
+
}, false);
|
995
|
+
}
|
996
|
+
|
997
|
+
}(i, this));
|
998
|
+
}
|
999
|
+
}
|
1000
|
+
}
|
1001
|
+
};
|
1002
|
+
|
1003
|
+
|
1004
|
+
|
1005
|
+
|
1006
|
+
|
1007
|
+
|
1008
|
+
|
1009
|
+
|
1010
|
+
//
|
1011
|
+
// Draws the radar, but only the non-equi-angular variant
|
1012
|
+
//
|
1013
|
+
this.drawRoseNonEquiAngular = function (opt)
|
1014
|
+
{
|
1015
|
+
var group = RG.SVG.create({
|
1016
|
+
svg: this.svg,
|
1017
|
+
type:'g',
|
1018
|
+
parent: this.svg.all,
|
1019
|
+
attr: {
|
1020
|
+
id: 'rgraph_rose_segments_' + this.id
|
1021
|
+
}
|
1022
|
+
});
|
1023
|
+
|
1024
|
+
//Loop through the data summing the second data-pieces
|
1025
|
+
for (var i=0,total=0; i<this.data.length; ++i) {
|
1026
|
+
total += parseFloat(this.data[i][1]);
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
|
1030
|
+
|
1031
|
+
|
1032
|
+
|
1033
|
+
|
1034
|
+
|
1035
|
+
|
1036
|
+
|
1037
|
+
|
1038
|
+
|
1039
|
+
// The initial angles
|
1040
|
+
var start = 0;
|
1041
|
+
|
1042
|
+
|
1043
|
+
|
1044
|
+
|
1045
|
+
// Now loop thru the data
|
1046
|
+
for (var i=0,seq=0; i<this.data.length; ++i,++seq) {
|
1047
|
+
|
1048
|
+
var radians = (this.data[i][1] / total) * RG.SVG.TRIG.TWOPI,
|
1049
|
+
end = start + radians;
|
1050
|
+
|
1051
|
+
// Get the exploded distance
|
1052
|
+
var explosion = this.getExploded({
|
1053
|
+
index: i,
|
1054
|
+
start: start - RG.SVG.TRIG.HALFPI,
|
1055
|
+
end: end - RG.SVG.TRIG.HALFPI
|
1056
|
+
});
|
1057
|
+
|
1058
|
+
|
1059
|
+
|
1060
|
+
|
1061
|
+
|
1062
|
+
|
1063
|
+
|
1064
|
+
|
1065
|
+
|
1066
|
+
|
1067
|
+
|
1068
|
+
|
1069
|
+
|
1070
|
+
|
1071
|
+
|
1072
|
+
// A stacked non-equi-angular segment
|
1073
|
+
if (typeof this.data[i][0] === 'object' && !RG.SVG.isNull(this.data[i][0])) {
|
1074
|
+
|
1075
|
+
|
1076
|
+
|
1077
|
+
// Loop thru the set of values for this segment
|
1078
|
+
for (var j=0,sum=0; j<this.data[i][0].length; ++j,++seq) {
|
1079
|
+
|
1080
|
+
sum += this.data[i][0][j];
|
1081
|
+
|
1082
|
+
// First segment in the stack or not?
|
1083
|
+
if (j === 0) {
|
1084
|
+
|
1085
|
+
var prevRadius = 0,
|
1086
|
+
radius = (sum / this.scale.max) * this.radius;
|
1087
|
+
|
1088
|
+
var arcPath = RG.SVG.TRIG.getArcPath2({
|
1089
|
+
cx: this.centerx + explosion[0],
|
1090
|
+
cy: this.centery + explosion[1],
|
1091
|
+
r: radius,
|
1092
|
+
start: start + prop.margin + prop.segmentsAngleOffset,
|
1093
|
+
end: end - prop.margin + prop.segmentsAngleOffset,
|
1094
|
+
anticlockwise: false
|
1095
|
+
});
|
1096
|
+
|
1097
|
+
var arcPath2 = '';
|
1098
|
+
|
1099
|
+
} else {
|
1100
|
+
|
1101
|
+
var prevRadius = radius, // The previous iterations radius
|
1102
|
+
radius = (sum / this.scale.max) * this.radius;
|
1103
|
+
|
1104
|
+
var arcPath = RG.SVG.TRIG.getArcPath2({
|
1105
|
+
cx: this.centerx + explosion[0],
|
1106
|
+
cy: this.centery + explosion[1],
|
1107
|
+
r: radius,
|
1108
|
+
start: start + prop.margin + prop.segmentsAngleOffset,
|
1109
|
+
end: end - prop.margin + prop.segmentsAngleOffset,
|
1110
|
+
anticlockwise: false
|
1111
|
+
});
|
1112
|
+
|
1113
|
+
var arcPath2 = RG.SVG.TRIG.getArcPath2({
|
1114
|
+
cx: this.centerx + explosion[0],
|
1115
|
+
cy: this.centery + explosion[1],
|
1116
|
+
r: prevRadius,
|
1117
|
+
start: end - prop.margin + prop.segmentsAngleOffset,
|
1118
|
+
end: start + prop.margin + prop.segmentsAngleOffset,
|
1119
|
+
anticlockwise: true
|
1120
|
+
});
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
var path = RG.SVG.create({
|
1124
|
+
svg: this.svg,
|
1125
|
+
type: 'path',
|
1126
|
+
parent: group,
|
1127
|
+
attr: {
|
1128
|
+
d: '{1} {2} z'.format(
|
1129
|
+
arcPath,
|
1130
|
+
arcPath2
|
1131
|
+
),
|
1132
|
+
fill: prop.colorsSequential ? prop.colors[seq] : prop.colors[j],
|
1133
|
+
'fill-opacity': prop.colorsOpacity,
|
1134
|
+
stroke: prop.strokestyle,
|
1135
|
+
'stroke-width': prop.linewidth,
|
1136
|
+
'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
|
1137
|
+
'data-centerx': this.centerx + explosion[0],
|
1138
|
+
'data-centery': this.centery + explosion[1],
|
1139
|
+
'data-index': '[{1},{2}]'.format(i, j),
|
1140
|
+
'data-value': this.data[i][0][j],
|
1141
|
+
'data-start-angle': start,
|
1142
|
+
'data-end-angle': end,
|
1143
|
+
'data-radius': radius,
|
1144
|
+
'data-radius-inner': prevRadius,
|
1145
|
+
'data-sequential': seq
|
1146
|
+
}
|
1147
|
+
});
|
1148
|
+
|
1149
|
+
|
1150
|
+
|
1151
|
+
// Add the segment to the angles array
|
1152
|
+
this.angles.push({
|
1153
|
+
object: path,
|
1154
|
+
index: i,
|
1155
|
+
cx: this.centerx + explosion[0],
|
1156
|
+
cy: this.centery + explosion[1],
|
1157
|
+
start: start,
|
1158
|
+
end: end,
|
1159
|
+
radius: radius,
|
1160
|
+
'radius-inner': prevRadius,
|
1161
|
+
value: this.data[i][0]
|
1162
|
+
});
|
1163
|
+
|
1164
|
+
this.angles2[i].push({
|
1165
|
+
object: path,
|
1166
|
+
index: seq,
|
1167
|
+
cx: this.centerx + explosion[0],
|
1168
|
+
cy: this.centery + explosion[1],
|
1169
|
+
start: start,
|
1170
|
+
end: end,
|
1171
|
+
radius: radius,
|
1172
|
+
'radius-inner': prevRadius,
|
1173
|
+
value: this.data[i][j]
|
1174
|
+
});
|
1175
|
+
|
1176
|
+
|
1177
|
+
|
1178
|
+
|
1179
|
+
// Install tooltips listeners
|
1180
|
+
if (prop.tooltips && prop.tooltips[seq]) {
|
1181
|
+
|
1182
|
+
// Make the tooltipsEvent default to click
|
1183
|
+
if (prop.tooltipsEvent !== 'mousemove') {
|
1184
|
+
prop.tooltipsEvent = 'click';
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
(function (index,group,seq,obj)
|
1188
|
+
{
|
1189
|
+
path.addEventListener(prop.tooltipsEvent, function (e)
|
1190
|
+
{
|
1191
|
+
obj.removeHighlight();
|
1192
|
+
|
1193
|
+
// Show the tooltip
|
1194
|
+
RG.SVG.tooltip({
|
1195
|
+
object: obj,
|
1196
|
+
index: index,
|
1197
|
+
group: group,
|
1198
|
+
sequentialIndex: seq,
|
1199
|
+
text: prop.tooltips[seq],
|
1200
|
+
event: e
|
1201
|
+
});
|
1202
|
+
|
1203
|
+
// Highlight the rect that has been clicked on
|
1204
|
+
obj.highlight(e.target);
|
1205
|
+
|
1206
|
+
var highlight = RG.SVG.REG.get('highlight');
|
1207
|
+
|
1208
|
+
if (prop.tooltipsEvent === 'mousemove') {
|
1209
|
+
highlight.style.cursor = 'pointer';
|
1210
|
+
}
|
1211
|
+
|
1212
|
+
}, false);
|
1213
|
+
|
1214
|
+
// Install the event listener that changes the
|
1215
|
+
// cursor if necessary
|
1216
|
+
if (prop.tooltipsEvent === 'click') {
|
1217
|
+
path.addEventListener('mousemove', function (e)
|
1218
|
+
{
|
1219
|
+
e.target.style.cursor = 'pointer';
|
1220
|
+
}, false);
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
}(j, i, seq, this));
|
1224
|
+
}
|
1225
|
+
var prevRadius = radius;
|
1226
|
+
}
|
1227
|
+
seq--
|
1228
|
+
|
1229
|
+
|
1230
|
+
|
1231
|
+
|
1232
|
+
|
1233
|
+
|
1234
|
+
|
1235
|
+
|
1236
|
+
|
1237
|
+
|
1238
|
+
|
1239
|
+
|
1240
|
+
|
1241
|
+
|
1242
|
+
|
1243
|
+
|
1244
|
+
|
1245
|
+
|
1246
|
+
|
1247
|
+
|
1248
|
+
// A regular non-equi-angular segment
|
1249
|
+
} else {
|
1250
|
+
var radius = (this.data[i][0] / this.scale.max) * this.radius;
|
1251
|
+
|
1252
|
+
var arcPath = RG.SVG.TRIG.getArcPath2({
|
1253
|
+
cx: this.centerx + explosion[0],
|
1254
|
+
cy: this.centery + explosion[1],
|
1255
|
+
r: radius,
|
1256
|
+
start: start + prop.margin + prop.segmentsAngleOffset,
|
1257
|
+
end: end - prop.margin + prop.segmentsAngleOffset,
|
1258
|
+
anticlockwise: false
|
1259
|
+
});
|
1260
|
+
|
1261
|
+
var path = RG.SVG.create({
|
1262
|
+
svg: this.svg,
|
1263
|
+
type: 'path',
|
1264
|
+
parent: group,
|
1265
|
+
attr: {
|
1266
|
+
d: '{1} z'.format(
|
1267
|
+
arcPath
|
1268
|
+
),
|
1269
|
+
fill: prop.colorsSequential ? prop.colors[i] : prop.colors[0],
|
1270
|
+
'fill-opacity': prop.colorsOpacity,
|
1271
|
+
stroke: prop.strokestyle,
|
1272
|
+
'stroke-width': prop.linewidth,
|
1273
|
+
|
1274
|
+
'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
|
1275
|
+
'data-centerx': this.centerx + explosion[0],
|
1276
|
+
'data-centery': this.centery + explosion[1],
|
1277
|
+
'data-index': i,
|
1278
|
+
'data-value': this.data[i],
|
1279
|
+
'data-start-angle': start,
|
1280
|
+
'data-end-angle': end,
|
1281
|
+
'data-radius': radius,
|
1282
|
+
'data-sequential': seq
|
1283
|
+
}
|
1284
|
+
});
|
1285
|
+
|
1286
|
+
// Add the segment to the angles array
|
1287
|
+
this.angles.push({
|
1288
|
+
object: path,
|
1289
|
+
index: i,
|
1290
|
+
cx: this.centerx + explosion[0],
|
1291
|
+
cy: this.centery + explosion[1],
|
1292
|
+
start: start,
|
1293
|
+
end: end,
|
1294
|
+
radius: radius,
|
1295
|
+
value: this.data[i][0]
|
1296
|
+
});
|
1297
|
+
|
1298
|
+
this.angles2[i].push({
|
1299
|
+
object: path,
|
1300
|
+
index: seq,
|
1301
|
+
cx: this.centerx + explosion[0],
|
1302
|
+
cy: this.centery + explosion[1],
|
1303
|
+
start: start,
|
1304
|
+
end: end,
|
1305
|
+
radius: radius,
|
1306
|
+
'radius-inner': 0,
|
1307
|
+
value: this.data[i][j]
|
1308
|
+
});
|
1309
|
+
|
1310
|
+
|
1311
|
+
|
1312
|
+
|
1313
|
+
if (prop.tooltips && prop.tooltips[i]) {
|
1314
|
+
|
1315
|
+
// Make the tooltipsEvent default to click
|
1316
|
+
if (prop.tooltipsEvent !== 'mousemove') {
|
1317
|
+
prop.tooltipsEvent = 'click';
|
1318
|
+
}
|
1319
|
+
|
1320
|
+
(function (index, group, seq, obj)
|
1321
|
+
{
|
1322
|
+
path.addEventListener(prop.tooltipsEvent, function (e)
|
1323
|
+
{
|
1324
|
+
obj.removeHighlight();
|
1325
|
+
|
1326
|
+
// Show the tooltip
|
1327
|
+
RG.SVG.tooltip({
|
1328
|
+
object: obj,
|
1329
|
+
index: index,
|
1330
|
+
group: index,
|
1331
|
+
sequentialIndex: seq,
|
1332
|
+
text: prop.tooltips[index],
|
1333
|
+
event: e
|
1334
|
+
});
|
1335
|
+
|
1336
|
+
// Highlight the rect that has been clicked on
|
1337
|
+
obj.highlight(e.target);
|
1338
|
+
|
1339
|
+
var highlight = RG.SVG.REG.get('highlight');
|
1340
|
+
|
1341
|
+
if (prop.tooltipsEvent === 'mousemove') {
|
1342
|
+
highlight.style.cursor = 'pointer';
|
1343
|
+
}
|
1344
|
+
|
1345
|
+
}, false);
|
1346
|
+
|
1347
|
+
// Install the event listener that changes the
|
1348
|
+
// cursor if necessary
|
1349
|
+
if (prop.tooltipsEvent === 'click') {
|
1350
|
+
path.addEventListener('mousemove', function (e)
|
1351
|
+
{
|
1352
|
+
e.target.style.cursor = 'pointer';
|
1353
|
+
}, false);
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
}(i, i, seq, this));
|
1357
|
+
}
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
|
1361
|
+
// Increment the start angle for the next iteration of the loop
|
1362
|
+
start += radians;
|
1363
|
+
}
|
1364
|
+
};
|
1365
|
+
|
1366
|
+
|
1367
|
+
|
1368
|
+
|
1369
|
+
|
1370
|
+
|
1371
|
+
|
1372
|
+
|
1373
|
+
//
|
1374
|
+
// Redraws the chart if required
|
1375
|
+
//
|
1376
|
+
this.redrawRose = function ()
|
1377
|
+
{
|
1378
|
+
};
|
1379
|
+
|
1380
|
+
|
1381
|
+
|
1382
|
+
|
1383
|
+
|
1384
|
+
|
1385
|
+
|
1386
|
+
|
1387
|
+
//
|
1388
|
+
// Draw the labels
|
1389
|
+
//
|
1390
|
+
this.drawLabels = function ()
|
1391
|
+
{
|
1392
|
+
// Draw the scale if required
|
1393
|
+
if (prop.scaleVisible) {
|
1394
|
+
for (var i=0; i<this.scale.labels.length; ++i) {
|
1395
|
+
|
1396
|
+
var x = this.centerx;
|
1397
|
+
var y = this.centery - (this.radius / this.scale.labels.length * (i+1) );
|
1398
|
+
|
1399
|
+
|
1400
|
+
RG.SVG.text({
|
1401
|
+
object: this,
|
1402
|
+
svg: this.svg,
|
1403
|
+
parent: this.svg.all,
|
1404
|
+
text: this.scale.labels[i],
|
1405
|
+
size: prop.scaleSize || prop.textSize - 2,
|
1406
|
+
x: x,
|
1407
|
+
y: y,
|
1408
|
+
halign: 'center',
|
1409
|
+
valign: 'center',
|
1410
|
+
background: 'rgba(255,255,255,0.7)',
|
1411
|
+
padding:2,
|
1412
|
+
color: prop.scaleColor || prop.textColor,
|
1413
|
+
bold: typeof prop.scaleBold === 'boolean' ? prop.scaleBold : prop.textBold,
|
1414
|
+
italic: typeof prop.scaleItalic === 'boolean' ? prop.scaleItalic : prop.textItalic,
|
1415
|
+
font: prop.scaleFont || prop.textFont
|
1416
|
+
});
|
1417
|
+
}
|
1418
|
+
|
1419
|
+
// Draw the zero label
|
1420
|
+
var str = RG.SVG.numberFormat({
|
1421
|
+
object: this,
|
1422
|
+
num: this.scale.min.toFixed(prop.scaleDecimals),
|
1423
|
+
prepend: prop.scaleUnitsPre,
|
1424
|
+
append: prop.scaleUnitsPost,
|
1425
|
+
point: prop.scalePoint,
|
1426
|
+
thousand: prop.scaleThousand,
|
1427
|
+
formatter: prop.scaleFormatter
|
1428
|
+
});
|
1429
|
+
|
1430
|
+
|
1431
|
+
RG.SVG.text({
|
1432
|
+
object: this,
|
1433
|
+
svg: this.svg,
|
1434
|
+
parent: this.svg.all,
|
1435
|
+
text: str,
|
1436
|
+
size: prop.scaleSize || prop.textSize - 2,
|
1437
|
+
x: this.centerx,
|
1438
|
+
y: this.centery,
|
1439
|
+
halign: 'center',
|
1440
|
+
valign: 'center',
|
1441
|
+
background: 'rgba(255,255,255,0.7)',
|
1442
|
+
padding:2,
|
1443
|
+
color: prop.scaleColor || prop.textColor,
|
1444
|
+
bold: typeof prop.scaleBold === 'boolean' ? prop.scaleBold : prop.textBold,
|
1445
|
+
italic: typeof prop.scaleItalic === 'boolean' ? prop.scaleItalic : prop.textItalic,
|
1446
|
+
font: prop.scaleFont || prop.textFont
|
1447
|
+
});
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
|
1451
|
+
|
1452
|
+
|
1453
|
+
|
1454
|
+
|
1455
|
+
|
1456
|
+
// Used further down
|
1457
|
+
var halign;
|
1458
|
+
|
1459
|
+
// Set a default size for the labels
|
1460
|
+
if (typeof prop.labelsSize !== 'number') {
|
1461
|
+
prop.labelsSize = prop.textSize + 4;
|
1462
|
+
}
|
1463
|
+
|
1464
|
+
|
1465
|
+
|
1466
|
+
// Draw the circular labels if necessary
|
1467
|
+
for (var i=0; i<prop.labels.length; ++i) {
|
1468
|
+
|
1469
|
+
if (prop.variant === 'non-equi-angular') {
|
1470
|
+
var angle = ((this.angles2[i][0].end - this.angles2[i][0].start) / 2) + this.angles2[i][0].start - RG.SVG.TRIG.HALFPI;
|
1471
|
+
} else {
|
1472
|
+
var angle = (((RG.SVG.TRIG.TWOPI / prop.labels.length)) * i) - RG.SVG.TRIG.HALFPI + prop.labelsAngleOffset + ((this.angles2[i][0].end - this.angles2[i][0].start) / 2);
|
1473
|
+
}
|
1474
|
+
|
1475
|
+
var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
|
1476
|
+
r: this.radius + prop.labelsRadialMargin,
|
1477
|
+
angle: angle
|
1478
|
+
});
|
1479
|
+
|
1480
|
+
// Accommodate the explosion for the label
|
1481
|
+
var explosion = this.getExploded({
|
1482
|
+
index: i,
|
1483
|
+
start: this.angles2[i][0].start - RG.SVG.TRIG.HALFPI,
|
1484
|
+
end: this.angles2[i][0].end - RG.SVG.TRIG.HALFPI
|
1485
|
+
});
|
1486
|
+
|
1487
|
+
endpoint[0] += this.centerx + explosion[0];
|
1488
|
+
endpoint[1] += this.centery + explosion[1];
|
1489
|
+
|
1490
|
+
|
1491
|
+
// Do the alignment based on which quadrant the label is in
|
1492
|
+
if (ma.round(endpoint[0]) > this.centerx) {
|
1493
|
+
halign = 'left';
|
1494
|
+
} else if (ma.round(endpoint[0]) === this.centerx) {
|
1495
|
+
halign = 'center';
|
1496
|
+
} else {
|
1497
|
+
halign = 'right';
|
1498
|
+
}
|
1499
|
+
|
1500
|
+
|
1501
|
+
|
1502
|
+
|
1503
|
+
|
1504
|
+
RG.SVG.text({
|
1505
|
+
object: this,
|
1506
|
+
svg: this.svg,
|
1507
|
+
parent: this.svg.all,
|
1508
|
+
text: typeof prop.labels[i] === 'string' ? prop.labels[i] : '',
|
1509
|
+
size: prop.labelsSize,
|
1510
|
+
x: endpoint[0],
|
1511
|
+
y: endpoint[1],
|
1512
|
+
halign: halign,
|
1513
|
+
valign: 'center',
|
1514
|
+
background: 'rgba(255,255,255,0.7)',
|
1515
|
+
padding:2,
|
1516
|
+
color: prop.labelsColor || prop.textColor,
|
1517
|
+
bold: typeof prop.labelsBold === 'boolean' ? prop.labelsBold : prop.textBold,
|
1518
|
+
italic: typeof prop.labelsItalic === 'boolean' ? prop.labelsItalic : prop.textItalic,
|
1519
|
+
font: prop.labelsFont || prop.textFont
|
1520
|
+
});
|
1521
|
+
}
|
1522
|
+
};
|
1523
|
+
|
1524
|
+
|
1525
|
+
|
1526
|
+
|
1527
|
+
|
1528
|
+
|
1529
|
+
|
1530
|
+
|
1531
|
+
/**
|
1532
|
+
* This function can be used to highlight a segment on the chart
|
1533
|
+
*
|
1534
|
+
* @param object circle The circle to highlight
|
1535
|
+
*/
|
1536
|
+
this.highlight = function (path)
|
1537
|
+
{
|
1538
|
+
var path = path.getAttribute('d');
|
1539
|
+
|
1540
|
+
var highlight = RG.SVG.create({
|
1541
|
+
svg: this.svg,
|
1542
|
+
parent: this.svg.all,
|
1543
|
+
type: 'path',
|
1544
|
+
attr: {
|
1545
|
+
d: path,
|
1546
|
+
fill: prop.highlightFill,
|
1547
|
+
stroke: prop.highlightStroke,
|
1548
|
+
'stroke-width': prop.highlightLinewidth
|
1549
|
+
}
|
1550
|
+
});
|
1551
|
+
|
1552
|
+
|
1553
|
+
if (prop.tooltipsEvent === 'mousemove') {
|
1554
|
+
highlight.addEventListener('mouseout', function (e)
|
1555
|
+
{
|
1556
|
+
highlight.parentNode.removeChild(highlight);
|
1557
|
+
RG.SVG.hideTooltip();
|
1558
|
+
|
1559
|
+
RG.SVG.REG.set('highlight', null);
|
1560
|
+
}, false);
|
1561
|
+
}
|
1562
|
+
|
1563
|
+
|
1564
|
+
// Store the highlight rect in the registry so
|
1565
|
+
// it can be cleared later
|
1566
|
+
RG.SVG.REG.set('highlight', highlight);
|
1567
|
+
};
|
1568
|
+
|
1569
|
+
|
1570
|
+
|
1571
|
+
|
1572
|
+
|
1573
|
+
|
1574
|
+
|
1575
|
+
|
1576
|
+
/**
|
1577
|
+
* This allows for easy specification of gradients
|
1578
|
+
*/
|
1579
|
+
this.parseColors = function ()
|
1580
|
+
{
|
1581
|
+
// Save the original colors so that they can be restored when the canvas is reset
|
1582
|
+
if (!Object.keys(this.originalColors).length) {
|
1583
|
+
this.originalColors = {
|
1584
|
+
colors: RG.SVG.arrayClone(prop.colors),
|
1585
|
+
highlightFill: RG.SVG.arrayClone(prop.highlightFill)
|
1586
|
+
}
|
1587
|
+
}
|
1588
|
+
|
1589
|
+
|
1590
|
+
// colors
|
1591
|
+
var colors = prop.colors;
|
1592
|
+
|
1593
|
+
if (colors) {
|
1594
|
+
for (var i=0; i<colors.length; ++i) {
|
1595
|
+
colors[i] = RG.SVG.parseColorRadial({
|
1596
|
+
object: this,
|
1597
|
+
color: colors[i]
|
1598
|
+
});
|
1599
|
+
}
|
1600
|
+
}
|
1601
|
+
|
1602
|
+
// Highlight fill
|
1603
|
+
prop.highlightFill = RG.SVG.parseColorRadial({
|
1604
|
+
object: this,
|
1605
|
+
color: prop.highlightFill
|
1606
|
+
});
|
1607
|
+
};
|
1608
|
+
|
1609
|
+
|
1610
|
+
|
1611
|
+
|
1612
|
+
|
1613
|
+
|
1614
|
+
|
1615
|
+
|
1616
|
+
//
|
1617
|
+
// Get the maximum value
|
1618
|
+
//
|
1619
|
+
this.getMaxValue = function ()
|
1620
|
+
{
|
1621
|
+
var max = 0;
|
1622
|
+
|
1623
|
+
if (prop.variant === 'non-equi-angular') {
|
1624
|
+
for (var i=0; i<this.data.length; ++i) {
|
1625
|
+
if (!RG.SVG.isNull(this.data[i])) {
|
1626
|
+
if (typeof this.data[i][0] === 'number') {
|
1627
|
+
max = ma.max(max, this.data[i][0]);
|
1628
|
+
} else if (typeof this.data[i][0] === 'object'){
|
1629
|
+
max = ma.max(max, RG.SVG.arraySum(this.data[i][0]));
|
1630
|
+
}
|
1631
|
+
}
|
1632
|
+
}
|
1633
|
+
} else {
|
1634
|
+
for (var i=0; i<this.data.length; ++i) {
|
1635
|
+
if (!RG.SVG.isNull(this.data[i])) {
|
1636
|
+
if (typeof this.data[i] === 'number') {
|
1637
|
+
max = ma.max(max, this.data[i]);
|
1638
|
+
} else if (typeof this.data[i] === 'object') {
|
1639
|
+
max = ma.max(max, RG.SVG.arraySum(this.data[i]));
|
1640
|
+
}
|
1641
|
+
}
|
1642
|
+
}
|
1643
|
+
}
|
1644
|
+
|
1645
|
+
this.max = max;
|
1646
|
+
};
|
1647
|
+
|
1648
|
+
|
1649
|
+
|
1650
|
+
|
1651
|
+
|
1652
|
+
|
1653
|
+
|
1654
|
+
|
1655
|
+
//
|
1656
|
+
// Gets the radius of a value
|
1657
|
+
//
|
1658
|
+
//@param number The value to get the radius for
|
1659
|
+
//
|
1660
|
+
this.getRadius = function (value)
|
1661
|
+
{
|
1662
|
+
return ( (value - prop.scaleMin) / (this.scale.max - prop.scaleMin) ) * this.radius;
|
1663
|
+
};
|
1664
|
+
|
1665
|
+
|
1666
|
+
|
1667
|
+
|
1668
|
+
|
1669
|
+
|
1670
|
+
|
1671
|
+
|
1672
|
+
//
|
1673
|
+
// A roundRobin effect for the Pie chart
|
1674
|
+
//
|
1675
|
+
// @param object Options for the effect
|
1676
|
+
// @param function An optional callback function to call when
|
1677
|
+
// the effect is complete
|
1678
|
+
//
|
1679
|
+
this.roundRobin = function ()
|
1680
|
+
{
|
1681
|
+
};
|
1682
|
+
|
1683
|
+
|
1684
|
+
|
1685
|
+
|
1686
|
+
|
1687
|
+
|
1688
|
+
|
1689
|
+
|
1690
|
+
/**
|
1691
|
+
* Using a function to add events makes it easier to facilitate method
|
1692
|
+
* chaining
|
1693
|
+
*
|
1694
|
+
* @param string type The type of even to add
|
1695
|
+
* @param function func
|
1696
|
+
*/
|
1697
|
+
this.on = function (type, func)
|
1698
|
+
{
|
1699
|
+
if (type.substr(0,2) !== 'on') {
|
1700
|
+
type = 'on' + type;
|
1701
|
+
}
|
1702
|
+
|
1703
|
+
RG.SVG.addCustomEventListener(this, type, func);
|
1704
|
+
|
1705
|
+
return this;
|
1706
|
+
};
|
1707
|
+
|
1708
|
+
|
1709
|
+
|
1710
|
+
|
1711
|
+
|
1712
|
+
|
1713
|
+
|
1714
|
+
|
1715
|
+
//
|
1716
|
+
// Used in chaining. Runs a function there and then - not waiting for
|
1717
|
+
// the events to fire (eg the onbeforedraw event)
|
1718
|
+
//
|
1719
|
+
// @param function func The function to execute
|
1720
|
+
//
|
1721
|
+
this.exec = function (func)
|
1722
|
+
{
|
1723
|
+
func(this);
|
1724
|
+
|
1725
|
+
return this;
|
1726
|
+
};
|
1727
|
+
|
1728
|
+
|
1729
|
+
|
1730
|
+
|
1731
|
+
|
1732
|
+
|
1733
|
+
|
1734
|
+
|
1735
|
+
//
|
1736
|
+
// Removes the tooltip highlight from the chart
|
1737
|
+
//
|
1738
|
+
this.removeHighlight =
|
1739
|
+
this.hideHighlight = function ()
|
1740
|
+
{
|
1741
|
+
var highlight = RG.SVG.REG.get('highlight');
|
1742
|
+
|
1743
|
+
if (highlight && this.highlight_node) {
|
1744
|
+
this.highlight_node.setAttribute('fill','transparent');
|
1745
|
+
this.highlight_node.setAttribute('stroke','transparent');
|
1746
|
+
|
1747
|
+
RG.SVG.REG.set('highlight', null);
|
1748
|
+
}
|
1749
|
+
};
|
1750
|
+
|
1751
|
+
|
1752
|
+
|
1753
|
+
|
1754
|
+
|
1755
|
+
|
1756
|
+
|
1757
|
+
|
1758
|
+
//
|
1759
|
+
// Returns the exploded X/Y for a given explosion
|
1760
|
+
//
|
1761
|
+
//TODO Needs updating to current coding style, including converting
|
1762
|
+
// arguments to an object
|
1763
|
+
//
|
1764
|
+
this.getExploded = function (opt)
|
1765
|
+
{
|
1766
|
+
var index = opt.index,
|
1767
|
+
start = opt.start,
|
1768
|
+
end = opt.end,
|
1769
|
+
exploded = prop.exploded,
|
1770
|
+
explodedX,
|
1771
|
+
explodedY;
|
1772
|
+
|
1773
|
+
/**
|
1774
|
+
* Retrieve any exploded - the exploded can be an array of numbers or a single number
|
1775
|
+
* (which is applied to all segments)
|
1776
|
+
*/
|
1777
|
+
if (typeof exploded === 'object' && typeof exploded[index] === 'number') {
|
1778
|
+
explodedX = ma.cos(((end - start) / 2) + start) * exploded[index];
|
1779
|
+
explodedY = (ma.sin(((end - start) / 2) + start) * exploded[index]);
|
1780
|
+
|
1781
|
+
} else if (typeof exploded === 'number') {
|
1782
|
+
explodedX = ma.cos(((end - start) / 2) + start) * exploded;
|
1783
|
+
explodedY = ma.sin(((end - start) / 2) + start) * exploded;
|
1784
|
+
|
1785
|
+
} else {
|
1786
|
+
explodedX = 0;
|
1787
|
+
explodedY = 0;
|
1788
|
+
}
|
1789
|
+
|
1790
|
+
return [explodedX, explodedY];
|
1791
|
+
};
|
1792
|
+
|
1793
|
+
|
1794
|
+
|
1795
|
+
|
1796
|
+
|
1797
|
+
|
1798
|
+
|
1799
|
+
|
1800
|
+
//
|
1801
|
+
// Set the options that the user has provided
|
1802
|
+
//
|
1803
|
+
for (i in conf.options) {
|
1804
|
+
if (typeof i === 'string') {
|
1805
|
+
this.set(i, conf.options[i]);
|
1806
|
+
}
|
1807
|
+
}
|
1808
|
+
};
|
1809
|
+
|
1810
|
+
|
1811
|
+
|
1812
|
+
return this;
|
1813
|
+
|
1814
|
+
|
1815
|
+
|
1816
|
+
|
1817
|
+
// End module pattern
|
1818
|
+
})(window, document);
|