rgraph-rails 1.0.8 → 4.62

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