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,2789 +1,163 @@
|
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
'chart.xmin': 0,
|
176
|
-
'chart.xmax': 0,
|
177
|
-
'chart.axis.color': 'black',
|
178
|
-
'chart.shadow': false,
|
179
|
-
'chart.shadow.color': '#666',
|
180
|
-
'chart.shadow.blur': 3,
|
181
|
-
'chart.shadow.offsetx': 3,
|
182
|
-
'chart.shadow.offsety': 3,
|
183
|
-
'chart.vmargin': 2,
|
184
|
-
'chart.vmargin.grouped': 2,
|
185
|
-
'chart.grouping': 'grouped',
|
186
|
-
'chart.tooltips': null,
|
187
|
-
'chart.tooltips.event': 'onclick',
|
188
|
-
'chart.tooltips.effect': 'fade',
|
189
|
-
'chart.tooltips.css.class': 'RGraph_tooltip',
|
190
|
-
'chart.tooltips.highlight': true,
|
191
|
-
'chart.highlight.fill': 'rgba(255,255,255,0.7)',
|
192
|
-
'chart.highlight.stroke': 'rgba(0,0,0,0)',
|
193
|
-
'chart.highlight.style': null,
|
194
|
-
'chart.annotatable': false,
|
195
|
-
'chart.annotate.color': 'black',
|
196
|
-
'chart.zoom.factor': 1.5,
|
197
|
-
'chart.zoom.fade.in': true,
|
198
|
-
'chart.zoom.fade.out': true,
|
199
|
-
'chart.zoom.hdir': 'right',
|
200
|
-
'chart.zoom.vdir': 'down',
|
201
|
-
'chart.zoom.frames': 25,
|
202
|
-
'chart.zoom.delay': 16.666,
|
203
|
-
'chart.zoom.shadow': true,
|
204
|
-
'chart.zoom.background': true,
|
205
|
-
'chart.zoom.action': 'zoom',
|
206
|
-
'chart.resizable': false,
|
207
|
-
'chart.resize.handle.adjust': [0,0],
|
208
|
-
'chart.resize.handle.background': null,
|
209
|
-
'chart.scale.point': '.',
|
210
|
-
'chart.scale.thousand': ',',
|
211
|
-
'chart.scale.decimals': null,
|
212
|
-
'chart.scale.zerostart': true,
|
213
|
-
'chart.noredraw': false,
|
214
|
-
'chart.events.click': null,
|
215
|
-
'chart.events.mousemove': null,
|
216
|
-
'chart.noxaxis': false,
|
217
|
-
'chart.noyaxis': false,
|
218
|
-
'chart.noaxes': false,
|
219
|
-
'chart.noxtickmarks': false,
|
220
|
-
'chart.noytickmarks': false,
|
221
|
-
'chart.numyticks': data.length,
|
222
|
-
'chart.numxticks': 10,
|
223
|
-
'chart.variant': 'hbar',
|
224
|
-
'chart.variant.threed.angle': 0.1,
|
225
|
-
'chart.variant.threed.offsetx': 10,
|
226
|
-
'chart.variant.threed.offsety': 5,
|
227
|
-
'chart.variant.threed.xaxis': true,
|
228
|
-
'chart.variant.threed.yaxis': true,
|
229
|
-
'chart.yaxispos': 'left',
|
230
|
-
'chart.variant': 'hbar',
|
231
|
-
'chart.clearto': 'rgba(0,0,0,0)',
|
232
|
-
'chart.adjustable': false,
|
233
|
-
'chart.adjustable.only': null
|
234
|
-
}
|
235
|
-
|
236
|
-
// Check for support
|
237
|
-
if (!this.canvas) {
|
238
|
-
alert('[HBAR] No canvas support');
|
239
|
-
return;
|
240
|
-
}
|
241
|
-
|
242
|
-
// This loop is used to check for stacked or grouped charts and now
|
243
|
-
// also to convert strings to numbers. And now also undefined values
|
244
|
-
// (29/07/2016
|
245
|
-
for (i=0,len=this.data.length; i<len; ++i) {
|
246
|
-
if (typeof this.data[i] == 'object' && !RGraph.isNull(this.data[i])) {
|
247
|
-
|
248
|
-
this.stackedOrGrouped = true;
|
249
|
-
|
250
|
-
for (var j=0,len2=this.data[i].length; j<len2; ++j) {
|
251
|
-
if (typeof this.data[i][j] === 'string') {
|
252
|
-
this.data[i][j] = parseFloat(this.data[i][j]);
|
253
|
-
}
|
254
|
-
}
|
255
|
-
|
256
|
-
} else if (typeof this.data[i] == 'string') {
|
257
|
-
this.data[i] = parseFloat(this.data[i]) || 0;
|
258
|
-
|
259
|
-
} else if (typeof this.data[i] === 'undefined') {
|
260
|
-
this.data[i] = null;
|
261
|
-
}
|
262
|
-
}
|
263
|
-
|
264
|
-
|
265
|
-
/**
|
266
|
-
* Create the dollar objects so that functions can be added to them
|
267
|
-
*/
|
268
|
-
var linear_data = RGraph.arrayLinearize(data);
|
269
|
-
for (var i=0,len=linear_data.length; i<len; ++i) {
|
270
|
-
this['$' + i] = {};
|
271
|
-
}
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
/**
|
276
|
-
* Create the linear data array
|
277
|
-
*/
|
278
|
-
this.data_arr = RGraph.arrayLinearize(this.data);
|
279
|
-
|
280
|
-
|
281
|
-
/**
|
282
|
-
* Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
|
283
|
-
* done already
|
284
|
-
*/
|
285
|
-
if (!this.canvas.__rgraph_aa_translated__) {
|
286
|
-
this.context.translate(0.5,0.5);
|
287
|
-
|
288
|
-
this.canvas.__rgraph_aa_translated__ = true;
|
289
|
-
}
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
// Short variable names
|
295
|
-
var RG = RGraph,
|
296
|
-
ca = this.canvas,
|
297
|
-
co = ca.getContext('2d'),
|
298
|
-
prop = this.properties,
|
299
|
-
pa2 = RG.path2,
|
300
|
-
win = window,
|
301
|
-
doc = document,
|
302
|
-
ma = Math
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
/**
|
307
|
-
* "Decorate" the object with the generic effects if the effects library has been included
|
308
|
-
*/
|
309
|
-
if (RG.Effects && typeof RG.Effects.decorate === 'function') {
|
310
|
-
RG.Effects.decorate(this);
|
311
|
-
}
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
/**
|
317
|
-
* A setter
|
318
|
-
*
|
319
|
-
* @param name string The name of the property to set
|
320
|
-
* @param value mixed The value of the property
|
321
|
-
*/
|
322
|
-
this.set =
|
323
|
-
this.Set = function (name)
|
324
|
-
{
|
325
|
-
var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
|
326
|
-
|
327
|
-
/**
|
328
|
-
* the number of arguments is only one and it's an
|
329
|
-
* object - parse it for configuration data and return.
|
330
|
-
*/
|
331
|
-
if (arguments.length === 1 && typeof name === 'object') {
|
332
|
-
RG.parseObjectStyleConfig(this, name);
|
333
|
-
return this;
|
334
|
-
}
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
/**
|
340
|
-
* This should be done first - prepend the propertyy name with "chart." if necessary
|
341
|
-
*/
|
342
|
-
if (name.substr(0,6) != 'chart.') {
|
343
|
-
name = 'chart.' + name;
|
344
|
-
}
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
// Convert uppercase letters to dot+lower case letter
|
349
|
-
while(name.match(/([A-Z])/)) {
|
350
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
351
|
-
}
|
352
|
-
|
353
|
-
if (name == 'chart.labels.abovebar') {
|
354
|
-
name = 'chart.labels.above';
|
355
|
-
}
|
356
|
-
|
357
|
-
prop[name] = value;
|
358
|
-
|
359
|
-
return this;
|
360
|
-
};
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
/**
|
366
|
-
* A getter
|
367
|
-
*
|
368
|
-
* @param name string The name of the property to get
|
369
|
-
*/
|
370
|
-
this.get =
|
371
|
-
this.Get = function (name)
|
372
|
-
{
|
373
|
-
/**
|
374
|
-
* This should be done first - prepend the property name with "chart." if necessary
|
375
|
-
*/
|
376
|
-
if (name.substr(0,6) != 'chart.') {
|
377
|
-
name = 'chart.' + name;
|
378
|
-
}
|
379
|
-
|
380
|
-
// Convert uppercase letters to dot+lower case letter
|
381
|
-
while(name.match(/([A-Z])/)) {
|
382
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
383
|
-
}
|
384
|
-
|
385
|
-
|
386
|
-
if (name == 'chart.labels.abovebar') {
|
387
|
-
name = 'chart.labels.above';
|
388
|
-
}
|
389
|
-
|
390
|
-
return prop[name];
|
391
|
-
};
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
/**
|
397
|
-
* The function you call to draw the bar chart
|
398
|
-
*/
|
399
|
-
this.draw =
|
400
|
-
this.Draw = function ()
|
401
|
-
{
|
402
|
-
/**
|
403
|
-
* Fire the onbeforedraw event
|
404
|
-
*/
|
405
|
-
RG.fireCustomEvent(this, 'onbeforedraw');
|
406
|
-
|
407
|
-
|
408
|
-
//
|
409
|
-
// Check that the bHBar isn't stacked with adjusting enabled
|
410
|
-
//
|
411
|
-
if (prop['chart.adjustable'] && prop['chart.grouping'] === 'stacked') {
|
412
|
-
alert('[RGRAPH] The HBar does not support stacked charts with adjusting');
|
413
|
-
}
|
414
|
-
|
415
|
-
//
|
416
|
-
// If the chart is 3d then angle it it
|
417
|
-
//
|
418
|
-
|
419
|
-
if (prop['chart.variant'] === '3d') {
|
420
|
-
|
421
|
-
if (prop['chart.text.accessible']) {
|
422
|
-
// Nada
|
423
|
-
} else {
|
424
|
-
co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);
|
425
|
-
}
|
426
|
-
|
427
|
-
// Enlarge the gutter if its 25
|
428
|
-
if (prop['chart.gutter.bottom'] === 25) {
|
429
|
-
this.set('gutterBottom', 80);
|
430
|
-
}
|
431
|
-
}
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
/**
|
437
|
-
* Parse the colors. This allows for simple gradient syntax
|
438
|
-
*/
|
439
|
-
if (!this.colorsParsed) {
|
440
|
-
this.parseColors();
|
441
|
-
|
442
|
-
// Don't want to do this again
|
443
|
-
this.colorsParsed = true;
|
444
|
-
}
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
/**
|
452
|
-
* Accomodate autosizing the left gutter
|
453
|
-
*/
|
454
|
-
if (prop['chart.gutter.left.autosize']) {
|
455
|
-
var len = 0;
|
456
|
-
var labels = prop['chart.labels'];
|
457
|
-
var font = prop['chart.text.font'];
|
458
|
-
var size = prop['chart.text.size'];
|
459
|
-
|
460
|
-
for (var i=0; i<labels.length; i+=1) {
|
461
|
-
var length = RG.measureText(labels[i], false, font, size)[0] || 0
|
462
|
-
len = ma.max(len, length);
|
463
|
-
}
|
464
|
-
|
465
|
-
prop['chart.gutter.left'] = len + 10;
|
466
|
-
}
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
/**
|
481
|
-
* This is new in May 2011 and facilitates indiviual gutter settings,
|
482
|
-
* eg chart.gutter.left
|
483
|
-
*/
|
484
|
-
this.gutterLeft = prop['chart.gutter.left'];
|
485
|
-
this.gutterRight = prop['chart.gutter.right'];
|
486
|
-
this.gutterTop = prop['chart.gutter.top'];
|
487
|
-
this.gutterBottom = prop['chart.gutter.bottom'];
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
/**
|
493
|
-
* Stop the coords array from growing uncontrollably
|
494
|
-
*/
|
495
|
-
this.coords = [];
|
496
|
-
this.coords2 = [];
|
497
|
-
this.coordsText = [];
|
498
|
-
this.max = 0;
|
499
|
-
|
500
|
-
/**
|
501
|
-
* Check for chart.xmin in stacked charts
|
502
|
-
*/
|
503
|
-
if (prop['chart.xmin'] > 0 && prop['chart.grouping'] == 'stacked') {
|
504
|
-
alert('[HBAR] Using chart.xmin is not supported with stacked charts, resetting chart.xmin to zero');
|
505
|
-
this.Set('chart.xmin', 0);
|
506
|
-
}
|
507
|
-
|
508
|
-
/**
|
509
|
-
* Work out a few things. They need to be here because they depend on things you can change before you
|
510
|
-
* call Draw() but after you instantiate the object
|
511
|
-
*/
|
512
|
-
this.graphwidth = ca.width - this.gutterLeft - this.gutterRight;
|
513
|
-
this.graphheight = ca.height - this.gutterTop - this.gutterBottom;
|
514
|
-
this.halfgrapharea = this.grapharea / 2;
|
515
|
-
this.halfTextHeight = prop['chart.text.size'] / 2;
|
516
|
-
this.halfway = ma.round((this.graphwidth / 2) + this.gutterLeft)
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
// Progressively Draw the chart
|
528
|
-
RG.Background.draw(this);
|
529
|
-
|
530
|
-
this.drawbars();
|
531
|
-
this.drawAxes();
|
532
|
-
this.drawLabels();
|
533
|
-
|
534
|
-
|
535
|
-
// Draw the key if necessary
|
536
|
-
if (prop['chart.key'] && prop['chart.key'].length) {
|
537
|
-
RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
|
538
|
-
}
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
/**
|
543
|
-
* Setup the context menu if required
|
544
|
-
*/
|
545
|
-
if (prop['chart.contextmenu']) {
|
546
|
-
RG.ShowContext(this);
|
547
|
-
}
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
/**
|
552
|
-
* Draw "in graph" labels
|
553
|
-
*/
|
554
|
-
RG.DrawInGraphLabels(this);
|
555
|
-
|
556
|
-
|
557
|
-
/**
|
558
|
-
* This function enables resizing
|
559
|
-
*/
|
560
|
-
if (prop['chart.resizable']) {
|
561
|
-
RG.AllowResizing(this);
|
562
|
-
}
|
563
|
-
|
564
|
-
|
565
|
-
/**
|
566
|
-
* This installs the event listeners
|
567
|
-
*/
|
568
|
-
RG.InstallEventListeners(this);
|
569
|
-
|
570
|
-
|
571
|
-
/**
|
572
|
-
* Fire the onfirstdraw event
|
573
|
-
*/
|
574
|
-
if (this.firstDraw) {
|
575
|
-
RG.fireCustomEvent(this, 'onfirstdraw');
|
576
|
-
this.firstDraw = false;
|
577
|
-
this.firstDrawFunc();
|
578
|
-
}
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
/**
|
583
|
-
* Fire the RGraph ondraw event
|
584
|
-
*/
|
585
|
-
RG.FireCustomEvent(this, 'ondraw');
|
586
|
-
|
587
|
-
return this;
|
588
|
-
};
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
/**
|
593
|
-
* Used in chaining. Runs a function there and then - not waiting for
|
594
|
-
* the events to fire (eg the onbeforedraw event)
|
595
|
-
*
|
596
|
-
* @param function func The function to execute
|
597
|
-
*/
|
598
|
-
this.exec = function (func)
|
599
|
-
{
|
600
|
-
func(this);
|
601
|
-
|
602
|
-
return this;
|
603
|
-
};
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
/**
|
609
|
-
* This draws the axes
|
610
|
-
*/
|
611
|
-
this.drawAxes =
|
612
|
-
this.DrawAxes = function ()
|
613
|
-
{
|
614
|
-
var halfway = this.halfway
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
co.beginPath();
|
622
|
-
|
623
|
-
co.lineWidth = prop['chart.axis.linewidth'] ? prop['chart.axis.linewidth'] + 0.001 : 1.001;
|
624
|
-
co.strokeStyle = prop['chart.axis.color'];
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
// Draw the Y axis
|
630
|
-
if (prop['chart.noyaxis'] == false && prop['chart.noaxes'] == false) {
|
631
|
-
if (prop['chart.yaxispos'] == 'center') {
|
632
|
-
co.moveTo(halfway, this.gutterTop);
|
633
|
-
co.lineTo(halfway, ca.height - this.gutterBottom);
|
634
|
-
|
635
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
636
|
-
co.moveTo(ca.width - this.gutterRight, this.gutterTop);
|
637
|
-
co.lineTo(ca.width - this.gutterRight, ca.height - this.gutterBottom);
|
638
|
-
|
639
|
-
} else {
|
640
|
-
co.moveTo(this.gutterLeft, this.gutterTop);
|
641
|
-
co.lineTo(this.gutterLeft, ca.height - this.gutterBottom);
|
642
|
-
}
|
643
|
-
}
|
644
|
-
|
645
|
-
// Draw the X axis
|
646
|
-
if (prop['chart.noxaxis'] == false && prop['chart.noaxes'] == false) {
|
647
|
-
co.moveTo(this.gutterLeft +0.001, ca.height - this.gutterBottom + 0.001);
|
648
|
-
co.lineTo(ca.width - this.gutterRight + 0.001, ca.height - this.gutterBottom + 0.001);
|
649
|
-
}
|
650
|
-
|
651
|
-
// Draw the Y tickmarks
|
652
|
-
if ( prop['chart.noytickmarks'] == false
|
653
|
-
&& prop['chart.noyaxis'] == false
|
654
|
-
&& prop['chart.numyticks'] > 0
|
655
|
-
&& prop['chart.noaxes'] == false
|
656
|
-
) {
|
657
|
-
|
658
|
-
var yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / (prop['chart.numyticks'] > 0 ? prop['chart.numyticks'] : this.data.length);
|
659
|
-
|
660
|
-
for (y=this.gutterTop; y<(ca.height - this.gutterBottom - 1); y+=yTickGap) {
|
661
|
-
if (prop['chart.yaxispos'] == 'center') {
|
662
|
-
co.moveTo(halfway + 3, ma.round(y));
|
663
|
-
co.lineTo(halfway - 3, ma.round(y));
|
664
|
-
|
665
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
666
|
-
co.moveTo(ca.width - this.gutterRight, ma.round(y));
|
667
|
-
co.lineTo(ca.width - this.gutterRight + 3, ma.round(y));
|
668
|
-
|
669
|
-
} else {
|
670
|
-
co.moveTo(this.gutterLeft, ma.round(y));
|
671
|
-
co.lineTo( this.gutterLeft - 3, ma.round(y));
|
672
|
-
}
|
673
|
-
}
|
674
|
-
|
675
|
-
// If the X axis isn't being shown draw the end tick
|
676
|
-
if (prop['chart.noxaxis'] == true) {
|
677
|
-
if (prop['chart.yaxispos'] == 'center') {
|
678
|
-
co.moveTo(halfway + 3, ma.round(y));
|
679
|
-
co.lineTo(halfway - 3, ma.round(y));
|
680
|
-
|
681
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
682
|
-
co.moveTo(ca.width - this.gutterRight, ma.round(y));
|
683
|
-
co.lineTo(ca.width - this.gutterRight + 3, ma.round(y));
|
684
|
-
|
685
|
-
} else {
|
686
|
-
co.moveTo(this.gutterLeft, ma.round(y));
|
687
|
-
co.lineTo( this.gutterLeft - 3, ma.round(y));
|
688
|
-
}
|
689
|
-
}
|
690
|
-
}
|
691
|
-
|
692
|
-
|
693
|
-
// Draw the X tickmarks
|
694
|
-
if ( prop['chart.noxtickmarks'] == false
|
695
|
-
&& prop['chart.noxaxis'] == false
|
696
|
-
&& prop['chart.numxticks'] > 0
|
697
|
-
&& prop['chart.noaxes'] == false) {
|
698
|
-
|
699
|
-
xTickGap = (ca.width - this.gutterLeft - this.gutterRight ) / prop['chart.numxticks'];
|
700
|
-
yStart = ca.height - this.gutterBottom;
|
701
|
-
yEnd = (ca.height - this.gutterBottom) + 3;
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
var i = prop['chart.numxticks']
|
708
|
-
|
709
|
-
while(i--) {
|
710
|
-
|
711
|
-
var x = ca.width - this.gutterRight - (i * xTickGap);
|
712
|
-
|
713
|
-
if (prop['chart.yaxispos'] === 'right') {
|
714
|
-
x -= xTickGap;
|
715
|
-
}
|
716
|
-
|
717
|
-
co.moveTo(ma.round(x), yStart);
|
718
|
-
co.lineTo(ma.round(x), yEnd);
|
719
|
-
}
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
if (prop['chart.yaxispos'] === 'center') {
|
724
|
-
var i = 5; while (i--) {
|
725
|
-
var x = this.gutterLeft + (xTickGap * i);
|
726
|
-
|
727
|
-
co.moveTo(ma.round(x), yStart);
|
728
|
-
co.lineTo(ma.round(x), yEnd);
|
729
|
-
|
730
|
-
}
|
731
|
-
}
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
// If the Y axis isn't being shown draw the end tick
|
738
|
-
if (prop['chart.noyaxis'] == true) {
|
739
|
-
co.moveTo(this.gutterLeft, ma.round(yStart));
|
740
|
-
co.lineTo( this.gutterLeft, ma.round(yEnd));
|
741
|
-
}
|
742
|
-
}
|
743
|
-
co.stroke();
|
744
|
-
|
745
|
-
/**
|
746
|
-
* Reset the linewidth
|
747
|
-
*/
|
748
|
-
co.lineWidth = 1;
|
749
|
-
};
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
/**
|
755
|
-
* This draws the labels for the graph
|
756
|
-
*/
|
757
|
-
this.drawLabels =
|
758
|
-
this.DrawLabels = function ()
|
759
|
-
{
|
760
|
-
var units_pre = prop['chart.units.pre'],
|
761
|
-
units_post = prop['chart.units.post'],
|
762
|
-
text_size = prop['chart.text.size'],
|
763
|
-
font = prop['chart.text.font'],
|
764
|
-
offsetx = prop['chart.xlabels.offsetx'],
|
765
|
-
offsety = prop['chart.xlabels.offsety']
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
/**
|
770
|
-
* Set the units to blank if they're to be used for ingraph labels only
|
771
|
-
*/
|
772
|
-
if (prop['chart.units.ingraph']) {
|
773
|
-
units_pre = '';
|
774
|
-
units_post = '';
|
775
|
-
}
|
776
|
-
|
777
|
-
|
778
|
-
/**
|
779
|
-
* Draw the X axis labels
|
780
|
-
*/
|
781
|
-
if (prop['chart.xlabels']) {
|
782
|
-
|
783
|
-
/**
|
784
|
-
* Specific X labels
|
785
|
-
*/
|
786
|
-
if (RG.isArray(prop['chart.xlabels.specific'])) {
|
787
|
-
|
788
|
-
if (prop['chart.yaxispos'] == 'center') {
|
789
|
-
|
790
|
-
var halfGraphWidth = this.graphwidth / 2;
|
791
|
-
var labels = prop['chart.xlabels.specific'];
|
792
|
-
var interval = (this.graphwidth / 2) / (labels.length - 1);
|
793
|
-
|
794
|
-
co.fillStyle = prop['chart.text.color'];
|
795
|
-
|
796
|
-
for (var i=0; i<labels.length; i+=1) {
|
797
|
-
RG.text2(this, {
|
798
|
-
'font':font,
|
799
|
-
'size':text_size,
|
800
|
-
'x':this.gutterLeft + halfGraphWidth + (interval * i) + offsetx,
|
801
|
-
'y':ca.height - this.gutterBottom + offsetx,
|
802
|
-
'text':labels[i],
|
803
|
-
'valign':'top',
|
804
|
-
'halign':'center',
|
805
|
-
'tag': 'scale'
|
806
|
-
});
|
807
|
-
}
|
808
|
-
|
809
|
-
for (var i=(labels.length - 1); i>0; i-=1) {
|
810
|
-
RG.Text2(this, {
|
811
|
-
'font':font,
|
812
|
-
'size':text_size,
|
813
|
-
'x':this.gutterLeft + (interval * (labels.length - i - 1)) + offsetx,
|
814
|
-
'y':ca.height - this.gutterBottom + offsety,
|
815
|
-
'text':labels[i],
|
816
|
-
'valign':'top',
|
817
|
-
'halign':'center',
|
818
|
-
'tag': 'scale'
|
819
|
-
});
|
820
|
-
}
|
821
|
-
|
822
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
823
|
-
|
824
|
-
var labels = prop['chart.xlabels.specific'];
|
825
|
-
var interval = this.graphwidth / (labels.length - 1);
|
826
|
-
|
827
|
-
co.fillStyle = prop['chart.text.color'];
|
828
|
-
|
829
|
-
for (var i=0; i<labels.length; i+=1) {
|
830
|
-
RG.text2(this, {
|
831
|
-
'font': font,
|
832
|
-
'size': text_size,
|
833
|
-
'x': this.gutterLeft + (interval * i) + offsetx,
|
834
|
-
'y': ca.height - this.gutterBottom + offsety,
|
835
|
-
'text': labels[labels.length - i - 1],
|
836
|
-
'valign':'top',
|
837
|
-
'halign':'center',
|
838
|
-
'tag': 'scale'
|
839
|
-
});
|
840
|
-
}
|
841
|
-
|
842
|
-
} else {
|
843
|
-
|
844
|
-
var labels = prop['chart.xlabels.specific'];
|
845
|
-
var interval = this.graphwidth / (labels.length - 1);
|
846
|
-
|
847
|
-
co.fillStyle = prop['chart.text.color'];
|
848
|
-
|
849
|
-
for (var i=0; i<labels.length; i+=1) {
|
850
|
-
RG.text2(this, {
|
851
|
-
font: font,
|
852
|
-
size: text_size,
|
853
|
-
x: this.gutterLeft + (interval * i) + offsetx,
|
854
|
-
y: ca.height - this.gutterBottom + offsety,
|
855
|
-
text: labels[i],
|
856
|
-
valign:'top',
|
857
|
-
halign:'center',
|
858
|
-
tag: 'scale'
|
859
|
-
});
|
860
|
-
}
|
861
|
-
}
|
862
|
-
|
863
|
-
/**
|
864
|
-
* Draw an X scale
|
865
|
-
*/
|
866
|
-
} else {
|
867
|
-
|
868
|
-
var gap = 7;
|
869
|
-
|
870
|
-
co.beginPath();
|
871
|
-
co.fillStyle = prop['chart.text.color'];
|
872
|
-
|
873
|
-
|
874
|
-
if (prop['chart.yaxispos'] == 'center') {
|
875
|
-
|
876
|
-
for (var i=0; i<this.scale2.labels.length; ++i) {
|
877
|
-
RG.text2(this, {
|
878
|
-
'font':font,
|
879
|
-
'size':text_size,
|
880
|
-
'x':this.gutterLeft + (this.graphwidth / 2) - ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)) + offsetx,
|
881
|
-
'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
|
882
|
-
'text':'-' + this.scale2.labels[i],
|
883
|
-
'valign':'center',
|
884
|
-
'halign':'center',
|
885
|
-
'tag': 'scale'
|
886
|
-
});
|
887
|
-
}
|
888
|
-
|
889
|
-
for (var i=0; i<this.scale2.labels.length; ++i) {
|
890
|
-
RG.text2(this, {
|
891
|
-
'font':font,
|
892
|
-
'size':text_size,
|
893
|
-
'x':this.gutterLeft + ((this.graphwidth / 2) * ((i+1)/this.scale2.labels.length)) + (this.graphwidth / 2) + offsetx,
|
894
|
-
'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
|
895
|
-
'text':this.scale2.labels[i],
|
896
|
-
'valign':'center',
|
897
|
-
'halign':'center',
|
898
|
-
'tag': 'scale'
|
899
|
-
});
|
900
|
-
}
|
901
|
-
|
902
|
-
}else if (prop['chart.yaxispos'] == 'right') {
|
903
|
-
|
904
|
-
|
905
|
-
for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
|
906
|
-
RG.Text2(this, {
|
907
|
-
'font':font,
|
908
|
-
'size':text_size,
|
909
|
-
'x':this.gutterLeft + (i * (this.graphwidth / len)) + offsetx,
|
910
|
-
'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
|
911
|
-
'text':'-' + this.scale2.labels[len - 1 - i],
|
912
|
-
'valign':'center',
|
913
|
-
'halign':'center',
|
914
|
-
'tag': 'scale'
|
915
|
-
});
|
916
|
-
}
|
917
|
-
|
918
|
-
|
919
|
-
} else {
|
920
|
-
for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
|
921
|
-
RG.Text2(this, {
|
922
|
-
'font':font,
|
923
|
-
'size':text_size,
|
924
|
-
'x':this.gutterLeft + (this.graphwidth * ((i+1)/len)) + offsetx,
|
925
|
-
'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
|
926
|
-
'text':this.scale2.labels[i],
|
927
|
-
'valign':'center',
|
928
|
-
'halign':'center',
|
929
|
-
'tag': 'scale'
|
930
|
-
});
|
931
|
-
}
|
932
|
-
}
|
933
|
-
|
934
|
-
/**
|
935
|
-
* If xmin is not zero - draw that
|
936
|
-
*/
|
937
|
-
if (prop['chart.xmin'] > 0 || prop['chart.noyaxis'] == true || prop['chart.scale.zerostart'] || prop['chart.noaxes']) {
|
938
|
-
|
939
|
-
var x = prop['chart.yaxispos'] == 'center' ? this.gutterLeft + (this.graphwidth / 2): this.gutterLeft;
|
940
|
-
|
941
|
-
/**
|
942
|
-
* Y axis on the right
|
943
|
-
*/
|
944
|
-
if (prop['chart.yaxispos'] === 'right') {
|
945
|
-
var x = ca.width - this.gutterRight;
|
946
|
-
}
|
947
|
-
|
948
|
-
RG.text2(this, {
|
949
|
-
'font':font,
|
950
|
-
'size':text_size,
|
951
|
-
'x':x + offsetx,
|
952
|
-
'y':this.gutterTop + this.halfTextHeight + this.graphheight + gap + offsety,
|
953
|
-
'text':RG.numberFormat(this, prop['chart.xmin'].toFixed(prop['chart.xmin'] === 0 ? 0 : prop['chart.scale.decimals']), units_pre, units_post),
|
954
|
-
'valign':'center',
|
955
|
-
'halign':'center',
|
956
|
-
'tag': 'scale'
|
957
|
-
});
|
958
|
-
}
|
959
|
-
|
960
|
-
co.fill();
|
961
|
-
co.stroke();
|
962
|
-
}
|
963
|
-
}
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
/**
|
972
|
-
* The Y axis labels
|
973
|
-
*/
|
974
|
-
if (typeof prop['chart.labels'] == 'object') {
|
975
|
-
|
976
|
-
var xOffset = prop['chart.variant'] === '3d' && prop['chart.yaxispos'] === 'right' ? 15 : 5,
|
977
|
-
font = prop['chart.text.font'],
|
978
|
-
color = prop['chart.labels.color'] || prop['chart.text.color'],
|
979
|
-
bold = prop['chart.labels.bold'],
|
980
|
-
offsetx = prop['chart.labels.offsetx'],
|
981
|
-
offsety = prop['chart.labels.offsety']
|
982
|
-
|
983
|
-
|
984
|
-
// Draw the X axis labels
|
985
|
-
co.fillStyle = color;
|
986
|
-
|
987
|
-
// How high is each bar
|
988
|
-
var barHeight = (ca.height - this.gutterTop - this.gutterBottom ) / prop['chart.labels'].length;
|
989
|
-
|
990
|
-
// Reset the yTickGap
|
991
|
-
yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / prop['chart.labels'].length
|
992
|
-
|
993
|
-
/**
|
994
|
-
* If the Y axis is on the right set the alignment and the X position, otherwise on the left
|
995
|
-
*/
|
996
|
-
if (prop['chart.yaxispos'] === 'right') {
|
997
|
-
var x = ca.width - this.gutterRight + xOffset;
|
998
|
-
var halign = 'left'
|
999
|
-
} else {
|
1000
|
-
var x = this.gutterLeft - xOffset;
|
1001
|
-
var halign = 'right'
|
1002
|
-
}
|
1003
|
-
|
1004
|
-
// Draw the X tickmarks
|
1005
|
-
var i=0;
|
1006
|
-
for (y=this.gutterTop + (yTickGap / 2); y<=ca.height - this.gutterBottom; y+=yTickGap) {
|
1007
|
-
|
1008
|
-
RG.text2(this, {
|
1009
|
-
'font': font,
|
1010
|
-
'size': prop['chart.text.size'],
|
1011
|
-
'bold': bold,
|
1012
|
-
'x': x + offsetx,
|
1013
|
-
'y': y + offsety,
|
1014
|
-
'text': String(prop['chart.labels'][i++]),
|
1015
|
-
'halign': halign,
|
1016
|
-
'valign': 'center',
|
1017
|
-
'tag': 'labels'
|
1018
|
-
});
|
1019
|
-
}
|
1020
|
-
}
|
1021
|
-
};
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
/**
|
1027
|
-
* This function draws the bars. It also draw 3D axes as the axes drawing bit
|
1028
|
-
* is don AFTER the bars are drawn
|
1029
|
-
*/
|
1030
|
-
this.drawbars =
|
1031
|
-
this.Drawbars = function ()
|
1032
|
-
{
|
1033
|
-
co.lineWidth = prop['chart.linewidth'];
|
1034
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
1035
|
-
co.fillStyle = prop['chart.colors'][0];
|
1036
|
-
|
1037
|
-
var prevX = 0,
|
1038
|
-
prevY = 0;
|
1039
|
-
|
1040
|
-
|
1041
|
-
/**
|
1042
|
-
* Work out the max value
|
1043
|
-
*/
|
1044
|
-
if (prop['chart.xmax']) {
|
1045
|
-
|
1046
|
-
this.scale2 = RG.getScale2(this, {
|
1047
|
-
'max':prop['chart.xmax'],
|
1048
|
-
'min':prop['chart.xmin'],
|
1049
|
-
'scale.decimals':Number(prop['chart.scale.decimals']),
|
1050
|
-
'scale.point':prop['chart.scale.point'],
|
1051
|
-
'scale.thousand':prop['chart.scale.thousand'],
|
1052
|
-
'scale.round':prop['chart.scale.round'],
|
1053
|
-
'units.pre':prop['chart.units.pre'],
|
1054
|
-
'units.post':prop['chart.units.post'],
|
1055
|
-
'ylabels.count':prop['chart.xlabels.count'],
|
1056
|
-
'strict':true
|
1057
|
-
});
|
1058
|
-
|
1059
|
-
this.max = this.scale2.max;
|
1060
|
-
|
1061
|
-
} else {
|
1062
|
-
|
1063
|
-
var grouping = prop['chart.grouping'];
|
1064
|
-
|
1065
|
-
for (i=0; i<this.data.length; ++i) {
|
1066
|
-
if (typeof(this.data[i]) == 'object') {
|
1067
|
-
var value = grouping == 'grouped' ? Number(RG.array_max(this.data[i], true)) : Number(RG.array_sum(this.data[i])) ;
|
1068
|
-
} else {
|
1069
|
-
var value = Number(ma.abs(this.data[i]));
|
1070
|
-
}
|
1071
|
-
|
1072
|
-
this.max = ma.max(Math.abs(this.max), Math.abs(value));
|
1073
|
-
}
|
1074
|
-
|
1075
|
-
this.scale2 = RG.getScale2(this, {
|
1076
|
-
'max':this.max,
|
1077
|
-
'min':prop['chart.xmin'],
|
1078
|
-
'scale.decimals':Number(prop['chart.scale.decimals']),
|
1079
|
-
'scale.point':prop['chart.scale.point'],
|
1080
|
-
'scale.thousand':prop['chart.scale.thousand'],
|
1081
|
-
'scale.round':prop['chart.scale.round'],
|
1082
|
-
'units.pre':prop['chart.units.pre'],
|
1083
|
-
'units.post':prop['chart.units.post'],
|
1084
|
-
'ylabels.count':prop['chart.xlabels.count']
|
1085
|
-
});
|
1086
|
-
|
1087
|
-
|
1088
|
-
this.max = this.scale2.max;
|
1089
|
-
this.min = this.scale2.min;
|
1090
|
-
}
|
1091
|
-
|
1092
|
-
if (prop['chart.scale.decimals'] == null && Number(this.max) == 1) {
|
1093
|
-
this.Set('chart.scale.decimals', 1);
|
1094
|
-
}
|
1095
|
-
|
1096
|
-
/**
|
1097
|
-
* This is here to facilitate sequential colors
|
1098
|
-
*/
|
1099
|
-
var colorIdx = 0;
|
1100
|
-
|
1101
|
-
//
|
1102
|
-
// For grouped bars we need to calculate the number of bars
|
1103
|
-
//
|
1104
|
-
this.numbars = RG.arrayLinearize(this.data).length;
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
/**
|
1110
|
-
* if the chart is adjustable fix the scale so that it doesn't change.
|
1111
|
-
*
|
1112
|
-
* It's here (after the scale generation) so that the max value can be
|
1113
|
-
* set to the maximum scale value)
|
1114
|
-
*/
|
1115
|
-
if (prop['chart.adjustable'] && !prop['chart.xmax']) {
|
1116
|
-
this.set('chart.xmax', this.scale2.max);
|
1117
|
-
}
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
// Draw the 3d axes if necessary
|
1122
|
-
if (prop['chart.variant'] === '3d') {
|
1123
|
-
RG.draw3DAxes(this);
|
1124
|
-
}
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
/**
|
1132
|
-
* The bars are drawn HERE
|
1133
|
-
*/
|
1134
|
-
var graphwidth = (ca.width - this.gutterLeft - this.gutterRight);
|
1135
|
-
var halfwidth = graphwidth / 2;
|
1136
|
-
|
1137
|
-
for (i=(len=this.data.length-1); i>=0; --i) {
|
1138
|
-
|
1139
|
-
// Work out the width and height
|
1140
|
-
var width = ma.abs((this.data[i] / this.max) * graphwidth);
|
1141
|
-
var height = this.graphheight / this.data.length;
|
1142
|
-
|
1143
|
-
var orig_height = height;
|
1144
|
-
|
1145
|
-
var x = this.gutterLeft;
|
1146
|
-
var y = this.gutterTop + (i * height);
|
1147
|
-
var vmargin = prop['chart.vmargin'];
|
1148
|
-
|
1149
|
-
// Account for the Y axis being on the right hand side
|
1150
|
-
if (prop['chart.yaxispos'] === 'right') {
|
1151
|
-
x = ca.width - this.gutterRight - ma.abs(width);
|
1152
|
-
}
|
1153
|
-
|
1154
|
-
// Account for negative lengths - Some browsers (eg Chrome) don't like a negative value
|
1155
|
-
if (width < 0) {
|
1156
|
-
x -= width;
|
1157
|
-
width = ma.abs(width);
|
1158
|
-
}
|
1159
|
-
|
1160
|
-
/**
|
1161
|
-
* Turn on the shadow if need be
|
1162
|
-
*/
|
1163
|
-
if (prop['chart.shadow']) {
|
1164
|
-
co.shadowColor = prop['chart.shadow.color'];
|
1165
|
-
co.shadowBlur = prop['chart.shadow.blur'];
|
1166
|
-
co.shadowOffsetX = prop['chart.shadow.offsetx'];
|
1167
|
-
co.shadowOffsetY = prop['chart.shadow.offsety'];
|
1168
|
-
}
|
1169
|
-
|
1170
|
-
/**
|
1171
|
-
* Draw the bar
|
1172
|
-
*/
|
1173
|
-
co.beginPath();
|
1174
|
-
|
1175
|
-
// Standard (non-grouped and non-stacked) bars here
|
1176
|
-
if (typeof this.data[i] == 'number' || RG.isNull(this.data[i])) {
|
1177
|
-
|
1178
|
-
var barHeight = height - (2 * vmargin),
|
1179
|
-
barWidth = ((this.data[i] - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * this.graphwidth,
|
1180
|
-
barX = this.gutterLeft;
|
1181
|
-
|
1182
|
-
// Account for Y axis pos
|
1183
|
-
if (prop['chart.yaxispos'] == 'center') {
|
1184
|
-
barWidth /= 2;
|
1185
|
-
barX += halfwidth;
|
1186
|
-
|
1187
|
-
if (this.data[i] < 0) {
|
1188
|
-
barWidth = (ma.abs(this.data[i]) - prop['chart.xmin']) / (this.max - prop['chart.xmin']);
|
1189
|
-
barWidth = barWidth * (this.graphwidth / 2);
|
1190
|
-
barX = ((this.graphwidth / 2) + this.gutterLeft) - barWidth;
|
1191
|
-
}
|
1192
|
-
|
1193
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
1194
|
-
|
1195
|
-
barWidth = ma.abs(barWidth);
|
1196
|
-
barX = ca.width - this.gutterRight - barWidth;
|
1197
|
-
|
1198
|
-
}
|
1199
|
-
|
1200
|
-
// Set the fill color
|
1201
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
1202
|
-
co.fillStyle = prop['chart.colors'][0];
|
1203
|
-
|
1204
|
-
// Sequential colors
|
1205
|
-
++colorIdx;
|
1206
|
-
if (prop['chart.colors.sequential'] && typeof colorIdx === 'number') {
|
1207
|
-
if (prop['chart.colors'][this.numbars - colorIdx]) {
|
1208
|
-
co.fillStyle = prop['chart.colors'][this.numbars - colorIdx];
|
1209
|
-
} else {
|
1210
|
-
co.fillStyle = prop['chart.colors'][prop['chart.colors'].length - 1];
|
1211
|
-
}
|
1212
|
-
}
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
co.strokeRect(barX, this.gutterTop + (i * height) + prop['chart.vmargin'], barWidth, barHeight);
|
1230
|
-
co.fillRect(barX, this.gutterTop + (i * height) + prop['chart.vmargin'], barWidth, barHeight);
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
this.coords.push([
|
1256
|
-
barX,
|
1257
|
-
y + vmargin,
|
1258
|
-
barWidth,
|
1259
|
-
height - (2 * vmargin),
|
1260
|
-
co.fillStyle,
|
1261
|
-
this.data[i],
|
1262
|
-
true
|
1263
|
-
]);
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
// Draw the 3D effect using the coords that have just been stored
|
1271
|
-
if (prop['chart.variant'] === '3d' && typeof this.data[i] == 'number') {
|
1272
|
-
|
1273
|
-
|
1274
|
-
var prevStrokeStyle = co.strokeStyle,
|
1275
|
-
prevFillStyle = co.fillStyle;
|
1276
|
-
|
1277
|
-
/**
|
1278
|
-
* Turn off the shadow for the 3D bits
|
1279
|
-
*/
|
1280
|
-
RG.noShadow(this);
|
1281
|
-
|
1282
|
-
// DRAW THE 3D BITS HERE
|
1283
|
-
var barX = barX,
|
1284
|
-
barY = y + vmargin,
|
1285
|
-
barW = barWidth,
|
1286
|
-
barH = height - (2 * vmargin),
|
1287
|
-
offsetX = prop['chart.variant.threed.offsetx'],
|
1288
|
-
offsetY = prop['chart.variant.threed.offsety'],
|
1289
|
-
value = this.data[i];
|
1290
|
-
|
1291
|
-
|
1292
|
-
pa2(
|
1293
|
-
co,
|
1294
|
-
[
|
1295
|
-
'b',
|
1296
|
-
'm', barX, barY,
|
1297
|
-
'l', barX + offsetX - (prop['chart.yaxispos'] == 'left' && value < 0 ? offsetX : 0), barY - offsetY,
|
1298
|
-
'l', barX + barW + offsetX - (prop['chart.yaxispos'] == 'center' && value < 0 ? offsetX : 0), barY - offsetY,
|
1299
|
-
'l', barX + barW, barY,
|
1300
|
-
'c',
|
1301
|
-
's', co.strokeStyle,
|
1302
|
-
'f', co.fillStyle,
|
1303
|
-
'f','rgba(255,255,255,0.6)'//Fill again to lighten it
|
1304
|
-
]
|
1305
|
-
);
|
1306
|
-
|
1307
|
-
if ( prop['chart.yaxispos'] !== 'right'
|
1308
|
-
&& !(prop['chart.yaxispos'] === 'center' && value < 0)
|
1309
|
-
&& value >= 0
|
1310
|
-
&& !RG.isNull(value)
|
1311
|
-
) {
|
1312
|
-
|
1313
|
-
pa2(
|
1314
|
-
co,
|
1315
|
-
[
|
1316
|
-
'b',
|
1317
|
-
'fs', prevFillStyle,
|
1318
|
-
'm', barX + barW, barY,
|
1319
|
-
'l', barX + barW + offsetX, barY - offsetY,
|
1320
|
-
'l', barX + barW + offsetX, barY - offsetY + barH,
|
1321
|
-
'l', barX + barW, barY + barH,
|
1322
|
-
'c',
|
1323
|
-
's', co.strokeStyle,
|
1324
|
-
'f', prevFillStyle,
|
1325
|
-
'f', 'rgba(0,0,0,0.25)'
|
1326
|
-
]
|
1327
|
-
);
|
1328
|
-
}
|
1329
|
-
|
1330
|
-
}
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
/**
|
1338
|
-
* Stacked bar chart
|
1339
|
-
*/
|
1340
|
-
} else if (typeof(this.data[i]) == 'object' && prop['chart.grouping'] == 'stacked') {
|
1341
|
-
|
1342
|
-
if (prop['chart.yaxispos'] == 'center') {
|
1343
|
-
alert('[HBAR] You can\'t have a stacked chart with the Y axis in the center, change it to grouped');
|
1344
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
1345
|
-
var x = ca.width - this.gutterRight
|
1346
|
-
}
|
1347
|
-
|
1348
|
-
var barHeight = height - (2 * vmargin);
|
1349
|
-
|
1350
|
-
if (typeof this.coords2[i] == 'undefined') {
|
1351
|
-
this.coords2[i] = [];
|
1352
|
-
}
|
1353
|
-
|
1354
|
-
for (j=0; j<this.data[i].length; ++j) {
|
1355
|
-
|
1356
|
-
// The previous 3D segments would have turned the shadow off - so turn it back on
|
1357
|
-
if (prop['chart.shadow'] && prop['chart.variant'] === '3d') {
|
1358
|
-
co.shadowColor = prop['chart.shadow.color'];
|
1359
|
-
co.shadowBlur = prop['chart.shadow.blur'];
|
1360
|
-
co.shadowOffsetX = prop['chart.shadow.offsetx'];
|
1361
|
-
co.shadowOffsetY = prop['chart.shadow.offsety'];
|
1362
|
-
}
|
1363
|
-
|
1364
|
-
//
|
1365
|
-
// Ensure the number is positive
|
1366
|
-
//(even though having the X axis on the right implies a
|
1367
|
-
//negative value)
|
1368
|
-
//
|
1369
|
-
if (!RG.isNull(this.data[i][j])) this.data[i][j] = ma.abs(this.data[i][j]);
|
1370
|
-
|
1371
|
-
|
1372
|
-
var last = (j === (this.data[i].length - 1) );
|
1373
|
-
|
1374
|
-
// Set the fill/stroke colors
|
1375
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
1376
|
-
|
1377
|
-
// Sequential colors
|
1378
|
-
++colorIdx;
|
1379
|
-
if (prop['chart.colors.sequential'] && typeof colorIdx === 'number') {
|
1380
|
-
if (prop['chart.colors'][this.numbars - colorIdx]) {
|
1381
|
-
co.fillStyle = prop['chart.colors'][this.numbars - colorIdx];
|
1382
|
-
} else {
|
1383
|
-
co.fillStyle = prop['chart.colors'][prop['chart.colors'].length - 1];
|
1384
|
-
}
|
1385
|
-
} else if (prop['chart.colors'][j]) {
|
1386
|
-
co.fillStyle = prop['chart.colors'][j];
|
1387
|
-
}
|
1388
|
-
|
1389
|
-
|
1390
|
-
var width = (((this.data[i][j]) / (this.max))) * this.graphwidth;
|
1391
|
-
var totalWidth = (RG.arraySum(this.data[i]) / this.max) * this.graphwidth;
|
1392
|
-
|
1393
|
-
if (prop['chart.yaxispos'] === 'right') {
|
1394
|
-
x -= width;
|
1395
|
-
}
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
co.strokeRect(x, this.gutterTop + prop['chart.vmargin'] + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
|
1400
|
-
co.fillRect(x, this.gutterTop + prop['chart.vmargin'] + (this.graphheight / this.data.length) * i, width, height - (2 * vmargin) );
|
1401
|
-
|
1402
|
-
|
1403
|
-
/**
|
1404
|
-
* Store the coords for tooltips
|
1405
|
-
*/
|
1406
|
-
|
1407
|
-
// The last property of this array is a boolean which tells you whether the value is the last or not
|
1408
|
-
this.coords.push([
|
1409
|
-
x,
|
1410
|
-
y + vmargin,
|
1411
|
-
width,
|
1412
|
-
height - (2 * vmargin),
|
1413
|
-
co.fillStyle,
|
1414
|
-
RG.array_sum(this.data[i]),
|
1415
|
-
j == (this.data[i].length - 1)
|
1416
|
-
]);
|
1417
|
-
|
1418
|
-
this.coords2[i].push([
|
1419
|
-
x,
|
1420
|
-
y + vmargin,
|
1421
|
-
width,
|
1422
|
-
height - (2 * vmargin),
|
1423
|
-
co.fillStyle,
|
1424
|
-
RG.array_sum(this.data[i]),
|
1425
|
-
j == (this.data[i].length - 1)
|
1426
|
-
]);
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
// 3D effect
|
1434
|
-
if (prop['chart.variant'] === '3d') {
|
1435
|
-
|
1436
|
-
/**
|
1437
|
-
* Turn off the shadow for the 3D bits
|
1438
|
-
*/
|
1439
|
-
RG.noShadow(this);
|
1440
|
-
|
1441
|
-
var prevStrokeStyle = co.strokeStyle,
|
1442
|
-
prevFillStyle = co.fillStyle;
|
1443
|
-
|
1444
|
-
// DRAW THE 3D BITS HERE
|
1445
|
-
var barX = x,
|
1446
|
-
barY = y + vmargin,
|
1447
|
-
barW = width,
|
1448
|
-
barH = height - (2 * vmargin),
|
1449
|
-
offsetX = prop['chart.variant.threed.offsetx'],
|
1450
|
-
offsetY = prop['chart.variant.threed.offsety'],
|
1451
|
-
value = this.data[i][j];
|
1452
|
-
|
1453
|
-
if (!RG.isNull(value)) {
|
1454
|
-
pa2(
|
1455
|
-
co,
|
1456
|
-
[
|
1457
|
-
'b',
|
1458
|
-
'm', barX, barY,
|
1459
|
-
'l', barX + offsetX, barY - offsetY,
|
1460
|
-
'l', barX + barW + offsetX, barY - offsetY,
|
1461
|
-
'l', barX + barW, barY,
|
1462
|
-
'c',
|
1463
|
-
's', co.strokeStyle,
|
1464
|
-
'f', co.fillStyle,
|
1465
|
-
'f','rgba(255,255,255,0.6)'//Fill again to lighten it
|
1466
|
-
]
|
1467
|
-
);
|
1468
|
-
}
|
1469
|
-
|
1470
|
-
if ( prop['chart.yaxispos'] !== 'right'
|
1471
|
-
&& !(prop['chart.yaxispos'] === 'center' && value < 0)
|
1472
|
-
&& !RG.isNull(value)
|
1473
|
-
) {
|
1474
|
-
|
1475
|
-
pa2(
|
1476
|
-
co,
|
1477
|
-
[
|
1478
|
-
'fs', prevFillStyle,
|
1479
|
-
'b',
|
1480
|
-
'm', barX + barW, barY,
|
1481
|
-
'l', barX + barW + offsetX, barY - offsetY,
|
1482
|
-
'l', barX + barW + offsetX, barY - offsetY + barH,
|
1483
|
-
'l', barX + barW, barY + barH,
|
1484
|
-
'c',
|
1485
|
-
's', co.strokeStyle,
|
1486
|
-
'f', prevFillStyle,
|
1487
|
-
'f', 'rgba(0,0,0,0.25)'
|
1488
|
-
]
|
1489
|
-
);
|
1490
|
-
}
|
1491
|
-
|
1492
|
-
co.beginPath();
|
1493
|
-
co.strokeStyle = prevStrokeStyle;
|
1494
|
-
co.fillStyle = prevFillStyle;
|
1495
|
-
}
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
if (prop['chart.yaxispos'] !== 'right') {
|
1503
|
-
x += width;
|
1504
|
-
}
|
1505
|
-
}
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
/**
|
1515
|
-
* A grouped bar chart
|
1516
|
-
*/
|
1517
|
-
} else if (typeof(this.data[i]) == 'object' && prop['chart.grouping'] == 'grouped') {
|
1518
|
-
|
1519
|
-
var vmarginGrouped = prop['chart.vmargin.grouped'];
|
1520
|
-
var individualBarHeight = ((height - (2 * vmargin) - ((this.data[i].length - 1) * vmarginGrouped)) / this.data[i].length)
|
1521
|
-
|
1522
|
-
if (typeof this.coords2[i] == 'undefined') {
|
1523
|
-
this.coords2[i] = [];
|
1524
|
-
}
|
1525
|
-
|
1526
|
-
for (j=(this.data[i].length - 1); j>=0; --j) {
|
1527
|
-
|
1528
|
-
/**
|
1529
|
-
* Turn on the shadow if need be
|
1530
|
-
*/
|
1531
|
-
if (prop['chart.shadow']) {
|
1532
|
-
RG.setShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
|
1533
|
-
}
|
1534
|
-
|
1535
|
-
// Set the fill/stroke colors
|
1536
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
1537
|
-
|
1538
|
-
// Sequential colors
|
1539
|
-
++colorIdx;
|
1540
|
-
if (prop['chart.colors.sequential'] && typeof colorIdx === 'number') {
|
1541
|
-
if (prop['chart.colors'][this.numbars - colorIdx]) {
|
1542
|
-
co.fillStyle = prop['chart.colors'][this.numbars - colorIdx];
|
1543
|
-
} else {
|
1544
|
-
co.fillStyle = prop['chart.colors'][prop['chart.colors'].length - 1];
|
1545
|
-
}
|
1546
|
-
} else if (prop['chart.colors'][j]) {
|
1547
|
-
co.fillStyle = prop['chart.colors'][j];
|
1548
|
-
}
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
var startY = this.gutterTop + (height * i) + (individualBarHeight * j) + vmargin + (vmarginGrouped * j);
|
1553
|
-
var width = ((this.data[i][j] - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * (ca.width - this.gutterLeft - this.gutterRight );
|
1554
|
-
var startX = this.gutterLeft;
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
// Account for the Y axis being in the middle
|
1559
|
-
if (prop['chart.yaxispos'] == 'center') {
|
1560
|
-
width /= 2;
|
1561
|
-
startX += halfwidth;
|
1562
|
-
|
1563
|
-
// Account for the Y axis being on the right
|
1564
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
1565
|
-
width = ma.abs(width);
|
1566
|
-
startX = ca.width - this.gutterRight - ma.abs(width);;
|
1567
|
-
}
|
1568
|
-
|
1569
|
-
if (width < 0) {
|
1570
|
-
startX += width;
|
1571
|
-
width *= -1;
|
1572
|
-
}
|
1573
|
-
|
1574
|
-
co.strokeRect(startX, startY, width, individualBarHeight);
|
1575
|
-
co.fillRect(startX, startY, width, individualBarHeight);
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
this.coords.push([
|
1583
|
-
startX,
|
1584
|
-
startY,
|
1585
|
-
width,
|
1586
|
-
individualBarHeight,
|
1587
|
-
co.fillStyle,
|
1588
|
-
this.data[i][j],
|
1589
|
-
true
|
1590
|
-
]);
|
1591
|
-
|
1592
|
-
this.coords2[i].push([
|
1593
|
-
startX,
|
1594
|
-
startY,
|
1595
|
-
width,
|
1596
|
-
individualBarHeight,
|
1597
|
-
co.fillStyle,
|
1598
|
-
this.data[i][j],
|
1599
|
-
true
|
1600
|
-
]);
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
// 3D effect
|
1614
|
-
if (prop['chart.variant'] === '3d') {
|
1615
|
-
|
1616
|
-
/**
|
1617
|
-
* Turn off the shadow for the 3D bits
|
1618
|
-
*/
|
1619
|
-
RG.noShadow(this);
|
1620
|
-
|
1621
|
-
var prevStrokeStyle = co.strokeStyle,
|
1622
|
-
prevFillStyle = co.fillStyle;
|
1623
|
-
|
1624
|
-
// DRAW THE 3D BITS HERE
|
1625
|
-
var barX = startX,
|
1626
|
-
barY = startY,
|
1627
|
-
barW = width,
|
1628
|
-
barH = individualBarHeight,
|
1629
|
-
offsetX = prop['chart.variant.threed.offsetx'],
|
1630
|
-
offsetY = prop['chart.variant.threed.offsety'],
|
1631
|
-
value = this.data[i][j];
|
1632
|
-
|
1633
|
-
pa2(
|
1634
|
-
co,
|
1635
|
-
[
|
1636
|
-
'b',
|
1637
|
-
'm', barX, barY,
|
1638
|
-
'l', barX + offsetX, barY - offsetY,
|
1639
|
-
'l', barX + barW + offsetX - (value < 0 ? offsetX : 0), barY - offsetY,
|
1640
|
-
'l', barX + barW, barY,
|
1641
|
-
'c',
|
1642
|
-
's', co.strokeStyle,
|
1643
|
-
'f', co.fillStyle,
|
1644
|
-
'f','rgba(255,255,255,0.6)'//Fill again to lighten it
|
1645
|
-
]
|
1646
|
-
);
|
1647
|
-
|
1648
|
-
if ( prop['chart.yaxispos'] !== 'right'
|
1649
|
-
&& !(prop['chart.yaxispos'] === 'center' && value < 0)
|
1650
|
-
&& value >= 0
|
1651
|
-
&& !RG.isNull(value)
|
1652
|
-
) {
|
1653
|
-
|
1654
|
-
pa2(
|
1655
|
-
co,
|
1656
|
-
[
|
1657
|
-
'fs', prevFillStyle,
|
1658
|
-
'b',
|
1659
|
-
'm', barX + barW, barY,
|
1660
|
-
'l', barX + barW + offsetX, barY - offsetY,
|
1661
|
-
'l', barX + barW + offsetX, barY - offsetY + barH,
|
1662
|
-
'l', barX + barW, barY + barH,
|
1663
|
-
'c',
|
1664
|
-
's', co.strokeStyle,
|
1665
|
-
'f', prevFillStyle,
|
1666
|
-
'f', 'rgba(0,0,0,0.25)'
|
1667
|
-
]
|
1668
|
-
);
|
1669
|
-
}
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
co.beginPath();
|
1676
|
-
co.strokeStyle = prevStrokeStyle;
|
1677
|
-
co.fillStyle = prevFillStyle;
|
1678
|
-
}
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
}
|
1686
|
-
|
1687
|
-
startY += vmargin;
|
1688
|
-
}
|
1689
|
-
|
1690
|
-
co.closePath();
|
1691
|
-
}
|
1692
|
-
|
1693
|
-
co.stroke();
|
1694
|
-
co.fill();
|
1695
|
-
|
1696
|
-
// Under certain circumstances we can cover the shadow
|
1697
|
-
// overspill with a white rectangle
|
1698
|
-
if (prop['chart,yaxispos'] === 'right') {
|
1699
|
-
pa2(co, 'cr % % % %',
|
1700
|
-
ca.width - this.gutterRight + prop['chart.variant.threed.offsetx'],
|
1701
|
-
'0',
|
1702
|
-
this.gutterRight,
|
1703
|
-
ca.height
|
1704
|
-
);
|
1705
|
-
}
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
// Draw the 3d axes AGAIN if the Y axis is on the right
|
1713
|
-
if ( prop['chart.yaxispos'] === 'right'
|
1714
|
-
&& prop['chart.variant'] === '3d'
|
1715
|
-
) {
|
1716
|
-
RG.draw3DYAxis(this);
|
1717
|
-
}
|
1718
|
-
|
1719
|
-
/**
|
1720
|
-
* Now the bars are stroke()ed, turn off the shadow
|
1721
|
-
*/
|
1722
|
-
RG.noShadow(this);
|
1723
|
-
|
1724
|
-
|
1725
|
-
//
|
1726
|
-
// Reverse the coords arrays as the bars are drawn from the borrom up now
|
1727
|
-
//
|
1728
|
-
this.coords = RG.arrayReverse(this.coords);
|
1729
|
-
|
1730
|
-
if (prop['chart.grouping'] === 'grouped') {
|
1731
|
-
for (var i=0; i<this.coords2.length; ++i) {
|
1732
|
-
this.coords2[i] = RG.arrayReverse(this.coords2[i]);
|
1733
|
-
}
|
1734
|
-
}
|
1735
|
-
|
1736
|
-
|
1737
|
-
this.redrawBars();
|
1738
|
-
};
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
/**
|
1744
|
-
* This function goes over the bars after they been drawn, so that upwards shadows are underneath the bars
|
1745
|
-
*/
|
1746
|
-
this.redrawBars =
|
1747
|
-
this.RedrawBars = function ()
|
1748
|
-
{
|
1749
|
-
if (prop['chart.noredraw']) {
|
1750
|
-
return;
|
1751
|
-
}
|
1752
|
-
|
1753
|
-
var coords = this.coords;
|
1754
|
-
|
1755
|
-
var font = prop['chart.text.font'],
|
1756
|
-
size = prop['chart.text.size'],
|
1757
|
-
color = prop['chart.text.color'];
|
1758
|
-
|
1759
|
-
RG.noShadow(this);
|
1760
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
1761
|
-
|
1762
|
-
for (var i=0; i<coords.length; ++i) {
|
1763
|
-
|
1764
|
-
if (prop['chart.shadow']) {
|
1765
|
-
|
1766
|
-
pa2(co, 'b lw % r % % % % s % f %',
|
1767
|
-
prop['chart.linewidth'],
|
1768
|
-
coords[i][0],
|
1769
|
-
coords[i][1],
|
1770
|
-
coords[i][2],
|
1771
|
-
coords[i][3],
|
1772
|
-
prop['chart.strokestyle'],
|
1773
|
-
coords[i][4]
|
1774
|
-
);
|
1775
|
-
}
|
1776
|
-
|
1777
|
-
/**
|
1778
|
-
* Draw labels "above" the bar
|
1779
|
-
*/
|
1780
|
-
var halign = 'left';
|
1781
|
-
if (prop['chart.labels.above'] && coords[i][6]) {
|
1782
|
-
|
1783
|
-
var border = (coords[i][0] + coords[i][2] + 7 + co.measureText(prop['chart.labels.above.units.pre'] + this.coords[i][5] + prop['chart.labels.above.units.post']).width) > ca.width ? true : false,
|
1784
|
-
text = RG.numberFormat(this, (this.coords[i][5]).toFixed(prop['chart.labels.above.decimals']), prop['chart.labels.above.units.pre'], prop['chart.labels.above.units.post']);
|
1785
|
-
|
1786
|
-
RG.noShadow(this);
|
1787
|
-
|
1788
|
-
/**
|
1789
|
-
* Default to the value - then check for specific labels
|
1790
|
-
*/
|
1791
|
-
|
1792
|
-
|
1793
|
-
if (typeof prop['chart.labels.above.specific'] === 'object' && prop['chart.labels.above.specific'] && prop['chart.labels.above.specific'][i]) {
|
1794
|
-
text = prop['chart.labels.above.specific'][i];
|
1795
|
-
}
|
1796
|
-
|
1797
|
-
var x = coords[i][0] + coords[i][2] + 5;
|
1798
|
-
var y = coords[i][1] + (coords[i][3] / 2);
|
1799
|
-
|
1800
|
-
if (prop['chart.yaxispos'] === 'right') {
|
1801
|
-
x = coords[i][0] - 5;
|
1802
|
-
halign = 'right';
|
1803
|
-
} else if (prop['chart.yaxispos'] === 'center' && this.data_arr[i] < 0) {
|
1804
|
-
x = coords[i][0] - 5;
|
1805
|
-
halign = 'right';
|
1806
|
-
}
|
1807
|
-
|
1808
|
-
RG.text2(this, {
|
1809
|
-
font: typeof prop['chart.labels.above.font'] === 'string' ? prop['chart.labels.above.font'] : font,
|
1810
|
-
size: typeof prop['chart.labels.above.size'] === 'number' ? prop['chart.labels.above.size'] : size,
|
1811
|
-
color: typeof prop['chart.labels.above.color'] ==='string' ? prop['chart.labels.above.color'] : color,
|
1812
|
-
x: x,
|
1813
|
-
y: y,
|
1814
|
-
bold: prop['chart.labels.above.bold'],
|
1815
|
-
italic: prop['chart.labels.above.italic'],
|
1816
|
-
text: text,
|
1817
|
-
valign: 'center',
|
1818
|
-
halign: halign,
|
1819
|
-
tag: 'labels.above'
|
1820
|
-
});
|
1821
|
-
}
|
1822
|
-
}
|
1823
|
-
};
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
/**
|
1829
|
-
* This function can be used to get the appropriate bar information (if any)
|
1830
|
-
*
|
1831
|
-
* @param e Event object
|
1832
|
-
* @return Appriate bar information (if any)
|
1833
|
-
*/
|
1834
|
-
this.getShape =
|
1835
|
-
this.getBar = function (e)
|
1836
|
-
{
|
1837
|
-
var mouseXY = RG.getMouseXY(e);
|
1838
|
-
|
1839
|
-
/**
|
1840
|
-
* Loop through the bars determining if the mouse is over a bar
|
1841
|
-
*/
|
1842
|
-
for (var i=0,len=this.coords.length; i<len; i++) {
|
1843
|
-
|
1844
|
-
var mouseX = mouseXY[0], // In relation to the canvas
|
1845
|
-
mouseY = mouseXY[1], // In relation to the canvas
|
1846
|
-
left = this.coords[i][0],
|
1847
|
-
top = this.coords[i][1],
|
1848
|
-
width = this.coords[i][2],
|
1849
|
-
height = this.coords[i][3],
|
1850
|
-
idx = i;
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
// Recreate the path/rectangle so that it can be tested
|
1855
|
-
// ** DO NOT STROKE OR FILL IT **
|
1856
|
-
pa2(co,['b','r',left,top,width,height]);
|
1857
|
-
|
1858
|
-
if (co.isPointInPath(mouseX, mouseY)) {
|
1859
|
-
|
1860
|
-
var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
|
1861
|
-
|
1862
|
-
return {
|
1863
|
-
0: this, 'object': this,
|
1864
|
-
1: left, 'x': left,
|
1865
|
-
2: top, 'y': top,
|
1866
|
-
3: width, 'width': width,
|
1867
|
-
4: height, 'height': height,
|
1868
|
-
5: idx, 'index': idx,
|
1869
|
-
'tooltip': tooltip
|
1870
|
-
};
|
1871
|
-
}
|
1872
|
-
}
|
1873
|
-
};
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
/**
|
1879
|
-
* When you click on the chart, this method can return the X value at that point. It works for any point on the
|
1880
|
-
* chart (that is inside the gutters) - not just points within the Bars.
|
1881
|
-
*
|
1882
|
-
* @param object e The event object
|
1883
|
-
*/
|
1884
|
-
this.getValue = function (arg)
|
1885
|
-
{
|
1886
|
-
if (arg.length == 2) {
|
1887
|
-
var mouseX = arg[0];
|
1888
|
-
var mouseY = arg[1];
|
1889
|
-
} else {
|
1890
|
-
var mouseCoords = RG.getMouseXY(arg);
|
1891
|
-
var mouseX = mouseCoords[0];
|
1892
|
-
var mouseY = mouseCoords[1];
|
1893
|
-
}
|
1894
|
-
|
1895
|
-
if ( mouseY < this.gutterTop
|
1896
|
-
|| mouseY > (ca.height - this.gutterBottom)
|
1897
|
-
|| mouseX < this.gutterLeft
|
1898
|
-
|| mouseX > (ca.width - this.gutterRight)
|
1899
|
-
) {
|
1900
|
-
return null;
|
1901
|
-
}
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
if (prop['chart.yaxispos'] == 'center') {
|
1908
|
-
var value = ((mouseX - this.gutterLeft) / (this.graphwidth / 2)) * (this.max - prop['chart.xmin']);
|
1909
|
-
value = value - this.max
|
1910
|
-
|
1911
|
-
// Special case if xmin is defined
|
1912
|
-
if (prop['chart.xmin'] > 0) {
|
1913
|
-
value = ((mouseX - this.gutterLeft - (this.graphwidth / 2)) / (this.graphwidth / 2)) * (this.max - prop['chart.xmin']);
|
1914
|
-
value += prop['chart.xmin'];
|
1915
|
-
|
1916
|
-
if (mouseX < (this.gutterLeft + (this.graphwidth / 2))) {
|
1917
|
-
value -= (2 * prop['chart.xmin']);
|
1918
|
-
}
|
1919
|
-
}
|
1920
|
-
|
1921
|
-
|
1922
|
-
// TODO This needs fixing
|
1923
|
-
} else if (prop['chart.yaxispos'] == 'right') {
|
1924
|
-
var value = ((mouseX - this.gutterLeft) / this.graphwidth) * (this.scale2.max - prop['chart.xmin']);
|
1925
|
-
value = this.scale2.max - value;
|
1926
|
-
|
1927
|
-
} else {
|
1928
|
-
var value = ((mouseX - this.gutterLeft) / this.graphwidth) * (this.scale2.max - prop['chart.xmin']);
|
1929
|
-
value += prop['chart.xmin'];
|
1930
|
-
}
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
return value;
|
1938
|
-
};
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
/**
|
1944
|
-
* Each object type has its own Highlight() function which highlights the appropriate shape
|
1945
|
-
*
|
1946
|
-
* @param object shape The shape to highlight
|
1947
|
-
*/
|
1948
|
-
this.highlight =
|
1949
|
-
this.Highlight = function (shape)
|
1950
|
-
{
|
1951
|
-
if (typeof prop['chart.highlight.style'] === 'function') {
|
1952
|
-
(prop['chart.highlight.style'])(shape);
|
1953
|
-
} else {
|
1954
|
-
RG.Highlight.Rect(this, shape);
|
1955
|
-
}
|
1956
|
-
};
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
/**
|
1962
|
-
* The getObjectByXY() worker method. Don't call this call:
|
1963
|
-
*
|
1964
|
-
* RG.ObjectRegistry.getObjectByXY(e)
|
1965
|
-
*
|
1966
|
-
* @param object e The event object
|
1967
|
-
*/
|
1968
|
-
this.getObjectByXY = function (e)
|
1969
|
-
{
|
1970
|
-
var mouseXY = RG.getMouseXY(e);
|
1971
|
-
|
1972
|
-
// Adjust the mouse Y coordinate for when the bar chart is
|
1973
|
-
// a 3D variant
|
1974
|
-
if (prop['chart.variant'] === '3d') {
|
1975
|
-
var adjustment = prop['chart.variant.threed.angle'] * mouseXY[0];
|
1976
|
-
mouseXY[1] -= adjustment;
|
1977
|
-
}
|
1978
|
-
|
1979
|
-
|
1980
|
-
if (
|
1981
|
-
mouseXY[0] >= this.gutterLeft
|
1982
|
-
&& mouseXY[0] <= (ca.width - this.gutterRight)
|
1983
|
-
&& mouseXY[1] >= this.gutterTop
|
1984
|
-
&& mouseXY[1] <= (ca.height - this.gutterBottom)
|
1985
|
-
) {
|
1986
|
-
|
1987
|
-
return this;
|
1988
|
-
}
|
1989
|
-
};
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
/**
|
1995
|
-
* This function positions a tooltip when it is displayed
|
1996
|
-
*
|
1997
|
-
* @param obj object The chart object
|
1998
|
-
* @param int x The X coordinate specified for the tooltip
|
1999
|
-
* @param int y The Y coordinate specified for the tooltip
|
2000
|
-
* @param objec tooltip The tooltips DIV element
|
2001
|
-
*
|
2002
|
-
this.positionTooltip = function (obj, x, y, tooltip, idx)
|
2003
|
-
{
|
2004
|
-
var coordX = obj.coords[tooltip.__index__][0],
|
2005
|
-
coordY = obj.coords[tooltip.__index__][1],
|
2006
|
-
coordW = obj.coords[tooltip.__index__][2],
|
2007
|
-
coordH = obj.coords[tooltip.__index__][3],
|
2008
|
-
canvasXY = RG.getCanvasXY(obj.canvas),
|
2009
|
-
gutterLeft = obj.gutterLeft,
|
2010
|
-
gutterTop = obj.gutterTop,
|
2011
|
-
width = tooltip.offsetWidth,
|
2012
|
-
height = tooltip.offsetHeight,
|
2013
|
-
mouseXY = RG.getMouseXY(window.event);
|
2014
|
-
|
2015
|
-
// If the chart is a 3D version the tooltip Y position needs this
|
2016
|
-
// adjustment
|
2017
|
-
if (prop['chart.variant'] === '3d' && coordW) {
|
2018
|
-
var adjustment = (prop['chart.variant.threed.angle'] * ((coordX + coordW) / 2));
|
2019
|
-
}
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
// Set the top position
|
2024
|
-
tooltip.style.left = 0;
|
2025
|
-
tooltip.style.top = window.event.pageY - height - 5 + 'px';
|
2026
|
-
|
2027
|
-
// By default any overflow is hidden
|
2028
|
-
tooltip.style.overflow = '';
|
2029
|
-
|
2030
|
-
// Reposition the tooltip if at the edges:
|
2031
|
-
|
2032
|
-
// LEFT edge
|
2033
|
-
if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
|
2034
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
|
2035
|
-
|
2036
|
-
// RIGHT edge
|
2037
|
-
} else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
|
2038
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
|
2039
|
-
|
2040
|
-
// Default positioning - CENTERED
|
2041
|
-
} else {
|
2042
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
|
2043
|
-
}
|
2044
|
-
};*/
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2049
|
-
/**
|
2050
|
-
* Returns the appropriate Y coord for the given value
|
2051
|
-
*
|
2052
|
-
* @param number value The value to get the coord for
|
2053
|
-
*/
|
2054
|
-
this.getXCoord = function (value)
|
2055
|
-
{
|
2056
|
-
|
2057
|
-
if (prop['chart.yaxispos'] == 'center') {
|
2058
|
-
|
2059
|
-
// Range checking
|
2060
|
-
if (value > this.max || value < (-1 * this.max)) {
|
2061
|
-
return null;
|
2062
|
-
}
|
2063
|
-
|
2064
|
-
var width = (ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right']) / 2;
|
2065
|
-
var coord = (((value - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * width) + width;
|
2066
|
-
|
2067
|
-
coord = prop['chart.gutter.left'] + coord;
|
2068
|
-
} else {
|
2069
|
-
|
2070
|
-
// Range checking
|
2071
|
-
if (value > this.max || value < 0) {
|
2072
|
-
return null;
|
2073
|
-
}
|
2074
|
-
|
2075
|
-
var width = ca.width - prop['chart.gutter.left'] - prop['chart.gutter.right'];
|
2076
|
-
var coord = ((value - prop['chart.xmin']) / (this.max - prop['chart.xmin'])) * width;
|
2077
|
-
|
2078
|
-
coord = prop['chart.gutter.left'] + coord;
|
2079
|
-
}
|
2080
|
-
|
2081
|
-
return coord;
|
2082
|
-
};
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
/**
|
2088
|
-
*
|
2089
|
-
*/
|
2090
|
-
this.parseColors = function ()
|
2091
|
-
{
|
2092
|
-
// Save the original colors so that they can be restored when the canvas is reset
|
2093
|
-
if (this.original_colors.length === 0) {
|
2094
|
-
//this.original_colors['chart.'] = RG.array_clone(prop['chart.']);
|
2095
|
-
this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
|
2096
|
-
this.original_colors['chart.background.grid.color'] = RG.array_clone(prop['chart.background.grid.color']);
|
2097
|
-
this.original_colors['chart.background.color'] = RG.array_clone(prop['chart.background.color']);
|
2098
|
-
this.original_colors['chart.background.barcolor1'] = RG.array_clone(prop['chart.background.barcolor1']);
|
2099
|
-
this.original_colors['chart.background.barcolor2'] = RG.array_clone(prop['chart.background.barcolor2']);
|
2100
|
-
this.original_colors['chart.text.color'] = RG.array_clone(prop['chart.text.color']);
|
2101
|
-
this.original_colors['chart.labels.colors'] = RG.array_clone(prop['chart.labels.colors']);
|
2102
|
-
this.original_colors['chart.strokestyle'] = RG.array_clone(prop['chart.strokestyle']);
|
2103
|
-
this.original_colors['chart.axis.color'] = RG.array_clone(prop['chart.axis.color']);
|
2104
|
-
this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
|
2105
|
-
this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
|
2106
|
-
|
2107
|
-
}
|
2108
|
-
|
2109
|
-
var colors = prop['chart.colors'];
|
2110
|
-
|
2111
|
-
for (var i=0; i<colors.length; ++i) {
|
2112
|
-
colors[i] = this.parseSingleColorForGradient(colors[i]);
|
2113
|
-
}
|
2114
|
-
|
2115
|
-
prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
|
2116
|
-
prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
|
2117
|
-
prop['chart.background.barcolor1'] = this.parseSingleColorForGradient(prop['chart.background.barcolor1']);
|
2118
|
-
prop['chart.background.barcolor2'] = this.parseSingleColorForGradient(prop['chart.background.barcolor2']);
|
2119
|
-
prop['chart.text.color'] = this.parseSingleColorForGradient(prop['chart.text.color']);
|
2120
|
-
prop['chart.labels.colors'] = this.parseSingleColorForGradient(prop['chart.labels.colors']);
|
2121
|
-
prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
|
2122
|
-
prop['chart.axis.color'] = this.parseSingleColorForGradient(prop['chart.axis.color']);
|
2123
|
-
prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
|
2124
|
-
prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
|
2125
|
-
};
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
/**
|
2131
|
-
* Use this function to reset the object to the post-constructor state. Eg reset colors if
|
2132
|
-
* need be etc
|
2133
|
-
*/
|
2134
|
-
this.reset = function ()
|
2135
|
-
{
|
2136
|
-
};
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
/**
|
2141
|
-
* This parses a single color value
|
2142
|
-
*/
|
2143
|
-
this.parseSingleColorForGradient = function (color)
|
2144
|
-
{
|
2145
|
-
if (!color || typeof(color) != 'string') {
|
2146
|
-
return color;
|
2147
|
-
}
|
2148
|
-
|
2149
|
-
if (color.match(/^gradient\((.*)\)$/i)) {
|
2150
|
-
|
2151
|
-
var parts = RegExp.$1.split(':');
|
2152
|
-
|
2153
|
-
if (prop['chart.yaxispos'] === 'right') {
|
2154
|
-
parts = RG.arrayReverse(parts);
|
2155
|
-
}
|
2156
|
-
|
2157
|
-
// Create the gradient
|
2158
|
-
var grad = co.createLinearGradient(prop['chart.gutter.left'],0,ca.width - prop['chart.gutter.right'],0);
|
2159
|
-
|
2160
|
-
var diff = 1 / (parts.length - 1);
|
2161
|
-
|
2162
|
-
grad.addColorStop(0, RG.trim(parts[0]));
|
2163
|
-
|
2164
|
-
for (var j=1; j<parts.length; ++j) {
|
2165
|
-
grad.addColorStop(j * diff, RG.trim(parts[j]));
|
2166
|
-
}
|
2167
|
-
}
|
2168
|
-
|
2169
|
-
return grad ? grad : color;
|
2170
|
-
};
|
2171
|
-
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2175
|
-
/**
|
2176
|
-
* This function handles highlighting an entire data-series for the interactive
|
2177
|
-
* key
|
2178
|
-
*
|
2179
|
-
* @param int index The index of the data series to be highlighted
|
2180
|
-
*/
|
2181
|
-
this.interactiveKeyHighlight = function (index)
|
2182
|
-
{
|
2183
|
-
var obj = this;
|
2184
|
-
|
2185
|
-
this.coords2.forEach(function (value, idx, arr)
|
2186
|
-
{
|
2187
|
-
var shape = obj.coords2[idx][index]
|
2188
|
-
var pre_linewidth = co.lineWidth;
|
2189
|
-
co.lineWidth = 2;
|
2190
|
-
co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
|
2191
|
-
co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
|
2192
|
-
co.fillRect(shape[0], shape[1], shape[2], shape[3]);
|
2193
|
-
co.strokeRect(shape[0], shape[1], shape[2], shape[3]);
|
2194
|
-
|
2195
|
-
// Reset the lineWidth
|
2196
|
-
co.lineWidth = pre_linewidth;
|
2197
|
-
});
|
2198
|
-
};
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2203
|
-
/**
|
2204
|
-
* Using a function to add events makes it easier to facilitate method chaining
|
2205
|
-
*
|
2206
|
-
* @param string type The type of even to add
|
2207
|
-
* @param function func
|
2208
|
-
*/
|
2209
|
-
this.on = function (type, func)
|
2210
|
-
{
|
2211
|
-
if (type.substr(0,2) !== 'on') {
|
2212
|
-
type = 'on' + type;
|
2213
|
-
}
|
2214
|
-
|
2215
|
-
if (typeof this[type] !== 'function') {
|
2216
|
-
this[type] = func;
|
2217
|
-
} else {
|
2218
|
-
RG.addCustomEventListener(this, type, func);
|
2219
|
-
}
|
2220
|
-
|
2221
|
-
return this;
|
2222
|
-
};
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
/**
|
2228
|
-
* This function runs once only
|
2229
|
-
* (put at the end of the file (before any effects))
|
2230
|
-
*/
|
2231
|
-
this.firstDrawFunc = function ()
|
2232
|
-
{
|
2233
|
-
};
|
2234
|
-
|
2235
|
-
|
2236
|
-
|
2237
|
-
|
2238
|
-
/**
|
2239
|
-
* This retrives the bar based on the X coordinate only.
|
2240
|
-
*
|
2241
|
-
* @param object e The event object
|
2242
|
-
* @param object OPTIONAL You can pass in the bar object instead of the
|
2243
|
-
* function using "this"
|
2244
|
-
*/
|
2245
|
-
this.getShapeByY = function (e)
|
2246
|
-
{
|
2247
|
-
var mouseXY = RG.getMouseXY(e);
|
2248
|
-
|
2249
|
-
|
2250
|
-
// This facilitates you being able to pass in the bar object as a parameter instead of
|
2251
|
-
// the function getting it from itself
|
2252
|
-
var obj = arguments[1] ? arguments[1] : this;
|
2253
|
-
|
2254
|
-
|
2255
|
-
/**
|
2256
|
-
* Loop through the bars determining if the mouse is over a bar
|
2257
|
-
*/
|
2258
|
-
for (var i=0,len=obj.coords.length; i<len; i++) {
|
2259
|
-
|
2260
|
-
if (obj.coords[i].length == 0) {
|
2261
|
-
continue;
|
2262
|
-
}
|
2263
|
-
|
2264
|
-
var mouseX = mouseXY[0],
|
2265
|
-
mouseY = mouseXY[1],
|
2266
|
-
left = obj.coords[i][0],
|
2267
|
-
top = obj.coords[i][1],
|
2268
|
-
width = obj.coords[i][2],
|
2269
|
-
height = obj.coords[i][3];
|
2270
|
-
|
2271
|
-
if (mouseY >= top && mouseY <= (top + height)) {
|
2272
|
-
|
2273
|
-
if (prop['chart.tooltips']) {
|
2274
|
-
var tooltip = RG.parseTooltipText ? RG.parseTooltipText(prop['chart.tooltips'], i) : prop['chart.tooltips'][i];
|
2275
|
-
}
|
2276
|
-
|
2277
|
-
return {
|
2278
|
-
0: obj, object: obj,
|
2279
|
-
1: left, x: left,
|
2280
|
-
2: top, y: top,
|
2281
|
-
3: width, width: width,
|
2282
|
-
4: height, height: height,
|
2283
|
-
5: i, index: i,
|
2284
|
-
tooltip: tooltip
|
2285
|
-
};
|
2286
|
-
}
|
2287
|
-
}
|
2288
|
-
|
2289
|
-
return null;
|
2290
|
-
};
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
/**
|
2296
|
-
* This method handles the adjusting calculation for when the mouse is moved
|
2297
|
-
*
|
2298
|
-
* @param object e The event object
|
2299
|
-
*/
|
2300
|
-
this.adjusting_mousemove =
|
2301
|
-
this.Adjusting_mousemove = function (e)
|
2302
|
-
{
|
2303
|
-
/**
|
2304
|
-
* Handle adjusting for the Bar
|
2305
|
-
*/
|
2306
|
-
if (prop['chart.adjustable'] && RG.Registry.get('chart.adjusting') && RG.Registry.get('chart.adjusting').uid == this.uid) {
|
2307
|
-
|
2308
|
-
// Rounding the value to the given number of decimals make the chart step
|
2309
|
-
var value = Number(this.getValue(e)),
|
2310
|
-
shape = RG.Registry.get('chart.adjusting.shape');
|
2311
|
-
|
2312
|
-
if (shape) {
|
2313
|
-
|
2314
|
-
RG.Registry.Set('chart.adjusting.shape', shape);
|
2315
|
-
|
2316
|
-
if (this.stackedOrGrouped && prop['chart.grouping'] == 'grouped') {
|
2317
|
-
|
2318
|
-
var indexes = RG.sequentialIndexToGrouped(shape['index'], this.data);
|
2319
|
-
|
2320
|
-
if (typeof this.data[indexes[0]] == 'number') {
|
2321
|
-
this.data[indexes[0]] = Number(value);
|
2322
|
-
} else if (!RG.is_null(this.data[indexes[0]])) {
|
2323
|
-
this.data[indexes[0]][indexes[1]] = Number(value);
|
2324
|
-
}
|
2325
|
-
} else if (typeof this.data[shape['index']] == 'number') {
|
2326
|
-
|
2327
|
-
this.data[shape['index']] = Number(value);
|
2328
|
-
}
|
2329
|
-
|
2330
|
-
RG.redrawCanvas(e.target);
|
2331
|
-
RG.fireCustomEvent(this, 'onadjust');
|
2332
|
-
}
|
2333
|
-
}
|
2334
|
-
};
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
/**
|
2340
|
-
* Grow
|
2341
|
-
*
|
2342
|
-
* The HBar chart Grow effect gradually increases the values of the bars
|
2343
|
-
*
|
2344
|
-
* @param object OPTIONAL Options for the effect. You can pass frames here
|
2345
|
-
* @param function OPTIONAL A callback function
|
2346
|
-
*/
|
2347
|
-
this.grow = function ()
|
2348
|
-
{
|
2349
|
-
var obj = this,
|
2350
|
-
opt = arguments[0] || {},
|
2351
|
-
frames = opt.frames || 30,
|
2352
|
-
frame = 0,
|
2353
|
-
callback = arguments[1] || function () {},
|
2354
|
-
labelsAbove = prop['chart.labels.above'];
|
2355
|
-
|
2356
|
-
this.set('labelsAbove', false);
|
2357
|
-
|
2358
|
-
|
2359
|
-
// Save the data
|
2360
|
-
obj.original_data = RG.arrayClone(obj.data);
|
2361
|
-
|
2362
|
-
|
2363
|
-
// Stop the scale from changing by setting chart.xmax (if it's not already set)
|
2364
|
-
if (prop['chart.xmax'] == 0) {
|
2365
|
-
|
2366
|
-
var xmax = 0;
|
2367
|
-
|
2368
|
-
for (var i=0; i<obj.data.length; ++i) {
|
2369
|
-
if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'stacked') {
|
2370
|
-
xmax = ma.max(xmax, RG.arraySum(obj.data[i]));
|
2371
|
-
} else if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'grouped') {
|
2372
|
-
xmax = ma.max(xmax, RG.arrayMax(obj.data[i]));
|
2373
|
-
} else {
|
2374
|
-
xmax = ma.max(xmax, ma.abs(RG.arrayMax(obj.data[i])));
|
2375
|
-
}
|
2376
|
-
}
|
2377
|
-
|
2378
|
-
var scale2 = RG.getScale2(obj, {'max':xmax});
|
2379
|
-
obj.Set('chart.xmax', scale2.max);
|
2380
|
-
}
|
2381
|
-
|
2382
|
-
function iterator ()
|
2383
|
-
{
|
2384
|
-
// Alter the Bar chart data depending on the frame
|
2385
|
-
for (var j=0,len=obj.original_data.length; j<len; ++j) {
|
2386
|
-
|
2387
|
-
// This stops the animation from being completely linear
|
2388
|
-
var easingFactor = RG.Effects.getEasingMultiplier(frames, frame);
|
2389
|
-
|
2390
|
-
if (typeof obj.data[j] === 'object' && obj.data[j]) {
|
2391
|
-
for (var k=0,len2=obj.data[j].length; k<len2; ++k) {
|
2392
|
-
obj.data[j][k] = RG.isNull(obj.data[j][k]) ? null : obj.original_data[j][k] * easingFactor;
|
2393
|
-
}
|
2394
|
-
} else {
|
2395
|
-
obj.data[j] = RG.isNull(obj.data[j]) ? null : obj.original_data[j] * easingFactor;
|
2396
|
-
}
|
2397
|
-
}
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
RG.redrawCanvas(obj.canvas);
|
2402
|
-
|
2403
|
-
if (frame < frames) {
|
2404
|
-
frame += 1;
|
2405
|
-
RG.Effects.updateCanvas(iterator);
|
2406
|
-
} else {
|
2407
|
-
|
2408
|
-
if (labelsAbove) {
|
2409
|
-
obj.set('labelsAbove', true);
|
2410
|
-
RG.redraw();
|
2411
|
-
}
|
2412
|
-
|
2413
|
-
callback(obj);
|
2414
|
-
}
|
2415
|
-
}
|
2416
|
-
|
2417
|
-
iterator();
|
2418
|
-
|
2419
|
-
return this;
|
2420
|
-
};
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
|
2427
|
-
|
2428
|
-
|
2429
|
-
/**
|
2430
|
-
* Grow
|
2431
|
-
*
|
2432
|
-
* The HBar chart Grow effect gradually increases the values of the bars
|
2433
|
-
*
|
2434
|
-
* @param object An object of options - eg: {frames: 30}
|
2435
|
-
* @param function A function to call when the effect is complete
|
2436
|
-
*/
|
2437
|
-
this.grow = function ()
|
2438
|
-
{
|
2439
|
-
// Callback
|
2440
|
-
var opt = arguments[0] || {},
|
2441
|
-
frames = opt.frames || 30,
|
2442
|
-
frame = 0,
|
2443
|
-
callback = arguments[1] || function () {},
|
2444
|
-
obj = this,
|
2445
|
-
labelsAbove = this.get('labelsAbove')
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
this.original_data = RG.arrayClone(this.data);
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
// Stop the scale from changing by setting chart.xmax (if it's not already set)
|
2455
|
-
if (prop['chart.xmax'] == 0) {
|
2456
|
-
|
2457
|
-
var xmax = 0;
|
2458
|
-
|
2459
|
-
for (var i=0; i<obj.data.length; ++i) {
|
2460
|
-
if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'stacked') {
|
2461
|
-
xmax = ma.max(xmax, RG.arraySum(obj.data[i]));
|
2462
|
-
} else if (RG.isArray(obj.data[i]) && prop['chart.grouping'] == 'grouped') {
|
2463
|
-
xmax = ma.max(xmax, RG.arrayMax(obj.data[i]));
|
2464
|
-
} else {
|
2465
|
-
xmax = ma.max(xmax, ma.abs(RG.arrayMax(obj.data[i])));
|
2466
|
-
}
|
2467
|
-
}
|
2468
|
-
|
2469
|
-
var scale2 = RG.getScale2(obj, {'max':xmax});
|
2470
|
-
obj.Set('chart.xmax', scale2.max);
|
2471
|
-
}
|
2472
|
-
|
2473
|
-
|
2474
|
-
// Go through the data and change string arguments of the format +/-[0-9]
|
2475
|
-
// to absolute numbers
|
2476
|
-
if (RG.isArray(opt.data)) {
|
2477
|
-
|
2478
|
-
var xmax = 0;
|
2479
|
-
|
2480
|
-
for (var i=0; i<opt.data.length; ++i) {
|
2481
|
-
if (typeof opt.data[i] === 'object') {
|
2482
|
-
for (var j=0; j<opt.data[i].length; ++j) {
|
2483
|
-
if (typeof opt.data[i][j] === 'string'&& opt.data[i][j].match(/(\+|\-)([0-9]+)/)) {
|
2484
|
-
if (RegExp.$1 === '+') {
|
2485
|
-
opt.data[i][j] = this.original_data[i][j] + parseInt(RegExp.$2);
|
2486
|
-
} else {
|
2487
|
-
opt.data[i][j] = this.original_data[i][j] - parseInt(RegExp.$2);
|
2488
|
-
}
|
2489
|
-
}
|
2490
|
-
|
2491
|
-
xmax = ma.max(xmax, opt.data[i][j]);
|
2492
|
-
}
|
2493
|
-
} else if (typeof opt.data[i] === 'string' && opt.data[i].match(/(\+|\-)([0-9]+)/)) {
|
2494
|
-
if (RegExp.$1 === '+') {
|
2495
|
-
opt.data[i] = this.original_data[i] + parseFloat(RegExp.$2);
|
2496
|
-
} else {
|
2497
|
-
opt.data[i] = this.original_data[i] - parseFloat(RegExp.$2);
|
2498
|
-
}
|
2499
|
-
|
2500
|
-
xmax = ma.max(xmax, opt.data[i]);
|
2501
|
-
} else {
|
2502
|
-
xmax = ma.max(xmax, opt.data[i]);
|
2503
|
-
}
|
2504
|
-
}
|
2505
|
-
|
2506
|
-
|
2507
|
-
var scale = RG.getScale2(this, {'max':xmax});
|
2508
|
-
if (typeof this.get('chart.xmax') === 'null') {
|
2509
|
-
this.set('chart.xmax', scale.max);
|
2510
|
-
}
|
2511
|
-
}
|
2512
|
-
|
2513
|
-
|
2514
|
-
|
2515
|
-
|
2516
|
-
|
2517
|
-
|
2518
|
-
//
|
2519
|
-
// turn off the labelsAbove option whilst animating
|
2520
|
-
//
|
2521
|
-
this.set('labelsAbove', false);
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
// Stop the scale from changing by setting chart.xmax (if it's not already set)
|
2529
|
-
if (RG.isNull(prop['chart.xmax'])) {
|
2530
|
-
|
2531
|
-
var xmax = 0;
|
2532
|
-
|
2533
|
-
for (var i=0; i<obj.data.length; ++i) {
|
2534
|
-
if (RG.isArray(this.data[i]) && prop['chart.grouping'] === 'stacked') {
|
2535
|
-
xmax = ma.max(xmax, ma.abs(RG.arraySum(this.data[i])));
|
2536
|
-
|
2537
|
-
} else if (RG.isArray(this.data[i]) && prop['chart.grouping'] === 'grouped') {
|
2538
|
-
|
2539
|
-
for (var j=0,group=[]; j<this.data[i].length; j++) {
|
2540
|
-
group.push(ma.abs(this.data[i][j]));
|
2541
|
-
}
|
2542
|
-
|
2543
|
-
xmax = ma.max(xmax, ma.abs(RG.arrayMax(group)));
|
2544
|
-
|
2545
|
-
} else {
|
2546
|
-
xmax = ma.max(xmax, ma.abs(this.data[i]));
|
2547
|
-
}
|
2548
|
-
}
|
2549
|
-
|
2550
|
-
var scale = RG.getScale2(this, {'max':xmax});
|
2551
|
-
this.Set('chart.xmax', scale.max);
|
2552
|
-
}
|
2553
|
-
|
2554
|
-
// You can give an xmax to the grow function
|
2555
|
-
if (typeof opt.xmax === 'number') {
|
2556
|
-
obj.set('xmax', opt.xmax);
|
2557
|
-
}
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
var iterator = function ()
|
2562
|
-
{
|
2563
|
-
var easingMultiplier = RG.Effects.getEasingMultiplier(frames, frame);
|
2564
|
-
|
2565
|
-
// Alter the Bar chart data depending on the frame
|
2566
|
-
for (var j=0,len=obj.original_data.length; j<len; ++j) {
|
2567
|
-
if (typeof obj.data[j] === 'object' && !RG.isNull(obj.data[j])) {
|
2568
|
-
for (var k=0,len2=obj.data[j].length; k<len2; ++k) {
|
2569
|
-
if (obj.firstDraw || !opt.data) {
|
2570
|
-
obj.data[j][k] = easingMultiplier * obj.original_data[j][k];
|
2571
|
-
} else if (opt.data && opt.data.length === obj.original_data.length) {
|
2572
|
-
var diff = opt.data[j][k] - obj.original_data[j][k];
|
2573
|
-
obj.data[j][k] = (easingMultiplier * diff) + obj.original_data[j][k];
|
2574
|
-
}
|
2575
|
-
}
|
2576
|
-
} else {
|
2577
|
-
|
2578
|
-
if (obj.firstDraw || !opt.data) {
|
2579
|
-
obj.data[j] = easingMultiplier * obj.original_data[j];
|
2580
|
-
} else if (opt.data && opt.data.length === obj.original_data.length) {
|
2581
|
-
var diff = opt.data[j] - obj.original_data[j];
|
2582
|
-
obj.data[j] = (easingMultiplier * diff) + obj.original_data[j];
|
2583
|
-
}
|
2584
|
-
}
|
2585
|
-
}
|
2586
|
-
|
2587
|
-
|
2588
|
-
|
2589
|
-
|
2590
|
-
//RGraph.clear(obj.canvas);
|
2591
|
-
RG.redrawCanvas(obj.canvas);
|
2592
|
-
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
if (frame < frames) {
|
2597
|
-
frame += 1;
|
2598
|
-
|
2599
|
-
RG.Effects.updateCanvas(iterator);
|
2600
|
-
|
2601
|
-
// Call the callback function
|
2602
|
-
} else {
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
|
2608
|
-
// Do some housekeeping if new data was specified thats done in
|
2609
|
-
// the constructor - but needs to be redone because new data
|
2610
|
-
// has been specified
|
2611
|
-
if (RG.isArray(opt.data)) {
|
2612
|
-
|
2613
|
-
var linear_data = RG.arrayLinearize(data);
|
2614
|
-
|
2615
|
-
for (var i=0; i<linear_data.length; ++i) {
|
2616
|
-
if (!obj['$' + i]) {
|
2617
|
-
obj['$' + i] = {};
|
2618
|
-
}
|
2619
|
-
}
|
2620
|
-
}
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
obj.data = data;
|
2625
|
-
obj.original_data = RG.arrayClone(data);
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
if (labelsAbove) {
|
2632
|
-
obj.set('labelsAbove', true);
|
2633
|
-
RG.redraw();
|
2634
|
-
}
|
2635
|
-
callback(obj);
|
2636
|
-
}
|
2637
|
-
};
|
2638
|
-
|
2639
|
-
iterator();
|
2640
|
-
|
2641
|
-
return this;
|
2642
|
-
};
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
|
2647
|
-
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
2651
|
-
/**
|
2652
|
-
* (new) Bar chart Wave effect. This is a rewrite that should be smoother
|
2653
|
-
* because it just uses a single loop and not setTimeout
|
2654
|
-
*
|
2655
|
-
* @param object OPTIONAL An object map of options. You specify 'frames' here to give the number of frames in the effect
|
2656
|
-
* @param function OPTIONAL A function that will be called when the effect is complete
|
2657
|
-
*/
|
2658
|
-
this.wave = function ()
|
2659
|
-
{
|
2660
|
-
var obj = this,
|
2661
|
-
opt = arguments[0] || {};
|
2662
|
-
opt.frames = opt.frames || 60;
|
2663
|
-
opt.startFrames = [];
|
2664
|
-
opt.counters = [];
|
2665
|
-
|
2666
|
-
var framesperbar = opt.frames / 3,
|
2667
|
-
frame = -1,
|
2668
|
-
callback = arguments[1] || function () {},
|
2669
|
-
original = RG.arrayClone(obj.data),
|
2670
|
-
labelsAbove = prop['chart.labels.above'];
|
2671
|
-
|
2672
|
-
this.set('labelsAbove', false);
|
2673
|
-
|
2674
|
-
for (var i=0,len=obj.data.length; i<len; i+=1) {
|
2675
|
-
opt.startFrames[i] = ((opt.frames / 2) / (obj.data.length - 1)) * i;
|
2676
|
-
|
2677
|
-
if (typeof obj.data[i] === 'object' && obj.data[i]) {
|
2678
|
-
opt.counters[i] = [];
|
2679
|
-
for (var j=0; j<obj.data[i].length; j++) {
|
2680
|
-
opt.counters[i][j] = 0;
|
2681
|
-
}
|
2682
|
-
} else {
|
2683
|
-
opt.counters[i] = 0;
|
2684
|
-
}
|
2685
|
-
}
|
2686
|
-
|
2687
|
-
/**
|
2688
|
-
* This stops the chart from jumping
|
2689
|
-
*/
|
2690
|
-
obj.draw();
|
2691
|
-
obj.Set('xmax', obj.scale2.max);
|
2692
|
-
RG.clear(obj.canvas);
|
2693
|
-
|
2694
|
-
function iterator ()
|
2695
|
-
{
|
2696
|
-
++frame;
|
2697
|
-
|
2698
|
-
for (var i=0,len=obj.data.length; i<len; i+=1) {
|
2699
|
-
if (frame > opt.startFrames[i]) {
|
2700
|
-
if (typeof obj.data[i] === 'number') {
|
2701
|
-
|
2702
|
-
obj.data[i] = ma.min(
|
2703
|
-
ma.abs(original[i]),
|
2704
|
-
ma.abs(original[i] * ( (opt.counters[i]++) / framesperbar))
|
2705
|
-
);
|
2706
|
-
|
2707
|
-
// Make the number negative if the original was
|
2708
|
-
if (original[i] < 0) {
|
2709
|
-
obj.data[i] *= -1;
|
2710
|
-
}
|
2711
|
-
} else if (!RG.isNull(obj.data[i])) {
|
2712
|
-
for (var j=0,len2=obj.data[i].length; j<len2; j+=1) {
|
2713
|
-
|
2714
|
-
obj.data[i][j] = ma.min(
|
2715
|
-
ma.abs(original[i][j]),
|
2716
|
-
ma.abs(original[i][j] * ( (opt.counters[i][j]++) / framesperbar))
|
2717
|
-
);
|
2718
|
-
|
2719
|
-
// Make the number negative if the original was
|
2720
|
-
if (original[i][j] < 0) {
|
2721
|
-
obj.data[i][j] *= -1;
|
2722
|
-
}
|
2723
|
-
}
|
2724
|
-
}
|
2725
|
-
} else {
|
2726
|
-
obj.data[i] = typeof obj.data[i] === 'object' && obj.data[i] ? RG.arrayPad([], obj.data[i].length, 0) : (RG.isNull(obj.data[i]) ? null : 0);
|
2727
|
-
}
|
2728
|
-
}
|
2729
|
-
|
2730
|
-
|
2731
|
-
if (frame >= opt.frames) {
|
2732
|
-
|
2733
|
-
if (labelsAbove) {
|
2734
|
-
obj.set('labelsAbove', true);
|
2735
|
-
RG.redrawCanvas(obj.canvas);
|
2736
|
-
}
|
2737
|
-
|
2738
|
-
callback(obj);
|
2739
|
-
} else {
|
2740
|
-
RG.redrawCanvas(obj.canvas);
|
2741
|
-
RG.Effects.updateCanvas(iterator);
|
2742
|
-
}
|
2743
|
-
}
|
2744
|
-
|
2745
|
-
iterator();
|
2746
|
-
|
2747
|
-
return this;
|
2748
|
-
};
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
//
|
2754
|
-
// Determines whether the given shape is adjustable or not
|
2755
|
-
//
|
2756
|
-
// @param object The shape that pertains to the relevant bar
|
2757
|
-
//
|
2758
|
-
this.isAdjustable = function (shape)
|
2759
|
-
{
|
2760
|
-
if (RG.isNull(prop['chart.adjustable.only'])) {
|
2761
|
-
return true;
|
2762
|
-
}
|
2763
|
-
|
2764
|
-
if (RG.isArray(prop['chart.adjustable.only']) && prop['chart.adjustable.only'][shape.index]) {
|
2765
|
-
return true;
|
2766
|
-
}
|
2767
|
-
|
2768
|
-
return false;
|
2769
|
-
};
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
/**
|
2775
|
-
* Charts are now always registered
|
2776
|
-
*/
|
2777
|
-
RG.Register(this);
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
/**
|
2783
|
-
* This is the 'end' of the constructor so if the first argument
|
2784
|
-
* contains configuration data - handle that.
|
2785
|
-
*/
|
2786
|
-
if (parseConfObjectForOptions) {
|
2787
|
-
RG.parseObjectStyleConfig(this, conf.options);
|
2788
|
-
}
|
2789
|
-
};
|
2
|
+
RGraph=window.RGraph||{isRGraph:true};RGraph.HBar=function(conf)
|
3
|
+
{if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var id=conf.id
|
4
|
+
var canvas=document.getElementById(id);var data=conf.data;var parseConfObjectForOptions=true;}else{var id=conf;var canvas=document.getElementById(id);var data=arguments[1];}
|
5
|
+
this.id=id;this.canvas=canvas;this.context=this.canvas.getContext?this.canvas.getContext("2d",{alpha:(typeof id==='object'&&id.alpha===false)?false:true}):null;this.canvas.__object__=this;this.data=data;this.type='hbar';this.isRGraph=true;this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.coords=[];this.coords2=[];this.coordsText=[];this.original_colors=[];this.firstDraw=true;this.max=0;this.stackedOrGrouped=false;this.properties={'chart.gutter.left':75,'chart.gutter.left.autosize':false,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.background.grid':true,'chart.background.grid.color':'#ddd','chart.background.grid.width':1,'chart.background.grid.hsize':25,'chart.background.grid.vsize':25,'chart.background.barcolor1':'rgba(0,0,0,0)','chart.background.barcolor2':'rgba(0,0,0,0)','chart.background.grid.hlines':true,'chart.background.grid.vlines':true,'chart.background.grid.border':true,'chart.background.grid.autofit':true,'chart.background.grid.autofit.align':true,'chart.background.grid.autofit.numhlines':null,'chart.background.grid.autofit.numvlines':5,'chart.background.grid.dashed':false,'chart.background.grid.dotted':false,'chart.background.color':null,'chart.linewidth':1,'chart.title':'','chart.title.background':null,'chart.title.xaxis':'','chart.title.xaxis.bold':true,'chart.title.xaxis.size':null,'chart.title.xaxis.font':null,'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':0.8,'chart.title.yaxis.x':null,'chart.title.yaxis.y':null,'chart.title.xaxis.x':null,'chart.title.xaxis.y':null,'chart.title.xaxis.color':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.text.size':12,'chart.text.color':'black','chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.angle':0,'chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'chart.colors':['red','blue','green','pink','yellow','cyan','navy','gray','black'],'chart.colors.sequential':false,'chart.xlabels.specific':null,'chart.labels':[],'chart.labels.bold':false,'chart.labels.color':null,'chart.labels.above':false,'chart.labels.above.decimals':0,'chart.labels.above.specific':null,'chart.labels.above.color':null,'chart.labels.above.units.pre':'','chart.labels.above.units.post':'','chart.labels.above.font':null,'chart.labels.above.size':null,'chart.labels.above.bold':false,'chart.labels.above.italic':false,'chart.labels.offsetx':0,'chart.labels.offsety':0,'chart.xlabels.offsetx':0,'chart.xlabels.offsety':0,'chart.xlabels':true,'chart.xlabels.count':5,'chart.contextmenu':null,'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':'black','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','chart.units.pre':'','chart.units.post':'','chart.units.ingraph':false,'chart.strokestyle':'rgba(0,0,0,0)','chart.xmin':0,'chart.xmax':0,'chart.axis.color':'black','chart.shadow':false,'chart.shadow.color':'#666','chart.shadow.blur':3,'chart.shadow.offsetx':3,'chart.shadow.offsety':3,'chart.vmargin':2,'chart.vmargin.grouped':2,'chart.grouping':'grouped','chart.tooltips':null,'chart.tooltips.event':'onclick','chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.highlight':true,'chart.highlight.fill':'rgba(255,255,255,0.7)','chart.highlight.stroke':'rgba(0,0,0,0)','chart.highlight.style':null,'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.adjust':[0,0],'chart.resize.handle.background':null,'chart.scale.point':'.','chart.scale.thousand':',','chart.scale.decimals':null,'chart.scale.zerostart':true,'chart.noredraw':false,'chart.events.click':null,'chart.events.mousemove':null,'chart.noxaxis':false,'chart.noyaxis':false,'chart.noaxes':false,'chart.noxtickmarks':false,'chart.noytickmarks':false,'chart.numyticks':data.length,'chart.numxticks':10,'chart.variant':'hbar','chart.variant.threed.angle':0.1,'chart.variant.threed.offsetx':10,'chart.variant.threed.offsety':5,'chart.variant.threed.xaxis':true,'chart.variant.threed.yaxis':true,'chart.yaxispos':'left','chart.variant':'hbar','chart.clearto':'rgba(0,0,0,0)','chart.adjustable':false,'chart.adjustable.only':null}
|
6
|
+
if(!this.canvas){alert('[HBAR] No canvas support');return;}
|
7
|
+
for(i=0,len=this.data.length;i<len;++i){if(typeof this.data[i]=='object'&&!RGraph.isNull(this.data[i])){this.stackedOrGrouped=true;for(var j=0,len2=this.data[i].length;j<len2;++j){if(typeof this.data[i][j]==='string'){this.data[i][j]=parseFloat(this.data[i][j]);}}}else if(typeof this.data[i]=='string'){this.data[i]=parseFloat(this.data[i])||0;}else if(typeof this.data[i]==='undefined'){this.data[i]=null;}}
|
8
|
+
var linear_data=RGraph.arrayLinearize(data);for(var i=0,len=linear_data.length;i<len;++i){this['$'+i]={};}
|
9
|
+
this.data_arr=RGraph.arrayLinearize(this.data);if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
|
10
|
+
var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
|
11
|
+
if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
|
12
|
+
this.set=this.Set=function(name)
|
13
|
+
{var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
|
14
|
+
if(name.substr(0,6)!='chart.'){name='chart.'+name;}
|
15
|
+
while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
|
16
|
+
if(name=='chart.labels.abovebar'){name='chart.labels.above';}
|
17
|
+
prop[name]=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
|
+
if(name=='chart.labels.abovebar'){name='chart.labels.above';}
|
21
|
+
return prop[name];};this.draw=this.Draw=function()
|
22
|
+
{RG.fireCustomEvent(this,'onbeforedraw');if(prop['chart.adjustable']&&prop['chart.grouping']==='stacked'){alert('[RGRAPH] The HBar does not support stacked charts with adjusting');}
|
23
|
+
if(prop['chart.variant']==='3d'){if(prop['chart.text.accessible']){}else{co.setTransform(1,prop['chart.variant.threed.angle'],0,1,0.5,0.5);}
|
24
|
+
if(prop['chart.gutter.bottom']===25){this.set('gutterBottom',80);}}
|
25
|
+
if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
|
26
|
+
if(prop['chart.gutter.left.autosize']){var len=0;var labels=prop['chart.labels'];var font=prop['chart.text.font'];var size=prop['chart.text.size'];for(var i=0;i<labels.length;i+=1){var length=RG.measureText(labels[i],false,font,size)[0]||0
|
27
|
+
len=ma.max(len,length);}
|
28
|
+
prop['chart.gutter.left']=len+10;}
|
29
|
+
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.coords2=[];this.coordsText=[];this.max=0;if(prop['chart.xmin']>0&&prop['chart.grouping']=='stacked'){alert('[HBAR] Using chart.xmin is not supported with stacked charts, resetting chart.xmin to zero');this.Set('chart.xmin',0);}
|
30
|
+
this.graphwidth=ca.width-this.gutterLeft-this.gutterRight;this.graphheight=ca.height-this.gutterTop-this.gutterBottom;this.halfgrapharea=this.grapharea/2;this.halfTextHeight=prop['chart.text.size']/2;this.halfway=ma.round((this.graphwidth/2)+this.gutterLeft)
|
31
|
+
RG.Background.draw(this);this.drawbars();this.drawAxes();this.drawLabels();if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
|
32
|
+
if(prop['chart.contextmenu']){RG.ShowContext(this);}
|
33
|
+
RG.DrawInGraphLabels(this);if(prop['chart.resizable']){RG.AllowResizing(this);}
|
34
|
+
RG.InstallEventListeners(this);if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
|
35
|
+
RG.FireCustomEvent(this,'ondraw');return this;};this.exec=function(func)
|
36
|
+
{func(this);return this;};this.drawAxes=this.DrawAxes=function()
|
37
|
+
{var halfway=this.halfway
|
38
|
+
co.beginPath();co.lineWidth=prop['chart.axis.linewidth']?prop['chart.axis.linewidth']+0.001:1.001;co.strokeStyle=prop['chart.axis.color'];if(prop['chart.noyaxis']==false&&prop['chart.noaxes']==false){if(prop['chart.yaxispos']=='center'){co.moveTo(halfway,this.gutterTop);co.lineTo(halfway,ca.height-this.gutterBottom);}else if(prop['chart.yaxispos']=='right'){co.moveTo(ca.width-this.gutterRight,this.gutterTop);co.lineTo(ca.width-this.gutterRight,ca.height-this.gutterBottom);}else{co.moveTo(this.gutterLeft,this.gutterTop);co.lineTo(this.gutterLeft,ca.height-this.gutterBottom);}}
|
39
|
+
if(prop['chart.noxaxis']==false&&prop['chart.noaxes']==false){co.moveTo(this.gutterLeft+0.001,ca.height-this.gutterBottom+0.001);co.lineTo(ca.width-this.gutterRight+0.001,ca.height-this.gutterBottom+0.001);}
|
40
|
+
if(prop['chart.noytickmarks']==false&&prop['chart.noyaxis']==false&&prop['chart.numyticks']>0&&prop['chart.noaxes']==false){var yTickGap=(ca.height-this.gutterTop-this.gutterBottom)/(prop['chart.numyticks']>0?prop['chart.numyticks']:this.data.length);for(y=this.gutterTop;y<(ca.height-this.gutterBottom-1);y+=yTickGap){if(prop['chart.yaxispos']=='center'){co.moveTo(halfway+3,ma.round(y));co.lineTo(halfway-3,ma.round(y));}else if(prop['chart.yaxispos']=='right'){co.moveTo(ca.width-this.gutterRight,ma.round(y));co.lineTo(ca.width-this.gutterRight+3,ma.round(y));}else{co.moveTo(this.gutterLeft,ma.round(y));co.lineTo(this.gutterLeft-3,ma.round(y));}}
|
41
|
+
if(prop['chart.noxaxis']==true){if(prop['chart.yaxispos']=='center'){co.moveTo(halfway+3,ma.round(y));co.lineTo(halfway-3,ma.round(y));}else if(prop['chart.yaxispos']=='right'){co.moveTo(ca.width-this.gutterRight,ma.round(y));co.lineTo(ca.width-this.gutterRight+3,ma.round(y));}else{co.moveTo(this.gutterLeft,ma.round(y));co.lineTo(this.gutterLeft-3,ma.round(y));}}}
|
42
|
+
if(prop['chart.noxtickmarks']==false&&prop['chart.noxaxis']==false&&prop['chart.numxticks']>0&&prop['chart.noaxes']==false){xTickGap=(ca.width-this.gutterLeft-this.gutterRight)/prop['chart.numxticks'];yStart=ca.height-this.gutterBottom;yEnd=(ca.height-this.gutterBottom)+3;var i=prop['chart.numxticks']
|
43
|
+
while(i--){var x=ca.width-this.gutterRight-(i*xTickGap);if(prop['chart.yaxispos']==='right'){x-=xTickGap;}
|
44
|
+
co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}
|
45
|
+
if(prop['chart.yaxispos']==='center'){var i=5;while(i--){var x=this.gutterLeft+(xTickGap*i);co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}}
|
46
|
+
if(prop['chart.noyaxis']==true){co.moveTo(this.gutterLeft,ma.round(yStart));co.lineTo(this.gutterLeft,ma.round(yEnd));}}
|
47
|
+
co.stroke();co.lineWidth=1;};this.drawLabels=this.DrawLabels=function()
|
48
|
+
{var units_pre=prop['chart.units.pre'],units_post=prop['chart.units.post'],text_size=prop['chart.text.size'],font=prop['chart.text.font'],offsetx=prop['chart.xlabels.offsetx'],offsety=prop['chart.xlabels.offsety']
|
49
|
+
if(prop['chart.units.ingraph']){units_pre='';units_post='';}
|
50
|
+
if(prop['chart.xlabels']){if(RG.isArray(prop['chart.xlabels.specific'])){if(prop['chart.yaxispos']=='center'){var halfGraphWidth=this.graphwidth/2;var labels=prop['chart.xlabels.specific'];var interval=(this.graphwidth/2)/(labels.length-1);co.fillStyle=prop['chart.text.color'];for(var i=0;i<labels.length;i+=1){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+halfGraphWidth+(interval*i)+offsetx,y:ca.height-this.gutterBottom+offsetx,text:labels[i],valign:'top',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}
|
51
|
+
for(var i=(labels.length-1);i>0;i-=1){RG.Text2(this,{'font':font,'size':text_size,'x':this.gutterLeft+(interval*(labels.length-i-1))+offsetx,'y':ca.height-this.gutterBottom+offsety,'text':labels[i],'valign':'top','halign':prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}}else if(prop['chart.yaxispos']=='right'){var labels=prop['chart.xlabels.specific'];var interval=this.graphwidth/(labels.length-1);co.fillStyle=prop['chart.text.color'];for(var i=0;i<labels.length;i+=1){RG.text2(this,{'font':font,'size':text_size,'x':this.gutterLeft+(interval*i)+offsetx,'y':ca.height-this.gutterBottom+offsety,'text':labels[labels.length-i-1],'valign':'top','halign':prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}}else{var labels=prop['chart.xlabels.specific'];var interval=this.graphwidth/(labels.length-1);co.fillStyle=prop['chart.text.color'];for(var i=0;i<labels.length;i+=1){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+(interval*i)+offsetx,y:ca.height-this.gutterBottom+offsety,text:labels[i],valign:'top',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}}}else{var gap=7;co.beginPath();co.fillStyle=prop['chart.text.color'];if(prop['chart.yaxispos']=='center'){for(var i=0;i<this.scale2.labels.length;++i){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+(this.graphwidth/2)-((this.graphwidth/2)*((i+1)/this.scale2.labels.length))+offsetx,y:this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,text:'-'+this.scale2.labels[i],valign:'center',halign:(typeof prop['chart.text.angle']==='number'&&prop['chart.text.angle']!==0)?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}
|
52
|
+
for(var i=0;i<this.scale2.labels.length;++i){RG.text2(this,{font:font,size:text_size,x:this.gutterLeft+((this.graphwidth/2)*((i+1)/this.scale2.labels.length))+(this.graphwidth/2)+offsetx,y:this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,text:this.scale2.labels[i],valign:'center',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}}else if(prop['chart.yaxispos']=='right'){for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.Text2(this,{'font':font,'size':text_size,'x':this.gutterLeft+(i*(this.graphwidth/len))+offsetx,'y':this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,'text':'-'+this.scale2.labels[len-1-i],'valign':'center','halign':prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}}else{for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.Text2(this,{font:font,size:text_size,x:this.gutterLeft+(this.graphwidth*((i+1)/len))+offsetx,y:this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,text:this.scale2.labels[i],valign:'center',halign:prop['chart.text.angle']!==0?'right':'center',tag:'scale',angle:-1*prop['chart.text.angle']});}}
|
53
|
+
if(prop['chart.xmin']>0||prop['chart.noyaxis']==true||prop['chart.scale.zerostart']||prop['chart.noaxes']){var x=prop['chart.yaxispos']=='center'?this.gutterLeft+(this.graphwidth/2):this.gutterLeft;if(prop['chart.yaxispos']==='right'){var x=ca.width-this.gutterRight;}
|
54
|
+
RG.text2(this,{'font':font,'size':text_size,'x':x+offsetx,'y':this.gutterTop+this.halfTextHeight+this.graphheight+gap+offsety,'text':RG.numberFormat(this,prop['chart.xmin'].toFixed(prop['chart.xmin']===0?0:prop['chart.scale.decimals']),units_pre,units_post),'valign':'center',halign:prop['chart.text.angle']!==0?'right':'center','tag':'scale',angle:-1*prop['chart.text.angle']});}
|
55
|
+
co.fill();co.stroke();}}
|
56
|
+
if(typeof prop['chart.labels']=='object'){var xOffset=prop['chart.variant']==='3d'&&prop['chart.yaxispos']==='right'?15:5,font=prop['chart.text.font'],color=prop['chart.labels.color']||prop['chart.text.color'],bold=prop['chart.labels.bold'],offsetx=prop['chart.labels.offsetx'],offsety=prop['chart.labels.offsety']
|
57
|
+
co.fillStyle=color;var barHeight=(ca.height-this.gutterTop-this.gutterBottom)/prop['chart.labels'].length;yTickGap=(ca.height-this.gutterTop-this.gutterBottom)/prop['chart.labels'].length
|
58
|
+
if(prop['chart.yaxispos']==='right'){var x=ca.width-this.gutterRight+xOffset;var halign='left'}else{var x=this.gutterLeft-xOffset;var halign='right'}
|
59
|
+
var i=0;for(y=this.gutterTop+(yTickGap/2);y<=ca.height-this.gutterBottom;y+=yTickGap){RG.text2(this,{'font':font,'size':prop['chart.text.size'],'bold':bold,'x':x+offsetx,'y':y+offsety,'text':String(prop['chart.labels'][i++]),'halign':halign,'valign':'center','tag':'labels'});}}};this.drawbars=this.Drawbars=function()
|
60
|
+
{co.lineWidth=prop['chart.linewidth'];co.strokeStyle=prop['chart.strokestyle'];co.fillStyle=prop['chart.colors'][0];var prevX=0,prevY=0;if(prop['chart.xmax']){this.scale2=RG.getScale2(this,{'max':prop['chart.xmax'],'min':prop['chart.xmin'],'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.xlabels.count'],'strict':true});this.max=this.scale2.max;}else{var grouping=prop['chart.grouping'];for(i=0;i<this.data.length;++i){if(typeof(this.data[i])=='object'){var value=grouping=='grouped'?Number(RG.array_max(this.data[i],true)):Number(RG.array_sum(this.data[i]));}else{var value=Number(ma.abs(this.data[i]));}
|
61
|
+
this.max=ma.max(Math.abs(this.max),Math.abs(value));}
|
62
|
+
this.scale2=RG.getScale2(this,{'max':this.max,'min':prop['chart.xmin'],'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.xlabels.count']});this.max=this.scale2.max;this.min=this.scale2.min;}
|
63
|
+
if(prop['chart.scale.decimals']==null&&Number(this.max)==1){this.Set('chart.scale.decimals',1);}
|
64
|
+
var colorIdx=0;this.numbars=RG.arrayLinearize(this.data).length;if(prop['chart.adjustable']&&!prop['chart.xmax']){this.set('chart.xmax',this.scale2.max);}
|
65
|
+
if(prop['chart.variant']==='3d'){RG.draw3DAxes(this);}
|
66
|
+
var graphwidth=(ca.width-this.gutterLeft-this.gutterRight);var halfwidth=graphwidth/2;for(i=(len=this.data.length-1);i>=0;--i){var width=ma.abs((this.data[i]/this.max)*graphwidth);var height=this.graphheight/this.data.length;var orig_height=height;var x=this.gutterLeft;var y=this.gutterTop+(i*height);var vmargin=prop['chart.vmargin'];if(prop['chart.yaxispos']==='right'){x=ca.width-this.gutterRight-ma.abs(width);}
|
67
|
+
if(width<0){x-=width;width=ma.abs(width);}
|
68
|
+
if(prop['chart.shadow']){co.shadowColor=prop['chart.shadow.color'];co.shadowBlur=prop['chart.shadow.blur'];co.shadowOffsetX=prop['chart.shadow.offsetx'];co.shadowOffsetY=prop['chart.shadow.offsety'];}
|
69
|
+
co.beginPath();if(typeof this.data[i]=='number'||RG.isNull(this.data[i])){var barHeight=height-(2*vmargin),barWidth=((this.data[i]-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*this.graphwidth,barX=this.gutterLeft;if(prop['chart.yaxispos']=='center'){barWidth/=2;barX+=halfwidth;if(this.data[i]<0){barWidth=(ma.abs(this.data[i])-prop['chart.xmin'])/(this.max-prop['chart.xmin']);barWidth=barWidth*(this.graphwidth/2);barX=((this.graphwidth/2)+this.gutterLeft)-barWidth;}}else if(prop['chart.yaxispos']=='right'){barWidth=ma.abs(barWidth);barX=ca.width-this.gutterRight-barWidth;}
|
70
|
+
co.strokeStyle=prop['chart.strokestyle'];co.fillStyle=prop['chart.colors'][0];++colorIdx;if(prop['chart.colors.sequential']&&typeof colorIdx==='number'){if(prop['chart.colors'][this.numbars-colorIdx]){co.fillStyle=prop['chart.colors'][this.numbars-colorIdx];}else{co.fillStyle=prop['chart.colors'][prop['chart.colors'].length-1];}}
|
71
|
+
co.strokeRect(barX,this.gutterTop+(i*height)+prop['chart.vmargin'],barWidth,barHeight);co.fillRect(barX,this.gutterTop+(i*height)+prop['chart.vmargin'],barWidth,barHeight);this.coords.push([barX,y+vmargin,barWidth,height-(2*vmargin),co.fillStyle,this.data[i],true]);if(prop['chart.variant']==='3d'&&typeof this.data[i]=='number'){var prevStrokeStyle=co.strokeStyle,prevFillStyle=co.fillStyle;RG.noShadow(this);var barX=barX,barY=y+vmargin,barW=barWidth,barH=height-(2*vmargin),offsetX=prop['chart.variant.threed.offsetx'],offsetY=prop['chart.variant.threed.offsety'],value=this.data[i];pa2(co,['b','m',barX,barY,'l',barX+offsetX-(prop['chart.yaxispos']=='left'&&value<0?offsetX:0),barY-offsetY,'l',barX+barW+offsetX-(prop['chart.yaxispos']=='center'&&value<0?offsetX:0),barY-offsetY,'l',barX+barW,barY,'c','s',co.strokeStyle,'f',co.fillStyle,'f','rgba(255,255,255,0.6)']);if(prop['chart.yaxispos']!=='right'&&!(prop['chart.yaxispos']==='center'&&value<0)&&value>=0&&!RG.isNull(value)){pa2(co,['b','fs',prevFillStyle,'m',barX+barW,barY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY+barH,'l',barX+barW,barY+barH,'c','s',co.strokeStyle,'f',prevFillStyle,'f','rgba(0,0,0,0.25)']);}}}else if(typeof(this.data[i])=='object'&&prop['chart.grouping']=='stacked'){if(prop['chart.yaxispos']=='center'){alert('[HBAR] You can\'t have a stacked chart with the Y axis in the center, change it to grouped');}else if(prop['chart.yaxispos']=='right'){var x=ca.width-this.gutterRight}
|
72
|
+
var barHeight=height-(2*vmargin);if(typeof this.coords2[i]=='undefined'){this.coords2[i]=[];}
|
73
|
+
for(j=0;j<this.data[i].length;++j){if(prop['chart.shadow']&&prop['chart.variant']==='3d'){co.shadowColor=prop['chart.shadow.color'];co.shadowBlur=prop['chart.shadow.blur'];co.shadowOffsetX=prop['chart.shadow.offsetx'];co.shadowOffsetY=prop['chart.shadow.offsety'];}
|
74
|
+
if(!RG.isNull(this.data[i][j]))this.data[i][j]=ma.abs(this.data[i][j]);var last=(j===(this.data[i].length-1));co.strokeStyle=prop['chart.strokestyle'];++colorIdx;if(prop['chart.colors.sequential']&&typeof colorIdx==='number'){if(prop['chart.colors'][this.numbars-colorIdx]){co.fillStyle=prop['chart.colors'][this.numbars-colorIdx];}else{co.fillStyle=prop['chart.colors'][prop['chart.colors'].length-1];}}else if(prop['chart.colors'][j]){co.fillStyle=prop['chart.colors'][j];}
|
75
|
+
var width=(((this.data[i][j])/(this.max)))*this.graphwidth;var totalWidth=(RG.arraySum(this.data[i])/this.max)*this.graphwidth;if(prop['chart.yaxispos']==='right'){x-=width;}
|
76
|
+
co.strokeRect(x,this.gutterTop+prop['chart.vmargin']+(this.graphheight/this.data.length)*i,width,height-(2*vmargin));co.fillRect(x,this.gutterTop+prop['chart.vmargin']+(this.graphheight/this.data.length)*i,width,height-(2*vmargin));this.coords.push([x,y+vmargin,width,height-(2*vmargin),co.fillStyle,RG.array_sum(this.data[i]),j==(this.data[i].length-1)]);this.coords2[i].push([x,y+vmargin,width,height-(2*vmargin),co.fillStyle,RG.array_sum(this.data[i]),j==(this.data[i].length-1)]);if(prop['chart.variant']==='3d'){RG.noShadow(this);var prevStrokeStyle=co.strokeStyle,prevFillStyle=co.fillStyle;var barX=x,barY=y+vmargin,barW=width,barH=height-(2*vmargin),offsetX=prop['chart.variant.threed.offsetx'],offsetY=prop['chart.variant.threed.offsety'],value=this.data[i][j];if(!RG.isNull(value)){pa2(co,['b','m',barX,barY,'l',barX+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW,barY,'c','s',co.strokeStyle,'f',co.fillStyle,'f','rgba(255,255,255,0.6)']);}
|
77
|
+
if(prop['chart.yaxispos']!=='right'&&!(prop['chart.yaxispos']==='center'&&value<0)&&!RG.isNull(value)){pa2(co,['fs',prevFillStyle,'b','m',barX+barW,barY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY+barH,'l',barX+barW,barY+barH,'c','s',co.strokeStyle,'f',prevFillStyle,'f','rgba(0,0,0,0.25)']);}
|
78
|
+
co.beginPath();co.strokeStyle=prevStrokeStyle;co.fillStyle=prevFillStyle;}
|
79
|
+
if(prop['chart.yaxispos']!=='right'){x+=width;}}}else if(typeof(this.data[i])=='object'&&prop['chart.grouping']=='grouped'){var vmarginGrouped=prop['chart.vmargin.grouped'];var individualBarHeight=((height-(2*vmargin)-((this.data[i].length-1)*vmarginGrouped))/this.data[i].length)
|
80
|
+
if(typeof this.coords2[i]=='undefined'){this.coords2[i]=[];}
|
81
|
+
for(j=(this.data[i].length-1);j>=0;--j){if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}
|
82
|
+
co.strokeStyle=prop['chart.strokestyle'];++colorIdx;if(prop['chart.colors.sequential']&&typeof colorIdx==='number'){if(prop['chart.colors'][this.numbars-colorIdx]){co.fillStyle=prop['chart.colors'][this.numbars-colorIdx];}else{co.fillStyle=prop['chart.colors'][prop['chart.colors'].length-1];}}else if(prop['chart.colors'][j]){co.fillStyle=prop['chart.colors'][j];}
|
83
|
+
var startY=this.gutterTop+(height*i)+(individualBarHeight*j)+vmargin+(vmarginGrouped*j);var width=((this.data[i][j]-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*(ca.width-this.gutterLeft-this.gutterRight);var startX=this.gutterLeft;if(prop['chart.yaxispos']=='center'){width/=2;startX+=halfwidth;}else if(prop['chart.yaxispos']=='right'){width=ma.abs(width);startX=ca.width-this.gutterRight-ma.abs(width);;}
|
84
|
+
if(width<0){startX+=width;width*=-1;}
|
85
|
+
co.strokeRect(startX,startY,width,individualBarHeight);co.fillRect(startX,startY,width,individualBarHeight);this.coords.push([startX,startY,width,individualBarHeight,co.fillStyle,this.data[i][j],true]);this.coords2[i].push([startX,startY,width,individualBarHeight,co.fillStyle,this.data[i][j],true]);if(prop['chart.variant']==='3d'){RG.noShadow(this);var prevStrokeStyle=co.strokeStyle,prevFillStyle=co.fillStyle;var barX=startX,barY=startY,barW=width,barH=individualBarHeight,offsetX=prop['chart.variant.threed.offsetx'],offsetY=prop['chart.variant.threed.offsety'],value=this.data[i][j];pa2(co,['b','m',barX,barY,'l',barX+offsetX,barY-offsetY,'l',barX+barW+offsetX-(value<0?offsetX:0),barY-offsetY,'l',barX+barW,barY,'c','s',co.strokeStyle,'f',co.fillStyle,'f','rgba(255,255,255,0.6)']);if(prop['chart.yaxispos']!=='right'&&!(prop['chart.yaxispos']==='center'&&value<0)&&value>=0&&!RG.isNull(value)){pa2(co,['fs',prevFillStyle,'b','m',barX+barW,barY,'l',barX+barW+offsetX,barY-offsetY,'l',barX+barW+offsetX,barY-offsetY+barH,'l',barX+barW,barY+barH,'c','s',co.strokeStyle,'f',prevFillStyle,'f','rgba(0,0,0,0.25)']);}
|
86
|
+
co.beginPath();co.strokeStyle=prevStrokeStyle;co.fillStyle=prevFillStyle;}}
|
87
|
+
startY+=vmargin;}
|
88
|
+
co.closePath();}
|
89
|
+
co.stroke();co.fill();if(prop['chart,yaxispos']==='right'){pa2(co,'cr % % % %',ca.width-this.gutterRight+prop['chart.variant.threed.offsetx'],'0',this.gutterRight,ca.height);}
|
90
|
+
if(prop['chart.yaxispos']==='right'&&prop['chart.variant']==='3d'){RG.draw3DYAxis(this);}
|
91
|
+
RG.noShadow(this);this.coords=RG.arrayReverse(this.coords);if(prop['chart.grouping']==='grouped'){for(var i=0;i<this.coords2.length;++i){this.coords2[i]=RG.arrayReverse(this.coords2[i]);}}
|
92
|
+
this.redrawBars();};this.redrawBars=this.RedrawBars=function()
|
93
|
+
{if(prop['chart.noredraw']){return;}
|
94
|
+
var coords=this.coords;var font=prop['chart.text.font'],size=prop['chart.text.size'],color=prop['chart.text.color'];RG.noShadow(this);co.strokeStyle=prop['chart.strokestyle'];for(var i=0;i<coords.length;++i){if(prop['chart.shadow']){pa2(co,'b lw % r % % % % s % f %',prop['chart.linewidth'],coords[i][0],coords[i][1],coords[i][2],coords[i][3],prop['chart.strokestyle'],coords[i][4]);}
|
95
|
+
var halign='left';if(prop['chart.labels.above']&&coords[i][6]){var border=(coords[i][0]+coords[i][2]+7+co.measureText(prop['chart.labels.above.units.pre']+this.coords[i][5]+prop['chart.labels.above.units.post']).width)>ca.width?true:false,text=RG.numberFormat(this,(this.coords[i][5]).toFixed(prop['chart.labels.above.decimals']),prop['chart.labels.above.units.pre'],prop['chart.labels.above.units.post']);RG.noShadow(this);if(typeof prop['chart.labels.above.specific']==='object'&&prop['chart.labels.above.specific']&&prop['chart.labels.above.specific'][i]){text=prop['chart.labels.above.specific'][i];}
|
96
|
+
var x=coords[i][0]+coords[i][2]+5;var y=coords[i][1]+(coords[i][3]/2);if(prop['chart.yaxispos']==='right'){x=coords[i][0]-5;halign='right';}else if(prop['chart.yaxispos']==='center'&&this.data_arr[i]<0){x=coords[i][0]-5;halign='right';}
|
97
|
+
RG.text2(this,{font:typeof prop['chart.labels.above.font']==='string'?prop['chart.labels.above.font']:font,size:typeof prop['chart.labels.above.size']==='number'?prop['chart.labels.above.size']:size,color:typeof prop['chart.labels.above.color']==='string'?prop['chart.labels.above.color']:color,x:x,y:y,bold:prop['chart.labels.above.bold'],italic:prop['chart.labels.above.italic'],text:text,valign:'center',halign:halign,tag:'labels.above'});}}};this.getShape=this.getBar=function(e)
|
98
|
+
{var mouseXY=RG.getMouseXY(e);for(var i=0,len=this.coords.length;i<len;i++){var mouseX=mouseXY[0],mouseY=mouseXY[1],left=this.coords[i][0],top=this.coords[i][1],width=this.coords[i][2],height=this.coords[i][3],idx=i;pa2(co,['b','r',left,top,width,height]);if(co.isPointInPath(mouseX,mouseY)){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:idx,'index':idx,'tooltip':tooltip};}}};this.getValue=function(arg)
|
99
|
+
{if(arg.length==2){var mouseX=arg[0];var mouseY=arg[1];}else{var mouseCoords=RG.getMouseXY(arg);var mouseX=mouseCoords[0];var mouseY=mouseCoords[1];}
|
100
|
+
if(mouseY<this.gutterTop||mouseY>(ca.height-this.gutterBottom)||mouseX<this.gutterLeft||mouseX>(ca.width-this.gutterRight)){return null;}
|
101
|
+
if(prop['chart.yaxispos']=='center'){var value=((mouseX-this.gutterLeft)/(this.graphwidth/2))*(this.max-prop['chart.xmin']);value=value-this.max
|
102
|
+
if(prop['chart.xmin']>0){value=((mouseX-this.gutterLeft-(this.graphwidth/2))/(this.graphwidth/2))*(this.max-prop['chart.xmin']);value+=prop['chart.xmin'];if(mouseX<(this.gutterLeft+(this.graphwidth/2))){value-=(2*prop['chart.xmin']);}}}else if(prop['chart.yaxispos']=='right'){var value=((mouseX-this.gutterLeft)/this.graphwidth)*(this.scale2.max-prop['chart.xmin']);value=this.scale2.max-value;}else{var value=((mouseX-this.gutterLeft)/this.graphwidth)*(this.scale2.max-prop['chart.xmin']);value+=prop['chart.xmin'];}
|
103
|
+
return value;};this.highlight=this.Highlight=function(shape)
|
104
|
+
{if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Rect(this,shape);}};this.getObjectByXY=function(e)
|
105
|
+
{var mouseXY=RG.getMouseXY(e);if(prop['chart.variant']==='3d'){var adjustment=prop['chart.variant.threed.angle']*mouseXY[0];mouseXY[1]-=adjustment;}
|
106
|
+
if(mouseXY[0]>=this.gutterLeft&&mouseXY[0]<=(ca.width-this.gutterRight)&&mouseXY[1]>=this.gutterTop&&mouseXY[1]<=(ca.height-this.gutterBottom)){return this;}};this.getXCoord=function(value)
|
107
|
+
{if(prop['chart.yaxispos']=='center'){if(value>this.max||value<(-1*this.max)){return null;}
|
108
|
+
var width=(ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'])/2;var coord=(((value-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*width)+width;coord=prop['chart.gutter.left']+coord;}else{if(value>this.max||value<0){return null;}
|
109
|
+
var width=ca.width-prop['chart.gutter.left']-prop['chart.gutter.right'];var coord=((value-prop['chart.xmin'])/(this.max-prop['chart.xmin']))*width;coord=prop['chart.gutter.left']+coord;}
|
110
|
+
return coord;};this.parseColors=function()
|
111
|
+
{if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.array_clone(prop['chart.colors']);this.original_colors['chart.background.grid.color']=RG.array_clone(prop['chart.background.grid.color']);this.original_colors['chart.background.color']=RG.array_clone(prop['chart.background.color']);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.text.color']=RG.array_clone(prop['chart.text.color']);this.original_colors['chart.labels.colors']=RG.array_clone(prop['chart.labels.colors']);this.original_colors['chart.strokestyle']=RG.array_clone(prop['chart.strokestyle']);this.original_colors['chart.axis.color']=RG.array_clone(prop['chart.axis.color']);this.original_colors['chart.highlight.fill']=RG.array_clone(prop['chart.highlight.fill']);this.original_colors['chart.highlight.stroke']=RG.array_clone(prop['chart.highlight.stroke']);}
|
112
|
+
var colors=prop['chart.colors'];for(var i=0;i<colors.length;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}
|
113
|
+
prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.background.color']=this.parseSingleColorForGradient(prop['chart.background.color']);prop['chart.background.barcolor1']=this.parseSingleColorForGradient(prop['chart.background.barcolor1']);prop['chart.background.barcolor2']=this.parseSingleColorForGradient(prop['chart.background.barcolor2']);prop['chart.text.color']=this.parseSingleColorForGradient(prop['chart.text.color']);prop['chart.labels.colors']=this.parseSingleColorForGradient(prop['chart.labels.colors']);prop['chart.strokestyle']=this.parseSingleColorForGradient(prop['chart.strokestyle']);prop['chart.axis.color']=this.parseSingleColorForGradient(prop['chart.axis.color']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);};this.reset=function()
|
114
|
+
{};this.parseSingleColorForGradient=function(color)
|
115
|
+
{if(!color||typeof(color)!='string'){return color;}
|
116
|
+
if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');if(prop['chart.yaxispos']==='right'){parts=RG.arrayReverse(parts);}
|
117
|
+
var grad=co.createLinearGradient(prop['chart.gutter.left'],0,ca.width-prop['chart.gutter.right'],0);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]));}}
|
118
|
+
return grad?grad:color;};this.interactiveKeyHighlight=function(index)
|
119
|
+
{var obj=this;this.coords2.forEach(function(value,idx,arr)
|
120
|
+
{var shape=obj.coords2[idx][index]
|
121
|
+
var pre_linewidth=co.lineWidth;co.lineWidth=2;co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.strokeStyle=prop['chart.key.interactive.highlight.chart.stroke'];co.fillRect(shape[0],shape[1],shape[2],shape[3]);co.strokeRect(shape[0],shape[1],shape[2],shape[3]);co.lineWidth=pre_linewidth;});};this.on=function(type,func)
|
122
|
+
{if(type.substr(0,2)!=='on'){type='on'+type;}
|
123
|
+
if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
|
124
|
+
return this;};this.firstDrawFunc=function()
|
125
|
+
{};this.getShapeByY=function(e)
|
126
|
+
{var mouseXY=RG.getMouseXY(e);var obj=arguments[1]?arguments[1]:this;for(var i=0,len=obj.coords.length;i<len;i++){if(obj.coords[i].length==0){continue;}
|
127
|
+
var mouseX=mouseXY[0],mouseY=mouseXY[1],left=obj.coords[i][0],top=obj.coords[i][1],width=obj.coords[i][2],height=obj.coords[i][3];if(mouseY>=top&&mouseY<=(top+height)){if(prop['chart.tooltips']){var tooltip=RG.parseTooltipText?RG.parseTooltipText(prop['chart.tooltips'],i):prop['chart.tooltips'][i];}
|
128
|
+
return{0:obj,object:obj,1:left,x:left,2:top,y:top,3:width,width:width,4:height,height:height,5:i,index:i,tooltip:tooltip};}}
|
129
|
+
return null;};this.adjusting_mousemove=this.Adjusting_mousemove=function(e)
|
130
|
+
{if(prop['chart.adjustable']&&RG.Registry.get('chart.adjusting')&&RG.Registry.get('chart.adjusting').uid==this.uid){var value=Number(this.getValue(e)),shape=RG.Registry.get('chart.adjusting.shape');if(shape){RG.Registry.Set('chart.adjusting.shape',shape);if(this.stackedOrGrouped&&prop['chart.grouping']=='grouped'){var indexes=RG.sequentialIndexToGrouped(shape['index'],this.data);if(typeof this.data[indexes[0]]=='number'){this.data[indexes[0]]=Number(value);}else if(!RG.is_null(this.data[indexes[0]])){this.data[indexes[0]][indexes[1]]=Number(value);}}else if(typeof this.data[shape['index']]=='number'){this.data[shape['index']]=Number(value);}
|
131
|
+
RG.redrawCanvas(e.target);RG.fireCustomEvent(this,'onadjust');}}};this.grow=function()
|
132
|
+
{var obj=this,opt=arguments[0]||{},frames=opt.frames||30,frame=0,callback=arguments[1]||function(){},labelsAbove=prop['chart.labels.above'];this.set('labelsAbove',false);obj.original_data=RG.arrayClone(obj.data);if(prop['chart.xmax']==0){var xmax=0;for(var i=0;i<obj.data.length;++i){if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='stacked'){xmax=ma.max(xmax,RG.arraySum(obj.data[i]));}else if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='grouped'){xmax=ma.max(xmax,RG.arrayMax(obj.data[i]));}else{xmax=ma.max(xmax,ma.abs(RG.arrayMax(obj.data[i])));}}
|
133
|
+
var scale2=RG.getScale2(obj,{'max':xmax});obj.Set('chart.xmax',scale2.max);}
|
134
|
+
function iterator()
|
135
|
+
{for(var j=0,len=obj.original_data.length;j<len;++j){var easingFactor=RG.Effects.getEasingMultiplier(frames,frame);if(typeof obj.data[j]==='object'&&obj.data[j]){for(var k=0,len2=obj.data[j].length;k<len2;++k){obj.data[j][k]=RG.isNull(obj.data[j][k])?null:obj.original_data[j][k]*easingFactor;}}else{obj.data[j]=RG.isNull(obj.data[j])?null:obj.original_data[j]*easingFactor;}}
|
136
|
+
RG.redrawCanvas(obj.canvas);if(frame<frames){frame+=1;RG.Effects.updateCanvas(iterator);}else{if(labelsAbove){obj.set('labelsAbove',true);RG.redraw();}
|
137
|
+
callback(obj);}}
|
138
|
+
iterator();return this;};this.grow=function()
|
139
|
+
{var opt=arguments[0]||{},frames=opt.frames||30,frame=0,callback=arguments[1]||function(){},obj=this,labelsAbove=this.get('labelsAbove')
|
140
|
+
this.original_data=RG.arrayClone(this.data);if(prop['chart.xmax']==0){var xmax=0;for(var i=0;i<obj.data.length;++i){if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='stacked'){xmax=ma.max(xmax,RG.arraySum(obj.data[i]));}else if(RG.isArray(obj.data[i])&&prop['chart.grouping']=='grouped'){xmax=ma.max(xmax,RG.arrayMax(obj.data[i]));}else{xmax=ma.max(xmax,ma.abs(RG.arrayMax(obj.data[i])));}}
|
141
|
+
var scale2=RG.getScale2(obj,{'max':xmax});obj.Set('chart.xmax',scale2.max);}
|
142
|
+
if(RG.isArray(opt.data)){var xmax=0;for(var i=0;i<opt.data.length;++i){if(typeof opt.data[i]==='object'){for(var j=0;j<opt.data[i].length;++j){if(typeof opt.data[i][j]==='string'&&opt.data[i][j].match(/(\+|\-)([0-9]+)/)){if(RegExp.$1==='+'){opt.data[i][j]=this.original_data[i][j]+parseInt(RegExp.$2);}else{opt.data[i][j]=this.original_data[i][j]-parseInt(RegExp.$2);}}
|
143
|
+
xmax=ma.max(xmax,opt.data[i][j]);}}else if(typeof opt.data[i]==='string'&&opt.data[i].match(/(\+|\-)([0-9]+)/)){if(RegExp.$1==='+'){opt.data[i]=this.original_data[i]+parseFloat(RegExp.$2);}else{opt.data[i]=this.original_data[i]-parseFloat(RegExp.$2);}
|
144
|
+
xmax=ma.max(xmax,opt.data[i]);}else{xmax=ma.max(xmax,opt.data[i]);}}
|
145
|
+
var scale=RG.getScale2(this,{'max':xmax});if(typeof this.get('chart.xmax')==='null'){this.set('chart.xmax',scale.max);}}
|
146
|
+
this.set('labelsAbove',false);if(RG.isNull(prop['chart.xmax'])){var xmax=0;for(var i=0;i<obj.data.length;++i){if(RG.isArray(this.data[i])&&prop['chart.grouping']==='stacked'){xmax=ma.max(xmax,ma.abs(RG.arraySum(this.data[i])));}else if(RG.isArray(this.data[i])&&prop['chart.grouping']==='grouped'){for(var j=0,group=[];j<this.data[i].length;j++){group.push(ma.abs(this.data[i][j]));}
|
147
|
+
xmax=ma.max(xmax,ma.abs(RG.arrayMax(group)));}else{xmax=ma.max(xmax,ma.abs(this.data[i]));}}
|
148
|
+
var scale=RG.getScale2(this,{'max':xmax});this.Set('chart.xmax',scale.max);}
|
149
|
+
if(typeof opt.xmax==='number'){obj.set('xmax',opt.xmax);}
|
150
|
+
var iterator=function()
|
151
|
+
{var easingMultiplier=RG.Effects.getEasingMultiplier(frames,frame);for(var j=0,len=obj.original_data.length;j<len;++j){if(typeof obj.data[j]==='object'&&!RG.isNull(obj.data[j])){for(var k=0,len2=obj.data[j].length;k<len2;++k){if(obj.firstDraw||!opt.data){obj.data[j][k]=easingMultiplier*obj.original_data[j][k];}else if(opt.data&&opt.data.length===obj.original_data.length){var diff=opt.data[j][k]-obj.original_data[j][k];obj.data[j][k]=(easingMultiplier*diff)+obj.original_data[j][k];}}}else{if(obj.firstDraw||!opt.data){obj.data[j]=easingMultiplier*obj.original_data[j];}else if(opt.data&&opt.data.length===obj.original_data.length){var diff=opt.data[j]-obj.original_data[j];obj.data[j]=(easingMultiplier*diff)+obj.original_data[j];}}}
|
152
|
+
RG.redrawCanvas(obj.canvas);if(frame<frames){frame+=1;RG.Effects.updateCanvas(iterator);}else{if(RG.isArray(opt.data)){var linear_data=RG.arrayLinearize(data);for(var i=0;i<linear_data.length;++i){if(!obj['$'+i]){obj['$'+i]={};}}}
|
153
|
+
obj.data=data;obj.original_data=RG.arrayClone(data);if(labelsAbove){obj.set('labelsAbove',true);RG.redraw();}
|
154
|
+
callback(obj);}};iterator();return this;};this.wave=function()
|
155
|
+
{var obj=this,opt=arguments[0]||{};opt.frames=opt.frames||60;opt.startFrames=[];opt.counters=[];var framesperbar=opt.frames/3,frame=-1,callback=arguments[1]||function(){},original=RG.arrayClone(obj.data),labelsAbove=prop['chart.labels.above'];this.set('labelsAbove',false);for(var i=0,len=obj.data.length;i<len;i+=1){opt.startFrames[i]=((opt.frames/2)/(obj.data.length-1))*i;if(typeof obj.data[i]==='object'&&obj.data[i]){opt.counters[i]=[];for(var j=0;j<obj.data[i].length;j++){opt.counters[i][j]=0;}}else{opt.counters[i]=0;}}
|
156
|
+
obj.draw();obj.Set('xmax',obj.scale2.max);RG.clear(obj.canvas);function iterator()
|
157
|
+
{++frame;for(var i=0,len=obj.data.length;i<len;i+=1){if(frame>opt.startFrames[i]){if(typeof obj.data[i]==='number'){obj.data[i]=ma.min(ma.abs(original[i]),ma.abs(original[i]*((opt.counters[i]++)/framesperbar)));if(original[i]<0){obj.data[i]*=-1;}}else if(!RG.isNull(obj.data[i])){for(var j=0,len2=obj.data[i].length;j<len2;j+=1){obj.data[i][j]=ma.min(ma.abs(original[i][j]),ma.abs(original[i][j]*((opt.counters[i][j]++)/framesperbar)));if(original[i][j]<0){obj.data[i][j]*=-1;}}}}else{obj.data[i]=typeof obj.data[i]==='object'&&obj.data[i]?RG.arrayPad([],obj.data[i].length,0):(RG.isNull(obj.data[i])?null:0);}}
|
158
|
+
if(frame>=opt.frames){if(labelsAbove){obj.set('labelsAbove',true);RG.redrawCanvas(obj.canvas);}
|
159
|
+
callback(obj);}else{RG.redrawCanvas(obj.canvas);RG.Effects.updateCanvas(iterator);}}
|
160
|
+
iterator();return this;};this.isAdjustable=function(shape)
|
161
|
+
{if(RG.isNull(prop['chart.adjustable.only'])){return true;}
|
162
|
+
if(RG.isArray(prop['chart.adjustable.only'])&&prop['chart.adjustable.only'][shape.index]){return true;}
|
163
|
+
return false;};RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};
|