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,292 @@
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
+ ModalDialog =
17
+ {
18
+ dialog: null,
19
+ background: null,
20
+ offset: 50,
21
+ events: [],
22
+
23
+
24
+
25
+
26
+ /**
27
+ * Shows the dialog with the supplied DIV acting as the contents
28
+ *
29
+ * @param string id The ID of the DIV to use as the dialogs contents
30
+ * @param int width The width of the dialog
31
+ */
32
+ Show: function (id, width)
33
+ {
34
+ ModalDialog.id = id;
35
+ ModalDialog.width = width;
36
+
37
+ ModalDialog.ShowBackground();
38
+ ModalDialog.ShowDialog();
39
+
40
+ // Install the event handlers
41
+ window.onresize = ModalDialog.Resize;
42
+
43
+
44
+ // Call them initially
45
+ ModalDialog.Resize();
46
+
47
+ if (typeof(ModalDialog.onmodaldialog) == 'function') {
48
+ ModalDialog.onmodaldialog();
49
+ }
50
+ ModalDialog.FireCustomEvent('onmodaldialog');
51
+ },
52
+
53
+
54
+
55
+
56
+ /**
57
+ * Shows the background semi-transparent darkened DIV
58
+ */
59
+ ShowBackground: function ()
60
+ {
61
+ // Create the background if neccessary
62
+ ModalDialog.background = document.createElement('DIV');
63
+ ModalDialog.background.className = 'ModalDialog_background';
64
+ ModalDialog.background.style.position = 'fixed';
65
+ ModalDialog.background.style.top = 0;
66
+ ModalDialog.background.style.left = 0;
67
+ ModalDialog.background.style.width = (screen.width + 100) + 'px';
68
+ ModalDialog.background.style.height = (screen.height + 100) + 'px';
69
+ ModalDialog.background.style.backgroundColor = 'rgb(204,204,204)';
70
+ ModalDialog.background.style.opacity = 0;
71
+ ModalDialog.background.style.zIndex = 3276;
72
+ ModalDialog.background.style.filter = "Alpha(opacity=50)";
73
+
74
+ document.body.appendChild(ModalDialog.background);
75
+
76
+ ModalDialog.background.style.visibility = 'visible';
77
+ },
78
+
79
+
80
+
81
+
82
+ /**
83
+ * Shows the dialog itself
84
+ */
85
+ ShowDialog: function ()
86
+ {
87
+ // Create the DIV if necessary
88
+ // Jan 2012- Changed so that the dialog is ALWAYS (re)created
89
+ if (!ModalDialog.dialog || true) {
90
+ ModalDialog.dialog = document.createElement('DIV');
91
+
92
+ ModalDialog.dialog.id = 'ModalDialog_dialog';
93
+ ModalDialog.dialog.className = 'ModalDialog_dialog';
94
+
95
+ var borderRadius = '15px';
96
+
97
+ ModalDialog.dialog.style.borderRadius = borderRadius;
98
+ ModalDialog.dialog.style.MozBorderRadius = borderRadius;
99
+ ModalDialog.dialog.style.WebkitBorderRadius = borderRadius;
100
+
101
+ ModalDialog.dialog.style.boxShadow = '3px 3px 3px rgba(96,96,96,0.5)';
102
+ ModalDialog.dialog.style.MozBoxShadow = '3px 3px 3px rgba(96,96,96,0.5)';
103
+ ModalDialog.dialog.style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 3px 3px 3px';
104
+
105
+ ModalDialog.dialog.style.position = 'fixed';
106
+ ModalDialog.dialog.style.backgroundColor = 'white';
107
+ ModalDialog.dialog.style.width = parseInt(ModalDialog.width) + 'px';
108
+ ModalDialog.dialog.style.border = '2px solid #999';
109
+ ModalDialog.dialog.style.zIndex = 32767;
110
+ ModalDialog.dialog.style.padding = '5px';
111
+ ModalDialog.dialog.style.paddingTop = '25px';
112
+ ModalDialog.dialog.style.opacity = 0;
113
+
114
+ if (document.all) {
115
+ ModalDialog.dialog.style.zIndex = 32767;
116
+ }
117
+
118
+
119
+
120
+ // Accomodate various browsers
121
+ if (navigator.userAgent.indexOf('Opera') != -1) {
122
+ ModalDialog.dialog.style.paddingTop = '25px';
123
+
124
+ } else if (navigator.userAgent.indexOf('MSIE') != -1) {
125
+ ModalDialog.dialog.style.paddingTop = '25px';
126
+
127
+ } else if (navigator.userAgent.indexOf('Safari') != -1) {
128
+ ModalDialog.dialog.style.paddingTop = '25px';
129
+ }
130
+
131
+ document.body.appendChild(ModalDialog.dialog);
132
+
133
+
134
+ // Now create the grey bar at the top of the dialog
135
+ var bar = document.createElement('DIV');
136
+ bar.className = 'ModalDialog_topbar';
137
+ bar.style.top = 0;
138
+ bar.style.left = 0;
139
+ bar.style.width = '100%';//(ModalDialog.dialog.offsetWidth - 4) + 'px';
140
+ bar.style.height = '20px';
141
+ bar.style.backgroundColor = '#bbb';
142
+ bar.style.borderBottom = '2px solid #999';
143
+ //bar.style.zIndex = 50000;
144
+ bar.style.position = 'absolute';
145
+ var borderRadius = '11px';
146
+ bar.style.WebkitBorderTopLeftRadius = borderRadius;
147
+ bar.style.WebkitBorderTopRightRadius = borderRadius;
148
+ bar.style.MozBorderRadiusTopleft = borderRadius;
149
+ bar.style.MozBorderRadiusTopright = borderRadius;
150
+ bar.style.borderTopRightRadius = borderRadius;
151
+ bar.style.borderTopLeftRadius = borderRadius;
152
+ ModalDialog.dialog.appendChild(bar);
153
+
154
+ // Add the content div
155
+ var content = document.createElement('DIV');
156
+ //content.style.paddingTop = '20px';
157
+ content.style.width = '100%';
158
+ content.style.height = '100%';
159
+ ModalDialog.dialog.appendChild(content);
160
+
161
+ if (ModalDialog.id.toLowerCase().substring(0, 7) == 'string:') {
162
+ content.innerHTML = ModalDialog.id.substring(7);
163
+ } else {
164
+ content.innerHTML = document.getElementById(ModalDialog.id).innerHTML;
165
+ }
166
+
167
+ // Now reposition the dialog in the center
168
+ ModalDialog.dialog.style.left = (document.body.offsetWidth / 2) - (ModalDialog.dialog.offsetWidth / 2) + 'px';
169
+ ModalDialog.dialog.style.top = '30%';
170
+ }
171
+
172
+ // Show the dialog
173
+ ModalDialog.dialog.style.visibility = 'visible';
174
+
175
+ // A simple fade-in effect
176
+ setTimeout('ModalDialog.dialog.style.opacity = 0.2', 50);
177
+ setTimeout('ModalDialog.dialog.style.opacity = 0.4', 100);
178
+ setTimeout('ModalDialog.dialog.style.opacity = 0.6', 150);
179
+ setTimeout('ModalDialog.dialog.style.opacity = 0.8', 200);
180
+ setTimeout('ModalDialog.dialog.style.opacity = 1', 250);
181
+
182
+ setTimeout('ModalDialog.background.style.opacity = 0.1', 50);
183
+ setTimeout('ModalDialog.background.style.opacity = 0.2', 100);
184
+ setTimeout('ModalDialog.background.style.opacity = 0.3', 150);
185
+ setTimeout('ModalDialog.background.style.opacity = 0.4', 200);
186
+ setTimeout('ModalDialog.background.style.opacity = 0.5', 250);
187
+ },
188
+
189
+
190
+
191
+
192
+ /**
193
+ * Hides everything
194
+ */
195
+ Close: function ()
196
+ {
197
+ if (ModalDialog.dialog) {
198
+ // February 2012 - now remove the dialog node from the DOM
199
+ if (document.getElementById(ModalDialog.dialog.id)) {
200
+ document.body.removeChild(ModalDialog.dialog);
201
+ }
202
+
203
+ ModalDialog.dialog.style.visibility = 'hidden';
204
+ ModalDialog.dialog.style.opacity = 0;
205
+ }
206
+
207
+ if (ModalDialog.background) {
208
+ ModalDialog.background.style.visibility = 'hidden';
209
+ ModalDialog.background.style.opacity = 0;
210
+
211
+ // February 2012 - now remove the dialog node from the DOM
212
+ if (document.getElementById(ModalDialog.background.id)) {
213
+ document.body.removeChild(ModalDialog.background);
214
+ }
215
+ }
216
+ },
217
+
218
+
219
+
220
+
221
+ /**
222
+ * Accommodate the window being resized
223
+ */
224
+ Resize: function ()
225
+ {
226
+ if (ModalDialog.dialog) {
227
+ ModalDialog.dialog.style.left = (document.body.offsetWidth / 2) - (ModalDialog.dialog.offsetWidth / 2) + 'px';
228
+ }
229
+
230
+ ModalDialog.background.style.width = '2500px';
231
+ ModalDialog.background.style.height = '2500px';
232
+ },
233
+
234
+
235
+
236
+
237
+ /**
238
+ * Returns the page height
239
+ *
240
+ * @return int The page height
241
+ */
242
+ AddCustomEventListener: function (name, func)
243
+ {
244
+ if (typeof(ModalDialog.events) == 'undefined') {
245
+ ModalDialog.events = [];
246
+ }
247
+
248
+ ModalDialog.events.push([name, func]);
249
+ },
250
+
251
+
252
+
253
+
254
+ /**
255
+ * Used to fire the ModalDialog custom event
256
+ *
257
+ * @param object obj The graph object that fires the event
258
+ * @param string event The name of the event to fire
259
+ */
260
+ FireCustomEvent: function (name)
261
+ {
262
+ for (var i=0; i<ModalDialog.events.length; ++i) {
263
+ if (typeof(ModalDialog.events[i][0]) == 'string' && ModalDialog.events[i][0] == name && typeof(ModalDialog.events[i][1]) == 'function') {
264
+ ModalDialog.events[i][1]();
265
+ }
266
+ }
267
+ },
268
+
269
+
270
+
271
+
272
+ /**
273
+ * Returns true if the browser is IE8
274
+ */
275
+ isIE8: function ()
276
+ {
277
+ return document.all && (navigator.userAgent.indexOf('MSIE 8') > 0);
278
+ }
279
+ };
280
+
281
+
282
+
283
+
284
+ // An alias
285
+ ModalDialog.Hide = ModalDialog.Close;
286
+
287
+ // Lowercase all of the function names
288
+ for (i in ModalDialog) {
289
+ if (typeof ModalDialog[i] === 'function') {
290
+ ModalDialog[i.toLowerCase()] = ModalDialog[i]
291
+ }
292
+ }
@@ -0,0 +1,1265 @@
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 odometer constructor. Pass it the ID of the canvas tag, the start value of the odo,
20
+ * the end value, and the value that the pointer should point to.
21
+ *
22
+ * @param string id The ID of the canvas tag
23
+ * @param int start The start value of the Odo
24
+ * @param int end The end value of the odo
25
+ * @param int value The indicated value (what the needle points to)
26
+ */
27
+ RGraph.Odometer = function (conf)
28
+ {
29
+ /**
30
+ * Allow for object config style
31
+ */
32
+ if ( typeof conf === 'object'
33
+ && typeof conf.min === 'number'
34
+ && typeof conf.max === 'number'
35
+ && typeof conf.value !== 'undefined'
36
+ && typeof conf.id === 'string') {
37
+
38
+ var id = conf.id
39
+ var canvas = document.getElementById(id);
40
+ var min = conf.min;
41
+ var max = conf.max;
42
+ var value = conf.value;
43
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
44
+
45
+ } else {
46
+
47
+ var id = conf;
48
+ var canvas = document.getElementById(id);
49
+ var min = arguments[1];
50
+ var max = arguments[2];
51
+ var value = arguments[3];
52
+ }
53
+
54
+
55
+
56
+
57
+ this.id = id;
58
+ this.canvas = canvas;
59
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
60
+ this.canvas.__object__ = this;
61
+ this.type = 'odo';
62
+ this.isRGraph = true;
63
+ this.min = min;
64
+ this.max = max;
65
+ this.value = RGraph.stringsToNumbers(value);
66
+ this.currentValue = null;
67
+ this.uid = RGraph.CreateUID();
68
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
69
+ this.colorsParsed = false;
70
+ this.coordsText = [];
71
+ this.original_colors = [];
72
+ this.firstDraw = true; // After the first draw this will be false
73
+
74
+
75
+ /**
76
+ * Compatibility with older browsers
77
+ */
78
+ //RGraph.OldBrowserCompat(this.context);
79
+
80
+
81
+ this.properties =
82
+ {
83
+ 'chart.background.border': 'black',
84
+ 'chart.background.color': '#eee',
85
+ 'chart.background.lines.color': '#ddd',
86
+ 'chart.centerx': null,
87
+ 'chart.centery': null,
88
+ 'chart.radius': null,
89
+ 'chart.value.text': false,
90
+ 'chart.value.text.decimals': 0,
91
+ 'chart.needle.color': 'black',
92
+ 'chart.needle.width': 2,
93
+ 'chart.needle.head': true,
94
+ 'chart.needle.tail': true,
95
+ 'chart.needle.type': 'pointer',
96
+ 'chart.needle.extra': [],
97
+ 'chart.needle.triangle.border': '#aaa',
98
+ 'chart.text.size': 12,
99
+ 'chart.text.color': 'black',
100
+ 'chart.text.font': 'Arial',
101
+ 'chart.green.max': max * 0.75,
102
+ 'chart.red.min': max * 0.9,
103
+ 'chart.green.color': 'Gradient(white:#0c0)',
104
+ 'chart.yellow.color': 'Gradient(white:#ff0)',
105
+ 'chart.red.color': 'Gradient(white:#f00)',
106
+ 'chart.label.area': 35,
107
+ 'chart.gutter.left': 25,
108
+ 'chart.gutter.right': 25,
109
+ 'chart.gutter.top': 25,
110
+ 'chart.gutter.bottom': 25,
111
+ 'chart.title': '',
112
+ 'chart.title.background': null,
113
+ 'chart.title.hpos': null,
114
+ 'chart.title.vpos': null,
115
+ 'chart.title.font': null,
116
+ 'chart.title.bold': true,
117
+ 'chart.title.x': null,
118
+ 'chart.title.y': null,
119
+ 'chart.title.halign': null,
120
+ 'chart.title.valign': null,
121
+ 'chart.contextmenu': null,
122
+ 'chart.linewidth': 1,
123
+ 'chart.shadow.inner': false,
124
+ 'chart.shadow.inner.color': 'black',
125
+ 'chart.shadow.inner.offsetx': 3,
126
+ 'chart.shadow.inner.offsety': 3,
127
+ 'chart.shadow.inner.blur': 6,
128
+ 'chart.shadow.outer': false,
129
+ 'chart.shadow.outer.color': 'black',
130
+ 'chart.shadow.outer.offsetx': 3,
131
+ 'chart.shadow.outer.offsety': 3,
132
+ 'chart.shadow.outer.blur': 6,
133
+ 'chart.annotatable': false,
134
+ 'chart.annotate.color': 'black',
135
+ 'chart.scale.decimals': 0,
136
+ 'chart.scale.point': '.',
137
+ 'chart.scale.thousand': ',',
138
+ 'chart.zoom.factor': 1.5,
139
+ 'chart.zoom.fade.in': true,
140
+ 'chart.zoom.fade.out': true,
141
+ 'chart.zoom.hdir': 'right',
142
+ 'chart.zoom.vdir': 'down',
143
+ 'chart.zoom.frames': 25,
144
+ 'chart.zoom.delay': 16.666,
145
+ 'chart.zoom.shadow': true,
146
+ 'chart.zoom.background': true,
147
+ 'chart.zoom.action': 'zoom',
148
+ 'chart.resizable': false,
149
+ 'chart.resize.handle.adjust': [0,0],
150
+ 'chart.resize.handle.background': null,
151
+ 'chart.units.pre': '',
152
+ 'chart.units.post': '',
153
+ 'chart.border': false,
154
+ 'chart.border.color1': '#BEBCB0',
155
+ 'chart.border.color2': '#F0EFEA',
156
+ 'chart.border.color3': '#BEBCB0',
157
+ 'chart.tickmarks': true,
158
+ 'chart.tickmarks.highlighted': false,
159
+ 'chart.tickmarks.big.color': '#999',
160
+ 'chart.zerostart': false,
161
+ 'chart.labels': null,
162
+ 'chart.units.pre': '',
163
+ 'chart.units.post': '',
164
+ 'chart.value.units.pre': '',
165
+ 'chart.value.units.post': '',
166
+ 'chart.key': null,
167
+ 'chart.key.background': 'white',
168
+ 'chart.key.position': 'graph',
169
+ 'chart.key.shadow': false,
170
+ 'chart.key.shadow.color': '#666',
171
+ 'chart.key.shadow.blur': 3,
172
+ 'chart.key.shadow.offsetx': 2,
173
+ 'chart.key.shadow.offsety': 2,
174
+ 'chart.key.position.gutter.boxed':false,
175
+ 'chart.key.position.x': null,
176
+ 'chart.key.position.y': null,
177
+ 'chart.key.halign': 'right',
178
+ 'chart.key.color.shape': 'square',
179
+ 'chart.key.rounded': true,
180
+ 'chart.key.text.size': 10,
181
+ 'chart.key.colors': null,
182
+ 'chart.key.text.color': 'black',
183
+ 'chart.adjustable': false
184
+ }
185
+
186
+
187
+
188
+ /*
189
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
190
+ * done already
191
+ */
192
+ if (!this.canvas.__rgraph_aa_translated__) {
193
+ this.context.translate(0.5,0.5);
194
+
195
+ this.canvas.__rgraph_aa_translated__ = true;
196
+ }
197
+
198
+
199
+
200
+ // Short variable names
201
+ var RG = RGraph,
202
+ ca = this.canvas,
203
+ co = ca.getContext('2d'),
204
+ prop = this.properties,
205
+ pa = RG.Path,
206
+ pa2 = RG.path2,
207
+ win = window,
208
+ doc = document,
209
+ ma = Math
210
+
211
+
212
+
213
+ /**
214
+ * "Decorate" the object with the generic effects if the effects library has been included
215
+ */
216
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
217
+ RG.Effects.decorate(this);
218
+ }
219
+
220
+
221
+
222
+
223
+ /**
224
+ * A peudo setter
225
+ *
226
+ * @param name string The name of the property to set
227
+ * @param value mixed The value of the property
228
+ */
229
+ this.set =
230
+ this.Set = function (name, value)
231
+ {
232
+ var value = arguments[1] || null;
233
+
234
+ /**
235
+ * the number of arguments is only one and it's an
236
+ * object - parse it for configuration data and return.
237
+ */
238
+ if (arguments.length === 1 && typeof name === 'object') {
239
+ RG.parseObjectStyleConfig(this, name);
240
+ return this;
241
+ }
242
+
243
+
244
+
245
+
246
+
247
+ /**
248
+ * This should be done first - prepend the property name with "chart." if necessary
249
+ */
250
+ if (name.substr(0,6) != 'chart.') {
251
+ name = 'chart.' + name;
252
+ }
253
+
254
+
255
+
256
+
257
+ // Convert uppercase letters to dot+lower case letter
258
+ name = name.replace(/([A-Z])/g, function (str)
259
+ {
260
+ return '.' + String(RegExp.$1).toLowerCase();
261
+ });
262
+
263
+ if (name == 'chart.needle.style') {
264
+ alert('[RGRAPH] The RGraph property chart.needle.style has changed to chart.needle.color');
265
+ }
266
+
267
+ if (name == 'chart.needle.thickness') {
268
+ name = 'chart.needle.width';
269
+ }
270
+
271
+ if (name == 'chart.value') {
272
+ this.value = value;
273
+ return;
274
+ }
275
+
276
+
277
+
278
+
279
+
280
+
281
+ prop[name] = value;
282
+
283
+ return this;
284
+ };
285
+
286
+
287
+
288
+
289
+ /**
290
+ * A getter
291
+ *
292
+ * @param name string The name of the property to get
293
+ */
294
+ this.get =
295
+ this.Get = function (name)
296
+ {
297
+ /**
298
+ * This should be done first - prepend the property name with "chart." if necessary
299
+ */
300
+ if (name.substr(0,6) != 'chart.') {
301
+ name = 'chart.' + name;
302
+ }
303
+
304
+ // Convert uppercase letters to dot+lower case letter
305
+ name = name.replace(/([A-Z])/g, function (str)
306
+ {
307
+ return '.' + String(RegExp.$1).toLowerCase()
308
+ });
309
+
310
+ if (name == 'chart.value') {
311
+ return this.value;
312
+ }
313
+
314
+ return prop[name.toLowerCase()];
315
+ };
316
+
317
+
318
+
319
+
320
+ /**
321
+ * Draws the odometer
322
+ */
323
+ this.draw =
324
+ this.Draw = function ()
325
+ {
326
+ /**
327
+ * Fire the onbeforedraw event
328
+ */
329
+ RG.FireCustomEvent(this, 'onbeforedraw');
330
+
331
+
332
+ /**
333
+ * Set the current value
334
+ */
335
+ this.currentValue = this.value;
336
+
337
+ /**
338
+ * No longer allow values outside the range of the Odo
339
+ */
340
+ if (this.value > this.max) {
341
+ this.value = this.max;
342
+ }
343
+
344
+ if (this.value < this.min) {
345
+ this.value = this.min;
346
+ }
347
+
348
+ /**
349
+ * This is new in May 2011 and facilitates indiviual gutter settings,
350
+ * eg chart.gutter.left
351
+ */
352
+ this.gutterLeft = prop['chart.gutter.left'];
353
+ this.gutterRight = prop['chart.gutter.right'];
354
+ this.gutterTop = prop['chart.gutter.top'];
355
+ this.gutterBottom = prop['chart.gutter.bottom'];
356
+
357
+ // Work out a few things
358
+ this.radius = Math.min(
359
+ (ca.width - this.gutterLeft - this.gutterRight) / 2,
360
+ (ca.height - this.gutterTop - this.gutterBottom) / 2
361
+ )
362
+ - (prop['chart.border'] ? 25 : 0);
363
+ this.diameter = 2 * this.radius;
364
+ this.centerx = ((ca.width - this.gutterLeft- this.gutterRight) / 2) + this.gutterLeft;
365
+ this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
366
+ this.range = this.max - this.min;
367
+ this.coordsText = [];
368
+
369
+ /**
370
+ * Move the centerx if the key is defined
371
+ */
372
+ if (prop['chart.key'] && prop['chart.key'].length > 0 && ca.width > ca.height) this.centerx = 5 + this.radius;
373
+ if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
374
+ if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
375
+
376
+
377
+ /**
378
+ * Allow custom setting of the radius
379
+ */
380
+ if (typeof(prop['chart.radius']) == 'number') {
381
+ this.radius = prop['chart.radius'];
382
+
383
+ if (prop['chart.border']) {
384
+ this.radius -= 25;
385
+ }
386
+ }
387
+
388
+
389
+ /**
390
+ * Parse the colors for gradients. Its down here so that the center X/Y can be used
391
+ */
392
+ if (!this.colorsParsed) {
393
+
394
+ this.parseColors();
395
+
396
+ // Don't want to do this again
397
+ this.colorsParsed = true;
398
+ }
399
+
400
+
401
+
402
+ co.lineWidth = prop['chart.linewidth'];
403
+
404
+ // Draw the background
405
+ this.DrawBackground();
406
+
407
+ // And lastly, draw the labels
408
+ this.DrawLabels();
409
+
410
+ // Draw the needle
411
+ this.DrawNeedle(this.value, prop['chart.needle.color']);
412
+
413
+ /**
414
+ * Draw any extra needles
415
+ */
416
+ if (prop['chart.needle.extra'].length > 0) {
417
+ for (var i=0; i<prop['chart.needle.extra'].length; ++i) {
418
+ var needle = prop['chart.needle.extra'][i];
419
+ this.DrawNeedle(needle[0], needle[1], needle[2]);
420
+ }
421
+ }
422
+
423
+ /**
424
+ * Draw the key if requested
425
+ */
426
+ if (prop['chart.key'] && prop['chart.key'].length > 0) {
427
+ // Build a colors array out of the needle colors
428
+ var colors = [prop['chart.needle.color']];
429
+
430
+ if (prop['chart.needle.extra'].length > 0) {
431
+ for (var i=0; i<prop['chart.needle.extra'].length; ++i) {
432
+ var needle = prop['chart.needle.extra'][i];
433
+ colors.push(needle[1]);
434
+ }
435
+ }
436
+
437
+ RG.DrawKey(this, prop['chart.key'], colors);
438
+ }
439
+
440
+
441
+ /**
442
+ * Setup the context menu if required
443
+ */
444
+ if (prop['chart.contextmenu']) {
445
+ RG.ShowContext(this);
446
+ }
447
+
448
+
449
+ /**
450
+ * This function enables resizing
451
+ */
452
+ if (prop['chart.resizable']) {
453
+ RG.AllowResizing(this);
454
+ }
455
+
456
+
457
+ /**
458
+ * This installs the event listeners
459
+ */
460
+ RG.InstallEventListeners(this);
461
+
462
+
463
+
464
+ /**
465
+ * Fire the onfirstdraw event
466
+ */
467
+ if (this.firstDraw) {
468
+ RG.fireCustomEvent(this, 'onfirstdraw');
469
+ this.firstDraw = false;
470
+ this.firstDrawFunc();
471
+ }
472
+
473
+
474
+
475
+
476
+ /**
477
+ * Fire the RGraph ondraw event
478
+ */
479
+ RG.FireCustomEvent(this, 'ondraw');
480
+
481
+ return this;
482
+ };
483
+
484
+
485
+
486
+ /**
487
+ * Used in chaining. Runs a function there and then - not waiting for
488
+ * the events to fire (eg the onbeforedraw event)
489
+ *
490
+ * @param function func The function to execute
491
+ */
492
+ this.exec = function (func)
493
+ {
494
+ func(this);
495
+
496
+ return this;
497
+ };
498
+
499
+
500
+
501
+
502
+ /**
503
+ * Draws the background
504
+ */
505
+ this.drawBackground =
506
+ this.DrawBackground = function ()
507
+ {
508
+ co.beginPath();
509
+
510
+ /**
511
+ * Turn on the shadow if need be
512
+ */
513
+ if (prop['chart.shadow.outer']) {
514
+ RG.setShadow(this, prop['chart.shadow.outer.color'], prop['chart.shadow.outer.offsetx'], prop['chart.shadow.outer.offsety'], prop['chart.shadow.outer.blur']);
515
+ }
516
+
517
+ var backgroundColor = prop['chart.background.color'];
518
+
519
+ // Draw the grey border
520
+ co.fillStyle = backgroundColor;
521
+ co.arc(this.centerx, this.centery, this.radius, 0.0001, RG.TWOPI, false);
522
+ co.fill();
523
+
524
+ /**
525
+ * Turn off the shadow
526
+ */
527
+ RG.noShadow(this);
528
+
529
+
530
+ // Draw a circle
531
+ co.strokeStyle = '#666';
532
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, false);
533
+
534
+ // Now draw a big white circle to make the lines appear as tick marks
535
+ // This is solely for Chrome
536
+ co.fillStyle = backgroundColor;
537
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, false);
538
+ co.fill();
539
+
540
+ /**
541
+ * Draw more tickmarks
542
+ */
543
+ if (prop['chart.tickmarks']) {
544
+ co.beginPath();
545
+ co.strokeStyle = '#bbb';
546
+
547
+ for (var i=0; i<=360; i+=3) {
548
+ co.arc(this.centerx, this.centery, this.radius, 0, i / 57.3, false);
549
+ co.lineTo(this.centerx, this.centery);
550
+ }
551
+ co.stroke();
552
+ }
553
+
554
+ co.beginPath();
555
+ co.lineWidth = 1;
556
+ co.strokeStyle = 'black';
557
+
558
+ // Now draw a big white circle to make the lines appear as tick marks
559
+ co.fillStyle = backgroundColor;
560
+ co.strokeStyle = backgroundColor;
561
+ co.arc(this.centerx, this.centery, this.radius - 5, 0, RG.TWOPI, false);
562
+ co.fill();
563
+ co.stroke();
564
+
565
+ // Gray lines at 18 degree intervals
566
+ co.beginPath();
567
+ co.strokeStyle = prop['chart.background.lines.color'];
568
+ for (var i=0; i<360; i+=18) {
569
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.degrees2Radians(i), false);
570
+ co.lineTo(this.centerx, this.centery);
571
+ }
572
+ co.stroke();
573
+
574
+ // Redraw the outer circle
575
+ co.beginPath();
576
+ co.strokeStyle = prop['chart.background.border'];
577
+ co.arc(this.centerx, this.centery, this.radius, 0, RG.TWOPI, false);
578
+ co.stroke();
579
+
580
+ /**
581
+ * Now draw the center bits shadow if need be
582
+ */
583
+ if (prop['chart.shadow.inner']) {
584
+ co.beginPath();
585
+ RG.SetShadow(this, prop['chart.shadow.inner.color'], prop['chart.shadow.inner.offsetx'], prop['chart.shadow.inner.offsety'], prop['chart.shadow.inner.blur']);
586
+ co.arc(this.centerx, this.centery, this.radius - prop['chart.label.area'], 0, RG.TWOPI, 0);
587
+ co.fill();
588
+ co.stroke();
589
+
590
+ /**
591
+ * Turn off the shadow
592
+ */
593
+ RG.NoShadow(this);
594
+ }
595
+
596
+ /*******************************************************
597
+ * Draw the green area
598
+ *******************************************************/
599
+ var greengrad = prop['chart.green.color'];
600
+
601
+ // Draw the "tick highlight"
602
+ if (prop['chart.tickmarks.highlighted']) {
603
+ co.beginPath();
604
+ co.lineWidth = 5;
605
+ co.strokeStyle = greengrad;
606
+ co.arc(this.centerx, this.centery, this.radius - 2.5,
607
+
608
+ -1 * RG.HALFPI,
609
+ (((prop['chart.green.max'] - this.min)/ (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
610
+ 0);
611
+
612
+ co.stroke();
613
+
614
+ co.lineWidth = 1;
615
+ }
616
+
617
+ co.beginPath();
618
+ co.fillStyle = greengrad;
619
+ co.arc(
620
+ this.centerx,
621
+ this.centery,
622
+ this.radius - prop['chart.label.area'],
623
+ 0 - RG.HALFPI,
624
+ (((prop['chart.green.max'] - this.min)/ (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
625
+ false
626
+ );
627
+ co.lineTo(this.centerx, this.centery);
628
+ co.closePath();
629
+ co.fill();
630
+
631
+
632
+ /*******************************************************
633
+ * Draw the yellow area
634
+ *******************************************************/
635
+ var yellowgrad = prop['chart.yellow.color'];
636
+
637
+ // Draw the "tick highlight"
638
+ if (prop['chart.tickmarks.highlighted']) {
639
+ co.beginPath();
640
+ co.lineWidth = 5;
641
+ co.strokeStyle = yellowgrad;
642
+ co.arc(this.centerx, this.centery, this.radius - 2.5, (
643
+
644
+ ((prop['chart.green.max'] - this.min) / (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
645
+ (((prop['chart.red.min'] - this.min) / (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
646
+ 0);
647
+
648
+ co.stroke();
649
+
650
+ co.lineWidth = 1;
651
+ }
652
+
653
+ co.beginPath();
654
+ co.fillStyle = yellowgrad;
655
+ co.arc(
656
+ this.centerx,
657
+ this.centery,
658
+ this.radius - prop['chart.label.area'],
659
+ ( ((prop['chart.green.max'] - this.min) / (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
660
+ ( ((prop['chart.red.min'] - this.min) / (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
661
+ false
662
+ );
663
+ co.lineTo(this.centerx, this.centery);
664
+ co.closePath();
665
+ co.fill();
666
+
667
+ /*******************************************************
668
+ * Draw the red area
669
+ *******************************************************/
670
+ var redgrad = prop['chart.red.color'];
671
+
672
+ // Draw the "tick highlight"
673
+ if (prop['chart.tickmarks.highlighted']) {
674
+ co.beginPath();
675
+ co.lineWidth = 5;
676
+ co.strokeStyle = redgrad;
677
+ co.arc(this.centerx, this.centery, this.radius - 2.5,(((prop['chart.red.min'] - this.min) / (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,RG.TWOPI - RG.HALFPI,0);
678
+ co.stroke();
679
+
680
+ co.lineWidth = 1;
681
+ }
682
+
683
+ co.beginPath();
684
+ co.fillStyle = redgrad;
685
+ co.strokeStyle = redgrad;
686
+ co.arc(
687
+ this.centerx,
688
+ this.centery,
689
+ this.radius - prop['chart.label.area'],
690
+ (((prop['chart.red.min'] - this.min) / (this.max - this.min)) * RG.TWOPI) - RG.HALFPI,
691
+ RG.TWOPI - RG.HALFPI,
692
+ false
693
+ );
694
+ co.lineTo(this.centerx, this.centery);
695
+ co.closePath();
696
+ co.fill();
697
+
698
+
699
+ /**
700
+ * Draw the thick border
701
+ */
702
+ if (prop['chart.border']) {
703
+
704
+ var grad = co.createRadialGradient(this.centerx, this.centery, this.radius, this.centerx, this.centery, this.radius + 20);
705
+ grad.addColorStop(0, prop['chart.border.color1']);
706
+ grad.addColorStop(0.5, prop['chart.border.color2']);
707
+ grad.addColorStop(1, prop['chart.border.color3']);
708
+
709
+
710
+ co.beginPath();
711
+ co.fillStyle = grad;
712
+ co.strokeStyle = 'rgba(0,0,0,0)'
713
+ co.lineWidth = 0.001;
714
+ co.arc(this.centerx, this.centery, this.radius + 20, 0, RG.TWOPI, 0);
715
+ co.arc(this.centerx, this.centery, this.radius - 2, RG.TWOPI, 0, 1);
716
+ co.fill();
717
+ }
718
+
719
+ // Put the linewidth back to what it was
720
+ co.lineWidth = prop['chart.linewidth'];
721
+
722
+
723
+ /**
724
+ * Draw the title if specified
725
+ */
726
+ if (prop['chart.title']) {
727
+ RG.DrawTitle(this,
728
+ prop['chart.title'],
729
+ this.centery - this.radius,
730
+ null,
731
+ prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2);
732
+ }
733
+
734
+
735
+ // Draw the big tick marks
736
+ if (!prop['chart.tickmarks.highlighted']) {
737
+ for (var i=18; i<=360; i+=36) {
738
+ co.beginPath();
739
+ co.strokeStyle = prop['chart.tickmarks.big.color'];
740
+ co.lineWidth = 2;
741
+ co.arc(this.centerx, this.centery, this.radius - 1, RG.degrees2Radians(i), RG.degrees2Radians(i+0.01), false);
742
+ co.arc(this.centerx, this.centery, this.radius - 7, RG.degrees2Radians(i), RG.degrees2Radians(i+0.01), false);
743
+ co.stroke();
744
+ }
745
+ }
746
+ };
747
+
748
+
749
+
750
+
751
+ /**
752
+ * Draws the needle of the odometer
753
+ *
754
+ * @param number value The value to represent
755
+ * @param string color The color of the needle
756
+ * @param number The OPTIONAL length of the needle
757
+ */
758
+ this.drawNeedle =
759
+ this.DrawNeedle = function (value, color)
760
+ {
761
+ // The optional length of the needle
762
+ var length = arguments[2] ? arguments[2] : this.radius - prop['chart.label.area'];
763
+
764
+ // ===== First draw a grey background circle =====
765
+
766
+ co.fillStyle = '#999';
767
+
768
+ co.beginPath();
769
+ co.moveTo(this.centerx, this.centery);
770
+ co.arc(this.centerx, this.centery, 10, 0, RG.TWOPI, false);
771
+ co.fill();
772
+ co.closePath();
773
+
774
+ co.fill();
775
+
776
+ // ===============================================
777
+
778
+ co.fillStyle = color
779
+ co.strokeStyle = '#666';
780
+
781
+ // Draw the centre bit
782
+ co.beginPath();
783
+ co.moveTo(this.centerx, this.centery);
784
+ co.arc(this.centerx, this.centery, 8, 0, RG.TWOPI, false);
785
+ co.fill();
786
+ co.closePath();
787
+
788
+ co.stroke();
789
+ co.fill();
790
+
791
+ if (prop['chart.needle.type'] == 'pointer') {
792
+
793
+ co.strokeStyle = color;
794
+ co.lineWidth = prop['chart.needle.width'];
795
+ co.lineCap = 'round';
796
+ co.lineJoin = 'round';
797
+
798
+ // Draw the needle
799
+ co.beginPath();
800
+ // The trailing bit on the opposite side of the dial
801
+ co.beginPath();
802
+ co.moveTo(this.centerx, this.centery);
803
+
804
+ if (prop['chart.needle.tail']) {
805
+
806
+ co.arc(this.centerx,
807
+ this.centery,
808
+ 20,
809
+ (((value / this.range) * 360) + 90) / (180 / RG.PI),
810
+ (((value / this.range) * 360) + 90 + 0.01) / (180 / RG.PI), // The 0.01 avoids a bug in ExCanvas and Chrome 6
811
+ false
812
+ );
813
+ }
814
+
815
+ // Draw the long bit on the opposite side
816
+ co.arc(this.centerx,
817
+ this.centery,
818
+ length - 10,
819
+ (((value / this.range) * 360) - 90) / (180 / RG.PI),
820
+ (((value / this.range) * 360) - 90 + 0.1 ) / (180 / RG.PI), // The 0.1 avoids a bug in ExCanvas and Chrome 6
821
+ false
822
+ );
823
+ co.closePath();
824
+
825
+ //co.stroke();
826
+ //co.fill();
827
+
828
+
829
+ } else if (prop['chart.needle.type'] == 'triangle') {
830
+
831
+ co.lineWidth = 0.01;
832
+ co.lineEnd = 'square';
833
+ co.lineJoin = 'miter';
834
+
835
+ /**
836
+ * This draws the version of the pointer that becomes the border
837
+ */
838
+ co.beginPath();
839
+ co.fillStyle = prop['chart.needle.triangle.border'];
840
+ co.arc(this.centerx, this.centery, 11, (((value / this.range) * 360)) / 57.3, ((((value / this.range) * 360)) + 0.01) / 57.3, 0);
841
+ co.arc(this.centerx, this.centery, 11, (((value / this.range) * 360) + 180) / 57.3, ((((value / this.range) * 360) + 180) + 0.01)/ 57.3, 0);
842
+ co.arc(this.centerx, this.centery, length - 5, (((value / this.range) * 360) - 90) / 57.3, ((((value / this.range) * 360) - 90) / 57.3) + 0.01, 0);
843
+ co.closePath();
844
+ co.fill();
845
+
846
+ co.beginPath();
847
+ co.arc(this.centerx, this.centery, 15, 0, RG.TWOPI, 0);
848
+ co.closePath();
849
+ co.fill();
850
+
851
+ // This draws the pointer
852
+ co.beginPath();
853
+ co.strokeStyle = 'black';
854
+ co.fillStyle = color;
855
+ co.arc(this.centerx, this.centery, 7, (((value / this.range) * 360)) / 57.3, ((((value / this.range) * 360)) + 0.01) / 57.3, 0);
856
+ co.arc(this.centerx, this.centery, 7, (((value / this.range) * 360) + 180) / 57.3, ((((value / this.range) * 360) + 180) + 0.01)/ 57.3, 0);
857
+ co.arc(this.centerx, this.centery, length - 13, (((value / this.range) * 360) - 90) / 57.3, ((((value / this.range) * 360) - 90) / 57.3) + 0.01, 0);
858
+ co.closePath();
859
+ co.stroke();
860
+ co.fill();
861
+
862
+
863
+ /**
864
+ * This is here to accomodate the MSIE/ExCanvas combo
865
+ */
866
+ co.beginPath();
867
+ co.arc(this.centerx, this.centery, 7, 0, RG.TWOPI, 0);
868
+ co.closePath();
869
+ co.fill();
870
+ }
871
+
872
+
873
+ co.stroke();
874
+ co.fill();
875
+
876
+ // Draw the mini center circle
877
+ co.beginPath();
878
+ co.fillStyle = color;
879
+ co.arc(this.centerx, this.centery, prop['chart.needle.type'] == 'pointer' ? 7 : 12, 0.01, RG.TWOPI, false);
880
+ co.fill();
881
+
882
+ // This draws the arrow at the end of the line
883
+ if (prop['chart.needle.head'] && prop['chart.needle.type'] == 'pointer') {
884
+ co.lineWidth = 1;
885
+ co.fillStyle = color;
886
+
887
+ // round, bevel, miter
888
+ co.lineJoin = 'miter';
889
+ co.lineCap = 'butt';
890
+
891
+ co.beginPath();
892
+ co.arc(this.centerx, this.centery, length - 5, (((value / this.range) * 360) - 90) / 57.3, (((value / this.range) * 360) - 90 + 0.1) / 57.3, false);
893
+
894
+ co.arc(this.centerx,
895
+ this.centery,
896
+ length - 20,
897
+ RG.degrees2Radians( ((value / this.range) * 360) - (length < 60 ? 80 : 85) ),
898
+ RG.degrees2Radians( ((value / this.range) * 360) - (length < 60 ? 100 : 95) ),
899
+ 1);
900
+ co.closePath();
901
+
902
+ co.fill();
903
+ //co.stroke();
904
+ }
905
+
906
+
907
+ /**
908
+ * Draw a white circle at the centre
909
+ */
910
+ co.beginPath();
911
+ co.fillStyle = 'gray';
912
+ co.moveTo(this.centerx, this.centery);
913
+ co.arc(this.centerx,this.centery,2,0,6.2795,false);
914
+ co.closePath();
915
+
916
+ co.fill();
917
+ };
918
+
919
+
920
+
921
+
922
+ /**
923
+ * Draws the labels for the Odo
924
+ */
925
+ this.drawLabels =
926
+ this.DrawLabels = function ()
927
+ {
928
+ var size = prop['chart.text.size'];
929
+ var font = prop['chart.text.font'];
930
+ var centerx = this.centerx;
931
+ var centery = this.centery;
932
+ var r = this.radius - (prop['chart.label.area'] / 2);
933
+ var start = this.min;
934
+ var end = this.max;
935
+ var decimals = prop['chart.scale.decimals'];
936
+ var labels = prop['chart.labels'];
937
+ var units_pre = prop['chart.units.pre'];
938
+ var units_post = prop['chart.units.post'];
939
+
940
+ co.beginPath();
941
+ co.fillStyle = prop['chart.text.color'];
942
+
943
+ /**
944
+ * If labels are specified, use those
945
+ */
946
+ if (labels) {
947
+ for (var i=0; i<labels.length; ++i) {
948
+
949
+ RG.Text2(this, {'font':font,
950
+ 'size':size,
951
+ 'x':centerx + (Math.cos(((i / labels.length) * RG.TWOPI) - RG.HALFPI) * (this.radius - (prop['chart.label.area'] / 2) ) ), // Sin A = Opp / Hyp
952
+ 'y':centery + (Math.sin(((i / labels.length) * RG.TWOPI) - RG.HALFPI) * (this.radius - (prop['chart.label.area'] / 2) ) ), // Cos A = Adj / Hyp
953
+ 'text': String(labels[i]),
954
+ 'valign':'center',
955
+ 'halign':'center',
956
+ 'tag': 'labels'
957
+ });
958
+ }
959
+
960
+ /**
961
+ * If not, use the maximum value
962
+ */
963
+ } else {
964
+ RG.Text2(this, {'font':font,'size':size,'x':centerx + (0.588 * r ),'y':centery - (0.809 * r ),'text':RG.number_format(this, (((end - start) * (1/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':36,'tag': 'scale'});
965
+ RG.Text2(this, {'font':font,'size':size,'x':centerx + (0.951 * r ),'y':centery - (0.309 * r),'text':RG.number_format(this, (((end - start) * (2/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':72,'tag': 'scale'});
966
+ RG.Text2(this, {'font':font,'size':size,'x':centerx + (0.949 * r),'y':centery + (0.31 * r),'text':RG.number_format(this, (((end - start) * (3/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':108,'tag': 'scale'});
967
+ RG.Text2(this, {'font':font,'size':size,'x':centerx + (0.588 * r ),'y':centery + (0.809 * r ),'text':RG.number_format(this, (((end - start) * (4/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':144,'tag': 'scale'});
968
+ RG.Text2(this, {'font':font,'size':size,'x':centerx,'y':centery + r,'text':RG.number_format(this, (((end - start) * (5/10)) + start).toFixed(decimals),units_pre, units_post),'halign':'center','valign':'center','angle':180,'tag': 'scale'});
969
+
970
+ RG.Text2(this, {'font':font,'size':size,'x':centerx - (0.588 * r ),'y':centery + (0.809 * r ),'text':RG.number_format(this, (((end - start) * (6/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':216,'tag': 'scale'});
971
+ RG.Text2(this, {'font':font,'size':size,'x':centerx - (0.949 * r),'y':centery + (0.300 * r),'text':RG.number_format(this, (((end - start) * (7/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':252,'tag': 'scale'});
972
+ RG.Text2(this, {'font':font,'size':size,'x':centerx - (0.951 * r),'y':centery - (0.309 * r),'text':RG.number_format(this, (((end - start) * (8/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':288,'tag': 'scale'});
973
+ RG.Text2(this, {'font':font,'size':size,'x':centerx - (0.588 * r ),'y':centery - (0.809 * r ),'text':RG.number_format(this, (((end - start) * (9/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','angle':324,'tag': 'scale'});
974
+ RG.Text2(this, {'font':font,'size':size,'x':centerx,'y':centery - r,'text': prop['chart.zerostart'] ? RG.number_format(this, this.min.toFixed(decimals), units_pre, units_post) : RG.number_format(this, (((end - start) * (10/10)) + start).toFixed(decimals), units_pre, units_post),'halign':'center','valign':'center','tag': 'scale'});
975
+ }
976
+
977
+ co.fill();
978
+
979
+ /**
980
+ * Draw the text label below the center point
981
+ */
982
+ if (prop['chart.value.text']) {
983
+ co.strokeStyle = 'black';
984
+ RG.Text2(this, {'font':font,
985
+ 'size':size+2,
986
+ 'x':centerx,
987
+ 'y':centery + size + 15,
988
+ 'text':String(prop['chart.value.units.pre'] + this.value.toFixed(prop['chart.value.text.decimals']) + prop['chart.value.units.post']),
989
+ 'halign':'center',
990
+ 'valign':'center',
991
+ 'bounding':true,
992
+ 'boundingFill':'white',
993
+ 'tag': 'value.text'
994
+ });
995
+ }
996
+ };
997
+
998
+
999
+
1000
+
1001
+ /**
1002
+ * A placeholder function
1003
+ *
1004
+ * @param object The event object
1005
+ */
1006
+ this.getShape = function (e) {};
1007
+
1008
+
1009
+
1010
+
1011
+ /**
1012
+ * This function returns the pertinent value at the point of click
1013
+ *
1014
+ * @param object The event object
1015
+ */
1016
+ this.getValue = function (e)
1017
+ {
1018
+ var mouseXY = RG.getMouseXY(e)
1019
+ var angle = RG.getAngleByXY(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
1020
+ angle += RG.HALFPI;
1021
+
1022
+ if (mouseXY[0] >= this.centerx && mouseXY[1] <= this.centery) {
1023
+ angle -= RG.TWOPI;
1024
+ }
1025
+
1026
+ var value = ((angle / RG.TWOPI) * (this.max - this.min)) + this.min;
1027
+
1028
+ return value;
1029
+ };
1030
+
1031
+
1032
+
1033
+
1034
+ /**
1035
+ * The getObjectByXY() worker method. Don't call this call:
1036
+ *
1037
+ * RGraph.ObjectRegistry.getObjectByXY(e)
1038
+ *
1039
+ * @param object e The event object
1040
+ */
1041
+ this.getObjectByXY = function (e)
1042
+ {
1043
+ var mouseXY = RG.getMouseXY(e);
1044
+ var radius = RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
1045
+
1046
+ if (
1047
+ mouseXY[0] > (this.centerx - this.radius)
1048
+ && mouseXY[0] < (this.centerx + this.radius)
1049
+ && mouseXY[1] > (this.centery - this.radius)
1050
+ && mouseXY[1] < (this.centery + this.radius)
1051
+ && radius <= this.radius
1052
+ ) {
1053
+
1054
+ return this;
1055
+ }
1056
+ };
1057
+
1058
+
1059
+
1060
+
1061
+ /**
1062
+ * This method handles the adjusting calculation for when the mouse is moved
1063
+ *
1064
+ * @param object e The event object
1065
+ */
1066
+ this.adjusting_mousemove =
1067
+ this.Adjusting_mousemove = function (e)
1068
+ {
1069
+ /**
1070
+ * Handle adjusting for the Bar
1071
+ */
1072
+ if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
1073
+ this.value = this.getValue(e);
1074
+ RG.clear(ca);
1075
+ RG.redrawCanvas(ca);
1076
+ RG.fireCustomEvent(this, 'onadjust');
1077
+ }
1078
+ };
1079
+
1080
+
1081
+
1082
+
1083
+ /**
1084
+ * This method returns the appropriate angle for a value
1085
+ *
1086
+ * @param number value The value
1087
+ */
1088
+ this.getAngle = function (value)
1089
+ {
1090
+ // Higher than max or lower than min
1091
+ if (value > this.max || value < this.min) {
1092
+ return null;
1093
+ }
1094
+
1095
+ var angle = (((value - this.min) / (this.max - this.min)) * RG.TWOPI);
1096
+ angle -= RG.HALFPI;
1097
+
1098
+ return angle;
1099
+ };
1100
+
1101
+
1102
+
1103
+
1104
+ /**
1105
+ * This allows for easy specification of gradients
1106
+ */
1107
+ this.parseColors = function ()
1108
+ {
1109
+ // Save the original colors so that they can be restored when the canvas is reset
1110
+ if (this.original_colors.length === 0) {
1111
+ this.original_colors['chart.green.color'] = RG.array_clone(prop['chart.green.color']);
1112
+ this.original_colors['chart.yellow.color'] = RG.array_clone(prop['chart.yellow.color']);
1113
+ this.original_colors['chart.red.color'] = RG.array_clone(prop['chart.red.color']);
1114
+ }
1115
+
1116
+ // Parse the basic colors
1117
+ prop['chart.green.color'] = this.parseSingleColorForGradient(prop['chart.green.color']);
1118
+ prop['chart.yellow.color'] = this.parseSingleColorForGradient(prop['chart.yellow.color']);
1119
+ prop['chart.red.color'] = this.parseSingleColorForGradient(prop['chart.red.color']);
1120
+ };
1121
+
1122
+
1123
+
1124
+
1125
+ /**
1126
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
1127
+ * need be etc
1128
+ */
1129
+ this.reset = function ()
1130
+ {
1131
+ };
1132
+
1133
+
1134
+
1135
+
1136
+ /**
1137
+ * This parses a single color value
1138
+ */
1139
+ this.parseSingleColorForGradient = function (color)
1140
+ {
1141
+ if (!color || typeof(color) != 'string') {
1142
+ return color;
1143
+ }
1144
+
1145
+ if (color.match(/^gradient\((.*)\)$/i)) {
1146
+
1147
+ var parts = RegExp.$1.split(':');
1148
+
1149
+ // Create the gradient
1150
+ var grad = co.createRadialGradient(this.centerx, this.centery, 0, this.centerx, this.centery, this.radius);
1151
+
1152
+ var diff = 1 / (parts.length - 1);
1153
+
1154
+ grad.addColorStop(0, RG.trim(parts[0]));
1155
+
1156
+ for (var j=1; j<parts.length; ++j) {
1157
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1158
+ }
1159
+ }
1160
+
1161
+ return grad ? grad : color;
1162
+ };
1163
+
1164
+
1165
+
1166
+
1167
+ /**
1168
+ * Using a function to add events makes it easier to facilitate method chaining
1169
+ *
1170
+ * @param string type The type of even to add
1171
+ * @param function func
1172
+ */
1173
+ this.on = function (type, func)
1174
+ {
1175
+ if (type.substr(0,2) !== 'on') {
1176
+ type = 'on' + type;
1177
+ }
1178
+
1179
+ this[type] = func;
1180
+
1181
+ return this;
1182
+ };
1183
+
1184
+
1185
+
1186
+
1187
+ /**
1188
+ * This function runs once only
1189
+ * (put at the end of the file (before any effects))
1190
+ */
1191
+ this.firstDrawFunc = function ()
1192
+ {
1193
+ };
1194
+
1195
+
1196
+
1197
+
1198
+ /**
1199
+ * Odo Grow
1200
+ *
1201
+ * This effect gradually increases the represented value
1202
+ *
1203
+ * @param An object of effect properties - eg: {frames: 30}
1204
+ * @param function An optional callback function
1205
+ */
1206
+ this.grow = function ()
1207
+ {
1208
+ var obj = this;
1209
+ var opt = arguments[0] || {};
1210
+ var frames = opt.frames || 30;
1211
+ var frame = 0;
1212
+ var current = obj.currentValue || 0;
1213
+ var origValue = Number(obj.currentValue);
1214
+ var newValue = obj.value;
1215
+ var diff = newValue - origValue;
1216
+ var step = (diff / frames);
1217
+ var callback = arguments[1] || function () {};
1218
+
1219
+
1220
+
1221
+ function iterator ()
1222
+ {
1223
+ obj.value = origValue + (frame * step);
1224
+
1225
+ RG.clear(obj.canvas);
1226
+ RG.redrawCanvas(obj.canvas);
1227
+
1228
+ if (frame++ < frames) {
1229
+ RG.Effects.updateCanvas(iterator);
1230
+ } else {
1231
+ callback(obj);
1232
+ }
1233
+ }
1234
+
1235
+ iterator();
1236
+
1237
+ return this;
1238
+ };
1239
+
1240
+
1241
+
1242
+
1243
+
1244
+
1245
+ RG.att(ca);
1246
+
1247
+
1248
+
1249
+
1250
+ /**
1251
+ * Register the object
1252
+ */
1253
+ RG.register(this);
1254
+
1255
+
1256
+
1257
+
1258
+ /**
1259
+ * This is the 'end' of the constructor so if the first argument
1260
+ * contains configuration data - handle that.
1261
+ */
1262
+ if (parseConfObjectForOptions) {
1263
+ RG.parseObjectStyleConfig(this, conf.options);
1264
+ }
1265
+ };