rgraph-rails 1.0.8 → 4.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/lib/rgraph-rails/version.rb +1 -1
- data/vendor/assets/javascripts/RGraph.bar.js +16 -8
- data/vendor/assets/javascripts/RGraph.bipolar.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.annotate.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.context.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.core.js +84 -7
- data/vendor/assets/javascripts/RGraph.common.csv.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.deprecated.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.dynamic.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.effects.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.key.js +3 -3
- data/vendor/assets/javascripts/RGraph.common.resizing.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.sheets.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.tooltips.js +1 -1
- data/vendor/assets/javascripts/RGraph.common.zoom.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.background.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.circle.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.image.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.marker1.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.marker2.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.marker3.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.poly.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.rect.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.text.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +1 -1
- data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +1 -1
- data/vendor/assets/javascripts/RGraph.fuel.js +1 -1
- data/vendor/assets/javascripts/RGraph.funnel.js +1 -1
- data/vendor/assets/javascripts/RGraph.gantt.js +1 -1
- data/vendor/assets/javascripts/RGraph.gauge.js +1 -1
- data/vendor/assets/javascripts/RGraph.hbar.js +228 -2
- data/vendor/assets/javascripts/RGraph.hprogress.js +1 -1
- data/vendor/assets/javascripts/RGraph.line.js +27 -5
- data/vendor/assets/javascripts/RGraph.meter.js +1 -1
- data/vendor/assets/javascripts/RGraph.modaldialog.js +1 -1
- data/vendor/assets/javascripts/RGraph.odo.js +1 -1
- data/vendor/assets/javascripts/RGraph.pie.js +1 -1
- data/vendor/assets/javascripts/RGraph.radar.js +1 -1
- data/vendor/assets/javascripts/RGraph.rose.js +1 -1
- data/vendor/assets/javascripts/RGraph.rscatter.js +1 -1
- data/vendor/assets/javascripts/RGraph.scatter.js +161 -34
- data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.bar.js +772 -103
- data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.common.core.js +806 -231
- data/vendor/assets/javascripts/RGraph.svg.common.csv.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.common.fx.js +24 -24
- data/vendor/assets/javascripts/RGraph.svg.common.key.js +206 -0
- data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +1 -1
- data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +63 -22
- data/vendor/assets/javascripts/RGraph.svg.hbar.js +351 -91
- data/vendor/assets/javascripts/RGraph.svg.line.js +159 -64
- data/vendor/assets/javascripts/RGraph.svg.pie.js +402 -51
- data/vendor/assets/javascripts/RGraph.svg.radar.js +320 -143
- data/vendor/assets/javascripts/RGraph.svg.rose.js +1818 -0
- data/vendor/assets/javascripts/RGraph.svg.scatter.js +1262 -0
- data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +106 -57
- data/vendor/assets/javascripts/RGraph.svg.waterfall.js +1253 -0
- data/vendor/assets/javascripts/RGraph.thermometer.js +7 -6
- data/vendor/assets/javascripts/RGraph.vprogress.js +1 -1
- data/vendor/assets/javascripts/RGraph.waterfall.js +1 -1
- data/vendor/assets/javascripts/financial-data.js +1067 -0
- metadata +8 -5
- data/vendor/assets/javascripts/RGraph.cornergauge.js +0 -71
- data/vendor/assets/javascripts/RGraph.thermometer.old.js +0 -68
@@ -1,4 +1,4 @@
|
|
1
|
-
// version: 2017-
|
1
|
+
// version: 2017-05-08
|
2
2
|
/**
|
3
3
|
* o--------------------------------------------------------------------------------o
|
4
4
|
* | This file is part of the RGraph package - you can learn more at: |
|
@@ -26,6 +26,56 @@
|
|
26
26
|
|
27
27
|
RG.SVG.SemiCircularProgress = function (conf)
|
28
28
|
{
|
29
|
+
//
|
30
|
+
// A setter that the constructor uses (at the end)
|
31
|
+
// to set all of the properties
|
32
|
+
//
|
33
|
+
// @param string name The name of the property to set
|
34
|
+
// @param string value The value to set the property to
|
35
|
+
//
|
36
|
+
this.set = function (name, value)
|
37
|
+
{
|
38
|
+
if (arguments.length === 1 && typeof name === 'object') {
|
39
|
+
for (i in arguments[0]) {
|
40
|
+
if (typeof i === 'string') {
|
41
|
+
|
42
|
+
var ret = RG.SVG.commonSetter({
|
43
|
+
object: this,
|
44
|
+
name: i,
|
45
|
+
value: arguments[0][i]
|
46
|
+
});
|
47
|
+
|
48
|
+
name = ret.name;
|
49
|
+
value = ret.value;
|
50
|
+
|
51
|
+
this.set(name, value);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
} else {
|
55
|
+
|
56
|
+
|
57
|
+
var ret = RG.SVG.commonSetter({
|
58
|
+
object: this,
|
59
|
+
name: name,
|
60
|
+
value: value
|
61
|
+
});
|
62
|
+
|
63
|
+
name = ret.name;
|
64
|
+
value = ret.value;
|
65
|
+
|
66
|
+
this.properties[name] = value;
|
67
|
+
}
|
68
|
+
|
69
|
+
return this;
|
70
|
+
};
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
29
79
|
this.min = RG.SVG.stringsToNumbers(conf.min);
|
30
80
|
this.max = RG.SVG.stringsToNumbers(conf.max);
|
31
81
|
this.value = RG.SVG.stringsToNumbers(conf.value);
|
@@ -143,7 +193,7 @@
|
|
143
193
|
titleX: null,
|
144
194
|
titleY: null,
|
145
195
|
titleHalign: 'center',
|
146
|
-
titleValign:
|
196
|
+
titleValign: null,
|
147
197
|
titleColor: 'black',
|
148
198
|
titleFont: null,
|
149
199
|
titleBold: false,
|
@@ -154,7 +204,7 @@
|
|
154
204
|
titleSubtitleX: null,
|
155
205
|
titleSubtitleY: null,
|
156
206
|
titleSubtitleHalign: 'center',
|
157
|
-
titleSubtitleValign:
|
207
|
+
titleSubtitleValign: null,
|
158
208
|
titleSubtitleColor: '#aaa',
|
159
209
|
titleSubtitleFont: null,
|
160
210
|
titleSubtitleBold: false,
|
@@ -163,10 +213,10 @@
|
|
163
213
|
attribution: true,
|
164
214
|
attributionX: null,
|
165
215
|
attributionY: null,
|
166
|
-
attributionHref:
|
216
|
+
attributionHref: null,// Default is set in RGraph.svg.common.core.js
|
167
217
|
attributionHalign: 'right',
|
168
218
|
attributionValign: 'bottom',
|
169
|
-
attributionSize:
|
219
|
+
attributionSize: 7,
|
170
220
|
attributionColor: 'gray',
|
171
221
|
attributionFont: 'sans-serif',
|
172
222
|
attributionItalic: false,
|
@@ -198,31 +248,6 @@
|
|
198
248
|
|
199
249
|
|
200
250
|
|
201
|
-
//
|
202
|
-
// A setter that the constructor uses (at the end)
|
203
|
-
// to set all of the properties
|
204
|
-
//
|
205
|
-
// @param string name The name of the property to set
|
206
|
-
// @param string value The value to set the property to
|
207
|
-
//
|
208
|
-
this.set = function (name, value)
|
209
|
-
{
|
210
|
-
if (arguments.length === 1 && typeof name === 'object') {
|
211
|
-
for (i in arguments[0]) {
|
212
|
-
if (typeof i === 'string') {
|
213
|
-
this.set(i, arguments[0][i]);
|
214
|
-
}
|
215
|
-
}
|
216
|
-
} else {
|
217
|
-
this.properties[name] = value;
|
218
|
-
}
|
219
|
-
|
220
|
-
return this;
|
221
|
-
};
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
251
|
|
227
252
|
|
228
253
|
|
@@ -270,19 +295,12 @@
|
|
270
295
|
|
271
296
|
// Set the width of the meter
|
272
297
|
this.progressWidth = prop.width || (this.radius / 3);
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
*/
|
280
|
-
if (!this.colorsParsed) {
|
281
|
-
this.parseColors();
|
282
|
-
|
283
|
-
// Don't want to do this again
|
284
|
-
this.colorsParsed = true;
|
285
|
-
}
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
// Parse the colors for gradients
|
302
|
+
RG.SVG.resetColorsToOriginalValues({object:this});
|
303
|
+
this.parseColors();
|
286
304
|
|
287
305
|
|
288
306
|
|
@@ -320,8 +338,10 @@
|
|
320
338
|
//
|
321
339
|
// Add tooltip event listeners
|
322
340
|
//
|
323
|
-
this.path
|
341
|
+
this.path.addEventListener(prop.tooltipsEvent, function (e)
|
324
342
|
{
|
343
|
+
obj.removeHighlight();
|
344
|
+
|
325
345
|
// Show the tooltip
|
326
346
|
RG.SVG.tooltip({
|
327
347
|
object: obj,
|
@@ -334,24 +354,22 @@
|
|
334
354
|
|
335
355
|
// Highlight the rect that has been clicked on
|
336
356
|
obj.highlight(e.target);
|
337
|
-
|
338
|
-
};
|
357
|
+
}, false);
|
339
358
|
|
340
|
-
this.path.
|
359
|
+
this.path.addEventListener('mousemove', function (e)
|
341
360
|
{
|
342
361
|
e.target.style.cursor = 'pointer'
|
343
|
-
};
|
362
|
+
}, false);
|
344
363
|
}
|
345
364
|
|
346
365
|
|
347
366
|
// Add the event listener that clears the highlight if
|
348
367
|
// there is any. Must be MOUSEDOWN (ie before the click event)
|
349
|
-
RG.SVG.SSP_window_mousedown_listener = function (e)
|
350
|
-
{
|
351
|
-
RG.SVG.removeHighlight(obj);
|
352
|
-
}
|
353
368
|
var obj = this;
|
354
|
-
doc.body.addEventListener('mousedown',
|
369
|
+
doc.body.addEventListener('mousedown', function (e)
|
370
|
+
{
|
371
|
+
obj.removeHighlight();
|
372
|
+
}, false);
|
355
373
|
|
356
374
|
|
357
375
|
|
@@ -400,6 +418,7 @@
|
|
400
418
|
RG.SVG.create({
|
401
419
|
svg: this.svg,
|
402
420
|
type: 'path',
|
421
|
+
parent: this.svg.all,
|
403
422
|
attr: {
|
404
423
|
d: path + " L " + (this.centerx + this.radius - this.progressWidth) + " " + this.centery + path2 + " L " + (this.centerx - this.radius) + " " + this.centery,
|
405
424
|
fill: prop.backgroundFill || prop.colors[0],
|
@@ -455,6 +474,7 @@
|
|
455
474
|
var path = RG.SVG.create({
|
456
475
|
svg: this.svg,
|
457
476
|
type: 'path',
|
477
|
+
parent: this.svg.all,
|
458
478
|
attr: {
|
459
479
|
d: path + " L{1} {2} ".format(
|
460
480
|
path2[1],
|
@@ -496,6 +516,7 @@
|
|
496
516
|
|
497
517
|
RG.SVG.text({
|
498
518
|
object: this,
|
519
|
+
parent: this.svg.all,
|
499
520
|
text: typeof prop.labelsMinSpecific === 'string' ? prop.labelsMinSpecific : min,
|
500
521
|
x: this.centerx - this.radius + (this.progressWidth / 2),
|
501
522
|
y: this.height - prop.gutterBottom + 5,
|
@@ -531,6 +552,7 @@
|
|
531
552
|
|
532
553
|
RG.SVG.text({
|
533
554
|
object: this,
|
555
|
+
parent: this.svg.all,
|
534
556
|
text: typeof prop.labelsMaxSpecific === 'string' ? prop.labelsMaxSpecific : max,
|
535
557
|
x: this.centerx + this.radius - (this.progressWidth / 2),
|
536
558
|
y: this.height - prop.gutterBottom + 5,
|
@@ -565,6 +587,7 @@
|
|
565
587
|
|
566
588
|
RG.SVG.text({
|
567
589
|
object: this,
|
590
|
+
parent: this.svg.all,
|
568
591
|
text: typeof prop.labelsCenterSpecific === 'string' ? prop.labelsCenterSpecific : center,
|
569
592
|
x: this.centerx,
|
570
593
|
y: this.centery,
|
@@ -597,9 +620,10 @@
|
|
597
620
|
// installed
|
598
621
|
this.removeHighlight();
|
599
622
|
|
600
|
-
|
623
|
+
var highlight = RG.SVG.create({
|
601
624
|
svg: this.svg,
|
602
625
|
type: 'path',
|
626
|
+
parent: this.svg.all,
|
603
627
|
attr: {
|
604
628
|
d: this.path.getAttribute('d'),
|
605
629
|
fill: prop.highlightFill,
|
@@ -607,6 +631,9 @@
|
|
607
631
|
'stroke-width': prop.highlightLinewidth
|
608
632
|
}
|
609
633
|
});
|
634
|
+
|
635
|
+
// Store the highlight node in the registry
|
636
|
+
RG.SVG.REG.set('highlight', highlight);
|
610
637
|
|
611
638
|
// Add the event listener that clears the highlight path if
|
612
639
|
// there is any. Must be MOUSEDOWN (ie before the click event)
|
@@ -631,9 +658,11 @@
|
|
631
658
|
*/
|
632
659
|
this.removeHighlight = function ()
|
633
660
|
{
|
634
|
-
|
635
|
-
|
636
|
-
|
661
|
+
var highlight = RG.SVG.REG.get('highlight');
|
662
|
+
|
663
|
+
if (highlight) {
|
664
|
+
highlight.parentNode.removeChild(highlight);
|
665
|
+
highlight = null;
|
637
666
|
}
|
638
667
|
};
|
639
668
|
|
@@ -796,6 +825,26 @@
|
|
796
825
|
|
797
826
|
|
798
827
|
|
828
|
+
//
|
829
|
+
// Remove highlight from the chart (tooltips)
|
830
|
+
//
|
831
|
+
this.removeHighlight = function ()
|
832
|
+
{
|
833
|
+
var highlight = RG.SVG.REG.get('highlight');
|
834
|
+
if (highlight && highlight.parentNode) {
|
835
|
+
highlight.parentNode.removeChild(highlight);
|
836
|
+
}
|
837
|
+
|
838
|
+
RG.SVG.REG.set('highlight', null);
|
839
|
+
};
|
840
|
+
|
841
|
+
|
842
|
+
|
843
|
+
|
844
|
+
|
845
|
+
|
846
|
+
|
847
|
+
|
799
848
|
//
|
800
849
|
// Set the options that the user has provided
|
801
850
|
//
|
@@ -0,0 +1,1253 @@
|
|
1
|
+
// version: 2017-05-08
|
2
|
+
/**
|
3
|
+
* o--------------------------------------------------------------------------------o
|
4
|
+
* | This file is part of the RGraph package - you can learn more at: |
|
5
|
+
* | |
|
6
|
+
* | http://www.rgraph.net |
|
7
|
+
* | |
|
8
|
+
* | RGraph is licensed under the Open Source MIT license. That means that it's |
|
9
|
+
* | totally free to use! |
|
10
|
+
* o--------------------------------------------------------------------------------o
|
11
|
+
*/
|
12
|
+
|
13
|
+
RGraph = window.RGraph || {isRGraph: true};
|
14
|
+
RGraph.SVG = RGraph.SVG || {};
|
15
|
+
|
16
|
+
// Module pattern
|
17
|
+
(function (win, doc, undefined)
|
18
|
+
{
|
19
|
+
var RG = RGraph,
|
20
|
+
ua = navigator.userAgent,
|
21
|
+
ma = Math,
|
22
|
+
win = window,
|
23
|
+
doc = document;
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
RG.SVG.Waterfall = function (conf)
|
28
|
+
{
|
29
|
+
//
|
30
|
+
// A setter that the constructor uses (at the end)
|
31
|
+
// to set all of the properties
|
32
|
+
//
|
33
|
+
// @param string name The name of the property to set
|
34
|
+
// @param string value The value to set the property to
|
35
|
+
//
|
36
|
+
this.set = function (name, value)
|
37
|
+
{
|
38
|
+
if (arguments.length === 1 && typeof name === 'object') {
|
39
|
+
for (i in arguments[0]) {
|
40
|
+
if (typeof i === 'string') {
|
41
|
+
|
42
|
+
var ret = RG.SVG.commonSetter({
|
43
|
+
object: this,
|
44
|
+
name: i,
|
45
|
+
value: arguments[0][i]
|
46
|
+
});
|
47
|
+
|
48
|
+
name = ret.name;
|
49
|
+
value = ret.value;
|
50
|
+
|
51
|
+
this.set(name, value);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
} else {
|
55
|
+
|
56
|
+
var ret = RG.SVG.commonSetter({
|
57
|
+
object: this,
|
58
|
+
name: name,
|
59
|
+
value: value
|
60
|
+
});
|
61
|
+
|
62
|
+
name = ret.name;
|
63
|
+
value = ret.value;
|
64
|
+
|
65
|
+
this.properties[name] = value;
|
66
|
+
}
|
67
|
+
|
68
|
+
return this;
|
69
|
+
};
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
this.id = conf.id;
|
79
|
+
this.uid = RG.SVG.createUID();
|
80
|
+
this.container = document.getElementById(this.id);
|
81
|
+
this.svg = RG.SVG.createSVG({container: this.container});
|
82
|
+
this.isRGraph = true;
|
83
|
+
this.width = Number(this.svg.getAttribute('width'));
|
84
|
+
this.height = Number(this.svg.getAttribute('height'));
|
85
|
+
this.data = conf.data;
|
86
|
+
this.type = 'waterfall';
|
87
|
+
this.coords = [];
|
88
|
+
this.colorsParsed = false;
|
89
|
+
this.originalColors = {};
|
90
|
+
this.gradientCounter = 1;
|
91
|
+
|
92
|
+
// Add this object to the ObjectRegistry
|
93
|
+
RG.SVG.OR.add(this);
|
94
|
+
|
95
|
+
this.container.style.display = 'inline-block';
|
96
|
+
|
97
|
+
this.properties =
|
98
|
+
{
|
99
|
+
gutterLeft: 35,
|
100
|
+
gutterRight: 35,
|
101
|
+
gutterTop: 35,
|
102
|
+
gutterBottom: 35,
|
103
|
+
|
104
|
+
backgroundColor: null,
|
105
|
+
backgroundImage: null,
|
106
|
+
backgroundImageAspect: 'none',
|
107
|
+
backgroundImageStretch: true,
|
108
|
+
backgroundImageOpacity: null,
|
109
|
+
backgroundImageX: null,
|
110
|
+
backgroundImageY: null,
|
111
|
+
backgroundImageW: null,
|
112
|
+
backgroundImageH: null,
|
113
|
+
backgroundGrid: true,
|
114
|
+
backgroundGridColor: '#ddd',
|
115
|
+
backgroundGridLinewidth: 1,
|
116
|
+
backgroundGridHlines: true,
|
117
|
+
backgroundGridHlinesCount: null,
|
118
|
+
backgroundGridVlines: true,
|
119
|
+
backgroundGridVlinesCount: null,
|
120
|
+
backgroundGridBorder: true,
|
121
|
+
|
122
|
+
// 20 colors. If you need more you need to set the colors property
|
123
|
+
colors: ['black', 'red', 'blue'],
|
124
|
+
colorsSequential: false,
|
125
|
+
strokestyle: '#aaa',
|
126
|
+
strokestyleConnector: null,
|
127
|
+
|
128
|
+
total: true,
|
129
|
+
hmargin: 5,
|
130
|
+
linewidth: 1,
|
131
|
+
|
132
|
+
yaxis: true,
|
133
|
+
yaxisTickmarks: true,
|
134
|
+
yaxisTickmarksLength: 5,
|
135
|
+
yaxisColor: 'black',
|
136
|
+
yaxisScale: true,
|
137
|
+
yaxisLabels: null,
|
138
|
+
yaxisLabelsOffsetx: 0,
|
139
|
+
yaxisLabelsOffsety: 0,
|
140
|
+
yaxisLabelsCount: 5,
|
141
|
+
yaxisUnitsPre: '',
|
142
|
+
yaxisUnitsPost: '',
|
143
|
+
yaxisStrict: false,
|
144
|
+
yaxisDecimals: 0,
|
145
|
+
yaxisPoint: '.',
|
146
|
+
yaxisThousand: ',',
|
147
|
+
yaxisRound: false,
|
148
|
+
yaxisMax: null,
|
149
|
+
yaxisMin: 0,
|
150
|
+
yaxisFormatter: null,
|
151
|
+
yaxisTextColor: null,
|
152
|
+
yaxisTextBold: null,
|
153
|
+
yaxisTextItalic: null,
|
154
|
+
yaxisTextFont: null,
|
155
|
+
yaxisTextSize: null,
|
156
|
+
|
157
|
+
xaxis: true,
|
158
|
+
xaxisTickmarks: true,
|
159
|
+
xaxisTickmarksLength: 5,
|
160
|
+
xaxisLabels: null,
|
161
|
+
xaxisLabelsPosition: 'section',
|
162
|
+
xaxisLabelsPositionEdgeTickmarksCount: null,
|
163
|
+
xaxisColor: 'black',
|
164
|
+
xaxisLabelsOffsetx: 0,
|
165
|
+
xaxisLabelsOffsety: 0,
|
166
|
+
|
167
|
+
labelsAbove: false,
|
168
|
+
labelsAboveFont: null,
|
169
|
+
labelsAboveSize: null,
|
170
|
+
labelsAboveBold: null,
|
171
|
+
labelsAboveItalic: null,
|
172
|
+
labelsAboveColor: null,
|
173
|
+
labelsAboveBackground: 'rgba(255,255,255,0.5)',
|
174
|
+
labelsAboveBackgroundPadding: 2,
|
175
|
+
labelsAboveUnitsPre: null,
|
176
|
+
labelsAboveUnitsPost: null,
|
177
|
+
labelsAbovePoint: null,
|
178
|
+
labelsAboveThousand: null,
|
179
|
+
labelsAboveFormatter: null,
|
180
|
+
labelsAboveDecimals: null,
|
181
|
+
labelsAboveOffsetx: 0,
|
182
|
+
labelsAboveOffsety: 0,
|
183
|
+
labelsAboveHalign: 'center',
|
184
|
+
labelsAboveValign: 'bottom',
|
185
|
+
labelsAboveSpecific: null,
|
186
|
+
|
187
|
+
textColor: 'black',
|
188
|
+
textFont: 'sans-serif',
|
189
|
+
textSize: 12,
|
190
|
+
textBold: false,
|
191
|
+
textItalic: false,
|
192
|
+
|
193
|
+
|
194
|
+
tooltips: null,
|
195
|
+
tooltipsOverride: null,
|
196
|
+
tooltipsEffect: 'fade',
|
197
|
+
tooltipsCssClass: 'RGraph_tooltip',
|
198
|
+
tooltipsEvent: 'click',
|
199
|
+
|
200
|
+
highlightStroke: 'rgba(0,0,0,0)',
|
201
|
+
highlightFill: 'rgba(255,255,255,0.7)',
|
202
|
+
highlightLinewidth: 1,
|
203
|
+
|
204
|
+
title: '',
|
205
|
+
titleSize: 16,
|
206
|
+
titleX: null,
|
207
|
+
titleY: null,
|
208
|
+
titleHalign: 'center',
|
209
|
+
titleValign: null,
|
210
|
+
titleColor: 'black',
|
211
|
+
titleFont: null,
|
212
|
+
titleBold: false,
|
213
|
+
titleItalic: false,
|
214
|
+
|
215
|
+
titleSubtitle: '',
|
216
|
+
titleSubtitleSize: 10,
|
217
|
+
titleSubtitleX: null,
|
218
|
+
titleSubtitleY: null,
|
219
|
+
titleSubtitleHalign: 'center',
|
220
|
+
titleSubtitleValign: null,
|
221
|
+
titleSubtitleColor: '#aaa',
|
222
|
+
titleSubtitleFont: null,
|
223
|
+
titleSubtitleBold: false,
|
224
|
+
titleSubtitleItalic: false,
|
225
|
+
|
226
|
+
//shadow: false,
|
227
|
+
//shadowOffsetx: 2,
|
228
|
+
//shadowOffsety: 2,
|
229
|
+
//shadowBlur: 2,
|
230
|
+
//shadowOpacity: 0.25,
|
231
|
+
|
232
|
+
|
233
|
+
|
234
|
+
key: null,
|
235
|
+
keyColors: null,
|
236
|
+
keyOffsetx: 0,
|
237
|
+
keyOffsety: 0,
|
238
|
+
keyTextOffsetx: 0,
|
239
|
+
keyTextOffsety: -1,
|
240
|
+
keyTextSize: null,
|
241
|
+
keyTextBold: null,
|
242
|
+
keyTextItalic: null,
|
243
|
+
|
244
|
+
attribution: true,
|
245
|
+
attributionX: null,
|
246
|
+
attributionY: null,
|
247
|
+
attributionHref: null,// Default is set in RGraph.svg.common.core.js
|
248
|
+
attributionHalign: 'right',
|
249
|
+
attributionValign: 'bottom',
|
250
|
+
attributionSize: 7,
|
251
|
+
attributionColor: 'gray',
|
252
|
+
attributionFont: 'sans-serif',
|
253
|
+
attributionItalic: false,
|
254
|
+
attributionBold: false
|
255
|
+
};
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
/**
|
262
|
+
* "Decorate" the object with the generic effects if the effects library has been included
|
263
|
+
*/
|
264
|
+
if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
|
265
|
+
RG.SVG.FX.decorate(this);
|
266
|
+
}
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
|
271
|
+
var prop = this.properties;
|
272
|
+
|
273
|
+
|
274
|
+
|
275
|
+
|
276
|
+
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
//
|
281
|
+
// The draw method draws the Bar chart
|
282
|
+
//
|
283
|
+
this.draw = function ()
|
284
|
+
{
|
285
|
+
// Fire the beforedraw event
|
286
|
+
RG.SVG.fireCustomEvent(this, 'onbeforedraw');
|
287
|
+
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
// Create the defs tag if necessary
|
292
|
+
RG.SVG.createDefs(this);
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
|
299
|
+
this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
// Parse the colors for gradients
|
304
|
+
RG.SVG.resetColorsToOriginalValues({object:this});
|
305
|
+
this.parseColors();
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
|
310
|
+
// Work out the sum of the data and add it to the data
|
311
|
+
if (prop.total) {
|
312
|
+
var sum = RG.SVG.arraySum(this.data);
|
313
|
+
|
314
|
+
// Now append the sum to the data
|
315
|
+
this.data.push(sum);
|
316
|
+
|
317
|
+
// May need to append something to the labels array if prop.total
|
318
|
+
// is enabled, so that the labels line up
|
319
|
+
|
320
|
+
if (prop.xaxisLabels && prop.xaxisLabels.length === (this.data.length - 1)) {
|
321
|
+
prop.xaxisLabels.push('');
|
322
|
+
}
|
323
|
+
}
|
324
|
+
|
325
|
+
|
326
|
+
|
327
|
+
|
328
|
+
for (var i=0,max=0,runningTotal=0; i<this.data.length - (prop.total ? 1 : 0); ++i) {
|
329
|
+
runningTotal += this.data[i]
|
330
|
+
max = ma.max(max, runningTotal);
|
331
|
+
}
|
332
|
+
|
333
|
+
// A custom, user-specified maximum value
|
334
|
+
if (typeof prop.yaxisMax === 'number') {
|
335
|
+
max = prop.yaxisMax;
|
336
|
+
}
|
337
|
+
|
338
|
+
// Set the ymin to zero if it's set mirror
|
339
|
+
if (prop.yaxisMin === 'mirror' || prop.yaxisMin === 'middle' || prop.yaxisMin === 'center') {
|
340
|
+
var mirrorScale = true;
|
341
|
+
prop.yaxisMin = 0;
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
//
|
346
|
+
// Generate an appropiate scale
|
347
|
+
//
|
348
|
+
this.scale = RG.SVG.getScale({
|
349
|
+
object: this,
|
350
|
+
numlabels: prop.yaxisLabelsCount,
|
351
|
+
unitsPre: prop.yaxisUnitsPre,
|
352
|
+
unitsPost: prop.yaxisUnitsPost,
|
353
|
+
max: max,
|
354
|
+
min: prop.yaxisMin,
|
355
|
+
point: prop.yaxisPoint,
|
356
|
+
round: prop.yaxisRound,
|
357
|
+
thousand: prop.yaxisThousand,
|
358
|
+
decimals: prop.yaxisDecimals,
|
359
|
+
strict: typeof prop.yaxisMax === 'number',
|
360
|
+
formatter: prop.yaxisFormatter
|
361
|
+
});
|
362
|
+
|
363
|
+
|
364
|
+
|
365
|
+
//
|
366
|
+
// Get the scale a second time if the ymin should be mirored
|
367
|
+
//
|
368
|
+
// Set the ymin to zero if it's set mirror
|
369
|
+
if (mirrorScale) {
|
370
|
+
this.scale = RG.SVG.getScale({
|
371
|
+
object: this,
|
372
|
+
numlabels: prop.yaxisLabelsCount,
|
373
|
+
unitsPre: prop.yaxisUnitsPre,
|
374
|
+
unitsPost: prop.yaxisUnitsPost,
|
375
|
+
max: this.scale.max,
|
376
|
+
min: this.scale.max * -1,
|
377
|
+
point: prop.yaxisPoint,
|
378
|
+
round: false,
|
379
|
+
thousand: prop.yaxisThousand,
|
380
|
+
decimals: prop.yaxisDecimals,
|
381
|
+
strict: typeof prop.yaxisMax === 'number',
|
382
|
+
formatter: prop.yaxisFormatter
|
383
|
+
});
|
384
|
+
}
|
385
|
+
|
386
|
+
// Now the scale has been generated adopt its max value
|
387
|
+
this.max = this.scale.max;
|
388
|
+
this.min = this.scale.min;
|
389
|
+
prop.yaxisMax = this.scale.max;
|
390
|
+
prop.yaxisMin = this.scale.min;
|
391
|
+
|
392
|
+
|
393
|
+
|
394
|
+
|
395
|
+
// Draw the background first
|
396
|
+
RG.SVG.drawBackground(this);
|
397
|
+
|
398
|
+
|
399
|
+
|
400
|
+
// Draw the axes BEFORE the bars
|
401
|
+
RG.SVG.drawXAxis(this);
|
402
|
+
RG.SVG.drawYAxis(this);
|
403
|
+
|
404
|
+
|
405
|
+
// Draw the bars
|
406
|
+
this.drawBars();
|
407
|
+
|
408
|
+
|
409
|
+
// Draw the labelsAbove labels
|
410
|
+
this.drawLabelsAbove();
|
411
|
+
|
412
|
+
|
413
|
+
|
414
|
+
|
415
|
+
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
|
420
|
+
|
421
|
+
// Draw the key
|
422
|
+
if (typeof prop.key !== null && RG.SVG.drawKey) {
|
423
|
+
RG.SVG.drawKey(this);
|
424
|
+
} else if (!RGraph.SVG.isNull(prop.key)) {
|
425
|
+
alert('The drawKey() function does not exist - have you forgotten to include the key library?');
|
426
|
+
}
|
427
|
+
|
428
|
+
|
429
|
+
|
430
|
+
|
431
|
+
|
432
|
+
|
433
|
+
|
434
|
+
// Add the attribution link. If you're adding this elsewhere on your page/site
|
435
|
+
// and you don't want it displayed then there are options available to not
|
436
|
+
// show it.
|
437
|
+
RG.SVG.attribution(this);
|
438
|
+
|
439
|
+
|
440
|
+
|
441
|
+
|
442
|
+
// Add the event listener that clears the highlight rect if
|
443
|
+
// there is any. Must be MOUSEDOWN (ie before the click event)
|
444
|
+
//var obj = this;
|
445
|
+
//document.body.addEventListener('mousedown', function (e)
|
446
|
+
//{
|
447
|
+
// //RG.SVG.removeHighlight(obj);
|
448
|
+
//
|
449
|
+
//}, false);
|
450
|
+
|
451
|
+
|
452
|
+
|
453
|
+
// Fire the draw event
|
454
|
+
RG.SVG.fireCustomEvent(this, 'ondraw');
|
455
|
+
|
456
|
+
|
457
|
+
|
458
|
+
|
459
|
+
return this;
|
460
|
+
};
|
461
|
+
|
462
|
+
|
463
|
+
|
464
|
+
|
465
|
+
|
466
|
+
|
467
|
+
|
468
|
+
|
469
|
+
//
|
470
|
+
// Draws the bars
|
471
|
+
//
|
472
|
+
this.drawBars = function ()
|
473
|
+
{
|
474
|
+
this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
|
475
|
+
this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
|
476
|
+
|
477
|
+
// The width of the bars
|
478
|
+
var innerWidth = (this.graphWidth / this.data.length) - (2 * prop.hmargin),
|
479
|
+
outerWidth = (this.graphWidth / this.data.length);
|
480
|
+
|
481
|
+
|
482
|
+
// The starting Y coordinate
|
483
|
+
var y = this.getYCoord(0),
|
484
|
+
total = 0;
|
485
|
+
|
486
|
+
|
487
|
+
|
488
|
+
// Loop thru the data drawing the bars
|
489
|
+
for (var i=0; i<(this.data.length); ++i) {
|
490
|
+
|
491
|
+
var prevValue = this.data[i - 1],
|
492
|
+
nextValue = this.data[i + 1],
|
493
|
+
currentValue = this.data[i],
|
494
|
+
prevTotal = total;
|
495
|
+
|
496
|
+
total += parseFloat(this.data[i]) || 0;
|
497
|
+
|
498
|
+
// Figure out the height
|
499
|
+
var height = ma.abs((this.data[i] / (this.scale.max - this.scale.min) ) * this.graphHeight);
|
500
|
+
|
501
|
+
|
502
|
+
|
503
|
+
|
504
|
+
|
505
|
+
|
506
|
+
|
507
|
+
|
508
|
+
|
509
|
+
|
510
|
+
// Work out the starting coord
|
511
|
+
if (prevValue === null) {
|
512
|
+
|
513
|
+
if (currentValue > 0) {
|
514
|
+
y = this.getYCoord(prevTotal) - height;
|
515
|
+
} else {
|
516
|
+
y = this.getYCoord(prevTotal);
|
517
|
+
}
|
518
|
+
|
519
|
+
} else {
|
520
|
+
if (i == 0 && this.data[i] > 0) {
|
521
|
+
y = y - height;
|
522
|
+
|
523
|
+
} else if (this.data[i] > 0 && this.data[i - 1] > 0) {
|
524
|
+
y = y - height;
|
525
|
+
|
526
|
+
} else if (this.data[i] > 0 && this.data[i - 1] < 0) {
|
527
|
+
y = y + prevHeight - height;
|
528
|
+
|
529
|
+
} else if (this.data[i] < 0 && this.data[i - 1] > 0) {
|
530
|
+
// Nada
|
531
|
+
|
532
|
+
} else if (this.data[i] < 0 && this.data[i - 1] < 0) {
|
533
|
+
y = y + prevHeight;
|
534
|
+
}
|
535
|
+
}
|
536
|
+
|
537
|
+
//
|
538
|
+
// Determine the color
|
539
|
+
//
|
540
|
+
var fill = this.data[i] > 0 ? prop.colors[0] : prop.colors[1];
|
541
|
+
|
542
|
+
if (prop.colorsSequential) {
|
543
|
+
fill = prop.colors[i];
|
544
|
+
}
|
545
|
+
|
546
|
+
|
547
|
+
|
548
|
+
|
549
|
+
|
550
|
+
// The last (the total) value if required
|
551
|
+
if (i === (this.data.length - 1) && this.data[this.data.length - 1] >= 0) {
|
552
|
+
y = this.getYCoord(0) - height;
|
553
|
+
|
554
|
+
if (!prop.colorsSequential) {
|
555
|
+
fill = prop.colors[2];
|
556
|
+
}
|
557
|
+
} else if (i === (this.data.length - 1) && this.data[this.data.length - 1] < 0) {
|
558
|
+
y = this.getYCoord(0);
|
559
|
+
|
560
|
+
if (!prop.colorsSequential) {
|
561
|
+
fill = prop.colors[2];
|
562
|
+
}
|
563
|
+
}
|
564
|
+
|
565
|
+
|
566
|
+
|
567
|
+
|
568
|
+
|
569
|
+
|
570
|
+
// Calculate the X coordinate
|
571
|
+
var x = prop.gutterLeft + (outerWidth * i) + prop.hmargin;
|
572
|
+
|
573
|
+
|
574
|
+
|
575
|
+
|
576
|
+
|
577
|
+
// This handles an intermediate total
|
578
|
+
if (this.data[i] === null || typeof this.data[i] === 'undefined') {
|
579
|
+
|
580
|
+
var axisY = this.getYCoord(0);
|
581
|
+
|
582
|
+
if (prevValue < 0) {
|
583
|
+
y = prevY + prevHeight;
|
584
|
+
} else {
|
585
|
+
y = prevY;
|
586
|
+
}
|
587
|
+
|
588
|
+
height = this.getYCoord(0) - this.getYCoord(total);
|
589
|
+
|
590
|
+
// Do this if not sequential colors
|
591
|
+
if (!prop.colorsSequential) {
|
592
|
+
fill = prop.colors[3] || prop.colors[2];
|
593
|
+
}
|
594
|
+
|
595
|
+
if (height < 0) {
|
596
|
+
y += height;
|
597
|
+
height *= -1;
|
598
|
+
}
|
599
|
+
}
|
600
|
+
|
601
|
+
|
602
|
+
|
603
|
+
|
604
|
+
|
605
|
+
|
606
|
+
// Create the rect object
|
607
|
+
var rect = RG.SVG.create({
|
608
|
+
svg: this.svg,
|
609
|
+
type: 'rect',
|
610
|
+
parent: this.svg.all,
|
611
|
+
attr: {
|
612
|
+
x: x,
|
613
|
+
y: y,
|
614
|
+
width: innerWidth,
|
615
|
+
height: height,
|
616
|
+
stroke: prop.strokestyle,
|
617
|
+
fill: fill,
|
618
|
+
'stroke-width': prop.linewidth,
|
619
|
+
'shape-rendering': 'crispEdges',
|
620
|
+
'data-index': i,
|
621
|
+
'data-original-x': x,
|
622
|
+
'data-original-y': y,
|
623
|
+
'data-original-width': innerWidth,
|
624
|
+
'data-original-height': height,
|
625
|
+
'data-original-stroke': prop.strokestyle,
|
626
|
+
'data-original-fill': fill,
|
627
|
+
'data-value': String(this.data[i])
|
628
|
+
}
|
629
|
+
});
|
630
|
+
|
631
|
+
// Store the coordinates
|
632
|
+
this.coords[i] = {
|
633
|
+
object: rect,
|
634
|
+
x: x,
|
635
|
+
y: y,
|
636
|
+
width: innerWidth,
|
637
|
+
height: height
|
638
|
+
};
|
639
|
+
|
640
|
+
|
641
|
+
|
642
|
+
|
643
|
+
|
644
|
+
|
645
|
+
|
646
|
+
|
647
|
+
// Add the tooltips
|
648
|
+
if (!RG.SVG.isNull(prop.tooltips) && prop.tooltips[i]) {
|
649
|
+
|
650
|
+
var obj = this;
|
651
|
+
|
652
|
+
//
|
653
|
+
// Add tooltip event listeners
|
654
|
+
//
|
655
|
+
(function (idx)
|
656
|
+
{
|
657
|
+
rect.addEventListener(prop.tooltipsEvent.replace(/^on/, ''), function (e)
|
658
|
+
{
|
659
|
+
obj.removeHighlight();
|
660
|
+
|
661
|
+
// Show the tooltip
|
662
|
+
RG.SVG.tooltip({
|
663
|
+
object: obj,
|
664
|
+
index: idx,
|
665
|
+
text: prop.tooltips[idx],
|
666
|
+
event: e
|
667
|
+
});
|
668
|
+
|
669
|
+
// Highlight the rect that has been clicked on
|
670
|
+
obj.highlight(e.target);
|
671
|
+
}, false);
|
672
|
+
|
673
|
+
rect.addEventListener('mousemove', function (e)
|
674
|
+
{
|
675
|
+
e.target.style.cursor = 'pointer'
|
676
|
+
}, false);
|
677
|
+
})(i);
|
678
|
+
}
|
679
|
+
|
680
|
+
|
681
|
+
|
682
|
+
|
683
|
+
|
684
|
+
|
685
|
+
|
686
|
+
|
687
|
+
|
688
|
+
|
689
|
+
// Store these for the next iteration of the loop
|
690
|
+
var prevX = x,
|
691
|
+
prevY = y,
|
692
|
+
prevWidth = innerWidth,
|
693
|
+
prevHeight = height,
|
694
|
+
prevValue = this.data[i];
|
695
|
+
}
|
696
|
+
|
697
|
+
|
698
|
+
|
699
|
+
|
700
|
+
|
701
|
+
|
702
|
+
|
703
|
+
|
704
|
+
|
705
|
+
|
706
|
+
|
707
|
+
|
708
|
+
|
709
|
+
|
710
|
+
|
711
|
+
|
712
|
+
|
713
|
+
|
714
|
+
|
715
|
+
|
716
|
+
// Now draw the connecting lines
|
717
|
+
for (var i=0; i<this.coords.length; ++i) {
|
718
|
+
|
719
|
+
if (this.coords[i+1] && this.coords[i+1].object) {
|
720
|
+
|
721
|
+
var x1 = Number(this.coords[i].object.getAttribute('x')) + Number(this.coords[i].object.getAttribute('width')),
|
722
|
+
y1 = parseInt(this.coords[i].object.getAttribute('y')) + (this.data[i] > 0 ? 0 : parseInt(this.coords[i].object.getAttribute('height')) ),
|
723
|
+
x2 = x1 + (2 * prop.hmargin),
|
724
|
+
y2 = parseInt(this.coords[i].object.getAttribute('y')) + (this.data[i] > 0 ? 0 : parseInt(this.coords[i].object.getAttribute('height')) );
|
725
|
+
|
726
|
+
// Handle total columns
|
727
|
+
if(this.coords[i].object.getAttribute('data-value') === 'null') {
|
728
|
+
y1 = parseFloat(this.coords[i].object.getAttribute('y'));
|
729
|
+
y2 = parseFloat(y1);
|
730
|
+
}
|
731
|
+
|
732
|
+
var line = RG.SVG.create({
|
733
|
+
svg: this.svg,
|
734
|
+
type: 'line',
|
735
|
+
parent: this.svg.all,
|
736
|
+
attr: {
|
737
|
+
x1: x1,
|
738
|
+
y1: y1 + 0.5,
|
739
|
+
x2: x2,
|
740
|
+
y2: y2 + 0.5,
|
741
|
+
stroke: prop.strokestyleConnector || prop.strokestyle,
|
742
|
+
'stroke-width': prop.linewidth,
|
743
|
+
'data-index': i,
|
744
|
+
'data-original-x1': x1,
|
745
|
+
'data-original-y1': y1 + 0.5,
|
746
|
+
'data-original-x2': x2,
|
747
|
+
'data-original-y2': y2 + 0.5
|
748
|
+
}
|
749
|
+
});
|
750
|
+
}
|
751
|
+
}
|
752
|
+
};
|
753
|
+
|
754
|
+
|
755
|
+
|
756
|
+
|
757
|
+
|
758
|
+
|
759
|
+
|
760
|
+
|
761
|
+
/**
|
762
|
+
* This function can be used to retrieve the relevant Y coordinate for a
|
763
|
+
* particular value.
|
764
|
+
*
|
765
|
+
* @param int value The value to get the Y coordinate for
|
766
|
+
*/
|
767
|
+
this.getYCoord = function (value)
|
768
|
+
{
|
769
|
+
var prop = this.properties;
|
770
|
+
|
771
|
+
if (value > this.scale.max) {
|
772
|
+
return null;
|
773
|
+
}
|
774
|
+
|
775
|
+
var y, xaxispos = prop.xaxispos;
|
776
|
+
|
777
|
+
if (value < this.scale.min) {
|
778
|
+
return null;
|
779
|
+
}
|
780
|
+
|
781
|
+
y = ((value - this.scale.min) / (this.scale.max - this.scale.min));
|
782
|
+
y *= (this.height - prop.gutterTop - prop.gutterBottom);
|
783
|
+
|
784
|
+
y = this.height - prop.gutterBottom - y;
|
785
|
+
|
786
|
+
return y;
|
787
|
+
};
|
788
|
+
|
789
|
+
|
790
|
+
|
791
|
+
|
792
|
+
|
793
|
+
|
794
|
+
|
795
|
+
|
796
|
+
/**
|
797
|
+
* This function can be used to highlight a bar on the chart
|
798
|
+
*
|
799
|
+
* @param object rect The rectangle to highlight
|
800
|
+
*/
|
801
|
+
this.highlight = function (rect)
|
802
|
+
{
|
803
|
+
var x = rect.getAttribute('x'),
|
804
|
+
y = rect.getAttribute('y'),
|
805
|
+
width = rect.getAttribute('width'),
|
806
|
+
height = rect.getAttribute('height');
|
807
|
+
|
808
|
+
var highlight = RG.SVG.create({
|
809
|
+
svg: this.svg,
|
810
|
+
type: 'rect',
|
811
|
+
parent: this.svg.all,
|
812
|
+
attr: {
|
813
|
+
stroke: prop.highlightStroke,
|
814
|
+
fill: prop.highlightFill,
|
815
|
+
x: x,
|
816
|
+
y: y,
|
817
|
+
width: width,
|
818
|
+
height: height,
|
819
|
+
'stroke-width': prop.highlightLinewidth
|
820
|
+
}
|
821
|
+
});
|
822
|
+
|
823
|
+
|
824
|
+
//if (prop.tooltipsEvent === 'mousemove') {
|
825
|
+
|
826
|
+
//var obj = this;
|
827
|
+
|
828
|
+
//highlight.addEventListener('mouseout', function (e)
|
829
|
+
//{
|
830
|
+
// obj.removeHighlight();
|
831
|
+
// RG.SVG.hideTooltip();
|
832
|
+
// RG.SVG.REG.set('highlight', null);
|
833
|
+
//}, false);
|
834
|
+
//}
|
835
|
+
|
836
|
+
|
837
|
+
// Store the highlight rect in the rebistry so
|
838
|
+
// it can be cleared later
|
839
|
+
RG.SVG.REG.set('highlight', highlight);
|
840
|
+
};
|
841
|
+
|
842
|
+
|
843
|
+
|
844
|
+
|
845
|
+
|
846
|
+
|
847
|
+
|
848
|
+
|
849
|
+
/**
|
850
|
+
* This allows for easy specification of gradients
|
851
|
+
*/
|
852
|
+
this.parseColors = function ()
|
853
|
+
{
|
854
|
+
// Save the original colors so that they can be restored when
|
855
|
+
// the canvas is cleared
|
856
|
+
if (!Object.keys(this.originalColors).length) {
|
857
|
+
this.originalColors = {
|
858
|
+
colors: RG.SVG.arrayClone(prop.colors),
|
859
|
+
backgroundGridColor: RG.SVG.arrayClone(prop.backgroundGridColor),
|
860
|
+
highlightFill: RG.SVG.arrayClone(prop.highlightFill),
|
861
|
+
backgroundColor: RG.SVG.arrayClone(prop.backgroundColor)
|
862
|
+
}
|
863
|
+
}
|
864
|
+
|
865
|
+
|
866
|
+
// colors
|
867
|
+
var colors = prop.colors;
|
868
|
+
|
869
|
+
if (colors) {
|
870
|
+
for (var i=0; i<colors.length; ++i) {
|
871
|
+
colors[i] = RG.SVG.parseColorLinear({
|
872
|
+
object: this,
|
873
|
+
color: colors[i]
|
874
|
+
});
|
875
|
+
}
|
876
|
+
}
|
877
|
+
|
878
|
+
prop.backgroundGridColor = RG.SVG.parseColorLinear({object: this, color: prop.backgroundGridColor});
|
879
|
+
prop.highlightFill = RG.SVG.parseColorLinear({object: this, color: prop.highlightFill});
|
880
|
+
prop.backgroundColor = RG.SVG.parseColorLinear({object: this, color: prop.backgroundColor});
|
881
|
+
};
|
882
|
+
|
883
|
+
|
884
|
+
|
885
|
+
|
886
|
+
|
887
|
+
|
888
|
+
|
889
|
+
|
890
|
+
//
|
891
|
+
// Draws the labelsAbove
|
892
|
+
//
|
893
|
+
this.drawLabelsAbove = function ()
|
894
|
+
{
|
895
|
+
// Go through the above labels
|
896
|
+
if (prop.labelsAbove) {
|
897
|
+
|
898
|
+
var total = 0;
|
899
|
+
|
900
|
+
for (var i=0; i<this.coords.length; ++i) {
|
901
|
+
|
902
|
+
var num = this.data[i],
|
903
|
+
total = total + num;
|
904
|
+
|
905
|
+
if (typeof num === 'number' || RG.SVG.isNull(num)) {
|
906
|
+
|
907
|
+
if (RG.SVG.isNull(num)) {
|
908
|
+
num = total;
|
909
|
+
}
|
910
|
+
|
911
|
+
var str = RG.SVG.numberFormat({
|
912
|
+
object: this,
|
913
|
+
num: num.toFixed(prop.labelsAboveDecimals),
|
914
|
+
prepend: typeof prop.labelsAboveUnitsPre === 'string' ? prop.labelsAboveUnitsPre : null,
|
915
|
+
append: typeof prop.labelsAboveUnitsPost === 'string' ? prop.labelsAboveUnitsPost : null,
|
916
|
+
point: typeof prop.labelsAbovePoint === 'string' ? prop.labelsAbovePoint : null,
|
917
|
+
thousand: typeof prop.labelsAboveThousand === 'string' ? prop.labelsAboveThousand : null,
|
918
|
+
formatter: typeof prop.labelsAboveFormatter === 'function' ? prop.labelsAboveFormatter : null
|
919
|
+
});
|
920
|
+
|
921
|
+
// Facilitate labelsAboveSpecific
|
922
|
+
if (prop.labelsAboveSpecific && prop.labelsAboveSpecific.length && (typeof prop.labelsAboveSpecific[i] === 'string' || typeof prop.labelsAboveSpecific[i] === 'number') ) {
|
923
|
+
str = prop.labelsAboveSpecific[i];
|
924
|
+
} else if ( prop.labelsAboveSpecific && prop.labelsAboveSpecific.length && typeof prop.labelsAboveSpecific[i] !== 'string' && typeof prop.labelsAboveSpecific[i] !== 'number') {
|
925
|
+
continue;
|
926
|
+
}
|
927
|
+
|
928
|
+
var x = parseFloat(this.coords[i].object.getAttribute('x')) + parseFloat(this.coords[i].object.getAttribute('width') / 2) + prop.labelsAboveOffsetx;
|
929
|
+
|
930
|
+
if (this.data[i] >= 0) {
|
931
|
+
var y = parseFloat(this.coords[i].object.getAttribute('y')) - 7 + prop.labelsAboveOffsety;
|
932
|
+
var valign = prop.labelsAboveValign;
|
933
|
+
} else {
|
934
|
+
var y = parseFloat(this.coords[i].object.getAttribute('y')) + parseFloat(this.coords[i].object.getAttribute('height')) + 7 - prop.labelsAboveOffsety;
|
935
|
+
var valign = prop.labelsAboveValign === 'top' ? 'bottom' : 'top';
|
936
|
+
}
|
937
|
+
|
938
|
+
RG.SVG.text({
|
939
|
+
object: this,
|
940
|
+
parent: this.svg.all,
|
941
|
+
text: str,
|
942
|
+
x: x,
|
943
|
+
y: y,
|
944
|
+
halign: prop.labelsAboveHalign,
|
945
|
+
valign: valign,
|
946
|
+
font: prop.labelsAboveFont || prop.textFont,
|
947
|
+
size: prop.labelsAboveSize || prop.textSize,
|
948
|
+
bold: prop.labelsAboveBold || prop.textBold,
|
949
|
+
italic: prop.labelsAboveItalic || prop.textItalic,
|
950
|
+
color: prop.labelsAboveColor || prop.textColor,
|
951
|
+
background: prop.labelsAboveBackground || null,
|
952
|
+
padding: prop.labelsAboveBackgroundPadding || 0
|
953
|
+
});
|
954
|
+
}
|
955
|
+
}
|
956
|
+
}
|
957
|
+
};
|
958
|
+
|
959
|
+
|
960
|
+
|
961
|
+
|
962
|
+
|
963
|
+
|
964
|
+
|
965
|
+
|
966
|
+
/**
|
967
|
+
* Using a function to add events makes it easier to facilitate method
|
968
|
+
* chaining
|
969
|
+
*
|
970
|
+
* @param string type The type of even to add
|
971
|
+
* @param function func
|
972
|
+
*/
|
973
|
+
this.on = function (type, func)
|
974
|
+
{
|
975
|
+
if (type.substr(0,2) !== 'on') {
|
976
|
+
type = 'on' + type;
|
977
|
+
}
|
978
|
+
|
979
|
+
RG.SVG.addCustomEventListener(this, type, func);
|
980
|
+
|
981
|
+
return this;
|
982
|
+
};
|
983
|
+
|
984
|
+
|
985
|
+
|
986
|
+
|
987
|
+
|
988
|
+
|
989
|
+
|
990
|
+
|
991
|
+
//
|
992
|
+
// Used in chaining. Runs a function there and then - not waiting for
|
993
|
+
// the events to fire (eg the onbeforedraw event)
|
994
|
+
//
|
995
|
+
// @param function func The function to execute
|
996
|
+
//
|
997
|
+
this.exec = function (func)
|
998
|
+
{
|
999
|
+
func(this);
|
1000
|
+
|
1001
|
+
return this;
|
1002
|
+
};
|
1003
|
+
|
1004
|
+
|
1005
|
+
|
1006
|
+
|
1007
|
+
|
1008
|
+
|
1009
|
+
|
1010
|
+
|
1011
|
+
//
|
1012
|
+
// Remove highlight from the chart (tooltips)
|
1013
|
+
//
|
1014
|
+
this.removeHighlight = function ()
|
1015
|
+
{
|
1016
|
+
var highlight = RG.SVG.REG.get('highlight');
|
1017
|
+
if (highlight && highlight.parentNode) {
|
1018
|
+
highlight.parentNode.removeChild(highlight);
|
1019
|
+
}
|
1020
|
+
|
1021
|
+
RG.SVG.REG.set('highlight', null);
|
1022
|
+
};
|
1023
|
+
|
1024
|
+
|
1025
|
+
|
1026
|
+
|
1027
|
+
|
1028
|
+
|
1029
|
+
|
1030
|
+
|
1031
|
+
//
|
1032
|
+
// The Bar chart grow effect
|
1033
|
+
//
|
1034
|
+
this.grow = function ()
|
1035
|
+
{
|
1036
|
+
var opt = arguments[0] || {},
|
1037
|
+
frames = opt.frames || 30,
|
1038
|
+
frame = 0,
|
1039
|
+
obj = this,
|
1040
|
+
data = [],
|
1041
|
+
height = null,
|
1042
|
+
seq = 0;
|
1043
|
+
/*
|
1044
|
+
//
|
1045
|
+
// Copy the data
|
1046
|
+
//
|
1047
|
+
data = RG.SVG.arrayClone(this.data);
|
1048
|
+
|
1049
|
+
this.draw();
|
1050
|
+
|
1051
|
+
var iterate = function ()
|
1052
|
+
{
|
1053
|
+
|
1054
|
+
for (var i=0,seq=0,len=obj.coords.length; i<len; ++i, ++seq) {
|
1055
|
+
|
1056
|
+
var multiplier = (frame / frames)
|
1057
|
+
* RG.SVG.FX.getEasingMultiplier(frames, frame)
|
1058
|
+
* RG.SVG.FX.getEasingMultiplier(frames, frame);
|
1059
|
+
|
1060
|
+
|
1061
|
+
|
1062
|
+
|
1063
|
+
// TODO Go through the data and update the value according to
|
1064
|
+
// the frame number
|
1065
|
+
if (typeof data[i] === 'number') {
|
1066
|
+
|
1067
|
+
height = ma.abs(obj.getYCoord(data[i]) - obj.getYCoord(0));
|
1068
|
+
obj.data[i] = data[i] * multiplier;
|
1069
|
+
height = multiplier * height;
|
1070
|
+
|
1071
|
+
// Set the new height on the rect
|
1072
|
+
obj.coords[seq].object.setAttribute(
|
1073
|
+
'height',
|
1074
|
+
height
|
1075
|
+
);
|
1076
|
+
|
1077
|
+
// Set the correct Y coord on the object
|
1078
|
+
obj.coords[seq].object.setAttribute(
|
1079
|
+
'y',
|
1080
|
+
data[i] < 0 ? obj.getYCoord(0) : obj.getYCoord(0) - height
|
1081
|
+
);
|
1082
|
+
|
1083
|
+
} else if (typeof data[i] === 'object') {
|
1084
|
+
|
1085
|
+
var accumulativeHeight = 0;
|
1086
|
+
|
1087
|
+
for (var j=0,len2=data[i].length; j<len2; ++j, ++seq) {
|
1088
|
+
|
1089
|
+
height = ma.abs(obj.getYCoord(data[i][j]) - obj.getYCoord(0));
|
1090
|
+
height = multiplier * height;
|
1091
|
+
obj.data[i][j] = data[i][j] * multiplier;
|
1092
|
+
|
1093
|
+
obj.coords[seq].object.setAttribute(
|
1094
|
+
'height',
|
1095
|
+
height
|
1096
|
+
);
|
1097
|
+
|
1098
|
+
obj.coords[seq].object.setAttribute(
|
1099
|
+
'y',
|
1100
|
+
data[i][j] < 0 ? (obj.getYCoord(0) + accumulativeHeight) : (obj.getYCoord(0) - height - accumulativeHeight)
|
1101
|
+
);
|
1102
|
+
|
1103
|
+
accumulativeHeight += (prop.grouping === 'stacked' ? height : 0);
|
1104
|
+
}
|
1105
|
+
|
1106
|
+
//
|
1107
|
+
// Set the height and Y cooord of the backfaces if necessary
|
1108
|
+
//
|
1109
|
+
if (obj.stackedBackfaces[i]) {
|
1110
|
+
obj.stackedBackfaces[i].setAttribute(
|
1111
|
+
'height',
|
1112
|
+
accumulativeHeight
|
1113
|
+
);
|
1114
|
+
|
1115
|
+
obj.stackedBackfaces[i].setAttribute(
|
1116
|
+
'y',
|
1117
|
+
obj.height - prop.gutterBottom - accumulativeHeight
|
1118
|
+
);
|
1119
|
+
}
|
1120
|
+
|
1121
|
+
// Decrease seq by one so that it's not incremented twice
|
1122
|
+
--seq;
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
if (frame++ < frames) {
|
1127
|
+
//setTimeout(iterate, frame > 1 ? opt.delay : 200);
|
1128
|
+
RG.SVG.FX.update(iterate);
|
1129
|
+
} else if (opt.callback) {
|
1130
|
+
(opt.callback)(obj);
|
1131
|
+
}
|
1132
|
+
};
|
1133
|
+
|
1134
|
+
iterate();
|
1135
|
+
*/
|
1136
|
+
return this;
|
1137
|
+
};
|
1138
|
+
|
1139
|
+
|
1140
|
+
|
1141
|
+
|
1142
|
+
|
1143
|
+
|
1144
|
+
|
1145
|
+
|
1146
|
+
/**
|
1147
|
+
* HBar chart Wave effect.
|
1148
|
+
*
|
1149
|
+
* @param object OPTIONAL An object map of options. You specify 'frames'
|
1150
|
+
* here to give the number of frames in the effect
|
1151
|
+
* and also callback to specify a callback function
|
1152
|
+
* thats called at the end of the effect
|
1153
|
+
*/
|
1154
|
+
this.wave = function ()
|
1155
|
+
{
|
1156
|
+
/*
|
1157
|
+
// First draw the chart
|
1158
|
+
this.draw();
|
1159
|
+
|
1160
|
+
|
1161
|
+
var obj = this,
|
1162
|
+
opt = arguments[0] || {};
|
1163
|
+
|
1164
|
+
opt.frames = opt.frames || 60;
|
1165
|
+
opt.startFrames = [];
|
1166
|
+
opt.counters = [];
|
1167
|
+
|
1168
|
+
var framesperbar = opt.frames / 3,
|
1169
|
+
frame = -1,
|
1170
|
+
callback = opt.callback || function () {};
|
1171
|
+
|
1172
|
+
for (var i=0,len=this.coords.length; i<len; i+=1) {
|
1173
|
+
opt.startFrames[i] = ((opt.frames / 2) / (obj.coords.length - 1)) * i;
|
1174
|
+
opt.counters[i] = 0;
|
1175
|
+
|
1176
|
+
// Now zero the width of the bar
|
1177
|
+
this.coords[i].object.setAttribute('height', 0);
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
|
1181
|
+
function iterator ()
|
1182
|
+
{
|
1183
|
+
++frame;
|
1184
|
+
|
1185
|
+
for (var i=0,len=obj.coords.length; i<len; i+=1) {
|
1186
|
+
if (frame > opt.startFrames[i]) {
|
1187
|
+
|
1188
|
+
var originalHeight = obj.coords[i].object.getAttribute('data-original-height'),
|
1189
|
+
height,
|
1190
|
+
value = parseFloat(obj.coords[i].object.getAttribute('data-value'));
|
1191
|
+
|
1192
|
+
obj.coords[i].object.setAttribute(
|
1193
|
+
'height',
|
1194
|
+
height = ma.min(
|
1195
|
+
((frame - opt.startFrames[i]) / framesperbar) * originalHeight,
|
1196
|
+
originalHeight
|
1197
|
+
)
|
1198
|
+
);
|
1199
|
+
|
1200
|
+
obj.coords[i].object.setAttribute(
|
1201
|
+
'y',
|
1202
|
+
value >=0 ? obj.getYCoord(0) - height : obj.getYCoord(0)
|
1203
|
+
);
|
1204
|
+
|
1205
|
+
if (prop.grouping === 'stacked') {
|
1206
|
+
var seq = obj.coords[i].object.getAttribute('data-sequential-index');
|
1207
|
+
|
1208
|
+
var indexes = RG.SVG.sequentialIndexToGrouped(seq, obj.data);
|
1209
|
+
|
1210
|
+
if (indexes[1] > 0) {
|
1211
|
+
obj.coords[i].object.setAttribute(
|
1212
|
+
'y',
|
1213
|
+
parseInt(obj.coords[i - 1].object.getAttribute('y')) - height
|
1214
|
+
);
|
1215
|
+
}
|
1216
|
+
}
|
1217
|
+
}
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
|
1221
|
+
if (frame >= opt.frames) {
|
1222
|
+
callback(obj);
|
1223
|
+
} else {
|
1224
|
+
RG.SVG.FX.update(iterator);
|
1225
|
+
}
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
iterator();
|
1229
|
+
*/
|
1230
|
+
return this;
|
1231
|
+
};
|
1232
|
+
|
1233
|
+
|
1234
|
+
|
1235
|
+
|
1236
|
+
|
1237
|
+
|
1238
|
+
|
1239
|
+
|
1240
|
+
//
|
1241
|
+
// Set the options that the user has provided
|
1242
|
+
//
|
1243
|
+
for (i in conf.options) {
|
1244
|
+
if (typeof i === 'string') {
|
1245
|
+
this.set(i, conf.options[i]);
|
1246
|
+
}
|
1247
|
+
}
|
1248
|
+
};
|
1249
|
+
|
1250
|
+
return this;
|
1251
|
+
|
1252
|
+
// End module pattern
|
1253
|
+
})(window, document);
|