rgraph-rails 1.0.5 → 1.0.6
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.
- checksums.yaml +8 -8
- data/.travis.yml +0 -1
- data/README.md +3 -3
- data/lib/rgraph-rails/version.rb +1 -1
- data/vendor/assets/javascripts/RGraph.bar.js +239 -3764
- data/vendor/assets/javascripts/RGraph.bipolar.js +115 -1986
- data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -399
- data/vendor/assets/javascripts/RGraph.common.context.js +30 -600
- data/vendor/assets/javascripts/RGraph.common.core.js +403 -5187
- data/vendor/assets/javascripts/RGraph.common.csv.js +19 -275
- data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -454
- data/vendor/assets/javascripts/RGraph.common.dynamic.js +84 -1189
- data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1548
- data/vendor/assets/javascripts/RGraph.common.key.js +54 -755
- data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -567
- data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -356
- data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -614
- data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -223
- data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
- data/vendor/assets/javascripts/RGraph.drawing.background.js +35 -620
- data/vendor/assets/javascripts/RGraph.drawing.circle.js +35 -576
- data/vendor/assets/javascripts/RGraph.drawing.image.js +52 -807
- data/vendor/assets/javascripts/RGraph.drawing.marker1.js +41 -717
- data/vendor/assets/javascripts/RGraph.drawing.marker2.js +37 -668
- data/vendor/assets/javascripts/RGraph.drawing.marker3.js +36 -563
- data/vendor/assets/javascripts/RGraph.drawing.poly.js +40 -608
- data/vendor/assets/javascripts/RGraph.drawing.rect.js +35 -597
- data/vendor/assets/javascripts/RGraph.drawing.text.js +34 -642
- data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -809
- data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
- data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
- data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
- data/vendor/assets/javascripts/RGraph.gantt.js +75 -1241
- data/vendor/assets/javascripts/RGraph.gauge.js +87 -1397
- data/vendor/assets/javascripts/RGraph.hbar.js +143 -2376
- data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1397
- data/vendor/assets/javascripts/RGraph.line.js +241 -4162
- data/vendor/assets/javascripts/RGraph.meter.js +74 -1278
- metadata +3 -30
- data/vendor/assets/images/bg.png +0 -0
- data/vendor/assets/images/bullet.png +0 -0
- data/vendor/assets/images/facebook-large.png +0 -0
- data/vendor/assets/images/google-plus-large.png +0 -0
- data/vendor/assets/images/logo.png +0 -0
- data/vendor/assets/images/meter-image-sd-needle.png +0 -0
- data/vendor/assets/images/meter-image-sd.png +0 -0
- data/vendor/assets/images/meter-sketch-needle.png +0 -0
- data/vendor/assets/images/meter-sketch.png +0 -0
- data/vendor/assets/images/odometer-background.png +0 -0
- data/vendor/assets/images/rgraph.jpg +0 -0
- data/vendor/assets/images/title.png +0 -0
- data/vendor/assets/images/twitter-large.png +0 -0
- data/vendor/assets/javascripts/RGraph.modaldialog.js +0 -301
- data/vendor/assets/javascripts/RGraph.odo.js +0 -1265
- data/vendor/assets/javascripts/RGraph.pie.js +0 -2272
- data/vendor/assets/javascripts/RGraph.radar.js +0 -1847
- data/vendor/assets/javascripts/RGraph.rose.js +0 -1877
- data/vendor/assets/javascripts/RGraph.rscatter.js +0 -1425
- data/vendor/assets/javascripts/RGraph.scatter.js +0 -2970
- data/vendor/assets/javascripts/RGraph.semicircularprogress.js +0 -1015
- data/vendor/assets/javascripts/RGraph.thermometer.js +0 -1129
- data/vendor/assets/javascripts/RGraph.vprogress.js +0 -1452
- data/vendor/assets/javascripts/RGraph.waterfall.js +0 -1252
- data/vendor/assets/javascripts/financial-data.js +0 -1067
- data/vendor/assets/stylesheets/ModalDialog.css +0 -90
- data/vendor/assets/stylesheets/animations.css +0 -3347
- data/vendor/assets/stylesheets/website.css +0 -446
@@ -1,1252 +0,0 @@
|
|
1
|
-
// version: 2016-06-04
|
2
|
-
/**
|
3
|
-
* o--------------------------------------------------------------------------------o
|
4
|
-
* | This file is part of the RGraph package - you can learn more at: |
|
5
|
-
* | |
|
6
|
-
* | http://www.rgraph.net |
|
7
|
-
* | |
|
8
|
-
* | RGraph is dual licensed under the Open Source GPL (General Public License) |
|
9
|
-
* | v2.0 license and a commercial license which means that you're not bound by |
|
10
|
-
* | the terms of the GPL. The commercial license is just 99 GBP and you can |
|
11
|
-
* | read about it here: |
|
12
|
-
* | http://www.rgraph.net/license |
|
13
|
-
* o--------------------------------------------------------------------------------o
|
14
|
-
*/
|
15
|
-
|
16
|
-
RGraph = window.RGraph || {isRGraph: true};
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
/**
|
22
|
-
* The bar chart constructor
|
23
|
-
*
|
24
|
-
* @param object canvas The canvas object
|
25
|
-
* @param array data The chart data
|
26
|
-
*/
|
27
|
-
RGraph.Waterfall = function (conf)
|
28
|
-
{
|
29
|
-
/**
|
30
|
-
* Allow for object config style
|
31
|
-
*/
|
32
|
-
if ( typeof conf === 'object'
|
33
|
-
&& typeof conf.data === 'object'
|
34
|
-
&& typeof conf.id === 'string') {
|
35
|
-
|
36
|
-
var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
|
37
|
-
|
38
|
-
} else {
|
39
|
-
|
40
|
-
var conf = {
|
41
|
-
id: conf,
|
42
|
-
data: arguments[1]
|
43
|
-
};
|
44
|
-
}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
this.id = conf.id;
|
50
|
-
this.canvas = document.getElementById(this.id);
|
51
|
-
this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
|
52
|
-
this.canvas.__object__ = this;
|
53
|
-
this.type = 'waterfall';
|
54
|
-
this.max = 0;
|
55
|
-
this.data = conf.data;
|
56
|
-
this.isRGraph = true;
|
57
|
-
this.coords = [];
|
58
|
-
this.uid = RGraph.CreateUID();
|
59
|
-
this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
|
60
|
-
this.colorsParsed = false;
|
61
|
-
this.coordsText = [];
|
62
|
-
this.original_colors = [];
|
63
|
-
this.firstDraw = true; // After the first draw this will be false
|
64
|
-
|
65
|
-
|
66
|
-
// Various config
|
67
|
-
this.properties =
|
68
|
-
{
|
69
|
-
'chart.background.barcolor1': 'rgba(0,0,0,0)',
|
70
|
-
'chart.background.barcolor2': 'rgba(0,0,0,0)',
|
71
|
-
'chart.background.grid': true,
|
72
|
-
'chart.background.grid.color': '#ddd',
|
73
|
-
'chart.background.grid.width': 1,
|
74
|
-
'chart.background.grid.hsize': 20,
|
75
|
-
'chart.background.grid.vsize': 20,
|
76
|
-
'chart.background.grid.vlines': true,
|
77
|
-
'chart.background.grid.hlines': true,
|
78
|
-
'chart.background.grid.border': true,
|
79
|
-
'chart.background.grid.autofit':true,
|
80
|
-
'chart.background.grid.autofit.align': true,
|
81
|
-
'chart.background.grid.autofit.numhlines': 5,
|
82
|
-
'chart.background.grid.autofit.numvlines': 20,
|
83
|
-
'chart.background.image': null,
|
84
|
-
'chart.background.hbars': null,
|
85
|
-
'chart.linewidth': 1,
|
86
|
-
'chart.axis.linewidth': 1,
|
87
|
-
'chart.xaxispos': 'bottom',
|
88
|
-
'chart.numxticks': null,
|
89
|
-
'chart.numyticks': 10,
|
90
|
-
'chart.hmargin': 5,
|
91
|
-
'chart.strokestyle': '#666',
|
92
|
-
'chart.axis.color': 'black',
|
93
|
-
'chart.gutter.left': 25,
|
94
|
-
'chart.gutter.right': 25,
|
95
|
-
'chart.gutter.top': 25,
|
96
|
-
'chart.gutter.bottom': 25,
|
97
|
-
'chart.labels': [],
|
98
|
-
'chart.labels.bold': false,
|
99
|
-
'chart.labels.offsetx': 0,
|
100
|
-
'chart.labels.offsety': 0,
|
101
|
-
'chart.ylabels.offsetx': 0,
|
102
|
-
'chart.ylabels.offsety': 0,
|
103
|
-
'chart.ylabels': true,
|
104
|
-
'chart.text.color': 'black',
|
105
|
-
'chart.text.size': 12,
|
106
|
-
'chart.text.angle': 0,
|
107
|
-
'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
|
108
|
-
'chart.text.accessible': true,
|
109
|
-
'chart.text.accessible.overflow': 'visible',
|
110
|
-
'chart.text.accessible.pointerevents': false,
|
111
|
-
'chart.ymax': null,
|
112
|
-
'chart.title': '',
|
113
|
-
'chart.title.color': 'black',
|
114
|
-
'chart.title.background': null,
|
115
|
-
'chart.title.hpos': null,
|
116
|
-
'chart.title.vpos': null,
|
117
|
-
'chart.title.bold': true,
|
118
|
-
'chart.title.font': null,
|
119
|
-
'chart.title.xaxis': '',
|
120
|
-
'chart.title.yaxis': '',
|
121
|
-
'chart.title.yaxis.bold': true,
|
122
|
-
'chart.title.yaxis.size': null,
|
123
|
-
'chart.title.yaxis.font': null,
|
124
|
-
'chart.title.yaxis.color': null,
|
125
|
-
'chart.title.xaxis.pos': null,
|
126
|
-
'chart.title.yaxis.pos': null,
|
127
|
-
'chart.title.yaxis.align': 'left',
|
128
|
-
'chart.title.xaxis.bold': true,
|
129
|
-
'chart.title.xaxis.size': null,
|
130
|
-
'chart.title.xaxis.font': null,
|
131
|
-
'chart.title.yaxis.x': null,
|
132
|
-
'chart.title.yaxis.y': null,
|
133
|
-
'chart.title.xaxis.x': null,
|
134
|
-
'chart.title.xaxis.y': null,
|
135
|
-
'chart.title.x': null,
|
136
|
-
'chart.title.y': null,
|
137
|
-
'chart.title.halign': null,
|
138
|
-
'chart.title.valign': null,
|
139
|
-
'chart.colors': ['Gradient(white:green)', 'Gradient(white:red)', 'Gradient(white:blue)'],
|
140
|
-
'chart.shadow': false,
|
141
|
-
'chart.shadow.color': '#666',
|
142
|
-
'chart.shadow.offsetx': 3,
|
143
|
-
'chart.shadow.offsety': 3,
|
144
|
-
'chart.shadow.blur': 3,
|
145
|
-
'chart.tooltips': null,
|
146
|
-
'chart.tooltips.effect': 'fade',
|
147
|
-
'chart.tooltips.css.class': 'RGraph_tooltip',
|
148
|
-
'chart.tooltips.event': 'onclick',
|
149
|
-
'chart.tooltips.highlight': true,
|
150
|
-
'chart.tooltips.override': null,
|
151
|
-
'chart.highlight.stroke': 'rgba(0,0,0,0)',
|
152
|
-
'chart.highlight.fill': 'rgba(255,255,255,0.7)',
|
153
|
-
'chart.contextmenu': null,
|
154
|
-
'chart.units.pre': '',
|
155
|
-
'chart.units.post': '',
|
156
|
-
'chart.scale.decimals': 0,
|
157
|
-
'chart.scale.point': '.',
|
158
|
-
'chart.scale.thousand': ',',
|
159
|
-
//'chart.scale.formatter': null,
|
160
|
-
'chart.crosshairs': false,
|
161
|
-
'chart.crosshairs.color': '#333',
|
162
|
-
'chart.crosshairs.hline': true,
|
163
|
-
'chart.crosshairs.vline': true,
|
164
|
-
'chart.annotatable': false,
|
165
|
-
'chart.annotate.color': 'black',
|
166
|
-
'chart.zoom.factor': 1.5,
|
167
|
-
'chart.zoom.fade.in': true,
|
168
|
-
'chart.zoom.fade.out': true,
|
169
|
-
'chart.zoom.hdir': 'right',
|
170
|
-
'chart.zoom.vdir': 'down',
|
171
|
-
'chart.zoom.frames': 25,
|
172
|
-
'chart.zoom.delay': 16.666,
|
173
|
-
'chart.zoom.shadow': true,
|
174
|
-
'chart.zoom.background': true,
|
175
|
-
'chart.resizable': false,
|
176
|
-
'chart.resize.handle.background': null,
|
177
|
-
'chart.noaxes': false,
|
178
|
-
'chart.noxaxis': false,
|
179
|
-
'chart.noyaxis': false,
|
180
|
-
'chart.axis.color': 'black',
|
181
|
-
'chart.total': true,
|
182
|
-
'chart.multiplier.x': 1,
|
183
|
-
'chart.multiplier.w': 1,
|
184
|
-
'chart.events.click': null,
|
185
|
-
'chart.events.mousemove': null,
|
186
|
-
'chart.ylabels.count': 5,
|
187
|
-
'chart.clearto': 'rgba(0,0,0,0)'
|
188
|
-
}
|
189
|
-
|
190
|
-
// Check for support
|
191
|
-
if (!this.canvas) {
|
192
|
-
alert('[WATERFALL] No canvas support');
|
193
|
-
return;
|
194
|
-
}
|
195
|
-
|
196
|
-
/**
|
197
|
-
* Create the $ objects
|
198
|
-
*
|
199
|
-
* 2/5/016: Now also use this loop to go through the dat conerting
|
200
|
-
* strings to floats
|
201
|
-
*/
|
202
|
-
for (var i=0,len=this.data.length; i<=len; ++i) {
|
203
|
-
|
204
|
-
// Create the object for adding event listeners
|
205
|
-
this['$' + i] = {}
|
206
|
-
|
207
|
-
// Ensure that the data point is numeric
|
208
|
-
if (typeof this.data[i] === 'string') {
|
209
|
-
this.data[i] = parseFloat(this.data[i]);
|
210
|
-
}
|
211
|
-
}
|
212
|
-
|
213
|
-
|
214
|
-
/**
|
215
|
-
* Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
|
216
|
-
* done already
|
217
|
-
*/
|
218
|
-
if (!this.canvas.__rgraph_aa_translated__) {
|
219
|
-
this.context.translate(0.5,0.5);
|
220
|
-
|
221
|
-
this.canvas.__rgraph_aa_translated__ = true;
|
222
|
-
}
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
// Short variable names
|
228
|
-
var RG = RGraph,
|
229
|
-
ca = this.canvas,
|
230
|
-
co = ca.getContext('2d'),
|
231
|
-
prop = this.properties,
|
232
|
-
pa2 = RG.path2,
|
233
|
-
win = window,
|
234
|
-
doc = document,
|
235
|
-
ma = Math
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
/**
|
240
|
-
* "Decorate" the object with the generic effects if the effects library has been included
|
241
|
-
*/
|
242
|
-
if (RG.Effects && typeof RG.Effects.decorate === 'function') {
|
243
|
-
RG.Effects.decorate(this);
|
244
|
-
}
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
/**
|
250
|
-
* A setter
|
251
|
-
*
|
252
|
-
* @param name string The name of the property to set
|
253
|
-
* @param value mixed The value of the property
|
254
|
-
*/
|
255
|
-
this.set =
|
256
|
-
this.Set = function (name, value)
|
257
|
-
{
|
258
|
-
var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
|
259
|
-
|
260
|
-
/**
|
261
|
-
* the number of arguments is only one and it's an
|
262
|
-
* object - parse it for configuration data and return.
|
263
|
-
*/
|
264
|
-
if (arguments.length === 1 && typeof name === 'object') {
|
265
|
-
RG.parseObjectStyleConfig(this, name);
|
266
|
-
return this;
|
267
|
-
}
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
/**
|
273
|
-
* This should be done first - prepend the propertyy name with "chart." if necessary
|
274
|
-
*/
|
275
|
-
if (name.substr(0,6) != 'chart.') {
|
276
|
-
name = 'chart.' + name;
|
277
|
-
}
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
// Convert uppercase letters to dot+lower case letter
|
282
|
-
while(name.match(/([A-Z])/)) {
|
283
|
-
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
284
|
-
}
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
if (name == 'chart.total' && prop['chart.numxticks'] == null) {
|
289
|
-
prop['chart.numxticks'] = this.data.length;
|
290
|
-
}
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
prop[name.toLowerCase()] = value;
|
295
|
-
|
296
|
-
return this;
|
297
|
-
};
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
/**
|
303
|
-
* A getter
|
304
|
-
*
|
305
|
-
* @param name string The name of the property to get
|
306
|
-
*/
|
307
|
-
this.get =
|
308
|
-
this.Get = function (name)
|
309
|
-
{
|
310
|
-
/**
|
311
|
-
* This should be done first - prepend the property name with "chart." if necessary
|
312
|
-
*/
|
313
|
-
if (name.substr(0,6) != 'chart.') {
|
314
|
-
name = 'chart.' + name;
|
315
|
-
}
|
316
|
-
|
317
|
-
// Convert uppercase letters to dot+lower case letter
|
318
|
-
name = name.replace(/([A-Z])/g, function (str)
|
319
|
-
{
|
320
|
-
return '.' + String(RegExp.$1).toLowerCase()
|
321
|
-
});
|
322
|
-
|
323
|
-
return prop[name.toLowerCase()];
|
324
|
-
};
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
/**
|
330
|
-
* The function you call to draw the bar chart
|
331
|
-
*/
|
332
|
-
this.draw =
|
333
|
-
this.Draw = function ()
|
334
|
-
{
|
335
|
-
/**
|
336
|
-
* Fire the onbeforedraw event
|
337
|
-
*/
|
338
|
-
RGraph.FireCustomEvent(this, 'onbeforedraw');
|
339
|
-
|
340
|
-
|
341
|
-
/**
|
342
|
-
* Parse the colors. This allows for simple gradient syntax
|
343
|
-
*/
|
344
|
-
if (!this.colorsParsed) {
|
345
|
-
this.parseColors();
|
346
|
-
|
347
|
-
// Don't want to do this again
|
348
|
-
this.colorsParsed = true;
|
349
|
-
}
|
350
|
-
|
351
|
-
|
352
|
-
/**
|
353
|
-
* Draw the background image
|
354
|
-
*/
|
355
|
-
RGraph.DrawBackgroundImage(this);
|
356
|
-
|
357
|
-
/**
|
358
|
-
* This is new in May 2011 and facilitates indiviual gutter settings,
|
359
|
-
* eg chart.gutter.left
|
360
|
-
*/
|
361
|
-
this.gutterLeft = prop['chart.gutter.left'];
|
362
|
-
this.gutterRight = prop['chart.gutter.right'];
|
363
|
-
this.gutterTop = prop['chart.gutter.top'];
|
364
|
-
this.gutterBottom = prop['chart.gutter.bottom'];
|
365
|
-
|
366
|
-
/**
|
367
|
-
* Stop the coords array from growing uncontrollably
|
368
|
-
*/
|
369
|
-
this.coords = [];
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
/**
|
374
|
-
* Stop this growing uncontrollably
|
375
|
-
*/
|
376
|
-
this.coordsText = [];
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
/**
|
382
|
-
* This gets used a lot
|
383
|
-
*/
|
384
|
-
this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
|
385
|
-
|
386
|
-
/**
|
387
|
-
* Work out a few things. They need to be here because they depend on things you can change after you instantiate the object
|
388
|
-
*/
|
389
|
-
this.max = 0;
|
390
|
-
this.grapharea = ca.height - this.gutterTop - this.gutterBottom;
|
391
|
-
this.graphwidth = ca.width - this.gutterLeft - this.gutterRight;
|
392
|
-
this.halfTextHeight = prop['chart.text.size'] / 2;
|
393
|
-
|
394
|
-
|
395
|
-
/**
|
396
|
-
* Work out the maximum value
|
397
|
-
*/
|
398
|
-
this.max = this.getMax(this.data);
|
399
|
-
|
400
|
-
var decimals = prop['chart.scale.decimals'];
|
401
|
-
this.scale2 = RGraph.getScale2(this, {'max':typeof(prop['chart.ymax']) == 'number' ? prop['chart.ymax'] : this.max,
|
402
|
-
'min':prop['chart.xmin'],
|
403
|
-
'strict': typeof(prop['chart.ymax']) == 'number' ? true : false,
|
404
|
-
'scale.decimals':Number(decimals),
|
405
|
-
'scale.point':prop['chart.scale.point'],
|
406
|
-
'scale.thousand':prop['chart.scale.thousand'],
|
407
|
-
'scale.round':prop['chart.scale.round'],
|
408
|
-
'units.pre':prop['chart.units.pre'],
|
409
|
-
'units.post':prop['chart.units.post'],
|
410
|
-
'ylabels.count':prop['chart.ylabels.count']
|
411
|
-
});
|
412
|
-
|
413
|
-
this.max = this.scale2.max;
|
414
|
-
|
415
|
-
|
416
|
-
// Draw the background hbars
|
417
|
-
RGraph.DrawBars(this)
|
418
|
-
|
419
|
-
// Progressively Draw the chart
|
420
|
-
RG.background.Draw(this);
|
421
|
-
|
422
|
-
this.DrawAxes();
|
423
|
-
this.Drawbars();
|
424
|
-
this.DrawLabels();
|
425
|
-
|
426
|
-
/**
|
427
|
-
* If the X axis is at the bottom - draw the it again so that it appears "on top" of the bars
|
428
|
-
*/
|
429
|
-
if (prop['chart.xaxispos'] == 'bottom' && prop['chart.noaxes'] == false && prop['chart.noxaxis'] == false) {
|
430
|
-
co.strokeStyle = prop['chart.axis.color'];
|
431
|
-
co.strokeRect(prop['chart.gutter.left'], ca.height - prop['chart.gutter.bottom'], ca.width - this.gutterLeft - this.gutterRight, 0);
|
432
|
-
}
|
433
|
-
|
434
|
-
/**
|
435
|
-
* Setup the context menu if required
|
436
|
-
*/
|
437
|
-
if (prop['chart.contextmenu']) {
|
438
|
-
RG.ShowContext(this);
|
439
|
-
}
|
440
|
-
|
441
|
-
|
442
|
-
/**
|
443
|
-
* This function enables resizing
|
444
|
-
*/
|
445
|
-
if (prop['chart.resizable']) {
|
446
|
-
RG.AllowResizing(this);
|
447
|
-
}
|
448
|
-
|
449
|
-
|
450
|
-
/**
|
451
|
-
* This installs the event listeners
|
452
|
-
*/
|
453
|
-
RG.InstallEventListeners(this);
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
/**
|
458
|
-
* Fire the onfirstdraw event
|
459
|
-
*/
|
460
|
-
if (this.firstDraw) {
|
461
|
-
RG.fireCustomEvent(this, 'onfirstdraw');
|
462
|
-
this.firstDraw = false;
|
463
|
-
this.firstDrawFunc();
|
464
|
-
}
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
/**
|
470
|
-
* Fire the RGraph ondraw event
|
471
|
-
*/
|
472
|
-
RG.FireCustomEvent(this, 'ondraw');
|
473
|
-
|
474
|
-
return this;
|
475
|
-
};
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
/**
|
481
|
-
* Draws the charts axes
|
482
|
-
*/
|
483
|
-
this.drawAxes =
|
484
|
-
this.DrawAxes = function ()
|
485
|
-
{
|
486
|
-
if (prop['chart.noaxes']) {
|
487
|
-
return;
|
488
|
-
}
|
489
|
-
|
490
|
-
co.beginPath();
|
491
|
-
co.strokeStyle = prop['chart.axis.color'];
|
492
|
-
co.lineWidth = prop['chart.axis.linewidth'] + 0.001;
|
493
|
-
|
494
|
-
// Draw the Y axis
|
495
|
-
if (prop['chart.noyaxis'] == false) {
|
496
|
-
co.moveTo(Math.round(this.gutterLeft), this.gutterTop);
|
497
|
-
co.lineTo(Math.round(this.gutterLeft), ca.height - this.gutterBottom);
|
498
|
-
}
|
499
|
-
|
500
|
-
// Draw the X axis
|
501
|
-
if (prop['chart.noxaxis'] == false) {
|
502
|
-
// Center X axis
|
503
|
-
if (prop['chart.xaxispos'] == 'center') {
|
504
|
-
co.moveTo(this.gutterLeft, Math.round( ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop));
|
505
|
-
co.lineTo(ca.width - this.gutterRight, Math.round( ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop));
|
506
|
-
} else {
|
507
|
-
co.moveTo(this.gutterLeft, Math.round(ca.height - this.gutterBottom));
|
508
|
-
co.lineTo(ca.width - this.gutterRight, Math.round(ca.height - this.gutterBottom));
|
509
|
-
}
|
510
|
-
}
|
511
|
-
|
512
|
-
var numYTicks = prop['chart.numyticks'];
|
513
|
-
|
514
|
-
// Draw the Y tickmarks
|
515
|
-
if (prop['chart.noyaxis'] == false && prop['chart.numyticks'] > 0) {
|
516
|
-
|
517
|
-
var yTickGap = (ca.height - this.gutterTop - this.gutterBottom) / numYTicks;
|
518
|
-
|
519
|
-
for (y=this.gutterTop; y < (ca.height - this.gutterBottom); y += yTickGap) {
|
520
|
-
if (prop['chart.xaxispos'] == 'bottom' || (y != ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop)) {
|
521
|
-
co.moveTo(this.gutterLeft, Math.round( y));
|
522
|
-
co.lineTo(this.gutterLeft - 3, Math.round( y));
|
523
|
-
}
|
524
|
-
}
|
525
|
-
|
526
|
-
/**
|
527
|
-
* If the X axis is not being shown, draw an extra tick
|
528
|
-
*/
|
529
|
-
if (prop['chart.noxaxis'] || prop['chart.xaxispos'] == 'center') {
|
530
|
-
co.moveTo(this.gutterLeft - 3, Math.round(ca.height - this.gutterBottom));
|
531
|
-
co.lineTo(this.gutterLeft, Math.round(ca.height - this.gutterBottom));
|
532
|
-
}
|
533
|
-
}
|
534
|
-
|
535
|
-
|
536
|
-
// Draw the X tickmarks
|
537
|
-
if (prop['chart.numxticks'] == null) {
|
538
|
-
prop['chart.numxticks'] = this.data.length + (prop['chart.total'] ? 1 : 0)
|
539
|
-
}
|
540
|
-
|
541
|
-
if (prop['chart.noxaxis'] == false && prop['chart.numxticks'] > 0) {
|
542
|
-
|
543
|
-
xTickGap = (ca.width - this.gutterLeft - this.gutterRight ) / prop['chart.numxticks'];
|
544
|
-
|
545
|
-
if (prop['chart.xaxispos'] == 'center') {
|
546
|
-
yStart = ((ca.height - this.gutterBottom - this.gutterTop) / 2) + this.gutterTop - 3;
|
547
|
-
yEnd = ((ca.height - this.gutterBottom - this.gutterTop) / 2) + this.gutterTop + 3;
|
548
|
-
} else {
|
549
|
-
yStart = ca.height - this.gutterBottom;
|
550
|
-
yEnd = (ca.height - this.gutterBottom) + 3;
|
551
|
-
}
|
552
|
-
|
553
|
-
for (x=this.gutterLeft + xTickGap; x<=ca.width - this.gutterRight + 1; x+=xTickGap) {
|
554
|
-
co.moveTo(Math.round( x), yStart);
|
555
|
-
co.lineTo(Math.round( x), yEnd);
|
556
|
-
}
|
557
|
-
|
558
|
-
if (prop['chart.noyaxis']) {
|
559
|
-
co.moveTo(Math.round( this.gutterLeft), yStart);
|
560
|
-
co.lineTo(Math.round( this.gutterLeft), yEnd);
|
561
|
-
}
|
562
|
-
}
|
563
|
-
|
564
|
-
/**
|
565
|
-
* If the Y axis is not being shown, draw an extra tick
|
566
|
-
*/
|
567
|
-
if (prop['chart.noyaxis'] && prop['chart.noxaxis'] == false) {
|
568
|
-
co.moveTo(Math.round( this.gutterLeft), ca.height - this.gutterBottom);
|
569
|
-
co.lineTo(Math.round( this.gutterLeft), ca.height - this.gutterBottom + 3);
|
570
|
-
}
|
571
|
-
|
572
|
-
co.stroke();
|
573
|
-
};
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
/**
|
579
|
-
* Draws the labels for the graph
|
580
|
-
*/
|
581
|
-
this.drawLabels =
|
582
|
-
this.DrawLabels = function ()
|
583
|
-
{
|
584
|
-
var context = co,
|
585
|
-
numYLabels = 5, // TODO Make this configurable
|
586
|
-
interval = this.grapharea / numYLabels,
|
587
|
-
font = prop['chart.text.font'],
|
588
|
-
size = prop['chart.text.size'],
|
589
|
-
color = prop['chart.text.color'],
|
590
|
-
units_pre = prop['chart.units.pre'],
|
591
|
-
units_post = prop['chart.units.post'],
|
592
|
-
offsetx = prop['chart.ylabels.offsetx'],
|
593
|
-
offsety = prop['chart.ylabels.offsety'];
|
594
|
-
|
595
|
-
co.beginPath();
|
596
|
-
co.fillStyle = color;
|
597
|
-
|
598
|
-
/**
|
599
|
-
* First, draw the Y labels
|
600
|
-
*/
|
601
|
-
if (prop['chart.ylabels']) {
|
602
|
-
if (prop['chart.xaxispos'] == 'center') {
|
603
|
-
|
604
|
-
var halfInterval = interval / 2;
|
605
|
-
var halfWay = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
|
606
|
-
|
607
|
-
for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
|
608
|
-
RG.text2(this, {
|
609
|
-
'font':font,
|
610
|
-
'size':size,
|
611
|
-
'x':this.gutterLeft - 5 + offsetx,
|
612
|
-
'y': this.gutterTop + (((this.grapharea/2) / len) * i) + offsety,
|
613
|
-
'text':this.scale2.labels[len - i - 1],
|
614
|
-
'valign':'center',
|
615
|
-
'halign':'right',
|
616
|
-
'tag': 'scale'
|
617
|
-
});
|
618
|
-
|
619
|
-
RG.Text2(this, {
|
620
|
-
'font':font,
|
621
|
-
'size':size,
|
622
|
-
'x':this.gutterLeft - 5 + offsetx,
|
623
|
-
'y': halfWay + (((this.grapharea/2) / len) * (i + 1)) + offsety,
|
624
|
-
'text':this.scale2.labels[i],
|
625
|
-
'valign':'center',
|
626
|
-
'halign':'right',
|
627
|
-
'tag': 'scale'
|
628
|
-
});
|
629
|
-
}
|
630
|
-
|
631
|
-
} else {
|
632
|
-
|
633
|
-
for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
|
634
|
-
RG.text2(this, {
|
635
|
-
'font':font,
|
636
|
-
'size':size,
|
637
|
-
'x':this.gutterLeft - 5 + offsetx,
|
638
|
-
'y': ca.height - this.gutterBottom - ((this.grapharea / len) * (i + 1)) + offsety,
|
639
|
-
'text':this.scale2.labels[i],
|
640
|
-
'valign':'center',
|
641
|
-
'halign':'right',
|
642
|
-
'tag': 'scale'
|
643
|
-
});
|
644
|
-
}
|
645
|
-
}
|
646
|
-
}
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
/**
|
651
|
-
* Now, draw the X labels
|
652
|
-
*/
|
653
|
-
if (prop['chart.labels'].length > 0) {
|
654
|
-
|
655
|
-
// Recalculate the interval for the X labels
|
656
|
-
interval = (ca.width - this.gutterLeft - this.gutterRight) / prop['chart.labels'].length;
|
657
|
-
|
658
|
-
var halign = 'center';
|
659
|
-
var angle = prop['chart.text.angle'];
|
660
|
-
|
661
|
-
if (angle) {
|
662
|
-
halign = 'right';
|
663
|
-
angle *= -1;
|
664
|
-
}
|
665
|
-
|
666
|
-
var labels = prop['chart.labels'],
|
667
|
-
labelsColor = prop['chart.labels.color'],
|
668
|
-
bold = prop['chart.labels.bold'],
|
669
|
-
offsetx = prop['chart.labels.offsetx'],
|
670
|
-
offsety = prop['chart.labels.offsety']
|
671
|
-
|
672
|
-
for (var i=0,len=labels.length; i<len; i+=1) {
|
673
|
-
RG.text2(this, {
|
674
|
-
'color': labelsColor,
|
675
|
-
'font':font,
|
676
|
-
'size':size,
|
677
|
-
'bold': bold,
|
678
|
-
'x':this.gutterLeft + (i * interval) + (interval / 2) + offsetx,
|
679
|
-
'y':ca.height - this.gutterBottom + 5 + this.halfTextHeight + offsety,
|
680
|
-
'text':labels[i],
|
681
|
-
'valign':'center',
|
682
|
-
'halign':halign,
|
683
|
-
'angle':angle,
|
684
|
-
'tag': 'labels'
|
685
|
-
});
|
686
|
-
}
|
687
|
-
}
|
688
|
-
|
689
|
-
co.stroke();
|
690
|
-
co.fill();
|
691
|
-
};
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
/**
|
697
|
-
* Draws the bars on to the chart
|
698
|
-
*/
|
699
|
-
this.drawbars =
|
700
|
-
this.Drawbars = function ()
|
701
|
-
{
|
702
|
-
var context = co;
|
703
|
-
var canvas = ca;
|
704
|
-
var hmargin = prop['chart.hmargin'];
|
705
|
-
var runningTotal = 0;
|
706
|
-
|
707
|
-
co.lineWidth = prop['chart.linewidth'] + 0.001;
|
708
|
-
|
709
|
-
for (var i=0,len=this.data.length; i<len; ++i) {
|
710
|
-
co.beginPath();
|
711
|
-
co.strokeStyle = prop['chart.strokestyle'];
|
712
|
-
|
713
|
-
var x = Math.round( this.gutterLeft + hmargin + (((this.graphwidth / (this.data.length + (prop['chart.total'] ? 1 : 0))) * i) * prop['chart.multiplier.x']));
|
714
|
-
var y = Math.round( this.gutterTop + this.grapharea - (i == 0 ? ((this.data[0] / this.max) * this.grapharea) : (this.data[i] > 0 ? ((runningTotal + this.data[i]) / this.max) * this.grapharea : (runningTotal / this.max) * this.grapharea)));
|
715
|
-
var w = ((ca.width - this.gutterLeft - this.gutterRight) / (this.data.length + (prop['chart.total'] ? 1 : 0 )) ) - (2 * prop['chart.hmargin']);
|
716
|
-
w = w * prop['chart.multiplier.w'];
|
717
|
-
var h = (Math.abs(this.data[i]) / this.max) * this.grapharea;
|
718
|
-
|
719
|
-
if (prop['chart.xaxispos'] == 'center') {
|
720
|
-
h /= 2;
|
721
|
-
y = (i == 0 ? ((this.data[0] / this.max) * this.grapharea) : (this.data[i] > 0 ? ((runningTotal + this.data[i]) / this.max) * this.grapharea : (runningTotal / this.max) * this.grapharea));
|
722
|
-
y = this.gutterTop + (this.grapharea/2) - (y / 2);
|
723
|
-
}
|
724
|
-
|
725
|
-
// Color
|
726
|
-
co.fillStyle = this.data[i] >= 0 ? prop['chart.colors'][0] : prop['chart.colors'][1];
|
727
|
-
|
728
|
-
|
729
|
-
if (prop['chart.shadow']) {
|
730
|
-
RG.SetShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
|
731
|
-
} else {
|
732
|
-
RG.NoShadow(this);
|
733
|
-
}
|
734
|
-
|
735
|
-
co.rect(x, y, w, h);
|
736
|
-
|
737
|
-
this.coords.push([x, y, w, h]);
|
738
|
-
|
739
|
-
runningTotal += this.data[i];
|
740
|
-
|
741
|
-
co.stroke();
|
742
|
-
co.fill();
|
743
|
-
}
|
744
|
-
|
745
|
-
// Store the total
|
746
|
-
this.total = runningTotal;
|
747
|
-
|
748
|
-
if (prop['chart.total']) {
|
749
|
-
|
750
|
-
// This is the height of the final bar
|
751
|
-
h = (runningTotal / this.max) * (this.grapharea / (prop['chart.xaxispos'] == 'center' ? 2 : 1));
|
752
|
-
|
753
|
-
/**
|
754
|
-
* Set the Y (ie the start point) value
|
755
|
-
*/
|
756
|
-
if (prop['chart.xaxispos'] == 'center') {
|
757
|
-
y = runningTotal > 0 ? this.centery - h : this.centery - h;
|
758
|
-
} else {
|
759
|
-
y = ca.height - this.gutterBottom - h;
|
760
|
-
}
|
761
|
-
|
762
|
-
// This is the X position of the final bar
|
763
|
-
x = x + (prop['chart.hmargin'] * 2) + w;
|
764
|
-
|
765
|
-
|
766
|
-
// Final color
|
767
|
-
co.fillStyle = prop['chart.colors'][2];
|
768
|
-
|
769
|
-
co.beginPath();
|
770
|
-
co.strokeRect(x, y, w, h);
|
771
|
-
co.fillRect(x, y, w, h);
|
772
|
-
co.stroke();
|
773
|
-
co.fill();
|
774
|
-
|
775
|
-
this.coords.push([x, y - (runningTotal > 0 ? 0 : Math.abs(h)), w, Math.abs(h)]);
|
776
|
-
}
|
777
|
-
|
778
|
-
RG.NoShadow(this);
|
779
|
-
|
780
|
-
/**
|
781
|
-
* This draws the connecting lines
|
782
|
-
*/
|
783
|
-
co.lineWidth = 1;
|
784
|
-
|
785
|
-
for (var i=1,len=this.coords.length; i<len; i+=1) {
|
786
|
-
co.strokeStyle = 'gray';
|
787
|
-
co.beginPath();
|
788
|
-
if (this.data[i - 1] > 0) {
|
789
|
-
co.moveTo(this.coords[i - 1][0] + this.coords[i - 1][2], Math.round( this.coords[i - 1][1]));
|
790
|
-
co.lineTo(this.coords[i - 1][0] + this.coords[i - 1][2] + (2 * hmargin), Math.round( this.coords[i - 1][1]));
|
791
|
-
} else {
|
792
|
-
co.moveTo(this.coords[i - 1][0] + this.coords[i - 1][2], Math.round( this.coords[i - 1][1] + this.coords[i - 1][3]));
|
793
|
-
co.lineTo(this.coords[i - 1][0] + this.coords[i - 1][2] + (2 * hmargin), Math.round( this.coords[i - 1][1] + this.coords[i - 1][3]));
|
794
|
-
}
|
795
|
-
co.stroke();
|
796
|
-
}
|
797
|
-
};
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
/**
|
803
|
-
* Not used by the class during creating the graph, but is used by event handlers
|
804
|
-
* to get the coordinates (if any) of the selected bar
|
805
|
-
*
|
806
|
-
* @param object e The event object
|
807
|
-
*/
|
808
|
-
this.getShape =
|
809
|
-
this.getBar = function (e)
|
810
|
-
{
|
811
|
-
/**
|
812
|
-
* Loop through the bars determining if the mouse is over a bar
|
813
|
-
*/
|
814
|
-
for (var i=0,len=this.coords.length; i<len; i++) {
|
815
|
-
|
816
|
-
var mouseCoords = RG.getMouseXY(e);
|
817
|
-
var mouseX = mouseCoords[0];
|
818
|
-
var mouseY = mouseCoords[1];
|
819
|
-
|
820
|
-
var left = this.coords[i][0];
|
821
|
-
var top = this.coords[i][1];
|
822
|
-
var width = this.coords[i][2];
|
823
|
-
var height = this.coords[i][3];
|
824
|
-
|
825
|
-
if ( mouseX >= left
|
826
|
-
&& mouseX <= (left + width)
|
827
|
-
&& mouseY >= top
|
828
|
-
&& mouseY <= top + height) {
|
829
|
-
|
830
|
-
var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
|
831
|
-
|
832
|
-
return {0: this, 'object': this,
|
833
|
-
1: left, 'x': left,
|
834
|
-
2: top, 'y': top,
|
835
|
-
3: width, 'width': width,
|
836
|
-
4: height, 'height': height,
|
837
|
-
5: i, 'index': i,
|
838
|
-
'tooltip': tooltip};
|
839
|
-
}
|
840
|
-
}
|
841
|
-
|
842
|
-
return null;
|
843
|
-
};
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
/**
|
849
|
-
* The Waterfall is slightly different to Bar/Line charts so has this function to get the max value
|
850
|
-
*/
|
851
|
-
this.getMax = function (data)
|
852
|
-
{
|
853
|
-
var runningTotal = 0;
|
854
|
-
var max = 0;
|
855
|
-
|
856
|
-
for (var i=0,len=data.length; i<len; i+=1) {
|
857
|
-
runningTotal += data[i];
|
858
|
-
max = ma.max(max, ma.abs(runningTotal));
|
859
|
-
}
|
860
|
-
|
861
|
-
return max;
|
862
|
-
};
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
/**
|
868
|
-
* This function facilitates the installation of tooltip event listeners if
|
869
|
-
* tooltips are defined.
|
870
|
-
*/
|
871
|
-
this.allowTooltips =
|
872
|
-
this.AllowTooltips = function ()
|
873
|
-
{
|
874
|
-
// Preload any tooltip images that are used in the tooltips
|
875
|
-
RG.PreLoadTooltipImages(this);
|
876
|
-
|
877
|
-
|
878
|
-
/**
|
879
|
-
* This installs the window mousedown event listener that lears any
|
880
|
-
* highlight that may be visible.
|
881
|
-
*/
|
882
|
-
RG.InstallWindowMousedownTooltipListener(this);
|
883
|
-
|
884
|
-
|
885
|
-
/**
|
886
|
-
* This installs the canvas mousemove event listener. This function
|
887
|
-
* controls the pointer shape.
|
888
|
-
*/
|
889
|
-
RG.InstallCanvasMousemoveTooltipListener(this);
|
890
|
-
|
891
|
-
|
892
|
-
/**
|
893
|
-
* This installs the canvas mouseup event listener. This is the
|
894
|
-
* function that actually shows the appropriate tooltip (if any).
|
895
|
-
*/
|
896
|
-
RG.InstallCanvasMouseupTooltipListener(this);
|
897
|
-
};
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
/**
|
903
|
-
* Each object type has its own Highlight() function which highlights the appropriate shape
|
904
|
-
*
|
905
|
-
* @param object shape The shape to highlight
|
906
|
-
*/
|
907
|
-
this.highlight =
|
908
|
-
this.Highlight = function (shape)
|
909
|
-
{
|
910
|
-
if (typeof prop['chart.highlight.style'] === 'function') {
|
911
|
-
(prop['chart.highlight.style'])(shape);
|
912
|
-
} else {
|
913
|
-
RG.Highlight.Rect(this, shape);
|
914
|
-
}
|
915
|
-
};
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
/**
|
921
|
-
* The getObjectByXY() worker method. Don't call this call:
|
922
|
-
*
|
923
|
-
* RGraph.ObjectRegistry.getObjectByXY(e)
|
924
|
-
*
|
925
|
-
* @param object e The event object
|
926
|
-
*/
|
927
|
-
this.getObjectByXY = function (e)
|
928
|
-
{
|
929
|
-
var mouseXY = RG.getMouseXY(e);
|
930
|
-
|
931
|
-
if (
|
932
|
-
mouseXY[0] > this.gutterLeft
|
933
|
-
&& mouseXY[0] < (ca.width - this.gutterRight)
|
934
|
-
&& mouseXY[1] > this.gutterTop
|
935
|
-
&& mouseXY[1] < (ca.height - this.gutterBottom)
|
936
|
-
) {
|
937
|
-
|
938
|
-
return this;
|
939
|
-
}
|
940
|
-
};
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
/**
|
946
|
-
* This function positions a tooltip when it is displayed
|
947
|
-
*
|
948
|
-
* @param obj object The chart object
|
949
|
-
* @param int x The X coordinate specified for the tooltip
|
950
|
-
* @param int y The Y coordinate specified for the tooltip
|
951
|
-
* @param objec tooltip The tooltips DIV element
|
952
|
-
*/
|
953
|
-
this.positionTooltip = function (obj, x, y, tooltip, idx)
|
954
|
-
{
|
955
|
-
var coordX = obj.coords[tooltip.__index__][0];
|
956
|
-
var coordY = obj.coords[tooltip.__index__][1];
|
957
|
-
var coordW = obj.coords[tooltip.__index__][2];
|
958
|
-
var coordH = obj.coords[tooltip.__index__][3];
|
959
|
-
var canvasXY = RG.getCanvasXY(obj.canvas);
|
960
|
-
var mouseXY = RG.getMouseXY(window.event);
|
961
|
-
var gutterLeft = obj.gutterLeft;
|
962
|
-
var gutterTop = obj.gutterTop;
|
963
|
-
var width = tooltip.offsetWidth;
|
964
|
-
var height = tooltip.offsetHeight;
|
965
|
-
var value = obj.data[idx];
|
966
|
-
|
967
|
-
/**
|
968
|
-
* Change the value to be the total if necessary
|
969
|
-
*/
|
970
|
-
if (tooltip.__index__ == obj.data.length) {
|
971
|
-
value = obj.total;
|
972
|
-
}
|
973
|
-
|
974
|
-
// Set the top position
|
975
|
-
tooltip.style.left = 0;
|
976
|
-
tooltip.style.top = window.event.pageY - height - 5 + 'px';
|
977
|
-
|
978
|
-
|
979
|
-
// By default any overflow is hidden
|
980
|
-
tooltip.style.overflow = '';
|
981
|
-
|
982
|
-
|
983
|
-
// Reposition the tooltip if at the edges:
|
984
|
-
|
985
|
-
// LEFT edge
|
986
|
-
if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
|
987
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
|
988
|
-
|
989
|
-
// RIGHT edge
|
990
|
-
} else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
|
991
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
|
992
|
-
|
993
|
-
// Default positioning - CENTERED
|
994
|
-
} else {
|
995
|
-
tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
|
996
|
-
}
|
997
|
-
};
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
/**
|
1003
|
-
* This method returns the appropriate Y coord for the given value
|
1004
|
-
*
|
1005
|
-
* @param number value The value
|
1006
|
-
*/
|
1007
|
-
this.getYCoord = function (value)
|
1008
|
-
{
|
1009
|
-
if (value > this.max) {
|
1010
|
-
return null;
|
1011
|
-
}
|
1012
|
-
|
1013
|
-
if (prop['chart.xaxispos'] == 'center') {
|
1014
|
-
|
1015
|
-
if (value < (-1 * this.max)) {
|
1016
|
-
return null;
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
var coord = (value / this.max) * (this.grapharea / 2);
|
1020
|
-
return this.gutterTop + (this.grapharea / 2) - coord;
|
1021
|
-
|
1022
|
-
} else {
|
1023
|
-
|
1024
|
-
if (value < 0) {
|
1025
|
-
return null;
|
1026
|
-
}
|
1027
|
-
|
1028
|
-
var coord = (value / this.max) * this.grapharea;
|
1029
|
-
coord = coord + this.gutterTop;
|
1030
|
-
return ca.height - coord;
|
1031
|
-
}
|
1032
|
-
};
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
/**
|
1038
|
-
* This allows for easy specification of gradients
|
1039
|
-
*/
|
1040
|
-
this.parseColors = function ()
|
1041
|
-
{
|
1042
|
-
// Save the original colors so that they can be restored when the canvas is reset
|
1043
|
-
if (this.original_colors.length === 0) {
|
1044
|
-
this.original_colors['chart.colors'] = RG.array_clone(prop['chart.colors']);
|
1045
|
-
this.original_colors['chart.key.colors'] = RG.array_clone(prop['chart.key.colors']);
|
1046
|
-
this.original_colors['chart.crosshairs.color'] = RG.array_clone(prop['chart.crosshairs.color']);
|
1047
|
-
this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']);
|
1048
|
-
this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']);
|
1049
|
-
this.original_colors['chart.background.barcolor1'] = RG.array_clone(prop['chart.background.barcolor1']);
|
1050
|
-
this.original_colors['chart.background.barcolor2'] = RG.array_clone(prop['chart.background.barcolor2']);
|
1051
|
-
this.original_colors['chart.background.grid.color'] = RG.array_clone(prop['chart.background.grid.color']);
|
1052
|
-
this.original_colors['chart.strokestyle'] = RG.array_clone(prop['chart.strokestyle']);
|
1053
|
-
this.original_colors['chart.axis.color'] = RG.array_clone(prop['chart.axis.color']);
|
1054
|
-
}
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
// chart.colors
|
1064
|
-
var colors = prop['chart.colors'];
|
1065
|
-
|
1066
|
-
if (colors) {
|
1067
|
-
for (var i=0,len=colors.length; i<len; ++i) {
|
1068
|
-
colors[i] = this.parseSingleColorForGradient(colors[i]);
|
1069
|
-
}
|
1070
|
-
}
|
1071
|
-
|
1072
|
-
// chart.key.colors
|
1073
|
-
var colors = prop['chart.key.colors'];
|
1074
|
-
|
1075
|
-
if (colors) {
|
1076
|
-
for (var i=0,len=colors.length; i<len; ++i) {
|
1077
|
-
colors[i] = this.parseSingleColorForGradient(colors[i]);
|
1078
|
-
}
|
1079
|
-
}
|
1080
|
-
|
1081
|
-
prop['chart.crosshairs.color'] = this.parseSingleColorForGradient(prop['chart.crosshairs.color']);
|
1082
|
-
prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
|
1083
|
-
prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
|
1084
|
-
prop['chart.background.barcolor1'] = this.parseSingleColorForGradient(prop['chart.background.barcolor1']);
|
1085
|
-
prop['chart.background.barcolor2'] = this.parseSingleColorForGradient(prop['chart.background.barcolor2']);
|
1086
|
-
prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
|
1087
|
-
prop['chart.strokestyle'] = this.parseSingleColorForGradient(prop['chart.strokestyle']);
|
1088
|
-
prop['chart.axis.color'] = this.parseSingleColorForGradient(prop['chart.axis.color']);
|
1089
|
-
};
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
/**
|
1095
|
-
* Use this function to reset the object to the post-constructor state. Eg reset colors if
|
1096
|
-
* need be etc
|
1097
|
-
*/
|
1098
|
-
this.reset = function ()
|
1099
|
-
{
|
1100
|
-
};
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
/**
|
1106
|
-
* This parses a single color value
|
1107
|
-
*
|
1108
|
-
* @param string color The color to parse for gradients
|
1109
|
-
*/
|
1110
|
-
this.parseSingleColorForGradient = function (color)
|
1111
|
-
{
|
1112
|
-
if (!color || typeof color != 'string') {
|
1113
|
-
return color;
|
1114
|
-
}
|
1115
|
-
|
1116
|
-
if (typeof color === 'string' && color.match(/^gradient\((.*)\)$/i)) {
|
1117
|
-
|
1118
|
-
var parts = RegExp.$1.split(':');
|
1119
|
-
|
1120
|
-
// Create the gradient
|
1121
|
-
|
1122
|
-
var grad = co.createLinearGradient(0,ca.height - prop['chart.gutter.bottom'], 0, prop['chart.gutter.top']);
|
1123
|
-
|
1124
|
-
var diff = 1 / (parts.length - 1);
|
1125
|
-
|
1126
|
-
grad.addColorStop(0, RG.trim(parts[0]));
|
1127
|
-
|
1128
|
-
for (var j=1,len=parts.length; j<len; ++j) {
|
1129
|
-
grad.addColorStop(j * diff, RG.trim(parts[j]));
|
1130
|
-
}
|
1131
|
-
}
|
1132
|
-
|
1133
|
-
return grad ? grad : color;
|
1134
|
-
};
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
/**
|
1140
|
-
* Using a function to add events makes it easier to facilitate method chaining
|
1141
|
-
*
|
1142
|
-
* @param string type The type of even to add
|
1143
|
-
* @param function func
|
1144
|
-
*/
|
1145
|
-
this.on = function (type, func)
|
1146
|
-
{
|
1147
|
-
if (type.substr(0,2) !== 'on') {
|
1148
|
-
type = 'on' + type;
|
1149
|
-
}
|
1150
|
-
|
1151
|
-
this[type] = func;
|
1152
|
-
|
1153
|
-
return this;
|
1154
|
-
};
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
/**
|
1160
|
-
* This function runs once only
|
1161
|
-
* (put at the end of the file (before any effects))
|
1162
|
-
*/
|
1163
|
-
this.firstDrawFunc = function ()
|
1164
|
-
{
|
1165
|
-
};
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
/**
|
1171
|
-
* Waterfall Grow
|
1172
|
-
*
|
1173
|
-
* @param object Options. You can pass frames here - which should be a number
|
1174
|
-
* @param function An optional function which is called when the animation is finished
|
1175
|
-
*/
|
1176
|
-
this.grow = function ()
|
1177
|
-
{
|
1178
|
-
var opt = arguments[0] || {};
|
1179
|
-
var callback = arguments[1] || function () {};
|
1180
|
-
var frames = opt.frames || 30;
|
1181
|
-
var numFrame = 0;
|
1182
|
-
var obj = this;
|
1183
|
-
var data = RG.array_clone(obj.data);
|
1184
|
-
|
1185
|
-
//Reset The data to zeros
|
1186
|
-
for (var i=0,len=obj.data.length; i<len; ++i) {
|
1187
|
-
obj.data[i] /= frames;
|
1188
|
-
}
|
1189
|
-
|
1190
|
-
/**
|
1191
|
-
* Fix the scale
|
1192
|
-
*/
|
1193
|
-
if (obj.Get('chart.ymax') == null) {
|
1194
|
-
var max = obj.getMax(data);
|
1195
|
-
var scale2 = RG.getScale2(obj, {'max':max});
|
1196
|
-
obj.Set('chart.ymax', scale2.max);
|
1197
|
-
}
|
1198
|
-
|
1199
|
-
//obj.Set('chart.multiplier.x', 0);
|
1200
|
-
//obj.Set('chart.multiplier.w', 0);
|
1201
|
-
|
1202
|
-
function iterator ()
|
1203
|
-
{
|
1204
|
-
for (var i=0; i<obj.data.length; ++i) {
|
1205
|
-
|
1206
|
-
// This produces a very slight easing effect
|
1207
|
-
obj.data[i] = data[i] * RG.Effects.getEasingMultiplier(frames, numFrame);
|
1208
|
-
}
|
1209
|
-
|
1210
|
-
RGraph.clear(obj.canvas);
|
1211
|
-
RGraph.redrawCanvas(obj.canvas);
|
1212
|
-
|
1213
|
-
if (++numFrame < frames) {
|
1214
|
-
RGraph.Effects.updateCanvas(iterator);
|
1215
|
-
} else {
|
1216
|
-
callback(obj);
|
1217
|
-
}
|
1218
|
-
}
|
1219
|
-
|
1220
|
-
iterator();
|
1221
|
-
|
1222
|
-
return this;
|
1223
|
-
};
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
RG.att(ca);
|
1230
|
-
|
1231
|
-
|
1232
|
-
/**
|
1233
|
-
* Now, because canvases can support multiple charts, canvases must always be registered
|
1234
|
-
*/
|
1235
|
-
RG.Register(this);
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
/**
|
1241
|
-
* This is the 'end' of the constructor so if the first argument
|
1242
|
-
* contains configuration data - handle that.
|
1243
|
-
*/
|
1244
|
-
if (parseConfObjectForOptions) {
|
1245
|
-
RG.parseObjectStyleConfig(this, conf.options);
|
1246
|
-
}
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
return this;
|
1252
|
-
};
|