rgraph-rails 4.62 → 4.64

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