How to use this.setup method in Cypress

Best JavaScript code snippet using cypress

export.js

Source:export.js Github

copy

Full Screen

1/*2Plugin Name: amCharts Export3Description: Adds export capabilities to amCharts products4Author: Benjamin Maertz, amCharts5Version: 1.3.36Author URI: http://www.amcharts.com/7Copyright 2015 amCharts8Licensed under the Apache License, Version 2.0 (the "License");9you may not use this file except in compliance with the License.10You may obtain a copy of the License at11 http://www.apache.org/licenses/LICENSE-2.012Unless required by applicable law or agreed to in writing, software13distributed under the License is distributed on an "AS IS" BASIS,14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15See the License for the specific language governing permissions and16limitations under the License.17Please note that the above license covers only this plugin. It by all means does18not apply to any other amCharts products that are covered by different licenses.19*/20/*21 ** Polyfill translation22 */23if ( !AmCharts.translations[ "export" ] ) {24 AmCharts.translations[ "export" ] = {}25}26if ( !AmCharts.translations[ "export" ][ "en" ] ) {27 AmCharts.translations[ "export" ][ "en" ] = {28 "fallback.save.text": "CTRL + C to copy the data into the clipboard.",29 "fallback.save.image": "Rightclick -> Save picture as... to save the image.",30 "capturing.delayed.menu.label": "{{duration}}",31 "capturing.delayed.menu.title": "Click to cancel",32 "menu.label.print": "Print",33 "menu.label.undo": "Undo",34 "menu.label.redo": "Redo",35 "menu.label.cancel": "Cancel",36 "menu.label.save.image": "Download as ...",37 "menu.label.save.data": "Save as ...",38 "menu.label.draw": "Annotate ...",39 "menu.label.draw.change": "Change ...",40 "menu.label.draw.add": "Add ...",41 "menu.label.draw.shapes": "Shape ...",42 "menu.label.draw.colors": "Color ...",43 "menu.label.draw.widths": "Size ...",44 "menu.label.draw.opacities": "Opacity ...",45 "menu.label.draw.text": "Text",46 "menu.label.draw.modes": "Mode ...",47 "menu.label.draw.modes.pencil": "Pencil",48 "menu.label.draw.modes.line": "Line",49 "menu.label.draw.modes.arrow": "Arrow"50 }51}52/*53 ** Polyfill export class54 */55( function() {56 AmCharts[ "export" ] = function( chart, config ) {57 var _this = {58 name: "export",59 version: "1.3.3",60 libs: {61 async: true,62 autoLoad: true,63 reload: false,64 resources: [ {65 "pdfmake/pdfmake.js": [ "pdfmake/vfs_fonts.js" ],66 "jszip/jszip.js": [ "xlsx/xlsx.js" ]67 }, "fabric.js/fabric.js", "FileSaver.js/FileSaver.js" ]68 },69 config: {},70 setup: {71 chart: chart,72 hasBlob: false73 },74 drawing: {75 enabled: false,76 undos: [],77 redos: [],78 buffer: {79 position: {80 x1: 0,81 y1: 0,82 x2: 0,83 y2: 0,84 xD: 0,85 yD: 086 }87 },88 handler: {89 undo: function( options, skipped ) {90 var item = _this.drawing.undos.pop();91 if ( item ) {92 item.selectable = true;93 _this.drawing.redos.push( item );94 if ( item.action == "added" ) {95 _this.setup.fabric.remove( item.target );96 }97 var state = JSON.parse( item.state );98 item.target.set( state );99 if ( item.target instanceof fabric.Group ) {100 _this.drawing.handler.change( {101 color: state.cfg.color,102 width: state.cfg.width,103 opacity: state.cfg.opacity104 }, true, item.target );105 }106 _this.setup.fabric.renderAll();107 // RECALL108 if ( item.state == item.target.recentState && !skipped ) {109 _this.drawing.handler.undo( item, true );110 }111 }112 },113 redo: function( options, skipped ) {114 var item = _this.drawing.redos.pop();115 if ( item ) {116 item.selectable = true;117 _this.drawing.undos.push( item );118 if ( item.action == "added" ) {119 _this.setup.fabric.add( item.target );120 }121 var state = JSON.parse( item.state );122 item.target.recentState = item.state;123 item.target.set( state );124 if ( item.target instanceof fabric.Group ) {125 _this.drawing.handler.change( {126 color: state.cfg.color,127 width: state.cfg.width,128 opacity: state.cfg.opacity129 }, true, item.target );130 }131 _this.setup.fabric.renderAll();132 // RECALL133 if ( item.action == "addified" ) {134 _this.drawing.handler.redo();135 }136 }137 },138 done: function( options ) {139 _this.drawing.buffer.enabled = false;140 _this.drawing.undos = [];141 _this.drawing.redos = [];142 _this.createMenu( _this.config.menu );143 _this.setup.fabric.deactivateAll();144 _this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas" );145 _this.setup.wrapper.style.display = "none";146 },147 add: function( options ) {148 var cfg = _this.deepMerge( {149 top: _this.setup.fabric.height / 2,150 left: _this.setup.fabric.width / 2151 }, options || {} );152 var method = cfg.url.indexOf( ".svg" ) != -1 ? fabric.loadSVGFromURL : fabric.Image.fromURL;153 method( cfg.url, function( objects, options ) {154 var group = options !== undefined ? fabric.util.groupSVGElements( objects, options ) : objects;155 var ratio = false;156 // RESCALE ONLY IF IT EXCEEDS THE CANVAS157 if ( group.height > _this.setup.fabric.height || group.width > _this.setup.fabric.width ) {158 ratio = ( _this.setup.fabric.height / 2 ) / group.height;159 }160 if ( cfg.top > _this.setup.fabric.height ) {161 cfg.top = _this.setup.fabric.height / 2;162 }163 if ( cfg.left > _this.setup.fabric.width ) {164 cfg.left = _this.setup.fabric.width / 2;165 }166 group.set( {167 originX: "center",168 originY: "center",169 top: cfg.top,170 left: cfg.left,171 width: ratio ? group.width * ratio : group.width,172 height: ratio ? group.height * ratio : group.height,173 fill: _this.drawing.color174 } );175 _this.setup.fabric.add( group );176 } );177 },178 change: function( options, skipped, target ) {179 var cfg = _this.deepMerge( {}, options || {} );180 var state, i1, rgba;181 var current = target || _this.drawing.buffer.target;182 var objects = current ? current._objects ? current._objects : [ current ] : null;183 // UPDATE DRAWING OBJECT184 if ( cfg.mode ) {185 _this.drawing.mode = cfg.mode;186 }187 if ( cfg.width ) {188 _this.drawing.width = cfg.width;189 _this.drawing.fontSize = cfg.width * 3;190 }191 if ( cfg.fontSize ) {192 _this.drawing.fontSize = cfg.fontSize;193 }194 if ( cfg.color ) {195 _this.drawing.color = cfg.color;196 }197 if ( cfg.opacity ) {198 _this.drawing.opacity = cfg.opacity;199 }200 // APPLY OPACITY ON CURRENT COLOR201 rgba = new fabric.Color( _this.drawing.color ).getSource();202 rgba.pop();203 rgba.push( _this.drawing.opacity );204 _this.drawing.color = "rgba(" + rgba.join() + ")";205 _this.setup.fabric.freeDrawingBrush.color = _this.drawing.color;206 _this.setup.fabric.freeDrawingBrush.width = _this.drawing.width;207 // UPDATE CURRENT SELECTION208 if ( current ) {209 state = JSON.parse( current.recentState ).cfg;210 // UPDATE GIVE OPTIONS ONLY211 if ( state ) {212 cfg.color = cfg.color || state.color;213 cfg.width = cfg.width || state.width;214 cfg.opacity = cfg.opacity || state.opacity;215 cfg.fontSize = cfg.fontSize || cfg.width * 3;216 rgba = new fabric.Color( cfg.color ).getSource();217 rgba.pop();218 rgba.push( cfg.opacity );219 cfg.color = "rgba(" + rgba.join() + ")";220 }221 // UPDATE OBJECTS222 for ( i1 = 0; i1 < objects.length; i1++ ) {223 if (224 objects[ i1 ] instanceof fabric.Text ||225 objects[ i1 ] instanceof fabric.PathGroup ||226 objects[ i1 ] instanceof fabric.Triangle227 ) {228 if ( cfg.color || cfg.opacity ) {229 objects[ i1 ].set( {230 fill: cfg.color231 } );232 }233 if ( cfg.fontSize ) {234 objects[ i1 ].set( {235 fontSize: cfg.fontSize236 } );237 }238 } else if (239 objects[ i1 ] instanceof fabric.Path ||240 objects[ i1 ] instanceof fabric.Line241 ) {242 if ( current instanceof fabric.Group ) {243 if ( cfg.color || cfg.opacity ) {244 objects[ i1 ].set( {245 stroke: cfg.color246 } );247 }248 } else {249 if ( cfg.color || cfg.opacity ) {250 objects[ i1 ].set( {251 stroke: cfg.color252 } );253 }254 if ( cfg.width ) {255 objects[ i1 ].set( {256 strokeWidth: cfg.width257 } );258 }259 }260 }261 }262 // ADD UNDO263 if ( !skipped ) {264 state = JSON.stringify( _this.deepMerge( current.saveState().originalState, {265 cfg: {266 color: cfg.color,267 width: cfg.width,268 opacity: cfg.opacity269 }270 } ) );271 current.recentState = state;272 _this.drawing.redos = [];273 _this.drawing.undos.push( {274 action: "modified",275 target: current,276 state: state277 } );278 }279 _this.setup.fabric.renderAll();280 }281 },282 text: function( options ) {283 var cfg = _this.deepMerge( {284 text: _this.i18l( "menu.label.draw.text" ),285 top: _this.setup.fabric.height / 2,286 left: _this.setup.fabric.width / 2,287 fontSize: _this.drawing.fontSize,288 fontFamily: _this.setup.chart.fontFamily || "Verdana",289 fill: _this.drawing.color290 }, options || {} );291 cfg.click = function() {};292 var text = new fabric.IText( cfg.text, cfg );293 _this.setup.fabric.add( text );294 _this.setup.fabric.setActiveObject( text );295 text.selectAll();296 text.enterEditing();297 return text;298 },299 line: function( options ) {300 var cfg = _this.deepMerge( {301 x1: ( _this.setup.fabric.width / 2 ) - ( _this.setup.fabric.width / 10 ),302 x2: ( _this.setup.fabric.width / 2 ) + ( _this.setup.fabric.width / 10 ),303 y1: ( _this.setup.fabric.height / 2 ),304 y2: ( _this.setup.fabric.height / 2 ),305 angle: 90,306 strokeLineCap: _this.drawing.lineCap,307 arrow: _this.drawing.arrow,308 color: _this.drawing.color,309 width: _this.drawing.width,310 group: [],311 }, options || {} );312 var i1, arrow, arrowTop, arrowLeft;313 var line = new fabric.Line( [ cfg.x1, cfg.y1, cfg.x2, cfg.y2 ], {314 stroke: cfg.color,315 strokeWidth: cfg.width,316 strokeLineCap: cfg.strokeLineCap317 } );318 cfg.group.push( line );319 if ( cfg.arrow ) {320 cfg.angle = cfg.angle ? cfg.angle : _this.getAngle( cfg.x1, cfg.y1, cfg.x2, cfg.y2 );321 if ( cfg.arrow == "start" ) {322 arrowTop = cfg.y1 + ( cfg.width / 2 );323 arrowLeft = cfg.x1 + ( cfg.width / 2 );324 } else if ( cfg.arrow == "middle" ) {325 arrowTop = cfg.y2 + ( cfg.width / 2 ) - ( ( cfg.y2 - cfg.y1 ) / 2 );326 arrowLeft = cfg.x2 + ( cfg.width / 2 ) - ( ( cfg.x2 - cfg.x1 ) / 2 );327 } else { // arrow: end328 arrowTop = cfg.y2 + ( cfg.width / 2 );329 arrowLeft = cfg.x2 + ( cfg.width / 2 );330 }331 arrow = new fabric.Triangle( {332 top: arrowTop,333 left: arrowLeft,334 fill: cfg.color,335 height: cfg.width * 7,336 width: cfg.width * 7,337 angle: cfg.angle,338 originX: "center",339 originY: "bottom"340 } );341 cfg.group.push( arrow );342 }343 if ( cfg.action != "config" ) {344 if ( cfg.arrow ) {345 var group = new fabric.Group( cfg.group );346 group.set( {347 cfg: cfg,348 fill: cfg.color,349 action: cfg.action,350 selectable: true,351 known: cfg.action == "change"352 } );353 if ( cfg.action == "change" ) {354 _this.setup.fabric.setActiveObject( group );355 }356 _this.setup.fabric.add( group );357 return group;358 } else {359 _this.setup.fabric.add( line );360 return line;361 }362 } else {363 for ( i1 = 0; i1 < cfg.group.length; i1++ ) {364 cfg.group[ i1 ].noUndo = true;365 _this.setup.fabric.add( cfg.group[ i1 ] );366 }367 }368 return cfg;369 }370 }371 },372 defaults: {373 position: "top-right",374 fileName: "amCharts",375 action: "download",376 path: ( ( chart.path || "" ) + "plugins/export/" ),377 formats: {378 JPG: {379 mimeType: "image/jpg",380 extension: "jpg",381 capture: true382 },383 PNG: {384 mimeType: "image/png",385 extension: "png",386 capture: true387 },388 SVG: {389 mimeType: "text/xml",390 extension: "svg",391 capture: true392 },393 PDF: {394 mimeType: "application/pdf",395 extension: "pdf",396 capture: true397 },398 CSV: {399 mimeType: "text/plain",400 extension: "csv"401 },402 JSON: {403 mimeType: "text/plain",404 extension: "json"405 },406 XLSX: {407 mimeType: "application/octet-stream",408 extension: "xlsx"409 }410 },411 fabric: {412 backgroundColor: "#FFFFFF",413 removeImages: true,414 selection: false,415 drawing: {416 enabled: true,417 arrow: "end",418 lineCap: "butt",419 mode: "pencil",420 modes: [ "pencil", "line", "arrow" ],421 color: "#000000",422 colors: [ "#000000", "#FFFFFF", "#FF0000", "#00FF00", "#0000FF" ],423 shapes: [ "11.svg", "14.svg", "16.svg", "17.svg", "20.svg", "27.svg" ],424 width: 1,425 fontSize: 11,426 widths: [ 1, 5, 10, 15 ],427 opacity: 1,428 opacities: [ 1, 0.8, 0.6, 0.4, 0.2 ],429 menu: undefined,430 autoClose: true431 }432 },433 pdfMake: {434 pageSize: "A4",435 pageOrientation: "portrait",436 images: {},437 content: [ "Saved from:", window.location.href, {438 image: "reference",439 fit: [ 523.28, 769.89 ]440 } ]441 },442 menu: undefined,443 divId: null,444 menuReviver: null,445 menuWalker: null,446 fallback: true,447 keyListener: true,448 fileListener: true449 },450 /**451 * Returns translated message, takes english as default452 */453 i18l: function( key, language ) {454 var lang = language ? langugage : _this.setup.chart.language ? _this.setup.chart.language : "en";455 var catalog = AmCharts.translations[ _this.name ][ lang ] || AmCharts.translations[ _this.name ][ "en" ];456 return catalog[ key ] || key;457 },458 /**459 * Generates download file; if unsupported offers fallback to save manually460 */461 download: function( data, type, filename ) {462 // SAVE463 if ( window.saveAs && _this.setup.hasBlob ) {464 var blob = _this.toBlob( {465 data: data,466 type: type467 }, function( data ) {468 saveAs( data, filename );469 } );470 // FALLBACK TEXTAREA471 } else if ( _this.config.fallback && type == "text/plain" ) {472 var div = document.createElement( "div" );473 var msg = document.createElement( "div" );474 var textarea = document.createElement( "textarea" );475 msg.innerHTML = _this.i18l( "fallback.save.text" );476 div.appendChild( msg );477 div.appendChild( textarea );478 msg.setAttribute( "class", "amcharts-export-fallback-message" );479 div.setAttribute( "class", "amcharts-export-fallback" );480 _this.setup.chart.containerDiv.appendChild( div );481 // FULFILL TEXTAREA AND PRESELECT482 textarea.setAttribute( "readonly", "" );483 textarea.value = data;484 textarea.focus();485 textarea.select();486 // UPDATE MENU487 _this.createMenu( [ {488 "class": "export-main export-close",489 label: "Done",490 click: function() {491 _this.createMenu( _this.config.menu );492 _this.setup.chart.containerDiv.removeChild( div );493 }494 } ] );495 // FALLBACK IMAGE496 } else if ( _this.config.fallback && type.split( "/" )[ 0 ] == "image" ) {497 var div = document.createElement( "div" );498 var msg = document.createElement( "div" );499 var img = _this.toImage( {500 data: data501 } );502 msg.innerHTML = _this.i18l( "fallback.save.image" );503 // FULFILL TEXTAREA AND PRESELECT504 div.appendChild( msg );505 div.appendChild( img );506 msg.setAttribute( "class", "amcharts-export-fallback-message" );507 div.setAttribute( "class", "amcharts-export-fallback" );508 _this.setup.chart.containerDiv.appendChild( div );509 // UPDATE MENU510 _this.createMenu( [ {511 "class": "export-main export-close",512 label: "Done",513 click: function() {514 _this.createMenu( _this.config.menu );515 _this.setup.chart.containerDiv.removeChild( div );516 }517 } ] );518 // ERROR519 } else {520 throw new Error( "Unable to create file. Ensure saveAs (FileSaver.js) is supported." );521 }522 return data;523 },524 /**525 * Generates script, links tags and places them into the document's head526 * In case of reload it replaces the node to force the download527 */528 loadResource: function( src, addons ) {529 var i1, exist, node, item, check, type;530 var url = src.indexOf( "//" ) != -1 ? src : [ _this.libs.path, src ].join( "" );531 function callback() {532 if ( addons ) {533 for ( i1 = 0; i1 < addons.length; i1++ ) {534 _this.loadResource( addons[ i1 ] );535 }536 }537 }538 if ( src.indexOf( ".js" ) != -1 ) {539 node = document.createElement( "script" );540 node.setAttribute( "type", "text/javascript" );541 node.setAttribute( "src", url );542 if ( _this.libs.async ) {543 node.setAttribute( "async", "" );544 }545 } else if ( src.indexOf( ".css" ) != -1 ) {546 node = document.createElement( "link" );547 node.setAttribute( "type", "text/css" );548 node.setAttribute( "rel", "stylesheet" );549 node.setAttribute( "href", url );550 }551 for ( i1 = 0; i1 < document.head.childNodes.length; i1++ ) {552 item = document.head.childNodes[ i1 ];553 check = item ? ( item.src || item.href ) : false;554 type = item ? item.tagName : false;555 if ( item && check && check.indexOf( src ) != -1 ) {556 if ( _this.libs.reload ) {557 document.head.removeChild( item );558 }559 exist = true;560 break;561 }562 }563 if ( !exist || _this.libs.reload ) {564 node.addEventListener( "load", callback );565 document.head.appendChild( node );566 }567 },568 /**569 * Walker to generate the script,link tags570 */571 loadDependencies: function() {572 var i1, i2;573 if ( _this.libs.autoLoad ) {574 for ( i1 = 0; i1 < _this.libs.resources.length; i1++ ) {575 if ( _this.libs.resources[ i1 ] instanceof Object ) {576 for ( i2 in _this.libs.resources[ i1 ] ) {577 _this.loadResource( i2, _this.libs.resources[ i1 ][ i2 ] );578 }579 } else {580 _this.loadResource( _this.libs.resources[ i1 ] );581 }582 }583 }584 },585 /**586 * Converts string to number587 */588 pxToNumber: function( attr ) {589 return Number( String( attr ).replace( "px", "" ) ) || 0;590 },591 /**592 * Converts number to string593 */594 numberToPx: function( attr ) {595 return String( attr ) + "px";596 },597 /**598 * Recursive method to merge the given objects together599 * Overwrite flag replaces the value instead to crawl through600 */601 deepMerge: function( a, b, overwrite ) {602 var i1, v, type = b instanceof Array ? "array" : "object";603 for ( i1 in b ) {604 // PREVENT METHODS605 if ( type == "array" && isNaN( i1 ) ) {606 continue;607 }608 v = b[ i1 ];609 // NEW610 if ( a[ i1 ] == undefined || overwrite ) {611 if ( v instanceof Array ) {612 a[ i1 ] = new Array();613 } else if ( v instanceof Function ) {614 a[ i1 ] = new Function();615 } else if ( v instanceof Date ) {616 a[ i1 ] = new Date();617 } else if ( v instanceof Object ) {618 a[ i1 ] = new Object();619 } else if ( v instanceof Number ) {620 a[ i1 ] = new Number();621 } else if ( v instanceof String ) {622 a[ i1 ] = new String();623 }624 }625 if (626 ( a instanceof Object || a instanceof Array ) &&627 ( v instanceof Object || v instanceof Array ) &&628 !( v instanceof Function || v instanceof Date || _this.isElement( v ) ) &&629 i1 != "chart"630 ) {631 _this.deepMerge( a[ i1 ], v, overwrite );632 } else {633 if ( a instanceof Array && !overwrite ) {634 a.push( v );635 } else {636 a[ i1 ] = v;637 }638 }639 }640 return a;641 },642 /**643 * Checks if given argument is a valid node644 */645 isElement: function( thingy ) {646 return thingy instanceof Object && thingy && thingy.nodeType === 1;647 },648 /**649 * Checks if given event has been thrown with pressed click / touch650 */651 isPressed: function( event ) {652 // IE EXCEPTION653 if ( event.type == "mousemove" && event.which === 1 ) {654 // IGNORE655 // OTHERS656 } else if (657 event.type == "touchmove" ||658 event.buttons === 1 ||659 event.button === 1 ||660 event.which === 1661 ) {662 _this.drawing.buffer.isPressed = true;663 } else {664 _this.drawing.buffer.isPressed = false;665 }666 return _this.drawing.buffer.isPressed;667 },668 /**669 * Checks if given source is within the current origin670 */671 isTainted: function( source ) {672 var origin = String( window.location.origin || window.location.protocol + "//" + window.location.hostname + ( window.location.port ? ':' + window.location.port : '' ) );673 // CHECK IF TAINTED674 if (675 source &&676 source.indexOf( "//" ) != -1 &&677 source.indexOf( origin.replace( /.*:/, "" ) ) == -1678 ) {679 return true;680 }681 return false;682 },683 /*684 ** Checks several indicators for acceptance;685 */686 isSupported: function() {687 // CHECK CONFIG688 if ( !_this.config.enabled ) {689 return false;690 }691 // CHECK IE; ATTEMPT TO ACCESS HEAD ELEMENT692 if ( AmCharts.isIE && AmCharts.IEversion <= 9 ) {693 if ( !Array.prototype.indexOf || !document.head || _this.config.fallback === false ) {694 return false;695 }696 }697 return true;698 },699 getAngle: function( x1, y1, x2, y2 ) {700 var x = x2 - x1;701 var y = y2 - y1;702 var angle;703 if ( x == 0 ) {704 if ( y == 0 ) {705 angle = 0;706 } else if ( y > 0 ) {707 angle = Math.PI / 2;708 } else {709 angle = Math.PI * 3 / 2;710 }711 } else if ( y == 0 ) {712 if ( x > 0 ) {713 angle = 0;714 } else {715 angle = Math.PI;716 }717 } else {718 if ( x < 0 ) {719 angle = Math.atan( y / x ) + Math.PI;720 } else if ( y < 0 ) {721 angle = Math.atan( y / x ) + ( 2 * Math.PI );722 } else {723 angle = Math.atan( y / x );724 }725 }726 return angle * 180 / Math.PI;727 },728 /**729 * Recursive method which crawls upwards to gather the requested attribute730 */731 gatherAttribute: function( elm, attr, limit, lvl ) {732 var value, lvl = lvl ? lvl : 0,733 limit = limit ? limit : 3;734 if ( elm ) {735 value = elm.getAttribute( attr );736 if ( !value && lvl < limit ) {737 return _this.gatherAttribute( elm.parentNode, attr, limit, lvl + 1 );738 }739 }740 return value;741 },742 /**743 * Recursive method which crawls upwards to gather the requested classname744 */745 gatherClassName: function( elm, className, limit, lvl ) {746 var value, lvl = lvl ? lvl : 0,747 limit = limit ? limit : 3;748 if ( _this.isElement(elm) ) {749 value = ( elm.getAttribute( "class" ) || "" ).split( " " ).indexOf( className ) != -1;750 if ( !value && lvl < limit ) {751 return _this.gatherClassName( elm.parentNode, className, limit, lvl + 1 );752 } else if ( value ) {753 value = elm;754 }755 }756 return value;757 },758 /**759 * Collects the clip-paths and patterns760 */761 gatherElements: function( group, cfg, images ) {762 var i1, i2;763 for ( i1 = 0; i1 < group.children.length; i1++ ) {764 var childNode = group.children[ i1 ];765 // CLIPPATH766 if ( childNode.tagName == "clipPath" ) {767 for ( i2 = 0; i2 < childNode.childNodes.length; i2++ ) {768 childNode.childNodes[ i2 ].setAttribute( "fill", "transparent" );769 }770 group.clippings[ childNode.id ] = childNode;771 // PATTERN772 } else if ( childNode.tagName == "pattern" ) {773 var props = {774 node: childNode,775 source: childNode.getAttribute( "xlink:href" ),776 width: Number( childNode.getAttribute( "width" ) ),777 height: Number( childNode.getAttribute( "height" ) ),778 repeat: "repeat"779 }780 // GATHER BACKGROUND COLOR781 for ( i2 = 0; i2 < childNode.childNodes.length; i2++ ) {782 if ( childNode.childNodes[ i2 ].tagName == "rect" ) {783 props.fill = childNode.childNodes[ i2 ].getAttribute( "fill" );784 }785 }786 // TAINTED787 if ( cfg.removeImages && _this.isTainted( props.source ) ) {788 group.patterns[ childNode.id ] = props.fill ? props.fill : "transparent";789 } else {790 images.included++;791 // LOAD IMAGE MANUALLY; TO RERENDER THE CANVAS792 fabric.Image.fromURL( props.source, ( function( props ) {793 return function( img ) {794 images.loaded++;795 var patternSourceCanvas = new fabric.StaticCanvas( undefined, {796 backgroundColor: props.fill797 } );798 patternSourceCanvas.add( img );799 var pattern = new fabric.Pattern( {800 source: function() {801 patternSourceCanvas.setDimensions( {802 width: props.width,803 height: props.height804 } );805 return patternSourceCanvas.getElement();806 },807 repeat: 'repeat'808 } );809 group.patterns[ props.node.id ] = pattern;810 }811 } )( props ) );812 }813 // IMAGES814 } else if ( childNode.tagName == "image" ) {815 images.included++;816 // LOAD IMAGE MANUALLY; TO RERENDER THE CANVAS817 fabric.Image.fromURL( childNode.getAttribute( "xlink:href" ), function( img ) {818 images.loaded++;819 } );820 }821 }822 return group;823 },824 /*825 ** GATHER MOUSE POSITION;826 */827 gatherPosition: function( event, type ) {828 var ref = _this.drawing.buffer.position;829 var ivt = fabric.util.invertTransform( _this.setup.fabric.viewportTransform );830 var pos;831 if ( event.type == "touchmove" ) {832 if ( "touches" in event ) {833 event = event.touches[ 0 ];834 } else if ( "changedTouches" in event ) {835 event = event.changedTouches[ 0 ];836 }837 }838 pos = fabric.util.transformPoint( _this.setup.fabric.getPointer( event, true ), ivt );839 if ( type == 1 ) {840 ref.x1 = pos.x;841 ref.y1 = pos.y;842 }843 ref.x2 = pos.x;844 ref.y2 = pos.y;845 ref.xD = ( ref.x1 - ref.x2 ) < 0 ? ( ref.x1 - ref.x2 ) * -1 : ( ref.x1 - ref.x2 );846 ref.yD = ( ref.y1 - ref.y2 ) < 0 ? ( ref.y1 - ref.y2 ) * -1 : ( ref.y1 - ref.y2 );847 return ref;848 },849 /**850 * Method to capture the current state of the chart851 */852 capture: function( options, callback ) {853 var i1;854 var cfg = _this.deepMerge( _this.deepMerge( {}, _this.config.fabric ), options || {} );855 var groups = [];856 var offset = {857 x: 0,858 y: 0,859 pX: 0,860 pY: 0,861 width: _this.setup.chart.divRealWidth,862 height: _this.setup.chart.divRealHeight863 };864 var images = {865 loaded: 0,866 included: 0867 }868 // GATHER SVGS869 var svgs = _this.setup.chart.containerDiv.getElementsByTagName( "svg" );870 for ( i1 = 0; i1 < svgs.length; i1++ ) {871 var group = {872 svg: svgs[ i1 ],873 parent: svgs[ i1 ].parentNode,874 children: svgs[ i1 ].getElementsByTagName( "*" ),875 offset: {876 x: 0,877 y: 0878 },879 patterns: {},880 clippings: {}881 }882 // GATHER ELEMENTS883 group = _this.gatherElements( group, cfg, images );884 // APPEND GROUP885 groups.push( group );886 }887 // GATHER EXTERNAL LEGEND888 if ( _this.config.legend && _this.setup.chart.legend && _this.setup.chart.legend.position == "outside" ) {889 var group = {890 svg: _this.setup.chart.legend.container.container,891 parent: _this.setup.chart.legend.container.container.parentNode,892 children: _this.setup.chart.legend.container.container.getElementsByTagName( "*" ),893 offset: {894 x: 0,895 y: 0896 },897 legend: {898 type: [ "top", "left" ].indexOf( _this.config.legend.position ) != -1 ? "unshift" : "push",899 position: _this.config.legend.position,900 width: _this.config.legend.width ? _this.config.legend.width : _this.setup.chart.legend.container.width,901 height: _this.config.legend.height ? _this.config.legend.height : _this.setup.chart.legend.container.height902 },903 patterns: {},904 clippings: {}905 }906 // ADAPT CANVAS DIMENSIONS907 if ( [ "left", "right" ].indexOf( group.legend.position ) != -1 ) {908 offset.width += group.legend.width;909 offset.height = group.legend.height > offset.height ? group.legend.height : offset.height;910 } else if ( [ "top", "bottom" ].indexOf( group.legend.position ) != -1 ) {911 offset.height += group.legend.height;912 }913 // GATHER ELEMENTS914 group = _this.gatherElements( group, cfg, images );915 // PRE/APPEND SVG916 groups[ group.legend.type ]( group );917 }918 // CLEAR IF EXIST919 _this.drawing.buffer.enabled = cfg.action == "draw";920 if ( !_this.setup.wrapper ) {921 _this.setup.wrapper = document.createElement( "div" );922 _this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas" );923 _this.setup.chart.containerDiv.appendChild( _this.setup.wrapper );924 } else {925 _this.setup.wrapper.innerHTML = "";926 }927 // STOCK CHART; SELECTOR OFFSET928 if ( _this.setup.chart.type == "stock" ) {929 var padding = {930 top: 0,931 right: 0,932 bottom: 0,933 left: 0934 }935 if ( _this.setup.chart.leftContainer ) {936 offset.width -= _this.setup.chart.leftContainer.offsetWidth;937 padding.left = _this.setup.chart.leftContainer.offsetWidth + ( _this.setup.chart.panelsSettings.panelSpacing * 2 );938 }939 if ( _this.setup.chart.rightContainer ) {940 offset.width -= _this.setup.chart.rightContainer.offsetWidth;941 padding.right = _this.setup.chart.rightContainer.offsetWidth + ( _this.setup.chart.panelsSettings.panelSpacing * 2 );942 }943 if ( _this.setup.chart.periodSelector && [ "top", "bottom" ].indexOf( _this.setup.chart.periodSelector.position ) != -1 ) {944 offset.height -= _this.setup.chart.periodSelector.offsetHeight + _this.setup.chart.panelsSettings.panelSpacing;945 padding[ _this.setup.chart.periodSelector.position ] += _this.setup.chart.periodSelector.offsetHeight + _this.setup.chart.panelsSettings.panelSpacing;946 }947 if ( _this.setup.chart.dataSetSelector && [ "top", "bottom" ].indexOf( _this.setup.chart.dataSetSelector.position ) != -1 ) {948 offset.height -= _this.setup.chart.dataSetSelector.offsetHeight;949 padding[ _this.setup.chart.dataSetSelector.position ] += _this.setup.chart.dataSetSelector.offsetHeight;950 }951 // APPLY OFFSET ON WRAPPER952 _this.setup.wrapper.style.paddingTop = _this.numberToPx( padding.top );953 _this.setup.wrapper.style.paddingRight = _this.numberToPx( padding.right );954 _this.setup.wrapper.style.paddingBottom = _this.numberToPx( padding.bottom );955 _this.setup.wrapper.style.paddingLeft = _this.numberToPx( padding.left );956 }957 // CREATE CANVAS958 _this.setup.canvas = document.createElement( "canvas" );959 _this.setup.wrapper.appendChild( _this.setup.canvas );960 _this.setup.fabric = new fabric.Canvas( _this.setup.canvas, _this.deepMerge( {961 width: offset.width,962 height: offset.height,963 isDrawingMode: true964 }, cfg ) );965 // REAPPLY FOR SOME REASON966 _this.deepMerge( _this.setup.fabric, cfg );967 _this.deepMerge( _this.setup.fabric.freeDrawingBrush, cfg.drawing );968 // RELIABLE VARIABLES; UPDATE DRAWING969 _this.deepMerge( _this.drawing, cfg.drawing );970 _this.drawing.handler.change( cfg.drawing );971 // OBSERVE MOUSE EVENTS972 _this.setup.fabric.on( "mouse:down", function( e ) {973 var p = _this.gatherPosition( e.e, 1 );974 _this.drawing.buffer.pressedTS = Number( new Date() );975 _this.isPressed( e.e );976 } );977 _this.setup.fabric.on( "mouse:move", function( e ) {978 var p = _this.gatherPosition( e.e, 2 );979 _this.isPressed( e.e );980 // CREATE INITIAL LINE / ARROW; JUST ON LEFT CLICK981 if ( _this.drawing.buffer.isPressed && !_this.drawing.buffer.line ) {982 if ( !_this.drawing.buffer.isSelected && _this.drawing.mode != "pencil" && ( p.xD > 5 || p.xD > 5 ) ) {983 _this.drawing.buffer.hasLine = true;984 _this.setup.fabric.isDrawingMode = false;985 _this.setup.fabric._onMouseUpInDrawingMode( e );986 _this.drawing.buffer.line = _this.drawing.handler.line( {987 x1: p.x1,988 y1: p.y1,989 x2: p.x2,990 y2: p.y2,991 arrow: _this.drawing.mode == "line" ? false : _this.drawing.arrow,992 action: "config"993 } );994 }995 }996 // UPDATE LINE / ARROW997 if ( _this.drawing.buffer.line ) {998 var obj, top, left;999 var l = _this.drawing.buffer.line;1000 l.x2 = p.x2;1001 l.y2 = p.y2;1002 for ( i1 = 0; i1 < l.group.length; i1++ ) {1003 obj = l.group[ i1 ];1004 if ( obj instanceof fabric.Line ) {1005 obj.set( {1006 x2: l.x2,1007 y2: l.y21008 } );1009 } else if ( obj instanceof fabric.Triangle ) {1010 l.angle = ( _this.getAngle( l.x1, l.y1, l.x2, l.y2 ) + 90 );1011 if ( l.arrow == "start" ) {1012 top = l.y1 + ( l.width / 2 );1013 left = l.x1 + ( l.width / 2 );1014 } else if ( l.arrow == "middle" ) {1015 top = l.y2 + ( l.width / 2 ) - ( ( l.y2 - l.y1 ) / 2 );1016 left = l.x2 + ( l.width / 2 ) - ( ( l.x2 - l.x1 ) / 2 );1017 } else { // arrow: end1018 top = l.y2 + ( l.width / 2 );1019 left = l.x2 + ( l.width / 2 );1020 }1021 obj.set( {1022 top: top,1023 left: left,1024 angle: l.angle1025 } );1026 }1027 }1028 _this.setup.fabric.renderAll();1029 }1030 } );1031 _this.setup.fabric.on( "mouse:up", function( e ) {1032 // SELECT TARGET1033 if ( Number( new Date() ) - _this.drawing.buffer.pressedTS < 200 ) {1034 var target = _this.setup.fabric.findTarget( e.e );1035 if ( target && target.selectable ) {1036 _this.setup.fabric.setActiveObject( target );1037 }1038 }1039 // UPDATE LINE / ARROW1040 if ( _this.drawing.buffer.line ) {1041 for ( i1 = 0; i1 < _this.drawing.buffer.line.group.length; i1++ ) {1042 _this.drawing.buffer.line.group[ i1 ].remove();1043 }1044 delete _this.drawing.buffer.line.action;1045 delete _this.drawing.buffer.line.group;1046 _this.drawing.handler.line( _this.drawing.buffer.line );1047 }1048 _this.drawing.buffer.line = false;1049 _this.drawing.buffer.hasLine = false;1050 _this.drawing.buffer.isPressed = false;1051 } );1052 // OBSERVE OBJECT SELECTION1053 _this.setup.fabric.on( "object:selected", function( e ) {1054 _this.drawing.buffer.isSelected = true;1055 _this.drawing.buffer.target = e.target;1056 _this.setup.fabric.isDrawingMode = false;1057 } );1058 _this.setup.fabric.on( "selection:cleared", function( e ) {1059 _this.drawing.buffer.onMouseDown = _this.setup.fabric.freeDrawingBrush.onMouseDown;1060 _this.drawing.buffer.target = false;1061 // FREEHAND WORKAROUND1062 if ( _this.drawing.buffer.isSelected ) {1063 _this.setup.fabric._isCurrentlyDrawing = false;1064 _this.setup.fabric.freeDrawingBrush.onMouseDown = function() {};1065 }1066 // DELAYED DESELECTION TO PREVENT DRAWING1067 setTimeout( function() {1068 _this.drawing.buffer.isSelected = false;1069 _this.setup.fabric.isDrawingMode = true;1070 _this.setup.fabric.freeDrawingBrush.onMouseDown = _this.drawing.buffer.onMouseDown;1071 }, 10 );1072 } );1073 _this.setup.fabric.on( "path:created", function( e ) {1074 var item = e.path;1075 if ( Number( new Date() ) - _this.drawing.buffer.pressedTS < 200 || _this.drawing.buffer.hasLine ) {1076 _this.setup.fabric.remove( item );1077 _this.setup.fabric.renderAll();1078 return;1079 }1080 } );1081 // OBSERVE OBJECT MODIFICATIONS1082 _this.setup.fabric.on( "object:added", function( e ) {1083 var item = e.target;1084 var state = _this.deepMerge( item.saveState().originalState, {1085 cfg: {1086 color: _this.drawing.color,1087 width: _this.drawing.width,1088 opacity: _this.drawing.opacity,1089 fontSize: _this.drawing.fontSize1090 }1091 } );1092 if ( Number( new Date() ) - _this.drawing.buffer.pressedTS < 200 && !item.noUndo ) {1093 _this.setup.fabric.remove( item );1094 _this.setup.fabric.renderAll();1095 return;1096 }1097 state = JSON.stringify( state );1098 item.recentState = state;1099 if ( item.selectable && !item.known && !item.noUndo ) {1100 _this.drawing.undos.push( {1101 action: "added",1102 target: item,1103 state: state1104 } );1105 _this.drawing.undos.push( {1106 action: "addified",1107 target: item,1108 state: state1109 } );1110 _this.drawing.redos = [];1111 }1112 item.known = true;1113 _this.setup.fabric.isDrawingMode = true;1114 } );1115 _this.setup.fabric.on( "object:modified", function( e ) {1116 var item = e.target;1117 var recentState = JSON.parse( item.recentState );1118 var state = _this.deepMerge( item.saveState().originalState, {1119 cfg: recentState.cfg1120 } );1121 state = JSON.stringify( state );1122 item.recentState = state;1123 _this.drawing.undos.push( {1124 action: "modified",1125 target: item,1126 state: state1127 } );1128 _this.drawing.redos = [];1129 } );1130 _this.setup.fabric.on( "text:changed", function( e ) {1131 var item = e.target;1132 clearTimeout( item.timer );1133 item.timer = setTimeout( function() {1134 var state = JSON.stringify( item.saveState().originalState );1135 item.recentState = state;1136 _this.drawing.redos = [];1137 _this.drawing.undos.push( {1138 action: "modified",1139 target: item,1140 state: state1141 } );1142 }, 250 );1143 } );1144 // DRAWING1145 if ( _this.drawing.buffer.enabled ) {1146 _this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas active" );1147 _this.setup.wrapper.style.backgroundColor = cfg.backgroundColor;1148 _this.setup.wrapper.style.display = "block";1149 } else {1150 _this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas" );1151 _this.setup.wrapper.style.display = "none";1152 }1153 for ( i1 = 0; i1 < groups.length; i1++ ) {1154 var group = groups[ i1 ];1155 var isLegend = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + "-legend-div", 1 );1156 var isPanel = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + "-stock-panel-div" );1157 var isScrollbar = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + "-scrollbar-chart-div" );1158 // STOCK CHART; SVG OFFSET;; SVG OFFSET1159 if ( _this.setup.chart.type == "stock" && _this.setup.chart.legendSettings.position ) {1160 // TOP / BOTTOM1161 if ( [ "top", "bottom" ].indexOf( _this.setup.chart.legendSettings.position ) != -1 ) {1162 // POSITION; ABSOLUTE1163 if ( group.parent.style.top && group.parent.style.left ) {1164 group.offset.y = _this.pxToNumber( group.parent.style.top );1165 group.offset.x = _this.pxToNumber( group.parent.style.left );1166 // POSITION; RELATIVE1167 } else {1168 group.offset.x = offset.x;1169 group.offset.y = offset.y;1170 offset.y += _this.pxToNumber( group.parent.style.height );1171 // LEGEND; OFFSET1172 if ( isPanel ) {1173 offset.pY = _this.pxToNumber( isPanel.style.marginTop );1174 group.offset.y += offset.pY;1175 // SCROLLBAR; OFFSET1176 } else if ( isScrollbar ) {1177 group.offset.y += offset.pY;1178 }1179 }1180 // LEFT / RIGHT1181 } else if ( [ "left", "right" ].indexOf( _this.setup.chart.legendSettings.position ) != -1 ) {1182 group.offset.y = _this.pxToNumber( group.parent.style.top ) + offset.pY;1183 group.offset.x = _this.pxToNumber( group.parent.style.left ) + offset.pX;1184 // LEGEND; OFFSET1185 if ( isLegend ) {1186 offset.pY += _this.pxToNumber( isPanel.style.height ) + _this.setup.chart.panelsSettings.panelSpacing;1187 // SCROLLBAR; OFFSET1188 } else if ( isScrollbar ) {1189 group.offset.y -= _this.setup.chart.panelsSettings.panelSpacing;1190 }1191 }1192 // REGULAR CHARTS; SVG OFFSET1193 } else {1194 // POSITION; ABSOLUTE1195 if ( group.parent.style.top && group.parent.style.left ) {1196 group.offset.y = _this.pxToNumber( group.parent.style.top );1197 group.offset.x = _this.pxToNumber( group.parent.style.left );1198 // POSITION; RELATIVE1199 } else {1200 // EXTERNAL LEGEND1201 if ( group.legend ) {1202 if ( group.legend.position == "left" ) {1203 offset.x += group.legend.width;1204 } else if ( group.legend.position == "right" ) {1205 group.offset.x += offset.width - group.legend.width;1206 } else if ( group.legend.position == "top" ) {1207 offset.y += group.legend.height;1208 } else if ( group.legend.position == "bottom" ) {1209 group.offset.y += offset.height - group.legend.height; // OFFSET.Y1210 }1211 // NORMAL1212 } else {1213 group.offset.x = offset.x;1214 group.offset.y = offset.y + offset.pY;1215 offset.y += _this.pxToNumber( group.parent.style.height );1216 }1217 }1218 // PANEL1219 if ( isLegend && isPanel && isPanel.style.marginTop ) {1220 offset.y += _this.pxToNumber( isPanel.style.marginTop );1221 group.offset.y += _this.pxToNumber( isPanel.style.marginTop );1222 }1223 }1224 // BEFORE CAPTURING1225 _this.handleCallback( cfg.beforeCapture, cfg );1226 // ADD TO CANVAS1227 fabric.parseSVGDocument( group.svg, ( function( group ) {1228 return function( objects, options ) {1229 var i1;1230 var g = fabric.util.groupSVGElements( objects, options );1231 var tmp = {1232 top: group.offset.y,1233 left: group.offset.x,1234 selectable: false1235 };1236 for ( i1 = 0; i1 < g.paths.length; i1++ ) {1237 // OPACITY; TODO: DISTINGUISH OPACITY TYPES1238 if ( g.paths[ i1 ] ) {1239 // CHECK ORIGIN; REMOVE TAINTED1240 if ( cfg.removeImages && _this.isTainted( g.paths[ i1 ][ "xlink:href" ] ) ) {1241 g.paths.splice( i1, 1 );1242 continue;1243 }1244 // SET OPACITY1245 if ( g.paths[ i1 ].fill instanceof Object ) {1246 // MISINTERPRETATION OF FABRIC1247 if ( g.paths[ i1 ].fill.type == "radial" ) {1248 g.paths[ i1 ].fill.coords.r2 = g.paths[ i1 ].fill.coords.r1 * -1;1249 g.paths[ i1 ].fill.coords.r1 = 0;1250 }1251 g.paths[ i1 ].set( {1252 opacity: g.paths[ i1 ].fillOpacity1253 } );1254 // PATTERN; TODO: DISTINGUISH OPACITY TYPES1255 } else if ( String( g.paths[ i1 ].fill ).slice( 0, 3 ) == "url" ) {1256 var PID = g.paths[ i1 ].fill.slice( 5, -1 );1257 if ( group.patterns && group.patterns[ PID ] ) {1258 g.paths[ i1 ].set( {1259 fill: group.patterns[ PID ],1260 opacity: g.paths[ i1 ].fillOpacity1261 } );1262 }1263 }1264 // CLIPPATH;1265 if ( String( g.paths[ i1 ].clipPath ).slice( 0, 3 ) == "url" ) {1266 var PID = g.paths[ i1 ].clipPath.slice( 5, -1 );1267 if ( group.clippings[ PID ] ) {1268 var mask = group.clippings[ PID ].childNodes[ 0 ];1269 var transform = g.paths[ i1 ].svg.getAttribute( "transform" ) || "translate(0,0)";1270 transform = transform.slice( 10, -1 ).split( "," );1271 g.paths[ i1 ].set( {1272 clipTo: ( function( mask, transform ) {1273 return function( ctx ) {1274 var width = Number( mask.getAttribute( "width" ) || "0" );1275 var height = Number( mask.getAttribute( "height" ) || "0" );1276 var x = Number( mask.getAttribute( "x" ) || "0" );1277 var y = Number( mask.getAttribute( "y" ) || "0" );1278 ctx.rect( Number( transform[ 0 ] ) * -1 + x, Number( transform[ 1 ] ) * -1 + y, width, height );1279 }1280 } )( mask, transform )1281 } );1282 }1283 }1284 // TODO; WAIT FOR TSPAN SUPPORT FROM FABRICJS SIDE1285 if ( g.paths[ i1 ].originalBBox ) {1286 var bb = g.paths[ i1 ].originalBBox;1287 if ( g.paths[ i1 ].textAlign == "left" ) {1288 g.paths[ i1 ].set( {1289 left: bb.left + ( g.paths[ i1 ].width / 2 )1290 } );1291 } else {1292 g.paths[ i1 ].set( {1293 left: bb.left - ( g.paths[ i1 ].width / 2 )1294 } );1295 }1296 }1297 }1298 }1299 g.set( tmp );1300 _this.setup.fabric.add( g );1301 // ADD BALLOONS1302 if ( group.svg.parentNode && group.svg.parentNode.getElementsByTagName ) {1303 var balloons = group.svg.parentNode.getElementsByClassName( _this.setup.chart.classNamePrefix + "-balloon-div" );1304 for ( i1 = 0; i1 < balloons.length; i1++ ) {1305 if ( cfg.balloonFunction instanceof Function ) {1306 cfg.balloonFunction.apply( _this, [ balloons[ i1 ], group ] );1307 } else {1308 var parent = balloons[ i1 ];1309 var text = parent.childNodes[ 0 ];1310 var label = new fabric.Text( text.innerText || text.innerHTML, {1311 fontSize: _this.pxToNumber( text.style.fontSize ),1312 fontFamily: text.style.fontFamily,1313 fill: text.style.color,1314 top: _this.pxToNumber( parent.style.top ) + group.offset.y,1315 left: _this.pxToNumber( parent.style.left ) + group.offset.x,1316 selectable: false1317 } );1318 _this.setup.fabric.add( label );1319 }1320 }1321 }1322 if ( group.svg.nextSibling && group.svg.nextSibling.tagName == "A" ) {1323 var label = new fabric.Text( group.svg.nextSibling.innerText || group.svg.nextSibling.innerHTML, {1324 fontSize: _this.pxToNumber( group.svg.nextSibling.style.fontSize ),1325 fontFamily: group.svg.nextSibling.style.fontFamily,1326 fill: group.svg.nextSibling.style.color,1327 top: _this.pxToNumber( group.svg.nextSibling.style.top ) + group.offset.y,1328 left: _this.pxToNumber( group.svg.nextSibling.style.left ) + group.offset.x,1329 selectable: false1330 } );1331 _this.setup.fabric.add( label );1332 }1333 groups.pop();1334 // TRIGGER CALLBACK WITH SAFETY DELAY1335 if ( !groups.length ) {1336 var timer = setInterval( function() {1337 if ( images.loaded == images.included ) {1338 clearTimeout( timer );1339 _this.handleCallback( cfg.afterCapture, cfg );1340 _this.setup.fabric.renderAll();1341 _this.handleCallback( callback, cfg );1342 }1343 }, AmCharts.updateRate );1344 }1345 }1346 // IDENTIFY ELEMENTS THROUGH CLASSNAMES1347 } )( group ), function( svg, obj ) {1348 var i1;1349 var className = _this.gatherAttribute( svg, "class" );1350 var visibility = _this.gatherAttribute( svg, "visibility" );1351 var clipPath = _this.gatherAttribute( svg, "clip-path", 1 );1352 obj.className = String( className );1353 obj.classList = String( className ).split( " " );1354 obj.clipPath = clipPath;1355 obj.svg = svg;1356 // TODO; WAIT FOR TSPAN SUPPORT FROM FABRICJS SIDE1357 if ( svg.tagName == "text" && svg.childNodes.length > 1 ) {1358 var lines = [];1359 var textAnchor = svg.getAttribute( "text-anchor" ) || "left";1360 var anchorMap = {1361 "start": "left",1362 "middle": "center",1363 "end": "right"1364 }1365 for ( i1 = 0; i1 < svg.childNodes.length; i1++ ) {1366 lines.push( svg.childNodes[ i1 ].textContent );1367 }1368 if ( textAnchor != "middle" ) {1369 obj.originalBBox = obj.getBoundingRect();1370 }1371 obj.set( {1372 lineHeight: 1.05,1373 top: obj.top + obj.height - ( obj.fontSize * ( 0.18 + obj._fontSizeFraction ) / 2 ),1374 text: lines.join( "\n" ),1375 textAlign: anchorMap[ textAnchor ],1376 selectable: false1377 } );1378 }1379 // HIDE HIDDEN ELEMENTS; TODO: FIND A BETTER WAY TO HANDLE THAT1380 if ( visibility == "hidden" ) {1381 obj.opacity = 0;1382 // WALKTHROUGH ELEMENTS1383 } else {1384 // TRANSPORT FILL/STROKE OPACITY1385 var attrs = [ "fill", "stroke" ];1386 for ( i1 = 0; i1 < attrs.length; i1++ ) {1387 var attr = attrs[ i1 ]1388 var attrVal = String( svg.getAttribute( attr ) || "" );1389 var attrOpacity = Number( svg.getAttribute( attr + "-opacity" ) || "1" );1390 var attrRGBA = fabric.Color.fromHex( attrVal ).getSource();1391 // EXCEPTION1392 if ( obj.classList.indexOf( _this.setup.chart.classNamePrefix + "-guide-fill" ) != -1 && !attrVal ) {1393 attrOpacity = 0;1394 attrRGBA = fabric.Color.fromHex( "#000000" ).getSource();1395 }1396 if ( attrRGBA ) {1397 attrRGBA.pop();1398 attrRGBA.push( attrOpacity )1399 obj[ attr ] = "rgba(" + attrRGBA.join() + ")";1400 obj[ attr + _this.capitalize( "opacity" ) ] = attrOpacity;1401 }1402 }1403 }1404 // REVIVER1405 _this.handleCallback( cfg.reviver, obj, svg );1406 } );1407 }1408 },1409 /**1410 * Returns the current canvas1411 */1412 toCanvas: function( options, callback ) {1413 var cfg = _this.deepMerge( {1414 // NUFFIN1415 }, options || {} );1416 var data = _this.setup.canvas;1417 _this.handleCallback( callback, data );1418 return data;1419 },1420 /**1421 * Returns an image; by default PNG1422 */1423 toImage: function( options, callback ) {1424 var cfg = _this.deepMerge( {1425 format: "png",1426 quality: 1,1427 multiplier: 11428 }, options || {} );1429 var data = cfg.data;1430 var img = document.createElement( "img" );1431 if ( !cfg.data ) {1432 if ( cfg.lossless || cfg.format == "svg" ) {1433 data = _this.toSVG( _this.deepMerge( cfg, {1434 getBase64: true1435 } ) );1436 } else {1437 data = _this.setup.fabric.toDataURL( cfg );1438 }1439 }1440 img.setAttribute( "src", data );1441 _this.handleCallback( callback, img );1442 return img;1443 },1444 /**1445 * Generates a blob instance image; returns base64 datastring1446 */1447 toBlob: function( options, callback ) {1448 var cfg = _this.deepMerge( {1449 data: "empty",1450 type: "text/plain"1451 }, options || {} );1452 var data;1453 var isBase64 = /^data:.+;base64,(.*)$/.exec( cfg.data );1454 // GATHER BODY1455 if ( isBase64 ) {1456 cfg.data = isBase64[ 0 ];1457 cfg.type = cfg.data.slice( 5, cfg.data.indexOf( "," ) - 7 );1458 cfg.data = _this.toByteArray( {1459 data: cfg.data.slice( cfg.data.indexOf( "," ) + 1, cfg.data.length )1460 } );1461 }1462 if ( cfg.getByteArray ) {1463 data = cfg.data;1464 } else {1465 data = new Blob( [ cfg.data ], {1466 type: cfg.type1467 } );1468 }1469 _this.handleCallback( callback, data );1470 return data;1471 },1472 /**1473 * Generates JPG image; returns base64 datastring1474 */1475 toJPG: function( options, callback ) {1476 var cfg = _this.deepMerge( {1477 format: "jpeg",1478 quality: 1,1479 multiplier: 11480 }, options || {} );1481 cfg.format = cfg.format.toLowerCase();1482 var data = _this.setup.fabric.toDataURL( cfg );1483 _this.handleCallback( callback, data );1484 return data;1485 },1486 /**1487 * Generates PNG image; returns base64 datastring1488 */1489 toPNG: function( options, callback ) {1490 var cfg = _this.deepMerge( {1491 format: "png",1492 quality: 1,1493 multiplier: 11494 }, options || {} );1495 var data = _this.setup.fabric.toDataURL( cfg );1496 _this.handleCallback( callback, data );1497 return data;1498 },1499 /**1500 * Generates SVG image; returns base64 datastring1501 */1502 toSVG: function( options, callback ) {1503 var cfg = _this.deepMerge( {1504 reviver: function( string ) {1505 var matcher = new RegExp( /\bstyle=(['"])(.*?)\1/ );1506 var match = matcher.exec( string )[ 0 ].slice( 7, -1 );1507 var styles = match.split( ";" );1508 var replacement = [];1509 for ( i1 = 0; i1 < styles.length; i1++ ) {1510 if ( styles[ i1 ] ) {1511 var pair = styles[ i1 ].replace( /\s/g, "" ).split( ":" );1512 var key = pair[ 0 ];1513 var value = pair[ 1 ];1514 if ( [ "fill", "stroke" ].indexOf( key ) != -1 ) {1515 value = fabric.Color.fromRgba( value );1516 if ( value && value._source ) {1517 var color = "#" + value.toHex();1518 var opacity = value._source[ 3 ];1519 replacement.push( [ key, color ].join( ":" ) );1520 replacement.push( [ key + "-opacity", opacity ].join( ":" ) );1521 } else {1522 replacement.push( styles[ i1 ] );1523 }1524 } else if ( key != "opactiy" ) {1525 replacement.push( styles[ i1 ] );1526 }1527 }1528 }1529 return string.replace( match, replacement.join( ";" ) );1530 }1531 }, options || {} );1532 var data = _this.setup.fabric.toSVG( cfg, cfg.reviver );1533 if ( cfg.getBase64 ) {1534 data = "data:image/svg+xml;base64," + btoa( data );1535 }1536 _this.handleCallback( callback, data );1537 return data;1538 },1539 /**1540 * Generates PDF; returns base64 datastring1541 */1542 toPDF: function( options, callback ) {1543 var cfg = _this.deepMerge( _this.deepMerge( {1544 multiplier: 21545 }, _this.config.pdfMake ), options || {}, true );1546 cfg.images.reference = _this.toPNG( cfg );1547 var data = new pdfMake.createPdf( cfg );1548 if ( callback ) {1549 data.getDataUrl( ( function( callback ) {1550 return function() {1551 callback.apply( _this, arguments );1552 }1553 } )( callback ) );1554 }1555 return data;1556 },1557 /**1558 * Generates an image; hides all elements on page to trigger native print method1559 */1560 toPRINT: function( options, callback ) {1561 var i1;1562 var cfg = _this.deepMerge( {1563 delay: 1,1564 lossless: false1565 }, options || {} );1566 var data = _this.toImage( cfg );1567 var states = [];1568 var items = document.body.childNodes;1569 data.setAttribute( "style", "width: 100%; max-height: 100%;" );1570 for ( i1 = 0; i1 < items.length; i1++ ) {1571 if ( _this.isElement( items[ i1 ] ) ) {1572 states[ i1 ] = items[ i1 ].style.display;1573 items[ i1 ].style.display = "none";1574 }1575 }1576 document.body.appendChild( data );1577 window.print();1578 setTimeout( function() {1579 for ( i1 = 0; i1 < items.length; i1++ ) {1580 if ( _this.isElement( items[ i1 ] ) ) {1581 items[ i1 ].style.display = states[ i1 ];1582 }1583 }1584 document.body.removeChild( data );1585 _this.handleCallback( callback, data );1586 }, cfg.delay );1587 return data;1588 },1589 /**1590 * Generates JSON string1591 */1592 toJSON: function( options, callback ) {1593 var cfg = _this.deepMerge( {1594 dateFormat: _this.config.dateFormat || "dateObject",1595 }, options || {}, true );1596 cfg.data = cfg.data ? cfg.data : _this.getChartData( cfg );1597 var data = JSON.stringify( cfg.data, undefined, "\t" );1598 _this.handleCallback( callback, data );1599 return data;1600 },1601 /**1602 * Generates CSV string1603 */1604 toCSV: function( options, callback ) {1605 var row, col;1606 var cfg = _this.deepMerge( {1607 data: _this.getChartData( options ),1608 delimiter: ",",1609 quotes: true,1610 escape: true1611 }, options || {}, true );1612 var data = "";1613 var cols = [];1614 var buffer = [];1615 function enchant( value, column ) {1616 // STRING1617 if ( typeof value === "string" ) {1618 value = value;1619 }1620 // WRAP IN QUOTES 1621 if ( typeof value === "string" ) {1622 if ( cfg.escape ) {1623 value = value.replace( '"', '""' );1624 }1625 if ( cfg.quotes ) {1626 value = [ '"', value, '"' ].join( "" );1627 }1628 }1629 return value;1630 }1631 // HEADER1632 for ( value in cfg.data[ 0 ] ) {1633 buffer.push( enchant( value ) );1634 cols.push( value );1635 }1636 data += buffer.join( cfg.delimiter ) + "\n";1637 // BODY1638 for ( row in cfg.data ) {1639 buffer = [];1640 if ( !isNaN( row ) ) {1641 for ( col in cols ) {1642 if ( !isNaN( col ) ) {1643 var column = cols[ col ];1644 var value = cfg.data[ row ][ column ];1645 buffer.push( enchant( value, column ) );1646 }1647 }1648 data += buffer.join( cfg.delimiter ) + "\n";1649 }1650 }1651 _this.handleCallback( callback, data );1652 return data;1653 },1654 /**1655 * Generates excel sheet; returns base64 datastring1656 */1657 toXLSX: function( options, callback ) {1658 var cfg = _this.deepMerge( {1659 name: "amCharts",1660 dateFormat: _this.config.dateFormat || "dateObject",1661 withHeader: true,1662 stringify: false1663 }, options || {}, true );1664 var data = "";1665 var wb = {1666 SheetNames: [],1667 Sheets: {}1668 }1669 cfg.data = cfg.data ? cfg.data : _this.getChartData( cfg );1670 function datenum( v, date1904 ) {1671 if ( date1904 ) v += 1462;1672 var epoch = Date.parse( v );1673 return ( epoch - new Date( Date.UTC( 1899, 11, 30 ) ) ) / ( 24 * 60 * 60 * 1000 );1674 }1675 function sheet_from_array_of_arrays( data, opts ) {1676 var ws = {};1677 var range = {1678 s: {1679 c: 10000000,1680 r: 100000001681 },1682 e: {1683 c: 0,1684 r: 01685 }1686 };1687 for ( var R = 0; R != data.length; ++R ) {1688 for ( var C = 0; C != data[ R ].length; ++C ) {1689 if ( range.s.r > R ) range.s.r = R;1690 if ( range.s.c > C ) range.s.c = C;1691 if ( range.e.r < R ) range.e.r = R;1692 if ( range.e.c < C ) range.e.c = C;1693 var cell = {1694 v: data[ R ][ C ]1695 };1696 if ( cell.v == null ) continue;1697 var cell_ref = XLSX.utils.encode_cell( {1698 c: C,1699 r: R1700 } );1701 if ( typeof cell.v === "number" ) cell.t = "n";1702 else if ( typeof cell.v === "boolean" ) cell.t = "b";1703 else if ( cell.v instanceof Date ) {1704 cell.t = "n";1705 cell.z = XLSX.SSF._table[ 14 ];1706 cell.v = datenum( cell.v );1707 } else cell.t = "s";1708 ws[ cell_ref ] = cell;1709 }1710 }1711 if ( range.s.c < 10000000 ) ws[ "!ref" ] = XLSX.utils.encode_range( range );1712 return ws;1713 }1714 wb.SheetNames.push( cfg.name );1715 wb.Sheets[ cfg.name ] = sheet_from_array_of_arrays( _this.toArray( cfg ) );1716 data = XLSX.write( wb, {1717 bookType: "xlsx",1718 bookSST: true,1719 type: "base64"1720 } );1721 data = "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," + data;1722 _this.handleCallback( callback, data );1723 return data;1724 },1725 /**1726 * Generates an array of arrays1727 */1728 toArray: function( options, callback ) {1729 var row, col;1730 var cfg = _this.deepMerge( {1731 data: _this.getChartData( options ),1732 withHeader: false,1733 stringify: true1734 }, options || {}, true );1735 var data = [];1736 var cols = [];1737 // HEADER1738 for ( col in cfg.data[ 0 ] ) {1739 cols.push( col );1740 }1741 if ( cfg.withHeader ) {1742 data.push( cols );1743 }1744 // BODY1745 for ( row in cfg.data ) {1746 var buffer = [];1747 if ( !isNaN( row ) ) {1748 for ( col in cols ) {1749 if ( !isNaN( col ) ) {1750 var col = cols[ col ];1751 var value = cfg.data[ row ][ col ] || "";1752 if ( cfg.stringify ) {1753 value = String( value );1754 } else {1755 value = value;1756 }1757 buffer.push( value );1758 }1759 }1760 data.push( buffer );1761 }1762 }1763 _this.handleCallback( callback, data );1764 return data;1765 },1766 /**1767 * Generates byte array with given base64 datastring; returns byte array1768 */1769 toByteArray: function( options, callback ) {1770 var cfg = _this.deepMerge( {1771 // NUFFIN1772 }, options || {} );1773 var Arr = ( typeof Uint8Array !== 'undefined' ) ? Uint8Array : Array1774 var PLUS = '+'.charCodeAt( 0 )1775 var SLASH = '/'.charCodeAt( 0 )1776 var NUMBER = '0'.charCodeAt( 0 )1777 var LOWER = 'a'.charCodeAt( 0 )1778 var UPPER = 'A'.charCodeAt( 0 )1779 var data = b64ToByteArray( cfg.data );1780 function decode( elt ) {1781 var code = elt.charCodeAt( 0 )1782 if ( code === PLUS )1783 return 62 // '+'1784 if ( code === SLASH )1785 return 63 // '/'1786 if ( code < NUMBER )1787 return -1 //no match1788 if ( code < NUMBER + 10 )1789 return code - NUMBER + 26 + 261790 if ( code < UPPER + 26 )1791 return code - UPPER1792 if ( code < LOWER + 26 )1793 return code - LOWER + 261794 }1795 function b64ToByteArray( b64 ) {1796 var i, j, l, tmp, placeHolders, arr1797 if ( b64.length % 4 > 0 ) {1798 throw new Error( 'Invalid string. Length must be a multiple of 4' )1799 }1800 // THE NUMBER OF EQUAL SIGNS (PLACE HOLDERS)1801 // IF THERE ARE TWO PLACEHOLDERS, THAN THE TWO CHARACTERS BEFORE IT1802 // REPRESENT ONE BYTE1803 // IF THERE IS ONLY ONE, THEN THE THREE CHARACTERS BEFORE IT REPRESENT 2 BYTES1804 // THIS IS JUST A CHEAP HACK TO NOT DO INDEXOF TWICE1805 var len = b64.length1806 placeHolders = '=' === b64.charAt( len - 2 ) ? 2 : '=' === b64.charAt( len - 1 ) ? 1 : 01807 // BASE64 IS 4/3 + UP TO TWO CHARACTERS OF THE ORIGINAL DATA1808 arr = new Arr( b64.length * 3 / 4 - placeHolders )1809 // IF THERE ARE PLACEHOLDERS, ONLY GET UP TO THE LAST COMPLETE 4 CHARS1810 l = placeHolders > 0 ? b64.length - 4 : b64.length1811 var L = 01812 function push( v ) {1813 arr[ L++ ] = v1814 }1815 for ( i = 0, j = 0; i < l; i += 4, j += 3 ) {1816 tmp = ( decode( b64.charAt( i ) ) << 18 ) | ( decode( b64.charAt( i + 1 ) ) << 12 ) | ( decode( b64.charAt( i + 2 ) ) << 6 ) | decode( b64.charAt( i + 3 ) )1817 push( ( tmp & 0xFF0000 ) >> 16 )1818 push( ( tmp & 0xFF00 ) >> 8 )1819 push( tmp & 0xFF )1820 }1821 if ( placeHolders === 2 ) {1822 tmp = ( decode( b64.charAt( i ) ) << 2 ) | ( decode( b64.charAt( i + 1 ) ) >> 4 )1823 push( tmp & 0xFF )1824 } else if ( placeHolders === 1 ) {1825 tmp = ( decode( b64.charAt( i ) ) << 10 ) | ( decode( b64.charAt( i + 1 ) ) << 4 ) | ( decode( b64.charAt( i + 2 ) ) >> 2 )1826 push( ( tmp >> 8 ) & 0xFF )1827 push( tmp & 0xFF )1828 }1829 return arr1830 }1831 _this.handleCallback( callback, data );1832 return data;1833 },1834 /**1835 * Callback handler; injects additional arguments to callback1836 */1837 handleCallback: function( callback ) {1838 var i1, data = Array();1839 if ( callback && callback instanceof Function ) {1840 for ( i1 = 0; i1 < arguments.length; i1++ ) {1841 if ( i1 > 0 ) {1842 data.push( arguments[ i1 ] );1843 }1844 }1845 callback.apply( _this, data );1846 }1847 },1848 /**1849 * Handles drag/drop events; loads given imagery1850 */1851 handleDropbox: function( e ) {1852 if ( _this.drawing.buffer.enabled ) {1853 e.preventDefault();1854 e.stopPropagation();1855 // DRAG OVER1856 if ( e.type == "dragover" ) {1857 _this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas active dropbox" );1858 // DRAGLEAVE; DROP1859 } else {1860 _this.setup.wrapper.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-canvas active" );1861 if ( e.type == "drop" && e.dataTransfer.files.length ) {1862 for ( var i1 = 0; i1 < e.dataTransfer.files.length; i1++ ) {1863 var reader = new FileReader();1864 reader.onloadend = ( function( index ) {1865 return function() {1866 _this.drawing.handler.add( {1867 url: reader.result,1868 top: e.layerY - ( index * 10 ),1869 left: e.layerX - ( index * 10 )1870 } );1871 }1872 } )( i1 );1873 reader.readAsDataURL( e.dataTransfer.files[ i1 ] );1874 }1875 }1876 }1877 }1878 },1879 /**1880 * Gathers chart data according to its type1881 */1882 getChartData: function( options ) {1883 var cfg = _this.deepMerge( {1884 data: [],1885 titles: {},1886 dateFields: [],1887 dataFields: [],1888 dataFieldsMap: {},1889 exportTitles: _this.config.exportTitles,1890 exportSelection: _this.config.exportSelection1891 }, options || {}, true );1892 var uid, i1, i2, i3;1893 var lookupFields = [ "valueField", "openField", "closeField", "highField", "lowField", "xField", "yField" ];1894 // HANDLE FIELDS1895 function addField( field, title, type ) {1896 function checkExistance( field, type ) {1897 if ( cfg.dataFields.indexOf( field ) != -1 ) {1898 return checkExistance( [ field, ".", type ].join( "" ) );1899 }1900 return field;1901 }1902 if ( field && cfg.exportTitles && _this.setup.chart.type != "gantt" ) {1903 uid = checkExistance( field, type );1904 cfg.dataFieldsMap[ uid ] = field;1905 cfg.dataFields.push( uid );1906 cfg.titles[ uid ] = title || uid;1907 }1908 }1909 if ( cfg.data.length == 0 ) {1910 // STOCK DATA; GATHER COMPARED GRAPHS1911 if ( _this.setup.chart.type == "stock" ) {1912 cfg.data = _this.setup.chart.mainDataSet.dataProvider;1913 // CATEGORY AXIS1914 addField( _this.setup.chart.mainDataSet.categoryField );1915 cfg.dateFields.push( _this.setup.chart.mainDataSet.categoryField );1916 // WALKTHROUGH GRAPHS1917 for ( i1 = 0; i1 < _this.setup.chart.mainDataSet.fieldMappings.length; i1++ ) {1918 var fieldMap = _this.setup.chart.mainDataSet.fieldMappings[ i1 ];1919 for ( i2 = 0; i2 < _this.setup.chart.panels.length; i2++ ) {1920 var panel = _this.setup.chart.panels[ i2 ]1921 for ( i3 = 0; i3 < panel.stockGraphs.length; i3++ ) {1922 var graph = panel.stockGraphs[ i3 ];1923 for ( i4 = 0; i4 < lookupFields.length; i4++ ) {1924 if ( graph[ lookupFields[ i4 ] ] == fieldMap.toField ) {1925 addField( fieldMap.fromField, graph.title, lookupFields[ i4 ] );1926 }1927 }1928 }1929 }1930 }1931 // WALKTHROUGH COMPARISON AND MERGE IT'S DATA1932 for ( i1 = 0; i1 < _this.setup.chart.comparedGraphs.length; i1++ ) {1933 var graph = _this.setup.chart.comparedGraphs[ i1 ];1934 for ( i2 = 0; i2 < graph.dataSet.dataProvider.length; i2++ ) {1935 for ( i3 = 0; i3 < graph.dataSet.fieldMappings.length; i3++ ) {1936 var fieldMap = graph.dataSet.fieldMappings[ i3 ];1937 var uid = graph.dataSet.id + "_" + fieldMap.toField;1938 if ( i2 < cfg.data.length ) {1939 cfg.data[ i2 ][ uid ] = graph.dataSet.dataProvider[ i2 ][ fieldMap.fromField ];1940 if ( !cfg.titles[ uid ] ) {1941 addField( uid, graph.dataSet.title )1942 }1943 }1944 }1945 }1946 }1947 // GANTT DATA; FLATTEN SEGMENTS1948 } else if ( _this.setup.chart.type == "gantt" ) {1949 // CATEGORY AXIS1950 addField( _this.setup.chart.categoryField );1951 cfg.dateFields.push( _this.setup.chart.categoryField );1952 var field = _this.setup.chart.segmentsField;1953 for ( i1 = 0; i1 < _this.setup.chart.dataProvider.length; i1++ ) {1954 var dataItem = _this.setup.chart.dataProvider[ i1 ];1955 if ( dataItem[ field ] ) {1956 for ( i2 = 0; i2 < dataItem[ field ].length; i2++ ) {1957 dataItem[ field ][ i2 ][ _this.setup.chart.categoryField ] = dataItem[ _this.setup.chart.categoryField ];1958 cfg.data.push( dataItem[ field ][ i2 ] );1959 }1960 }1961 }1962 // GRAPHS1963 for ( i1 = 0; i1 < _this.setup.chart.graphs.length; i1++ ) {1964 var graph = _this.setup.chart.graphs[ i1 ];1965 for ( i2 = 0; i2 < lookupFields.length; i2++ ) {1966 var dataField = lookupFields[ i2 ];1967 var graphField = graph[ dataField ];1968 var title = graph.title;1969 addField( graphField, graph.title, dataField );1970 }1971 }1972 // PIE/FUNNEL DATA;1973 } else if ( [ "pie", "funnel" ].indexOf( _this.setup.chart.type ) != -1 ) {1974 cfg.data = _this.setup.chart.dataProvider;1975 // CATEGORY AXIS1976 addField( _this.setup.chart.titleField );1977 cfg.dateFields.push( _this.setup.chart.titleField );1978 // VALUE1979 addField( _this.setup.chart.valueField );1980 // DEFAULT DATA;1981 } else if ( _this.setup.chart.type != "map" ) {1982 cfg.data = _this.setup.chart.dataProvider;1983 // CATEGORY AXIS1984 if ( _this.setup.chart.categoryAxis ) {1985 addField( _this.setup.chart.categoryField, _this.setup.chart.categoryAxis.title );1986 cfg.dateFields.push( _this.setup.chart.categoryField );1987 }1988 // GRAPHS1989 for ( i1 = 0; i1 < _this.setup.chart.graphs.length; i1++ ) {1990 var graph = _this.setup.chart.graphs[ i1 ];1991 for ( i2 = 0; i2 < lookupFields.length; i2++ ) {1992 var dataField = lookupFields[ i2 ];1993 var graphField = graph[ dataField ];1994 addField( graphField, graph.title, dataField );1995 }1996 }1997 }1998 }1999 return _this.processData( cfg );2000 },2001 /**2002 * Walkthrough data to format dates and titles2003 */2004 processData: function( options ) {2005 var cfg = _this.deepMerge( {2006 data: [],2007 titles: {},2008 dateFields: [],2009 dataFields: [],2010 dataFieldsMap: {},2011 dataDateFormat: _this.setup.chart.dataDateFormat,2012 dateFormat: _this.config.dateFormat || _this.setup.chart.dataDateFormat || "YYYY-MM-DD",2013 exportTitles: _this.config.exportTitles,2014 exportSelection: _this.config.exportSelection2015 }, options || {}, true );2016 var i1, i2;2017 if ( cfg.data.length ) {2018 // GATHER MISSING FIELDS2019 for ( i1 = 0; i1 < cfg.data.length; i1++ ) {2020 for ( i2 in cfg.data[ i1 ] ) {2021 if ( cfg.dataFields.indexOf( i2 ) == -1 ) {2022 cfg.dataFields.push( i2 );2023 cfg.dataFieldsMap[ i2 ] = i2;2024 }2025 }2026 }2027 // REBUILD DATA2028 var buffer = [];2029 for ( i1 = 0; i1 < cfg.data.length; i1++ ) {2030 var tmp = {};2031 var skip = false;2032 for ( i2 = 0; i2 < cfg.dataFields.length; i2++ ) {2033 var uniqueField = cfg.dataFields[ i2 ];2034 var dataField = cfg.dataFieldsMap[ uniqueField ];2035 var title = cfg.titles[ uniqueField ] || uniqueField;2036 var value = cfg.data[ i1 ][ dataField ] || undefined;2037 // TITLEFY2038 if ( cfg.exportTitles && _this.setup.chart.type != "gantt" ) {2039 if ( title in tmp ) {2040 title += [ "( ", uniqueField, " )" ].join( "" );2041 }2042 }2043 // PROCESS CATEGORY2044 if ( cfg.dateFields.indexOf( dataField ) != -1 ) {2045 // CONVERT DATESTRING TO DATE OBJECT2046 if ( cfg.dataDateFormat && ( value instanceof String || typeof value == "string" ) ) {2047 value = AmCharts.stringToDate( value, cfg.dataDateFormat );2048 // CONVERT TIMESTAMP TO DATE OBJECT2049 } else if ( cfg.dateFormat && ( value instanceof Number || typeof value == "number" ) ) {2050 value = new Date(value);2051 }2052 // CATEGORY RANGE2053 if ( cfg.exportSelection ) {2054 if ( value instanceof Date ) {2055 if ( value < chart.startDate || value > chart.endDate ) {2056 skip = true;2057 }2058 } else if ( i1 < chart.startIndex || i1 > chart.endIndex ) {2059 skip = true;2060 }2061 }2062 // CATEGORY FORMAT2063 if ( cfg.dateFormat && cfg.dateFormat != "dateObject" && value instanceof Date ) {2064 value = AmCharts.formatDate( value, cfg.dateFormat );2065 }2066 }2067 tmp[ title ] = value;2068 }2069 if ( !skip ) {2070 buffer.push( tmp );2071 }2072 }2073 cfg.data = buffer;2074 }2075 return cfg.data;2076 },2077 /**2078 * Prettifies string2079 */2080 capitalize: function( string ) {2081 return string.charAt( 0 ).toUpperCase() + string.slice( 1 ).toLowerCase();2082 },2083 /**2084 * Generates export menu; returns UL node2085 */2086 createMenu: function( list, container ) {2087 var div;2088 function buildList( list, container ) {2089 var i1, i2, ul = document.createElement( "ul" );2090 for ( i1 = 0; i1 < list.length; i1++ ) {2091 var item = typeof list[ i1 ] === "string" ? {2092 format: list[ i1 ]2093 } : list[ i1 ];2094 var li = document.createElement( "li" );2095 var a = document.createElement( "a" );2096 var img = document.createElement( "img" );2097 var span = document.createElement( "span" );2098 var action = String( item.action ? item.action : item.format ).toLowerCase();2099 item.format = String( item.format ).toUpperCase();2100 // MERGE WITH GIVEN FORMAT2101 if ( _this.config.formats[ item.format ] ) {2102 item = _this.deepMerge( {2103 label: item.icon ? "" : item.format,2104 format: item.format,2105 mimeType: _this.config.formats[ item.format ].mimeType,2106 extension: _this.config.formats[ item.format ].extension,2107 capture: _this.config.formats[ item.format ].capture,2108 action: _this.config.action,2109 fileName: _this.config.fileName2110 }, item );2111 } else if ( !item.label ) {2112 item.label = item.label ? item.label : _this.i18l( "menu.label." + action );2113 }2114 // FILTER; TOGGLE FLAG2115 if ( [ "CSV", "JSON", "XLSX" ].indexOf( item.format ) != -1 && [ "map", "gauge" ].indexOf( _this.setup.chart.type ) != -1 ) {2116 continue;2117 // BLOB EXCEPTION2118 } else if ( !_this.setup.hasBlob && item.format != "UNDEFINED" ) {2119 if ( item.mimeType && item.mimeType.split( "/" )[ 0 ] != "image" && item.mimeType != "text/plain" ) {2120 continue;2121 }2122 }2123 // DRAWING2124 if ( item.action == "draw" ) {2125 if ( _this.config.fabric.drawing.enabled ) {2126 item.menu = item.menu ? item.menu : _this.config.fabric.drawing.menu;2127 item.click = ( function( item ) {2128 return function() {2129 this.capture( item, function() {2130 this.createMenu( item.menu );2131 } );2132 }2133 } )( item );2134 } else {2135 item.menu = [];2136 }2137 // DRAWING CHOICES2138 } else if ( !item.populated && item.action && item.action.indexOf( "draw." ) != -1 ) {2139 var type = item.action.split( "." )[ 1 ];2140 var items = item[ type ] || _this.config.fabric.drawing[ type ] || [];2141 item.menu = [];2142 item.populated = true;2143 for ( i2 = 0; i2 < items.length; i2++ ) {2144 var tmp = {2145 "label": items[ i2 ]2146 }2147 if ( type == "shapes" ) {2148 var io = items[ i2 ].indexOf( "//" ) == -1;2149 var url = ( io ? _this.config.path + "shapes/" : "" ) + items[ i2 ];2150 tmp.action = "add";2151 tmp.url = url;2152 tmp.icon = url;2153 tmp.ignore = io;2154 tmp[ "class" ] = "export-drawing-shape";2155 } else if ( type == "colors" ) {2156 tmp.style = "background-color: " + items[ i2 ];2157 tmp.action = "change";2158 tmp.color = items[ i2 ];2159 tmp[ "class" ] = "export-drawing-color";2160 } else if ( type == "widths" ) {2161 tmp.action = "change";2162 tmp.width = items[ i2 ];2163 tmp.label = document.createElement( "span" );2164 tmp.label.style.width = _this.numberToPx( items[ i2 ] );2165 tmp.label.style.height = _this.numberToPx( items[ i2 ] );2166 tmp[ "class" ] = "export-drawing-width";2167 } else if ( type == "opacities" ) {2168 tmp.style = "opacity: " + items[ i2 ];2169 tmp.action = "change";2170 tmp.opacity = items[ i2 ];2171 tmp.label = ( items[ i2 ] * 100 ) + "%";2172 tmp[ "class" ] = "export-drawing-opacity";2173 } else if ( type == "modes" ) {2174 tmp.label = _this.i18l( "menu.label.draw.modes." + items[ i2 ] );2175 tmp.click = ( function( mode ) {2176 return function() {2177 _this.drawing.mode = mode;2178 }2179 } )( items[ i2 ] );2180 tmp[ "class" ] = "export-drawing-mode";2181 }2182 item.menu.push( tmp );2183 }2184 // ADD CLICK HANDLER2185 } else if ( !item.click && !item.menu && !item.items ) {2186 // DRAWING METHODS2187 if ( _this.drawing.handler[ action ] instanceof Function ) {2188 item.action = action;2189 item.click = ( function( item ) {2190 return function() {2191 this.drawing.handler[ item.action ]( item );2192 }2193 } )( item );2194 // DRAWING2195 } else if ( _this.drawing.buffer.enabled ) {2196 item.click = ( function( item ) {2197 return function() {2198 if ( this.config.drawing.autoClose ) {2199 this.drawing.handler.done();2200 }2201 this[ "to" + item.format ]( item, function( data ) {2202 if ( item.action == "download" ) {2203 this.download( data, item.mimeType, [ item.fileName, item.extension ].join( "." ) );2204 }2205 } );2206 }2207 } )( item );2208 // REGULAR2209 } else if ( item.format != "UNDEFINED" ) {2210 item.click = ( function( item ) {2211 return function() {2212 if ( item.capture || item.action == "print" || item.format == "PRINT" ) {2213 this.capture( item, function() {2214 if ( this.config.drawing.autoClose ) {2215 this.drawing.handler.done();2216 }2217 this[ "to" + item.format ]( item, function( data ) {2218 if ( item.action == "download" ) {2219 this.download( data, item.mimeType, [ item.fileName, item.extension ].join( "." ) );2220 }2221 } );2222 } )2223 } else if ( this[ "to" + item.format ] ) {2224 this[ "to" + item.format ]( item, function( data ) {2225 this.download( data, item.mimeType, [ item.fileName, item.extension ].join( "." ) );2226 } );2227 } else {2228 throw new Error( 'Invalid format. Could not determine output type.' );2229 }2230 }2231 } )( item );2232 }2233 }2234 // HIDE EMPTY ONES2235 if ( item.menu !== undefined && !item.menu.length ) {2236 continue;2237 }2238 // ADD LINK ATTR2239 a.setAttribute( "href", "#" );2240 a.addEventListener( "click", ( function( callback, item ) {2241 return function( e ) {2242 e.preventDefault();2243 var args = [ e, item ];2244 // DELAYED2245 if ( ( item.action == "draw" || item.format == "PRINT" || ( item.format != "UNDEFINED" && item.capture ) ) && !_this.drawing.enabled ) {2246 item.delay = item.delay ? item.delay : _this.config.delay;2247 if ( item.delay ) {2248 _this.delay( item, callback );2249 return;2250 }2251 }2252 callback.apply( _this, args );2253 }2254 } )( item.click || function( e ) {2255 e.preventDefault();2256 }, item ) );2257 li.appendChild( a );2258 // ADD LABEL2259 if ( _this.isElement( item.label ) ) {2260 span.appendChild( item.label );2261 } else {2262 span.innerHTML = item.label;2263 }2264 // APPEND ITEMS2265 if ( item[ "class" ] ) {2266 li.className = item[ "class" ];2267 }2268 if ( item.style ) {2269 li.setAttribute( "style", item.style );2270 }2271 if ( item.icon ) {2272 img.setAttribute( "src", ( !item.ignore && item.icon.slice( 0, 10 ).indexOf( "//" ) == -1 ? chart.pathToImages : "" ) + item.icon );2273 a.appendChild( img );2274 }2275 if ( item.label ) {2276 a.appendChild( span );2277 }2278 if ( item.title ) {2279 a.setAttribute( "title", item.title );2280 }2281 // CALLBACK; REVIVER FOR MENU ITEMS2282 if ( _this.config.menuReviver ) {2283 li = _this.config.menuReviver.apply( _this, [ item, li ] );2284 }2285 // ADD ELEMENTS FOR EASY ACCESS2286 item.elements = {2287 li: li,2288 a: a,2289 img: img,2290 span: span2291 }2292 // ADD SUBLIST; JUST WITH ENTRIES2293 if ( ( item.menu || item.items ) && item.action != "draw" ) {2294 if ( buildList( item.menu || item.items, li ).childNodes.length ) {2295 ul.appendChild( li );2296 }2297 } else {2298 ul.appendChild( li );2299 }2300 }2301 // JUST ADD THOSE WITH ENTRIES2302 if ( ul.childNodes.length ) {2303 container.appendChild( ul );2304 }2305 return ul;2306 }2307 // DETERMINE CONTAINER2308 if ( !container ) {2309 if ( typeof _this.config.divId == "string" ) {2310 _this.config.divId = container = document.getElementById( _this.config.divId );2311 } else if ( _this.isElement( _this.config.divId ) ) {2312 container = _this.config.divId;2313 } else {2314 container = _this.setup.chart.containerDiv;2315 }2316 }2317 // CREATE / RESET MENU CONTAINER2318 if ( _this.isElement( _this.setup.menu ) ) {2319 _this.setup.menu.innerHTML = "";2320 } else {2321 _this.setup.menu = document.createElement( "div" );2322 }2323 _this.setup.menu.setAttribute( "class", _this.setup.chart.classNamePrefix + "-export-menu " + _this.setup.chart.classNamePrefix + "-export-menu-" + _this.config.position + " amExportButton" );2324 // CALLBACK; REPLACES THE MENU WALKER2325 if ( _this.config.menuWalker ) {2326 buildList = _this.config.menuWalker;2327 }2328 buildList.apply( this, [ list, _this.setup.menu ] );2329 // JUST ADD THOSE WITH ENTRIES2330 if ( _this.setup.menu.childNodes.length ) {2331 container.appendChild( _this.setup.menu );2332 }2333 return _this.setup.menu;2334 },2335 /**2336 * Method to trigger the callback delayed2337 */2338 delay: function( options, callback ) {2339 var cfg = _this.deepMerge( {2340 delay: 3,2341 precision: 22342 }, options || {} );2343 var t1, t2, start = Number( new Date() );2344 var menu = _this.createMenu( [ {2345 label: _this.i18l( "capturing.delayed.menu.label" ).replace( "{{duration}}", AmCharts.toFixed( cfg.delay, cfg.precision ) ),2346 title: _this.i18l( "capturing.delayed.menu.title" ),2347 "class": "export-delayed-capturing",2348 click: function() {2349 clearTimeout( t1 );2350 clearTimeout( t2 );2351 _this.createMenu( _this.config.menu );2352 }2353 } ] );2354 var label = menu.getElementsByTagName( "a" )[ 0 ];2355 // MENU UPDATE2356 t1 = setInterval( function() {2357 var diff = cfg.delay - ( Number( new Date() ) - start ) / 1000;2358 if ( diff <= 0 ) {2359 clearTimeout( t1 );2360 if ( cfg.action != "draw" ) {2361 _this.createMenu( _this.config.menu );2362 }2363 } else if ( label ) {2364 label.innerHTML = _this.i18l( "capturing.delayed.menu.label" ).replace( "{{duration}}", AmCharts.toFixed( diff, 2 ) );2365 }2366 }, 10 );2367 // CALLBACK2368 t2 = setTimeout( function() {2369 callback.apply( _this, arguments );2370 }, cfg.delay * 1000 );2371 },2372 /**2373 * Migration method to support old export setup2374 */2375 migrateSetup: function( setup ) {2376 var cfg = {2377 enabled: true,2378 migrated: true,2379 libs: {2380 autoLoad: true2381 },2382 menu: []2383 };2384 function crawler( object ) {2385 var key;2386 for ( key in object ) {2387 var value = object[ key ];2388 if ( key.slice( 0, 6 ) == "export" && value ) {2389 cfg.menu.push( key.slice( 6 ) );2390 } else if ( key == "userCFG" ) {2391 crawler( value );2392 } else if ( key == "menuItems" ) {2393 cfg.menu = value;2394 } else if ( key == "libs" ) {2395 cfg.libs = value;2396 } else if ( typeof key == "string" ) {2397 cfg[ key ] = value;2398 }2399 }2400 }2401 crawler( setup );2402 return cfg;2403 },2404 /*2405 ** Add event listener2406 */2407 loadListeners: function() {2408 function handleClone( clone ) {2409 if ( clone ) {2410 clone.set( {2411 top: clone.top + 10,2412 left: clone.left + 102413 } );2414 _this.setup.fabric.add( clone );2415 }2416 }2417 // OBSERVE; KEY LISTENER; DRAWING FEATURES2418 if ( _this.config.keyListener && _this.config.keyListener != "attached" ) {2419 _this.config.keyListener = "attached";2420 document.addEventListener( "keydown", function( e ) {2421 var current = _this.drawing.buffer.target;2422 // REMOVE; key: BACKSPACE / DELETE2423 if ( ( e.keyCode == 8 || e.keyCode == 46 ) && current ) {2424 e.preventDefault();2425 _this.setup.fabric.remove( current );2426 // ESCAPE DRAWIN MODE; key: escape2427 } else if ( e.keyCode == 27 && _this.drawing.enabled ) {2428 e.preventDefault();2429 _this.drawing.handler.done();2430 // COPY; key: C2431 } else if ( e.keyCode == 67 && ( e.metaKey || e.ctrlKey ) && current ) {2432 _this.drawing.buffer.copy = current;2433 // CUT; key: X2434 } else if ( e.keyCode == 88 && ( e.metaKey || e.ctrlKey ) && current ) {2435 _this.drawing.buffer.copy = current;2436 _this.setup.fabric.remove( current );2437 // PASTE; key: V2438 } else if ( e.keyCode == 86 && ( e.metaKey || e.ctrlKey ) ) {2439 if ( _this.drawing.buffer.copy ) {2440 handleClone( _this.drawing.buffer.copy.clone( handleClone ) )2441 }2442 // UNDO / REDO; key: Z2443 } else if ( e.keyCode == 90 && ( e.metaKey || e.ctrlKey ) ) {2444 e.preventDefault();2445 if ( e.shiftKey ) {2446 _this.drawing.handler.redo();2447 } else {2448 _this.drawing.handler.undo();2449 }2450 }2451 } );2452 }2453 // OBSERVE; DRAG AND DROP LISTENER; DRAWING FEATURE2454 if ( _this.config.fileListener ) {2455 _this.setup.chart.containerDiv.addEventListener( "dragover", _this.handleDropbox );2456 _this.setup.chart.containerDiv.addEventListener( "dragleave", _this.handleDropbox );2457 _this.setup.chart.containerDiv.addEventListener( "drop", _this.handleDropbox );2458 }2459 },2460 /**2461 * Initiate export menu; waits for chart container to place menu2462 */2463 init: function() {2464 clearTimeout( _this.timer );2465 _this.timer = setInterval( function() {2466 if ( _this.setup.chart.containerDiv ) {2467 clearTimeout( _this.timer );2468 if ( _this.config.enabled ) {2469 // CREATE REFERENCE2470 _this.setup.chart.AmExport = _this;2471 // OVERWRITE PARENT OVERVIEW2472 _this.setup.chart.div.style.overflow = "visible";2473 // ATTACH EVENTS2474 _this.loadListeners();2475 // CREATE MENU2476 _this.createMenu( _this.config.menu );2477 }2478 }2479 }, AmCharts.updateRate );2480 },2481 /**2482 * Initiates export instance; merges given config; attaches event listener2483 */2484 construct: function() {2485 // ANNOTATION; MAP "DONE"2486 _this.drawing.handler.cancel = _this.drawing.handler.done;2487 // CHECK BLOB CONSTRUCTOR2488 try {2489 _this.setup.hasBlob = !!new Blob;2490 } catch ( e ) {}2491 // WORK AROUND TO BYPASS FILESAVER CHECK TRYING TO OPEN THE BLOB URL IN SAFARI BROWSER2492 window.safari = window.safari ? window.safari : {};2493 // OVERTAKE CHART FONTSIZE IF GIVEN2494 _this.defaults.fabric.drawing.fontSize = _this.setup.chart.fontSize || 11;2495 // MERGE SETTINGS2496 _this.config.drawing = _this.deepMerge( _this.defaults.fabric.drawing, _this.config.drawing || {}, true );2497 _this.deepMerge( _this.defaults.fabric, _this.config, true );2498 _this.deepMerge( _this.defaults.fabric, _this.config.fabric || {}, true );2499 _this.deepMerge( _this.defaults.pdfMake, _this.config, true );2500 _this.deepMerge( _this.defaults.pdfMake, _this.config.pdfMake || {}, true );2501 _this.deepMerge( _this.libs, _this.config.libs || {}, true );2502 // UPDATE CONFIG2503 _this.config.drawing = _this.defaults.fabric.drawing;2504 _this.config.fabric = _this.defaults.fabric;2505 _this.config.pdfMake = _this.defaults.pdfMake;2506 _this.config = _this.deepMerge( _this.defaults, _this.config, true );2507 // MERGE; SETUP DRAWING MENU2508 if ( _this.config.fabric.drawing.enabled ) {2509 if ( _this.config.fabric.drawing.menu === undefined ) {2510 _this.config.fabric.drawing.menu = [];2511 _this.deepMerge( _this.config.fabric.drawing.menu, [ {2512 "class": "export-drawing",2513 menu: [ {2514 label: _this.i18l( "menu.label.draw.add" ),2515 menu: [ {2516 label: _this.i18l( "menu.label.draw.shapes" ),2517 action: "draw.shapes"2518 }, {2519 label: _this.i18l( "menu.label.draw.text" ),2520 action: "text"2521 } ]2522 }, {2523 label: _this.i18l( "menu.label.draw.change" ),2524 menu: [ {2525 label: _this.i18l( "menu.label.draw.modes" ),2526 action: "draw.modes"2527 }, {2528 label: _this.i18l( "menu.label.draw.colors" ),2529 action: "draw.colors"2530 }, {2531 label: _this.i18l( "menu.label.draw.widths" ),2532 action: "draw.widths"2533 }, {2534 label: _this.i18l( "menu.label.draw.opacities" ),2535 action: "draw.opacities"2536 }, "UNDO", "REDO" ]2537 }, {2538 label: _this.i18l( "menu.label.save.image" ),2539 menu: [ "PNG", "JPG", "SVG", "PDF" ]2540 }, "PRINT", "CANCEL" ]2541 } ] );2542 }2543 }2544 // MERGE; SETUP MAIN MENU2545 if ( _this.config.menu === undefined ) {2546 _this.config.menu = [];2547 // PARENT MENU2548 _this.deepMerge( _this.config, {2549 menu: [ {2550 "class": "export-main",2551 menu: [ {2552 label: _this.i18l( "menu.label.save.image" ),2553 menu: [ "PNG", "JPG", "SVG", "PDF" ]2554 }, {2555 label: _this.i18l( "menu.label.save.data" ),2556 menu: [ "CSV", "XLSX", "JSON" ]2557 }, {2558 label: _this.i18l( "menu.label.draw" ),2559 action: "draw",2560 menu: _this.config.fabric.drawing.menu2561 }, {2562 format: "PRINT",2563 label: _this.i18l( "menu.label.print" )2564 } ]2565 } ]2566 } );2567 }2568 // ADD MISSING PATH2569 if ( !_this.libs.path ) {2570 _this.libs.path = _this.config.path + "libs/";2571 }2572 // CHECK ACCEPTANCE2573 if ( _this.isSupported() ) {2574 // LOAD DEPENDENCIES2575 _this.loadDependencies( _this.libs.resources, _this.libs.reload );2576 // ADD CLASSNAMES2577 _this.setup.chart.addClassNames = true;2578 // REFERENCE2579 _this.setup.chart[ _this.name ] = _this;2580 // INIT MENU; WAIT FOR CHART INSTANCE2581 _this.init();2582 }2583 }2584 }2585 // USE GIVEN CONFIG2586 if ( config ) {2587 _this.config = config;2588 // USE CHART EXPORT CONFIG2589 } else if ( _this.setup.chart[ _this.name ] ) {2590 _this.config = _this.setup.chart[ _this.name ];2591 // MIGRATE OLD EXPORT CHART CONFIG2592 } else if ( _this.setup.chart.amExport || _this.setup.chart.exportConfig ) {2593 _this.config = _this.migrateSetup( _this.setup.chart.amExport || _this.setup.chart.exportConfig );2594 // EXIT; NO CONFIG2595 } else {2596 return;2597 }2598 // CONSTRUCT INSTANCE2599 _this.construct();2600 // EXPORT SCOPE2601 return _this.deepMerge( this, _this );2602 }2603} )();2604/**2605 * Set init handler2606 */2607AmCharts.addInitHandler( function( chart ) {2608 new AmCharts["export"]( chart );...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', function() {2 it('Does not do much!', function() {3 cy.contains('type').click()4 cy.url().should('include', '/commands/actions')5 cy.get('.action-email')6 .type('

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', () => {2 it('Does not do much!', () => {3 cy.contains('type').click()4 cy.url().should('include', '/commands/actions')5 cy.get('.action-email')6 .type('

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', function() {2 it('Does not do much!', function() {3 expect(true).to.equal(true)4 })5})6describe('My First Test', function() {7 it('Does not do much!', function() {8 expect(true).to.equal(true)9 })10})11describe('My First Test', function() {12 it('Does not do much!', function() {13 expect(true).to.equal(true)14 })15})16describe('My First Test', function() {17 it('Does not do much!', function() {18 expect(true).to.equal(true)19 })20})21describe('My First Test', function() {22 it('Does not do much!', function() {23 expect(true).to.equal(true)24 })25})26describe('My First Test', function() {27 it('Does not do much!', function() {28 expect(true).to.equal(true)29 })30})31describe('My First Test', function() {32 it('Does not do much!', function() {33 expect(true).to.equal(true)34 })35})36describe('My First Test', function() {37 it('Does not do much!', function() {38 expect(true).to.equal(true)39 })40})41describe('My First Test', function() {42 it('Does not do much!', function() {43 expect(true).to.equal(true)44 })45})46describe('My First Test', function() {47 it('Does not do much!', function() {48 expect(true).to.equal(true)49 })50})51describe('My First Test', function() {52 it('Does not do much!', function() {53 expect(true).to.equal(true)54 })55})56describe('My First Test', function() {57 it('Does not do much!', function() {58 expect(true).to.equal(true)59 })60})61describe('My First Test', function

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', function() {2 it('Does not do much!', function() {3 expect(true).to.equal(true)4 })5})6describe('My First Test', function() {7 it('Does not do much!', function() {8 expect(true).to.equal(true)9 })10})11describe('My First Test', function() {12 it('Does not do much!', function() {13 expect(true).to.equal(true)14 })15})16describe('My Second Test', function() {17 it('Does not do much!', function() {18 expect(true).to.equal(true)19 })20})21describe('My First Test', function() {22 it('Does not do much!', function() {23 expect(true).to.equal(true)24 })25})26describe('My Second Test', function() {27 it('Does not do much!', function() {28 expect(true).to.equal(true)29 })30})31describe('My First Test', function() {32 it('Does not do much!', function() {33 expect(true).to.equal(true)34 })35})36describe('My Second Test', function() {37 it('Does not do much!', function() {38 expect(true).to.equal(true)39 })40})41describe('My First Test', function() {42 it('Does not do much!', function() {43 expect(true

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', function() {2 it('Does not do much!', function() {3 expect(true).to.equal(true)4 })5})6describe('My First Test', function() {7 it('Does not do much!', function() {8 expect(true).to.equal(true)9 })10})11describe('My First Test', function() {12 it('Does not do much!', function() {13 expect(true).to.equal(true)14 })15})16describe('My First Test', function() {17 it('Does not do much!', function() {18 expect(true).to.equal(true)19 })20})21describe('My First Test', function() {22 it('Does not do much!', function() {23 expect(true).to.equal(true)24 })25})26describe('My First Test', function() {27 it('Does not do much!', function() {28 expect(true).to.equal(true)29 })30})31describe('My First Test', function() {32 it('Does not do much!', function() {33 expect(true).to.equal(true)34 })35})36describe('My First Test', function() {37 it('Does not do much!', function() {38 expect(true).to.equal(true)39 })40})41describe('My First Test', function() {42 it('Does not do much!', function() {43 expect(true).to.equal(true)44 })45})46describe('My First Test', function() {47 it('Does not do much!', function() {48 expect(true).to.equal(true)49 })50})51describe('My First Test', function() {52 it('Does not do much!', function()

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', () => {2 it('Does not do much!', () => {3 expect(true).to.equal(true)4 })5})6import './commands'7Cypress.Commands.add('login', (email, password) => {8 cy.visit('/login')9 cy.get('#email').type(email)10 cy.get('#password').type(password)11 cy.get('button').click()12})13describe('My First Test', () => {14 it('Does not do much!', () => {15 expect(true).to.equal(true)16 })17})18describe('My First Test', () => {19 it('Does not do much!', () => {20 expect(true).to.equal(true)21 })22})23describe('My First Test', () => {24 it('Does not do much!', () => {25 expect(true).to.equal(true)26 })27})28describe('My First Test', () => {29 it('Does not do much!', () => {30 expect(true).to.equal(true)31 })32})33describe('My First Test', () => {34 it('Does not do much!', () => {35 expect(true).to.equal(true)36 })37})38describe('My First Test', () => {39 it('Does not do much!', () => {40 expect(true).to.equal(true)41 })42})43describe('My First Test', () => {44 it('Does not do much!', () => {45 expect(true).to.equal(true)46 })47})

Full Screen

Using AI Code Generation

copy

Full Screen

1describe("Test", () => {2 before(() => {3 cy.setup();4 });5});6Cypress.Commands.add("setup", () => {7 cy.server();8 cy.route({9 }).as("getEndpoint");10});

Full Screen

Cypress Tutorial

Cypress is a renowned Javascript-based open-source, easy-to-use end-to-end testing framework primarily used for testing web applications. Cypress is a relatively new player in the automation testing space and has been gaining much traction lately, as evidenced by the number of Forks (2.7K) and Stars (42.1K) for the project. LambdaTest’s Cypress Tutorial covers step-by-step guides that will help you learn from the basics till you run automation tests on LambdaTest.

Chapters:

  1. What is Cypress? -
  2. Why Cypress? - Learn why Cypress might be a good choice for testing your web applications.
  3. Features of Cypress Testing - Learn about features that make Cypress a powerful and flexible tool for testing web applications.
  4. Cypress Drawbacks - Although Cypress has many strengths, it has a few limitations that you should be aware of.
  5. Cypress Architecture - Learn more about Cypress architecture and how it is designed to be run directly in the browser, i.e., it does not have any additional servers.
  6. Browsers Supported by Cypress - Cypress is built on top of the Electron browser, supporting all modern web browsers. Learn browsers that support Cypress.
  7. Selenium vs Cypress: A Detailed Comparison - Compare and explore some key differences in terms of their design and features.
  8. Cypress Learning: Best Practices - Take a deep dive into some of the best practices you should use to avoid anti-patterns in your automation tests.
  9. How To Run Cypress Tests on LambdaTest? - Set up a LambdaTest account, and now you are all set to learn how to run Cypress tests.

Certification

You can elevate your expertise with end-to-end testing using the Cypress automation framework and stay one step ahead in your career by earning a Cypress certification. Check out our Cypress 101 Certification.

YouTube

Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful