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,1131 @@
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
+
20
+
21
+ /**
22
+ * The chart constructor. This function sets up the object. It takes the ID (the HTML attribute) of the canvas as the
23
+ * first argument and the data as the second. If you need to change this, you can.
24
+ *
25
+ * NB: If tooltips are ever implemented they must go below the use event listeners!!
26
+ *
27
+ * @param string id The canvas tag ID
28
+ * @param number min The minimum value
29
+ * @param number max The maximum value
30
+ * @param number value The value reported by the thermometer
31
+ */
32
+ RGraph.Thermometer = function (conf)
33
+ {
34
+ /**
35
+ * Allow for object config style
36
+ */
37
+ if ( typeof conf === 'object'
38
+ && typeof conf.min === 'number'
39
+ && typeof conf.max === 'number'
40
+ && typeof conf.id === 'string') {
41
+
42
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
43
+
44
+ } else {
45
+
46
+ var conf = {
47
+ id: arguments[0],
48
+ min: arguments[1],
49
+ max: arguments[2],
50
+ value: arguments[3]
51
+ }
52
+ }
53
+
54
+
55
+
56
+
57
+ this.id = conf.id;
58
+ this.canvas = document.getElementById(this.id);
59
+ this.context = this.canvas.getContext ? this.canvas.getContext('2d') : null;
60
+ this.canvas.__object__ = this;
61
+ this.uid = RGraph.CreateUID();
62
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
63
+ this.colorsParsed = false;
64
+ this.type = 'thermometer';
65
+ this.isRGraph = true;
66
+ this.min = conf.min;
67
+ this.max = conf.max;
68
+ this.value = RGraph.stringsToNumbers(conf.value);
69
+ this.coords = [];
70
+ this.graphArea = [];
71
+ this.currentValue = null;
72
+ this.bulbRadius = 0;
73
+ this.bulbTopRadius = 0;
74
+ this.bulbTopCenterX = 0
75
+ this.bulbTopCenterY = 0;
76
+ this.coordsText = [];
77
+ this.original_colors = [];
78
+ this.firstDraw = true; // After the first draw this will be false
79
+
80
+
81
+
82
+
83
+ this.properties =
84
+ {
85
+ 'chart.strokestyle': 'black',
86
+ 'chart.colors': ['Gradient(#c00:red:#f66:#fcc)'],
87
+ 'chart.gutter.left': 15,
88
+ 'chart.gutter.right': 15,
89
+ 'chart.gutter.top': 15,
90
+ 'chart.gutter.bottom': 15,
91
+ 'chart.ticksize': 3,
92
+ 'chart.text.color': 'black',
93
+ 'chart.text.font': 'Arial',
94
+ 'chart.text.size': 12,
95
+ 'chart.units.pre': '',
96
+ 'chart.units.post': '',
97
+ 'chart.zoom.factor': 1.5,
98
+ 'chart.zoom.fade.in': true,
99
+ 'chart.zoom.fade.out': true,
100
+ 'chart.zoom.hdir': 'right',
101
+ 'chart.zoom.vdir': 'down',
102
+ 'chart.zoom.frames': 25,
103
+ 'chart.zoom.delay': 16.666,
104
+ 'chart.zoom.shadow': true,
105
+ 'chart.zoom.background': true,
106
+ 'chart.title': '',
107
+ 'chart.title.side': '',
108
+ 'chart.title.side.bold': true,
109
+ 'chart.title.side.font': null,
110
+ 'chart.shadow': true,
111
+ 'chart.shadow.offsetx': 0,
112
+ 'chart.shadow.offsety': 0,
113
+ 'chart.shadow.blur': 15,
114
+ 'chart.shadow.color': 'gray',
115
+ 'chart.resizable': false,
116
+ 'chart.contextmenu': null,
117
+ 'chart.adjustable': false,
118
+ 'chart.value.label': true,
119
+ 'chart.value.label.decimals': null,
120
+ 'chart.value.label.thousand': ',',
121
+ 'chart.value.label.point': '.',
122
+ 'chart.labels.count': 5,
123
+ 'chart.scale.visible': false,
124
+ 'chart.scale.decimals': 0,
125
+ 'chart.annotatable': false,
126
+ 'chart.annotate.color': 'black',
127
+ 'chart.scale.decimals': 0,
128
+ 'chart.scale.point': '.',
129
+ 'chart.scale.thousand': ',',
130
+ 'chart.tooltips': null,
131
+ 'chart.tooltips.highlight': true,
132
+ 'chart.tooltips.effect': 'fade',
133
+ 'chart.tooltips.event': 'onclick',
134
+ 'chart.highlight.stroke': 'rgba(0,0,0,0)',
135
+ 'chart.highlight.fill': 'rgba(255,255,255,0.7)'
136
+ }
137
+
138
+
139
+
140
+ /**
141
+ * A simple check that the browser has canvas support
142
+ */
143
+ if (!this.canvas) {
144
+ alert('[THERMOMETER] No canvas support');
145
+ return;
146
+ }
147
+
148
+ /**
149
+ * The thermometer can only have one data point so only this.$0 needs to be created
150
+ */
151
+ this.$0 = {}
152
+
153
+
154
+ /**
155
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
156
+ * done already
157
+ */
158
+ if (!this.canvas.__rgraph_aa_translated__) {
159
+ this.context.translate(0.5,0.5);
160
+
161
+ this.canvas.__rgraph_aa_translated__ = true;
162
+ }
163
+
164
+
165
+
166
+
167
+ // Short variable names
168
+ var RG = RGraph,
169
+ ca = this.canvas,
170
+ co = ca.getContext('2d'),
171
+ prop = this.properties,
172
+ pa = RG.Path,
173
+ pa2 = RG.path2,
174
+ win = window,
175
+ doc = document,
176
+ ma = Math
177
+
178
+
179
+
180
+ /**
181
+ * "Decorate" the object with the generic effects if the effects library has been included
182
+ */
183
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
184
+ RG.Effects.decorate(this);
185
+ }
186
+
187
+
188
+
189
+
190
+ /**
191
+ * A setter.
192
+ *
193
+ * @param name string The name of the property to set
194
+ * @param value mixed The value of the property
195
+ */
196
+ this.set =
197
+ this.Set = function (name)
198
+ {
199
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
200
+
201
+ /**
202
+ * the number of arguments is only one and it's an
203
+ * object - parse it for configuration data and return.
204
+ */
205
+ if (arguments.length === 1 && typeof name === 'object') {
206
+ RG.parseObjectStyleConfig(this, name);
207
+ return this;
208
+ }
209
+
210
+
211
+
212
+
213
+ /**
214
+ * This should be done first - prepend the property name with "chart." if necessary
215
+ */
216
+ if (name.substr(0,6) != 'chart.') {
217
+ name = 'chart.' + name;
218
+ }
219
+
220
+
221
+
222
+
223
+ // Convert uppercase letters to dot+lower case letter
224
+ name = name.replace(/([A-Z])/g, function (str)
225
+ {
226
+ return '.' + String(RegExp.$1).toLowerCase();
227
+ });
228
+
229
+
230
+
231
+
232
+
233
+
234
+ /**
235
+ * Change of name
236
+ */
237
+ if (name == 'chart.ylabels.count') {
238
+ name = 'chart.labels.count';
239
+ }
240
+ prop[name.toLowerCase()] = value;
241
+
242
+ return this;
243
+ };
244
+
245
+
246
+
247
+
248
+ /**
249
+ * A getter.
250
+ *
251
+ * @param name string The name of the property to get
252
+ */
253
+ this.get =
254
+ this.Get = function (name)
255
+ {
256
+ /**
257
+ * This should be done first - prepend the property name with "chart." if necessary
258
+ */
259
+ if (name.substr(0,6) != 'chart.') {
260
+ name = 'chart.' + name;
261
+ }
262
+
263
+ // Convert uppercase letters to dot+lower case letter
264
+ name = name.replace(/([A-Z])/g, function (str)
265
+ {
266
+ return '.' + String(RegExp.$1).toLowerCase()
267
+ });
268
+
269
+ return prop[name];
270
+ };
271
+
272
+
273
+
274
+
275
+ /**
276
+ * Draws the thermometer
277
+ */
278
+ this.draw =
279
+ this.Draw = function ()
280
+ {
281
+ // Fire the custom RGraph onbeforedraw event (which should be fired before the chart is drawn)
282
+ RG.fireCustomEvent(this, 'onbeforedraw');
283
+
284
+ /**
285
+ * Parse the colors. This allows for simple gradient syntax
286
+ */
287
+ if (!this.colorsParsed) {
288
+ this.parseColors();
289
+
290
+ // Don't want to do this again
291
+ this.colorsParsed = true;
292
+ }
293
+
294
+ /**
295
+ * Set the current value
296
+ */
297
+ this.currentValue = this.value;
298
+
299
+
300
+
301
+ /**
302
+ * Stop this growing uncontrollably
303
+ */
304
+ this.coordsText = [];
305
+
306
+
307
+
308
+
309
+
310
+ // This is new in May 2011 and facilitates indiviual gutter settings,
311
+ // eg chart.gutter.left
312
+ this.gutterLeft = prop['chart.gutter.left'];
313
+ this.gutterRight = prop['chart.gutter.right'];
314
+ this.gutterTop = prop['chart.gutter.top'];
315
+ this.gutterBottom = prop['chart.gutter.bottom'];
316
+
317
+
318
+ // Get the scale
319
+ this.scale2 = RG.getScale2(
320
+ this, {
321
+ 'max':this.max,
322
+ 'min':this.min,
323
+ 'strict':true,
324
+ 'scale.thousand':prop['chart.scale.thousand'],
325
+ 'scale.point':prop['chart.scale.point'],
326
+ 'scale.decimals':prop['chart.scale.decimals'],
327
+ 'ylabels.count':prop['chart.labels.count'],
328
+ 'scale.round':prop['chart.scale.round'],
329
+ 'units.pre': prop['chart.units.pre'],
330
+ 'units.post': prop['chart.units.post']
331
+ }
332
+ );
333
+
334
+
335
+ // Draw the background
336
+ this.drawBackground();
337
+
338
+ // Draw the bar that represents the value
339
+ this.drawBar();
340
+
341
+
342
+
343
+
344
+ // Draw the tickmarks
345
+ this.drawTickMarks();
346
+
347
+
348
+
349
+ /**
350
+ * Draw the label
351
+ */
352
+ this.DrawLabels();
353
+
354
+
355
+
356
+ /**
357
+ * Draw the title
358
+ */
359
+ if (prop['chart.title']) {
360
+ this.DrawTitle();
361
+ }
362
+
363
+ /**
364
+ * Draw the side title
365
+ */
366
+ if (prop['chart.title.side']) {
367
+ this.DrawSideTitle();
368
+ }
369
+
370
+ /**
371
+ * This function enables resizing
372
+ */
373
+ if (prop['chart.resizable']) {
374
+ RG.AllowResizing(this);
375
+ }
376
+
377
+
378
+
379
+
380
+ /**
381
+ * Setup the context menu if required
382
+ */
383
+ if (prop['chart.contextmenu']) {
384
+ RG.ShowContext(this);
385
+ }
386
+
387
+
388
+
389
+
390
+ /**
391
+ * This installs the event listeners
392
+ */
393
+ RG.InstallEventListeners(this);
394
+
395
+
396
+ /**
397
+ * Fire the onfirstdraw event
398
+ */
399
+ if (this.firstDraw) {
400
+ RG.fireCustomEvent(this, 'onfirstdraw');
401
+ this.firstDraw = false;
402
+ this.firstDrawFunc();
403
+ }
404
+
405
+
406
+
407
+ /**
408
+ * Fire the custom RGraph ondraw event (which should be fired when you have drawn the chart)
409
+ */
410
+ RG.FireCustomEvent(this, 'ondraw');
411
+
412
+ return this;
413
+ };
414
+
415
+
416
+
417
+
418
+
419
+ /**
420
+ * Draws the thermometer itself
421
+ */
422
+ this.drawBackground =
423
+ this.DrawBackground = function ()
424
+ {
425
+ var bulbRadius = (ca.width - this.gutterLeft - this.gutterRight) / 2;
426
+
427
+ // This is the radius/x/y of the top "semi-circle"
428
+ this.bulbTopRadius = (ca.width - this.gutterLeft - this.gutterRight - 24)/ 2
429
+ this.bulbTopCenterX = this.gutterLeft + bulbRadius;
430
+ this.bulbTopCenterY = this.gutterTop + bulbRadius;
431
+
432
+ //This is the radius/x/y of the bottom bulb
433
+ this.bulbBottomRadius = bulbRadius;
434
+ this.bulbBottomCenterX = this.gutterLeft + bulbRadius;
435
+ this.bulbBottomCenterY = ca.height - this.gutterBottom - bulbRadius;
436
+
437
+ // Save the bulbRadius as an object variable
438
+ this.bulbRadius = bulbRadius;
439
+
440
+ // Draw the black background that becomes the border
441
+ co.beginPath();
442
+ co.fillStyle = prop['chart.strokestyle'];
443
+
444
+ if (prop['chart.shadow']) {
445
+ RG.setShadow(
446
+ this,
447
+ prop['chart.shadow.color'],
448
+ prop['chart.shadow.offsetx'],
449
+ prop['chart.shadow.offsety'],
450
+ prop['chart.shadow.blur']
451
+ );
452
+ }
453
+
454
+ co.fillRect(this.gutterLeft + 12,this.gutterTop + bulbRadius,ca.width - this.gutterLeft - this.gutterRight - 24, ca.height - this.gutterTop - this.gutterBottom - bulbRadius - bulbRadius);
455
+
456
+ // Bottom bulb
457
+ co.arc(this.bulbBottomCenterX, this.bulbBottomCenterY, bulbRadius, 0, RG.TWOPI, 0);
458
+
459
+ // Top bulb (which is actually a semi-circle)
460
+ co.arc(this.bulbTopCenterX,this.bulbTopCenterY,this.bulbTopRadius,0,RG.TWOPI,0);
461
+ co.fill();
462
+
463
+ // Save the radius of the top semi circle
464
+
465
+
466
+ RG.NoShadow(this);
467
+
468
+ // Draw the white inner content background that creates the border
469
+ co.beginPath();
470
+ co.fillStyle = 'white';
471
+ co.fillRect(this.gutterLeft + 12 + 1,this.gutterTop + bulbRadius,ca.width - this.gutterLeft - this.gutterRight - 24 - 2,ca.height - this.gutterTop - this.gutterBottom - bulbRadius - bulbRadius);
472
+ co.arc(this.gutterLeft + bulbRadius, ca.height - this.gutterBottom - bulbRadius, bulbRadius - 1, 0, RG.TWOPI, 0);
473
+ co.arc(this.gutterLeft + bulbRadius,this.gutterTop + bulbRadius,((ca.width - this.gutterLeft - this.gutterRight - 24)/ 2) - 1,0,RG.TWOPI,0);
474
+ co.fill();
475
+
476
+ // Draw the bottom content of the thermometer
477
+ co.beginPath();
478
+ co.fillStyle = prop['chart.colors'][0];
479
+ co.arc(this.gutterLeft + bulbRadius, ca.height - this.gutterBottom - bulbRadius, bulbRadius - 1, 0, RG.TWOPI, 0);
480
+ co.rect(this.gutterLeft + 12 + 1, ca.height - this.gutterBottom - bulbRadius - bulbRadius,ca.width - this.gutterLeft - this.gutterRight - 24 - 2, bulbRadius);
481
+ co.fill();
482
+
483
+
484
+ // Save the X/Y/width/height
485
+ this.graphArea[0] = this.gutterLeft + 12 + 1;
486
+ this.graphArea[1] = this.gutterTop + bulbRadius;
487
+ this.graphArea[2] = ca.width - this.gutterLeft - this.gutterRight - 24 - 2;
488
+ this.graphArea[3] = (ca.height - this.gutterBottom - bulbRadius - bulbRadius) - (this.graphArea[1]);
489
+ };
490
+
491
+
492
+
493
+
494
+ /**
495
+ * This draws the bar that indicates the value of the thermometer
496
+ */
497
+ this.drawBar =
498
+ this.DrawBar = function ()
499
+ {
500
+ var barHeight = ((this.value - this.min) / (this.max - this.min)) * this.graphArea[3];
501
+
502
+ // Draw the actual bar that indicates the value
503
+ co.beginPath();
504
+ co.fillStyle = prop['chart.colors'][0];
505
+
506
+ // This solves an issue with ExCanvas showing a whiite cutout in the chart
507
+ if (RGraph.ISOLD) {
508
+ co.arc(this.bulbBottomCenterX, this.bulbBottomCenterY, this.bulbBottomRadius - 1, 0, RG.TWOPI, false)
509
+ }
510
+
511
+
512
+ co.rect(this.graphArea[0],
513
+ this.graphArea[1] + this.graphArea[3] - barHeight,
514
+ this.graphArea[2],
515
+ barHeight + 2);
516
+ co.fill();
517
+
518
+ this.coords[0] = [this.graphArea[0],this.graphArea[1] + this.graphArea[3] - barHeight,this.graphArea[2],barHeight];
519
+ };
520
+
521
+
522
+
523
+
524
+ /**
525
+ * Draws the tickmarks of the thermometer
526
+ */
527
+ this.drawTickMarks =
528
+ this.DrawTickMarks = function ()
529
+ {
530
+ co.strokeStyle = prop['chart.strokestyle']
531
+ var ticksize = prop['chart.ticksize'];
532
+
533
+ // Left hand side tickmarks
534
+ co.beginPath();
535
+ for (var i=this.graphArea[1]; i<=(this.graphArea[1] + this.graphArea[3]); i += (this.graphArea[3] / 10)) {
536
+ co.moveTo(this.gutterLeft + 12, Math.round(i));
537
+ co.lineTo(this.gutterLeft + 12 + ticksize, Math.round(i));
538
+ }
539
+ co.stroke();
540
+
541
+ // Right hand side tickmarks
542
+ co.beginPath();
543
+ for (var i=this.graphArea[1]; i<=(this.graphArea[1] + this.graphArea[3]); i += (this.graphArea[3] / 10)) {
544
+ co.moveTo(ca.width - (this.gutterRight + 12), Math.round(i));
545
+ co.lineTo(ca.width - (this.gutterRight + 12 + ticksize), Math.round(i));
546
+ }
547
+ co.stroke();
548
+ };
549
+
550
+
551
+
552
+
553
+ /**
554
+ * Draws the labels of the thermometer. Now (4th August 2011) draws
555
+ * the scale too
556
+ */
557
+ this.drawLabels =
558
+ this.DrawLabels = function ()
559
+ {
560
+ /**
561
+ * This draws draws the label that sits at the top of the chart
562
+ */
563
+ if (prop['chart.value.label']) {
564
+ co.fillStyle = prop['chart.text.color'];
565
+
566
+ // Weird...
567
+ var text = prop['chart.scale.visible'] ? RG.number_format(this,
568
+ this.value.toFixed(typeof prop['chart.value.label.decimals'] == 'number' ? prop['chart.value.label.decimals'] : prop['chart.scale.decimals'])
569
+ )
570
+ :
571
+ RG.number_format(this,
572
+ this.value.toFixed(typeof prop['chart.value.label.decimals'] == 'number' ? prop['chart.value.label.decimals'] : prop['chart.scale.decimals']),
573
+ prop['chart.units.pre'],
574
+ prop['chart.units.post']
575
+ );
576
+
577
+ RG.Text2(this, {'font': prop['chart.text.font'],
578
+ 'size': prop['chart.text.size'],
579
+ 'x':this.gutterLeft + this.bulbRadius,
580
+ 'y': this.coords[0][1] + 7,
581
+ 'text': text,
582
+ 'valign':'top',
583
+ 'halign':'center',
584
+ 'bounding':true,
585
+ 'boundingFill':'white',
586
+ 'tag': 'value.label'
587
+ });
588
+ }
589
+
590
+
591
+ /**
592
+ * Draw the scale if requested
593
+ */
594
+ if (prop['chart.scale.visible']) {
595
+ this.DrawScale();
596
+ }
597
+ };
598
+
599
+
600
+
601
+
602
+ /**
603
+ * Draws the title
604
+ */
605
+ this.drawTitle =
606
+ this.DrawTitle = function ()
607
+ {
608
+ co.fillStyle = prop['chart.text.color'];
609
+ RG.Text2(this, {'font': prop['chart.text.font'],
610
+ 'size': prop['chart.text.size'] + 2,
611
+ 'x':this.gutterLeft + ((ca.width - this.gutterLeft - this.gutterRight) / 2),
612
+ 'y': this.gutterTop,
613
+ 'text': String(prop['chart.title']),
614
+ 'valign':'center',
615
+ 'halign':'center',
616
+ 'bold':true,
617
+ 'tag': 'title'
618
+ });
619
+ };
620
+
621
+
622
+
623
+
624
+ /**
625
+ * Draws the title
626
+ */
627
+ this.drawSideTitle =
628
+ this.DrawSideTitle = function ()
629
+ {
630
+ var font = prop['chart.title.side.font'] ? prop['chart.title.side.font'] : prop['chart.text.font'];
631
+ var size = prop['chart.title.side.size'] ? prop['chart.title.side.size'] : prop['chart.text.size'] + 2;
632
+
633
+ co.fillStyle = prop['chart.text.color'];
634
+ RG.Text2(this, {'font': font,
635
+ 'size': size + 2,
636
+ 'x':this.gutterLeft - 3,
637
+ 'y': ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop,
638
+ 'text': String(prop['chart.title.side']),
639
+ 'valign':'center',
640
+ 'halign':'center',
641
+ 'angle':270,
642
+ 'bold':prop['chart.title.side.bold'],
643
+ 'tag': 'title.side'
644
+ });
645
+ };
646
+
647
+
648
+
649
+
650
+ /**
651
+ * Draw the scale if requested
652
+ */
653
+ this.drawScale =
654
+ this.DrawScale = function ()
655
+ {
656
+ var numLabels = prop['chart.labels.count']; // The -1 is so that the number of labels tallies with what is displayed
657
+ var step = (this.max - this.min) / numLabels;
658
+
659
+ co.fillStyle = prop['chart.text.color'];
660
+
661
+ var font = prop['chart.text.font'];
662
+ var size = prop['chart.text.size'];
663
+ var units_pre = prop['chart.units.pre'];
664
+ var units_post = prop['chart.units.post'];
665
+ var decimals = prop['chart.scale.decimals'];
666
+
667
+ for (var i=1; i<=numLabels; ++i) {
668
+
669
+ var x = ca.width - this.gutterRight;
670
+ var y = ca.height - this.gutterBottom - (2 * this.bulbRadius) - ((this.graphArea[3] / numLabels) * i);
671
+ var text = RG.number_format(this, String((this.min + (i * step)).toFixed(decimals)), units_pre, units_post);
672
+
673
+ RG.Text2(this, {'font':font,
674
+ 'size':size,
675
+ 'x':x-6,
676
+ 'y':y,
677
+ 'text':text,
678
+ 'valign':'center',
679
+ 'tag': 'scale'
680
+ });
681
+ }
682
+
683
+ // Draw zero
684
+ RG.Text2(this, {'font':font,
685
+ 'size':size,
686
+ 'x':x-6,
687
+ 'y':ca.height - this.gutterBottom - (2 * this.bulbRadius),
688
+ 'text':RG.number_format(this, (this.min).toFixed(decimals),units_pre,units_post),
689
+ 'valign':'center',
690
+ 'tag': 'scale'
691
+ });
692
+ };
693
+
694
+
695
+
696
+
697
+ /**
698
+ * Returns the focused/clicked bar
699
+ *
700
+ * @param event e The event object
701
+ */
702
+ this.getShape =
703
+ this.getBar = function (e)
704
+ {
705
+ for (var i=0; i<this.coords.length; i++) {
706
+
707
+ var mouseCoords = RGraph.getMouseXY(e);
708
+ var mouseX = mouseCoords[0];
709
+ var mouseY = mouseCoords[1];
710
+
711
+ var left = this.coords[i][0];
712
+ var top = this.coords[i][1];
713
+ var width = this.coords[i][2];
714
+ var height = this.coords[i][3];
715
+
716
+ if ( (mouseX >= left && mouseX <= (left + width) && mouseY >= top && mouseY <= (top + height + this.bulbBottomRadius)) // The bulbBottomRadius is added as the rect and the bulb don't fully cover the red bit
717
+ || RG.getHypLength(this.bulbBottomCenterX, this.bulbBottomCenterY, mouseX, mouseY) <= this.bulbBottomRadius) {
718
+
719
+
720
+ var tooltip = RG.parseTooltipText ? RG.parseTooltipText(prop['chart.tooltips'], i) : '';
721
+
722
+
723
+ return {0: this, 'object': this,
724
+ 1: left, 'x': left,
725
+ 2: top, 'y': top,
726
+ 3: width, 'width': width,
727
+ 4: height, 'height': height,
728
+ 5: i, 'index': i,
729
+ 'tooltip': tooltip
730
+ };
731
+ }
732
+ }
733
+
734
+ return null;
735
+ };
736
+
737
+
738
+
739
+
740
+ /**
741
+ * This function returns the value that the mouse is positioned t, regardless of
742
+ * the actual indicated value.
743
+ *
744
+ * @param object e The event object (or it can also be an two element array containing the X/Y coords)
745
+ */
746
+ this.getValue = function (arg)
747
+ {
748
+ if (arg.length == 2) {
749
+ var mouseX = arg[0];
750
+ var mouseY = arg[1];
751
+ } else {
752
+ var mouseCoords = RGraph.getMouseXY(arg);
753
+ var mouseX = mouseCoords[0];
754
+ var mouseY = mouseCoords[1];
755
+ }
756
+
757
+
758
+
759
+ var value = this.graphArea[3] - (mouseY - this.graphArea[1]);
760
+ value = (value / this.graphArea[3]) * (this.max - this.min);
761
+ value = value + this.min;
762
+
763
+ value = Math.max(value, this.min);
764
+ value = Math.min(value, this.max);
765
+
766
+ return value;
767
+ };
768
+
769
+
770
+
771
+
772
+ /**
773
+ * Each object type has its own Highlight() function which highlights the appropriate shape
774
+ *
775
+ * @param object shape The shape to highlight
776
+ */
777
+ this.highlight =
778
+ this.Highlight = function (shape)
779
+ {
780
+ if (prop['chart.tooltips.highlight']) {
781
+
782
+ // Add the new highlight
783
+ //RGraph.Highlight.Rect(this, shape);
784
+
785
+ co.beginPath();
786
+ co.strokeStyle = prop['chart.highlight.stroke'];
787
+ co.fillStyle = prop['chart.highlight.fill'];
788
+ co.rect(shape['x'],shape['y'],shape['width'],shape['height'] + this.bulbBottomRadius);
789
+ co.arc(this.bulbBottomCenterX, this.bulbBottomCenterY, this.bulbBottomRadius - 1, 0, RG.TWOPI, false);
790
+ co.stroke;
791
+ co.fill();
792
+ }
793
+ };
794
+
795
+
796
+
797
+
798
+ /**
799
+ * The getObjectByXY() worker method. Don't call this - call:
800
+ *
801
+ * RGraph.ObjectRegistry.getObjectByXY(e)
802
+ *
803
+ * @param object e The event object
804
+ */
805
+ this.getObjectByXY = function (e)
806
+ {
807
+ var mouseXY = RGraph.getMouseXY(e);
808
+
809
+ if (
810
+ mouseXY[0] > this.gutterLeft
811
+ && mouseXY[0] < (ca.width - this.gutterRight)
812
+ && mouseXY[1] >= this.gutterTop
813
+ && mouseXY[1] <= (ca.height - this.gutterBottom)
814
+ ) {
815
+
816
+ return this;
817
+ }
818
+ };
819
+
820
+
821
+
822
+
823
+ /**
824
+ * This method handles the adjusting calculation for when the mouse is moved
825
+ *
826
+ * @param object e The event object
827
+ */
828
+ this.adjusting_mousemove =
829
+ this.Adjusting_mousemove = function (e)
830
+ {
831
+ /**
832
+ * Handle adjusting for the Thermometer
833
+ */
834
+ if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
835
+
836
+ var mouseXY = RGraph.getMouseXY(e);
837
+ var value = this.getValue(e);
838
+
839
+ if (typeof(value) == 'number') {
840
+
841
+ // Fire the onadjust event
842
+ RG.FireCustomEvent(this, 'onadjust');
843
+
844
+ this.value = Number(value.toFixed(prop['chart.scale.decimals']));
845
+
846
+ RG.redrawCanvas(ca);
847
+ }
848
+ }
849
+ };
850
+
851
+
852
+
853
+
854
+ /**
855
+ * This function positions a tooltip when it is displayed
856
+ *
857
+ * @param obj object The chart object
858
+ * @param int x The X coordinate specified for the tooltip
859
+ * @param int y The Y coordinate specified for the tooltip
860
+ * @param objec tooltip The tooltips DIV element
861
+ */
862
+ this.positionTooltip = function (obj, x, y, tooltip, idx)
863
+ {
864
+ var coordX = obj.coords[tooltip.__index__][0];
865
+ var coordY = obj.coords[tooltip.__index__][1];
866
+ var coordW = obj.coords[tooltip.__index__][2];
867
+ var coordH = obj.coords[tooltip.__index__][3];
868
+ var canvasXY = RGraph.getCanvasXY(ca);
869
+ var gutterLeft = obj.gutterLeft;
870
+ var gutterTop = obj.gutterTop;
871
+ var width = tooltip.offsetWidth;
872
+ var height = tooltip.offsetHeight;
873
+
874
+ // Set the top position
875
+ tooltip.style.left = 0;
876
+ tooltip.style.top = canvasXY[1] + coordY - height - 7 + 'px';
877
+
878
+ // By default any overflow is hidden
879
+ tooltip.style.overflow = '';
880
+
881
+ // The arrow
882
+ var img = new Image();
883
+ img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
884
+ img.style.position = 'absolute';
885
+ img.id = '__rgraph_tooltip_pointer__';
886
+ img.style.top = (tooltip.offsetHeight - 2) + 'px';
887
+ tooltip.appendChild(img);
888
+
889
+ // Reposition the tooltip if at the edges:
890
+
891
+ // LEFT edge
892
+ if ((canvasXY[0] + coordX - (width / 2)) < 10) {
893
+ tooltip.style.left = (canvasXY[0] + coordX - (width * 0.1)) + (coordW / 2) + 'px';
894
+ img.style.left = ((width * 0.1) - 8.5) + 'px';
895
+
896
+ // RIGHT edge
897
+ } else if ((canvasXY[0] + coordX + (width / 2)) > doc.body.offsetWidth) {
898
+ tooltip.style.left = canvasXY[0] + coordX - (width * 0.9) + (coordW / 2) + 'px';
899
+ img.style.left = ((width * 0.9) - 8.5) + 'px';
900
+
901
+ // Default positioning - CENTERED
902
+ } else {
903
+ tooltip.style.left = (canvasXY[0] + coordX + (coordW / 2) - (width * 0.5)) + 'px';
904
+ img.style.left = ((width * 0.5) - 8.5) + 'px';
905
+ }
906
+ };
907
+
908
+
909
+
910
+
911
+ /**
912
+ * Returns the appropriate Y coord for a value
913
+ *
914
+ * @param number value The value to return the coord for
915
+ */
916
+ this.getYCoord = function (value)
917
+ {
918
+ if (value > this.max || value < this.min) {
919
+ return null;
920
+ }
921
+
922
+ var y = (this.graphArea[1] + this.graphArea[3]) - (((value - this.min) / (this.max - this.min)) * this.graphArea[3]);
923
+
924
+ return y;
925
+ };
926
+
927
+
928
+
929
+
930
+ /**
931
+ * This returns true/false as to whether the cursor is over the chart area.
932
+ * The cursor does not necessarily have to be over the bar itself.
933
+ */
934
+ this.overChartArea = function (e)
935
+ {
936
+ var mouseXY = RG.getMouseXY(e);
937
+ var mouseX = mouseXY[0];
938
+ var mouseY = mouseXY[1];
939
+
940
+ // Is the mouse in the "graphArea"?
941
+ // ( with a little extra height added)
942
+ if ( mouseX >= this.graphArea[0]
943
+ && mouseX <= (this.graphArea[0] + this.graphArea[2])
944
+ && mouseY >= this.graphArea[1]
945
+ && mouseY <= (this.graphArea[1] + this.graphArea[3] + this.bulbRadius)
946
+ ) {
947
+
948
+ return true;
949
+ }
950
+
951
+ // Is the mouse over the bottom bulb?
952
+ if (RG.getHypLength(this.bulbBottomCenterX, this.bulbBottomCenterY, mouseX, mouseY) <= this.bulbRadius) {
953
+ return true;
954
+ }
955
+
956
+ // Is the mouse over the semi-circle at the top?
957
+ if (RG.getHypLength(this.bulbTopCenterX, this.bulbTopCenterY, mouseX, mouseY) <= this.bulbTopRadius) {
958
+ return true;
959
+ }
960
+
961
+ return false;
962
+ };
963
+
964
+
965
+
966
+
967
+ /**
968
+ * This allows for easy specification of gradients
969
+ */
970
+ this.parseColors = function ()
971
+ {
972
+ // Save the original colors so that they can be restored when the canvas is reset
973
+ if (this.original_colors.length === 0) {
974
+ this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
975
+ }
976
+
977
+
978
+
979
+
980
+
981
+ var colors = prop['chart.colors'];
982
+
983
+ for (var i=0; i<colors.length; ++i) {
984
+ colors[i] = this.parseSingleColorForGradient(colors[i]);
985
+ }
986
+ };
987
+
988
+
989
+
990
+
991
+ /**
992
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
993
+ * need be etc
994
+ */
995
+ this.reset = function ()
996
+ {
997
+ };
998
+
999
+
1000
+
1001
+
1002
+ /**
1003
+ * This parses a single color value
1004
+ */
1005
+ this.parseSingleColorForGradient = function (color)
1006
+ {
1007
+ if (!color) {
1008
+ return color;
1009
+ }
1010
+
1011
+ if (typeof color === 'string' && color.match(/^gradient\((.*)\)$/i)) {
1012
+
1013
+ var parts = RegExp.$1.split(':');
1014
+
1015
+ // Create the gradient
1016
+ var grad = co.createLinearGradient(prop['chart.gutter.left'], 0, ca.width - prop['chart.gutter.right'],0);
1017
+
1018
+ var diff = 1 / (parts.length - 1);
1019
+
1020
+ grad.addColorStop(0, RG.trim(parts[0]));
1021
+
1022
+ for (var j=1; j<parts.length; ++j) {
1023
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1024
+ }
1025
+ }
1026
+
1027
+ return grad ? grad : color;
1028
+ };
1029
+
1030
+
1031
+
1032
+
1033
+ /**
1034
+ * Using a function to add events makes it easier to facilitate method chaining
1035
+ *
1036
+ * @param string type The type of even to add
1037
+ * @param function func
1038
+ */
1039
+ this.on = function (type, func)
1040
+ {
1041
+ if (type.substr(0,2) !== 'on') {
1042
+ type = 'on' + type;
1043
+ }
1044
+
1045
+ this[type] = func;
1046
+
1047
+ return this;
1048
+ };
1049
+
1050
+
1051
+
1052
+
1053
+ /**
1054
+ * This function runs once only
1055
+ * (put at the end of the file (before any effects))
1056
+ */
1057
+ this.firstDrawFunc = function ()
1058
+ {
1059
+ };
1060
+
1061
+
1062
+
1063
+
1064
+ /**
1065
+ * Gauge Grow
1066
+ *
1067
+ * This effect gradually increases the represented value
1068
+ *
1069
+ * @param object obj The chart object
1070
+ * @param Not used - pass null
1071
+ * @param function An optional callback function
1072
+ */
1073
+ this.grow = function ()
1074
+ {
1075
+ var obj = this;
1076
+ var callback = arguments[1] || function () {};
1077
+ var opt = arguments[0] || {};
1078
+ var frames = opt.frames ? opt.frames : 30;
1079
+ var origValue = Number(obj.currentValue);
1080
+ var newValue = obj.value;
1081
+ newValue = ma.min(newValue, this.max);
1082
+ newValue = ma.max(newValue, this.min);
1083
+ var diff = newValue - origValue;
1084
+ var step = (diff / frames);
1085
+ var frame = 0;
1086
+
1087
+
1088
+ function iterate ()
1089
+ {
1090
+ // Set the new value
1091
+ obj.value = (step * frame) + origValue;
1092
+
1093
+ RGraph.clear(obj.canvas);
1094
+ RGraph.redrawCanvas(obj.canvas);
1095
+
1096
+ if (frame < frames) {
1097
+ frame++;
1098
+ RGraph.Effects.updateCanvas(iterate);
1099
+ } else {
1100
+ callback(obj);
1101
+ }
1102
+ }
1103
+
1104
+ iterate();
1105
+
1106
+ return this;
1107
+ };
1108
+
1109
+
1110
+
1111
+ RG.att(ca);
1112
+
1113
+
1114
+
1115
+
1116
+ /**
1117
+ * Now, because canvases can support multiple charts, canvases must always be registered
1118
+ */
1119
+ RG.Register(this);
1120
+
1121
+
1122
+
1123
+
1124
+ /**
1125
+ * This is the 'end' of the constructor so if the first argument
1126
+ * contains configuration data - handle that.
1127
+ */
1128
+ if (parseConfObjectForOptions) {
1129
+ RG.parseObjectStyleConfig(this, conf.options);
1130
+ }
1131
+ };