amcharts.rb 3.1.1.3 → 3.2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/amcharts/chart.rb +1 -1
- data/lib/amcharts/version.rb +1 -1
- data/vendor/assets/javascripts/amcharts/amcharts.js +188 -185
- data/vendor/assets/javascripts/amcharts/changeLog.txt +37 -0
- data/vendor/assets/javascripts/amcharts/exporting/amexport.js +623 -0
- data/vendor/assets/javascripts/amcharts/exporting/canvg.js +2842 -0
- data/vendor/assets/javascripts/amcharts/exporting/filesaver.js +232 -0
- data/vendor/assets/javascripts/amcharts/exporting/jspdf.js +1943 -0
- data/vendor/assets/javascripts/amcharts/exporting/jspdf.plugin.addimage.js +230 -0
- data/vendor/assets/javascripts/amcharts/exporting/rgbcolor.js +288 -0
- data/vendor/assets/javascripts/amcharts/gauge.js +10 -8
- data/vendor/assets/javascripts/amcharts/pie.js +1 -1
- data/vendor/assets/javascripts/amcharts/serial.js +20 -20
- data/vendor/assets/javascripts/amcharts/thirdPartySoftwareList.txt +28 -5
- data/vendor/assets/javascripts/amcharts/xy.js +7 -6
- metadata +8 -2
@@ -1,3 +1,40 @@
|
|
1
|
+
#### 3.2.0 ####################################################################################################################
|
2
|
+
|
3
|
+
|
4
|
+
# AmCharts.makeChart(divID, chartConfig); method added. divID is id of a div where your chart should appear. chartConfig is
|
5
|
+
JSON object with chart configuration. Check examples with _JSON_ prefix in samples folder to see this in action.
|
6
|
+
|
7
|
+
# type property added to AmChart class. It is required to specify type to one of the following, when creating charts from
|
8
|
+
JSON config: serial, xy, radar, pie, gauge, funnel, map, stock
|
9
|
+
|
10
|
+
# a possibility to export charts as image/pdf/svg added for all modern browsers except IE9 (IE10 is supported). The
|
11
|
+
exporting doesn't require any server side software and is made using js libraries only. Check samples with
|
12
|
+
_exporting_ prefix to see this in action. Exporting to SVG doesn't work very properly with stock chart or charts with
|
13
|
+
legend (will offer saving multiple files).
|
14
|
+
|
15
|
+
# You can set any legend items via legend.data property, for example:
|
16
|
+
legend.data = [{title:"first", color:"#CC0000", value:50}, {title:"second", color:"#00CC00", value:100}];
|
17
|
+
This allows creating any legend items you want. Call chart.legend.validateNow(); if you change legend's data at run time.
|
18
|
+
|
19
|
+
# AmAngularGauge supports legend now
|
20
|
+
|
21
|
+
# bug fix - if a chart with scrollbar was rotated after the chart is created, the scrollbar's graph was shifted to a wrong
|
22
|
+
position.
|
23
|
+
|
24
|
+
# bug fix - column graph type wasn't displayed in chart scrollbar (since 3.1.0)
|
25
|
+
|
26
|
+
# gridAboveGraphs property added to AmCoordinate chart. This allow to show grid lines above your graphs, as world-famous
|
27
|
+
data visualization guru Edward Tufte suggests. Note, this won't work properly with 3D charts.
|
28
|
+
|
29
|
+
# negative axis labels rotation possible. You can use values from -90 to -1 for labelRotation property since now.
|
30
|
+
|
31
|
+
# bug fix: step line with changing line color was rendered incorrectly if some values were missing.
|
32
|
+
|
33
|
+
# bug fix: labelPosition "inside" and "middle" for bar charts fixed.
|
34
|
+
|
35
|
+
# bug fix: AmAngularGauge chart wasn't firing "rendered" event.
|
36
|
+
|
37
|
+
|
1
38
|
#### 3.1.1 ####################################################################################################################
|
2
39
|
|
3
40
|
# FireFox error messages about style declarations fixed
|
@@ -0,0 +1,623 @@
|
|
1
|
+
AmCharts.AmExport = AmCharts.Class({
|
2
|
+
construct: function (chart,cfg) {
|
3
|
+
var _this = this;
|
4
|
+
_this.DEBUG = false;
|
5
|
+
_this.chart = chart;
|
6
|
+
_this.canvas = null;
|
7
|
+
_this.svgs = [];
|
8
|
+
_this.cfg = {
|
9
|
+
menuTop : 'auto',
|
10
|
+
menuLeft : 'auto',
|
11
|
+
menuRight : '0px',
|
12
|
+
menuBottom : '0px',
|
13
|
+
menuItems : [{
|
14
|
+
textAlign : 'center',
|
15
|
+
icon : _this.chart.pathToImages + 'export.png',
|
16
|
+
iconTitle : 'Save chart as an image',
|
17
|
+
format : 'png'
|
18
|
+
}],
|
19
|
+
menuItemStyle : {
|
20
|
+
backgroundColor : 'transparent',
|
21
|
+
rollOverBackgroundColor : '#EFEFEF',
|
22
|
+
color : '#000000',
|
23
|
+
rollOverColor : '#CC0000',
|
24
|
+
paddingTop : '6px',
|
25
|
+
paddingRight : '6px',
|
26
|
+
paddingBottom : '6px',
|
27
|
+
paddingLeft : '6px',
|
28
|
+
marginTop : '0px',
|
29
|
+
marginRight : '0px',
|
30
|
+
marginBottom : '0px',
|
31
|
+
marginLeft : '0px',
|
32
|
+
textAlign : 'left',
|
33
|
+
textDecoration : 'none',
|
34
|
+
fontFamily : _this.chart.fontFamily,
|
35
|
+
fontSize : _this.chart.fontSize + 'px'
|
36
|
+
},
|
37
|
+
menuItemOutput : {
|
38
|
+
backgroundColor : '#FFFFFF',
|
39
|
+
fileName : 'amChart',
|
40
|
+
format : 'png',
|
41
|
+
output : 'dataurlnewwindow',
|
42
|
+
render : 'browser',
|
43
|
+
dpi : 90,
|
44
|
+
onclick : function(instance,config,event) {
|
45
|
+
instance.output(config);
|
46
|
+
}
|
47
|
+
},
|
48
|
+
removeImagery : true
|
49
|
+
};
|
50
|
+
_this.processing = {
|
51
|
+
buffer : [],
|
52
|
+
drawn : 0,
|
53
|
+
timer : 0
|
54
|
+
}
|
55
|
+
|
56
|
+
// Config dependency adaption
|
57
|
+
if ( typeof(window.canvg) != 'undefined' && typeof(window.RGBColor) != 'undefined' ) {
|
58
|
+
_this.cfg.menuItemOutput.render = 'canvg';
|
59
|
+
}
|
60
|
+
if ( typeof(window.saveAs) != 'undefined' ) {
|
61
|
+
_this.cfg.menuItemOutput.output = 'save';
|
62
|
+
}
|
63
|
+
if ( AmCharts.isIE && AmCharts.IEversion < 10 ) {
|
64
|
+
_this.cfg.menuItemOutput.output = 'dataurlnewwindow';
|
65
|
+
}
|
66
|
+
|
67
|
+
// Merge given configs
|
68
|
+
if ( cfg ) {
|
69
|
+
cfg.menuItemOutput = AmCharts.extend(_this.cfg.menuItemOutput,cfg.menuItemOutput || {});
|
70
|
+
cfg.menuItemStyle = AmCharts.extend(_this.cfg.menuItemStyle,cfg.menuItemStyle || {});
|
71
|
+
_this.cfg = AmCharts.extend(_this.cfg,cfg);
|
72
|
+
}
|
73
|
+
|
74
|
+
// Add reference to chart
|
75
|
+
_this.chart.AmExport = _this;
|
76
|
+
|
77
|
+
// Listen to the drawer
|
78
|
+
_this.chart.addListener('rendered',function() {
|
79
|
+
_this.setup();
|
80
|
+
});
|
81
|
+
|
82
|
+
// DEBUG; Public reference
|
83
|
+
if ( _this.DEBUG ) { window.AmExport = _this };
|
84
|
+
},
|
85
|
+
|
86
|
+
/*
|
87
|
+
Simple log function for internal purpose
|
88
|
+
@param **args
|
89
|
+
*/
|
90
|
+
log: function() {
|
91
|
+
console.log('AmExport: ',arguments);
|
92
|
+
},
|
93
|
+
|
94
|
+
/* PUBLIC
|
95
|
+
Prepares everything to get exported
|
96
|
+
@param none
|
97
|
+
*/
|
98
|
+
setup: function() {
|
99
|
+
var _this = this;
|
100
|
+
|
101
|
+
if ( _this.DEBUG == 10 ) { _this.log('SETUP START'); } // DEBUG
|
102
|
+
|
103
|
+
|
104
|
+
if ( !AmCharts.isIE || ( AmCharts.isIE && AmCharts.IEversion > 9 ) ) {
|
105
|
+
window.clearTimeout(_this.processing.timer);
|
106
|
+
_this.processing.timer = setTimeout(function() {
|
107
|
+
// Polify SVG; needs to wait
|
108
|
+
_this.polifySVG();
|
109
|
+
|
110
|
+
// Build Buttons
|
111
|
+
_this.generateButtons();
|
112
|
+
if ( _this.DEBUG == 10 ) { _this.log('SETUP END'); } // DEBUG
|
113
|
+
},1000);
|
114
|
+
} else {
|
115
|
+
if ( _this.DEBUG == 10 ) { _this.log('< IE10 NOT SUPPORTED'); } // DEBUG
|
116
|
+
}
|
117
|
+
},
|
118
|
+
|
119
|
+
/* PUBLIC
|
120
|
+
Decodes base64 string to binary array
|
121
|
+
@param base64_string
|
122
|
+
@copyright Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
|
123
|
+
*/
|
124
|
+
generateBinaryArray: function(base64_string) {
|
125
|
+
var
|
126
|
+
len = base64_string.length
|
127
|
+
, buffer = new Uint8Array(len / 4 * 3 | 0)
|
128
|
+
, i = 0
|
129
|
+
, outptr = 0
|
130
|
+
, last = [0, 0]
|
131
|
+
, state = 0
|
132
|
+
, save = 0
|
133
|
+
, rank
|
134
|
+
, code
|
135
|
+
, undef
|
136
|
+
, base64_ranks = new Uint8Array([
|
137
|
+
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1
|
138
|
+
, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
139
|
+
, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
|
140
|
+
, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
|
141
|
+
, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
142
|
+
]);
|
143
|
+
while (len--) {
|
144
|
+
code = base64_string.charCodeAt(i++);
|
145
|
+
rank = base64_ranks[code-43];
|
146
|
+
if (rank !== 255 && rank !== undef) {
|
147
|
+
last[1] = last[0];
|
148
|
+
last[0] = code;
|
149
|
+
save = (save << 6) | rank;
|
150
|
+
state++;
|
151
|
+
if (state === 4) {
|
152
|
+
buffer[outptr++] = save >>> 16;
|
153
|
+
if (last[1] !== 61 /* padding character */) {
|
154
|
+
buffer[outptr++] = save >>> 8;
|
155
|
+
}
|
156
|
+
if (last[0] !== 61 /* padding character */) {
|
157
|
+
buffer[outptr++] = save;
|
158
|
+
}
|
159
|
+
state = 0;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
// 2/3 chance there's going to be some null bytes at the end, but that
|
164
|
+
// doesn't really matter with most image formats.
|
165
|
+
// If it somehow matters for you, truncate the buffer up outptr.
|
166
|
+
return buffer;
|
167
|
+
},
|
168
|
+
|
169
|
+
/*
|
170
|
+
Creates blob object
|
171
|
+
@param base64_datastring string
|
172
|
+
@param type string
|
173
|
+
*/
|
174
|
+
generateBlob: function(datastring,type) {
|
175
|
+
var _this = this,
|
176
|
+
header_end = datastring.indexOf(',') + 1,
|
177
|
+
header = datastring.substring(0,header_end),
|
178
|
+
data = datastring,
|
179
|
+
blob = new Blob();
|
180
|
+
|
181
|
+
if ( header.indexOf('base64') != -1 ) {
|
182
|
+
data = _this.generateBinaryArray(datastring.substring(header_end));
|
183
|
+
}
|
184
|
+
|
185
|
+
// Fake blob for IE
|
186
|
+
if ( AmCharts.isIE && AmCharts.IEversion < 10 ) {
|
187
|
+
blob.data = data;
|
188
|
+
blob.size = data.length;
|
189
|
+
blob.type = type;
|
190
|
+
blob.encoding = 'base64';
|
191
|
+
} else {
|
192
|
+
blob = new Blob([data],{type: type});
|
193
|
+
}
|
194
|
+
return blob
|
195
|
+
},
|
196
|
+
|
197
|
+
/*
|
198
|
+
Creates PDF object
|
199
|
+
@param config object
|
200
|
+
*/
|
201
|
+
generatePDF: function(cfg) {
|
202
|
+
var _this = this,
|
203
|
+
pdf = {output: function() {return ''}},
|
204
|
+
data = _this.canvas.toDataURL('image/jpeg'), // JSPDF ONLY SUPPORTS JPG
|
205
|
+
width = (_this.canvas.width * 25.4) / cfg.dpi,
|
206
|
+
height = (_this.canvas.height * 25.4) / cfg.dpi;
|
207
|
+
|
208
|
+
// Check
|
209
|
+
if ( window.jsPDF ) {
|
210
|
+
pdf = new jsPDF();
|
211
|
+
if ( pdf.addImage ) {
|
212
|
+
pdf.addImage(data, 'JPEG', 0, 0, width, height);
|
213
|
+
} else {
|
214
|
+
alert("Missing jsPDF plugin; Please add the 'addImage' plugin.");
|
215
|
+
}
|
216
|
+
} else {
|
217
|
+
alert("Missing jsPDF lib; Don't forget to add the addImage plugin.");
|
218
|
+
}
|
219
|
+
|
220
|
+
return pdf;
|
221
|
+
},
|
222
|
+
|
223
|
+
/*
|
224
|
+
Creates the CANVAS to receive the image data
|
225
|
+
@param format void()
|
226
|
+
@param callback; given callback function which returns the blob or datastring of the configured ouput type
|
227
|
+
*/
|
228
|
+
output: function(cfg,externalCallback) {
|
229
|
+
var _this = this,
|
230
|
+
cfg = AmCharts.extend(AmCharts.extend({},_this.cfg.menuItemOutput),cfg||{});
|
231
|
+
|
232
|
+
/* PRIVATE
|
233
|
+
Callback function which gets called after the drawing process is done
|
234
|
+
@param none
|
235
|
+
*/
|
236
|
+
function internalCallback() {
|
237
|
+
var data = null;
|
238
|
+
if ( _this.DEBUG == 10 ) { _this.log('OUTPUT',format); } // DEBUG
|
239
|
+
|
240
|
+
// SVG
|
241
|
+
if ( cfg.format == 'image/svg+xml' || cfg.format == 'svg' ) {
|
242
|
+
for ( var i = 0; i < _this.processing.buffer.length; i++ ) {
|
243
|
+
data = new XMLSerializer().serializeToString(_this.processing.buffer[i][0]),
|
244
|
+
blob = _this.generateBlob(data,'image/svg+xml');
|
245
|
+
|
246
|
+
if ( cfg.output == 'save' ) {
|
247
|
+
saveAs(blob, cfg.fileName + '.svg');
|
248
|
+
} else if ( cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring' ) {
|
249
|
+
blob = 'data:image/svg+xml;base64,' + btoa(data);
|
250
|
+
} else if ( cfg.output == 'dataurlnewwindow' ) {
|
251
|
+
window.open('data:image/svg+xml;base64,' + btoa(data));
|
252
|
+
} else if ( cfg.output == 'datauri' || cfg.output == 'dataurl' ) {
|
253
|
+
location.href = 'data:image/svg+xml;base64,' + btoa(data);
|
254
|
+
} else if ( cfg.output == 'datastream' ) {
|
255
|
+
location.href = 'data:image/octet-stream;base64,' + btoa(data);
|
256
|
+
}
|
257
|
+
|
258
|
+
if ( externalCallback )
|
259
|
+
externalCallback.apply(_this,[blob]);
|
260
|
+
}
|
261
|
+
// PDF
|
262
|
+
} else if ( cfg.format == 'application/pdf' || cfg.format == 'pdf' ) {
|
263
|
+
data = _this.generatePDF(cfg).output('dataurlstring'),
|
264
|
+
blob = _this.generateBlob(data,'application/pdf');
|
265
|
+
|
266
|
+
if ( cfg.output == 'save' ) {
|
267
|
+
saveAs(blob, cfg.fileName + '.pdf');
|
268
|
+
} else if ( cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring' ) {
|
269
|
+
blob = data;
|
270
|
+
} else if ( cfg.output == 'dataurlnewwindow' ) {
|
271
|
+
window.open(data);
|
272
|
+
} else if ( cfg.output == 'datauri' || cfg.output == 'dataurl' ) {
|
273
|
+
location.href = data;
|
274
|
+
} else if ( cfg.output == 'datastream' ) {
|
275
|
+
location.href = data.replace('application/pdf','application/octet-stream');
|
276
|
+
}
|
277
|
+
|
278
|
+
if ( externalCallback )
|
279
|
+
externalCallback.apply(_this,[blob]);
|
280
|
+
|
281
|
+
// PNG
|
282
|
+
} else if ( cfg.format == 'image/png' || cfg.format == 'png' ) {
|
283
|
+
data = _this.canvas.toDataURL('image/png'),
|
284
|
+
blob = _this.generateBlob(data,'image/png');
|
285
|
+
|
286
|
+
if ( cfg.output == 'save' ) {
|
287
|
+
saveAs(blob, cfg.fileName + '.png');
|
288
|
+
} else if ( cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring' ) {
|
289
|
+
blob = data;
|
290
|
+
} else if ( cfg.output == 'dataurlnewwindow' ) {
|
291
|
+
window.open(data);
|
292
|
+
} else if ( cfg.output == 'datauri' || cfg.output == 'dataurl' ) {
|
293
|
+
location.href = data;
|
294
|
+
} else if ( cfg.output == 'datastream' ) {
|
295
|
+
location.href = data.replace('image/png','image/octet-stream');
|
296
|
+
}
|
297
|
+
|
298
|
+
if ( externalCallback )
|
299
|
+
externalCallback.apply(_this,[blob]);
|
300
|
+
|
301
|
+
// JPG
|
302
|
+
} else if ( cfg.format == 'image/jpeg' || cfg.format == 'jpeg' || cfg.format == 'jpg' ) {
|
303
|
+
data = _this.canvas.toDataURL('image/jpeg'),
|
304
|
+
blob = _this.generateBlob(data,'image/jpeg');
|
305
|
+
|
306
|
+
if ( cfg.output == 'save' ) {
|
307
|
+
saveAs(blob, cfg.fileName + '.jpg');
|
308
|
+
} else if ( cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring' ) {
|
309
|
+
blob = data;
|
310
|
+
} else if ( cfg.output == 'dataurlnewwindow' ) {
|
311
|
+
window.open(data);
|
312
|
+
} else if ( cfg.output == 'datauri' || cfg.output == 'dataurl' ) {
|
313
|
+
location.href = data;
|
314
|
+
} else if ( cfg.output == 'datastream' ) {
|
315
|
+
location.href = data.replace('image/jpeg','image/octet-stream');
|
316
|
+
}
|
317
|
+
|
318
|
+
if ( externalCallback )
|
319
|
+
externalCallback.apply(_this,[blob]);
|
320
|
+
}
|
321
|
+
|
322
|
+
}
|
323
|
+
|
324
|
+
return _this.generateOutput(cfg,internalCallback);
|
325
|
+
},
|
326
|
+
|
327
|
+
/* PUBLIC
|
328
|
+
Polifies missing attributes to the SVG and replaces images to embedded base64 images
|
329
|
+
@param none
|
330
|
+
*/
|
331
|
+
polifySVG: function() {
|
332
|
+
var _this = this;
|
333
|
+
var svgs = _this.chart.div.getElementsByTagName('svg');
|
334
|
+
|
335
|
+
// Recursive function to force the attributes
|
336
|
+
function recursiveChange(svg,tag) {
|
337
|
+
var items = svg.getElementsByTagName(tag);
|
338
|
+
|
339
|
+
for ( var i = 0; i < items.length; i++) {
|
340
|
+
|
341
|
+
if ( _this.cfg.removeImagery ) {
|
342
|
+
items[i].parentNode.removeChild(items[i]);
|
343
|
+
|
344
|
+
} else {
|
345
|
+
var image = document.createElement('img');
|
346
|
+
var canvas = document.createElement('canvas');
|
347
|
+
var ctx = canvas.getContext('2d');
|
348
|
+
|
349
|
+
canvas.width = items[i].getAttribute('width');
|
350
|
+
canvas.height = items[i].getAttribute('height');
|
351
|
+
image.src = items[i].getAttribute('xlink:href');
|
352
|
+
image.width = items[i].getAttribute('width');
|
353
|
+
image.height = items[i].getAttribute('height');
|
354
|
+
|
355
|
+
try {
|
356
|
+
ctx.drawImage(image,0,0,image.width,image.height);
|
357
|
+
datastring = canvas.toDataURL(); // image.src; // canvas.toDataURL(); //
|
358
|
+
} catch(err) {
|
359
|
+
datastring = image.src; // image.src; // canvas.toDataURL(); //
|
360
|
+
|
361
|
+
_this.log('Tainted canvas, reached browser CORS security; origin from imagery must be equal to the server!');
|
362
|
+
throw new Error(err);
|
363
|
+
}
|
364
|
+
|
365
|
+
items[i].setAttribute('xlink:href',datastring);
|
366
|
+
}
|
367
|
+
|
368
|
+
if ( _this.DEBUG == 10 ) { _this.log('POLIFIED',items[i]); } // DEBUG
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
// Loop through svgs to add some standardization
|
373
|
+
for ( var i = 0; i < svgs.length; i++ ) {
|
374
|
+
var parent = svgs[i].parentNode;
|
375
|
+
|
376
|
+
// Put some attrs to it
|
377
|
+
/*
|
378
|
+
if ( !AmCharts.isIE ) {
|
379
|
+
svgs[i].setAttribute('xmlns','http://www.w3.org/2000/svg');
|
380
|
+
svgs[i].setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
381
|
+
}
|
382
|
+
svgs[i].setAttribute('width',parent.style.width);
|
383
|
+
svgs[i].setAttribute('height',parent.style.height);
|
384
|
+
*/
|
385
|
+
|
386
|
+
if ( _this.DEBUG == 10 ) { _this.log('POLIFIED',svgs[i]); } // DEBUG
|
387
|
+
|
388
|
+
// Force link adaption
|
389
|
+
recursiveChange(svgs[i],'pattern');
|
390
|
+
recursiveChange(svgs[i],'image');
|
391
|
+
|
392
|
+
_this.svgs.push(svgs[i]);
|
393
|
+
}
|
394
|
+
|
395
|
+
return svgs;
|
396
|
+
},
|
397
|
+
|
398
|
+
/* PUBLIC
|
399
|
+
Generates the canvas with the given SVGs and configured renderer
|
400
|
+
@param callback; function(); gets called after drawing process on the canvas has been finished
|
401
|
+
*/
|
402
|
+
generateOutput: function(cfg,callback) {
|
403
|
+
var _this = this,
|
404
|
+
svgs = _this.chart.div.getElementsByTagName('svg'),
|
405
|
+
canvas = document.createElement('canvas'),
|
406
|
+
context = canvas.getContext('2d'),
|
407
|
+
offset = {
|
408
|
+
y: 0,
|
409
|
+
x: 0
|
410
|
+
},
|
411
|
+
tmp = {};
|
412
|
+
|
413
|
+
// Reset
|
414
|
+
_this.processing.buffer = [];
|
415
|
+
_this.processing.drawn = 0;
|
416
|
+
_this.canvas = canvas;
|
417
|
+
|
418
|
+
// Walkthroug SVGs
|
419
|
+
if ( _this.DEBUG == 10 ) { _this.log('START EXPORT'); } // DEBUG
|
420
|
+
if ( _this.DEBUG == 10 ) { _this.log('START BUFFERING'); } // DEBUG
|
421
|
+
for ( var i = 0; i < svgs.length; i++ ) {
|
422
|
+
var parent = svgs[i].parentNode,
|
423
|
+
svgX = Number(parent.style.left.slice(0,-2)),
|
424
|
+
svgY = Number(parent.style.top.slice(0,-2));
|
425
|
+
tmp = AmCharts.extend({},offset);
|
426
|
+
|
427
|
+
// Overtake parent position if givwn
|
428
|
+
offset.x = svgX?svgX:offset.x;
|
429
|
+
offset.y = svgY?svgY:offset.y;
|
430
|
+
|
431
|
+
_this.processing.buffer.push([svgs[i],AmCharts.extend({},offset)]);
|
432
|
+
|
433
|
+
// Put back from "cache"
|
434
|
+
if ( svgY&&svgX ) {
|
435
|
+
offset = tmp;
|
436
|
+
|
437
|
+
// New offset for next one
|
438
|
+
} else {
|
439
|
+
offset.y += svgY?0:parent.offsetHeight;
|
440
|
+
}
|
441
|
+
|
442
|
+
if ( _this.DEBUG == 10 ) { _this.log('BUFFERED',svgs[i],offset); } // DEBUG
|
443
|
+
}
|
444
|
+
if ( _this.DEBUG == 10 ) { _this.log('END BUFFERING'); } // DEBUG
|
445
|
+
|
446
|
+
// Apply background
|
447
|
+
if ( _this.DEBUG == 10 ) { _this.log('START DRAWING',cfg.render); } // DEBUG
|
448
|
+
if ( _this.DEBUG == 10 ) { _this.log('FILL BACKGROUND'); } // DEBUG
|
449
|
+
canvas.id = AmCharts.getUniqueId();
|
450
|
+
canvas.width = _this.chart.divRealWidth;
|
451
|
+
canvas.height = _this.chart.divRealHeight;
|
452
|
+
|
453
|
+
// Set given background; jpeg default
|
454
|
+
if ( cfg.backgroundColor || format == 'image/jpeg' ) {
|
455
|
+
context.fillStyle = cfg.backgroundColor || '#FFFFFF';
|
456
|
+
context.fillRect(0,0,canvas.width,canvas.height);
|
457
|
+
}
|
458
|
+
|
459
|
+
/* PRIVATE
|
460
|
+
Recursive function to draw the images to the canvas;
|
461
|
+
@param none;
|
462
|
+
*/
|
463
|
+
function drawItWhenItsLoaded() {
|
464
|
+
var img,buffer,offset,source;
|
465
|
+
|
466
|
+
// DRAWING PROCESS DONE
|
467
|
+
if ( _this.processing.buffer.length == _this.processing.drawn ) {
|
468
|
+
if ( _this.DEBUG == 10 ) { _this.log('END DRAWING'); } // DEBUG
|
469
|
+
return callback();
|
470
|
+
|
471
|
+
// LOOPING LUI
|
472
|
+
} else {
|
473
|
+
if ( _this.DEBUG == 10 ) { _this.log('DRAW',_this.processing.drawn + 1,'OF',_this.processing.buffer.length); } // DEBUG
|
474
|
+
|
475
|
+
buffer = _this.processing.buffer[_this.processing.drawn];
|
476
|
+
source = new XMLSerializer().serializeToString(buffer[0]); //source = 'data:image/svg+xml;base64,' + btoa();
|
477
|
+
offset = buffer[1];
|
478
|
+
|
479
|
+
if ( _this.DEBUG == 10 ) { _this.log('SOURCE',source); } // DEBUG
|
480
|
+
|
481
|
+
// NATIVE
|
482
|
+
if ( cfg.render == 'browser' ) {
|
483
|
+
img = new Image();
|
484
|
+
img.id = AmCharts.getUniqueId();
|
485
|
+
source = 'data:image/svg+xml;base64,' + btoa(source);
|
486
|
+
|
487
|
+
//img.crossOrigin = "Anonymous";
|
488
|
+
img.onload = function() {
|
489
|
+
context.drawImage(this,buffer[1].x,buffer[1].y);
|
490
|
+
_this.processing.drawn++;
|
491
|
+
|
492
|
+
if ( _this.DEBUG == 10 ) { _this.log('ONLOAD',this); } // DEBUG
|
493
|
+
drawItWhenItsLoaded();
|
494
|
+
}
|
495
|
+
img.onerror = function() {
|
496
|
+
if ( _this.DEBUG == 10 ) { _this.log('ONERROR',this); } // DEBUG
|
497
|
+
context.drawImage(this,buffer[1].x,buffer[1].y);
|
498
|
+
_this.processing.drawn++;
|
499
|
+
drawItWhenItsLoaded();
|
500
|
+
}
|
501
|
+
img.src = source;
|
502
|
+
|
503
|
+
if ( _this.DEBUG == 10 ) { _this.log('ADD',img); } // DEBUG
|
504
|
+
if ( img.complete || typeof(img.complete) == 'undefined' || img.complete === undefined ) {
|
505
|
+
if ( _this.DEBUG == 10 ) { _this.log('FORCE ONLOAD',img); } // DEBUG
|
506
|
+
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
|
507
|
+
img.src = source;
|
508
|
+
}
|
509
|
+
|
510
|
+
// CANVG
|
511
|
+
} else if ( cfg.render == 'canvg' ) {
|
512
|
+
canvg(canvas,source,{
|
513
|
+
offsetX : offset.x,
|
514
|
+
offsetY : offset.y,
|
515
|
+
ignoreMouse : true,
|
516
|
+
ignoreAnimation : true,
|
517
|
+
ignoreDimensions : true,
|
518
|
+
ignoreClear : true,
|
519
|
+
renderCallback : function() {
|
520
|
+
_this.processing.drawn++;
|
521
|
+
drawItWhenItsLoaded();
|
522
|
+
}
|
523
|
+
});
|
524
|
+
}
|
525
|
+
}
|
526
|
+
}
|
527
|
+
return drawItWhenItsLoaded();
|
528
|
+
},
|
529
|
+
|
530
|
+
/*
|
531
|
+
Generates the export menu to trigger the exportation
|
532
|
+
@param none;
|
533
|
+
*/
|
534
|
+
generateButtons: function() {
|
535
|
+
var _this = this,
|
536
|
+
div = document.createElement('div'),
|
537
|
+
lvl = 0;
|
538
|
+
|
539
|
+
// Push sublings
|
540
|
+
function createList(items) {
|
541
|
+
var ul = document.createElement('ul');
|
542
|
+
|
543
|
+
ul.setAttribute('style','list-style: none; margin: 0; padding: 0;');
|
544
|
+
|
545
|
+
// Walkthrough items
|
546
|
+
for ( var i = 0; i < items.length; i++ ) {
|
547
|
+
var li = document.createElement('li'),
|
548
|
+
img = document.createElement('img'),
|
549
|
+
a = document.createElement('a'),
|
550
|
+
item = items[i],
|
551
|
+
children = null,
|
552
|
+
itemStyle = AmCharts.extend(AmCharts.extend({},_this.cfg.menuItemStyle),items[i]);
|
553
|
+
|
554
|
+
// MERGE CFG
|
555
|
+
item = AmCharts.extend(AmCharts.extend({},_this.cfg.menuItemOutput),item);
|
556
|
+
|
557
|
+
// ICON
|
558
|
+
if ( item['icon'] ) {
|
559
|
+
img.alt = '';
|
560
|
+
img.src = item['icon'];
|
561
|
+
img.setAttribute('style','margin: 0 auto;border: none;outline: none');
|
562
|
+
if ( item['iconTitle'] ) {
|
563
|
+
img.title=item['iconTitle'];
|
564
|
+
}
|
565
|
+
a.appendChild(img);
|
566
|
+
}
|
567
|
+
|
568
|
+
// TITLE; STYLING
|
569
|
+
a.href = '#';
|
570
|
+
if ( item['title'] ) {
|
571
|
+
img.setAttribute('style','margin-right: 5px;');
|
572
|
+
a.innerHTML += item.title;
|
573
|
+
}
|
574
|
+
a.setAttribute('style','display: block;');
|
575
|
+
AmCharts.extend(a.style,itemStyle)
|
576
|
+
|
577
|
+
// ONCLICK
|
578
|
+
a.onclick = item.onclick.bind(a,_this,item);
|
579
|
+
li.appendChild(a);
|
580
|
+
|
581
|
+
// APPEND SIBLINGS
|
582
|
+
if ( item.items ) {
|
583
|
+
children = createList(item.items);
|
584
|
+
li.appendChild(children);
|
585
|
+
|
586
|
+
li.onmouseover = function() {
|
587
|
+
children.style.display = 'block';
|
588
|
+
}
|
589
|
+
li.onmouseout = function() {
|
590
|
+
children.style.display = 'none';
|
591
|
+
}
|
592
|
+
children.style.display = 'none';
|
593
|
+
}
|
594
|
+
|
595
|
+
// Append to parent
|
596
|
+
ul.appendChild(li);
|
597
|
+
|
598
|
+
// Apply hover
|
599
|
+
a.onmouseover = function() {
|
600
|
+
this.style.backgroundColor = itemStyle.rollOverBackgroundColor;
|
601
|
+
this.style.color = itemStyle.rollOverColor;
|
602
|
+
this.style.borderColor = itemStyle.rollOverBorderColor;
|
603
|
+
}
|
604
|
+
a.onmouseout = function() {
|
605
|
+
this.style.backgroundColor = itemStyle.backgroundColor;
|
606
|
+
this.style.color = itemStyle.color;
|
607
|
+
this.style.borderColor = itemStyle.borderColor;
|
608
|
+
}
|
609
|
+
}
|
610
|
+
lvl++;
|
611
|
+
|
612
|
+
if ( _this.DEBUG == 10 ) { _this.log('MENU',ul); } // DEBUG
|
613
|
+
|
614
|
+
return ul;
|
615
|
+
}
|
616
|
+
|
617
|
+
// Style wrapper; Push into chart div
|
618
|
+
div.setAttribute('style','position: absolute;top:'+ _this.cfg.menuTop +';right:'+ _this.cfg.menuRight +';bottom:'+ _this.cfg.menuBottom +';left:'+ _this.cfg.menuLeft +';box-shadow:0px 0px 1px 0px rgba(0,0,0,0);');
|
619
|
+
div.appendChild(createList(_this.cfg.menuItems));
|
620
|
+
_this.chart.div.style.position = 'relative';
|
621
|
+
_this.chart.div.appendChild(div);
|
622
|
+
}
|
623
|
+
});
|