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,810 @@
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
+ /**
17
+ * Having this here means that the RGraph libraries can be included in any order, instead of you having
18
+ * to include the common core library first.
19
+ */
20
+
21
+ // Define the RGraph global variable
22
+ RGraph = window.RGraph || {isRGraph: true};
23
+ RGraph.Drawing = RGraph.Drawing || {};
24
+
25
+ /**
26
+ * The constructor. This function sets up the object. It takes the ID (the HTML attribute) of the canvas as the
27
+ * first argument and the data as the second. If you need to change this, you can.
28
+ *
29
+ * @param string id The canvas tag ID
30
+ * @param number x The X position of the label
31
+ * @param number y The Y position of the label
32
+ * @param number text The text used
33
+ */
34
+ RGraph.Drawing.Image = function (conf)
35
+ {
36
+ /**
37
+ * Allow for object config style
38
+ */
39
+ if ( typeof conf === 'object'
40
+ && typeof conf.x === 'number'
41
+ && typeof conf.y === 'number'
42
+ && typeof conf.src === 'string'
43
+ && typeof conf.id === 'string') {
44
+
45
+ var id = conf.id
46
+ var canvas = document.getElementById(id);
47
+ var x = conf.x;
48
+ var y = conf.y;
49
+ var src = conf.src;
50
+
51
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
52
+
53
+ } else {
54
+
55
+ var id = conf;
56
+ var canvas = document.getElementById(id);
57
+ var x = arguments[1];
58
+ var y = arguments[2];
59
+ var src = arguments[3];
60
+ }
61
+
62
+
63
+
64
+
65
+ // id, x, y
66
+ this.id = id;
67
+ this.canvas = document.getElementById(this.id);
68
+ this.context = this.canvas.getContext('2d');
69
+ this.colorsParsed = false;
70
+ this.canvas.__object__ = this;
71
+ this.alignmentProcessed = false;
72
+ this.original_colors = [];
73
+ this.firstDraw = true; // After the first draw this will be false
74
+
75
+
76
+ /**
77
+ * Store the properties
78
+ */
79
+ this.x = x;
80
+ this.y = y;
81
+ this.src = src;
82
+ this.img = new Image();
83
+ this.img.src = this.src;
84
+
85
+
86
+ /**
87
+ * This defines the type of this shape
88
+ */
89
+ this.type = 'drawing.image';
90
+
91
+
92
+ /**
93
+ * This facilitates easy object identification, and should always be true
94
+ */
95
+ this.isRGraph = true;
96
+
97
+
98
+ /**
99
+ * This adds a uid to the object that you can use for identification purposes
100
+ */
101
+ this.uid = RGraph.CreateUID();
102
+
103
+
104
+ /**
105
+ * This adds a UID to the canvas for identification purposes
106
+ */
107
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
108
+
109
+
110
+
111
+
112
+ /**
113
+ * Some example background properties
114
+ */
115
+ this.properties =
116
+ {
117
+ 'chart.src': null,
118
+ 'chart.width': null,
119
+ 'chart.height': null,
120
+ 'chart.halign': 'left',
121
+ 'chart.valign': 'top',
122
+ 'chart.events.mousemove': null,
123
+ 'chart.events.click': null,
124
+ 'chart.shadow': false,
125
+ 'chart.shadow.color': 'gray',
126
+ 'chart.shadow.offsetx': 3,
127
+ 'chart.shadow.offsety': 3,
128
+ 'chart.shadow.blur': 5,
129
+ 'chart.tooltips': null,
130
+ 'chart.tooltips.highlight': true,
131
+ 'chart.tooltips.css.class': 'RGraph_tooltip',
132
+ 'chart.tooltips.event': 'onclick',
133
+ 'chart.highlight.stroke': 'rgba(0,0,0,0)',
134
+ 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
135
+ 'chart.alpha': 1,
136
+ 'chart.border': false,
137
+ 'chart.border.color': 'black',
138
+ 'chart.border.linewidth': 1,
139
+ 'chart.border.radius': 0,
140
+ 'chart.background.color': 'rgba(0,0,0,0)'
141
+ }
142
+
143
+ /**
144
+ * A simple check that the browser has canvas support
145
+ */
146
+ if (!this.canvas) {
147
+ alert('[DRAWING.IMAGE] No canvas support');
148
+ return;
149
+ }
150
+
151
+ /**
152
+ * This can be used to store the coordinates of shapes on the graph
153
+ */
154
+ this.coords = [];
155
+
156
+
157
+ /**
158
+ * Create the dollar object so that functions can be added to them
159
+ */
160
+ this.$0 = {};
161
+
162
+
163
+ /*
164
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
165
+ * done already
166
+ */
167
+ if (!this.canvas.__rgraph_aa_translated__) {
168
+ this.context.translate(0.5,0.5);
169
+
170
+ this.canvas.__rgraph_aa_translated__ = true;
171
+ }
172
+
173
+
174
+
175
+
176
+ // Short variable names
177
+ var RG = RGraph,
178
+ ca = this.canvas,
179
+ co = ca.getContext('2d'),
180
+ prop = this.properties,
181
+ pa = RG.Path,
182
+ pa2 = RG.path2,
183
+ win = window,
184
+ doc = document,
185
+ ma = Math
186
+
187
+
188
+
189
+ /**
190
+ * "Decorate" the object with the generic effects if the effects library has been included
191
+ */
192
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
193
+ RG.Effects.decorate(this);
194
+ }
195
+
196
+
197
+
198
+
199
+ /**
200
+ * A setter method for setting graph properties. It can be used like this: obj.Set('chart.strokestyle', '#666');
201
+ *
202
+ * @param name string The name of the property to set OR it can be a map
203
+ * of name/value settings like what you set in the constructor
204
+ */
205
+ this.set =
206
+ this.Set = function (name)
207
+ {
208
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
209
+
210
+ /**
211
+ * the number of arguments is only one and it's an
212
+ * object - parse it for configuration data and return.
213
+ */
214
+ if (arguments.length === 1 && typeof name === 'object') {
215
+ RG.parseObjectStyleConfig(this, name);
216
+ return this;
217
+ }
218
+
219
+
220
+
221
+
222
+
223
+ /**
224
+ * This should be done first - prepend the propertyy name with "chart." if necessary
225
+ */
226
+ if (name.substr(0,6) != 'chart.') {
227
+ name = 'chart.' + name;
228
+ }
229
+
230
+
231
+
232
+
233
+ // Convert uppercase letters to dot+lower case letter
234
+ name = name.replace(/([A-Z])/g, function (str)
235
+ {
236
+ return '.' + String(RegExp.$1).toLowerCase();
237
+ });
238
+
239
+
240
+
241
+
242
+
243
+
244
+ prop[name] = value;
245
+
246
+ return this;
247
+ };
248
+
249
+
250
+
251
+
252
+ /**
253
+ * A getter method for retrieving graph properties. It can be used like this: obj.Get('chart.strokestyle');
254
+ *
255
+ * @param name string The name of the property to get
256
+ */
257
+ this.get =
258
+ this.Get = function (name)
259
+ {
260
+ /**
261
+ * This should be done first - prepend the property name with "chart." if necessary
262
+ */
263
+ if (name.substr(0,6) != 'chart.') {
264
+ name = 'chart.' + name;
265
+ }
266
+
267
+ // Convert uppercase letters to dot+lower case letter
268
+ name = name.replace(/([A-Z])/g, function (str)
269
+ {
270
+ return '.' + String(RegExp.$1).toLowerCase()
271
+ });
272
+
273
+ return prop[name.toLowerCase()];
274
+ };
275
+
276
+
277
+
278
+
279
+ /**
280
+ * Draws the circle
281
+ */
282
+ this.draw =
283
+ this.Draw = function ()
284
+ {
285
+ /**
286
+ * Fire the onbeforedraw event
287
+ */
288
+ RG.FireCustomEvent(this, 'onbeforedraw');
289
+
290
+
291
+ /**
292
+ * Parse the colors. This allows for simple gradient syntax
293
+ */
294
+ var obj = this;
295
+ this.img.onload = function ()
296
+ {
297
+ if (!obj.colorsParsed) {
298
+
299
+ obj.parseColors();
300
+
301
+ // Don't want to do this again
302
+ obj.colorsParsed = true;
303
+ }
304
+
305
+ obj.width = this.width;
306
+ obj.height = this.height;
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+ if (!this.alignmentProcessed) {
315
+
316
+ var customWidthHeight = (typeof obj.properties['chart.width'] == 'number' && typeof obj.properties['chart.width'] == 'number');
317
+
318
+ // Horizontal alignment
319
+ if (obj.properties['chart.halign'] == 'center') {
320
+ obj.x -= customWidthHeight ? (obj.properties['chart.width'] / 2) : (this.width / 2);
321
+ } else if (obj.properties['chart.halign'] == 'right') {
322
+ obj.x -= customWidthHeight ? obj.properties['chart.width'] : this.width;
323
+ }
324
+
325
+ // Vertical alignment
326
+ if (obj.properties['chart.valign'] == 'center') {
327
+ obj.y -= customWidthHeight ? (obj.properties['chart.height'] / 2) : (this.height / 2);
328
+ } else if (obj.properties['chart.valign'] == 'bottom') {
329
+ obj.y -= customWidthHeight ? obj.properties['chart.height'] : this.height;
330
+ }
331
+
332
+ // Don't do this again
333
+ this.alignmentProcessed = true;
334
+ }
335
+ }
336
+
337
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+ // The onload event doesn't always fire - so call it manually as well
345
+ if (this.img.complete || this.img.readyState === 4) {
346
+ this.img.onload();
347
+ }
348
+
349
+
350
+ /**
351
+ * Draw the image here
352
+ */
353
+
354
+ if (prop['chart.shadow']) {
355
+ RG.setShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
356
+ }
357
+
358
+ var oldAlpha = co.globalAlpha;
359
+ co.globalAlpha = prop['chart.alpha'];
360
+
361
+
362
+
363
+
364
+
365
+ /**
366
+ * Draw a border around the image
367
+ */
368
+ if (prop['chart.border']) {
369
+
370
+ co.strokeStyle = prop['chart.border.color'];
371
+ co.lineWidth = prop['chart.border.linewidth'];
372
+
373
+ var borderRadius = 0;
374
+
375
+ // Work out the borderRadius only if the image has been loaded
376
+ if (this.width || this.height) {
377
+ borderRadius = ma.min(this.width / 2, this.height / 2)
378
+ }
379
+
380
+ if ((prop['chart.width'] / 2) > borderRadius && (prop['chart.height'] / 2) > borderRadius) {
381
+ borderRadius = ma.min((prop['chart.width'] / 2), (prop['chart.height'] / 2))
382
+ }
383
+
384
+ if (prop['chart.border.radius'] < borderRadius) {
385
+ borderRadius = prop['chart.border.radius'];
386
+ }
387
+
388
+
389
+
390
+
391
+ co.beginPath();
392
+ this.roundedRect(
393
+ ma.round(this.x) - ma.round(co.lineWidth / 2),
394
+ ma.round(this.y) - ma.round(co.lineWidth / 2),
395
+ (prop['chart.width'] || this.img.width) + co.lineWidth,
396
+ (prop['chart.height'] || this.img.height) + co.lineWidth,
397
+ borderRadius
398
+ );
399
+ }
400
+
401
+
402
+
403
+ if (borderRadius) {
404
+ co.save();
405
+
406
+ // Draw the rect that casts the shadow
407
+
408
+ // Draw the background color
409
+ this.drawBackgroundColor(borderRadius);
410
+
411
+
412
+
413
+ // Clip the canvas
414
+ co.beginPath();
415
+ this.roundedRect(
416
+ ma.round(this.x) - ma.round(co.lineWidth / 2),
417
+ ma.round(this.y) - ma.round(co.lineWidth / 2),
418
+ (prop['chart.width'] || this.img.width) + co.lineWidth,
419
+ (prop['chart.height'] || this.img.height) + co.lineWidth,
420
+ borderRadius
421
+ );
422
+ co.clip();
423
+
424
+ } else {
425
+
426
+ // Draw the background color
427
+ this.drawBackgroundColor(0);
428
+ }
429
+
430
+ RG.noShadow(this);
431
+
432
+
433
+ if (typeof prop['chart.height'] === 'number' || typeof prop['chart.width'] === 'number') {
434
+ co.drawImage(
435
+ this.img,
436
+ ma.round(this.x),
437
+ ma.round(this.y),
438
+ prop['chart.width'] || this.width,
439
+ prop['chart.height'] || this.height
440
+ );
441
+ } else {
442
+ co.drawImage(
443
+ this.img,
444
+ ma.round(this.x),
445
+ ma.round(this.y)
446
+ );
447
+ }
448
+
449
+
450
+
451
+
452
+ // If borderRadius is enabled restore the canvas to it's pre-clipped state
453
+ if (borderRadius) {
454
+ co.restore();
455
+ }
456
+
457
+
458
+
459
+ // If the border is enabled need a stroke so that the border is drawn
460
+ if (prop['chart.border']) {
461
+ RG.noShadow(this);
462
+ co.stroke();
463
+ }
464
+
465
+
466
+
467
+
468
+
469
+ co.globalAlpha = oldAlpha;
470
+
471
+ //var obj = this;
472
+
473
+ this.img.onload = function ()
474
+ {
475
+ RG.redrawCanvas(ca);
476
+
477
+ obj.coords[0] = [Math.round(obj.x), Math.round(obj.y), typeof(prop['chart.width']) == 'number' ? prop['chart.width'] : this.width, typeof prop['chart.height'] == 'number' ? prop['chart.height'] : this.height];
478
+
479
+ }
480
+
481
+ RG.NoShadow(this);
482
+
483
+
484
+ /**
485
+ * This installs the event listeners
486
+ */
487
+ RG.InstallEventListeners(this);
488
+
489
+
490
+ /**
491
+ * Fire the onfirstdraw event
492
+ */
493
+ if (this.firstDraw) {
494
+ RG.fireCustomEvent(this, 'onfirstdraw');
495
+ this.firstDraw = false;
496
+ this.firstDrawFunc();
497
+ }
498
+
499
+
500
+
501
+
502
+ /**
503
+ * Fire the ondraw event
504
+ */
505
+ RG.FireCustomEvent(this, 'ondraw');
506
+
507
+ return this;
508
+ };
509
+
510
+
511
+
512
+ /**
513
+ * Used in chaining. Runs a function there and then - not waiting for
514
+ * the events to fire (eg the onbeforedraw event)
515
+ *
516
+ * @param function func The function to execute
517
+ */
518
+ this.exec = function (func)
519
+ {
520
+ func(this);
521
+
522
+ return this;
523
+ };
524
+
525
+
526
+
527
+
528
+ /**
529
+ * The getObjectByXY() worker method
530
+ */
531
+ this.getObjectByXY = function (e)
532
+ {
533
+ var mouseXY = RG.getMouseXY(e);
534
+
535
+ if (this.getShape(e)) {
536
+ return this;
537
+ }
538
+ };
539
+
540
+
541
+
542
+
543
+ /**
544
+ * Not used by the class during creating the shape, but is used by event handlers
545
+ * to get the coordinates (if any) of the selected bar
546
+ *
547
+ * @param object e The event object
548
+ * @param object OPTIONAL You can pass in the bar object instead of the
549
+ * function using "this"
550
+ */
551
+ this.getShape = function (e)
552
+ {
553
+ var mouseXY = RG.getMouseXY(e);
554
+ var mouseX = mouseXY[0];
555
+ var mouseY = mouseXY[1];
556
+
557
+ if ( this.coords
558
+ && this.coords[0]
559
+ && mouseXY[0] >= this.coords[0][0]
560
+ && mouseXY[0] <= (this.coords[0][0] + this.coords[0][2])
561
+ && mouseXY[1] >= this.coords[0][1]
562
+ && mouseXY[1] <= (this.coords[0][1] + this.coords[0][3])) {
563
+
564
+ return {
565
+ 0: this, 1: this.coords[0][0], 2: this.coords[0][1], 3: this.coords[0][2], 4: this.coords[0][3], 5: 0,
566
+ 'object': this, 'x': this.coords[0][0], 'y': this.coords[0][1], 'width': this.coords[0][2], 'height': this.coords[0][3], 'index': 0, 'tooltip': prop['chart.tooltips'] ? prop['chart.tooltips'][0] : null
567
+ };
568
+ }
569
+
570
+ return null;
571
+ };
572
+
573
+
574
+
575
+
576
+ /**
577
+ * This function positions a tooltip when it is displayed
578
+ *
579
+ * @param obj object The chart object
580
+ * @param int x The X coordinate specified for the tooltip
581
+ * @param int y The Y coordinate specified for the tooltip
582
+ * @param object tooltip The tooltips DIV element
583
+ * @param number idx The index of the tooltip
584
+ */
585
+ this.positionTooltip = function (obj, x, y, tooltip, idx)
586
+ {
587
+ var canvasXY = RG.getCanvasXY(obj.canvas);
588
+ var width = tooltip.offsetWidth;
589
+ var height = tooltip.offsetHeight;
590
+
591
+ // Set the top position
592
+ tooltip.style.left = 0;
593
+ tooltip.style.top = canvasXY[1] - height - 7 + this.coords[0][1] + (obj.coords[0][3] / 2) + 'px';
594
+
595
+ // By default any overflow is hidden
596
+ tooltip.style.overflow = '';
597
+
598
+ // The arrow
599
+ var img = new Image();
600
+ img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC';
601
+ img.style.position = 'absolute';
602
+ img.id = '__rgraph_tooltip_pointer__';
603
+ img.style.top = (tooltip.offsetHeight - 2) + 'px';
604
+ tooltip.appendChild(img);
605
+
606
+ // Reposition the tooltip if at the edges:
607
+
608
+ // LEFT edge
609
+ if ((canvasXY[0] + obj.coords[0][0] + (obj.coords[0][2] / 2) - (width / 2)) < 10) {
610
+ tooltip.style.left = (canvasXY[0] + this.coords[0][0] + (this.coords[0][2] / 2) - (width * 0.1)) + 'px';
611
+ img.style.left = ((width * 0.1) - 8.5) + 'px';
612
+
613
+ // RIGHT edge
614
+ } else if ((canvasXY[0] + this.coords[0][0] + (this.coords[0][2] / 2) + (width / 2)) > doc.body.offsetWidth) {
615
+ tooltip.style.left = (canvasXY[0] + this.coords[0][0] + (this.coords[0][2] / 2) - (width * 0.9)) + 'px';
616
+ img.style.left = ((width * 0.9) - 8.5) + 'px';
617
+
618
+ // Default positioning - CENTERED
619
+ } else {
620
+ tooltip.style.left = (canvasXY[0] + this.coords[0][0] + (this.coords[0][2] / 2) - (width * 0.5)) + 'px';
621
+ img.style.left = ((width * 0.5) - 8.5) + 'px';
622
+ }
623
+ };
624
+
625
+
626
+
627
+
628
+ /**
629
+ * Each object type has its own Highlight() function which highlights the appropriate shape
630
+ *
631
+ * @param object shape The shape to highlight
632
+ */
633
+ this.highlight =
634
+ this.Highlight = function (shape)
635
+ {
636
+ if (prop['chart.tooltips.highlight']) {
637
+ pa(co, ['b','r',this.coords[0][0],this.coords[0][1],this.coords[0][2],this.coords[0][3], 'f',prop['chart.highlight.fill'], 's', prop['chart.highlight.stroke']]);
638
+ }
639
+ };
640
+
641
+
642
+
643
+
644
+ /**
645
+ * This allows for easy specification of gradients
646
+ */
647
+ this.parseColors = function ()
648
+ {
649
+
650
+ // Save the original colors so that they can be restored when the canvas is reset
651
+ if (this.original_colors.length === 0) {
652
+ this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
653
+ this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
654
+ }
655
+
656
+
657
+
658
+
659
+ /**
660
+ * Parse various properties for colors
661
+ */
662
+ prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
663
+ prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
664
+ };
665
+
666
+
667
+
668
+
669
+ /**
670
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
671
+ * need be etc
672
+ */
673
+ this.reset = function ()
674
+ {
675
+ };
676
+
677
+
678
+
679
+
680
+ /**
681
+ * This parses a single color value
682
+ */
683
+ this.parseSingleColorForGradient = function (color)
684
+ {
685
+ if (!color) {
686
+ return color;
687
+ }
688
+
689
+
690
+ if (typeof color === 'string' && color.match(/^gradient\((.*)\)$/i)) {
691
+
692
+ var parts = RegExp.$1.split(':');
693
+
694
+ // Create the gradient
695
+ var grad = co.createLinearGradient(this.x, this.y, this.x + this.img.width, this.y);
696
+
697
+ var diff = 1 / (parts.length - 1);
698
+
699
+ grad.addColorStop(0, RG.trim(parts[0]));
700
+
701
+ for (var j=1; j<parts.length; ++j) {
702
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
703
+ }
704
+ }
705
+
706
+ return grad ? grad : color;
707
+ };
708
+
709
+
710
+
711
+
712
+ /**
713
+ * Using a function to add events makes it easier to facilitate method chaining
714
+ *
715
+ * @param string type The type of even to add
716
+ * @param function func
717
+ */
718
+ this.on = function (type, func)
719
+ {
720
+ if (type.substr(0,2) !== 'on') {
721
+ type = 'on' + type;
722
+ }
723
+
724
+ this[type] = func;
725
+
726
+ return this;
727
+ };
728
+
729
+
730
+
731
+
732
+ /**
733
+ * This function runs once only
734
+ * (put at the end of the file (before any effects))
735
+ */
736
+ this.firstDrawFunc = function ()
737
+ {
738
+ };
739
+
740
+
741
+
742
+
743
+ /**
744
+ * This draws a rectangle for the border of the image with optional rounded corners
745
+ */
746
+ this.roundedRect = function (x, y, width, height, radius)
747
+ {
748
+ // Save the existing state of the canvas so that it can be restored later
749
+ co.save();
750
+
751
+ // Translate to the given X/Y coordinates
752
+ co.translate(x, y);
753
+
754
+ // Move to the center of the top horizontal line
755
+ co.moveTo(width / 2,0);
756
+
757
+ // Draw the rounded corners. The connecting lines in between them are drawn automatically
758
+ co.arcTo(width,0,width,height, ma.min(height / 2, radius));
759
+ co.arcTo(width, height, 0, height, ma.min(width / 2, radius));
760
+ co.arcTo(0, height, 0, 0, ma.min(height / 2, radius));
761
+ co.arcTo(0, 0, radius, 0, ma.min(width / 2, radius));
762
+
763
+ // Draw a line back to the start coordinates
764
+ co.lineTo(width / 2,0);
765
+
766
+ // Restore the state of the canvas to as it was before the save()
767
+ co.restore();
768
+ };
769
+
770
+
771
+
772
+
773
+ /**
774
+ *
775
+ */
776
+ this.drawBackgroundColor = function (borderRadius)
777
+ {
778
+ co.beginPath();
779
+ co.fillStyle = prop['chart.background.color'];
780
+ this.roundedRect(
781
+ ma.round(this.x) - ma.round(co.lineWidth / 2),
782
+ ma.round(this.y) - ma.round(co.lineWidth / 2),
783
+ (prop['chart.width'] || this.img.width) + co.lineWidth,
784
+ (prop['chart.height'] || this.img.height) + co.lineWidth,
785
+ borderRadius
786
+ );
787
+ co.fill();
788
+ };
789
+
790
+
791
+
792
+ RG.att(ca);
793
+
794
+
795
+ /**
796
+ * Objects are now always registered so that the chart is redrawn if need be.
797
+ */
798
+ RG.Register(this);
799
+
800
+
801
+
802
+
803
+ /**
804
+ * This is the 'end' of the constructor so if the first argument
805
+ * contains configuration data - handle that.
806
+ */
807
+ if (parseConfObjectForOptions) {
808
+ RG.parseObjectStyleConfig(this, conf.options);
809
+ }
810
+ };