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,1348 +1,84 @@
|
|
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
|
-
|
94
|
-
|
95
|
-
|
96
|
-
'chart.labels.offsetx': 0,
|
97
|
-
'chart.labels.offsety': 0,
|
98
|
-
'chart.ylabels.offsetx': 0,
|
99
|
-
'chart.ylabels.offsety': 0,
|
100
|
-
'chart.ylabels': true,
|
101
|
-
'chart.text.color': 'black',
|
102
|
-
'chart.text.size': 12,
|
103
|
-
'chart.text.angle': 0,
|
104
|
-
'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
|
105
|
-
'chart.text.accessible': true,
|
106
|
-
'chart.text.accessible.overflow': 'visible',
|
107
|
-
'chart.text.accessible.pointerevents': true,
|
108
|
-
'chart.ymax': null,
|
109
|
-
'chart.title': '',
|
110
|
-
'chart.title.color': 'black',
|
111
|
-
'chart.title.background': null,
|
112
|
-
'chart.title.hpos': null,
|
113
|
-
'chart.title.vpos': null,
|
114
|
-
'chart.title.bold': true,
|
115
|
-
'chart.title.font': null,
|
116
|
-
'chart.title.xaxis': '',
|
117
|
-
'chart.title.yaxis': '',
|
118
|
-
'chart.title.yaxis.bold': true,
|
119
|
-
'chart.title.yaxis.size': null,
|
120
|
-
'chart.title.yaxis.font': null,
|
121
|
-
'chart.title.yaxis.color': null,
|
122
|
-
'chart.title.xaxis.pos': null,
|
123
|
-
'chart.title.yaxis.pos': null,
|
124
|
-
'chart.title.yaxis.align': 'left',
|
125
|
-
'chart.title.xaxis.bold': true,
|
126
|
-
'chart.title.xaxis.size': null,
|
127
|
-
'chart.title.xaxis.font': null,
|
128
|
-
'chart.title.xaxis.color': null,
|
129
|
-
'chart.title.yaxis.x': null,
|
130
|
-
'chart.title.yaxis.y': null,
|
131
|
-
'chart.title.xaxis.x': null,
|
132
|
-
'chart.title.xaxis.y': null,
|
133
|
-
'chart.title.x': null,
|
134
|
-
'chart.title.y': null,
|
135
|
-
'chart.title.halign': null,
|
136
|
-
'chart.title.valign': null,
|
137
|
-
'chart.colors': ['green','red','blue'],
|
138
|
-
'chart.shadow': false,
|
139
|
-
'chart.shadow.color': '#666',
|
140
|
-
'chart.shadow.offsetx': 3,
|
141
|
-
'chart.shadow.offsety': 3,
|
142
|
-
'chart.shadow.blur': 3,
|
143
|
-
'chart.tooltips': null,
|
144
|
-
'chart.tooltips.effect': 'fade',
|
145
|
-
'chart.tooltips.css.class': 'RGraph_tooltip',
|
146
|
-
'chart.tooltips.event': 'onclick',
|
147
|
-
'chart.tooltips.highlight': true,
|
148
|
-
'chart.tooltips.override': null,
|
149
|
-
'chart.highlight.stroke': 'rgba(0,0,0,0)',
|
150
|
-
'chart.highlight.fill': 'rgba(255,255,255,0.7)',
|
151
|
-
'chart.contextmenu': null,
|
152
|
-
'chart.units.pre': '',
|
153
|
-
'chart.units.post': '',
|
154
|
-
'chart.scale.decimals': 0,
|
155
|
-
'chart.scale.point': '.',
|
156
|
-
'chart.scale.thousand': ',',
|
157
|
-
'chart.scale.zerostart': true,
|
158
|
-
//'chart.scale.formatter': null,
|
159
|
-
'chart.crosshairs': false,
|
160
|
-
'chart.crosshairs.color': '#333',
|
161
|
-
'chart.crosshairs.hline': true,
|
162
|
-
'chart.crosshairs.vline': true,
|
163
|
-
'chart.annotatable': false,
|
164
|
-
'chart.annotate.color': 'black',
|
165
|
-
'chart.zoom.factor': 1.5,
|
166
|
-
'chart.zoom.fade.in': true,
|
167
|
-
'chart.zoom.fade.out': true,
|
168
|
-
'chart.zoom.hdir': 'right',
|
169
|
-
'chart.zoom.vdir': 'down',
|
170
|
-
'chart.zoom.frames': 25,
|
171
|
-
'chart.zoom.delay': 16.666,
|
172
|
-
'chart.zoom.shadow': true,
|
173
|
-
'chart.zoom.background': true,
|
174
|
-
'chart.resizable': false,
|
175
|
-
'chart.resize.handle.background': null,
|
176
|
-
'chart.noaxes': false,
|
177
|
-
'chart.noxaxis': false,
|
178
|
-
'chart.noyaxis': false,
|
179
|
-
'chart.axis.color': 'black',
|
180
|
-
'chart.total': true,
|
181
|
-
'chart.multiplier.x': 1,
|
182
|
-
'chart.multiplier.w': 1,
|
183
|
-
'chart.events.click': null,
|
184
|
-
'chart.events.mousemove': null,
|
185
|
-
'chart.ylabels.count': 5,
|
186
|
-
'chart.ymin': 0,
|
187
|
-
'chart.clearto': 'rgba(0,0,0,0)'
|
188
|
-
}
|
189
|
-
|
190
|
-
// Check for support
|
191
|
-
if (!this.canvas) {
|
192
|
-
alert('[WATERFALL] No canvas support');
|
193
|
-
return;
|
194
|
-
}
|
195
|
-
|
196
|
-
/**
|
197
|
-
* Create the $ objects
|
198
|
-
*
|
199
|
-
* 2/5/016: Now also use this loop to go through the dat conerting
|
200
|
-
* strings to floats
|
201
|
-
*/
|
202
|
-
for (var i=0,len=this.data.length; i<=len; ++i) {
|
203
|
-
|
204
|
-
// Create the object for adding event listeners
|
205
|
-
this['$' + i] = {}
|
206
|
-
|
207
|
-
// Ensure that the data point is numeric
|
208
|
-
if (typeof this.data[i] === 'string') {
|
209
|
-
this.data[i] = parseFloat(this.data[i]);
|
210
|
-
}
|
211
|
-
}
|
212
|
-
|
213
|
-
|
214
|
-
/**
|
215
|
-
* Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
|
216
|
-
* done already
|
217
|
-
*/
|
218
|
-
if (!this.canvas.__rgraph_aa_translated__) {
|
219
|
-
this.context.translate(0.5,0.5);
|
220
|
-
|
221
|
-
this.canvas.__rgraph_aa_translated__ = true;
|
222
|
-
}
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
// Short variable names
|
228
|
-
var RG = RGraph,
|
229
|
-
ca = this.canvas,
|
230
|
-
co = ca.getContext('2d'),
|
231
|
-
prop = this.properties,
|
232
|
-
pa2 = RG.path2,
|
233
|
-
win = window,
|
234
|
-
doc = document,
|
235
|
-
ma = Math
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
/**
|
240
|
-
* "Decorate" the object with the generic effects if the effects library has been included
|
241
|
-
*/
|
242
|
-
if (RG.Effects && typeof RG.Effects.decorate === 'function') {
|
243
|
-
RG.Effects.decorate(this);
|
244
|
-
}
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
/**
|
250
|
-
* A setter
|
251
|
-
*
|
252
|
-
* @param name string The name of the property to set
|
253
|
-
* @param value mixed The value of the property
|
254
|
-
*/
|
255
|
-
this.set =
|
256
|
-
this.Set = function (name, value)
|
257
|
-
{
|
258
|
-
var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
|
259
|
-
|
260
|
-
/**
|
261
|
-
* the number of arguments is only one and it's an
|
262
|
-
* object - parse it for configuration data and return.
|
263
|
-
*/
|
264
|
-
if (arguments.length === 1 && typeof name === 'object') {
|
265
|
-
RG.parseObjectStyleConfig(this, name);
|
266
|
-
return this;
|
267
|
-
}
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
/**
|
273
|
-
* This should be done first - prepend the propertyy name with "chart." if necessary
|
274
|
-
*/
|
275
|
-
if (name.substr(0,6) != 'chart.') {
|
276
|
-
name = 'chart.' + name;
|
277
|
-
}
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
// Convert uppercase letters to dot+lower case letter
|
282
|
-
while(name.match(/([A-Z])/)) {
|
283
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
284
|
-
}
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
if (name == 'chart.total' && prop['chart.numxticks'] == null) {
|
289
|
-
prop['chart.numxticks'] = this.data.length;
|
290
|
-
}
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
prop[name.toLowerCase()] = value;
|
295
|
-
|
296
|
-
return this;
|
297
|
-
};
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
/**
|
303
|
-
* A getter
|
304
|
-
*
|
305
|
-
* @param name string The name of the property to get
|
306
|
-
*/
|
307
|
-
this.get =
|
308
|
-
this.Get = function (name)
|
309
|
-
{
|
310
|
-
/**
|
311
|
-
* This should be done first - prepend the property name with "chart." if necessary
|
312
|
-
*/
|
313
|
-
if (name.substr(0,6) != 'chart.') {
|
314
|
-
name = 'chart.' + name;
|
315
|
-
}
|
316
|
-
|
317
|
-
// Convert uppercase letters to dot+lower case letter
|
318
|
-
while(name.match(/([A-Z])/)) {
|
319
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
320
|
-
}
|
321
|
-
|
322
|
-
return prop[name.toLowerCase()];
|
323
|
-
};
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
/**
|
329
|
-
* The function you call to draw the bar chart
|
330
|
-
*/
|
331
|
-
this.draw =
|
332
|
-
this.Draw = function ()
|
333
|
-
{
|
334
|
-
/**
|
335
|
-
* Fire the onbeforedraw event
|
336
|
-
*/
|
337
|
-
RGraph.fireCustomEvent(this, 'onbeforedraw');
|
338
|
-
|
339
|
-
|
340
|
-
/**
|
341
|
-
* Parse the colors. This allows for simple gradient syntax
|
342
|
-
*/
|
343
|
-
if (!this.colorsParsed) {
|
344
|
-
this.parseColors();
|
345
|
-
|
346
|
-
// Don't want to do this again
|
347
|
-
this.colorsParsed = true;
|
348
|
-
}
|
349
|
-
|
350
|
-
|
351
|
-
/**
|
352
|
-
* Draw the background image
|
353
|
-
*/
|
354
|
-
RGraph.DrawBackgroundImage(this);
|
355
|
-
|
356
|
-
/**
|
357
|
-
* This is new in May 2011 and facilitates indiviual gutter settings,
|
358
|
-
* eg chart.gutter.left
|
359
|
-
*/
|
360
|
-
this.gutterLeft = prop['chart.gutter.left'];
|
361
|
-
this.gutterRight = prop['chart.gutter.right'];
|
362
|
-
this.gutterTop = prop['chart.gutter.top'];
|
363
|
-
this.gutterBottom = prop['chart.gutter.bottom'];
|
364
|
-
|
365
|
-
/**
|
366
|
-
* Stop the coords array from growing uncontrollably
|
367
|
-
*/
|
368
|
-
this.coords = [];
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
/**
|
373
|
-
* Stop this growing uncontrollably
|
374
|
-
*/
|
375
|
-
this.coordsText = [];
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
/**
|
381
|
-
* This gets used a lot
|
382
|
-
*/
|
383
|
-
this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
|
384
|
-
|
385
|
-
/**
|
386
|
-
* Work out a few things. They need to be here because they depend on things you can change after you instantiate the object
|
387
|
-
*/
|
388
|
-
this.max = 0;
|
389
|
-
this.grapharea = ca.height - this.gutterTop - this.gutterBottom;
|
390
|
-
this.graphwidth = ca.width - this.gutterLeft - this.gutterRight;
|
391
|
-
this.halfTextHeight = prop['chart.text.size'] / 2;
|
392
|
-
|
393
|
-
|
394
|
-
/**
|
395
|
-
* Work out the maximum value
|
396
|
-
*/
|
397
|
-
this.max = this.getMax(this.data);
|
398
|
-
|
399
|
-
var decimals = prop['chart.scale.decimals'];
|
400
|
-
|
401
|
-
this.scale2 = RG.getScale2(this, {
|
402
|
-
max:typeof(prop['chart.ymax']) == 'number' ? prop['chart.ymax'] : this.max,
|
403
|
-
min:prop['chart.ymin'],
|
404
|
-
strict: typeof(prop['chart.ymax']) === 'number' ? true : false,
|
405
|
-
'scale.decimals':Number(decimals),
|
406
|
-
'scale.point':prop['chart.scale.point'],
|
407
|
-
'scale.thousand':prop['chart.scale.thousand'],
|
408
|
-
'scale.round':prop['chart.scale.round'],
|
409
|
-
'units.pre':prop['chart.units.pre'],
|
410
|
-
'units.post':prop['chart.units.post'],
|
411
|
-
'ylabels.count':prop['chart.ylabels.count']
|
412
|
-
});
|
413
|
-
|
414
|
-
this.max = this.scale2.max;
|
415
|
-
this.min = this.scale2.min;
|
416
|
-
|
417
|
-
// Draw the background hbars
|
418
|
-
RG.drawBars(this)
|
419
|
-
|
420
|
-
// Progressively Draw the chart
|
421
|
-
RG.Background.draw(this);
|
422
|
-
|
423
|
-
this.DrawAxes();
|
424
|
-
this.Drawbars();
|
425
|
-
this.DrawLabels();
|
426
|
-
|
427
|
-
/**
|
428
|
-
* If the X axis is at the bottom AND ymin is 0 - draw the it
|
429
|
-
* again so that it appears "on top" of the bars
|
430
|
-
*/
|
431
|
-
if ( prop['chart.xaxispos'] === 'bottom'
|
432
|
-
&& prop['chart.noaxes'] === false
|
433
|
-
&& prop['chart.noxaxis'] === false
|
434
|
-
&& prop['chart.ymin'] === 0) {
|
435
|
-
|
436
|
-
co.strokeStyle = prop['chart.axis.color'];
|
437
|
-
co.strokeRect(
|
438
|
-
prop['chart.gutter.left'],
|
439
|
-
ca.height - prop['chart.gutter.bottom'],
|
440
|
-
ca.width - this.gutterLeft - this.gutterRight,
|
441
|
-
0
|
442
|
-
);
|
443
|
-
}
|
444
|
-
|
445
|
-
/**
|
446
|
-
* Setup the context menu if required
|
447
|
-
*/
|
448
|
-
if (prop['chart.contextmenu']) {
|
449
|
-
RG.ShowContext(this);
|
450
|
-
}
|
451
|
-
|
452
|
-
|
453
|
-
/**
|
454
|
-
* This function enables resizing
|
455
|
-
*/
|
456
|
-
if (prop['chart.resizable']) {
|
457
|
-
RG.AllowResizing(this);
|
458
|
-
}
|
459
|
-
|
460
|
-
|
461
|
-
/**
|
462
|
-
* This installs the event listeners
|
463
|
-
*/
|
464
|
-
RG.InstallEventListeners(this);
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
/**
|
469
|
-
* Fire the onfirstdraw event
|
470
|
-
*/
|
471
|
-
if (this.firstDraw) {
|
472
|
-
RG.fireCustomEvent(this, 'onfirstdraw');
|
473
|
-
this.firstDraw = false;
|
474
|
-
this.firstDrawFunc();
|
475
|
-
}
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
/**
|
481
|
-
* Fire the RGraph ondraw event
|
482
|
-
*/
|
483
|
-
RG.FireCustomEvent(this, 'ondraw');
|
484
|
-
|
485
|
-
return this;
|
486
|
-
};
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
/**
|
492
|
-
* Draws the charts axes
|
493
|
-
*/
|
494
|
-
this.drawAxes =
|
495
|
-
this.DrawAxes = function ()
|
496
|
-
{
|
497
|
-
if (prop['chart.noaxes']) {
|
498
|
-
return;
|
499
|
-
}
|
500
|
-
|
501
|
-
co.beginPath();
|
502
|
-
co.strokeStyle = prop['chart.axis.color'];
|
503
|
-
co.lineWidth = prop['chart.axis.linewidth'] + 0.001;
|
504
|
-
|
505
|
-
// Draw the Y axis
|
506
|
-
if (prop['chart.noyaxis'] == false) {
|
507
|
-
co.moveTo(ma.round(this.gutterLeft), this.gutterTop);
|
508
|
-
co.lineTo(ma.round(this.gutterLeft), ca.height - this.gutterBottom);
|
509
|
-
}
|
510
|
-
|
511
|
-
// Draw the X axis
|
512
|
-
if (prop['chart.noxaxis'] == false) {
|
513
|
-
// Center X axis
|
514
|
-
if (prop['chart.xaxispos'] == 'center') {
|
515
|
-
co.moveTo(this.gutterLeft, ma.round( ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop));
|
516
|
-
co.lineTo(ca.width - this.gutterRight, ma.round( ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop));
|
517
|
-
} else {
|
518
|
-
|
519
|
-
var y = ma.floor(this.getYCoord(0));
|
520
|
-
|
521
|
-
co.moveTo(this.gutterLeft, y);
|
522
|
-
co.lineTo(ca.width - this.gutterRight, y);
|
523
|
-
}
|
524
|
-
}
|
525
|
-
|
526
|
-
var numYTicks = prop['chart.numyticks'];
|
527
|
-
|
528
|
-
// Draw the Y tickmarks
|
529
|
-
if ( prop['chart.noyaxis'] === false
|
530
|
-
&& prop['chart.numyticks'] > 0
|
531
|
-
) {
|
532
|
-
|
533
|
-
var yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / numYTicks;
|
534
|
-
|
535
|
-
for (y=this.gutterTop; y < (ca.height - this.gutterBottom); y += yTickGap) {
|
536
|
-
if (prop['chart.xaxispos'] == 'bottom' || (y != ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop)) {
|
537
|
-
co.moveTo(this.gutterLeft, ma.round( y));
|
538
|
-
co.lineTo(this.gutterLeft - 3, ma.round( y));
|
539
|
-
}
|
540
|
-
}
|
541
|
-
|
542
|
-
/**
|
543
|
-
* If the X axis is not being shown, draw an extra tick
|
544
|
-
*/
|
545
|
-
if ( prop['chart.noxaxis']
|
546
|
-
|| prop['chart.xaxispos'] == 'center'
|
547
|
-
|| prop['chart.ymin'] !== 0
|
548
|
-
) {
|
549
|
-
co.moveTo(this.gutterLeft - 3, Math.round(ca.height - this.gutterBottom));
|
550
|
-
co.lineTo(this.gutterLeft, Math.round(ca.height - this.gutterBottom));
|
551
|
-
}
|
552
|
-
}
|
553
|
-
|
554
|
-
|
555
|
-
// Draw the X tickmarks
|
556
|
-
if (prop['chart.numxticks'] == null) {
|
557
|
-
prop['chart.numxticks'] = this.data.length + (prop['chart.total'] ? 1 : 0)
|
558
|
-
}
|
559
|
-
|
560
|
-
if (prop['chart.noxaxis'] == false && prop['chart.numxticks'] > 0) {
|
561
|
-
|
562
|
-
xTickGap = (ca.width - this.gutterLeft - this.gutterRight ) / prop['chart.numxticks'];
|
563
|
-
|
564
|
-
if (prop['chart.xaxispos'] == 'center') {
|
565
|
-
yStart = ((ca.height - this.gutterBottom - this.gutterTop) / 2) + this.gutterTop - 3;
|
566
|
-
yEnd = ((ca.height - this.gutterBottom - this.gutterTop) / 2) + this.gutterTop + 3;
|
567
|
-
} else {
|
568
|
-
yStart = this.getYCoord(0) - (this.scale2.min < 0 ? 3 : 0);
|
569
|
-
yEnd = this.getYCoord(0) + 3;
|
570
|
-
}
|
571
|
-
|
572
|
-
for (x=this.gutterLeft + xTickGap; x<=ca.width - this.gutterRight + 1; x+=xTickGap) {
|
573
|
-
co.moveTo(ma.round(x), yStart);
|
574
|
-
co.lineTo(ma.round(x), yEnd);
|
575
|
-
}
|
576
|
-
|
577
|
-
if (prop['chart.noyaxis']) {
|
578
|
-
co.moveTo(ma.round( this.gutterLeft), yStart);
|
579
|
-
co.lineTo(ma.round( this.gutterLeft), yEnd);
|
580
|
-
}
|
581
|
-
}
|
582
|
-
|
583
|
-
/**
|
584
|
-
* If the Y axis is not being shown, draw an extra tick
|
585
|
-
*/
|
586
|
-
if (prop['chart.noyaxis'] && prop['chart.noxaxis'] == false) {
|
587
|
-
co.moveTo(ma.round(this.gutterLeft), this.getYCoord(0));
|
588
|
-
co.lineTo(ma.round(this.gutterLeft), this.getYCoord(0));
|
589
|
-
}
|
590
|
-
|
591
|
-
co.stroke();
|
592
|
-
};
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
/**
|
598
|
-
* Draws the labels for the graph
|
599
|
-
*/
|
600
|
-
this.drawLabels =
|
601
|
-
this.DrawLabels = function ()
|
602
|
-
{
|
603
|
-
var context = co,
|
604
|
-
numYLabels = 5, // TODO Make this configurable
|
605
|
-
interval = this.grapharea / numYLabels,
|
606
|
-
font = prop['chart.text.font'],
|
607
|
-
size = prop['chart.text.size'],
|
608
|
-
color = prop['chart.text.color'],
|
609
|
-
units_pre = prop['chart.units.pre'],
|
610
|
-
units_post = prop['chart.units.post'],
|
611
|
-
offsetx = prop['chart.ylabels.offsetx'],
|
612
|
-
offsety = prop['chart.ylabels.offsety'];
|
613
|
-
|
614
|
-
co.beginPath();
|
615
|
-
co.fillStyle = color;
|
616
|
-
|
617
|
-
/**
|
618
|
-
* First, draw the Y labels
|
619
|
-
*/
|
620
|
-
if (prop['chart.ylabels']) {
|
621
|
-
if (prop['chart.xaxispos'] == 'center') {
|
622
|
-
|
623
|
-
var halfInterval = interval / 2;
|
624
|
-
var halfWay = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
|
625
|
-
|
626
|
-
for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
|
627
|
-
RG.text2(this, {
|
628
|
-
font:font,
|
629
|
-
size:size,
|
630
|
-
x:this.gutterLeft - 5 + offsetx,
|
631
|
-
y: this.gutterTop + (((this.grapharea/2) / len) * i) + offsety,
|
632
|
-
text:this.scale2.labels[len - i - 1],
|
633
|
-
valign:'center',
|
634
|
-
halign:'right',
|
635
|
-
tag: 'scale'
|
636
|
-
});
|
637
|
-
|
638
|
-
RG.text2(this, {
|
639
|
-
font:font,
|
640
|
-
size:size,
|
641
|
-
x:this.gutterLeft - 5 + offsetx,
|
642
|
-
y: halfWay + (((this.grapharea/2) / len) * (i + 1)) + offsety,
|
643
|
-
text:this.scale2.labels[i],
|
644
|
-
valign:'center',
|
645
|
-
halign:'right',
|
646
|
-
tag: 'scale'
|
647
|
-
});
|
648
|
-
}
|
649
|
-
|
650
|
-
// Draw zero if required
|
651
|
-
if (prop['chart.scale.zerostart']) {
|
652
|
-
RG.text2(co, {
|
653
|
-
x: this.gutterLeft - 5 + offsetx,
|
654
|
-
y: halfWay,
|
655
|
-
text: '0',
|
656
|
-
font: font,
|
657
|
-
size: size,
|
658
|
-
valign: 'center',
|
659
|
-
halign: 'right',
|
660
|
-
tag: 'scale'
|
661
|
-
});
|
662
|
-
}
|
663
|
-
|
664
|
-
} else {
|
665
|
-
|
666
|
-
for (var i=0,len=this.scale2.values.length; i<len; ++i) {
|
667
|
-
|
668
|
-
var y = this.getYCoord(this.scale2.values[i]) + offsety;
|
669
|
-
|
670
|
-
RG.text2(this, {
|
671
|
-
font:font,
|
672
|
-
size:size,
|
673
|
-
x:this.gutterLeft - 5 + offsetx,
|
674
|
-
y: y,
|
675
|
-
text:this.scale2.labels[i],
|
676
|
-
valign:'center',
|
677
|
-
halign:'right',
|
678
|
-
tag: 'scale'
|
679
|
-
});
|
680
|
-
}
|
681
|
-
|
682
|
-
|
683
|
-
// Draw zero if required
|
684
|
-
if (prop['chart.scale.zerostart'] || prop['chart.ymin'] !== 0) {
|
685
|
-
|
686
|
-
RG.text2(co, {
|
687
|
-
x: this.gutterLeft - 5 + offsetx,
|
688
|
-
y: this.getYCoord(prop['chart.ymin'] || 0),
|
689
|
-
text: RG.numberFormat(this, String(Number(prop['chart.ymin'] || 0).toFixed(prop['chart.ymin'] === 0 ? 0 : prop['chart.scale.decimals'])), prop['chart.units.pre'], prop['chart.units.post']),
|
690
|
-
font: font,
|
691
|
-
size: size,
|
692
|
-
valign: 'center',
|
693
|
-
halign: 'right',
|
694
|
-
tag: 'scale'
|
695
|
-
});
|
696
|
-
}
|
697
|
-
}
|
698
|
-
}
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
/**
|
703
|
-
* Now, draw the X labels
|
704
|
-
*/
|
705
|
-
if (prop['chart.labels'].length > 0) {
|
706
|
-
|
707
|
-
// Recalculate the interval for the X labels
|
708
|
-
interval = (ca.width - this.gutterLeft - this.gutterRight) / prop['chart.labels'].length;
|
709
|
-
|
710
|
-
var halign = 'center';
|
711
|
-
var angle = prop['chart.text.angle'];
|
712
|
-
|
713
|
-
if (angle) {
|
714
|
-
halign = 'right';
|
715
|
-
angle *= -1;
|
716
|
-
}
|
717
|
-
|
718
|
-
var labels = prop['chart.labels'],
|
719
|
-
labelsColor = prop['chart.labels.color'],
|
720
|
-
bold = prop['chart.labels.bold'],
|
721
|
-
offsetx = prop['chart.labels.offsetx'],
|
722
|
-
offsety = prop['chart.labels.offsety']
|
723
|
-
|
724
|
-
for (var i=0,len=labels.length; i<len; i+=1) {
|
725
|
-
RG.text2(this, {
|
726
|
-
'color': labelsColor,
|
727
|
-
'font':font,
|
728
|
-
'size':size,
|
729
|
-
'bold': bold,
|
730
|
-
'x':this.gutterLeft + (i * interval) + (interval / 2) + offsetx,
|
731
|
-
'y':ca.height - this.gutterBottom + 5 + this.halfTextHeight + offsety,
|
732
|
-
'text':labels[i],
|
733
|
-
'valign':'center',
|
734
|
-
'halign':halign,
|
735
|
-
'angle':angle,
|
736
|
-
'tag': 'labels'
|
737
|
-
});
|
738
|
-
}
|
739
|
-
}
|
740
|
-
|
741
|
-
co.stroke();
|
742
|
-
co.fill();
|
743
|
-
};
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
/**
|
749
|
-
* Draws the bars on to the chart
|
750
|
-
*/
|
751
|
-
this.drawbars =
|
752
|
-
this.Drawbars = function ()
|
753
|
-
{
|
754
|
-
var context = co,
|
755
|
-
canvas = ca,
|
756
|
-
hmargin = prop['chart.hmargin'],
|
757
|
-
runningTotal = 0;
|
758
|
-
|
759
|
-
co.lineWidth = prop['chart.linewidth'] + 0.001;
|
760
|
-
|
761
|
-
for (var i=0,len=this.data.length; i<len; ++i) {
|
762
|
-
|
763
|
-
co.beginPath();
|
764
|
-
|
765
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
766
|
-
|
767
|
-
var x = ma.round( this.gutterLeft + hmargin + (((this.graphwidth / (this.data.length + (prop['chart.total'] ? 1 : 0))) * i) * prop['chart.multiplier.x']));
|
768
|
-
|
769
|
-
// Must be before the y coord calculation
|
770
|
-
var h = this.getYCoord(0) - this.getYCoord(ma.abs(this.data[i]));
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
// Work out the Y coordinate
|
775
|
-
if (i === 0) {
|
776
|
-
y = this.getYCoord(0) - h;
|
777
|
-
} else {
|
778
|
-
y = this.getYCoord(runningTotal) - h;
|
779
|
-
}
|
780
|
-
y = ma.round(y);
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
var w = ((ca.width - this.gutterLeft - this.gutterRight) / (this.data.length + (prop['chart.total'] ? 1 : 0 )) ) - (2 * prop['chart.hmargin']);
|
787
|
-
w = w * prop['chart.multiplier.w'];
|
788
|
-
|
789
|
-
|
790
|
-
// Adjust the coords for negative values
|
791
|
-
if (this.data[i] < 0) {
|
792
|
-
y += h;
|
793
|
-
}
|
794
|
-
|
795
|
-
// Color
|
796
|
-
co.fillStyle = this.data[i] >= 0 ? prop['chart.colors'][0] : prop['chart.colors'][1];
|
797
|
-
|
798
|
-
|
799
|
-
if (prop['chart.shadow']) {
|
800
|
-
RG.setShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
|
801
|
-
} else {
|
802
|
-
RG.noShadow(this);
|
803
|
-
}
|
804
|
-
|
805
|
-
co.rect(x, ma.floor(y), w, ma.floor(h));
|
806
|
-
|
807
|
-
this.coords.push([x, y, w, h]);
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
runningTotal += this.data[i];
|
812
|
-
|
813
|
-
co.stroke();
|
814
|
-
co.fill();
|
815
|
-
}
|
816
|
-
|
817
|
-
// Store the total
|
818
|
-
this.total = runningTotal;
|
819
|
-
|
820
|
-
if (prop['chart.total']) {
|
821
|
-
|
822
|
-
// This is the height of the final bar
|
823
|
-
h = this.getYCoord(0) - this.getYCoord(ma.abs(runningTotal));
|
824
|
-
|
825
|
-
/**
|
826
|
-
* Set the Y (ie the start point) value
|
827
|
-
*/
|
828
|
-
if (prop['chart.xaxispos'] == 'center') {
|
829
|
-
y = runningTotal > 0 ? this.getYCoord(0) - h : this.getYCoord(0);
|
830
|
-
} else {
|
831
|
-
if (runningTotal > 0) {
|
832
|
-
y = this.getYCoord(0) - h;
|
833
|
-
} else {
|
834
|
-
y = this.getYCoord(0);
|
835
|
-
}
|
836
|
-
}
|
837
|
-
|
838
|
-
// This is the X position of the final bar
|
839
|
-
x = x + (prop['chart.hmargin'] * 2) + w;
|
840
|
-
|
841
|
-
|
842
|
-
// Final color
|
843
|
-
co.fillStyle = prop['chart.colors'][2];
|
844
|
-
|
845
|
-
pa2(co, 'b r % % % % s % f %',
|
846
|
-
x, y, w, h,
|
847
|
-
co.strokeStyle,
|
848
|
-
co.fillStyle
|
849
|
-
);
|
850
|
-
|
851
|
-
// This is set so that the next iteration of the loop will be able to
|
852
|
-
// access THIS iterations coordinates
|
853
|
-
var previousCoords = [x, y, w, ma.abs(h)];
|
854
|
-
|
855
|
-
// Add the coordinates to the coords array (the previousCooords array, at
|
856
|
-
// this point, is actually THIS iterations coords
|
857
|
-
this.coords.push(previousCoords);
|
858
|
-
}
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
// Turn off the shadow
|
865
|
-
RG.noShadow(this);
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
/**
|
873
|
-
* This draws the connecting lines
|
874
|
-
*/
|
875
|
-
co.lineWidth = 1;
|
876
|
-
co.strokeStyle = '#666';
|
877
|
-
|
878
|
-
co.beginPath();
|
879
|
-
|
880
|
-
for (var i=1,len=this.coords.length; i<len; i+=1) {
|
881
|
-
|
882
|
-
var prev = this.coords[i - 1],
|
883
|
-
curr = this.coords[i],
|
884
|
-
prevData = this.data[i-1]
|
885
|
-
|
886
|
-
// CANNOT be a part of the var chain above
|
887
|
-
var y = (prevData > 0 ? prev[1] : prev[1] + prev[3]);
|
888
|
-
|
889
|
-
|
890
|
-
co.moveTo(prev[0] + prev[2], y);
|
891
|
-
co.lineTo(curr[0],(prevData > 0 ? prev[1] : prev[1] + prev[3]));
|
892
|
-
|
893
|
-
}
|
894
|
-
|
895
|
-
co.stroke();
|
896
|
-
};
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
/**
|
902
|
-
* Not used by the class during creating the graph, but is used by event handlers
|
903
|
-
* to get the coordinates (if any) of the selected bar
|
904
|
-
*
|
905
|
-
* @param object e The event object
|
906
|
-
*/
|
907
|
-
this.getShape =
|
908
|
-
this.getBar = function (e)
|
909
|
-
{
|
910
|
-
/**
|
911
|
-
* Loop through the bars determining if the mouse is over a bar
|
912
|
-
*/
|
913
|
-
for (var i=0,len=this.coords.length; i<len; i++) {
|
914
|
-
|
915
|
-
var mouseXY = RG.getMouseXY(e),
|
916
|
-
mouseX = mouseXY[0],
|
917
|
-
mouseY = mouseXY[1];
|
918
|
-
|
919
|
-
var left = this.coords[i][0],
|
920
|
-
top = this.coords[i][1],
|
921
|
-
width = this.coords[i][2],
|
922
|
-
height = this.coords[i][3];
|
923
|
-
|
924
|
-
if ( mouseX >= left
|
925
|
-
&& mouseX <= (left + width)
|
926
|
-
&& mouseY >= top
|
927
|
-
&& mouseY <= top + height) {
|
928
|
-
|
929
|
-
var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
|
930
|
-
|
931
|
-
return {
|
932
|
-
0: this, object: this,
|
933
|
-
1: left, x: left,
|
934
|
-
2: top, y: top,
|
935
|
-
3: width, width: width,
|
936
|
-
4: height, height: height,
|
937
|
-
5: i, index: i,
|
938
|
-
tooltip: tooltip
|
939
|
-
};
|
940
|
-
}
|
941
|
-
}
|
942
|
-
|
943
|
-
return null;
|
944
|
-
};
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
/**
|
950
|
-
* The Waterfall is slightly different to Bar/Line charts so has this function to get the max value
|
951
|
-
*/
|
952
|
-
this.getMax = function (data)
|
953
|
-
{
|
954
|
-
var runningTotal = 0, max = 0;
|
955
|
-
|
956
|
-
for (var i=0,len=data.length; i<len; i+=1) {
|
957
|
-
runningTotal += data[i];
|
958
|
-
|
959
|
-
max = ma.max(ma.abs(runningTotal), max);
|
960
|
-
}
|
961
|
-
|
962
|
-
return ma.abs(max);
|
963
|
-
};
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
/**
|
969
|
-
* This function facilitates the installation of tooltip event listeners if
|
970
|
-
* tooltips are defined.
|
971
|
-
*/
|
972
|
-
this.allowTooltips =
|
973
|
-
this.AllowTooltips = function ()
|
974
|
-
{
|
975
|
-
// Preload any tooltip images that are used in the tooltips
|
976
|
-
RG.PreLoadTooltipImages(this);
|
977
|
-
|
978
|
-
|
979
|
-
/**
|
980
|
-
* This installs the window mousedown event listener that lears any
|
981
|
-
* highlight that may be visible.
|
982
|
-
*/
|
983
|
-
RG.InstallWindowMousedownTooltipListener(this);
|
984
|
-
|
985
|
-
|
986
|
-
/**
|
987
|
-
* This installs the canvas mousemove event listener. This function
|
988
|
-
* controls the pointer shape.
|
989
|
-
*/
|
990
|
-
RG.InstallCanvasMousemoveTooltipListener(this);
|
991
|
-
|
992
|
-
|
993
|
-
/**
|
994
|
-
* This installs the canvas mouseup event listener. This is the
|
995
|
-
* function that actually shows the appropriate tooltip (if any).
|
996
|
-
*/
|
997
|
-
RG.InstallCanvasMouseupTooltipListener(this);
|
998
|
-
};
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
/**
|
1004
|
-
* Each object type has its own Highlight() function which highlights the appropriate shape
|
1005
|
-
*
|
1006
|
-
* @param object shape The shape to highlight
|
1007
|
-
*/
|
1008
|
-
this.highlight =
|
1009
|
-
this.Highlight = function (shape)
|
1010
|
-
{
|
1011
|
-
if (typeof prop['chart.highlight.style'] === 'function') {
|
1012
|
-
(prop['chart.highlight.style'])(shape);
|
1013
|
-
} else {
|
1014
|
-
RG.Highlight.Rect(this, shape);
|
1015
|
-
}
|
1016
|
-
};
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
/**
|
1022
|
-
* The getObjectByXY() worker method. Don't call this call:
|
1023
|
-
*
|
1024
|
-
* RGraph.ObjectRegistry.getObjectByXY(e)
|
1025
|
-
*
|
1026
|
-
* @param object e The event object
|
1027
|
-
*/
|
1028
|
-
this.getObjectByXY = function (e)
|
1029
|
-
{
|
1030
|
-
var mouseXY = RG.getMouseXY(e);
|
1031
|
-
|
1032
|
-
if (
|
1033
|
-
mouseXY[0] > this.gutterLeft
|
1034
|
-
&& mouseXY[0] < (ca.width - this.gutterRight)
|
1035
|
-
&& mouseXY[1] > this.gutterTop
|
1036
|
-
&& mouseXY[1] < (ca.height - this.gutterBottom)
|
1037
|
-
) {
|
1038
|
-
|
1039
|
-
return this;
|
1040
|
-
}
|
1041
|
-
};
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
/**
|
1047
|
-
* This function positions a tooltip when it is displayed
|
1048
|
-
*
|
1049
|
-
* @param obj object The chart object
|
1050
|
-
* @param int x The X coordinate specified for the tooltip
|
1051
|
-
* @param int y The Y coordinate specified for the tooltip
|
1052
|
-
* @param objec tooltip The tooltips DIV element
|
1053
|
-
*
|
1054
|
-
this.positionTooltip = function (obj, x, y, tooltip, idx)
|
1055
|
-
{
|
1056
|
-
var coordX = obj.coords[tooltip.__index__][0];
|
1057
|
-
var coordY = obj.coords[tooltip.__index__][1];
|
1058
|
-
var coordW = obj.coords[tooltip.__index__][2];
|
1059
|
-
var coordH = obj.coords[tooltip.__index__][3];
|
1060
|
-
var canvasXY = RG.getCanvasXY(obj.canvas);
|
1061
|
-
var mouseXY = RG.getMouseXY(window.event);
|
1062
|
-
var gutterLeft = obj.gutterLeft;
|
1063
|
-
var gutterTop = obj.gutterTop;
|
1064
|
-
var width = tooltip.offsetWidth;
|
1065
|
-
var height = tooltip.offsetHeight;
|
1066
|
-
var value = obj.data[idx];
|
1067
|
-
|
1068
|
-
// Change the value to be the total if necessary
|
1069
|
-
if (tooltip.__index__ == obj.data.length) {
|
1070
|
-
value = obj.total;
|
1071
|
-
}
|
1072
|
-
|
1073
|
-
// Set the top position
|
1074
|
-
tooltip.style.left = 0;
|
1075
|
-
tooltip.style.top = window.event.pageY - height - 5 + 'px';
|
1076
|
-
|
1077
|
-
|
1078
|
-
// By default any overflow is hidden
|
1079
|
-
tooltip.style.overflow = '';
|
1080
|
-
|
1081
|
-
|
1082
|
-
// Reposition the tooltip if at the edges:
|
1083
|
-
|
1084
|
-
// LEFT edge
|
1085
|
-
if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
|
1086
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
|
1087
|
-
|
1088
|
-
// RIGHT edge
|
1089
|
-
} else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
|
1090
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
|
1091
|
-
|
1092
|
-
// Default positioning - CENTERED
|
1093
|
-
} else {
|
1094
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
|
1095
|
-
}
|
1096
|
-
};*/
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
/**
|
1102
|
-
* This method returns the appropriate Y coord for the given value
|
1103
|
-
*
|
1104
|
-
* @param number value The value
|
1105
|
-
*/
|
1106
|
-
this.getYCoord = function (value)
|
1107
|
-
{
|
1108
|
-
if (prop['chart.xaxispos'] == 'center') {
|
1109
|
-
|
1110
|
-
if (value < (-1 * this.max)) {
|
1111
|
-
return null;
|
1112
|
-
}
|
1113
|
-
|
1114
|
-
var coord = (value / this.max) * (this.grapharea / 2);
|
1115
|
-
return this.gutterTop + (this.grapharea / 2) - coord;
|
1116
|
-
|
1117
|
-
} else {
|
1118
|
-
|
1119
|
-
var coord = ( (value - this.scale2.min) / (this.max - this.scale2.min) ) * this.grapharea;
|
1120
|
-
coord = coord + this.gutterBottom;
|
1121
|
-
|
1122
|
-
return ca.height - coord;
|
1123
|
-
}
|
1124
|
-
};
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
/**
|
1130
|
-
* This allows for easy specification of gradients
|
1131
|
-
*/
|
1132
|
-
this.parseColors = function ()
|
1133
|
-
{
|
1134
|
-
// Save the original colors so that they can be restored when the canvas is reset
|
1135
|
-
if (this.original_colors.length === 0) {
|
1136
|
-
this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
|
1137
|
-
this.original_colors['chart.key.colors'] = RG.array_clone(prop['chart.key.colors']);
|
1138
|
-
this.original_colors['chart.crosshairs.color'] = RG.array_clone(prop['chart.crosshairs.color']);
|
1139
|
-
this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
|
1140
|
-
this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
|
1141
|
-
this.original_colors['chart.background.barcolor1'] = RG.array_clone(prop['chart.background.barcolor1']);
|
1142
|
-
this.original_colors['chart.background.barcolor2'] = RG.array_clone(prop['chart.background.barcolor2']);
|
1143
|
-
this.original_colors['chart.background.grid.color'] = RG.array_clone(prop['chart.background.grid.color']);
|
1144
|
-
this.original_colors['chart.strokestyle'] = RG.array_clone(prop['chart.strokestyle']);
|
1145
|
-
this.original_colors['chart.axis.color'] = RG.array_clone(prop['chart.axis.color']);
|
1146
|
-
}
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
// chart.colors
|
1156
|
-
var colors = prop['chart.colors'];
|
1157
|
-
|
1158
|
-
if (colors) {
|
1159
|
-
for (var i=0,len=colors.length; i<len; ++i) {
|
1160
|
-
colors[i] = this.parseSingleColorForGradient(colors[i]);
|
1161
|
-
}
|
1162
|
-
}
|
1163
|
-
|
1164
|
-
// chart.key.colors
|
1165
|
-
var colors = prop['chart.key.colors'];
|
1166
|
-
|
1167
|
-
if (colors) {
|
1168
|
-
for (var i=0,len=colors.length; i<len; ++i) {
|
1169
|
-
colors[i] = this.parseSingleColorForGradient(colors[i]);
|
1170
|
-
}
|
1171
|
-
}
|
1172
|
-
|
1173
|
-
prop['chart.crosshairs.color'] = this.parseSingleColorForGradient(prop['chart.crosshairs.color']);
|
1174
|
-
prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
|
1175
|
-
prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
|
1176
|
-
prop['chart.background.barcolor1'] = this.parseSingleColorForGradient(prop['chart.background.barcolor1']);
|
1177
|
-
prop['chart.background.barcolor2'] = this.parseSingleColorForGradient(prop['chart.background.barcolor2']);
|
1178
|
-
prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
|
1179
|
-
prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
|
1180
|
-
prop['chart.axis.color'] = this.parseSingleColorForGradient(prop['chart.axis.color']);
|
1181
|
-
};
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
/**
|
1187
|
-
* Use this function to reset the object to the post-constructor state. Eg reset colors if
|
1188
|
-
* need be etc
|
1189
|
-
*/
|
1190
|
-
this.reset = function ()
|
1191
|
-
{
|
1192
|
-
};
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
/**
|
1198
|
-
* This parses a single color value
|
1199
|
-
*
|
1200
|
-
* @param string color The color to parse for gradients
|
1201
|
-
*/
|
1202
|
-
this.parseSingleColorForGradient = function (color)
|
1203
|
-
{
|
1204
|
-
if (!color || typeof color != 'string') {
|
1205
|
-
return color;
|
1206
|
-
}
|
1207
|
-
|
1208
|
-
if (typeof color === 'string' && color.match(/^gradient\((.*)\)$/i)) {
|
1209
|
-
|
1210
|
-
var parts = RegExp.$1.split(':');
|
1211
|
-
|
1212
|
-
// Create the gradient
|
1213
|
-
|
1214
|
-
var grad = co.createLinearGradient(0,ca.height - prop['chart.gutter.bottom'], 0, prop['chart.gutter.top']);
|
1215
|
-
|
1216
|
-
var diff = 1 / (parts.length - 1);
|
1217
|
-
|
1218
|
-
grad.addColorStop(0, RG.trim(parts[0]));
|
1219
|
-
|
1220
|
-
for (var j=1,len=parts.length; j<len; ++j) {
|
1221
|
-
grad.addColorStop(j * diff, RG.trim(parts[j]));
|
1222
|
-
}
|
1223
|
-
}
|
1224
|
-
|
1225
|
-
return grad ? grad : color;
|
1226
|
-
};
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
/**
|
1232
|
-
* Using a function to add events makes it easier to facilitate method chaining
|
1233
|
-
*
|
1234
|
-
* @param string type The type of even to add
|
1235
|
-
* @param function func
|
1236
|
-
*/
|
1237
|
-
this.on = function (type, func)
|
1238
|
-
{
|
1239
|
-
if (type.substr(0,2) !== 'on') {
|
1240
|
-
type = 'on' + type;
|
1241
|
-
}
|
1242
|
-
|
1243
|
-
if (typeof this[type] !== 'function') {
|
1244
|
-
this[type] = func;
|
1245
|
-
} else {
|
1246
|
-
RG.addCustomEventListener(this, type, func);
|
1247
|
-
}
|
1248
|
-
|
1249
|
-
return this;
|
1250
|
-
};
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
/**
|
1256
|
-
* This function runs once only
|
1257
|
-
* (put at the end of the file (before any effects))
|
1258
|
-
*/
|
1259
|
-
this.firstDrawFunc = function ()
|
1260
|
-
{
|
1261
|
-
};
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
/**
|
1267
|
-
* Waterfall Grow
|
1268
|
-
*
|
1269
|
-
* @param object Options. You can pass frames here - which should be a number
|
1270
|
-
* @param function An optional function which is called when the animation is finished
|
1271
|
-
*/
|
1272
|
-
this.grow = function ()
|
1273
|
-
{
|
1274
|
-
var opt = arguments[0] || {};
|
1275
|
-
var callback = arguments[1] || function () {};
|
1276
|
-
var frames = opt.frames || 30;
|
1277
|
-
var numFrame = 0;
|
1278
|
-
var obj = this;
|
1279
|
-
var data = RG.array_clone(obj.data);
|
1280
|
-
|
1281
|
-
//Reset The data to zeros
|
1282
|
-
for (var i=0,len=obj.data.length; i<len; ++i) {
|
1283
|
-
obj.data[i] /= frames;
|
1284
|
-
}
|
1285
|
-
|
1286
|
-
/**
|
1287
|
-
* Fix the scale
|
1288
|
-
*/
|
1289
|
-
if (obj.Get('chart.ymax') == null) {
|
1290
|
-
var max = obj.getMax(data);
|
1291
|
-
var scale2 = RG.getScale2(obj, {'max':max});
|
1292
|
-
obj.Set('chart.ymax', scale2.max);
|
1293
|
-
}
|
1294
|
-
|
1295
|
-
//obj.Set('chart.multiplier.x', 0);
|
1296
|
-
//obj.Set('chart.multiplier.w', 0);
|
1297
|
-
|
1298
|
-
function iterator ()
|
1299
|
-
{
|
1300
|
-
for (var i=0; i<obj.data.length; ++i) {
|
1301
|
-
|
1302
|
-
// This produces a very slight easing effect
|
1303
|
-
obj.data[i] = data[i] * RG.Effects.getEasingMultiplier(frames, numFrame);
|
1304
|
-
}
|
1305
|
-
|
1306
|
-
RGraph.clear(obj.canvas);
|
1307
|
-
RGraph.redrawCanvas(obj.canvas);
|
1308
|
-
|
1309
|
-
if (++numFrame < frames) {
|
1310
|
-
RGraph.Effects.updateCanvas(iterator);
|
1311
|
-
} else {
|
1312
|
-
callback(obj);
|
1313
|
-
}
|
1314
|
-
}
|
1315
|
-
|
1316
|
-
iterator();
|
1317
|
-
|
1318
|
-
return this;
|
1319
|
-
};
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
RG.att(ca);
|
1326
|
-
|
1327
|
-
|
1328
|
-
/**
|
1329
|
-
* Now, because canvases can support multiple charts, canvases must always be registered
|
1330
|
-
*/
|
1331
|
-
RG.Register(this);
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
/**
|
1337
|
-
* This is the 'end' of the constructor so if the first argument
|
1338
|
-
* contains configuration data - handle that.
|
1339
|
-
*/
|
1340
|
-
if (parseConfObjectForOptions) {
|
1341
|
-
RG.parseObjectStyleConfig(this, conf.options);
|
1342
|
-
}
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
return this;
|
1348
|
-
};
|
2
|
+
RGraph=window.RGraph||{isRGraph:true};RGraph.Waterfall=function(conf)
|
3
|
+
{if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var parseConfObjectForOptions=true;}else{var conf={id:conf,data:arguments[1]};}
|
4
|
+
this.id=conf.id;this.canvas=document.getElementById(this.id);this.context=this.canvas.getContext?this.canvas.getContext("2d"):null;this.canvas.__object__=this;this.type='waterfall';this.max=0;this.data=conf.data;this.isRGraph=true;this.coords=[];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.properties={'chart.background.barcolor1':'rgba(0,0,0,0)','chart.background.barcolor2':'rgba(0,0,0,0)','chart.background.grid':true,'chart.background.grid.color':'#ddd','chart.background.grid.width':1,'chart.background.grid.hsize':20,'chart.background.grid.vsize':20,'chart.background.grid.vlines':true,'chart.background.grid.hlines':true,'chart.background.grid.border':true,'chart.background.grid.autofit':true,'chart.background.grid.autofit.align':true,'chart.background.grid.autofit.numhlines':5,'chart.background.grid.autofit.numvlines':20,'chart.background.image':null,'chart.background.hbars':null,'chart.linewidth':1,'chart.axis.linewidth':1,'chart.xaxispos':'bottom','chart.numxticks':null,'chart.numyticks':10,'chart.hmargin':5,'chart.strokestyle':'#666','chart.axis.color':'black','chart.gutter.left':25,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.labels':[],'chart.labels.bold':false,'chart.labels.offsetx':0,'chart.labels.offsety':0,'chart.ylabels.offsetx':0,'chart.ylabels.offsety':0,'chart.ylabels':true,'chart.text.color':'black','chart.text.size':12,'chart.text.angle':0,'chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.ymax':null,'chart.title':'','chart.title.color':'black','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.bold':true,'chart.title.font':null,'chart.title.xaxis':'','chart.title.yaxis':'','chart.title.yaxis.bold':true,'chart.title.yaxis.size':null,'chart.title.yaxis.font':null,'chart.title.yaxis.color':null,'chart.title.xaxis.pos':null,'chart.title.yaxis.pos':null,'chart.title.yaxis.align':'left','chart.title.xaxis.bold':true,'chart.title.xaxis.size':null,'chart.title.xaxis.font':null,'chart.title.xaxis.color':null,'chart.title.yaxis.x':null,'chart.title.yaxis.y':null,'chart.title.xaxis.x':null,'chart.title.xaxis.y':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.colors':['green','red','blue'],'chart.colors.sequential':false,'chart.shadow':false,'chart.shadow.color':'#666','chart.shadow.offsetx':3,'chart.shadow.offsety':3,'chart.shadow.blur':3,'chart.tooltips':null,'chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.event':'onclick','chart.tooltips.highlight':true,'chart.tooltips.override':null,'chart.highlight.stroke':'rgba(0,0,0,0)','chart.highlight.fill':'rgba(255,255,255,0.7)','chart.contextmenu':null,'chart.units.pre':'','chart.units.post':'','chart.scale.decimals':0,'chart.scale.point':'.','chart.scale.thousand':',','chart.scale.zerostart':true,'chart.crosshairs':false,'chart.crosshairs.color':'#333','chart.crosshairs.hline':true,'chart.crosshairs.vline':true,'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.resizable':false,'chart.resize.handle.background':null,'chart.noaxes':false,'chart.noxaxis':false,'chart.noyaxis':false,'chart.axis.color':'black','chart.total':true,'chart.multiplier.x':1,'chart.multiplier.w':1,'chart.events.click':null,'chart.events.mousemove':null,'chart.ylabels.count':5,'chart.ymin':0,'chart.clearto':'rgba(0,0,0,0)','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.stroke':'#000','chart.key.interactive.highlight.chart.fill':'rgba(255,255,255,0.7)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.text.color':'black',}
|
5
|
+
if(!this.canvas){alert('[WATERFALL] No canvas support');return;}
|
6
|
+
for(var i=0,len=this.data.length;i<=len;++i){this['$'+i]={}
|
7
|
+
if(typeof this.data[i]==='string'){this.data[i]=parseFloat(this.data[i]);}}
|
8
|
+
if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
|
9
|
+
var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
|
10
|
+
if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
|
11
|
+
this.set=this.Set=function(name,value)
|
12
|
+
{var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
|
13
|
+
if(name.substr(0,6)!='chart.'){name='chart.'+name;}
|
14
|
+
while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
|
15
|
+
if(name=='chart.total'&&prop['chart.numxticks']==null){prop['chart.numxticks']=this.data.length;}
|
16
|
+
prop[name.toLowerCase()]=value;return this;};this.get=this.Get=function(name)
|
17
|
+
{if(name.substr(0,6)!='chart.'){name='chart.'+name;}
|
18
|
+
while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
|
19
|
+
return prop[name.toLowerCase()];};this.draw=this.Draw=function()
|
20
|
+
{RGraph.fireCustomEvent(this,'onbeforedraw');if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
|
21
|
+
RGraph.DrawBackgroundImage(this);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.coords=[];this.coordsText=[];this.centery=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop;this.max=0;this.grapharea=ca.height-this.gutterTop-this.gutterBottom;this.graphwidth=ca.width-this.gutterLeft-this.gutterRight;this.halfTextHeight=prop['chart.text.size']/2;this.max=this.getMax(this.data);var decimals=prop['chart.scale.decimals'];this.scale2=RG.getScale2(this,{max:typeof(prop['chart.ymax'])=='number'?prop['chart.ymax']:this.max,min:prop['chart.ymin'],strict:typeof(prop['chart.ymax'])==='number'?true:false,'scale.decimals':Number(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.ylabels.count']});this.max=this.scale2.max;this.min=this.scale2.min;RG.drawBars(this)
|
22
|
+
RG.Background.draw(this);this.DrawAxes();this.Drawbars();this.DrawLabels();if(prop['chart.xaxispos']==='bottom'&&prop['chart.noaxes']===false&&prop['chart.noxaxis']===false&&prop['chart.ymin']===0){co.strokeStyle=prop['chart.axis.color'];co.strokeRect(prop['chart.gutter.left'],ca.height-prop['chart.gutter.bottom'],ca.width-this.gutterLeft-this.gutterRight,0);}
|
23
|
+
if(prop['chart.contextmenu']){RG.ShowContext(this);}
|
24
|
+
if(prop['chart.resizable']){RG.AllowResizing(this);}
|
25
|
+
RG.InstallEventListeners(this);if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
|
26
|
+
if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
|
27
|
+
RG.FireCustomEvent(this,'ondraw');return this;};this.drawAxes=this.DrawAxes=function()
|
28
|
+
{if(prop['chart.noaxes']){return;}
|
29
|
+
co.beginPath();co.strokeStyle=prop['chart.axis.color'];co.lineWidth=prop['chart.axis.linewidth']+0.001;if(prop['chart.noyaxis']==false){co.moveTo(ma.round(this.gutterLeft),this.gutterTop);co.lineTo(ma.round(this.gutterLeft),ca.height-this.gutterBottom);}
|
30
|
+
if(prop['chart.noxaxis']==false){if(prop['chart.xaxispos']=='center'){co.moveTo(this.gutterLeft,ma.round(((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop));co.lineTo(ca.width-this.gutterRight,ma.round(((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop));}else{var y=ma.floor(this.getYCoord(0));co.moveTo(this.gutterLeft,y);co.lineTo(ca.width-this.gutterRight,y);}}
|
31
|
+
var numYTicks=prop['chart.numyticks'];if(prop['chart.noyaxis']===false&&prop['chart.numyticks']>0){var yTickGap=(ca.height-this.gutterTop-this.gutterBottom)/numYTicks;for(y=this.gutterTop;y<(ca.height-this.gutterBottom);y+=yTickGap){if(prop['chart.xaxispos']=='bottom'||(y!=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop)){co.moveTo(this.gutterLeft,ma.round(y));co.lineTo(this.gutterLeft-3,ma.round(y));}}
|
32
|
+
if(prop['chart.noxaxis']||prop['chart.xaxispos']=='center'||prop['chart.ymin']!==0){co.moveTo(this.gutterLeft-3,Math.round(ca.height-this.gutterBottom));co.lineTo(this.gutterLeft,Math.round(ca.height-this.gutterBottom));}}
|
33
|
+
if(prop['chart.numxticks']==null){prop['chart.numxticks']=this.data.length+(prop['chart.total']?1:0)}
|
34
|
+
if(prop['chart.noxaxis']==false&&prop['chart.numxticks']>0){xTickGap=(ca.width-this.gutterLeft-this.gutterRight)/prop['chart.numxticks'];if(prop['chart.xaxispos']=='center'){yStart=((ca.height-this.gutterBottom-this.gutterTop)/2)+this.gutterTop-3;yEnd=((ca.height-this.gutterBottom-this.gutterTop)/2)+this.gutterTop+3;}else{yStart=this.getYCoord(0)-(this.scale2.min<0?3:0);yEnd=this.getYCoord(0)+3;}
|
35
|
+
for(x=this.gutterLeft+xTickGap;x<=ca.width-this.gutterRight+1;x+=xTickGap){co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}
|
36
|
+
if(prop['chart.noyaxis']){co.moveTo(ma.round(this.gutterLeft),yStart);co.lineTo(ma.round(this.gutterLeft),yEnd);}}
|
37
|
+
if(prop['chart.noyaxis']&&prop['chart.noxaxis']==false){co.moveTo(ma.round(this.gutterLeft),this.getYCoord(0));co.lineTo(ma.round(this.gutterLeft),this.getYCoord(0));}
|
38
|
+
co.stroke();};this.drawLabels=this.DrawLabels=function()
|
39
|
+
{var context=co,numYLabels=5,interval=this.grapharea/numYLabels,font=prop['chart.text.font'],size=prop['chart.text.size'],color=prop['chart.text.color'],units_pre=prop['chart.units.pre'],units_post=prop['chart.units.post'],offsetx=prop['chart.ylabels.offsetx'],offsety=prop['chart.ylabels.offsety'];co.beginPath();co.fillStyle=color;if(prop['chart.ylabels']){if(prop['chart.xaxispos']=='center'){var halfInterval=interval/2;var halfWay=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop;for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.text2(this,{font:font,size:size,x:this.gutterLeft-5+offsetx,y:this.gutterTop+(((this.grapharea/2)/len)*i)+offsety,text:this.scale2.labels[len-i-1],valign:'center',halign:'right',tag:'scale'});RG.text2(this,{font:font,size:size,x:this.gutterLeft-5+offsetx,y:halfWay+(((this.grapharea/2)/len)*(i+1))+offsety,text:this.scale2.labels[i],valign:'center',halign:'right',tag:'scale'});}
|
40
|
+
if(prop['chart.scale.zerostart']){RG.text2(co,{x:this.gutterLeft-5+offsetx,y:halfWay,text:'0',font:font,size:size,valign:'center',halign:'right',tag:'scale'});}}else{for(var i=0,len=this.scale2.values.length;i<len;++i){var y=this.getYCoord(this.scale2.values[i])+offsety;RG.text2(this,{font:font,size:size,x:this.gutterLeft-5+offsetx,y:y,text:this.scale2.labels[i],valign:'center',halign:'right',tag:'scale'});}
|
41
|
+
if(prop['chart.scale.zerostart']||prop['chart.ymin']!==0){RG.text2(co,{x:this.gutterLeft-5+offsetx,y:this.getYCoord(prop['chart.ymin']||0),text:RG.numberFormat(this,String(Number(prop['chart.ymin']||0).toFixed(prop['chart.ymin']===0?0:prop['chart.scale.decimals'])),prop['chart.units.pre'],prop['chart.units.post']),font:font,size:size,valign:'center',halign:'right',tag:'scale'});}}}
|
42
|
+
if(prop['chart.labels'].length>0){interval=(ca.width-this.gutterLeft-this.gutterRight)/prop['chart.labels'].length;var halign='center';var angle=prop['chart.text.angle'];if(angle){halign='right';angle*=-1;}
|
43
|
+
var labels=prop['chart.labels'],labelsColor=prop['chart.labels.color'],bold=prop['chart.labels.bold'],offsetx=prop['chart.labels.offsetx'],offsety=prop['chart.labels.offsety']
|
44
|
+
for(var i=0,len=labels.length;i<len;i+=1){RG.text2(this,{'color':labelsColor,'font':font,'size':size,'bold':bold,'x':this.gutterLeft+(i*interval)+(interval/2)+offsetx,'y':ca.height-this.gutterBottom+5+this.halfTextHeight+offsety,'text':labels[i],'valign':'center','halign':halign,'angle':angle,'tag':'labels'});}}
|
45
|
+
co.stroke();co.fill();};this.drawbars=this.Drawbars=function()
|
46
|
+
{var context=co,canvas=ca,hmargin=prop['chart.hmargin'],runningTotal=0;co.lineWidth=prop['chart.linewidth']+0.001;for(var i=0,len=this.data.length,seq=0;i<len;++i,++seq){co.beginPath();co.strokeStyle=prop['chart.strokestyle'];var x=ma.round(this.gutterLeft+hmargin+(((this.graphwidth/(this.data.length+(prop['chart.total']?1:0)))*i)*prop['chart.multiplier.x']));var h=this.getYCoord(0)-this.getYCoord(ma.abs(this.data[i]));if(i===0){y=this.getYCoord(0)-h;}else{y=this.getYCoord(runningTotal)-h;}
|
47
|
+
y=ma.round(y);var w=((ca.width-this.gutterLeft-this.gutterRight)/(this.data.length+(prop['chart.total']?1:0)))-(2*prop['chart.hmargin']);w=w*prop['chart.multiplier.w'];if(this.data[i]<0){y+=h;}
|
48
|
+
co.fillStyle=this.data[i]>=0?prop['chart.colors'][0]:prop['chart.colors'][1];if(prop['chart.colors.sequential']){co.fillStyle=prop['chart.colors'][seq];}
|
49
|
+
if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}else{RG.noShadow(this);}
|
50
|
+
co.rect(x,ma.floor(y),w,ma.floor(h));this.coords.push([x,y,w,h]);runningTotal+=this.data[i];co.stroke();co.fill();}
|
51
|
+
this.total=runningTotal;if(prop['chart.total']){h=this.getYCoord(0)-this.getYCoord(ma.abs(runningTotal));if(prop['chart.xaxispos']=='center'){y=runningTotal>0?this.getYCoord(0)-h:this.getYCoord(0);}else{if(runningTotal>0){y=this.getYCoord(0)-h;}else{y=this.getYCoord(0);}}
|
52
|
+
x=x+(prop['chart.hmargin']*2)+w;co.fillStyle=prop['chart.colors'][2];if(prop['chart.colors.sequential']){co.fillStyle=prop['chart.colors'][seq]}
|
53
|
+
pa2(co,'b r % % % % s % f %',x,y,w,h,co.strokeStyle,co.fillStyle);var previousCoords=[x,y,w,ma.abs(h)];this.coords.push(previousCoords);}
|
54
|
+
RG.noShadow(this);co.lineWidth=1;co.strokeStyle='#666';co.beginPath();for(var i=1,len=this.coords.length;i<len;i+=1){var prev=this.coords[i-1],curr=this.coords[i],prevData=this.data[i-1]
|
55
|
+
var y=(prevData>0?prev[1]:prev[1]+prev[3]);co.moveTo(prev[0]+prev[2],y);co.lineTo(curr[0],(prevData>0?prev[1]:prev[1]+prev[3]));}
|
56
|
+
co.stroke();};this.getShape=this.getBar=function(e)
|
57
|
+
{for(var i=0,len=this.coords.length;i<len;i++){var mouseXY=RG.getMouseXY(e),mouseX=mouseXY[0],mouseY=mouseXY[1];var left=this.coords[i][0],top=this.coords[i][1],width=this.coords[i][2],height=this.coords[i][3];if(mouseX>=left&&mouseX<=(left+width)&&mouseY>=top&&mouseY<=top+height){var tooltip=RG.parseTooltipText(prop['chart.tooltips'],i);return{0:this,object:this,1:left,x:left,2:top,y:top,3:width,width:width,4:height,height:height,5:i,index:i,tooltip:tooltip};}}
|
58
|
+
return null;};this.getMax=function(data)
|
59
|
+
{var runningTotal=0,max=0;for(var i=0,len=data.length;i<len;i+=1){runningTotal+=data[i];max=ma.max(ma.abs(runningTotal),max);}
|
60
|
+
return ma.abs(max);};this.allowTooltips=this.AllowTooltips=function()
|
61
|
+
{RG.PreLoadTooltipImages(this);RG.InstallWindowMousedownTooltipListener(this);RG.InstallCanvasMousemoveTooltipListener(this);RG.InstallCanvasMouseupTooltipListener(this);};this.highlight=this.Highlight=function(shape)
|
62
|
+
{if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Rect(this,shape);}};this.getObjectByXY=function(e)
|
63
|
+
{var mouseXY=RG.getMouseXY(e);if(mouseXY[0]>this.gutterLeft&&mouseXY[0]<(ca.width-this.gutterRight)&&mouseXY[1]>this.gutterTop&&mouseXY[1]<(ca.height-this.gutterBottom)){return this;}};this.getYCoord=function(value)
|
64
|
+
{if(prop['chart.xaxispos']=='center'){if(value<(-1*this.max)){return null;}
|
65
|
+
var coord=(value/this.max)*(this.grapharea/2);return this.gutterTop+(this.grapharea/2)-coord;}else{var coord=((value-this.scale2.min)/(this.max-this.scale2.min))*this.grapharea;coord=coord+this.gutterBottom;return ca.height-coord;}};this.parseColors=function()
|
66
|
+
{if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.array_clone(prop['chart.colors']);this.original_colors['chart.key.colors']=RG.array_clone(prop['chart.key.colors']);this.original_colors['chart.crosshairs.color']=RG.array_clone(prop['chart.crosshairs.color']);this.original_colors['chart.highlight.stroke']=RG.array_clone(prop['chart.highlight.stroke']);this.original_colors['chart.highlight.fill']=RG.array_clone(prop['chart.highlight.fill']);this.original_colors['chart.background.barcolor1']=RG.array_clone(prop['chart.background.barcolor1']);this.original_colors['chart.background.barcolor2']=RG.array_clone(prop['chart.background.barcolor2']);this.original_colors['chart.background.grid.color']=RG.array_clone(prop['chart.background.grid.color']);this.original_colors['chart.strokestyle']=RG.array_clone(prop['chart.strokestyle']);this.original_colors['chart.axis.color']=RG.array_clone(prop['chart.axis.color']);}
|
67
|
+
var colors=prop['chart.colors'];if(colors){for(var i=0,len=colors.length;i<len;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}}
|
68
|
+
var colors=prop['chart.key.colors'];if(colors){for(var i=0,len=colors.length;i<len;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}}
|
69
|
+
prop['chart.crosshairs.color']=this.parseSingleColorForGradient(prop['chart.crosshairs.color']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.background.barcolor1']=this.parseSingleColorForGradient(prop['chart.background.barcolor1']);prop['chart.background.barcolor2']=this.parseSingleColorForGradient(prop['chart.background.barcolor2']);prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.strokestyle']=this.parseSingleColorForGradient(prop['chart.strokestyle']);prop['chart.axis.color']=this.parseSingleColorForGradient(prop['chart.axis.color']);};this.reset=function()
|
70
|
+
{};this.parseSingleColorForGradient=function(color)
|
71
|
+
{if(!color||typeof color!='string'){return color;}
|
72
|
+
if(typeof color==='string'&&color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');var grad=co.createLinearGradient(0,ca.height-prop['chart.gutter.bottom'],0,prop['chart.gutter.top']);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1,len=parts.length;j<len;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
|
73
|
+
return grad?grad:color;};this.on=function(type,func)
|
74
|
+
{if(type.substr(0,2)!=='on'){type='on'+type;}
|
75
|
+
if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
|
76
|
+
return this;};this.firstDrawFunc=function()
|
77
|
+
{};this.grow=function()
|
78
|
+
{var opt=arguments[0]||{};var callback=arguments[1]||function(){};var frames=opt.frames||30;var numFrame=0;var obj=this;var data=RG.array_clone(obj.data);for(var i=0,len=obj.data.length;i<len;++i){obj.data[i]/=frames;}
|
79
|
+
if(obj.Get('chart.ymax')==null){var max=obj.getMax(data);var scale2=RG.getScale2(obj,{'max':max});obj.Set('chart.ymax',scale2.max);}
|
80
|
+
function iterator()
|
81
|
+
{for(var i=0;i<obj.data.length;++i){obj.data[i]=data[i]*RG.Effects.getEasingMultiplier(frames,numFrame);}
|
82
|
+
RGraph.clear(obj.canvas);RGraph.redrawCanvas(obj.canvas);if(++numFrame<frames){RGraph.Effects.updateCanvas(iterator);}else{callback(obj);}}
|
83
|
+
iterator();return this;};RG.att(ca);RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}
|
84
|
+
return this;};
|