rgraph-rails 4.62 → 4.64

Sign up to get free protection for your applications and to get access to all the features.
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);