rgraph-rails 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/CODE_OF_CONDUCT.md +13 -0
  6. data/Gemfile +4 -0
  7. data/README.md +73 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/lib/rgraph-rails/version.rb +3 -0
  12. data/lib/rgraph-rails.rb +8 -0
  13. data/license.txt +19 -0
  14. data/rgraph-rails.gemspec +26 -0
  15. data/vendor/assets/images/bg.png +0 -0
  16. data/vendor/assets/images/bullet.png +0 -0
  17. data/vendor/assets/images/facebook-large.png +0 -0
  18. data/vendor/assets/images/google-plus-large.png +0 -0
  19. data/vendor/assets/images/logo.png +0 -0
  20. data/vendor/assets/images/meter-image-sd-needle.png +0 -0
  21. data/vendor/assets/images/meter-image-sd.png +0 -0
  22. data/vendor/assets/images/meter-sketch-needle.png +0 -0
  23. data/vendor/assets/images/meter-sketch.png +0 -0
  24. data/vendor/assets/images/odometer-background.png +0 -0
  25. data/vendor/assets/images/rgraph.jpg +0 -0
  26. data/vendor/assets/images/title.png +0 -0
  27. data/vendor/assets/images/twitter-large.png +0 -0
  28. data/vendor/assets/javascripts/RGraph.bar.js +3246 -0
  29. data/vendor/assets/javascripts/RGraph.bipolar.js +2003 -0
  30. data/vendor/assets/javascripts/RGraph.common.annotate.js +399 -0
  31. data/vendor/assets/javascripts/RGraph.common.context.js +600 -0
  32. data/vendor/assets/javascripts/RGraph.common.core.js +4751 -0
  33. data/vendor/assets/javascripts/RGraph.common.csv.js +275 -0
  34. data/vendor/assets/javascripts/RGraph.common.deprecated.js +454 -0
  35. data/vendor/assets/javascripts/RGraph.common.dynamic.js +1194 -0
  36. data/vendor/assets/javascripts/RGraph.common.effects.js +1524 -0
  37. data/vendor/assets/javascripts/RGraph.common.key.js +735 -0
  38. data/vendor/assets/javascripts/RGraph.common.resizing.js +550 -0
  39. data/vendor/assets/javascripts/RGraph.common.tooltips.js +605 -0
  40. data/vendor/assets/javascripts/RGraph.common.zoom.js +223 -0
  41. data/vendor/assets/javascripts/RGraph.drawing.background.js +636 -0
  42. data/vendor/assets/javascripts/RGraph.drawing.circle.js +579 -0
  43. data/vendor/assets/javascripts/RGraph.drawing.image.js +810 -0
  44. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +710 -0
  45. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +672 -0
  46. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +568 -0
  47. data/vendor/assets/javascripts/RGraph.drawing.poly.js +623 -0
  48. data/vendor/assets/javascripts/RGraph.drawing.rect.js +603 -0
  49. data/vendor/assets/javascripts/RGraph.drawing.text.js +648 -0
  50. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +815 -0
  51. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +860 -0
  52. data/vendor/assets/javascripts/RGraph.fuel.js +965 -0
  53. data/vendor/assets/javascripts/RGraph.funnel.js +988 -0
  54. data/vendor/assets/javascripts/RGraph.gantt.js +1242 -0
  55. data/vendor/assets/javascripts/RGraph.gauge.js +1391 -0
  56. data/vendor/assets/javascripts/RGraph.hbar.js +1794 -0
  57. data/vendor/assets/javascripts/RGraph.hprogress.js +1307 -0
  58. data/vendor/assets/javascripts/RGraph.line.js +3940 -0
  59. data/vendor/assets/javascripts/RGraph.meter.js +1242 -0
  60. data/vendor/assets/javascripts/RGraph.modaldialog.js +292 -0
  61. data/vendor/assets/javascripts/RGraph.odo.js +1265 -0
  62. data/vendor/assets/javascripts/RGraph.pie.js +1979 -0
  63. data/vendor/assets/javascripts/RGraph.radar.js +1840 -0
  64. data/vendor/assets/javascripts/RGraph.rose.js +1860 -0
  65. data/vendor/assets/javascripts/RGraph.rscatter.js +1332 -0
  66. data/vendor/assets/javascripts/RGraph.scatter.js +3029 -0
  67. data/vendor/assets/javascripts/RGraph.thermometer.js +1131 -0
  68. data/vendor/assets/javascripts/RGraph.vprogress.js +1326 -0
  69. data/vendor/assets/javascripts/RGraph.waterfall.js +1252 -0
  70. data/vendor/assets/javascripts/financial-data.js +1067 -0
  71. data/vendor/assets/stylesheets/ModalDialog.css +90 -0
  72. data/vendor/assets/stylesheets/animations.css +3347 -0
  73. data/vendor/assets/stylesheets/website.css +402 -0
  74. metadata +175 -0
@@ -0,0 +1,988 @@
1
+ // version: 2015-11-02
2
+ /**
3
+ * o--------------------------------------------------------------------------------o
4
+ * | This file is part of the RGraph package - you can learn more at: |
5
+ * | |
6
+ * | http://www.rgraph.net |
7
+ * | |
8
+ * | RGraph is dual licensed under the Open Source GPL (General Public License) |
9
+ * | v2.0 license and a commercial license which means that you're not bound by |
10
+ * | the terms of the GPL. The commercial license is just �99 (GBP) and you can |
11
+ * | read about it here: |
12
+ * | http://www.rgraph.net/license |
13
+ * o--------------------------------------------------------------------------------o
14
+ */
15
+
16
+ RGraph = window.RGraph || {isRGraph: true};
17
+
18
+ /**
19
+ * The bar chart constructor
20
+ *
21
+ * @param object canvas The canvas object
22
+ * @param array data The chart data
23
+ */
24
+ RGraph.Funnel = function (conf)
25
+ {
26
+ /**
27
+ * Allow for object config style
28
+ */
29
+ if ( typeof conf === 'object'
30
+ && typeof conf.data === 'object'
31
+ && typeof conf.id === 'string') {
32
+
33
+ var id = conf.id
34
+ var canvas = document.getElementById(id);
35
+ var data = conf.data;
36
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
37
+
38
+ } else {
39
+
40
+ var id = conf;
41
+ var canvas = document.getElementById(id);
42
+ var data = arguments[1];
43
+ }
44
+
45
+
46
+ this.id = id;
47
+ this.canvas = canvas;
48
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
49
+ this.canvas.__object__ = this;
50
+ this.type = 'funnel';
51
+ this.coords = [];
52
+ this.isRGraph = true;
53
+ this.uid = RGraph.CreateUID();
54
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
55
+ this.coordsText = [];
56
+ this.original_colors = [];
57
+ this.firstDraw = true; // After the first draw this will be false
58
+
59
+
60
+ /**
61
+ * Compatibility with older browsers
62
+ */
63
+ //RGraph.OldBrowserCompat(this.context);
64
+
65
+
66
+ // Check for support
67
+ if (!this.canvas) {
68
+ alert('[FUNNEL] No canvas support');
69
+ return;
70
+ }
71
+
72
+ /**
73
+ * The funnel charts properties
74
+ */
75
+ this.properties =
76
+ {
77
+ 'chart.strokestyle': 'rgba(0,0,0,0)',
78
+ 'chart.gutter.left': 25,
79
+ 'chart.gutter.right': 25,
80
+ 'chart.gutter.top': 25,
81
+ 'chart.gutter.bottom': 25,
82
+ 'chart.labels': null,
83
+ 'chart.labels.sticks': false,
84
+ 'chart.labels.x': null,
85
+ 'chart.title': '',
86
+ 'chart.title.background': null,
87
+ 'chart.title.hpos': null,
88
+ 'chart.title.vpos': null,
89
+ 'chart.title.bold': true,
90
+ 'chart.title.font': null,
91
+ 'chart.title.x': null,
92
+ 'chart.title.y': null,
93
+ 'chart.title.halign': null,
94
+ 'chart.title.valign': null,
95
+ 'chart.colors': [
96
+ 'Gradient(white:red)',
97
+ 'Gradient(white:green)',
98
+ 'Gradient(white:gray)',
99
+ 'Gradient(white:blue)',
100
+ 'Gradient(white:black)',
101
+ 'Gradient(white:gray)',
102
+ 'Gradient(white:pink)',
103
+ 'Gradient(white:blue)',
104
+ 'Gradient(white:yellow)',
105
+ 'Gradient(white:green)',
106
+ 'Gradient(white:red)'
107
+ ],
108
+ 'chart.text.size': 12,
109
+ 'chart.text.boxed': true,
110
+ 'chart.text.halign': 'left',
111
+ 'chart.text.color': 'black',
112
+ 'chart.text.font': 'Arial',
113
+ 'chart.contextmenu': null,
114
+ 'chart.shadow': false,
115
+ 'chart.shadow.color': '#666',
116
+ 'chart.shadow.blur': 3,
117
+ 'chart.shadow.offsetx': 3,
118
+ 'chart.shadow.offsety': 3,
119
+ 'chart.key': null,
120
+ 'chart.key.background': 'white',
121
+ 'chart.key.position': 'graph',
122
+ 'chart.key.halign': 'right',
123
+ 'chart.key.shadow': false,
124
+ 'chart.key.shadow.color': '#666',
125
+ 'chart.key.shadow.blur': 3,
126
+ 'chart.key.shadow.offsetx': 2,
127
+ 'chart.key.shadow.offsety': 2,
128
+ 'chart.key.position.gutter.boxed': false,
129
+ 'chart.key.position.x': null,
130
+ 'chart.key.position.y': null,
131
+ 'chart.key.color.shape': 'square',
132
+ 'chart.key.rounded': true,
133
+ 'chart.key.linewidth': 1,
134
+ 'chart.key.colors': null,
135
+ 'chart.key.interactive': false,
136
+ 'chart.key.interactive.highlight.chart.stroke': 'black',
137
+ 'chart.key.interactive.highlight.chart.fill': 'rgba(255,255,255,0.7)',
138
+ 'chart.key.interactive.highlight.label': 'rgba(255,0,0,0.2)',
139
+ 'chart.key.text.color': 'black',
140
+ 'chart.tooltips': null,
141
+ 'chart.tooltips.effect': 'fade',
142
+ 'chart.tooltips.css.class': 'RGraph_tooltip',
143
+ 'chart.tooltips.event': 'onclick',
144
+ 'chart.highlight.stroke': 'rgba(0,0,0,0)',
145
+ 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
146
+ 'chart.tooltips.highlight': true,
147
+ 'chart.annotatable': false,
148
+ 'chart.annotate.color': 'black',
149
+ 'chart.zoom.factor': 1.5,
150
+ 'chart.zoom.fade.in': true,
151
+ 'chart.zoom.fade.out': true,
152
+ 'chart.zoom.factor': 1.5,
153
+ 'chart.zoom.fade.in': true,
154
+ 'chart.zoom.fade.out': true,
155
+ 'chart.zoom.hdir': 'right',
156
+ 'chart.zoom.vdir': 'down',
157
+ 'chart.zoom.frames': 25,
158
+ 'chart.zoom.delay': 16.666,
159
+ 'chart.zoom.shadow': true,
160
+ 'chart.zoom.background': true,
161
+ 'chart.zoom.action': 'zoom',
162
+ 'chart.resizable': false,
163
+ 'chart.events.click': null,
164
+ 'chart.events.mousemove': null
165
+ }
166
+
167
+ // Store the data
168
+ this.data = data;
169
+
170
+
171
+ /**
172
+ * Create the dollar objects so that functions can be added to them
173
+ */
174
+ for (var i=0; i<data.length; ++i) {
175
+ this['$' + i] = {};
176
+ }
177
+
178
+
179
+ /**
180
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
181
+ * done already
182
+ */
183
+ if (!this.canvas.__rgraph_aa_translated__) {
184
+ this.context.translate(0.5,0.5);
185
+
186
+ this.canvas.__rgraph_aa_translated__ = true;
187
+ }
188
+
189
+
190
+
191
+
192
+ // Short variable names
193
+ var RG = RGraph,
194
+ ca = this.canvas,
195
+ co = ca.getContext('2d'),
196
+ prop = this.properties,
197
+ pa = RG.Path,
198
+ pa2 = RG.path2,
199
+ win = window,
200
+ doc = document,
201
+ ma = Math
202
+
203
+
204
+
205
+ /**
206
+ * "Decorate" the object with the generic effects if the effects library has been included
207
+ */
208
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
209
+ RG.Effects.decorate(this);
210
+ }
211
+
212
+
213
+
214
+
215
+ /**
216
+ * A setter
217
+ *
218
+ * @param name string The name of the property to set
219
+ * @param value mixed The value of the property
220
+ */
221
+ this.set =
222
+ this.Set = function (name)
223
+ {
224
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
225
+
226
+ /**
227
+ * the number of arguments is only one and it's an
228
+ * object - parse it for configuration data and return.
229
+ */
230
+ if (arguments.length === 1 && typeof name === 'object') {
231
+ RG.parseObjectStyleConfig(this, name);
232
+ return this;
233
+ }
234
+
235
+
236
+
237
+
238
+
239
+ /**
240
+ * This should be done first - prepend the propertyy name with "chart." if necessary
241
+ */
242
+ if (name.substr(0,6) != 'chart.') {
243
+ name = 'chart.' + name;
244
+ }
245
+
246
+
247
+
248
+
249
+ // Convert uppercase letters to dot+lower case letter
250
+ name = name.replace(/([A-Z])/g, function (str)
251
+ {
252
+ return '.' + String(RegExp.$1).toLowerCase();
253
+ });
254
+
255
+
256
+
257
+
258
+
259
+
260
+ prop[name] = value;
261
+
262
+ return this;
263
+ };
264
+
265
+
266
+
267
+
268
+ /**
269
+ * A getter
270
+ *
271
+ * @param name string The name of the property to get
272
+ */
273
+ this.get =
274
+ this.Get = function (name)
275
+ {
276
+ /**
277
+ * This should be done first - prepend the property name with "chart." if necessary
278
+ */
279
+ if (name.substr(0,6) != 'chart.') {
280
+ name = 'chart.' + name;
281
+ }
282
+
283
+ // Convert uppercase letters to dot+lower case letter
284
+ name = name.replace(/([A-Z])/g, function (str)
285
+ {
286
+ return '.' + String(RegExp.$1).toLowerCase()
287
+ });
288
+
289
+ return prop[name.toLowerCase()];
290
+ };
291
+
292
+
293
+
294
+
295
+ /**
296
+ * The function you call to draw the bar chart
297
+ */
298
+ this.draw =
299
+ this.Draw = function ()
300
+ {
301
+ /**
302
+ * Fire the onbeforedraw event
303
+ */
304
+ RG.FireCustomEvent(this, 'onbeforedraw');
305
+
306
+
307
+ /**
308
+ * Parse the colors. This allows for simple gradient syntax
309
+ */
310
+ if (!this.colorsParsed) {
311
+ this.parseColors();
312
+
313
+ // Don't want to do this again
314
+ this.colorsParsed = true;
315
+ }
316
+
317
+
318
+ /**
319
+ * This is new in May 2011 and facilitates indiviual gutter settings,
320
+ * eg chart.gutter.left
321
+ */
322
+ this.gutterLeft = prop['chart.gutter.left'];
323
+ this.gutterRight = prop['chart.gutter.right'];
324
+ this.gutterTop = prop['chart.gutter.top'];
325
+ this.gutterBottom = prop['chart.gutter.bottom'];
326
+
327
+ // This stops the coords array from growing
328
+ this.coords = [];
329
+
330
+ /**
331
+ * Stop this growing uncntrollably
332
+ */
333
+ this.coordsText = [];
334
+
335
+ RG.DrawTitle(this, prop['chart.title'], this.gutterTop, null, prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2);
336
+ this.DrawFunnel();
337
+
338
+
339
+ /**
340
+ * Setup the context menu if required
341
+ */
342
+ if (prop['chart.contextmenu']) {
343
+ RG.ShowContext(this);
344
+ }
345
+
346
+
347
+
348
+ /**
349
+ * Draw the labels on the chart
350
+ */
351
+ this.DrawLabels();
352
+
353
+
354
+ /**
355
+ * This function enables resizing
356
+ */
357
+ if (prop['chart.resizable']) {
358
+ RG.AllowResizing(this);
359
+ }
360
+
361
+
362
+ /**
363
+ * This installs the event listeners
364
+ */
365
+ RG.InstallEventListeners(this);
366
+
367
+
368
+
369
+
370
+ /**
371
+ * Fire the onfirstdraw event
372
+ */
373
+ if (this.firstDraw) {
374
+ RG.fireCustomEvent(this, 'onfirstdraw');
375
+ this.firstDraw = false;
376
+ this.firstDrawFunc();
377
+ }
378
+
379
+
380
+
381
+
382
+ /**
383
+ * Fire the RGraph ondraw event
384
+ */
385
+ RG.FireCustomEvent(this, 'ondraw');
386
+
387
+ return this;
388
+ };
389
+
390
+
391
+
392
+ /**
393
+ * Used in chaining. Runs a function there and then - not waiting for
394
+ * the events to fire (eg the onbeforedraw event)
395
+ *
396
+ * @param function func The function to execute
397
+ */
398
+ this.exec = function (func)
399
+ {
400
+ func(this);
401
+
402
+ return this;
403
+ };
404
+
405
+
406
+
407
+
408
+ /**
409
+ * This function actually draws the chart
410
+ */
411
+ this.drawFunnel =
412
+ this.DrawFunnel = function ()
413
+ {
414
+ var width = ca.width - this.gutterLeft - this.gutterRight;
415
+ var height = ca.height - this.gutterTop - this.gutterBottom;
416
+ var total = RG.array_max(this.data);
417
+ var accheight = this.gutterTop;
418
+
419
+
420
+ /**
421
+ * Loop through each segment to draw
422
+ */
423
+
424
+ // Set a shadow if it's been requested
425
+ if (prop['chart.shadow']) {
426
+ co.shadowColor = prop['chart.shadow.color'];
427
+ co.shadowBlur = prop['chart.shadow.blur'];
428
+ co.shadowOffsetX = prop['chart.shadow.offsetx'];
429
+ co.shadowOffsetY = prop['chart.shadow.offsety'];
430
+ }
431
+
432
+ for (i=0,len=this.data.length; i<len; ++i) {
433
+
434
+ var firstvalue = this.data[0];
435
+ var firstwidth = (firstvalue / total) * width;
436
+ var curvalue = this.data[i];
437
+ var curwidth = (curvalue / total) * width;
438
+ var curheight = height / this.data.length;
439
+ var halfCurWidth = (curwidth / 2);
440
+ var nextvalue = this.data[i + 1];
441
+ var nextwidth = this.data[i + 1] ? (nextvalue / total) * width : null;
442
+ var halfNextWidth = (nextwidth / 2);
443
+ var center = this.gutterLeft + (firstwidth / 2);
444
+
445
+ var x1 = center - halfCurWidth;
446
+ var y1 = accheight;
447
+ var x2 = center + halfCurWidth;
448
+ var y2 = accheight;
449
+ var x3 = center + halfNextWidth;
450
+ var y3 = accheight + curheight;
451
+ var x4 = center - halfNextWidth;
452
+ var y4 = accheight + curheight;
453
+
454
+ if (nextwidth && i < this.data.length - 1) {
455
+
456
+ co.beginPath();
457
+
458
+ co.strokeStyle = prop['chart.strokestyle'];
459
+ co.fillStyle = prop['chart.colors'][i];
460
+
461
+ co.moveTo(x1, y1);
462
+ co.lineTo(x2, y2);
463
+ co.lineTo(x3, y3);
464
+ co.lineTo(x4, y4);
465
+
466
+ co.closePath();
467
+
468
+ /**
469
+ * Store the coordinates
470
+ */
471
+ this.coords.push([x1, y1, x2, y2, x3, y3, x4, y4]);
472
+ }
473
+
474
+
475
+ // The redrawing if the shadow is on will do the stroke
476
+ if (!prop['chart.shadow']) {
477
+ co.stroke();
478
+ }
479
+
480
+ co.fill();
481
+
482
+ accheight += curheight;
483
+ }
484
+
485
+ /**
486
+ * If the shadow is enabled, redraw every segment, in order to allow for shadows going upwards
487
+ */
488
+ if (prop['chart.shadow']) {
489
+
490
+ RG.NoShadow(this);
491
+
492
+ for (i=0; i<this.coords.length; ++i) {
493
+
494
+ co.strokeStyle = prop['chart.strokestyle'];
495
+ co.fillStyle = prop['chart.colors'][i];
496
+
497
+ co.beginPath();
498
+ co.moveTo(this.coords[i][0], this.coords[i][1]);
499
+ co.lineTo(this.coords[i][2], this.coords[i][3]);
500
+ co.lineTo(this.coords[i][4], this.coords[i][5]);
501
+ co.lineTo(this.coords[i][6], this.coords[i][7]);
502
+ co.closePath();
503
+
504
+ co.stroke();
505
+ co.fill();
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Lastly, draw the key if necessary
511
+ */
512
+ if (prop['chart.key'] && prop['chart.key'].length) {
513
+ RG.DrawKey(this, prop['chart.key'], prop['chart.colors']);
514
+ }
515
+ };
516
+
517
+
518
+
519
+
520
+ /**
521
+ * Draws the labels
522
+ */
523
+ this.drawLabels =
524
+ this.DrawLabels = function ()
525
+ {
526
+ /**
527
+ * Draws the labels
528
+ */
529
+ if (prop['chart.labels'] && prop['chart.labels'].length > 0) {
530
+
531
+ var font = prop['chart.text.font'];
532
+ var size = prop['chart.text.size'];
533
+ var color = prop['chart.text.color'];
534
+ var labels = prop['chart.labels'];
535
+ var halign = prop['chart.text.halign'] == 'left' ? 'left' : 'center';
536
+ var bgcolor = prop['chart.text.boxed'] ? 'white' : null;
537
+
538
+ if (typeof prop['chart.labels.x'] == 'number') {
539
+ var x = prop['chart.labels.x'];
540
+ } else {
541
+ var x = halign == 'left' ? (this.gutterLeft - 15) : ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
542
+ }
543
+
544
+ for (var j=0; j<this.coords.length; ++j) { // MUST be "j"
545
+
546
+ co.beginPath();
547
+
548
+ // Set the color back to black
549
+ co.strokeStyle = 'black';
550
+ co.fillStyle = color;
551
+
552
+ // Turn off any shadow
553
+ RG.NoShadow(this);
554
+
555
+ var label = labels[j];
556
+
557
+ RG.text2(this,{'font':font,
558
+ 'size':size,
559
+ 'x':x,
560
+ 'y':this.coords[j][1],
561
+ 'text':label,
562
+ 'valign':'center',
563
+ 'halign':halign,
564
+ 'bounding': prop['chart.text.boxed'],
565
+ 'boundingFill':bgcolor,
566
+ 'tag': 'labels'
567
+ });
568
+
569
+ if (prop['chart.labels.sticks']) {
570
+ /**
571
+ * Measure the text
572
+ */
573
+ co.font = size + 'pt ' + font;
574
+ var labelWidth = co.measureText(label).width;
575
+
576
+ /**
577
+ * Draw the horizontal indicator line
578
+ */
579
+ co.beginPath();
580
+ co.strokeStyle = 'gray';
581
+ co.moveTo(x + labelWidth + 10, ma.round(this.coords[j][1]));
582
+ co.lineTo(this.coords[j][0] - 10, ma.round(this.coords[j][1]));
583
+ co.stroke();
584
+ }
585
+ }
586
+
587
+
588
+
589
+ /**
590
+ * This draws the last labels if defined
591
+ */
592
+ var lastLabel = labels[j];
593
+
594
+ if (lastLabel) {
595
+
596
+ RG.text2(this,{'font':font,
597
+ 'size':size,
598
+ 'x':x,
599
+ 'y':this.coords[j - 1][5],
600
+ 'text':lastLabel,
601
+ 'valign':'center',
602
+ 'halign':halign,
603
+ 'bounding': prop['chart.text.boxed'],
604
+ 'boundingFill':bgcolor,
605
+ 'tag': 'labels'
606
+ });
607
+
608
+ if (prop['chart.labels.sticks']) {
609
+
610
+ /**
611
+ * Measure the text
612
+ */
613
+ co.font = size + 'pt ' + font;
614
+ var labelWidth = co.measureText(lastLabel).width;
615
+
616
+ /**
617
+ * Draw the horizontal indicator line
618
+ */
619
+ co.beginPath();
620
+ co.strokeStyle = 'gray';
621
+
622
+ //co.moveTo(x + labelWidth + 10, ma.round(this.coords[j][1]));
623
+ //co.lineTo(this.coords[j][0] - 10, ma.round(this.coords[j][1]));
624
+
625
+ co.moveTo(x + labelWidth + 10, Math.round(this.coords[j - 1][7]));
626
+ co.lineTo(this.coords[j - 1][6] - 10, Math.round(this.coords[j - 1][7]));
627
+ co.stroke();
628
+ }
629
+ }
630
+ }
631
+ };
632
+
633
+
634
+
635
+
636
+ /**
637
+ * Gets the appropriate segment that has been highlighted
638
+ */
639
+ this.getShape =
640
+ this.getSegment = function (e)
641
+ {
642
+ //var canvas = ca = e.target;
643
+ //var co = this.context;
644
+ //var prop = this.properties;
645
+ var coords = this.coords;
646
+ var mouseCoords = RG.getMouseXY(e);
647
+ var x = mouseCoords[0];
648
+ var y = mouseCoords[1];
649
+
650
+ for (i=0,len=coords.length; i<len; ++i) {
651
+
652
+ var segment = coords[i]
653
+
654
+ // Path testing
655
+ co.beginPath();
656
+ co.moveTo(segment[0], segment[1]);
657
+ co.lineTo(segment[2], segment[3]);
658
+ co.lineTo(segment[4], segment[5]);
659
+ co.lineTo(segment[6], segment[7]);
660
+ co.lineTo(segment[8], segment[9]);
661
+
662
+ if (co.isPointInPath(x, y)) {
663
+ var tooltip = RGraph.parseTooltipText(prop['chart.tooltips'], i);
664
+ return {0: this, 1: coords, 2: i, 'object': this, 'coords': segment, 'index': i, 'tooltip': tooltip};
665
+ }
666
+ }
667
+
668
+ return null;
669
+ };
670
+
671
+
672
+
673
+
674
+ /**
675
+ * Each object type has its own Highlight() function which highlights the appropriate shape
676
+ *
677
+ * @param object shape The shape to highlight
678
+ */
679
+ this.highlight =
680
+ this.Highlight = function (shape)
681
+ {
682
+ if (prop['chart.tooltips.highlight']) {
683
+ // Add the new highlight
684
+ var coords = shape['coords'];
685
+
686
+ co.beginPath();
687
+ co.strokeStyle = prop['chart.highlight.stroke'];
688
+ co.fillStyle = prop['chart.highlight.fill'];
689
+
690
+ co.moveTo(coords[0], coords[1]);
691
+ co.lineTo(coords[2], coords[3]);
692
+ co.lineTo(coords[4], coords[5]);
693
+ co.lineTo(coords[6], coords[7]);
694
+ co.closePath();
695
+
696
+ co.stroke();
697
+ co.fill();
698
+ }
699
+ };
700
+
701
+
702
+
703
+
704
+ /**
705
+ * The getObjectByXY() worker method. Don't call this call:
706
+ *
707
+ * RGraph.ObjectRegistry.getObjectByXY(e)
708
+ *
709
+ * @param object e The event object
710
+ */
711
+ this.getObjectByXY = function (e)
712
+ {
713
+ var mouseXY = RGraph.getMouseXY(e);
714
+
715
+ if (
716
+ mouseXY[0] > prop['chart.gutter.left']
717
+ && mouseXY[0] < (ca.width - prop['chart.gutter.right'])
718
+ && mouseXY[1] > prop['chart.gutter.top']
719
+ && mouseXY[1] < (ca.height - prop['chart.gutter.bottom'])
720
+ ) {
721
+
722
+ return this;
723
+ }
724
+ };
725
+
726
+
727
+
728
+
729
+ /**
730
+ * This function positions a tooltip when it is displayed
731
+ *
732
+ * @param obj object The chart object
733
+ * @param int x The X coordinate specified for the tooltip
734
+ * @param int y The Y coordinate specified for the tooltip
735
+ * @param objec tooltip The tooltips DIV element
736
+ */
737
+ this.positionTooltip = function (obj, x, y, tooltip, idx)
738
+ {
739
+ var coords = obj.coords[tooltip.__index__];
740
+
741
+ var x1 = coords[0];
742
+ var y1 = coords[1];
743
+ var x2 = coords[2];
744
+ var y2 = coords[3];
745
+ var x3 = coords[4];
746
+ var y3 = coords[5];
747
+ var x4 = coords[6];
748
+ var y4 = coords[7];
749
+
750
+ var coordW = x2 - x1;
751
+ var coordX = x1 + (coordW / 2);
752
+ var canvasXY = RG.getCanvasXY(ca);
753
+ var gutterLeft = prop['chart.gutter.left'];
754
+ var gutterTop = prop['chart.gutter.top'];
755
+ var width = tooltip.offsetWidth;
756
+ var height = tooltip.offsetHeight;
757
+
758
+ // Set the top position
759
+ tooltip.style.left = 0;
760
+ tooltip.style.top = canvasXY[1] + y1 + ((y3 - y2) / 2) - height - 7 + 'px';
761
+
762
+ // By default any overflow is hidden
763
+ tooltip.style.overflow = '';
764
+
765
+ // The arrow
766
+ var img = new Image();
767
+ img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
768
+ img.style.position = 'absolute';
769
+ img.id = '__rgraph_tooltip_pointer__';
770
+ img.style.top = (tooltip.offsetHeight - 2) + 'px';
771
+ tooltip.appendChild(img);
772
+
773
+ // Reposition the tooltip if at the edges:
774
+
775
+ // LEFT edge
776
+ if ((canvasXY[0] + coordX - (width / 2)) < 5) {
777
+ tooltip.style.left = (canvasXY[0] + coordX - (width * 0.1)) + 'px';
778
+ img.style.left = ((width * 0.1) - 8.5) + 'px';
779
+
780
+ // RIGHT edge
781
+ } else if ((canvasXY[0] + coordX + (width / 2)) > document.body.offsetWidth) {
782
+ tooltip.style.left = canvasXY[0] + coordX - (width * 0.9) + 'px';
783
+ img.style.left = ((width * 0.9) - 8.5) + 'px';
784
+
785
+ // Default positioning - CENTERED
786
+ } else {
787
+ tooltip.style.left = (canvasXY[0] + coordX - (width / 2)) + 'px';
788
+ img.style.left = ((width * 0.5) - 8.5) + 'px';
789
+ }
790
+ };
791
+
792
+
793
+
794
+
795
+ /**
796
+ * This allows for easy specification of gradients
797
+ */
798
+ this.parseColors = function ()
799
+ {
800
+ // Save the original colors so that they can be restored when the canvas is reset
801
+ if (this.original_colors.length === 0) {
802
+ this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
803
+ this.original_colors['chart.key.colors'] = RG.array_clone(prop['chart.key.colors']);
804
+ this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
805
+ this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
806
+ this.original_colors['chart.strokestyle'] = RG.array_clone(prop['chart.strokestyle']);
807
+ }
808
+
809
+ var colors = prop['chart.colors'];
810
+
811
+ for (var i=0; i<colors.length; ++i) {
812
+ colors[i] = this.parseSingleColorForHorizontalGradient(colors[i]);
813
+ }
814
+
815
+ var keyColors = prop['chart.key.colors'];
816
+ if (keyColors) {
817
+ for (var i=0; i<keyColors.length; ++i) {
818
+ keyColors[i] = this.parseSingleColorForHorizontalGradient(keyColors[i]);
819
+ }
820
+ }
821
+
822
+
823
+ prop['chart.strokestyle'] = this.parseSingleColorForVerticalGradient(prop['chart.strokestyle']);
824
+ prop['chart.highlight.stroke'] = this.parseSingleColorForHorizontalGradient(prop['chart.highlight.stroke']);
825
+ prop['chart.highlight.fill'] = this.parseSingleColorForHorizontalGradient(prop['chart.highlight.fill']);
826
+ };
827
+
828
+
829
+
830
+
831
+ /**
832
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
833
+ * need be etc
834
+ */
835
+ this.reset = function ()
836
+ {
837
+ };
838
+
839
+
840
+
841
+
842
+ /**
843
+ * This parses a single color value
844
+ */
845
+ this.parseSingleColorForHorizontalGradient = function (color)
846
+ {
847
+ if (!color || typeof(color) != 'string') {
848
+ return color;
849
+ }
850
+
851
+ if (color.match(/^gradient\((.*)\)$/i)) {
852
+
853
+ var parts = RegExp.$1.split(':');
854
+
855
+ // Create the gradient
856
+ var grad = co.createLinearGradient(prop['chart.gutter.left'],0,ca.width - prop['chart.gutter.right'],0);
857
+
858
+ var diff = 1 / (parts.length - 1);
859
+
860
+ grad.addColorStop(0, RGraph.trim(parts[0]));
861
+
862
+ for (var j=1; j<parts.length; ++j) {
863
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
864
+ }
865
+ }
866
+
867
+ return grad ? grad : color;
868
+ };
869
+
870
+
871
+
872
+
873
+ /**
874
+ * This parses a single color value
875
+ */
876
+ this.parseSingleColorForVerticalGradient = function (color)
877
+ {
878
+ if (!color || typeof(color) != 'string') {
879
+ return color;
880
+ }
881
+
882
+ if (color.match(/^gradient\((.*)\)$/i)) {
883
+
884
+ var parts = RegExp.$1.split(':');
885
+
886
+ // Create the gradient
887
+ var grad = co.createLinearGradient(0, prop['chart.gutter.top'],0,ca.height - prop['chart.gutter.bottom']);
888
+
889
+ var diff = 1 / (parts.length - 1);
890
+
891
+ grad.addColorStop(0, RGraph.trim(parts[0]));
892
+
893
+ for (var j=1; j<parts.length; ++j) {
894
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
895
+ }
896
+ }
897
+
898
+ return grad ? grad : color;
899
+ };
900
+
901
+
902
+
903
+
904
+ /**
905
+ * This function handles highlighting an entire data-series for the interactive
906
+ * key
907
+ *
908
+ * @param int index The index of the data series to be highlighted
909
+ */
910
+ this.interactiveKeyHighlight = function (index)
911
+ {
912
+ var coords = this.coords[index];
913
+
914
+ if (coords && coords.length == 8) {
915
+ var pre_linewidth = co.lineWidth;
916
+
917
+ co.lineWidth = 2;
918
+ co.strokeStyle = prop['chart.key.interactive.highlight.chart.stroke'];
919
+ co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
920
+
921
+ co.beginPath();
922
+ co.moveTo(coords[0], coords[1]);
923
+ co.lineTo(coords[2], coords[3]);
924
+ co.lineTo(coords[4], coords[5]);
925
+ co.lineTo(coords[6], coords[7]);
926
+ co.closePath();
927
+ co.fill();
928
+ co.stroke();
929
+
930
+ // Reset the linewidth
931
+ co.lineWidth = pre_linewidth;
932
+ }
933
+ };
934
+
935
+
936
+
937
+
938
+ /**
939
+ * Using a function to add events makes it easier to facilitate method chaining
940
+ *
941
+ * @param string type The type of even to add
942
+ * @param function func
943
+ */
944
+ this.on = function (type, func)
945
+ {
946
+ if (type.substr(0,2) !== 'on') {
947
+ type = 'on' + type;
948
+ }
949
+
950
+ this[type] = func;
951
+
952
+ return this;
953
+ };
954
+
955
+
956
+
957
+
958
+ /**
959
+ * This function runs once only
960
+ * (put at the end of the file (before any effects))
961
+ */
962
+ this.firstDrawFunc = function ()
963
+ {
964
+ };
965
+
966
+
967
+
968
+ RG.att(ca);
969
+
970
+
971
+
972
+
973
+ /**
974
+ * Always now regsiter the object
975
+ */
976
+ RG.Register(this);
977
+
978
+
979
+
980
+
981
+ /**
982
+ * This is the 'end' of the constructor so if the first argument
983
+ * contains configuration data - handle that.
984
+ */
985
+ if (parseConfObjectForOptions) {
986
+ RG.parseObjectStyleConfig(this, conf.options);
987
+ }
988
+ };