rgraph-rails 4.62 → 4.64

Sign up to get free protection for your applications and to get access to all the features.
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;});};}