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,1486 @@
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.Line = 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
+
37
+ // Convert single datasets to a multi-dimensional format
38
+ if (RG.SVG.isArray(conf.data) && RG.SVG.isArray(conf.data[0])) {
39
+ this.data = RG.SVG.arrayClone(conf.data);
40
+ } else if (RG.SVG.isArray(conf.data)) {
41
+ this.data = [RG.SVG.arrayClone(conf.data)];
42
+ } else {
43
+ this.data = [[]];
44
+ }
45
+
46
+ this.type = 'line';
47
+ this.coords = [];
48
+ this.coords2 = [];
49
+ this.coordsSpline = [];
50
+ this.hasMultipleDatasets = typeof this.data[0] === 'object' && typeof this.data[1] === 'object' ? true : false;
51
+ this.colorsParsed = false;
52
+ this.originalColors = {};
53
+ this.gradientCounter = 1;
54
+ this.originalData = RG.SVG.arrayClone(this.data);
55
+
56
+ // Add this object to the ObjectRegistry
57
+ RG.SVG.OR.add(this);
58
+
59
+ this.container.style.display = 'inline-block';
60
+
61
+ this.properties =
62
+ {
63
+ gutterLeft: 35,
64
+ gutterRight: 35,
65
+ gutterTop: 35,
66
+ gutterBottom: 35,
67
+
68
+ backgroundGrid: true,
69
+ backgroundGridColor: '#ddd',
70
+ backgroundGridLinewidth: 1,
71
+ backgroundGridHlines: true,
72
+ backgroundGridHlinesCount: null,
73
+ backgroundGridVlines: true,
74
+ backgroundGridVlinesCount: null,
75
+ backgroundGridBorder: true,
76
+
77
+ colors: ['red', '#0f0', 'blue', '#ff0', '#0ff', 'green'],
78
+
79
+ fill: false,
80
+ filledColors: [],
81
+ filledClick: null,
82
+ filledOpacity: 1,
83
+ filledAccumulative: false,
84
+
85
+ hmargin: 0,
86
+
87
+ yaxis: true,
88
+ yaxisTickmarks: true,
89
+ yaxisTickmarksLength: 3,
90
+ yaxisColor: 'black',
91
+
92
+ yaxisScale: true,
93
+ yaxisLabels: null,
94
+ yaxisLabelsOffsetx: 0,
95
+ yaxisLabelsOffsety: 0,
96
+ yaxisLabelsCount: 5,
97
+
98
+ yaxisUnitsPre: '',
99
+ yaxisUnitsPost: '',
100
+ yaxisStrict: false,
101
+ yaxisDecimals: 0,
102
+ yaxisPoint: '.',
103
+ yaxisThousand: ',',
104
+ yaxisRound: false,
105
+ yaxisMax: null,
106
+ yaxisMin: 0,
107
+ yaxisFormatter: null,
108
+
109
+ xaxis: true,
110
+ xaxisTickmarks: true,
111
+ xaxisTickmarksLength: 3,
112
+ xaxisLabels: null,
113
+ xaxisLabelsOffsetx: 0,
114
+ xaxisLabelsOffsety: 0,
115
+ xaxisLabelsPosition: 'edge',
116
+ xaxisLabelsPositionEdgeTickmarksCount: null,
117
+ xaxisColor: 'black',
118
+
119
+ textColor: 'black',
120
+ textFont: 'sans-serif',
121
+ textSize: 12,
122
+ textBold: false,
123
+ textItalic: false,
124
+
125
+ linewidth: 1,
126
+
127
+ tooltips: null,
128
+ tooltipsOverride: null,
129
+ tooltipsEffect: 'fade',
130
+ tooltipsCssClass: 'RGraph_tooltip',
131
+ tooltipsEvent: 'mousemove',
132
+
133
+ highlightStroke: 'rgba(0,0,0,0)',
134
+ highlightFill: 'rgba(255,255,255,0.7)',
135
+ highlightLinewidth: 1,
136
+
137
+ tickmarksStyle: 'none',
138
+ tickmarksSize: 5,
139
+ tickmarksFill: 'white',
140
+ tickmarksLinewidth: 1,
141
+
142
+ labelsAbove: false,
143
+ labelsAboveFont: null,
144
+ labelsAboveSize: null,
145
+ labelsAboveBold: null,
146
+ labelsAboveItalic: null,
147
+ labelsAboveColor: null,
148
+ labelsAboveBackground: 'rgba(255,255,255,0.7)',
149
+ labelsAboveBackgroundPadding: 2,
150
+ labelsAboveUnitsPre: null,
151
+ labelsAboveUnitsPost: null,
152
+ labelsAbovePoint: null,
153
+ labelsAboveThousand: null,
154
+ labelsAboveFormatter: null,
155
+ labelsAboveDecimals: null,
156
+ labelsAboveOffsetx: 0,
157
+ labelsAboveOffsety: -10,
158
+ labelsAboveHalign: 'center',
159
+ labelsAboveValign: 'bottom',
160
+
161
+ shadow: false,
162
+ shadowOffsetx: 2,
163
+ shadowOffsety: 2,
164
+ shadowBlur: 2,
165
+ shadowOpacity: 0.25,
166
+
167
+ spline: false,
168
+
169
+ title: '',
170
+ titleSize: null,
171
+ titleX: null,
172
+ titleY: null,
173
+ titleHalign: 'center',
174
+ titleValign: 'bottom',
175
+ titleColor: null,
176
+ titleFont: null,
177
+ titleBold: false,
178
+ titleItalic: false,
179
+
180
+ titleSubtitle: '',
181
+ titleSubtitleSize: 10,
182
+ titleSubtitleX: null,
183
+ titleSubtitleY: null,
184
+ titleSubtitleHalign: 'center',
185
+ titleSubtitleValign: 'top',
186
+ titleSubtitleColor: '#aaa',
187
+ titleSubtitleFont: null,
188
+ titleSubtitleBold: false,
189
+ titleSubtitleItalic: false,
190
+
191
+ attribution: true,
192
+ attributionX: null,
193
+ attributionY: null,
194
+ attributionHref: 'http://www.rgraph.net/svg/index.html',
195
+ attributionHalign: 'right',
196
+ attributionValign: 'bottom',
197
+ attributionSize: 8,
198
+ attributionColor: 'gray',
199
+ attributionFont: 'sans-serif',
200
+ attributionItalic: false,
201
+ attributionBold: false
202
+ };
203
+
204
+
205
+
206
+
207
+
208
+ /**
209
+ * "Decorate" the object with the generic effects if the effects library has been included
210
+ */
211
+ if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
212
+ RG.SVG.FX.decorate(this);
213
+ }
214
+
215
+
216
+
217
+
218
+ var prop = this.properties;
219
+
220
+
221
+
222
+
223
+ //
224
+ // A setter that the constructor uses (at the end)
225
+ // to set all of the properties
226
+ //
227
+ // @param string name The name of the property to set
228
+ // @param string value The value to set the property to
229
+ //
230
+ this.set = function (name, value)
231
+ {
232
+ if (arguments.length === 1 && typeof name === 'object') {
233
+ for (i in arguments[0]) {
234
+ if (typeof i === 'string') {
235
+ this.set(i, arguments[0][i]);
236
+ }
237
+ }
238
+ } else {
239
+ this.properties[name] = value;
240
+ }
241
+
242
+ return this;
243
+ };
244
+
245
+
246
+
247
+
248
+
249
+
250
+
251
+
252
+ //
253
+ // The draw method draws the Bar chart
254
+ //
255
+ this.draw = function ()
256
+ {
257
+ // Fire the beforedraw event
258
+ RG.SVG.fireCustomEvent(this, 'onbeforedraw');
259
+
260
+
261
+
262
+
263
+
264
+ // Create the defs tag
265
+ RG.SVG.createDefs(this);
266
+
267
+
268
+
269
+
270
+
271
+ this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
272
+ this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
273
+
274
+
275
+
276
+ /**
277
+ * Parse the colors. This allows for simple gradient syntax
278
+ */
279
+ if (!this.colorsParsed) {
280
+
281
+ this.parseColors();
282
+
283
+ // Don't want to do this again
284
+ this.colorsParsed = true;
285
+ }
286
+
287
+ // Clear the coords arrays
288
+ this.coords = [];
289
+ this.coords2 = [];
290
+ this.coordsSpline = [];
291
+
292
+ // Reset the data back to the original
293
+ this.data = RG.SVG.arrayClone(this.originalData);
294
+
295
+
296
+ // Set this to zero
297
+ this.tooltipsSequentialIndex = 0;
298
+
299
+
300
+ // Go through the data and work out the maximum value
301
+ var values = [];
302
+
303
+ for (var i=0,max=0; i<this.data.length; ++i) {
304
+ if (typeof this.data[i] === 'number') {
305
+ values.push(this.data[i]);
306
+
307
+ } else if (RG.SVG.isArray(this.data[i]) && (!prop.filled || !prop.filledAccumulative) ) {
308
+ values.push(RG.SVG.arrayMax(this.data[i]));
309
+
310
+ } else if (RG.SVG.isArray(this.data[i]) && prop.filled && prop.filledAccumulative) {
311
+ for (var j=0; j<this.data[i].length; ++j) {
312
+ values[j] = values[j] || 0;
313
+ values[j] = values[j] + this.data[i][j];
314
+
315
+ // This adds values to prior values in order
316
+ // to create the stacking effect.
317
+ this.data[i][j] = values[j];
318
+ }
319
+ }
320
+ }
321
+
322
+ var max = RG.SVG.arrayMax(values);
323
+
324
+ // A custom, user-specified maximum value
325
+ if (typeof prop.yaxisMax === 'number') {
326
+ max = prop.yaxisMax;
327
+ }
328
+
329
+ // Set the ymin to zero if it's set mirror
330
+ if (prop.yaxisMin === 'mirror') {
331
+ var mirrorScale = true;
332
+ prop.yaxisMin = 0;
333
+ }
334
+
335
+
336
+ //
337
+ // Generate an appropiate scale
338
+ //
339
+ this.scale = RG.SVG.getScale({
340
+ object: this,
341
+ numlabels: prop.yaxisLabelsCount,
342
+ unitsPre: prop.yaxisUnitsPre,
343
+ unitsPost: prop.yaxisUnitsPost,
344
+ max: max,
345
+ min: prop.yaxisMin,
346
+ point: prop.yaxisPoint,
347
+ round: prop.yaxisRound,
348
+ thousand: prop.yaxisThousand,
349
+ decimals: prop.yaxisDecimals,
350
+ strict: typeof prop.yaxisMax === 'number',
351
+ formatter: prop.yaxisFormatter
352
+ });
353
+
354
+
355
+
356
+ //
357
+ // Get the scale a second time if the ymin should be mirored
358
+ //
359
+ // Set the ymin to zero if it's szet mirror
360
+ if (mirrorScale) {
361
+ this.scale = RG.SVG.getScale({
362
+ object: this,
363
+ numlabels: prop.yaxisLabelsCount,
364
+ unitsPre: prop.yaxisUnitsPre,
365
+ unitsPost: prop.yaxisUnitsPost,
366
+ max: this.scale.max,
367
+ min: this.scale.max * -1,
368
+ point: prop.yaxisPoint,
369
+ round: false,
370
+ thousand: prop.yaxisThousand,
371
+ decimals: prop.yaxisDecimals,
372
+ strict: typeof prop.yaxisMax === 'number',
373
+ formatter: prop.yaxisFormatter
374
+ });
375
+ }
376
+
377
+ // Now the scale has been generated adopt its max value
378
+ this.max = this.scale.max;
379
+ this.min = this.scale.min;
380
+ prop.yaxisMax = this.scale.max;
381
+ prop.yaxisMin = this.scale.min;
382
+
383
+
384
+
385
+
386
+ // Draw the background first
387
+ RG.SVG.drawBackground(this);
388
+
389
+
390
+ // Draw the axes over the bars
391
+ RG.SVG.drawXAxis(this);
392
+ RG.SVG.drawYAxis(this);
393
+
394
+
395
+ for (var i=0; i<this.data.length; ++i) {
396
+ this.drawLine(this.data[i], i);
397
+ }
398
+
399
+ // Always redraw the liines now so that tickmarks are drawn
400
+ this.redrawLines();
401
+
402
+
403
+ // Draw the labelsAbove labels
404
+ this.drawLabelsAbove();
405
+
406
+
407
+ // Add the attribution link. If you're adding this elsewhere on your page/site
408
+ // and you don't want it displayed then there are options available to not
409
+ // show it.
410
+ RG.SVG.attribution(this);
411
+
412
+
413
+
414
+ // Add the event listener that clears the highlight if
415
+ // there is any. Must be MOUSEDOWN (ie before the click event)
416
+ var obj = this;
417
+ document.body.addEventListener('mousedown', function (e)
418
+ {
419
+ RG.SVG.removeHighlight(obj);
420
+
421
+ }, false);
422
+
423
+
424
+
425
+ // Fire the draw event
426
+ RG.SVG.fireCustomEvent(this, 'ondraw');
427
+
428
+
429
+
430
+ return this;
431
+ };
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+
440
+ //
441
+ // Draws the bars
442
+ //
443
+ this.drawLine = function (data, index)
444
+ {
445
+ var coords = [],
446
+ path = [];
447
+
448
+ // Generate the coordinates
449
+ for (var i=0,len=data.length; i<len; ++i) {
450
+
451
+ var val = data[i],
452
+ x = (( (this.graphWidth - prop.hmargin - prop.hmargin) / (len - 1) ) * i) + prop.gutterLeft + prop.hmargin,
453
+ y = this.getYCoord(val);
454
+
455
+ coords.push([x, y]);
456
+ }
457
+
458
+
459
+ // Go through the coordinates and create the path that draws the line
460
+ for (var i=0; i<coords.length; ++i) {
461
+
462
+ if (i === 0 || RG.SVG.isNull(data[i]) || RG.SVG.isNull(data[i - 1])) {
463
+ var action = 'M';
464
+ } else {
465
+ var action = 'L';
466
+ }
467
+
468
+ path.push(action + '{1} {2}'.format(
469
+ coords[i][0],
470
+ coords[i][1]
471
+ ));
472
+ }
473
+
474
+
475
+
476
+
477
+
478
+
479
+ //
480
+ // Add the coordinates to the coords arrays
481
+ //
482
+ this.coords[index] = RG.SVG.arrayClone(coords);
483
+ this.coords2[index] = RG.SVG.arrayClone(coords);
484
+
485
+ if (prop.spline) {
486
+ this.coordsSpline[index] = this.drawSpline(coords);
487
+ }
488
+
489
+
490
+
491
+
492
+ // If the line should be filled, draw the fill part
493
+ if (prop.filled === true || (typeof prop.filled === 'object' && prop.filled[index]) ) {
494
+
495
+ if (prop.spline) {
496
+
497
+ var fillPath = ['M{1} {2}'.format(
498
+ this.coordsSpline[index][0][0],
499
+ this.coordsSpline[index][0][1]
500
+ )];
501
+
502
+ for (var i=1; i<this.coordsSpline[index].length; ++i) {
503
+ fillPath.push('L{1} {2}'.format(
504
+ this.coordsSpline[index][i][0] + ((i === (this.coordsSpline[index].length) - 1) ? 1 : 0),
505
+ this.coordsSpline[index][i][1]
506
+ ));
507
+ }
508
+
509
+ } else {
510
+ var fillPath = RG.SVG.arrayClone(path);
511
+ }
512
+
513
+
514
+ // Draw a line down to the X axis
515
+ fillPath.push('L{1} {2}'.format(
516
+ this.coords[index][this.coords[index].length - 1][0] + 1,
517
+ index > 0 && prop.filledAccumulative ? (prop.spline ? this.coordsSpline[index - 1][this.coordsSpline[index - 1].length - 1][1] : this.coords[index - 1][this.coords[index - 1].length - 1][1]) : this.getYCoord(prop.yaxisMin > 0 ? prop.yaxisMin : 0) + (prop.xaxis ? 0 : 1)
518
+ ));
519
+
520
+ if (index > 0 && prop.filledAccumulative) {
521
+
522
+ var path2 = RG.SVG.arrayClone(path);
523
+
524
+ if (index > 0 && prop.filledAccumulative) {
525
+ if (prop.spline) {
526
+ for (var i=this.coordsSpline[index - 1].length-1; i>=0; --i) {
527
+ fillPath.push('L{1} {2}'.format(
528
+ this.coordsSpline[index - 1][i][0],
529
+ this.coordsSpline[index - 1][i][1]
530
+ ));
531
+ }
532
+ } else {
533
+ for (var i=this.coords[index - 1].length-1; i>=0; --i) {
534
+ fillPath.push('L{1} {2}'.format(
535
+ this.coords[index - 1][i][0],
536
+ this.coords[index - 1][i][1]
537
+ ));
538
+ }
539
+ }
540
+ }
541
+ } else {
542
+
543
+ // This is the bottom left corner. The +1 is so that
544
+ // the fill doesn't go over the axis
545
+ fillPath.push('L{1} {2}'.format(
546
+ this.coords[index][0][0] + (prop.yaxis ? 1 : 0),
547
+ this.getYCoord(prop.yaxisMin > 0 ? prop.yaxisMin : 0) + (prop.xaxis ? 0 : 1)
548
+ ));
549
+ }
550
+
551
+ // Find the first none-null value and use that
552
+ // values X value
553
+ fillPath.push('L{1} {2}'.format(
554
+ this.coords[index][0][0] + (prop.yaxis ? 1 : 0),
555
+ this.coords[index][0][1]
556
+ ));
557
+
558
+ for (var i=0; i<this.data[index].length; ++i) {
559
+ if (!RG.SVG.isNull(this.data[index][i])) {
560
+ fillPath.push('L{1} {2}'.format(
561
+ this.coords[index][i][0],
562
+ this.getYCoord(0)
563
+ ));
564
+ break;
565
+ }
566
+ }
567
+
568
+
569
+
570
+ // Add the fill path to the scene
571
+ var fillPathObject = RG.SVG.create({
572
+ svg: this.svg,
573
+ type: 'path',
574
+ attr: {
575
+ d: fillPath.join(' '),
576
+ stroke: 'rgba(0,0,0,0)',
577
+ 'fill': prop.filledColors && prop.filledColors[index] ? prop.filledColors[index] : prop.colors[index],
578
+ 'fill-opacity': prop.filledOpacity,
579
+ 'stroke-width': 1,
580
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
581
+ }
582
+ });
583
+
584
+
585
+ if (prop.filledClick) {
586
+
587
+ var obj = this;
588
+ fillPathObject.onclick = function (e)
589
+ {
590
+ prop.filledClick(e, obj, index);
591
+ };
592
+ fillPathObject.onmousemove = function (e)
593
+ {
594
+ e.target.style.cursor = 'pointer';
595
+ }
596
+ }
597
+ }
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+ //
608
+ // Create the drop shadow effect if its required
609
+ //
610
+ if (prop.shadow) {
611
+ RG.SVG.setShadow({
612
+ object: this,
613
+ offsetx: prop.shadowOffsetx,
614
+ offsety: prop.shadowOffsety,
615
+ blur: prop.shadowBlur,
616
+ opacity: prop.shadowOpacity,
617
+ id: 'dropShadow'
618
+ });
619
+ }
620
+
621
+
622
+
623
+
624
+
625
+
626
+ // Add the path to the scene
627
+ if (prop.spline) {
628
+
629
+ // Make the raw coords into a path
630
+ var str = ['M{1} {2}'.format(
631
+ this.coordsSpline[index][0][0],
632
+ this.coordsSpline[index][0][1]
633
+ )];
634
+
635
+ for (var i=1; i<this.coordsSpline[index].length; ++i) {
636
+ str.push('L{1} {2}'.format(
637
+ this.coordsSpline[index][i][0],
638
+ this.coordsSpline[index][i][1]
639
+ ));
640
+ }
641
+
642
+ str = str.join(' ');
643
+
644
+ var line = RG.SVG.create({
645
+ svg: this.svg,
646
+ type: 'path',
647
+ attr: {
648
+ d: str,
649
+ stroke: prop['colors'][index],
650
+ 'fill':'none',
651
+ 'stroke-width': this.hasMultipleDatasets && prop.filled && prop.filledAccumulative ? 0.1 : (RG.SVG.isArray(prop.linewidth) ? prop.linewidth[index] : prop.linewidth + 0.01),
652
+ 'stroke-linecap': 'round',
653
+ 'stroke-linejoin': 'round',
654
+ filter: prop.shadow ? 'url(#dropShadow)' : '',
655
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
656
+ }
657
+ });
658
+
659
+ } else {
660
+
661
+ var path2 = RG.SVG.arrayClone(path);
662
+
663
+ if (prop.filled && prop.filledAccumulative && index > 0) {
664
+ for (var i=this.coords[index - 1].length-1; i>=0; --i) {
665
+ path2.push('L{1} {2}'.format(
666
+ this.coords[index - 1][i][0],
667
+ this.coords[index - 1][i][1]
668
+ ));
669
+ }
670
+ }
671
+
672
+ path2 = path2.join(' ');
673
+
674
+ var line = RG.SVG.create({
675
+ svg: this.svg,
676
+ type: 'path',
677
+ attr: {
678
+ d: path2,
679
+ stroke: prop.colors[index],
680
+ 'fill':'none',
681
+ 'stroke-width': this.hasMultipleDatasets && prop.filled && prop.filledAccumulative ? 0.1 : (RG.SVG.isArray(prop.linewidth) ? prop.linewidth[index]: prop.linewidth + 0.01),
682
+ 'stroke-linecap': 'round',
683
+ 'stroke-linejoin': 'round',
684
+ filter: prop.shadow ? 'url(#dropShadow)' : '',
685
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
686
+ }
687
+ });
688
+ }
689
+
690
+
691
+
692
+
693
+
694
+
695
+ if (prop.tooltips && prop.tooltips.length) {
696
+
697
+ var group = RG.SVG.create({
698
+ svg: this.svg,
699
+ type: 'g',
700
+ attr: {
701
+ 'fill': 'transparent',
702
+ className: "rgraph_hotspots"
703
+ },
704
+ style: {
705
+ cursor: 'pointer'
706
+ }
707
+ });
708
+
709
+
710
+ for (var i=0; i<this.coords[index].length; ++i,++this.tooltipsSequentialIndex) {
711
+
712
+ if (this.coords[index][i][0] && this.coords[index][i][1]) {
713
+
714
+ var hotspot = RG.SVG.create({
715
+ svg: this.svg,
716
+ parent: group,
717
+ type: 'circle',
718
+ attr: {
719
+ cx: this.coords[index][i][0],
720
+ cy: this.coords[index][i][1],
721
+ r: 5,
722
+ 'data-dataset': index,
723
+ 'data-index': i
724
+ }
725
+ });
726
+
727
+ var obj = this;
728
+ (function (sequentialIndex)
729
+ {
730
+ hotspot.addEventListener(prop.tooltipsEvent, function (e)
731
+ {
732
+ var indexes = RG.SVG.sequentialIndexToGrouped(sequentialIndex, obj.data),
733
+ index = indexes[1],
734
+ dataset = indexes[0];
735
+
736
+
737
+ if (RG.SVG.REG.get('tooltip') && RG.SVG.REG.get('tooltip').__index__ === index && RG.SVG.REG.get('tooltip').__dataset__ === dataset) {
738
+ return;
739
+ }
740
+
741
+ RG.SVG.hideTooltip();
742
+
743
+ // Show the tooltip
744
+ if (prop.tooltips[sequentialIndex]) {
745
+ var text = prop.tooltips[sequentialIndex];
746
+ }
747
+
748
+ RG.SVG.tooltip({
749
+ object: obj,
750
+ index: index,
751
+ dataset: dataset,
752
+ sequentialIndex: sequentialIndex,
753
+ text: text,
754
+ event: e
755
+ });
756
+
757
+
758
+ // Highlight the chart here
759
+ var outer_highlight1 = RG.SVG.create({
760
+ svg: obj.svg,
761
+ type: 'circle',
762
+ attr: {
763
+ cx: obj.coords[dataset][index][0],
764
+ cy: obj.coords[dataset][index][1],
765
+ r: 13,
766
+ fill: obj.properties.colors[dataset],
767
+ 'fill-opacity': 0.5
768
+ },
769
+ style: {
770
+ cursor: 'pointer'
771
+ }
772
+ });
773
+
774
+
775
+ var outer_highlight2 = RG.SVG.create({
776
+ svg: obj.svg,
777
+ type: 'circle',
778
+ attr: {
779
+ cx: obj.coords[dataset][index][0],
780
+ cy: obj.coords[dataset][index][1],
781
+ r: 14,
782
+ fill: 'white',
783
+ 'fill-opacity': 0.75
784
+ },
785
+ style: {
786
+ cursor: 'pointer'
787
+ }
788
+ });
789
+
790
+
791
+ var inner_highlight1 = RG.SVG.create({
792
+ svg: obj.svg,
793
+ type: 'circle',
794
+ attr: {
795
+ cx: obj.coords[dataset][index][0],
796
+ cy: obj.coords[dataset][index][1],
797
+ r: 6,
798
+ fill: 'white'
799
+ },
800
+ style: {
801
+ cursor: 'pointer'
802
+ }
803
+ });
804
+
805
+
806
+ var inner_highlight2 = RG.SVG.create({
807
+ svg: obj.svg,
808
+ type: 'circle',
809
+ attr: {
810
+ cx: obj.coords[dataset][index][0],
811
+ cy: obj.coords[dataset][index][1],
812
+ r: 5,
813
+ fill: obj.properties.colors[dataset]
814
+ },
815
+ style: {
816
+ cursor: 'pointer'
817
+ }
818
+ });
819
+
820
+ // Set the highlight in the registry
821
+ RG.SVG.REG.set('highlight', [
822
+ outer_highlight1,
823
+ outer_highlight2,
824
+ inner_highlight1,
825
+ inner_highlight2
826
+ ]);
827
+
828
+ }, false);
829
+ })(this.tooltipsSequentialIndex);
830
+
831
+ }
832
+ }
833
+ }
834
+ };
835
+
836
+
837
+
838
+
839
+
840
+
841
+
842
+
843
+ //
844
+ // Draws tickmarks
845
+ //
846
+ // @param number index The index of the line/dataset of coordinates
847
+ // @param object data The origvinal line data points
848
+ // @param object coords The coordinates of the points
849
+ //
850
+ this.drawTickmarks = function (index, data, coords)
851
+ {
852
+ for (var i=0; i<data.length; ++i) {
853
+
854
+ if (typeof data[i] === 'number') {
855
+ switch (prop.tickmarksStyle) {
856
+ case 'filledcircle':
857
+ case 'filledendcircle':
858
+ if (prop.tickmarksStyle === 'filledcircle' || (i === 0 || i === data.length - 1) ) {
859
+ var circle = RG.SVG.create({
860
+ svg: this.svg,
861
+ type: 'circle',
862
+ attr: {
863
+ cx: coords[index][i][0],
864
+ cy: coords[index][i][1],
865
+ r: prop.tickmarksSize,
866
+ 'fill': prop.colors[index],
867
+ filter: prop.shadow? 'url(#dropShadow)' : '',
868
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
869
+ }
870
+ });
871
+ }
872
+
873
+
874
+ break;
875
+
876
+ case 'circle':
877
+ case 'endcircle':
878
+
879
+ if (prop.tickmarksStyle === 'circle' || (prop.tickmarksStyle === 'endcircle' && (i === 0 || i === data.length - 1)) ) {
880
+
881
+ var outerCircle = RG.SVG.create({
882
+ svg: this.svg,
883
+ type: 'circle',
884
+ attr: {
885
+ cx: coords[index][i][0],
886
+ cy: coords[index][i][1],
887
+ r: prop.tickmarksSize + prop.tickmarksLinewidth,
888
+ 'fill': prop.colors[index],
889
+ filter: prop.shadow? 'url(#dropShadow)' : '',
890
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
891
+ }
892
+ });
893
+
894
+ var innerCircle = RG.SVG.create({
895
+ svg: this.svg,
896
+ type: 'circle',
897
+ attr: {
898
+ cx: coords[index][i][0],
899
+ cy: coords[index][i][1],
900
+ r: prop.tickmarksSize,
901
+ 'fill': prop.tickmarksFill,
902
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
903
+ }
904
+ });
905
+
906
+ break;
907
+ }
908
+ break;
909
+
910
+ case 'endrect':
911
+ case 'rect':
912
+ if (prop.tickmarksStyle === 'rect' || (prop.tickmarksStyle === 'endrect' && (i === 0 || i === data.length - 1)) ) {
913
+
914
+ var half = (prop.tickmarksSize + prop.tickmarksLinewidth) / 2;
915
+ var fill = typeof prop.tickmarksFill === 'object'&& typeof prop.tickmarksFill[index] === 'string' ? prop.tickmarksFill[index] : prop.tickmarksFill;
916
+
917
+ var rect = RG.SVG.create({
918
+ svg: this.svg,
919
+ type: 'rect',
920
+ attr: {
921
+ x: coords[index][i][0] - half,
922
+ y: coords[index][i][1] - half,
923
+ width: prop.tickmarksSize+ prop.tickmarksLinewidth,
924
+ height: prop.tickmarksSize+ prop.tickmarksLinewidth,
925
+
926
+ 'stroke-width': prop.tickmarksLinewidth,
927
+ 'stroke': prop.colors[index],
928
+ 'fill': fill,
929
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
930
+ }
931
+ });
932
+ }
933
+
934
+ break;
935
+
936
+ case 'filledendrect':
937
+ case 'filledrect':
938
+ if (prop.tickmarksStyle === 'filledrect' || (prop.tickmarksStyle === 'filledendrect' && (i === 0 || i === data.length - 1)) ) {
939
+
940
+ var half = (prop.tickmarksSize + prop.tickmarksLinewidth) / 2;
941
+ var fill = prop.colors[index];
942
+
943
+ var rect = RG.SVG.create({
944
+ svg: this.svg,
945
+ type: 'rect',
946
+ attr: {
947
+ x: coords[index][i][0] - half,
948
+ y: coords[index][i][1] - half,
949
+ width: prop.tickmarksSize+ prop.tickmarksLinewidth,
950
+ height: prop.tickmarksSize+ prop.tickmarksLinewidth,
951
+ 'fill': fill,
952
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
953
+ }
954
+ });
955
+ }
956
+ }
957
+ }
958
+ }
959
+ };
960
+
961
+
962
+
963
+
964
+
965
+
966
+
967
+
968
+ //
969
+ // Redraws the line in certain circumstances:
970
+ // o filled
971
+ // o filledAccumulative
972
+ // o Multiple lines
973
+ //
974
+ this.redrawLines = function ()
975
+ {
976
+ if (prop.spline) {
977
+ for (var i=0; i<this.coordsSpline.length; ++i) {
978
+
979
+ var linewidth = RG.SVG.isArray(prop.linewidth) ? prop.linewidth[i] : prop.linewidth,
980
+ color = prop['colors'][i],
981
+ path = '';
982
+
983
+ // Create the path from the spline coordinates
984
+ for (var j=0; j<this.coordsSpline[i].length; ++j) {
985
+ if (j === 0) {
986
+ path += 'M{1} {2} '.format(
987
+ this.coordsSpline[i][j][0],
988
+ this.coordsSpline[i][j][1]
989
+ );
990
+ } else {
991
+ path += 'L{1} {2} '.format(
992
+ this.coordsSpline[i][j][0],
993
+ this.coordsSpline[i][j][1]
994
+ );
995
+ }
996
+ }
997
+
998
+
999
+
1000
+ RG.SVG.create({
1001
+ svg: this.svg,
1002
+ type: 'path',
1003
+ attr: {
1004
+ d: path,
1005
+ stroke: color,
1006
+ 'fill':'none',
1007
+ 'stroke-width': linewidth + 0.01,
1008
+ 'stroke-linecap': 'round',
1009
+ 'stroke-linejoin': 'round',
1010
+ filter: prop.shadow ? 'url(#dropShadow)' : '',
1011
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
1012
+ }
1013
+ });
1014
+ }
1015
+
1016
+
1017
+ // Now draw the tickmarks
1018
+ for (var dataset=0; dataset<this.coords.length; ++dataset) {
1019
+ this.drawTickmarks(
1020
+ dataset,
1021
+ this.data[dataset],
1022
+ this.coords
1023
+ );
1024
+ }
1025
+
1026
+ } else {
1027
+
1028
+
1029
+ for (var i=0; i<this.coords.length; ++i) {
1030
+
1031
+ var linewidth = RG.SVG.isArray(prop.linewidth) ? prop.linewidth[i] : prop.linewidth,
1032
+ color = prop['colors'][i],
1033
+ path = '';
1034
+
1035
+ // Create the path from the coordinates
1036
+ for (var j=0; j<this.coords[i].length; ++j) {
1037
+ if (j === 0 || RG.SVG.isNull(this.data[i][j]) || RG.SVG.isNull(this.data[i][j - 1])) {
1038
+ path += 'M{1} {2} '.format(
1039
+ this.coords[i][j][0],
1040
+ this.coords[i][j][1]
1041
+ );
1042
+ } else {
1043
+ path += 'L{1} {2} '.format(
1044
+ this.coords[i][j][0],
1045
+ this.coords[i][j][1]
1046
+ );
1047
+ }
1048
+ }
1049
+
1050
+
1051
+
1052
+ RG.SVG.create({
1053
+ svg: this.svg,
1054
+ type: 'path',
1055
+ attr: {
1056
+ d: path,
1057
+ stroke: color,
1058
+ 'fill':'none',
1059
+ 'stroke-width': linewidth + 0.01,
1060
+ 'stroke-linecap': 'round',
1061
+ 'stroke-linejoin': 'round',
1062
+ filter: prop.shadow ? 'url(#dropshadow)' : '',
1063
+ 'clip-path': this.isTrace ? 'url(#trace-effect-clip)' : ''
1064
+ }
1065
+ });
1066
+
1067
+ }
1068
+
1069
+ // Now draw the tickmarks
1070
+ for (var dataset=0; dataset<this.coords.length; ++dataset) {
1071
+ this.drawTickmarks(
1072
+ dataset,
1073
+ this.data[dataset],
1074
+ this.coords
1075
+ );
1076
+ }
1077
+ }
1078
+ };
1079
+
1080
+
1081
+
1082
+
1083
+
1084
+
1085
+
1086
+
1087
+ /**
1088
+ * This function can be used to retrieve the relevant Y coordinate for a
1089
+ * particular value.
1090
+ *
1091
+ * @param int value The value to get the Y coordinate for
1092
+ */
1093
+ this.getYCoord = function (value)
1094
+ {
1095
+ var prop = this.properties, y;
1096
+
1097
+ if (value > this.scale.max) {
1098
+ return null;
1099
+ }
1100
+
1101
+ if (value < this.scale.min) {
1102
+ return null;
1103
+ }
1104
+
1105
+ y = ((value - this.scale.min) / (this.scale.max - this.scale.min));
1106
+ y *= (this.height - prop.gutterTop - prop.gutterBottom);
1107
+
1108
+ y = this.height - prop.gutterBottom - y;
1109
+
1110
+ return y;
1111
+ };
1112
+
1113
+
1114
+
1115
+
1116
+
1117
+
1118
+
1119
+
1120
+ /**
1121
+ * This function can be used to highlight a bar on the chart
1122
+ *
1123
+ * TODO This function looks like its needs updating
1124
+ *
1125
+ * @param object rect The rectangle to highlight
1126
+ */
1127
+ this.highlight = function (rect)
1128
+ {
1129
+ var x = rect.getAttribute('x'),
1130
+ y = rect.getAttribute('y');
1131
+
1132
+ /*
1133
+ var highlight = RG.SVG.create({
1134
+ svg: this.svg,
1135
+ type: 'rect',
1136
+ attr: {
1137
+ stroke: prop.highlightStroke,
1138
+ fill: prop.highlightFill,
1139
+ x: x,
1140
+ y: y,
1141
+ width: width,
1142
+ height: height,
1143
+ 'stroke-width': prop.highlightLinewidth
1144
+ }
1145
+ });
1146
+
1147
+
1148
+ if (prop.tooltipsEvent === 'mousemove') {
1149
+ highlight.addEventListener('mouseout', function (e)
1150
+ {
1151
+ highlight.parentNode.removeChild(highlight);
1152
+ RG.SVG.hideTooltip();
1153
+
1154
+ RG.SVG.REG.set('highlight', null);
1155
+ }, false);
1156
+ }
1157
+
1158
+
1159
+ // Store the highlight rect in the rebistry so
1160
+ // it can be cleared later
1161
+ RG.SVG.REG.set('highlight', highlight);
1162
+ */
1163
+ };
1164
+
1165
+
1166
+
1167
+
1168
+
1169
+
1170
+
1171
+
1172
+ //
1173
+ // Draw a spline Line chart
1174
+ //
1175
+ // @param array coords The coords for the line
1176
+ //
1177
+ this.drawSpline = function (coords)
1178
+ {
1179
+ var xCoords = [];
1180
+ gutterLeft = prop.gutterLeft,
1181
+ gutterRight = prop.gutterRight,
1182
+ hmargin = prop.hmargin,
1183
+ interval = (this.graphWidth - (2 * hmargin)) / (coords.length - 1),
1184
+ coordsSpline = [];
1185
+
1186
+ /**
1187
+ * The drawSpline function takes an array of JUST Y coords - not X/Y coords. So the line coords need converting
1188
+ * if we've been given X/Y pairs
1189
+ */
1190
+ for (var i=0,len=coords.length; i<len;i+=1) {
1191
+ if (typeof coords[i] == 'object' && coords[i] && coords[i].length == 2) {
1192
+ coords[i] = Number(coords[i][1]);
1193
+ }
1194
+ }
1195
+
1196
+ /**
1197
+ * Get the Points array in the format we want - the first value should
1198
+ * be null along with the lst value
1199
+ */
1200
+ var P = [coords[0]];
1201
+ for (var i=0; i<coords.length; ++i) {
1202
+ P.push(coords[i]);
1203
+ }
1204
+ P.push(coords[coords.length - 1] + (coords[coords.length - 1] - coords[coords.length - 2]));
1205
+
1206
+ for (var j=1; j<P.length-2; ++j) {
1207
+ for (var t=0; t<10; ++t) {
1208
+
1209
+ var yCoord = spline( t/10, P[j-1], P[j], P[j+1], P[j+2] );
1210
+
1211
+ xCoords.push(((j-1) * interval) + (t * (interval / 10)) + gutterLeft + hmargin);
1212
+
1213
+ coordsSpline.push([
1214
+ xCoords[xCoords.length - 1],
1215
+ yCoord
1216
+ ]);
1217
+
1218
+ if (typeof index === 'number') {
1219
+ coordsSpline[index].push([
1220
+ xCoords[xCoords.length - 1],
1221
+ yCoord
1222
+ ]);
1223
+ }
1224
+ }
1225
+ }
1226
+
1227
+
1228
+ // Draw the last section
1229
+ coordsSpline.push([
1230
+ ((j-1) * interval) + gutterLeft + hmargin,
1231
+ P[j]
1232
+ ]);
1233
+
1234
+ if (typeof index === 'number') {
1235
+ coordsSpline.push([
1236
+ ((j-1) * interval) + gutterLeft + hmargin,
1237
+ P[j]
1238
+ ]);
1239
+ }
1240
+
1241
+ function spline (t, P0, P1, P2, P3)
1242
+ {
1243
+ return 0.5 * ((2 * P1) +
1244
+ ((0-P0) + P2) * t +
1245
+ ((2*P0 - (5*P1) + (4*P2) - P3) * (t*t) +
1246
+ ((0-P0) + (3*P1)- (3*P2) + P3) * (t*t*t)));
1247
+ }
1248
+
1249
+
1250
+ return coordsSpline;
1251
+ };
1252
+
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+ /**
1261
+ * This allows for easy specification of gradients
1262
+ */
1263
+ this.parseColors = function ()
1264
+ {
1265
+ if (!Object.keys(this.originalColors).length) {
1266
+ this.originalColors = {
1267
+ colors: RG.SVG.arrayClone(prop.colors),
1268
+ filledColors: RG.SVG.arrayClone(prop.filledColors),
1269
+ backgroundGridColor: RG.SVG.arrayClone(prop.backgroundGridColor),
1270
+ highlightFill: RG.SVG.arrayClone(prop.highlightFill)
1271
+ }
1272
+ }
1273
+
1274
+ // colors
1275
+ var colors = prop.colors;
1276
+
1277
+ if (colors) {
1278
+ for (var i=0; i<colors.length; ++i) {
1279
+ colors[i] = RG.SVG.parseColorLinear({
1280
+ object: this,
1281
+ color: colors[i]
1282
+ });
1283
+ }
1284
+ }
1285
+
1286
+
1287
+ // Fill colors
1288
+ var filledColors = prop.filledColors;
1289
+
1290
+ if (filledColors) {
1291
+ for (var i=0; i<filledColors.length; ++i) {
1292
+ filledColors[i] = RG.SVG.parseColorLinear({
1293
+ object: this,
1294
+ color: filledColors[i]
1295
+ });
1296
+ }
1297
+ }
1298
+
1299
+ prop.backgroundGridColor = RG.SVG.parseColorLinear({object: this, color: prop.backgroundGridColor});
1300
+ prop.highlightFill = RG.SVG.parseColorLinear({object: this, color: prop.highlightFill});
1301
+ };
1302
+
1303
+
1304
+
1305
+
1306
+
1307
+
1308
+
1309
+
1310
+ //
1311
+ // Draws the labelsAbove
1312
+ //
1313
+ this.drawLabelsAbove = function ()
1314
+ {
1315
+ // Go through the above labels
1316
+ if (prop.labelsAbove) {
1317
+
1318
+ for (var dataset=0; dataset<this.coords.length; ++dataset) {
1319
+ for (var i=0; i<this.coords[dataset].length; ++i) {
1320
+
1321
+ var str = RG.SVG.numberFormat({
1322
+ object: this,
1323
+ num: this.data[dataset][i].toFixed(prop.labelsAboveDecimals ),
1324
+ prepend: typeof prop.labelsAboveUnitsPre === 'string' ? prop.labelsAboveUnitsPre : null,
1325
+ append: typeof prop.labelsAboveUnitsPost === 'string' ? prop.labelsAboveUnitsPost : null,
1326
+ point: typeof prop.labelsAbovePoint === 'string' ? prop.labelsAbovePoint : null,
1327
+ thousand: typeof prop.labelsAboveThousand === 'string' ? prop.labelsAboveThousand : null,
1328
+ formatter: typeof prop.labelsAboveFormatter === 'function' ? prop.labelsAboveFormatter : null
1329
+ });
1330
+
1331
+ RG.SVG.text({
1332
+ object: this,
1333
+ text: str,
1334
+ x: parseFloat(this.coords[dataset][i][0]) + prop.labelsAboveOffsetx,
1335
+ y: parseFloat(this.coords[dataset][i][1]) + prop.labelsAboveOffsety,
1336
+ halign: prop.labelsAboveHalign,
1337
+ valign: prop.labelsAboveValign,
1338
+ font: prop.labelsAboveFont || prop.textFont,
1339
+ size: prop.labelsAboveSize || prop.textSize,
1340
+ bold: prop.labelsAboveBold || prop.textBold,
1341
+ italic: prop.labelsAboveItalic || prop.textItalic,
1342
+ color: prop.labelsAboveColor || prop.textColor,
1343
+ background: prop.labelsAboveBackground || null,
1344
+ padding: prop.labelsAboveBackgroundPadding || 0
1345
+ });
1346
+ }
1347
+ }
1348
+ }
1349
+ };
1350
+
1351
+
1352
+
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+ /**
1359
+ * Using a function to add events makes it easier to facilitate method
1360
+ * chaining
1361
+ *
1362
+ * @param string type The type of even to add
1363
+ * @param function func
1364
+ */
1365
+ this.on = function (type, func)
1366
+ {
1367
+ if (type.substr(0,2) !== 'on') {
1368
+ type = 'on' + type;
1369
+ }
1370
+
1371
+ RG.SVG.addCustomEventListener(this, type, func);
1372
+
1373
+ return this;
1374
+ };
1375
+
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+
1383
+ //
1384
+ // Used in chaining. Runs a function there and then - not waiting for
1385
+ // the events to fire (eg the onbeforedraw event)
1386
+ //
1387
+ // @param function func The function to execute
1388
+ //
1389
+ this.exec = function (func)
1390
+ {
1391
+ func(this);
1392
+
1393
+ return this;
1394
+ };
1395
+
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+
1402
+
1403
+ //
1404
+ // A trace effect
1405
+ //
1406
+ // @param object Options to give to the effect
1407
+ // @param function A function to call when the effect has completed
1408
+ //
1409
+ this.trace = function ()
1410
+ {
1411
+ var opt = arguments[0] || {},
1412
+ frame = 1,
1413
+ frames = opt.frames || 60,
1414
+ obj = this;
1415
+
1416
+ this.isTrace = true;
1417
+
1418
+ this.draw();
1419
+
1420
+ // Create the clip area
1421
+ var clipPath = RG.SVG.create({
1422
+ svg: this.svg,
1423
+ parent: this.defs,
1424
+ type: 'clipPath',
1425
+ attr: {
1426
+ id: 'trace-effect-clip'
1427
+ }
1428
+ });
1429
+
1430
+ var clipPathRect = RG.SVG.create({
1431
+ svg: this.svg,
1432
+ parent: clipPath,
1433
+ type: 'rect',
1434
+ attr: {
1435
+ x: 0,
1436
+ y: 0,
1437
+ width: 0,
1438
+ height: this.height
1439
+ }
1440
+ });
1441
+
1442
+
1443
+ var iterator = function ()
1444
+ {
1445
+ var width = (frame++) / frames * obj.width;
1446
+
1447
+ clipPathRect.setAttribute("width", width);
1448
+
1449
+ if (frame <= frames) {
1450
+ RG.SVG.FX.update(iterator);
1451
+ } else if (opt.callback) {
1452
+ (opt.callback)(obj);
1453
+ }
1454
+ };
1455
+
1456
+ iterator();
1457
+
1458
+ return this;
1459
+ };
1460
+
1461
+
1462
+
1463
+
1464
+
1465
+
1466
+
1467
+
1468
+ //
1469
+ // Set the options that the user has provided
1470
+ //
1471
+ for (i in conf.options) {
1472
+ if (typeof i === 'string') {
1473
+ this.set(i, conf.options[i]);
1474
+ }
1475
+ }
1476
+ }
1477
+
1478
+
1479
+
1480
+ return this;
1481
+
1482
+
1483
+
1484
+
1485
+ // End module pattern
1486
+ })(window, document);