rgraph-rails 4.62 → 4.64

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 (67) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -4
  3. data/lib/rgraph-rails/version.rb +1 -1
  4. data/vendor/assets/javascripts/RGraph.bar.js +240 -3742
  5. data/vendor/assets/javascripts/RGraph.bipolar.js +165 -2005
  6. data/vendor/assets/javascripts/RGraph.common.annotate.js +35 -395
  7. data/vendor/assets/javascripts/RGraph.common.context.js +30 -595
  8. data/vendor/assets/javascripts/RGraph.common.core.js +418 -5359
  9. data/vendor/assets/javascripts/RGraph.common.csv.js +20 -276
  10. data/vendor/assets/javascripts/RGraph.common.deprecated.js +35 -450
  11. data/vendor/assets/javascripts/RGraph.common.dynamic.js +88 -1395
  12. data/vendor/assets/javascripts/RGraph.common.effects.js +90 -1545
  13. data/vendor/assets/javascripts/RGraph.common.key.js +52 -753
  14. data/vendor/assets/javascripts/RGraph.common.resizing.js +37 -563
  15. data/vendor/assets/javascripts/RGraph.common.sheets.js +29 -352
  16. data/vendor/assets/javascripts/RGraph.common.tooltips.js +32 -450
  17. data/vendor/assets/javascripts/RGraph.common.zoom.js +14 -219
  18. data/vendor/assets/javascripts/RGraph.cornergauge.js +71 -0
  19. data/vendor/assets/javascripts/RGraph.drawing.background.js +34 -570
  20. data/vendor/assets/javascripts/RGraph.drawing.circle.js +33 -544
  21. data/vendor/assets/javascripts/RGraph.drawing.image.js +51 -755
  22. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +37 -645
  23. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +36 -633
  24. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +35 -514
  25. data/vendor/assets/javascripts/RGraph.drawing.poly.js +37 -559
  26. data/vendor/assets/javascripts/RGraph.drawing.rect.js +33 -548
  27. data/vendor/assets/javascripts/RGraph.drawing.text.js +36 -664
  28. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +50 -812
  29. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +51 -856
  30. data/vendor/assets/javascripts/RGraph.fuel.js +58 -964
  31. data/vendor/assets/javascripts/RGraph.funnel.js +55 -984
  32. data/vendor/assets/javascripts/RGraph.gantt.js +77 -1354
  33. data/vendor/assets/javascripts/RGraph.gauge.js +85 -1421
  34. data/vendor/assets/javascripts/RGraph.hbar.js +162 -2788
  35. data/vendor/assets/javascripts/RGraph.hprogress.js +80 -1401
  36. data/vendor/assets/javascripts/RGraph.line.js +249 -4248
  37. data/vendor/assets/javascripts/RGraph.meter.js +74 -1280
  38. data/vendor/assets/javascripts/RGraph.modaldialog.js +19 -301
  39. data/vendor/assets/javascripts/RGraph.odo.js +71 -1264
  40. data/vendor/assets/javascripts/RGraph.pie.js +137 -2288
  41. data/vendor/assets/javascripts/RGraph.radar.js +110 -1847
  42. data/vendor/assets/javascripts/RGraph.rose.js +108 -1977
  43. data/vendor/assets/javascripts/RGraph.rscatter.js +80 -1432
  44. data/vendor/assets/javascripts/RGraph.scatter.js +172 -3163
  45. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +60 -1120
  46. data/vendor/assets/javascripts/RGraph.svg.bar.js +66 -1735
  47. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +21 -246
  48. data/vendor/assets/javascripts/RGraph.svg.common.core.js +255 -3937
  49. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +20 -276
  50. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +68 -1303
  51. data/vendor/assets/javascripts/RGraph.svg.common.key.js +19 -205
  52. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +29 -352
  53. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +22 -273
  54. data/vendor/assets/javascripts/RGraph.svg.funnel.js +32 -0
  55. data/vendor/assets/javascripts/RGraph.svg.hbar.js +59 -1400
  56. data/vendor/assets/javascripts/RGraph.svg.line.js +70 -1580
  57. data/vendor/assets/javascripts/RGraph.svg.pie.js +55 -1131
  58. data/vendor/assets/javascripts/RGraph.svg.radar.js +57 -1502
  59. data/vendor/assets/javascripts/RGraph.svg.rose.js +66 -1817
  60. data/vendor/assets/javascripts/RGraph.svg.scatter.js +58 -1261
  61. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +28 -865
  62. data/vendor/assets/javascripts/RGraph.svg.waterfall.js +45 -1252
  63. data/vendor/assets/javascripts/RGraph.thermometer.js +63 -1136
  64. data/vendor/assets/javascripts/RGraph.vprogress.js +83 -1470
  65. data/vendor/assets/javascripts/RGraph.waterfall.js +83 -1347
  66. metadata +5 -4
  67. data/vendor/assets/javascripts/financial-data.js +0 -1067
@@ -1,247 +1,22 @@
1
- // version: 2017-05-08
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 licensed under the Open Source MIT license. That means that it's |
9
- * | totally free to use! |
10
- * o--------------------------------------------------------------------------------o
11
- */
12
1
 
13
- RGraph = window.RGraph || {isRGraph: true,isRGraphSVG: true};
14
- RGraph.SVG = RGraph.SVG || {};
15
- RGraph.SVG.AJAX = RGraph.SVG.AJAX || {};
16
-
17
- // Module pattern
18
- (function (win, doc, undefined)
19
- {
20
- var RG = RGraph,
21
- ua = navigator.userAgent,
22
- ma = Math;
23
-
24
-
25
-
26
- /**
27
- * Makes an AJAX call. It calls the given callback (a function) when ready
28
- *
29
- * @param string url The URL to retrieve
30
- * @param function callback A function that is called when the response is ready, there's an example below
31
- * called "myCallback".
32
- */
33
- RG.SVG.AJAX = function (url, callback)
34
- {
35
- // Mozilla, Safari, ...
36
- if (window.XMLHttpRequest) {
37
- var httpRequest = new XMLHttpRequest();
38
-
39
- // MSIE
40
- } else if (window.ActiveXObject) {
41
- var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
42
- }
43
-
44
- httpRequest.onreadystatechange = function ()
45
- {
46
- if (this.readyState == 4 && this.status == 200) {
47
- this.__user_callback__ = callback;
48
- this.__user_callback__(this.responseText);
49
- }
50
- }
51
-
52
- httpRequest.open('GET', url, true);
53
- httpRequest.send();
54
- };
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
- /**
66
- * Makes an AJAX POST request. It calls the given callback (a function) when ready
67
- *
68
- * @param string url The URL to retrieve
69
- * @param object data The POST data
70
- * @param function callback A function that is called when the response is ready, there's an example below
71
- * called "myCallback".
72
- */
73
- RG.SVG.AJAX.POST = function (url, data, callback)
74
- {
75
- // Used when building the POST string
76
- var crumbs = [];
77
-
78
-
79
-
80
-
81
-
82
-
83
- // Mozilla, Safari, ...
84
- if (window.XMLHttpRequest) {
85
- var httpRequest = new XMLHttpRequest();
86
-
87
- // MSIE
88
- } else if (window.ActiveXObject) {
89
- var httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
90
- }
91
-
92
-
93
-
94
-
95
-
96
- httpRequest.onreadystatechange = function ()
97
- {
98
- if (this.readyState == 4 && this.status == 200) {
99
- this.__user_callback__ = callback;
100
- this.__user_callback__(this.responseText);
101
- }
102
- }
103
-
104
- httpRequest.open('POST', url, true);
105
- httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
106
-
107
- for (i in data) {
108
- if (typeof i == 'string') {
109
- crumbs.push(i + '=' + encodeURIComponent(data[i]));
110
- }
111
- }
112
-
113
- httpRequest.send(crumbs.join('&'));
114
- };
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
- /**
126
- * Uses the above function but calls the call back passing a number as its argument
127
- *
128
- * @param url string The URL to fetch
129
- * @param callback function Your callback function (which is passed the number as an argument)
130
- */
131
- RG.SVG.AJAX.getNumber = function (url, callback)
132
- {
133
- RG.SVG.AJAX(url, function ()
134
- {
135
- var num = parseFloat(this.responseText);
136
-
137
- callback(num);
138
- });
139
- };
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
- /**
151
- * Uses the above function but calls the call back passing a string as its argument
152
- *
153
- * @param url string The URL to fetch
154
- * @param callback function Your callback function (which is passed the string as an argument)
155
- */
156
- RG.SVG.AJAX.getString = function (url, callback)
157
- {
158
- RG.SVG.AJAX(url, function ()
159
- {
160
- var str = String(this.responseText);
161
-
162
- callback(str);
163
- });
164
- };
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
- /**
176
- * Uses the above function but calls the call back passing JSON (ie a JavaScript object ) as its argument
177
- *
178
- * @param url string The URL to fetch
179
- * @param callback function Your callback function (which is passed the JSON object as an argument)
180
- */
181
- RG.SVG.AJAX.getJSON = function (url, callback)
182
- {
183
- RG.SVG.AJAX(url, function ()
184
- {
185
- var json = eval('(' + this.responseText + ')');
186
-
187
- callback(json);
188
- });
189
- };
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
- /**
201
- * Uses the above RGraph.AJAX function but calls the call back passing an array as its argument.
202
- * Useful if you're retrieving CSV data
203
- *
204
- * @param url string The URL to fetch
205
- * @param callback function Your callback function (which is passed the CSV/array as an argument)
206
- */
207
- RG.SVG.AJAX.getCSV = function (url, callback)
208
- {
209
- var seperator = (typeof arguments[2] === 'string' ? arguments[2] : ','),
210
- lineSep = (typeof arguments[3] === 'string' ? arguments[3] : "\r?\n");
211
-
212
- RG.SVG.AJAX(url, function ()
213
- {
214
- var text = this.responseText,
215
- regexp = new RegExp(seperator),
216
- lines = this.responseText.split(lineSep),
217
- rows = [];
218
-
219
- for (var i=0; i<lines.length; ++i) {
220
-
221
- var row = lines[i].split(seperator);
222
-
223
- for (var j=0,len=row.length;j<len;++j) {
224
- if (row[j].match(/^[0-9.]+$/)) {
225
- row[j] = parseFloat(row[j]);
226
- }
227
- }
228
-
229
- rows.push(row);
230
- }
231
-
232
-
233
- callback(rows);
234
- });
235
- };
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
- // End module pattern
247
- })(window, document);
2
+ RGraph=window.RGraph||{isRGraph:true,isRGraphSVG:true};RGraph.SVG=RGraph.SVG||{};RGraph.SVG.AJAX=RGraph.SVG.AJAX||{};(function(win,doc,undefined)
3
+ {var RG=RGraph,ua=navigator.userAgent,ma=Math;RG.SVG.AJAX=function(url,callback)
4
+ {if(window.XMLHttpRequest){var httpRequest=new XMLHttpRequest();}else if(window.ActiveXObject){var httpRequest=new ActiveXObject("Microsoft.XMLHTTP");}
5
+ httpRequest.onreadystatechange=function()
6
+ {if(this.readyState==4&&this.status==200){this.__user_callback__=callback;this.__user_callback__(this.responseText);}}
7
+ httpRequest.open('GET',url,true);httpRequest.send();};RG.SVG.AJAX.POST=function(url,data,callback)
8
+ {var crumbs=[];if(window.XMLHttpRequest){var httpRequest=new XMLHttpRequest();}else if(window.ActiveXObject){var httpRequest=new ActiveXObject("Microsoft.XMLHTTP");}
9
+ httpRequest.onreadystatechange=function()
10
+ {if(this.readyState==4&&this.status==200){this.__user_callback__=callback;this.__user_callback__(this.responseText);}}
11
+ httpRequest.open('POST',url,true);httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");for(i in data){if(typeof i=='string'){crumbs.push(i+'='+encodeURIComponent(data[i]));}}
12
+ httpRequest.send(crumbs.join('&'));};RG.SVG.AJAX.getNumber=function(url,callback)
13
+ {RG.SVG.AJAX(url,function()
14
+ {var num=parseFloat(this.responseText);callback(num);});};RG.SVG.AJAX.getString=function(url,callback)
15
+ {RG.SVG.AJAX(url,function()
16
+ {var str=String(this.responseText);callback(str);});};RG.SVG.AJAX.getJSON=function(url,callback)
17
+ {RG.SVG.AJAX(url,function()
18
+ {var json=eval('('+this.responseText+')');callback(json);});};RG.SVG.AJAX.getCSV=function(url,callback)
19
+ {var seperator=(typeof arguments[2]==='string'?arguments[2]:','),lineSep=(typeof arguments[3]==='string'?arguments[3]:"\r?\n");RG.SVG.AJAX(url,function()
20
+ {var text=this.responseText,regexp=new RegExp(seperator),lines=this.responseText.split(lineSep),rows=[];for(var i=0;i<lines.length;++i){var row=lines[i].split(seperator);for(var j=0,len=row.length;j<len;++j){if(row[j].match(/^[0-9.]+$/)){row[j]=parseFloat(row[j]);}}
21
+ rows.push(row);}
22
+ callback(rows);});};})(window,document);
@@ -1,3938 +1,256 @@
1
- // version: 2017-05-08
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 licensed under the Open Source MIT license. That means that it's |
9
- * | totally free to use! |
10
- * o--------------------------------------------------------------------------------o
11
- */
12
1
 
13
- RGraph = window.RGraph || {isRGraph: true,isRGraphSVG: true};
14
- RGraph.SVG = RGraph.SVG || {};
15
- RGraph.SVG.FX = RGraph.SVG.FX || {};
16
-
17
-
18
- // Module pattern
19
- (function (win, doc, undefined)
20
- {
21
- var RG = RGraph,
22
- ua = navigator.userAgent,
23
- ma = Math;
24
-
25
- RG.SVG.REG = {
26
- store: []
27
- };
28
-
29
- // ObjectRegistry
30
- RG.SVG.OR = {objects: []};
31
-
32
- // Used to categorise trigonometery functions
33
- RG.SVG.TRIG = {};
34
- RG.SVG.TRIG.HALFPI = ma.PI * .4999;
35
- RG.SVG.TRIG.PI = RG.SVG.TRIG.HALFPI * 2;
36
- RG.SVG.TRIG.TWOPI = RG.SVG.TRIG.PI * 2;
37
-
38
- RG.SVG.ISIE = ua.indexOf('rident') > 0;
39
- RG.SVG.ISFF = ua.indexOf('irefox') > 0;
40
-
41
- RG.SVG.events = [];
42
-
43
-
44
- RG.SVG.ISFF = ua.indexOf('Firefox') != -1;
45
- RG.SVG.ISOPERA = ua.indexOf('Opera') != -1;
46
- RG.SVG.ISCHROME = ua.indexOf('Chrome') != -1;
47
- RG.SVG.ISSAFARI = ua.indexOf('Safari') != -1 && !RG.ISCHROME;
48
- RG.SVG.ISWEBKIT = ua.indexOf('WebKit') != -1;
49
-
50
- RG.SVG.ISIE = ua.indexOf('Trident') > 0 || navigator.userAgent.indexOf('MSIE') > 0;
51
- RG.SVG.ISIE6 = ua.indexOf('MSIE 6') > 0;
52
- RG.SVG.ISIE7 = ua.indexOf('MSIE 7') > 0;
53
- RG.SVG.ISIE8 = ua.indexOf('MSIE 8') > 0;
54
- RG.SVG.ISIE9 = ua.indexOf('MSIE 9') > 0;
55
- RG.SVG.ISIE10 = ua.indexOf('MSIE 10') > 0;
56
- RG.SVG.ISIE11UP = ua.indexOf('MSIE') == -1 && ua.indexOf('Trident') > 0;
57
- RG.SVG.ISIE10UP = RG.SVG.ISIE10 || RG.SVG.ISIE11UP;
58
- RG.SVG.ISIE9UP = RG.SVG.ISIE9 || RG.SVG.ISIE10UP;
59
-
60
-
61
-
62
-
63
- //
64
- // Create an SVG tag
65
- //
66
- RG.SVG.createSVG = function (opt)
67
- {
68
- var container = opt.container;
69
-
70
- if (container.__svg__) {
71
- return container.__svg__;
72
- }
73
-
74
- var svg = doc.createElementNS("http://www.w3.org/2000/svg", "svg");
75
- svg.setAttribute('style', 'top: 0; left: 0; position: absolute');
76
- svg.setAttribute('width', container.offsetWidth);
77
- svg.setAttribute('height', container.offsetHeight);
78
- svg.setAttribute('version', '1.1');
79
- svg.setAttributeNS("http://www.w3.org/2000/xmlns/", 'xmlns', 'http://www.w3.org/2000/svg');
80
- svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
81
- container.appendChild(svg);
82
-
83
- container.__svg__ = svg;
84
- container.style.position = 'relative';
85
-
86
- // Add the group tag to the SVG that contains all of the elements
87
- var group = RG.SVG.create({
88
- svg: svg,
89
- type: 'g',
90
- attr: {
91
- className: 'all-elements'
92
- }
93
- });
94
-
95
- container.__svg__.all = group;
96
-
97
- return svg;
98
- };
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
- //
108
- // Create a defs tag inside the SVG
109
- //
110
- RG.SVG.createDefs = function (obj)
111
- {
112
- if (!obj.svg.defs) {
113
-
114
- var defs = RG.SVG.create({
115
- svg: obj.svg,
116
- type: 'defs'
117
- });
118
-
119
- obj.svg.defs = defs;
120
- }
121
-
122
- return defs;
123
- };
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
- //
133
- // Creates a tag depending on the args that you give
134
- //
135
- //@param opt object The options for the function
136
- //
137
- RG.SVG.create = function (opt)
138
- {
139
- var ns = "http://www.w3.org/2000/svg",
140
- tag = doc.createElementNS(ns, opt.type);
141
-
142
- // Add the attributes
143
- for (var o in opt.attr) {
144
- if (typeof o === 'string') {
145
-
146
- var name = o;
147
-
148
- if (o === 'className') {
149
- name = 'class';
150
- }
151
- if ( (opt.type === 'a' || opt.type === 'image') && o === 'xlink:href') {
152
- tag.setAttributeNS('http://www.w3.org/1999/xlink', o, String(opt.attr[o]));
153
- } else {
154
- tag.setAttribute(name, String(opt.attr[o]));
155
- }
156
- }
157
- }
158
-
159
- // Add the style
160
- for (var o in opt.style) {
161
- if (typeof o === 'string') {
162
- tag.style[o] = String(opt.style[o]);
163
- }
164
- }
165
-
166
- if (opt.parent) {
167
- opt.parent.appendChild(tag);
168
- } else {
169
- opt.svg.appendChild(tag);
170
- }
171
-
172
- return tag;
173
- };
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
- //
183
- // Draws an X axis
184
- //
185
- //@param The chart object
186
- //
187
- RG.SVG.drawXAxis = function (obj)
188
- {
189
- var prop = obj.properties;
190
-
191
- // Draw the axis
192
- if (prop.xaxis) {
193
-
194
- var y = obj.type === 'hbar' ? obj.height - prop.gutterBottom : obj.getYCoord(obj.scale.min < 0 && obj.scale.max < 0 ? obj.scale.max : (obj.scale.min > 0 && obj.scale.max > 0 ? obj.scale.min : 0));
195
-
196
- var axis = RG.SVG.create({
197
- svg: obj.svg,
198
- parent: obj.svg.all,
199
- type: 'path',
200
- attr: {
201
- d: 'M{1} {2} L{3} {4}'.format(
202
- prop.gutterLeft,
203
- y + 0.01,
204
- obj.width - prop.gutterRight,
205
- y
206
- ),
207
- fill: prop.xaxisColor,
208
- stroke: prop.xaxisColor,
209
- 'stroke-width': typeof prop.xaxisLinewidth === 'number' ? prop.xaxisLinewidth : 1,
210
- 'shape-rendering': 'crispEdges',
211
- 'stroke-linecap': 'square'
212
- }
213
- });
214
-
215
-
216
- // HBar X axis
217
- if (obj.type === 'hbar') {
218
- var width = obj.graphWidth / obj.data.length,
219
- x = prop.gutterLeft,
220
- startY = (obj.height - prop.gutterBottom),
221
- endY = (obj.height - prop.gutterBottom) + prop.xaxisTickmarksLength;
222
-
223
- // Line/Bar/Waterfall/Scatter X axis
224
- } else {
225
- var width = obj.graphWidth / obj.data.length,
226
- x = prop.gutterLeft,
227
- startY = obj.getYCoord(0) - (prop.yaxisMin < 0 ? prop.xaxisTickmarksLength : 0),
228
- endY = obj.getYCoord(0) + prop.xaxisTickmarksLength;
229
-
230
- if (obj.scale.min < 0 && obj.scale.max <= 0) {
231
- startY = prop.gutterTop;
232
- endY = prop.gutterTop - prop.xaxisTickmarksLength;
233
- }
234
-
235
- if (obj.scale.min > 0 && obj.scale.max > 0) {
236
- startY = obj.getYCoord(obj.scale.min);
237
- endY = obj.getYCoord(obj.scale.min) + prop.xaxisTickmarksLength;
238
- }
239
- }
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
- // Draw the tickmarks
249
- if (prop.xaxisTickmarks) {
250
-
251
- // The HBar uses a scale
252
- if (prop.xaxisScale) {
253
-
254
- for (var i=0; i<(obj.scale.numlabels + (prop.yaxis && prop.xaxisMin === 0 ? 0 : 1)); ++i) {
255
-
256
- if (obj.type === 'hbar') {
257
- var dataPoints = obj.data.length;
258
- }
259
-
260
- x = prop.gutterLeft + ((i+(prop.yaxis && prop.xaxisMin === 0 ? 1 : 0)) * (obj.graphWidth / obj.scale.numlabels));
261
-
262
- RG.SVG.create({
263
- svg: obj.svg,
264
- parent: obj.svg.all,
265
- type: 'path',
266
- attr: {
267
- d: 'M{1} {2} L{3} {4}'.format(
268
- x + 0.001,
269
- startY,
270
- x,
271
- endY
272
- ),
273
- stroke: prop.xaxisColor,
274
- 'stroke-width': typeof prop.xaxisLinewidth === 'number' ? prop.xaxisLinewidth : 1,
275
- 'shape-rendering': "crispEdges"
276
- }
277
- });
278
- }
279
-
280
-
281
-
282
-
283
- } else {
284
-
285
- // This style is used by Bar and Scatter charts
286
- if (prop.xaxisLabelsPosition === 'section') {
287
-
288
- if (obj.type === 'bar' || obj.type === 'waterfall') {
289
- var dataPoints = obj.data.length;
290
- } else if (obj.type === 'line'){
291
- var dataPoints = obj.data[0].length;
292
- } else if (obj.type === 'scatter') {
293
- var dataPoints = prop.xaxisLabels ? prop.xaxisLabels.length : 10;
294
- }
295
-
296
- for (var i=0; i<dataPoints; ++i) {
297
-
298
- x = prop.gutterLeft + ((i+1) * (obj.graphWidth / dataPoints));
299
-
300
- RG.SVG.create({
301
- svg: obj.svg,
302
- parent: obj.svg.all,
303
- type: 'path',
304
- attr: {
305
- d: 'M{1} {2} L{3} {4}'.format(
306
- x + 0.001,
307
- startY,
308
- x,
309
- endY
310
- ),
311
- stroke: prop.xaxisColor,
312
- 'stroke-width': typeof prop.xaxisLinewidth === 'number' ? prop.xaxisLinewidth : 1,
313
- 'shape-rendering': "crispEdges"
314
- }
315
- });
316
- }
317
-
318
- // This style is used by line charts
319
- } else if (prop.xaxisLabelsPosition === 'edge') {
320
-
321
- if (typeof prop.xaxisLabelsPositionEdgeTickmarksCount === 'number') {
322
- var len = prop.xaxisLabelsPositionEdgeTickmarksCount;
323
- } else {
324
- var len = obj.data && obj.data[0] && obj.data[0].length ? obj.data[0].length : 0;
325
- }
326
-
327
- for (var i=0; i<len; ++i) {
328
-
329
- var gap = ( (obj.graphWidth) / (len - 1)),
330
- x = prop.gutterLeft + ((i+1) * gap);
331
-
332
- RG.SVG.create({
333
- svg: obj.svg,
334
- parent: obj.svg.all,
335
- type: 'path',
336
- attr: {
337
- d: 'M{1} {2} L{3} {4}'.format(
338
- x + 0.001,
339
- startY,
340
- x,
341
- endY
342
- ),
343
- stroke: prop.xaxisColor,
344
- 'stroke-width': typeof prop.xaxisLinewidth === 'number' ? prop.xaxisLinewidth : 1,
345
- 'shape-rendering': "crispEdges"
346
- }
347
- });
348
- }
349
- }
350
- }
351
-
352
-
353
-
354
-
355
-
356
-
357
- // Draw an extra tick if the Y axis is not being shown
358
- if (prop.yaxis === false) {
359
- RG.SVG.create({
360
- svg: obj.svg,
361
- parent: obj.svg.all,
362
- type: 'path',
363
- attr: {
364
- d: 'M{1} {2} L{3} {4}'.format(
365
- prop.gutterLeft + 0.001,
366
- startY,
367
- prop.gutterLeft,
368
- endY
369
- ),
370
- stroke: obj.properties.xaxisColor,
371
- 'stroke-width': typeof prop.xaxisLinewidth === 'number' ? prop.xaxisLinewidth : 1,
372
- 'shape-rendering': "crispEdges",
373
- parent: obj.svg.all,
374
- }
375
- });
376
- }
377
- }
378
- }
379
-
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
- //
392
- // Draw an X axis scale
393
- //
394
- if (prop.xaxisScale) {
395
-
396
- var segment = obj.graphWidth / prop.xaxisLabelsCount;
397
-
398
- for (var i=0; i<obj.scale.labels.length; ++i) {
399
-
400
- var x = prop.gutterLeft + (segment * i) + segment + prop.xaxisLabelsOffsetx;
401
-
402
- RG.SVG.text({
403
- object: obj,
404
- parent: obj.svg.all,
405
- text: obj.scale.labels[i],
406
- x: x,
407
- y: (obj.height - prop.gutterBottom) + (prop.xaxis ? prop.xaxisTickmarksLength + 6 : 10) + (prop.xaxisLinewidth || 1) + prop.xaxisLabelsOffsety,
408
- halign: 'center',
409
- valign: 'top',
410
- font: prop.xaxisTextFont || prop.textFont,
411
- size: prop.xaxisTextSize || (typeof prop.textSize === 'number' ? prop.textSize + 'pt' : prop.textSize),
412
- bold: prop.xaxisTextBold || prop.textBold,
413
- italic: prop.xaxisTextItalic || prop.textItalic,
414
- color: prop.xaxisTextColor || prop.textColor
415
- });
416
- }
417
-
418
-
419
-
420
-
421
-
422
- // Add the minimum label if labels are enabled
423
- if (prop.xaxisLabelsCount > 0) {
424
- var y = obj.height - prop.gutterBottom + prop.xaxisLabelsOffsety + (prop.xaxis ? prop.xaxisTickmarksLength + 6 : 10),
425
- str = RG.SVG.numberFormat({
426
- object: obj,
427
- num: prop.xaxisMin.toFixed(prop.xaxisDecimals),
428
- prepend: prop.xaxisUnitsPre,
429
- append: prop.xaxisUnitsPost,
430
- point: prop.xaxisPoint,
431
- thousand: prop.xaxisThousand,
432
- formatter: prop.xaxisFormatter
433
- });
434
-
435
- var text = RG.SVG.text({
436
- object: obj,
437
- parent: obj.svg.all,
438
- text: typeof prop.xaxisFormatter === 'function' ? (prop.xaxisFormatter)(this, prop.xaxisMin) : str,
439
- x: prop.gutterLeft + prop.xaxisLabelsOffsetx,
440
- y: y,
441
- halign: 'center',
442
- valign: 'top',
443
- font: prop.xaxisTextFont || prop.textFont,
444
- size: prop.xaxisTextSize || (typeof prop.textSize === 'number' ? prop.textSize + 'pt' : prop.textSize),
445
- bold: prop.xaxisTextBold || prop.textBold,
446
- italic: prop.xaxisTextItalic || prop.textItalic,
447
- color: prop.xaxisTextColor || prop.textColor
448
- });
449
- }
450
-
451
- //
452
- // Draw the X axis labels
453
- //
454
- } else {
455
- if (typeof prop.xaxisLabels === 'object' && !RG.SVG.isNull(prop.xaxisLabels) ) {
456
-
457
- // Loop through the X labels
458
- if (prop.xaxisLabelsPosition === 'section') {
459
-
460
- var segment = (obj.width - prop.gutterLeft - prop.gutterRight) / prop.xaxisLabels.length;
461
-
462
- for (var i=0; i<prop.xaxisLabels.length; ++i) {
463
-
464
- var x = prop.gutterLeft + (segment / 2) + (i * segment);
465
-
466
- if (obj.scale.max <=0 && obj.scale.min < obj.scale.max) {
467
- var y = prop.gutterTop - (RG.SVG.ISFF ? 5 : 10) - (prop.xaxisLinewidth || 1) + prop.xaxisLabelsOffsety;
468
- var valign = 'bottom';
469
- } else {
470
- var y = obj.height - prop.gutterBottom + (RG.SVG.ISFF ? 5 : 10) + (prop.xaxisLinewidth || 1) + prop.xaxisLabelsOffsety;
471
- var valign = 'top';
472
- }
473
-
474
- RG.SVG.text({
475
- object: obj,
476
- parent: obj.svg.all,
477
- text: prop.xaxisLabels[i],
478
- x: x + prop.xaxisLabelsOffsetx,
479
- y: y,
480
- valign: valign,
481
- halign: 'center',
482
- size: prop.xaxisTextSize || prop.textSize,
483
- italic: prop.xaxisTextItalic || prop.textItalic,
484
- font: prop.xaxisTextFont || prop.textFont,
485
- bold: prop.xaxisTextBold || prop.textBold,
486
- color: prop.xaxisTextColor || prop.textColor
487
- });
488
- }
489
- } else if (prop.xaxisLabelsPosition === 'edge') {
490
-
491
- if (obj.type === 'line') {
492
- var hmargin = prop.hmargin;
493
- } else {
494
- var hmargin = 0;
495
- }
496
-
497
-
498
-
499
- var segment = (obj.graphWidth - hmargin - hmargin) / (prop.xaxisLabels.length - 1);
500
-
501
- for (var i=0; i<prop.xaxisLabels.length; ++i) {
502
-
503
- var x = prop.gutterLeft + (i * segment) + hmargin;
504
-
505
- if (obj.scale.max <= 0 && obj.scale.min < 0) {
506
- valign = 'bottom';
507
- y = prop.gutterTop - (RG.SVG.ISFF ? 5 : 10) - (prop.xaxisTickmarksLength - 5) - (prop.xaxisLinewidth || 1) + prop.xaxisLabelsOffsety
508
- } else {
509
- valign = 'top';
510
- y = obj.height - prop.gutterBottom + (RG.SVG.ISFF ? 5 : 10) + (prop.xaxisTickmarksLength - 5) + (prop.xaxisLinewidth || 1) + prop.xaxisLabelsOffsety;
511
- }
512
-
513
- RG.SVG.text({
514
- object: obj,
515
- parent: obj.svg.all,
516
- text: prop.xaxisLabels[i],
517
- x: x + prop.xaxisLabelsOffsetx,
518
- y: y,
519
- valign: valign,
520
- halign: 'center',
521
- size: prop.xaxisTextSize || prop.textSize,
522
- italic: prop.xaxisTextItalic || prop.textItalic,
523
- font: prop.xaxisTextFont || prop.textFont,
524
- bold: prop.xaxisTextBold || prop.textBold,
525
- color: prop.xaxisTextColor || prop.textColor
526
- });
527
- }
528
- }
529
- }
530
- }
531
- };
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
- //
541
- // Draws an Y axis
542
- //
543
- //@param The chart object
544
- //
545
- RG.SVG.drawYAxis = function (obj)
546
- {
547
- var prop = obj.properties;
548
-
549
- if (prop.yaxis) {
550
-
551
- // The X coordinate that the Y axis is positioned at
552
- if (obj.type === 'hbar') {
553
-
554
- var x = obj.getXCoord(prop.xaxisMin > 0 ? prop.xaxisMin : 0);
555
-
556
- if (prop.xaxisMin < 0 && prop.xaxisMax <= 0) {
557
- x = obj.getXCoord(prop.xaxisMax);
558
- }
559
- } else {
560
- var x = prop.gutterLeft;
561
- }
562
-
563
-
564
- var axis = RG.SVG.create({
565
- svg: obj.svg,
566
- parent: obj.svg.all,
567
- type: 'path',
568
- attr: {
569
- d: 'M{1} {2} L{3} {4}'.format(
570
- x,
571
- prop.gutterTop,
572
- x + 0.001,
573
- obj.height - prop.gutterBottom
574
- ),
575
- stroke: prop.yaxisColor,
576
- fill: prop.yaxisColor,
577
- 'stroke-width': typeof prop.yaxisLinewidth === 'number' ? prop.yaxisLinewidth : 1,
578
- 'shape-rendering': "crispEdges",
579
- 'stroke-linecap': 'square'
580
- }
581
- });
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
- if (obj.type === 'hbar') {
590
-
591
- var height = (obj.graphHeight - prop.vmarginTop - prop.vmarginBottom) / prop.yaxisLabels.length,
592
- y = prop.gutterTop + prop.vmarginTop,
593
- len = prop.yaxisLabels.length,
594
- startX = obj.getXCoord(0) + (prop.xaxisMin < 0 ? prop.yaxisTickmarksLength : 0),
595
- endX = obj.getXCoord(0) - prop.yaxisTickmarksLength;
596
-
597
- if (obj.type === 'hbar' && prop.xaxisMin < 0 && prop.xaxisMax <=0) {
598
- startX = obj.getXCoord(prop.xaxisMax);
599
- endX = obj.getXCoord(prop.xaxisMax) + 5;
600
- }
601
-
602
- //
603
- // Draw the tickmarks
604
- //
605
- if (prop.yaxisTickmarks) {
606
- for (var i=0; i<len; ++i) {
607
-
608
- // Draw the axis
609
- var axis = RG.SVG.create({
610
- svg: obj.svg,
611
- parent: obj.svg.all,
612
- type: 'path',
613
- attr: {
614
- d: 'M{1} {2} L{3} {4}'.format(
615
- startX,
616
- y,
617
- endX,
618
- y + 0.001
619
- ),
620
- stroke: prop.yaxisColor,
621
- 'stroke-width': typeof prop.yaxisLinewidth === 'number' ? prop.yaxisLinewidth : 1,
622
- 'shape-rendering': "crispEdges"
623
- }
624
- });
625
-
626
- y += height;
627
- }
628
-
629
-
630
- // Draw an extra tick if the X axis position is not zero or
631
- // if the xaxis is not being shown
632
- if (prop.xaxis === false) {
633
-
634
- if (obj.type === 'hbar' && prop.xaxisMin <= 0 && prop.xaxisMax < 0) {
635
- var startX = obj.getXCoord(prop.xaxisMax);
636
- var endX = obj.getXCoord(prop.xaxisMax) + prop.yaxisTickmarksLength;
637
-
638
- } else {
639
- var startX = obj.getXCoord(0) - prop.yaxisTickmarksLength;
640
- var endX = obj.getXCoord(0) + (prop.xaxisMin < 0 ? prop.yaxisTickmarksLength : 0);
641
- }
642
-
643
- var axis = RG.SVG.create({
644
- svg: obj.svg,
645
- parent: obj.svg.all,
646
- type: 'path',
647
- attr: {
648
- d: 'M{1} {2} L{3} {4}'.format(
649
- startX,
650
- obj.height - prop.gutterBottom - parseFloat(prop.vmarginBottom),
651
-
652
- endX,
653
- obj.height - prop.gutterBottom - parseFloat(prop.vmarginBottom) - 0.001
654
- ),
655
- stroke: obj.properties.yaxisColor,
656
- 'stroke-width': typeof prop.yaxisLinewidth === 'number' ? prop.yaxisLinewidth : 1,
657
- 'shape-rendering': "crispEdges"
658
- }
659
- });
660
- }
661
- }
662
-
663
- //
664
- // Bar, Line etc types of chart
665
- //
666
- } else {
667
-
668
- var height = obj.graphHeight / prop.yaxisLabelsCount,
669
- y = prop.gutterTop,
670
- len = prop.yaxisLabelsCount,
671
- startX = prop.gutterLeft,
672
- endX = prop.gutterLeft - prop.yaxisTickmarksLength;
673
-
674
- //
675
- // Draw the tickmarks
676
- //
677
- if (prop.yaxisTickmarks) {
678
- for (var i=0; i<len; ++i) {
679
-
680
- // Draw the axis
681
- var axis = RG.SVG.create({
682
- svg: obj.svg,
683
- parent: obj.svg.all,
684
- type: 'path',
685
- attr: {
686
- d: 'M{1} {2} L{3} {4}'.format(
687
- startX,
688
- y,
689
- endX,
690
- y + 0.001
691
- ),
692
- stroke: prop.yaxisColor,
693
- 'stroke-width': typeof prop.yaxisLinewidth === 'number' ? prop.yaxisLinewidth : 1,
694
- 'shape-rendering': "crispEdges"
695
- }
696
- });
697
-
698
- y += height;
699
- }
700
-
701
-
702
- // Draw an extra tick if the X axis position is not zero or
703
- //if the xaxis is not being shown
704
- if ( (prop.yaxisMin !== 0 || prop.xaxis === false)
705
- && !(obj.scale.min > 0 && obj.scale.max > 0) ) {
706
-
707
-
708
- var axis = RG.SVG.create({
709
- svg: obj.svg,
710
- parent: obj.svg.all,
711
- type: 'path',
712
- attr: {
713
- d: 'M{1} {2} L{3} {4}'.format(
714
- prop.gutterLeft - prop.yaxisTickmarksLength,
715
- obj.height - prop.gutterBottom,
716
- prop.gutterLeft,
717
- obj.height - prop.gutterBottom - 0.001
718
- ),
719
- stroke: prop.yaxisColor,
720
- 'stroke-width': typeof prop.yaxisLinewidth === 'number' ? prop.yaxisLinewidth : 1,
721
- 'shape-rendering': "crispEdges"
722
- }
723
- });
724
- }
725
- }
726
- }
727
- }
728
-
729
-
730
-
731
-
732
-
733
-
734
- //
735
- // Draw the Y axis labels
736
- //
737
- if (prop.yaxisScale) {
738
-
739
- var segment = (obj.height - prop.gutterTop - prop.gutterBottom) / prop.yaxisLabelsCount;
740
-
741
- for (var i=0; i<obj.scale.labels.length; ++i) {
742
-
743
- var y = obj.height - prop.gutterBottom - (segment * i) - segment;
744
-
745
- RG.SVG.text({
746
- object: obj,
747
- parent: obj.svg.all,
748
- text: obj.scale.labels[i],
749
- x: prop.gutterLeft - 7 - (prop.yaxis ? (prop.yaxisTickmarksLength - 3) : 0) + prop.yaxisLabelsOffsetx,
750
- y: y + prop.yaxisLabelsOffsety,
751
- halign: 'right',
752
- valign: 'center',
753
- font: prop.yaxisTextFont || prop.textFont,
754
- size: prop.yaxisTextSize || (typeof prop.textSize === 'number' ? prop.textSize + 'pt' : prop.textSize),
755
- bold: prop.yaxisTextBold || prop.textBold,
756
- italic: prop.yaxisTextItalic || prop.textItalic,
757
- color: prop.yaxisTextColor || prop.textColor
758
- });
759
- }
760
-
761
-
762
-
763
-
764
- //
765
- // Add the minimum label
766
- //
767
- var y = obj.height - prop.gutterBottom,
768
- str = (prop.yaxisUnitsPre + prop.yaxisMin.toFixed(prop.yaxisDecimals).replace(/\./, prop.yaxisPoint) + prop.yaxisUnitsPost);
769
-
770
- var text = RG.SVG.text({
771
- object: obj,
772
- parent: obj.svg.all,
773
- text: typeof prop.yaxisFormatter === 'function' ? (prop.yaxisFormatter)(this, prop.yaxisMin) : str,
774
- x: prop.gutterLeft - 7 - (prop.yaxis ? (prop.yaxisTickmarksLength - 3) : 0) + prop.yaxisLabelsOffsetx,
775
- y: y + prop.yaxisLabelsOffsety,
776
- halign: 'right',
777
- valign: 'center',
778
- font: prop.yaxisTextFont || prop.textFont,
779
- size: prop.yaxisTextSize || (typeof prop.textSize === 'number' ? prop.textSize + 'pt' : prop.textSize),
780
- bold: prop.yaxisTextBold || prop.textBold,
781
- italic: prop.yaxisTextItalic || prop.textItalic,
782
- color: prop.yaxisTextColor || prop.textColor
783
- });
784
-
785
-
786
- //
787
- // Draw Y axis labels (eg when specific labels are defined or
788
- //the chart is an HBar
789
- //
790
- } else if (prop.yaxisLabels && prop.yaxisLabels.length) {
791
-
792
- for (var i=0; i<prop.yaxisLabels.length; ++i) {
793
-
794
- var segment = (obj.graphHeight - (prop.vmarginTop || 0) - (prop.vmarginBottom || 0) ) / prop.yaxisLabels.length,
795
- y = prop.gutterTop + (prop.vmarginTop || 0) + (segment * i) + (segment / 2) + prop.yaxisLabelsOffsety,
796
- x = prop.gutterLeft - 7 /*- (prop.yaxis ? (prop.yaxisTickmarksLength) : 0)*/ - (prop.yaxisLinewidth || 1) + prop.yaxisLabelsOffsetx,
797
- halign = 'right';
798
-
799
- // HBar labels
800
- if (obj.type === 'hbar' && obj.scale.min < obj.scale.max && obj.scale.max <= 0) {
801
- halign = 'left';
802
- x = obj.width - prop.gutterRight + 7 + prop.yaxisLabelsOffsetx;
803
-
804
- // HBar labels
805
- } else if (obj.type === 'hbar' && !prop.yaxisLabelsSpecific) {
806
- var segment = (obj.graphHeight - (prop.vmarginTop || 0) - (prop.vmarginBottom || 0) ) / (prop.yaxisLabels.length);
807
- y = prop.gutterTop + (prop.vmarginTop || 0) + (segment * i) + (segment / 2) + prop.yaxisLabelsOffsetx;
808
-
809
- // Specific scale
810
- } else {
811
- var segment = (obj.graphHeight - (prop.vmarginTop || 0) - (prop.vmarginBottom || 0) ) / (prop.yaxisLabels.length - 1);
812
- y = obj.height - prop.gutterBottom - (segment * i) + prop.yaxisLabelsOffsetx;
813
- }
814
-
815
- var text = RG.SVG.text({
816
- object: obj,
817
- parent: obj.svg.all,
818
- text: prop.yaxisLabels[i] ? prop.yaxisLabels[i] : '',
819
- x: x,
820
- y: y,
821
- halign: halign,
822
- valign: 'center',
823
- font: prop.yaxisTextFont || prop.textFont,
824
- size: prop.yaxisTextSize || (typeof prop.textSize === 'number' ? prop.textSize + 'pt' : prop.textSize),
825
- bold: prop.yaxisTextBold || prop.textBold,
826
- italic: prop.yaxisTextItalic || prop.textItalic,
827
- color: prop.yaxisTextColor || prop.textColor
828
- });
829
- }
830
- }
831
- };
832
-
833
-
834
-
835
-
836
-
837
-
838
-
839
-
840
- //
841
- // Draws the background
842
- //
843
- //@param The chart object
844
- //
845
- RG.SVG.drawBackground = function (obj)
846
- {
847
- var prop = obj.properties;
848
-
849
- // Set these properties so that if it doesn't exist things don't fail
850
- if (typeof prop.variant3dOffsetx !== 'number') prop.variant3dOffsetx = 0;
851
- if (typeof prop.variant3dOffsety !== 'number') prop.variant3dOffsety = 0;
852
-
853
-
854
-
855
-
856
- if (prop.backgroundColor) {
857
- RG.SVG.create({
858
- svg: obj.svg,
859
- parent: obj.svg.all,
860
- type: 'rect',
861
- attr: {
862
- x: -1 + prop.variant3dOffsetx,
863
- y: -1 - prop.variant3dOffsety,
864
- width: parseFloat(obj.svg.getAttribute('width')) + 2,
865
- height: parseFloat(obj.svg.getAttribute('height')) + 2,
866
- fill: prop.backgroundColor
867
- }
868
- });
869
- }
870
-
871
- // Render a background image
872
- // <image xlink:href="firefox.jpg" x="0" y="0" height="50px" width="50px"/>
873
- if (prop.backgroundImage) {
874
-
875
- var attr = {
876
- 'xlink:href': prop.backgroundImage,
877
- //preserveAspectRatio: 'xMidYMid slice',
878
- preserveAspectRatio: prop.backgroundImageAspect || 'none',
879
- x: prop.gutterLeft,
880
- y: prop.gutterTop
881
- };
882
-
883
- if (prop.backgroundImageStretch) {
884
-
885
- attr.x = prop.gutterLeft + prop.variant3dOffsetx;
886
- attr.y = prop.gutterTop + prop.variant3dOffsety;
887
- attr.width = obj.width - prop.gutterLeft - prop.gutterRight;
888
- attr.height = obj.height - prop.gutterTop - prop.gutterBottom;
889
-
890
- } else {
891
-
892
- if (typeof prop.backgroundImageX === 'number') {
893
- attr.x = prop.backgroundImageX + prop.variant3dOffsetx;
894
- }
895
-
896
- if (typeof prop.backgroundImageY === 'number') {
897
- attr.y = prop.backgroundImageY + prop.variant3dOffsety;
898
- }
899
-
900
- if (typeof prop.backgroundImageW === 'number') {
901
- attr.width = prop.backgroundImageW;
902
- }
903
-
904
- if (typeof prop.backgroundImageH === 'number') {
905
- attr.height = prop.backgroundImageH;
906
- }
907
- }
908
-
909
- //
910
- // Account for the chart being 3d
911
- //
912
- if (prop.variant === '3d') {
913
- attr.x += prop.variant3dOffsetx;
914
- attr.y -= prop.variant3dOffsety;
915
- }
916
-
917
-
918
-
919
- var img = RG.SVG.create({
920
- svg: obj.svg,
921
- parent: obj.svg.all,
922
- type: 'image',
923
- attr: attr,
924
- style: {
925
- opacity: typeof prop.backgroundImageOpacity === 'number' ? prop.backgroundImageOpacity : 1
926
- }
927
- });
928
- }
929
-
930
- if (prop .backgroundGrid) {
931
-
932
- var parts = [];
933
-
934
-
935
-
936
- // Add the horizontal lines to the path
937
- if (prop.backgroundGridHlines) {
938
-
939
- var count = typeof prop.backgroundGridHlinesCount === 'number' ? prop.backgroundGridHlinesCount : (obj.type === 'hbar' ? (prop.yaxisLabels.length || obj.data.length || 5) : prop.yaxisLabelsCount);
940
-
941
- for (var i=0; i<count; ++i) {
942
-
943
- parts.push('M{1} {2} L{3} {4}'.format(
944
- prop.gutterLeft + prop.variant3dOffsetx,
945
- prop.gutterTop + (obj.graphHeight / count) * i - prop.variant3dOffsety,
946
- obj.width - prop.gutterRight + prop.variant3dOffsetx,
947
- prop.gutterTop + (obj.graphHeight / count) * i - prop.variant3dOffsety
948
- ));
949
- }
950
-
951
- // Add an extra background grid line to the path - this its
952
- // underneath the X axis and shows up if its not there.
953
- parts.push('M{1} {2} L{3} {4}'.format(
954
- prop.gutterLeft + prop.variant3dOffsetx,
955
- obj.height - prop.gutterBottom - prop.variant3dOffsety,
956
- obj.width - prop.gutterRight + prop.variant3dOffsetx,
957
- obj.height - prop.gutterBottom - prop.variant3dOffsety
958
- ));
959
- }
960
-
961
-
962
-
963
- // Add the vertical lines to the path
964
- if (prop.backgroundGridVlines) {
965
-
966
- if (obj.type === 'line' && RG.SVG.isArray(obj.data[0])) {
967
- var len = obj.data[0].length;
968
- } else if (obj.type === 'hbar') {
969
- var len = prop.xaxisLabelsCount || 10;
970
- } else if (obj.type === 'scatter') {
971
- var len = (prop.xaxisLabels && prop.xaxisLabels.length) || 10;
972
- } else {
973
- var len = obj.data.length;
974
- }
975
-
976
- var count = typeof prop.backgroundGridVlinesCount === 'number' ? prop.backgroundGridVlinesCount : len;
977
-
978
- if (prop.xaxisLabelsPosition === 'edge') {
979
- count--;
980
- }
981
-
982
- for (var i=0; i<=count; ++i) {
983
- parts.push('M{1} {2} L{3} {4}'.format(
984
- prop.gutterLeft + ((obj.graphWidth / count) * i) + prop.variant3dOffsetx,
985
- prop.gutterTop - prop.variant3dOffsety,
986
- prop.gutterLeft + ((obj.graphWidth / count) * i) + prop.variant3dOffsetx,
987
- obj.height - prop.gutterBottom - prop.variant3dOffsety
988
- ));
989
- }
990
- }
991
-
992
-
993
-
994
-
995
-
996
- // Add the box around the grid
997
- if (prop.backgroundGridBorder) {
998
- parts.push('M{1} {2} L{3} {4} L{5} {6} L{7} {8} z'.format(
999
-
1000
- prop.gutterLeft + prop.variant3dOffsetx,
1001
- prop.gutterTop - prop.variant3dOffsety,
1002
-
1003
- obj.width - prop.gutterRight + prop.variant3dOffsetx,
1004
- prop.gutterTop - prop.variant3dOffsety,
1005
-
1006
- obj.width - prop.gutterRight + prop.variant3dOffsetx,
1007
- obj.height - prop.gutterBottom - prop.variant3dOffsety,
1008
-
1009
- prop.gutterLeft + prop.variant3dOffsetx,
1010
- obj.height - prop.gutterBottom - prop.variant3dOffsety
1011
- ));
1012
- }
1013
-
1014
-
1015
-
1016
- // Now draw the path
1017
- var grid = RG.SVG.create({
1018
- svg: obj.svg,
1019
- parent: obj.svg.all,
1020
- type: 'path',
1021
- attr: {
1022
- d: parts.join(' '),
1023
- stroke: prop.backgroundGridColor,
1024
- fill: 'rgba(0,0,0,0)',
1025
- 'stroke-width': prop.backgroundGridLinewidth,
1026
- 'shape-rendering': "crispEdges"
1027
- }
1028
- });
1029
-
1030
- }
1031
-
1032
-
1033
-
1034
- // Draw the title and subtitle
1035
- RG.SVG.drawTitle(obj);
1036
- };
1037
-
1038
-
1039
-
1040
-
1041
-
1042
-
1043
-
1044
-
1045
- /**
1046
- * Returns true/false as to whether the given variable is null or not
1047
- *
1048
- * @param mixed arg The argument to check
1049
- */
1050
- RG.SVG.isNull = function (arg)
1051
- {
1052
- // must BE DOUBLE EQUALS - NOT TRIPLE
1053
- if (arg == null || typeof arg === 'object' && !arg) {
1054
- return true;
1055
- }
1056
-
1057
- return false;
1058
- };
1059
-
1060
-
1061
-
1062
-
1063
-
1064
-
1065
-
1066
-
1067
- /**
1068
- * Returns an appropriate scale. The return value is actualy an object consisting of:
1069
- * scale.max
1070
- * scale.min
1071
- * scale.scale
1072
- *
1073
- * @param obj object The graph object
1074
- * @param prop object An object consisting of configuration properties
1075
- * @return object An object containg scale information
1076
- */
1077
- RG.SVG.getScale = function (opt)
1078
- {
1079
- var obj = opt.object,
1080
- prop = obj.properties,
1081
- numlabels = opt.numlabels,
1082
- unitsPre = opt.unitsPre,
1083
- unitsPost = opt.unitsPost,
1084
- max = Number(opt.max),
1085
- min = Number(opt.min),
1086
- strict = opt.strict,
1087
- decimals = Number(opt.decimals),
1088
- point = opt.point,
1089
- thousand = opt.thousand,
1090
- originalMax = max,
1091
- round = opt.round,
1092
- scale = {max:1,labels:[],values:[]},
1093
- formatter = opt.formatter;
1094
-
1095
-
1096
- /**
1097
- * Special case for 0
1098
- *
1099
- * ** Must be first **
1100
- */
1101
-
1102
- if (max === 0 && min === 0) {
1103
-
1104
- var max = 1;
1105
-
1106
- for (var i=0; i<numlabels; ++i) {
1107
-
1108
- var label = ((((max - min) / numlabels) * (i + 1)) + min).toFixed(decimals);
1109
-
1110
- scale.labels.push(unitsPre + label + unitsPost);
1111
- scale.values.push(parseFloat(label))
1112
- }
1113
-
1114
- /**
1115
- * Manually do decimals
1116
- */
1117
- } else if (max <= 1 && !strict) {
1118
-
1119
- var arr = [
1120
- 1,0.5,
1121
- 0.10,0.05,
1122
- 0.010,0.005,
1123
- 0.0010,0.0005,
1124
- 0.00010,0.00005,
1125
- 0.000010,0.000005,
1126
- 0.0000010,0.0000005,
1127
- 0.00000010,0.00000005,
1128
- 0.000000010,0.000000005,
1129
- 0.0000000010,0.0000000005,
1130
- 0.00000000010,0.00000000005,
1131
- 0.000000000010,0.000000000005,
1132
- 0.0000000000010,0.0000000000005
1133
- ], vals = [];
1134
-
1135
-
1136
-
1137
- for (var i=0; i<arr.length; ++i) {
1138
- if (max > arr[i]) {
1139
- i--;
1140
- break;
1141
- }
1142
- }
1143
-
1144
-
1145
- scale.max = arr[i]
1146
- scale.labels = [];
1147
- scale.values = [];
1148
-
1149
-
1150
- for (var j=0; j<numlabels; ++j) {
1151
-
1152
- var value = ((((arr[i] - min) / numlabels) * (j + 1)) + min).toFixed(decimals);
1153
-
1154
- scale.values.push(value);
1155
- scale.labels.push(RG.SVG.numberFormat({
1156
- object: obj,
1157
- num: value,
1158
- prepend: unitsPre,
1159
- append: unitsPost,
1160
- point: prop.yaxisPoint,
1161
- thousand: prop.yaxisThousand,
1162
- formatter: formatter
1163
- }));
1164
- }
1165
-
1166
-
1167
-
1168
-
1169
- } else if (!strict) {
1170
-
1171
- /**
1172
- * Now comes the scale handling for integer values
1173
- */
1174
-
1175
- // This accomodates decimals by rounding the max up to the next integer
1176
- max = ma.ceil(max);
1177
-
1178
- var interval = ma.pow(10, ma.max(1, Number(String(Number(max) - Number(min)).length - 1)) );
1179
- var topValue = interval;
1180
-
1181
- while (topValue < max) {
1182
- topValue += (interval / 2);
1183
- }
1184
-
1185
- // Handles cases where the max is (for example) 50.5
1186
- if (Number(originalMax) > Number(topValue)) {
1187
- topValue += (interval / 2);
1188
- }
1189
-
1190
- // Custom if the max is greater than 5 and less than 10
1191
- if (max <= 10) {
1192
- topValue = (Number(originalMax) <= 5 ? 5 : 10);
1193
- }
1194
-
1195
-
1196
- // Added 02/11/2010 to create "nicer" scales
1197
- if (obj && typeof(round) == 'boolean' && round) {
1198
- topValue = 10 * interval;
1199
- }
1200
-
1201
- scale.max = topValue;
1202
-
1203
-
1204
- for (var i=0; i<numlabels; ++i) {
1205
-
1206
- var label = RG.SVG.numberFormat({
1207
- object: obj,
1208
- num: ((((i+1) / numlabels) * (topValue - min)) + min).toFixed(decimals),
1209
- prepend: unitsPre,
1210
- append: unitsPost,
1211
- point: point,
1212
- thousand: thousand,
1213
- formatter: formatter
1214
- });
1215
-
1216
- scale.labels.push(label);
1217
- scale.values.push(((((i+1) / numlabels) * (topValue - min)) + min).toFixed(decimals));
1218
- }
1219
-
1220
- } else if (typeof max === 'number' && strict) {
1221
-
1222
- /**
1223
- * ymax is set and also strict
1224
- */
1225
- for (var i=0; i<numlabels; ++i) {
1226
-
1227
- scale.labels.push(RG.SVG.numberFormat({
1228
- object: obj,
1229
- formatter: formatter,
1230
- num: ((((i+1) / numlabels) * (max - min)) + min).toFixed(decimals),
1231
- prepend: unitsPre,
1232
- append: unitsPost,
1233
- point: point,
1234
- thousand: thousand
1235
- }));
1236
-
1237
-
1238
- scale.values.push(
1239
- ((((i+1) / numlabels) * (max - min)) + min).toFixed(decimals)
1240
- );
1241
- }
1242
-
1243
- // ???
1244
- scale.max = max;
1245
- }
1246
-
1247
-
1248
- scale.unitsPre = unitsPre;
1249
- scale.unitsPost = unitsPost;
1250
- scale.point = point;
1251
- scale.decimals = decimals;
1252
- scale.thousand = thousand;
1253
- scale.numlabels = numlabels;
1254
- scale.round = Boolean(round);
1255
- scale.min = min;
1256
-
1257
- //
1258
- // Convert all of the scale values to numbers
1259
- //
1260
- for (var i=0; i<scale.values.length; ++i) {
1261
- scale.values[i] = parseFloat(scale.values[i]);
1262
- }
1263
-
1264
- return scale;
1265
- };
1266
-
1267
-
1268
-
1269
-
1270
-
1271
-
1272
-
1273
-
1274
- /**
1275
- * Pads/fills the array
1276
- *
1277
- * @param array arr The array
1278
- * @param int len The length to pad the array to
1279
- * @param mixed The value to use to pad the array (optional)
1280
- */
1281
- RG.SVG.arrayFill =
1282
- RG.SVG.arrayPad = function (opt)
1283
- {
1284
- var arr = opt.array,
1285
- len = opt.length,
1286
- value = (opt.value ? opt.value : null);
1287
-
1288
- if (arr.length < len) {
1289
- for (var i=arr.length; i<len; i+=1) {
1290
- arr[i] = value;
1291
- }
1292
- }
1293
-
1294
- return arr;
1295
- };
1296
-
1297
-
1298
-
1299
-
1300
-
1301
-
1302
-
1303
-
1304
- /**
1305
- * An array sum function
1306
- *
1307
- * @param array arr The array to calculate the total of
1308
- * @return int The summed total of the arrays elements
1309
- */
1310
- RG.SVG.arraySum = function (arr)
1311
- {
1312
- // Allow integers
1313
- if (typeof arr === 'number') {
1314
- return arr;
1315
- }
1316
-
1317
- // Account for null
1318
- if (RG.SVG.isNull(arr)) {
1319
- return 0;
1320
- }
1321
-
1322
- var i, sum, len = arr.length;
1323
-
1324
- for(i=0,sum=0;i<len;sum+=arr[i++]);
1325
-
1326
- return sum;
1327
- };
1328
-
1329
-
1330
-
1331
-
1332
-
1333
-
1334
-
1335
-
1336
- /**
1337
- * Returns the maximum numeric value which is in an array. This function IS NOT
1338
- * recursive
1339
- *
1340
- * @param array arr The array (can also be a number, in which case it's returned as-is)
1341
- * @param int Whether to ignore signs (ie negative/positive)
1342
- * @return int The maximum value in the array
1343
- */
1344
- RG.SVG.arrayMax = function (arr)
1345
- {
1346
- var max = null
1347
-
1348
- if (typeof arr === 'number') {
1349
- return arr;
1350
- }
1351
-
1352
- if (RG.SVG.isNull(arr)) {
1353
- return 0;
1354
- }
1355
-
1356
- for (var i=0,len=arr.length; i<len; ++i) {
1357
- if (typeof arr[i] === 'number') {
1358
-
1359
- var val = arguments[1] ? ma.abs(arr[i]) : arr[i];
1360
-
1361
- if (typeof max === 'number') {
1362
- max = ma.max(max, val);
1363
- } else {
1364
- max = val;
1365
- }
1366
- }
1367
- }
1368
-
1369
- return max;
1370
- };
1371
-
1372
-
1373
-
1374
-
1375
-
1376
-
1377
-
1378
-
1379
- /**
1380
- * Returns the minimum numeric value which is in an array
1381
- *
1382
- * @param array arr The array (can also be a number, in which case it's returned as-is)
1383
- * @param int Whether to ignore signs (ie negative/positive)
1384
- * @return int The minimum value in the array
1385
- */
1386
- RG.SVG.arrayMin = function (arr)
1387
- {
1388
- var max = null,
1389
- min = null,
1390
- ma = Math;
1391
-
1392
- if (typeof arr === 'number') {
1393
- return arr;
1394
- }
1395
-
1396
- if (RG.SVG.isNull(arr)) {
1397
- return 0;
1398
- }
1399
-
1400
- for (var i=0,len=arr.length; i<len; ++i) {
1401
- if (typeof arr[i] === 'number') {
1402
-
1403
- var val = arguments[1] ? ma.abs(arr[i]) : arr[i];
1404
-
1405
- if (typeof min === 'number') {
1406
- min = ma.min(min, val);
1407
- } else {
1408
- min = val;
1409
- }
1410
- }
1411
- }
1412
-
1413
- return min;
1414
- };
1415
-
1416
-
1417
-
1418
-
1419
-
1420
-
1421
-
1422
-
1423
- /**
1424
- * Returns the maximum value which is in an array
1425
- *
1426
- * @param array arr The array
1427
- * @param int len The length to pad the array to
1428
- * @param mixed The value to use to pad the array (optional)
1429
- */
1430
- RG.SVG.arrayPad = function (arr, len)
1431
- {
1432
- if (arr.length < len) {
1433
- var val = arguments[2] ? arguments[2] : null;
1434
-
1435
- for (var i=arr.length; i<len; i+=1) {
1436
- arr[i] = val;
1437
- }
1438
- }
1439
-
1440
- return arr;
1441
- };
1442
-
1443
-
1444
-
1445
-
1446
-
1447
-
1448
-
1449
-
1450
- /**
1451
- * An array sum function
1452
- *
1453
- * @param array arr The array to calculate the total of
1454
- * @return int The summed total of the arrays elements
1455
- */
1456
- RG.SVG.arraySum = function (arr)
1457
- {
1458
- // Allow integers
1459
- if (typeof arr === 'number') {
1460
- return arr;
1461
- }
1462
-
1463
- // Account for null
1464
- if (RG.SVG.isNull(arr)) {
1465
- return 0;
1466
- }
1467
-
1468
- var i, sum, len = arr.length;
1469
-
1470
- for(i=0,sum=0;i<len;sum+=arr[i++]);
1471
-
1472
- return sum;
1473
- };
1474
-
1475
-
1476
-
1477
-
1478
-
1479
-
1480
-
1481
-
1482
- /**
1483
- * Takes any number of arguments and adds them to one big linear array
1484
- * which is then returned
1485
- *
1486
- * @param ... mixed The data to linearise. You can strings, booleans, numbers or arrays
1487
- */
1488
- RG.SVG.arrayLinearize = function ()
1489
- {
1490
- var arr = [],
1491
- args = arguments
1492
-
1493
- for (var i=0,len=args.length; i<len; ++i) {
1494
-
1495
- if (typeof args[i] === 'object' && args[i]) {
1496
- for (var j=0,len2=args[i].length; j<len2; ++j) {
1497
- var sub = RG.SVG.arrayLinearize(args[i][j]);
1498
-
1499
- for (var k=0,len3=sub.length; k<len3; ++k) {
1500
- arr.push(sub[k]);
1501
- }
1502
- }
1503
- } else {
1504
- arr.push(args[i]);
1505
- }
1506
- }
1507
-
1508
- return arr;
1509
- };
1510
-
1511
-
1512
-
1513
-
1514
-
1515
-
1516
-
1517
-
1518
- /**
1519
- * Takes one off the front of the given array and returns the new array.
1520
- *
1521
- * @param array arr The array from which to take one off the front of array
1522
- *
1523
- * @return array The new array
1524
- */
1525
- RG.SVG.arrayShift = function(arr)
1526
- {
1527
- var ret = [];
1528
-
1529
- for(var i=1,len=arr.length; i<len; ++i) {
1530
- ret.push(arr[i]);
1531
- }
1532
-
1533
- return ret;
1534
- };
1535
-
1536
-
1537
-
1538
-
1539
-
1540
-
1541
-
1542
-
1543
- /**
1544
- * Reverses the order of an array
1545
- *
1546
- * @param array arr The array to reverse
1547
- */
1548
- RG.SVG.arrayReverse = function (arr)
1549
- {
1550
- if (!arr) {
1551
- return;
1552
- }
1553
-
1554
- var newarr=[];
1555
-
1556
- for(var i=arr.length - 1; i>=0; i-=1) {
1557
- newarr.push(arr[i]);
1558
- }
1559
-
1560
- return newarr;
1561
- };
1562
-
1563
-
1564
-
1565
-
1566
-
1567
-
1568
-
1569
-
1570
- /**
1571
- * Makes a clone of an object
1572
- *
1573
- * @param obj val The object to clone
1574
- */
1575
- RG.SVG.arrayClone = function (obj)
1576
- {
1577
- if(obj === null || typeof obj !== 'object') {
1578
- return obj;
1579
- }
1580
-
1581
- if (RG.SVG.isArray(obj)) {
1582
-
1583
- var temp = [];
1584
-
1585
- for (var i=0,len=obj.length;i<len; ++i) {
1586
-
1587
- if (typeof obj[i] === 'number') {
1588
- temp[i] = (function (arg) {return Number(arg);})(obj[i]);
1589
-
1590
- } else if (typeof obj[i] === 'string') {
1591
- temp[i] = (function (arg) {return String(arg);})(obj[i]);
1592
-
1593
- } else if (typeof obj[i] === 'function') {
1594
- temp[i] = obj[i];
1595
-
1596
- } else {
1597
- temp[i] = RG.SVG.arrayClone(obj[i]);
1598
- }
1599
- }
1600
- } else if (typeof obj === 'object') {
1601
-
1602
- var temp = {};
1603
-
1604
- for (var i in obj) {
1605
- if (typeof i === 'string') {
1606
- temp[i] = obj[i];
1607
- }
1608
- }
1609
- }
1610
-
1611
- return temp;
1612
- };
1613
-
1614
-
1615
-
1616
-
1617
-
1618
-
1619
-
1620
-
1621
- //
1622
- // Converts an the truthy values to falsey values and vice-versa
1623
- //
1624
- RG.SVG.arrayInvert = function (arr)
1625
- {
1626
- for (var i=0,len=arr.length; i<len; ++i) {
1627
- arr[i] = !arr[i];
1628
- }
1629
-
1630
- return arr;
1631
- };
1632
-
1633
-
1634
-
1635
-
1636
-
1637
-
1638
-
1639
-
1640
- //
1641
- // An array_trim function that removes the empty elements off
1642
- //both ends
1643
- //
1644
- RG.SVG.arrayTrim = function (arr)
1645
- {
1646
- var out = [], content = false;
1647
-
1648
- // Trim the start
1649
- for (var i=0; i<arr.length; i++) {
1650
-
1651
- if (arr[i]) {
1652
- content = true;
1653
- }
1654
-
1655
- if (content) {
1656
- out.push(arr[i]);
1657
- }
1658
- }
1659
-
1660
- // Reverse the array and trim the start again
1661
- out = RG.SVG.arrayReverse(out);
1662
-
1663
- var out2 = [], content = false ;
1664
- for (var i=0; i<out.length; i++) {
1665
-
1666
- if (out[i]) {
1667
- content = true;
1668
- }
1669
-
1670
- if (content) {
1671
- out2.push(out[i]);
1672
- }
1673
- }
1674
-
1675
- // Now reverse the array and return it
1676
- out2 = RG.SVG.arrayReverse(out2);
1677
-
1678
- return out2;
1679
- };
1680
-
1681
-
1682
-
1683
-
1684
-
1685
-
1686
-
1687
-
1688
- /**
1689
- * Determines if the given object is an array or not
1690
- *
1691
- * @param mixed obj The variable to test
1692
- */
1693
- RG.SVG.isArray = function (obj)
1694
- {
1695
- if (obj && obj.constructor) {
1696
- var pos = obj.constructor.toString().indexOf('Array');
1697
- } else {
1698
- return false;
1699
- }
1700
-
1701
- return obj != null &&
1702
- typeof pos === 'number' &&
1703
- pos > 0 &&
1704
- pos < 20;
1705
- };
1706
-
1707
-
1708
-
1709
-
1710
-
1711
-
1712
-
1713
-
1714
- /**
1715
- * Returns the absolute value of a number. You can also pass in an
1716
- * array and it will run the abs() function on each element. It
1717
- * operates recursively so sub-arrays are also traversed.
1718
- *
1719
- * @param array arr The number or array to work on
1720
- */
1721
- RG.SVG.abs = function (value)
1722
- {
1723
- if (typeof value === 'string') {
1724
- value = parseFloat(value) || 0;
1725
- }
1726
-
1727
- if (typeof value === 'number') {
1728
- return ma.abs(value);
1729
- }
1730
-
1731
- if (typeof value === 'object') {
1732
- for (i in value) {
1733
- if ( typeof i === 'string'
1734
- || typeof i === 'number'
1735
- || typeof i === 'object') {
1736
-
1737
- value[i] = RG.SVG.abs(value[i]);
1738
- }
1739
- }
1740
-
1741
- return value;
1742
- }
1743
-
1744
- return 0;
1745
- };
1746
-
1747
-
1748
-
1749
-
1750
-
1751
-
1752
-
1753
-
1754
- //
1755
- // Formats a number with thousand seperators so it's easier to read
1756
- //
1757
- // @param opt object The options to the function
1758
- //
1759
- RG.SVG.numberFormat = function (opt)
1760
- {
1761
- var obj = opt.object,
1762
- prepend = opt.prepend ? String(opt.prepend) : '',
1763
- append = opt.append ? String(opt.append) : '',
1764
- output = '',
1765
- decimal_seperator = typeof opt.point === 'string' ? opt.point : '.',
1766
- thousand_seperator = typeof opt.thousand === 'string' ? opt.thousand : ',',
1767
- num = opt.num;
1768
-
1769
- RegExp.$1 = '';
1770
-
1771
- if (typeof opt.formatter === 'function') {
1772
- return opt.formatter(obj, num);
1773
- }
1774
-
1775
- // Ignore the preformatted version of "1e-2"
1776
- if (String(num).indexOf('e') > 0) {
1777
- return String(prepend + String(num) + append);
1778
- }
1779
-
1780
- // We need then number as a string
1781
- num = String(num);
1782
-
1783
- // Take off the decimal part - we re-append it later
1784
- if (num.indexOf('.') > 0) {
1785
- var tmp = num;
1786
- num = num.replace(/\.(.*)/, ''); // The front part of the number
1787
- decimal = tmp.replace(/(.*)\.(.*)/, '$2'); // The decimal part of the number
1788
- } else {
1789
- decimal = '';
1790
- }
1791
-
1792
- // Thousand seperator
1793
- //var seperator = arguments[1] ? String(arguments[1]) : ',';
1794
- var seperator = thousand_seperator;
1795
-
1796
- /**
1797
- * Work backwards adding the thousand seperators
1798
- */
1799
- var foundPoint;
1800
- for (i=(num.length - 1),j=0; i>=0; j++,i--) {
1801
- var character = num.charAt(i);
1802
-
1803
- if ( j % 3 == 0 && j != 0) {
1804
- output += seperator;
1805
- }
1806
-
1807
- /**
1808
- * Build the output
1809
- */
1810
- output += character;
1811
- }
1812
-
1813
- /**
1814
- * Now need to reverse the string
1815
- */
1816
- var rev = output;
1817
- output = '';
1818
- for (i=(rev.length - 1); i>=0; i--) {
1819
- output += rev.charAt(i);
1820
- }
1821
-
1822
- // Tidy up
1823
- //output = output.replace(/^-,/, '-');
1824
- if (output.indexOf('-' + thousand_seperator) == 0) {
1825
- output = '-' + output.substr(('-' + thousand_seperator).length);
1826
- }
1827
-
1828
- // Reappend the decimal
1829
- if (decimal.length) {
1830
- output = output + decimal_seperator + decimal;
1831
- decimal = '';
1832
- RegExp.$1 = '';
1833
- }
1834
-
1835
- // Minor bugette
1836
- if (output.charAt(0) == '-') {
1837
- output = output.replace(/-/, '');
1838
- prepend = '-' + prepend;
1839
- }
1840
-
1841
- return prepend + output + append;
1842
- };
1843
-
1844
-
1845
-
1846
-
1847
-
1848
-
1849
-
1850
-
1851
- //
1852
- // A function that adds text to the chart
1853
- //
1854
- RG.SVG.text = function (opt)
1855
- {
1856
- var obj = opt.object,
1857
- parent = opt.parent || opt.object.svg.all,
1858
- size = opt.size,
1859
- bold = opt.bold,
1860
- font = opt.font,
1861
- italic = opt.italic,
1862
- halign = opt.halign,
1863
- valign = opt.valign,
1864
- str = opt.text,
1865
- x = opt.x,
1866
- y = opt.y,
1867
- color = opt.color ? opt.color : 'black',
1868
- background = opt.background || null,
1869
- padding = opt.padding || 0;
1870
-
1871
-
1872
-
1873
-
1874
-
1875
- // Horizontal alignment
1876
- if (halign === 'right') {
1877
- halign = 'end';
1878
- } else if (halign === 'center' || halign === 'middle') {
1879
- halign = 'middle';
1880
- } else {
1881
- halign = 'start';
1882
- }
1883
-
1884
- // Vertical alignment
1885
- if (valign === 'top') {
1886
- valign = 'hanging';
1887
- } else if (valign === 'center' || valign === 'middle') {
1888
- valign = 'central';
1889
- valign = 'middle';
1890
- } else {
1891
- valign = 'bottom';
1892
- }
1893
-
1894
-
1895
- var text = RG.SVG.create({
1896
- svg: obj.svg,
1897
- parent: opt.parent,
1898
- type: 'text',
1899
- attr: {
1900
- fill: color,
1901
- x: x,
1902
- y: y,
1903
- 'font-size': typeof size === 'number' ? size + 'pt' : size,
1904
- 'font-weight': bold ? 900 : 100,
1905
- 'font-family': font ? font : 'sans-serif',
1906
- 'font-style': italic ? 'italic' : 'normal',
1907
- 'text-anchor': halign,
1908
- 'dominant-baseline': valign
1909
- }
1910
- });
1911
-
1912
- var textNode = document.createTextNode(str);
1913
- text.appendChild(textNode);
1914
-
1915
-
1916
-
1917
- //
1918
- // Add a background color if specified
1919
- //
1920
- if (typeof background === 'string') {
1921
-
1922
- var bbox = text.getBBox(),
1923
- rect = RG.SVG.create({
1924
- svg: obj.svg,
1925
- parent: opt.parent,
1926
- type: 'rect',
1927
- attr: {
1928
- x: bbox.x - padding,
1929
- y: bbox.y - padding,
1930
- width: bbox.width + (padding * 2),
1931
- height: bbox.height + (padding * 2),
1932
- fill: background
1933
- }
1934
- });
1935
-
1936
- parent.insertBefore(rect, text);
1937
- }
1938
-
1939
-
1940
-
1941
- if (RG.SVG.ISIE && (valign === 'hanging') ) {
1942
- text.setAttribute('y', y + (text.scrollHeight / 2));
1943
-
1944
- } else if (RG.SVG.ISIE && valign === 'middle') {
1945
- text.setAttribute('y', y + (text.scrollHeight / 3));
1946
- }
1947
-
1948
-
1949
-
1950
-
1951
- if (RG.SVG.ISFF) {
1952
- Y = y + (text.scrollHeight / 3);
1953
- }
1954
-
1955
- return text;
1956
- };
1957
-
1958
-
1959
-
1960
-
1961
-
1962
-
1963
-
1964
-
1965
- //
1966
- // Creates a UID that is applied to the object
1967
- //
1968
- RG.SVG.createUID = function ()
1969
- {
1970
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)
1971
- {
1972
- var r = ma.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
1973
- return v.toString(16);
1974
- });
1975
- };
1976
-
1977
-
1978
-
1979
-
1980
-
1981
-
1982
-
1983
-
1984
- //
1985
- // Determines if the SVG DIV container is fixed
1986
- //
1987
- RG.SVG.isFixed = function (svg)
1988
- {
1989
- var obj = svg.parentNode,
1990
- i = 0;
1991
-
1992
- while (obj && obj.tagName.toLowerCase() != 'body' && i < 99) {
1993
-
1994
- if (obj.style.position === 'fixed') {
1995
- return obj;
1996
- }
1997
-
1998
- obj = obj.offsetParent;
1999
- }
2000
-
2001
- return false;
2002
- };
2003
-
2004
-
2005
-
2006
-
2007
-
2008
-
2009
-
2010
-
2011
- /**
2012
- * Sets an object in the RGraph registry
2013
- *
2014
- * @param string name The name of the value to set
2015
- */
2016
- RG.SVG.REG.set = function (name, value)
2017
- {
2018
- RG.SVG.REG.store[name] = value;
2019
-
2020
- return value;
2021
- };
2022
-
2023
-
2024
-
2025
-
2026
-
2027
-
2028
-
2029
-
2030
- /**
2031
- * Gets an object from the RGraph registry
2032
- *
2033
- * @param string name The name of the value to fetch
2034
- */
2035
- RG.SVG.REG.get = function (name)
2036
- {
2037
- return RG.SVG.REG.store[name];
2038
- };
2039
-
2040
-
2041
-
2042
-
2043
-
2044
-
2045
-
2046
-
2047
- /**
2048
- * Removes white-space from the start aqnd end of a string
2049
- *
2050
- * @param string str The string to trim
2051
- */
2052
- RG.SVG.trim = function (str)
2053
- {
2054
- return RG.SVG.ltrim(RG.SVG.rtrim(str));
2055
- };
2056
-
2057
-
2058
-
2059
-
2060
-
2061
-
2062
-
2063
-
2064
- /**
2065
- * Trims the white-space from the start of a string
2066
- *
2067
- * @param string str The string to trim
2068
- */
2069
- RG.SVG.ltrim = function (str)
2070
- {
2071
- return str.replace(/^(\s|\0)+/, '');
2072
- };
2073
-
2074
-
2075
-
2076
-
2077
-
2078
-
2079
-
2080
-
2081
- /**
2082
- * Trims the white-space off of the end of a string
2083
- *
2084
- * @param string str The string to trim
2085
- */
2086
- RG.SVG.rtrim = function (str)
2087
- {
2088
- return str.replace(/(\s|\0)+$/, '');
2089
- };
2090
-
2091
-
2092
-
2093
-
2094
-
2095
-
2096
-
2097
-
2098
- //
2099
- // Hides the currently shown tooltip
2100
- //
2101
- RG.SVG.hideTooltip = function ()
2102
- {
2103
- var tooltip = RG.SVG.REG.get('tooltip');
2104
-
2105
- if (tooltip && tooltip.parentNode /*&& (!uid || uid == tooltip.__canvas__.uid)*/) {
2106
- tooltip.parentNode.removeChild(tooltip);
2107
- tooltip.style.display = 'none';
2108
- tooltip.style.visibility = 'hidden';
2109
- RG.SVG.REG.set('tooltip', null);
2110
- }
2111
-
2112
- if (tooltip && tooltip.__object__) {
2113
- RG.SVG.removeHighlight(tooltip.__object__);
2114
- }
2115
- };
2116
-
2117
-
2118
-
2119
-
2120
-
2121
-
2122
-
2123
-
2124
- //
2125
- // Creates a shadow
2126
- //
2127
- RG.SVG.setShadow = function (options)
2128
- {
2129
- var obj = options.object,
2130
- offsetx = options.offsetx || 0,
2131
- offsety = options.offsety || 0,
2132
- blur = options.blur || 0,
2133
- opacity = options.opacity || 0,
2134
- id = options.id;
2135
-
2136
- var filter = RG.SVG.create({
2137
- svg: obj.svg,
2138
- parent: obj.svg.defs,
2139
- type: 'filter',
2140
- attr: {
2141
- id: id,
2142
- width: "130%",
2143
- height: "130%"
2144
- }
2145
- });
2146
-
2147
- RG.SVG.create({
2148
- svg: obj.svg,
2149
- parent: filter,
2150
- type: 'feOffset',
2151
- attr: {
2152
- result: 'offOut',
2153
- 'in': 'SourceGraphic',
2154
- dx: offsetx,
2155
- dy: offsety
2156
- }
2157
- });
2158
-
2159
- RG.SVG.create({
2160
- svg: obj.svg,
2161
- parent: filter,
2162
- type: 'feColorMatrix',
2163
- attr: {
2164
- result: 'matrixOut',
2165
- 'in': 'offOut',
2166
- type: 'matrix',
2167
- values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 {1} 0'.format(
2168
- opacity
2169
- )
2170
- }
2171
- });
2172
-
2173
- RG.SVG.create({
2174
- svg: obj.svg,
2175
- parent: filter,
2176
- type: 'feGaussianBlur',
2177
- attr: {
2178
- result: 'blurOut',
2179
- 'in': 'matrixOut',
2180
- stdDeviation: blur
2181
- }
2182
- });
2183
-
2184
- RG.SVG.create({
2185
- svg: obj.svg,
2186
- parent: filter,
2187
- type: 'feBlend',
2188
- attr: {
2189
- 'in': 'SourceGraphic',
2190
- 'in2': 'blurOut',
2191
- mode: 'normal'
2192
- }
2193
- });
2194
- };
2195
-
2196
-
2197
-
2198
-
2199
-
2200
-
2201
-
2202
-
2203
- /**
2204
- * Takes a sequential index and returns the group/index variation of it. Eg if you have a
2205
- * sequential index from a grouped bar chart this function can be used to convert that into
2206
- * an appropriate group/index combination
2207
- *
2208
- * @param nindex number The sequential index
2209
- * @param data array The original data (which is grouped)
2210
- * @return The group/index information
2211
- */
2212
- RG.SVG.sequentialIndexToGrouped = function (index, data)
2213
- {
2214
- var group = 0,
2215
- grouped_index = 0;
2216
-
2217
- while (--index >= 0) {
2218
-
2219
- if (RG.SVG.isNull(data[group])) {
2220
- group++;
2221
- grouped_index = 0;
2222
- continue;
2223
- }
2224
-
2225
- // Allow for numbers as well as arrays in the dataset
2226
- if (typeof data[group] == 'number') {
2227
- group++
2228
- grouped_index = 0;
2229
- continue;
2230
- }
2231
-
2232
-
2233
- grouped_index++;
2234
-
2235
- if (grouped_index >= data[group].length) {
2236
- group++;
2237
- grouped_index = 0;
2238
- }
2239
- }
2240
-
2241
- return [group, grouped_index];
2242
- };
2243
-
2244
-
2245
-
2246
-
2247
-
2248
-
2249
-
2250
-
2251
- //
2252
- // This function converts coordinates into the type understood by
2253
- // SVG for drawing arcs
2254
- //
2255
- RG.SVG.TRIG.toCartesian = function (options)
2256
- {
2257
- return {
2258
- x: options.cx + (options.r * ma.cos(options.angle)),
2259
- y: options.cy + (options.r * ma.sin(options.angle))
2260
- };
2261
- };
2262
-
2263
-
2264
-
2265
-
2266
-
2267
-
2268
-
2269
-
2270
- //
2271
- // Gets a path that is usable by the SVG A path command
2272
- //
2273
- // @patam object options The options/arg to the function
2274
- //
2275
- // NB ** Still used by the Pie chart and the semi-circular Meter **
2276
- //
2277
- RG.SVG.TRIG.getArcPath = function (options)
2278
- {
2279
- //
2280
- // Make circles start at the top instead of the right hand side
2281
- //
2282
- options.start -= 1.57;
2283
- options.end -= 1.57;
2284
-
2285
- var start = RG.SVG.TRIG.toCartesian({
2286
- cx: options.cx,
2287
- cy: options.cy,
2288
- r: options.r,
2289
- angle: options.start}
2290
- );
2291
-
2292
- var end = RG.SVG.TRIG.toCartesian({
2293
- cx: options.cx,
2294
- cy: options.cy,
2295
- r: options.r,
2296
- angle: options.end
2297
- });
2298
-
2299
- var diff = options.end - options.start;
2300
-
2301
- // Initial values
2302
- var largeArc = '0';
2303
- var sweep = '0';
2304
-
2305
- if (options.anticlockwise && diff > 3.14) {
2306
- largeArc = '0';
2307
- sweep = '0';
2308
- } else if (options.anticlockwise && diff <= 3.14) {
2309
- largeArc = '1';
2310
- sweep = '0';
2311
- } else if (!options.anticlockwise && diff > 3.14) {
2312
- largeArc = '1';
2313
- sweep = '1';
2314
- } else if (!options.anticlockwise && diff <= 3.14) {
2315
- largeArc = '0';
2316
- sweep = '1';
2317
- }
2318
-
2319
- if (options.start > options.end && options.anticlockwise && diff <= 3.14) {
2320
- largeArc = '0';
2321
- sweep = '0';
2322
- }
2323
-
2324
- if (options.start > options.end && options.anticlockwise && diff > 3.14) {
2325
- largeArc = '1';
2326
- sweep = '1';
2327
- }
2328
-
2329
-
2330
- if (typeof options.moveto === 'boolean' && options.moveto === false) {
2331
- var d = [
2332
- "A", options.r, options.r, 0, largeArc, sweep, end.x, end.y
2333
- ];
2334
- } else {
2335
- var d = [
2336
- "M", start.x, start.y,
2337
- "A", options.r, options.r, 0, largeArc, sweep, end.x, end.y
2338
- ];
2339
- }
2340
-
2341
- if (options.array === true) {
2342
- return d;
2343
- } else {
2344
- return d.join(" ");
2345
- }
2346
- };
2347
-
2348
-
2349
-
2350
-
2351
-
2352
-
2353
-
2354
-
2355
- //
2356
- // Gets a path that is usable by the SVG A path command
2357
- //
2358
- // @patam object options The options/arg to the function
2359
- //
2360
- RG.SVG.TRIG.getArcPath2 = function (options)
2361
- {
2362
- //
2363
- // Make circles start at the top instead of the right hand side
2364
- //
2365
- options.start -= 1.57;
2366
- options.end -= 1.57;
2367
-
2368
- var start = RG.SVG.TRIG.toCartesian({
2369
- cx: options.cx,
2370
- cy: options.cy,
2371
- r: options.r,
2372
- angle: options.start
2373
- });
2374
-
2375
- var end = RG.SVG.TRIG.toCartesian({
2376
- cx: options.cx,
2377
- cy: options.cy,
2378
- r: options.r,
2379
- angle: options.end
2380
- });
2381
-
2382
- var diff = ma.abs(options.end - options.start);
2383
-
2384
- // Initial values
2385
- var largeArc = '0';
2386
- var sweep = '0';
2387
-
2388
- //TODO Put various options here for the correct combination of flags to use
2389
- if (!options.anticlockwise) {
2390
- if (diff > RG.SVG.TRIG.PI) {
2391
- largeArc = '1';
2392
- sweep = '1';
2393
- } else {
2394
- largeArc = '0';
2395
- sweep = '1';
2396
- }
2397
- } else {
2398
- if (diff > RG.SVG.TRIG.PI) {
2399
- largeArc = '1';
2400
- sweep = '0';
2401
- } else {
2402
- largeArc = '0';
2403
- sweep = '0';
2404
- }
2405
- }
2406
-
2407
- if (typeof options.lineto === 'boolean' && options.lineto === false) {
2408
- var d = [
2409
- "M", start.x, start.y,
2410
- "A", options.r, options.r, 0, largeArc, sweep, end.x, end.y
2411
- ];
2412
- } else {
2413
- var d = [
2414
- "M", options.cx, options.cy,
2415
- "L", start.x, start.y,
2416
- "A", options.r, options.r, 0, largeArc, sweep, end.x, end.y
2417
- ];
2418
- }
2419
-
2420
- if (options.array === true) {
2421
- return d;
2422
- } else {
2423
- return d.join(" ");
2424
- }
2425
- };
2426
-
2427
-
2428
-
2429
-
2430
-
2431
-
2432
-
2433
-
2434
- //
2435
- // Gets a path that is usable by the SVG A path command
2436
- //
2437
- // @patam object options The options/arg to the function
2438
- //
2439
- RG.SVG.TRIG.getArcPath3 = function (options)
2440
- {
2441
- //
2442
- // Make circles start at the top instead of the right hand side
2443
- //
2444
- options.start -= 1.57;
2445
- options.end -= 1.57;
2446
-
2447
- var start = RG.SVG.TRIG.toCartesian({
2448
- cx: options.cx,
2449
- cy: options.cy,
2450
- r: options.r,
2451
- angle: options.start
2452
- });
2453
-
2454
- var end = RG.SVG.TRIG.toCartesian({
2455
- cx: options.cx,
2456
- cy: options.cy,
2457
- r: options.r,
2458
- angle: options.end
2459
- });
2460
-
2461
- var diff = ma.abs(options.end - options.start);
2462
-
2463
- // Initial values
2464
- var largeArc = '0';
2465
- var sweep = '0';
2466
-
2467
- //TODO Put various options here for the correct combination of flags to use
2468
- if (!options.anticlockwise) {
2469
- if (diff > RG.SVG.TRIG.PI) {
2470
- largeArc = '1';
2471
- sweep = '1';
2472
- } else {
2473
- largeArc = '0';
2474
- sweep = '1';
2475
- }
2476
- } else {
2477
- if (diff > RG.SVG.TRIG.PI) {
2478
- largeArc = '1';
2479
- sweep = '0';
2480
- } else {
2481
- largeArc = '0';
2482
- sweep = '0';
2483
- }
2484
- }
2485
-
2486
- if (typeof options.lineto === 'boolean' && options.lineto === false) {
2487
- var d = [
2488
- "M", start.x, start.y,
2489
- "A", options.r, options.r, 0, largeArc, sweep, end.x, end.y
2490
- ];
2491
- } else {
2492
- var d = [
2493
- "L", start.x, start.y,
2494
- "A", options.r, options.r, 0, largeArc, sweep, end.x, end.y
2495
- ];
2496
- }
2497
-
2498
- if (options.array === true) {
2499
- return d;
2500
- } else {
2501
- return d.join(" ");
2502
- }
2503
- };
2504
-
2505
-
2506
-
2507
-
2508
-
2509
-
2510
-
2511
-
2512
- /**
2513
- * This function gets the end point (X/Y coordinates) of a given radius.
2514
- * You pass it the center X/Y and the radius and this function will return
2515
- * the endpoint X/Y coordinates.
2516
- *
2517
- * @param number cx The center X coord
2518
- * @param number cy The center Y coord
2519
- * @param number r The lrngth of the radius
2520
- */
2521
- RG.SVG.TRIG.getRadiusEndPoint = function (opt)
2522
- {
2523
- // Allow for two arguments style
2524
- if (arguments.length === 1) {
2525
-
2526
- var angle = opt.angle,
2527
- r = opt.r;
2528
-
2529
- } else if (arguments.length === 4) {
2530
-
2531
- var angle = arguments[0],
2532
- r = arguments[1];
2533
- }
2534
-
2535
- var x = ma.cos(angle) * r,
2536
- y = ma.sin(angle) * r;
2537
-
2538
- return [x, y];
2539
- };
2540
-
2541
-
2542
-
2543
-
2544
-
2545
-
2546
-
2547
-
2548
- /**
2549
- * This function draws the title. This function also draws the subtitle.
2550
- */
2551
- RG.SVG.drawTitle = function (obj)
2552
- {
2553
- var prop = obj.properties;
2554
- var valign = 'bottom';
2555
-
2556
- //
2557
- // The Pie chart title should default to being above the centerx
2558
- //
2559
- if (obj.type === 'pie') {
2560
- if (RG.SVG.isNull(prop.titleX)) {
2561
- prop.titleX = obj.centerx;
2562
- prop.titleSubtitleX = obj.centerx;
2563
- }
2564
-
2565
- if (RG.SVG.isNull(prop.titleY)) {
2566
- prop.titleY = obj.centery - obj.radius - 10;
2567
- }
2568
- }
2569
-
2570
-
2571
-
2572
-
2573
-
2574
-
2575
- if (obj.scale && obj.scale.max <= 0 && obj.scale.min < 0 && typeof prop.titleY !== 'number' && obj.type !== 'hbar') {
2576
- prop.titleY = obj.height - prop.gutterBottom + 10;
2577
- var positionBottom = true;
2578
- valign = 'top';
2579
- } else if (typeof prop.titleY !== 'number') {
2580
- var positionBottom = false;
2581
- prop.titleY = prop.gutterTop - 10;
2582
- valign = 'bottom';
2583
-
2584
- // Account for the key
2585
- if (!RG.SVG.isNull(prop.key)) {
2586
- prop.titleY -= (2 * (prop.keyTextSize || prop.textSize));
2587
- }
2588
- }
2589
-
2590
- // If a subtitle is specified move the title up a bit in
2591
- // order to accommodate it
2592
- if (prop.titleSubtitle && typeof prop.titleSubtitleY !== 'number' && !positionBottom) {
2593
- prop.titleY = prop.titleY - (prop.titleSubtitleSize * 1.5);
2594
- }
2595
-
2596
- // Work out the subtitle size
2597
- prop.titleSubTitleSize = prop.titleSubTitleSize || prop.textSize;
2598
-
2599
- // Work out the subtitle Y position
2600
- prop.titleSubtitleY = prop.titleSubtitleY || prop.titleY + 18;
2601
-
2602
- if (positionBottom && typeof prop.titleSubtitleY !== 'number') {
2603
- prop.titleSubtitleY = prop.titleY + 26;
2604
- }
2605
-
2606
-
2607
-
2608
-
2609
-
2610
-
2611
- // Draw the title
2612
- if (prop.title) {
2613
-
2614
- RG.SVG.text({
2615
- object: obj,
2616
- svg: obj.svg,
2617
- parent: obj.svg.all,
2618
- text: prop.title.toString(),
2619
- size: prop.titleSize || (prop.textSize + 4) || 16,
2620
-
2621
- x: typeof prop.titleX === 'number' ? prop.titleX + (prop.variant3dOffsetx || 0) : prop.gutterLeft + (obj.graphWidth / 2) + (prop.variant3dOffsetx || 0),
2622
- y: prop.titleY + (prop.variant3dOffsety || 0),
2623
-
2624
- halign: prop.titleHalign || 'center',
2625
- valign: prop.titleValign || valign,
2626
- color: prop.titleColor || prop.textColor || 'black',
2627
- bold: prop.titleBold || false,
2628
- italic: prop.titleItalic || false,
2629
- font: prop.titleFont || prop.textFont || 'Arial'
2630
- });
2631
- }
2632
-
2633
-
2634
-
2635
- // Draw the subtitle
2636
- if (prop.titleSubtitle) {
2637
- RG.SVG.text({
2638
- object: obj,
2639
- svg: obj.svg,
2640
- parent: obj.svg.all,
2641
- text: prop.titleSubtitle,
2642
- size: prop.titleSubtitleSize,
2643
- x: typeof prop.titleSubtitleX === 'number' ? prop.titleSubtitleX : prop.gutterLeft + (obj.graphWidth / 2) + (prop.variant3dOffsetx || 0),
2644
- y: prop.titleSubtitleY + (prop.variant3dOffsety || 0),
2645
- halign: prop.titleSubtitleHalign || 'center',
2646
- valign: prop.titleSubtitleValign || valign,
2647
- color: prop.titleSubtitleColor || prop.textColor || '#aaa',
2648
- bold: prop.titleSubtitleBold || false,
2649
- italic: prop.titleSubtitleItalic || false,
2650
- font: prop.titleSubtitleFont || prop.textFont || 'Arial'
2651
- });
2652
- }
2653
- };
2654
-
2655
-
2656
-
2657
-
2658
-
2659
-
2660
-
2661
-
2662
- /**
2663
- * Removes white-space from the start and end of a string
2664
- *
2665
- * @param string str The string to trim
2666
- */
2667
- RG.SVG.trim = function (str)
2668
- {
2669
- return RG.SVG.ltrim(RG.SVG.rtrim(str));
2670
- };
2671
-
2672
-
2673
-
2674
-
2675
-
2676
-
2677
-
2678
-
2679
- /**
2680
- * Trims the white-space from the start of a string
2681
- *
2682
- * @param string str The string to trim
2683
- */
2684
- RG.SVG.ltrim = function (str)
2685
- {
2686
- return String(str).replace(/^(\s|\0)+/, '');
2687
- };
2688
-
2689
-
2690
-
2691
-
2692
-
2693
-
2694
-
2695
-
2696
- /**
2697
- * Trims the white-space off of the end of a string
2698
- *
2699
- * @param string str The string to trim
2700
- */
2701
- RG.SVG.rtrim = function (str)
2702
- {
2703
- return String(str).replace(/(\s|\0)+$/, '');
2704
- };
2705
-
2706
-
2707
-
2708
-
2709
-
2710
-
2711
-
2712
-
2713
- /**
2714
- * This parses a single color value
2715
- */
2716
- RG.SVG.parseColorLinear = function (opt)
2717
- {
2718
- var obj = opt.object,
2719
- color = opt.color;
2720
-
2721
- if (!color || typeof color !== 'string') {
2722
- return color;
2723
- }
2724
-
2725
- if (color.match(/^gradient\((.*)\)$/i)) {
2726
-
2727
- var parts = RegExp.$1.split(':'),
2728
- diff = 1 / (parts.length - 1);
2729
-
2730
- if (opt && opt.direction && opt.direction === 'horizontal') {
2731
- var grad = RG.SVG.create({
2732
- type: 'linearGradient',
2733
- parent: obj.svg.defs,
2734
- attr: {
2735
- id: 'RGraph-linear-gradient' + obj.gradientCounter,
2736
- x1: opt.start || 0,
2737
- x2: opt.end || '100%',
2738
- y1: 0,
2739
- y2: 0,
2740
- gradientUnits: "userSpaceOnUse"
2741
- }
2742
- });
2743
-
2744
- } else {
2745
-
2746
- var grad = RG.SVG.create({
2747
- type: 'linearGradient',
2748
- parent: obj.svg.defs,
2749
- attr: {
2750
- id: 'RGraph-linear-gradient' + obj.gradientCounter,
2751
- x1: 0,
2752
- x2: 0,
2753
- y1: opt.start || 0,
2754
- y2: opt.end || '100%',
2755
- gradientUnits: "userSpaceOnUse"
2756
- }
2757
- });
2758
- }
2759
-
2760
- // Add the first color stop
2761
- var stop = RG.SVG.create({
2762
- type: 'stop',
2763
- parent: grad,
2764
- attr: {
2765
- offset: '0%',
2766
- 'stop-color': RG.SVG.trim(parts[0])
2767
- }
2768
- });
2769
-
2770
- // Add the rest of the color stops
2771
- for (var j=1,len=parts.length; j<len; ++j) {
2772
-
2773
- RG.SVG.create({
2774
- type: 'stop',
2775
- parent: grad,
2776
- attr: {
2777
- offset: (j * diff * 100) + '%',
2778
- 'stop-color': RG.SVG.trim(parts[j])
2779
- }
2780
- });
2781
- }
2782
- }
2783
-
2784
- color = grad ? 'url(#RGraph-linear-gradient' + (obj.gradientCounter++) + ')' : color;
2785
-
2786
- return color;
2787
- };
2788
-
2789
-
2790
-
2791
-
2792
-
2793
-
2794
-
2795
-
2796
- /**
2797
- * This parses a single color value
2798
- */
2799
- RG.SVG.parseColorRadial = function (opt)
2800
- {
2801
- var obj = opt.object,
2802
- color = opt.color;
2803
-
2804
- if (!color || typeof color !== 'string') {
2805
- return color;
2806
- }
2807
-
2808
- if (color.match(/^gradient\((.*)\)$/i)) {
2809
-
2810
- var parts = RegExp.$1.split(':'),
2811
- diff = 1 / (parts.length - 1);
2812
-
2813
-
2814
- var grad = RG.SVG.create({
2815
- type: 'radialGradient',
2816
- parent: obj.svg.defs,
2817
- attr: {
2818
- id: 'RGraph-radial-gradient' + obj.gradientCounter,
2819
- gradientUnits: opt.gradientUnits || 'userSpaceOnUse',
2820
- cx: opt.cx || obj.centerx,
2821
- cy: opt.cy || obj.centery,
2822
- fx: opt.fx || obj.centerx,
2823
- fy: opt.fy || obj.centery,
2824
- r: opt.r || obj.radius
2825
- }
2826
- });
2827
-
2828
- // Add the first color stop
2829
- var stop = RG.SVG.create({
2830
- type: 'stop',
2831
- parent: grad,
2832
- attr: {
2833
- offset: '0%',
2834
- 'stop-color': RG.SVG.trim(parts[0])
2835
- }
2836
- });
2837
-
2838
- // Add the rest of the color stops
2839
- for (var j=1,len=parts.length; j<len; ++j) {
2840
-
2841
- RG.SVG.create({
2842
- type: 'stop',
2843
- parent: grad,
2844
- attr: {
2845
- offset: (j * diff * 100) + '%',
2846
- 'stop-color': RG.SVG.trim(parts[j])
2847
- }
2848
- });
2849
- }
2850
- }
2851
-
2852
- color = grad ? 'url(#RGraph-radial-gradient' + (obj.gradientCounter++) + ')' : color;
2853
-
2854
- return color;
2855
- };
2856
-
2857
-
2858
-
2859
-
2860
-
2861
-
2862
-
2863
-
2864
- /**
2865
- * Reset all of the color values to their original values
2866
- *
2867
- * @param object
2868
- */
2869
- RG.SVG.resetColorsToOriginalValues = function (opt)
2870
- {
2871
- var obj = opt.object;
2872
-
2873
- if (obj.originalColors) {
2874
- // Reset the colors to their original values
2875
- for (var j in obj.originalColors) {
2876
- if (typeof j === 'string') {
2877
- obj.properties[j] = RG.SVG.arrayClone(obj.originalColors[j]);
2878
- }
2879
- }
2880
- }
2881
-
2882
- /**
2883
- * If the function is present on the object to reset specific
2884
- * colors - use that
2885
- */
2886
- if (typeof obj.resetColorsToOriginalValues === 'function') {
2887
- obj.resetColorsToOriginalValues();
2888
- }
2889
-
2890
- // Hmmm... Should this be necessary? I don't think it will
2891
- // do any harm to leave it in.
2892
- obj.originalColors = {};
2893
-
2894
-
2895
-
2896
- // Reset the colorsParsed flag so that they're parsed for gradients again
2897
- obj.colorsParsed = false;
2898
-
2899
- // Reset the gradient counter
2900
- obj.gradientCounter = 1;
2901
- };
2902
-
2903
-
2904
-
2905
-
2906
-
2907
-
2908
-
2909
-
2910
- //
2911
- // Clear the SVG tag by deleting all of its
2912
- // child nodes
2913
- //
2914
- // @param object svg The SVG tag (same as what is returned
2915
- // by document.getElementById() )
2916
- //
2917
- RG.SVG.clear = function (svg)
2918
- {
2919
- while (svg.all.lastChild) {
2920
- svg.all.removeChild(svg.all.lastChild);
2921
- }
2922
-
2923
- //while (svg.lastChild) {
2924
- // svg.removeChild(svg.lastChild);
2925
- //}
2926
- };
2927
-
2928
-
2929
-
2930
-
2931
-
2932
-
2933
-
2934
-
2935
- /**
2936
- * Adds an event listener
2937
- *
2938
- * @param object obj The graph object
2939
- * @param string event The name of the event, eg ontooltip
2940
- * @param object func The callback function
2941
- */
2942
- RG.SVG.addCustomEventListener = function (obj, name, func)
2943
- {
2944
- // Initialise the events array if necessary
2945
- if (typeof RG.SVG.events[obj.uid] === 'undefined') {
2946
- RG.SVG.events[obj.uid] = [];
2947
- }
2948
-
2949
- // Prepend "on" if necessary
2950
- if (name.substr(0, 2) !== 'on') {
2951
- name = 'on' + name;
2952
- }
2953
-
2954
- RG.SVG.events[obj.uid].push({
2955
- object: obj,
2956
- event: name,
2957
- func: func
2958
- });
2959
-
2960
- return RG.SVG.events[obj.uid].length - 1;
2961
- };
2962
-
2963
-
2964
-
2965
-
2966
-
2967
-
2968
-
2969
-
2970
- /**
2971
- * Used to fire one of the RGraph custom events
2972
- *
2973
- * @param object obj The graph object that fires the event
2974
- * @param string event The name of the event to fire
2975
- */
2976
- RG.SVG.fireCustomEvent = function (obj, name)
2977
- {
2978
- if (obj && obj.isRGraph) {
2979
-
2980
- var uid = obj.uid;
2981
-
2982
- if ( typeof uid === 'string'
2983
- && typeof RG.SVG.events === 'object'
2984
- && typeof RG.SVG.events[uid] === 'object'
2985
- && RG.SVG.events[uid].length > 0) {
2986
-
2987
- for(var j=0,len=RG.SVG.events[uid].length; j<len; ++j) {
2988
- if (RG.SVG.events[uid][j] && RG.SVG.events[uid][j].event === name) {
2989
- RG.SVG.events[uid][j].func(obj);
2990
- }
2991
- }
2992
- }
2993
- }
2994
- };
2995
-
2996
-
2997
-
2998
-
2999
-
3000
-
3001
-
3002
-
3003
- /**
3004
- * Clears all the custom event listeners that have been registered
3005
- *
3006
- * @param string optional Limits the clearing to this object UID
3007
- */
3008
- RG.SVG.removeAllCustomEventListeners = function ()
3009
- {
3010
- var uid = arguments[0];
3011
-
3012
- if (uid && RG.SVG.events[uid]) {
3013
- RG.SVG.events[uid] = {};
3014
- } else {
3015
- RG.SVG.events = [];
3016
- }
3017
- };
3018
-
3019
-
3020
-
3021
-
3022
-
3023
-
3024
-
3025
-
3026
- /**
3027
- * Clears a particular custom event listener
3028
- *
3029
- * @param object obj The graph object
3030
- * @param number i This is the index that is return by .addCustomEventListener()
3031
- */
3032
- RG.SVG.removeCustomEventListener = function (obj, i)
3033
- {
3034
- if ( typeof RG.SVG.events === 'object'
3035
- && typeof RG.SVG.events[obj.uid] === 'object'
3036
- && typeof RG.SVG.events[obj.uid][i] === 'object') {
3037
-
3038
- RG.SVG.events[obj.uid][i] = null;
3039
- }
3040
- };
3041
-
3042
-
3043
-
3044
-
3045
-
3046
-
3047
-
3048
-
3049
- //
3050
- // Removes the highlight from the chart added by tooltips (possibly others too)
3051
- //
3052
- RG.SVG.removeHighlight = function (obj)
3053
- {
3054
- var highlight = RG.SVG.REG.get('highlight');
3055
-
3056
- if (highlight && RG.SVG.isArray(highlight) && highlight.length) {
3057
- for (var i=0,len=highlight.length; i<len; ++i) {
3058
- if (highlight[i].parentNode) {
3059
- //obj.svg.removeChild(highlight[i]);
3060
- highlight[i].parentNode.removeChild(highlight[i]);
3061
- }
3062
- }
3063
- } else if (highlight && highlight.parentNode) {
3064
- if (obj.type === 'scatter') {
3065
- highlight.setAttribute('fill', 'transparent');
3066
- } else {
3067
- highlight.parentNode.removeChild(highlight);
3068
- }
3069
- }
3070
- };
3071
-
3072
-
3073
-
3074
-
3075
-
3076
-
3077
-
3078
-
3079
- //
3080
- // Removes the highlight from the chart added by tooltips (possibly others too)
3081
- //
3082
- RG.SVG.redraw = function ()
3083
- {
3084
- if (arguments.length === 1) {
3085
-
3086
- var svg = arguments[0];
3087
-
3088
- RG.SVG.clear(svg);
3089
-
3090
- var objects = RG.SVG.OR.get('id:' + svg.parentNode.id);
3091
-
3092
- for (var i=0,len=objects.length; i<len; ++i) {
3093
-
3094
- // Reset the colors to the original values
3095
- RG.SVG.resetColorsToOriginalValues({object: objects[i]});
3096
-
3097
- objects[i].draw();
3098
- }
3099
- } else {
3100
-
3101
- var tags = RG.SVG.OR.tags();
3102
-
3103
- for (var i in tags) {
3104
- RG.SVG.redraw(tags[i]);
3105
- }
3106
- }
3107
- };
3108
-
3109
-
3110
-
3111
-
3112
-
3113
-
3114
-
3115
-
3116
- //
3117
- // A better, more flexible, date parsing function
3118
- //
3119
- //@param string str The string to parse
3120
- //@retutn number A number, as returned by Date.parse()
3121
- //
3122
- RG.SVG.parseDate = function (str)
3123
- {
3124
- var d = new Date();
3125
-
3126
- // Initialise the default values
3127
- var defaults = {
3128
- seconds: '00',
3129
- minutes: '00',
3130
- hours: '00',
3131
- date: d.getDate(),
3132
- month: d.getMonth() + 1,
3133
- year: d.getFullYear()
3134
- };
3135
-
3136
- // Create the months array for turning textual months back to numbers
3137
- var months = ['january','february','march','april','may','june','july','august','september','october','november','december'],
3138
- months_regex = months.join('|');
3139
-
3140
- for (var i=0; i<months.length; ++i) {
3141
- months[months[i]] = i;
3142
- months[months[i].substring(0,3)] = i;
3143
- months_regex = months_regex + '|' + months[i].substring(0,3);
3144
- }
3145
-
3146
- // These are the seperators allowable for d/m/y and y/m/d dates
3147
- // (Its part of a regexp so the position of the square brackets
3148
- // is crucial)
3149
- var sep = '[-./_=+~#:;,]+';
3150
-
3151
-
3152
- // Tokenise the string
3153
- var tokens = str.split(/ +/);
3154
-
3155
- // Loop through each token checking what is is
3156
- for (var i=0,len=tokens.length; i<len; ++i) {
3157
- if (tokens[i]) {
3158
-
3159
- // Year
3160
- if (tokens[i].match(/^\d\d\d\d$/)) {
3161
- defaults.year = tokens[i];
3162
- }
3163
-
3164
- // Month
3165
- var res = isMonth(tokens[i]);
3166
- if (typeof res === 'number') {
3167
- defaults.month = res + 1; // Months are zero indexed
3168
- }
3169
-
3170
- // Date
3171
- if (tokens[i].match(/^\d?\d(?:st|nd|rd|th)?$/)) {
3172
- defaults.date = parseInt(tokens[i]);
3173
- }
3174
-
3175
- // Time
3176
- if (tokens[i].match(/^(\d\d):(\d\d)(?:(\d\d))?$/)) {
3177
- defaults.hours = parseInt(RegExp.$1);
3178
- defaults.minutes = parseInt(RegExp.$2);
3179
-
3180
- if (RegExp.$3) {
3181
- defaults.seconds = parseInt(RegExp.$3);
3182
- }
3183
- }
3184
-
3185
- // Dateformat: XXXX-XX-XX
3186
- if (tokens[i].match(new RegExp('^(\\d\\d\\d\\d)' + sep + '(\\d\\d)' + sep + '(\\d\\d)$', 'i'))) {
3187
- defaults.date = parseInt(RegExp.$3);
3188
- defaults.month = parseInt(RegExp.$2);
3189
- defaults.year = parseInt(RegExp.$1);
3190
- }
3191
-
3192
- // Dateformat: XX-XX-XXXX
3193
- if (tokens[i].match(new RegExp('^(\\d\\d)' + sep + '(\\d\\d)' + sep + '(\\d\\d\\d\\d)$','i') )) {
3194
- defaults.date = parseInt(RegExp.$1);
3195
- defaults.month = parseInt(RegExp.$2);
3196
- defaults.year = parseInt(RegExp.$3);
3197
- }
3198
- }
3199
- }
3200
-
3201
- // Now put the defaults into a format thats recognised by Date.parse()
3202
- str = '{1}/{2}/{3} {4}:{5}:{6}'.format(
3203
- defaults.year,
3204
- String(defaults.month).length === 1 ? '0' + (defaults.month) : defaults.month,
3205
- String(defaults.date).length === 1 ? '0' + (defaults.date) : defaults.date,
3206
- String(defaults.hours).length === 1 ? '0' + (defaults.hours) : defaults.hours,
3207
- String(defaults.minutes).length === 1 ? '0' + (defaults.minutes) : defaults.minutes,
3208
- String(defaults.seconds).length === 1 ? '0' + (defaults.seconds) : defaults.seconds
3209
- );
3210
-
3211
- return Date.parse(str);
3212
-
3213
- //
3214
- // Support functions
3215
- //
3216
- function isMonth(str)
3217
- {
3218
- var res = str.toLowerCase().match(months_regex);
3219
-
3220
- return res ? months[res[0]] : false;
3221
- }
3222
- };
3223
-
3224
-
3225
-
3226
-
3227
-
3228
-
3229
-
3230
-
3231
- // The ObjectRegistry add function
3232
- RG.SVG.OR.add = function (obj)
3233
- {
3234
- RG.SVG.OR.objects.push(obj);
3235
-
3236
- return obj;
3237
- };
3238
-
3239
-
3240
-
3241
-
3242
-
3243
-
3244
-
3245
-
3246
- // The ObjectRegistry function that returns all of the objects. Th argument
3247
- // can aither be:
3248
- //
3249
- // o omitted All of the registered objects are returned
3250
- // o id:XXX All of the objects on that SVG tag are returned
3251
- // o type:XXX All the objects of that type are returned
3252
- //
3253
- RG.SVG.OR.get = function ()
3254
- {
3255
- // Fetch objects that are on a particular SVG tag
3256
- if (typeof arguments[0] === 'string' && arguments[0].substr(0, 3).toLowerCase() === 'id:') {
3257
-
3258
- var ret = [];
3259
-
3260
- for (var i=0; i<RG.SVG.OR.objects.length; ++i) {
3261
- if (RG.SVG.OR.objects[i].id === arguments[0].substr(3)) {
3262
- ret.push(RG.SVG.OR.objects[i]);
3263
- }
3264
- }
3265
-
3266
- return ret;
3267
- }
3268
-
3269
-
3270
- // Fetch objects that are of a particular type
3271
- //
3272
- // TODO Allow multiple types to be specified
3273
- if (typeof arguments[0] === 'string' && arguments[0].substr(0, 4).toLowerCase() === 'type') {
3274
-
3275
- var ret = [];
3276
-
3277
- for (var i=0; i<RG.SVG.OR.objects.length; ++i) {
3278
- if (RG.SVG.OR.objects[i].type === arguments[0].substr(5)) {
3279
- ret.push(RG.SVG.OR.objects[i]);
3280
- }
3281
- }
3282
-
3283
- return ret;
3284
- }
3285
-
3286
-
3287
- // Fetch an object that has a specific UID
3288
- if (typeof arguments[0] === 'string' && arguments[0].substr(0, 3).toLowerCase() === 'uid') {
3289
-
3290
- var ret = [];
3291
-
3292
- for (var i=0; i<RG.SVG.OR.objects.length; ++i) {
3293
- if (RG.SVG.OR.objects[i].uid === arguments[0].substr(4)) {
3294
- ret.push(RG.SVG.OR.objects[i]);
3295
- }
3296
- }
3297
-
3298
- return ret;
3299
- }
3300
-
3301
- return RG.SVG.OR.objects;
3302
- };
3303
-
3304
-
3305
-
3306
-
3307
-
3308
-
3309
-
3310
-
3311
- // The ObjectRegistry function that returns all of the registeredt SVG tags
3312
- //
3313
- RG.SVG.OR.tags = function ()
3314
- {
3315
- var tags = [];
3316
-
3317
- for (var i=0; i<RG.SVG.OR.objects.length; ++i) {
3318
- if (!tags[RG.SVG.OR.objects[i].svg.parentNode.id]) {
3319
- tags[RG.SVG.OR.objects[i].svg.parentNode.id] = RG.SVG.OR.objects[i].svg;
3320
- }
3321
- }
3322
-
3323
- return tags;
3324
- };
3325
-
3326
-
3327
-
3328
-
3329
-
3330
-
3331
-
3332
-
3333
- //
3334
- // This function returns a two element array of the SVG x/y position in
3335
- // relation to the page
3336
- //
3337
- // @param object svg
3338
- //
3339
- RG.SVG.getSVGXY = function (svg)
3340
- {
3341
- var x = 0,
3342
- y = 0,
3343
- el = svg.parentNode; // !!!
3344
-
3345
- do {
3346
-
3347
- x += el.offsetLeft;
3348
- y += el.offsetTop;
3349
-
3350
- // Account for tables in webkit
3351
- if (el.tagName.toLowerCase() == 'table' && (RG.SVG.ISCHROME || RG.SVG.ISSAFARI)) {
3352
- x += parseInt(el.border) || 0;
3353
- y += parseInt(el.border) || 0;
3354
- }
3355
-
3356
- el = el.offsetParent;
3357
-
3358
- } while (el && el.tagName && el.tagName.toLowerCase() != 'body');
3359
-
3360
-
3361
- var paddingLeft = svg.style.paddingLeft ? parseInt(svg.style.paddingLeft) : 0,
3362
- paddingTop = svg.style.paddingTop ? parseInt(svg.style.paddingTop) : 0,
3363
- borderLeft = svg.style.borderLeftWidth ? parseInt(svg.style.borderLeftWidth) : 0,
3364
- borderTop = svg.style.borderTopWidth ? parseInt(svg.style.borderTopWidth) : 0;
3365
-
3366
- if (navigator.userAgent.indexOf('Firefox') > 0) {
3367
- x += parseInt(document.body.style.borderLeftWidth) || 0;
3368
- y += parseInt(document.body.style.borderTopWidth) || 0;
3369
- }
3370
-
3371
- return [x + paddingLeft + borderLeft, y + paddingTop + borderTop];
3372
- };
3373
-
3374
-
3375
-
3376
-
3377
-
3378
-
3379
-
3380
-
3381
- //
3382
- // This function is a compatibility wrapper around
3383
- // the requestAnimationFrame function.
3384
- //
3385
- // @param function func The function to give to the
3386
- // requestAnimationFrame function
3387
- //
3388
- RG.SVG.FX.update = function (func)
3389
- {
3390
- win.requestAnimationFrame =
3391
- win.requestAnimationFrame ||
3392
- win.webkitRequestAnimationFrame ||
3393
- win.msRequestAnimationFrame ||
3394
- win.mozRequestAnimationFrame ||
3395
- (function (func){setTimeout(func, 16.666);});
3396
-
3397
- win.requestAnimationFrame(func);
3398
- };
3399
-
3400
-
3401
-
3402
-
3403
-
3404
-
3405
-
3406
-
3407
- /**
3408
- * This function returns an easing multiplier for effects so they eas out towards the
3409
- * end of the effect.
3410
- *
3411
- * @param number frames The total number of frames
3412
- * @param number frame The frame number
3413
- */
3414
- RG.SVG.FX.getEasingMultiplier = function (frames, frame)
3415
- {
3416
- var multiplier = ma.pow(ma.sin((frame / frames) * RG.SVG.TRIG.HALFPI), 3);
3417
-
3418
- return multiplier;
3419
- };
3420
-
3421
-
3422
-
3423
-
3424
-
3425
-
3426
-
3427
-
3428
- /**
3429
- * Measures text by creating a DIV in the document and adding the relevant
3430
- * text to it, then checking the .offsetWidth and .offsetHeight.
3431
- *
3432
- * @param object opt An object containing the following:
3433
- * o text( string) The text to measure
3434
- * o bold (bool) Whether the text is bold or not
3435
- * o font (string) The font to use
3436
- * o size (number) The size of the text (in pts)
3437
- *
3438
- * @return array A two element array of the width and height of the text
3439
- */
3440
- RG.SVG.measureText = function (opt)
3441
- {
3442
- //text, bold, font, size
3443
- var text = opt.text || '',
3444
- bold = opt.bold || false,
3445
- font = opt.font || 'Arial',
3446
- size = opt.size || 10,
3447
- str = text + ':' + bold + ':' + font + ':' + size;
3448
-
3449
- // Add the sizes to the cache as adding DOM elements is costly and causes slow downs
3450
- if (typeof RG.SVG.measuretext_cache === 'undefined') {
3451
- RG.SVG.measuretext_cache = [];
3452
- }
3453
-
3454
- if (typeof RG.SVG.measuretext_cache == 'object' && RG.SVG.measuretext_cache[str]) {
3455
-
3456
- return RG.SVG.measuretext_cache[str];
3457
- }
3458
-
3459
- if (!RG.SVG.measuretext_cache['text-span']) {
3460
- var span = document.createElement('SPAN');
3461
- span.style.position = 'absolute';
3462
- //span.style.backgroundColor = 'red';
3463
- span.style.padding = 0;
3464
- span.style.display = 'inline';
3465
- span.style.top = '-200px';
3466
- span.style.left = '-200px';
3467
- span.style.lineHeight = '1em';
3468
- document.body.appendChild(span);
3469
-
3470
- // Now store the newly created DIV
3471
- RG.SVG.measuretext_cache['text-span'] = span;
3472
-
3473
- } else if (RG.SVG.measuretext_cache['text-span']) {
3474
- var span = RG.SVG.measuretext_cache['text-span'];
3475
- }
3476
-
3477
- span.innerHTML = text.replace(/\r\n/g, '<br />');
3478
- span.style.fontFamily = font;
3479
- span.style.fontWeight = bold ? 'bold' : 'normal';
3480
- span.style.fontSize = size + 'pt';
3481
-
3482
- var sizes = [span.offsetWidth, span.offsetHeight];
3483
-
3484
- //document.body.removeChild(span);
3485
- RG.SVG.measuretext_cache[str] = sizes;
3486
-
3487
- return sizes;
3488
- };
3489
-
3490
-
3491
-
3492
-
3493
-
3494
-
3495
-
3496
-
3497
- /**
3498
- * This function converts an array of strings to an array of numbers. Its used by the meter/gauge
3499
- * style charts so that if you want you can pass in a string. It supports various formats:
3500
- *
3501
- * '45.2'
3502
- * '-45.2'
3503
- * ['45.2']
3504
- * ['-45.2']
3505
- * '45.2,45.2,45.2' // A CSV style string
3506
- *
3507
- * @param number frames The string or array to parse
3508
- */
3509
- RG.SVG.stringsToNumbers = function (str)
3510
- {
3511
- // An optional seperator to use intead of a comma
3512
- var sep = arguments[1] || ',';
3513
-
3514
-
3515
- // If it's already a number just return it
3516
- if (typeof str === 'number') {
3517
- return str;
3518
- }
3519
-
3520
-
3521
-
3522
-
3523
-
3524
- if (typeof str === 'string') {
3525
- if (str.indexOf(sep) != -1) {
3526
- str = str.split(sep);
3527
- } else {
3528
- str = parseFloat(str);
3529
- }
3530
- }
3531
-
3532
-
3533
-
3534
-
3535
-
3536
- if (typeof str === 'object') {
3537
- for (var i=0,len=str.length; i<len; i+=1) {
3538
- str[i] = parseFloat(str[i]);
3539
- }
3540
- }
3541
-
3542
- return str;
3543
- };
3544
-
3545
-
3546
-
3547
-
3548
-
3549
-
3550
-
3551
-
3552
- // This function allows for numbers that are given as a +/- adjustment
3553
- RG.SVG.getAdjustedNumber = function (opt)
3554
- {
3555
- var value = opt.value,
3556
- prop = opt.prop;
3557
-
3558
- if (typeof prop === 'string' && match(/^(\+|-)([0-9.]+)/)) {
3559
- if (RegExp.$1 === '+') {
3560
- value += parseFloat(RegExp.$2);
3561
- } else if (RegExp.$1 === '-') {
3562
- value -= parseFloat(RegExp.$2);
3563
- }
3564
- }
3565
-
3566
- return value;
3567
- };
3568
-
3569
-
3570
-
3571
-
3572
-
3573
-
3574
-
3575
-
3576
- //
3577
- // Adds the attribution link to the chart in the
3578
- // (by default) bottom right corner
3579
- //
3580
- //@param ibject obj The chart object
3581
- //
3582
- RG.SVG.attribution = function (obj)
3583
- {
3584
- return;
3585
- /*
3586
- var prop = obj.properties;
3587
-
3588
- if (!prop.attribution && typeof prop.attribution !== 'undefined') {
3589
- return false;
3590
- }
3591
-
3592
-
3593
- // Create the A tag
3594
- var a = RG.SVG.create({
3595
- svg: obj.svg,
3596
- parent: obj.svg.all,
3597
- type: 'a',
3598
- attr: {
3599
- rel: 'nofollow',
3600
- target: '_blank',
3601
- 'xlink:href': prop.attributionHref || 'http://www.rgraph.net/'
3602
- }
3603
- });
3604
-
3605
-
3606
-
3607
- // Work out the X/Y coords
3608
- var x = parseFloat(obj.svg.getAttribute('width')) - 2,
3609
- y = parseFloat(obj.svg.getAttribute('height')) - 2;
3610
-
3611
- // Allow the X coord to be a +/- string
3612
- if (typeof prop.attributionX === 'string') {
3613
- x += parseFloat(prop.attributionX);
3614
- } else if (typeof prop.attributionX === 'number') {
3615
- x = parseFloat(prop.attributionX);
3616
- }
3617
-
3618
- // Allow the Y coord to be a +/- string|
3619
- if (typeof prop.attributionY === 'string') {
3620
- y += parseFloat(prop.attributionY);
3621
- } else if (typeof prop.attributionY === 'number') {
3622
- y = parseFloat(prop.attributionY);
3623
- }
3624
-
3625
- // Add a text tag to the attribution A tag
3626
- var text = RG.SVG.text({
3627
- object: obj,
3628
- parent: a,
3629
- text: typeof prop.attributionText === 'string' ? prop.attributionText : 'JavaScript charts with RGraph',
3630
- x: x,
3631
- y: y,
3632
- halign: prop.attributionHalign || 'right',
3633
- valign: prop.attributionValign || 'bottom',
3634
- font: prop.attributionFont || 'sans-serif',
3635
- size: prop.attributionSize || 7,
3636
- color: prop.attributionColor || 'gray',
3637
- italic: prop.attributionItalic,
3638
- bold: prop.attributionBold
3639
- });
3640
- */
3641
- };
3642
-
3643
-
3644
-
3645
-
3646
-
3647
-
3648
-
3649
-
3650
- /**
3651
- * Parse a gradient and returns the various parts
3652
- *
3653
- * @param string str The gradient string
3654
- */
3655
- RG.SVG.parseGradient = function (str)
3656
- {
3657
- };
3658
-
3659
-
3660
-
3661
-
3662
-
3663
-
3664
-
3665
-
3666
- /**
3667
- * Generates a random number between the minimum and maximum
3668
- *
3669
- * @param number min The minimum value
3670
- * @param number max The maximum value
3671
- * @param number OPTIONAL Number of decimal places
3672
- */
3673
- RG.SVG.random = function (opt)
3674
- {
3675
- var min = opt.min,
3676
- max = opt.max,
3677
- dp = opt.dp || opt.decimals || 0,
3678
- r = ma.random();
3679
-
3680
- return Number((((max - min) * r) + min).toFixed(dp));
3681
- };
3682
-
3683
-
3684
-
3685
-
3686
-
3687
-
3688
-
3689
-
3690
- /**
3691
- * Fill an array full of random numbers
3692
- */
3693
- RG.SVG.arrayRand =
3694
- RG.SVG.arrayRandom =
3695
- RG.SVG.random.array = function (opt)
3696
- {
3697
- var num = opt.num,
3698
- min = opt.min,
3699
- max = opt.max,
3700
- dp = opt.dp || opt.decimals || 0;
3701
-
3702
- for(var i=0,arr=[]; i<num; i+=1) {
3703
- arr.push(RG.SVG.random({min: min, max: max, dp: dp}));
3704
- }
3705
-
3706
- return arr;
3707
- };
3708
-
3709
-
3710
-
3711
-
3712
-
3713
-
3714
-
3715
-
3716
- //
3717
- // This function is called by each objects setter so that common BC
3718
- // and adjustments are centralised. And there's less typing for me too.
3719
- //
3720
- // @param object opt An object of options to the function, which are:
3721
- // object: The chart object
3722
- // name: The name of the config parameter
3723
- // value: The value thats being set
3724
- //
3725
- RG.SVG.commonSetter = function (opt)
3726
- {
3727
- var obj = opt.object,
3728
- name = opt.name,
3729
- value = opt.value;
3730
-
3731
- // The default event for tooltips is click
3732
- if (name === 'tooltipsEvent'&& value !== 'click' && value !== 'mousemove') {
3733
- value = 'click';
3734
- }
3735
-
3736
- return {
3737
- name: name,
3738
- value: value
3739
- };
3740
- };
3741
-
3742
-
3743
-
3744
-
3745
-
3746
-
3747
-
3748
-
3749
- //
3750
- // Generates logs for... log charts
3751
- //
3752
- // @param object opt The options:
3753
- // o num The number
3754
- // o base The base
3755
- //
3756
- RG.SVG.log = function (opt)
3757
- {
3758
- var num = opt.num,
3759
- base = opt.base;
3760
-
3761
- return ma.log(num) / (base ? ma.log(base) : 1);
3762
- };
3763
-
3764
-
3765
-
3766
-
3767
-
3768
-
3769
-
3770
-
3771
- RG.SVG.donut = function (opt)
3772
- {
3773
- var arcPath1 = RG.SVG.TRIG.getArcPath3({
3774
- cx: opt.cx,
3775
- cy: opt.cy,
3776
- r: opt.outerRadius,
3777
- start: 0,
3778
- end: RG.SVG.TRIG.TWOPI,
3779
- anticlockwise: false,
3780
- lineto: false
3781
- });
3782
-
3783
- var arcPath2 = RG.SVG.TRIG.getArcPath3({
3784
- cx: opt.cx,
3785
- cy: opt.cy,
3786
- r: opt.innerRadius,
3787
- start: RG.SVG.TRIG.TWOPI,
3788
- end: 0,
3789
- anticlockwise: true,
3790
- lineto: false
3791
- });
3792
-
3793
- //
3794
- // Create the red circle
3795
- //
3796
- var path = RG.SVG.create({
3797
- svg: opt.svg,
3798
- type: 'path',
3799
- attr: {
3800
- d: arcPath1 + arcPath2,
3801
- stroke: opt.stroke,
3802
- fill: opt.fill
3803
- }
3804
- });
3805
-
3806
- return path;
3807
- };
3808
-
3809
-
3810
-
3811
-
3812
-
3813
-
3814
-
3815
-
3816
- //
3817
- // This is here so that if the tooltip library has not
3818
- // been included, this function will show an alert
3819
- //informing the user
3820
- //
3821
- if (typeof RG.SVG.tooltip !== 'function') {
3822
- RG.SVG.tooltip = function ()
3823
- {
3824
- $a('The tooltip library has not been included!');
3825
- };
3826
- }
3827
-
3828
-
3829
-
3830
-
3831
-
3832
-
3833
-
3834
-
3835
- // End module pattern
3836
- })(window, document);
3837
-
3838
-
3839
-
3840
-
3841
- /**
3842
- * Loosly mimicks the PHP function print_r();
3843
- */
3844
- window.$p = function (obj)
3845
- {
3846
- var indent = (arguments[2] ? arguments[2] : ' ');
3847
- var str = '';
3848
-
3849
- var counter = typeof arguments[3] == 'number' ? arguments[3] : 0;
3850
-
3851
- if (counter >= 5) {
3852
- return '';
3853
- }
3854
-
3855
- switch (typeof obj) {
3856
-
3857
- case 'string': str += obj + ' (' + (typeof obj) + ', ' + obj.length + ')'; break;
3858
- case 'number': str += obj + ' (' + (typeof obj) + ')'; break;
3859
- case 'boolean': str += obj + ' (' + (typeof obj) + ')'; break;
3860
- case 'function': str += 'function () {}'; break;
3861
- case 'undefined': str += 'undefined'; break;
3862
- case 'null': str += 'null'; break;
3863
-
3864
- case 'object':
3865
- // In case of null
3866
- if (RGraph.SVG.isNull(obj)) {
3867
- str += indent + 'null\n';
3868
- } else {
3869
- str += indent + 'Object {' + '\n'
3870
- for (j in obj) {
3871
- str += indent + ' ' + j + ' => ' + window.$p(obj[j], true, indent + ' ', counter + 1) + '\n';
3872
- }
3873
- str += indent + '}';
3874
- }
3875
- break;
3876
-
3877
-
3878
- default:
3879
- str += 'Unknown type: ' + typeof obj + '';
3880
- break;
3881
- }
3882
-
3883
-
3884
- /**
3885
- * Finished, now either return if we're in a recursed call, or alert()
3886
- * if we're not.
3887
- */
3888
- if (!arguments[1]) {
3889
- alert(str);
3890
- }
3891
-
3892
- return str;
3893
- };
3894
-
3895
-
3896
-
3897
- /**
3898
- * A shorthand for the default alert() function
3899
- */
3900
- window.$a = function (v)
3901
- {
3902
- alert(v);
3903
- };
3904
-
3905
-
3906
-
3907
-
3908
- /**
3909
- * Short-hand for console.log
3910
- *
3911
- * @param mixed v The variable to log to the console
3912
- */
3913
- window.$cl = function (v)
3914
- {
3915
- return console.log(v);
3916
- };
3917
-
3918
-
3919
-
3920
-
3921
- /**
3922
- * A basic string formatting function. Use it like this:
3923
- *
3924
- * var str = '{0} {1} {2}'.format('a', 'b', 'c');
3925
- *
3926
- * Outputs: a b c
3927
- */
3928
- if (!String.prototype.format) {
3929
- String.prototype.format = function()
3930
- {
3931
- var args = arguments;
3932
-
3933
- return this.replace(/{(\d+)}/g, function(str, idx)
3934
- {
3935
- return typeof args[idx - 1] !== 'undefined' ? args[idx - 1] : str;
3936
- });
3937
- };
3938
- }
2
+ RGraph=window.RGraph||{isRGraph:true,isRGraphSVG:true};RGraph.SVG=RGraph.SVG||{};RGraph.SVG.FX=RGraph.SVG.FX||{};(function(win,doc,undefined)
3
+ {var RG=RGraph,ua=navigator.userAgent,ma=Math;RG.SVG.REG={store:[]};RG.SVG.OR={objects:[]};RG.SVG.TRIG={};RG.SVG.TRIG.HALFPI=ma.PI*.4999;RG.SVG.TRIG.PI=RG.SVG.TRIG.HALFPI*2;RG.SVG.TRIG.TWOPI=RG.SVG.TRIG.PI*2;RG.SVG.ISIE=ua.indexOf('rident')>0;RG.SVG.ISFF=ua.indexOf('irefox')>0;RG.SVG.events=[];RG.SVG.GLOBALS={};RG.SVG.ISFF=ua.indexOf('Firefox')!=-1;RG.SVG.ISOPERA=ua.indexOf('Opera')!=-1;RG.SVG.ISCHROME=ua.indexOf('Chrome')!=-1;RG.SVG.ISSAFARI=ua.indexOf('Safari')!=-1&&!RG.ISCHROME;RG.SVG.ISWEBKIT=ua.indexOf('WebKit')!=-1;RG.SVG.ISIE=ua.indexOf('Trident')>0||navigator.userAgent.indexOf('MSIE')>0;RG.SVG.ISIE6=ua.indexOf('MSIE 6')>0;RG.SVG.ISIE7=ua.indexOf('MSIE 7')>0;RG.SVG.ISIE8=ua.indexOf('MSIE 8')>0;RG.SVG.ISIE9=ua.indexOf('MSIE 9')>0;RG.SVG.ISIE10=ua.indexOf('MSIE 10')>0;RG.SVG.ISIE11UP=ua.indexOf('MSIE')==-1&&ua.indexOf('Trident')>0;RG.SVG.ISIE10UP=RG.SVG.ISIE10||RG.SVG.ISIE11UP;RG.SVG.ISIE9UP=RG.SVG.ISIE9||RG.SVG.ISIE10UP;RG.SVG.createSVG=function(opt)
4
+ {var container=opt.container,obj=opt.object;if(container.__svg__){return container.__svg__;}
5
+ var svg=doc.createElementNS("http://www.w3.org/2000/svg","svg");svg.setAttribute('style','top: 0; left: 0; position: absolute');svg.setAttribute('width',container.offsetWidth);svg.setAttribute('height',container.offsetHeight);svg.setAttribute('version','1.1');svg.setAttributeNS("http://www.w3.org/2000/xmlns/",'xmlns','http://www.w3.org/2000/svg');svg.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink");container.appendChild(svg);container.__svg__=svg;container.style.position='relative';var numLayers=10;for(var i=1;i<=numLayers;++i){var group=RG.SVG.create({svg:svg,type:'g',attr:{className:'background'+i}});obj.layers['background'+i]=group;svg['background'+i]=group;}
6
+ var group=RG.SVG.create({svg:svg,type:'g',attr:{className:'all-elements'}});container.__svg__.all=group;return svg;};RG.SVG.createDefs=function(obj)
7
+ {if(!obj.svg.defs){var defs=RG.SVG.create({svg:obj.svg,type:'defs'});obj.svg.defs=defs;}
8
+ return defs;};RG.SVG.create=function(opt)
9
+ {var ns="http://www.w3.org/2000/svg",tag=doc.createElementNS(ns,opt.type);for(var o in opt.attr){if(typeof o==='string'){var name=o;if(o==='className'){name='class';}
10
+ if((opt.type==='a'||opt.type==='image')&&o==='xlink:href'){tag.setAttributeNS('http://www.w3.org/1999/xlink',o,String(opt.attr[o]));}else{tag.setAttribute(name,String(opt.attr[o]));}}}
11
+ for(var o in opt.style){if(typeof o==='string'){tag.style[o]=String(opt.style[o]);}}
12
+ if(opt.parent){opt.parent.appendChild(tag);}else{opt.svg.appendChild(tag);}
13
+ return tag;};RG.SVG.getMouseXY=function(e)
14
+ {if(!e.target){return;}
15
+ var el=e.target,offsetX=0,offsetY=0,x,y;if(typeof el.offsetParent!=='undefined'){do{offsetX+=el.offsetLeft;offsetY+=el.offsetTop;}while((el=el.offsetParent));}
16
+ x=e.pageX;y=e.pageY;x-=(2*(parseInt(document.body.style.borderLeftWidth)||0));y-=(2*(parseInt(document.body.style.borderTopWidth)||0));return[x,y];};RG.SVG.drawXAxis=function(obj)
17
+ {var prop=obj.properties;if(prop.xaxis){var y=obj.type==='hbar'?obj.height-prop.gutterBottom:obj.getYCoord(obj.scale.min<0&&obj.scale.max<0?obj.scale.max:(obj.scale.min>0&&obj.scale.max>0?obj.scale.min:0));var axis=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(prop.gutterLeft,y,obj.width-prop.gutterRight,y),fill:prop.xaxisColor,stroke:prop.xaxisColor,'stroke-width':typeof prop.xaxisLinewidth==='number'?prop.xaxisLinewidth:1,'shape-rendering':'crispEdges','stroke-linecap':'square'}});if(obj.type==='hbar'){var width=obj.graphWidth/obj.data.length,x=prop.gutterLeft,startY=(obj.height-prop.gutterBottom),endY=(obj.height-prop.gutterBottom)+prop.xaxisTickmarksLength;}else{var width=obj.graphWidth/obj.data.length,x=prop.gutterLeft,startY=obj.getYCoord(0)-(prop.yaxisMin<0?prop.xaxisTickmarksLength:0),endY=obj.getYCoord(0)+prop.xaxisTickmarksLength;if(obj.scale.min<0&&obj.scale.max<=0){startY=prop.gutterTop;endY=prop.gutterTop-prop.xaxisTickmarksLength;}
18
+ if(obj.scale.min>0&&obj.scale.max>0){startY=obj.getYCoord(obj.scale.min);endY=obj.getYCoord(obj.scale.min)+prop.xaxisTickmarksLength;}}
19
+ if(prop.xaxisTickmarks){if(prop.xaxisScale){for(var i=0;i<(typeof prop.xaxisLabelsPositionEdgeTickmarksCount==='number'?prop.xaxisLabelsPositionEdgeTickmarksCount:(obj.scale.numlabels+(prop.yaxis&&prop.xaxisMin===0?0:1)));++i){if(obj.type==='hbar'){var dataPoints=obj.data.length;}
20
+ x=prop.gutterLeft+((i+(prop.yaxis&&prop.xaxisMin===0?1:0))*(obj.graphWidth/obj.scale.numlabels));if(typeof prop.xaxisLabelsPositionEdgeTickmarksCount==='number'){dataPoints=prop.xaxisLabelsPositionEdgeTickmarksCount;var gap=(obj.graphWidth/prop.xaxisLabelsPositionEdgeTickmarksCount);x=(gap*i)+prop.gutterLeft+gap;}
21
+ RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(x,startY,x,endY),stroke:prop.xaxisColor,'stroke-width':typeof prop.xaxisLinewidth==='number'?prop.xaxisLinewidth:1,'shape-rendering':"crispEdges"}});}}else{if(prop.xaxisLabelsPosition==='section'){if(obj.type==='bar'||obj.type==='waterfall'){var dataPoints=obj.data.length;}else if(obj.type==='line'){var dataPoints=obj.data[0].length;}else if(obj.type==='scatter'){var dataPoints=prop.xaxisLabels?prop.xaxisLabels.length:10;}
22
+ if(typeof prop.xaxisLabelsPositionSectionTickmarksCount==='number'){dataPoints=prop.xaxisLabelsPositionSectionTickmarksCount;}
23
+ for(var i=0;i<dataPoints;++i){x=prop.gutterLeft+((i+1)*(obj.graphWidth/dataPoints));RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(x+0.001,startY,x,endY),stroke:prop.xaxisColor,'stroke-width':typeof prop.xaxisLinewidth==='number'?prop.xaxisLinewidth:1,'shape-rendering':"crispEdges"}});}}else if(prop.xaxisLabelsPosition==='edge'){if(typeof prop.xaxisLabelsPositionEdgeTickmarksCount==='number'){var len=prop.xaxisLabelsPositionEdgeTickmarksCount;}else{var len=obj.data&&obj.data[0]&&obj.data[0].length?obj.data[0].length:0;}
24
+ for(var i=0;i<len;++i){var gap=((obj.graphWidth)/(len-1)),x=prop.gutterLeft+((i+1)*gap);RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(x+0.001,startY,x,endY),stroke:prop.xaxisColor,'stroke-width':typeof prop.xaxisLinewidth==='number'?prop.xaxisLinewidth:1,'shape-rendering':"crispEdges"}});}}}
25
+ if(prop.yaxis===false){RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(prop.gutterLeft+0.001,startY,prop.gutterLeft,endY),stroke:obj.properties.xaxisColor,'stroke-width':typeof prop.xaxisLinewidth==='number'?prop.xaxisLinewidth:1,'shape-rendering':"crispEdges",parent:obj.svg.all,}});}}}
26
+ if(prop.xaxisScale){var segment=obj.graphWidth/prop.xaxisLabelsCount;for(var i=0;i<obj.scale.labels.length;++i){var x=prop.gutterLeft+(segment*i)+segment+prop.xaxisLabelsOffsetx;RG.SVG.text({object:obj,parent:obj.svg.all,text:obj.scale.labels[i],x:x,y:(obj.height-prop.gutterBottom)+(prop.xaxis?prop.xaxisTickmarksLength+6:10)+(prop.xaxisLinewidth||1)+prop.xaxisLabelsOffsety,halign:'center',valign:'top',font:prop.xaxisTextFont||prop.textFont,size:prop.xaxisTextSize||(typeof prop.textSize==='number'?prop.textSize+'pt':prop.textSize),bold:prop.xaxisTextBold||prop.textBold,italic:prop.xaxisTextItalic||prop.textItalic,color:prop.xaxisTextColor||prop.textColor});}
27
+ if(prop.xaxisLabelsCount>0){var y=obj.height-prop.gutterBottom+prop.xaxisLabelsOffsety+(prop.xaxis?prop.xaxisTickmarksLength+6:10),str=RG.SVG.numberFormat({object:obj,num:prop.xaxisMin.toFixed(prop.xaxisDecimals),prepend:prop.xaxisUnitsPre,append:prop.xaxisUnitsPost,point:prop.xaxisPoint,thousand:prop.xaxisThousand,formatter:prop.xaxisFormatter});var text=RG.SVG.text({object:obj,parent:obj.svg.all,text:typeof prop.xaxisFormatter==='function'?(prop.xaxisFormatter)(this,prop.xaxisMin):str,x:prop.gutterLeft+prop.xaxisLabelsOffsetx,y:y,halign:'center',valign:'top',font:prop.xaxisTextFont||prop.textFont,size:prop.xaxisTextSize||(typeof prop.textSize==='number'?prop.textSize+'pt':prop.textSize),bold:prop.xaxisTextBold||prop.textBold,italic:prop.xaxisTextItalic||prop.textItalic,color:prop.xaxisTextColor||prop.textColor});}}else{if(typeof prop.xaxisLabels==='object'&&!RG.SVG.isNull(prop.xaxisLabels)){if(prop.xaxisLabelsPosition==='section'){var segment=(obj.width-prop.gutterLeft-prop.gutterRight)/prop.xaxisLabels.length;for(var i=0;i<prop.xaxisLabels.length;++i){var x=prop.gutterLeft+(segment/2)+(i*segment);if(obj.scale.max<=0&&obj.scale.min<obj.scale.max){var y=prop.gutterTop-(RG.SVG.ISFF?5:10)-(prop.xaxisLinewidth||1)+prop.xaxisLabelsOffsety;var valign='bottom';}else{var y=obj.height-prop.gutterBottom+(RG.SVG.ISFF?5:10)+(prop.xaxisLinewidth||1)+prop.xaxisLabelsOffsety;var valign='top';}
28
+ RG.SVG.text({object:obj,parent:obj.svg.all,text:prop.xaxisLabels[i],x:x+prop.xaxisLabelsOffsetx,y:y,valign:valign,halign:'center',size:prop.xaxisTextSize||prop.textSize,italic:prop.xaxisTextItalic||prop.textItalic,font:prop.xaxisTextFont||prop.textFont,bold:prop.xaxisTextBold||prop.textBold,color:prop.xaxisTextColor||prop.textColor});}}else if(prop.xaxisLabelsPosition==='edge'){if(obj.type==='line'){var hmargin=prop.hmargin;}else{var hmargin=0;}
29
+ var segment=(obj.graphWidth-hmargin-hmargin)/(prop.xaxisLabels.length-1);for(var i=0;i<prop.xaxisLabels.length;++i){var x=prop.gutterLeft+(i*segment)+hmargin;if(obj.scale.max<=0&&obj.scale.min<0){valign='bottom';y=prop.gutterTop-(RG.SVG.ISFF?5:10)-(prop.xaxisTickmarksLength-5)-(prop.xaxisLinewidth||1)+prop.xaxisLabelsOffsety}else{valign='top';y=obj.height-prop.gutterBottom+(RG.SVG.ISFF?5:10)+(prop.xaxisTickmarksLength-5)+(prop.xaxisLinewidth||1)+prop.xaxisLabelsOffsety;}
30
+ RG.SVG.text({object:obj,parent:obj.svg.all,text:prop.xaxisLabels[i],x:x+prop.xaxisLabelsOffsetx,y:y,valign:valign,halign:'center',size:prop.xaxisTextSize||prop.textSize,italic:prop.xaxisTextItalic||prop.textItalic,font:prop.xaxisTextFont||prop.textFont,bold:prop.xaxisTextBold||prop.textBold,color:prop.xaxisTextColor||prop.textColor});}}}}};RG.SVG.drawYAxis=function(obj)
31
+ {var prop=obj.properties;if(prop.yaxis){if(obj.type==='hbar'){var x=obj.getXCoord(prop.xaxisMin>0?prop.xaxisMin:0);if(prop.xaxisMin<0&&prop.xaxisMax<=0){x=obj.getXCoord(prop.xaxisMax);}}else{var x=prop.gutterLeft;}
32
+ var axis=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(x,prop.gutterTop,x,obj.height-prop.gutterBottom),stroke:prop.yaxisColor,fill:prop.yaxisColor,'stroke-width':typeof prop.yaxisLinewidth==='number'?prop.yaxisLinewidth:1,'shape-rendering':"crispEdges",'stroke-linecap':'square'}});if(obj.type==='hbar'){var height=(obj.graphHeight-prop.vmarginTop-prop.vmarginBottom)/prop.yaxisLabels.length,y=prop.gutterTop+prop.vmarginTop,len=prop.yaxisLabels.length,startX=obj.getXCoord(0)+(prop.xaxisMin<0?prop.yaxisTickmarksLength:0),endX=obj.getXCoord(0)-prop.yaxisTickmarksLength;if(prop.xaxisMin<0&&prop.xaxisMax<=0){startX=obj.getXCoord(prop.xaxisMax);endX=obj.getXCoord(prop.xaxisMax)+5;}
33
+ if(typeof prop.yaxisLabelsPositionSectionTickmarksCount==='number'){len=prop.yaxisLabelsPositionSectionTickmarksCount;height=(obj.graphHeight-prop.vmarginTop-prop.vmarginBottom)/len;}
34
+ if(prop.yaxisTickmarks){for(var i=0;i<len;++i){var axis=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(startX,y,endX,y+0.001),stroke:prop.yaxisColor,'stroke-width':typeof prop.yaxisLinewidth==='number'?prop.yaxisLinewidth:1,'shape-rendering':"crispEdges"}});y+=height;}
35
+ if(prop.xaxis===false){if(obj.type==='hbar'&&prop.xaxisMin<=0&&prop.xaxisMax<0){var startX=obj.getXCoord(prop.xaxisMax);var endX=obj.getXCoord(prop.xaxisMax)+prop.yaxisTickmarksLength;}else{var startX=obj.getXCoord(0)-prop.yaxisTickmarksLength;var endX=obj.getXCoord(0)+(prop.xaxisMin<0?prop.yaxisTickmarksLength:0);}
36
+ var axis=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(startX,ma.round(obj.height-prop.gutterBottom-parseFloat(prop.vmarginBottom)),endX,ma.round(obj.height-prop.gutterBottom-parseFloat(prop.vmarginBottom))),stroke:obj.properties.yaxisColor,'stroke-width':typeof prop.yaxisLinewidth==='number'?prop.yaxisLinewidth:1,'shape-rendering':"crispEdges"}});}}}else{var height=obj.graphHeight/prop.yaxisLabelsCount,y=prop.gutterTop,len=prop.yaxisLabelsCount,startX=prop.gutterLeft,endX=prop.gutterLeft-prop.yaxisTickmarksLength;if(typeof prop.yaxisLabelsPositionEdgeTickmarksCount==='number'){len=prop.yaxisLabelsPositionEdgeTickmarksCount;height=obj.graphHeight/len;}
37
+ if(prop.yaxisTickmarks){for(var i=0;i<len;++i){var axis=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(startX,y,endX,y),stroke:prop.yaxisColor,'stroke-width':typeof prop.yaxisLinewidth==='number'?prop.yaxisLinewidth:1,'shape-rendering':"crispEdges"}});y+=height;}
38
+ if((prop.yaxisMin!==0||prop.xaxis===false)&&!(obj.scale.min>0&&obj.scale.max>0)){var axis=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:'M{1} {2} L{3} {4}'.format(prop.gutterLeft-prop.yaxisTickmarksLength,obj.height-prop.gutterBottom,prop.gutterLeft,obj.height-prop.gutterBottom-0.001),stroke:prop.yaxisColor,'stroke-width':typeof prop.yaxisLinewidth==='number'?prop.yaxisLinewidth:1,'shape-rendering':"crispEdges"}});}}}}
39
+ if(prop.yaxisScale){var segment=(obj.height-prop.gutterTop-prop.gutterBottom)/prop.yaxisLabelsCount;for(var i=0;i<obj.scale.labels.length;++i){var y=obj.height-prop.gutterBottom-(segment*i)-segment;RG.SVG.text({object:obj,parent:obj.svg.all,text:obj.scale.labels[i],x:prop.gutterLeft-7-(prop.yaxis?(prop.yaxisTickmarksLength-3):0)+prop.yaxisLabelsOffsetx,y:y+prop.yaxisLabelsOffsety,halign:'right',valign:'center',font:prop.yaxisTextFont||prop.textFont,size:prop.yaxisTextSize||(typeof prop.textSize==='number'?prop.textSize+'pt':prop.textSize),bold:prop.yaxisTextBold||prop.textBold,italic:prop.yaxisTextItalic||prop.textItalic,color:prop.yaxisTextColor||prop.textColor});}
40
+ var y=obj.height-prop.gutterBottom,str=(prop.yaxisUnitsPre+prop.yaxisMin.toFixed(prop.yaxisDecimals).replace(/\./,prop.yaxisPoint)+prop.yaxisUnitsPost);var text=RG.SVG.text({object:obj,parent:obj.svg.all,text:typeof prop.yaxisFormatter==='function'?(prop.yaxisFormatter)(this,prop.yaxisMin):str,x:prop.gutterLeft-7-(prop.yaxis?(prop.yaxisTickmarksLength-3):0)+prop.yaxisLabelsOffsetx,y:y+prop.yaxisLabelsOffsety,halign:'right',valign:'center',font:prop.yaxisTextFont||prop.textFont,size:prop.yaxisTextSize||(typeof prop.textSize==='number'?prop.textSize+'pt':prop.textSize),bold:prop.yaxisTextBold||prop.textBold,italic:prop.yaxisTextItalic||prop.textItalic,color:prop.yaxisTextColor||prop.textColor});}else if(prop.yaxisLabels&&prop.yaxisLabels.length){for(var i=0;i<prop.yaxisLabels.length;++i){var segment=(obj.graphHeight-(prop.vmarginTop||0)-(prop.vmarginBottom||0))/prop.yaxisLabels.length,y=prop.gutterTop+(prop.vmarginTop||0)+(segment*i)+(segment/2)+prop.yaxisLabelsOffsety,x=prop.gutterLeft-7-(prop.yaxisLinewidth||1)+prop.yaxisLabelsOffsetx,halign='right';if(obj.type==='hbar'&&obj.scale.min<obj.scale.max&&obj.scale.max<=0){halign='left';x=obj.width-prop.gutterRight+7+prop.yaxisLabelsOffsetx;}else if(obj.type==='hbar'&&!prop.yaxisLabelsSpecific){var segment=(obj.graphHeight-(prop.vmarginTop||0)-(prop.vmarginBottom||0))/(prop.yaxisLabels.length);y=prop.gutterTop+(prop.vmarginTop||0)+(segment*i)+(segment/2)+prop.yaxisLabelsOffsetx;}else{var segment=(obj.graphHeight-(prop.vmarginTop||0)-(prop.vmarginBottom||0))/(prop.yaxisLabels.length-1);y=obj.height-prop.gutterBottom-(segment*i)+prop.yaxisLabelsOffsetx;}
41
+ var text=RG.SVG.text({object:obj,parent:obj.svg.all,text:prop.yaxisLabels[i]?prop.yaxisLabels[i]:'',x:x,y:y,halign:halign,valign:'center',font:prop.yaxisTextFont||prop.textFont,size:prop.yaxisTextSize||(typeof prop.textSize==='number'?prop.textSize+'pt':prop.textSize),bold:prop.yaxisTextBold||prop.textBold,italic:prop.yaxisTextItalic||prop.textItalic,color:prop.yaxisTextColor||prop.textColor});}}};RG.SVG.drawBackground=function(obj)
42
+ {var prop=obj.properties;if(typeof prop.variant3dOffsetx!=='number')prop.variant3dOffsetx=0;if(typeof prop.variant3dOffsety!=='number')prop.variant3dOffsety=0;if(prop.backgroundColor){RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'rect',attr:{x:-1+prop.variant3dOffsetx+prop.gutterLeft,y:-1-prop.variant3dOffsety+prop.gutterTop,width:parseFloat(obj.svg.getAttribute('width'))+2-prop.gutterLeft-prop.gutterRight,height:parseFloat(obj.svg.getAttribute('height'))+2-prop.gutterTop-prop.gutterBottom,fill:prop.backgroundColor}});}
43
+ if(prop.backgroundImage){var attr={'xlink:href':prop.backgroundImage,preserveAspectRatio:prop.backgroundImageAspect||'none',x:prop.gutterLeft,y:prop.gutterTop};if(prop.backgroundImageStretch){attr.x=prop.gutterLeft+prop.variant3dOffsetx;attr.y=prop.gutterTop+prop.variant3dOffsety;attr.width=obj.width-prop.gutterLeft-prop.gutterRight;attr.height=obj.height-prop.gutterTop-prop.gutterBottom;}else{if(typeof prop.backgroundImageX==='number'){attr.x=prop.backgroundImageX+prop.variant3dOffsetx;}
44
+ if(typeof prop.backgroundImageY==='number'){attr.y=prop.backgroundImageY+prop.variant3dOffsety;}
45
+ if(typeof prop.backgroundImageW==='number'){attr.width=prop.backgroundImageW;}
46
+ if(typeof prop.backgroundImageH==='number'){attr.height=prop.backgroundImageH;}}
47
+ if(prop.variant==='3d'){attr.x+=prop.variant3dOffsetx;attr.y-=prop.variant3dOffsety;}
48
+ var img=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'image',attr:attr,style:{opacity:typeof prop.backgroundImageOpacity==='number'?prop.backgroundImageOpacity:1}});}
49
+ if(prop.backgroundGrid){var parts=[];if(prop.backgroundGridHlines){var count=typeof prop.backgroundGridHlinesCount==='number'?prop.backgroundGridHlinesCount:(obj.type==='hbar'?(prop.yaxisLabels.length||obj.data.length||5):prop.yaxisLabelsCount);for(var i=0;i<=count;++i){parts.push('M{1} {2} L{3} {4}'.format(prop.gutterLeft+prop.variant3dOffsetx,prop.gutterTop+(obj.graphHeight/count)*i-prop.variant3dOffsety,obj.width-prop.gutterRight+prop.variant3dOffsetx,prop.gutterTop+(obj.graphHeight/count)*i-prop.variant3dOffsety));}
50
+ parts.push('M{1} {2} L{3} {4}'.format(prop.gutterLeft+prop.variant3dOffsetx,obj.height-prop.gutterBottom-prop.variant3dOffsety,obj.width-prop.gutterRight+prop.variant3dOffsetx,obj.height-prop.gutterBottom-prop.variant3dOffsety));}
51
+ if(prop.backgroundGridVlines){if(obj.type==='line'&&RG.SVG.isArray(obj.data[0])){var len=obj.data[0].length;}else if(obj.type==='hbar'){var len=prop.xaxisLabelsCount||10;}else if(obj.type==='scatter'){var len=(prop.xaxisLabels&&prop.xaxisLabels.length)||10;}else{var len=obj.data.length;}
52
+ var count=typeof prop.backgroundGridVlinesCount==='number'?prop.backgroundGridVlinesCount:len;if(prop.xaxisLabelsPosition==='edge'){count--;}
53
+ for(var i=0;i<=count;++i){parts.push('M{1} {2} L{3} {4}'.format(prop.gutterLeft+((obj.graphWidth/count)*i)+prop.variant3dOffsetx,prop.gutterTop-prop.variant3dOffsety,prop.gutterLeft+((obj.graphWidth/count)*i)+prop.variant3dOffsetx,obj.height-prop.gutterBottom-prop.variant3dOffsety));}}
54
+ if(prop.backgroundGridBorder){parts.push('M{1} {2} L{3} {4} L{5} {6} L{7} {8} z'.format(prop.gutterLeft+prop.variant3dOffsetx,prop.gutterTop-prop.variant3dOffsety,obj.width-prop.gutterRight+prop.variant3dOffsetx,prop.gutterTop-prop.variant3dOffsety,obj.width-prop.gutterRight+prop.variant3dOffsetx,obj.height-prop.gutterBottom-prop.variant3dOffsety,prop.gutterLeft+prop.variant3dOffsetx,obj.height-prop.gutterBottom-prop.variant3dOffsety));}
55
+ var dasharray;if(prop.backgroundGridDashed){dasharray=[3,5];}else if(prop.backgroundGridDotted){dasharray=[1,3];}else if(prop.backgroundGridDashArray){dasharray=prop.backgroundGridDashArray;}else{dasharray='';}
56
+ var grid=RG.SVG.create({svg:obj.svg,parent:obj.svg.all,type:'path',attr:{d:parts.join(' '),stroke:prop.backgroundGridColor,fill:'rgba(0,0,0,0)','stroke-width':prop.backgroundGridLinewidth,'shape-rendering':"crispEdges",'stroke-dasharray':dasharray}});}
57
+ RG.SVG.drawTitle(obj);};RG.SVG.isNull=function(arg)
58
+ {if(arg==null||typeof arg==='object'&&!arg){return true;}
59
+ return false;};RG.SVG.getScale=function(opt)
60
+ {var obj=opt.object,prop=obj.properties,numlabels=opt.numlabels,unitsPre=opt.unitsPre,unitsPost=opt.unitsPost,max=Number(opt.max),min=Number(opt.min),strict=opt.strict,decimals=Number(opt.decimals),point=opt.point,thousand=opt.thousand,originalMax=max,round=opt.round,scale={max:1,labels:[],values:[]},formatter=opt.formatter;if(max===0&&min===0){var max=1;for(var i=0;i<numlabels;++i){var label=((((max-min)/numlabels)*(i+1))+min).toFixed(decimals);scale.labels.push(unitsPre+label+unitsPost);scale.values.push(parseFloat(label))}}else if(max<=1&&!strict){var arr=[1,0.5,0.10,0.05,0.010,0.005,0.0010,0.0005,0.00010,0.00005,0.000010,0.000005,0.0000010,0.0000005,0.00000010,0.00000005,0.000000010,0.000000005,0.0000000010,0.0000000005,0.00000000010,0.00000000005,0.000000000010,0.000000000005,0.0000000000010,0.0000000000005],vals=[];for(var i=0;i<arr.length;++i){if(max>arr[i]){i--;break;}}
61
+ scale.max=arr[i]
62
+ scale.labels=[];scale.values=[];for(var j=0;j<numlabels;++j){var value=((((arr[i]-min)/numlabels)*(j+1))+min).toFixed(decimals);scale.values.push(value);scale.labels.push(RG.SVG.numberFormat({object:obj,num:value,prepend:unitsPre,append:unitsPost,point:prop.yaxisPoint,thousand:prop.yaxisThousand,formatter:formatter}));}}else if(!strict){max=ma.ceil(max);var interval=ma.pow(10,ma.max(1,Number(String(Number(max)-Number(min)).length-1)));var topValue=interval;while(topValue<max){topValue+=(interval/2);}
63
+ if(Number(originalMax)>Number(topValue)){topValue+=(interval/2);}
64
+ if(max<=10){topValue=(Number(originalMax)<=5?5:10);}
65
+ if(obj&&typeof(round)=='boolean'&&round){topValue=10*interval;}
66
+ scale.max=topValue;for(var i=0;i<numlabels;++i){var label=RG.SVG.numberFormat({object:obj,num:((((i+1)/numlabels)*(topValue-min))+min).toFixed(decimals),prepend:unitsPre,append:unitsPost,point:point,thousand:thousand,formatter:formatter});scale.labels.push(label);scale.values.push(((((i+1)/numlabels)*(topValue-min))+min).toFixed(decimals));}}else if(typeof max==='number'&&strict){for(var i=0;i<numlabels;++i){scale.labels.push(RG.SVG.numberFormat({object:obj,formatter:formatter,num:((((i+1)/numlabels)*(max-min))+min).toFixed(decimals),prepend:unitsPre,append:unitsPost,point:point,thousand:thousand}));scale.values.push(((((i+1)/numlabels)*(max-min))+min).toFixed(decimals));}
67
+ scale.max=max;}
68
+ scale.unitsPre=unitsPre;scale.unitsPost=unitsPost;scale.point=point;scale.decimals=decimals;scale.thousand=thousand;scale.numlabels=numlabels;scale.round=Boolean(round);scale.min=min;for(var i=0;i<scale.values.length;++i){scale.values[i]=parseFloat(scale.values[i]);}
69
+ return scale;};RG.SVG.arrayFill=RG.SVG.arrayPad=function(opt)
70
+ {var arr=opt.array,len=opt.length,value=(opt.value?opt.value:null);if(arr.length<len){for(var i=arr.length;i<len;i+=1){arr[i]=value;}}
71
+ return arr;};RG.SVG.arraySum=function(arr)
72
+ {if(typeof arr==='number'){return arr;}
73
+ if(RG.SVG.isNull(arr)){return 0;}
74
+ var i,sum,len=arr.length;for(i=0,sum=0;i<len;sum+=arr[i++]);return sum;};RG.SVG.arrayMax=function(arr)
75
+ {var max=null
76
+ if(typeof arr==='number'){return arr;}
77
+ if(RG.SVG.isNull(arr)){return 0;}
78
+ for(var i=0,len=arr.length;i<len;++i){if(typeof arr[i]==='number'){var val=arguments[1]?ma.abs(arr[i]):arr[i];if(typeof max==='number'){max=ma.max(max,val);}else{max=val;}}}
79
+ return max;};RG.SVG.arrayMin=function(arr)
80
+ {var max=null,min=null,ma=Math;if(typeof arr==='number'){return arr;}
81
+ if(RG.SVG.isNull(arr)){return 0;}
82
+ for(var i=0,len=arr.length;i<len;++i){if(typeof arr[i]==='number'){var val=arguments[1]?ma.abs(arr[i]):arr[i];if(typeof min==='number'){min=ma.min(min,val);}else{min=val;}}}
83
+ return min;};RG.SVG.arrayPad=function(arr,len)
84
+ {if(arr.length<len){var val=arguments[2]?arguments[2]:null;for(var i=arr.length;i<len;i+=1){arr[i]=val;}}
85
+ return arr;};RG.SVG.arraySum=function(arr)
86
+ {if(typeof arr==='number'){return arr;}
87
+ if(RG.SVG.isNull(arr)){return 0;}
88
+ var i,sum,len=arr.length;for(i=0,sum=0;i<len;sum+=arr[i++]);return sum;};RG.SVG.arrayLinearize=function()
89
+ {var arr=[],args=arguments
90
+ for(var i=0,len=args.length;i<len;++i){if(typeof args[i]==='object'&&args[i]){for(var j=0,len2=args[i].length;j<len2;++j){var sub=RG.SVG.arrayLinearize(args[i][j]);for(var k=0,len3=sub.length;k<len3;++k){arr.push(sub[k]);}}}else{arr.push(args[i]);}}
91
+ return arr;};RG.SVG.arrayShift=function(arr)
92
+ {var ret=[];for(var i=1,len=arr.length;i<len;++i){ret.push(arr[i]);}
93
+ return ret;};RG.SVG.arrayReverse=function(arr)
94
+ {if(!arr){return;}
95
+ var newarr=[];for(var i=arr.length-1;i>=0;i-=1){newarr.push(arr[i]);}
96
+ return newarr;};RG.SVG.arrayClone=function(obj)
97
+ {if(obj===null||typeof obj!=='object'){return obj;}
98
+ if(RG.SVG.isArray(obj)){var temp=[];for(var i=0,len=obj.length;i<len;++i){if(typeof obj[i]==='number'){temp[i]=(function(arg){return Number(arg);})(obj[i]);}else if(typeof obj[i]==='string'){temp[i]=(function(arg){return String(arg);})(obj[i]);}else if(typeof obj[i]==='function'){temp[i]=obj[i];}else{temp[i]=RG.SVG.arrayClone(obj[i]);}}}else if(typeof obj==='object'){var temp={};for(var i in obj){if(typeof i==='string'){temp[i]=obj[i];}}}
99
+ return temp;};RG.SVG.arrayInvert=function(arr)
100
+ {for(var i=0,len=arr.length;i<len;++i){arr[i]=!arr[i];}
101
+ return arr;};RG.SVG.arrayTrim=function(arr)
102
+ {var out=[],content=false;for(var i=0;i<arr.length;i++){if(arr[i]){content=true;}
103
+ if(content){out.push(arr[i]);}}
104
+ out=RG.SVG.arrayReverse(out);var out2=[],content=false;for(var i=0;i<out.length;i++){if(out[i]){content=true;}
105
+ if(content){out2.push(out[i]);}}
106
+ out2=RG.SVG.arrayReverse(out2);return out2;};RG.SVG.isArray=function(obj)
107
+ {if(obj&&obj.constructor){var pos=obj.constructor.toString().indexOf('Array');}else{return false;}
108
+ return obj!=null&&typeof pos==='number'&&pos>0&&pos<20;};RG.SVG.abs=function(value)
109
+ {if(typeof value==='string'){value=parseFloat(value)||0;}
110
+ if(typeof value==='number'){return ma.abs(value);}
111
+ if(typeof value==='object'){for(i in value){if(typeof i==='string'||typeof i==='number'||typeof i==='object'){value[i]=RG.SVG.abs(value[i]);}}
112
+ return value;}
113
+ return 0;};RG.SVG.numberFormat=function(opt)
114
+ {var obj=opt.object,prepend=opt.prepend?String(opt.prepend):'',append=opt.append?String(opt.append):'',output='',decimal_seperator=typeof opt.point==='string'?opt.point:'.',thousand_seperator=typeof opt.thousand==='string'?opt.thousand:',',num=opt.num
115
+ decimals_trim=opt.decimals_trim;RegExp.$1='';if(typeof opt.formatter==='function'){return opt.formatter(obj,num);}
116
+ if(String(num).indexOf('e')>0){return String(prepend+String(num)+append);}
117
+ num=String(num);if(num.indexOf('.')>0){var tmp=num;num=num.replace(/\.(.*)/,'');decimal=tmp.replace(/(.*)\.(.*)/,'$2');}else{decimal='';}
118
+ var seperator=thousand_seperator;var foundPoint;for(i=(num.length-1),j=0;i>=0;j++,i--){var character=num.charAt(i);if(j%3==0&&j!=0){output+=seperator;}
119
+ output+=character;}
120
+ var rev=output;output='';for(i=(rev.length-1);i>=0;i--){output+=rev.charAt(i);}
121
+ if(output.indexOf('-'+thousand_seperator)==0){output='-'+output.substr(('-'+thousand_seperator).length);}
122
+ if(decimal.length){output=output+decimal_seperator+decimal;decimal='';RegExp.$1='';}
123
+ if(decimals_trim){output=output.replace(/0+$/,'');output=output.replace(/\.$/,'');}
124
+ if(output.charAt(0)=='-'){output=output.replace(/-/,'');prepend='-'+prepend;}
125
+ return prepend+output+append;};RG.SVG.text=function(opt)
126
+ {var obj=opt.object,parent=opt.parent||opt.object.svg.all,size=opt.size,bold=opt.bold,font=opt.font,italic=opt.italic,halign=opt.halign,valign=opt.valign,str=opt.text,x=opt.x,y=opt.y,color=opt.color?opt.color:'black',background=opt.background||null,padding=opt.padding||0,link=opt.link||'',linkTarget=opt.linkTarget||'_blank';if(halign==='right'){halign='end';}else if(halign==='center'||halign==='middle'){halign='middle';}else{halign='start';}
127
+ if(valign==='top'){valign='hanging';}else if(valign==='center'||valign==='middle'){valign='central';valign='middle';}else{valign='bottom';}
128
+ if(link){var a=RGraph.SVG.create({svg:bar.svg,type:'a',parent:opt.parent,attr:{'xlink:href':link,target:linkTarget}});}
129
+ var text=RG.SVG.create({svg:obj.svg,parent:link?a:opt.parent,type:'text',attr:{fill:color,x:x,y:y,'font-size':typeof size==='number'?size+'pt':size,'font-weight':bold?900:100,'font-family':font?font:'sans-serif','font-style':italic?'italic':'normal','text-anchor':halign,'dominant-baseline':valign}});var textNode=document.createTextNode(str);text.appendChild(textNode);if(typeof background==='string'){var bbox=text.getBBox(),rect=RG.SVG.create({svg:obj.svg,parent:opt.parent,type:'rect',attr:{x:bbox.x-padding,y:bbox.y-padding,width:bbox.width+(padding*2),height:bbox.height+(padding*2),fill:background}});parent.insertBefore(rect,text);}
130
+ if(RG.SVG.ISIE&&(valign==='hanging')){text.setAttribute('y',y+(text.scrollHeight/2));}else if(RG.SVG.ISIE&&valign==='middle'){text.setAttribute('y',y+(text.scrollHeight/3));}
131
+ if(RG.SVG.ISFF){Y=y+(text.scrollHeight/3);}
132
+ return text;};RG.SVG.createUID=function()
133
+ {return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c)
134
+ {var r=ma.random()*16|0,v=c=='x'?r:(r&0x3|0x8);return v.toString(16);});};RG.SVG.isFixed=function(svg)
135
+ {var obj=svg.parentNode,i=0;while(obj&&obj.tagName.toLowerCase()!='body'&&i<99){if(obj.style.position==='fixed'){return obj;}
136
+ obj=obj.offsetParent;}
137
+ return false;};RG.SVG.REG.set=function(name,value)
138
+ {RG.SVG.REG.store[name]=value;return value;};RG.SVG.REG.get=function(name)
139
+ {return RG.SVG.REG.store[name];};RG.SVG.trim=function(str)
140
+ {return RG.SVG.ltrim(RG.SVG.rtrim(str));};RG.SVG.ltrim=function(str)
141
+ {return str.replace(/^(\s|\0)+/,'');};RG.SVG.rtrim=function(str)
142
+ {return str.replace(/(\s|\0)+$/,'');};RG.SVG.hideTooltip=function()
143
+ {var tooltip=RG.SVG.REG.get('tooltip');if(tooltip&&tooltip.parentNode){tooltip.parentNode.removeChild(tooltip);tooltip.style.display='none';tooltip.style.visibility='hidden';RG.SVG.REG.set('tooltip',null);}
144
+ if(tooltip&&tooltip.__object__){RG.SVG.removeHighlight(tooltip.__object__);}};RG.SVG.setShadow=function(options)
145
+ {var obj=options.object,offsetx=options.offsetx||0,offsety=options.offsety||0,blur=options.blur||0,opacity=options.opacity||0,id=options.id;var filter=RG.SVG.create({svg:obj.svg,parent:obj.svg.defs,type:'filter',attr:{id:id,width:"130%",height:"130%"}});RG.SVG.create({svg:obj.svg,parent:filter,type:'feOffset',attr:{result:'offOut','in':'SourceGraphic',dx:offsetx,dy:offsety}});RG.SVG.create({svg:obj.svg,parent:filter,type:'feColorMatrix',attr:{result:'matrixOut','in':'offOut',type:'matrix',values:'0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 {1} 0'.format(opacity)}});RG.SVG.create({svg:obj.svg,parent:filter,type:'feGaussianBlur',attr:{result:'blurOut','in':'matrixOut',stdDeviation:blur}});RG.SVG.create({svg:obj.svg,parent:filter,type:'feBlend',attr:{'in':'SourceGraphic','in2':'blurOut',mode:'normal'}});};RG.SVG.sequentialIndexToGrouped=function(index,data)
146
+ {var group=0,grouped_index=0;while(--index>=0){if(RG.SVG.isNull(data[group])){group++;grouped_index=0;continue;}
147
+ if(typeof data[group]=='number'){group++
148
+ grouped_index=0;continue;}
149
+ grouped_index++;if(grouped_index>=data[group].length){group++;grouped_index=0;}}
150
+ return[group,grouped_index];};RG.SVG.TRIG.toCartesian=function(options)
151
+ {return{x:options.cx+(options.r*ma.cos(options.angle)),y:options.cy+(options.r*ma.sin(options.angle))};};RG.SVG.TRIG.getArcPath=function(options)
152
+ {options.start-=1.57;options.end-=1.57;var start=RG.SVG.TRIG.toCartesian({cx:options.cx,cy:options.cy,r:options.r,angle:options.start});var end=RG.SVG.TRIG.toCartesian({cx:options.cx,cy:options.cy,r:options.r,angle:options.end});var diff=options.end-options.start;var largeArc='0';var sweep='0';if(options.anticlockwise&&diff>3.14){largeArc='0';sweep='0';}else if(options.anticlockwise&&diff<=3.14){largeArc='1';sweep='0';}else if(!options.anticlockwise&&diff>3.14){largeArc='1';sweep='1';}else if(!options.anticlockwise&&diff<=3.14){largeArc='0';sweep='1';}
153
+ if(options.start>options.end&&options.anticlockwise&&diff<=3.14){largeArc='0';sweep='0';}
154
+ if(options.start>options.end&&options.anticlockwise&&diff>3.14){largeArc='1';sweep='1';}
155
+ if(typeof options.moveto==='boolean'&&options.moveto===false){var d=["A",options.r,options.r,0,largeArc,sweep,end.x,end.y];}else{var d=["M",start.x,start.y,"A",options.r,options.r,0,largeArc,sweep,end.x,end.y];}
156
+ if(options.array===true){return d;}else{return d.join(" ");}};RG.SVG.TRIG.getArcPath2=function(options)
157
+ {options.start-=1.57;options.end-=1.57;var start=RG.SVG.TRIG.toCartesian({cx:options.cx,cy:options.cy,r:options.r,angle:options.start});var end=RG.SVG.TRIG.toCartesian({cx:options.cx,cy:options.cy,r:options.r,angle:options.end});var diff=ma.abs(options.end-options.start);var largeArc='0';var sweep='0';if(!options.anticlockwise){if(diff>RG.SVG.TRIG.PI){largeArc='1';sweep='1';}else{largeArc='0';sweep='1';}}else{if(diff>RG.SVG.TRIG.PI){largeArc='1';sweep='0';}else{largeArc='0';sweep='0';}}
158
+ if(typeof options.lineto==='boolean'&&options.lineto===false){var d=["M",start.x,start.y,"A",options.r,options.r,0,largeArc,sweep,end.x,end.y];}else{var d=["M",options.cx,options.cy,"L",start.x,start.y,"A",options.r,options.r,0,largeArc,sweep,end.x,end.y];}
159
+ if(options.array===true){return d;}else{return d.join(" ");}};RG.SVG.TRIG.getArcPath3=function(options)
160
+ {options.start-=1.57;options.end-=1.57;var start=RG.SVG.TRIG.toCartesian({cx:options.cx,cy:options.cy,r:options.r,angle:options.start});var end=RG.SVG.TRIG.toCartesian({cx:options.cx,cy:options.cy,r:options.r,angle:options.end});var diff=ma.abs(options.end-options.start);var largeArc='0';var sweep='0';if(!options.anticlockwise){if(diff>RG.SVG.TRIG.PI){largeArc='1';sweep='1';}else{largeArc='0';sweep='1';}}else{if(diff>RG.SVG.TRIG.PI){largeArc='1';sweep='0';}else{largeArc='0';sweep='0';}}
161
+ if(typeof options.lineto==='boolean'&&options.lineto===false){var d=["M",start.x,start.y,"A",options.r,options.r,0,largeArc,sweep,end.x,end.y];}else{var d=["L",start.x,start.y,"A",options.r,options.r,0,largeArc,sweep,end.x,end.y];}
162
+ if(options.array===true){return d;}else{return d.join(" ");}};RG.SVG.TRIG.getRadiusEndPoint=function(opt)
163
+ {if(arguments.length===1){var angle=opt.angle,r=opt.r;}else if(arguments.length===4){var angle=arguments[0],r=arguments[1];}
164
+ var x=ma.cos(angle)*r,y=ma.sin(angle)*r;return[x,y];};RG.SVG.drawTitle=function(obj)
165
+ {var prop=obj.properties,valign='bottom',originalTitleX=prop.titleX,originalTitleY=prop.titleY,originalTitleSubtitleX=prop.titleSubtitleX,originalTitleSubtitleY=prop.titleSubtitleY;if(typeof originalTitleX==='string')originalTitleX.replace(/^\+/,'');if(typeof originalTitleY==='string')originalTitleY.replace(/^\+/,'');if(typeof originalTitleSubtitleX==='string')originalTitleSubtitleX.replace(/^\+/,'');if(typeof originalTitleSubtitleY==='string')originalTitleSubtitleY.replace(/^\+/,'');if(obj.type==='pie'){if(RG.SVG.isNull(prop.titleX)){prop.titleX=obj.centerx;prop.titleSubtitleX=obj.centerx;}
166
+ if(RG.SVG.isNull(prop.titleY)){prop.titleY=obj.centery-obj.radius-10;}}
167
+ if(obj.scale&&obj.scale.max<=0&&obj.scale.min<0&&typeof prop.titleY!=='number'&&obj.type!=='hbar'){prop.titleY=obj.height-prop.gutterBottom+10;var positionBottom=true;valign='top';}else if(typeof prop.titleY!=='number'){var positionBottom=false;prop.titleY=prop.gutterTop-10;valign='bottom';if(!RG.SVG.isNull(prop.key)){prop.titleY-=(2*(prop.keyTextSize||prop.textSize));}}
168
+ if(prop.titleSubtitle&&typeof prop.titleSubtitleY!=='number'&&!positionBottom){prop.titleY=prop.titleY-(prop.titleSubtitleSize*1.5);}
169
+ prop.titleSubTitleSize=prop.titleSubTitleSize||prop.textSize;prop.titleSubtitleY=prop.titleSubtitleY||prop.titleY+18;if(positionBottom&&typeof prop.titleSubtitleY!=='number'){prop.titleSubtitleY=prop.titleY+26;}
170
+ if(prop.title){var x=typeof prop.titleX==='number'?prop.titleX+(prop.variant3dOffsetx||0):prop.gutterLeft+(obj.graphWidth/2)+(prop.variant3dOffsetx||0);var y=prop.titleY+(prop.variant3dOffsety||0);if(typeof originalTitleX==='string'){x+=parseFloat(originalTitleX);}
171
+ if(typeof originalTitleY==='string'){y+=parseFloat(originalTitleY);}
172
+ RG.SVG.text({object:obj,svg:obj.svg,parent:obj.svg.all,text:prop.title.toString(),size:prop.titleSize||(prop.textSize+4)||16,x:x,y:y,halign:prop.titleHalign||'center',valign:prop.titleValign||valign,color:prop.titleColor||prop.textColor||'black',bold:prop.titleBold||false,italic:prop.titleItalic||false,font:prop.titleFont||prop.textFont||'Arial'});}
173
+ if(typeof prop.title==='string'&&typeof prop.titleSubtitle==='string'){y+=(prop.titleSubtitleSize*1.5);if(typeof originalTitleSubtitleX==='number'){x=originalTitleSubtitleX;}
174
+ if(typeof originalTitleSubtitleY==='number'){y=originalTitleSubtitleY;}
175
+ if(typeof originalTitleSubtitleX==='string'){x+=parseFloat(originalTitleSubtitleX);}
176
+ if(typeof originalTitleSubtitleY==='string'){y+=parseFloat(originalTitleSubtitleY);}
177
+ RG.SVG.text({object:obj,svg:obj.svg,parent:obj.svg.all,text:prop.titleSubtitle,size:prop.titleSubtitleSize,x:x,y:y,halign:prop.titleSubtitleHalign||'center',valign:prop.titleSubtitleValign||valign,color:prop.titleSubtitleColor||prop.textColor||'#aaa',bold:prop.titleSubtitleBold||false,italic:prop.titleSubtitleItalic||false,font:prop.titleSubtitleFont||prop.textFont||'Arial'});}};RG.SVG.trim=function(str)
178
+ {return RG.SVG.ltrim(RG.SVG.rtrim(str));};RG.SVG.ltrim=function(str)
179
+ {return String(str).replace(/^(\s|\0)+/,'');};RG.SVG.rtrim=function(str)
180
+ {return String(str).replace(/(\s|\0)+$/,'');};RG.SVG.parseColorLinear=function(opt)
181
+ {var obj=opt.object,color=opt.color;if(!color||typeof color!=='string'){return color;}
182
+ if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':'),diff=1/(parts.length-1);if(opt&&opt.direction&&opt.direction==='horizontal'){var grad=RG.SVG.create({type:'linearGradient',parent:obj.svg.defs,attr:{id:'RGraph-linear-gradient-'+obj.uid+'-'+obj.gradientCounter,x1:opt.start||0,x2:opt.end||'100%',y1:0,y2:0,gradientUnits:"userSpaceOnUse"}});}else{var grad=RG.SVG.create({type:'linearGradient',parent:obj.svg.defs,attr:{id:'RGraph-linear-gradient-'+obj.uid+'-'+obj.gradientCounter,x1:0,x2:0,y1:opt.start||0,y2:opt.end||'100%',gradientUnits:"userSpaceOnUse"}});}
183
+ var stop=RG.SVG.create({type:'stop',parent:grad,attr:{offset:'0%','stop-color':RG.SVG.trim(parts[0])}});for(var j=1,len=parts.length;j<len;++j){RG.SVG.create({type:'stop',parent:grad,attr:{offset:(j*diff*100)+'%','stop-color':RG.SVG.trim(parts[j])}});}}
184
+ color=grad?'url(#RGraph-linear-gradient-'+obj.uid+'-'+(obj.gradientCounter++)+')':color;return color;};RG.SVG.parseColorRadial=function(opt)
185
+ {var obj=opt.object,color=opt.color;if(!color||typeof color!=='string'){return color;}
186
+ if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':'),diff=1/(parts.length-1);var grad=RG.SVG.create({type:'radialGradient',parent:obj.svg.defs,attr:{id:'RGraph-radial-gradient-'+obj.uid+'-'+obj.gradientCounter,gradientUnits:opt.gradientUnits||'userSpaceOnUse',cx:opt.cx||obj.centerx,cy:opt.cy||obj.centery,fx:opt.fx||obj.centerx,fy:opt.fy||obj.centery,r:opt.r||obj.radius}});var stop=RG.SVG.create({type:'stop',parent:grad,attr:{offset:'0%','stop-color':RG.SVG.trim(parts[0])}});for(var j=1,len=parts.length;j<len;++j){RG.SVG.create({type:'stop',parent:grad,attr:{offset:(j*diff*100)+'%','stop-color':RG.SVG.trim(parts[j])}});}}
187
+ color=grad?'url(#RGraph-radial-gradient-'+obj.uid+'-'+(obj.gradientCounter++)+')':color;return color;};RG.SVG.resetColorsToOriginalValues=function(opt)
188
+ {var obj=opt.object;if(obj.originalColors){for(var j in obj.originalColors){if(typeof j==='string'){obj.properties[j]=RG.SVG.arrayClone(obj.originalColors[j]);}}}
189
+ if(typeof obj.resetColorsToOriginalValues==='function'){obj.resetColorsToOriginalValues();}
190
+ obj.originalColors={};obj.colorsParsed=false;obj.gradientCounter=1;};RG.SVG.clear=function(svg)
191
+ {for(var i=1;i<=100;++i){if(svg['background'+i]){while(svg['background'+i].lastChild){svg['background'+i].removeChild(svg['background'+i].lastChild);}}else{break;}}
192
+ while(svg.all.lastChild){svg.all.removeChild(svg.all.lastChild);}};RG.SVG.addCustomEventListener=function(obj,name,func)
193
+ {if(typeof RG.SVG.events[obj.uid]==='undefined'){RG.SVG.events[obj.uid]=[];}
194
+ if(name.substr(0,2)!=='on'){name='on'+name;}
195
+ RG.SVG.events[obj.uid].push({object:obj,event:name,func:func});return RG.SVG.events[obj.uid].length-1;};RG.SVG.fireCustomEvent=function(obj,name)
196
+ {if(obj&&obj.isRGraph){var uid=obj.uid;if(typeof uid==='string'&&typeof RG.SVG.events==='object'&&typeof RG.SVG.events[uid]==='object'&&RG.SVG.events[uid].length>0){for(var j=0,len=RG.SVG.events[uid].length;j<len;++j){if(RG.SVG.events[uid][j]&&RG.SVG.events[uid][j].event===name){RG.SVG.events[uid][j].func(obj);}}}}};RG.SVG.removeAllCustomEventListeners=function()
197
+ {var uid=arguments[0];if(uid&&RG.SVG.events[uid]){RG.SVG.events[uid]={};}else{RG.SVG.events=[];}};RG.SVG.removeCustomEventListener=function(obj,i)
198
+ {if(typeof RG.SVG.events==='object'&&typeof RG.SVG.events[obj.uid]==='object'&&typeof RG.SVG.events[obj.uid][i]==='object'){RG.SVG.events[obj.uid][i]=null;}};RG.SVG.removeHighlight=function(obj)
199
+ {var highlight=RG.SVG.REG.get('highlight');if(highlight&&RG.SVG.isArray(highlight)&&highlight.length){for(var i=0,len=highlight.length;i<len;++i){if(highlight[i].parentNode){highlight[i].parentNode.removeChild(highlight[i]);}}}else if(highlight&&highlight.parentNode){if(obj.type==='scatter'){highlight.setAttribute('fill','transparent');}else{highlight.parentNode.removeChild(highlight);}}};RG.SVG.redraw=function()
200
+ {if(arguments.length===1){var svg=arguments[0];RG.SVG.clear(svg);var objects=RG.SVG.OR.get('id:'+svg.parentNode.id);for(var i=0,len=objects.length;i<len;++i){RG.SVG.resetColorsToOriginalValues({object:objects[i]});objects[i].draw();}}else{var tags=RG.SVG.OR.tags();for(var i in tags){RG.SVG.redraw(tags[i]);}}};RG.SVG.parseDate=function(str)
201
+ {var d=new Date();var defaults={seconds:'00',minutes:'00',hours:'00',date:d.getDate(),month:d.getMonth()+1,year:d.getFullYear()};var months=['january','february','march','april','may','june','july','august','september','october','november','december'],months_regex=months.join('|');for(var i=0;i<months.length;++i){months[months[i]]=i;months[months[i].substring(0,3)]=i;months_regex=months_regex+'|'+months[i].substring(0,3);}
202
+ var sep='[-./_=+~#:;,]+';var tokens=str.split(/ +/);for(var i=0,len=tokens.length;i<len;++i){if(tokens[i]){if(tokens[i].match(/^\d\d\d\d$/)){defaults.year=tokens[i];}
203
+ var res=isMonth(tokens[i]);if(typeof res==='number'){defaults.month=res+1;}
204
+ if(tokens[i].match(/^\d?\d(?:st|nd|rd|th)?$/)){defaults.date=parseInt(tokens[i]);}
205
+ if(tokens[i].match(/^(\d\d):(\d\d)(?:(\d\d))?$/)){defaults.hours=parseInt(RegExp.$1);defaults.minutes=parseInt(RegExp.$2);if(RegExp.$3){defaults.seconds=parseInt(RegExp.$3);}}
206
+ if(tokens[i].match(new RegExp('^(\\d\\d\\d\\d)'+sep+'(\\d\\d)'+sep+'(\\d\\d)$','i'))){defaults.date=parseInt(RegExp.$3);defaults.month=parseInt(RegExp.$2);defaults.year=parseInt(RegExp.$1);}
207
+ if(tokens[i].match(new RegExp('^(\\d\\d)'+sep+'(\\d\\d)'+sep+'(\\d\\d\\d\\d)$','i'))){defaults.date=parseInt(RegExp.$1);defaults.month=parseInt(RegExp.$2);defaults.year=parseInt(RegExp.$3);}}}
208
+ str='{1}/{2}/{3} {4}:{5}:{6}'.format(defaults.year,String(defaults.month).length===1?'0'+(defaults.month):defaults.month,String(defaults.date).length===1?'0'+(defaults.date):defaults.date,String(defaults.hours).length===1?'0'+(defaults.hours):defaults.hours,String(defaults.minutes).length===1?'0'+(defaults.minutes):defaults.minutes,String(defaults.seconds).length===1?'0'+(defaults.seconds):defaults.seconds);return Date.parse(str);function isMonth(str)
209
+ {var res=str.toLowerCase().match(months_regex);return res?months[res[0]]:false;}};RG.SVG.OR.add=function(obj)
210
+ {RG.SVG.OR.objects.push(obj);return obj;};RG.SVG.OR.get=function()
211
+ {if(typeof arguments[0]==='string'&&arguments[0].substr(0,3).toLowerCase()==='id:'){var ret=[];for(var i=0;i<RG.SVG.OR.objects.length;++i){if(RG.SVG.OR.objects[i].id===arguments[0].substr(3)){ret.push(RG.SVG.OR.objects[i]);}}
212
+ return ret;}
213
+ if(typeof arguments[0]==='string'&&arguments[0].substr(0,4).toLowerCase()==='type'){var ret=[];for(var i=0;i<RG.SVG.OR.objects.length;++i){if(RG.SVG.OR.objects[i].type===arguments[0].substr(5)){ret.push(RG.SVG.OR.objects[i]);}}
214
+ return ret;}
215
+ if(typeof arguments[0]==='string'&&arguments[0].substr(0,3).toLowerCase()==='uid'){var ret=[];for(var i=0;i<RG.SVG.OR.objects.length;++i){if(RG.SVG.OR.objects[i].uid===arguments[0].substr(4)){ret.push(RG.SVG.OR.objects[i]);}}
216
+ return ret;}
217
+ return RG.SVG.OR.objects;};RG.SVG.OR.tags=function()
218
+ {var tags=[];for(var i=0;i<RG.SVG.OR.objects.length;++i){if(!tags[RG.SVG.OR.objects[i].svg.parentNode.id]){tags[RG.SVG.OR.objects[i].svg.parentNode.id]=RG.SVG.OR.objects[i].svg;}}
219
+ return tags;};RG.SVG.getSVGXY=function(svg)
220
+ {var x=0,y=0,el=svg.parentNode;do{x+=el.offsetLeft;y+=el.offsetTop;if(el.tagName.toLowerCase()=='table'&&(RG.SVG.ISCHROME||RG.SVG.ISSAFARI)){x+=parseInt(el.border)||0;y+=parseInt(el.border)||0;}
221
+ el=el.offsetParent;}while(el&&el.tagName&&el.tagName.toLowerCase()!='body');var paddingLeft=svg.style.paddingLeft?parseInt(svg.style.paddingLeft):0,paddingTop=svg.style.paddingTop?parseInt(svg.style.paddingTop):0,borderLeft=svg.style.borderLeftWidth?parseInt(svg.style.borderLeftWidth):0,borderTop=svg.style.borderTopWidth?parseInt(svg.style.borderTopWidth):0;if(navigator.userAgent.indexOf('Firefox')>0){x+=parseInt(document.body.style.borderLeftWidth)||0;y+=parseInt(document.body.style.borderTopWidth)||0;}
222
+ return[x+paddingLeft+borderLeft,y+paddingTop+borderTop];};RG.SVG.FX.update=function(func)
223
+ {win.requestAnimationFrame=win.requestAnimationFrame||win.webkitRequestAnimationFrame||win.msRequestAnimationFrame||win.mozRequestAnimationFrame||(function(func){setTimeout(func,16.666);});win.requestAnimationFrame(func);};RG.SVG.FX.getEasingMultiplier=function(frames,frame)
224
+ {var multiplier=ma.pow(ma.sin((frame/frames)*RG.SVG.TRIG.HALFPI),3);return multiplier;};RG.SVG.measureText=function(opt)
225
+ {var text=opt.text||'',bold=opt.bold||false,font=opt.font||'Arial',size=opt.size||10,str=text+':'+bold+':'+font+':'+size;if(typeof RG.SVG.measuretext_cache==='undefined'){RG.SVG.measuretext_cache=[];}
226
+ if(typeof RG.SVG.measuretext_cache=='object'&&RG.SVG.measuretext_cache[str]){return RG.SVG.measuretext_cache[str];}
227
+ if(!RG.SVG.measuretext_cache['text-span']){var span=document.createElement('SPAN');span.style.position='absolute';span.style.padding=0;span.style.display='inline';span.style.top='-200px';span.style.left='-200px';span.style.lineHeight='1em';document.body.appendChild(span);RG.SVG.measuretext_cache['text-span']=span;}else if(RG.SVG.measuretext_cache['text-span']){var span=RG.SVG.measuretext_cache['text-span'];}
228
+ span.innerHTML=text.replace(/\r\n/g,'<br />');span.style.fontFamily=font;span.style.fontWeight=bold?'bold':'normal';span.style.fontSize=size+'pt';var sizes=[span.offsetWidth,span.offsetHeight];RG.SVG.measuretext_cache[str]=sizes;return sizes;};RG.SVG.stringsToNumbers=function(str)
229
+ {var sep=arguments[1]||',';if(typeof str==='number'){return str;}
230
+ if(typeof str==='string'){if(str.indexOf(sep)!=-1){str=str.split(sep);}else{str=parseFloat(str);}}
231
+ if(typeof str==='object'){for(var i=0,len=str.length;i<len;i+=1){str[i]=parseFloat(str[i]);}}
232
+ return str;};RG.SVG.getAdjustedNumber=function(opt)
233
+ {var value=opt.value,prop=opt.prop;if(typeof prop==='string'&&match(/^(\+|-)([0-9.]+)/)){if(RegExp.$1==='+'){value+=parseFloat(RegExp.$2);}else if(RegExp.$1==='-'){value-=parseFloat(RegExp.$2);}}
234
+ return value;};RG.SVG.attribution=function(){return;};RG.SVG.parseGradient=function(str)
235
+ {};RG.SVG.random=function(opt)
236
+ {var min=opt.min,max=opt.max,dp=opt.dp||opt.decimals||0,r=ma.random();return Number((((max-min)*r)+min).toFixed(dp));};RG.SVG.arrayRand=RG.SVG.arrayRandom=RG.SVG.random.array=function(opt)
237
+ {var num=opt.num,min=opt.min,max=opt.max,dp=opt.dp||opt.decimals||0;for(var i=0,arr=[];i<num;i+=1){arr.push(RG.SVG.random({min:min,max:max,dp:dp}));}
238
+ return arr;};RG.SVG.commonSetter=function(opt)
239
+ {var obj=opt.object,name=opt.name,value=opt.value;if(name==='tooltipsEvent'&&value!=='click'&&value!=='mousemove'){value='click';}
240
+ return{name:name,value:value};};RG.SVG.log=function(opt)
241
+ {var num=opt.num,base=opt.base;return ma.log(num)/(base?ma.log(base):1);};RG.SVG.donut=function(opt)
242
+ {var arcPath1=RG.SVG.TRIG.getArcPath3({cx:opt.cx,cy:opt.cy,r:opt.outerRadius,start:0,end:RG.SVG.TRIG.TWOPI,anticlockwise:false,lineto:false});var arcPath2=RG.SVG.TRIG.getArcPath3({cx:opt.cx,cy:opt.cy,r:opt.innerRadius,start:RG.SVG.TRIG.TWOPI,end:0,anticlockwise:true,lineto:false});var path=RG.SVG.create({svg:opt.svg,type:'path',attr:{d:arcPath1+arcPath2,stroke:opt.stroke,fill:opt.fill}});return path;};RG.SVG.getGlobals=function(obj)
243
+ {var prop=obj.properties;for(i in RG.SVG.GLOBALS){if(typeof i==='string'){prop[i]=RG.SVG.arrayClone(RG.SVG.GLOBALS[i]);}}};RG.SVG.link=function(opt)
244
+ {var a=RGraph.SVG.create({svg:bar.svg,type:'a',parent:bar.svg.all,attr:{'xlink:href':href,target:target}});var text=RGraph.SVG.create({svg:bar.svg,type:'text',parent:a,attr:{x:x,y:y,fill:fill}});text.innerHTML=text;};if(typeof RG.SVG.tooltip!=='function'){RG.SVG.tooltip=function()
245
+ {$a('The tooltip library has not been included!');};}})(window,document);window.$p=function(obj)
246
+ {var indent=(arguments[2]?arguments[2]:' ');var str='';var counter=typeof arguments[3]=='number'?arguments[3]:0;if(counter>=5){return'';}
247
+ switch(typeof obj){case'string':str+=obj+' ('+(typeof obj)+', '+obj.length+')';break;case'number':str+=obj+' ('+(typeof obj)+')';break;case'boolean':str+=obj+' ('+(typeof obj)+')';break;case'function':str+='function () {}';break;case'undefined':str+='undefined';break;case'null':str+='null';break;case'object':if(RGraph.SVG.isNull(obj)){str+=indent+'null\n';}else{str+=indent+'Object {'+'\n'
248
+ for(j in obj){str+=indent+' '+j+' => '+window.$p(obj[j],true,indent+' ',counter+1)+'\n';}
249
+ str+=indent+'}';}
250
+ break;default:str+='Unknown type: '+typeof obj+'';break;}
251
+ if(!arguments[1]){alert(str);}
252
+ return str;};window.$a=function(v)
253
+ {alert(v);};window.$cl=function(v)
254
+ {return console.log(v);};if(!String.prototype.format){String.prototype.format=function()
255
+ {var args=arguments;return this.replace(/{(\d+)}/g,function(str,idx)
256
+ {return typeof args[idx-1]!=='undefined'?args[idx-1]:str;});};}