| 23 |
liveuser |
1 |
/*
|
|
|
2 |
Plugin Name: amCharts Export
|
|
|
3 |
Description: Adds export capabilities to amCharts products
|
|
|
4 |
Author: Benjamin Maertz, amCharts
|
|
|
5 |
Version: 1.4.10
|
|
|
6 |
Author URI: http://www.amcharts.com/
|
|
|
7 |
|
|
|
8 |
Copyright 2015 amCharts
|
|
|
9 |
|
|
|
10 |
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
11 |
you may not use this file except in compliance with the License.
|
|
|
12 |
You may obtain a copy of the License at
|
|
|
13 |
|
|
|
14 |
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
15 |
|
|
|
16 |
Unless required by applicable law or agreed to in writing, software
|
|
|
17 |
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
18 |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
19 |
See the License for the specific language governing permissions and
|
|
|
20 |
limitations under the License.
|
|
|
21 |
|
|
|
22 |
Please note that the above license covers only this plugin. It by all means does
|
|
|
23 |
not apply to any other amCharts products that are covered by different licenses.
|
|
|
24 |
*/
|
|
|
25 |
|
|
|
26 |
/*
|
|
|
27 |
** Polyfill translation
|
|
|
28 |
*/
|
|
|
29 |
if ( !AmCharts.translations[ "export" ] ) {
|
|
|
30 |
AmCharts.translations[ "export" ] = {}
|
|
|
31 |
}
|
|
|
32 |
if ( !AmCharts.translations[ "export" ][ "en" ] ) {
|
|
|
33 |
AmCharts.translations[ "export" ][ "en" ] = {
|
|
|
34 |
"fallback.save.text": "CTRL + C to copy the data into the clipboard.",
|
|
|
35 |
"fallback.save.image": "Rightclick -> Save picture as... to save the image.",
|
|
|
36 |
|
|
|
37 |
"capturing.delayed.menu.label": "{{duration}}",
|
|
|
38 |
"capturing.delayed.menu.title": "Click to cancel",
|
|
|
39 |
|
|
|
40 |
"menu.label.print": "Print",
|
|
|
41 |
"menu.label.undo": "Undo",
|
|
|
42 |
"menu.label.redo": "Redo",
|
|
|
43 |
"menu.label.cancel": "Cancel",
|
|
|
44 |
|
|
|
45 |
"menu.label.save.image": "Download as ...",
|
|
|
46 |
"menu.label.save.data": "Save as ...",
|
|
|
47 |
|
|
|
48 |
"menu.label.draw": "Annotate ...",
|
|
|
49 |
"menu.label.draw.change": "Change ...",
|
|
|
50 |
"menu.label.draw.add": "Add ...",
|
|
|
51 |
"menu.label.draw.shapes": "Shape ...",
|
|
|
52 |
"menu.label.draw.colors": "Color ...",
|
|
|
53 |
"menu.label.draw.widths": "Size ...",
|
|
|
54 |
"menu.label.draw.opacities": "Opacity ...",
|
|
|
55 |
"menu.label.draw.text": "Text",
|
|
|
56 |
|
|
|
57 |
"menu.label.draw.modes": "Mode ...",
|
|
|
58 |
"menu.label.draw.modes.pencil": "Pencil",
|
|
|
59 |
"menu.label.draw.modes.line": "Line",
|
|
|
60 |
"menu.label.draw.modes.arrow": "Arrow"
|
|
|
61 |
}
|
|
|
62 |
}
|
|
|
63 |
|
|
|
64 |
/*
|
|
|
65 |
** Polyfill export class
|
|
|
66 |
*/
|
|
|
67 |
( function() {
|
|
|
68 |
AmCharts[ "export" ] = function( chart, config ) {
|
|
|
69 |
var _this = {
|
|
|
70 |
name: "export",
|
|
|
71 |
version: "1.4.10",
|
|
|
72 |
libs: {
|
|
|
73 |
async: true,
|
|
|
74 |
autoLoad: true,
|
|
|
75 |
reload: false,
|
|
|
76 |
resources: [ {
|
|
|
77 |
"pdfmake/pdfmake.js": [ "pdfmake/vfs_fonts.js" ],
|
|
|
78 |
"jszip/jszip.js": [ "xlsx/xlsx.js" ]
|
|
|
79 |
}, "fabric.js/fabric.js", "FileSaver.js/FileSaver.js" ],
|
|
|
80 |
namespaces: {
|
|
|
81 |
"pdfmake.js": "pdfMake",
|
|
|
82 |
"jszip.js": "JSZip",
|
|
|
83 |
"xlsx.js": "XLSX",
|
|
|
84 |
"fabric.js": "fabric",
|
|
|
85 |
"FileSaver.js": "saveAs"
|
|
|
86 |
}
|
|
|
87 |
},
|
|
|
88 |
config: {},
|
|
|
89 |
setup: {
|
|
|
90 |
chart: chart,
|
|
|
91 |
hasBlob: false,
|
|
|
92 |
wrapper: false
|
|
|
93 |
},
|
|
|
94 |
drawing: {
|
|
|
95 |
enabled: false,
|
|
|
96 |
undos: [],
|
|
|
97 |
redos: [],
|
|
|
98 |
buffer: {
|
|
|
99 |
position: {
|
|
|
100 |
x1: 0,
|
|
|
101 |
y1: 0,
|
|
|
102 |
x2: 0,
|
|
|
103 |
y2: 0,
|
|
|
104 |
xD: 0,
|
|
|
105 |
yD: 0
|
|
|
106 |
}
|
|
|
107 |
},
|
|
|
108 |
handler: {
|
|
|
109 |
undo: function( options, skipped ) {
|
|
|
110 |
var item = _this.drawing.undos.pop();
|
|
|
111 |
if ( item ) {
|
|
|
112 |
item.selectable = true;
|
|
|
113 |
_this.drawing.redos.push( item );
|
|
|
114 |
|
|
|
115 |
if ( item.action == "added" ) {
|
|
|
116 |
_this.setup.fabric.remove( item.target );
|
|
|
117 |
}
|
|
|
118 |
|
|
|
119 |
var state = JSON.parse( item.state );
|
|
|
120 |
item.target.set( state );
|
|
|
121 |
|
|
|
122 |
if ( item.target instanceof fabric.Group ) {
|
|
|
123 |
_this.drawing.handler.change( {
|
|
|
124 |
color: state.cfg.color,
|
|
|
125 |
width: state.cfg.width,
|
|
|
126 |
opacity: state.cfg.opacity
|
|
|
127 |
}, true, item.target );
|
|
|
128 |
}
|
|
|
129 |
|
|
|
130 |
_this.setup.fabric.renderAll();
|
|
|
131 |
|
|
|
132 |
// RECALL
|
|
|
133 |
if ( item.state == item.target.recentState && !skipped ) {
|
|
|
134 |
_this.drawing.handler.undo( item, true );
|
|
|
135 |
}
|
|
|
136 |
}
|
|
|
137 |
},
|
|
|
138 |
redo: function( options, skipped ) {
|
|
|
139 |
var item = _this.drawing.redos.pop();
|
|
|
140 |
if ( item ) {
|
|
|
141 |
item.selectable = true;
|
|
|
142 |
_this.drawing.undos.push( item );
|
|
|
143 |
|
|
|
144 |
if ( item.action == "added" ) {
|
|
|
145 |
_this.setup.fabric.add( item.target );
|
|
|
146 |
}
|
|
|
147 |
|
|
|
148 |
var state = JSON.parse( item.state );
|
|
|
149 |
item.target.recentState = item.state;
|
|
|
150 |
item.target.set( state );
|
|
|
151 |
|
|
|
152 |
if ( item.target instanceof fabric.Group ) {
|
|
|
153 |
_this.drawing.handler.change( {
|
|
|
154 |
color: state.cfg.color,
|
|
|
155 |
width: state.cfg.width,
|
|
|
156 |
opacity: state.cfg.opacity
|
|
|
157 |
}, true, item.target );
|
|
|
158 |
}
|
|
|
159 |
|
|
|
160 |
_this.setup.fabric.renderAll();
|
|
|
161 |
|
|
|
162 |
// RECALL
|
|
|
163 |
if ( item.action == "addified" ) {
|
|
|
164 |
_this.drawing.handler.redo();
|
|
|
165 |
}
|
|
|
166 |
}
|
|
|
167 |
},
|
|
|
168 |
done: function( options ) {
|
|
|
169 |
_this.drawing.buffer.enabled = false;
|
|
|
170 |
_this.drawing.undos = [];
|
|
|
171 |
_this.drawing.redos = [];
|
|
|
172 |
_this.createMenu( _this.config.menu );
|
|
|
173 |
_this.setup.fabric.deactivateAll();
|
|
|
174 |
|
|
|
175 |
if ( _this.setup.wrapper ) {
|
|
|
176 |
_this.setup.chart.containerDiv.removeChild( _this.setup.wrapper );
|
|
|
177 |
_this.setup.wrapper = false;
|
|
|
178 |
}
|
|
|
179 |
},
|
|
|
180 |
add: function( options ) {
|
|
|
181 |
var cfg = _this.deepMerge( {
|
|
|
182 |
top: _this.setup.fabric.height / 2,
|
|
|
183 |
left: _this.setup.fabric.width / 2
|
|
|
184 |
}, options || {} );
|
|
|
185 |
var method = cfg.url.indexOf( ".svg" ) != -1 ? fabric.loadSVGFromURL : fabric.Image.fromURL;
|
|
|
186 |
|
|
|
187 |
method( cfg.url, function( objects, options ) {
|
|
|
188 |
var group = options !== undefined ? fabric.util.groupSVGElements( objects, options ) : objects;
|
|
|
189 |
var ratio = false;
|
|
|
190 |
|
|
|
191 |
// RESCALE ONLY IF IT EXCEEDS THE CANVAS
|
|
|
192 |
if ( group.height > _this.setup.fabric.height || group.width > _this.setup.fabric.width ) {
|
|
|
193 |
ratio = ( _this.setup.fabric.height / 2 ) / group.height;
|
|
|
194 |
}
|
|
|
195 |
|
|
|
196 |
if ( cfg.top > _this.setup.fabric.height ) {
|
|
|
197 |
cfg.top = _this.setup.fabric.height / 2;
|
|
|
198 |
}
|
|
|
199 |
|
|
|
200 |
if ( cfg.left > _this.setup.fabric.width ) {
|
|
|
201 |
cfg.left = _this.setup.fabric.width / 2;
|
|
|
202 |
}
|
|
|
203 |
|
|
|
204 |
group.set( {
|
|
|
205 |
originX: "center",
|
|
|
206 |
originY: "center",
|
|
|
207 |
top: cfg.top,
|
|
|
208 |
left: cfg.left,
|
|
|
209 |
width: ratio ? group.width * ratio : group.width,
|
|
|
210 |
height: ratio ? group.height * ratio : group.height,
|
|
|
211 |
fill: _this.drawing.color
|
|
|
212 |
} );
|
|
|
213 |
_this.setup.fabric.add( group );
|
|
|
214 |
} );
|
|
|
215 |
},
|
|
|
216 |
change: function( options, skipped, target ) {
|
|
|
217 |
var cfg = _this.deepMerge( {}, options || {} );
|
|
|
218 |
var state, i1, rgba;
|
|
|
219 |
var current = target || _this.drawing.buffer.target;
|
|
|
220 |
var objects = current ? current._objects ? current._objects : [ current ] : null;
|
|
|
221 |
|
|
|
222 |
// UPDATE DRAWING OBJECT
|
|
|
223 |
if ( cfg.mode ) {
|
|
|
224 |
_this.drawing.mode = cfg.mode;
|
|
|
225 |
}
|
|
|
226 |
if ( cfg.width ) {
|
|
|
227 |
_this.drawing.width = cfg.width;
|
|
|
228 |
_this.drawing.fontSize = cfg.width * 3;
|
|
|
229 |
}
|
|
|
230 |
if ( cfg.fontSize ) {
|
|
|
231 |
_this.drawing.fontSize = cfg.fontSize;
|
|
|
232 |
}
|
|
|
233 |
if ( cfg.color ) {
|
|
|
234 |
_this.drawing.color = cfg.color;
|
|
|
235 |
}
|
|
|
236 |
if ( cfg.opacity ) {
|
|
|
237 |
_this.drawing.opacity = cfg.opacity;
|
|
|
238 |
}
|
|
|
239 |
|
|
|
240 |
// APPLY OPACITY ON CURRENT COLOR
|
|
|
241 |
rgba = new fabric.Color( _this.drawing.color ).getSource();
|
|
|
242 |
rgba.pop();
|
|
|
243 |
rgba.push( _this.drawing.opacity );
|
|
|
244 |
_this.drawing.color = "rgba(" + rgba.join() + ")";
|
|
|
245 |
_this.setup.fabric.freeDrawingBrush.color = _this.drawing.color;
|
|
|
246 |
_this.setup.fabric.freeDrawingBrush.width = _this.drawing.width;
|
|
|
247 |
|
|
|
248 |
// UPDATE CURRENT SELECTION
|
|
|
249 |
if ( current ) {
|
|
|
250 |
state = JSON.parse( current.recentState ).cfg;
|
|
|
251 |
|
|
|
252 |
// UPDATE GIVE OPTIONS ONLY
|
|
|
253 |
if ( state ) {
|
|
|
254 |
cfg.color = cfg.color || state.color;
|
|
|
255 |
cfg.width = cfg.width || state.width;
|
|
|
256 |
cfg.opacity = cfg.opacity || state.opacity;
|
|
|
257 |
cfg.fontSize = cfg.fontSize || cfg.width * 3;
|
|
|
258 |
|
|
|
259 |
rgba = new fabric.Color( cfg.color ).getSource();
|
|
|
260 |
rgba.pop();
|
|
|
261 |
rgba.push( cfg.opacity );
|
|
|
262 |
cfg.color = "rgba(" + rgba.join() + ")";
|
|
|
263 |
}
|
|
|
264 |
|
|
|
265 |
// UPDATE OBJECTS
|
|
|
266 |
for ( i1 = 0; i1 < objects.length; i1++ ) {
|
|
|
267 |
if (
|
|
|
268 |
objects[ i1 ] instanceof fabric.Text ||
|
|
|
269 |
objects[ i1 ] instanceof fabric.PathGroup ||
|
|
|
270 |
objects[ i1 ] instanceof fabric.Triangle
|
|
|
271 |
) {
|
|
|
272 |
if ( cfg.color || cfg.opacity ) {
|
|
|
273 |
objects[ i1 ].set( {
|
|
|
274 |
fill: cfg.color
|
|
|
275 |
} );
|
|
|
276 |
}
|
|
|
277 |
if ( cfg.fontSize ) {
|
|
|
278 |
objects[ i1 ].set( {
|
|
|
279 |
fontSize: cfg.fontSize
|
|
|
280 |
} );
|
|
|
281 |
}
|
|
|
282 |
} else if (
|
|
|
283 |
objects[ i1 ] instanceof fabric.Path ||
|
|
|
284 |
objects[ i1 ] instanceof fabric.Line
|
|
|
285 |
) {
|
|
|
286 |
if ( current instanceof fabric.Group ) {
|
|
|
287 |
if ( cfg.color || cfg.opacity ) {
|
|
|
288 |
objects[ i1 ].set( {
|
|
|
289 |
stroke: cfg.color
|
|
|
290 |
} );
|
|
|
291 |
}
|
|
|
292 |
} else {
|
|
|
293 |
if ( cfg.color || cfg.opacity ) {
|
|
|
294 |
objects[ i1 ].set( {
|
|
|
295 |
stroke: cfg.color
|
|
|
296 |
} );
|
|
|
297 |
}
|
|
|
298 |
if ( cfg.width ) {
|
|
|
299 |
objects[ i1 ].set( {
|
|
|
300 |
strokeWidth: cfg.width
|
|
|
301 |
} );
|
|
|
302 |
}
|
|
|
303 |
}
|
|
|
304 |
}
|
|
|
305 |
}
|
|
|
306 |
|
|
|
307 |
// ADD UNDO
|
|
|
308 |
if ( !skipped ) {
|
|
|
309 |
state = JSON.stringify( _this.deepMerge( current.saveState().originalState, {
|
|
|
310 |
cfg: {
|
|
|
311 |
color: cfg.color,
|
|
|
312 |
width: cfg.width,
|
|
|
313 |
opacity: cfg.opacity
|
|
|
314 |
}
|
|
|
315 |
} ) );
|
|
|
316 |
current.recentState = state;
|
|
|
317 |
_this.drawing.redos = [];
|
|
|
318 |
_this.drawing.undos.push( {
|
|
|
319 |
action: "modified",
|
|
|
320 |
target: current,
|
|
|
321 |
state: state
|
|
|
322 |
} );
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
_this.setup.fabric.renderAll();
|
|
|
326 |
}
|
|
|
327 |
},
|
|
|
328 |
text: function( options ) {
|
|
|
329 |
var cfg = _this.deepMerge( {
|
|
|
330 |
text: _this.i18l( "menu.label.draw.text" ),
|
|
|
331 |
top: _this.setup.fabric.height / 2,
|
|
|
332 |
left: _this.setup.fabric.width / 2,
|
|
|
333 |
fontSize: _this.drawing.fontSize,
|
|
|
334 |
fontFamily: _this.setup.chart.fontFamily || "Verdana",
|
|
|
335 |
fill: _this.drawing.color
|
|
|
336 |
}, options || {} );
|
|
|
337 |
|
|
|
338 |
cfg.click = function() {};
|
|
|
339 |
|
|
|
340 |
var text = new fabric.IText( cfg.text, cfg );
|
|
|
341 |
|
|
|
342 |
_this.setup.fabric.add( text );
|
|
|
343 |
_this.setup.fabric.setActiveObject( text );
|
|
|
344 |
|
|
|
345 |
text.selectAll();
|
|
|
346 |
text.enterEditing();
|
|
|
347 |
|
|
|
348 |
return text;
|
|
|
349 |
},
|
|
|
350 |
line: function( options ) {
|
|
|
351 |
var cfg = _this.deepMerge( {
|
|
|
352 |
x1: ( _this.setup.fabric.width / 2 ) - ( _this.setup.fabric.width / 10 ),
|
|
|
353 |
x2: ( _this.setup.fabric.width / 2 ) + ( _this.setup.fabric.width / 10 ),
|
|
|
354 |
y1: ( _this.setup.fabric.height / 2 ),
|
|
|
355 |
y2: ( _this.setup.fabric.height / 2 ),
|
|
|
356 |
angle: 90,
|
|
|
357 |
strokeLineCap: _this.drawing.lineCap,
|
|
|
358 |
arrow: _this.drawing.arrow,
|
|
|
359 |
color: _this.drawing.color,
|
|
|
360 |
width: _this.drawing.width,
|
|
|
361 |
group: [],
|
|
|
362 |
}, options || {} );
|
|
|
363 |
var i1, arrow, arrowTop, arrowLeft;
|
|
|
364 |
var line = new fabric.Line( [ cfg.x1, cfg.y1, cfg.x2, cfg.y2 ], {
|
|
|
365 |
stroke: cfg.color,
|
|
|
366 |
strokeWidth: cfg.width,
|
|
|
367 |
strokeLineCap: cfg.strokeLineCap
|
|
|
368 |
} );
|
|
|
369 |
|
|
|
370 |
cfg.group.push( line );
|
|
|
371 |
|
|
|
372 |
if ( cfg.arrow ) {
|
|
|
373 |
cfg.angle = cfg.angle ? cfg.angle : _this.getAngle( cfg.x1, cfg.y1, cfg.x2, cfg.y2 );
|
|
|
374 |
|
|
|
375 |
if ( cfg.arrow == "start" ) {
|
|
|
376 |
arrowTop = cfg.y1 + ( cfg.width / 2 );
|
|
|
377 |
arrowLeft = cfg.x1 + ( cfg.width / 2 );
|
|
|
378 |
} else if ( cfg.arrow == "middle" ) {
|
|
|
379 |
arrowTop = cfg.y2 + ( cfg.width / 2 ) - ( ( cfg.y2 - cfg.y1 ) / 2 );
|
|
|
380 |
arrowLeft = cfg.x2 + ( cfg.width / 2 ) - ( ( cfg.x2 - cfg.x1 ) / 2 );
|
|
|
381 |
} else { // arrow: end
|
|
|
382 |
arrowTop = cfg.y2 + ( cfg.width / 2 );
|
|
|
383 |
arrowLeft = cfg.x2 + ( cfg.width / 2 );
|
|
|
384 |
}
|
|
|
385 |
|
|
|
386 |
arrow = new fabric.Triangle( {
|
|
|
387 |
top: arrowTop,
|
|
|
388 |
left: arrowLeft,
|
|
|
389 |
fill: cfg.color,
|
|
|
390 |
height: cfg.width * 7,
|
|
|
391 |
width: cfg.width * 7,
|
|
|
392 |
angle: cfg.angle,
|
|
|
393 |
originX: "center",
|
|
|
394 |
originY: "bottom"
|
|
|
395 |
} );
|
|
|
396 |
cfg.group.push( arrow );
|
|
|
397 |
}
|
|
|
398 |
|
|
|
399 |
if ( cfg.action != "config" ) {
|
|
|
400 |
if ( cfg.arrow ) {
|
|
|
401 |
var group = new fabric.Group( cfg.group );
|
|
|
402 |
group.set( {
|
|
|
403 |
cfg: cfg,
|
|
|
404 |
fill: cfg.color,
|
|
|
405 |
action: cfg.action,
|
|
|
406 |
selectable: true,
|
|
|
407 |
known: cfg.action == "change"
|
|
|
408 |
} );
|
|
|
409 |
if ( cfg.action == "change" ) {
|
|
|
410 |
_this.setup.fabric.setActiveObject( group );
|
|
|
411 |
}
|
|
|
412 |
_this.setup.fabric.add( group );
|
|
|
413 |
return group;
|
|
|
414 |
} else {
|
|
|
415 |
_this.setup.fabric.add( line );
|
|
|
416 |
return line;
|
|
|
417 |
}
|
|
|
418 |
} else {
|
|
|
419 |
for ( i1 = 0; i1 < cfg.group.length; i1++ ) {
|
|
|
420 |
cfg.group[ i1 ].noUndo = true;
|
|
|
421 |
_this.setup.fabric.add( cfg.group[ i1 ] );
|
|
|
422 |
}
|
|
|
423 |
}
|
|
|
424 |
return cfg;
|
|
|
425 |
}
|
|
|
426 |
}
|
|
|
427 |
},
|
|
|
428 |
defaults: {
|
|
|
429 |
position: "top-right",
|
|
|
430 |
fileName: "amCharts",
|
|
|
431 |
action: "download",
|
|
|
432 |
overflow: true,
|
|
|
433 |
path: ( ( chart.path || "" ) + "plugins/export/" ),
|
|
|
434 |
formats: {
|
|
|
435 |
JPG: {
|
|
|
436 |
mimeType: "image/jpg",
|
|
|
437 |
extension: "jpg",
|
|
|
438 |
capture: true
|
|
|
439 |
},
|
|
|
440 |
PNG: {
|
|
|
441 |
mimeType: "image/png",
|
|
|
442 |
extension: "png",
|
|
|
443 |
capture: true
|
|
|
444 |
},
|
|
|
445 |
SVG: {
|
|
|
446 |
mimeType: "text/xml",
|
|
|
447 |
extension: "svg",
|
|
|
448 |
capture: true
|
|
|
449 |
},
|
|
|
450 |
PDF: {
|
|
|
451 |
mimeType: "application/pdf",
|
|
|
452 |
extension: "pdf",
|
|
|
453 |
capture: true
|
|
|
454 |
},
|
|
|
455 |
CSV: {
|
|
|
456 |
mimeType: "text/plain",
|
|
|
457 |
extension: "csv"
|
|
|
458 |
},
|
|
|
459 |
JSON: {
|
|
|
460 |
mimeType: "text/plain",
|
|
|
461 |
extension: "json"
|
|
|
462 |
},
|
|
|
463 |
XLSX: {
|
|
|
464 |
mimeType: "application/octet-stream",
|
|
|
465 |
extension: "xlsx"
|
|
|
466 |
}
|
|
|
467 |
},
|
|
|
468 |
fabric: {
|
|
|
469 |
backgroundColor: "#FFFFFF",
|
|
|
470 |
removeImages: true,
|
|
|
471 |
selection: false,
|
|
|
472 |
drawing: {
|
|
|
473 |
enabled: true,
|
|
|
474 |
arrow: "end",
|
|
|
475 |
lineCap: "butt",
|
|
|
476 |
mode: "pencil",
|
|
|
477 |
modes: [ "pencil", "line", "arrow" ],
|
|
|
478 |
color: "#000000",
|
|
|
479 |
colors: [ "#000000", "#FFFFFF", "#FF0000", "#00FF00", "#0000FF" ],
|
|
|
480 |
shapes: [ "11.svg", "14.svg", "16.svg", "17.svg", "20.svg", "27.svg" ],
|
|
|
481 |
width: 1,
|
|
|
482 |
fontSize: 11,
|
|
|
483 |
widths: [ 1, 5, 10, 15 ],
|
|
|
484 |
opacity: 1,
|
|
|
485 |
opacities: [ 1, 0.8, 0.6, 0.4, 0.2 ],
|
|
|
486 |
menu: undefined,
|
|
|
487 |
autoClose: true
|
|
|
488 |
}
|
|
|
489 |
},
|
|
|
490 |
pdfMake: {
|
|
|
491 |
pageSize: "A4",
|
|
|
492 |
pageOrientation: "portrait",
|
|
|
493 |
images: {},
|
|
|
494 |
content: [ "Saved from:", window.location.href, {
|
|
|
495 |
image: "reference",
|
|
|
496 |
fit: [ 523.28, 769.89 ]
|
|
|
497 |
} ]
|
|
|
498 |
},
|
|
|
499 |
menu: undefined,
|
|
|
500 |
divId: null,
|
|
|
501 |
menuReviver: null,
|
|
|
502 |
menuWalker: null,
|
|
|
503 |
fallback: true,
|
|
|
504 |
keyListener: true,
|
|
|
505 |
fileListener: true
|
|
|
506 |
},
|
|
|
507 |
|
|
|
508 |
/**
|
|
|
509 |
* Returns translated message, takes english as default
|
|
|
510 |
*/
|
|
|
511 |
i18l: function( key, language ) {
|
|
|
512 |
var lang = language ? langugage : _this.setup.chart.language ? _this.setup.chart.language : "en";
|
|
|
513 |
var catalog = AmCharts.translations[ _this.name ][ lang ] || AmCharts.translations[ _this.name ][ "en" ];
|
|
|
514 |
|
|
|
515 |
return catalog[ key ] || key;
|
|
|
516 |
},
|
|
|
517 |
|
|
|
518 |
/**
|
|
|
519 |
* Generates download file; if unsupported offers fallback to save manually
|
|
|
520 |
*/
|
|
|
521 |
download: function( data, type, filename ) {
|
|
|
522 |
// SAVE
|
|
|
523 |
if ( window.saveAs && _this.setup.hasBlob ) {
|
|
|
524 |
var blob = _this.toBlob( {
|
|
|
525 |
data: data,
|
|
|
526 |
type: type
|
|
|
527 |
}, function( data ) {
|
|
|
528 |
saveAs( data, filename );
|
|
|
529 |
} );
|
|
|
530 |
|
|
|
531 |
// FALLBACK TEXTAREA
|
|
|
532 |
} else if ( _this.config.fallback && type == "text/plain" ) {
|
|
|
533 |
var div = document.createElement( "div" );
|
|
|
534 |
var msg = document.createElement( "div" );
|
|
|
535 |
var textarea = document.createElement( "textarea" );
|
|
|
536 |
|
|
|
537 |
msg.innerHTML = _this.i18l( "fallback.save.text" );
|
|
|
538 |
|
|
|
539 |
div.appendChild( msg );
|
|
|
540 |
div.appendChild( textarea );
|
|
|
541 |
msg.setAttribute( "class", "amcharts-export-fallback-message" );
|
|
|
542 |
div.setAttribute( "class", "amcharts-export-fallback" );
|
|
|
543 |
_this.setup.chart.containerDiv.appendChild( div );
|
|
|
544 |
|
|
|
545 |
// FULFILL TEXTAREA AND PRESELECT
|
|
|
546 |
textarea.setAttribute( "readonly", "" );
|
|
|
547 |
textarea.value = data;
|
|
|
548 |
textarea.focus();
|
|
|
549 |
textarea.select();
|
|
|
550 |
|
|
|
551 |
// UPDATE MENU
|
|
|
552 |
_this.createMenu( [ {
|
|
|
553 |
"class": "export-main export-close",
|
|
|
554 |
label: "Done",
|
|
|
555 |
click: function() {
|
|
|
556 |
_this.createMenu( _this.config.menu );
|
|
|
557 |
_this.setup.chart.containerDiv.removeChild( div );
|
|
|
558 |
}
|
|
|
559 |
} ] );
|
|
|
560 |
|
|
|
561 |
// FALLBACK IMAGE
|
|
|
562 |
} else if ( _this.config.fallback && type.split( "/" )[ 0 ] == "image" ) {
|
|
|
563 |
var div = document.createElement( "div" );
|
|
|
564 |
var msg = document.createElement( "div" );
|
|
|
565 |
var img = _this.toImage( {
|
|
|
566 |
data: data
|
|
|
567 |
} );
|
|
|
568 |
|
|
|
569 |
msg.innerHTML = _this.i18l( "fallback.save.image" );
|
|
|
570 |
|
|
|
571 |
// FULFILL TEXTAREA AND PRESELECT
|
|
|
572 |
div.appendChild( msg );
|
|
|
573 |
div.appendChild( img );
|
|
|
574 |
msg.setAttribute( "class", "amcharts-export-fallback-message" );
|
|
|
575 |
div.setAttribute( "class", "amcharts-export-fallback" );
|
|
|
576 |
_this.setup.chart.containerDiv.appendChild( div );
|
|
|
577 |
|
|
|
578 |
// UPDATE MENU
|
|
|
579 |
_this.createMenu( [ {
|
|
|
580 |
"class": "export-main export-close",
|
|
|
581 |
label: "Done",
|
|
|
582 |
click: function() {
|
|
|
583 |
_this.createMenu( _this.config.menu );
|
|
|
584 |
_this.setup.chart.containerDiv.removeChild( div );
|
|
|
585 |
}
|
|
|
586 |
} ] );
|
|
|
587 |
|
|
|
588 |
// ERROR
|
|
|
589 |
} else {
|
|
|
590 |
throw new Error( "Unable to create file. Ensure saveAs (FileSaver.js) is supported." );
|
|
|
591 |
}
|
|
|
592 |
return data;
|
|
|
593 |
},
|
|
|
594 |
|
|
|
595 |
/**
|
|
|
596 |
* Generates script, links tags and places them into the document's head
|
|
|
597 |
* In case of reload it replaces the node to force the download
|
|
|
598 |
*/
|
|
|
599 |
loadResource: function( src, addons ) {
|
|
|
600 |
var i1, exist, node, item, check, type;
|
|
|
601 |
var url = src.indexOf( "//" ) != -1 ? src : [ _this.libs.path, src ].join( "" );
|
|
|
602 |
|
|
|
603 |
function callback() {
|
|
|
604 |
if ( addons ) {
|
|
|
605 |
for ( i1 = 0; i1 < addons.length; i1++ ) {
|
|
|
606 |
_this.loadResource( addons[ i1 ] );
|
|
|
607 |
}
|
|
|
608 |
}
|
|
|
609 |
}
|
|
|
610 |
|
|
|
611 |
if ( src.indexOf( ".js" ) != -1 ) {
|
|
|
612 |
node = document.createElement( "script" );
|
|
|
613 |
node.setAttribute( "type", "text/javascript" );
|
|
|
614 |
node.setAttribute( "src", url );
|
|
|
615 |
if ( _this.libs.async ) {
|
|
|
616 |
node.setAttribute( "async", "" );
|
|
|
617 |
}
|
|
|
618 |
|
|
|
619 |
} else if ( src.indexOf( ".css" ) != -1 ) {
|
|
|
620 |
node = document.createElement( "link" );
|
|
|
621 |
node.setAttribute( "type", "text/css" );
|
|
|
622 |
node.setAttribute( "rel", "stylesheet" );
|
|
|
623 |
node.setAttribute( "href", url );
|
|
|
624 |
}
|
|
|
625 |
|
|
|
626 |
// NODE CHECK
|
|
|
627 |
for ( i1 = 0; i1 < document.head.childNodes.length; i1++ ) {
|
|
|
628 |
item = document.head.childNodes[ i1 ];
|
|
|
629 |
check = item ? ( item.src || item.href ) : false;
|
|
|
630 |
type = item ? item.tagName : false;
|
|
|
631 |
|
|
|
632 |
if ( item && check && check.indexOf( src ) != -1 ) {
|
|
|
633 |
if ( _this.libs.reload ) {
|
|
|
634 |
document.head.removeChild( item );
|
|
|
635 |
}
|
|
|
636 |
exist = true;
|
|
|
637 |
break;
|
|
|
638 |
}
|
|
|
639 |
}
|
|
|
640 |
|
|
|
641 |
// NAMESPACE CHECK
|
|
|
642 |
for ( i1 in _this.libs.namespaces ) {
|
|
|
643 |
var namespace = _this.libs.namespaces[ i1 ];
|
|
|
644 |
var check = src.toLowerCase();
|
|
|
645 |
var item = i1.toLowerCase();
|
|
|
646 |
if ( check.indexOf( item ) != -1 && window[ namespace ] !== undefined ) {
|
|
|
647 |
exist = true;
|
|
|
648 |
break;
|
|
|
649 |
}
|
|
|
650 |
}
|
|
|
651 |
|
|
|
652 |
if ( !exist || _this.libs.reload ) {
|
|
|
653 |
node.addEventListener( "load", callback );
|
|
|
654 |
document.head.appendChild( node );
|
|
|
655 |
}
|
|
|
656 |
|
|
|
657 |
},
|
|
|
658 |
|
|
|
659 |
/**
|
|
|
660 |
* Walker to generate the script,link tags
|
|
|
661 |
*/
|
|
|
662 |
loadDependencies: function() {
|
|
|
663 |
var i1, i2;
|
|
|
664 |
if ( _this.libs.autoLoad ) {
|
|
|
665 |
for ( i1 = 0; i1 < _this.libs.resources.length; i1++ ) {
|
|
|
666 |
if ( _this.libs.resources[ i1 ] instanceof Object ) {
|
|
|
667 |
for ( i2 in _this.libs.resources[ i1 ] ) {
|
|
|
668 |
_this.loadResource( i2, _this.libs.resources[ i1 ][ i2 ] );
|
|
|
669 |
}
|
|
|
670 |
} else {
|
|
|
671 |
_this.loadResource( _this.libs.resources[ i1 ] );
|
|
|
672 |
}
|
|
|
673 |
}
|
|
|
674 |
}
|
|
|
675 |
},
|
|
|
676 |
|
|
|
677 |
/**
|
|
|
678 |
* Converts string to number
|
|
|
679 |
*/
|
|
|
680 |
pxToNumber: function( attr, returnUndefined ) {
|
|
|
681 |
if ( !attr && returnUndefined ) {
|
|
|
682 |
return undefined;
|
|
|
683 |
}
|
|
|
684 |
return Number( String( attr ).replace( "px", "" ) ) || 0;
|
|
|
685 |
},
|
|
|
686 |
|
|
|
687 |
/**
|
|
|
688 |
* Converts number to string
|
|
|
689 |
*/
|
|
|
690 |
numberToPx: function( attr ) {
|
|
|
691 |
return String( attr ) + "px";
|
|
|
692 |
},
|
|
|
693 |
|
|
|
694 |
/**
|
|
|
695 |
* Recursive method to merge the given objects together
|
|
|
696 |
* Overwrite flag replaces the value instead to crawl through
|
|
|
697 |
*/
|
|
|
698 |
deepMerge: function( a, b, overwrite ) {
|
|
|
699 |
var i1, v, type = b instanceof Array ? "array" : "object";
|
|
|
700 |
|
|
|
701 |
for ( i1 in b ) {
|
|
|
702 |
// PREVENT METHODS
|
|
|
703 |
if ( type == "array" && isNaN( i1 ) ) {
|
|
|
704 |
continue;
|
|
|
705 |
}
|
|
|
706 |
|
|
|
707 |
v = b[ i1 ];
|
|
|
708 |
|
|
|
709 |
// NEW
|
|
|
710 |
if ( a[ i1 ] == undefined || overwrite ) {
|
|
|
711 |
if ( v instanceof Array ) {
|
|
|
712 |
a[ i1 ] = new Array();
|
|
|
713 |
} else if ( v instanceof Function ) {
|
|
|
714 |
a[ i1 ] = function() {};
|
|
|
715 |
} else if ( v instanceof Date ) {
|
|
|
716 |
a[ i1 ] = new Date();
|
|
|
717 |
} else if ( v instanceof Object ) {
|
|
|
718 |
a[ i1 ] = new Object();
|
|
|
719 |
} else if ( v instanceof Number ) {
|
|
|
720 |
a[ i1 ] = new Number();
|
|
|
721 |
} else if ( v instanceof String ) {
|
|
|
722 |
a[ i1 ] = new String();
|
|
|
723 |
}
|
|
|
724 |
}
|
|
|
725 |
|
|
|
726 |
if (
|
|
|
727 |
( a instanceof Object || a instanceof Array ) &&
|
|
|
728 |
( v instanceof Object || v instanceof Array ) &&
|
|
|
729 |
!( v instanceof Function || v instanceof Date || _this.isElement( v ) ) &&
|
|
|
730 |
i1 != "chart"
|
|
|
731 |
) {
|
|
|
732 |
_this.deepMerge( a[ i1 ], v, overwrite );
|
|
|
733 |
} else {
|
|
|
734 |
if ( a instanceof Array && !overwrite ) {
|
|
|
735 |
a.push( v );
|
|
|
736 |
} else {
|
|
|
737 |
a[ i1 ] = v;
|
|
|
738 |
}
|
|
|
739 |
}
|
|
|
740 |
}
|
|
|
741 |
return a;
|
|
|
742 |
},
|
|
|
743 |
|
|
|
744 |
/**
|
|
|
745 |
* Checks if given argument is a valid node
|
|
|
746 |
*/
|
|
|
747 |
isElement: function( thingy ) {
|
|
|
748 |
return thingy instanceof Object && thingy && thingy.nodeType === 1;
|
|
|
749 |
},
|
|
|
750 |
|
|
|
751 |
/**
|
|
|
752 |
* Checks if given argument contains a hashbang and returns it
|
|
|
753 |
*/
|
|
|
754 |
isHashbanged: function( thingy ) {
|
|
|
755 |
var str = String( thingy ).replace( /\"/g, "" );
|
|
|
756 |
|
|
|
757 |
return str.slice( 0, 3 ) == "url" ? str.slice( str.indexOf( "#" ) + 1, str.length - 1 ) : false;
|
|
|
758 |
},
|
|
|
759 |
|
|
|
760 |
/**
|
|
|
761 |
* Checks if given event has been thrown with pressed click / touch
|
|
|
762 |
*/
|
|
|
763 |
isPressed: function( event ) {
|
|
|
764 |
// IE EXCEPTION
|
|
|
765 |
if ( event.type == "mousemove" && event.which === 1 ) {
|
|
|
766 |
// IGNORE
|
|
|
767 |
|
|
|
768 |
// OTHERS
|
|
|
769 |
} else if (
|
|
|
770 |
event.type == "touchmove" ||
|
|
|
771 |
event.buttons === 1 ||
|
|
|
772 |
event.button === 1 ||
|
|
|
773 |
event.which === 1
|
|
|
774 |
) {
|
|
|
775 |
_this.drawing.buffer.isPressed = true;
|
|
|
776 |
} else {
|
|
|
777 |
_this.drawing.buffer.isPressed = false;
|
|
|
778 |
}
|
|
|
779 |
return _this.drawing.buffer.isPressed;
|
|
|
780 |
},
|
|
|
781 |
|
|
|
782 |
/**
|
|
|
783 |
* Checks if given source is within the current origin
|
|
|
784 |
*/
|
|
|
785 |
isTainted: function( source ) {
|
|
|
786 |
var origin = String( window.location.origin || window.location.protocol + "//" + window.location.hostname + ( window.location.port ? ':' + window.location.port : '' ) );
|
|
|
787 |
|
|
|
788 |
// CHECK IF TAINTED
|
|
|
789 |
if (
|
|
|
790 |
source &&
|
|
|
791 |
source.indexOf( "//" ) != -1 &&
|
|
|
792 |
source.indexOf( origin.replace( /.*:/, "" ) ) == -1
|
|
|
793 |
) {
|
|
|
794 |
return true;
|
|
|
795 |
}
|
|
|
796 |
return false;
|
|
|
797 |
},
|
|
|
798 |
|
|
|
799 |
/*
|
|
|
800 |
** Checks several indicators for acceptance;
|
|
|
801 |
*/
|
|
|
802 |
isSupported: function() {
|
|
|
803 |
// CHECK CONFIG
|
|
|
804 |
if ( !_this.config.enabled ) {
|
|
|
805 |
return false;
|
|
|
806 |
}
|
|
|
807 |
|
|
|
808 |
// CHECK IE; ATTEMPT TO ACCESS HEAD ELEMENT
|
|
|
809 |
if ( AmCharts.isIE && AmCharts.IEversion <= 9 ) {
|
|
|
810 |
if ( !Array.prototype.indexOf || !document.head || _this.config.fallback === false ) {
|
|
|
811 |
return false;
|
|
|
812 |
}
|
|
|
813 |
}
|
|
|
814 |
return true;
|
|
|
815 |
},
|
|
|
816 |
|
|
|
817 |
|
|
|
818 |
getAngle: function( x1, y1, x2, y2 ) {
|
|
|
819 |
var x = x2 - x1;
|
|
|
820 |
var y = y2 - y1;
|
|
|
821 |
var angle;
|
|
|
822 |
if ( x == 0 ) {
|
|
|
823 |
if ( y == 0 ) {
|
|
|
824 |
angle = 0;
|
|
|
825 |
} else if ( y > 0 ) {
|
|
|
826 |
angle = Math.PI / 2;
|
|
|
827 |
} else {
|
|
|
828 |
angle = Math.PI * 3 / 2;
|
|
|
829 |
}
|
|
|
830 |
} else if ( y == 0 ) {
|
|
|
831 |
if ( x > 0 ) {
|
|
|
832 |
angle = 0;
|
|
|
833 |
} else {
|
|
|
834 |
angle = Math.PI;
|
|
|
835 |
}
|
|
|
836 |
} else {
|
|
|
837 |
if ( x < 0 ) {
|
|
|
838 |
angle = Math.atan( y / x ) + Math.PI;
|
|
|
839 |
} else if ( y < 0 ) {
|
|
|
840 |
angle = Math.atan( y / x ) + ( 2 * Math.PI );
|
|
|
841 |
} else {
|
|
|
842 |
angle = Math.atan( y / x );
|
|
|
843 |
}
|
|
|
844 |
}
|
|
|
845 |
return angle * 180 / Math.PI;
|
|
|
846 |
},
|
|
|
847 |
|
|
|
848 |
/**
|
|
|
849 |
* Recursive method which crawls upwards to gather the requested attribute
|
|
|
850 |
*/
|
|
|
851 |
gatherAttribute: function( elm, attr, limit, lvl ) {
|
|
|
852 |
var value, lvl = lvl ? lvl : 0,
|
|
|
853 |
limit = limit ? limit : 3;
|
|
|
854 |
if ( elm ) {
|
|
|
855 |
value = elm.getAttribute( attr );
|
|
|
856 |
|
|
|
857 |
if ( !value && lvl < limit ) {
|
|
|
858 |
return _this.gatherAttribute( elm.parentNode, attr, limit, lvl + 1 );
|
|
|
859 |
}
|
|
|
860 |
}
|
|
|
861 |
return value;
|
|
|
862 |
},
|
|
|
863 |
|
|
|
864 |
/**
|
|
|
865 |
* Recursive method which crawls upwards to gather the requested classname
|
|
|
866 |
*/
|
|
|
867 |
gatherClassName: function( elm, className, limit, lvl ) {
|
|
|
868 |
var value, lvl = lvl ? lvl : 0,
|
|
|
869 |
limit = limit ? limit : 3;
|
|
|
870 |
|
|
|
871 |
if ( _this.isElement( elm ) ) {
|
|
|
872 |
value = ( elm.getAttribute( "class" ) || "" ).split( " " ).indexOf( className ) != -1;
|
|
|
873 |
|
|
|
874 |
if ( !value && lvl < limit ) {
|
|
|
875 |
return _this.gatherClassName( elm.parentNode, className, limit, lvl + 1 );
|
|
|
876 |
} else if ( value ) {
|
|
|
877 |
value = elm;
|
|
|
878 |
}
|
|
|
879 |
}
|
|
|
880 |
return value;
|
|
|
881 |
},
|
|
|
882 |
|
|
|
883 |
/**
|
|
|
884 |
* Collects the clip-paths and patterns
|
|
|
885 |
*/
|
|
|
886 |
gatherElements: function( group, cfg, images ) {
|
|
|
887 |
var i1, i2;
|
|
|
888 |
for ( i1 = 0; i1 < group.children.length; i1++ ) {
|
|
|
889 |
var childNode = group.children[ i1 ];
|
|
|
890 |
|
|
|
891 |
// CLIPPATH
|
|
|
892 |
if ( childNode.tagName == "clipPath" ) {
|
|
|
893 |
var bbox = {};
|
|
|
894 |
var transform = fabric.parseTransformAttribute( _this.gatherAttribute( childNode, "transform" ) );
|
|
|
895 |
|
|
|
896 |
// HIDE SIBLINGS; GATHER IT'S DIMENSIONS
|
|
|
897 |
for ( i2 = 0; i2 < childNode.childNodes.length; i2++ ) {
|
|
|
898 |
childNode.childNodes[ i2 ].setAttribute( "fill", "transparent" );
|
|
|
899 |
bbox = {
|
|
|
900 |
x: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( "x" ) ),
|
|
|
901 |
y: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( "y" ) ),
|
|
|
902 |
width: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( "width" ) ),
|
|
|
903 |
height: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( "height" ) )
|
|
|
904 |
}
|
|
|
905 |
}
|
|
|
906 |
|
|
|
907 |
group.clippings[ childNode.id ] = {
|
|
|
908 |
svg: childNode,
|
|
|
909 |
bbox: bbox,
|
|
|
910 |
transform: transform
|
|
|
911 |
};
|
|
|
912 |
|
|
|
913 |
// PATTERN
|
|
|
914 |
} else if ( childNode.tagName == "pattern" ) {
|
|
|
915 |
var props = {
|
|
|
916 |
node: childNode,
|
|
|
917 |
source: childNode.getAttribute( "xlink:href" ),
|
|
|
918 |
width: Number( childNode.getAttribute( "width" ) ),
|
|
|
919 |
height: Number( childNode.getAttribute( "height" ) ),
|
|
|
920 |
repeat: "repeat"
|
|
|
921 |
}
|
|
|
922 |
|
|
|
923 |
// GATHER BACKGROUND COLOR
|
|
|
924 |
for ( i2 = 0; i2 < childNode.childNodes.length; i2++ ) {
|
|
|
925 |
if ( childNode.childNodes[ i2 ].tagName == "rect" ) {
|
|
|
926 |
props.fill = childNode.childNodes[ i2 ].getAttribute( "fill" );
|
|
|
927 |
}
|
|
|
928 |
}
|
|
|
929 |
|
|
|
930 |
// TAINTED
|
|
|
931 |
if ( cfg.removeImages && _this.isTainted( props.source ) ) {
|
|
|
932 |
group.patterns[ childNode.id ] = props.fill ? props.fill : "transparent";
|
|
|
933 |
} else {
|
|
|
934 |
images.included++;
|
|
|
935 |
|
|
|
936 |
group.patterns[ props.node.id ] = props;
|
|
|
937 |
}
|
|
|
938 |
|
|
|
939 |
// IMAGES
|
|
|
940 |
} else if ( childNode.tagName == "image" ) {
|
|
|
941 |
images.included++;
|
|
|
942 |
|
|
|
943 |
// LOAD IMAGE MANUALLY; TO RERENDER THE CANVAS
|
|
|
944 |
fabric.Image.fromURL( childNode.getAttribute( "xlink:href" ), function( img ) {
|
|
|
945 |
images.loaded++;
|
|
|
946 |
} );
|
|
|
947 |
}
|
|
|
948 |
}
|
|
|
949 |
return group;
|
|
|
950 |
},
|
|
|
951 |
|
|
|
952 |
/*
|
|
|
953 |
** GATHER MOUSE POSITION;
|
|
|
954 |
*/
|
|
|
955 |
gatherPosition: function( event, type ) {
|
|
|
956 |
var ref = _this.drawing.buffer.position;
|
|
|
957 |
var ivt = fabric.util.invertTransform( _this.setup.fabric.viewportTransform );
|
|
|
958 |
var pos;
|
|
|
959 |
|
|
|
960 |
if ( event.type == "touchmove" ) {
|
|
|
961 |
if ( "touches" in event ) {
|
|
|
962 |
event = event.touches[ 0 ];
|
|
|
963 |
} else if ( "changedTouches" in event ) {
|
|
|
964 |
event = event.changedTouches[ 0 ];
|
|
|
965 |
}
|
|
|
966 |
}
|
|
|
967 |
|
|
|
968 |
pos = fabric.util.transformPoint( _this.setup.fabric.getPointer( event, true ), ivt );
|
|
|
969 |
|
|
|
970 |
if ( type == 1 ) {
|
|
|
971 |
ref.x1 = pos.x;
|
|
|
972 |
ref.y1 = pos.y;
|
|
|
973 |
}
|
|
|
974 |
|
|
|
975 |
ref.x2 = pos.x;
|
|
|
976 |
ref.y2 = pos.y;
|
|
|
977 |
ref.xD = ( ref.x1 - ref.x2 ) < 0 ? ( ref.x1 - ref.x2 ) * -1 : ( ref.x1 - ref.x2 );
|
|
|
978 |
ref.yD = ( ref.y1 - ref.y2 ) < 0 ? ( ref.y1 - ref.y2 ) * -1 : ( ref.y1 - ref.y2 );
|
|
|
979 |
|
|
|
980 |
return ref;
|
|
|
981 |
},
|
|
|
982 |
|
|
|
983 |
/**
|
|
|
984 |
* Method to capture the current state of the chart
|
|
|
985 |
*/
|
|
|
986 |
capture: function( options, callback ) {
|
|
|
987 |
var i1;
|
|
|
988 |
var cfg = _this.deepMerge( _this.deepMerge( {}, _this.config.fabric ), options || {} );
|
|
|
989 |
var groups = [];
|
|
|
990 |
var offset = {
|
|
|
991 |
x: 0,
|
|
|
992 |
y: 0,
|
|
|
993 |
pX: 0,
|
|
|
994 |
pY: 0,
|
|
|
995 |
width: _this.setup.chart.divRealWidth,
|
|
|
996 |
height: _this.setup.chart.divRealHeight
|
|
|
997 |
};
|
|
|
998 |
var images = {
|
|
|
999 |
loaded: 0,
|
|
|
1000 |
included: 0
|
|
|
1001 |
}
|
|
|
1002 |
|
|
|
1003 |
fabric.ElementsParser.prototype.resolveGradient = function( obj, property ) {
|
|
|
1004 |
|
|
|
1005 |
var instanceFillValue = obj.get( property );
|
|
|
1006 |
if ( !( /^url\(/ ).test( instanceFillValue ) ) {
|
|
|
1007 |
return;
|
|
|
1008 |
}
|
|
|
1009 |
var gradientId = instanceFillValue.slice( instanceFillValue.indexOf( "#" ) + 1, instanceFillValue.length - 1 );
|
|
|
1010 |
if ( fabric.gradientDefs[ this.svgUid ][ gradientId ] ) {
|
|
|
1011 |
obj.set( property, fabric.Gradient.fromElement( fabric.gradientDefs[ this.svgUid ][ gradientId ], obj ) );
|
|
|
1012 |
}
|
|
|
1013 |
};
|
|
|
1014 |
|
|
|
1015 |
// BEFORE CAPTURING
|
|
|
1016 |
_this.handleCallback( cfg.beforeCapture, cfg );
|
|
|
1017 |
|
|
|
1018 |
// GATHER SVGS
|
|
|
1019 |
var svgs = _this.setup.chart.containerDiv.getElementsByTagName( "svg" );
|
|
|
1020 |
for ( i1 = 0; i1 < svgs.length; i1++ ) {
|
|
|
1021 |
var group = {
|
|
|
1022 |
svg: svgs[ i1 ],
|
|
|
1023 |
parent: svgs[ i1 ].parentNode,
|
|
|
1024 |
children: svgs[ i1 ].getElementsByTagName( "*" ),
|
|
|
1025 |
offset: {
|
|
|
1026 |
x: 0,
|
|
|
1027 |
y: 0
|
|
|
1028 |
},
|
|
|
1029 |
patterns: {},
|
|
|
1030 |
clippings: {}
|
|
|
1031 |
}
|
|
|
1032 |
|
|
|
1033 |
// GATHER ELEMENTS
|
|
|
1034 |
group = _this.gatherElements( group, cfg, images );
|
|
|
1035 |
|
|
|
1036 |
// APPEND GROUP
|
|
|
1037 |
groups.push( group );
|
|
|
1038 |
}
|
|
|
1039 |
|
|
|
1040 |
// GATHER EXTERNAL LEGEND
|
|
|
1041 |
if ( _this.config.legend && _this.setup.chart.legend && _this.setup.chart.legend.position == "outside" ) {
|
|
|
1042 |
var group = {
|
|
|
1043 |
svg: _this.setup.chart.legend.container.container,
|
|
|
1044 |
parent: _this.setup.chart.legend.container.container.parentNode,
|
|
|
1045 |
children: _this.setup.chart.legend.container.container.getElementsByTagName( "*" ),
|
|
|
1046 |
offset: {
|
|
|
1047 |
x: 0,
|
|
|
1048 |
y: 0
|
|
|
1049 |
},
|
|
|
1050 |
legend: {
|
|
|
1051 |
type: [ "top", "left" ].indexOf( _this.config.legend.position ) != -1 ? "unshift" : "push",
|
|
|
1052 |
position: _this.config.legend.position,
|
|
|
1053 |
width: _this.config.legend.width ? _this.config.legend.width : _this.setup.chart.legend.container.width,
|
|
|
1054 |
height: _this.config.legend.height ? _this.config.legend.height : _this.setup.chart.legend.container.height
|
|
|
1055 |
},
|
|
|
1056 |
patterns: {},
|
|
|
1057 |
clippings: {}
|
|
|
1058 |
}
|
|
|
1059 |
|
|
|
1060 |
// ADAPT CANVAS DIMENSIONS
|
|
|
1061 |
if ( [ "left", "right" ].indexOf( group.legend.position ) != -1 ) {
|
|
|
1062 |
offset.width += group.legend.width;
|
|
|
1063 |
offset.height = group.legend.height > offset.height ? group.legend.height : offset.height;
|
|
|
1064 |
} else if ( [ "top", "bottom" ].indexOf( group.legend.position ) != -1 ) {
|
|
|
1065 |
offset.height += group.legend.height;
|
|
|
1066 |
}
|
|
|
1067 |
|
|
|
1068 |
// GATHER ELEMENTS
|
|
|
1069 |
group = _this.gatherElements( group, cfg, images );
|
|
|
1070 |
|
|
|
1071 |
// PRE/APPEND SVG
|
|
|
1072 |
groups[ group.legend.type ]( group );
|
|
|
1073 |
}
|
|
|
1074 |
|
|
|
1075 |
// CLEAR IF EXIST
|
|
|
1076 |
_this.drawing.buffer.enabled = cfg.action == "draw";
|
|
|
1077 |
|
|
|
1078 |
_this.setup.wrapper = document.createElement( "div" );
|
|
|
1079 |
_this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas" );
|
|
|
1080 |
_this.setup.chart.containerDiv.appendChild( _this.setup.wrapper );
|
|
|
1081 |
|
|
|
1082 |
// STOCK CHART; SELECTOR OFFSET
|
|
|
1083 |
if ( _this.setup.chart.type == "stock" ) {
|
|
|
1084 |
var padding = {
|
|
|
1085 |
top: 0,
|
|
|
1086 |
right: 0,
|
|
|
1087 |
bottom: 0,
|
|
|
1088 |
left: 0
|
|
|
1089 |
}
|
|
|
1090 |
if ( _this.setup.chart.leftContainer ) {
|
|
|
1091 |
offset.width -= _this.setup.chart.leftContainer.offsetWidth;
|
|
|
1092 |
padding.left = _this.setup.chart.leftContainer.offsetWidth + ( _this.setup.chart.panelsSettings.panelSpacing * 2 );
|
|
|
1093 |
}
|
|
|
1094 |
if ( _this.setup.chart.rightContainer ) {
|
|
|
1095 |
offset.width -= _this.setup.chart.rightContainer.offsetWidth;
|
|
|
1096 |
padding.right = _this.setup.chart.rightContainer.offsetWidth + ( _this.setup.chart.panelsSettings.panelSpacing * 2 );
|
|
|
1097 |
}
|
|
|
1098 |
if ( _this.setup.chart.periodSelector && [ "top", "bottom" ].indexOf( _this.setup.chart.periodSelector.position ) != -1 ) {
|
|
|
1099 |
offset.height -= _this.setup.chart.periodSelector.offsetHeight + _this.setup.chart.panelsSettings.panelSpacing;
|
|
|
1100 |
padding[ _this.setup.chart.periodSelector.position ] += _this.setup.chart.periodSelector.offsetHeight + _this.setup.chart.panelsSettings.panelSpacing;
|
|
|
1101 |
}
|
|
|
1102 |
if ( _this.setup.chart.dataSetSelector && [ "top", "bottom" ].indexOf( _this.setup.chart.dataSetSelector.position ) != -1 ) {
|
|
|
1103 |
offset.height -= _this.setup.chart.dataSetSelector.offsetHeight;
|
|
|
1104 |
padding[ _this.setup.chart.dataSetSelector.position ] += _this.setup.chart.dataSetSelector.offsetHeight;
|
|
|
1105 |
}
|
|
|
1106 |
|
|
|
1107 |
// APPLY OFFSET ON WRAPPER
|
|
|
1108 |
_this.setup.wrapper.style.paddingTop = _this.numberToPx( padding.top );
|
|
|
1109 |
_this.setup.wrapper.style.paddingRight = _this.numberToPx( padding.right );
|
|
|
1110 |
_this.setup.wrapper.style.paddingBottom = _this.numberToPx( padding.bottom );
|
|
|
1111 |
_this.setup.wrapper.style.paddingLeft = _this.numberToPx( padding.left );
|
|
|
1112 |
}
|
|
|
1113 |
|
|
|
1114 |
// CREATE CANVAS
|
|
|
1115 |
_this.setup.canvas = document.createElement( "canvas" );
|
|
|
1116 |
_this.setup.wrapper.appendChild( _this.setup.canvas );
|
|
|
1117 |
_this.setup.fabric = new fabric.Canvas( _this.setup.canvas, _this.deepMerge( {
|
|
|
1118 |
width: offset.width,
|
|
|
1119 |
height: offset.height,
|
|
|
1120 |
isDrawingMode: true
|
|
|
1121 |
}, cfg ) );
|
|
|
1122 |
|
|
|
1123 |
// REAPPLY FOR SOME REASON
|
|
|
1124 |
_this.deepMerge( _this.setup.fabric, cfg );
|
|
|
1125 |
_this.deepMerge( _this.setup.fabric.freeDrawingBrush, cfg.drawing );
|
|
|
1126 |
|
|
|
1127 |
// RELIABLE VARIABLES; UPDATE DRAWING
|
|
|
1128 |
_this.deepMerge( _this.drawing, cfg.drawing );
|
|
|
1129 |
_this.drawing.handler.change( cfg.drawing );
|
|
|
1130 |
|
|
|
1131 |
// OBSERVE MOUSE EVENTS
|
|
|
1132 |
_this.setup.fabric.on( "mouse:down", function( e ) {
|
|
|
1133 |
var p = _this.gatherPosition( e.e, 1 );
|
|
|
1134 |
_this.drawing.buffer.pressedTS = Number( new Date() );
|
|
|
1135 |
_this.isPressed( e.e );
|
|
|
1136 |
} );
|
|
|
1137 |
_this.setup.fabric.on( "mouse:move", function( e ) {
|
|
|
1138 |
var p = _this.gatherPosition( e.e, 2 );
|
|
|
1139 |
_this.isPressed( e.e );
|
|
|
1140 |
|
|
|
1141 |
// CREATE INITIAL LINE / ARROW; JUST ON LEFT CLICK
|
|
|
1142 |
if ( _this.drawing.buffer.isPressed && !_this.drawing.buffer.line ) {
|
|
|
1143 |
if ( !_this.drawing.buffer.isSelected && _this.drawing.mode != "pencil" && ( p.xD > 5 || p.xD > 5 ) ) {
|
|
|
1144 |
_this.drawing.buffer.hasLine = true;
|
|
|
1145 |
_this.setup.fabric.isDrawingMode = false;
|
|
|
1146 |
_this.setup.fabric._onMouseUpInDrawingMode( e );
|
|
|
1147 |
_this.drawing.buffer.line = _this.drawing.handler.line( {
|
|
|
1148 |
x1: p.x1,
|
|
|
1149 |
y1: p.y1,
|
|
|
1150 |
x2: p.x2,
|
|
|
1151 |
y2: p.y2,
|
|
|
1152 |
arrow: _this.drawing.mode == "line" ? false : _this.drawing.arrow,
|
|
|
1153 |
action: "config"
|
|
|
1154 |
} );
|
|
|
1155 |
}
|
|
|
1156 |
}
|
|
|
1157 |
|
|
|
1158 |
// UPDATE LINE / ARROW
|
|
|
1159 |
if ( _this.drawing.buffer.line ) {
|
|
|
1160 |
var obj, top, left;
|
|
|
1161 |
var l = _this.drawing.buffer.line;
|
|
|
1162 |
|
|
|
1163 |
l.x2 = p.x2;
|
|
|
1164 |
l.y2 = p.y2;
|
|
|
1165 |
|
|
|
1166 |
for ( i1 = 0; i1 < l.group.length; i1++ ) {
|
|
|
1167 |
obj = l.group[ i1 ];
|
|
|
1168 |
|
|
|
1169 |
if ( obj instanceof fabric.Line ) {
|
|
|
1170 |
obj.set( {
|
|
|
1171 |
x2: l.x2,
|
|
|
1172 |
y2: l.y2
|
|
|
1173 |
} );
|
|
|
1174 |
} else if ( obj instanceof fabric.Triangle ) {
|
|
|
1175 |
l.angle = ( _this.getAngle( l.x1, l.y1, l.x2, l.y2 ) + 90 );
|
|
|
1176 |
|
|
|
1177 |
if ( l.arrow == "start" ) {
|
|
|
1178 |
top = l.y1 + ( l.width / 2 );
|
|
|
1179 |
left = l.x1 + ( l.width / 2 );
|
|
|
1180 |
} else if ( l.arrow == "middle" ) {
|
|
|
1181 |
top = l.y2 + ( l.width / 2 ) - ( ( l.y2 - l.y1 ) / 2 );
|
|
|
1182 |
left = l.x2 + ( l.width / 2 ) - ( ( l.x2 - l.x1 ) / 2 );
|
|
|
1183 |
} else { // arrow: end
|
|
|
1184 |
top = l.y2 + ( l.width / 2 );
|
|
|
1185 |
left = l.x2 + ( l.width / 2 );
|
|
|
1186 |
}
|
|
|
1187 |
|
|
|
1188 |
obj.set( {
|
|
|
1189 |
top: top,
|
|
|
1190 |
left: left,
|
|
|
1191 |
angle: l.angle
|
|
|
1192 |
} );
|
|
|
1193 |
}
|
|
|
1194 |
}
|
|
|
1195 |
_this.setup.fabric.renderAll();
|
|
|
1196 |
}
|
|
|
1197 |
} );
|
|
|
1198 |
_this.setup.fabric.on( "mouse:up", function( e ) {
|
|
|
1199 |
// SELECT TARGET
|
|
|
1200 |
if ( Number( new Date() ) - _this.drawing.buffer.pressedTS < 200 ) {
|
|
|
1201 |
var target = _this.setup.fabric.findTarget( e.e );
|
|
|
1202 |
if ( target && target.selectable ) {
|
|
|
1203 |
_this.setup.fabric.setActiveObject( target );
|
|
|
1204 |
}
|
|
|
1205 |
}
|
|
|
1206 |
|
|
|
1207 |
// UPDATE LINE / ARROW
|
|
|
1208 |
if ( _this.drawing.buffer.line ) {
|
|
|
1209 |
for ( i1 = 0; i1 < _this.drawing.buffer.line.group.length; i1++ ) {
|
|
|
1210 |
_this.drawing.buffer.line.group[ i1 ].remove();
|
|
|
1211 |
}
|
|
|
1212 |
delete _this.drawing.buffer.line.action;
|
|
|
1213 |
delete _this.drawing.buffer.line.group;
|
|
|
1214 |
_this.drawing.handler.line( _this.drawing.buffer.line );
|
|
|
1215 |
}
|
|
|
1216 |
_this.drawing.buffer.line = false;
|
|
|
1217 |
_this.drawing.buffer.hasLine = false;
|
|
|
1218 |
_this.drawing.buffer.isPressed = false;
|
|
|
1219 |
} );
|
|
|
1220 |
|
|
|
1221 |
// OBSERVE OBJECT SELECTION
|
|
|
1222 |
_this.setup.fabric.on( "object:selected", function( e ) {
|
|
|
1223 |
_this.drawing.buffer.isSelected = true;
|
|
|
1224 |
_this.drawing.buffer.target = e.target;
|
|
|
1225 |
_this.setup.fabric.isDrawingMode = false;
|
|
|
1226 |
} );
|
|
|
1227 |
_this.setup.fabric.on( "selection:cleared", function( e ) {
|
|
|
1228 |
_this.drawing.buffer.onMouseDown = _this.setup.fabric.freeDrawingBrush.onMouseDown;
|
|
|
1229 |
_this.drawing.buffer.target = false;
|
|
|
1230 |
|
|
|
1231 |
// FREEHAND WORKAROUND
|
|
|
1232 |
if ( _this.drawing.buffer.isSelected ) {
|
|
|
1233 |
_this.setup.fabric._isCurrentlyDrawing = false;
|
|
|
1234 |
_this.setup.fabric.freeDrawingBrush.onMouseDown = function() {};
|
|
|
1235 |
}
|
|
|
1236 |
|
|
|
1237 |
// DELAYED DESELECTION TO PREVENT DRAWING
|
|
|
1238 |
setTimeout( function() {
|
|
|
1239 |
_this.drawing.buffer.isSelected = false;
|
|
|
1240 |
_this.setup.fabric.isDrawingMode = true;
|
|
|
1241 |
_this.setup.fabric.freeDrawingBrush.onMouseDown = _this.drawing.buffer.onMouseDown;
|
|
|
1242 |
}, 10 );
|
|
|
1243 |
} );
|
|
|
1244 |
_this.setup.fabric.on( "path:created", function( e ) {
|
|
|
1245 |
var item = e.path;
|
|
|
1246 |
if ( Number( new Date() ) - _this.drawing.buffer.pressedTS < 200 || _this.drawing.buffer.hasLine ) {
|
|
|
1247 |
_this.setup.fabric.remove( item );
|
|
|
1248 |
_this.setup.fabric.renderAll();
|
|
|
1249 |
return;
|
|
|
1250 |
}
|
|
|
1251 |
} );
|
|
|
1252 |
|
|
|
1253 |
// OBSERVE OBJECT MODIFICATIONS
|
|
|
1254 |
_this.setup.fabric.on( "object:added", function( e ) {
|
|
|
1255 |
var item = e.target;
|
|
|
1256 |
var state = _this.deepMerge( item.saveState().originalState, {
|
|
|
1257 |
cfg: {
|
|
|
1258 |
color: _this.drawing.color,
|
|
|
1259 |
width: _this.drawing.width,
|
|
|
1260 |
opacity: _this.drawing.opacity,
|
|
|
1261 |
fontSize: _this.drawing.fontSize
|
|
|
1262 |
}
|
|
|
1263 |
} );
|
|
|
1264 |
|
|
|
1265 |
if ( Number( new Date() ) - _this.drawing.buffer.pressedTS < 200 && !item.noUndo ) {
|
|
|
1266 |
_this.setup.fabric.remove( item );
|
|
|
1267 |
_this.setup.fabric.renderAll();
|
|
|
1268 |
return;
|
|
|
1269 |
}
|
|
|
1270 |
|
|
|
1271 |
state = JSON.stringify( state );
|
|
|
1272 |
item.recentState = state;
|
|
|
1273 |
|
|
|
1274 |
if ( item.selectable && !item.known && !item.noUndo ) {
|
|
|
1275 |
_this.drawing.undos.push( {
|
|
|
1276 |
action: "added",
|
|
|
1277 |
target: item,
|
|
|
1278 |
state: state
|
|
|
1279 |
} );
|
|
|
1280 |
_this.drawing.undos.push( {
|
|
|
1281 |
action: "addified",
|
|
|
1282 |
target: item,
|
|
|
1283 |
state: state
|
|
|
1284 |
} );
|
|
|
1285 |
_this.drawing.redos = [];
|
|
|
1286 |
}
|
|
|
1287 |
|
|
|
1288 |
item.known = true;
|
|
|
1289 |
_this.setup.fabric.isDrawingMode = true;
|
|
|
1290 |
} );
|
|
|
1291 |
_this.setup.fabric.on( "object:modified", function( e ) {
|
|
|
1292 |
var item = e.target;
|
|
|
1293 |
var recentState = JSON.parse( item.recentState );
|
|
|
1294 |
var state = _this.deepMerge( item.saveState().originalState, {
|
|
|
1295 |
cfg: recentState.cfg
|
|
|
1296 |
} );
|
|
|
1297 |
|
|
|
1298 |
state = JSON.stringify( state );
|
|
|
1299 |
item.recentState = state;
|
|
|
1300 |
|
|
|
1301 |
_this.drawing.undos.push( {
|
|
|
1302 |
action: "modified",
|
|
|
1303 |
target: item,
|
|
|
1304 |
state: state
|
|
|
1305 |
} );
|
|
|
1306 |
|
|
|
1307 |
_this.drawing.redos = [];
|
|
|
1308 |
} );
|
|
|
1309 |
_this.setup.fabric.on( "text:changed", function( e ) {
|
|
|
1310 |
var item = e.target;
|
|
|
1311 |
clearTimeout( item.timer );
|
|
|
1312 |
item.timer = setTimeout( function() {
|
|
|
1313 |
var state = JSON.stringify( item.saveState().originalState );
|
|
|
1314 |
|
|
|
1315 |
item.recentState = state;
|
|
|
1316 |
|
|
|
1317 |
_this.drawing.redos = [];
|
|
|
1318 |
_this.drawing.undos.push( {
|
|
|
1319 |
action: "modified",
|
|
|
1320 |
target: item,
|
|
|
1321 |
state: state
|
|
|
1322 |
} );
|
|
|
1323 |
}, 250 );
|
|
|
1324 |
} );
|
|
|
1325 |
|
|
|
1326 |
// DRAWING
|
|
|
1327 |
if ( _this.drawing.buffer.enabled ) {
|
|
|
1328 |
_this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas active" );
|
|
|
1329 |
_this.setup.wrapper.style.backgroundColor = cfg.backgroundColor;
|
|
|
1330 |
_this.setup.wrapper.style.display = "block";
|
|
|
1331 |
|
|
|
1332 |
} else {
|
|
|
1333 |
_this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas" );
|
|
|
1334 |
_this.setup.wrapper.style.display = "none";
|
|
|
1335 |
}
|
|
|
1336 |
|
|
|
1337 |
for ( i1 = 0; i1 < groups.length; i1++ ) {
|
|
|
1338 |
var group = groups[ i1 ];
|
|
|
1339 |
var isLegend = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + "-legend-div", 1 );
|
|
|
1340 |
var isPanel = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + "-stock-panel-div" );
|
|
|
1341 |
var isScrollbar = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + "-scrollbar-chart-div" );
|
|
|
1342 |
|
|
|
1343 |
// STOCK CHART; SVG OFFSET;; SVG OFFSET
|
|
|
1344 |
if ( _this.setup.chart.type == "stock" && _this.setup.chart.legendSettings.position ) {
|
|
|
1345 |
|
|
|
1346 |
// TOP / BOTTOM
|
|
|
1347 |
if ( [ "top", "bottom" ].indexOf( _this.setup.chart.legendSettings.position ) != -1 ) {
|
|
|
1348 |
|
|
|
1349 |
// POSITION; ABSOLUTE
|
|
|
1350 |
if ( group.parent.style.top && group.parent.style.left ) {
|
|
|
1351 |
group.offset.y = _this.pxToNumber( group.parent.style.top );
|
|
|
1352 |
group.offset.x = _this.pxToNumber( group.parent.style.left );
|
|
|
1353 |
|
|
|
1354 |
// POSITION; RELATIVE
|
|
|
1355 |
} else {
|
|
|
1356 |
group.offset.x = offset.x;
|
|
|
1357 |
group.offset.y = offset.y;
|
|
|
1358 |
offset.y += _this.pxToNumber( group.parent.style.height );
|
|
|
1359 |
|
|
|
1360 |
// LEGEND; OFFSET
|
|
|
1361 |
if ( isPanel ) {
|
|
|
1362 |
offset.pY = _this.pxToNumber( isPanel.style.marginTop );
|
|
|
1363 |
group.offset.y += offset.pY;
|
|
|
1364 |
|
|
|
1365 |
// SCROLLBAR; OFFSET
|
|
|
1366 |
} else if ( isScrollbar ) {
|
|
|
1367 |
group.offset.y += offset.pY;
|
|
|
1368 |
}
|
|
|
1369 |
}
|
|
|
1370 |
|
|
|
1371 |
// LEFT / RIGHT
|
|
|
1372 |
} else if ( [ "left", "right" ].indexOf( _this.setup.chart.legendSettings.position ) != -1 ) {
|
|
|
1373 |
group.offset.y = _this.pxToNumber( group.parent.style.top ) + offset.pY;
|
|
|
1374 |
group.offset.x = _this.pxToNumber( group.parent.style.left ) + offset.pX;
|
|
|
1375 |
|
|
|
1376 |
// LEGEND; OFFSET
|
|
|
1377 |
if ( isLegend ) {
|
|
|
1378 |
offset.pY += _this.pxToNumber( isPanel.style.height ) + _this.setup.chart.panelsSettings.panelSpacing;
|
|
|
1379 |
|
|
|
1380 |
// SCROLLBAR; OFFSET
|
|
|
1381 |
} else if ( isScrollbar ) {
|
|
|
1382 |
group.offset.y -= _this.setup.chart.panelsSettings.panelSpacing;
|
|
|
1383 |
}
|
|
|
1384 |
}
|
|
|
1385 |
|
|
|
1386 |
// REGULAR CHARTS; SVG OFFSET
|
|
|
1387 |
} else {
|
|
|
1388 |
// POSITION; ABSOLUTE
|
|
|
1389 |
if ( group.parent.style.position == "absolute" ) {
|
|
|
1390 |
group.offset.absolute = true;
|
|
|
1391 |
group.offset.top = _this.pxToNumber( group.parent.style.top );
|
|
|
1392 |
group.offset.right = _this.pxToNumber( group.parent.style.right, true );
|
|
|
1393 |
group.offset.bottom = _this.pxToNumber( group.parent.style.bottom, true );
|
|
|
1394 |
group.offset.left = _this.pxToNumber( group.parent.style.left );
|
|
|
1395 |
group.offset.width = _this.pxToNumber( group.parent.style.width );
|
|
|
1396 |
group.offset.height = _this.pxToNumber( group.parent.style.height );
|
|
|
1397 |
|
|
|
1398 |
// POSITION; RELATIVE
|
|
|
1399 |
} else if ( group.parent.style.top && group.parent.style.left ) {
|
|
|
1400 |
group.offset.y = _this.pxToNumber( group.parent.style.top );
|
|
|
1401 |
group.offset.x = _this.pxToNumber( group.parent.style.left );
|
|
|
1402 |
|
|
|
1403 |
// POSITION; GENERIC
|
|
|
1404 |
} else {
|
|
|
1405 |
|
|
|
1406 |
// EXTERNAL LEGEND
|
|
|
1407 |
if ( group.legend ) {
|
|
|
1408 |
if ( group.legend.position == "left" ) {
|
|
|
1409 |
offset.x += group.legend.width;
|
|
|
1410 |
} else if ( group.legend.position == "right" ) {
|
|
|
1411 |
group.offset.x += offset.width - group.legend.width;
|
|
|
1412 |
} else if ( group.legend.position == "top" ) {
|
|
|
1413 |
offset.y += group.legend.height;
|
|
|
1414 |
} else if ( group.legend.position == "bottom" ) {
|
|
|
1415 |
group.offset.y += offset.height - group.legend.height; // OFFSET.Y
|
|
|
1416 |
}
|
|
|
1417 |
|
|
|
1418 |
// NORMAL
|
|
|
1419 |
} else {
|
|
|
1420 |
group.offset.x = offset.x;
|
|
|
1421 |
group.offset.y = offset.y + offset.pY;
|
|
|
1422 |
offset.y += _this.pxToNumber( group.parent.style.height );
|
|
|
1423 |
}
|
|
|
1424 |
}
|
|
|
1425 |
|
|
|
1426 |
// PANEL
|
|
|
1427 |
if ( isLegend && isPanel && isPanel.style.marginTop ) {
|
|
|
1428 |
offset.y += _this.pxToNumber( isPanel.style.marginTop );
|
|
|
1429 |
group.offset.y += _this.pxToNumber( isPanel.style.marginTop );
|
|
|
1430 |
}
|
|
|
1431 |
}
|
|
|
1432 |
|
|
|
1433 |
// ADD TO CANVAS
|
|
|
1434 |
fabric.parseSVGDocument( group.svg, ( function( group ) {
|
|
|
1435 |
return function( objects, options ) {
|
|
|
1436 |
var i1;
|
|
|
1437 |
var g = fabric.util.groupSVGElements( objects, options );
|
|
|
1438 |
var paths = [];
|
|
|
1439 |
var tmp = {
|
|
|
1440 |
selectable: false
|
|
|
1441 |
};
|
|
|
1442 |
|
|
|
1443 |
// GROUP OFFSET; ABSOLUTE
|
|
|
1444 |
if ( group.offset.absolute ) {
|
|
|
1445 |
if ( group.offset.bottom !== undefined ) {
|
|
|
1446 |
tmp.top = offset.height - group.offset.height - group.offset.bottom;
|
|
|
1447 |
} else {
|
|
|
1448 |
tmp.top = group.offset.top;
|
|
|
1449 |
}
|
|
|
1450 |
|
|
|
1451 |
if ( group.offset.right !== undefined ) {
|
|
|
1452 |
tmp.left = offset.width - group.offset.width - group.offset.right;
|
|
|
1453 |
} else {
|
|
|
1454 |
tmp.left = group.offset.left;
|
|
|
1455 |
}
|
|
|
1456 |
|
|
|
1457 |
// GROUP OFFSET; REGULAR
|
|
|
1458 |
} else {
|
|
|
1459 |
tmp.top = group.offset.y;
|
|
|
1460 |
tmp.left = group.offset.x;
|
|
|
1461 |
}
|
|
|
1462 |
|
|
|
1463 |
// WALKTHROUGH ELEMENTS
|
|
|
1464 |
for ( i1 = 0; i1 < g.paths.length; i1++ ) {
|
|
|
1465 |
var PID = null;
|
|
|
1466 |
|
|
|
1467 |
// OPACITY; TODO: DISTINGUISH OPACITY TYPES
|
|
|
1468 |
if ( g.paths[ i1 ] ) {
|
|
|
1469 |
|
|
|
1470 |
// CHECK ORIGIN; REMOVE TAINTED
|
|
|
1471 |
if ( cfg.removeImages && _this.isTainted( g.paths[ i1 ][ "xlink:href" ] ) ) {
|
|
|
1472 |
continue;
|
|
|
1473 |
}
|
|
|
1474 |
|
|
|
1475 |
// SET OPACITY
|
|
|
1476 |
if ( g.paths[ i1 ].fill instanceof Object ) {
|
|
|
1477 |
|
|
|
1478 |
// MISINTERPRETATION OF FABRIC
|
|
|
1479 |
if ( g.paths[ i1 ].fill.type == "radial" ) {
|
|
|
1480 |
|
|
|
1481 |
// PIE EXCEPTION
|
|
|
1482 |
if ( _this.setup.chart.type == "pie" ) {
|
|
|
1483 |
var tmp_n = g.paths[ i1 ];
|
|
|
1484 |
var tmp_c = tmp_n.getCenterPoint();
|
|
|
1485 |
var tmp_cp = tmp_n.group.getCenterPoint();
|
|
|
1486 |
var tmp_cd = {
|
|
|
1487 |
x: tmp_n.pathOffset.x - tmp_cp.x,
|
|
|
1488 |
y: tmp_n.pathOffset.y - tmp_cp.y
|
|
|
1489 |
};
|
|
|
1490 |
|
|
|
1491 |
g.paths[ i1 ].fill.gradientTransform[ 4 ] = tmp_n.pathOffset.x - tmp_cd.x;
|
|
|
1492 |
g.paths[ i1 ].fill.gradientTransform[ 5 ] = tmp_n.pathOffset.y - tmp_cd.y;
|
|
|
1493 |
|
|
|
1494 |
// OTHERS
|
|
|
1495 |
} else {
|
|
|
1496 |
g.paths[ i1 ].fill.coords.r2 = g.paths[ i1 ].fill.coords.r1 * -1;
|
|
|
1497 |
g.paths[ i1 ].fill.coords.r1 = 0;
|
|
|
1498 |
g.paths[ i1 ].set( {
|
|
|
1499 |
opacity: g.paths[ i1 ].fillOpacity
|
|
|
1500 |
} );
|
|
|
1501 |
}
|
|
|
1502 |
}
|
|
|
1503 |
|
|
|
1504 |
// FILLING; TODO: DISTINGUISH OPACITY TYPES
|
|
|
1505 |
} else if ( PID = _this.isHashbanged( g.paths[ i1 ].fill ) ) {
|
|
|
1506 |
|
|
|
1507 |
// PATTERN
|
|
|
1508 |
if ( group.patterns && group.patterns[ PID ] ) {
|
|
|
1509 |
|
|
|
1510 |
var props = group.patterns[ PID ];
|
|
|
1511 |
|
|
|
1512 |
// LOAD IMAGE MANUALLY; TO RERENDER THE CANVAS
|
|
|
1513 |
fabric.Image.fromURL( props.source, ( function( props, i1 ) {
|
|
|
1514 |
return function( img ) {
|
|
|
1515 |
images.loaded++;
|
|
|
1516 |
|
|
|
1517 |
var pattern = null;
|
|
|
1518 |
var patternSourceCanvas = new fabric.StaticCanvas( undefined, {
|
|
|
1519 |
backgroundColor: props.fill
|
|
|
1520 |
} );
|
|
|
1521 |
patternSourceCanvas.add( img );
|
|
|
1522 |
|
|
|
1523 |
pattern = new fabric.Pattern( {
|
|
|
1524 |
source: function() {
|
|
|
1525 |
patternSourceCanvas.setDimensions( {
|
|
|
1526 |
width: props.width,
|
|
|
1527 |
height: props.height
|
|
|
1528 |
} );
|
|
|
1529 |
return patternSourceCanvas.getElement();
|
|
|
1530 |
},
|
|
|
1531 |
repeat: 'repeat'
|
|
|
1532 |
} );
|
|
|
1533 |
|
|
|
1534 |
g.paths[ i1 ].set( {
|
|
|
1535 |
fill: pattern,
|
|
|
1536 |
opacity: g.paths[ i1 ].fillOpacity
|
|
|
1537 |
} );
|
|
|
1538 |
}
|
|
|
1539 |
} )( props, i1 ) );
|
|
|
1540 |
}
|
|
|
1541 |
}
|
|
|
1542 |
|
|
|
1543 |
// CLIPPATH;
|
|
|
1544 |
if ( PID = _this.isHashbanged( g.paths[ i1 ].clipPath ) ) {
|
|
|
1545 |
|
|
|
1546 |
if ( group.clippings && group.clippings[ PID ] ) {
|
|
|
1547 |
g.paths[ i1 ].set( {
|
|
|
1548 |
clipTo: ( function( i1, PID ) {
|
|
|
1549 |
return function( ctx ) {
|
|
|
1550 |
var cp = group.clippings[ PID ];
|
|
|
1551 |
var tm = this.transformMatrix || [ 1, 0, 0, 1, 0, 0 ];
|
|
|
1552 |
var dim = {
|
|
|
1553 |
top: ( cp.bbox.y - tm[ 5 ] ) + cp.transform[ 5 ],
|
|
|
1554 |
left: ( cp.bbox.x - tm[ 4 ] ) + cp.transform[ 4 ],
|
|
|
1555 |
width: cp.bbox.width,
|
|
|
1556 |
height: cp.bbox.height
|
|
|
1557 |
}
|
|
|
1558 |
|
|
|
1559 |
ctx.rect( dim.left, dim.top, dim.width, dim.height );
|
|
|
1560 |
}
|
|
|
1561 |
} )( i1, PID )
|
|
|
1562 |
} );
|
|
|
1563 |
}
|
|
|
1564 |
}
|
|
|
1565 |
|
|
|
1566 |
// TODO; WAIT FOR TSPAN SUPPORT FROM FABRICJS SIDE
|
|
|
1567 |
if ( g.paths[ i1 ].TSPANWORKAROUND ) {
|
|
|
1568 |
var parsedAttributes = fabric.parseAttributes( g.paths[ i1 ].svg, fabric.Text.ATTRIBUTE_NAMES );
|
|
|
1569 |
var options = fabric.util.object.extend( {}, parsedAttributes );
|
|
|
1570 |
|
|
|
1571 |
// CREATE NEW SET
|
|
|
1572 |
var tmpBuffer = [];
|
|
|
1573 |
for ( var i = 0; i < g.paths[ i1 ].svg.childNodes.length; i++ ) {
|
|
|
1574 |
var textNode = g.paths[ i1 ].svg.childNodes[ i ];
|
|
|
1575 |
var textElement = fabric.Text.fromElement( textNode, options );
|
|
|
1576 |
|
|
|
1577 |
textElement.set( {
|
|
|
1578 |
left: 0
|
|
|
1579 |
} );
|
|
|
1580 |
|
|
|
1581 |
tmpBuffer.push( textElement );
|
|
|
1582 |
}
|
|
|
1583 |
|
|
|
1584 |
// HIDE ORIGINAL ELEMENT
|
|
|
1585 |
g.paths[ i1 ].set( {
|
|
|
1586 |
opacity: 0
|
|
|
1587 |
} );
|
|
|
1588 |
|
|
|
1589 |
// REPLACE BY GROUP AND CANCEL FIRST OFFSET
|
|
|
1590 |
var tmpGroup = new fabric.Group( tmpBuffer, {
|
|
|
1591 |
top: g.paths[ i1 ].top * -1
|
|
|
1592 |
} );
|
|
|
1593 |
_this.setup.fabric.add( tmpGroup );
|
|
|
1594 |
}
|
|
|
1595 |
}
|
|
|
1596 |
paths.push( g.paths[ i1 ] );
|
|
|
1597 |
}
|
|
|
1598 |
|
|
|
1599 |
// REPLACE WITH WHITELIST
|
|
|
1600 |
g.paths = paths;
|
|
|
1601 |
|
|
|
1602 |
// SET PROPS
|
|
|
1603 |
g.set( tmp );
|
|
|
1604 |
|
|
|
1605 |
// ADD TO CANVAS
|
|
|
1606 |
_this.setup.fabric.add( g );
|
|
|
1607 |
|
|
|
1608 |
// ADD BALLOONS
|
|
|
1609 |
if ( group.svg.parentNode && group.svg.parentNode.getElementsByTagName ) {
|
|
|
1610 |
var balloons = group.svg.parentNode.getElementsByClassName( _this.setup.chart.classNamePrefix + "-balloon-div" );
|
|
|
1611 |
for ( i1 = 0; i1 < balloons.length; i1++ ) {
|
|
|
1612 |
if ( cfg.balloonFunction instanceof Function ) {
|
|
|
1613 |
cfg.balloonFunction.apply( _this, [ balloons[ i1 ], group ] );
|
|
|
1614 |
} else {
|
|
|
1615 |
var elm_parent = balloons[ i1 ];
|
|
|
1616 |
var style_parent = fabric.parseStyleAttribute( elm_parent );
|
|
|
1617 |
var style_text = fabric.parseStyleAttribute( elm_parent.childNodes[ 0 ] );
|
|
|
1618 |
var fabric_label = new fabric.Text( elm_parent.innerText || elm_parent.innerHTML, {
|
|
|
1619 |
selectable: false,
|
|
|
1620 |
top: style_parent.top + group.offset.y,
|
|
|
1621 |
left: style_parent.left + group.offset.x,
|
|
|
1622 |
fill: style_text[ "color" ],
|
|
|
1623 |
fontSize: style_text[ "fontSize" ],
|
|
|
1624 |
fontFamily: style_text[ "fontFamily" ],
|
|
|
1625 |
textAlign: style_text[ "text-align" ]
|
|
|
1626 |
} );
|
|
|
1627 |
|
|
|
1628 |
_this.setup.fabric.add( fabric_label );
|
|
|
1629 |
}
|
|
|
1630 |
}
|
|
|
1631 |
}
|
|
|
1632 |
|
|
|
1633 |
if ( group.svg.nextSibling && group.svg.nextSibling.tagName == "A" ) {
|
|
|
1634 |
var elm_parent = group.svg.nextSibling;
|
|
|
1635 |
var style_parent = fabric.parseStyleAttribute( elm_parent );
|
|
|
1636 |
var fabric_label = new fabric.Text( elm_parent.innerText || elm_parent.innerHTML, {
|
|
|
1637 |
selectable: false,
|
|
|
1638 |
top: style_parent.top + group.offset.y,
|
|
|
1639 |
left: style_parent.left + group.offset.x,
|
|
|
1640 |
fill: style_parent[ "color" ],
|
|
|
1641 |
fontSize: style_parent[ "fontSize" ],
|
|
|
1642 |
fontFamily: style_parent[ "fontFamily" ],
|
|
|
1643 |
opacity: style_parent[ "opacity" ]
|
|
|
1644 |
} );
|
|
|
1645 |
|
|
|
1646 |
_this.setup.fabric.add( fabric_label );
|
|
|
1647 |
}
|
|
|
1648 |
|
|
|
1649 |
groups.pop();
|
|
|
1650 |
|
|
|
1651 |
// TRIGGER CALLBACK WITH SAFETY DELAY
|
|
|
1652 |
if ( !groups.length ) {
|
|
|
1653 |
var timer = setInterval( function() {
|
|
|
1654 |
if ( images.loaded == images.included ) {
|
|
|
1655 |
clearTimeout( timer );
|
|
|
1656 |
_this.handleCallback( cfg.afterCapture, cfg );
|
|
|
1657 |
_this.setup.fabric.renderAll();
|
|
|
1658 |
_this.handleCallback( callback, cfg );
|
|
|
1659 |
}
|
|
|
1660 |
}, AmCharts.updateRate );
|
|
|
1661 |
}
|
|
|
1662 |
}
|
|
|
1663 |
|
|
|
1664 |
// IDENTIFY ELEMENTS THROUGH CLASSNAMES
|
|
|
1665 |
} )( group ), function( svg, obj ) {
|
|
|
1666 |
var i1;
|
|
|
1667 |
var className = _this.gatherAttribute( svg, "class" );
|
|
|
1668 |
var visibility = _this.gatherAttribute( svg, "visibility" );
|
|
|
1669 |
var clipPath = _this.gatherAttribute( svg, "clip-path" );
|
|
|
1670 |
|
|
|
1671 |
obj.className = String( className );
|
|
|
1672 |
obj.classList = String( className ).split( " " );
|
|
|
1673 |
obj.clipPath = clipPath;
|
|
|
1674 |
obj.svg = svg;
|
|
|
1675 |
|
|
|
1676 |
// TODO; WAIT FOR TSPAN SUPPORT FROM FABRICJS SIDE
|
|
|
1677 |
if ( svg.tagName == "text" && svg.childNodes.length > 1 ) {
|
|
|
1678 |
obj.TSPANWORKAROUND = true;
|
|
|
1679 |
}
|
|
|
1680 |
|
|
|
1681 |
// HIDE HIDDEN ELEMENTS; TODO: FIND A BETTER WAY TO HANDLE THAT
|
|
|
1682 |
if ( visibility == "hidden" ) {
|
|
|
1683 |
obj.opacity = 0;
|
|
|
1684 |
|
|
|
1685 |
// WALKTHROUGH ELEMENTS
|
|
|
1686 |
} else {
|
|
|
1687 |
|
|
|
1688 |
// TRANSPORT FILL/STROKE OPACITY
|
|
|
1689 |
var attrs = [ "fill", "stroke" ];
|
|
|
1690 |
for ( i1 = 0; i1 < attrs.length; i1++ ) {
|
|
|
1691 |
var attr = attrs[ i1 ]
|
|
|
1692 |
var attrVal = String( svg.getAttribute( attr ) || "" );
|
|
|
1693 |
var attrOpacity = Number( svg.getAttribute( attr + "-opacity" ) || "1" );
|
|
|
1694 |
var attrRGBA = fabric.Color.fromHex( attrVal ).getSource();
|
|
|
1695 |
|
|
|
1696 |
// EXCEPTION
|
|
|
1697 |
if ( obj.classList.indexOf( _this.setup.chart.classNamePrefix + "-guide-fill" ) != -1 && !attrVal ) {
|
|
|
1698 |
attrOpacity = 0;
|
|
|
1699 |
attrRGBA = fabric.Color.fromHex( "#000000" ).getSource();
|
|
|
1700 |
}
|
|
|
1701 |
|
|
|
1702 |
if ( attrRGBA ) {
|
|
|
1703 |
attrRGBA.pop();
|
|
|
1704 |
attrRGBA.push( attrOpacity )
|
|
|
1705 |
obj[ attr ] = "rgba(" + attrRGBA.join() + ")";
|
|
|
1706 |
obj[ attr + _this.capitalize( "opacity" ) ] = attrOpacity;
|
|
|
1707 |
}
|
|
|
1708 |
}
|
|
|
1709 |
}
|
|
|
1710 |
|
|
|
1711 |
// REVIVER
|
|
|
1712 |
_this.handleCallback( cfg.reviver, obj, svg );
|
|
|
1713 |
} );
|
|
|
1714 |
}
|
|
|
1715 |
},
|
|
|
1716 |
|
|
|
1717 |
/**
|
|
|
1718 |
* Returns the current canvas
|
|
|
1719 |
*/
|
|
|
1720 |
toCanvas: function( options, callback ) {
|
|
|
1721 |
var cfg = _this.deepMerge( {
|
|
|
1722 |
// NUFFIN
|
|
|
1723 |
}, options || {} );
|
|
|
1724 |
var data = _this.setup.canvas;
|
|
|
1725 |
|
|
|
1726 |
_this.handleCallback( callback, data );
|
|
|
1727 |
|
|
|
1728 |
return data;
|
|
|
1729 |
},
|
|
|
1730 |
|
|
|
1731 |
/**
|
|
|
1732 |
* Returns an image; by default PNG
|
|
|
1733 |
*/
|
|
|
1734 |
toImage: function( options, callback ) {
|
|
|
1735 |
var cfg = _this.deepMerge( {
|
|
|
1736 |
format: "png",
|
|
|
1737 |
quality: 1,
|
|
|
1738 |
multiplier: 1
|
|
|
1739 |
}, options || {} );
|
|
|
1740 |
var data = cfg.data;
|
|
|
1741 |
var img = document.createElement( "img" );
|
|
|
1742 |
|
|
|
1743 |
if ( !cfg.data ) {
|
|
|
1744 |
if ( cfg.lossless || cfg.format == "svg" ) {
|
|
|
1745 |
data = _this.toSVG( _this.deepMerge( cfg, {
|
|
|
1746 |
getBase64: true
|
|
|
1747 |
} ) );
|
|
|
1748 |
} else {
|
|
|
1749 |
data = _this.setup.fabric.toDataURL( cfg );
|
|
|
1750 |
}
|
|
|
1751 |
}
|
|
|
1752 |
|
|
|
1753 |
img.setAttribute( "src", data );
|
|
|
1754 |
|
|
|
1755 |
_this.handleCallback( callback, img );
|
|
|
1756 |
|
|
|
1757 |
return img;
|
|
|
1758 |
},
|
|
|
1759 |
|
|
|
1760 |
/**
|
|
|
1761 |
* Generates a blob instance image; returns base64 datastring
|
|
|
1762 |
*/
|
|
|
1763 |
toBlob: function( options, callback ) {
|
|
|
1764 |
var cfg = _this.deepMerge( {
|
|
|
1765 |
data: "empty",
|
|
|
1766 |
type: "text/plain"
|
|
|
1767 |
}, options || {} );
|
|
|
1768 |
var data;
|
|
|
1769 |
var isBase64 = /^data:.+;base64,(.*)$/.exec( cfg.data );
|
|
|
1770 |
|
|
|
1771 |
// GATHER BODY
|
|
|
1772 |
if ( isBase64 ) {
|
|
|
1773 |
cfg.data = isBase64[ 0 ];
|
|
|
1774 |
cfg.type = cfg.data.slice( 5, cfg.data.indexOf( "," ) - 7 );
|
|
|
1775 |
cfg.data = _this.toByteArray( {
|
|
|
1776 |
data: cfg.data.slice( cfg.data.indexOf( "," ) + 1, cfg.data.length )
|
|
|
1777 |
} );
|
|
|
1778 |
}
|
|
|
1779 |
|
|
|
1780 |
if ( cfg.getByteArray ) {
|
|
|
1781 |
data = cfg.data;
|
|
|
1782 |
} else {
|
|
|
1783 |
data = new Blob( [ cfg.data ], {
|
|
|
1784 |
type: cfg.type
|
|
|
1785 |
} );
|
|
|
1786 |
}
|
|
|
1787 |
|
|
|
1788 |
_this.handleCallback( callback, data );
|
|
|
1789 |
|
|
|
1790 |
return data;
|
|
|
1791 |
},
|
|
|
1792 |
|
|
|
1793 |
/**
|
|
|
1794 |
* Generates JPG image; returns base64 datastring
|
|
|
1795 |
*/
|
|
|
1796 |
toJPG: function( options, callback ) {
|
|
|
1797 |
var cfg = _this.deepMerge( {
|
|
|
1798 |
format: "jpeg",
|
|
|
1799 |
quality: 1,
|
|
|
1800 |
multiplier: 1
|
|
|
1801 |
}, options || {} );
|
|
|
1802 |
cfg.format = cfg.format.toLowerCase();
|
|
|
1803 |
var data = _this.setup.fabric.toDataURL( cfg );
|
|
|
1804 |
|
|
|
1805 |
_this.handleCallback( callback, data );
|
|
|
1806 |
|
|
|
1807 |
return data;
|
|
|
1808 |
},
|
|
|
1809 |
|
|
|
1810 |
/**
|
|
|
1811 |
* Generates PNG image; returns base64 datastring
|
|
|
1812 |
*/
|
|
|
1813 |
toPNG: function( options, callback ) {
|
|
|
1814 |
var cfg = _this.deepMerge( {
|
|
|
1815 |
format: "png",
|
|
|
1816 |
quality: 1,
|
|
|
1817 |
multiplier: 1
|
|
|
1818 |
}, options || {} );
|
|
|
1819 |
var data = _this.setup.fabric.toDataURL( cfg );
|
|
|
1820 |
|
|
|
1821 |
_this.handleCallback( callback, data );
|
|
|
1822 |
|
|
|
1823 |
return data;
|
|
|
1824 |
},
|
|
|
1825 |
|
|
|
1826 |
/**
|
|
|
1827 |
* Generates SVG image; returns base64 datastring
|
|
|
1828 |
*/
|
|
|
1829 |
toSVG: function( options, callback ) {
|
|
|
1830 |
var cfg = _this.deepMerge( {
|
|
|
1831 |
reviver: function( string ) {
|
|
|
1832 |
var matcher = new RegExp( /\bstyle=(['"])(.*?)\1/ );
|
|
|
1833 |
var match = matcher.exec( string )[ 0 ].slice( 7, -1 );
|
|
|
1834 |
var styles = match.split( ";" );
|
|
|
1835 |
var replacement = [];
|
|
|
1836 |
|
|
|
1837 |
for ( i1 = 0; i1 < styles.length; i1++ ) {
|
|
|
1838 |
if ( styles[ i1 ] ) {
|
|
|
1839 |
var pair = styles[ i1 ].replace( /\s/g, "" ).split( ":" );
|
|
|
1840 |
var key = pair[ 0 ];
|
|
|
1841 |
var value = pair[ 1 ];
|
|
|
1842 |
|
|
|
1843 |
if ( [ "fill", "stroke" ].indexOf( key ) != -1 ) {
|
|
|
1844 |
value = fabric.Color.fromRgba( value );
|
|
|
1845 |
if ( value && value._source ) {
|
|
|
1846 |
var color = "#" + value.toHex();
|
|
|
1847 |
var opacity = value._source[ 3 ];
|
|
|
1848 |
|
|
|
1849 |
replacement.push( [ key, color ].join( ":" ) );
|
|
|
1850 |
replacement.push( [ key + "-opacity", opacity ].join( ":" ) );
|
|
|
1851 |
} else {
|
|
|
1852 |
replacement.push( styles[ i1 ] );
|
|
|
1853 |
}
|
|
|
1854 |
} else if ( key != "opactiy" ) {
|
|
|
1855 |
replacement.push( styles[ i1 ] );
|
|
|
1856 |
}
|
|
|
1857 |
}
|
|
|
1858 |
}
|
|
|
1859 |
|
|
|
1860 |
return string.replace( match, replacement.join( ";" ) );
|
|
|
1861 |
}
|
|
|
1862 |
}, options || {} );
|
|
|
1863 |
var data = _this.setup.fabric.toSVG( cfg, cfg.reviver );
|
|
|
1864 |
|
|
|
1865 |
if ( cfg.getBase64 ) {
|
|
|
1866 |
data = "data:image/svg+xml;base64," + btoa( data );
|
|
|
1867 |
}
|
|
|
1868 |
|
|
|
1869 |
_this.handleCallback( callback, data );
|
|
|
1870 |
|
|
|
1871 |
return data;
|
|
|
1872 |
},
|
|
|
1873 |
|
|
|
1874 |
/**
|
|
|
1875 |
* Generates PDF; returns base64 datastring
|
|
|
1876 |
*/
|
|
|
1877 |
toPDF: function( options, callback ) {
|
|
|
1878 |
var cfg = _this.deepMerge( _this.deepMerge( {
|
|
|
1879 |
multiplier: 2
|
|
|
1880 |
}, _this.config.pdfMake ), options || {}, true );
|
|
|
1881 |
cfg.images.reference = _this.toPNG( cfg );
|
|
|
1882 |
var data = new pdfMake.createPdf( cfg );
|
|
|
1883 |
|
|
|
1884 |
if ( callback ) {
|
|
|
1885 |
data.getDataUrl( ( function( callback ) {
|
|
|
1886 |
return function() {
|
|
|
1887 |
callback.apply( _this, arguments );
|
|
|
1888 |
}
|
|
|
1889 |
} )( callback ) );
|
|
|
1890 |
}
|
|
|
1891 |
|
|
|
1892 |
return data;
|
|
|
1893 |
},
|
|
|
1894 |
|
|
|
1895 |
/**
|
|
|
1896 |
* Generates an image; hides all elements on page to trigger native print method
|
|
|
1897 |
*/
|
|
|
1898 |
toPRINT: function( options, callback ) {
|
|
|
1899 |
var i1;
|
|
|
1900 |
var cfg = _this.deepMerge( {
|
|
|
1901 |
delay: 1,
|
|
|
1902 |
lossless: false
|
|
|
1903 |
}, options || {} );
|
|
|
1904 |
var data = _this.toImage( cfg );
|
|
|
1905 |
var states = [];
|
|
|
1906 |
var items = document.body.childNodes;
|
|
|
1907 |
|
|
|
1908 |
data.setAttribute( "style", "width: 100%; max-height: 100%;" );
|
|
|
1909 |
|
|
|
1910 |
for ( i1 = 0; i1 < items.length; i1++ ) {
|
|
|
1911 |
if ( _this.isElement( items[ i1 ] ) ) {
|
|
|
1912 |
states[ i1 ] = items[ i1 ].style.display;
|
|
|
1913 |
items[ i1 ].style.display = "none";
|
|
|
1914 |
}
|
|
|
1915 |
}
|
|
|
1916 |
|
|
|
1917 |
document.body.appendChild( data );
|
|
|
1918 |
window.print();
|
|
|
1919 |
|
|
|
1920 |
setTimeout( function() {
|
|
|
1921 |
for ( i1 = 0; i1 < items.length; i1++ ) {
|
|
|
1922 |
if ( _this.isElement( items[ i1 ] ) ) {
|
|
|
1923 |
items[ i1 ].style.display = states[ i1 ];
|
|
|
1924 |
}
|
|
|
1925 |
}
|
|
|
1926 |
document.body.removeChild( data );
|
|
|
1927 |
_this.handleCallback( callback, data );
|
|
|
1928 |
}, cfg.delay );
|
|
|
1929 |
|
|
|
1930 |
return data;
|
|
|
1931 |
},
|
|
|
1932 |
|
|
|
1933 |
/**
|
|
|
1934 |
* Generates JSON string
|
|
|
1935 |
*/
|
|
|
1936 |
toJSON: function( options, callback ) {
|
|
|
1937 |
var cfg = _this.deepMerge( {
|
|
|
1938 |
dateFormat: _this.config.dateFormat || "dateObject",
|
|
|
1939 |
}, options || {}, true );
|
|
|
1940 |
cfg.data = cfg.data ? cfg.data : _this.getChartData( cfg );
|
|
|
1941 |
var data = JSON.stringify( cfg.data, undefined, "\t" );
|
|
|
1942 |
|
|
|
1943 |
_this.handleCallback( callback, data );
|
|
|
1944 |
|
|
|
1945 |
return data;
|
|
|
1946 |
},
|
|
|
1947 |
|
|
|
1948 |
/**
|
|
|
1949 |
* Generates CSV string
|
|
|
1950 |
*/
|
|
|
1951 |
toCSV: function( options, callback ) {
|
|
|
1952 |
var row, col;
|
|
|
1953 |
var cfg = _this.deepMerge( {
|
|
|
1954 |
data: _this.getChartData( options ),
|
|
|
1955 |
delimiter: ",",
|
|
|
1956 |
quotes: true,
|
|
|
1957 |
escape: true,
|
|
|
1958 |
withHeader: true
|
|
|
1959 |
}, options || {}, true );
|
|
|
1960 |
var data = "";
|
|
|
1961 |
var cols = [];
|
|
|
1962 |
var buffer = [];
|
|
|
1963 |
|
|
|
1964 |
function enchant( value, column ) {
|
|
|
1965 |
|
|
|
1966 |
// WRAP IN QUOTES
|
|
|
1967 |
if ( typeof value === "string" ) {
|
|
|
1968 |
if ( cfg.escape ) {
|
|
|
1969 |
value = value.replace( '"', '""' );
|
|
|
1970 |
}
|
|
|
1971 |
if ( cfg.quotes ) {
|
|
|
1972 |
value = [ '"', value, '"' ].join( "" );
|
|
|
1973 |
}
|
|
|
1974 |
}
|
|
|
1975 |
|
|
|
1976 |
return value;
|
|
|
1977 |
}
|
|
|
1978 |
|
|
|
1979 |
// HEADER
|
|
|
1980 |
for ( value in cfg.data[ 0 ] ) {
|
|
|
1981 |
buffer.push( enchant( value ) );
|
|
|
1982 |
cols.push( value );
|
|
|
1983 |
}
|
|
|
1984 |
if ( cfg.withHeader ) {
|
|
|
1985 |
data += buffer.join( cfg.delimiter ) + "\n";
|
|
|
1986 |
}
|
|
|
1987 |
|
|
|
1988 |
// BODY
|
|
|
1989 |
for ( row in cfg.data ) {
|
|
|
1990 |
buffer = [];
|
|
|
1991 |
if ( !isNaN( row ) ) {
|
|
|
1992 |
for ( col in cols ) {
|
|
|
1993 |
if ( !isNaN( col ) ) {
|
|
|
1994 |
var column = cols[ col ];
|
|
|
1995 |
var value = cfg.data[ row ][ column ];
|
|
|
1996 |
|
|
|
1997 |
buffer.push( enchant( value, column ) );
|
|
|
1998 |
}
|
|
|
1999 |
}
|
|
|
2000 |
data += buffer.join( cfg.delimiter ) + "\n";
|
|
|
2001 |
}
|
|
|
2002 |
}
|
|
|
2003 |
|
|
|
2004 |
_this.handleCallback( callback, data );
|
|
|
2005 |
|
|
|
2006 |
return data;
|
|
|
2007 |
},
|
|
|
2008 |
|
|
|
2009 |
/**
|
|
|
2010 |
* Generates excel sheet; returns base64 datastring
|
|
|
2011 |
*/
|
|
|
2012 |
toXLSX: function( options, callback ) {
|
|
|
2013 |
var cfg = _this.deepMerge( {
|
|
|
2014 |
name: "amCharts",
|
|
|
2015 |
dateFormat: _this.config.dateFormat || "dateObject",
|
|
|
2016 |
withHeader: true,
|
|
|
2017 |
stringify: false
|
|
|
2018 |
}, options || {}, true );
|
|
|
2019 |
var data = "";
|
|
|
2020 |
var wb = {
|
|
|
2021 |
SheetNames: [],
|
|
|
2022 |
Sheets: {}
|
|
|
2023 |
}
|
|
|
2024 |
|
|
|
2025 |
cfg.data = cfg.data ? cfg.data : _this.getChartData( cfg );
|
|
|
2026 |
|
|
|
2027 |
function datenum( v, date1904 ) {
|
|
|
2028 |
if ( date1904 ) v += 1462;
|
|
|
2029 |
var epoch = Date.parse( v );
|
|
|
2030 |
return ( epoch - new Date( Date.UTC( 1899, 11, 30 ) ) ) / ( 24 * 60 * 60 * 1000 );
|
|
|
2031 |
}
|
|
|
2032 |
|
|
|
2033 |
function sheet_from_array_of_arrays( data, opts ) {
|
|
|
2034 |
var ws = {};
|
|
|
2035 |
var range = {
|
|
|
2036 |
s: {
|
|
|
2037 |
c: 10000000,
|
|
|
2038 |
r: 10000000
|
|
|
2039 |
},
|
|
|
2040 |
e: {
|
|
|
2041 |
c: 0,
|
|
|
2042 |
r: 0
|
|
|
2043 |
}
|
|
|
2044 |
};
|
|
|
2045 |
for ( var R = 0; R != data.length; ++R ) {
|
|
|
2046 |
for ( var C = 0; C != data[ R ].length; ++C ) {
|
|
|
2047 |
if ( range.s.r > R ) range.s.r = R;
|
|
|
2048 |
if ( range.s.c > C ) range.s.c = C;
|
|
|
2049 |
if ( range.e.r < R ) range.e.r = R;
|
|
|
2050 |
if ( range.e.c < C ) range.e.c = C;
|
|
|
2051 |
var cell = {
|
|
|
2052 |
v: data[ R ][ C ]
|
|
|
2053 |
};
|
|
|
2054 |
if ( cell.v == null ) continue;
|
|
|
2055 |
var cell_ref = XLSX.utils.encode_cell( {
|
|
|
2056 |
c: C,
|
|
|
2057 |
r: R
|
|
|
2058 |
} );
|
|
|
2059 |
|
|
|
2060 |
if ( typeof cell.v === "number" ) cell.t = "n";
|
|
|
2061 |
else if ( typeof cell.v === "boolean" ) cell.t = "b";
|
|
|
2062 |
else if ( cell.v instanceof Date ) {
|
|
|
2063 |
cell.t = "n";
|
|
|
2064 |
cell.z = XLSX.SSF._table[ 14 ];
|
|
|
2065 |
cell.v = datenum( cell.v );
|
|
|
2066 |
} else cell.t = "s";
|
|
|
2067 |
|
|
|
2068 |
ws[ cell_ref ] = cell;
|
|
|
2069 |
}
|
|
|
2070 |
}
|
|
|
2071 |
if ( range.s.c < 10000000 ) ws[ "!ref" ] = XLSX.utils.encode_range( range );
|
|
|
2072 |
return ws;
|
|
|
2073 |
}
|
|
|
2074 |
|
|
|
2075 |
wb.SheetNames.push( cfg.name );
|
|
|
2076 |
wb.Sheets[ cfg.name ] = sheet_from_array_of_arrays( _this.toArray( cfg ) );
|
|
|
2077 |
|
|
|
2078 |
data = XLSX.write( wb, {
|
|
|
2079 |
bookType: "xlsx",
|
|
|
2080 |
bookSST: true,
|
|
|
2081 |
type: "base64"
|
|
|
2082 |
} );
|
|
|
2083 |
|
|
|
2084 |
data = "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," + data;
|
|
|
2085 |
|
|
|
2086 |
_this.handleCallback( callback, data );
|
|
|
2087 |
|
|
|
2088 |
return data;
|
|
|
2089 |
},
|
|
|
2090 |
|
|
|
2091 |
/**
|
|
|
2092 |
* Generates an array of arrays
|
|
|
2093 |
*/
|
|
|
2094 |
toArray: function( options, callback ) {
|
|
|
2095 |
var row, col;
|
|
|
2096 |
var cfg = _this.deepMerge( {
|
|
|
2097 |
data: _this.getChartData( options ),
|
|
|
2098 |
withHeader: false,
|
|
|
2099 |
stringify: true
|
|
|
2100 |
}, options || {}, true );
|
|
|
2101 |
var data = [];
|
|
|
2102 |
var cols = [];
|
|
|
2103 |
|
|
|
2104 |
// HEADER
|
|
|
2105 |
for ( col in cfg.data[ 0 ] ) {
|
|
|
2106 |
cols.push( col );
|
|
|
2107 |
}
|
|
|
2108 |
if ( cfg.withHeader ) {
|
|
|
2109 |
data.push( cols );
|
|
|
2110 |
}
|
|
|
2111 |
|
|
|
2112 |
// BODY
|
|
|
2113 |
for ( row in cfg.data ) {
|
|
|
2114 |
var buffer = [];
|
|
|
2115 |
if ( !isNaN( row ) ) {
|
|
|
2116 |
for ( col in cols ) {
|
|
|
2117 |
if ( !isNaN( col ) ) {
|
|
|
2118 |
var col = cols[ col ];
|
|
|
2119 |
var value = cfg.data[ row ][ col ];
|
|
|
2120 |
if ( value == null ) {
|
|
|
2121 |
value = "";
|
|
|
2122 |
} else if ( cfg.stringify ) {
|
|
|
2123 |
value = String( value );
|
|
|
2124 |
} else {
|
|
|
2125 |
value = value;
|
|
|
2126 |
}
|
|
|
2127 |
buffer.push( value );
|
|
|
2128 |
}
|
|
|
2129 |
}
|
|
|
2130 |
data.push( buffer );
|
|
|
2131 |
}
|
|
|
2132 |
}
|
|
|
2133 |
|
|
|
2134 |
_this.handleCallback( callback, data );
|
|
|
2135 |
|
|
|
2136 |
return data;
|
|
|
2137 |
},
|
|
|
2138 |
|
|
|
2139 |
/**
|
|
|
2140 |
* Generates byte array with given base64 datastring; returns byte array
|
|
|
2141 |
*/
|
|
|
2142 |
toByteArray: function( options, callback ) {
|
|
|
2143 |
var cfg = _this.deepMerge( {
|
|
|
2144 |
// NUFFIN
|
|
|
2145 |
}, options || {} );
|
|
|
2146 |
var Arr = ( typeof Uint8Array !== 'undefined' ) ? Uint8Array : Array
|
|
|
2147 |
var PLUS = '+'.charCodeAt( 0 )
|
|
|
2148 |
var SLASH = '/'.charCodeAt( 0 )
|
|
|
2149 |
var NUMBER = '0'.charCodeAt( 0 )
|
|
|
2150 |
var LOWER = 'a'.charCodeAt( 0 )
|
|
|
2151 |
var UPPER = 'A'.charCodeAt( 0 )
|
|
|
2152 |
var data = b64ToByteArray( cfg.data );
|
|
|
2153 |
|
|
|
2154 |
function decode( elt ) {
|
|
|
2155 |
var code = elt.charCodeAt( 0 )
|
|
|
2156 |
if ( code === PLUS )
|
|
|
2157 |
return 62 // '+'
|
|
|
2158 |
if ( code === SLASH )
|
|
|
2159 |
return 63 // '/'
|
|
|
2160 |
if ( code < NUMBER )
|
|
|
2161 |
return -1 //no match
|
|
|
2162 |
if ( code < NUMBER + 10 )
|
|
|
2163 |
return code - NUMBER + 26 + 26
|
|
|
2164 |
if ( code < UPPER + 26 )
|
|
|
2165 |
return code - UPPER
|
|
|
2166 |
if ( code < LOWER + 26 )
|
|
|
2167 |
return code - LOWER + 26
|
|
|
2168 |
}
|
|
|
2169 |
|
|
|
2170 |
function b64ToByteArray( b64 ) {
|
|
|
2171 |
var i, j, l, tmp, placeHolders, arr
|
|
|
2172 |
|
|
|
2173 |
if ( b64.length % 4 > 0 ) {
|
|
|
2174 |
throw new Error( 'Invalid string. Length must be a multiple of 4' )
|
|
|
2175 |
}
|
|
|
2176 |
|
|
|
2177 |
// THE NUMBER OF EQUAL SIGNS (PLACE HOLDERS)
|
|
|
2178 |
// IF THERE ARE TWO PLACEHOLDERS, THAN THE TWO CHARACTERS BEFORE IT
|
|
|
2179 |
// REPRESENT ONE BYTE
|
|
|
2180 |
// IF THERE IS ONLY ONE, THEN THE THREE CHARACTERS BEFORE IT REPRESENT 2 BYTES
|
|
|
2181 |
// THIS IS JUST A CHEAP HACK TO NOT DO INDEXOF TWICE
|
|
|
2182 |
var len = b64.length
|
|
|
2183 |
placeHolders = '=' === b64.charAt( len - 2 ) ? 2 : '=' === b64.charAt( len - 1 ) ? 1 : 0
|
|
|
2184 |
|
|
|
2185 |
// BASE64 IS 4/3 + UP TO TWO CHARACTERS OF THE ORIGINAL DATA
|
|
|
2186 |
arr = new Arr( b64.length * 3 / 4 - placeHolders )
|
|
|
2187 |
|
|
|
2188 |
// IF THERE ARE PLACEHOLDERS, ONLY GET UP TO THE LAST COMPLETE 4 CHARS
|
|
|
2189 |
l = placeHolders > 0 ? b64.length - 4 : b64.length
|
|
|
2190 |
|
|
|
2191 |
var L = 0
|
|
|
2192 |
|
|
|
2193 |
function push( v ) {
|
|
|
2194 |
arr[ L++ ] = v
|
|
|
2195 |
}
|
|
|
2196 |
|
|
|
2197 |
for ( i = 0, j = 0; i < l; i += 4, j += 3 ) {
|
|
|
2198 |
tmp = ( decode( b64.charAt( i ) ) << 18 ) | ( decode( b64.charAt( i + 1 ) ) << 12 ) | ( decode( b64.charAt( i + 2 ) ) << 6 ) | decode( b64.charAt( i + 3 ) )
|
|
|
2199 |
push( ( tmp & 0xFF0000 ) >> 16 )
|
|
|
2200 |
push( ( tmp & 0xFF00 ) >> 8 )
|
|
|
2201 |
push( tmp & 0xFF )
|
|
|
2202 |
}
|
|
|
2203 |
|
|
|
2204 |
if ( placeHolders === 2 ) {
|
|
|
2205 |
tmp = ( decode( b64.charAt( i ) ) << 2 ) | ( decode( b64.charAt( i + 1 ) ) >> 4 )
|
|
|
2206 |
push( tmp & 0xFF )
|
|
|
2207 |
} else if ( placeHolders === 1 ) {
|
|
|
2208 |
tmp = ( decode( b64.charAt( i ) ) << 10 ) | ( decode( b64.charAt( i + 1 ) ) << 4 ) | ( decode( b64.charAt( i + 2 ) ) >> 2 )
|
|
|
2209 |
push( ( tmp >> 8 ) & 0xFF )
|
|
|
2210 |
push( tmp & 0xFF )
|
|
|
2211 |
}
|
|
|
2212 |
|
|
|
2213 |
return arr
|
|
|
2214 |
}
|
|
|
2215 |
|
|
|
2216 |
_this.handleCallback( callback, data );
|
|
|
2217 |
|
|
|
2218 |
return data;
|
|
|
2219 |
},
|
|
|
2220 |
|
|
|
2221 |
/**
|
|
|
2222 |
* Callback handler; injects additional arguments to callback
|
|
|
2223 |
*/
|
|
|
2224 |
handleCallback: function( callback ) {
|
|
|
2225 |
var i1, data = Array();
|
|
|
2226 |
if ( callback && callback instanceof Function ) {
|
|
|
2227 |
for ( i1 = 0; i1 < arguments.length; i1++ ) {
|
|
|
2228 |
if ( i1 > 0 ) {
|
|
|
2229 |
data.push( arguments[ i1 ] );
|
|
|
2230 |
}
|
|
|
2231 |
}
|
|
|
2232 |
callback.apply( _this, data );
|
|
|
2233 |
}
|
|
|
2234 |
},
|
|
|
2235 |
|
|
|
2236 |
/**
|
|
|
2237 |
* Handles drag/drop events; loads given imagery
|
|
|
2238 |
*/
|
|
|
2239 |
handleDropbox: function( e ) {
|
|
|
2240 |
if ( _this.drawing.buffer.enabled ) {
|
|
|
2241 |
e.preventDefault();
|
|
|
2242 |
e.stopPropagation();
|
|
|
2243 |
|
|
|
2244 |
// DRAG OVER
|
|
|
2245 |
if ( e.type == "dragover" ) {
|
|
|
2246 |
_this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas active dropbox" );
|
|
|
2247 |
|
|
|
2248 |
// DRAGLEAVE; DROP
|
|
|
2249 |
} else {
|
|
|
2250 |
_this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas active" );
|
|
|
2251 |
|
|
|
2252 |
if ( e.type == "drop" && e.dataTransfer.files.length ) {
|
|
|
2253 |
for ( var i1 = 0; i1 < e.dataTransfer.files.length; i1++ ) {
|
|
|
2254 |
var reader = new FileReader();
|
|
|
2255 |
reader.onloadend = ( function( index ) {
|
|
|
2256 |
return function() {
|
|
|
2257 |
_this.drawing.handler.add( {
|
|
|
2258 |
url: reader.result,
|
|
|
2259 |
top: e.layerY - ( index * 10 ),
|
|
|
2260 |
left: e.layerX - ( index * 10 )
|
|
|
2261 |
} );
|
|
|
2262 |
}
|
|
|
2263 |
} )( i1 );
|
|
|
2264 |
reader.readAsDataURL( e.dataTransfer.files[ i1 ] );
|
|
|
2265 |
}
|
|
|
2266 |
}
|
|
|
2267 |
}
|
|
|
2268 |
}
|
|
|
2269 |
},
|
|
|
2270 |
|
|
|
2271 |
/**
|
|
|
2272 |
* Gathers chart data according to its type
|
|
|
2273 |
*/
|
|
|
2274 |
getChartData: function( options ) {
|
|
|
2275 |
var cfg = _this.deepMerge( {
|
|
|
2276 |
data: [],
|
|
|
2277 |
titles: {},
|
|
|
2278 |
dateFields: [],
|
|
|
2279 |
dataFields: [],
|
|
|
2280 |
dataFieldsMap: {},
|
|
|
2281 |
exportTitles: _this.config.exportTitles,
|
|
|
2282 |
exportFields: _this.config.exportFields,
|
|
|
2283 |
exportSelection: _this.config.exportSelection,
|
|
|
2284 |
columnNames: _this.config.columnNames
|
|
|
2285 |
}, options || {}, true );
|
|
|
2286 |
var uid, i1, i2, i3;
|
|
|
2287 |
var lookupFields = [ "valueField", "openField", "closeField", "highField", "lowField", "xField", "yField" ];
|
|
|
2288 |
|
|
|
2289 |
// HANDLE FIELDS
|
|
|
2290 |
function addField( field, title, type ) {
|
|
|
2291 |
|
|
|
2292 |
function checkExistance( field, type ) {
|
|
|
2293 |
if ( cfg.dataFields.indexOf( field ) != -1 ) {
|
|
|
2294 |
return checkExistance( [ field, ".", type ].join( "" ) );
|
|
|
2295 |
}
|
|
|
2296 |
return field;
|
|
|
2297 |
}
|
|
|
2298 |
|
|
|
2299 |
if ( field && cfg.exportTitles && _this.setup.chart.type != "gantt" ) {
|
|
|
2300 |
uid = checkExistance( field, type );
|
|
|
2301 |
cfg.dataFieldsMap[ uid ] = field;
|
|
|
2302 |
cfg.dataFields.push( uid );
|
|
|
2303 |
cfg.titles[ uid ] = title || uid;
|
|
|
2304 |
}
|
|
|
2305 |
}
|
|
|
2306 |
|
|
|
2307 |
if ( cfg.data.length == 0 ) {
|
|
|
2308 |
// STOCK DATA; GATHER COMPARED GRAPHS
|
|
|
2309 |
if ( _this.setup.chart.type == "stock" ) {
|
|
|
2310 |
cfg.data = _this.setup.chart.mainDataSet.dataProvider;
|
|
|
2311 |
|
|
|
2312 |
// CATEGORY AXIS
|
|
|
2313 |
addField( _this.setup.chart.mainDataSet.categoryField );
|
|
|
2314 |
cfg.dateFields.push( _this.setup.chart.mainDataSet.categoryField );
|
|
|
2315 |
|
|
|
2316 |
// WALKTHROUGH GRAPHS
|
|
|
2317 |
for ( i1 = 0; i1 < _this.setup.chart.mainDataSet.fieldMappings.length; i1++ ) {
|
|
|
2318 |
var fieldMap = _this.setup.chart.mainDataSet.fieldMappings[ i1 ];
|
|
|
2319 |
for ( i2 = 0; i2 < _this.setup.chart.panels.length; i2++ ) {
|
|
|
2320 |
var panel = _this.setup.chart.panels[ i2 ]
|
|
|
2321 |
for ( i3 = 0; i3 < panel.stockGraphs.length; i3++ ) {
|
|
|
2322 |
var graph = panel.stockGraphs[ i3 ];
|
|
|
2323 |
|
|
|
2324 |
for ( i4 = 0; i4 < lookupFields.length; i4++ ) {
|
|
|
2325 |
if ( graph[ lookupFields[ i4 ] ] == fieldMap.toField ) {
|
|
|
2326 |
addField( fieldMap.fromField, graph.title, lookupFields[ i4 ] );
|
|
|
2327 |
}
|
|
|
2328 |
}
|
|
|
2329 |
}
|
|
|
2330 |
}
|
|
|
2331 |
}
|
|
|
2332 |
|
|
|
2333 |
// WALKTHROUGH COMPARISON AND MERGE IT'S DATA
|
|
|
2334 |
for ( i1 = 0; i1 < _this.setup.chart.comparedGraphs.length; i1++ ) {
|
|
|
2335 |
var graph = _this.setup.chart.comparedGraphs[ i1 ];
|
|
|
2336 |
for ( i2 = 0; i2 < graph.dataSet.dataProvider.length; i2++ ) {
|
|
|
2337 |
for ( i3 = 0; i3 < graph.dataSet.fieldMappings.length; i3++ ) {
|
|
|
2338 |
var fieldMap = graph.dataSet.fieldMappings[ i3 ];
|
|
|
2339 |
var uid = graph.dataSet.id + "_" + fieldMap.toField;
|
|
|
2340 |
|
|
|
2341 |
if ( i2 < cfg.data.length ) {
|
|
|
2342 |
cfg.data[ i2 ][ uid ] = graph.dataSet.dataProvider[ i2 ][ fieldMap.fromField ];
|
|
|
2343 |
|
|
|
2344 |
if ( !cfg.titles[ uid ] ) {
|
|
|
2345 |
addField( uid, graph.dataSet.title )
|
|
|
2346 |
}
|
|
|
2347 |
}
|
|
|
2348 |
}
|
|
|
2349 |
}
|
|
|
2350 |
}
|
|
|
2351 |
|
|
|
2352 |
// GANTT DATA; FLATTEN SEGMENTS
|
|
|
2353 |
} else if ( _this.setup.chart.type == "gantt" ) {
|
|
|
2354 |
// CATEGORY AXIS
|
|
|
2355 |
addField( _this.setup.chart.categoryField );
|
|
|
2356 |
cfg.dateFields.push( _this.setup.chart.categoryField );
|
|
|
2357 |
|
|
|
2358 |
var field = _this.setup.chart.segmentsField;
|
|
|
2359 |
for ( i1 = 0; i1 < _this.setup.chart.dataProvider.length; i1++ ) {
|
|
|
2360 |
var dataItem = _this.setup.chart.dataProvider[ i1 ];
|
|
|
2361 |
if ( dataItem[ field ] ) {
|
|
|
2362 |
for ( i2 = 0; i2 < dataItem[ field ].length; i2++ ) {
|
|
|
2363 |
dataItem[ field ][ i2 ][ _this.setup.chart.categoryField ] = dataItem[ _this.setup.chart.categoryField ];
|
|
|
2364 |
cfg.data.push( dataItem[ field ][ i2 ] );
|
|
|
2365 |
}
|
|
|
2366 |
}
|
|
|
2367 |
}
|
|
|
2368 |
|
|
|
2369 |
// GRAPHS
|
|
|
2370 |
for ( i1 = 0; i1 < _this.setup.chart.graphs.length; i1++ ) {
|
|
|
2371 |
var graph = _this.setup.chart.graphs[ i1 ];
|
|
|
2372 |
|
|
|
2373 |
for ( i2 = 0; i2 < lookupFields.length; i2++ ) {
|
|
|
2374 |
var dataField = lookupFields[ i2 ];
|
|
|
2375 |
var graphField = graph[ dataField ];
|
|
|
2376 |
var title = graph.title;
|
|
|
2377 |
|
|
|
2378 |
addField( graphField, graph.title, dataField );
|
|
|
2379 |
}
|
|
|
2380 |
}
|
|
|
2381 |
|
|
|
2382 |
// PIE/FUNNEL DATA;
|
|
|
2383 |
} else if ( [ "pie", "funnel" ].indexOf( _this.setup.chart.type ) != -1 ) {
|
|
|
2384 |
cfg.data = _this.setup.chart.dataProvider;
|
|
|
2385 |
|
|
|
2386 |
// CATEGORY AXIS
|
|
|
2387 |
addField( _this.setup.chart.titleField );
|
|
|
2388 |
cfg.dateFields.push( _this.setup.chart.titleField );
|
|
|
2389 |
|
|
|
2390 |
// VALUE
|
|
|
2391 |
addField( _this.setup.chart.valueField );
|
|
|
2392 |
|
|
|
2393 |
// DEFAULT DATA;
|
|
|
2394 |
} else if ( _this.setup.chart.type != "map" ) {
|
|
|
2395 |
cfg.data = _this.setup.chart.dataProvider;
|
|
|
2396 |
|
|
|
2397 |
// CATEGORY AXIS
|
|
|
2398 |
if ( _this.setup.chart.categoryAxis ) {
|
|
|
2399 |
addField( _this.setup.chart.categoryField, _this.setup.chart.categoryAxis.title );
|
|
|
2400 |
if ( _this.setup.chart.categoryAxis.parseDates !== false ) {
|
|
|
2401 |
cfg.dateFields.push( _this.setup.chart.categoryField );
|
|
|
2402 |
}
|
|
|
2403 |
}
|
|
|
2404 |
|
|
|
2405 |
// GRAPHS
|
|
|
2406 |
for ( i1 = 0; i1 < _this.setup.chart.graphs.length; i1++ ) {
|
|
|
2407 |
var graph = _this.setup.chart.graphs[ i1 ];
|
|
|
2408 |
|
|
|
2409 |
for ( i2 = 0; i2 < lookupFields.length; i2++ ) {
|
|
|
2410 |
var dataField = lookupFields[ i2 ];
|
|
|
2411 |
var graphField = graph[ dataField ];
|
|
|
2412 |
|
|
|
2413 |
addField( graphField, graph.title, dataField );
|
|
|
2414 |
}
|
|
|
2415 |
}
|
|
|
2416 |
}
|
|
|
2417 |
}
|
|
|
2418 |
return _this.processData( cfg );
|
|
|
2419 |
},
|
|
|
2420 |
|
|
|
2421 |
/**
|
|
|
2422 |
* Walkthrough data to format dates and titles
|
|
|
2423 |
*/
|
|
|
2424 |
processData: function( options ) {
|
|
|
2425 |
var cfg = _this.deepMerge( {
|
|
|
2426 |
data: [],
|
|
|
2427 |
titles: {},
|
|
|
2428 |
dateFields: [],
|
|
|
2429 |
dataFields: [],
|
|
|
2430 |
dataFieldsMap: {},
|
|
|
2431 |
dataDateFormat: _this.setup.chart.dataDateFormat,
|
|
|
2432 |
dateFormat: _this.config.dateFormat || _this.setup.chart.dataDateFormat || "YYYY-MM-DD",
|
|
|
2433 |
exportTitles: _this.config.exportTitles,
|
|
|
2434 |
exportFields: _this.config.exportFields,
|
|
|
2435 |
exportSelection: _this.config.exportSelection,
|
|
|
2436 |
columnNames: _this.config.columnNames
|
|
|
2437 |
}, options || {}, true );
|
|
|
2438 |
var i1, i2;
|
|
|
2439 |
|
|
|
2440 |
if ( cfg.data.length ) {
|
|
|
2441 |
// GATHER MISSING FIELDS
|
|
|
2442 |
for ( i1 = 0; i1 < cfg.data.length; i1++ ) {
|
|
|
2443 |
for ( i2 in cfg.data[ i1 ] ) {
|
|
|
2444 |
if ( cfg.dataFields.indexOf( i2 ) == -1 ) {
|
|
|
2445 |
cfg.dataFields.push( i2 );
|
|
|
2446 |
cfg.dataFieldsMap[ i2 ] = i2;
|
|
|
2447 |
}
|
|
|
2448 |
}
|
|
|
2449 |
}
|
|
|
2450 |
|
|
|
2451 |
// REMOVE FIELDS SELECTIVELY
|
|
|
2452 |
if ( cfg.exportFields !== undefined ) {
|
|
|
2453 |
cfg.dataFields = cfg.dataFields.filter( function( n ) {
|
|
|
2454 |
return cfg.exportFields.indexOf( n ) != -1;
|
|
|
2455 |
} );
|
|
|
2456 |
}
|
|
|
2457 |
|
|
|
2458 |
// REBUILD DATA
|
|
|
2459 |
var buffer = [];
|
|
|
2460 |
for ( i1 = 0; i1 < cfg.data.length; i1++ ) {
|
|
|
2461 |
var tmp = {};
|
|
|
2462 |
var skip = false;
|
|
|
2463 |
for ( i2 = 0; i2 < cfg.dataFields.length; i2++ ) {
|
|
|
2464 |
var uniqueField = cfg.dataFields[ i2 ];
|
|
|
2465 |
var dataField = cfg.dataFieldsMap[ uniqueField ];
|
|
|
2466 |
var title = ( cfg.columnNames && cfg.columnNames[ uniqueField ] ) || cfg.titles[ uniqueField ] || uniqueField;
|
|
|
2467 |
var value = cfg.data[ i1 ][ dataField ];
|
|
|
2468 |
if ( value == null ) {
|
|
|
2469 |
value = undefined;
|
|
|
2470 |
}
|
|
|
2471 |
|
|
|
2472 |
// TITLEFY
|
|
|
2473 |
if ( cfg.exportTitles && _this.setup.chart.type != "gantt" ) {
|
|
|
2474 |
if ( title in tmp ) {
|
|
|
2475 |
title += [ "( ", uniqueField, " )" ].join( "" );
|
|
|
2476 |
}
|
|
|
2477 |
}
|
|
|
2478 |
|
|
|
2479 |
// PROCESS CATEGORY
|
|
|
2480 |
if ( cfg.dateFields.indexOf( dataField ) != -1 ) {
|
|
|
2481 |
|
|
|
2482 |
// CONVERT DATESTRING TO DATE OBJECT
|
|
|
2483 |
if ( cfg.dataDateFormat && ( value instanceof String || typeof value == "string" ) ) {
|
|
|
2484 |
value = AmCharts.stringToDate( value, cfg.dataDateFormat );
|
|
|
2485 |
|
|
|
2486 |
// CONVERT TIMESTAMP TO DATE OBJECT
|
|
|
2487 |
} else if ( cfg.dateFormat && ( value instanceof Number || typeof value == "number" ) ) {
|
|
|
2488 |
value = new Date( value );
|
|
|
2489 |
}
|
|
|
2490 |
|
|
|
2491 |
// CATEGORY RANGE
|
|
|
2492 |
if ( cfg.exportSelection ) {
|
|
|
2493 |
if ( value instanceof Date ) {
|
|
|
2494 |
if ( value < chart.startDate || value > chart.endDate ) {
|
|
|
2495 |
skip = true;
|
|
|
2496 |
}
|
|
|
2497 |
|
|
|
2498 |
} else if ( i1 < chart.startIndex || i1 > chart.endIndex ) {
|
|
|
2499 |
skip = true;
|
|
|
2500 |
}
|
|
|
2501 |
}
|
|
|
2502 |
|
|
|
2503 |
// CATEGORY FORMAT
|
|
|
2504 |
if ( cfg.dateFormat && cfg.dateFormat != "dateObject" && value instanceof Date ) {
|
|
|
2505 |
value = AmCharts.formatDate( value, cfg.dateFormat );
|
|
|
2506 |
}
|
|
|
2507 |
}
|
|
|
2508 |
|
|
|
2509 |
tmp[ title ] = value;
|
|
|
2510 |
}
|
|
|
2511 |
if ( !skip ) {
|
|
|
2512 |
buffer.push( tmp );
|
|
|
2513 |
}
|
|
|
2514 |
}
|
|
|
2515 |
cfg.data = buffer;
|
|
|
2516 |
}
|
|
|
2517 |
return cfg.data;
|
|
|
2518 |
},
|
|
|
2519 |
|
|
|
2520 |
/**
|
|
|
2521 |
* Prettifies string
|
|
|
2522 |
*/
|
|
|
2523 |
capitalize: function( string ) {
|
|
|
2524 |
return string.charAt( 0 ).toUpperCase() + string.slice( 1 ).toLowerCase();
|
|
|
2525 |
},
|
|
|
2526 |
|
|
|
2527 |
/**
|
|
|
2528 |
* Generates export menu; returns UL node
|
|
|
2529 |
*/
|
|
|
2530 |
createMenu: function( list, container ) {
|
|
|
2531 |
var div;
|
|
|
2532 |
|
|
|
2533 |
function buildList( list, container ) {
|
|
|
2534 |
var i1, i2, ul = document.createElement( "ul" );
|
|
|
2535 |
for ( i1 = 0; i1 < list.length; i1++ ) {
|
|
|
2536 |
var item = typeof list[ i1 ] === "string" ? {
|
|
|
2537 |
format: list[ i1 ]
|
|
|
2538 |
} : list[ i1 ];
|
|
|
2539 |
var li = document.createElement( "li" );
|
|
|
2540 |
var a = document.createElement( "a" );
|
|
|
2541 |
var img = document.createElement( "img" );
|
|
|
2542 |
var span = document.createElement( "span" );
|
|
|
2543 |
var action = String( item.action ? item.action : item.format ).toLowerCase();
|
|
|
2544 |
|
|
|
2545 |
item.format = String( item.format ).toUpperCase();
|
|
|
2546 |
|
|
|
2547 |
// MERGE WITH GIVEN FORMAT
|
|
|
2548 |
if ( _this.config.formats[ item.format ] ) {
|
|
|
2549 |
item = _this.deepMerge( {
|
|
|
2550 |
label: item.icon ? "" : item.format,
|
|
|
2551 |
format: item.format,
|
|
|
2552 |
mimeType: _this.config.formats[ item.format ].mimeType,
|
|
|
2553 |
extension: _this.config.formats[ item.format ].extension,
|
|
|
2554 |
capture: _this.config.formats[ item.format ].capture,
|
|
|
2555 |
action: _this.config.action,
|
|
|
2556 |
fileName: _this.config.fileName
|
|
|
2557 |
}, item );
|
|
|
2558 |
} else if ( !item.label ) {
|
|
|
2559 |
item.label = item.label ? item.label : _this.i18l( "menu.label." + action );
|
|
|
2560 |
}
|
|
|
2561 |
|
|
|
2562 |
// FILTER; TOGGLE FLAG
|
|
|
2563 |
if ( [ "CSV", "JSON", "XLSX" ].indexOf( item.format ) != -1 && [ "map", "gauge" ].indexOf( _this.setup.chart.type ) != -1 ) {
|
|
|
2564 |
continue;
|
|
|
2565 |
|
|
|
2566 |
// BLOB EXCEPTION
|
|
|
2567 |
} else if ( !_this.setup.hasBlob && item.format != "UNDEFINED" ) {
|
|
|
2568 |
if ( item.mimeType && item.mimeType.split( "/" )[ 0 ] != "image" && item.mimeType != "text/plain" ) {
|
|
|
2569 |
continue;
|
|
|
2570 |
}
|
|
|
2571 |
}
|
|
|
2572 |
|
|
|
2573 |
// DRAWING
|
|
|
2574 |
if ( item.action == "draw" ) {
|
|
|
2575 |
if ( _this.config.fabric.drawing.enabled ) {
|
|
|
2576 |
item.menu = item.menu ? item.menu : _this.config.fabric.drawing.menu;
|
|
|
2577 |
item.click = ( function( item ) {
|
|
|
2578 |
return function() {
|
|
|
2579 |
this.capture( item, function() {
|
|
|
2580 |
this.createMenu( item.menu );
|
|
|
2581 |
} );
|
|
|
2582 |
}
|
|
|
2583 |
} )( item );
|
|
|
2584 |
} else {
|
|
|
2585 |
item.menu = [];
|
|
|
2586 |
}
|
|
|
2587 |
|
|
|
2588 |
// DRAWING CHOICES
|
|
|
2589 |
} else if ( !item.populated && item.action && item.action.indexOf( "draw." ) != -1 ) {
|
|
|
2590 |
var type = item.action.split( "." )[ 1 ];
|
|
|
2591 |
var items = item[ type ] || _this.config.fabric.drawing[ type ] || [];
|
|
|
2592 |
|
|
|
2593 |
item.menu = [];
|
|
|
2594 |
item.populated = true;
|
|
|
2595 |
|
|
|
2596 |
for ( i2 = 0; i2 < items.length; i2++ ) {
|
|
|
2597 |
var tmp = {
|
|
|
2598 |
"label": items[ i2 ]
|
|
|
2599 |
}
|
|
|
2600 |
|
|
|
2601 |
if ( type == "shapes" ) {
|
|
|
2602 |
var io = items[ i2 ].indexOf( "//" ) == -1;
|
|
|
2603 |
var url = ( io ? _this.config.path + "shapes/" : "" ) + items[ i2 ];
|
|
|
2604 |
|
|
|
2605 |
tmp.action = "add";
|
|
|
2606 |
tmp.url = url;
|
|
|
2607 |
tmp.icon = url;
|
|
|
2608 |
tmp.ignore = io;
|
|
|
2609 |
tmp[ "class" ] = "export-drawing-shape";
|
|
|
2610 |
|
|
|
2611 |
} else if ( type == "colors" ) {
|
|
|
2612 |
tmp.style = "background-color: " + items[ i2 ];
|
|
|
2613 |
tmp.action = "change";
|
|
|
2614 |
tmp.color = items[ i2 ];
|
|
|
2615 |
tmp[ "class" ] = "export-drawing-color";
|
|
|
2616 |
|
|
|
2617 |
} else if ( type == "widths" ) {
|
|
|
2618 |
tmp.action = "change";
|
|
|
2619 |
tmp.width = items[ i2 ];
|
|
|
2620 |
tmp.label = document.createElement( "span" );
|
|
|
2621 |
|
|
|
2622 |
tmp.label.style.width = _this.numberToPx( items[ i2 ] );
|
|
|
2623 |
tmp.label.style.height = _this.numberToPx( items[ i2 ] );
|
|
|
2624 |
tmp[ "class" ] = "export-drawing-width";
|
|
|
2625 |
} else if ( type == "opacities" ) {
|
|
|
2626 |
tmp.style = "opacity: " + items[ i2 ];
|
|
|
2627 |
tmp.action = "change";
|
|
|
2628 |
tmp.opacity = items[ i2 ];
|
|
|
2629 |
tmp.label = ( items[ i2 ] * 100 ) + "%";
|
|
|
2630 |
tmp[ "class" ] = "export-drawing-opacity";
|
|
|
2631 |
} else if ( type == "modes" ) {
|
|
|
2632 |
tmp.label = _this.i18l( "menu.label.draw.modes." + items[ i2 ] );
|
|
|
2633 |
tmp.click = ( function( mode ) {
|
|
|
2634 |
return function() {
|
|
|
2635 |
_this.drawing.mode = mode;
|
|
|
2636 |
}
|
|
|
2637 |
} )( items[ i2 ] );
|
|
|
2638 |
tmp[ "class" ] = "export-drawing-mode";
|
|
|
2639 |
}
|
|
|
2640 |
|
|
|
2641 |
item.menu.push( tmp );
|
|
|
2642 |
}
|
|
|
2643 |
|
|
|
2644 |
// ADD CLICK HANDLER
|
|
|
2645 |
} else if ( !item.click && !item.menu && !item.items ) {
|
|
|
2646 |
// DRAWING METHODS
|
|
|
2647 |
if ( _this.drawing.handler[ action ] instanceof Function ) {
|
|
|
2648 |
item.action = action;
|
|
|
2649 |
item.click = ( function( item ) {
|
|
|
2650 |
return function() {
|
|
|
2651 |
this.drawing.handler[ item.action ]( item );
|
|
|
2652 |
}
|
|
|
2653 |
} )( item );
|
|
|
2654 |
|
|
|
2655 |
// DRAWING
|
|
|
2656 |
} else if ( _this.drawing.buffer.enabled ) {
|
|
|
2657 |
item.click = ( function( item ) {
|
|
|
2658 |
return function() {
|
|
|
2659 |
if ( this.config.drawing.autoClose ) {
|
|
|
2660 |
this.drawing.handler.done();
|
|
|
2661 |
}
|
|
|
2662 |
this[ "to" + item.format ]( item, function( data ) {
|
|
|
2663 |
if ( item.action == "download" ) {
|
|
|
2664 |
this.download( data, item.mimeType, [ item.fileName, item.extension ].join( "." ) );
|
|
|
2665 |
}
|
|
|
2666 |
} );
|
|
|
2667 |
}
|
|
|
2668 |
} )( item );
|
|
|
2669 |
|
|
|
2670 |
// REGULAR
|
|
|
2671 |
} else if ( item.format != "UNDEFINED" ) {
|
|
|
2672 |
item.click = ( function( item ) {
|
|
|
2673 |
return function() {
|
|
|
2674 |
if ( item.capture || item.action == "print" || item.format == "PRINT" ) {
|
|
|
2675 |
this.capture( item, function() {
|
|
|
2676 |
if ( this.config.drawing.autoClose ) {
|
|
|
2677 |
this.drawing.handler.done();
|
|
|
2678 |
}
|
|
|
2679 |
this[ "to" + item.format ]( item, function( data ) {
|
|
|
2680 |
if ( item.action == "download" ) {
|
|
|
2681 |
this.download( data, item.mimeType, [ item.fileName, item.extension ].join( "." ) );
|
|
|
2682 |
}
|
|
|
2683 |
} );
|
|
|
2684 |
} )
|
|
|
2685 |
|
|
|
2686 |
} else if ( this[ "to" + item.format ] ) {
|
|
|
2687 |
this[ "to" + item.format ]( item, function( data ) {
|
|
|
2688 |
this.download( data, item.mimeType, [ item.fileName, item.extension ].join( "." ) );
|
|
|
2689 |
} );
|
|
|
2690 |
} else {
|
|
|
2691 |
throw new Error( 'Invalid format. Could not determine output type.' );
|
|
|
2692 |
}
|
|
|
2693 |
}
|
|
|
2694 |
} )( item );
|
|
|
2695 |
}
|
|
|
2696 |
}
|
|
|
2697 |
|
|
|
2698 |
// HIDE EMPTY ONES
|
|
|
2699 |
if ( item.menu !== undefined && !item.menu.length ) {
|
|
|
2700 |
continue;
|
|
|
2701 |
}
|
|
|
2702 |
|
|
|
2703 |
// ADD LINK ATTR
|
|
|
2704 |
a.setAttribute( "href", "#" );
|
|
|
2705 |
a.addEventListener( "click", ( function( callback, item ) {
|
|
|
2706 |
return function( e ) {
|
|
|
2707 |
e.preventDefault();
|
|
|
2708 |
var args = [ e, item ];
|
|
|
2709 |
|
|
|
2710 |
// DELAYED
|
|
|
2711 |
if ( ( item.action == "draw" || item.format == "PRINT" || ( item.format != "UNDEFINED" && item.capture ) ) && !_this.drawing.enabled ) {
|
|
|
2712 |
item.delay = item.delay ? item.delay : _this.config.delay;
|
|
|
2713 |
if ( item.delay ) {
|
|
|
2714 |
_this.delay( item, callback );
|
|
|
2715 |
return;
|
|
|
2716 |
}
|
|
|
2717 |
}
|
|
|
2718 |
|
|
|
2719 |
callback.apply( _this, args );
|
|
|
2720 |
}
|
|
|
2721 |
} )( item.click || function( e ) {
|
|
|
2722 |
e.preventDefault();
|
|
|
2723 |
}, item ) );
|
|
|
2724 |
li.appendChild( a );
|
|
|
2725 |
|
|
|
2726 |
// ADD LABEL
|
|
|
2727 |
if ( _this.isElement( item.label ) ) {
|
|
|
2728 |
span.appendChild( item.label );
|
|
|
2729 |
} else {
|
|
|
2730 |
span.innerHTML = item.label;
|
|
|
2731 |
}
|
|
|
2732 |
|
|
|
2733 |
// APPEND ITEMS
|
|
|
2734 |
if ( item[ "class" ] ) {
|
|
|
2735 |
li.className = item[ "class" ];
|
|
|
2736 |
}
|
|
|
2737 |
|
|
|
2738 |
if ( item.style ) {
|
|
|
2739 |
li.setAttribute( "style", item.style );
|
|
|
2740 |
}
|
|
|
2741 |
|
|
|
2742 |
if ( item.icon ) {
|
|
|
2743 |
img.setAttribute( "src", ( !item.ignore && item.icon.slice( 0, 10 ).indexOf( "//" ) == -1 ? chart.pathToImages : "" ) + item.icon );
|
|
|
2744 |
a.appendChild( img );
|
|
|
2745 |
}
|
|
|
2746 |
if ( item.label ) {
|
|
|
2747 |
a.appendChild( span );
|
|
|
2748 |
}
|
|
|
2749 |
if ( item.title ) {
|
|
|
2750 |
a.setAttribute( "title", item.title );
|
|
|
2751 |
}
|
|
|
2752 |
|
|
|
2753 |
// CALLBACK; REVIVER FOR MENU ITEMS
|
|
|
2754 |
if ( _this.config.menuReviver ) {
|
|
|
2755 |
li = _this.config.menuReviver.apply( _this, [ item, li ] );
|
|
|
2756 |
}
|
|
|
2757 |
|
|
|
2758 |
// ADD ELEMENTS FOR EASY ACCESS
|
|
|
2759 |
item.elements = {
|
|
|
2760 |
li: li,
|
|
|
2761 |
a: a,
|
|
|
2762 |
img: img,
|
|
|
2763 |
span: span
|
|
|
2764 |
}
|
|
|
2765 |
|
|
|
2766 |
// ADD SUBLIST; JUST WITH ENTRIES
|
|
|
2767 |
if ( ( item.menu || item.items ) && item.action != "draw" ) {
|
|
|
2768 |
if ( buildList( item.menu || item.items, li ).childNodes.length ) {
|
|
|
2769 |
ul.appendChild( li );
|
|
|
2770 |
}
|
|
|
2771 |
} else {
|
|
|
2772 |
ul.appendChild( li );
|
|
|
2773 |
}
|
|
|
2774 |
}
|
|
|
2775 |
|
|
|
2776 |
// JUST ADD THOSE WITH ENTRIES
|
|
|
2777 |
if ( ul.childNodes.length ) {
|
|
|
2778 |
container.appendChild( ul );
|
|
|
2779 |
}
|
|
|
2780 |
|
|
|
2781 |
return ul;
|
|
|
2782 |
}
|
|
|
2783 |
|
|
|
2784 |
// DETERMINE CONTAINER
|
|
|
2785 |
if ( !container ) {
|
|
|
2786 |
if ( typeof _this.config.divId == "string" ) {
|
|
|
2787 |
_this.config.divId = container = document.getElementById( _this.config.divId );
|
|
|
2788 |
} else if ( _this.isElement( _this.config.divId ) ) {
|
|
|
2789 |
container = _this.config.divId;
|
|
|
2790 |
} else {
|
|
|
2791 |
container = _this.setup.chart.containerDiv;
|
|
|
2792 |
}
|
|
|
2793 |
}
|
|
|
2794 |
|
|
|
2795 |
// CREATE / RESET MENU CONTAINER
|
|
|
2796 |
if ( _this.isElement( _this.setup.menu ) ) {
|
|
|
2797 |
_this.setup.menu.innerHTML = "";
|
|
|
2798 |
} else {
|
|
|
2799 |
_this.setup.menu = document.createElement( "div" );
|
|
|
2800 |
}
|
|
|
2801 |
_this.setup.menu.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-menu " + _this.setup.chart.classNamePrefix + "-export-menu-" + _this.config.position + " amExportButton" );
|
|
|
2802 |
|
|
|
2803 |
// CALLBACK; REPLACES THE MENU WALKER
|
|
|
2804 |
if ( _this.config.menuWalker ) {
|
|
|
2805 |
buildList = _this.config.menuWalker;
|
|
|
2806 |
}
|
|
|
2807 |
buildList.apply( this, [ list, _this.setup.menu ] );
|
|
|
2808 |
|
|
|
2809 |
// JUST ADD THOSE WITH ENTRIES
|
|
|
2810 |
if ( _this.setup.menu.childNodes.length ) {
|
|
|
2811 |
container.appendChild( _this.setup.menu );
|
|
|
2812 |
}
|
|
|
2813 |
|
|
|
2814 |
return _this.setup.menu;
|
|
|
2815 |
},
|
|
|
2816 |
|
|
|
2817 |
/**
|
|
|
2818 |
* Method to trigger the callback delayed
|
|
|
2819 |
*/
|
|
|
2820 |
delay: function( options, callback ) {
|
|
|
2821 |
var cfg = _this.deepMerge( {
|
|
|
2822 |
delay: 3,
|
|
|
2823 |
precision: 2
|
|
|
2824 |
}, options || {} );
|
|
|
2825 |
var t1, t2, start = Number( new Date() );
|
|
|
2826 |
var menu = _this.createMenu( [ {
|
|
|
2827 |
label: _this.i18l( "capturing.delayed.menu.label" ).replace( "{{duration}}", AmCharts.toFixed( cfg.delay, cfg.precision ) ),
|
|
|
2828 |
title: _this.i18l( "capturing.delayed.menu.title" ),
|
|
|
2829 |
"class": "export-delayed-capturing",
|
|
|
2830 |
click: function() {
|
|
|
2831 |
clearTimeout( t1 );
|
|
|
2832 |
clearTimeout( t2 );
|
|
|
2833 |
_this.createMenu( _this.config.menu );
|
|
|
2834 |
}
|
|
|
2835 |
} ] );
|
|
|
2836 |
var label = menu.getElementsByTagName( "a" )[ 0 ];
|
|
|
2837 |
|
|
|
2838 |
// MENU UPDATE
|
|
|
2839 |
t1 = setInterval( function() {
|
|
|
2840 |
var diff = cfg.delay - ( Number( new Date() ) - start ) / 1000;
|
|
|
2841 |
if ( diff <= 0 ) {
|
|
|
2842 |
clearTimeout( t1 );
|
|
|
2843 |
if ( cfg.action != "draw" ) {
|
|
|
2844 |
_this.createMenu( _this.config.menu );
|
|
|
2845 |
}
|
|
|
2846 |
} else if ( label ) {
|
|
|
2847 |
label.innerHTML = _this.i18l( "capturing.delayed.menu.label" ).replace( "{{duration}}", AmCharts.toFixed( diff, 2 ) );
|
|
|
2848 |
}
|
|
|
2849 |
}, 10 );
|
|
|
2850 |
|
|
|
2851 |
// CALLBACK
|
|
|
2852 |
t2 = setTimeout( function() {
|
|
|
2853 |
callback.apply( _this, arguments );
|
|
|
2854 |
}, cfg.delay * 1000 );
|
|
|
2855 |
},
|
|
|
2856 |
|
|
|
2857 |
/**
|
|
|
2858 |
* Migration method to support old export setup
|
|
|
2859 |
*/
|
|
|
2860 |
migrateSetup: function( setup ) {
|
|
|
2861 |
var cfg = {
|
|
|
2862 |
enabled: true,
|
|
|
2863 |
migrated: true,
|
|
|
2864 |
libs: {
|
|
|
2865 |
autoLoad: true
|
|
|
2866 |
},
|
|
|
2867 |
menu: []
|
|
|
2868 |
};
|
|
|
2869 |
|
|
|
2870 |
function crawler( object ) {
|
|
|
2871 |
var key;
|
|
|
2872 |
for ( key in object ) {
|
|
|
2873 |
var value = object[ key ];
|
|
|
2874 |
|
|
|
2875 |
if ( key.slice( 0, 6 ) == "export" && value ) {
|
|
|
2876 |
cfg.menu.push( key.slice( 6 ) );
|
|
|
2877 |
} else if ( key == "userCFG" ) {
|
|
|
2878 |
crawler( value );
|
|
|
2879 |
} else if ( key == "menuItems" ) {
|
|
|
2880 |
cfg.menu = value;
|
|
|
2881 |
} else if ( key == "libs" ) {
|
|
|
2882 |
cfg.libs = value;
|
|
|
2883 |
} else if ( typeof key == "string" ) {
|
|
|
2884 |
cfg[ key ] = value;
|
|
|
2885 |
}
|
|
|
2886 |
}
|
|
|
2887 |
}
|
|
|
2888 |
|
|
|
2889 |
crawler( setup );
|
|
|
2890 |
|
|
|
2891 |
return cfg;
|
|
|
2892 |
},
|
|
|
2893 |
|
|
|
2894 |
/*
|
|
|
2895 |
** Add event listener
|
|
|
2896 |
*/
|
|
|
2897 |
loadListeners: function() {
|
|
|
2898 |
function handleClone( clone ) {
|
|
|
2899 |
if ( clone ) {
|
|
|
2900 |
clone.set( {
|
|
|
2901 |
top: clone.top + 10,
|
|
|
2902 |
left: clone.left + 10
|
|
|
2903 |
} );
|
|
|
2904 |
_this.setup.fabric.add( clone );
|
|
|
2905 |
}
|
|
|
2906 |
}
|
|
|
2907 |
|
|
|
2908 |
// OBSERVE; KEY LISTENER; DRAWING FEATURES
|
|
|
2909 |
if ( _this.config.keyListener && _this.config.keyListener != "attached" ) {
|
|
|
2910 |
_this.config.keyListener = "attached";
|
|
|
2911 |
document.addEventListener( "keydown", function( e ) {
|
|
|
2912 |
var current = _this.drawing.buffer.target;
|
|
|
2913 |
|
|
|
2914 |
// REMOVE; key: BACKSPACE / DELETE
|
|
|
2915 |
if ( ( e.keyCode == 8 || e.keyCode == 46 ) && current ) {
|
|
|
2916 |
e.preventDefault();
|
|
|
2917 |
_this.setup.fabric.remove( current );
|
|
|
2918 |
|
|
|
2919 |
// ESCAPE DRAWIN MODE; key: escape
|
|
|
2920 |
} else if ( e.keyCode == 27 && _this.drawing.enabled ) {
|
|
|
2921 |
e.preventDefault();
|
|
|
2922 |
_this.drawing.handler.done();
|
|
|
2923 |
|
|
|
2924 |
// COPY; key: C
|
|
|
2925 |
} else if ( e.keyCode == 67 && ( e.metaKey || e.ctrlKey ) && current ) {
|
|
|
2926 |
_this.drawing.buffer.copy = current;
|
|
|
2927 |
|
|
|
2928 |
// CUT; key: X
|
|
|
2929 |
} else if ( e.keyCode == 88 && ( e.metaKey || e.ctrlKey ) && current ) {
|
|
|
2930 |
_this.drawing.buffer.copy = current;
|
|
|
2931 |
_this.setup.fabric.remove( current );
|
|
|
2932 |
|
|
|
2933 |
// PASTE; key: V
|
|
|
2934 |
} else if ( e.keyCode == 86 && ( e.metaKey || e.ctrlKey ) ) {
|
|
|
2935 |
if ( _this.drawing.buffer.copy ) {
|
|
|
2936 |
handleClone( _this.drawing.buffer.copy.clone( handleClone ) )
|
|
|
2937 |
}
|
|
|
2938 |
|
|
|
2939 |
// UNDO / REDO; key: Z
|
|
|
2940 |
} else if ( e.keyCode == 90 && ( e.metaKey || e.ctrlKey ) ) {
|
|
|
2941 |
e.preventDefault();
|
|
|
2942 |
if ( e.shiftKey ) {
|
|
|
2943 |
_this.drawing.handler.redo();
|
|
|
2944 |
} else {
|
|
|
2945 |
_this.drawing.handler.undo();
|
|
|
2946 |
}
|
|
|
2947 |
}
|
|
|
2948 |
} );
|
|
|
2949 |
}
|
|
|
2950 |
|
|
|
2951 |
// OBSERVE; DRAG AND DROP LISTENER; DRAWING FEATURE
|
|
|
2952 |
if ( _this.config.fileListener ) {
|
|
|
2953 |
_this.setup.chart.containerDiv.addEventListener( "dragover", _this.handleDropbox );
|
|
|
2954 |
_this.setup.chart.containerDiv.addEventListener( "dragleave", _this.handleDropbox );
|
|
|
2955 |
_this.setup.chart.containerDiv.addEventListener( "drop", _this.handleDropbox );
|
|
|
2956 |
}
|
|
|
2957 |
},
|
|
|
2958 |
|
|
|
2959 |
/**
|
|
|
2960 |
* Initiate export menu; waits for chart container to place menu
|
|
|
2961 |
*/
|
|
|
2962 |
init: function() {
|
|
|
2963 |
clearTimeout( _this.timer );
|
|
|
2964 |
_this.timer = setInterval( function() {
|
|
|
2965 |
if ( _this.setup.chart.containerDiv ) {
|
|
|
2966 |
clearTimeout( _this.timer );
|
|
|
2967 |
|
|
|
2968 |
if ( _this.config.enabled ) {
|
|
|
2969 |
// CREATE REFERENCE
|
|
|
2970 |
_this.setup.chart.AmExport = _this;
|
|
|
2971 |
|
|
|
2972 |
// OVERWRITE PARENT OVERFLOW
|
|
|
2973 |
if ( _this.config.overflow ) {
|
|
|
2974 |
_this.setup.chart.div.style.overflow = "visible";
|
|
|
2975 |
}
|
|
|
2976 |
|
|
|
2977 |
// ATTACH EVENTS
|
|
|
2978 |
_this.loadListeners();
|
|
|
2979 |
|
|
|
2980 |
// CREATE MENU
|
|
|
2981 |
_this.createMenu( _this.config.menu );
|
|
|
2982 |
}
|
|
|
2983 |
}
|
|
|
2984 |
}, AmCharts.updateRate );
|
|
|
2985 |
|
|
|
2986 |
},
|
|
|
2987 |
|
|
|
2988 |
/**
|
|
|
2989 |
* Initiates export instance; merges given config; attaches event listener
|
|
|
2990 |
*/
|
|
|
2991 |
construct: function() {
|
|
|
2992 |
// ANNOTATION; MAP "DONE"
|
|
|
2993 |
_this.drawing.handler.cancel = _this.drawing.handler.done;
|
|
|
2994 |
|
|
|
2995 |
// CHECK BLOB CONSTRUCTOR
|
|
|
2996 |
try {
|
|
|
2997 |
_this.setup.hasBlob = !!new Blob;
|
|
|
2998 |
} catch ( e ) {}
|
|
|
2999 |
|
|
|
3000 |
// WORK AROUND TO BYPASS FILESAVER CHECK TRYING TO OPEN THE BLOB URL IN SAFARI BROWSER
|
|
|
3001 |
window.safari = window.safari ? window.safari : {};
|
|
|
3002 |
|
|
|
3003 |
// OVERTAKE CHART FONTSIZE IF GIVEN
|
|
|
3004 |
_this.defaults.fabric.drawing.fontSize = _this.setup.chart.fontSize || 11;
|
|
|
3005 |
|
|
|
3006 |
// MERGE SETTINGS
|
|
|
3007 |
_this.config.drawing = _this.deepMerge( _this.defaults.fabric.drawing, _this.config.drawing || {}, true );
|
|
|
3008 |
_this.deepMerge( _this.defaults.fabric, _this.config, true );
|
|
|
3009 |
_this.deepMerge( _this.defaults.fabric, _this.config.fabric || {}, true );
|
|
|
3010 |
_this.deepMerge( _this.defaults.pdfMake, _this.config, true );
|
|
|
3011 |
_this.deepMerge( _this.defaults.pdfMake, _this.config.pdfMake || {}, true );
|
|
|
3012 |
_this.deepMerge( _this.libs, _this.config.libs || {}, true );
|
|
|
3013 |
|
|
|
3014 |
// UPDATE CONFIG
|
|
|
3015 |
_this.config.drawing = _this.defaults.fabric.drawing;
|
|
|
3016 |
_this.config.fabric = _this.defaults.fabric;
|
|
|
3017 |
_this.config.pdfMake = _this.defaults.pdfMake;
|
|
|
3018 |
_this.config = _this.deepMerge( _this.defaults, _this.config, true );
|
|
|
3019 |
|
|
|
3020 |
// MERGE; SETUP DRAWING MENU
|
|
|
3021 |
if ( _this.config.fabric.drawing.enabled ) {
|
|
|
3022 |
if ( _this.config.fabric.drawing.menu === undefined ) {
|
|
|
3023 |
_this.config.fabric.drawing.menu = [];
|
|
|
3024 |
_this.deepMerge( _this.config.fabric.drawing.menu, [ {
|
|
|
3025 |
"class": "export-drawing",
|
|
|
3026 |
menu: [ {
|
|
|
3027 |
label: _this.i18l( "menu.label.draw.add" ),
|
|
|
3028 |
menu: [ {
|
|
|
3029 |
label: _this.i18l( "menu.label.draw.shapes" ),
|
|
|
3030 |
action: "draw.shapes"
|
|
|
3031 |
}, {
|
|
|
3032 |
label: _this.i18l( "menu.label.draw.text" ),
|
|
|
3033 |
action: "text"
|
|
|
3034 |
} ]
|
|
|
3035 |
}, {
|
|
|
3036 |
label: _this.i18l( "menu.label.draw.change" ),
|
|
|
3037 |
menu: [ {
|
|
|
3038 |
label: _this.i18l( "menu.label.draw.modes" ),
|
|
|
3039 |
action: "draw.modes"
|
|
|
3040 |
}, {
|
|
|
3041 |
label: _this.i18l( "menu.label.draw.colors" ),
|
|
|
3042 |
action: "draw.colors"
|
|
|
3043 |
}, {
|
|
|
3044 |
label: _this.i18l( "menu.label.draw.widths" ),
|
|
|
3045 |
action: "draw.widths"
|
|
|
3046 |
}, {
|
|
|
3047 |
label: _this.i18l( "menu.label.draw.opacities" ),
|
|
|
3048 |
action: "draw.opacities"
|
|
|
3049 |
}, "UNDO", "REDO" ]
|
|
|
3050 |
}, {
|
|
|
3051 |
label: _this.i18l( "menu.label.save.image" ),
|
|
|
3052 |
menu: [ "PNG", "JPG", "SVG", "PDF" ]
|
|
|
3053 |
}, "PRINT", "CANCEL" ]
|
|
|
3054 |
} ] );
|
|
|
3055 |
}
|
|
|
3056 |
}
|
|
|
3057 |
|
|
|
3058 |
// MERGE; SETUP MAIN MENU
|
|
|
3059 |
if ( _this.config.menu === undefined ) {
|
|
|
3060 |
_this.config.menu = [];
|
|
|
3061 |
// PARENT MENU
|
|
|
3062 |
_this.deepMerge( _this.config, {
|
|
|
3063 |
menu: [ {
|
|
|
3064 |
"class": "export-main",
|
|
|
3065 |
menu: [ {
|
|
|
3066 |
label: _this.i18l( "menu.label.save.image" ),
|
|
|
3067 |
menu: [ "PNG", "JPG", "SVG", "PDF" ]
|
|
|
3068 |
}, {
|
|
|
3069 |
label: _this.i18l( "menu.label.save.data" ),
|
|
|
3070 |
menu: [ "CSV", "XLSX", "JSON" ]
|
|
|
3071 |
}, {
|
|
|
3072 |
label: _this.i18l( "menu.label.draw" ),
|
|
|
3073 |
action: "draw",
|
|
|
3074 |
menu: _this.config.fabric.drawing.menu
|
|
|
3075 |
}, {
|
|
|
3076 |
format: "PRINT",
|
|
|
3077 |
label: _this.i18l( "menu.label.print" )
|
|
|
3078 |
} ]
|
|
|
3079 |
} ]
|
|
|
3080 |
} );
|
|
|
3081 |
}
|
|
|
3082 |
|
|
|
3083 |
// ADD MISSING PATH
|
|
|
3084 |
if ( !_this.libs.path ) {
|
|
|
3085 |
_this.libs.path = _this.config.path + "libs/";
|
|
|
3086 |
}
|
|
|
3087 |
|
|
|
3088 |
// CHECK ACCEPTANCE
|
|
|
3089 |
if ( _this.isSupported() ) {
|
|
|
3090 |
// LOAD DEPENDENCIES
|
|
|
3091 |
_this.loadDependencies( _this.libs.resources, _this.libs.reload );
|
|
|
3092 |
// ADD CLASSNAMES
|
|
|
3093 |
_this.setup.chart.addClassNames = true;
|
|
|
3094 |
// REFERENCE
|
|
|
3095 |
_this.setup.chart[ _this.name ] = _this;
|
|
|
3096 |
// INIT MENU; WAIT FOR CHART INSTANCE
|
|
|
3097 |
_this.init();
|
|
|
3098 |
}
|
|
|
3099 |
}
|
|
|
3100 |
}
|
|
|
3101 |
|
|
|
3102 |
// USE GIVEN CONFIG
|
|
|
3103 |
if ( config ) {
|
|
|
3104 |
_this.config = config;
|
|
|
3105 |
|
|
|
3106 |
// USE CHART EXPORT CONFIG
|
|
|
3107 |
} else if ( _this.setup.chart[ _this.name ] ) {
|
|
|
3108 |
_this.config = _this.setup.chart[ _this.name ];
|
|
|
3109 |
|
|
|
3110 |
// MIGRATE OLD EXPORT CHART CONFIG
|
|
|
3111 |
} else if ( _this.setup.chart.amExport || _this.setup.chart.exportConfig ) {
|
|
|
3112 |
_this.config = _this.migrateSetup( _this.setup.chart.amExport || _this.setup.chart.exportConfig );
|
|
|
3113 |
|
|
|
3114 |
// EXIT; NO CONFIG
|
|
|
3115 |
} else {
|
|
|
3116 |
return;
|
|
|
3117 |
}
|
|
|
3118 |
|
|
|
3119 |
// CONSTRUCT INSTANCE
|
|
|
3120 |
_this.construct();
|
|
|
3121 |
|
|
|
3122 |
// EXPORT SCOPE
|
|
|
3123 |
return _this.deepMerge( this, _this );
|
|
|
3124 |
}
|
|
|
3125 |
} )();
|
|
|
3126 |
|
|
|
3127 |
/**
|
|
|
3128 |
* Set init handler
|
|
|
3129 |
*/
|
|
|
3130 |
AmCharts.addInitHandler( function( chart ) {
|
|
|
3131 |
new AmCharts[ "export" ]( chart );
|
|
|
3132 |
|
|
|
3133 |
}, [ "pie", "serial", "xy", "funnel", "radar", "gauge", "stock", "map", "gantt" ] );
|