amcharts.rb 3.11.2.14 → 3.11.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/.travis.yml +12 -0
- data/README.md +1 -1
- data/amcharts.rb.gemspec +12 -5
- data/lib/amcharts/chart.rb +22 -2
- data/lib/amcharts/settings.rb +2 -2
- data/lib/amcharts/version.rb +1 -1
- data/spec/chart_spec.rb +96 -11
- data/vendor/assets/javascripts/amcharts/amcharts.js +380 -380
- data/vendor/assets/javascripts/amcharts/amstock.js +97 -97
- data/vendor/assets/javascripts/amcharts/changeLog.txt +1070 -1070
- data/vendor/assets/javascripts/amcharts/exporting/amexport.js +854 -854
- data/vendor/assets/javascripts/amcharts/exporting/canvg.js +2841 -2841
- data/vendor/assets/javascripts/amcharts/exporting/rgbcolor.js +288 -288
- data/vendor/assets/javascripts/amcharts/funnel.js +16 -16
- data/vendor/assets/javascripts/amcharts/gauge.js +19 -19
- data/vendor/assets/javascripts/amcharts/lang/de.js +12 -12
- data/vendor/assets/javascripts/amcharts/licence.txt +15 -15
- data/vendor/assets/javascripts/amcharts/pie.js +9 -9
- data/vendor/assets/javascripts/amcharts/radar.js +9 -9
- data/vendor/assets/javascripts/amcharts/serial.js +56 -56
- data/vendor/assets/javascripts/amcharts/themes/black.js +205 -205
- data/vendor/assets/javascripts/amcharts/themes/chalk.js +216 -216
- data/vendor/assets/javascripts/amcharts/themes/dark.js +204 -204
- data/vendor/assets/javascripts/amcharts/themes/light.js +198 -198
- data/vendor/assets/javascripts/amcharts/themes/patterns.js +258 -258
- data/vendor/assets/javascripts/amcharts/thirdPartySoftwareList.txt +33 -33
- data/vendor/assets/javascripts/amcharts/xy.js +16 -16
- metadata +69 -49
@@ -1,855 +1,855 @@
|
|
1
|
-
AmCharts.AmExport = AmCharts.Class({
|
2
|
-
construct: function(chart, cfg, init ) {
|
3
|
-
var _this = this;
|
4
|
-
_this.DEBUG = false;
|
5
|
-
_this.chart = chart;
|
6
|
-
_this.canvas = null;
|
7
|
-
_this.svgs = [];
|
8
|
-
_this.userCFG = cfg;
|
9
|
-
|
10
|
-
_this.buttonIcon = 'export.png';
|
11
|
-
_this.exportPNG = true;
|
12
|
-
_this.exportPDF = false;
|
13
|
-
_this.exportJPG = false;
|
14
|
-
_this.exportSVG = false;
|
15
|
-
//_this.left;
|
16
|
-
_this.right = 0;
|
17
|
-
//_this.bottom;
|
18
|
-
_this.top = 0;
|
19
|
-
//_this.color;
|
20
|
-
_this.buttonRollOverColor = "#EFEFEF";
|
21
|
-
//_this.buttonColor = "#FFFFFF";
|
22
|
-
//_this.buttonRollOverAlpha = 0.5;
|
23
|
-
_this.textRollOverColor = "#CC0000";
|
24
|
-
_this.buttonTitle = "Save chart as an image";
|
25
|
-
_this.buttonAlpha = 0.75;
|
26
|
-
_this.imageFileName = "amChart";
|
27
|
-
_this.imageBackgroundColor = "#FFFFFF";
|
28
|
-
|
29
|
-
if (init) {
|
30
|
-
_this.init();
|
31
|
-
}
|
32
|
-
},
|
33
|
-
|
34
|
-
toCoordinate:function(value){
|
35
|
-
if(value === undefined){
|
36
|
-
return "auto";
|
37
|
-
}
|
38
|
-
if(String(value).indexOf("%") != -1){
|
39
|
-
return value;
|
40
|
-
}
|
41
|
-
else{
|
42
|
-
return value + "px";
|
43
|
-
}
|
44
|
-
},
|
45
|
-
|
46
|
-
init: function(){
|
47
|
-
var _this = this;
|
48
|
-
|
49
|
-
var formats = [];
|
50
|
-
if (_this.exportPNG) {
|
51
|
-
formats.push("png");
|
52
|
-
}
|
53
|
-
if (_this.exportPDF) {
|
54
|
-
formats.push("pdf");
|
55
|
-
}
|
56
|
-
if (_this.exportJPG) {
|
57
|
-
formats.push("jpg");
|
58
|
-
}
|
59
|
-
if (_this.exportSVG) {
|
60
|
-
formats.push("svg");
|
61
|
-
}
|
62
|
-
|
63
|
-
var menuItems = [];
|
64
|
-
if(formats.length == 1){
|
65
|
-
var format = formats[0];
|
66
|
-
menuItems.push({format:format, iconTitle:_this.buttonTitle, icon:_this.chart.pathToImages + _this.buttonIcon})
|
67
|
-
}
|
68
|
-
else if(formats.length > 1){
|
69
|
-
var subItems = [];
|
70
|
-
for(var i = 0; i < formats.length; i++){
|
71
|
-
subItems.push({format:formats[i], title:formats[i].toUpperCase()});
|
72
|
-
}
|
73
|
-
menuItems.push({onclick: function() {}, icon:_this.chart.pathToImages + _this.buttonIcon, items:subItems})
|
74
|
-
}
|
75
|
-
|
76
|
-
|
77
|
-
var color = _this.color;
|
78
|
-
if(color === undefined){
|
79
|
-
color = _this.chart.color;
|
80
|
-
}
|
81
|
-
|
82
|
-
var buttonColor = _this.buttonColor;
|
83
|
-
if(buttonColor === undefined){
|
84
|
-
buttonColor = "transparent";
|
85
|
-
}
|
86
|
-
|
87
|
-
|
88
|
-
_this.cfg = {
|
89
|
-
menuTop : _this.toCoordinate(_this.top),
|
90
|
-
menuLeft : _this.toCoordinate(_this.left),
|
91
|
-
menuRight : _this.toCoordinate(_this.right),
|
92
|
-
menuBottom : _this.toCoordinate(_this.bottom),
|
93
|
-
menuItems : menuItems,
|
94
|
-
menuItemStyle: {
|
95
|
-
backgroundColor : buttonColor,
|
96
|
-
opacity :_this.buttonAlpha,
|
97
|
-
rollOverBackgroundColor : _this.buttonRollOverColor,
|
98
|
-
color : color,
|
99
|
-
rollOverColor : _this.textRollOverColor,
|
100
|
-
paddingTop : '6px',
|
101
|
-
paddingRight : '6px',
|
102
|
-
paddingBottom : '6px',
|
103
|
-
paddingLeft : '6px',
|
104
|
-
marginTop : '0px',
|
105
|
-
marginRight : '0px',
|
106
|
-
marginBottom : '0px',
|
107
|
-
marginLeft : '0px',
|
108
|
-
textAlign : 'left',
|
109
|
-
textDecoration : 'none',
|
110
|
-
fontFamily : _this.chart.fontFamily,
|
111
|
-
fontSize : _this.chart.fontSize + 'px'
|
112
|
-
},
|
113
|
-
menuItemOutput: {
|
114
|
-
backgroundColor : _this.imageBackgroundColor,
|
115
|
-
fileName : _this.imageFileName,
|
116
|
-
format : 'png',
|
117
|
-
output : 'dataurlnewwindow',
|
118
|
-
render : 'browser',
|
119
|
-
dpi : 90,
|
120
|
-
onclick : function(instance, config, event) {
|
121
|
-
event.preventDefault();
|
122
|
-
instance.output(config);
|
123
|
-
}
|
124
|
-
},
|
125
|
-
removeImagery: true
|
126
|
-
};
|
127
|
-
|
128
|
-
_this.processing = {
|
129
|
-
buffer: [],
|
130
|
-
drawn: 0,
|
131
|
-
timer: 0
|
132
|
-
};
|
133
|
-
|
134
|
-
// Config dependency adaption
|
135
|
-
if (typeof(window.canvg) != 'undefined' && typeof(window.RGBColor) != 'undefined') {
|
136
|
-
_this.cfg.menuItemOutput.render = 'canvg';
|
137
|
-
}
|
138
|
-
if (typeof(window.saveAs) != 'undefined') {
|
139
|
-
_this.cfg.menuItemOutput.output = 'save';
|
140
|
-
}
|
141
|
-
if (AmCharts.isIE && AmCharts.IEversion < 10) {
|
142
|
-
_this.cfg.menuItemOutput.output = 'dataurlnewwindow';
|
143
|
-
}
|
144
|
-
|
145
|
-
// Merge given configs
|
146
|
-
var cfg = _this.userCFG;
|
147
|
-
if (cfg) {
|
148
|
-
cfg.menuItemOutput = AmCharts.extend(_this.cfg.menuItemOutput, cfg.menuItemOutput || {});
|
149
|
-
cfg.menuItemStyle = AmCharts.extend(_this.cfg.menuItemStyle, cfg.menuItemStyle || {});
|
150
|
-
_this.cfg = AmCharts.extend(_this.cfg, cfg);
|
151
|
-
}
|
152
|
-
|
153
|
-
// Add reference to chart
|
154
|
-
_this.chart.AmExport = _this;
|
155
|
-
|
156
|
-
// Listen to the drawer
|
157
|
-
_this.chart.addListener('rendered', function() {
|
158
|
-
_this.setup();
|
159
|
-
});
|
160
|
-
|
161
|
-
// DEBUG; Public reference
|
162
|
-
if (_this.DEBUG) {
|
163
|
-
window.AmExport = _this;
|
164
|
-
}
|
165
|
-
},
|
166
|
-
|
167
|
-
|
168
|
-
/*
|
169
|
-
Simple log function for internal purpose
|
170
|
-
@param **args
|
171
|
-
*/
|
172
|
-
log: function() {
|
173
|
-
console.log('AmExport: ', arguments);
|
174
|
-
},
|
175
|
-
|
176
|
-
/* PUBLIC
|
177
|
-
Prepares everything to get exported
|
178
|
-
@param none
|
179
|
-
*/
|
180
|
-
setup: function() {
|
181
|
-
var _this = this;
|
182
|
-
|
183
|
-
if (_this.DEBUG == 10) {
|
184
|
-
_this.log('SETUP START');
|
185
|
-
} // DEBUG
|
186
|
-
|
187
|
-
|
188
|
-
if (!AmCharts.isIE || (AmCharts.isIE && AmCharts.IEversion > 9)) {
|
189
|
-
// Build Buttons
|
190
|
-
_this.generateButtons();
|
191
|
-
if (_this.DEBUG == 10) {
|
192
|
-
_this.log('SETUP END');
|
193
|
-
} // DEBUG
|
194
|
-
} else {
|
195
|
-
if (_this.DEBUG == 10) {
|
196
|
-
_this.log('< IE10 NOT SUPPORTED');
|
197
|
-
} // DEBUG
|
198
|
-
}
|
199
|
-
},
|
200
|
-
|
201
|
-
/* PUBLIC
|
202
|
-
Decodes base64 string to binary array
|
203
|
-
@param base64_string
|
204
|
-
@copyright Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
|
205
|
-
*/
|
206
|
-
generateBinaryArray: function(base64_string) {
|
207
|
-
var
|
208
|
-
len = base64_string.length,
|
209
|
-
buffer = new Uint8Array(len / 4 * 3 | 0),
|
210
|
-
i = 0,
|
211
|
-
outptr = 0,
|
212
|
-
last = [0, 0],
|
213
|
-
state = 0,
|
214
|
-
save = 0,
|
215
|
-
rank, code, undef, base64_ranks = new Uint8Array([
|
216
|
-
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
217
|
-
]);
|
218
|
-
while (len--) {
|
219
|
-
code = base64_string.charCodeAt(i++);
|
220
|
-
rank = base64_ranks[code - 43];
|
221
|
-
if (rank !== 255 && rank !== undef) {
|
222
|
-
last[1] = last[0];
|
223
|
-
last[0] = code;
|
224
|
-
save = (save << 6) | rank;
|
225
|
-
state++;
|
226
|
-
if (state === 4) {
|
227
|
-
buffer[outptr++] = save >>> 16;
|
228
|
-
if (last[1] !== 61 /* padding character */ ) {
|
229
|
-
buffer[outptr++] = save >>> 8;
|
230
|
-
}
|
231
|
-
if (last[0] !== 61 /* padding character */ ) {
|
232
|
-
buffer[outptr++] = save;
|
233
|
-
}
|
234
|
-
state = 0;
|
235
|
-
}
|
236
|
-
}
|
237
|
-
}
|
238
|
-
// 2/3 chance there's going to be some null bytes at the end, but that
|
239
|
-
// doesn't really matter with most image formats.
|
240
|
-
// If it somehow matters for you, truncate the buffer up outptr.
|
241
|
-
return buffer;
|
242
|
-
},
|
243
|
-
|
244
|
-
/*
|
245
|
-
Creates blob object
|
246
|
-
@param base64_datastring string
|
247
|
-
@param type string
|
248
|
-
*/
|
249
|
-
generateBlob: function(datastring, type) {
|
250
|
-
var _this = this,
|
251
|
-
header_end = type!='image/svg+xml'?datastring.indexOf(',') + 1:0,
|
252
|
-
header = datastring.substring(0, header_end),
|
253
|
-
data = datastring,
|
254
|
-
blob = new Blob();
|
255
|
-
|
256
|
-
if (header.indexOf('base64') != -1) {
|
257
|
-
data = _this.generateBinaryArray(datastring.substring(header_end));
|
258
|
-
}
|
259
|
-
|
260
|
-
// Fake blob for IE
|
261
|
-
if (AmCharts.isIE && AmCharts.IEversion < 10) {
|
262
|
-
blob.data = data;
|
263
|
-
blob.size = data.length;
|
264
|
-
blob.type = type;
|
265
|
-
blob.encoding = 'base64';
|
266
|
-
} else {
|
267
|
-
blob = new Blob([data], {
|
268
|
-
type: type
|
269
|
-
});
|
270
|
-
}
|
271
|
-
return blob;
|
272
|
-
},
|
273
|
-
|
274
|
-
/*
|
275
|
-
Creates PDF object
|
276
|
-
@param config object
|
277
|
-
*/
|
278
|
-
generatePDF: function(cfg) {
|
279
|
-
var _this = this,
|
280
|
-
pdf = {
|
281
|
-
output: function() {
|
282
|
-
return '';
|
283
|
-
}
|
284
|
-
},
|
285
|
-
data = _this.canvas.toDataURL('image/jpeg'), // JSPDF ONLY SUPPORTS JPG
|
286
|
-
width = (_this.canvas.width * 25.4) / cfg.dpi,
|
287
|
-
height = (_this.canvas.height * 25.4) / cfg.dpi;
|
288
|
-
|
289
|
-
// Check
|
290
|
-
if (window.jsPDF) {
|
291
|
-
pdf = new jsPDF();
|
292
|
-
if (pdf.addImage) {
|
293
|
-
pdf.addImage(data, 'JPEG', 0, 0, width, height);
|
294
|
-
} else {
|
295
|
-
alert("Missing jsPDF plugin; Please add the 'addImage' plugin.");
|
296
|
-
}
|
297
|
-
} else {
|
298
|
-
alert("Missing jsPDF lib; Don't forget to add the addImage plugin.");
|
299
|
-
}
|
300
|
-
|
301
|
-
return pdf;
|
302
|
-
},
|
303
|
-
|
304
|
-
/*
|
305
|
-
Creates the CANVAS to receive the image data
|
306
|
-
@param format void()
|
307
|
-
@param callback; given callback function which returns the blob or datastring of the configured ouput type
|
308
|
-
*/
|
309
|
-
output: function(cfg, externalCallback) {
|
310
|
-
var _this = this;
|
311
|
-
cfg = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), cfg || {});
|
312
|
-
|
313
|
-
// Prepare chart
|
314
|
-
if(_this.chart.prepareForExport){
|
315
|
-
_this.chart.prepareForExport();
|
316
|
-
}
|
317
|
-
|
318
|
-
/* PRIVATE
|
319
|
-
Callback function which gets called after the drawing process is done
|
320
|
-
@param none
|
321
|
-
*/
|
322
|
-
function internalCallback() {
|
323
|
-
var data = null;
|
324
|
-
var blob;
|
325
|
-
if (_this.DEBUG == 10) {
|
326
|
-
_this.log('OUTPUT', cfg.format);
|
327
|
-
} // DEBUG
|
328
|
-
|
329
|
-
// SVG
|
330
|
-
if (cfg.format == 'image/svg+xml' || cfg.format == 'svg') {
|
331
|
-
data = _this.generateSVG();
|
332
|
-
blob = _this.generateBlob(data, 'image/svg+xml');
|
333
|
-
|
334
|
-
if (cfg.output == 'save') {
|
335
|
-
saveAs(blob, cfg.fileName + '.svg');
|
336
|
-
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
337
|
-
blob = 'data:image/svg+xml;base64,' + btoa(data);
|
338
|
-
} else if (cfg.output == 'dataurlnewwindow') {
|
339
|
-
window.open('data:image/svg+xml;base64,' + btoa(data));
|
340
|
-
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
341
|
-
location.href = 'data:image/svg+xml;base64,' + btoa(data);
|
342
|
-
} else if (cfg.output == 'datastream') {
|
343
|
-
location.href = 'data:image/octet-stream;base64,' + data;
|
344
|
-
}
|
345
|
-
|
346
|
-
if (externalCallback)
|
347
|
-
externalCallback.apply(_this, [blob]);
|
348
|
-
|
349
|
-
// PDF
|
350
|
-
} else if (cfg.format == 'application/pdf' || cfg.format == 'pdf') {
|
351
|
-
data = _this.generatePDF(cfg).output('dataurlstring');
|
352
|
-
blob = _this.generateBlob(data, 'application/pdf');
|
353
|
-
|
354
|
-
if (cfg.output == 'save') {
|
355
|
-
saveAs(blob, cfg.fileName + '.pdf');
|
356
|
-
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
357
|
-
blob = data;
|
358
|
-
} else if (cfg.output == 'dataurlnewwindow') {
|
359
|
-
window.open(data);
|
360
|
-
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
361
|
-
location.href = data;
|
362
|
-
} else if (cfg.output == 'datastream') {
|
363
|
-
location.href = data.replace('application/pdf', 'application/octet-stream');
|
364
|
-
}
|
365
|
-
|
366
|
-
if (externalCallback)
|
367
|
-
externalCallback.apply(_this, [blob]);
|
368
|
-
|
369
|
-
// PNG
|
370
|
-
} else if (cfg.format == 'image/png' || cfg.format == 'png') {
|
371
|
-
data = _this.canvas.toDataURL('image/png');
|
372
|
-
blob = _this.generateBlob(data, 'image/png');
|
373
|
-
|
374
|
-
if (cfg.output == 'save') {
|
375
|
-
saveAs(blob, cfg.fileName + '.png');
|
376
|
-
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
377
|
-
blob = data;
|
378
|
-
} else if (cfg.output == 'dataurlnewwindow') {
|
379
|
-
window.open(data);
|
380
|
-
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
381
|
-
location.href = data;
|
382
|
-
} else if (cfg.output == 'datastream') {
|
383
|
-
location.href = data.replace('image/png', 'image/octet-stream');
|
384
|
-
}
|
385
|
-
|
386
|
-
if (externalCallback)
|
387
|
-
externalCallback.apply(_this, [blob]);
|
388
|
-
|
389
|
-
// JPG
|
390
|
-
} else if (cfg.format == 'image/jpeg' || cfg.format == 'jpeg' || cfg.format == 'jpg') {
|
391
|
-
data = _this.canvas.toDataURL('image/jpeg');
|
392
|
-
blob = _this.generateBlob(data, 'image/jpeg');
|
393
|
-
|
394
|
-
if (cfg.output == 'save') {
|
395
|
-
saveAs(blob, cfg.fileName + '.jpg');
|
396
|
-
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
397
|
-
blob = data;
|
398
|
-
} else if (cfg.output == 'dataurlnewwindow') {
|
399
|
-
window.open(data);
|
400
|
-
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
401
|
-
location.href = data;
|
402
|
-
} else if (cfg.output == 'datastream') {
|
403
|
-
location.href = data.replace('image/jpeg', 'image/octet-stream');
|
404
|
-
}
|
405
|
-
|
406
|
-
if (externalCallback)
|
407
|
-
externalCallback.apply(_this, [blob]);
|
408
|
-
}
|
409
|
-
|
410
|
-
}
|
411
|
-
|
412
|
-
return _this.generateOutput(cfg, internalCallback);
|
413
|
-
},
|
414
|
-
|
415
|
-
/* PUBLIC
|
416
|
-
Polifies missing attributes to the SVG and replaces images to embedded base64 images
|
417
|
-
@param none
|
418
|
-
*/
|
419
|
-
polifySVG: function(svg) {
|
420
|
-
var _this = this;
|
421
|
-
|
422
|
-
// Recursive function to force the attributes
|
423
|
-
function recursiveChange(svg, tag) {
|
424
|
-
var items = svg.getElementsByTagName(tag);
|
425
|
-
var i = items.length;
|
426
|
-
|
427
|
-
while(i--) {
|
428
|
-
if (_this.cfg.removeImagery) {
|
429
|
-
items[i].parentNode.removeChild(items[i]);
|
430
|
-
|
431
|
-
} else {
|
432
|
-
var image = document.createElement('img');
|
433
|
-
var canvas = document.createElement('canvas');
|
434
|
-
var ctx = canvas.getContext('2d');
|
435
|
-
|
436
|
-
canvas.width = items[i].getAttribute('width');
|
437
|
-
canvas.height = items[i].getAttribute('height');
|
438
|
-
image.src = items[i].getAttribute('xlink:href');
|
439
|
-
image.width = items[i].getAttribute('width');
|
440
|
-
image.height = items[i].getAttribute('height');
|
441
|
-
|
442
|
-
try {
|
443
|
-
ctx.drawImage(image, 0, 0, image.width, image.height);
|
444
|
-
datastring = canvas.toDataURL(); // image.src; // canvas.toDataURL(); //
|
445
|
-
} catch (err) {
|
446
|
-
datastring = image.src; // image.src; // canvas.toDataURL(); //
|
447
|
-
|
448
|
-
_this.log('Tainted canvas, reached browser CORS security; origin from imagery must be equal to the server!');
|
449
|
-
throw new Error(err);
|
450
|
-
}
|
451
|
-
|
452
|
-
items[i].setAttribute('xlink:href', datastring);
|
453
|
-
}
|
454
|
-
|
455
|
-
if (_this.DEBUG == 10) {
|
456
|
-
_this.log('POLIFIED', items[i]);
|
457
|
-
} // DEBUG
|
458
|
-
}
|
459
|
-
}
|
460
|
-
|
461
|
-
// Put some attrs to it; fixed 20/03/14 xmlns is required to produce a valid svg file
|
462
|
-
if (AmCharts.IEversion == 0) {
|
463
|
-
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
464
|
-
if ( !_this.cfg.removeImagery ) {
|
465
|
-
svg.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
466
|
-
}
|
467
|
-
}
|
468
|
-
|
469
|
-
// DEBUG
|
470
|
-
if (_this.DEBUG == 10) {
|
471
|
-
_this.log('POLIFIED', svg);
|
472
|
-
}
|
473
|
-
|
474
|
-
// Force link adaption
|
475
|
-
recursiveChange(svg, 'pattern');
|
476
|
-
recursiveChange(svg, 'image');
|
477
|
-
|
478
|
-
_this.svgs.push(svg);
|
479
|
-
|
480
|
-
return svg;
|
481
|
-
},
|
482
|
-
|
483
|
-
|
484
|
-
/* PUBLIC
|
485
|
-
Stacks multiple SVGs into one
|
486
|
-
@param none
|
487
|
-
*/
|
488
|
-
generateSVG: function() {
|
489
|
-
var _this = this;
|
490
|
-
var context = document.createElement('svg');
|
491
|
-
context.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
492
|
-
context.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
493
|
-
|
494
|
-
for (var i = 0; i < _this.processing.buffer.length; i++) {
|
495
|
-
var group = document.createElement('g'),
|
496
|
-
data = _this.processing.buffer[i];
|
497
|
-
|
498
|
-
data[0].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
499
|
-
data[0].setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
500
|
-
|
501
|
-
group.setAttribute('transform', 'translate('+data[1].x+','+data[1].y+')');
|
502
|
-
group.appendChild(data[0]);
|
503
|
-
context.appendChild(group);
|
504
|
-
}
|
505
|
-
|
506
|
-
return new XMLSerializer().serializeToString(context);
|
507
|
-
},
|
508
|
-
|
509
|
-
/* PUBLIC
|
510
|
-
Generates the canvas with the given SVGs and configured renderer
|
511
|
-
@param callback; function(); gets called after drawing process on the canvas has been finished
|
512
|
-
*/
|
513
|
-
generateOutput: function(cfg, callback) {
|
514
|
-
var _this = this,
|
515
|
-
coll = [],
|
516
|
-
svgs = [],
|
517
|
-
canvas = document.createElement('canvas'),
|
518
|
-
context = canvas.getContext('2d'),
|
519
|
-
offset = {
|
520
|
-
y: 0,
|
521
|
-
x: 0
|
522
|
-
},
|
523
|
-
|
524
|
-
// Push svgs into array
|
525
|
-
coll = _this.chart.div.getElementsByTagName('svg');
|
526
|
-
for ( var i = 0; i < coll.length; i++ ) svgs.push(coll[i]);
|
527
|
-
|
528
|
-
// Add external legend
|
529
|
-
if ( _this.chart.legend && _this.chart.legend.position == 'outside' ) {
|
530
|
-
_this.chart.legend.container.container.externalLegend = true
|
531
|
-
svgs.push(_this.chart.legend.container.container);
|
532
|
-
|
533
|
-
// Add offset
|
534
|
-
if ( _this.cfg.legendPosition == 'left' ) {
|
535
|
-
offset.x = _this.chart.legend.div.offsetWidth;
|
536
|
-
} else if ( _this.cfg.legendPosition == 'top' ) {
|
537
|
-
offset.y = _this.chart.legend.div.offsetHeight;
|
538
|
-
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
539
|
-
offset.y = _this.cfg.legendPosition.chartTop;
|
540
|
-
offset.x = _this.cfg.legendPosition.chartLeft;
|
541
|
-
}
|
542
|
-
}
|
543
|
-
|
544
|
-
// Reset
|
545
|
-
_this.processing.buffer = [];
|
546
|
-
_this.processing.drawn = 0;
|
547
|
-
_this.canvas = canvas;
|
548
|
-
_this.svgs = [];
|
549
|
-
|
550
|
-
// Walkthroug SVGs
|
551
|
-
if (_this.DEBUG == 10) {
|
552
|
-
_this.log('START EXPORT');
|
553
|
-
} // DEBUG
|
554
|
-
if (_this.DEBUG == 10) {
|
555
|
-
_this.log('START BUFFERING');
|
556
|
-
} // DEBUG
|
557
|
-
for (var i = 0; i < svgs.length; i++) {
|
558
|
-
var parent = svgs[i].parentNode,
|
559
|
-
svgX = Number(parent.style.left.slice(0, -2)),
|
560
|
-
svgY = Number(parent.style.top.slice(0, -2)),
|
561
|
-
svgClone = _this.polifySVG(svgs[i].cloneNode(true)),
|
562
|
-
tmp = AmCharts.extend({}, offset);
|
563
|
-
|
564
|
-
// Add external legend
|
565
|
-
if ( svgs[i].externalLegend ) {
|
566
|
-
if ( _this.cfg.legendPosition == 'right' ) {
|
567
|
-
offset.y = 0;
|
568
|
-
offset.x = _this.chart.divRealWidth;
|
569
|
-
|
570
|
-
} else if ( _this.cfg.legendPosition == 'bottom' ) {
|
571
|
-
offset.y = svgY ? svgY : offset.y;
|
572
|
-
|
573
|
-
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
574
|
-
offset.x = _this.cfg.legendPosition.left;
|
575
|
-
offset.y = _this.cfg.legendPosition.top;
|
576
|
-
|
577
|
-
} else {
|
578
|
-
offset.x = 0;
|
579
|
-
offset.y = 0;
|
580
|
-
}
|
581
|
-
|
582
|
-
// Overtake parent position if given; fixed 20/03/14 distinguish between relativ and others
|
583
|
-
} else {
|
584
|
-
if ( parent.style.position == 'relative' ) {
|
585
|
-
offset.x = svgX ? svgX : offset.x;
|
586
|
-
offset.y = svgY ? svgY : offset.y;
|
587
|
-
} else {
|
588
|
-
offset.x = svgX;
|
589
|
-
offset.y = svgY;
|
590
|
-
}
|
591
|
-
}
|
592
|
-
|
593
|
-
_this.processing.buffer.push([svgClone, AmCharts.extend({}, offset)]);
|
594
|
-
|
595
|
-
// Put back from "cache"
|
596
|
-
if (svgY && svgX) {
|
597
|
-
offset = tmp;
|
598
|
-
|
599
|
-
// New offset for next one
|
600
|
-
} else {
|
601
|
-
offset.y += svgY ? 0 : parent.offsetHeight;
|
602
|
-
}
|
603
|
-
|
604
|
-
if (_this.DEBUG == 10) {
|
605
|
-
_this.log('BUFFERED', svgs[i], offset);
|
606
|
-
} // DEBUG
|
607
|
-
}
|
608
|
-
if (_this.DEBUG == 10) {
|
609
|
-
_this.log('END BUFFERING');
|
610
|
-
} // DEBUG
|
611
|
-
|
612
|
-
// Apply background
|
613
|
-
if (_this.DEBUG == 10) {
|
614
|
-
_this.log('START DRAWING', cfg.render);
|
615
|
-
} // DEBUG
|
616
|
-
if (_this.DEBUG == 10) {
|
617
|
-
_this.log('FILL BACKGROUND');
|
618
|
-
} // DEBUG
|
619
|
-
canvas.id = AmCharts.getUniqueId();
|
620
|
-
canvas.width = _this.chart.divRealWidth;
|
621
|
-
canvas.height = _this.chart.divRealHeight;
|
622
|
-
|
623
|
-
// External legend exception
|
624
|
-
if ( _this.chart.legend && _this.chart.legend.position == "outside" ) {
|
625
|
-
if ( ['left','right'].indexOf(_this.cfg.legendPosition) != -1 ) {
|
626
|
-
canvas.width += _this.chart.legend.div.offsetWidth;
|
627
|
-
|
628
|
-
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
629
|
-
canvas.width += _this.cfg.legendPosition.width;
|
630
|
-
canvas.height += _this.cfg.legendPosition.height;
|
631
|
-
|
632
|
-
} else {
|
633
|
-
canvas.height += _this.chart.legend.div.offsetHeight;
|
634
|
-
}
|
635
|
-
}
|
636
|
-
|
637
|
-
// Stockchart exception
|
638
|
-
var adapted = {
|
639
|
-
width: false,
|
640
|
-
height: false
|
641
|
-
};
|
642
|
-
if ( _this.chart.periodSelector ) {
|
643
|
-
if ( ['left','right'].indexOf(_this.chart.periodSelector.position) != -1 ) {
|
644
|
-
canvas.width -= _this.chart.periodSelector.div.offsetWidth + 16;
|
645
|
-
adapted.width = true;
|
646
|
-
} else {
|
647
|
-
canvas.height -= _this.chart.periodSelector.div.offsetHeight;
|
648
|
-
adapted.height = true;
|
649
|
-
}
|
650
|
-
}
|
651
|
-
|
652
|
-
if ( _this.chart.dataSetSelector ) {
|
653
|
-
if ( ['left','right'].indexOf(_this.chart.dataSetSelector.position) != -1 ) {
|
654
|
-
if ( !adapted.width ) {
|
655
|
-
canvas.width -= _this.chart.dataSetSelector.div.offsetWidth + 16;
|
656
|
-
}
|
657
|
-
} else {
|
658
|
-
canvas.height -= _this.chart.dataSetSelector.div.offsetHeight;
|
659
|
-
}
|
660
|
-
}
|
661
|
-
|
662
|
-
// Set given background; jpeg default
|
663
|
-
if (cfg.backgroundColor || cfg.format == 'image/jpeg') {
|
664
|
-
context.fillStyle = cfg.backgroundColor || '#FFFFFF';
|
665
|
-
context.fillRect(0, 0, canvas.width, canvas.height);
|
666
|
-
}
|
667
|
-
|
668
|
-
/* PRIVATE
|
669
|
-
Recursive function to draw the images to the canvas;
|
670
|
-
@param none;
|
671
|
-
*/
|
672
|
-
function drawItWhenItsLoaded() {
|
673
|
-
var img, buffer, offset, source;
|
674
|
-
|
675
|
-
// DRAWING PROCESS DONE
|
676
|
-
if (_this.processing.buffer.length == _this.processing.drawn || cfg.format == 'svg' ) {
|
677
|
-
if (_this.DEBUG == 10) {
|
678
|
-
_this.log('END DRAWING');
|
679
|
-
} // DEBUG
|
680
|
-
return callback();
|
681
|
-
|
682
|
-
// LOOPING LUI
|
683
|
-
} else {
|
684
|
-
if (_this.DEBUG == 10) {
|
685
|
-
_this.log('DRAW', _this.processing.drawn + 1, 'OF', _this.processing.buffer.length);
|
686
|
-
} // DEBUG
|
687
|
-
|
688
|
-
buffer = _this.processing.buffer[_this.processing.drawn];
|
689
|
-
source = new XMLSerializer().serializeToString(buffer[0]); //source = 'data:image/svg+xml;base64,' + btoa();
|
690
|
-
offset = buffer[1];
|
691
|
-
|
692
|
-
if (_this.DEBUG == 10) {
|
693
|
-
_this.log('SOURCE', source);
|
694
|
-
} // DEBUG
|
695
|
-
|
696
|
-
// NATIVE
|
697
|
-
if (cfg.render == 'browser') {
|
698
|
-
img = new Image();
|
699
|
-
img.id = AmCharts.getUniqueId();
|
700
|
-
source = 'data:image/svg+xml;base64,' + btoa(source);
|
701
|
-
|
702
|
-
//img.crossOrigin = "Anonymous";
|
703
|
-
img.onload = function() {
|
704
|
-
context.drawImage(this, buffer[1].x, buffer[1].y);
|
705
|
-
_this.processing.drawn++;
|
706
|
-
|
707
|
-
if (_this.DEBUG == 10) {
|
708
|
-
_this.log('ONLOAD', this);
|
709
|
-
} // DEBUG
|
710
|
-
drawItWhenItsLoaded();
|
711
|
-
};
|
712
|
-
img.onerror = function() {
|
713
|
-
if (_this.DEBUG == 10) {
|
714
|
-
_this.log('ONERROR', this);
|
715
|
-
} // DEBUG
|
716
|
-
context.drawImage(this, buffer[1].x, buffer[1].y);
|
717
|
-
_this.processing.drawn++;
|
718
|
-
drawItWhenItsLoaded();
|
719
|
-
};
|
720
|
-
img.src = source;
|
721
|
-
|
722
|
-
if (_this.DEBUG == 10) {
|
723
|
-
_this.log('ADD', img);
|
724
|
-
} // DEBUG
|
725
|
-
if (img.complete || typeof(img.complete) == 'undefined' || img.complete === undefined) {
|
726
|
-
if (_this.DEBUG == 10) {
|
727
|
-
_this.log('FORCE ONLOAD', img);
|
728
|
-
} // DEBUG
|
729
|
-
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
|
730
|
-
img.src = source;
|
731
|
-
}
|
732
|
-
|
733
|
-
// CANVG
|
734
|
-
} else if (cfg.render == 'canvg') {
|
735
|
-
canvg(canvas, source, {
|
736
|
-
offsetX: offset.x,
|
737
|
-
offsetY: offset.y,
|
738
|
-
ignoreMouse: true,
|
739
|
-
ignoreAnimation: true,
|
740
|
-
ignoreDimensions: true,
|
741
|
-
ignoreClear: true,
|
742
|
-
renderCallback: function() {
|
743
|
-
_this.processing.drawn++;
|
744
|
-
drawItWhenItsLoaded();
|
745
|
-
}
|
746
|
-
});
|
747
|
-
}
|
748
|
-
}
|
749
|
-
}
|
750
|
-
return drawItWhenItsLoaded();
|
751
|
-
},
|
752
|
-
|
753
|
-
/*
|
754
|
-
Generates the export menu to trigger the exportation
|
755
|
-
@param none;
|
756
|
-
*/
|
757
|
-
generateButtons: function() {
|
758
|
-
var _this = this,lvl = 0;
|
759
|
-
|
760
|
-
if(_this.div){
|
761
|
-
div = _this.div;
|
762
|
-
div.innerHTML = "";
|
763
|
-
}
|
764
|
-
else{
|
765
|
-
div = document.createElement('div'),
|
766
|
-
_this.div = div;
|
767
|
-
}
|
768
|
-
|
769
|
-
// Push sublings
|
770
|
-
function createList(items) {
|
771
|
-
var ul = document.createElement('ul');
|
772
|
-
|
773
|
-
ul.setAttribute('style', 'list-style: none; margin: 0; padding: 0;');
|
774
|
-
|
775
|
-
// Walkthrough items
|
776
|
-
for (var i = 0; i < items.length; i++) {
|
777
|
-
var li = document.createElement('li'),
|
778
|
-
img = document.createElement('img'),
|
779
|
-
a = document.createElement('a'),
|
780
|
-
item = items[i],
|
781
|
-
children = null,
|
782
|
-
itemStyle = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemStyle), items[i]);
|
783
|
-
|
784
|
-
// MERGE CFG
|
785
|
-
item = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), item);
|
786
|
-
|
787
|
-
// ICON
|
788
|
-
if (item['icon']) {
|
789
|
-
img.alt = '';
|
790
|
-
img.src = item['icon'];
|
791
|
-
img.setAttribute('style', 'margin: 0 auto;border: none;outline: none');
|
792
|
-
if (item['iconTitle']) {
|
793
|
-
img.title = item['iconTitle'];
|
794
|
-
}
|
795
|
-
a.appendChild(img);
|
796
|
-
}
|
797
|
-
|
798
|
-
// TITLE; STYLING
|
799
|
-
a.href = '#';
|
800
|
-
if (item['title']) {
|
801
|
-
img.setAttribute('style', 'margin: 0px 5px;');
|
802
|
-
a.innerHTML += item.title;
|
803
|
-
}
|
804
|
-
a.setAttribute('style', 'display: block;');
|
805
|
-
AmCharts.extend(a.style, itemStyle);
|
806
|
-
|
807
|
-
// ONCLICK
|
808
|
-
a.onclick = item.onclick.bind(a, _this, item);
|
809
|
-
li.appendChild(a);
|
810
|
-
|
811
|
-
// APPEND SIBLINGS
|
812
|
-
if (item.items) {
|
813
|
-
children = createList(item.items);
|
814
|
-
li.appendChild(children);
|
815
|
-
|
816
|
-
li.onmouseover = function() {
|
817
|
-
children.style.display = 'block';
|
818
|
-
};
|
819
|
-
li.onmouseout = function() {
|
820
|
-
children.style.display = 'none';
|
821
|
-
};
|
822
|
-
children.style.display = 'none';
|
823
|
-
}
|
824
|
-
|
825
|
-
// Append to parent
|
826
|
-
ul.appendChild(li);
|
827
|
-
|
828
|
-
// Apply hover
|
829
|
-
a.onmouseover = function() {
|
830
|
-
this.style.backgroundColor = itemStyle.rollOverBackgroundColor;
|
831
|
-
this.style.color = itemStyle.rollOverColor;
|
832
|
-
this.style.borderColor = itemStyle.rollOverBorderColor;
|
833
|
-
};
|
834
|
-
a.onmouseout = function() {
|
835
|
-
this.style.backgroundColor = itemStyle.backgroundColor;
|
836
|
-
this.style.color = itemStyle.color;
|
837
|
-
this.style.borderColor = itemStyle.borderColor;
|
838
|
-
};
|
839
|
-
}
|
840
|
-
lvl++;
|
841
|
-
|
842
|
-
if (_this.DEBUG == 10) {
|
843
|
-
_this.log('MENU', ul);
|
844
|
-
} // DEBUG
|
845
|
-
|
846
|
-
return ul;
|
847
|
-
}
|
848
|
-
|
849
|
-
// Style wrapper; Push into chart div
|
850
|
-
div.setAttribute('style', 'position: absolute;top:' + _this.cfg.menuTop + ';right:' + _this.cfg.menuRight + ';bottom:' + _this.cfg.menuBottom + ';left:' + _this.cfg.menuLeft + ';');
|
851
|
-
div.setAttribute('class', 'amExportButton');
|
852
|
-
div.appendChild(createList(_this.cfg.menuItems));
|
853
|
-
_this.chart.containerDiv.appendChild(div);
|
854
|
-
}
|
1
|
+
AmCharts.AmExport = AmCharts.Class({
|
2
|
+
construct: function(chart, cfg, init ) {
|
3
|
+
var _this = this;
|
4
|
+
_this.DEBUG = false;
|
5
|
+
_this.chart = chart;
|
6
|
+
_this.canvas = null;
|
7
|
+
_this.svgs = [];
|
8
|
+
_this.userCFG = cfg;
|
9
|
+
|
10
|
+
_this.buttonIcon = 'export.png';
|
11
|
+
_this.exportPNG = true;
|
12
|
+
_this.exportPDF = false;
|
13
|
+
_this.exportJPG = false;
|
14
|
+
_this.exportSVG = false;
|
15
|
+
//_this.left;
|
16
|
+
_this.right = 0;
|
17
|
+
//_this.bottom;
|
18
|
+
_this.top = 0;
|
19
|
+
//_this.color;
|
20
|
+
_this.buttonRollOverColor = "#EFEFEF";
|
21
|
+
//_this.buttonColor = "#FFFFFF";
|
22
|
+
//_this.buttonRollOverAlpha = 0.5;
|
23
|
+
_this.textRollOverColor = "#CC0000";
|
24
|
+
_this.buttonTitle = "Save chart as an image";
|
25
|
+
_this.buttonAlpha = 0.75;
|
26
|
+
_this.imageFileName = "amChart";
|
27
|
+
_this.imageBackgroundColor = "#FFFFFF";
|
28
|
+
|
29
|
+
if (init) {
|
30
|
+
_this.init();
|
31
|
+
}
|
32
|
+
},
|
33
|
+
|
34
|
+
toCoordinate:function(value){
|
35
|
+
if(value === undefined){
|
36
|
+
return "auto";
|
37
|
+
}
|
38
|
+
if(String(value).indexOf("%") != -1){
|
39
|
+
return value;
|
40
|
+
}
|
41
|
+
else{
|
42
|
+
return value + "px";
|
43
|
+
}
|
44
|
+
},
|
45
|
+
|
46
|
+
init: function(){
|
47
|
+
var _this = this;
|
48
|
+
|
49
|
+
var formats = [];
|
50
|
+
if (_this.exportPNG) {
|
51
|
+
formats.push("png");
|
52
|
+
}
|
53
|
+
if (_this.exportPDF) {
|
54
|
+
formats.push("pdf");
|
55
|
+
}
|
56
|
+
if (_this.exportJPG) {
|
57
|
+
formats.push("jpg");
|
58
|
+
}
|
59
|
+
if (_this.exportSVG) {
|
60
|
+
formats.push("svg");
|
61
|
+
}
|
62
|
+
|
63
|
+
var menuItems = [];
|
64
|
+
if(formats.length == 1){
|
65
|
+
var format = formats[0];
|
66
|
+
menuItems.push({format:format, iconTitle:_this.buttonTitle, icon:_this.chart.pathToImages + _this.buttonIcon})
|
67
|
+
}
|
68
|
+
else if(formats.length > 1){
|
69
|
+
var subItems = [];
|
70
|
+
for(var i = 0; i < formats.length; i++){
|
71
|
+
subItems.push({format:formats[i], title:formats[i].toUpperCase()});
|
72
|
+
}
|
73
|
+
menuItems.push({onclick: function() {}, icon:_this.chart.pathToImages + _this.buttonIcon, items:subItems})
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
var color = _this.color;
|
78
|
+
if(color === undefined){
|
79
|
+
color = _this.chart.color;
|
80
|
+
}
|
81
|
+
|
82
|
+
var buttonColor = _this.buttonColor;
|
83
|
+
if(buttonColor === undefined){
|
84
|
+
buttonColor = "transparent";
|
85
|
+
}
|
86
|
+
|
87
|
+
|
88
|
+
_this.cfg = {
|
89
|
+
menuTop : _this.toCoordinate(_this.top),
|
90
|
+
menuLeft : _this.toCoordinate(_this.left),
|
91
|
+
menuRight : _this.toCoordinate(_this.right),
|
92
|
+
menuBottom : _this.toCoordinate(_this.bottom),
|
93
|
+
menuItems : menuItems,
|
94
|
+
menuItemStyle: {
|
95
|
+
backgroundColor : buttonColor,
|
96
|
+
opacity :_this.buttonAlpha,
|
97
|
+
rollOverBackgroundColor : _this.buttonRollOverColor,
|
98
|
+
color : color,
|
99
|
+
rollOverColor : _this.textRollOverColor,
|
100
|
+
paddingTop : '6px',
|
101
|
+
paddingRight : '6px',
|
102
|
+
paddingBottom : '6px',
|
103
|
+
paddingLeft : '6px',
|
104
|
+
marginTop : '0px',
|
105
|
+
marginRight : '0px',
|
106
|
+
marginBottom : '0px',
|
107
|
+
marginLeft : '0px',
|
108
|
+
textAlign : 'left',
|
109
|
+
textDecoration : 'none',
|
110
|
+
fontFamily : _this.chart.fontFamily,
|
111
|
+
fontSize : _this.chart.fontSize + 'px'
|
112
|
+
},
|
113
|
+
menuItemOutput: {
|
114
|
+
backgroundColor : _this.imageBackgroundColor,
|
115
|
+
fileName : _this.imageFileName,
|
116
|
+
format : 'png',
|
117
|
+
output : 'dataurlnewwindow',
|
118
|
+
render : 'browser',
|
119
|
+
dpi : 90,
|
120
|
+
onclick : function(instance, config, event) {
|
121
|
+
event.preventDefault();
|
122
|
+
instance.output(config);
|
123
|
+
}
|
124
|
+
},
|
125
|
+
removeImagery: true
|
126
|
+
};
|
127
|
+
|
128
|
+
_this.processing = {
|
129
|
+
buffer: [],
|
130
|
+
drawn: 0,
|
131
|
+
timer: 0
|
132
|
+
};
|
133
|
+
|
134
|
+
// Config dependency adaption
|
135
|
+
if (typeof(window.canvg) != 'undefined' && typeof(window.RGBColor) != 'undefined') {
|
136
|
+
_this.cfg.menuItemOutput.render = 'canvg';
|
137
|
+
}
|
138
|
+
if (typeof(window.saveAs) != 'undefined') {
|
139
|
+
_this.cfg.menuItemOutput.output = 'save';
|
140
|
+
}
|
141
|
+
if (AmCharts.isIE && AmCharts.IEversion < 10) {
|
142
|
+
_this.cfg.menuItemOutput.output = 'dataurlnewwindow';
|
143
|
+
}
|
144
|
+
|
145
|
+
// Merge given configs
|
146
|
+
var cfg = _this.userCFG;
|
147
|
+
if (cfg) {
|
148
|
+
cfg.menuItemOutput = AmCharts.extend(_this.cfg.menuItemOutput, cfg.menuItemOutput || {});
|
149
|
+
cfg.menuItemStyle = AmCharts.extend(_this.cfg.menuItemStyle, cfg.menuItemStyle || {});
|
150
|
+
_this.cfg = AmCharts.extend(_this.cfg, cfg);
|
151
|
+
}
|
152
|
+
|
153
|
+
// Add reference to chart
|
154
|
+
_this.chart.AmExport = _this;
|
155
|
+
|
156
|
+
// Listen to the drawer
|
157
|
+
_this.chart.addListener('rendered', function() {
|
158
|
+
_this.setup();
|
159
|
+
});
|
160
|
+
|
161
|
+
// DEBUG; Public reference
|
162
|
+
if (_this.DEBUG) {
|
163
|
+
window.AmExport = _this;
|
164
|
+
}
|
165
|
+
},
|
166
|
+
|
167
|
+
|
168
|
+
/*
|
169
|
+
Simple log function for internal purpose
|
170
|
+
@param **args
|
171
|
+
*/
|
172
|
+
log: function() {
|
173
|
+
console.log('AmExport: ', arguments);
|
174
|
+
},
|
175
|
+
|
176
|
+
/* PUBLIC
|
177
|
+
Prepares everything to get exported
|
178
|
+
@param none
|
179
|
+
*/
|
180
|
+
setup: function() {
|
181
|
+
var _this = this;
|
182
|
+
|
183
|
+
if (_this.DEBUG == 10) {
|
184
|
+
_this.log('SETUP START');
|
185
|
+
} // DEBUG
|
186
|
+
|
187
|
+
|
188
|
+
if (!AmCharts.isIE || (AmCharts.isIE && AmCharts.IEversion > 9)) {
|
189
|
+
// Build Buttons
|
190
|
+
_this.generateButtons();
|
191
|
+
if (_this.DEBUG == 10) {
|
192
|
+
_this.log('SETUP END');
|
193
|
+
} // DEBUG
|
194
|
+
} else {
|
195
|
+
if (_this.DEBUG == 10) {
|
196
|
+
_this.log('< IE10 NOT SUPPORTED');
|
197
|
+
} // DEBUG
|
198
|
+
}
|
199
|
+
},
|
200
|
+
|
201
|
+
/* PUBLIC
|
202
|
+
Decodes base64 string to binary array
|
203
|
+
@param base64_string
|
204
|
+
@copyright Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
|
205
|
+
*/
|
206
|
+
generateBinaryArray: function(base64_string) {
|
207
|
+
var
|
208
|
+
len = base64_string.length,
|
209
|
+
buffer = new Uint8Array(len / 4 * 3 | 0),
|
210
|
+
i = 0,
|
211
|
+
outptr = 0,
|
212
|
+
last = [0, 0],
|
213
|
+
state = 0,
|
214
|
+
save = 0,
|
215
|
+
rank, code, undef, base64_ranks = new Uint8Array([
|
216
|
+
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
217
|
+
]);
|
218
|
+
while (len--) {
|
219
|
+
code = base64_string.charCodeAt(i++);
|
220
|
+
rank = base64_ranks[code - 43];
|
221
|
+
if (rank !== 255 && rank !== undef) {
|
222
|
+
last[1] = last[0];
|
223
|
+
last[0] = code;
|
224
|
+
save = (save << 6) | rank;
|
225
|
+
state++;
|
226
|
+
if (state === 4) {
|
227
|
+
buffer[outptr++] = save >>> 16;
|
228
|
+
if (last[1] !== 61 /* padding character */ ) {
|
229
|
+
buffer[outptr++] = save >>> 8;
|
230
|
+
}
|
231
|
+
if (last[0] !== 61 /* padding character */ ) {
|
232
|
+
buffer[outptr++] = save;
|
233
|
+
}
|
234
|
+
state = 0;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
// 2/3 chance there's going to be some null bytes at the end, but that
|
239
|
+
// doesn't really matter with most image formats.
|
240
|
+
// If it somehow matters for you, truncate the buffer up outptr.
|
241
|
+
return buffer;
|
242
|
+
},
|
243
|
+
|
244
|
+
/*
|
245
|
+
Creates blob object
|
246
|
+
@param base64_datastring string
|
247
|
+
@param type string
|
248
|
+
*/
|
249
|
+
generateBlob: function(datastring, type) {
|
250
|
+
var _this = this,
|
251
|
+
header_end = type!='image/svg+xml'?datastring.indexOf(',') + 1:0,
|
252
|
+
header = datastring.substring(0, header_end),
|
253
|
+
data = datastring,
|
254
|
+
blob = new Blob();
|
255
|
+
|
256
|
+
if (header.indexOf('base64') != -1) {
|
257
|
+
data = _this.generateBinaryArray(datastring.substring(header_end));
|
258
|
+
}
|
259
|
+
|
260
|
+
// Fake blob for IE
|
261
|
+
if (AmCharts.isIE && AmCharts.IEversion < 10) {
|
262
|
+
blob.data = data;
|
263
|
+
blob.size = data.length;
|
264
|
+
blob.type = type;
|
265
|
+
blob.encoding = 'base64';
|
266
|
+
} else {
|
267
|
+
blob = new Blob([data], {
|
268
|
+
type: type
|
269
|
+
});
|
270
|
+
}
|
271
|
+
return blob;
|
272
|
+
},
|
273
|
+
|
274
|
+
/*
|
275
|
+
Creates PDF object
|
276
|
+
@param config object
|
277
|
+
*/
|
278
|
+
generatePDF: function(cfg) {
|
279
|
+
var _this = this,
|
280
|
+
pdf = {
|
281
|
+
output: function() {
|
282
|
+
return '';
|
283
|
+
}
|
284
|
+
},
|
285
|
+
data = _this.canvas.toDataURL('image/jpeg'), // JSPDF ONLY SUPPORTS JPG
|
286
|
+
width = (_this.canvas.width * 25.4) / cfg.dpi,
|
287
|
+
height = (_this.canvas.height * 25.4) / cfg.dpi;
|
288
|
+
|
289
|
+
// Check
|
290
|
+
if (window.jsPDF) {
|
291
|
+
pdf = new jsPDF();
|
292
|
+
if (pdf.addImage) {
|
293
|
+
pdf.addImage(data, 'JPEG', 0, 0, width, height);
|
294
|
+
} else {
|
295
|
+
alert("Missing jsPDF plugin; Please add the 'addImage' plugin.");
|
296
|
+
}
|
297
|
+
} else {
|
298
|
+
alert("Missing jsPDF lib; Don't forget to add the addImage plugin.");
|
299
|
+
}
|
300
|
+
|
301
|
+
return pdf;
|
302
|
+
},
|
303
|
+
|
304
|
+
/*
|
305
|
+
Creates the CANVAS to receive the image data
|
306
|
+
@param format void()
|
307
|
+
@param callback; given callback function which returns the blob or datastring of the configured ouput type
|
308
|
+
*/
|
309
|
+
output: function(cfg, externalCallback) {
|
310
|
+
var _this = this;
|
311
|
+
cfg = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), cfg || {});
|
312
|
+
|
313
|
+
// Prepare chart
|
314
|
+
if(_this.chart.prepareForExport){
|
315
|
+
_this.chart.prepareForExport();
|
316
|
+
}
|
317
|
+
|
318
|
+
/* PRIVATE
|
319
|
+
Callback function which gets called after the drawing process is done
|
320
|
+
@param none
|
321
|
+
*/
|
322
|
+
function internalCallback() {
|
323
|
+
var data = null;
|
324
|
+
var blob;
|
325
|
+
if (_this.DEBUG == 10) {
|
326
|
+
_this.log('OUTPUT', cfg.format);
|
327
|
+
} // DEBUG
|
328
|
+
|
329
|
+
// SVG
|
330
|
+
if (cfg.format == 'image/svg+xml' || cfg.format == 'svg') {
|
331
|
+
data = _this.generateSVG();
|
332
|
+
blob = _this.generateBlob(data, 'image/svg+xml');
|
333
|
+
|
334
|
+
if (cfg.output == 'save') {
|
335
|
+
saveAs(blob, cfg.fileName + '.svg');
|
336
|
+
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
337
|
+
blob = 'data:image/svg+xml;base64,' + btoa(data);
|
338
|
+
} else if (cfg.output == 'dataurlnewwindow') {
|
339
|
+
window.open('data:image/svg+xml;base64,' + btoa(data));
|
340
|
+
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
341
|
+
location.href = 'data:image/svg+xml;base64,' + btoa(data);
|
342
|
+
} else if (cfg.output == 'datastream') {
|
343
|
+
location.href = 'data:image/octet-stream;base64,' + data;
|
344
|
+
}
|
345
|
+
|
346
|
+
if (externalCallback)
|
347
|
+
externalCallback.apply(_this, [blob]);
|
348
|
+
|
349
|
+
// PDF
|
350
|
+
} else if (cfg.format == 'application/pdf' || cfg.format == 'pdf') {
|
351
|
+
data = _this.generatePDF(cfg).output('dataurlstring');
|
352
|
+
blob = _this.generateBlob(data, 'application/pdf');
|
353
|
+
|
354
|
+
if (cfg.output == 'save') {
|
355
|
+
saveAs(blob, cfg.fileName + '.pdf');
|
356
|
+
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
357
|
+
blob = data;
|
358
|
+
} else if (cfg.output == 'dataurlnewwindow') {
|
359
|
+
window.open(data);
|
360
|
+
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
361
|
+
location.href = data;
|
362
|
+
} else if (cfg.output == 'datastream') {
|
363
|
+
location.href = data.replace('application/pdf', 'application/octet-stream');
|
364
|
+
}
|
365
|
+
|
366
|
+
if (externalCallback)
|
367
|
+
externalCallback.apply(_this, [blob]);
|
368
|
+
|
369
|
+
// PNG
|
370
|
+
} else if (cfg.format == 'image/png' || cfg.format == 'png') {
|
371
|
+
data = _this.canvas.toDataURL('image/png');
|
372
|
+
blob = _this.generateBlob(data, 'image/png');
|
373
|
+
|
374
|
+
if (cfg.output == 'save') {
|
375
|
+
saveAs(blob, cfg.fileName + '.png');
|
376
|
+
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
377
|
+
blob = data;
|
378
|
+
} else if (cfg.output == 'dataurlnewwindow') {
|
379
|
+
window.open(data);
|
380
|
+
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
381
|
+
location.href = data;
|
382
|
+
} else if (cfg.output == 'datastream') {
|
383
|
+
location.href = data.replace('image/png', 'image/octet-stream');
|
384
|
+
}
|
385
|
+
|
386
|
+
if (externalCallback)
|
387
|
+
externalCallback.apply(_this, [blob]);
|
388
|
+
|
389
|
+
// JPG
|
390
|
+
} else if (cfg.format == 'image/jpeg' || cfg.format == 'jpeg' || cfg.format == 'jpg') {
|
391
|
+
data = _this.canvas.toDataURL('image/jpeg');
|
392
|
+
blob = _this.generateBlob(data, 'image/jpeg');
|
393
|
+
|
394
|
+
if (cfg.output == 'save') {
|
395
|
+
saveAs(blob, cfg.fileName + '.jpg');
|
396
|
+
} else if (cfg.output == 'datastring' || cfg.output == 'datauristring' || cfg.output == 'dataurlstring') {
|
397
|
+
blob = data;
|
398
|
+
} else if (cfg.output == 'dataurlnewwindow') {
|
399
|
+
window.open(data);
|
400
|
+
} else if (cfg.output == 'datauri' || cfg.output == 'dataurl') {
|
401
|
+
location.href = data;
|
402
|
+
} else if (cfg.output == 'datastream') {
|
403
|
+
location.href = data.replace('image/jpeg', 'image/octet-stream');
|
404
|
+
}
|
405
|
+
|
406
|
+
if (externalCallback)
|
407
|
+
externalCallback.apply(_this, [blob]);
|
408
|
+
}
|
409
|
+
|
410
|
+
}
|
411
|
+
|
412
|
+
return _this.generateOutput(cfg, internalCallback);
|
413
|
+
},
|
414
|
+
|
415
|
+
/* PUBLIC
|
416
|
+
Polifies missing attributes to the SVG and replaces images to embedded base64 images
|
417
|
+
@param none
|
418
|
+
*/
|
419
|
+
polifySVG: function(svg) {
|
420
|
+
var _this = this;
|
421
|
+
|
422
|
+
// Recursive function to force the attributes
|
423
|
+
function recursiveChange(svg, tag) {
|
424
|
+
var items = svg.getElementsByTagName(tag);
|
425
|
+
var i = items.length;
|
426
|
+
|
427
|
+
while(i--) {
|
428
|
+
if (_this.cfg.removeImagery) {
|
429
|
+
items[i].parentNode.removeChild(items[i]);
|
430
|
+
|
431
|
+
} else {
|
432
|
+
var image = document.createElement('img');
|
433
|
+
var canvas = document.createElement('canvas');
|
434
|
+
var ctx = canvas.getContext('2d');
|
435
|
+
|
436
|
+
canvas.width = items[i].getAttribute('width');
|
437
|
+
canvas.height = items[i].getAttribute('height');
|
438
|
+
image.src = items[i].getAttribute('xlink:href');
|
439
|
+
image.width = items[i].getAttribute('width');
|
440
|
+
image.height = items[i].getAttribute('height');
|
441
|
+
|
442
|
+
try {
|
443
|
+
ctx.drawImage(image, 0, 0, image.width, image.height);
|
444
|
+
datastring = canvas.toDataURL(); // image.src; // canvas.toDataURL(); //
|
445
|
+
} catch (err) {
|
446
|
+
datastring = image.src; // image.src; // canvas.toDataURL(); //
|
447
|
+
|
448
|
+
_this.log('Tainted canvas, reached browser CORS security; origin from imagery must be equal to the server!');
|
449
|
+
throw new Error(err);
|
450
|
+
}
|
451
|
+
|
452
|
+
items[i].setAttribute('xlink:href', datastring);
|
453
|
+
}
|
454
|
+
|
455
|
+
if (_this.DEBUG == 10) {
|
456
|
+
_this.log('POLIFIED', items[i]);
|
457
|
+
} // DEBUG
|
458
|
+
}
|
459
|
+
}
|
460
|
+
|
461
|
+
// Put some attrs to it; fixed 20/03/14 xmlns is required to produce a valid svg file
|
462
|
+
if (AmCharts.IEversion == 0) {
|
463
|
+
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
464
|
+
if ( !_this.cfg.removeImagery ) {
|
465
|
+
svg.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
466
|
+
}
|
467
|
+
}
|
468
|
+
|
469
|
+
// DEBUG
|
470
|
+
if (_this.DEBUG == 10) {
|
471
|
+
_this.log('POLIFIED', svg);
|
472
|
+
}
|
473
|
+
|
474
|
+
// Force link adaption
|
475
|
+
recursiveChange(svg, 'pattern');
|
476
|
+
recursiveChange(svg, 'image');
|
477
|
+
|
478
|
+
_this.svgs.push(svg);
|
479
|
+
|
480
|
+
return svg;
|
481
|
+
},
|
482
|
+
|
483
|
+
|
484
|
+
/* PUBLIC
|
485
|
+
Stacks multiple SVGs into one
|
486
|
+
@param none
|
487
|
+
*/
|
488
|
+
generateSVG: function() {
|
489
|
+
var _this = this;
|
490
|
+
var context = document.createElement('svg');
|
491
|
+
context.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
492
|
+
context.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
493
|
+
|
494
|
+
for (var i = 0; i < _this.processing.buffer.length; i++) {
|
495
|
+
var group = document.createElement('g'),
|
496
|
+
data = _this.processing.buffer[i];
|
497
|
+
|
498
|
+
data[0].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
499
|
+
data[0].setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
|
500
|
+
|
501
|
+
group.setAttribute('transform', 'translate('+data[1].x+','+data[1].y+')');
|
502
|
+
group.appendChild(data[0]);
|
503
|
+
context.appendChild(group);
|
504
|
+
}
|
505
|
+
|
506
|
+
return new XMLSerializer().serializeToString(context);
|
507
|
+
},
|
508
|
+
|
509
|
+
/* PUBLIC
|
510
|
+
Generates the canvas with the given SVGs and configured renderer
|
511
|
+
@param callback; function(); gets called after drawing process on the canvas has been finished
|
512
|
+
*/
|
513
|
+
generateOutput: function(cfg, callback) {
|
514
|
+
var _this = this,
|
515
|
+
coll = [],
|
516
|
+
svgs = [],
|
517
|
+
canvas = document.createElement('canvas'),
|
518
|
+
context = canvas.getContext('2d'),
|
519
|
+
offset = {
|
520
|
+
y: 0,
|
521
|
+
x: 0
|
522
|
+
},
|
523
|
+
|
524
|
+
// Push svgs into array
|
525
|
+
coll = _this.chart.div.getElementsByTagName('svg');
|
526
|
+
for ( var i = 0; i < coll.length; i++ ) svgs.push(coll[i]);
|
527
|
+
|
528
|
+
// Add external legend
|
529
|
+
if ( _this.chart.legend && _this.chart.legend.position == 'outside' ) {
|
530
|
+
_this.chart.legend.container.container.externalLegend = true
|
531
|
+
svgs.push(_this.chart.legend.container.container);
|
532
|
+
|
533
|
+
// Add offset
|
534
|
+
if ( _this.cfg.legendPosition == 'left' ) {
|
535
|
+
offset.x = _this.chart.legend.div.offsetWidth;
|
536
|
+
} else if ( _this.cfg.legendPosition == 'top' ) {
|
537
|
+
offset.y = _this.chart.legend.div.offsetHeight;
|
538
|
+
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
539
|
+
offset.y = _this.cfg.legendPosition.chartTop;
|
540
|
+
offset.x = _this.cfg.legendPosition.chartLeft;
|
541
|
+
}
|
542
|
+
}
|
543
|
+
|
544
|
+
// Reset
|
545
|
+
_this.processing.buffer = [];
|
546
|
+
_this.processing.drawn = 0;
|
547
|
+
_this.canvas = canvas;
|
548
|
+
_this.svgs = [];
|
549
|
+
|
550
|
+
// Walkthroug SVGs
|
551
|
+
if (_this.DEBUG == 10) {
|
552
|
+
_this.log('START EXPORT');
|
553
|
+
} // DEBUG
|
554
|
+
if (_this.DEBUG == 10) {
|
555
|
+
_this.log('START BUFFERING');
|
556
|
+
} // DEBUG
|
557
|
+
for (var i = 0; i < svgs.length; i++) {
|
558
|
+
var parent = svgs[i].parentNode,
|
559
|
+
svgX = Number(parent.style.left.slice(0, -2)),
|
560
|
+
svgY = Number(parent.style.top.slice(0, -2)),
|
561
|
+
svgClone = _this.polifySVG(svgs[i].cloneNode(true)),
|
562
|
+
tmp = AmCharts.extend({}, offset);
|
563
|
+
|
564
|
+
// Add external legend
|
565
|
+
if ( svgs[i].externalLegend ) {
|
566
|
+
if ( _this.cfg.legendPosition == 'right' ) {
|
567
|
+
offset.y = 0;
|
568
|
+
offset.x = _this.chart.divRealWidth;
|
569
|
+
|
570
|
+
} else if ( _this.cfg.legendPosition == 'bottom' ) {
|
571
|
+
offset.y = svgY ? svgY : offset.y;
|
572
|
+
|
573
|
+
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
574
|
+
offset.x = _this.cfg.legendPosition.left;
|
575
|
+
offset.y = _this.cfg.legendPosition.top;
|
576
|
+
|
577
|
+
} else {
|
578
|
+
offset.x = 0;
|
579
|
+
offset.y = 0;
|
580
|
+
}
|
581
|
+
|
582
|
+
// Overtake parent position if given; fixed 20/03/14 distinguish between relativ and others
|
583
|
+
} else {
|
584
|
+
if ( parent.style.position == 'relative' ) {
|
585
|
+
offset.x = svgX ? svgX : offset.x;
|
586
|
+
offset.y = svgY ? svgY : offset.y;
|
587
|
+
} else {
|
588
|
+
offset.x = svgX;
|
589
|
+
offset.y = svgY;
|
590
|
+
}
|
591
|
+
}
|
592
|
+
|
593
|
+
_this.processing.buffer.push([svgClone, AmCharts.extend({}, offset)]);
|
594
|
+
|
595
|
+
// Put back from "cache"
|
596
|
+
if (svgY && svgX) {
|
597
|
+
offset = tmp;
|
598
|
+
|
599
|
+
// New offset for next one
|
600
|
+
} else {
|
601
|
+
offset.y += svgY ? 0 : parent.offsetHeight;
|
602
|
+
}
|
603
|
+
|
604
|
+
if (_this.DEBUG == 10) {
|
605
|
+
_this.log('BUFFERED', svgs[i], offset);
|
606
|
+
} // DEBUG
|
607
|
+
}
|
608
|
+
if (_this.DEBUG == 10) {
|
609
|
+
_this.log('END BUFFERING');
|
610
|
+
} // DEBUG
|
611
|
+
|
612
|
+
// Apply background
|
613
|
+
if (_this.DEBUG == 10) {
|
614
|
+
_this.log('START DRAWING', cfg.render);
|
615
|
+
} // DEBUG
|
616
|
+
if (_this.DEBUG == 10) {
|
617
|
+
_this.log('FILL BACKGROUND');
|
618
|
+
} // DEBUG
|
619
|
+
canvas.id = AmCharts.getUniqueId();
|
620
|
+
canvas.width = _this.chart.divRealWidth;
|
621
|
+
canvas.height = _this.chart.divRealHeight;
|
622
|
+
|
623
|
+
// External legend exception
|
624
|
+
if ( _this.chart.legend && _this.chart.legend.position == "outside" ) {
|
625
|
+
if ( ['left','right'].indexOf(_this.cfg.legendPosition) != -1 ) {
|
626
|
+
canvas.width += _this.chart.legend.div.offsetWidth;
|
627
|
+
|
628
|
+
} else if ( typeof _this.cfg.legendPosition == 'object' ) {
|
629
|
+
canvas.width += _this.cfg.legendPosition.width;
|
630
|
+
canvas.height += _this.cfg.legendPosition.height;
|
631
|
+
|
632
|
+
} else {
|
633
|
+
canvas.height += _this.chart.legend.div.offsetHeight;
|
634
|
+
}
|
635
|
+
}
|
636
|
+
|
637
|
+
// Stockchart exception
|
638
|
+
var adapted = {
|
639
|
+
width: false,
|
640
|
+
height: false
|
641
|
+
};
|
642
|
+
if ( _this.chart.periodSelector ) {
|
643
|
+
if ( ['left','right'].indexOf(_this.chart.periodSelector.position) != -1 ) {
|
644
|
+
canvas.width -= _this.chart.periodSelector.div.offsetWidth + 16;
|
645
|
+
adapted.width = true;
|
646
|
+
} else {
|
647
|
+
canvas.height -= _this.chart.periodSelector.div.offsetHeight;
|
648
|
+
adapted.height = true;
|
649
|
+
}
|
650
|
+
}
|
651
|
+
|
652
|
+
if ( _this.chart.dataSetSelector ) {
|
653
|
+
if ( ['left','right'].indexOf(_this.chart.dataSetSelector.position) != -1 ) {
|
654
|
+
if ( !adapted.width ) {
|
655
|
+
canvas.width -= _this.chart.dataSetSelector.div.offsetWidth + 16;
|
656
|
+
}
|
657
|
+
} else {
|
658
|
+
canvas.height -= _this.chart.dataSetSelector.div.offsetHeight;
|
659
|
+
}
|
660
|
+
}
|
661
|
+
|
662
|
+
// Set given background; jpeg default
|
663
|
+
if (cfg.backgroundColor || cfg.format == 'image/jpeg') {
|
664
|
+
context.fillStyle = cfg.backgroundColor || '#FFFFFF';
|
665
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
666
|
+
}
|
667
|
+
|
668
|
+
/* PRIVATE
|
669
|
+
Recursive function to draw the images to the canvas;
|
670
|
+
@param none;
|
671
|
+
*/
|
672
|
+
function drawItWhenItsLoaded() {
|
673
|
+
var img, buffer, offset, source;
|
674
|
+
|
675
|
+
// DRAWING PROCESS DONE
|
676
|
+
if (_this.processing.buffer.length == _this.processing.drawn || cfg.format == 'svg' ) {
|
677
|
+
if (_this.DEBUG == 10) {
|
678
|
+
_this.log('END DRAWING');
|
679
|
+
} // DEBUG
|
680
|
+
return callback();
|
681
|
+
|
682
|
+
// LOOPING LUI
|
683
|
+
} else {
|
684
|
+
if (_this.DEBUG == 10) {
|
685
|
+
_this.log('DRAW', _this.processing.drawn + 1, 'OF', _this.processing.buffer.length);
|
686
|
+
} // DEBUG
|
687
|
+
|
688
|
+
buffer = _this.processing.buffer[_this.processing.drawn];
|
689
|
+
source = new XMLSerializer().serializeToString(buffer[0]); //source = 'data:image/svg+xml;base64,' + btoa();
|
690
|
+
offset = buffer[1];
|
691
|
+
|
692
|
+
if (_this.DEBUG == 10) {
|
693
|
+
_this.log('SOURCE', source);
|
694
|
+
} // DEBUG
|
695
|
+
|
696
|
+
// NATIVE
|
697
|
+
if (cfg.render == 'browser') {
|
698
|
+
img = new Image();
|
699
|
+
img.id = AmCharts.getUniqueId();
|
700
|
+
source = 'data:image/svg+xml;base64,' + btoa(source);
|
701
|
+
|
702
|
+
//img.crossOrigin = "Anonymous";
|
703
|
+
img.onload = function() {
|
704
|
+
context.drawImage(this, buffer[1].x, buffer[1].y);
|
705
|
+
_this.processing.drawn++;
|
706
|
+
|
707
|
+
if (_this.DEBUG == 10) {
|
708
|
+
_this.log('ONLOAD', this);
|
709
|
+
} // DEBUG
|
710
|
+
drawItWhenItsLoaded();
|
711
|
+
};
|
712
|
+
img.onerror = function() {
|
713
|
+
if (_this.DEBUG == 10) {
|
714
|
+
_this.log('ONERROR', this);
|
715
|
+
} // DEBUG
|
716
|
+
context.drawImage(this, buffer[1].x, buffer[1].y);
|
717
|
+
_this.processing.drawn++;
|
718
|
+
drawItWhenItsLoaded();
|
719
|
+
};
|
720
|
+
img.src = source;
|
721
|
+
|
722
|
+
if (_this.DEBUG == 10) {
|
723
|
+
_this.log('ADD', img);
|
724
|
+
} // DEBUG
|
725
|
+
if (img.complete || typeof(img.complete) == 'undefined' || img.complete === undefined) {
|
726
|
+
if (_this.DEBUG == 10) {
|
727
|
+
_this.log('FORCE ONLOAD', img);
|
728
|
+
} // DEBUG
|
729
|
+
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
|
730
|
+
img.src = source;
|
731
|
+
}
|
732
|
+
|
733
|
+
// CANVG
|
734
|
+
} else if (cfg.render == 'canvg') {
|
735
|
+
canvg(canvas, source, {
|
736
|
+
offsetX: offset.x,
|
737
|
+
offsetY: offset.y,
|
738
|
+
ignoreMouse: true,
|
739
|
+
ignoreAnimation: true,
|
740
|
+
ignoreDimensions: true,
|
741
|
+
ignoreClear: true,
|
742
|
+
renderCallback: function() {
|
743
|
+
_this.processing.drawn++;
|
744
|
+
drawItWhenItsLoaded();
|
745
|
+
}
|
746
|
+
});
|
747
|
+
}
|
748
|
+
}
|
749
|
+
}
|
750
|
+
return drawItWhenItsLoaded();
|
751
|
+
},
|
752
|
+
|
753
|
+
/*
|
754
|
+
Generates the export menu to trigger the exportation
|
755
|
+
@param none;
|
756
|
+
*/
|
757
|
+
generateButtons: function() {
|
758
|
+
var _this = this,lvl = 0;
|
759
|
+
|
760
|
+
if(_this.div){
|
761
|
+
div = _this.div;
|
762
|
+
div.innerHTML = "";
|
763
|
+
}
|
764
|
+
else{
|
765
|
+
div = document.createElement('div'),
|
766
|
+
_this.div = div;
|
767
|
+
}
|
768
|
+
|
769
|
+
// Push sublings
|
770
|
+
function createList(items) {
|
771
|
+
var ul = document.createElement('ul');
|
772
|
+
|
773
|
+
ul.setAttribute('style', 'list-style: none; margin: 0; padding: 0;');
|
774
|
+
|
775
|
+
// Walkthrough items
|
776
|
+
for (var i = 0; i < items.length; i++) {
|
777
|
+
var li = document.createElement('li'),
|
778
|
+
img = document.createElement('img'),
|
779
|
+
a = document.createElement('a'),
|
780
|
+
item = items[i],
|
781
|
+
children = null,
|
782
|
+
itemStyle = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemStyle), items[i]);
|
783
|
+
|
784
|
+
// MERGE CFG
|
785
|
+
item = AmCharts.extend(AmCharts.extend({}, _this.cfg.menuItemOutput), item);
|
786
|
+
|
787
|
+
// ICON
|
788
|
+
if (item['icon']) {
|
789
|
+
img.alt = '';
|
790
|
+
img.src = item['icon'];
|
791
|
+
img.setAttribute('style', 'margin: 0 auto;border: none;outline: none');
|
792
|
+
if (item['iconTitle']) {
|
793
|
+
img.title = item['iconTitle'];
|
794
|
+
}
|
795
|
+
a.appendChild(img);
|
796
|
+
}
|
797
|
+
|
798
|
+
// TITLE; STYLING
|
799
|
+
a.href = '#';
|
800
|
+
if (item['title']) {
|
801
|
+
img.setAttribute('style', 'margin: 0px 5px;');
|
802
|
+
a.innerHTML += item.title;
|
803
|
+
}
|
804
|
+
a.setAttribute('style', 'display: block;');
|
805
|
+
AmCharts.extend(a.style, itemStyle);
|
806
|
+
|
807
|
+
// ONCLICK
|
808
|
+
a.onclick = item.onclick.bind(a, _this, item);
|
809
|
+
li.appendChild(a);
|
810
|
+
|
811
|
+
// APPEND SIBLINGS
|
812
|
+
if (item.items) {
|
813
|
+
children = createList(item.items);
|
814
|
+
li.appendChild(children);
|
815
|
+
|
816
|
+
li.onmouseover = function() {
|
817
|
+
children.style.display = 'block';
|
818
|
+
};
|
819
|
+
li.onmouseout = function() {
|
820
|
+
children.style.display = 'none';
|
821
|
+
};
|
822
|
+
children.style.display = 'none';
|
823
|
+
}
|
824
|
+
|
825
|
+
// Append to parent
|
826
|
+
ul.appendChild(li);
|
827
|
+
|
828
|
+
// Apply hover
|
829
|
+
a.onmouseover = function() {
|
830
|
+
this.style.backgroundColor = itemStyle.rollOverBackgroundColor;
|
831
|
+
this.style.color = itemStyle.rollOverColor;
|
832
|
+
this.style.borderColor = itemStyle.rollOverBorderColor;
|
833
|
+
};
|
834
|
+
a.onmouseout = function() {
|
835
|
+
this.style.backgroundColor = itemStyle.backgroundColor;
|
836
|
+
this.style.color = itemStyle.color;
|
837
|
+
this.style.borderColor = itemStyle.borderColor;
|
838
|
+
};
|
839
|
+
}
|
840
|
+
lvl++;
|
841
|
+
|
842
|
+
if (_this.DEBUG == 10) {
|
843
|
+
_this.log('MENU', ul);
|
844
|
+
} // DEBUG
|
845
|
+
|
846
|
+
return ul;
|
847
|
+
}
|
848
|
+
|
849
|
+
// Style wrapper; Push into chart div
|
850
|
+
div.setAttribute('style', 'position: absolute;top:' + _this.cfg.menuTop + ';right:' + _this.cfg.menuRight + ';bottom:' + _this.cfg.menuBottom + ';left:' + _this.cfg.menuLeft + ';');
|
851
|
+
div.setAttribute('class', 'amExportButton');
|
852
|
+
div.appendChild(createList(_this.cfg.menuItems));
|
853
|
+
_this.chart.containerDiv.appendChild(div);
|
854
|
+
}
|
855
855
|
});
|