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