rgraph-rails 1.0.7 → 1.0.8

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/rgraph-rails/version.rb +1 -1
  4. data/license.txt +4 -16
  5. data/vendor/assets/javascripts/RGraph.bar.js +3734 -241
  6. data/vendor/assets/javascripts/RGraph.bipolar.js +2005 -115
  7. data/vendor/assets/javascripts/RGraph.common.annotate.js +395 -35
  8. data/vendor/assets/javascripts/RGraph.common.context.js +595 -30
  9. data/vendor/assets/javascripts/RGraph.common.core.js +5282 -405
  10. data/vendor/assets/javascripts/RGraph.common.csv.js +276 -19
  11. data/vendor/assets/javascripts/RGraph.common.deprecated.js +450 -35
  12. data/vendor/assets/javascripts/RGraph.common.dynamic.js +1395 -86
  13. data/vendor/assets/javascripts/RGraph.common.effects.js +1545 -90
  14. data/vendor/assets/javascripts/RGraph.common.key.js +753 -54
  15. data/vendor/assets/javascripts/RGraph.common.resizing.js +563 -37
  16. data/vendor/assets/javascripts/RGraph.common.sheets.js +352 -29
  17. data/vendor/assets/javascripts/RGraph.common.tooltips.js +450 -32
  18. data/vendor/assets/javascripts/RGraph.common.zoom.js +219 -14
  19. data/vendor/assets/javascripts/RGraph.drawing.background.js +570 -35
  20. data/vendor/assets/javascripts/RGraph.drawing.circle.js +544 -35
  21. data/vendor/assets/javascripts/RGraph.drawing.image.js +755 -52
  22. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +645 -41
  23. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +633 -37
  24. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +514 -36
  25. data/vendor/assets/javascripts/RGraph.drawing.poly.js +559 -39
  26. data/vendor/assets/javascripts/RGraph.drawing.rect.js +548 -35
  27. data/vendor/assets/javascripts/RGraph.drawing.text.js +664 -36
  28. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +812 -50
  29. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +856 -51
  30. data/vendor/assets/javascripts/RGraph.fuel.js +964 -58
  31. data/vendor/assets/javascripts/RGraph.funnel.js +984 -55
  32. data/vendor/assets/javascripts/RGraph.gantt.js +1354 -77
  33. data/vendor/assets/javascripts/RGraph.gauge.js +1421 -87
  34. data/vendor/assets/javascripts/RGraph.hbar.js +2562 -146
  35. data/vendor/assets/javascripts/RGraph.hprogress.js +1401 -80
  36. data/vendor/assets/javascripts/RGraph.line.js +4226 -244
  37. data/vendor/assets/javascripts/RGraph.meter.js +1280 -74
  38. data/vendor/assets/javascripts/RGraph.modaldialog.js +301 -19
  39. data/vendor/assets/javascripts/RGraph.odo.js +1264 -71
  40. data/vendor/assets/javascripts/RGraph.pie.js +2288 -137
  41. data/vendor/assets/javascripts/RGraph.radar.js +1847 -110
  42. data/vendor/assets/javascripts/RGraph.rose.js +1977 -108
  43. data/vendor/assets/javascripts/RGraph.rscatter.js +1432 -80
  44. data/vendor/assets/javascripts/RGraph.scatter.js +3036 -168
  45. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1120 -60
  46. data/vendor/assets/javascripts/RGraph.svg.bar.js +1067 -0
  47. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +247 -0
  48. data/vendor/assets/javascripts/RGraph.svg.common.core.js +3363 -0
  49. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +277 -0
  50. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +1304 -0
  51. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +353 -0
  52. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +233 -0
  53. data/vendor/assets/javascripts/RGraph.svg.hbar.js +1141 -0
  54. data/vendor/assets/javascripts/RGraph.svg.line.js +1486 -0
  55. data/vendor/assets/javascripts/RGraph.svg.pie.js +781 -0
  56. data/vendor/assets/javascripts/RGraph.svg.radar.js +1326 -0
  57. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +817 -0
  58. data/vendor/assets/javascripts/RGraph.thermometer.js +1135 -62
  59. data/vendor/assets/javascripts/RGraph.vprogress.js +1470 -83
  60. data/vendor/assets/javascripts/RGraph.waterfall.js +1347 -80
  61. metadata +15 -3
@@ -0,0 +1,1067 @@
1
+ // version: 2017-01-02
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.Bar = function (conf)
28
+ {
29
+ this.id = conf.id;
30
+ this.uid = RG.SVG.createUID();
31
+ this.container = document.getElementById(this.id);
32
+ this.svg = RG.SVG.createSVG({container: this.container});
33
+ this.isRGraph = true;
34
+ this.width = Number(this.svg.getAttribute('width'));
35
+ this.height = Number(this.svg.getAttribute('height'));
36
+ this.data = conf.data;
37
+ this.type = 'bar';
38
+ this.coords = [];
39
+ this.stackedBackfaces = [];
40
+ this.colorsParsed = false;
41
+ this.originalColors = {};
42
+ this.gradientCounter = 1;
43
+
44
+ // Add this object to the ObjectRegistry
45
+ RG.SVG.OR.add(this);
46
+
47
+ this.container.style.display = 'inline-block';
48
+
49
+ this.properties =
50
+ {
51
+ gutterLeft: 35,
52
+ gutterRight: 35,
53
+ gutterTop: 35,
54
+ gutterBottom: 35,
55
+
56
+ backgroundGrid: true,
57
+ backgroundGridColor: '#ddd',
58
+ backgroundGridLinewidth: 1,
59
+ backgroundGridHlines: true,
60
+ backgroundGridHlinesCount: null,
61
+ backgroundGridVlines: true,
62
+ backgroundGridVlinesCount: null,
63
+ backgroundGridBorder: true,
64
+
65
+ // 20 colors. If you need more you need to set the colors property
66
+ colors: [
67
+ 'red', '#0f0', '#00f', '#ff0', '#0ff', '#0f0','pink','orange','gray','black',
68
+ 'red', '#0f0', '#00f', '#ff0', '#0ff', '#0f0','pink','orange','gray','black'
69
+ ],
70
+ colorsSequential: false,
71
+ strokestyle: 'rgba(0,0,0,0)',
72
+
73
+ hmargin: 3,
74
+ hmarginGrouped: 2,
75
+
76
+ yaxis: true,
77
+ yaxisTickmarks: true,
78
+ yaxisTickmarksLength: 3,
79
+ yaxisColor: 'black',
80
+
81
+ yaxisScale: true,
82
+ yaxisLabels: null,
83
+ yaxisLabelsOffsetx: 0,
84
+ yaxisLabelsOffsety: 0,
85
+ yaxisLabelsCount: 5,
86
+
87
+ yaxisUnitsPre: '',
88
+ yaxisUnitsPost: '',
89
+ yaxisStrict: false,
90
+ yaxisDecimals: 0,
91
+ yaxisPoint: '.',
92
+ yaxisThousand: ',',
93
+ yaxisRound: false,
94
+ yaxisMax: null,
95
+ yaxisMin: 0,
96
+ yaxisFormatter: null,
97
+
98
+ xaxis: true,
99
+ xaxisTickmarks: true,
100
+ xaxisTickmarksLength: 3,
101
+ xaxisLabels: null,
102
+ xaxisLabelsPosition: 'section',
103
+ xaxisLabelsPositionEdgeTickmarksCount: null,
104
+ xaxisColor: 'black',
105
+ xaxisLabelsOffsetx: 0,
106
+ xaxisLabelsOffsety: 0,
107
+
108
+ labelsAbove: false,
109
+ labelsAboveFont: null,
110
+ labelsAboveSize: null,
111
+ labelsAboveBold: null,
112
+ labelsAboveItalic: null,
113
+ labelsAboveColor: null,
114
+ labelsAboveBackground: null,
115
+ labelsAboveBackgroundPadding: 0,
116
+ labelsAboveUnitsPre: null,
117
+ labelsAboveUnitsPost: null,
118
+ labelsAbovePoint: null,
119
+ labelsAboveThousand: null,
120
+ labelsAboveFormatter: null,
121
+ labelsAboveDecimals: null,
122
+ labelsAboveOffsetx: 0,
123
+ labelsAboveOffsety: 0,
124
+ labelsAboveHalign: 'center',
125
+ labelsAboveValign: 'bottom',
126
+
127
+ textColor: 'black',
128
+ textFont: 'sans-serif',
129
+ textSize: 12,
130
+ textBold: false,
131
+ textItalic: false,
132
+
133
+ linewidth: 1,
134
+ grouping: 'grouped',
135
+
136
+ tooltips: null,
137
+ tooltipsOverride: null,
138
+ tooltipsEffect: 'fade',
139
+ tooltipsCssClass: 'RGraph_tooltip',
140
+ tooltipsEvent: 'click',
141
+
142
+ highlightStroke: 'rgba(0,0,0,0)',
143
+ highlightFill: 'rgba(255,255,255,0.7)',
144
+ highlightLinewidth: 1,
145
+
146
+ title: '',
147
+ titleSize: 16,
148
+ titleX: null,
149
+ titleY: null,
150
+ titleHalign: 'center',
151
+ titleValign: 'bottom',
152
+ titleColor: 'black',
153
+ titleFont: null,
154
+ titleBold: false,
155
+ titleItalic: false,
156
+
157
+ titleSubtitle: '',
158
+ titleSubtitleSize: 10,
159
+ titleSubtitleX: null,
160
+ titleSubtitleY: null,
161
+ titleSubtitleHalign: 'center',
162
+ titleSubtitleValign: 'top',
163
+ titleSubtitleColor: '#aaa',
164
+ titleSubtitleFont: null,
165
+ titleSubtitleBold: false,
166
+ titleSubtitleItalic: false,
167
+
168
+ shadow: false,
169
+ shadowOffsetx: 2,
170
+ shadowOffsety: 2,
171
+ shadowBlur: 2,
172
+ shadowOpacity: 0.25,
173
+
174
+ attribution: true,
175
+ attributionX: null,
176
+ attributionY: null,
177
+ attributionHref: 'http://www.rgraph.net/svg/index.html',
178
+ attributionHalign: 'right',
179
+ attributionValign: 'bottom',
180
+ attributionSize: 8,
181
+ attributionColor: 'gray',
182
+ attributionFont: 'sans-serif',
183
+ attributionItalic: false,
184
+ attributionBold: false
185
+ };
186
+
187
+
188
+
189
+
190
+
191
+ /**
192
+ * "Decorate" the object with the generic effects if the effects library has been included
193
+ */
194
+ if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
195
+ RG.SVG.FX.decorate(this);
196
+ }
197
+
198
+
199
+
200
+
201
+ var prop = this.properties;
202
+
203
+
204
+
205
+
206
+
207
+ //
208
+ // A setter that the constructor uses (at the end)
209
+ // to set all of the properties
210
+ //
211
+ // @param string name The name of the property to set
212
+ // @param string value The value to set the property to
213
+ //
214
+ this.set = function (name, value)
215
+ {
216
+ if (arguments.length === 1 && typeof name === 'object') {
217
+ for (i in arguments[0]) {
218
+ if (typeof i === 'string') {
219
+ this.set(i, arguments[0][i]);
220
+ }
221
+ }
222
+ } else {
223
+ this.properties[name] = value;
224
+ }
225
+
226
+ return this;
227
+ };
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+ //
237
+ // The draw method draws the Bar chart
238
+ //
239
+ this.draw = function ()
240
+ {
241
+ // Fire the beforedraw event
242
+ RG.SVG.fireCustomEvent(this, 'onbeforedraw');
243
+
244
+
245
+
246
+
247
+ // Create the defs tag if necessary
248
+ RG.SVG.createDefs(this);
249
+
250
+
251
+
252
+
253
+
254
+ this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
255
+ this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
256
+
257
+
258
+
259
+ /**
260
+ * Parse the colors. This allows for simple gradient syntax
261
+ */
262
+ if (!this.colorsParsed) {
263
+ this.parseColors();
264
+
265
+ // Don't want to do this again
266
+ this.colorsParsed = true;
267
+ }
268
+
269
+
270
+
271
+ // Go through the data and work out the maximum value
272
+ var values = [];
273
+
274
+ for (var i=0,max=0; i<this.data.length; ++i) {
275
+ if (typeof this.data[i] === 'number') {
276
+ values.push(this.data[i]);
277
+
278
+ } else if (RG.SVG.isArray(this.data[i]) && prop.grouping === 'grouped') {
279
+ values.push(RG.SVG.arrayMax(this.data[i]));
280
+
281
+ } else if (RG.SVG.isArray(this.data[i]) && prop.grouping === 'stacked') {
282
+ values.push(RG.SVG.arraySum(this.data[i]));
283
+ }
284
+ }
285
+ var max = RG.SVG.arrayMax(values);
286
+
287
+ // A custom, user-specified maximum value
288
+ if (typeof prop.yaxisMax === 'number') {
289
+ max = prop.yaxisMax;
290
+ }
291
+
292
+ // Set the ymin to zero if it's szet mirror
293
+ if (prop.yaxisMin === 'mirror' || prop.yaxisMin === 'middle' || prop.yaxisMin === 'center') {
294
+ var mirrorScale = true;
295
+ prop.yaxisMin = 0;
296
+ }
297
+
298
+
299
+ //
300
+ // Generate an appropiate scale
301
+ //
302
+ this.scale = RG.SVG.getScale({
303
+ object: this,
304
+ numlabels: prop.yaxisLabelsCount,
305
+ unitsPre: prop.yaxisUnitsPre,
306
+ unitsPost: prop.yaxisUnitsPost,
307
+ max: max,
308
+ min: prop.yaxisMin,
309
+ point: prop.yaxisPoint,
310
+ round: prop.yaxisRound,
311
+ thousand: prop.yaxisThousand,
312
+ decimals: prop.yaxisDecimals,
313
+ strict: typeof prop.yaxisMax === 'number',
314
+ formatter: prop.yaxisFormatter
315
+ });
316
+
317
+
318
+
319
+ //
320
+ // Get the scale a second time if the ymin should be mirored
321
+ //
322
+ // Set the ymin to zero if it's szet mirror
323
+ if (mirrorScale) {
324
+ this.scale = RG.SVG.getScale({
325
+ object: this,
326
+ numlabels: prop.yaxisLabelsCount,
327
+ unitsPre: prop.yaxisUnitsPre,
328
+ unitsPost: prop.yaxisUnitsPost,
329
+ max: this.scale.max,
330
+ min: this.scale.max * -1,
331
+ point: prop.yaxisPoint,
332
+ round: false,
333
+ thousand: prop.yaxisThousand,
334
+ decimals: prop.yaxisDecimals,
335
+ strict: typeof prop.yaxisMax === 'number',
336
+ formatter: prop.yaxisFormatter
337
+ });
338
+ }
339
+
340
+ // Now the scale has been generated adopt its max value
341
+ this.max = this.scale.max;
342
+ this.min = this.scale.min;
343
+ prop.yaxisMax = this.scale.max;
344
+ prop.yaxisMin = this.scale.min;
345
+
346
+
347
+
348
+
349
+ // Draw the background first
350
+ RG.SVG.drawBackground(this);
351
+
352
+ // Draw the bars
353
+ this.drawBars();
354
+
355
+
356
+ // Draw the axes over the bars
357
+ RG.SVG.drawXAxis(this);
358
+ RG.SVG.drawYAxis(this);
359
+
360
+
361
+ // Draw the labelsAbove labels
362
+ this.drawLabelsAbove();
363
+
364
+
365
+
366
+
367
+
368
+ // Add the attribution link. If you're adding this elsewhere on your page/site
369
+ // and you don't want it displayed then there are options available to not
370
+ // show it.
371
+ RG.SVG.attribution(this);
372
+
373
+
374
+
375
+
376
+ // Add the event listener that clears the highlight rect if
377
+ // there is any. Must be MOUSEDOWN (ie before the click event)
378
+ var obj = this;
379
+ document.body.addEventListener('mousedown', function (e)
380
+ {
381
+ RG.SVG.removeHighlight(obj);
382
+
383
+ }, false);
384
+
385
+
386
+
387
+ // Fire the draw event
388
+ RG.SVG.fireCustomEvent(this, 'ondraw');
389
+
390
+
391
+
392
+
393
+ return this;
394
+ };
395
+
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+ //
404
+ // Draws the bars
405
+ //
406
+ this.drawBars = function ()
407
+ {
408
+ var y = this.getYCoord(0);
409
+
410
+ if (prop.shadow) {
411
+ RG.SVG.setShadow({
412
+ object: this,
413
+ offsetx: prop.shadowOffsetx,
414
+ offsety: prop.shadowOffsety,
415
+ blur: prop.shadowBlur,
416
+ opacity: prop.shadowOpacity,
417
+ id: 'dropShadow'
418
+ });
419
+ }
420
+
421
+ // Go through the bars
422
+ for (var i=0,sequentialIndex=0; i<this.data.length; ++i,++sequentialIndex) {
423
+
424
+ //
425
+ // Regular bars
426
+ //
427
+ if (typeof this.data[i] === 'number') {
428
+
429
+ var outerSegment = this.graphWidth / this.data.length,
430
+ height = ma.abs((this.data[i] / (this.max - this.min)) * this.graphHeight),
431
+ width = (this.graphWidth / this.data.length) - prop.hmargin - prop.hmargin,
432
+ x = prop.gutterLeft + prop.hmargin + (outerSegment * i),
433
+ y = this.getYCoord(0);
434
+
435
+ var rect = RG.SVG.create({
436
+ svg: this.svg,
437
+ type: 'rect',
438
+ attr: {
439
+ stroke: prop.strokestyle,
440
+ fill: prop.colorsSequential ? (prop.colors[sequentialIndex] ? prop.colors[sequentialIndex] : prop.colors[prop.colors.length - 1]) : prop.colors[0],
441
+ x: x,
442
+ y: y - (this.data[i] > 0 ? height : 0),
443
+ width: width,
444
+ height: height,
445
+ 'stroke-width': prop.linewidth,
446
+ 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[i] : '',
447
+ 'data-index': i,
448
+ 'data-sequential-index': sequentialIndex,
449
+ 'data-value': this.data[i],
450
+ filter: prop.shadow ? 'url(#dropShadow)' : ''
451
+ }
452
+ });
453
+
454
+ this.coords.push({
455
+ object: rect,
456
+ x: x,
457
+ y: y - (this.data[i] > 0 ? height : 0),
458
+ width: width,
459
+ height: height
460
+ });
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+ // Add the tooltip data- attribute
469
+ if (!RG.SVG.isNull(prop.tooltips) && prop.tooltips[sequentialIndex]) {
470
+
471
+ var obj = this;
472
+
473
+ //
474
+ // Add tooltip event listeners
475
+ //
476
+ (function (idx, seq)
477
+ {
478
+ rect['on' + prop.tooltipsEvent] = function (e)
479
+ {
480
+ // Hide any existing tooltip
481
+ RG.SVG.hideTooltip();
482
+
483
+ // Show the tooltip
484
+ RG.SVG.tooltip({
485
+ object: obj,
486
+ index: idx,
487
+ group: null,
488
+ sequentialIndex: seq,
489
+ text: prop.tooltips[seq],
490
+ event: e
491
+ });
492
+
493
+ // Highlight the rect that has been clicked on
494
+ obj.highlight(e.target);
495
+ };
496
+
497
+ rect.onmousemove = function (e)
498
+ {
499
+ e.target.style.cursor = 'pointer'
500
+ };
501
+ })(i, sequentialIndex);
502
+ }
503
+
504
+
505
+
506
+
507
+
508
+ //
509
+ // Grouped bars
510
+ //
511
+ } else if (RG.SVG.isArray(this.data[i]) && prop.grouping === 'grouped') {
512
+
513
+ var outerSegment = (this.graphWidth / this.data.length),
514
+ innerSegment = outerSegment - (2 * prop.hmargin);
515
+
516
+ // Loop through the group
517
+ for (var j=0; j<this.data[i].length; ++j,++sequentialIndex) {
518
+
519
+ var height = ma.abs((this.data[i][j] / (this.max - this.min)) * this.graphHeight),
520
+ width = ( (innerSegment - ((this.data[i].length - 1) * prop.hmarginGrouped)) / this.data[i].length),
521
+ x = (outerSegment * i) + prop.hmargin + prop.gutterLeft + (j * width) + ((j - 1) * prop.hmarginGrouped);
522
+
523
+ x = prop.gutterLeft + (outerSegment * i) + (width * j) + prop.hmargin + (j * prop.hmarginGrouped);
524
+
525
+ var rect = RG.SVG.create({
526
+ svg: this.svg,
527
+ type: 'rect',
528
+ attr: {
529
+ stroke: prop['strokestyle'],
530
+ fill: (prop.colorsSequential && prop.colors[sequentialIndex]) ? prop.colors[sequentialIndex] : prop.colors[j],
531
+ x: x,
532
+ y: y - (this.data[i][j] > 0 ? height : 0),
533
+ width: width,
534
+ height: height,
535
+ 'stroke-width': prop.linewidth,
536
+ 'data-index': i,
537
+ 'data-sequential-index': sequentialIndex,
538
+ 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[sequentialIndex] : '',
539
+ 'data-value': this.data[i][j],
540
+ filter: prop.shadow ? 'url(#dropShadow)' : ''
541
+ }
542
+ });
543
+
544
+ this.coords.push({
545
+ object: rect,
546
+ x: x,
547
+ y: y - (this.data[i][j] > 0 ? height : 0),
548
+ width: width,
549
+ height: height
550
+ });
551
+
552
+
553
+
554
+ // Add the tooltip data- attribute
555
+ if (!RG.SVG.isNull(prop.tooltips) && prop.tooltips[sequentialIndex]) {
556
+
557
+ var obj = this;
558
+
559
+
560
+ //
561
+ // Add tooltip event listeners
562
+ //
563
+ (function (idx, seq)
564
+ {
565
+ var indexes = RG.SVG.sequentialIndexToGrouped(seq, obj.data);
566
+
567
+ rect['on' + prop.tooltipsEvent] = function (e)
568
+ {
569
+ // Show the tooltip
570
+ RG.SVG.tooltip({
571
+ object: obj,
572
+ group: idx,
573
+ index: indexes[1],
574
+ sequentialIndex: seq,
575
+ text: prop.tooltips[seq],
576
+ event: e
577
+ });
578
+
579
+ // Highlight the rect that has been clicked on
580
+ obj.highlight(e.target);
581
+
582
+ };
583
+
584
+ rect.onmousemove = function (e)
585
+ {
586
+ e.target.style.cursor = 'pointer'
587
+ };
588
+ })(i, sequentialIndex);
589
+ }
590
+ }
591
+
592
+ --sequentialIndex;
593
+
594
+
595
+
596
+
597
+ //
598
+ // Stacked charts
599
+ //
600
+ } else if (RG.SVG.isArray(this.data[i]) && prop.grouping === 'stacked') {
601
+
602
+ var section = (this.graphWidth / this.data.length);
603
+
604
+
605
+ // Intialise the Y coordinate to the bottom gutter
606
+ var y = this.getYCoord(0);
607
+
608
+
609
+
610
+ // Loop through the stack
611
+ for (var j=0; j<this.data[i].length; ++j,++sequentialIndex) {
612
+
613
+ var height = ma.abs((this.data[i][j] / (this.max - this.min)) * this.graphHeight),
614
+ width = section - (2 * prop.hmargin),
615
+ x = prop.gutterLeft + (i * section) + prop.hmargin,
616
+ y = y - height;
617
+
618
+ // If this is the first iteration of the loop and a shadow
619
+ // is requested draw a rect here to create it.
620
+ if (j === 0 && prop.shadow) {
621
+
622
+ var fullHeight = ma.abs((RG.SVG.arraySum(this.data[i]) / (this.max - this.min)) * this.graphHeight);
623
+
624
+ var rect = RG.SVG.create({
625
+ svg: this.svg,
626
+ type: 'rect',
627
+ attr: {
628
+ fill: 'white',
629
+ x: x,
630
+ y: this.height - prop.gutterBottom - fullHeight,
631
+ width: width,
632
+ height: fullHeight,
633
+ 'stroke-width': 0,
634
+ 'data-index': i,
635
+ filter: 'url(#dropShadow)'
636
+ }
637
+ });
638
+
639
+ this.stackedBackfaces[i] = rect;
640
+ }
641
+
642
+
643
+
644
+ // Create the visible bar
645
+ var rect = RG.SVG.create({
646
+ svg: this.svg,
647
+ type: 'rect',
648
+ attr: {
649
+ stroke: prop['strokestyle'],
650
+ fill: prop.colorsSequential ? (prop.colors[sequentialIndex] ? prop.colors[sequentialIndex] : prop.colors[prop.colors.length - 1]) : prop.colors[j],
651
+ x: x,
652
+ y: y,
653
+ width: width,
654
+ height: height,
655
+ 'stroke-width': prop.linewidth,
656
+ 'data-index': i,
657
+ 'data-sequential-index': sequentialIndex,
658
+ 'data-tooltip': (!RG.SVG.isNull(prop.tooltips) && prop.tooltips.length) ? prop.tooltips[sequentialIndex] : '',
659
+ 'data-value': this.data[i][j]
660
+ }
661
+ });
662
+
663
+
664
+ this.coords.push({
665
+ object: rect,
666
+ x: x,
667
+ y: y,
668
+ width: width,
669
+ height: height
670
+ });
671
+
672
+
673
+
674
+ // Add the tooltip data- attribute
675
+ if (!RG.SVG.isNull(prop.tooltips) && prop.tooltips[sequentialIndex]) {
676
+
677
+ var obj = this;
678
+
679
+
680
+ //
681
+ // Add tooltip event listeners
682
+ //
683
+ (function (idx, seq)
684
+ {
685
+ rect['on' + prop.tooltipsEvent] = function (e)
686
+ {
687
+
688
+ var indexes = RG.SVG.sequentialIndexToGrouped(seq, obj.data);
689
+
690
+ // Show the tooltip
691
+ RG.SVG.tooltip({
692
+ object: obj,
693
+ index: indexes[1],
694
+ group: idx,
695
+ sequentialIndex: seq,
696
+ text: prop.tooltips[seq],
697
+ event: e
698
+ });
699
+
700
+ // Highlight the rect that has been clicked on
701
+ obj.highlight(e.target);
702
+ };
703
+
704
+ rect.onmousemove = function (e)
705
+ {
706
+ e.target.style.cursor = 'pointer'
707
+ };
708
+ })(i, sequentialIndex);
709
+ }
710
+ }
711
+
712
+ --sequentialIndex;
713
+ }
714
+ }
715
+ };
716
+
717
+
718
+
719
+
720
+
721
+
722
+
723
+
724
+ /**
725
+ * This function can be used to retrieve the relevant Y coordinate for a
726
+ * particular value.
727
+ *
728
+ * @param int value The value to get the Y coordinate for
729
+ */
730
+ this.getYCoord = function (value)
731
+ {
732
+ var prop = this.properties;
733
+
734
+ if (value > this.scale.max) {
735
+ return null;
736
+ }
737
+
738
+ var y, xaxispos = prop.xaxispos;
739
+
740
+ if (value < this.scale.min) {
741
+ return null;
742
+ }
743
+
744
+ y = ((value - this.scale.min) / (this.scale.max - this.scale.min));
745
+ y *= (this.height - prop.gutterTop - prop.gutterBottom);
746
+
747
+ y = this.height - prop.gutterBottom - y;
748
+ //}
749
+
750
+ return y;
751
+ };
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+ /**
761
+ * This function can be used to highlight a bar on the chart
762
+ *
763
+ * @param object rect The rectangle to highlight
764
+ */
765
+ this.highlight = function (rect)
766
+ {
767
+ var x = rect.getAttribute('x'),
768
+ y = rect.getAttribute('y'),
769
+ width = rect.getAttribute('width'),
770
+ height = rect.getAttribute('height');
771
+
772
+ var highlight = RG.SVG.create({
773
+ svg: this.svg,
774
+ type: 'rect',
775
+ attr: {
776
+ stroke: prop.highlightStroke,
777
+ fill: prop.highlightFill,
778
+ x: x,
779
+ y: y,
780
+ width: width,
781
+ height: height,
782
+ 'stroke-width': prop.highlightLinewidth
783
+ }
784
+ });
785
+
786
+
787
+ if (prop.tooltipsEvent === 'mousemove') {
788
+ highlight.addEventListener('mouseout', function (e)
789
+ {
790
+ highlight.parentNode.removeChild(highlight);
791
+ RG.SVG.hideTooltip();
792
+
793
+ RG.SVG.REG.set('highlight', null);
794
+ }, false);
795
+ }
796
+
797
+
798
+ // Store the highlight rect in the rebistry so
799
+ // it can be cleared later
800
+ RG.SVG.REG.set('highlight', highlight);
801
+ };
802
+
803
+
804
+
805
+
806
+
807
+
808
+
809
+
810
+ /**
811
+ * This allows for easy specification of gradients
812
+ */
813
+ this.parseColors = function ()
814
+ {
815
+ // Save the original colors so that they can be restored when
816
+ // the canvas is cleared
817
+ if (!Object.keys(this.originalColors).length) {
818
+ this.originalColors = {
819
+ colors: RG.SVG.arrayClone(prop.colors),
820
+ backgroundGridColor: RG.SVG.arrayClone(prop.backgroundGridColor),
821
+ highlightFill: RG.SVG.arrayClone(prop.highlightFill)
822
+ }
823
+ }
824
+
825
+
826
+ // colors
827
+ var colors = prop.colors;
828
+
829
+ if (colors) {
830
+ for (var i=0; i<colors.length; ++i) {
831
+ colors[i] = RG.SVG.parseColorLinear({
832
+ object: this,
833
+ color: colors[i]
834
+ });
835
+ }
836
+ }
837
+
838
+ prop.backgroundGridColor = RG.SVG.parseColorLinear({object: this, color: prop.backgroundGridColor});
839
+ prop.highlightFill = RG.SVG.parseColorLinear({object: this, color: prop.highlightFill});
840
+ };
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+
849
+ //
850
+ // Draws the labelsAbove
851
+ //
852
+ this.drawLabelsAbove = function ()
853
+ {
854
+ // Go through the above labels
855
+ if (prop.labelsAbove) {
856
+ for (var i=0; i<this.coords.length; ++i) {
857
+
858
+ var str = RG.SVG.numberFormat({
859
+ object: this,
860
+ num: this.data[i].toFixed(prop.labelsAboveDecimals ),
861
+ prepend: typeof prop.labelsAboveUnitsPre === 'string' ? prop.labelsAboveUnitsPre : null,
862
+ append: typeof prop.labelsAboveUnitsPost === 'string' ? prop.labelsAboveUnitsPost : null,
863
+ point: typeof prop.labelsAbovePoint === 'string' ? prop.labelsAbovePoint : null,
864
+ thousand: typeof prop.labelsAboveThousand === 'string' ? prop.labelsAboveThousand : null,
865
+ formatter: typeof prop.labelsAboveFormatter === 'function' ? prop.labelsAboveFormatter : null
866
+ });
867
+
868
+ RG.SVG.text({
869
+ object: this,
870
+ text: str,
871
+ x: parseFloat(this.coords[i].object.getAttribute('x')) + parseFloat(this.coords[i].object.getAttribute('width') / 2) + prop.labelsAboveOffsetx,
872
+ y: parseFloat(this.coords[i].object.getAttribute('y')) - 7 + prop.labelsAboveOffsety,
873
+ halign: prop.labelsAboveHalign,
874
+ valign: prop.labelsAboveValign,
875
+ font: prop.labelsAboveFont || prop.textFont,
876
+ size: prop.labelsAboveSize || prop.textSize,
877
+ bold: prop.labelsAboveBold || prop.textBold,
878
+ italic: prop.labelsAboveItalic || prop.textItalic,
879
+ color: prop.labelsAboveColor || prop.textColor,
880
+ background: prop.labelsAboveBackground || null,
881
+ padding: prop.labelsAboveBackgroundPadding || 0
882
+ });
883
+ }
884
+ }
885
+ };
886
+
887
+
888
+
889
+
890
+
891
+
892
+
893
+
894
+ /**
895
+ * Using a function to add events makes it easier to facilitate method
896
+ * chaining
897
+ *
898
+ * @param string type The type of even to add
899
+ * @param function func
900
+ */
901
+ this.on = function (type, func)
902
+ {
903
+ if (type.substr(0,2) !== 'on') {
904
+ type = 'on' + type;
905
+ }
906
+
907
+ RG.SVG.addCustomEventListener(this, type, func);
908
+
909
+ return this;
910
+ };
911
+
912
+
913
+
914
+
915
+
916
+
917
+
918
+
919
+ //
920
+ // Used in chaining. Runs a function there and then - not waiting for
921
+ // the events to fire (eg the onbeforedraw event)
922
+ //
923
+ // @param function func The function to execute
924
+ //
925
+ this.exec = function (func)
926
+ {
927
+ func(this);
928
+
929
+ return this;
930
+ };
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+ //
940
+ // The Bar chart grow effect
941
+ //
942
+ this.grow = function ()
943
+ {
944
+ var opt = arguments[0] || {},
945
+ frames = opt.frames || 30,
946
+ frame = 0,
947
+ obj = this,
948
+ data = [],
949
+ height = null,
950
+ seq = 0;
951
+
952
+ //
953
+ // Copy the data
954
+ //
955
+ data = RG.SVG.arrayClone(this.data);
956
+
957
+ this.draw();
958
+
959
+ var iterate = function ()
960
+ {
961
+
962
+ for (var i=0,seq=0,len=obj.coords.length; i<len; ++i, ++seq) {
963
+
964
+ var multiplier = (frame / frames)
965
+ * RG.SVG.FX.getEasingMultiplier(frames, frame)
966
+ * RG.SVG.FX.getEasingMultiplier(frames, frame);
967
+
968
+
969
+
970
+
971
+ // TODO Go through the data and update the value according to
972
+ // the frame number
973
+ if (typeof data[i] === 'number') {
974
+
975
+ height = ma.abs(obj.getYCoord(data[i]) - obj.getYCoord(0));
976
+ obj.data[i] = data[i] * multiplier;
977
+ height = multiplier * height;
978
+
979
+ // Set the new height on the rect
980
+ obj.coords[seq].object.setAttribute(
981
+ 'height',
982
+ height
983
+ );
984
+
985
+ // Set the correct Y coord on the object
986
+ obj.coords[seq].object.setAttribute(
987
+ 'y',
988
+ data[i] < 0 ? obj.getYCoord(0) : obj.getYCoord(0) - height
989
+ );
990
+
991
+ } else if (typeof data[i] === 'object') {
992
+
993
+ var accumulativeHeight = 0;
994
+
995
+ for (var j=0,len2=data[i].length; j<len2; ++j, ++seq) {
996
+
997
+ height = ma.abs(obj.getYCoord(data[i][j]) - obj.getYCoord(0));
998
+ height = multiplier * height;
999
+ obj.data[i][j] = data[i][j] * multiplier;
1000
+
1001
+ obj.coords[seq].object.setAttribute(
1002
+ 'height',
1003
+ height
1004
+ );
1005
+
1006
+ obj.coords[seq].object.setAttribute(
1007
+ 'y',
1008
+ data[i][j] < 0 ? (obj.getYCoord(0) + accumulativeHeight) : (obj.getYCoord(0) - height - accumulativeHeight)
1009
+ );
1010
+
1011
+ accumulativeHeight += (prop.grouping === 'stacked' ? height : 0);
1012
+ }
1013
+
1014
+ //
1015
+ // Set the height and Y cooord of the backfaces if necessary
1016
+ //
1017
+ if (obj.stackedBackfaces[i]) {
1018
+ obj.stackedBackfaces[i].setAttribute(
1019
+ 'height',
1020
+ accumulativeHeight
1021
+ );
1022
+
1023
+ obj.stackedBackfaces[i].setAttribute(
1024
+ 'y',
1025
+ obj.height - prop.gutterBottom - accumulativeHeight
1026
+ );
1027
+ }
1028
+
1029
+ // Decrease seq by one so that it's not incremented twice
1030
+ --seq;
1031
+ }
1032
+ }
1033
+
1034
+ if (frame++ < frames) {
1035
+ //setTimeout(iterate, frame > 1 ? opt.delay : 200);
1036
+ RG.SVG.FX.update(iterate);
1037
+ } else if (opt.callback) {
1038
+ (opt.callback)(obj);
1039
+ }
1040
+ };
1041
+
1042
+ iterate();
1043
+
1044
+ return this;
1045
+ };
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+ //
1055
+ // Set the options that the user has provided
1056
+ //
1057
+ for (i in conf.options) {
1058
+ if (typeof i === 'string') {
1059
+ this.set(i, conf.options[i]);
1060
+ }
1061
+ }
1062
+ };
1063
+
1064
+ return this;
1065
+
1066
+ // End module pattern
1067
+ })(window, document);