rgraph-rails 1.0.1

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