rgraph-rails 4.62 → 4.64
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 +5 -5
- data/README.md +3 -4
- data/lib/rgraph-rails/version.rb +1 -1
- data/vendor/assets/javascripts/RGraph.bar.js +240 -3742
- data/vendor/assets/javascripts/RGraph.bipolar.js +165 -2005
- data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -395
- data/vendor/assets/javascripts/RGraph.common.context.js +30 -595
- data/vendor/assets/javascripts/RGraph.common.core.js +418 -5359
- data/vendor/assets/javascripts/RGraph.common.csv.js +20 -276
- data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -450
- data/vendor/assets/javascripts/RGraph.common.dynamic.js +88 -1395
- data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1545
- data/vendor/assets/javascripts/RGraph.common.key.js +52 -753
- data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -563
- data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -352
- data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -450
- data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -219
- data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
- data/vendor/assets/javascripts/RGraph.drawing.background.js +34 -570
- data/vendor/assets/javascripts/RGraph.drawing.circle.js +33 -544
- data/vendor/assets/javascripts/RGraph.drawing.image.js +51 -755
- data/vendor/assets/javascripts/RGraph.drawing.marker1.js +37 -645
- data/vendor/assets/javascripts/RGraph.drawing.marker2.js +36 -633
- data/vendor/assets/javascripts/RGraph.drawing.marker3.js +35 -514
- data/vendor/assets/javascripts/RGraph.drawing.poly.js +37 -559
- data/vendor/assets/javascripts/RGraph.drawing.rect.js +33 -548
- data/vendor/assets/javascripts/RGraph.drawing.text.js +36 -664
- data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -812
- data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
- data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
- data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
- data/vendor/assets/javascripts/RGraph.gantt.js +77 -1354
- data/vendor/assets/javascripts/RGraph.gauge.js +85 -1421
- data/vendor/assets/javascripts/RGraph.hbar.js +162 -2788
- data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1401
- data/vendor/assets/javascripts/RGraph.line.js +249 -4248
- data/vendor/assets/javascripts/RGraph.meter.js +74 -1280
- data/vendor/assets/javascripts/RGraph.modaldialog.js +19 -301
- data/vendor/assets/javascripts/RGraph.odo.js +71 -1264
- data/vendor/assets/javascripts/RGraph.pie.js +137 -2288
- data/vendor/assets/javascripts/RGraph.radar.js +110 -1847
- data/vendor/assets/javascripts/RGraph.rose.js +108 -1977
- data/vendor/assets/javascripts/RGraph.rscatter.js +80 -1432
- data/vendor/assets/javascripts/RGraph.scatter.js +172 -3163
- data/vendor/assets/javascripts/RGraph.semicircularprogress.js +60 -1120
- data/vendor/assets/javascripts/RGraph.svg.bar.js +66 -1735
- data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +21 -246
- data/vendor/assets/javascripts/RGraph.svg.common.core.js +255 -3937
- data/vendor/assets/javascripts/RGraph.svg.common.csv.js +20 -276
- data/vendor/assets/javascripts/RGraph.svg.common.fx.js +68 -1303
- data/vendor/assets/javascripts/RGraph.svg.common.key.js +19 -205
- data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +29 -352
- data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +22 -273
- data/vendor/assets/javascripts/RGraph.svg.funnel.js +32 -0
- data/vendor/assets/javascripts/RGraph.svg.hbar.js +59 -1400
- data/vendor/assets/javascripts/RGraph.svg.line.js +70 -1580
- data/vendor/assets/javascripts/RGraph.svg.pie.js +55 -1131
- data/vendor/assets/javascripts/RGraph.svg.radar.js +57 -1502
- data/vendor/assets/javascripts/RGraph.svg.rose.js +66 -1817
- data/vendor/assets/javascripts/RGraph.svg.scatter.js +58 -1261
- data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +28 -865
- data/vendor/assets/javascripts/RGraph.svg.waterfall.js +45 -1252
- data/vendor/assets/javascripts/RGraph.thermometer.js +63 -1136
- data/vendor/assets/javascripts/RGraph.vprogress.js +83 -1470
- data/vendor/assets/javascripts/RGraph.waterfall.js +83 -1347
- metadata +5 -4
- data/vendor/assets/javascripts/financial-data.js +0 -1067
@@ -1,1433 +1,81 @@
|
|
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
1
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
this.radius = 0;
|
94
|
-
this.max = 0;
|
95
|
-
|
96
|
-
// Convert all of the data pieces to numbers
|
97
|
-
for (var i=0; i<this.data.length; ++i) {
|
98
|
-
for (var j=0; j<this.data[i].length; ++j) {
|
99
|
-
if (typeof this.data[i][j][0] === 'string') {
|
100
|
-
this.data[i][j][0] = parseFloat(this.data[i][j][0]);
|
101
|
-
}
|
102
|
-
|
103
|
-
if (typeof this.data[i][j][1] === 'string') {
|
104
|
-
this.data[i][j][1] = parseFloat(this.data[i][j][1]);
|
105
|
-
}
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
|
-
|
110
|
-
this.properties =
|
111
|
-
{
|
112
|
-
'chart.background.color': 'transparent',
|
113
|
-
'chart.background.grid': true,
|
114
|
-
'chart.background.grid.diagonals': true,
|
115
|
-
'chart.background.grid.diagonals.count': null,
|
116
|
-
'chart.background.grid.radials': true,
|
117
|
-
'chart.background.grid.radials.count': null,
|
118
|
-
'chart.background.grid.linewidth': 1,
|
119
|
-
'chart.background.grid.color': '#ccc',
|
120
|
-
'chart.radius': null,
|
121
|
-
'chart.colors': [], // This is used internally for the key
|
122
|
-
'chart.colors.default': 'black',
|
123
|
-
'chart.gutter.left': 25,
|
124
|
-
'chart.gutter.right': 25,
|
125
|
-
'chart.gutter.top': 25,
|
126
|
-
'chart.gutter.bottom': 25,
|
127
|
-
'chart.title': '',
|
128
|
-
'chart.title.background': null,
|
129
|
-
'chart.title.hpos': null,
|
130
|
-
'chart.title.vpos': null,
|
131
|
-
'chart.title.bold': true,
|
132
|
-
'chart.title.font': null,
|
133
|
-
'chart.title.x': null,
|
134
|
-
'chart.title.y': null,
|
135
|
-
'chart.title.halign': null,
|
136
|
-
'chart.title.valign': null,
|
137
|
-
'chart.labels': null,
|
138
|
-
'chart.labels.color': null,
|
139
|
-
'chart.labels.axes': 'nsew',
|
140
|
-
'chart.labels.axes.background': 'rgba(255,255,255,0.8)',
|
141
|
-
'chart.labels.count': 5,
|
142
|
-
'chart.text.color': 'black',
|
143
|
-
'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
|
144
|
-
'chart.text.size': 12,
|
145
|
-
'chart.text.accessible': true,
|
146
|
-
'chart.text.accessible.overflow': 'visible',
|
147
|
-
'chart.text.accessible.pointerevents': true,
|
148
|
-
'chart.key': null,
|
149
|
-
'chart.key.background': 'white',
|
150
|
-
'chart.key.position': 'graph',
|
151
|
-
'chart.key.halign': 'right',
|
152
|
-
'chart.key.shadow': false,
|
153
|
-
'chart.key.shadow.color': '#666',
|
154
|
-
'chart.key.shadow.blur': 3,
|
155
|
-
'chart.key.shadow.offsetx': 2,
|
156
|
-
'chart.key.shadow.offsety': 2,
|
157
|
-
'chart.key.position.gutter.boxed':false,
|
158
|
-
'chart.key.position.x': null,
|
159
|
-
'chart.key.position.y': null,
|
160
|
-
'chart.key.color.shape': 'square',
|
161
|
-
'chart.key.rounded': true,
|
162
|
-
'chart.key.linewidth': 1,
|
163
|
-
'chart.key.colors': null,
|
164
|
-
'chart.key.interactive': false,
|
165
|
-
'chart.key.interactive.highlight.chart.fill':'rgba(255,0,0,0.9)',
|
166
|
-
'chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)',
|
167
|
-
'chart.key.text.color': 'black',
|
168
|
-
'chart.contextmenu': null,
|
169
|
-
'chart.tooltips': null,
|
170
|
-
'chart.tooltips.event': 'onmousemove',
|
171
|
-
'chart.tooltips.effect': 'fade',
|
172
|
-
'chart.tooltips.css.class': 'RGraph_tooltip',
|
173
|
-
'chart.tooltips.highlight': true,
|
174
|
-
'chart.tooltips.hotspot': 3,
|
175
|
-
'chart.tooltips.coords.page': false,
|
176
|
-
'chart.annotatable': false,
|
177
|
-
'chart.annotate.color': 'black',
|
178
|
-
'chart.zoom.factor': 1.5,
|
179
|
-
'chart.zoom.fade.in': true,
|
180
|
-
'chart.zoom.fade.out': true,
|
181
|
-
'chart.zoom.hdir': 'right',
|
182
|
-
'chart.zoom.vdir': 'down',
|
183
|
-
'chart.zoom.frames': 25,
|
184
|
-
'chart.zoom.delay': 16.666,
|
185
|
-
'chart.zoom.shadow': true,
|
186
|
-
'chart.zoom.background': true,
|
187
|
-
'chart.zoom.action': 'zoom',
|
188
|
-
'chart.resizable': false,
|
189
|
-
'chart.resize.handle.background': null,
|
190
|
-
'chart.ymax': null,
|
191
|
-
'chart.ymin': 0,
|
192
|
-
'chart.tickmarks': 'cross',
|
193
|
-
'chart.ticksize': 3,
|
194
|
-
'chart.scale.decimals': null,
|
195
|
-
'chart.scale.point': '.',
|
196
|
-
'chart.scale.thousand': ',',
|
197
|
-
'chart.scale.round': false,
|
198
|
-
'chart.scale.zerostart': true,
|
199
|
-
'chart.units.pre': '',
|
200
|
-
'chart.units.post': '',
|
201
|
-
'chart.events.mousemove': null,
|
202
|
-
'chart.events.click': null,
|
203
|
-
'chart.highlight.stroke': 'transparent',
|
204
|
-
'chart.highlight.fill': 'rgba(255,255,255,0.7)',
|
205
|
-
'chart.highlight.point.radius': 3,
|
206
|
-
'chart.axes.color': 'black',
|
207
|
-
'chart.axes.numticks': null,
|
208
|
-
'chart.axes.caps': true,
|
209
|
-
'chart.segment.highlight': false,
|
210
|
-
'chart.segment.highlight.count': null,
|
211
|
-
'chart.segment.highlight.fill': 'rgba(0,255,0,0.5)',
|
212
|
-
'chart.segment.highlight.stroke':'rgba(0,0,0,0)',
|
213
|
-
'chart.line': false,
|
214
|
-
'chart.line.close': false,
|
215
|
-
'chart.line.linewidth': 1,
|
216
|
-
'chart.line.colors': ['black'],
|
217
|
-
'chart.line.shadow': false,
|
218
|
-
'chart.line.shadow.color': 'black',
|
219
|
-
'chart.line.shadow.blur': 2,
|
220
|
-
'chart.line.shadow.offsetx': 3,
|
221
|
-
'chart.line.shadow.offsety': 3,
|
222
|
-
'chart.clearto': 'rgba(0,0,0,0)'
|
223
|
-
}
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
/**
|
229
|
-
* Create the $ objects so that functions can be added to them
|
230
|
-
*/
|
231
|
-
|
232
|
-
for (var i=0,idx=0; i<this.data.length; ++i) {
|
233
|
-
for (var j=0,len=this.data[i].length; j<len; j+=1,idx+=1) {
|
234
|
-
this['$' + idx] = {}
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
/**
|
243
|
-
* Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
|
244
|
-
* done already
|
245
|
-
*/
|
246
|
-
if (!this.canvas.__rgraph_aa_translated__) {
|
247
|
-
this.context.translate(0.5,0.5);
|
248
|
-
|
249
|
-
this.canvas.__rgraph_aa_translated__ = true;
|
250
|
-
}
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
// Short variable names
|
255
|
-
var RG = RGraph,
|
256
|
-
ca = this.canvas,
|
257
|
-
co = ca.getContext('2d'),
|
258
|
-
prop = this.properties,
|
259
|
-
pa2 = RG.path2,
|
260
|
-
win = window,
|
261
|
-
doc = document,
|
262
|
-
ma = Math
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
/**
|
267
|
-
* "Decorate" the object with the generic effects if the effects library has been included
|
268
|
-
*/
|
269
|
-
if (RG.Effects && typeof RG.Effects.decorate === 'function') {
|
270
|
-
RG.Effects.decorate(this);
|
271
|
-
}
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
/**
|
277
|
-
* A simple setter
|
278
|
-
*
|
279
|
-
* @param string name The name of the property to set
|
280
|
-
* @param string value The value of the property
|
281
|
-
*/
|
282
|
-
this.set =
|
283
|
-
this.Set = function (name, value)
|
284
|
-
{
|
285
|
-
var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
|
286
|
-
|
287
|
-
/**
|
288
|
-
* the number of arguments is only one and it's an
|
289
|
-
* object - parse it for configuration data and return.
|
290
|
-
*/
|
291
|
-
if (arguments.length === 1 && typeof name === 'object') {
|
292
|
-
RG.parseObjectStyleConfig(this, name);
|
293
|
-
return this;
|
294
|
-
}
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
/**
|
299
|
-
* This should be done first - prepend the property name with "chart." if necessary
|
300
|
-
*/
|
301
|
-
if (name.substr(0,6) != 'chart.') {
|
302
|
-
name = 'chart.' + name;
|
303
|
-
}
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
// Convert uppercase letters to dot+lower case letter
|
309
|
-
while(name.match(/([A-Z])/)) {
|
310
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
311
|
-
}
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
//
|
320
|
-
// Change chart.segments.highlight* to chart.segment.highlight (no plural)
|
321
|
-
//
|
322
|
-
if (name === 'chart.segments.highlight') name = 'chart.segment.highlight';
|
323
|
-
if (name === 'chart.segments.highlight.count') name = 'chart.segment.highlight.count';
|
324
|
-
if (name === 'chart.segments.highlight.fill') name = 'chart.segment.highlight.fill';
|
325
|
-
if (name === 'chart.segments.highlight.stroke') name = 'chart.segment.highlight.stroke';
|
326
|
-
|
327
|
-
prop[name.toLowerCase()] = value;
|
328
|
-
|
329
|
-
return this;
|
330
|
-
};
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
/**
|
336
|
-
* A simple getter
|
337
|
-
*
|
338
|
-
* @param string name The name of the property to get
|
339
|
-
*/
|
340
|
-
this.get =
|
341
|
-
this.Get = function (name)
|
342
|
-
{
|
343
|
-
/**
|
344
|
-
* This should be done first - prepend the property name with "chart." if necessary
|
345
|
-
*/
|
346
|
-
if (name.substr(0,6) != 'chart.') {
|
347
|
-
name = 'chart.' + name;
|
348
|
-
}
|
349
|
-
|
350
|
-
// Convert uppercase letters to dot+lower case letter
|
351
|
-
while(name.match(/([A-Z])/)) {
|
352
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
353
|
-
}
|
354
|
-
|
355
|
-
return prop[name.toLowerCase()];
|
356
|
-
};
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
/**
|
362
|
-
* This method draws the rose chart
|
363
|
-
*/
|
364
|
-
this.draw =
|
365
|
-
this.Draw = function ()
|
366
|
-
{
|
367
|
-
/**
|
368
|
-
* Fire the onbeforedraw event
|
369
|
-
*/
|
370
|
-
RG.FireCustomEvent(this, 'onbeforedraw');
|
371
|
-
|
372
|
-
|
373
|
-
/**
|
374
|
-
* This doesn't affect the chart, but is used for compatibility
|
375
|
-
*/
|
376
|
-
this.gutterLeft = prop['chart.gutter.left'];
|
377
|
-
this.gutterRight = prop['chart.gutter.right'];
|
378
|
-
this.gutterTop = prop['chart.gutter.top'];
|
379
|
-
this.gutterBottom = prop['chart.gutter.bottom'];
|
380
|
-
|
381
|
-
// Calculate the radius
|
382
|
-
this.radius = (Math.min(ca.width - this.gutterLeft - this.gutterRight, ca.height - this.gutterTop - this.gutterBottom) / 2);
|
383
|
-
this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
|
384
|
-
this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
|
385
|
-
this.coords = [];
|
386
|
-
this.coords2 = [];
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
/**
|
391
|
-
* Stop this growing uncontrollably
|
392
|
-
*/
|
393
|
-
this.coordsText = [];
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
/**
|
399
|
-
* If there's a user specified radius/centerx/centery, use them
|
400
|
-
*/
|
401
|
-
if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
|
402
|
-
if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
|
403
|
-
if (typeof(prop['chart.radius']) == 'number') this.radius = prop['chart.radius'];
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
/**
|
408
|
-
* Parse the colors for gradients. Its down here so that the center X/Y can be used
|
409
|
-
*/
|
410
|
-
if (!this.colorsParsed) {
|
411
|
-
|
412
|
-
this.parseColors();
|
413
|
-
|
414
|
-
// Don't want to do this again
|
415
|
-
this.colorsParsed = true;
|
416
|
-
}
|
417
|
-
|
418
|
-
|
419
|
-
/**
|
420
|
-
* Work out the scale
|
421
|
-
*/
|
422
|
-
var max = prop['chart.ymax'];
|
423
|
-
var min = prop['chart.ymin'];
|
424
|
-
|
425
|
-
if (typeof(max) == 'number') {
|
426
|
-
this.max = max;
|
427
|
-
this.scale2 = RG.getScale2(this, {
|
428
|
-
'max':max,
|
429
|
-
'min':min,
|
430
|
-
'strict':true,
|
431
|
-
'scale.decimals':Number(prop['chart.scale.decimals']),
|
432
|
-
'scale.point':prop['chart.scale.point'],
|
433
|
-
'scale.thousand':prop['chart.scale.thousand'],
|
434
|
-
'scale.round':prop['chart.scale.round'],
|
435
|
-
'units.pre':prop['chart.units.pre'],
|
436
|
-
'units.post':prop['chart.units.post'],
|
437
|
-
'ylabels.count':prop['chart.labels.count']
|
438
|
-
});
|
439
|
-
} else {
|
440
|
-
|
441
|
-
for (var i=0; i<this.data.length; i+=1) {
|
442
|
-
for (var j=0,len=this.data[i].length; j<len; j+=1) {
|
443
|
-
this.max = Math.max(this.max, this.data[i][j][1]);
|
444
|
-
}
|
445
|
-
}
|
446
|
-
|
447
|
-
this.min = prop['chart.ymin'];
|
448
|
-
|
449
|
-
this.scale2 = RG.getScale2(this, {
|
450
|
-
'max':this.max,
|
451
|
-
'min':min,
|
452
|
-
'scale.decimals':Number(prop['chart.scale.decimals']),
|
453
|
-
'scale.point':prop['chart.scale.point'],
|
454
|
-
'scale.thousand':prop['chart.scale.thousand'],
|
455
|
-
'scale.round':prop['chart.scale.round'],
|
456
|
-
'units.pre':prop['chart.units.pre'],
|
457
|
-
'units.post':prop['chart.units.post'],
|
458
|
-
'ylabels.count':prop['chart.labels.count']
|
459
|
-
});
|
460
|
-
this.max = this.scale2.max;
|
461
|
-
}
|
462
|
-
|
463
|
-
/**
|
464
|
-
* Change the centerx marginally if the key is defined
|
465
|
-
*/
|
466
|
-
if (prop['chart.key'] && prop['chart.key'].length > 0 && prop['chart.key'].length >= 3) {
|
467
|
-
this.centerx = this.centerx - prop['chart.gutter.right'] + 5;
|
468
|
-
}
|
469
|
-
|
470
|
-
/**
|
471
|
-
* Populate the colors array for the purposes of generating the key
|
472
|
-
*/
|
473
|
-
if (typeof(prop['chart.key']) == 'object' && RG.is_array(prop['chart.key']) && prop['chart.key'][0]) {
|
474
|
-
|
475
|
-
// Reset the colors array
|
476
|
-
prop['chart.colors'] = [];
|
477
|
-
|
478
|
-
for (var i=0; i<this.data.length; i+=1) {
|
479
|
-
for (var j=0,len=this.data[i].length; j<len; j+=1) {
|
480
|
-
if (typeof this.data[i][j][2] == 'string') {
|
481
|
-
prop['chart.colors'].push(this.data[i][j][2]);
|
482
|
-
}
|
483
|
-
}
|
484
|
-
}
|
485
|
-
}
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
/**
|
491
|
-
* Populate the chart.tooltips array
|
492
|
-
*/
|
493
|
-
this.Set('chart.tooltips', []);
|
494
|
-
|
495
|
-
for (var i=0; i<this.data.length; i+=1) {
|
496
|
-
for (var j=0,len=this.data[i].length; j<len; j+=1) {
|
497
|
-
if (typeof this.data[i][j][3] == 'string') {
|
498
|
-
prop['chart.tooltips'].push(this.data[i][j][3]);
|
499
|
-
}
|
500
|
-
}
|
501
|
-
}
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
// This resets the chart drawing state
|
506
|
-
co.beginPath();
|
507
|
-
|
508
|
-
this.DrawBackground();
|
509
|
-
this.DrawRscatter();
|
510
|
-
this.DrawLabels();
|
511
|
-
|
512
|
-
/**
|
513
|
-
* Setup the context menu if required
|
514
|
-
*/
|
515
|
-
if (prop['chart.contextmenu']) {
|
516
|
-
RG.ShowContext(this);
|
517
|
-
}
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
// Draw the title if any has been set
|
522
|
-
if (prop['chart.title']) {
|
523
|
-
RG.DrawTitle(
|
524
|
-
this,
|
525
|
-
prop['chart.title'],
|
526
|
-
this.centery - this.radius - 10,
|
527
|
-
this.centerx,
|
528
|
-
prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
|
529
|
-
);
|
530
|
-
}
|
531
|
-
|
532
|
-
|
533
|
-
/**
|
534
|
-
* This function enables resizing
|
535
|
-
*/
|
536
|
-
if (prop['chart.resizable']) {
|
537
|
-
RG.AllowResizing(this);
|
538
|
-
}
|
539
|
-
|
540
|
-
|
541
|
-
/**
|
542
|
-
* This installs the event listeners
|
543
|
-
*/
|
544
|
-
RG.InstallEventListeners(this);
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
//
|
552
|
-
// Allow the segments to be highlighted
|
553
|
-
//
|
554
|
-
if (prop['chart.segment.highlight']) {
|
555
|
-
RG.allowSegmentHighlight({
|
556
|
-
object: this,
|
557
|
-
|
558
|
-
// This is duplicated in the drawBackground function
|
559
|
-
count: typeof prop['chart.segment.highlight.count'] === 'number' ? prop['chart.segment.highlight.count'] : ((prop['chart.background.grid.diagonals.count'] ? prop['chart.background.grid.diagonals.count'] : (prop['chart.labels'] ? prop['chart.labels'].length : 8))),
|
560
|
-
|
561
|
-
fill: prop['chart.segment.highlight.fill'],
|
562
|
-
stroke: prop['chart.segment.highlight.stroke']
|
563
|
-
});
|
564
|
-
}
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
/**
|
570
|
-
* Fire the onfirstdraw event
|
571
|
-
*/
|
572
|
-
if (this.firstDraw) {
|
573
|
-
RG.fireCustomEvent(this, 'onfirstdraw');
|
574
|
-
this.firstDraw = false;
|
575
|
-
this.firstDrawFunc();
|
576
|
-
}
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
/**
|
582
|
-
* Fire the RGraph ondraw event
|
583
|
-
*/
|
584
|
-
RG.FireCustomEvent(this, 'ondraw');
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
return this;
|
590
|
-
};
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
/**
|
596
|
-
* This method draws the rscatter charts background
|
597
|
-
*/
|
598
|
-
this.drawBackground =
|
599
|
-
this.DrawBackground = function ()
|
600
|
-
{
|
601
|
-
//
|
602
|
-
// Draw the background color first
|
603
|
-
//
|
604
|
-
if (prop['chart.background.color'] != 'transparent') {
|
605
|
-
pa2(co, ['b','a', this.centerx, this.centery, this.radius, 0, 2 * ma.PI, -1, 'f', prop['chart.background.color']]);
|
606
|
-
}
|
607
|
-
|
608
|
-
|
609
|
-
var gridEnabled = prop['chart.background.grid'];
|
610
|
-
|
611
|
-
|
612
|
-
if (gridEnabled) {
|
613
|
-
co.lineWidth = prop['chart.background.grid.linewidth'];
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
// Draw the background grey circles
|
618
|
-
if (prop['chart.background.grid.radials']) {
|
619
|
-
|
620
|
-
co.strokeStyle = prop['chart.background.grid.color'];
|
621
|
-
|
622
|
-
if (RG.isNull(prop['chart.background.grid.radials.count'])) {
|
623
|
-
prop['chart.background.grid.radials.count'] = prop['chart.labels.count'];
|
624
|
-
}
|
625
|
-
|
626
|
-
// Radius must be greater than 0 for Opera to work
|
627
|
-
|
628
|
-
var r = this.radius / prop['chart.background.grid.radials.count'];
|
629
|
-
|
630
|
-
for (var i=0,len=this.radius; i<=len; i+=r) {
|
631
|
-
|
632
|
-
// Radius must be greater than 0 for Opera to work
|
633
|
-
co.arc(this.centerx, this.centery, i, 0, RG.TWOPI, 0);
|
634
|
-
}
|
635
|
-
co.stroke();
|
636
|
-
}
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
// Draw the background lines that go from the center outwards
|
645
|
-
if (prop['chart.background.grid.diagonals']) {
|
646
|
-
|
647
|
-
co.strokeStyle = prop['chart.background.grid.color'];
|
648
|
-
|
649
|
-
co.beginPath();
|
650
|
-
|
651
|
-
// This is duplicated in the allowSegmentHighlight call
|
652
|
-
var inc = 360 / ((prop['chart.background.grid.diagonals.count'] ? prop['chart.background.grid.diagonals.count'] : (prop['chart.labels'] ? prop['chart.labels'].length : 8)));
|
653
|
-
|
654
|
-
|
655
|
-
for (var i=inc; i<360; i+=inc) {
|
656
|
-
|
657
|
-
// Radius must be greater than 0 for Opera to work
|
658
|
-
co.arc(
|
659
|
-
this.centerx,
|
660
|
-
this.centery,
|
661
|
-
this.radius,
|
662
|
-
(i / (180 / RG.PI)) - RG.HALFPI,
|
663
|
-
((i + 0.01) / (180 / RG.PI)) - RG.HALFPI,
|
664
|
-
0
|
665
|
-
);
|
666
|
-
|
667
|
-
co.lineTo(this.centerx, this.centery);
|
668
|
-
}
|
669
|
-
co.stroke();
|
670
|
-
}
|
671
|
-
}
|
672
|
-
|
673
|
-
// Reset the linewidth
|
674
|
-
co.lineWidth = 1;
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
co.beginPath();
|
689
|
-
co.strokeStyle = prop['chart.axes.color'];
|
690
|
-
|
691
|
-
// Draw the X axis
|
692
|
-
co.moveTo(this.centerx - this.radius, Math.round(this.centery));
|
693
|
-
co.lineTo(this.centerx + this.radius, Math.round(this.centery));
|
694
|
-
|
695
|
-
// Draw the X ends
|
696
|
-
if (prop['chart.axes.caps']) {
|
697
|
-
co.moveTo(ma.round(this.centerx - this.radius), this.centery - 5);
|
698
|
-
co.lineTo(ma.round(this.centerx - this.radius), this.centery + 5);
|
699
|
-
co.moveTo(ma.round(this.centerx + this.radius), this.centery - 5);
|
700
|
-
co.lineTo(ma.round(this.centerx + this.radius), this.centery + 5);
|
701
|
-
}
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
if (!RG.isNull(prop['chart.axes.numticks'])) {
|
706
|
-
var numticks = prop['chart.axes.numticks']
|
707
|
-
} else {
|
708
|
-
var numticks = prop['chart.labels.count'];
|
709
|
-
}
|
710
|
-
|
711
|
-
var caps = prop['chart.axes.caps'];
|
712
|
-
|
713
|
-
if (numticks) {
|
714
|
-
// Draw the X check marks
|
715
|
-
for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=(this.radius / numticks)) {
|
716
|
-
co.moveTo(ma.round(i), this.centery - 3);
|
717
|
-
co.lineTo(ma.round(i), this.centery + 3);
|
718
|
-
}
|
719
|
-
|
720
|
-
// Draw the Y check marks
|
721
|
-
for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=(this.radius / numticks)) {
|
722
|
-
co.moveTo(this.centerx - 3, ma.round(i));
|
723
|
-
co.lineTo(this.centerx + 3, ma.round(i));
|
724
|
-
}
|
725
|
-
}
|
726
|
-
|
727
|
-
// Draw the Y axis
|
728
|
-
co.moveTo(ma.round(this.centerx), this.centery - this.radius);
|
729
|
-
co.lineTo(ma.round(this.centerx), this.centery + this.radius);
|
730
|
-
|
731
|
-
// Draw the Y ends
|
732
|
-
if (prop['chart.axes.caps']) {
|
733
|
-
co.moveTo(this.centerx - 5, ma.round(this.centery - this.radius));
|
734
|
-
co.lineTo(this.centerx + 5, ma.round(this.centery - this.radius));
|
735
|
-
|
736
|
-
co.moveTo(this.centerx - 5, ma.round(this.centery + this.radius));
|
737
|
-
co.lineTo(this.centerx + 5, ma.round(this.centery + this.radius));
|
738
|
-
}
|
739
|
-
|
740
|
-
// Stroke it
|
741
|
-
co.closePath();
|
742
|
-
co.stroke();
|
743
|
-
};
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
/**
|
749
|
-
* This method draws a set of data on the graph
|
750
|
-
*/
|
751
|
-
this.drawRscatter =
|
752
|
-
this.DrawRscatter = function ()
|
753
|
-
{
|
754
|
-
for (var dataset=0; dataset<this.data.length; dataset+=1) {
|
755
|
-
|
756
|
-
var data = this.data[dataset];
|
757
|
-
|
758
|
-
// Don't do this
|
759
|
-
// this.coords = [];
|
760
|
-
|
761
|
-
this.coords2[dataset] = [];
|
762
|
-
|
763
|
-
var drawPoints = function (obj)
|
764
|
-
{
|
765
|
-
for (var i=0; i<data.length; ++i) {
|
766
|
-
|
767
|
-
var d1 = data[i][0],
|
768
|
-
d2 = data[i][1],
|
769
|
-
a = d1 / (180 / RG.PI), // RADIANS
|
770
|
-
r = ( (d2 - prop['chart.ymin']) / (obj.scale2.max - obj.scale2.min) ) * obj.radius,
|
771
|
-
x = ma.sin(a) * r,
|
772
|
-
y = ma.cos(a) * r,
|
773
|
-
color = data[i][2] ? data[i][2] : prop['chart.colors.default'],
|
774
|
-
tooltip = data[i][3] ? data[i][3] : null
|
775
|
-
|
776
|
-
if (tooltip && String(tooltip).length) {
|
777
|
-
obj.hasTooltips = true;
|
778
|
-
}
|
779
|
-
|
780
|
-
/**
|
781
|
-
* Account for the correct quadrant
|
782
|
-
*/
|
783
|
-
x = x + obj.centerx;
|
784
|
-
y = obj.centery - y;
|
785
|
-
|
786
|
-
|
787
|
-
obj.drawTick(x, y, color);
|
788
|
-
|
789
|
-
// Populate the coords array with the coordinates and the tooltip
|
790
|
-
|
791
|
-
obj.coords.push([x, y, color, tooltip]);
|
792
|
-
obj.coords2[dataset].push([x, y, color, tooltip]);
|
793
|
-
}
|
794
|
-
}
|
795
|
-
|
796
|
-
drawPoints(this);
|
797
|
-
|
798
|
-
if (prop['chart.line']) {
|
799
|
-
this.drawLine(dataset);
|
800
|
-
}
|
801
|
-
|
802
|
-
// Causes tooltips not to appear sometimes on this demo page:
|
803
|
-
// /demos/rscatter-multiple-datasets-single-array.html
|
804
|
-
//
|
805
|
-
//drawPoints(this);
|
806
|
-
}
|
807
|
-
};
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
/*
|
813
|
-
* Draws a connecting line through the points if requested
|
814
|
-
*
|
815
|
-
* @param object opt The options to the line
|
816
|
-
*/
|
817
|
-
this.drawLine = function (idx)
|
818
|
-
{
|
819
|
-
var opt = {
|
820
|
-
dataset: idx,
|
821
|
-
coords: this.coords2[idx],
|
822
|
-
color: prop['chart.line.colors'][idx],
|
823
|
-
shadow: prop['chart.line.shadow'],
|
824
|
-
shadowColor: prop['chart.line.shadow.color'],
|
825
|
-
shadowOffsetX: prop['chart.line.shadow.offsetx'],
|
826
|
-
shadowOffsetY: prop['chart.line.shadow.offsety'],
|
827
|
-
shadowBlur: prop['chart.line.shadow.blur'],
|
828
|
-
linewidth: prop['chart.line.linewidth']
|
829
|
-
};
|
830
|
-
|
831
|
-
co.beginPath();
|
832
|
-
|
833
|
-
co.strokeStyle = this.parseSingleColorForGradient(opt.color);
|
834
|
-
co.lineWidth = typeof prop['chart.line.linewidth'] === 'object' ? prop['chart.line.linewidth'][idx] : prop['chart.line.linewidth'];
|
835
|
-
co.lineCap = 'round';
|
836
|
-
|
837
|
-
if (opt.shadow) {
|
838
|
-
RG.setShadow(
|
839
|
-
this,
|
840
|
-
opt.shadowColor,
|
841
|
-
opt.shadowOffsetX,
|
842
|
-
opt.shadowOffsetY,
|
843
|
-
opt.shadowBlur
|
844
|
-
);
|
845
|
-
}
|
846
|
-
|
847
|
-
for (var i=0; i<this.coords2[idx].length; ++i) {
|
848
|
-
if (i === 0) {
|
849
|
-
co.moveTo(this.coords2[idx][i][0], this.coords2[idx][i][1]);
|
850
|
-
|
851
|
-
var startCoords = RG.arrayClone(this.coords2[idx]);
|
852
|
-
|
853
|
-
} else {
|
854
|
-
co.lineTo(this.coords2[idx][i][0], this.coords2[idx][i][1]);
|
855
|
-
}
|
856
|
-
}
|
857
|
-
|
858
|
-
// Draw the line back to the start?
|
859
|
-
if (
|
860
|
-
(typeof prop['chart.line.close'] === 'boolean' && prop['chart.line.close'])
|
861
|
-
|| (typeof prop['chart.line.close'] === 'object' && prop['chart.line.close'][idx])
|
862
|
-
) {
|
863
|
-
co.lineTo(this.coords2[idx][0][0], this.coords2[idx][0][1]);
|
864
|
-
}
|
865
|
-
|
866
|
-
co.stroke();
|
867
|
-
|
868
|
-
RG.noShadow(this);
|
869
|
-
};
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
/**
|
875
|
-
* Unsuprisingly, draws the labels
|
876
|
-
*/
|
877
|
-
this.drawLabels =
|
878
|
-
this.DrawLabels = function ()
|
879
|
-
{
|
880
|
-
co.lineWidth = 1;
|
881
|
-
|
882
|
-
// Default the color to black
|
883
|
-
co.fillStyle = 'black';
|
884
|
-
co.strokeStyle = 'black';
|
885
|
-
|
886
|
-
var key = prop['chart.key'];
|
887
|
-
var r = this.radius;
|
888
|
-
var axesColor = prop['chart.axes.color'];
|
889
|
-
var color = prop['chart.text.color'];
|
890
|
-
var font = prop['chart.text.font'];
|
891
|
-
var size = prop['chart.text.size'];
|
892
|
-
var axes = prop['chart.labels.axes'].toLowerCase();
|
893
|
-
var units_pre = prop['chart.units.pre'];
|
894
|
-
var units_post = prop['chart.units.post'];
|
895
|
-
var decimals = prop['chart.scale.decimals'];
|
896
|
-
var centerx = this.centerx;
|
897
|
-
var centery = this.centery;
|
898
|
-
|
899
|
-
co.fillStyle = prop['chart.text.color'];
|
900
|
-
|
901
|
-
// Draw any labels
|
902
|
-
if (typeof prop['chart.labels'] == 'object' && prop['chart.labels']) {
|
903
|
-
this.DrawCircularLabels(co, prop['chart.labels'], font , size, r);
|
904
|
-
}
|
905
|
-
|
906
|
-
|
907
|
-
//
|
908
|
-
// If the axes are transparent - then the labels should have no offset,
|
909
|
-
// otherwise it defaults to true. Similarly the labels can or can't be
|
910
|
-
// centered if there's no axes
|
911
|
-
//
|
912
|
-
var offset = 10;
|
913
|
-
var centered = false;
|
914
|
-
|
915
|
-
if ( axesColor === 'rgba(0,0,0,0)'
|
916
|
-
|| axesColor === 'rgb(0,0,0)'
|
917
|
-
|| axesColor === 'transparent') {
|
918
|
-
|
919
|
-
offset = 0;
|
920
|
-
centered = true;
|
921
|
-
}
|
922
|
-
|
923
|
-
// Draw the axis labels
|
924
|
-
for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
|
925
|
-
if (axes.indexOf('n') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - offset,'y':centery - (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':centered ? 'center' : 'right',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
|
926
|
-
if (axes.indexOf('s') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - offset,'y':centery + (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':centered ? 'center' : 'right',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
|
927
|
-
if (axes.indexOf('e') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx + (r * ((i+1) / len)),'y':centery + offset,'text':this.scale2.labels[i],'valign':centered ? 'center' : 'top','halign':'center',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
|
928
|
-
if (axes.indexOf('w') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - (r * ((i+1) / len)),'y':centery + offset,'text':this.scale2.labels[i],'valign':centered ? 'center' : 'top','halign':'center',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
|
929
|
-
}
|
930
|
-
|
931
|
-
// Draw the center minimum value (but only if there's at least one axes labels stipulated)
|
932
|
-
if (prop['chart.labels.axes'].length > 0 && prop['chart.scale.zerostart']) {
|
933
|
-
RG.text2(this, {
|
934
|
-
'font':font,
|
935
|
-
'size':size,
|
936
|
-
'x':centerx,
|
937
|
-
'y':centery,
|
938
|
-
'text':RG.numberFormat(this, Number(this.scale2.min).toFixed(this.scale2.decimals), this.scale2.units_pre, this.scale2.units_post),
|
939
|
-
'valign':'center',
|
940
|
-
'halign':'center',
|
941
|
-
'bounding':true,
|
942
|
-
'boundingFill': prop['chart.labels.axes.background'],
|
943
|
-
'boundingStroke': 'rgba(0,0,0,0)',
|
944
|
-
'tag': 'scale'
|
945
|
-
});
|
946
|
-
}
|
947
|
-
|
948
|
-
/**
|
949
|
-
* Draw the key
|
950
|
-
*/
|
951
|
-
if (key && key.length) {
|
952
|
-
RG.drawKey(this, key, prop['chart.colors']);
|
953
|
-
}
|
954
|
-
};
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
/**
|
960
|
-
* Draws the circular labels that go around the charts
|
961
|
-
*
|
962
|
-
* @param labels array The labels that go around the chart
|
963
|
-
*/
|
964
|
-
this.drawCircularLabels =
|
965
|
-
this.DrawCircularLabels = function (context, labels, font_face, font_size, r)
|
966
|
-
{
|
967
|
-
var r = r + 10,
|
968
|
-
color = prop['chart.labels.color'];
|
969
|
-
|
970
|
-
for (var i=0; i<labels.length; ++i) {
|
971
|
-
|
972
|
-
var a = (360 / labels.length) * (i + 1) - (360 / (labels.length * 2));
|
973
|
-
var a = a - 90 + (prop['chart.labels.position'] == 'edge' ? ((360 / labels.length) / 2) : 0);
|
974
|
-
|
975
|
-
var x = ma.cos(a / (180/RG.PI) ) * r;
|
976
|
-
var y = ma.sin(a / (180/RG.PI)) * r;
|
977
|
-
|
978
|
-
RG.Text2(this, {
|
979
|
-
'color': color,
|
980
|
-
'font':font_face,
|
981
|
-
'size':font_size,
|
982
|
-
'x':this.centerx + x,
|
983
|
-
'y':this.centery + y,
|
984
|
-
'text':String(labels[i]),
|
985
|
-
'valign':'center',
|
986
|
-
'halign':( (this.centerx + x) > this.centerx) ? 'left' : 'right',
|
987
|
-
'tag': 'labels'
|
988
|
-
});
|
989
|
-
}
|
990
|
-
};
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
/**
|
996
|
-
* Draws a single tickmark
|
997
|
-
*/
|
998
|
-
this.drawTick =
|
999
|
-
this.DrawTick = function (x, y, color)
|
1000
|
-
{
|
1001
|
-
var tickmarks = prop['chart.tickmarks'];
|
1002
|
-
var ticksize = prop['chart.ticksize'];
|
1003
|
-
|
1004
|
-
co.strokeStyle = color;
|
1005
|
-
co.fillStyle = color;
|
1006
|
-
|
1007
|
-
// Set the linewidth for the tickmark to 1
|
1008
|
-
var prevLinewidth = co.lineWidth;
|
1009
|
-
co.lineWidth = 1;
|
1010
|
-
|
1011
|
-
// Cross
|
1012
|
-
if (tickmarks == 'cross') {
|
1013
|
-
|
1014
|
-
co.beginPath();
|
1015
|
-
co.moveTo(x + ticksize, y + ticksize);
|
1016
|
-
co.lineTo(x - ticksize, y - ticksize);
|
1017
|
-
co.stroke();
|
1018
|
-
|
1019
|
-
co.beginPath();
|
1020
|
-
co.moveTo(x - ticksize, y + ticksize);
|
1021
|
-
co.lineTo(x + ticksize, y - ticksize);
|
1022
|
-
co.stroke();
|
1023
|
-
|
1024
|
-
// Circle
|
1025
|
-
} else if (tickmarks == 'circle') {
|
1026
|
-
|
1027
|
-
co.beginPath();
|
1028
|
-
co.arc(x, y, ticksize, 0, 6.2830, false);
|
1029
|
-
co.fill();
|
1030
|
-
|
1031
|
-
// Square
|
1032
|
-
} else if (tickmarks == 'square') {
|
1033
|
-
|
1034
|
-
co.beginPath();
|
1035
|
-
co.fillRect(x - ticksize, y - ticksize, 2 * ticksize, 2 * ticksize);
|
1036
|
-
co.fill();
|
1037
|
-
|
1038
|
-
// Diamond shape tickmarks
|
1039
|
-
} else if (tickmarks == 'diamond') {
|
1040
|
-
|
1041
|
-
co.beginPath();
|
1042
|
-
co.moveTo(x, y - ticksize);
|
1043
|
-
co.lineTo(x + ticksize, y);
|
1044
|
-
co.lineTo(x, y + ticksize);
|
1045
|
-
co.lineTo(x - ticksize, y);
|
1046
|
-
co.closePath();
|
1047
|
-
co.fill();
|
1048
|
-
|
1049
|
-
// Plus style tickmarks
|
1050
|
-
} else if (tickmarks == 'plus') {
|
1051
|
-
|
1052
|
-
co.lineWidth = 1;
|
1053
|
-
|
1054
|
-
co.beginPath();
|
1055
|
-
co.moveTo(x, y - ticksize);
|
1056
|
-
co.lineTo(x, y + ticksize);
|
1057
|
-
co.moveTo(x - ticksize, y);
|
1058
|
-
co.lineTo(x + ticksize, y);
|
1059
|
-
co.stroke();
|
1060
|
-
}
|
1061
|
-
|
1062
|
-
|
1063
|
-
co.lineWidth = prevLinewidth;
|
1064
|
-
};
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
/**
|
1070
|
-
* This function makes it much easier to get the (if any) point that is currently being hovered over.
|
1071
|
-
*
|
1072
|
-
* @param object e The event object
|
1073
|
-
*/
|
1074
|
-
this.getShape =
|
1075
|
-
this.getPoint = function (e)
|
1076
|
-
{
|
1077
|
-
var mouseXY = RG.getMouseXY(e);
|
1078
|
-
var mouseX = mouseXY[0];
|
1079
|
-
var mouseY = mouseXY[1];
|
1080
|
-
var overHotspot = false;
|
1081
|
-
var offset = prop['chart.tooltips.hotspot']; // This is how far the hotspot extends
|
1082
|
-
|
1083
|
-
for (var i=0,len=this.coords.length; i<len; ++i) {
|
1084
|
-
|
1085
|
-
var x = this.coords[i][0];
|
1086
|
-
var y = this.coords[i][1];
|
1087
|
-
var tooltip = this.coords[i][3];
|
1088
|
-
|
1089
|
-
if (
|
1090
|
-
mouseX < (x + offset) &&
|
1091
|
-
mouseX > (x - offset) &&
|
1092
|
-
mouseY < (y + offset) &&
|
1093
|
-
mouseY > (y - offset)
|
1094
|
-
) {
|
1095
|
-
|
1096
|
-
var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
|
1097
|
-
|
1098
|
-
return {0:this,1:x,2:y,3:i,'object':this, 'x':x, 'y':y, 'index':i, 'tooltip': tooltip};
|
1099
|
-
}
|
1100
|
-
}
|
1101
|
-
};
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
/**
|
1107
|
-
* This function facilitates the installation of tooltip event listeners if
|
1108
|
-
* tooltips are defined.
|
1109
|
-
*/
|
1110
|
-
this.allowTooltips =
|
1111
|
-
this.AllowTooltips = function ()
|
1112
|
-
{
|
1113
|
-
// Preload any tooltip images that are used in the tooltips
|
1114
|
-
RG.PreLoadTooltipImages(this);
|
1115
|
-
|
1116
|
-
|
1117
|
-
/**
|
1118
|
-
* This installs the window mousedown event listener that lears any
|
1119
|
-
* highlight that may be visible.
|
1120
|
-
*/
|
1121
|
-
RG.InstallWindowMousedownTooltipListener(this);
|
1122
|
-
|
1123
|
-
|
1124
|
-
/**
|
1125
|
-
* This installs the canvas mousemove event listener. This function
|
1126
|
-
* controls the pointer shape.
|
1127
|
-
*/
|
1128
|
-
RG.InstallCanvasMousemoveTooltipListener(this);
|
1129
|
-
|
1130
|
-
|
1131
|
-
/**
|
1132
|
-
* This installs the canvas mouseup event listener. This is the
|
1133
|
-
* function that actually shows the appropriate tooltip (if any).
|
1134
|
-
*/
|
1135
|
-
RG.InstallCanvasMouseupTooltipListener(this);
|
1136
|
-
};
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
/**
|
1142
|
-
* Each object type has its own Highlight() function which highlights the appropriate shape
|
1143
|
-
*
|
1144
|
-
* @param object shape The shape to highlight
|
1145
|
-
*/
|
1146
|
-
this.highlight =
|
1147
|
-
this.Highlight = function (shape)
|
1148
|
-
{
|
1149
|
-
if (typeof prop['chart.highlight.style'] === 'function') {
|
1150
|
-
(prop['chart.highlight.style'])(shape);
|
1151
|
-
} else {
|
1152
|
-
RG.Highlight.Point(this, shape);
|
1153
|
-
}
|
1154
|
-
};
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
/**
|
1160
|
-
* The getObjectByXY() worker method. Don't call this call:
|
1161
|
-
*
|
1162
|
-
* RGraph.ObjectRegistry.getObjectByXY(e)
|
1163
|
-
*
|
1164
|
-
* @param object e The event object
|
1165
|
-
*/
|
1166
|
-
this.getObjectByXY = function (e)
|
1167
|
-
{
|
1168
|
-
var mouseXY = RG.getMouseXY(e);
|
1169
|
-
var mouseX = mouseXY[0];
|
1170
|
-
var mouseY = mouseXY[1];
|
1171
|
-
var centerx = this.centerx;
|
1172
|
-
var centery = this.centery;
|
1173
|
-
var radius = this.radius;
|
1174
|
-
|
1175
|
-
if (
|
1176
|
-
mouseX > (centerx - radius)
|
1177
|
-
&& mouseX < (centerx + radius)
|
1178
|
-
&& mouseY > (centery - radius)
|
1179
|
-
&& mouseY < (centery + radius)
|
1180
|
-
) {
|
1181
|
-
|
1182
|
-
return this;
|
1183
|
-
}
|
1184
|
-
};
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
/**
|
1190
|
-
* This function positions a tooltip when it is displayed
|
1191
|
-
*
|
1192
|
-
* @param obj object The chart object
|
1193
|
-
* @param int x The X coordinate specified for the tooltip
|
1194
|
-
* @param int y The Y coordinate specified for the tooltip
|
1195
|
-
* @param objec tooltip The tooltips DIV element
|
1196
|
-
*
|
1197
|
-
this.positionTooltip = function (obj, x, y, tooltip, idx)
|
1198
|
-
{
|
1199
|
-
var coordX = obj.coords[tooltip.__index__][0];
|
1200
|
-
var coordY = obj.coords[tooltip.__index__][1];
|
1201
|
-
var canvasXY = RG.getCanvasXY(obj.canvas);
|
1202
|
-
var mouseXY = RG.getMouseXY(window.event);
|
1203
|
-
var gutterLeft = obj.gutterLeft;
|
1204
|
-
var gutterTop = obj.gutterTop;
|
1205
|
-
var width = tooltip.offsetWidth;
|
1206
|
-
var height = tooltip.offsetHeight;
|
1207
|
-
|
1208
|
-
// Set the top position
|
1209
|
-
tooltip.style.left = 0;
|
1210
|
-
tooltip.style.top = window.event.pageY - height - 5 + 'px';
|
1211
|
-
|
1212
|
-
// By default any overflow is hidden
|
1213
|
-
tooltip.style.overflow = '';
|
1214
|
-
|
1215
|
-
// Reposition the tooltip if at the edges:
|
1216
|
-
|
1217
|
-
// LEFT edge
|
1218
|
-
if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
|
1219
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
|
1220
|
-
|
1221
|
-
// RIGHT edge
|
1222
|
-
} else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
|
1223
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
|
1224
|
-
|
1225
|
-
// Default positioning - CENTERED
|
1226
|
-
} else {
|
1227
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
|
1228
|
-
}
|
1229
|
-
};*/
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
/**
|
1235
|
-
* This function returns the radius (ie the distance from the center) for a particular
|
1236
|
-
* value.
|
1237
|
-
*
|
1238
|
-
* @param number value The value you want the radius for
|
1239
|
-
*/
|
1240
|
-
this.getRadius = function (value)
|
1241
|
-
{
|
1242
|
-
var max = this.max;
|
1243
|
-
|
1244
|
-
if (value < 0 || value > max) {
|
1245
|
-
return null;
|
1246
|
-
}
|
1247
|
-
|
1248
|
-
var r = (value / max) * this.radius;
|
1249
|
-
|
1250
|
-
return r;
|
1251
|
-
};
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
/**
|
1257
|
-
* This allows for easy specification of gradients
|
1258
|
-
*/
|
1259
|
-
this.parseColors = function ()
|
1260
|
-
{
|
1261
|
-
// Save the original colors so that they can be restored when the canvas is reset
|
1262
|
-
if (this.original_colors.length === 0) {
|
1263
|
-
this.original_colors['data'] = RG.array_clone(this.data);
|
1264
|
-
this.original_colors['chart.highlight.stroke'] = RG.arrayClone(prop['chart.highlight.stroke']);
|
1265
|
-
this.original_colors['chart.highlight.fill'] = RG.arrayClone(prop['chart.highlight.fill']);
|
1266
|
-
this.original_colors['chart.colors.default'] = RG.arrayClone(prop['chart.colors.default']);
|
1267
|
-
this.original_colors['chart.background.grid.color'] = RG.arrayClone(prop['chart.background.grid.color']);
|
1268
|
-
this.original_colors['chart.background.color'] = RG.arrayClone(prop['chart.background.color']);
|
1269
|
-
this.original_colors['chart.segment.highlight.stroke'] = RG.arrayClone(prop['chart.segment.highlight.stroke']);
|
1270
|
-
this.original_colors['chart.segment.highlight.fill'] = RG.arrayClone(prop['chart.segment.highlight.fill']);
|
1271
|
-
}
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
// Go through the data
|
1279
|
-
for (var i=0; i<this.data.length; i+=1) {
|
1280
|
-
for (var j=0,len=this.data[i].length; j<len; j+=1) {
|
1281
|
-
this.data[i][j][2] = this.parseSingleColorForGradient(this.data[i][j][2]);
|
1282
|
-
}
|
1283
|
-
}
|
1284
|
-
|
1285
|
-
prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
|
1286
|
-
prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
|
1287
|
-
prop['chart.colors.default'] = this.parseSingleColorForGradient(prop['chart.colors.default']);
|
1288
|
-
prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
|
1289
|
-
prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
|
1290
|
-
prop['chart.segment.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.stroke']);
|
1291
|
-
prop['chart.segment.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.fill']);
|
1292
|
-
};
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
/**
|
1298
|
-
* Use this function to reset the object to the post-constructor state. Eg reset colors if
|
1299
|
-
* need be etc
|
1300
|
-
*/
|
1301
|
-
this.reset = function ()
|
1302
|
-
{
|
1303
|
-
};
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
/**
|
1309
|
-
* This parses a single color value
|
1310
|
-
*/
|
1311
|
-
this.parseSingleColorForGradient = function (color)
|
1312
|
-
{
|
1313
|
-
if (!color || typeof color != 'string') {
|
1314
|
-
return color;
|
1315
|
-
}
|
1316
|
-
|
1317
|
-
if (color.match(/^gradient\((.*)\)$/i)) {
|
1318
|
-
|
1319
|
-
var parts = RegExp.$1.split(':');
|
1320
|
-
|
1321
|
-
// Create the gradient
|
1322
|
-
var grad = co.createRadialGradient(this.centerx, this.centery, 0, this.centerx, this.centery, this.radius);
|
1323
|
-
|
1324
|
-
var diff = 1 / (parts.length - 1);
|
1325
|
-
|
1326
|
-
grad.addColorStop(0, RG.trim(parts[0]));
|
1327
|
-
|
1328
|
-
for (var j=1; j<parts.length; ++j) {
|
1329
|
-
grad.addColorStop(j * diff, RG.trim(parts[j]));
|
1330
|
-
}
|
1331
|
-
}
|
1332
|
-
|
1333
|
-
return grad ? grad : color;
|
1334
|
-
};
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
/**
|
1340
|
-
* This function handles highlighting an entire data-series for the interactive
|
1341
|
-
* key
|
1342
|
-
*
|
1343
|
-
* @param int index The index of the data series to be highlighted
|
1344
|
-
*/
|
1345
|
-
this.interactiveKeyHighlight = function (index)
|
1346
|
-
{
|
1347
|
-
if (this.coords2 && this.coords2[index] && this.coords2[index].length) {
|
1348
|
-
this.coords2[index].forEach(function (value, idx, arr)
|
1349
|
-
{
|
1350
|
-
co.beginPath();
|
1351
|
-
co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
|
1352
|
-
co.arc(value[0], value[1], prop['chart.ticksize'] + 2, 0, RG.TWOPI, false);
|
1353
|
-
co.fill();
|
1354
|
-
});
|
1355
|
-
}
|
1356
|
-
};
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
/**
|
1362
|
-
* Using a function to add events makes it easier to facilitate method chaining
|
1363
|
-
*
|
1364
|
-
* @param string type The type of even to add
|
1365
|
-
* @param function func
|
1366
|
-
*/
|
1367
|
-
this.on = function (type, func)
|
1368
|
-
{
|
1369
|
-
if (type.substr(0,2) !== 'on') {
|
1370
|
-
type = 'on' + type;
|
1371
|
-
}
|
1372
|
-
|
1373
|
-
if (typeof this[type] !== 'function') {
|
1374
|
-
this[type] = func;
|
1375
|
-
} else {
|
1376
|
-
RG.addCustomEventListener(this, type, func);
|
1377
|
-
}
|
1378
|
-
|
1379
|
-
return this;
|
1380
|
-
};
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
/**
|
1386
|
-
* This helps the Gantt reset colors when the reset function is called.
|
1387
|
-
* It handles going through the data and resetting the colors.
|
1388
|
-
*/
|
1389
|
-
this.resetColorsToOriginalValues = function ()
|
1390
|
-
{
|
1391
|
-
/**
|
1392
|
-
* Copy the original colors over for single-event-per-line data
|
1393
|
-
*/
|
1394
|
-
for (var i=0,len=this.original_colors['data'].length; i<len; ++i) {
|
1395
|
-
for (var j=0,len2=this.original_colors['data'][i].length; j<len2;++j) {
|
1396
|
-
this.data[i][j][2] = RG.array_clone(this.original_colors['data'][i][j][2]);
|
1397
|
-
}
|
1398
|
-
}
|
1399
|
-
};
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
/**
|
1405
|
-
* This function runs once only
|
1406
|
-
* (put at the end of the file (before any effects))
|
1407
|
-
*/
|
1408
|
-
this.firstDrawFunc = function ()
|
1409
|
-
{
|
1410
|
-
};
|
1411
|
-
|
1412
|
-
|
1413
|
-
RG.att(ca);
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
/**
|
1419
|
-
* Register the object
|
1420
|
-
*/
|
1421
|
-
RG.Register(this);
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
/**
|
1427
|
-
* This is the 'end' of the constructor so if the first argument
|
1428
|
-
* contains configuration data - handle that.
|
1429
|
-
*/
|
1430
|
-
if (parseConfObjectForOptions) {
|
1431
|
-
RG.parseObjectStyleConfig(this, conf.options);
|
1432
|
-
}
|
1433
|
-
};
|
2
|
+
RGraph=window.RGraph||{isRGraph:true};RGraph.RScatter=RGraph.Rscatter=function(conf)
|
3
|
+
{if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var parseConfObjectForOptions=true;this.data=new Array(conf.data.length);this.data=RGraph.arrayClone(conf.data);if(typeof conf.data==='object'&&typeof conf.data[0]==='object'&&typeof conf.data[0][0]==='number'){var tmp=RGraph.arrayClone(conf.data);conf.data=new Array();conf.data[0]=RGraph.arrayClone(tmp);this.data=RGraph.arrayClone(conf.data);}}else{var conf={id:conf};conf.data=arguments[1];this.data=[];if(arguments[1][0]&&arguments[1][0][0]&&typeof arguments[1][0][0]=='object'){for(var i=0;i<arguments[1].length;++i){this.data[i]=arguments[1][i];}}else{for(var i=1;i<arguments.length;++i){this.data[i-1]=RGraph.arrayClone(arguments[i]);}}}
|
4
|
+
this.id=conf.id
|
5
|
+
this.canvas=document.getElementById(this.id)
|
6
|
+
this.context=this.canvas.getContext?this.canvas.getContext("2d"):null;this.canvas.__object__=this;this.type='rscatter';this.hasTooltips=false;this.isRGraph=true;this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.coordsText=[];this.original_colors=[];this.firstDraw=true;this.centerx=0;this.centery=0;this.radius=0;this.max=0;for(var i=0;i<this.data.length;++i){for(var j=0;j<this.data[i].length;++j){if(typeof this.data[i][j][0]==='string'){this.data[i][j][0]=parseFloat(this.data[i][j][0]);}
|
7
|
+
if(typeof this.data[i][j][1]==='string'){this.data[i][j][1]=parseFloat(this.data[i][j][1]);}}}
|
8
|
+
this.properties={'chart.background.color':'transparent','chart.background.grid':true,'chart.background.grid.diagonals':true,'chart.background.grid.diagonals.count':null,'chart.background.grid.radials':true,'chart.background.grid.radials.count':null,'chart.background.grid.linewidth':1,'chart.background.grid.color':'#ccc','chart.radius':null,'chart.colors':[],'chart.colors.default':'black','chart.gutter.left':25,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.title':'','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.bold':true,'chart.title.font':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.labels':null,'chart.labels.color':null,'chart.labels.axes':'nsew','chart.labels.axes.background':'rgba(255,255,255,0.8)','chart.labels.count':5,'chart.text.color':'black','chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.size':12,'chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.key':null,'chart.key.background':'white','chart.key.position':'graph','chart.key.halign':'right','chart.key.shadow':false,'chart.key.shadow.color':'#666','chart.key.shadow.blur':3,'chart.key.shadow.offsetx':2,'chart.key.shadow.offsety':2,'chart.key.position.gutter.boxed':false,'chart.key.position.x':null,'chart.key.position.y':null,'chart.key.color.shape':'square','chart.key.rounded':true,'chart.key.linewidth':1,'chart.key.colors':null,'chart.key.interactive':false,'chart.key.interactive.highlight.chart.fill':'rgba(255,0,0,0.9)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.text.color':'black','chart.contextmenu':null,'chart.tooltips':null,'chart.tooltips.event':'onmousemove','chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.highlight':true,'chart.tooltips.hotspot':3,'chart.tooltips.coords.page':false,'chart.annotatable':false,'chart.annotate.color':'black','chart.zoom.factor':1.5,'chart.zoom.fade.in':true,'chart.zoom.fade.out':true,'chart.zoom.hdir':'right','chart.zoom.vdir':'down','chart.zoom.frames':25,'chart.zoom.delay':16.666,'chart.zoom.shadow':true,'chart.zoom.background':true,'chart.zoom.action':'zoom','chart.resizable':false,'chart.resize.handle.background':null,'chart.ymax':null,'chart.ymin':0,'chart.tickmarks':'cross','chart.ticksize':3,'chart.scale.decimals':null,'chart.scale.point':'.','chart.scale.thousand':',','chart.scale.round':false,'chart.scale.zerostart':true,'chart.units.pre':'','chart.units.post':'','chart.events.mousemove':null,'chart.events.click':null,'chart.highlight.stroke':'transparent','chart.highlight.fill':'rgba(255,255,255,0.7)','chart.highlight.point.radius':3,'chart.axes.color':'black','chart.axes.numticks':null,'chart.axes.caps':true,'chart.segment.highlight':false,'chart.segment.highlight.count':null,'chart.segment.highlight.fill':'rgba(0,255,0,0.5)','chart.segment.highlight.stroke':'rgba(0,0,0,0)','chart.line':false,'chart.line.close':false,'chart.line.linewidth':1,'chart.line.colors':['black'],'chart.line.shadow':false,'chart.line.shadow.color':'black','chart.line.shadow.blur':2,'chart.line.shadow.offsetx':3,'chart.line.shadow.offsety':3,'chart.clearto':'rgba(0,0,0,0)'}
|
9
|
+
for(var i=0,idx=0;i<this.data.length;++i){for(var j=0,len=this.data[i].length;j<len;j+=1,idx+=1){this['$'+idx]={}}}
|
10
|
+
if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
|
11
|
+
var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
|
12
|
+
if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
|
13
|
+
this.set=this.Set=function(name,value)
|
14
|
+
{var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
|
15
|
+
if(name.substr(0,6)!='chart.'){name='chart.'+name;}
|
16
|
+
while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
|
17
|
+
if(name==='chart.segments.highlight')name='chart.segment.highlight';if(name==='chart.segments.highlight.count')name='chart.segment.highlight.count';if(name==='chart.segments.highlight.fill')name='chart.segment.highlight.fill';if(name==='chart.segments.highlight.stroke')name='chart.segment.highlight.stroke';prop[name.toLowerCase()]=value;return this;};this.get=this.Get=function(name)
|
18
|
+
{if(name.substr(0,6)!='chart.'){name='chart.'+name;}
|
19
|
+
while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
|
20
|
+
return prop[name.toLowerCase()];};this.draw=this.Draw=function()
|
21
|
+
{RG.FireCustomEvent(this,'onbeforedraw');this.gutterLeft=prop['chart.gutter.left'];this.gutterRight=prop['chart.gutter.right'];this.gutterTop=prop['chart.gutter.top'];this.gutterBottom=prop['chart.gutter.bottom'];this.radius=(Math.min(ca.width-this.gutterLeft-this.gutterRight,ca.height-this.gutterTop-this.gutterBottom)/2);this.centerx=((ca.width-this.gutterLeft-this.gutterRight)/2)+this.gutterLeft;this.centery=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop;this.coords=[];this.coords2=[];this.coordsText=[];if(typeof(prop['chart.centerx'])=='number')this.centerx=prop['chart.centerx'];if(typeof(prop['chart.centery'])=='number')this.centery=prop['chart.centery'];if(typeof(prop['chart.radius'])=='number')this.radius=prop['chart.radius'];if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
|
22
|
+
var max=prop['chart.ymax'];var min=prop['chart.ymin'];if(typeof(max)=='number'){this.max=max;this.scale2=RG.getScale2(this,{'max':max,'min':min,'strict':true,'scale.decimals':Number(prop['chart.scale.decimals']),'scale.point':prop['chart.scale.point'],'scale.thousand':prop['chart.scale.thousand'],'scale.round':prop['chart.scale.round'],'units.pre':prop['chart.units.pre'],'units.post':prop['chart.units.post'],'ylabels.count':prop['chart.labels.count']});}else{for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){this.max=Math.max(this.max,this.data[i][j][1]);}}
|
23
|
+
this.min=prop['chart.ymin'];this.scale2=RG.getScale2(this,{'max':this.max,'min':min,'scale.decimals':Number(prop['chart.scale.decimals']),'scale.point':prop['chart.scale.point'],'scale.thousand':prop['chart.scale.thousand'],'scale.round':prop['chart.scale.round'],'units.pre':prop['chart.units.pre'],'units.post':prop['chart.units.post'],'ylabels.count':prop['chart.labels.count']});this.max=this.scale2.max;}
|
24
|
+
if(prop['chart.key']&&prop['chart.key'].length>0&&prop['chart.key'].length>=3){this.centerx=this.centerx-prop['chart.gutter.right']+5;}
|
25
|
+
if(typeof(prop['chart.key'])=='object'&&RG.is_array(prop['chart.key'])&&prop['chart.key'][0]){prop['chart.colors']=[];for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){if(typeof this.data[i][j][2]=='string'){prop['chart.colors'].push(this.data[i][j][2]);}}}}
|
26
|
+
this.Set('chart.tooltips',[]);for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){if(typeof this.data[i][j][3]=='string'){prop['chart.tooltips'].push(this.data[i][j][3]);}}}
|
27
|
+
co.beginPath();this.DrawBackground();this.DrawRscatter();this.DrawLabels();if(prop['chart.contextmenu']){RG.ShowContext(this);}
|
28
|
+
if(prop['chart.title']){RG.DrawTitle(this,prop['chart.title'],this.centery-this.radius-10,this.centerx,prop['chart.title.size']?prop['chart.title.size']:prop['chart.text.size']+2);}
|
29
|
+
if(prop['chart.resizable']){RG.AllowResizing(this);}
|
30
|
+
RG.InstallEventListeners(this);if(prop['chart.segment.highlight']){RG.allowSegmentHighlight({object:this,count:typeof prop['chart.segment.highlight.count']==='number'?prop['chart.segment.highlight.count']:((prop['chart.background.grid.diagonals.count']?prop['chart.background.grid.diagonals.count']:(prop['chart.labels']?prop['chart.labels'].length:8))),fill:prop['chart.segment.highlight.fill'],stroke:prop['chart.segment.highlight.stroke']});}
|
31
|
+
if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
|
32
|
+
RG.FireCustomEvent(this,'ondraw');return this;};this.drawBackground=this.DrawBackground=function()
|
33
|
+
{if(prop['chart.background.color']!='transparent'){pa2(co,['b','a',this.centerx,this.centery,this.radius,0,2*ma.PI,-1,'f',prop['chart.background.color']]);}
|
34
|
+
var gridEnabled=prop['chart.background.grid'];if(gridEnabled){co.lineWidth=prop['chart.background.grid.linewidth'];if(prop['chart.background.grid.radials']){co.strokeStyle=prop['chart.background.grid.color'];if(RG.isNull(prop['chart.background.grid.radials.count'])){prop['chart.background.grid.radials.count']=prop['chart.labels.count'];}
|
35
|
+
var r=this.radius/prop['chart.background.grid.radials.count'];for(var i=0,len=this.radius;i<=len;i+=r){co.arc(this.centerx,this.centery,i,0,RG.TWOPI,0);}
|
36
|
+
co.stroke();}
|
37
|
+
if(prop['chart.background.grid.diagonals']){co.strokeStyle=prop['chart.background.grid.color'];co.beginPath();var inc=360/((prop['chart.background.grid.diagonals.count']?prop['chart.background.grid.diagonals.count']:(prop['chart.labels']?prop['chart.labels'].length:8)));for(var i=inc;i<360;i+=inc){co.arc(this.centerx,this.centery,this.radius,(i/(180/RG.PI))-RG.HALFPI,((i+0.01)/(180/RG.PI))-RG.HALFPI,0);co.lineTo(this.centerx,this.centery);}
|
38
|
+
co.stroke();}}
|
39
|
+
co.lineWidth=1;co.beginPath();co.strokeStyle=prop['chart.axes.color'];co.moveTo(this.centerx-this.radius,Math.round(this.centery));co.lineTo(this.centerx+this.radius,Math.round(this.centery));if(prop['chart.axes.caps']){co.moveTo(ma.round(this.centerx-this.radius),this.centery-5);co.lineTo(ma.round(this.centerx-this.radius),this.centery+5);co.moveTo(ma.round(this.centerx+this.radius),this.centery-5);co.lineTo(ma.round(this.centerx+this.radius),this.centery+5);}
|
40
|
+
if(!RG.isNull(prop['chart.axes.numticks'])){var numticks=prop['chart.axes.numticks']}else{var numticks=prop['chart.labels.count'];}
|
41
|
+
var caps=prop['chart.axes.caps'];if(numticks){for(var i=(this.centerx-this.radius);i<(this.centerx+this.radius);i+=(this.radius/numticks)){co.moveTo(ma.round(i),this.centery-3);co.lineTo(ma.round(i),this.centery+3);}
|
42
|
+
for(var i=(this.centery-this.radius);i<(this.centery+this.radius);i+=(this.radius/numticks)){co.moveTo(this.centerx-3,ma.round(i));co.lineTo(this.centerx+3,ma.round(i));}}
|
43
|
+
co.moveTo(ma.round(this.centerx),this.centery-this.radius);co.lineTo(ma.round(this.centerx),this.centery+this.radius);if(prop['chart.axes.caps']){co.moveTo(this.centerx-5,ma.round(this.centery-this.radius));co.lineTo(this.centerx+5,ma.round(this.centery-this.radius));co.moveTo(this.centerx-5,ma.round(this.centery+this.radius));co.lineTo(this.centerx+5,ma.round(this.centery+this.radius));}
|
44
|
+
co.closePath();co.stroke();};this.drawRscatter=this.DrawRscatter=function()
|
45
|
+
{for(var dataset=0;dataset<this.data.length;dataset+=1){var data=this.data[dataset];this.coords2[dataset]=[];var drawPoints=function(obj)
|
46
|
+
{for(var i=0;i<data.length;++i){var d1=data[i][0],d2=data[i][1],a=d1/(180/RG.PI),r=((d2-prop['chart.ymin'])/(obj.scale2.max-obj.scale2.min))*obj.radius,x=ma.sin(a)*r,y=ma.cos(a)*r,color=data[i][2]?data[i][2]:prop['chart.colors.default'],tooltip=data[i][3]?data[i][3]:null
|
47
|
+
if(tooltip&&String(tooltip).length){obj.hasTooltips=true;}
|
48
|
+
x=x+obj.centerx;y=obj.centery-y;obj.drawTick(x,y,color);obj.coords.push([x,y,color,tooltip]);obj.coords2[dataset].push([x,y,color,tooltip]);}}
|
49
|
+
drawPoints(this);if(prop['chart.line']){this.drawLine(dataset);}}};this.drawLine=function(idx)
|
50
|
+
{var opt={dataset:idx,coords:this.coords2[idx],color:prop['chart.line.colors'][idx],shadow:prop['chart.line.shadow'],shadowColor:prop['chart.line.shadow.color'],shadowOffsetX:prop['chart.line.shadow.offsetx'],shadowOffsetY:prop['chart.line.shadow.offsety'],shadowBlur:prop['chart.line.shadow.blur'],linewidth:prop['chart.line.linewidth']};co.beginPath();co.strokeStyle=this.parseSingleColorForGradient(opt.color);co.lineWidth=typeof prop['chart.line.linewidth']==='object'?prop['chart.line.linewidth'][idx]:prop['chart.line.linewidth'];co.lineCap='round';if(opt.shadow){RG.setShadow(this,opt.shadowColor,opt.shadowOffsetX,opt.shadowOffsetY,opt.shadowBlur);}
|
51
|
+
for(var i=0;i<this.coords2[idx].length;++i){if(i===0){co.moveTo(this.coords2[idx][i][0],this.coords2[idx][i][1]);var startCoords=RG.arrayClone(this.coords2[idx]);}else{co.lineTo(this.coords2[idx][i][0],this.coords2[idx][i][1]);}}
|
52
|
+
if((typeof prop['chart.line.close']==='boolean'&&prop['chart.line.close'])||(typeof prop['chart.line.close']==='object'&&prop['chart.line.close'][idx])){co.lineTo(this.coords2[idx][0][0],this.coords2[idx][0][1]);}
|
53
|
+
co.stroke();RG.noShadow(this);};this.drawLabels=this.DrawLabels=function()
|
54
|
+
{co.lineWidth=1;co.fillStyle='black';co.strokeStyle='black';var key=prop['chart.key'];var r=this.radius;var axesColor=prop['chart.axes.color'];var color=prop['chart.text.color'];var font=prop['chart.text.font'];var size=prop['chart.text.size'];var axes=prop['chart.labels.axes'].toLowerCase();var units_pre=prop['chart.units.pre'];var units_post=prop['chart.units.post'];var decimals=prop['chart.scale.decimals'];var centerx=this.centerx;var centery=this.centery;co.fillStyle=prop['chart.text.color'];if(typeof prop['chart.labels']=='object'&&prop['chart.labels']){this.DrawCircularLabels(co,prop['chart.labels'],font,size,r);}
|
55
|
+
var offset=10;var centered=false;if(axesColor==='rgba(0,0,0,0)'||axesColor==='rgb(0,0,0)'||axesColor==='transparent'){offset=0;centered=true;}
|
56
|
+
for(var i=0,len=this.scale2.labels.length;i<len;++i){if(axes.indexOf('n')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx-offset,'y':centery-(r*((i+1)/len)),'text':this.scale2.labels[i],'valign':'center','halign':centered?'center':'right',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});if(axes.indexOf('s')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx-offset,'y':centery+(r*((i+1)/len)),'text':this.scale2.labels[i],'valign':'center','halign':centered?'center':'right',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});if(axes.indexOf('e')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx+(r*((i+1)/len)),'y':centery+offset,'text':this.scale2.labels[i],'valign':centered?'center':'top','halign':'center',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});if(axes.indexOf('w')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx-(r*((i+1)/len)),'y':centery+offset,'text':this.scale2.labels[i],'valign':centered?'center':'top','halign':'center',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});}
|
57
|
+
if(prop['chart.labels.axes'].length>0&&prop['chart.scale.zerostart']){RG.text2(this,{'font':font,'size':size,'x':centerx,'y':centery,'text':RG.numberFormat(this,Number(this.scale2.min).toFixed(this.scale2.decimals),this.scale2.units_pre,this.scale2.units_post),'valign':'center','halign':'center','bounding':true,'boundingFill':prop['chart.labels.axes.background'],'boundingStroke':'rgba(0,0,0,0)','tag':'scale'});}
|
58
|
+
if(key&&key.length){RG.drawKey(this,key,prop['chart.colors']);}};this.drawCircularLabels=this.DrawCircularLabels=function(context,labels,font_face,font_size,r)
|
59
|
+
{var r=r+10,color=prop['chart.labels.color'];for(var i=0;i<labels.length;++i){var a=(360/labels.length)*(i+1)-(360/(labels.length*2));var a=a-90+(prop['chart.labels.position']=='edge'?((360/labels.length)/2):0);var x=ma.cos(a/(180/RG.PI))*r;var y=ma.sin(a/(180/RG.PI))*r;RG.Text2(this,{'color':color,'font':font_face,'size':font_size,'x':this.centerx+x,'y':this.centery+y,'text':String(labels[i]),'valign':'center','halign':((this.centerx+x)>this.centerx)?'left':'right','tag':'labels'});}};this.drawTick=this.DrawTick=function(x,y,color)
|
60
|
+
{var tickmarks=prop['chart.tickmarks'];var ticksize=prop['chart.ticksize'];co.strokeStyle=color;co.fillStyle=color;var prevLinewidth=co.lineWidth;co.lineWidth=1;if(tickmarks=='cross'){co.beginPath();co.moveTo(x+ticksize,y+ticksize);co.lineTo(x-ticksize,y-ticksize);co.stroke();co.beginPath();co.moveTo(x-ticksize,y+ticksize);co.lineTo(x+ticksize,y-ticksize);co.stroke();}else if(tickmarks=='circle'){co.beginPath();co.arc(x,y,ticksize,0,6.2830,false);co.fill();}else if(tickmarks=='square'){co.beginPath();co.fillRect(x-ticksize,y-ticksize,2*ticksize,2*ticksize);co.fill();}else if(tickmarks=='diamond'){co.beginPath();co.moveTo(x,y-ticksize);co.lineTo(x+ticksize,y);co.lineTo(x,y+ticksize);co.lineTo(x-ticksize,y);co.closePath();co.fill();}else if(tickmarks=='plus'){co.lineWidth=1;co.beginPath();co.moveTo(x,y-ticksize);co.lineTo(x,y+ticksize);co.moveTo(x-ticksize,y);co.lineTo(x+ticksize,y);co.stroke();}
|
61
|
+
co.lineWidth=prevLinewidth;};this.getShape=this.getPoint=function(e)
|
62
|
+
{var mouseXY=RG.getMouseXY(e);var mouseX=mouseXY[0];var mouseY=mouseXY[1];var overHotspot=false;var offset=prop['chart.tooltips.hotspot'];for(var i=0,len=this.coords.length;i<len;++i){var x=this.coords[i][0];var y=this.coords[i][1];var tooltip=this.coords[i][3];if(mouseX<(x+offset)&&mouseX>(x-offset)&&mouseY<(y+offset)&&mouseY>(y-offset)){var tooltip=RG.parseTooltipText(prop['chart.tooltips'],i);return{0:this,1:x,2:y,3:i,'object':this,'x':x,'y':y,'index':i,'tooltip':tooltip};}}};this.allowTooltips=this.AllowTooltips=function()
|
63
|
+
{RG.PreLoadTooltipImages(this);RG.InstallWindowMousedownTooltipListener(this);RG.InstallCanvasMousemoveTooltipListener(this);RG.InstallCanvasMouseupTooltipListener(this);};this.highlight=this.Highlight=function(shape)
|
64
|
+
{if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Point(this,shape);}};this.getObjectByXY=function(e)
|
65
|
+
{var mouseXY=RG.getMouseXY(e);var mouseX=mouseXY[0];var mouseY=mouseXY[1];var centerx=this.centerx;var centery=this.centery;var radius=this.radius;if(mouseX>(centerx-radius)&&mouseX<(centerx+radius)&&mouseY>(centery-radius)&&mouseY<(centery+radius)){return this;}};this.getRadius=function(value)
|
66
|
+
{var max=this.max;if(value<0||value>max){return null;}
|
67
|
+
var r=(value/max)*this.radius;return r;};this.parseColors=function()
|
68
|
+
{if(this.original_colors.length===0){this.original_colors['data']=RG.array_clone(this.data);this.original_colors['chart.highlight.stroke']=RG.arrayClone(prop['chart.highlight.stroke']);this.original_colors['chart.highlight.fill']=RG.arrayClone(prop['chart.highlight.fill']);this.original_colors['chart.colors.default']=RG.arrayClone(prop['chart.colors.default']);this.original_colors['chart.background.grid.color']=RG.arrayClone(prop['chart.background.grid.color']);this.original_colors['chart.background.color']=RG.arrayClone(prop['chart.background.color']);this.original_colors['chart.segment.highlight.stroke']=RG.arrayClone(prop['chart.segment.highlight.stroke']);this.original_colors['chart.segment.highlight.fill']=RG.arrayClone(prop['chart.segment.highlight.fill']);}
|
69
|
+
for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){this.data[i][j][2]=this.parseSingleColorForGradient(this.data[i][j][2]);}}
|
70
|
+
prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.colors.default']=this.parseSingleColorForGradient(prop['chart.colors.default']);prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.background.color']=this.parseSingleColorForGradient(prop['chart.background.color']);prop['chart.segment.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.segment.highlight.stroke']);prop['chart.segment.highlight.fill']=this.parseSingleColorForGradient(prop['chart.segment.highlight.fill']);};this.reset=function()
|
71
|
+
{};this.parseSingleColorForGradient=function(color)
|
72
|
+
{if(!color||typeof color!='string'){return color;}
|
73
|
+
if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');var grad=co.createRadialGradient(this.centerx,this.centery,0,this.centerx,this.centery,this.radius);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
|
74
|
+
return grad?grad:color;};this.interactiveKeyHighlight=function(index)
|
75
|
+
{if(this.coords2&&this.coords2[index]&&this.coords2[index].length){this.coords2[index].forEach(function(value,idx,arr)
|
76
|
+
{co.beginPath();co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.arc(value[0],value[1],prop['chart.ticksize']+2,0,RG.TWOPI,false);co.fill();});}};this.on=function(type,func)
|
77
|
+
{if(type.substr(0,2)!=='on'){type='on'+type;}
|
78
|
+
if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
|
79
|
+
return this;};this.resetColorsToOriginalValues=function()
|
80
|
+
{for(var i=0,len=this.original_colors['data'].length;i<len;++i){for(var j=0,len2=this.original_colors['data'][i].length;j<len2;++j){this.data[i][j][2]=RG.array_clone(this.original_colors['data'][i][j][2]);}}};this.firstDrawFunc=function()
|
81
|
+
{};RG.att(ca);RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};
|