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,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
+ };