=b&&(b=.001);if(void 0==g||0===g)g=.01;void 0===f&&(f=\"#000000\");void 0===h&&(h=0);e={fill:c,stroke:f,\"fill-opacity\":e,\"stroke-width\":g,\"stroke-opacity\":h};a=isNaN(l)?a.circle(0,0,b).attr(e):a.ellipse(0,0,b,l).attr(e);k&&a.gradient(\"radialGradient\",[c,d.adjustLuminosity(c,-.6)]);return a};d.text=function(a,b,c,e,g,f,h,k){f||(f=\"middle\");\"right\"==f&&(f=\"end\");\"left\"==f&&(f=\"start\");isNaN(k)&&(k=1);void 0!==b&&(b=String(b),d.isIE&&\n!d.isModern&&(b=b.replace(\"&\",\"&\"),b=b.replace(\"&\",\"&\")));c={fill:c,\"font-family\":e,\"font-size\":g+\"px\",opacity:k};!0===h&&(c[\"font-weight\"]=\"bold\");c[\"text-anchor\"]=f;return a.text(b,c)};d.polygon=function(a,b,c,e,g,f,h,k,l,m,p){isNaN(f)&&(f=.01);isNaN(k)&&(k=g);var q=e,n=!1;\"object\"==typeof q&&1b&&(b=Math.abs(b),t=-b);0>c&&(c=Math.abs(c),r=-c);t+=d.dx;r+=d.dy;g={fill:q,stroke:h,\"fill-opacity\":g,\"stroke-opacity\":k};void 0!==p&&0=x&&(g=x);var u=1/180*Math.PI,x=b+Math.sin(e*u)*k,A=c-Math.cos(e*u)*w,y=b+Math.sin(e*u)*f,B=c-Math.cos(e*u)*h,D=b+Math.sin((e+g)*u)*f,C=c-Math.cos((e+g)*u)*h,I=b+Math.sin((e+g)*u)*k,u=c-Math.cos((e+g)*u)*w,H={fill:d.adjustLuminosity(m.fill,-.2),\"stroke-opacity\":0,\"fill-opacity\":m[\"fill-opacity\"]},Q=0;180Math.abs(g)&&1>=Math.abs(D-y)&&1>=Math.abs(C-B)&&(M=!0));g=\"\";var P;q&&(H[\"fill-opacity\"]=0,H[\"stroke-opacity\"]=m[\"stroke-opacity\"]/2,H.stroke=m.stroke);if(0a.length&&(a=String(a[0])+String(a[0])+String(a[1])+String(a[1])+String(a[2])+String(a[2]));b=b||0;var c=\"#\",e,g;for(g=0;3>g;g++)e=parseInt(a.substr(2*g,2),16),e=Math.round(Math.min(Math.max(0,e+e*b),255)).toString(16),c+=(\"00\"+\ne).substr(e.length);return c}})();(function(){var d=window.AmCharts;d.Bezier=d.Class({construct:function(a,b,c,e,g,f,h,k,l,m,p){var q=a.chart,n=d.bezierX,t=d.bezierY;isNaN(q.bezierX)||(n=q.bezierX);isNaN(q.bezierY)||(t=q.bezierY);isNaN(n)&&(q.rotate?(n=20,t=4):(t=20,n=4));var r,w;\"object\"==typeof h&&1=a.length-2?(f.push({x:h.x,y:h.y}),f.push({x:k.x,y:k.y}),f.push({x:l.x,y:l.y}),f.push({x:l.x,y:l.y})):(f.push({x:h.x,y:h.y}),f.push({x:k.x,y:k.y}),f.push({x:l.x,y:l.y}),f.push({x:m.x,y:m.y}));h=[];k=Math.round;h.push({x:k(f[1].x),y:k(f[1].y)});h.push({x:k((-f[0].x+b*f[1].x+f[2].x)/b),y:k((-f[0].y+c*f[1].y+f[2].y)/c)});h.push({x:k((f[1].x+b*f[2].x-f[3].x)/b),y:k((f[1].y+c*f[2].y-f[3].y)/c)});h.push({x:k(f[2].x),y:k(f[2].y)});d+=\"C\"+\nh[1].x+\",\"+h[1].y+\",\"+h[2].x+\",\"+h[2].y+\",\"+h[3].x+\",\"+h[3].y+\" \"}else 1b&&(b=10);1>c&&(c=10);this.div=a;this.width=b;this.height=c;this.rBin=document.createElement(\"div\");d.hasSVG?(d.SVG=!0,b=this.createSvgElement(\"svg\"),a.appendChild(b),this.container=b,this.addDefs(e),this.R=new d.SVGRenderer(this)):d.isIE&&d.VMLRenderer&&\n(d.VML=!0,d.vmlStyleSheet||(document.namespaces.add(\"amvml\",\"urn:schemas-microsoft-com:vml\"),31>document.styleSheets.length?(b=document.createStyleSheet(),b.addRule(\".amvml\",\"behavior:url(#default#VML); display:inline-block; antialias:true\"),d.vmlStyleSheet=b):document.styleSheets[0].addRule(\".amvml\",\"behavior:url(#default#VML); display:inline-block; antialias:true\")),this.container=a,this.R=new d.VMLRenderer(this,e),this.R.disableSelection(a))},createSvgElement:function(a){return document.createElementNS(d.SVG_NS,\na)},circle:function(a,b,c,e){var g=new d.AmDObject(\"circle\",this);g.attr({r:c,cx:a,cy:b});this.addToContainer(g.node,e);return g},ellipse:function(a,b,c,e,g){var f=new d.AmDObject(\"ellipse\",this);f.attr({rx:c,ry:e,cx:a,cy:b});this.addToContainer(f.node,g);return f},setSize:function(a,b){0c&&(c=1);1>e&&(e=1);k.attr({x:a,y:b,width:c,height:e,rx:g,ry:g,\"stroke-width\":f});this.addToContainer(k.node,h);return k},image:function(a,b,c,e,g,f){var h=new d.AmDObject(\"image\",this);h.attr({x:b,y:c,width:e,height:g});this.R.path(h,a);this.addToContainer(h.node,f);return h},addToContainer:function(a,b){b||(b=this.container);b.appendChild(a)},text:function(a,b,c){return this.R.text(a,b,c)},path:function(a,b,c,e){var g=new d.AmDObject(\"path\",this);e||(e=\"100,100\");\ng.attr({cs:e});c?g.attr({dd:a}):g.attr({d:a});this.addToContainer(g.node,b);return g},set:function(a){return this.R.set(a)},remove:function(a){if(a){var b=this.rBin;b.appendChild(a);b.innerHTML=\"\"}},renderFix:function(){var a=this.container,b=a.style;b.top=\"0px\";b.left=\"0px\";try{var c=a.getBoundingClientRect(),d=c.left-Math.round(c.left),g=c.top-Math.round(c.top);d&&(b.left=d+\"px\");g&&(b.top=g+\"px\")}catch(f){}},update:function(){this.R.update()},addDefs:function(a){if(d.hasSVG){var b=this.createSvgElement(\"desc\"),\nc=this.container;c.setAttribute(\"version\",\"1.1\");c.style.position=\"absolute\";this.setSize(this.width,this.height);if(a.accessibleTitle){var e=this.createSvgElement(\"text\");c.appendChild(e);e.innerHTML=a.accessibleTitle;e.style.opacity=0}d.rtl&&(c.setAttribute(\"direction\",\"rtl\"),c.style.left=\"auto\",c.style.right=\"0px\");a&&(a.addCodeCredits&&b.appendChild(document.createTextNode(\"JavaScript chart by amCharts \"+a.version)),c.appendChild(b),a.defs&&(b=this.createSvgElement(\"defs\"),c.appendChild(b),d.parseDefs(a.defs,\nb),this.defs=b))}}})})();(function(){var d=window.AmCharts;d.AmDObject=d.Class({construct:function(a,b){this.D=b;this.R=b.R;this.node=this.R.create(this,a);this.y=this.x=0;this.scale=1},attr:function(a){this.R.attr(this,a);return this},getAttr:function(a){return this.node.getAttribute(a)},setAttr:function(a,b){this.R.setAttr(this,a,b);return this},clipRect:function(a,b,c,d){this.R.clipRect(this,a,b,c,d)},translate:function(a,b,c,d){d||(a=Math.round(a),b=Math.round(b));this.R.move(this,a,b,c);this.x=a;this.y=b;this.scale=\nc;this.angle&&this.rotate(this.angle)},rotate:function(a,b){this.R.rotate(this,a,b);this.angle=a},animate:function(a,b,c){for(var e in a)if(a.hasOwnProperty(e)){var g=e,f=a[e];c=d.getEffect(c);this.R.animate(this,g,f,b,c)}},push:function(a){if(a){var b=this.node;b.appendChild(a.node);var c=a.clipPath;c&&b.appendChild(c);(a=a.grad)&&b.appendChild(a)}},text:function(a){this.R.setText(this,a)},remove:function(){this.stop();this.R.remove(this)},clear:function(){var a=this.node;if(a.hasChildNodes())for(;1<=\na.childNodes.length;)a.removeChild(a.firstChild)},hide:function(){this.setAttr(\"visibility\",\"hidden\")},show:function(){this.setAttr(\"visibility\",\"visible\")},getBBox:function(){return this.R.getBBox(this)},toFront:function(){var a=this.node;if(a){this.prevNextNode=a.nextSibling;var b=a.parentNode;b&&b.appendChild(a)}},toPrevious:function(){var a=this.node;a&&this.prevNextNode&&(a=a.parentNode)&&a.insertBefore(this.prevNextNode,null)},toBack:function(){var a=this.node;if(a){this.prevNextNode=a.nextSibling;\nvar b=a.parentNode;if(b){var c=b.firstChild;c&&b.insertBefore(a,c)}}},mouseover:function(a){this.R.addListener(this,\"mouseover\",a);return this},mouseout:function(a){this.R.addListener(this,\"mouseout\",a);return this},click:function(a){this.R.addListener(this,\"click\",a);return this},dblclick:function(a){this.R.addListener(this,\"dblclick\",a);return this},mousedown:function(a){this.R.addListener(this,\"mousedown\",a);return this},mouseup:function(a){this.R.addListener(this,\"mouseup\",a);return this},touchmove:function(a){this.R.addListener(this,\n\"touchmove\",a);return this},touchstart:function(a){this.R.addListener(this,\"touchstart\",a);return this},touchend:function(a){this.R.addListener(this,\"touchend\",a);return this},keyup:function(a){this.R.addListener(this,\"keyup\",a);return this},focus:function(a){this.R.addListener(this,\"focus\",a);return this},blur:function(a){this.R.addListener(this,\"blur\",a);return this},contextmenu:function(a){this.node.addEventListener?this.node.addEventListener(\"contextmenu\",a,!0):this.R.addListener(this,\"contextmenu\",\na);return this},stop:function(){d.removeFromArray(this.R.animations,this.an_translate);d.removeFromArray(this.R.animations,this.an_y);d.removeFromArray(this.R.animations,this.an_x)},length:function(){return this.node.childNodes.length},gradient:function(a,b,c){this.R.gradient(this,a,b,c)},pattern:function(a,b,c){a&&this.R.pattern(this,a,b,c)}})})();(function(){var d=window.AmCharts;d.VMLRenderer=d.Class({construct:function(a,b){this.chart=b;this.D=a;this.cNames={circle:\"oval\",ellipse:\"oval\",rect:\"roundrect\",path:\"shape\"};this.styleMap={x:\"left\",y:\"top\",width:\"width\",height:\"height\",\"font-family\":\"fontFamily\",\"font-size\":\"fontSize\",visibility:\"visibility\"}},create:function(a,b){var c;if(\"group\"==b)c=document.createElement(\"div\"),a.type=\"div\";else if(\"text\"==b)c=document.createElement(\"div\"),a.type=\"text\";else if(\"image\"==b)c=document.createElement(\"img\"),\na.type=\"image\";else{a.type=\"shape\";a.shapeType=this.cNames[b];c=document.createElement(\"amvml:\"+this.cNames[b]);var d=document.createElement(\"amvml:stroke\");c.appendChild(d);a.stroke=d;var g=document.createElement(\"amvml:fill\");c.appendChild(g);a.fill=g;g.className=\"amvml\";d.className=\"amvml\";c.className=\"amvml\"}c.style.position=\"absolute\";c.style.top=0;c.style.left=0;return c},path:function(a,b){a.node.setAttribute(\"src\",b)},setAttr:function(a,b,c){if(void 0!==c){var e;8===document.documentMode&&\n(e=!0);var g=a.node,f=a.type,h=g.style;\"r\"==b&&(h.width=2*c,h.height=2*c);\"oval\"==a.shapeType&&(\"rx\"==b&&(h.width=2*c),\"ry\"==b&&(h.height=2*c));\"roundrect\"==a.shapeType&&(\"width\"!=b&&\"height\"!=b||--c);\"cursor\"==b&&(h.cursor=c);\"cx\"==b&&(h.left=c-d.removePx(h.width)/2);\"cy\"==b&&(h.top=c-d.removePx(h.height)/2);var k=this.styleMap[b];\"width\"==k&&0>c&&(c=0);void 0!==k&&(h[k]=c);\"text\"==f&&(\"text-anchor\"==b&&(a.anchor=c,k=g.clientWidth,\"end\"==c&&(h.marginLeft=-k+\"px\"),\"middle\"==c&&(h.marginLeft=-(k/2)+\n\"px\",h.textAlign=\"center\"),\"start\"==c&&(h.marginLeft=\"0px\")),\"fill\"==b&&(h.color=c),\"font-weight\"==b&&(h.fontWeight=c));if(h=a.children)for(k=0;kc&&(h=\"dot\"),3<=c&&6>=c&&(h=\"dash\"),6h&&(b+=h);0>k&&(c+=k)}return{x:b,y:c,width:d,height:g}},setText:function(a,b){var c=a.node;c&&(c.innerHTML=b);this.setAttr(a,\"text-anchor\",a.anchor)},addListener:function(a,b,c){a.node[\"on\"+b]=c},move:function(a,b,c){var e=a.node,g=e.style;\"text\"==a.type&&(c-=d.removePx(g.fontSize)/2-1);\"oval\"==a.shapeType&&(b-=d.removePx(g.width)/2,c-=d.removePx(g.height)/2);a=a.bw;isNaN(a)||(b-=a,c-=a);isNaN(b)||isNaN(c)||(e.style.left=b+\"px\",e.style.top=\nc+\"px\")},svgPathToVml:function(a){var b=a.split(\" \");a=\"\";var c,d=Math.round,g;for(g=0;gthis.fontSize&&(this.ly=g/2-1);0n&&(n=y);u=u.height;u>t&&(t=u)}var y=t=0,B=f,D=0,C=0;for(A=0;Aq&&0C&&(C=u.height);I.translate(H,D);y++;!isNaN(l)&&y>=l&&(y=0,t++,D=D+C+m,B=f,C=0);z.push(I)}u=z.getBBox();l=u.height+2*m-1;\"left\"==a||\"right\"==a?(p=u.width+2*f,k=p+b+c,h.style.width=k+\"px\",this.ieW=k):p=k-b-c-1;c=d.polygon(this.container,[0,p,p,0],[0,0,l,l],this.backgroundColor,this.backgroundAlpha,1,this.borderColor,this.borderAlpha);d.setCN(this.chart,\nc,\"legend-bg\");w.push(c);w.translate(b,e);c.toBack();b=f;if(\"top\"==a||\"bottom\"==a||\"absolute\"==a||\"outside\"==a)\"center\"==this.align?b=f+(p-u.width)/2:\"right\"==this.align&&(b=f+p-u.width);z.translate(b,m+1);this.titleHeight>l&&(l=this.titleHeight);e=l+e+g+1;0>e&&(e=0);\"absolute\"!=a&&\"outside\"!=a&&e>this.chart.divRealHeight&&(h.style.top=\"0px\");h.style.height=Math.round(e)+\"px\";r.setSize(this.divWidth,e)},createEntry:function(a){if(!1!==a.visibleInLegend&&!a.hideFromLegend){var b=this,c=b.chart,e=b.useGraphSettings,\ng=a.markerType;g&&(e=!1);a.legendEntryWidth=b.markerSize;g||(g=b.markerType);var f=a.color,h=a.alpha;a.legendKeyColor&&(f=a.legendKeyColor());a.legendKeyAlpha&&(h=a.legendKeyAlpha());var k;!0===a.hidden&&(k=f=b.markerDisabledColor);var l=a.pattern,m,p=a.customMarker;p||(p=b.customMarker);var q=b.container,n=b.markerSize,t=0,r=0,w=n/2;if(e){e=a.type;b.switchType=void 0;if(\"line\"==e||\"step\"==e||\"smoothedLine\"==e||\"ohlc\"==e)m=q.set(),a.hidden||(f=a.lineColorR,k=a.bulletBorderColorR),t=d.line(q,[0,2*\nn],[n/2,n/2],f,a.lineAlpha,a.lineThickness,a.dashLength),d.setCN(c,t,\"graph-stroke\"),m.push(t),a.bullet&&(a.hidden||(f=a.bulletColorR),t=d.bullet(q,a.bullet,a.bulletSize,f,a.bulletAlpha,a.bulletBorderThickness,k,a.bulletBorderAlpha))&&(d.setCN(c,t,\"graph-bullet\"),t.translate(n+1,n/2),m.push(t)),w=0,t=n,r=n/3;else{a.getGradRotation&&(m=a.getGradRotation(),0===m&&(m=180));t=a.fillColorsR;!0===a.hidden&&(t=f);if(m=b.createMarker(\"rectangle\",t,a.fillAlphas,a.lineThickness,f,a.lineAlpha,m,l,a.dashLength))w=\nn,m.translate(w,n/2);t=n}d.setCN(c,m,\"graph-\"+e);d.setCN(c,m,\"graph-\"+a.id)}else if(p)m=q.image(p,0,0,n,n);else{var z;isNaN(b.gradientRotation)||(z=180+b.gradientRotation);(m=b.createMarker(g,f,h,void 0,void 0,void 0,z,l))&&m.translate(n/2,n/2)}d.setCN(c,m,\"legend-marker\");b.addListeners(m,a);q=q.set([m]);b.switchable&&a.switchable&&q.setAttr(\"cursor\",\"pointer\");void 0!==a.id&&d.setCN(c,q,\"legend-item-\"+a.id);d.setCN(c,q,a.className,!0);k=b.switchType;var x;k&&\"none\"!=k&&0c&&(d=\"00\"+c);10<=c&&100>c&&(d=\"0\"+c);a=a.replace(/fff/g,d)}return a};d.extractPeriod=function(a){var b=d.stripNumbers(a),c=1;b!=a&&(c=Number(a.slice(0,a.indexOf(b))));return{period:b,count:c}};d.getDate=function(a,b,c){return a instanceof Date?d.newDate(a,c):b&&isNaN(a)?d.stringToDate(a,b):new Date(a)};d.daysInMonth=function(a){return(new Date(a.getYear(),a.getMonth()+\n1,0)).getDate()};d.newDate=function(a,b){return b&&-1==b.indexOf(\"fff\")?new Date(a):new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours(),a.getMinutes(),a.getSeconds(),a.getMilliseconds())};d.resetDateToMin=function(a,b,c,e){void 0===e&&(e=1);var g,f,h,k,l,m,p;d.useUTC?(g=a.getUTCFullYear(),f=a.getUTCMonth(),h=a.getUTCDate(),k=a.getUTCHours(),l=a.getUTCMinutes(),m=a.getUTCSeconds(),p=a.getUTCMilliseconds(),a=a.getUTCDay()):(g=a.getFullYear(),f=a.getMonth(),h=a.getDate(),k=a.getHours(),l=\na.getMinutes(),m=a.getSeconds(),p=a.getMilliseconds(),a=a.getDay());switch(b){case \"YYYY\":g=Math.floor(g/c)*c;f=0;h=1;p=m=l=k=0;break;case \"MM\":f=Math.floor(f/c)*c;h=1;p=m=l=k=0;break;case \"WW\":h=a>=e?h-a+e:h-(7+a)+e;p=m=l=k=0;break;case \"DD\":p=m=l=k=0;break;case \"hh\":k=Math.floor(k/c)*c;p=m=l=0;break;case \"mm\":l=Math.floor(l/c)*c;p=m=0;break;case \"ss\":m=Math.floor(m/c)*c;p=0;break;case \"fff\":p=Math.floor(p/c)*c}d.useUTC?(a=new Date,a.setUTCFullYear(g,f,h),a.setUTCHours(k,l,m,p)):a=new Date(g,f,h,\nk,l,m,p);return a};d.getPeriodDuration=function(a,b){void 0===b&&(b=1);var c;switch(a){case \"YYYY\":c=316224E5;break;case \"MM\":c=26784E5;break;case \"WW\":c=6048E5;break;case \"DD\":c=864E5;break;case \"hh\":c=36E5;break;case \"mm\":c=6E4;break;case \"ss\":c=1E3;break;case \"fff\":c=1}return c*b};d.intervals={s:{nextInterval:\"ss\",contains:1E3},ss:{nextInterval:\"mm\",contains:60,count:0},mm:{nextInterval:\"hh\",contains:60,count:1},hh:{nextInterval:\"DD\",contains:24,count:2},DD:{nextInterval:\"\",contains:Infinity,count:3}};\nd.getMaxInterval=function(a,b){var c=d.intervals;return a>=c[b].contains?(a=Math.round(a/c[b].contains),b=c[b].nextInterval,d.getMaxInterval(a,b)):\"ss\"==b?c[b].nextInterval:b};d.dayNames=\"Sunday Monday Tuesday Wednesday Thursday Friday Saturday\".split(\" \");d.shortDayNames=\"Sun Mon Tue Wed Thu Fri Sat\".split(\" \");d.monthNames=\"January February March April May June July August September October November December\".split(\" \");d.shortMonthNames=\"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec\".split(\" \");\nd.getWeekNumber=function(a){a=new Date(a);a.setHours(0,0,0);a.setDate(a.getDate()+4-(a.getDay()||7));var b=new Date(a.getFullYear(),0,1);return Math.ceil(((a-b)/864E5+1)/7)};d.stringToDate=function(a,b){var c={},e=[{pattern:\"YYYY\",period:\"year\"},{pattern:\"YY\",period:\"year\"},{pattern:\"MM\",period:\"month\"},{pattern:\"M\",period:\"month\"},{pattern:\"DD\",period:\"date\"},{pattern:\"D\",period:\"date\"},{pattern:\"JJ\",period:\"hours\"},{pattern:\"J\",period:\"hours\"},{pattern:\"HH\",period:\"hours\"},{pattern:\"H\",period:\"hours\"},\n{pattern:\"KK\",period:\"hours\"},{pattern:\"K\",period:\"hours\"},{pattern:\"LL\",period:\"hours\"},{pattern:\"L\",period:\"hours\"},{pattern:\"NN\",period:\"minutes\"},{pattern:\"N\",period:\"minutes\"},{pattern:\"SS\",period:\"seconds\"},{pattern:\"S\",period:\"seconds\"},{pattern:\"QQQ\",period:\"milliseconds\"},{pattern:\"QQ\",period:\"milliseconds\"},{pattern:\"Q\",period:\"milliseconds\"}],g=!0,f=b.indexOf(\"AA\");-1!=f&&(a.substr(f,2),\"pm\"==a.toLowerCase&&(g=!1));var f=b,h,k,l;for(l=0;lr&&(r=\"0\"+r);b=b.replace(/JJ/g,r);b=b.replace(/J/g,q);r=k;0===r&&(r=24,-1!=b.indexOf(\"H\")&&(f--,0===f&&(e=new Date(a),e.setDate(e.getDate()-1),g=e.getMonth(),f=e.getDate(),e=e.getFullYear())));a=g+1;9>g&&(a=\"0\"+a);q=f;10>f&&(q=\"0\"+f);var w=r;10>w&&(w=\"0\"+w);b=b.replace(/HH/g,w);b=b.replace(/H/g,r);r=k;11w&&(w=\"0\"+w);b=b.replace(/KK/g,w);b=b.replace(/K/g,r);r=k;0===r&&(r=12);12w&&(w=\"0\"+w);b=b.replace(/LL/g,w);b=b.replace(/L/g,r);\nr=l;10>r&&(r=\"0\"+r);b=b.replace(/NN/g,r);b=b.replace(/N/g,l);l=m;10>l&&(l=\"0\"+l);b=b.replace(/SS/g,l);b=b.replace(/S/g,m);m=p;10>m?m=\"00\"+m:100>m&&(m=\"0\"+m);l=p;10>l&&(l=\"00\"+l);b=b.replace(/A/g,\"@A@\");b=b.replace(/QQQ/g,m);b=b.replace(/QQ/g,l);b=b.replace(/Q/g,p);b=b.replace(/YYYY/g,\"@IIII@\");b=b.replace(/YY/g,\"@II@\");b=b.replace(/MMMM/g,\"@XXXX@\");b=b.replace(/MMM/g,\"@XXX@\");b=b.replace(/MM/g,\"@XX@\");b=b.replace(/M/g,\"@X@\");b=b.replace(/DD/g,\"@RR@\");b=b.replace(/D/g,\"@R@\");b=b.replace(/EEEE/g,\"@PPPP@\");\nb=b.replace(/EEE/g,\"@PPP@\");b=b.replace(/EE/g,\"@PP@\");b=b.replace(/E/g,\"@P@\");b=b.replace(/@IIII@/g,e);b=b.replace(/@II@/g,n);b=b.replace(/@XXXX@/g,c.monthNames[g]);b=b.replace(/@XXX@/g,c.shortMonthNames[g]);b=b.replace(/@XX@/g,a);b=b.replace(/@X@/g,g+1);b=b.replace(/@RR@/g,q);b=b.replace(/@R@/g,f);b=b.replace(/@PPPP@/g,c.dayNames[h]);b=b.replace(/@PPP@/g,c.shortDayNames[h]);b=b.replace(/@PP@/g,t);b=b.replace(/@P@/g,h);return b=12>k?b.replace(/@A@/g,c.amString):b.replace(/@A@/g,c.pmString)};d.changeDate=\nfunction(a,b,c,e,g){if(d.useUTC)return d.changeUTCDate(a,b,c,e,g);var f=-1;void 0===e&&(e=!0);void 0===g&&(g=!1);!0===e&&(f=1);switch(b){case \"YYYY\":a.setFullYear(a.getFullYear()+c*f);e||g||a.setDate(a.getDate()+1);break;case \"MM\":b=a.getMonth();a.setMonth(a.getMonth()+c*f);a.getMonth()>b+c*f&&a.setDate(a.getDate()-1);e||g||a.setDate(a.getDate()+1);break;case \"DD\":a.setDate(a.getDate()+c*f);break;case \"WW\":a.setDate(a.getDate()+c*f*7);break;case \"hh\":a.setHours(a.getHours()+c*f);break;case \"mm\":a.setMinutes(a.getMinutes()+\nc*f);break;case \"ss\":a.setSeconds(a.getSeconds()+c*f);break;case \"fff\":a.setMilliseconds(a.getMilliseconds()+c*f)}return a};d.changeUTCDate=function(a,b,c,d,g){var f=-1;void 0===d&&(d=!0);void 0===g&&(g=!1);!0===d&&(f=1);switch(b){case \"YYYY\":a.setUTCFullYear(a.getUTCFullYear()+c*f);d||g||a.setUTCDate(a.getUTCDate()+1);break;case \"MM\":b=a.getUTCMonth();a.setUTCMonth(a.getUTCMonth()+c*f);a.getUTCMonth()>b+c*f&&a.setUTCDate(a.getUTCDate()-1);d||g||a.setUTCDate(a.getUTCDate()+1);break;case \"DD\":a.setUTCDate(a.getUTCDate()+\nc*f);break;case \"WW\":a.setUTCDate(a.getUTCDate()+c*f*7);break;case \"hh\":a.setUTCHours(a.getUTCHours()+c*f);break;case \"mm\":a.setUTCMinutes(a.getUTCMinutes()+c*f);break;case \"ss\":a.setUTCSeconds(a.getUTCSeconds()+c*f);break;case \"fff\":a.setUTCMilliseconds(a.getUTCMilliseconds()+c*f)}return a}})();\n","AmCharts.themes.light = {\n\n\tthemeName:\"light\",\n\n\tAmChart: {\n\t\tcolor: \"#000000\", backgroundColor: \"#FFFFFF\"\n\t},\n\n\tAmCoordinateChart: {\n\t\tcolors: [\"#67b7dc\", \"#fdd400\", \"#84b761\", \"#cc4748\", \"#cd82ad\", \"#2f4074\", \"#448e4d\", \"#b7b83f\", \"#b9783f\", \"#b93e3d\", \"#913167\"]\n\t},\n\n\tAmStockChart: {\n\t\tcolors: [\"#67b7dc\", \"#fdd400\", \"#84b761\", \"#cc4748\", \"#cd82ad\", \"#2f4074\", \"#448e4d\", \"#b7b83f\", \"#b9783f\", \"#b93e3d\", \"#913167\"]\n\t},\n\n\tAmSlicedChart: {\n\t\tcolors: [\"#67b7dc\", \"#fdd400\", \"#84b761\", \"#cc4748\", \"#cd82ad\", \"#2f4074\", \"#448e4d\", \"#b7b83f\", \"#b9783f\", \"#b93e3d\", \"#913167\"],\n\t\toutlineAlpha: 1,\n\t\toutlineThickness: 2,\n\t\tlabelTickColor: \"#000000\",\n\t\tlabelTickAlpha: 0.3\n\t},\n\n\tAmRectangularChart: {\n\t\tzoomOutButtonColor: '#000000',\n\t\tzoomOutButtonRollOverAlpha: 0.15,\n\t\tzoomOutButtonImage: \"lens\"\n\t},\n\n\tAxisBase: {\n\t\taxisColor: \"#000000\",\n\t\taxisAlpha: 0.3,\n\t\tgridAlpha: 0.1,\n\t\tgridColor: \"#000000\"\n\t},\n\n\tChartScrollbar: {\n\t\tbackgroundColor: \"#000000\",\n\t\tbackgroundAlpha: 0.12,\n\t\tgraphFillAlpha: 0.5,\n\t\tgraphLineAlpha: 0,\n\t\tselectedBackgroundColor: \"#FFFFFF\",\n\t\tselectedBackgroundAlpha: 0.4,\n\t\tgridAlpha: 0.15\n\t},\n\n\tChartCursor: {\n\t\tcursorColor: \"#000000\",\n\t\tcolor: \"#FFFFFF\",\n\t\tcursorAlpha: 0.5\n\t},\n\n\tAmLegend: {\n\t\tcolor: \"#000000\"\n\t},\n\n\tAmGraph: {\n\t\tlineAlpha: 0.9\n\t},\n\tGaugeArrow: {\n\t\tcolor: \"#000000\",\n\t\talpha: 0.8,\n\t\tnailAlpha: 0,\n\t\tinnerRadius: \"40%\",\n\t\tnailRadius: 15,\n\t\tstartWidth: 15,\n\t\tborderAlpha: 0.8,\n\t\tnailBorderAlpha: 0\n\t},\n\n\tGaugeAxis: {\n\t\ttickColor: \"#000000\",\n\t\ttickAlpha: 1,\n\t\ttickLength: 15,\n\t\tminorTickLength: 8,\n\t\taxisThickness: 3,\n\t\taxisColor: '#000000',\n\t\taxisAlpha: 1,\n\t\tbandAlpha: 0.8\n\t},\n\n\tTrendLine: {\n\t\tlineColor: \"#c03246\",\n\t\tlineAlpha: 0.8\n\t},\n\n\t// ammap\n\tAreasSettings: {\n\t\talpha: 0.8,\n\t\tcolor: \"#67b7dc\",\n\t\tcolorSolid: \"#003767\",\n\t\tunlistedAreasAlpha: 0.4,\n\t\tunlistedAreasColor: \"#000000\",\n\t\toutlineColor: \"#FFFFFF\",\n\t\toutlineAlpha: 0.5,\n\t\toutlineThickness: 0.5,\n\t\trollOverColor: \"#3c5bdc\",\n\t\trollOverOutlineColor: \"#FFFFFF\",\n\t\tselectedOutlineColor: \"#FFFFFF\",\n\t\tselectedColor: \"#f15135\",\n\t\tunlistedAreasOutlineColor: \"#FFFFFF\",\n\t\tunlistedAreasOutlineAlpha: 0.5\n\t},\n\n\tLinesSettings: {\n\t\tcolor: \"#000000\",\n\t\talpha: 0.8\n\t},\n\n\tImagesSettings: {\n\t\talpha: 0.8,\n\t\tlabelColor: \"#000000\",\n\t\tcolor: \"#000000\",\n\t\tlabelRollOverColor: \"#3c5bdc\"\n\t},\n\n\tZoomControl: {\n\t\tbuttonFillAlpha:0.7,\n\t\tbuttonIconColor:\"#a7a7a7\"\n\t},\n\n\tSmallMap: {\n\t\tmapColor: \"#000000\",\n\t\trectangleColor: \"#f15135\",\n\t\tbackgroundColor: \"#FFFFFF\",\n\t\tbackgroundAlpha: 0.7,\n\t\tborderThickness: 1,\n\t\tborderAlpha: 0.8\n\t},\n\n\t// the defaults below are set using CSS syntax, you can use any existing css property\n\t// if you don't use Stock chart, you can delete lines below\n\tPeriodSelector: {\n\t\tcolor: \"#000000\"\n\t},\n\n\tPeriodButton: {\n\t\tcolor: \"#000000\",\n\t\tbackground: \"transparent\",\n\t\topacity: 0.7,\n\t\tborder: \"1px solid rgba(0, 0, 0, .3)\",\n\t\tMozBorderRadius: \"5px\",\n\t\tborderRadius: \"5px\",\n\t\tmargin: \"1px\",\n\t\toutline: \"none\",\n\t\tboxSizing: \"border-box\"\n\t},\n\n\tPeriodButtonSelected: {\n\t\tcolor: \"#000000\",\n\t\tbackgroundColor: \"#b9cdf5\",\n\t\tborder: \"1px solid rgba(0, 0, 0, .3)\",\n\t\tMozBorderRadius: \"5px\",\n\t\tborderRadius: \"5px\",\n\t\tmargin: \"1px\",\n\t\toutline: \"none\",\n\t\topacity: 1,\n\t\tboxSizing: \"border-box\"\n\t},\n\n\tPeriodInputField: {\n\t\tcolor: \"#000000\",\n\t\tbackground: \"transparent\",\n\t\tborder: \"1px solid rgba(0, 0, 0, .3)\",\n\t\toutline: \"none\"\n\t},\n\n\tDataSetSelector: {\n\n\t\tcolor: \"#000000\",\n\t\tselectedBackgroundColor: \"#b9cdf5\",\n\t\trollOverBackgroundColor: \"#a8b0e4\"\n\t},\n\n\tDataSetCompareList: {\n\t\tcolor: \"#000000\",\n\t\tlineHeight: \"100%\",\n\t\tboxSizing: \"initial\",\n\t\twebkitBoxSizing: \"initial\",\n\t\tborder: \"1px solid rgba(0, 0, 0, .3)\"\n\t},\n\n\tDataSetSelect: {\n\t\tborder: \"1px solid rgba(0, 0, 0, .3)\",\n\t\toutline: \"none\"\n\t}\n\n};","(function(){var f=window.AmCharts;f.AmRectangularChart=f.Class({inherits:f.AmCoordinateChart,construct:function(a){f.AmRectangularChart.base.construct.call(this,a);this.theme=a;this.createEvents(\"zoomed\",\"changed\");this.marginRight=this.marginBottom=this.marginTop=this.marginLeft=20;this.depth3D=this.angle=0;this.plotAreaFillColors=\"#FFFFFF\";this.plotAreaFillAlphas=0;this.plotAreaBorderColor=\"#000000\";this.plotAreaBorderAlpha=0;this.maxZoomFactor=20;this.zoomOutButtonImageSize=19;this.zoomOutButtonImage=\n\"lens\";this.zoomOutText=\"Show all\";this.zoomOutButtonColor=\"#e5e5e5\";this.zoomOutButtonAlpha=0;this.zoomOutButtonRollOverAlpha=1;this.zoomOutButtonPadding=8;this.trendLines=[];this.autoMargins=!0;this.marginsUpdated=!1;this.autoMarginOffset=10;f.applyTheme(this,a,\"AmRectangularChart\")},initChart:function(){f.AmRectangularChart.base.initChart.call(this);this.updateDxy();!this.marginsUpdated&&this.autoMargins&&(this.resetMargins(),this.drawGraphs=!1);this.processScrollbars();this.updateMargins();this.updatePlotArea();\nthis.updateScrollbars();this.updateTrendLines();this.updateChartCursor();this.updateValueAxes();this.scrollbarOnly||this.updateGraphs()},drawChart:function(){f.AmRectangularChart.base.drawChart.call(this);this.drawPlotArea();if(f.ifArray(this.chartData)){var a=this.chartCursor;a&&a.draw()}},resetMargins:function(){var a={},b;if(\"xy\"==this.type){var c=this.xAxes,d=this.yAxes;for(b=0;b=g-c&&(this.marginRight=Math.round(k-g+c),!isNaN(this.minMarginRight)&&this.marginRighth-c&&(this.marginBottom=Math.round(this.marginBottom+b-h+c),!isNaN(this.minMarginBottom)&&\nthis.marginBottoma&&(d=a);break;case \"bottom\":a=h.y+h.height;ga&&(b=a)}}return{l:b,t:d,r:c,b:g}},drawZoomOutButton:function(){var a=this;if(!a.zbSet){var b=a.container.set();\na.zoomButtonSet.push(b);var c=a.color,d=a.fontSize,g=a.zoomOutButtonImageSize,h=a.zoomOutButtonImage.replace(/\\.[a-z]*$/i,\"\"),e=a.langObj.zoomOutText||a.zoomOutText,l=a.zoomOutButtonColor,k=a.zoomOutButtonAlpha,m=a.zoomOutButtonFontSize,p=a.zoomOutButtonPadding;isNaN(m)||(d=m);(m=a.zoomOutButtonFontColor)&&(c=m);var m=a.zoomOutButton,n;m&&(m.fontSize&&(d=m.fontSize),m.color&&(c=m.color),m.backgroundColor&&(l=m.backgroundColor),isNaN(m.backgroundAlpha)||(a.zoomOutButtonRollOverAlpha=m.backgroundAlpha));\nvar u=m=0,u=a.pathToImages;if(h){if(f.isAbsolute(h)||void 0===u)u=\"\";n=a.container.image(u+h+a.extension,0,0,g,g);f.setCN(a,n,\"zoom-out-image\");b.push(n);n=n.getBBox();m=n.width+5}void 0!==e&&(c=f.text(a.container,e,c,a.fontFamily,d,\"start\"),f.setCN(a,c,\"zoom-out-label\"),d=c.getBBox(),u=n?n.height/2-3:d.height/2,c.translate(m,u),b.push(c));n=b.getBBox();c=1;f.isModern||(c=0);l=f.rect(a.container,n.width+2*p+5,n.height+2*p-2,l,1,1,l,c);l.setAttr(\"opacity\",k);l.translate(-p,-p);f.setCN(a,l,\"zoom-out-bg\");\nb.push(l);l.toBack();a.zbBG=l;n=l.getBBox();b.translate(a.marginLeftReal+a.plotAreaWidth-n.width+p,a.marginTopReal+p);b.hide();b.mouseover(function(){a.rollOverZB()}).mouseout(function(){a.rollOutZB()}).click(function(){a.clickZB()}).touchstart(function(){a.rollOverZB()}).touchend(function(){a.rollOutZB();a.clickZB()});for(k=0;ka&&(a=1);1>b&&(b=1);this.plotAreaWidth=Math.round(a);this.plotAreaHeight=Math.round(b);\nthis.plotBalloonsSet.translate(c,d)},updateDxy:function(){this.dx=Math.round(this.depth3D*Math.cos(this.angle*Math.PI/180));this.dy=Math.round(-this.depth3D*Math.sin(this.angle*Math.PI/180));this.d3x=Math.round(this.columnSpacing3D*Math.cos(this.angle*Math.PI/180));this.d3y=Math.round(-this.columnSpacing3D*Math.sin(this.angle*Math.PI/180))},updateMargins:function(){var a=this.getTitleHeight();this.titleHeight=a;this.marginTopReal=this.marginTop-this.dy;this.fixMargins&&!this.fixMargins.top&&(this.marginTopReal+=\na);this.marginBottomReal=this.marginBottom;this.marginLeftReal=this.marginLeft;this.marginRightReal=this.marginRight},updateValueAxes:function(){var a=this.valueAxes,b;for(b=0;bd)var g=c,c=d,d=g;this.relativeZoomValueAxes(b,c,d);this.updateAfterValueZoom()},\nupdateAfterValueZoom:function(){this.zoomAxesAndGraphs();this.zoomScrollbar()},relativeZoomValueAxes:function(a,b,c){this.hideBalloonReal();b=f.fitToBounds(b,0,1);c=f.fitToBounds(c,0,1);if(b>c){var d=b;b=c;c=d}var d=1/this.maxZoomFactor,g=f.getDecimals(d)+4;c-bb&&(b=0,c=d));b=f.roundTo(b,g);c=f.roundTo(c,g);d=!1;if(a){for(g=0;gb.min-g*b.step&&(e+=g,g=0);0>=b.max&&0k&&(k=1);h*=k;e*=k;if(!d||c.equalSpacing)h=Math.round(h),e=Math.round(e)}f=this.chartData.length;c=this.lastTime;k=this.firstTime;0>a?d?(f=this.endTime-this.startTime,d=this.startTime+h*g,g=this.endTime+e*g,0=c&&(g=c,d=c-f),this.zoomToDates(new Date(d),new Date(g))):(0=f-1&&(h=e=0),d=this.start+h,g=this.end+e,this.zoomToIndexes(d,g)):d?(f=this.endTime-this.startTime,d=this.startTime-h*g,g=this.endTime-\ne*g,0this.start&&(h=e=0),d=this.start-h,g=this.end-e,this.zoomToIndexes(d,g))}},validateData:function(a){this.marginsUpdated=!1;this.zoomOutOnDataUpdate&&!a&&(this.endTime=this.end=this.startTime=this.start=NaN);var b=a=!1,c=!1,d=this.chartScrollbar;d&&(d.dragging&&(a=!0,d.handleDragStop()),d.resizingRight&&(c=!0,d.rightDragStop()),d.resizingLeft&&(b=!0,d.leftDragStop()));f.AmSerialChart.base.validateData.call(this);\na&&d.handleDragStart();c&&d.rightDragStart();b&&d.leftDragStart()},drawChart:function(){if(0c&&(a=b-c),a!=this.startTime&&b-a>c&&(b=a+c));var d=this.minSelectedTime;if(0l&&(a=l);bl&&(b=l);bthis.firstTime&&(a=!0),this.endTimec&&(a=b-c,d=!0),a!=this.start&&b-a>c&&(b=a+c,d=!0));if(d&&(d=this.chartScrollbar)&&d.dragger){var g=d.dragger.getBBox();d.maxWidth=\ng.width;d.maxHeight=g.height}if(a!=this.start||b!=this.end)d=this.chartData.length-1,isNaN(a)&&(a=0,isNaN(c)||(a=d-c)),isNaN(b)&&(b=d),bd&&(b=d),a>d&&(a=d-1),0>a&&(a=0),this.start=a,this.end=b,this.categoryAxis.zoom(a,b),this.zoomAxesAndGraphs(),this.zoomScrollbar(),this.fixCursor(),0!==a||b!=this.chartData.length-1?this.showZB(!0):this.showZB(!1),this.syncGrid(),this.updateColumnsDepth(),this.dispatchIndexZoomEvent()},updateGraphs:function(){f.AmSerialChart.base.updateGraphs.call(this);\nvar a=this.graphs,b;for(b=0;bb.depth?1:-1},zoomScrollbar:function(){var a=this.chartScrollbar,b=this.categoryAxis;if(a){if(!this.zoomedByScrollbar){var c=a.dragger;c&&c.stop()}this.zoomedByScrollbar=!1;b.parseDates&&!b.equalSpacing?a.timeZoom(this.startTime,\nthis.endTime):a.zoom(this.start,this.end)}this.zoomValueScrollbar(this.valueScrollbar)},updateTrendLines:function(){var a=this.trendLines,b;for(b=0;bg&&(g=0);f>a.length-1&&(f=a.length-1);var e=g+Math.round((f-g)/2),l=a[e][b];return c==l?e:1>=f-g?d?g:Math.abs(a[g][b]-c)a&&(a=0),b>d-1&&(b=d-1),d=this.categoryAxis,d.parseDates&&!d.equalSpacing?this.zoom(c[a].time,this.getEndTime(c[b].time)):this.zoom(a,b))}},zoomToDates:function(a,b){var c=this.chartData;if(c)if(this.categoryAxis.equalSpacing){var d=this.getClosestIndex(c,\"time\",a.getTime(),!0,0,c.length);b=f.resetDateToMin(b,this.categoryAxis.minPeriod,1);c=this.getClosestIndex(c,\"time\",b.getTime(),\n!1,0,c.length);this.zoom(d,c)}else this.zoom(a.getTime(),b.getTime())},zoomToCategoryValues:function(a,b){this.chartData&&this.zoom(this.getCategoryIndexByValue(a),this.getCategoryIndexByValue(b))},formatPeriodString:function(a,b){if(b){b.periodDataItem={};b.periodPercentDataItem={};var c=[\"value\",\"open\",\"low\",\"high\",\"close\"],d=\"value open low high close average sum count\".split(\" \"),g=b.valueAxis,h=this.chartData,e=b.numberFormatter;e||(e=this.nf);for(var l=0;lD||D>A.graph.height)z=NaN}else if(0>D||D>A.graph.width)z=NaN;if(!isNaN(z)){isNaN(v)&&(v=z);x=z;if(isNaN(E)||E>z)E=z;if(isNaN(t)||tA)w=A;if(isNaN(y)||\nyb&&0===p&&(p=180):0>c&&270==p&&(p=90);this.gradientRotation=p;0===d&&0===f&&(this.cornerRadius=n);this.draw()},draw:function(){var a=this.set;a.clear();\nvar b=this.container,c=b.chart,d=this.w,g=this.h,h=this.dx,e=this.dy,l=this.colors,k=this.alpha,m=this.bwidth,p=this.bcolor,n=this.balpha,u=this.gradientRotation,v=this.cornerRadius,x=this.dashLength,E=this.pattern,t=this.topRadius,r=this.bcn,B=l,q=l;\"object\"==typeof l&&(B=l[0],q=l[l.length-1]);var w,y,C,F,D,A,z,L,M,Q=k;E&&(k=0);var G,H,I,J,K=this.rotate;if(0Math.abs(g)&&(g=0);1>Math.abs(d)&&(d=0);!isNaN(t)&&(0g&&(m=\" A\"),k+=m+Math.round(d/2-I)+\",\"+Math.round(g-J)+\",\"+Math.round(d/2+I)+\",\"+Math.round(g+J)+\",0,\"+g+\",\"+d+\",\"+g,k+=\" L\"+d+\",0\",k+=m+Math.round(d/\n2+G)+\",\"+Math.round(H)+\",\"+Math.round(d/2-G)+\",\"+Math.round(-H)+\",\"+d+\",0,0,0\"):(k+=\"A\"+I+\",\"+J+\",0,0,0,\"+(d-d/2*(1-t))+\",\"+g+\"L\"+d+\",0\",k+=\"A\"+G+\",\"+H+\",0,0,1,0,0\"),G=180),b=b.path(k).attr(l),b.gradient(\"linearGradient\",[B,f.adjustLuminosity(B,-.3),f.adjustLuminosity(B,-.3),B],G),K?b.translate(h/2,0):b.translate(0,e/2)):b=0===g?f.line(b,[0,d],[0,0],p,n,m,x):0===d?f.line(b,[0,0],[0,g],p,n,m,x):0g?[w,\nM,y,C,F,D,A,z,L,b]:[z,L,y,C,F,D,w,M,A,b]:K?0g?[w,b,z]:[z,b,w];f.setCN(c,b,r+\"front\");f.setCN(c,y,r+\"back\");f.setCN(c,z,r+\"top\");f.setCN(c,w,r+\"bottom\");f.setCN(c,F,r+\"left\");f.setCN(c,D,r+\"right\");for(w=0;wb&&(this.endTime=b);r=this.minorGridEnabled;x=this.gridAlpha;var y=0,C=0;if(this.widthField)for(b=this.start;b<=this.end;b++)if(t=this.data[b]){var F=Number(this.data[b].dataContext[this.widthField]);isNaN(F)||(y+=F,t.widthValue=F)}if(this.parseDates&&!this.equalSpacing)this.lastTime=a[a.length-1].time,this.maxTime=f.resetDateToMin(new Date(this.lastTime+1.05*u),this.minPeriod,\n1,q).getTime(),this.timeDifference=this.endTime-this.startTime,this.parseDatesDraw();else if(!this.parseDates){if(this.cellWidth=this.getStepWidth(e),ee&&(e=0),w=0,this.widthField&&(e=this.start),this.end-e+1>=this.autoRotateCount&&(this.labelRotationR=this.autoRotateAngle),b=e;b<=this.end+2;b++){l=!1;0<=b&&bthis.end&&\"start\"==this.tickPosition&&(n=\" \");this.rotate&&this.inside&&(l-=2);isNaN(v.widthValue)||(v.percentWidthValue=v.widthValue/y*100,a=this.rotate?this.height*v.widthValue/y:this.width*v.widthValue/y,e=C,C+=a,E=l=a/2);p=new this.axisItemRenderer(this,e,n,p,a,l,void 0,u,E,!1,v.labelColor,v.className);p.serialDataItem=v;this.pushAxisItem(p);\nthis.gridAlpha=x}}else if(this.parseDates&&this.equalSpacing){h=this.start;this.startTime=this.data[this.start].time;this.endTime=this.data[this.end].time;this.timeDifference=this.endTime-this.startTime;b=this.choosePeriod(0);g=b.period;v=b.count;b=f.getPeriodDuration(g,v);be&&(e=0);C=this.end+2;C>=this.data.length&&(C=this.data.length);a=!1;a=!k;this.previousPos=-1E3;20=F){e=this.getCoordinate(b-this.start);r=!1;this.nextPeriod[x]&&(r=this.checkPeriodChange(this.nextPeriod[x],1,t,n,x))&&f.resetDateToMin(new Date(t),this.nextPeriod[x],1,q).getTime()!=t&&(r=!1);u=!1;r&&this.markPeriodChange?(r=this.dateFormatsObject[this.nextPeriod[x]],u=!0):r=this.dateFormatsObject[x];n=f.formatDate(new Date(t),r,c);if(b==d&&!k||b==l&&!m)n=\" \";a?a=!1:(w||(u=!1),\ne-this.previousPos>this.safeDistance*Math.cos(this.labelRotationR*Math.PI/180)&&(this.labelFunction&&(n=this.labelFunction(n,new Date(t),this,g,v,E)),this.boldLabels&&(u=!0),p=new this.axisItemRenderer(this,e,n,void 0,void 0,void 0,void 0,u),r=p.graphics(),this.pushAxisItem(p),r=r.getBBox().width,f.isModern||(r-=e),this.previousPos=e+r));E=n=t}}for(b=k=0;bthis.height+1&&h--:l>this.width+1&&h--;0>l&&h++;return h=f.fitToBounds(h,0,b.length-1)},\ndateToCoordinate:function(a){return this.parseDates&&!this.equalSpacing?(a.getTime()-this.startTime)*this.stepWidth:this.parseDates&&this.equalSpacing?(a=this.chart.getClosestIndex(this.data,\"time\",a.getTime(),!1,0,this.data.length-1),this.getCoordinate(a-this.start)):NaN},categoryToCoordinate:function(a){if(this.chart){if(this.parseDates)return this.dateToCoordinate(new Date(a));a=this.chart.getCategoryIndexByValue(a);if(!isNaN(a))return this.getCoordinate(a-this.start)}else return NaN},coordinateToDate:function(a){return this.equalSpacing?\n(a=this.xToIndex(a),new Date(this.data[a].time)):new Date(this.startTime+a/this.stepWidth)},coordinateToValue:function(a){a=this.xToIndex(a);if(a=this.data[a])return this.parseDates?a.time:a.category},getCoordinate:function(a){a*=this.stepWidth;this.startOnAxis||(a+=this.stepWidth/2);return Math.round(a)},formatValue:function(a,b){b||(b=this.currentDateFormat);this.parseDates&&(a=f.formatDate(new Date(a),b,this.chart));return a},showBalloonAt:function(a,b){void 0===b&&(b=this.parseDates?this.dateToCoordinate(new Date(a)):\nthis.categoryToCoordinate(a));return this.adjustBalloonCoordinate(b)},formatBalloonText:function(a,b,c){var d=\"\",g=\"\",h=this.chart,e=this.data[b];if(e)if(this.parseDates)d=f.formatDate(e.category,c,h),b=f.changeDate(new Date(e.category),this.minPeriod,1),g=f.formatDate(b,c,h),-1!=d.indexOf(\"fff\")&&(d=f.formatMilliseconds(d,e.category),g=f.formatMilliseconds(g,b));else{var l;this.data[b+1]&&(l=this.data[b+1]);d=f.fixNewLines(e.category);l&&(g=f.fixNewLines(l.category))}a=a.replace(/\\[\\[category\\]\\]/g,\nString(d));return a=a.replace(/\\[\\[toCategory\\]\\]/g,String(g))},adjustBalloonCoordinate:function(a,b){var c=this.xToIndex(a),d=this.chart.chartCursor;if(this.stickBalloonToCategory){var f=this.data[c];f&&(a=f.x[this.id]+1);this.stickBalloonToStart&&(a-=this.cellWidth/2);var h=0;if(d){var e=d.limitToGraph;if(e){var l=e.valueAxis.id;e.hidden||(h=f.axes[l].graphs[e.id].y)}this.rotate?(\"left\"==this.position?(e&&(h-=d.width),0h&&(h=0),d.fixHLine(a,h)):(\"top\"==this.position?(e&&(h-=d.height),\n0h&&(h=0),d.fixVLine(a,h))}}d&&!b&&(d.setIndex(c),this.parseDates&&d.setTimestamp(this.coordinateToDate(a).getTime()));return a}})})();\n","(function(){var e=window.AmCharts;e.AmStockChart=e.Class({construct:function(a){this.type=\"stock\";this.cname=\"AmStockChart\";e.addChart(this);this.version=\"3.21.6\";this.theme=a;this.createEvents(\"buildStarted\",\"zoomed\",\"rollOverStockEvent\",\"rollOutStockEvent\",\"clickStockEvent\",\"panelRemoved\",\"dataUpdated\",\"init\",\"rendered\",\"drawn\",\"resized\");this.colors=\"#FF6600 #FCD202 #B0DE09 #0D8ECF #2A0CD0 #CD0D74 #CC0000 #00CC00 #0000CC #DDDDDD #999999 #333333 #990000\".split(\" \");this.firstDayOfWeek=1;this.glueToTheEnd=!1;this.dataSetCounter=-1;this.zoomOutOnDataSetChange=!1;this.panels=[];this.dataSets=[];this.chartCursors=[];this.comparedDataSets=[];this.classNamePrefix=\"amcharts\";this.categoryAxesSettings=new e.CategoryAxesSettings(a);this.valueAxesSettings=new e.ValueAxesSettings(a);this.panelsSettings=new e.PanelsSettings(a);this.chartScrollbarSettings=new e.ChartScrollbarSettings(a);this.chartCursorSettings=new e.ChartCursorSettings(a);this.stockEventsSettings=new e.StockEventsSettings(a);this.legendSettings=new e.LegendSettings(a);this.balloon=new e.AmBalloon(a);this.previousEndDate=new Date(0);this.previousStartDate=new Date(0);this.dataSetCount=this.graphCount=0;this.chartCreated=!1;this.processTimeout=0;this.autoResize=this.extendToFullPeriod=!0;this.langObj={};e.applyTheme(this,a,this.cname)},write:function(a){var b=this;if(b.listeners)for(var c in b.listeners){var d=b.listeners[c];b.addListener(d.event,d.method)}b.fire({type:\"buildStarted\",chart:b});b.afterWriteTO&&clearTimeout(b.afterWriteTO);0c?this.colors[c]:e.randomColor())}!a&&e.ifArray(b)&&(this.mainDataSet=this.dataSets[0]);this.getSelections()},getLastDate:function(a){var b=e.getDate(a,this.dataDateFormat,\"fff\");a=this.categoryAxesSettings.minPeriod;var c=e.extractPeriod(a),b=e.changeDate(b,c.period,1*c.count,!0).getTime();-1==a.indexOf(\"fff\")&&--b;return new Date(b)},getFirstDate:function(a){a=e.getDate(a,this.dataDateFormat,\"fff\");var b=e.extractPeriod(this.categoryAxesSettings.minPeriod);return new Date(e.resetDateToMin(a,b.period,1*b.count,this.firstDayOfWeek))},updateData:function(){var a=this,b=a.mainDataSet;if(b){a.parsingData=!1;var c=a.categoryAxesSettings;-1==e.getItemIndex(c.minPeriod,c.groupToPeriods)&&c.groupToPeriods.unshift(c.minPeriod);var d=b.dataProvider;if(e.ifArray(d)){var k=b.categoryField;a.firstDate=a.getFirstDate(d[0][k]);a.lastDate=a.getLastDate(d[d.length-1][k]);a.periodSelector&&a.periodSelector.setRanges(a.firstDate,a.lastDate);b.dataParsed||(a.parsingData=!0,0=y[p]||!y[p]){v[p]={};v[p].amCategoryIdField=String(e.resetDateToMin(D,F,G,d).getTime());var H;for(H=0;Hf&&(u=e.newDate(D,b),u=e.changeDate(u,F,G,!0),u=e.resetDateToMin(u,F,G,d),y[p]=u.getTime());if(z==f)for(var I in B)B.hasOwnProperty(I)&&(v[p][I]=B[I]);v[p][n]=e.newDate(D,b)}else for(w=v[p],w.rawData&&w.rawData.push(B),p=0;pw[u+\"High\"]&&(w[u+\"High\"]=x),isNaN(w[u+\"AbsHigh\"])&&(w[u+\"AbsHigh\"]=x),Math.abs(x)>w[u+\"AbsHigh\"]&&(w[u+\"AbsHigh\"]=x),w[u+\"Close\"]=x,F=e.getDecimals(w[u+\"Sum\"]),G=e.getDecimals(x),isNaN(w[u+\"Sum\"])&&(w[u+\"Sum\"]=0),w[u+\"Sum\"]+=x,w[u+\"Sum\"]=e.roundTo(w[u+\"Sum\"],Math.max(F,G)),w[u+\"Count\"]++,w[u+\"Average\"]=w[u+\"Sum\"]/w[u+\"Count\"]))}}}a.agregatedDataProviders=l;e.ifArray(a.stockEvents)?0=q&&a=k-d))return a<\nq?this.getEventDataItem(a,b,c,d,n,g):this.getEventDataItem(a,b,c,n,k,g)},createLayout:function(){var a=this.div,b,c,d=this.classNamePrefix,e=document.createElement(\"div\");e.style.position=\"relative\";this.containerDiv=e;e.className=d+\"-stock-div\";a.appendChild(e);if(a=this.periodSelector)b=a.position;if(a=this.dataSetSelector)c=a.position;if(\"left\"==b||\"left\"==c)a=document.createElement(\"div\"),a.className=d+\"-left-div\",a.style.cssFloat=\"left\",a.style.styleFloat=\"left\",a.style.width=\"0px\",a.style.position=\"absolute\",e.appendChild(a),this.leftContainer=a;if(\"right\"==b||\"right\"==c)b=document.createElement(\"div\"),b.className=d+\"-right-div\",b.style.cssFloat=\"right\",b.style.styleFloat=\"right\",b.style.width=\"0px\",e.appendChild(b),this.rightContainer=b;b=document.createElement(\"div\");b.className=d+\"-center-div\";e.appendChild(b);this.centerContainer=b;e=document.createElement(\"div\");e.className=d+\"-panels-div\";b.appendChild(e);this.panelsContainer=e},addPanels:function(){this.measurePanels(!0);for(var a=this.panels,b=0;bg.getTime()&&(a=g);b.getTime()g.getTime()&&(b=g);n=e.getItemIndex(n,h.groupToPeriods);h=l;l=c.choosePeriod(n,a,b);c.currentPeriod=l;var n=e.extractPeriod(l),A=e.getPeriodDuration(n.period,n.count);1>b.getTime()-a.getTime()&&(a=new Date(b.getTime()-1));v=e.newDate(a);c.extendToFullPeriod&&(v.getTime()-k.getTime()<.1*A&&(v=e.resetDateToMin(a,n.period,n.count,y)),g.getTime()-b.getTime()<.1*A&&(b=e.resetDateToMin(g,n.period,n.count,y),b=e.changeDate(b,n.period,n.count,!0)));for(k=0;km&&0\";var l=a.firstChild;a=b.theme;k=b.position;k=\"top\"==k||\"bottom\"==k?!1:!0;b.vertical=k;var h=g=0;if(b.inputFieldsEnabled){var n=document.createElement(\"div\");l.appendChild(n);var f=document.createTextNode(c.langObj.fromText||b.fromText);n.appendChild(f);k?e.addBr(n):(n.style.styleFloat=\"left\",n.style.display=\"inline\");var m=document.createElement(\"input\");m.setAttribute(\"aria-label\",c.langObj.fromText||b.fromText);m.className=\"amChartsInputField \"+d+\"-start-date-input\";a&&e.applyStyles(m.style,a.PeriodInputField);m.style.textAlign=\"center\";m.onblur=function(a){b.handleCalChange(a)};e.isNN&&m.addEventListener(\"keypress\",function(a){b.handleCalendarChange.call(b,a)},!0);e.isIE&&m.attachEvent(\"onkeypress\",function(a){b.handleCalendarChange.call(b,a)});n.appendChild(m);b.startDateField=m;if(k)f=b.width-6+\"px\",e.addBr(n);else{var f=b.inputFieldWidth+\"px\",q=document.createTextNode(\" \");n.appendChild(q)}m.style.width=f;m=document.createTextNode(c.langObj.toText||b.toText);n.appendChild(m);k&&e.addBr(n);m=document.createElement(\"input\");m.setAttribute(\"aria-label\",c.langObj.toText||b.toText);m.className=\"amChartsInputField \"+d+\"-end-date-input\";a&&e.applyStyles(m.style,a.PeriodInputField);m.style.textAlign=\"center\";m.onblur=function(){b.handleCalChange()};e.isNN&&m.addEventListener(\"keypress\",function(a){b.handleCalendarChange.call(b,a)},!0);e.isIE&&m.attachEvent(\"onkeypress\",function(a){b.handleCalendarChange.call(b,a)});n.appendChild(m);b.endDateField=m;k?e.addBr(n):g=m.offsetHeight+2;f&&(m.style.width=f)}n=b.periods;if(e.ifArray(n)){f=document.createElement(\"div\");k||(f.style.cssFloat=\"right\",f.style.styleFloat=\"right\",f.style.display=\"inline\");l.appendChild(f);k&&e.addBr(f);c=document.createTextNode(c.langObj.periodsText||b.periodsText);f.appendChild(c);b.periodContainer=f;for(var t,c=0;cm.getTime()&&(q=e.getPeriodDuration(\"DD\",1),h=new Date(m.getTime()-q)),h.getTime()k&&(d=k);k=this.theme;this.unselectButtons();var g;for(g=b.length-1;0<=g;g--){var l=b[g],h=l.button;l.startTime&&l.endTime&&c==l.startTime&&d==l.endTime&&(this.unselectButtons(),h.className=\"amChartsButtonSelected \"+a.classNamePrefix+\"-period-input-selected\",k&&e.applyStyles(h.style,k.PeriodButtonSelected))}}this.skipMark=!1},unselectButtons:function(){var a=this.chart,b=this.periods,c,d=this.theme;for(c=b.length-1;0<=c;c--){var k=b[c].button;k.className=\"amChartsButton \"+a.classNamePrefix+\"-period-input\";d&&e.applyStyles(k.style,d.PeriodButton)}},setDefaultPeriod:function(){var a=this.periods,b;if(this.chart.chartCreated)for(b=0;bg&&(g=.005),0>a?(d=c.percentStart+d*g,e=c.percentEnd+e*g):(d=c.percentStart-d*g,e=c.percentEnd-e*g),e>d&&c.percentZoom(d,e,!0)}}})})();(function(){var e=window.AmCharts;e.CategoryAxesSettings=e.Class({construct:function(a){this.cname=\"CategoryAxesSettings\";this.minPeriod=\"DD\";this.equalSpacing=!1;this.axisHeight=28;this.tickLength=this.axisAlpha=0;this.gridCount=10;this.maxSeries=150;this.groupToPeriods=\"ss 10ss 30ss mm 10mm 30mm hh DD WW MM YYYY\".split(\" \");this.markPeriodChange=this.autoGridCount=!0;e.applyTheme(this,a,this.cname)}})})();(function(){var e=window.AmCharts;e.ChartCursorSettings=e.Class({construct:function(a){this.cname=\"ChartCursorSettings\";this.enabled=!0;this.bulletsEnabled=this.valueBalloonsEnabled=!1;this.graphBulletSize=1;this.onePanelOnly=!1;this.categoryBalloonDateFormats=[{period:\"YYYY\",format:\"YYYY\"},{period:\"MM\",format:\"MMM, YYYY\"},{period:\"WW\",format:\"MMM DD, YYYY\"},{period:\"DD\",format:\"MMM DD, YYYY\"},{period:\"hh\",format:\"JJ:NN\"},{period:\"mm\",format:\"JJ:NN\"},{period:\"ss\",format:\"JJ:NN:SS\"},{period:\"fff\",format:\"JJ:NN:SS\"}];e.applyTheme(this,a,this.cname)},categoryBalloonDateFormat:function(a){var b=this.categoryBalloonDateFormats,c,d;for(d=0;dthis.availableSpace&&(this.stackDown=!0);this.set=a.set();this.cset=a.set();this.set.push(this.cset);this.set.doNotScale=!0;a=0;var c;for(c=0;c Save picture as... to save the image.\",\n\n\t\t\"capturing.delayed.menu.label\": \"{{duration}}\",\n\t\t\"capturing.delayed.menu.title\": \"Click to cancel\",\n\n\t\t\"menu.label.print\": \"Print\",\n\t\t\"menu.label.undo\": \"Undo\",\n\t\t\"menu.label.redo\": \"Redo\",\n\t\t\"menu.label.cancel\": \"Cancel\",\n\n\t\t\"menu.label.save.image\": \"Download as ...\",\n\t\t\"menu.label.save.data\": \"Save as ...\",\n\n\t\t\"menu.label.draw\": \"Annotate ...\",\n\t\t\"menu.label.draw.change\": \"Change ...\",\n\t\t\"menu.label.draw.add\": \"Add ...\",\n\t\t\"menu.label.draw.shapes\": \"Shape ...\",\n\t\t\"menu.label.draw.colors\": \"Color ...\",\n\t\t\"menu.label.draw.widths\": \"Size ...\",\n\t\t\"menu.label.draw.opacities\": \"Opacity ...\",\n\t\t\"menu.label.draw.text\": \"Text\",\n\n\t\t\"menu.label.draw.modes\": \"Mode ...\",\n\t\t\"menu.label.draw.modes.pencil\": \"Pencil\",\n\t\t\"menu.label.draw.modes.line\": \"Line\",\n\t\t\"menu.label.draw.modes.arrow\": \"Arrow\",\n\n\t\t\"label.saved.from\": \"Saved from: \"\n\t}\n}\n\n/*\n ** Polyfill export class\n */\n( function() {\n\tAmCharts[ \"export\" ] = function( chart, config ) {\n\t\tvar _timer;\n\t\tvar _this = {\n\t\t\tname: \"export\",\n\t\t\tversion: \"1.4.66\",\n\t\t\tlibs: {\n\t\t\t\tasync: true,\n\t\t\t\tautoLoad: true,\n\t\t\t\treload: false,\n\t\t\t\tresources: [ \"fabric.js/fabric.min.js\", \"FileSaver.js/FileSaver.min.js\", {\n\t\t\t\t\t\"jszip/jszip.min.js\": [ \"xlsx/xlsx.min.js\" ],\n\t\t\t\t\t\"pdfmake/pdfmake.min.js\": [ \"pdfmake/vfs_fonts.js\" ]\n\t\t\t\t} ],\n\t\t\t\tnamespaces: {\n\t\t\t\t\t\"pdfmake.min.js\": \"pdfMake\",\n\t\t\t\t\t\"jszip.min.js\": \"JSZip\",\n\t\t\t\t\t\"xlsx.min.js\": \"XLSX\",\n\t\t\t\t\t\"fabric.min.js\": \"fabric\",\n\t\t\t\t\t\"FileSaver.min.js\": \"saveAs\"\n\t\t\t\t},\n\t\t\t\tloadTimeout: 10000\n\t\t\t},\n\t\t\tconfig: {},\n\t\t\tsetup: {\n\t\t\t\tchart: chart,\n\t\t\t\thasBlob: false,\n\t\t\t\twrapper: false,\n\t\t\t\tisIE: !!window.document.documentMode,\n\t\t\t\tIEversion: window.document.documentMode,\n\t\t\t\thasTouch: typeof window.Touch == \"object\",\n\t\t\t\tfocusedMenuItem: undefined\n\t\t\t},\n\t\t\tdrawing: {\n\t\t\t\tenabled: false,\n\t\t\t\tundos: [],\n\t\t\t\tredos: [],\n\t\t\t\tbuffer: {\n\t\t\t\t\tposition: {\n\t\t\t\t\t\tx1: 0,\n\t\t\t\t\t\ty1: 0,\n\t\t\t\t\t\tx2: 0,\n\t\t\t\t\t\ty2: 0,\n\t\t\t\t\t\txD: 0,\n\t\t\t\t\t\tyD: 0\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\thandler: {\n\t\t\t\t\tundo: function( options, skipped ) {\n\t\t\t\t\t\tvar item = _this.drawing.undos.pop();\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\titem.selectable = true;\n\t\t\t\t\t\t\t_this.drawing.redos.push( item );\n\n\t\t\t\t\t\t\tif ( item.action == \"added\" ) {\n\t\t\t\t\t\t\t\t_this.setup.fabric.remove( item.target );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar state = JSON.parse( item.state );\n\t\t\t\t\t\t\titem.target.set( state );\n\n\t\t\t\t\t\t\tif ( item.target instanceof fabric.Group ) {\n\t\t\t\t\t\t\t\t_this.drawing.handler.change( {\n\t\t\t\t\t\t\t\t\tcolor: state.cfg.color,\n\t\t\t\t\t\t\t\t\twidth: state.cfg.width,\n\t\t\t\t\t\t\t\t\topacity: state.cfg.opacity\n\t\t\t\t\t\t\t\t}, true, item.target );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.setup.fabric.renderAll();\n\n\t\t\t\t\t\t\t// RECALL\n\t\t\t\t\t\t\tif ( item.state == item.target.recentState && !skipped ) {\n\t\t\t\t\t\t\t\t_this.drawing.handler.undo( item, true );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tredo: function( options, skipped ) {\n\t\t\t\t\t\tvar item = _this.drawing.redos.pop();\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\titem.selectable = true;\n\t\t\t\t\t\t\t_this.drawing.undos.push( item );\n\n\t\t\t\t\t\t\tif ( item.action == \"added\" ) {\n\t\t\t\t\t\t\t\t_this.setup.fabric.add( item.target );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar state = JSON.parse( item.state );\n\t\t\t\t\t\t\titem.target.recentState = item.state;\n\t\t\t\t\t\t\titem.target.set( state );\n\n\t\t\t\t\t\t\tif ( item.target instanceof fabric.Group ) {\n\t\t\t\t\t\t\t\t_this.drawing.handler.change( {\n\t\t\t\t\t\t\t\t\tcolor: state.cfg.color,\n\t\t\t\t\t\t\t\t\twidth: state.cfg.width,\n\t\t\t\t\t\t\t\t\topacity: state.cfg.opacity\n\t\t\t\t\t\t\t\t}, true, item.target );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.setup.fabric.renderAll();\n\n\t\t\t\t\t\t\t// RECALL\n\t\t\t\t\t\t\tif ( item.action == \"addified\" ) {\n\t\t\t\t\t\t\t\t_this.drawing.handler.redo();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdone: function( options ) {\n\t\t\t\t\t\t_this.drawing.enabled = false;\n\t\t\t\t\t\t_this.drawing.buffer.enabled = false;\n\t\t\t\t\t\t_this.drawing.undos = [];\n\t\t\t\t\t\t_this.drawing.redos = [];\n\t\t\t\t\t\t_this.createMenu( _this.config.menu );\n\t\t\t\t\t\t_this.setup.fabric.deactivateAll();\n\n\t\t\t\t\t\tif ( _this.setup.wrapper ) {\n\t\t\t\t\t\t\t_this.setup.chart.containerDiv.removeChild( _this.setup.wrapper );\n\t\t\t\t\t\t\t_this.setup.wrapper = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tadd: function( options ) {\n\t\t\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\t\t\ttop: _this.setup.fabric.height / 2,\n\t\t\t\t\t\t\tleft: _this.setup.fabric.width / 2\n\t\t\t\t\t\t}, options || {} );\n\t\t\t\t\t\tvar method = cfg.url.indexOf( \".svg\" ) != -1 ? fabric.loadSVGFromURL : fabric.Image.fromURL;\n\n\t\t\t\t\t\tmethod( cfg.url, function( objects, options ) {\n\t\t\t\t\t\t\tvar group = options !== undefined ? fabric.util.groupSVGElements( objects, options ) : objects;\n\t\t\t\t\t\t\tvar ratio = false;\n\n\t\t\t\t\t\t\t// RESCALE ONLY IF IT EXCEEDS THE CANVAS\n\t\t\t\t\t\t\tif ( group.height > _this.setup.fabric.height || group.width > _this.setup.fabric.width ) {\n\t\t\t\t\t\t\t\tratio = ( _this.setup.fabric.height / 2 ) / group.height;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( cfg.top > _this.setup.fabric.height ) {\n\t\t\t\t\t\t\t\tcfg.top = _this.setup.fabric.height / 2;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( cfg.left > _this.setup.fabric.width ) {\n\t\t\t\t\t\t\t\tcfg.left = _this.setup.fabric.width / 2;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// SET DRAWING FLAG\n\t\t\t\t\t\t\t_this.drawing.buffer.isDrawing = true;\n\n\t\t\t\t\t\t\tgroup.set( {\n\t\t\t\t\t\t\t\toriginX: \"center\",\n\t\t\t\t\t\t\t\toriginY: \"center\",\n\t\t\t\t\t\t\t\ttop: cfg.top,\n\t\t\t\t\t\t\t\tleft: cfg.left,\n\t\t\t\t\t\t\t\twidth: ratio ? group.width * ratio : group.width,\n\t\t\t\t\t\t\t\theight: ratio ? group.height * ratio : group.height,\n\t\t\t\t\t\t\t\tfill: _this.drawing.color\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t_this.setup.fabric.add( group );\n\t\t\t\t\t\t} );\n\t\t\t\t\t},\n\t\t\t\t\tchange: function( options, skipped, target ) {\n\t\t\t\t\t\tvar cfg = _this.deepMerge( {}, options || {} );\n\t\t\t\t\t\tvar state, i1, rgba;\n\t\t\t\t\t\tvar current = target || _this.drawing.buffer.target;\n\t\t\t\t\t\tvar objects = current ? current._objects ? current._objects : [ current ] : null;\n\n\t\t\t\t\t\t// UPDATE DRAWING OBJECT\n\t\t\t\t\t\tif ( cfg.mode ) {\n\t\t\t\t\t\t\t_this.drawing.mode = cfg.mode;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( cfg.width ) {\n\t\t\t\t\t\t\t_this.drawing.width = cfg.width;\n\t\t\t\t\t\t\t_this.drawing.fontSize = cfg.fontSize = cfg.width * 3;\n\n\t\t\t\t\t\t\t// BACK TO DEFAULT\n\t\t\t\t\t\t\tif ( _this.drawing.width == 1 ) {\n\t\t\t\t\t\t\t\t_this.drawing.fontSize = cfg.fontSize = _this.defaults.fabric.drawing.fontSize;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( cfg.fontSize ) {\n\t\t\t\t\t\t\t_this.drawing.fontSize = cfg.fontSize;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( cfg.color ) {\n\t\t\t\t\t\t\t_this.drawing.color = cfg.color;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( cfg.opacity ) {\n\t\t\t\t\t\t\t_this.drawing.opacity = cfg.opacity;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// APPLY OPACITY ON CURRENT COLOR\n\t\t\t\t\t\trgba = _this.getRGBA( _this.drawing.color );\n\t\t\t\t\t\trgba.pop();\n\t\t\t\t\t\trgba.push( _this.drawing.opacity );\n\t\t\t\t\t\t_this.drawing.color = \"rgba(\" + rgba.join() + \")\";\n\t\t\t\t\t\t_this.setup.fabric.freeDrawingBrush.color = _this.drawing.color;\n\t\t\t\t\t\t_this.setup.fabric.freeDrawingBrush.width = _this.drawing.width;\n\n\t\t\t\t\t\t// UPDATE CURRENT SELECTION\n\t\t\t\t\t\tif ( current ) {\n\t\t\t\t\t\t\tstate = JSON.parse( current.recentState ).cfg;\n\n\t\t\t\t\t\t\t// UPDATE GIVE OPTIONS ONLY\n\t\t\t\t\t\t\tif ( state ) {\n\t\t\t\t\t\t\t\tcfg.color = cfg.color || state.color;\n\t\t\t\t\t\t\t\tcfg.width = cfg.width || state.width;\n\t\t\t\t\t\t\t\tcfg.opacity = cfg.opacity || state.opacity;\n\t\t\t\t\t\t\t\tcfg.fontSize = cfg.fontSize || state.fontSize;\n\n\t\t\t\t\t\t\t\trgba = _this.getRGBA( cfg.color );\n\t\t\t\t\t\t\t\trgba.pop();\n\t\t\t\t\t\t\t\trgba.push( cfg.opacity );\n\t\t\t\t\t\t\t\tcfg.color = \"rgba(\" + rgba.join() + \")\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// UPDATE OBJECTS\n\t\t\t\t\t\t\tfor ( i1 = 0; i1 < objects.length; i1++ ) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tobjects[ i1 ] instanceof fabric.Text ||\n\t\t\t\t\t\t\t\t\tobjects[ i1 ] instanceof fabric.PathGroup ||\n\t\t\t\t\t\t\t\t\tobjects[ i1 ] instanceof fabric.Triangle\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tif ( cfg.color || cfg.opacity ) {\n\t\t\t\t\t\t\t\t\t\tobjects[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\tfill: cfg.color\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif ( cfg.fontSize ) {\n\t\t\t\t\t\t\t\t\t\tobjects[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\tfontSize: cfg.fontSize\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\t\tobjects[ i1 ] instanceof fabric.Path ||\n\t\t\t\t\t\t\t\t\tobjects[ i1 ] instanceof fabric.Line\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tif ( current instanceof fabric.Group ) {\n\t\t\t\t\t\t\t\t\t\tif ( cfg.color || cfg.opacity ) {\n\t\t\t\t\t\t\t\t\t\t\tobjects[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\t\tstroke: cfg.color\n\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif ( cfg.color || cfg.opacity ) {\n\t\t\t\t\t\t\t\t\t\t\tobjects[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\t\tstroke: cfg.color\n\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif ( cfg.width ) {\n\t\t\t\t\t\t\t\t\t\t\tobjects[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\t\tstrokeWidth: cfg.width\n\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// ADD UNDO\n\t\t\t\t\t\t\tif ( !skipped ) {\n\t\t\t\t\t\t\t\tstate = JSON.stringify( _this.deepMerge( current.saveState().originalState, {\n\t\t\t\t\t\t\t\t\tcfg: {\n\t\t\t\t\t\t\t\t\t\tcolor: cfg.color,\n\t\t\t\t\t\t\t\t\t\twidth: cfg.width,\n\t\t\t\t\t\t\t\t\t\topacity: cfg.opacity\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} ) );\n\t\t\t\t\t\t\t\tcurrent.recentState = state;\n\t\t\t\t\t\t\t\t_this.drawing.redos = [];\n\t\t\t\t\t\t\t\t_this.drawing.undos.push( {\n\t\t\t\t\t\t\t\t\taction: \"modified\",\n\t\t\t\t\t\t\t\t\ttarget: current,\n\t\t\t\t\t\t\t\t\tstate: state\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t_this.setup.fabric.renderAll();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\ttext: function( options ) {\n\t\t\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\t\t\ttext: _this.i18l( \"menu.label.draw.text\" ),\n\t\t\t\t\t\t\ttop: _this.setup.fabric.height / 2,\n\t\t\t\t\t\t\tleft: _this.setup.fabric.width / 2,\n\t\t\t\t\t\t\tfontSize: _this.drawing.fontSize,\n\t\t\t\t\t\t\tfontFamily: _this.setup.chart.fontFamily || \"Verdana\",\n\t\t\t\t\t\t\tfill: _this.drawing.color\n\t\t\t\t\t\t}, options || {} );\n\n\t\t\t\t\t\tcfg.click = function() {};\n\n\t\t\t\t\t\tvar text = new fabric.IText( cfg.text, cfg );\n\n\t\t\t\t\t\t// SET DRAWING FLAG\n\t\t\t\t\t\t_this.drawing.buffer.isDrawing = true;\n\n\t\t\t\t\t\t_this.setup.fabric.add( text );\n\t\t\t\t\t\t_this.setup.fabric.setActiveObject( text );\n\n\t\t\t\t\t\ttext.selectAll();\n\t\t\t\t\t\ttext.enterEditing();\n\n\t\t\t\t\t\treturn text;\n\t\t\t\t\t},\n\t\t\t\t\tline: function( options ) {\n\t\t\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\t\t\tx1: ( _this.setup.fabric.width / 2 ) - ( _this.setup.fabric.width / 10 ),\n\t\t\t\t\t\t\tx2: ( _this.setup.fabric.width / 2 ) + ( _this.setup.fabric.width / 10 ),\n\t\t\t\t\t\t\ty1: ( _this.setup.fabric.height / 2 ),\n\t\t\t\t\t\t\ty2: ( _this.setup.fabric.height / 2 ),\n\t\t\t\t\t\t\tangle: 90,\n\t\t\t\t\t\t\tstrokeLineCap: _this.drawing.lineCap,\n\t\t\t\t\t\t\tarrow: _this.drawing.arrow,\n\t\t\t\t\t\t\tcolor: _this.drawing.color,\n\t\t\t\t\t\t\twidth: _this.drawing.width,\n\t\t\t\t\t\t\tgroup: [],\n\t\t\t\t\t\t}, options || {} );\n\t\t\t\t\t\tvar i1, arrow, arrowTop, arrowLeft;\n\t\t\t\t\t\tvar line = new fabric.Line( [ cfg.x1, cfg.y1, cfg.x2, cfg.y2 ], {\n\t\t\t\t\t\t\tstroke: cfg.color,\n\t\t\t\t\t\t\tstrokeWidth: cfg.width,\n\t\t\t\t\t\t\tstrokeLineCap: cfg.strokeLineCap\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\tcfg.group.push( line );\n\n\t\t\t\t\t\tif ( cfg.arrow ) {\n\t\t\t\t\t\t\tcfg.angle = cfg.angle ? cfg.angle : _this.getAngle( cfg.x1, cfg.y1, cfg.x2, cfg.y2 );\n\n\t\t\t\t\t\t\tif ( cfg.arrow == \"start\" ) {\n\t\t\t\t\t\t\t\tarrowTop = cfg.y1 + ( cfg.width / 2 );\n\t\t\t\t\t\t\t\tarrowLeft = cfg.x1 + ( cfg.width / 2 );\n\t\t\t\t\t\t\t} else if ( cfg.arrow == \"middle\" ) {\n\t\t\t\t\t\t\t\tarrowTop = cfg.y2 + ( cfg.width / 2 ) - ( ( cfg.y2 - cfg.y1 ) / 2 );\n\t\t\t\t\t\t\t\tarrowLeft = cfg.x2 + ( cfg.width / 2 ) - ( ( cfg.x2 - cfg.x1 ) / 2 );\n\t\t\t\t\t\t\t} else { // arrow: end\n\t\t\t\t\t\t\t\tarrowTop = cfg.y2 + ( cfg.width / 2 );\n\t\t\t\t\t\t\t\tarrowLeft = cfg.x2 + ( cfg.width / 2 );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tarrow = new fabric.Triangle( {\n\t\t\t\t\t\t\t\ttop: arrowTop,\n\t\t\t\t\t\t\t\tleft: arrowLeft,\n\t\t\t\t\t\t\t\tfill: cfg.color,\n\t\t\t\t\t\t\t\theight: cfg.width * 7,\n\t\t\t\t\t\t\t\twidth: cfg.width * 7,\n\t\t\t\t\t\t\t\tangle: cfg.angle,\n\t\t\t\t\t\t\t\toriginX: \"center\",\n\t\t\t\t\t\t\t\toriginY: \"bottom\"\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\tcfg.group.push( arrow );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// SET DRAWING FLAG\n\t\t\t\t\t\t_this.drawing.buffer.isDrawing = true;\n\n\t\t\t\t\t\tif ( cfg.action != \"config\" ) {\n\t\t\t\t\t\t\tif ( cfg.arrow ) {\n\t\t\t\t\t\t\t\tvar group = new fabric.Group( cfg.group );\n\t\t\t\t\t\t\t\tgroup.set( {\n\t\t\t\t\t\t\t\t\tcfg: cfg,\n\t\t\t\t\t\t\t\t\tfill: cfg.color,\n\t\t\t\t\t\t\t\t\taction: cfg.action,\n\t\t\t\t\t\t\t\t\tselectable: true,\n\t\t\t\t\t\t\t\t\tknown: cfg.action == \"change\"\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\tif ( cfg.action == \"change\" ) {\n\t\t\t\t\t\t\t\t\t_this.setup.fabric.setActiveObject( group );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t_this.setup.fabric.add( group );\n\t\t\t\t\t\t\t\treturn group;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t_this.setup.fabric.add( line );\n\t\t\t\t\t\t\t\treturn line;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor ( i1 = 0; i1 < cfg.group.length; i1++ ) {\n\t\t\t\t\t\t\t\t_this.setup.fabric.add( cfg.group[ i1 ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn cfg;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdefaults: {\n\t\t\t\tposition: \"top-right\",\n\t\t\t\tfileName: \"amCharts\",\n\t\t\t\taction: \"download\",\n\t\t\t\toverflow: true,\n\t\t\t\tpath: ( ( chart.path || \"\" ) + \"plugins/export/\" ),\n\t\t\t\tformats: {\n\t\t\t\t\tJPG: {\n\t\t\t\t\t\tmimeType: \"image/jpg\",\n\t\t\t\t\t\textension: \"jpg\",\n\t\t\t\t\t\tcapture: true\n\t\t\t\t\t},\n\t\t\t\t\tPNG: {\n\t\t\t\t\t\tmimeType: \"image/png\",\n\t\t\t\t\t\textension: \"png\",\n\t\t\t\t\t\tcapture: true\n\t\t\t\t\t},\n\t\t\t\t\tSVG: {\n\t\t\t\t\t\tmimeType: \"text/xml\",\n\t\t\t\t\t\textension: \"svg\",\n\t\t\t\t\t\tcapture: true\n\t\t\t\t\t},\n\t\t\t\t\tPDF: {\n\t\t\t\t\t\tmimeType: \"application/pdf\",\n\t\t\t\t\t\textension: \"pdf\",\n\t\t\t\t\t\tcapture: true\n\t\t\t\t\t},\n\t\t\t\t\tCSV: {\n\t\t\t\t\t\tmimeType: \"text/plain\",\n\t\t\t\t\t\textension: \"csv\"\n\t\t\t\t\t},\n\t\t\t\t\tJSON: {\n\t\t\t\t\t\tmimeType: \"text/plain\",\n\t\t\t\t\t\textension: \"json\"\n\t\t\t\t\t},\n\t\t\t\t\tXLSX: {\n\t\t\t\t\t\tmimeType: \"application/octet-stream\",\n\t\t\t\t\t\textension: \"xlsx\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tfabric: {\n\t\t\t\t\tbackgroundColor: \"#FFFFFF\",\n\t\t\t\t\tremoveImages: true,\n\t\t\t\t\tforceRemoveImages: false,\n\t\t\t\t\tselection: false,\n\t\t\t\t\tloadTimeout: 5000,\n\t\t\t\t\tdrawing: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tarrow: \"end\",\n\t\t\t\t\t\tlineCap: \"butt\",\n\t\t\t\t\t\tmode: \"pencil\",\n\t\t\t\t\t\tmodes: [ \"pencil\", \"line\", \"arrow\" ],\n\t\t\t\t\t\tcolor: \"#000000\",\n\t\t\t\t\t\tcolors: [ \"#000000\", \"#FFFFFF\", \"#FF0000\", \"#00FF00\", \"#0000FF\" ],\n\t\t\t\t\t\tshapes: [ \"11.svg\", \"14.svg\", \"16.svg\", \"17.svg\", \"20.svg\", \"27.svg\" ],\n\t\t\t\t\t\twidth: 1,\n\t\t\t\t\t\tfontSize: 11,\n\t\t\t\t\t\twidths: [ 1, 5, 10, 15 ],\n\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\topacities: [ 1, 0.8, 0.6, 0.4, 0.2 ],\n\t\t\t\t\t\tmenu: undefined,\n\t\t\t\t\t\tautoClose: true\n\t\t\t\t\t},\n\t\t\t\t\tborder: {\n\t\t\t\t\t\tfill: \"\",\n\t\t\t\t\t\tfillOpacity: 0,\n\t\t\t\t\t\tstroke: \"#000000\",\n\t\t\t\t\t\tstrokeWidth: 1,\n\t\t\t\t\t\tstrokeOpacity: 1\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tpdfMake: {\n\t\t\t\t\timages: {},\n\t\t\t\t\tpageOrientation: \"portrait\",\n\t\t\t\t\tpageMargins: 40,\n\t\t\t\t\tpageOrigin: true,\n\t\t\t\t\tpageSize: \"A4\",\n\t\t\t\t\tpageSizes: {\n\t\t\t\t\t\t\"4A0\": [ 4767.87, 6740.79 ],\n\t\t\t\t\t\t\"2A0\": [ 3370.39, 4767.87 ],\n\t\t\t\t\t\t\"A0\": [ 2383.94, 3370.39 ],\n\t\t\t\t\t\t\"A1\": [ 1683.78, 2383.94 ],\n\t\t\t\t\t\t\"A2\": [ 1190.55, 1683.78 ],\n\t\t\t\t\t\t\"A3\": [ 841.89, 1190.55 ],\n\t\t\t\t\t\t\"A4\": [ 595.28, 841.89 ],\n\t\t\t\t\t\t\"A5\": [ 419.53, 595.28 ],\n\t\t\t\t\t\t\"A6\": [ 297.64, 419.53 ],\n\t\t\t\t\t\t\"A7\": [ 209.76, 297.64 ],\n\t\t\t\t\t\t\"A8\": [ 147.40, 209.76 ],\n\t\t\t\t\t\t\"A9\": [ 104.88, 147.40 ],\n\t\t\t\t\t\t\"A10\": [ 73.70, 104.88 ],\n\t\t\t\t\t\t\"B0\": [ 2834.65, 4008.19 ],\n\t\t\t\t\t\t\"B1\": [ 2004.09, 2834.65 ],\n\t\t\t\t\t\t\"B2\": [ 1417.32, 2004.09 ],\n\t\t\t\t\t\t\"B3\": [ 1000.63, 1417.32 ],\n\t\t\t\t\t\t\"B4\": [ 708.66, 1000.63 ],\n\t\t\t\t\t\t\"B5\": [ 498.90, 708.66 ],\n\t\t\t\t\t\t\"B6\": [ 354.33, 498.90 ],\n\t\t\t\t\t\t\"B7\": [ 249.45, 354.33 ],\n\t\t\t\t\t\t\"B8\": [ 175.75, 249.45 ],\n\t\t\t\t\t\t\"B9\": [ 124.72, 175.75 ],\n\t\t\t\t\t\t\"B10\": [ 87.87, 124.72 ],\n\t\t\t\t\t\t\"C0\": [ 2599.37, 3676.54 ],\n\t\t\t\t\t\t\"C1\": [ 1836.85, 2599.37 ],\n\t\t\t\t\t\t\"C2\": [ 1298.27, 1836.85 ],\n\t\t\t\t\t\t\"C3\": [ 918.43, 1298.27 ],\n\t\t\t\t\t\t\"C4\": [ 649.13, 918.43 ],\n\t\t\t\t\t\t\"C5\": [ 459.21, 649.13 ],\n\t\t\t\t\t\t\"C6\": [ 323.15, 459.21 ],\n\t\t\t\t\t\t\"C7\": [ 229.61, 323.15 ],\n\t\t\t\t\t\t\"C8\": [ 161.57, 229.61 ],\n\t\t\t\t\t\t\"C9\": [ 113.39, 161.57 ],\n\t\t\t\t\t\t\"C10\": [ 79.37, 113.39 ],\n\t\t\t\t\t\t\"RA0\": [ 2437.80, 3458.27 ],\n\t\t\t\t\t\t\"RA1\": [ 1729.13, 2437.80 ],\n\t\t\t\t\t\t\"RA2\": [ 1218.90, 1729.13 ],\n\t\t\t\t\t\t\"RA3\": [ 864.57, 1218.90 ],\n\t\t\t\t\t\t\"RA4\": [ 609.45, 864.57 ],\n\t\t\t\t\t\t\"SRA0\": [ 2551.18, 3628.35 ],\n\t\t\t\t\t\t\"SRA1\": [ 1814.17, 2551.18 ],\n\t\t\t\t\t\t\"SRA2\": [ 1275.59, 1814.17 ],\n\t\t\t\t\t\t\"SRA3\": [ 907.09, 1275.59 ],\n\t\t\t\t\t\t\"SRA4\": [ 637.80, 907.09 ],\n\t\t\t\t\t\t\"EXECUTIVE\": [ 521.86, 756.00 ],\n\t\t\t\t\t\t\"FOLIO\": [ 612.00, 936.00 ],\n\t\t\t\t\t\t\"LEGAL\": [ 612.00, 1008.00 ],\n\t\t\t\t\t\t\"LETTER\": [ 612.00, 792.00 ],\n\t\t\t\t\t\t\"TABLOID\": [ 792.00, 1224.00 ]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmenu: undefined,\n\t\t\t\tdivId: null,\n\t\t\t\tmenuReviver: null,\n\t\t\t\tmenuWalker: null,\n\t\t\t\tfallback: true,\n\t\t\t\tkeyListener: true,\n\t\t\t\tfileListener: true,\n\t\t\t\tcompress: true,\n\t\t\t\tdebug: false\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns translated message, takes english as default\n\t\t\t */\n\t\t\ti18l: function( key, language ) {\n\t\t\t\tvar lang = language ? language : _this.setup.chart.language ? _this.setup.chart.language : \"en\";\n\t\t\t\tvar catalog = AmCharts.translations[ _this.name ][ lang ] || AmCharts.translations[ _this.name ][ \"en\" ];\n\n\t\t\t\treturn catalog[ key ] || key;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates download file; if unsupported offers fallback to save manually\n\t\t\t */\n\t\t\tdownload: function( data, type, filename ) {\n\t\t\t\t// SAVE\n\t\t\t\tif ( window.saveAs && _this.setup.hasBlob ) {\n\t\t\t\t\tvar blob = _this.toBlob( {\n\t\t\t\t\t\tdata: data,\n\t\t\t\t\t\ttype: type\n\t\t\t\t\t}, function( data ) {\n\t\t\t\t\t\tsaveAs( data, filename );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// FALLBACK TEXTAREA\n\t\t\t\t} else if ( _this.config.fallback && type == \"text/plain\" ) {\n\t\t\t\t\tvar div = document.createElement( \"div\" );\n\t\t\t\t\tvar msg = document.createElement( \"div\" );\n\t\t\t\t\tvar textarea = document.createElement( \"textarea\" );\n\n\t\t\t\t\tmsg.innerHTML = _this.i18l( \"fallback.save.text\" );\n\n\t\t\t\t\tdiv.appendChild( msg );\n\t\t\t\t\tdiv.appendChild( textarea );\n\t\t\t\t\tmsg.setAttribute( \"class\", \"amcharts-export-fallback-message\" );\n\t\t\t\t\tdiv.setAttribute( \"class\", \"amcharts-export-fallback\" );\n\t\t\t\t\t_this.setup.chart.containerDiv.appendChild( div );\n\n\t\t\t\t\t// FULFILL TEXTAREA AND PRESELECT\n\t\t\t\t\ttextarea.setAttribute( \"readonly\", \"\" );\n\t\t\t\t\ttextarea.value = data;\n\t\t\t\t\ttextarea.focus();\n\t\t\t\t\ttextarea.select();\n\n\t\t\t\t\t// UPDATE MENU\n\t\t\t\t\t_this.createMenu( [ {\n\t\t\t\t\t\t\"class\": \"export-main export-close\",\n\t\t\t\t\t\tlabel: \"Done\",\n\t\t\t\t\t\tclick: function() {\n\t\t\t\t\t\t\t_this.createMenu( _this.config.menu );\n\t\t\t\t\t\t\t_this.setup.chart.containerDiv.removeChild( div );\n\t\t\t\t\t\t}\n\t\t\t\t\t} ] );\n\n\t\t\t\t\t// FALLBACK IMAGE\n\t\t\t\t} else if ( _this.config.fallback && type.split( \"/\" )[ 0 ] == \"image\" ) {\n\t\t\t\t\tvar div = document.createElement( \"div\" );\n\t\t\t\t\tvar msg = document.createElement( \"div\" );\n\t\t\t\t\tvar img = _this.toImage( {\n\t\t\t\t\t\tdata: data\n\t\t\t\t\t} );\n\n\t\t\t\t\tmsg.innerHTML = _this.i18l( \"fallback.save.image\" );\n\n\t\t\t\t\t// FULFILL TEXTAREA AND PRESELECT\n\t\t\t\t\tdiv.appendChild( msg );\n\t\t\t\t\tdiv.appendChild( img );\n\t\t\t\t\tmsg.setAttribute( \"class\", \"amcharts-export-fallback-message\" );\n\t\t\t\t\tdiv.setAttribute( \"class\", \"amcharts-export-fallback\" );\n\t\t\t\t\t_this.setup.chart.containerDiv.appendChild( div );\n\n\t\t\t\t\t// UPDATE MENU\n\t\t\t\t\t_this.createMenu( [ {\n\t\t\t\t\t\t\"class\": \"export-main export-close\",\n\t\t\t\t\t\tlabel: \"Done\",\n\t\t\t\t\t\tclick: function() {\n\t\t\t\t\t\t\t_this.createMenu( _this.config.menu );\n\t\t\t\t\t\t\t_this.setup.chart.containerDiv.removeChild( div );\n\t\t\t\t\t\t}\n\t\t\t\t\t} ] );\n\n\t\t\t\t\t// ERROR\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error( \"Unable to create file. Ensure saveAs (FileSaver.js) is supported.\" );\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates script, links tags and places them into the document's head\n\t\t\t * In case of reload it replaces the node to force the download\n\t\t\t */\n\t\t\tloadResource: function( src, addons ) {\n\t\t\t\tvar i1, exist, node, item, check, type;\n\t\t\t\tvar url = src.indexOf( \"//\" ) != -1 ? src : [ _this.libs.path, src ].join( \"\" );\n\n\t\t\t\tvar loadCallback = function callback() {\n\t\t\t\t\tif ( addons ) {\n\t\t\t\t\t\tfor ( i1 = 0; i1 < addons.length; i1++ ) {\n\t\t\t\t\t\t\t_this.loadResource( addons[ i1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( src.indexOf( \".js\" ) != -1 ) {\n\t\t\t\t\tnode = document.createElement( \"script\" );\n\t\t\t\t\tnode.setAttribute( \"type\", \"text/javascript\" );\n\t\t\t\t\tnode.setAttribute( \"src\", url );\n\t\t\t\t\tif ( _this.libs.async ) {\n\t\t\t\t\t\tnode.setAttribute( \"async\", \"\" );\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( src.indexOf( \".css\" ) != -1 ) {\n\t\t\t\t\tnode = document.createElement( \"link\" );\n\t\t\t\t\tnode.setAttribute( \"type\", \"text/css\" );\n\t\t\t\t\tnode.setAttribute( \"rel\", \"stylesheet\" );\n\t\t\t\t\tnode.setAttribute( \"href\", url );\n\t\t\t\t}\n\n\t\t\t\t// NODE CHECK\n\t\t\t\tfor ( i1 = 0; i1 < document.head.childNodes.length; i1++ ) {\n\t\t\t\t\titem = document.head.childNodes[ i1 ];\n\t\t\t\t\tcheck = item ? ( item.src || item.href ) : false;\n\t\t\t\t\ttype = item ? item.tagName : false;\n\n\t\t\t\t\tif ( item && check && check.indexOf( src ) != -1 ) {\n\t\t\t\t\t\tif ( _this.libs.reload ) {\n\t\t\t\t\t\t\tdocument.head.removeChild( item );\n\t\t\t\t\t\t}\n\t\t\t\t\t\texist = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tfor ( i1 in _this.libs.namespaces ) {\n\t\t\t\t\tvar namespace = _this.libs.namespaces[ i1 ];\n\t\t\t\t\tvar check = src.toLowerCase();\n\t\t\t\t\tvar item = i1.toLowerCase();\n\t\t\t\t\tif ( check.indexOf( item ) != -1 && window[ namespace ] !== undefined ) {\n\t\t\t\t\t\texist = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( !exist || _this.libs.reload ) {\n\t\t\t\t\tnode.addEventListener( \"load\", loadCallback );\n\t\t\t\t\tnode.addEventListener( \"error\", function() {\n\t\t\t\t\t\t_this.handleLog( [ \"amCharts[export]: Loading error on \", this.src || this.href ].join( \"\" ) );\n\t\t\t\t\t} );\n\t\t\t\t\tdocument.head.appendChild( node );\n\n\t\t\t\t\tif ( !_this.listenersToRemove ) {\n\t\t\t\t\t\t_this.listenersToRemove = [];\n\t\t\t\t\t}\n\n\t\t\t\t\t_this.listenersToRemove.push( {\n\t\t\t\t\t\tnode: node,\n\t\t\t\t\t\tmethod: loadCallback,\n\t\t\t\t\t\tevent: \"load\"\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Walker to generate the script,link tags\n\t\t\t */\n\t\t\tloadDependencies: function() {\n\t\t\t\tvar i1, i2;\n\t\t\t\tif ( _this.libs.autoLoad ) {\n\t\t\t\t\tfor ( i1 = 0; i1 < _this.libs.resources.length; i1++ ) {\n\t\t\t\t\t\tif ( _this.libs.resources[ i1 ] instanceof Object ) {\n\t\t\t\t\t\t\tfor ( i2 in _this.libs.resources[ i1 ] ) {\n\t\t\t\t\t\t\t\t_this.loadResource( i2, _this.libs.resources[ i1 ][ i2 ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t_this.loadResource( _this.libs.resources[ i1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Converts string to number\n\t\t\t */\n\t\t\tpxToNumber: function( attr, returnUndefined ) {\n\t\t\t\tif ( !attr && returnUndefined ) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\treturn Number( String( attr ).replace( \"px\", \"\" ) ) || 0;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Converts number to string\n\t\t\t */\n\t\t\tnumberToPx: function( attr ) {\n\t\t\t\treturn String( attr ) + \"px\";\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Referenceless copy of object type variables\n\t\t\t */\n\t\t\tcloneObject: function( o ) {\n\t\t\t\tvar clone, v, k, isObject, isDate;\n\t\t\t\tclone = Array.isArray( o ) ? [] : {};\n\n\t\t\t\t// Walkthrough values\n\t\t\t\tfor ( k in o ) {\n\t\t\t\t\tv = o[ k ];\n\t\t\t\t\tisObject = typeof v === \"object\";\n\t\t\t\t\tisDate = v instanceof Date;\n\n\t\t\t\t\t// Set value; call recursivly if value is an object\n\t\t\t\t\tclone[ k ] = isObject && !isDate ? _this.cloneObject( v ) : v;\n\t\t\t\t}\n\t\t\t\treturn clone;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Recursive method to merge the given objects together\n\t\t\t * Overwrite flag replaces the value instead to crawl through\n\t\t\t */\n\t\t\tdeepMerge: function( a, b, overwrite ) {\n\t\t\t\tvar i1, v, type = b instanceof Array ? \"array\" : \"object\";\n\n\t\t\t\t// SKIP; OBJECTS AND ARRAYS ONLY\n\t\t\t\tif ( !( a instanceof Object || a instanceof Array ) ) {\n\t\t\t\t\treturn a;\n\t\t\t\t}\n\n\t\t\t\t// WALKTHOUGH SOURCE\n\t\t\t\tfor ( i1 in b ) {\n\n\t\t\t\t\t// PREVENT METHODS\n\t\t\t\t\tif ( type == \"array\" && isNaN( i1 ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// ASSIGN VALUE\n\t\t\t\t\tv = b[ i1 ];\n\n\t\t\t\t\t// NEW INSTANCE\n\t\t\t\t\tif ( a && a[ i1 ] == undefined || overwrite ) {\n\t\t\t\t\t\tif ( v instanceof Array ) {\n\t\t\t\t\t\t\ta[ i1 ] = new Array();\n\t\t\t\t\t\t} else if ( v instanceof Function ) {\n\t\t\t\t\t\t\ta[ i1 ] = function() {};\n\t\t\t\t\t\t} else if ( v instanceof Date ) {\n\t\t\t\t\t\t\ta[ i1 ] = new Date();\n\t\t\t\t\t\t} else if ( v instanceof Object ) {\n\t\t\t\t\t\t\ta[ i1 ] = new Object();\n\t\t\t\t\t\t} else if ( v instanceof Number ) {\n\t\t\t\t\t\t\ta[ i1 ] = new Number();\n\t\t\t\t\t\t} else if ( v instanceof String ) {\n\t\t\t\t\t\t\ta[ i1 ] = new String();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// WALKTHROUGH RECURSIVLY\n\t\t\t\t\tif (\n\t\t\t\t\t\t( v instanceof Object || v instanceof Array ) &&\n\t\t\t\t\t\t!( v instanceof Function || v instanceof Date || _this.isElement( v ) ) &&\n\t\t\t\t\t\ti1 != \"chart\" &&\n\t\t\t\t\t\ti1 != \"scope\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t_this.deepMerge( a[ i1 ], v, overwrite );\n\n\t\t\t\t\t\t// ASSIGN\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( a instanceof Array && !overwrite ) {\n\t\t\t\t\t\t\ta.push( v );\n\t\t\t\t\t\t} else if ( a ) {\n\t\t\t\t\t\t\ta[ i1 ] = v;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn a;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Checks if given argument is a valid node\n\t\t\t */\n\t\t\tisElement: function( thingy ) {\n\t\t\t\treturn thingy instanceof Object && thingy && thingy.nodeType === 1;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Checks if given argument contains a hashbang and returns it\n\t\t\t */\n\t\t\tisHashbanged: function( thingy ) {\n\t\t\t\tvar str = String( thingy ).replace( /\\\"/g, \"\" );\n\n\t\t\t\treturn str.slice( 0, 3 ) == \"url\" ? str.slice( str.indexOf( \"#\" ) + 1, str.length - 1 ) : false;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Checks if given event has been thrown with pressed click / touch\n\t\t\t */\n\t\t\tisPressed: function( event ) {\n\t\t\t\t// IE EXCEPTION\n\t\t\t\tif ( event.type == \"mousemove\" && event.which === 1 ) {\n\t\t\t\t\t// IGNORE\n\n\t\t\t\t\t// OTHERS\n\t\t\t\t} else if (\n\t\t\t\t\tevent.type == \"touchmove\" ||\n\t\t\t\t\tevent.buttons === 1 ||\n\t\t\t\t\tevent.button === 1 ||\n\t\t\t\t\tevent.which === 1\n\t\t\t\t) {\n\t\t\t\t\t_this.drawing.buffer.isPressed = true;\n\t\t\t\t} else {\n\t\t\t\t\t_this.drawing.buffer.isPressed = false;\n\t\t\t\t}\n\t\t\t\treturn _this.drawing.buffer.isPressed;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Checks if given source needs to be removed\n\t\t\t */\n\t\t\tremoveImage: function( source ) {\n\t\t\t\tif ( source ) {\n\n\t\t\t\t\t// FORCE REMOVAL\n\t\t\t\t\tif ( _this.config.fabric.forceRemoveImages ) {\n\t\t\t\t\t\treturn true;\n\n\t\t\t\t\t\t// REMOVE TAINTED\n\t\t\t\t\t} else if ( _this.config.fabric.removeImages && _this.isTainted( source ) ) {\n\t\t\t\t\t\treturn true;\n\n\t\t\t\t\t\t// IE 10 internal bug handling SVG images in canvas context\n\t\t\t\t\t} else if ( _this.setup.isIE && ( _this.setup.IEversion == 10 || _this.setup.IEversion == 11 ) && source.toLowerCase().indexOf( \".svg\" ) != -1 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Checks if given source is within the current origin\n\t\t\t */\n\t\t\tisTainted: function( source ) {\n\t\t\t\tvar origin = String( window.location.origin || window.location.protocol + \"//\" + window.location.hostname + ( window.location.port ? ':' + window.location.port : '' ) );\n\n\t\t\t\t// CHECK GIVEN SOURCE\n\t\t\t\tif ( source ) {\n\t\t\t\t\t// LOCAL FILES ARE ALWAYS TAINTED\n\t\t\t\t\tif (\n\t\t\t\t\t\torigin.indexOf( \":\\\\\" ) != -1 || source.indexOf( \":\\\\\" ) != -1 ||\n\t\t\t\t\t\torigin.indexOf( \"file://\" ) != -1 || source.indexOf( \"file://\" ) != -1\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn true\n\n\t\t\t\t\t\t// MISMATCHING ORIGIN\n\t\t\t\t\t} else if ( source.indexOf( \"//\" ) != -1 && source.indexOf( origin.replace( /.*:/, \"\" ) ) == -1 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\n\t\t\t/*\n\t\t\t ** Checks several indicators for acceptance;\n\t\t\t */\n\t\t\tisSupported: function() {\n\t\t\t\t// CHECK CONFIG\n\t\t\t\tif ( !_this.config.enabled ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// CHECK IE; ATTEMPT TO ACCESS HEAD ELEMENT\n\t\t\t\tif ( _this.setup.isIE && _this.setup.IEversion <= 9 ) {\n\t\t\t\t\tif ( !Array.prototype.indexOf || !document.head || _this.config.fallback === false ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\n\n\t\t\tgetAngle: function( x1, y1, x2, y2 ) {\n\t\t\t\tvar x = x2 - x1;\n\t\t\t\tvar y = y2 - y1;\n\t\t\t\tvar angle;\n\t\t\t\tif ( x == 0 ) {\n\t\t\t\t\tif ( y == 0 ) {\n\t\t\t\t\t\tangle = 0;\n\t\t\t\t\t} else if ( y > 0 ) {\n\t\t\t\t\t\tangle = Math.PI / 2;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tangle = Math.PI * 3 / 2;\n\t\t\t\t\t}\n\t\t\t\t} else if ( y == 0 ) {\n\t\t\t\t\tif ( x > 0 ) {\n\t\t\t\t\t\tangle = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tangle = Math.PI;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif ( x < 0 ) {\n\t\t\t\t\t\tangle = Math.atan( y / x ) + Math.PI;\n\t\t\t\t\t} else if ( y < 0 ) {\n\t\t\t\t\t\tangle = Math.atan( y / x ) + ( 2 * Math.PI );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tangle = Math.atan( y / x );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn angle * 180 / Math.PI;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Recursive method which crawls upwards to gather the requested attribute\n\t\t\t */\n\t\t\tgatherAttribute: function( elm, attr, limit, lvl ) {\n\t\t\t\tvar value, lvl = lvl ? lvl : 0,\n\t\t\t\t\tlimit = limit ? limit : 3;\n\t\t\t\tif ( elm ) {\n\t\t\t\t\tvalue = elm.getAttribute( attr );\n\n\t\t\t\t\tif ( !value && lvl < limit ) {\n\t\t\t\t\t\treturn _this.gatherAttribute( elm.parentNode, attr, limit, lvl + 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Recursive method which crawls upwards to gather the requested classname\n\t\t\t */\n\t\t\tgatherClassName: function( elm, className, limit, lvl ) {\n\t\t\t\tvar value, lvl = lvl ? lvl : 0,\n\t\t\t\t\tlimit = limit ? limit : 3;\n\n\t\t\t\tif ( _this.isElement( elm ) ) {\n\t\t\t\t\tvalue = ( elm.getAttribute( \"class\" ) || \"\" ).split( \" \" ).indexOf( className ) != -1;\n\n\t\t\t\t\tif ( !value && lvl < limit ) {\n\t\t\t\t\t\treturn _this.gatherClassName( elm.parentNode, className, limit, lvl + 1 );\n\t\t\t\t\t} else if ( value ) {\n\t\t\t\t\t\tvalue = elm;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Collects the clip-paths and patterns\n\t\t\t */\n\t\t\tgatherElements: function( group, cfg, images ) {\n\t\t\t\tvar i1, i2;\n\t\t\t\tfor ( i1 = 0; i1 < group.children.length; i1++ ) {\n\t\t\t\t\tvar childNode = group.children[ i1 ];\n\n\t\t\t\t\t// CLIPPATH\n\t\t\t\t\tif ( childNode.tagName == \"clipPath\" ) {\n\t\t\t\t\t\tvar bbox = {};\n\t\t\t\t\t\tvar transform = fabric.parseTransformAttribute( _this.gatherAttribute( childNode, \"transform\" ) );\n\n\t\t\t\t\t\t// HIDE SIBLINGS; GATHER IT'S DIMENSIONS\n\t\t\t\t\t\tfor ( i2 = 0; i2 < childNode.childNodes.length; i2++ ) {\n\t\t\t\t\t\t\tchildNode.childNodes[ i2 ].setAttribute( \"fill\", \"transparent\" );\n\t\t\t\t\t\t\tbbox = {\n\t\t\t\t\t\t\t\tx: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( \"x\" ) ),\n\t\t\t\t\t\t\t\ty: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( \"y\" ) ),\n\t\t\t\t\t\t\t\twidth: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( \"width\" ) ),\n\t\t\t\t\t\t\t\theight: _this.pxToNumber( childNode.childNodes[ i2 ].getAttribute( \"height\" ) )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tgroup.clippings[ childNode.id ] = {\n\t\t\t\t\t\t\tsvg: childNode,\n\t\t\t\t\t\t\tbbox: bbox,\n\t\t\t\t\t\t\ttransform: transform\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// PATTERN\n\t\t\t\t\t} else if ( childNode.tagName == \"pattern\" ) {\n\t\t\t\t\t\tvar props = {\n\t\t\t\t\t\t\tnode: childNode,\n\t\t\t\t\t\t\tsource: childNode.getAttribute( \"xlink:href\" ),\n\t\t\t\t\t\t\twidth: Number( childNode.getAttribute( \"width\" ) ),\n\t\t\t\t\t\t\theight: Number( childNode.getAttribute( \"height\" ) ),\n\t\t\t\t\t\t\trepeat: \"repeat\",\n\t\t\t\t\t\t\toffsetX: 0,\n\t\t\t\t\t\t\toffsetY: 0\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GATHER BACKGROUND\n\t\t\t\t\t\tfor ( i2 = 0; i2 < childNode.childNodes.length; i2++ ) {\n\t\t\t\t\t\t\t// RECT; COLOR\n\t\t\t\t\t\t\tif ( childNode.childNodes[ i2 ].tagName == \"rect\" ) {\n\t\t\t\t\t\t\t\tprops.fill = childNode.childNodes[ i2 ].getAttribute( \"fill\" );\n\n\t\t\t\t\t\t\t\t// IMAGE\n\t\t\t\t\t\t\t} else if ( childNode.childNodes[ i2 ].tagName == \"image\" ) {\n\t\t\t\t\t\t\t\tvar attrs = fabric.parseAttributes( childNode.childNodes[ i2 ], fabric.SHARED_ATTRIBUTES );\n\n\t\t\t\t\t\t\t\tif ( attrs.transformMatrix ) {\n\t\t\t\t\t\t\t\t\tprops.offsetX = attrs.transformMatrix[ 4 ];\n\t\t\t\t\t\t\t\t\tprops.offsetY = attrs.transformMatrix[ 5 ];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// TAINTED\n\t\t\t\t\t\tif ( _this.removeImage( props.source ) ) {\n\t\t\t\t\t\t\tgroup.patterns[ childNode.id ] = props.fill ? props.fill : \"transparent\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tgroup.patterns[ props.node.id ] = props;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// IMAGES\n\t\t\t\t\t} else if ( childNode.tagName == \"image\" ) {\n\t\t\t\t\t\timages.included++;\n\n\t\t\t\t\t\t// LOAD IMAGE MANUALLY; TO RERENDER THE CANVAS\n\t\t\t\t\t\tfabric.Image.fromURL( childNode.getAttribute( \"xlink:href\" ), function( img ) {\n\t\t\t\t\t\t\timages.loaded++;\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t// FILL STROKE POLYFILL ON EVERY ELEMENT\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar attrs = [ \"fill\", \"stroke\" ];\n\t\t\t\t\t\tfor ( i2 = 0; i2 < attrs.length; i2++ ) {\n\t\t\t\t\t\t\tvar attr = attrs[ i2 ];\n\t\t\t\t\t\t\tvar attrVal = childNode.getAttribute( attr );\n\t\t\t\t\t\t\tvar attrRGBA = _this.getRGBA( attrVal );\n\t\t\t\t\t\t\tvar isHashbanged = _this.isHashbanged( attrVal );\n\n\t\t\t\t\t\t\t// VALIDATE AND RESET UNKNOWN COLORS (avoids fabric to crash)\n\t\t\t\t\t\t\tif ( attrVal && !attrRGBA && !isHashbanged ) {\n\t\t\t\t\t\t\t\tchildNode.setAttribute( attr, \"none\" );\n\t\t\t\t\t\t\t\tchildNode.setAttribute( attr + \"-opacity\", \"0\" );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn group;\n\t\t\t},\n\n\t\t\t/*\n\t\t\t ** GET RGBA COLOR ARRAY FROM INPUT\n\t\t\t */\n\t\t\tgetRGBA: function( source, returnInstance ) {\n\n\t\t\t\tif ( source != \"none\" && source != \"transparent\" && !_this.isHashbanged( source ) ) {\n\t\t\t\t\tsource = new fabric.Color( source );\n\n\t\t\t\t\tif ( source._source ) {\n\t\t\t\t\t\treturn returnInstance ? source : source.getSource();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\n\t\t\t/*\n\t\t\t ** GATHER MOUSE POSITION;\n\t\t\t */\n\t\t\tgatherPosition: function( event, type ) {\n\t\t\t\tvar ref = _this.drawing.buffer.position;\n\t\t\t\tvar ivt = fabric.util.invertTransform( _this.setup.fabric.viewportTransform );\n\t\t\t\tvar pos;\n\n\t\t\t\tif ( event.type == \"touchmove\" ) {\n\t\t\t\t\tif ( \"touches\" in event ) {\n\t\t\t\t\t\tevent = event.touches[ 0 ];\n\t\t\t\t\t} else if ( \"changedTouches\" in event ) {\n\t\t\t\t\t\tevent = event.changedTouches[ 0 ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpos = fabric.util.transformPoint( _this.setup.fabric.getPointer( event, true ), ivt );\n\n\t\t\t\tif ( type == 1 ) {\n\t\t\t\t\tref.x1 = pos.x;\n\t\t\t\t\tref.y1 = pos.y;\n\t\t\t\t}\n\n\t\t\t\tref.x2 = pos.x;\n\t\t\t\tref.y2 = pos.y;\n\t\t\t\tref.xD = ( ref.x1 - ref.x2 ) < 0 ? ( ref.x1 - ref.x2 ) * -1 : ( ref.x1 - ref.x2 );\n\t\t\t\tref.yD = ( ref.y1 - ref.y2 ) < 0 ? ( ref.y1 - ref.y2 ) * -1 : ( ref.y1 - ref.y2 );\n\n\t\t\t\treturn ref;\n\t\t\t},\n\n\t\t\tmodifyFabric: function() {\n\n\t\t\t\t// ADAPTED THE WAY TO RECEIVE THE GRADIENTID\n\t\t\t\tfabric.ElementsParser.prototype.resolveGradient = function( obj, property ) {\n\n\t\t\t\t\tvar instanceFillValue = obj.get( property );\n\t\t\t\t\tif ( !( /^url\\(/ ).test( instanceFillValue ) ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar gradientId = instanceFillValue.slice( instanceFillValue.indexOf( \"#\" ) + 1, instanceFillValue.length - 1 );\n\t\t\t\t\tif ( fabric.gradientDefs[ this.svgUid ][ gradientId ] ) {\n\t\t\t\t\t\tvar tmp = fabric.Gradient.fromElement( fabric.gradientDefs[ this.svgUid ][ gradientId ], obj );\n\n\t\t\t\t\t\t// WORKAROUND FOR VERTICAL GRADIENT ISSUE; FOR NONE PIE CHARTS\n\t\t\t\t\t\tif ( tmp.coords.y1 && _this.setup.chart.type != \"pie\" ) {\n\t\t\t\t\t\t\ttmp.coords.y2 = tmp.coords.y1 * -1;\n\t\t\t\t\t\t\ttmp.coords.y1 = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobj.set( property, tmp );\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// MULTILINE SUPPORT; TODO: BETTER POSITIONING\n\t\t\t\tfabric.Text.fromElement = function( element, options ) {\n\t\t\t\t\tif ( !element ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar parsedAttributes = fabric.parseAttributes( element, fabric.Text.ATTRIBUTE_NAMES );\n\t\t\t\t\toptions = fabric.util.object.extend( ( options ? fabric.util.object.clone( options ) : {} ), parsedAttributes );\n\n\t\t\t\t\toptions.top = options.top || 0;\n\t\t\t\t\toptions.left = options.left || 0;\n\t\t\t\t\tif ( 'dx' in parsedAttributes ) {\n\t\t\t\t\t\toptions.left += parsedAttributes.dx;\n\t\t\t\t\t}\n\t\t\t\t\tif ( 'dy' in parsedAttributes ) {\n\t\t\t\t\t\toptions.top += parsedAttributes.dy;\n\t\t\t\t\t}\n\t\t\t\t\tif ( !( 'fontSize' in options ) ) {\n\t\t\t\t\t\toptions.fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !options.originX ) {\n\t\t\t\t\t\toptions.originX = 'left';\n\t\t\t\t\t}\n\n\t\t\t\t\tvar textContent = '';\n\t\t\t\t\tvar textBuffer = [];\n\n\t\t\t\t\t// The XML is not properly parsed in IE9 so a workaround to get\n\t\t\t\t\t// textContent is through firstChild.data. Another workaround would be\n\t\t\t\t\t// to convert XML loaded from a file to be converted using DOMParser (same way loadSVGFromString() does)\n\t\t\t\t\tif ( !( 'textContent' in element ) ) {\n\t\t\t\t\t\tif ( 'firstChild' in element && element.firstChild !== null ) {\n\t\t\t\t\t\t\tif ( 'data' in element.firstChild && element.firstChild.data !== null ) {\n\t\t\t\t\t\t\t\ttextBuffer.push( element.firstChild.data );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( element.childNodes ) {\n\t\t\t\t\t\tfor ( var i1 = 0; i1 < element.childNodes.length; i1++ ) {\n\t\t\t\t\t\t\ttextBuffer.push( element.childNodes[ i1 ].textContent );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttextBuffer.push( element.textContent );\n\t\t\t\t\t}\n\n\t\t\t\t\ttextContent = textBuffer.join( \"\\n\" );\n\t\t\t\t\t//textContent = textContent.replace(/^\\s+|\\s+$|\\n+/g, '').replace(/\\s+/g, ' ');\n\n\t\t\t\t\tvar text = new fabric.Text( textContent, options ),\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t Adjust positioning:\n\t\t\t\t\t\t x/y attributes in SVG correspond to the bottom-left corner of text bounding box\n\t\t\t\t\t\t top/left properties in Fabric correspond to center point of text bounding box\n\t\t\t\t\t\t*/\n\t\t\t\t\t\toffX = 0;\n\n\t\t\t\t\tif ( text.originX === 'left' ) {\n\t\t\t\t\t\toffX = text.getWidth() / 2;\n\t\t\t\t\t}\n\t\t\t\t\tif ( text.originX === 'right' ) {\n\t\t\t\t\t\toffX = -text.getWidth() / 2;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( textBuffer.length > 1 ) {\n\n\t\t\t\t\t\ttext.set( {\n\t\t\t\t\t\t\tleft: text.getLeft() + offX,\n\t\t\t\t\t\t\ttop: text.getTop() + text.fontSize * ( textBuffer.length - 1 ) * ( 0.18 + text._fontSizeFraction ),\n\t\t\t\t\t\t\ttextAlign: options.originX,\n\t\t\t\t\t\t\tlineHeight: textBuffer.length > 1 ? 0.965 : 1.16,\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext.set( {\n\t\t\t\t\t\t\tleft: text.getLeft() + offX,\n\t\t\t\t\t\t\ttop: text.getTop() - text.getHeight() / 2 + text.fontSize * ( 0.18 + text._fontSizeFraction ) /* 0.3 is the old lineHeight */\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn text;\n\t\t\t\t};\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Method to capture the current state of the chart\n\t\t\t */\n\t\t\tcapture: function( options, callback ) {\n\t\t\t\tvar i1;\n\t\t\t\tvar cfg = _this.deepMerge( _this.deepMerge( {}, _this.config.fabric ), options || {} );\n\t\t\t\tvar groups = [];\n\t\t\t\tvar offset = {\n\t\t\t\t\tx: 0,\n\t\t\t\t\ty: 0,\n\t\t\t\t\tpX: 0,\n\t\t\t\t\tpY: 0,\n\t\t\t\t\tlX: 0,\n\t\t\t\t\tlY: 0,\n\t\t\t\t\twidth: _this.setup.chart.divRealWidth,\n\t\t\t\t\theight: _this.setup.chart.divRealHeight\n\t\t\t\t};\n\t\t\t\tvar images = {\n\t\t\t\t\tloaded: 0,\n\t\t\t\t\tincluded: 0\n\t\t\t\t}\n\t\t\t\tvar legends = {\n\t\t\t\t\titems: [],\n\t\t\t\t\twidth: 0,\n\t\t\t\t\theight: 0,\n\t\t\t\t\tmaxWidth: 0,\n\t\t\t\t\tmaxHeight: 0\n\t\t\t\t}\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"fabric\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.capture,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// MODIFY FABRIC UNTIL IT'S OFFICIALLY SUPPORTED\n\t\t\t\t_this.modifyFabric();\n\n\t\t\t\t// BEFORE CAPTURING\n\t\t\t\t_this.handleCallback( cfg.beforeCapture, cfg );\n\n\t\t\t\t// GATHER SVGS\n\t\t\t\tvar svgs = _this.setup.chart.containerDiv.getElementsByTagName( \"svg\" );\n\t\t\t\tfor ( i1 = 0; i1 < svgs.length; i1++ ) {\n\t\t\t\t\tvar group = {\n\t\t\t\t\t\tsvg: svgs[ i1 ],\n\t\t\t\t\t\tparent: svgs[ i1 ].parentNode,\n\t\t\t\t\t\tchildren: svgs[ i1 ].getElementsByTagName( \"*\" ),\n\t\t\t\t\t\toffset: {\n\t\t\t\t\t\t\tx: 0,\n\t\t\t\t\t\t\ty: 0\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpatterns: {},\n\t\t\t\t\t\tclippings: {},\n\t\t\t\t\t\thas: {\n\t\t\t\t\t\t\tlegend: false,\n\t\t\t\t\t\t\tpanel: false,\n\t\t\t\t\t\t\tscrollbar: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// CHECK IT'S SURROUNDINGS\n\t\t\t\t\tgroup.has.legend = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + \"-legend-div\", 1 );\n\t\t\t\t\tgroup.has.panel = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + \"-stock-panel-div\" );\n\t\t\t\t\tgroup.has.scrollbar = _this.gatherClassName( group.parent, _this.setup.chart.classNamePrefix + \"-scrollbar-chart-div\" );\n\n\t\t\t\t\t// GATHER ELEMENTS\n\t\t\t\t\tgroup = _this.gatherElements( group, cfg, images );\n\n\t\t\t\t\t// APPEND GROUP\n\t\t\t\t\tgroups.push( group );\n\t\t\t\t}\n\n\t\t\t\t// GATHER EXTERNAL LEGEND\n\t\t\t\tif ( _this.config.legend ) {\n\n\t\t\t\t\t// STOCK\n\t\t\t\t\tif ( _this.setup.chart.type == \"stock\" ) {\n\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.setup.chart.panels.length; i1++ ) {\n\t\t\t\t\t\t\tif ( _this.setup.chart.panels[ i1 ].stockLegend && _this.setup.chart.panels[ i1 ].stockLegend.divId ) {\n\t\t\t\t\t\t\t\tlegends.items.push( _this.setup.chart.panels[ i1 ].stockLegend );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// NORMAL\n\t\t\t\t\t} else if ( _this.setup.chart.legend && _this.setup.chart.legend.divId ) {\n\t\t\t\t\t\tlegends.items.push( _this.setup.chart.legend );\n\t\t\t\t\t}\n\n\t\t\t\t\t// WALKTHROUGH\n\t\t\t\t\tfor ( i1 = 0; i1 < legends.items.length; i1++ ) {\n\t\t\t\t\t\tvar legend = legends.items[ i1 ];\n\t\t\t\t\t\tvar group = {\n\t\t\t\t\t\t\tsvg: legend.container.container,\n\t\t\t\t\t\t\tparent: legend.container.container.parentNode,\n\t\t\t\t\t\t\tchildren: legend.container.container.getElementsByTagName( \"*\" ),\n\t\t\t\t\t\t\toffset: {\n\t\t\t\t\t\t\t\tx: 0,\n\t\t\t\t\t\t\t\ty: 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tlegend: {\n\t\t\t\t\t\t\t\tid: i1,\n\t\t\t\t\t\t\t\ttype: [ \"top\", \"left\" ].indexOf( _this.config.legend.position ) != -1 ? \"unshift\" : \"push\",\n\t\t\t\t\t\t\t\tposition: _this.config.legend.position,\n\t\t\t\t\t\t\t\twidth: _this.config.legend.width ? _this.config.legend.width : legend.container.div.offsetWidth,\n\t\t\t\t\t\t\t\theight: _this.config.legend.height ? _this.config.legend.height : legend.container.div.offsetHeight\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpatterns: {},\n\t\t\t\t\t\t\tclippings: {},\n\t\t\t\t\t\t\thas: {\n\t\t\t\t\t\t\t\tlegend: false,\n\t\t\t\t\t\t\t\tpanel: false,\n\t\t\t\t\t\t\t\tscrollbar: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GATHER DIMENSIONS\n\t\t\t\t\t\tlegends.width += group.legend.width;\n\t\t\t\t\t\tlegends.height += group.legend.height;\n\t\t\t\t\t\tlegends.maxWidth = group.legend.width > legends.maxWidth ? group.legend.width : legends.maxWidth;\n\t\t\t\t\t\tlegends.maxHeight = group.legend.height > legends.maxHeight ? group.legend.height : legends.maxHeight;\n\n\t\t\t\t\t\t// GATHER ELEMENTS\n\t\t\t\t\t\tgroup = _this.gatherElements( group, cfg, images );\n\n\t\t\t\t\t\t// PRE/APPEND SVG\n\t\t\t\t\t\tgroups[ group.legend.type ]( group );\n\t\t\t\t\t}\n\n\t\t\t\t\t// ADAPT WIDTH IF NEEDED; EXPAND HEIGHT\n\t\t\t\t\tif ( [ \"top\", \"bottom\" ].indexOf( _this.config.legend.position ) != -1 ) {\n\t\t\t\t\t\toffset.width = legends.maxWidth > offset.width ? legends.maxWidth : offset.width;\n\t\t\t\t\t\toffset.height += legends.height;\n\n\t\t\t\t\t\t// EXPAND WIDTH; ADAPT HEIGHT IF NEEDED\n\t\t\t\t\t} else if ( [ \"left\", \"right\" ].indexOf( _this.config.legend.position ) != -1 ) {\n\t\t\t\t\t\toffset.width += legends.maxWidth;\n\t\t\t\t\t\toffset.height = legends.height > offset.height ? legends.height : offset.height;\n\n\t\t\t\t\t\t// SIMPLY EXPAND CANVAS\n\t\t\t\t\t} else {\n\t\t\t\t\t\toffset.height += legends.height;\n\t\t\t\t\t\toffset.width += legends.maxWidth;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// CLEAR IF EXIST\n\t\t\t\t_this.drawing.enabled = cfg.drawing.enabled = cfg.action == \"draw\";\n\t\t\t\t_this.drawing.buffer.enabled = _this.drawing.enabled; // history reasons\n\n\t\t\t\t_this.setup.wrapper = document.createElement( \"div\" );\n\t\t\t\t_this.setup.wrapper.setAttribute( \"class\", _this.setup.chart.classNamePrefix + \"-export-canvas\" );\n\t\t\t\t_this.setup.chart.containerDiv.appendChild( _this.setup.wrapper );\n\n\t\t\t\t// STOCK CHART; SELECTOR OFFSET\n\t\t\t\tif ( _this.setup.chart.type == \"stock\" ) {\n\t\t\t\t\tvar padding = {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tright: 0,\n\t\t\t\t\t\tbottom: 0,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t}\n\t\t\t\t\tif ( _this.setup.chart.leftContainer ) {\n\t\t\t\t\t\toffset.width -= _this.setup.chart.leftContainer.offsetWidth;\n\t\t\t\t\t\tpadding.left = _this.setup.chart.leftContainer.offsetWidth + ( _this.setup.chart.panelsSettings.panelSpacing * 2 );\n\t\t\t\t\t}\n\t\t\t\t\tif ( _this.setup.chart.rightContainer ) {\n\t\t\t\t\t\toffset.width -= _this.setup.chart.rightContainer.offsetWidth;\n\t\t\t\t\t\tpadding.right = _this.setup.chart.rightContainer.offsetWidth + ( _this.setup.chart.panelsSettings.panelSpacing * 2 );\n\t\t\t\t\t}\n\t\t\t\t\tif ( _this.setup.chart.periodSelector && [ \"top\", \"bottom\" ].indexOf( _this.setup.chart.periodSelector.position ) != -1 ) {\n\t\t\t\t\t\toffset.height -= _this.setup.chart.periodSelector.offsetHeight + _this.setup.chart.panelsSettings.panelSpacing;\n\t\t\t\t\t\tpadding[ _this.setup.chart.periodSelector.position ] += _this.setup.chart.periodSelector.offsetHeight + _this.setup.chart.panelsSettings.panelSpacing;\n\t\t\t\t\t}\n\t\t\t\t\tif ( _this.setup.chart.dataSetSelector && [ \"top\", \"bottom\" ].indexOf( _this.setup.chart.dataSetSelector.position ) != -1 ) {\n\t\t\t\t\t\toffset.height -= _this.setup.chart.dataSetSelector.offsetHeight;\n\t\t\t\t\t\tpadding[ _this.setup.chart.dataSetSelector.position ] += _this.setup.chart.dataSetSelector.offsetHeight;\n\t\t\t\t\t}\n\n\t\t\t\t\t// APPLY OFFSET ON WRAPPER\n\t\t\t\t\t_this.setup.wrapper.style.paddingTop = _this.numberToPx( padding.top );\n\t\t\t\t\t_this.setup.wrapper.style.paddingRight = _this.numberToPx( padding.right );\n\t\t\t\t\t_this.setup.wrapper.style.paddingBottom = _this.numberToPx( padding.bottom );\n\t\t\t\t\t_this.setup.wrapper.style.paddingLeft = _this.numberToPx( padding.left );\n\t\t\t\t}\n\n\t\t\t\t// CREATE CANVAS\n\t\t\t\t_this.setup.canvas = document.createElement( \"canvas\" );\n\t\t\t\t_this.setup.wrapper.appendChild( _this.setup.canvas );\n\n\n\t\t\t\t_this.setup.fabric = new fabric.Canvas( _this.setup.canvas, _this.deepMerge( {\n\t\t\t\t\twidth: offset.width,\n\t\t\t\t\theight: offset.height,\n\t\t\t\t\tisDrawingMode: true\n\t\t\t\t}, cfg ) );\n\n\t\t\t\t// REAPPLY FOR SOME REASON\n\t\t\t\t_this.deepMerge( _this.setup.fabric, cfg );\n\t\t\t\t_this.deepMerge( _this.setup.fabric.freeDrawingBrush, cfg.drawing );\n\n\t\t\t\t// RELIABLE VARIABLES; UPDATE DRAWING\n\t\t\t\t_this.deepMerge( _this.drawing, cfg.drawing );\n\t\t\t\t_this.drawing.handler.change( cfg.drawing );\n\n\t\t\t\t// OBSERVE MOUSE EVENTS\n\t\t\t\t_this.setup.fabric.on( \"mouse:down\", function( e ) {\n\t\t\t\t\tvar p = _this.gatherPosition( e.e, 1 );\n\t\t\t\t\t_this.drawing.buffer.pressedTS = Number( new Date() );\n\t\t\t\t\t_this.isPressed( e.e );\n\n\t\t\t\t\t// FLAG ISDRAWING\n\t\t\t\t\t_this.drawing.buffer.isDrawing = false;\n\t\t\t\t\t_this.drawing.buffer.isDrawingTimer = setTimeout( function() {\n\t\t\t\t\t\tif ( !_this.drawing.buffer.isSelected ) {\n\t\t\t\t\t\t\t_this.drawing.buffer.isDrawing = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 200 );\n\t\t\t\t} );\n\t\t\t\t_this.setup.fabric.on( \"mouse:move\", function( e ) {\n\t\t\t\t\tvar p = _this.gatherPosition( e.e, 2 );\n\t\t\t\t\t_this.isPressed( e.e );\n\n\t\t\t\t\t// IS PRESSED BUT UNSELECTED\n\t\t\t\t\tif ( _this.drawing.buffer.isPressed && !_this.drawing.buffer.isSelected ) {\n\n\t\t\t\t\t\t// FLAG ISDRAWING\n\t\t\t\t\t\t_this.drawing.buffer.isDrawing = true;\n\n\t\t\t\t\t\t// CREATE INITIAL LINE / ARROW; JUST ON LEFT CLICK\n\t\t\t\t\t\tif ( !_this.drawing.buffer.line && _this.drawing.mode != \"pencil\" && ( p.xD > 5 || p.yD > 5 ) ) {\n\n\t\t\t\t\t\t\t// FORCE FABRIC TO DISABLE DRAWING MODE WHILE PRESSED / MOVEING MOUSE INPUT\n\t\t\t\t\t\t\t_this.setup.fabric.isDrawingMode = false;\n\t\t\t\t\t\t\t_this.setup.fabric._isCurrentlyDrawing = false;\n\t\t\t\t\t\t\t_this.setup.fabric.freeDrawingBrush.onMouseUp();\n\t\t\t\t\t\t\t_this.setup.fabric.remove( _this.setup.fabric._objects.pop() );\n\n\t\t\t\t\t\t\t// INITIAL POINT\n\t\t\t\t\t\t\t_this.drawing.buffer.line = _this.drawing.handler.line( {\n\t\t\t\t\t\t\t\tx1: p.x1,\n\t\t\t\t\t\t\t\ty1: p.y1,\n\t\t\t\t\t\t\t\tx2: p.x2,\n\t\t\t\t\t\t\t\ty2: p.y2,\n\t\t\t\t\t\t\t\tarrow: _this.drawing.mode == \"line\" ? false : _this.drawing.arrow,\n\t\t\t\t\t\t\t\taction: \"config\"\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( _this.drawing.buffer.isSelected ) {\n\t\t\t\t\t\t_this.setup.fabric.isDrawingMode = false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// UPDATE LINE / ARROW\n\t\t\t\t\tif ( _this.drawing.buffer.line ) {\n\t\t\t\t\t\tvar obj, top, left;\n\t\t\t\t\t\tvar l = _this.drawing.buffer.line;\n\n\t\t\t\t\t\tl.x2 = p.x2;\n\t\t\t\t\t\tl.y2 = p.y2;\n\n\t\t\t\t\t\t// // RESET INTERNAL FLAGS\t\n\t\t\t\t\t\t// _this.drawing.buffer.isDrawing = true;\n\t\t\t\t\t\t// _this.drawing.buffer.isPressed = true;\n\t\t\t\t\t\t// _this.drawing.buffer.hasLine = true;\n\n\t\t\t\t\t\tfor ( i1 = 0; i1 < l.group.length; i1++ ) {\n\t\t\t\t\t\t\tobj = l.group[ i1 ];\n\n\t\t\t\t\t\t\tif ( obj instanceof fabric.Line ) {\n\t\t\t\t\t\t\t\tobj.set( {\n\t\t\t\t\t\t\t\t\tx2: l.x2,\n\t\t\t\t\t\t\t\t\ty2: l.y2\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t} else if ( obj instanceof fabric.Triangle ) {\n\t\t\t\t\t\t\t\tl.angle = ( _this.getAngle( l.x1, l.y1, l.x2, l.y2 ) + 90 );\n\n\t\t\t\t\t\t\t\tif ( l.arrow == \"start\" ) {\n\t\t\t\t\t\t\t\t\ttop = l.y1 + ( l.width / 2 );\n\t\t\t\t\t\t\t\t\tleft = l.x1 + ( l.width / 2 );\n\t\t\t\t\t\t\t\t} else if ( l.arrow == \"middle\" ) {\n\t\t\t\t\t\t\t\t\ttop = l.y2 + ( l.width / 2 ) - ( ( l.y2 - l.y1 ) / 2 );\n\t\t\t\t\t\t\t\t\tleft = l.x2 + ( l.width / 2 ) - ( ( l.x2 - l.x1 ) / 2 );\n\t\t\t\t\t\t\t\t} else { // arrow: end\n\t\t\t\t\t\t\t\t\ttop = l.y2 + ( l.width / 2 );\n\t\t\t\t\t\t\t\t\tleft = l.x2 + ( l.width / 2 );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tobj.set( {\n\t\t\t\t\t\t\t\t\ttop: top,\n\t\t\t\t\t\t\t\t\tleft: left,\n\t\t\t\t\t\t\t\t\tangle: l.angle\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_this.setup.fabric.renderAll();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\t_this.setup.fabric.on( \"mouse:up\", function( e ) {\n\t\t\t\t\t// SELECT TARGET\n\t\t\t\t\tif ( !_this.drawing.buffer.isDrawing ) {\n\t\t\t\t\t\tvar target = _this.setup.fabric.findTarget( e.e );\n\t\t\t\t\t\tif ( target && target.selectable ) {\n\t\t\t\t\t\t\t_this.setup.fabric.setActiveObject( target );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// UPDATE LINE / ARROW\n\t\t\t\t\tif ( _this.drawing.buffer.line ) {\n\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.drawing.buffer.line.group.length; i1++ ) {\n\t\t\t\t\t\t\t_this.drawing.buffer.line.group[ i1 ].remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdelete _this.drawing.buffer.line.action;\n\t\t\t\t\t\tdelete _this.drawing.buffer.line.group;\n\t\t\t\t\t\t_this.drawing.handler.line( _this.drawing.buffer.line );\n\t\t\t\t\t}\n\t\t\t\t\t_this.drawing.buffer.line = false;\n\t\t\t\t\t_this.drawing.buffer.hasLine = false;\n\t\t\t\t\t_this.drawing.buffer.isPressed = false;\n\n\t\t\t\t\t// RESET ISDRAWING FLAG\n\t\t\t\t\tclearTimeout( _this.drawing.buffer.isDrawingTimer );\n\t\t\t\t\t_this.drawing.buffer.isDrawing = false;\n\t\t\t\t} );\n\n\t\t\t\t// OBSERVE OBJECT SELECTION\n\t\t\t\t_this.setup.fabric.on( \"object:selected\", function( e ) {\n\t\t\t\t\t_this.drawing.buffer.isSelected = true;\n\t\t\t\t\t_this.drawing.buffer.target = e.target;\n\t\t\t\t\t_this.setup.fabric.isDrawingMode = false;\n\t\t\t\t} );\n\t\t\t\t_this.setup.fabric.on( \"selection:cleared\", function( e ) {\n\t\t\t\t\t_this.drawing.buffer.target = false;\n\n\t\t\t\t\t// FREEHAND WORKAROUND\n\t\t\t\t\tif ( _this.drawing.buffer.isSelected ) {\n\t\t\t\t\t\t_this.setup.fabric._isCurrentlyDrawing = false;\n\t\t\t\t\t}\n\n\t\t\t\t\t_this.drawing.buffer.isSelected = false;\n\t\t\t\t\t_this.setup.fabric.isDrawingMode = true;\n\t\t\t\t} );\n\t\t\t\t_this.setup.fabric.on( \"path:created\", function( e ) {\n\t\t\t\t\tvar item = e.path;\n\t\t\t\t\tif ( !_this.drawing.buffer.isDrawing || _this.drawing.buffer.hasLine ) {\n\t\t\t\t\t\t_this.setup.fabric.remove( item );\n\t\t\t\t\t\t_this.setup.fabric.renderAll();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\t// OBSERVE OBJECT MODIFICATIONS\n\t\t\t\t_this.setup.fabric.on( \"object:added\", function( e ) {\n\t\t\t\t\tvar item = e.target;\n\t\t\t\t\tvar state = _this.deepMerge( item.saveState().originalState, {\n\t\t\t\t\t\tcfg: {\n\t\t\t\t\t\t\tcolor: _this.drawing.color,\n\t\t\t\t\t\t\twidth: _this.drawing.width,\n\t\t\t\t\t\t\topacity: _this.drawing.opacity,\n\t\t\t\t\t\t\tfontSize: _this.drawing.fontSize\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\tstate = JSON.stringify( state );\n\t\t\t\t\titem.recentState = state;\n\n\t\t\t\t\tif ( item.selectable && !item.known ) {\n\t\t\t\t\t\titem.isAnnotation = true;\n\t\t\t\t\t\t_this.drawing.undos.push( {\n\t\t\t\t\t\t\taction: \"added\",\n\t\t\t\t\t\t\ttarget: item,\n\t\t\t\t\t\t\tstate: state\n\t\t\t\t\t\t} );\n\t\t\t\t\t\t_this.drawing.undos.push( {\n\t\t\t\t\t\t\taction: \"addified\",\n\t\t\t\t\t\t\ttarget: item,\n\t\t\t\t\t\t\tstate: state\n\t\t\t\t\t\t} );\n\t\t\t\t\t\t_this.drawing.redos = [];\n\t\t\t\t\t}\n\n\t\t\t\t\titem.known = true;\n\t\t\t\t\t_this.setup.fabric.isDrawingMode = true;\n\t\t\t\t} );\n\t\t\t\t_this.setup.fabric.on( \"object:modified\", function( e ) {\n\t\t\t\t\tvar item = e.target;\n\t\t\t\t\tvar recentState = JSON.parse( item.recentState );\n\t\t\t\t\tvar state = _this.deepMerge( item.saveState().originalState, {\n\t\t\t\t\t\tcfg: recentState.cfg\n\t\t\t\t\t} );\n\n\t\t\t\t\tstate = JSON.stringify( state );\n\t\t\t\t\titem.recentState = state;\n\n\t\t\t\t\t_this.drawing.undos.push( {\n\t\t\t\t\t\taction: \"modified\",\n\t\t\t\t\t\ttarget: item,\n\t\t\t\t\t\tstate: state\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this.drawing.redos = [];\n\t\t\t\t} );\n\t\t\t\t_this.setup.fabric.on( \"text:changed\", function( e ) {\n\t\t\t\t\tvar item = e.target;\n\t\t\t\t\tclearTimeout( item.timer );\n\t\t\t\t\titem.timer = setTimeout( function() {\n\t\t\t\t\t\tvar state = JSON.stringify( item.saveState().originalState );\n\n\t\t\t\t\t\titem.recentState = state;\n\n\t\t\t\t\t\t_this.drawing.redos = [];\n\t\t\t\t\t\t_this.drawing.undos.push( {\n\t\t\t\t\t\t\taction: \"modified\",\n\t\t\t\t\t\t\ttarget: item,\n\t\t\t\t\t\t\tstate: state\n\t\t\t\t\t\t} );\n\t\t\t\t\t}, 250 );\n\t\t\t\t} );\n\n\t\t\t\t// DRAWING\n\t\t\t\tif ( _this.drawing.enabled ) {\n\t\t\t\t\t_this.setup.wrapper.setAttribute( \"class\", _this.setup.chart.classNamePrefix + \"-export-canvas active\" );\n\t\t\t\t\t_this.setup.wrapper.style.backgroundColor = cfg.backgroundColor;\n\t\t\t\t\t_this.setup.wrapper.style.display = \"block\";\n\n\t\t\t\t} else {\n\t\t\t\t\t_this.setup.wrapper.setAttribute( \"class\", _this.setup.chart.classNamePrefix + \"-export-canvas\" );\n\t\t\t\t\t_this.setup.wrapper.style.display = \"none\";\n\t\t\t\t}\n\n\t\t\t\tfor ( i1 = 0; i1 < groups.length; i1++ ) {\n\t\t\t\t\tvar group = groups[ i1 ];\n\n\t\t\t\t\t// STOCK CHART; SVG OFFSET; SVG OFFSET\n\t\t\t\t\tif ( _this.setup.chart.type == \"stock\" && _this.setup.chart.legendSettings.position ) {\n\n\t\t\t\t\t\t// TOP / BOTTOM\n\t\t\t\t\t\tif ( [ \"top\", \"bottom\" ].indexOf( _this.setup.chart.legendSettings.position ) != -1 ) {\n\n\t\t\t\t\t\t\t// POSITION; ABSOLUTE\n\t\t\t\t\t\t\tif ( group.parent.style.top && group.parent.style.left ) {\n\t\t\t\t\t\t\t\tgroup.offset.y = _this.pxToNumber( group.parent.style.top );\n\t\t\t\t\t\t\t\tgroup.offset.x = _this.pxToNumber( group.parent.style.left );\n\n\t\t\t\t\t\t\t\t// POSITION; RELATIVE\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tgroup.offset.x = offset.x;\n\t\t\t\t\t\t\t\tgroup.offset.y = offset.y;\n\t\t\t\t\t\t\t\toffset.y += _this.pxToNumber( group.parent.style.height );\n\n\t\t\t\t\t\t\t\t// LEGEND; OFFSET\n\t\t\t\t\t\t\t\tif ( group.has.panel ) {\n\t\t\t\t\t\t\t\t\toffset.pY = _this.pxToNumber( group.has.panel.style.marginTop );\n\t\t\t\t\t\t\t\t\tgroup.offset.y += offset.pY;\n\n\t\t\t\t\t\t\t\t\t// SCROLLBAR; OFFSET\n\t\t\t\t\t\t\t\t} else if ( group.has.scrollbar ) {\n\t\t\t\t\t\t\t\t\tgroup.offset.y += offset.pY;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// LEFT / RIGHT\n\t\t\t\t\t\t} else if ( [ \"left\", \"right\" ].indexOf( _this.setup.chart.legendSettings.position ) != -1 ) {\n\t\t\t\t\t\t\tgroup.offset.y = _this.pxToNumber( group.parent.style.top ) + offset.pY;\n\t\t\t\t\t\t\tgroup.offset.x = _this.pxToNumber( group.parent.style.left ) + offset.pX;\n\n\t\t\t\t\t\t\t// LEGEND; OFFSET\n\t\t\t\t\t\t\tif ( group.has.legend ) {\n\t\t\t\t\t\t\t\toffset.pY += _this.pxToNumber( group.has.panel.style.height ) + _this.setup.chart.panelsSettings.panelSpacing;\n\n\t\t\t\t\t\t\t\t// SCROLLBAR; OFFSET\n\t\t\t\t\t\t\t} else if ( group.has.scrollbar ) {\n\t\t\t\t\t\t\t\tgroup.offset.y -= _this.setup.chart.panelsSettings.panelSpacing;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// REGULAR CHARTS; SVG OFFSET\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// POSITION; ABSOLUTE\n\t\t\t\t\t\tif ( group.parent.style.position == \"absolute\" ) {\n\t\t\t\t\t\t\tgroup.offset.absolute = true;\n\t\t\t\t\t\t\tgroup.offset.top = _this.pxToNumber( group.parent.style.top );\n\t\t\t\t\t\t\tgroup.offset.right = _this.pxToNumber( group.parent.style.right, true );\n\t\t\t\t\t\t\tgroup.offset.bottom = _this.pxToNumber( group.parent.style.bottom, true );\n\t\t\t\t\t\t\tgroup.offset.left = _this.pxToNumber( group.parent.style.left );\n\t\t\t\t\t\t\tgroup.offset.width = _this.pxToNumber( group.parent.style.width );\n\t\t\t\t\t\t\tgroup.offset.height = _this.pxToNumber( group.parent.style.height );\n\n\t\t\t\t\t\t\t// POSITION; RELATIVE\n\t\t\t\t\t\t} else if ( group.parent.style.top && group.parent.style.left ) {\n\t\t\t\t\t\t\tgroup.offset.y = _this.pxToNumber( group.parent.style.top );\n\t\t\t\t\t\t\tgroup.offset.x = _this.pxToNumber( group.parent.style.left );\n\n\t\t\t\t\t\t\t// POSITION; GENERIC\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// EXTERNAL LEGEND\n\t\t\t\t\t\t\tif ( group.legend ) {\n\t\t\t\t\t\t\t\tif ( group.legend.position == \"left\" ) {\n\t\t\t\t\t\t\t\t\toffset.x = legends.maxWidth;\n\t\t\t\t\t\t\t\t} else if ( group.legend.position == \"right\" ) {\n\t\t\t\t\t\t\t\t\tgroup.offset.x = offset.width - legends.maxWidth;\n\t\t\t\t\t\t\t\t} else if ( group.legend.position == \"top\" ) {\n\t\t\t\t\t\t\t\t\toffset.y += group.legend.height;\n\t\t\t\t\t\t\t\t} else if ( group.legend.position == \"bottom\" ) {\n\t\t\t\t\t\t\t\t\tgroup.offset.y = offset.height - legends.height;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// STACK LEGENDS\n\t\t\t\t\t\t\t\tgroup.offset.y += offset.lY;\n\t\t\t\t\t\t\t\toffset.lY += group.legend.height;\n\n\t\t\t\t\t\t\t\t// NORMAL\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tgroup.offset.x = offset.x;\n\t\t\t\t\t\t\t\tgroup.offset.y = offset.y + offset.pY;\n\t\t\t\t\t\t\t\toffset.y += _this.pxToNumber( group.parent.style.height );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// PANEL OFFSET (STOCK CHARTS)\n\t\t\t\t\t\tif ( group.has.legend && group.has.panel && group.has.panel.style.marginTop ) {\n\t\t\t\t\t\t\toffset.y += _this.pxToNumber( group.has.panel.style.marginTop );\n\t\t\t\t\t\t\tgroup.offset.y += _this.pxToNumber( group.has.panel.style.marginTop );\n\n\t\t\t\t\t\t\t// GENERAL LEFT / RIGHT POSITION\n\t\t\t\t\t\t} else if ( _this.setup.chart.legend && [ \"left\", \"right\" ].indexOf( _this.setup.chart.legend.position ) != -1 ) {\n\t\t\t\t\t\t\tgroup.offset.y = _this.pxToNumber( group.parent.style.top );\n\t\t\t\t\t\t\tgroup.offset.x = _this.pxToNumber( group.parent.style.left );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// ADD TO CANVAS\n\t\t\t\t\tfabric.parseSVGDocument( group.svg, ( function( group ) {\n\t\t\t\t\t\treturn function( objects, options ) {\n\t\t\t\t\t\t\tvar i1, i2;\n\t\t\t\t\t\t\tvar g = fabric.util.groupSVGElements( objects, options );\n\t\t\t\t\t\t\tvar paths = [];\n\t\t\t\t\t\t\tvar tmp = {\n\t\t\t\t\t\t\t\tselectable: false,\n\t\t\t\t\t\t\t\tisCoreElement: true\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// GROUP OFFSET; ABSOLUTE\n\t\t\t\t\t\t\tif ( group.offset.absolute ) {\n\t\t\t\t\t\t\t\tif ( group.offset.bottom !== undefined ) {\n\t\t\t\t\t\t\t\t\ttmp.top = offset.height - group.offset.height - group.offset.bottom;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttmp.top = group.offset.top;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif ( group.offset.right !== undefined ) {\n\t\t\t\t\t\t\t\t\ttmp.left = offset.width - group.offset.width - group.offset.right;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttmp.left = group.offset.left;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// GROUP OFFSET; REGULAR\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttmp.top = group.offset.y;\n\t\t\t\t\t\t\t\ttmp.left = group.offset.x;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// WALKTHROUGH ELEMENTS\n\t\t\t\t\t\t\tfor ( i1 = 0; i1 < g.paths.length; i1++ ) {\n\t\t\t\t\t\t\t\tvar PID = null;\n\n\t\t\t\t\t\t\t\t// OPACITY; TODO: DISTINGUISH OPACITY TYPES\n\t\t\t\t\t\t\t\tif ( g.paths[ i1 ] ) {\n\n\t\t\t\t\t\t\t\t\t// CHECK ORIGIN; REMOVE TAINTED\n\t\t\t\t\t\t\t\t\tif ( _this.removeImage( g.paths[ i1 ][ \"xlink:href\" ] ) ) {\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// SET OPACITY\n\t\t\t\t\t\t\t\t\tif ( g.paths[ i1 ].fill instanceof Object ) {\n\n\t\t\t\t\t\t\t\t\t\t// MISINTERPRETATION OF FABRIC\n\t\t\t\t\t\t\t\t\t\tif ( g.paths[ i1 ].fill.type == \"radial\" ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// OTHERS\n\t\t\t\t\t\t\t\t\t\t\tif ( [ \"pie\", \"gauge\" ].indexOf( _this.setup.chart.type ) == -1 ) {\n\t\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].fill.coords.r2 = g.paths[ i1 ].fill.coords.r1 * -1;\n\t\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].fill.coords.r1 = 0;\n\t\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\t\t\topacity: g.paths[ i1 ].fillOpacity\n\t\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// FILLING; TODO: DISTINGUISH OPACITY TYPES\n\t\t\t\t\t\t\t\t\t} else if ( PID = _this.isHashbanged( g.paths[ i1 ].fill ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// PATTERN\n\t\t\t\t\t\t\t\t\t\tif ( group.patterns && group.patterns[ PID ] ) {\n\n\t\t\t\t\t\t\t\t\t\t\tvar props = group.patterns[ PID ];\n\n\t\t\t\t\t\t\t\t\t\t\timages.included++;\n\n\t\t\t\t\t\t\t\t\t\t\t// LOAD IMAGE MANUALLY; TO RERENDER THE CANVAS\n\t\t\t\t\t\t\t\t\t\t\tfabric.Image.fromURL( props.source, ( function( props, i1 ) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn function( img ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\timages.loaded++;\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// ADAPT IMAGE\n\t\t\t\t\t\t\t\t\t\t\t\t\timg.set( {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttop: props.offsetY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tleft: props.offsetX,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: props.width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: props.height\n\t\t\t\t\t\t\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// RETINA DISPLAY\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( _this.setup.fabric._isRetinaScaling() ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\timg.set( {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttop: props.offsetY / 2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tleft: props.offsetX / 2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tscaleX: 0.5,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tscaleY: 0.5\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// CREATE CANVAS WITH BACKGROUND COLOR\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar patternSourceCanvas = new fabric.StaticCanvas( undefined, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbackgroundColor: props.fill,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: img.getWidth(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: img.getHeight()\n\t\t\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t\t\t\tpatternSourceCanvas.add( img );\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// CREATE PATTERN OBTAIN OFFSET TO TARGET\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar pattern = new fabric.Pattern( {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsource: patternSourceCanvas.getElement(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\toffsetX: g.paths[ i1 ].width / 2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\toffsetY: g.paths[ i1 ].height / 2,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trepeat: 'repeat',\n\t\t\t\t\t\t\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// ASSIGN TO OBJECT\n\t\t\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfill: pattern,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\topacity: g.paths[ i1 ].fillOpacity\n\t\t\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} )( props, i1 ) );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// CLIPPATH;\n\t\t\t\t\t\t\t\t\tif ( PID = _this.isHashbanged( g.paths[ i1 ].clipPath ) ) {\n\n\t\t\t\t\t\t\t\t\t\tif ( group.clippings && group.clippings[ PID ] ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// TODO: WAIT UNTIL FABRICJS HANDLES CLIPPATH FOR SVG OUTPUT\n\t\t\t\t\t\t\t\t\t\t\t( function( i1, PID ) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar toSVG = g.paths[ i1 ].toSVG;\n\n\t\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].toSVG = function( original_reviver ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn toSVG.apply( this, [ function( string ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn original_reviver( string, group.clippings[ PID ] );\n\t\t\t\t\t\t\t\t\t\t\t\t\t} ] );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} )( i1, PID );\n\n\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].set( {\n\t\t\t\t\t\t\t\t\t\t\t\tclipTo: ( function( i1, PID ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn function( ctx ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar cp = group.clippings[ PID ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar tm = this.transformMatrix || [ 1, 0, 0, 1, 0, 0 ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar dim = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttop: cp.bbox.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tleft: cp.bbox.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: cp.bbox.width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: cp.bbox.height\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( _this.setup.chart.type == \"map\" ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdim.top += cp.transform[ 5 ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdim.left += cp.transform[ 4 ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( cp.bbox.x && tm[ 4 ] && cp.bbox.y && tm[ 5 ] ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdim.top -= tm[ 5 ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdim.left -= tm[ 4 ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// SMOOTHCUSTOMBULLETS PLUGIN SUPPORT; ROUND BORDER\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t_this.setup.chart.smoothCustomBullets !== undefined &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis.className == _this.setup.chart.classNamePrefix + \"-graph-bullet\" &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tg.paths[ i1 ].svg.tagName == \"image\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tradius = cp.svg.firstChild.rx.baseVal.value / 2 + 2;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.moveTo(dim.left + radius, dim.top);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.lineTo(dim.left + dim.width - radius, dim.top);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.quadraticCurveTo(dim.left + dim.width, dim.top, dim.left + dim.width, dim.top + radius);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.lineTo(dim.left + dim.width, dim.top + dim.height - radius);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.quadraticCurveTo(dim.left + dim.width, dim.top + dim.height, dim.left + dim.width - radius, dim.top + dim.height);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.lineTo(dim.left + radius, dim.top + dim.height);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.quadraticCurveTo(dim.left, dim.top + dim.height, dim.left, dim.top + dim.height - radius);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.lineTo(dim.left, dim.top + radius);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.quadraticCurveTo(dim.left, dim.top, dim.left + radius, dim.top);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.closePath();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.rect( dim.left, dim.top, dim.width, dim.height );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} )( i1, PID )\n\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpaths.push( g.paths[ i1 ] );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// REPLACE WITH WHITELIST\n\t\t\t\t\t\t\tg.paths = paths;\n\n\t\t\t\t\t\t\t// CANCEL HALFPIXEL OFFSET ON CANVAS, KEEPS THE DECIMALS ON INDIVIDUAL PATHS\n\t\t\t\t\t\t\ttmp.top += 0.5;\n\t\t\t\t\t\t\ttmp.left += 0.5;\n\n\t\t\t\t\t\t\t// SET PROPS\n\t\t\t\t\t\t\tg.set( tmp );\n\n\t\t\t\t\t\t\t// ADD TO CANVAS\n\t\t\t\t\t\t\t_this.setup.fabric.add( g );\n\n\t\t\t\t\t\t\t// ADD BALLOONS\n\t\t\t\t\t\t\tif ( group.svg.parentNode && group.svg.parentNode.getElementsByTagName ) {\n\t\t\t\t\t\t\t\tvar balloons = group.svg.parentNode.getElementsByClassName( _this.setup.chart.classNamePrefix + \"-balloon-div\" );\n\t\t\t\t\t\t\t\tfor ( i1 = 0; i1 < balloons.length; i1++ ) {\n\t\t\t\t\t\t\t\t\tif ( cfg.balloonFunction instanceof Function ) {\n\t\t\t\t\t\t\t\t\t\tcfg.balloonFunction.apply( _this, [ balloons[ i1 ], group ] );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tvar elm_parent = balloons[ i1 ];\n\t\t\t\t\t\t\t\t\t\tvar style_parent = fabric.parseStyleAttribute( elm_parent );\n\t\t\t\t\t\t\t\t\t\tvar style_text = fabric.parseStyleAttribute( elm_parent.childNodes[ 0 ] );\n\t\t\t\t\t\t\t\t\t\tvar fabric_label = new fabric.Text( elm_parent.innerText || elm_parent.textContent || elm_parent.innerHTML, {\n\t\t\t\t\t\t\t\t\t\t\tselectable: false,\n\t\t\t\t\t\t\t\t\t\t\ttop: style_parent.top + group.offset.y,\n\t\t\t\t\t\t\t\t\t\t\tleft: style_parent.left + group.offset.x,\n\t\t\t\t\t\t\t\t\t\t\tfill: style_text[ \"color\" ],\n\t\t\t\t\t\t\t\t\t\t\tfontSize: style_text[ \"fontSize\" ],\n\t\t\t\t\t\t\t\t\t\t\tfontFamily: style_text[ \"fontFamily\" ],\n\t\t\t\t\t\t\t\t\t\t\ttextAlign: style_text[ \"text-align\" ],\n\t\t\t\t\t\t\t\t\t\t\tisCoreElement: true\n\t\t\t\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t\t\t\t_this.setup.fabric.add( fabric_label );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( group.svg.nextSibling && group.svg.nextSibling.tagName == \"A\" ) {\n\t\t\t\t\t\t\t\tvar elm_parent = group.svg.nextSibling;\n\t\t\t\t\t\t\t\tvar style_parent = fabric.parseStyleAttribute( elm_parent );\n\t\t\t\t\t\t\t\tvar fabric_label = new fabric.Text( elm_parent.innerText || elm_parent.textContent || elm_parent.innerHTML, {\n\t\t\t\t\t\t\t\t\tselectable: false,\n\t\t\t\t\t\t\t\t\ttop: style_parent.top + group.offset.y,\n\t\t\t\t\t\t\t\t\tleft: style_parent.left + group.offset.x,\n\t\t\t\t\t\t\t\t\tfill: style_parent[ \"color\" ],\n\t\t\t\t\t\t\t\t\tfontSize: style_parent[ \"fontSize\" ],\n\t\t\t\t\t\t\t\t\tfontFamily: style_parent[ \"fontFamily\" ],\n\t\t\t\t\t\t\t\t\topacity: style_parent[ \"opacity\" ],\n\t\t\t\t\t\t\t\t\tisCoreElement: true\n\t\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t\tif ( !group.has.scrollbar ) {\n\t\t\t\t\t\t\t\t\t_this.setup.fabric.add( fabric_label );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tgroups.pop();\n\n\t\t\t\t\t\t\t// TRIGGER CALLBACK WITH SAFETY DELAY\n\t\t\t\t\t\t\tif ( !groups.length ) {\n\t\t\t\t\t\t\t\tvar ts1 = Number( new Date() );\n\t\t\t\t\t\t\t\tvar timer = setInterval( function() {\n\t\t\t\t\t\t\t\t\tvar ts2 = Number( new Date() );\n\n\t\t\t\t\t\t\t\t\t// WAIT FOR LOADED IMAGES OR UNTIL THE TIMEOUT KICKS IN\n\t\t\t\t\t\t\t\t\tif ( images.loaded == images.included || ts2 - ts1 > _this.config.fabric.loadTimeout ) {\n\t\t\t\t\t\t\t\t\t\tclearTimeout( timer );\n\t\t\t\t\t\t\t\t\t\t_this.handleBorder( cfg );\n\t\t\t\t\t\t\t\t\t\t_this.handleCallback( cfg.afterCapture, cfg );\n\t\t\t\t\t\t\t\t\t\t_this.setup.fabric.renderAll();\n\t\t\t\t\t\t\t\t\t\t_this.handleCallback( callback, cfg );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}, AmCharts.updateRate );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// IDENTIFY ELEMENTS THROUGH CLASSNAMES\n\t\t\t\t\t} )( group ), function( svg, obj ) {\n\t\t\t\t\t\tvar i1;\n\t\t\t\t\t\tvar className = _this.gatherAttribute( svg, \"class\" );\n\t\t\t\t\t\tvar visibility = _this.gatherAttribute( svg, \"visibility\" );\n\t\t\t\t\t\tvar clipPath = _this.gatherAttribute( svg, \"clip-path\" );\n\n\t\t\t\t\t\tobj.className = String( className );\n\t\t\t\t\t\tobj.classList = String( className ).split( \" \" );\n\t\t\t\t\t\tobj.clipPath = clipPath;\n\t\t\t\t\t\tobj.svg = svg;\n\n\t\t\t\t\t\t// TRANSPORT FILL/STROKE OPACITY\n\t\t\t\t\t\tvar attrs = [ \"fill\", \"stroke\" ];\n\t\t\t\t\t\tfor ( i1 = 0; i1 < attrs.length; i1++ ) {\n\t\t\t\t\t\t\tvar attr = attrs[ i1 ]\n\t\t\t\t\t\t\tvar attrVal = String( svg.getAttribute( attr ) || \"none\" );\n\t\t\t\t\t\t\tvar attrOpacity = Number( svg.getAttribute( attr + \"-opacity\" ) || \"1\" );\n\t\t\t\t\t\t\tvar attrRGBA = _this.getRGBA( attrVal );\n\n\t\t\t\t\t\t\t// HIDE HIDDEN ELEMENTS; TODO: FIND A BETTER WAY TO HANDLE THAT\n\t\t\t\t\t\t\tif ( visibility == \"hidden\" ) {\n\t\t\t\t\t\t\t\tobj.opacity = 0;\n\t\t\t\t\t\t\t\tattrOpacity = 0;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// SET COLOR\n\t\t\t\t\t\t\tif ( attrRGBA ) {\n\t\t\t\t\t\t\t\tattrRGBA.pop();\n\t\t\t\t\t\t\t\tattrRGBA.push( attrOpacity )\n\t\t\t\t\t\t\t\tobj[ attr ] = \"rgba(\" + attrRGBA.join() + \")\";\n\t\t\t\t\t\t\t\tobj[ attr + _this.capitalize( \"opacity\" ) ] = attrOpacity;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// REVIVER\n\t\t\t\t\t\t_this.handleCallback( cfg.reviver, obj, svg );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns the current canvas\n\t\t\t */\n\t\t\ttoCanvas: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\t// NUFFIN\n\t\t\t\t}, options || {} );\n\t\t\t\tvar data = _this.setup.canvas;\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns an image; by default PNG\n\t\t\t */\n\t\t\ttoImage: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tformat: \"png\",\n\t\t\t\t\tquality: 1,\n\t\t\t\t\tmultiplier: _this.config.multiplier\n\t\t\t\t}, options || {} );\n\t\t\t\tvar data = cfg.data;\n\t\t\t\tvar img = document.createElement( \"img\" );\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"fabric\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toImage,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif ( !cfg.data ) {\n\t\t\t\t\tif ( cfg.lossless || cfg.format == \"svg\" ) {\n\t\t\t\t\t\tdata = _this.toSVG( _this.deepMerge( cfg, {\n\t\t\t\t\t\t\tgetBase64: true\n\t\t\t\t\t\t} ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata = _this.setup.fabric.toDataURL( cfg );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\timg.setAttribute( \"src\", data );\n\n\t\t\t\t_this.handleCallback( callback, img, cfg );\n\n\t\t\t\treturn img;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates a blob instance image; returns base64 datastring\n\t\t\t */\n\t\t\ttoBlob: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdata: \"empty\",\n\t\t\t\t\ttype: \"text/plain\"\n\t\t\t\t}, options || {} );\n\t\t\t\tvar data;\n\t\t\t\tvar isBase64 = /^data:.+;base64,(.*)$/.exec( cfg.data );\n\n\t\t\t\t// GATHER BODY\n\t\t\t\tif ( isBase64 ) {\n\t\t\t\t\tcfg.data = isBase64[ 0 ];\n\t\t\t\t\tcfg.type = cfg.data.slice( 5, cfg.data.indexOf( \",\" ) - 7 );\n\t\t\t\t\tcfg.data = _this.toByteArray( {\n\t\t\t\t\t\tdata: cfg.data.slice( cfg.data.indexOf( \",\" ) + 1, cfg.data.length )\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\tif ( cfg.getByteArray ) {\n\t\t\t\t\tdata = cfg.data;\n\t\t\t\t} else {\n\t\t\t\t\tdata = new Blob( [ cfg.data ], {\n\t\t\t\t\t\ttype: cfg.type\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates JPG image; returns base64 datastring\n\t\t\t */\n\t\t\ttoJPG: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tformat: \"jpeg\",\n\t\t\t\t\tquality: 1,\n\t\t\t\t\tmultiplier: _this.config.multiplier\n\t\t\t\t}, options || {} );\n\t\t\t\tcfg.format = cfg.format.toLowerCase();\n\t\t\t\tvar data;\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"fabric\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toJPG,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Get data context from fabric\n\t\t\t\tdata = _this.setup.fabric.toDataURL( cfg );\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates PNG image; returns base64 datastring\n\t\t\t */\n\t\t\ttoPNG: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tformat: \"png\",\n\t\t\t\t\tquality: 1,\n\t\t\t\t\tmultiplier: _this.config.multiplier\n\t\t\t\t}, options || {} );\n\t\t\t\tvar data;\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"fabric\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toPNG,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Get data context from fabric\n\t\t\t\tdata = _this.setup.fabric.toDataURL( cfg );\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates SVG image; returns base64 datastring\n\t\t\t */\n\t\t\ttoSVG: function( options, callback ) {\n\t\t\t\tvar clipPaths = [];\n\t\t\t\tvar clipPathIds = [];\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tcompress: _this.config.compress,\n\t\t\t\t\treviver: function( string, clipPath ) {\n\t\t\t\t\t\tvar matcher = new RegExp( /\\bstyle=(['\"])(.*?)\\1/ );\n\t\t\t\t\t\tvar match = matcher.exec( string )[ 0 ].slice( 7, -1 );\n\t\t\t\t\t\tvar styles = match.split( \";\" );\n\t\t\t\t\t\tvar replacement = [];\n\n\t\t\t\t\t\t// BEAUTIFY STYLES\n\t\t\t\t\t\tfor ( i1 = 0; i1 < styles.length; i1++ ) {\n\t\t\t\t\t\t\tif ( styles[ i1 ] ) {\n\t\t\t\t\t\t\t\tvar pair = styles[ i1 ].replace( /\\s/g, \"\" ).split( \":\" );\n\t\t\t\t\t\t\t\tvar key = pair[ 0 ];\n\t\t\t\t\t\t\t\tvar value = pair[ 1 ];\n\n\t\t\t\t\t\t\t\tif ( [ \"fill\", \"stroke\" ].indexOf( key ) != -1 ) {\n\t\t\t\t\t\t\t\t\tvalue = _this.getRGBA( value, true );\n\t\t\t\t\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\t\t\t\t\tvar color = \"#\" + value.toHex();\n\t\t\t\t\t\t\t\t\t\tvar opacity = value._source[ 3 ];\n\n\t\t\t\t\t\t\t\t\t\treplacement.push( [ key, color ].join( \":\" ) );\n\t\t\t\t\t\t\t\t\t\treplacement.push( [ key + \"-opacity\", opacity ].join( \":\" ) );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\treplacement.push( styles[ i1 ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if ( key != \"opactiy\" ) {\n\t\t\t\t\t\t\t\t\treplacement.push( styles[ i1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstring = string.replace( match, replacement.join( \";\" ) );\n\n\t\t\t\t\t\t// TODO: WAIT UNTIL FABRICJS HANDLES CLIPPATH FOR SVG OUTPUT\n\t\t\t\t\t\tif ( clipPath && clipPath.svg ) {\n\t\t\t\t\t\t\tvar clipPathId = clipPath.svg.id;\n\t\t\t\t\t\t\tvar sliceOffset = 2;\n\t\t\t\t\t\t\tvar end = string.slice( -sliceOffset );\n\n\t\t\t\t\t\t\tif ( end != \"/>\" ) {\n\t\t\t\t\t\t\t\tsliceOffset = 3;\n\t\t\t\t\t\t\t\tend = string.slice( -sliceOffset );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvar start = string.slice( 0, string.length - sliceOffset );\n\t\t\t\t\t\t\tvar clipPathAttr = \" clip-path=\\\"url(#\" + clipPathId + \")\\\" \";\n\t\t\t\t\t\t\tvar parentClassList = _this.gatherAttribute(clipPath.svg,\"class\");\n\n\t\t\t\t\t\t\tparentClassList = parentClassList ? parentClassList.split(\" \") : [];\n\n\t\t\t\t\t\t\t// APPLY CLIP PATH DIRECTLY ON GRAPHLINES\n\t\t\t\t\t\t\tif ( parentClassList.indexOf(_this.setup.chart.classNamePrefix + \"-graph-line\") != -1 ) {\n\t\t\t\t\t\t\t\tstring = start + clipPathAttr + end;\n\n\t\t\t\t\t\t\t// WRAP ELEMENT TO BE ABLE TO APPLY THE CLIP-PATH\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tstring = \"\" + string + \"\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// INJECT CLIP PATH ONCE INTO THE DOCUMENT\n\t\t\t\t\t\t\tif ( clipPathIds.indexOf( clipPathId ) == -1 ) {\n\t\t\t\t\t\t\t\tvar clipPathString = new XMLSerializer().serializeToString( clipPath.svg );\n\t\t\t\t\t\t\t\tclipPaths.push( clipPathString );\n\t\t\t\t\t\t\t\tclipPathIds.push( clipPathId );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn string;\n\t\t\t\t\t}\n\t\t\t\t}, options || {} );\n\t\t\t\tvar data;\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"fabric\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toSVG,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Get SVG context from fabric\n\t\t\t\tdata = _this.setup.fabric.toSVG( cfg, cfg.reviver );\n\n\t\t\t\t// TODO: WAIT UNTIL FABRICJS HANDLES CLIPPATH FOR SVG OUTPUT\n\t\t\t\tif ( clipPaths.length ) {\n\t\t\t\t\tvar start = data.slice( 0, data.length - 6 );\n\t\t\t\t\tvar end = data.slice( -6 );\n\t\t\t\t\tdata = start + clipPaths.join( \"\" ) + end;\n\t\t\t\t}\n\n\t\t\t\t// SOLVES #21840\n\t\t\t\tif ( cfg.compress ) {\n\t\t\t\t\tdata = data.replace( /[\\t\\r\\n]+/g, \"\" );\n\t\t\t\t}\n\n\t\t\t\tif ( cfg.getBase64 ) {\n\t\t\t\t\tdata = \"data:image/svg+xml;base64,\" + btoa( data );\n\t\t\t\t}\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates PDF; returns base64 datastring\n\t\t\t */\n\t\t\ttoPDF: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( _this.deepMerge( {\n\t\t\t\t\tmultiplier: _this.config.multiplier || 2,\n\t\t\t\t\tpageOrigin: _this.config.pageOrigin === undefined ? true : false\n\t\t\t\t}, _this.config.pdfMake ), options || {}, true );\n\t\t\t\tvar data;\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"pdfMake\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toPDF,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Create PDF instance\n\t\t\t\tdata = new pdfMake.createPdf( cfg );\n\n\t\t\t\t// Get image data\n\t\t\t\tcfg.images.reference = _this.toPNG( cfg );\n\n\t\t\t\t// Get page margins; exported from pdfMake\n\t\t\t\tfunction getMargins( margin ) {\n\t\t\t\t\tif ( typeof margin === 'number' || margin instanceof Number ) {\n\t\t\t\t\t\tmargin = {\n\t\t\t\t\t\t\tleft: margin,\n\t\t\t\t\t\t\tright: margin,\n\t\t\t\t\t\t\ttop: margin,\n\t\t\t\t\t\t\tbottom: margin\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if ( margin instanceof Array ) {\n\t\t\t\t\t\tif ( margin.length === 2 ) {\n\t\t\t\t\t\t\tmargin = {\n\t\t\t\t\t\t\t\tleft: margin[ 0 ],\n\t\t\t\t\t\t\t\ttop: margin[ 1 ],\n\t\t\t\t\t\t\t\tright: margin[ 0 ],\n\t\t\t\t\t\t\t\tbottom: margin[ 1 ]\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if ( margin.length === 4 ) {\n\t\t\t\t\t\t\tmargin = {\n\t\t\t\t\t\t\t\tleft: margin[ 0 ],\n\t\t\t\t\t\t\t\ttop: margin[ 1 ],\n\t\t\t\t\t\t\t\tright: margin[ 2 ],\n\t\t\t\t\t\t\t\tbottom: margin[ 3 ]\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else throw 'Invalid pageMargins definition';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmargin = {\n\t\t\t\t\t\t\tleft: _this.defaults.pdfMake.pageMargins,\n\t\t\t\t\t\t\ttop: _this.defaults.pdfMake.pageMargins,\n\t\t\t\t\t\t\tright: _this.defaults.pdfMake.pageMargins,\n\t\t\t\t\t\t\tbottom: _this.defaults.pdfMake.pageMargins\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn margin;\n\t\t\t\t}\n\n\t\t\t\t// Get page dimensions\n\t\t\t\tfunction getSize( pageSize, pageOrientation ) {\n\t\t\t\t\tvar pageDimensions = _this.defaults.pdfMake.pageSizes[ String( pageSize ).toUpperCase() ].slice();\n\n\t\t\t\t\tif ( !pageDimensions ) {\n\t\t\t\t\t\tthrow new Error( \"The given pageSize \\\"\" + pageSize + \"\\\" does not exist!\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Revers in case of landscape\n\t\t\t\t\tif ( pageOrientation == \"landscape\" ) {\n\t\t\t\t\t\tpageDimensions.reverse();\n\t\t\t\t\t}\n\n\t\t\t\t\treturn pageDimensions;\n\t\t\t\t}\n\n\t\t\t\t// Polyfill default content if none is given\n\t\t\t\tif ( !cfg.content ) {\n\t\t\t\t\tvar pageContent = [];\n\t\t\t\t\tvar pageDimensions = getSize( cfg.pageSize, cfg.pageOrientation );\n\t\t\t\t\tvar pageMargins = getMargins( cfg.pageMargins );\n\n\t\t\t\t\tpageDimensions[ 0 ] -= ( pageMargins.left + pageMargins.right );\n\t\t\t\t\tpageDimensions[ 1 ] -= ( pageMargins.top + pageMargins.bottom );\n\n\t\t\t\t\tif ( cfg.pageOrigin ) {\n\t\t\t\t\t\tpageContent.push( _this.i18l( \"label.saved.from\" ) );\n\t\t\t\t\t\tpageContent.push( window.location.href );\n\t\t\t\t\t\tpageDimensions[ 1 ] -= ( 14.064 * 2 );\n\t\t\t\t\t}\n\n\t\t\t\t\tpageContent.push( {\n\t\t\t\t\t\timage: \"reference\",\n\t\t\t\t\t\tfit: pageDimensions\n\t\t\t\t\t} );\n\n\t\t\t\t\tcfg.content = pageContent;\n\t\t\t\t}\n\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tdata.getDataUrl( ( function( callback ) {\n\t\t\t\t\t\treturn function( a ) {\n\t\t\t\t\t\t\tcallback.apply( _this, arguments );\n\t\t\t\t\t\t}\n\t\t\t\t\t} )( callback ) );\n\t\t\t\t}\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates an image; hides all elements on page to trigger native print method\n\t\t\t */\n\t\t\ttoPRINT: function( options, callback ) {\n\t\t\t\tvar i1;\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdelay: 0.01,\n\t\t\t\t\tlossless: false\n\t\t\t\t}, options || {} );\n\t\t\t\tvar data = _this.toImage( cfg );\n\t\t\t\tvar states = [];\n\t\t\t\tvar items = document.body.childNodes;\n\t\t\t\tvar scroll = document.documentElement.scrollTop || document.body.scrollTop;\n\n\t\t\t\tdata.setAttribute( \"style\", \"width: 100%; max-height: 100%;\" );\n\n\t\t\t\tfor ( i1 = 0; i1 < items.length; i1++ ) {\n\t\t\t\t\tif ( _this.isElement( items[ i1 ] ) ) {\n\t\t\t\t\t\tstates[ i1 ] = items[ i1 ].style.display;\n\t\t\t\t\t\titems[ i1 ].style.display = \"none\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdocument.body.appendChild( data );\n\n\t\t\t\t// DELAY WHOLE PROCESS\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t// PRINT\n\t\t\t\t\twindow.print();\n\n\t\t\t\t\t// CONVERT TO SECONDS\n\t\t\t\t\tcfg.delay *= 1000;\n\n\t\t\t\t\t// IOS EXCEPTION DELAY MIN. 1 SECOND\n\t\t\t\t\tvar isIOS = /iPad|iPhone|iPod/.test( navigator.userAgent ) && !window.MSStream;\n\t\t\t\t\tif ( isIOS && cfg.delay < 1000 ) {\n\t\t\t\t\t\tcfg.delay = 1000;\n\t\t\t\t\t}\n\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tfor ( i1 = 0; i1 < items.length; i1++ ) {\n\t\t\t\t\t\t\tif ( _this.isElement( items[ i1 ] ) ) {\n\t\t\t\t\t\t\t\titems[ i1 ].style.display = states[ i1 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdocument.body.removeChild( data );\n\t\t\t\t\t\tdocument.documentElement.scrollTop = document.body.scrollTop = scroll;\n\n\t\t\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t\t\t_this.handleCallback( callback, data, cfg );\n\t\t\t\t\t}, cfg.delay );\n\t\t\t\t},1);\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates JSON string\n\t\t\t */\n\t\t\ttoJSON: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdateFormat: _this.config.dateFormat || \"dateObject\"\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar data = {};\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"JSON\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toJSON,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// GATHER DATA\n\t\t\t\tcfg.data = cfg.data !== undefined ? cfg.data : _this.getChartData( cfg );\n\n\t\t\t\t// STRINGIFY DATA\n\t\t\t\tdata = JSON.stringify( cfg.data, undefined, \"\\t\" );\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates CSV string\n\t\t\t */\n\t\t\ttoCSV: function( options, callback ) {\n\t\t\t\tvar row, col;\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdelimiter: \",\",\n\t\t\t\t\tquotes: true,\n\t\t\t\t\tescape: true,\n\t\t\t\t\twithHeader: true\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar buffer = [];\n\t\t\t\tvar data = \"\";\n\n\t\t\t\t// GATHER DATA\n\t\t\t\tbuffer = _this.toArray( cfg );\n\n\t\t\t\t// MERGE\n\t\t\t\tfor ( row in buffer ) {\n\t\t\t\t\tif ( !isNaN( row ) ) {\n\t\t\t\t\t\tdata += buffer[ row ].join( cfg.delimiter ) + \"\\n\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates excel sheet; returns base64 datastring\n\t\t\t */\n\t\t\ttoXLSX: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tname: \"amCharts\",\n\t\t\t\t\tdateFormat: _this.config.dateFormat || \"dateObject\",\n\t\t\t\t\twithHeader: true,\n\t\t\t\t\tstringify: false\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar buffer = [];\n\t\t\t\tvar data = \"\";\n\t\t\t\tvar wb = {\n\t\t\t\t\tSheetNames: [],\n\t\t\t\t\tSheets: {}\n\t\t\t\t}\n\n\t\t\t\t// NAMESPACE CHECK\n\t\t\t\tif ( !_this.handleNamespace( \"XLSX\", {\n\t\t\t\t\t\tscope: this,\n\t\t\t\t\t\tcb: _this.toXLSX,\n\t\t\t\t\t\targs: arguments\n\t\t\t\t\t} ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// GATHER DATA\n\t\t\t\tbuffer = _this.toArray( cfg );\n\n\t\t\t\tfunction datenum( v, date1904 ) {\n\t\t\t\t\tif ( date1904 ) v += 1462;\n\t\t\t\t\tvar epoch = Date.parse( v );\n\t\t\t\t\tvar offset = v.getTimezoneOffset() * 60 * 1000;\n\t\t\t\t\treturn ( epoch - offset - new Date( Date.UTC( 1899, 11, 30 ) ) ) / ( 24 * 60 * 60 * 1000 );\n\t\t\t\t}\n\n\t\t\t\tfunction sheet_from_array_of_arrays( data, opts ) {\n\t\t\t\t\tvar ws = {};\n\t\t\t\t\tvar range = {\n\t\t\t\t\t\ts: {\n\t\t\t\t\t\t\tc: 10000000,\n\t\t\t\t\t\t\tr: 10000000\n\t\t\t\t\t\t},\n\t\t\t\t\t\te: {\n\t\t\t\t\t\t\tc: 0,\n\t\t\t\t\t\t\tr: 0\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tfor ( var R = 0; R != data.length; ++R ) {\n\t\t\t\t\t\tfor ( var C = 0; C != data[ R ].length; ++C ) {\n\t\t\t\t\t\t\tif ( range.s.r > R ) range.s.r = R;\n\t\t\t\t\t\t\tif ( range.s.c > C ) range.s.c = C;\n\t\t\t\t\t\t\tif ( range.e.r < R ) range.e.r = R;\n\t\t\t\t\t\t\tif ( range.e.c < C ) range.e.c = C;\n\t\t\t\t\t\t\tvar cell = {\n\t\t\t\t\t\t\t\tv: data[ R ][ C ]\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tif ( cell.v == null ) continue;\n\t\t\t\t\t\t\tvar cell_ref = XLSX.utils.encode_cell( {\n\t\t\t\t\t\t\t\tc: C,\n\t\t\t\t\t\t\t\tr: R\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\tif ( typeof cell.v === \"number\" ) {\n\t\t\t\t\t\t\t\tcell.t = \"n\";\n\t\t\t\t\t\t\t} else if ( typeof cell.v === \"boolean\" ) {\n\t\t\t\t\t\t\t\tcell.t = \"b\";\n\t\t\t\t\t\t\t} else if ( cell.v instanceof Date ) {\n\t\t\t\t\t\t\t\tcell.t = \"n\";\n\t\t\t\t\t\t\t\tcell.z = XLSX.SSF._table[ 14 ];\n\t\t\t\t\t\t\t\tcell.v = datenum( cell.v );\n\t\t\t\t\t\t\t} else if ( cell.v instanceof Object ) {\n\t\t\t\t\t\t\t\tcell.t = \"s\";\n\t\t\t\t\t\t\t\tcell.v = JSON.stringify( cell.v );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcell.t = \"s\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tws[ cell_ref ] = cell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( range.s.c < 10000000 ) ws[ \"!ref\" ] = XLSX.utils.encode_range( range );\n\t\t\t\t\treturn ws;\n\t\t\t\t}\n\n\t\t\t\twb.SheetNames.push( cfg.name );\n\t\t\t\twb.Sheets[ cfg.name ] = sheet_from_array_of_arrays( buffer );\n\n\t\t\t\tdata = XLSX.write( wb, {\n\t\t\t\t\tbookType: \"xlsx\",\n\t\t\t\t\tbookSST: true,\n\t\t\t\t\ttype: \"base64\"\n\t\t\t\t} );\n\n\t\t\t\tdata = \"data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,\" + data;\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates an array of arrays\n\t\t\t */\n\t\t\ttoArray: function( options, callback ) {\n\t\t\t\tvar row, col;\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\twithHeader: false,\n\t\t\t\t\tstringify: true,\n\t\t\t\t\tescape: false,\n\t\t\t\t\tquotes: false\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar data = [];\n\t\t\t\tvar cols = [];\n\t\t\t\tvar buffer = [];\n\t\t\t\tvar _processData = _this.config.processData;\n\n\t\t\t\t// RETRIEVES RIGHT FIELD ORDER OF TRANSLATED FIELDS\n\t\t\t\tfunction processData( data, cfg ) {\n\t\t\t\t\tvar fields = cfg.exportFields || Object.keys( cfg.dataFieldsMap );\n\n\t\t\t\t\t// WALKTHROUGH FIELDS\n\t\t\t\t\tfor ( col = 0; col < fields.length; col++ ) {\n\t\t\t\t\t\tvar key = fields[ col ];\n\t\t\t\t\t\tvar field = cfg.dataFieldsTitlesMap[ key ];\n\t\t\t\t\t\tcols.push( field );\n\t\t\t\t\t}\n\n\t\t\t\t\t// TRIGGER GIVEN CALLBACK\n\t\t\t\t\tif ( _processData ) {\n\t\t\t\t\t\treturn _this.handleCallback( _processData, data, cfg );\n\t\t\t\t\t}\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// STRING PROCESSOR\n\t\t\t\tfunction enchant( value ) {\n\n\t\t\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\t\t\tif ( cfg.escape ) {\n\t\t\t\t\t\t\tvalue = value.replace( '\"', '\"\"' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( cfg.quotes ) {\n\t\t\t\t\t\t\tvalue = [ '\"', value, '\"' ].join( \"\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\n\t\t\t\t// INVOKE PROCESS DATA\n\t\t\t\tcfg.processData = processData;\n\n\t\t\t\t// GET DATA\n\t\t\t\tcfg.data = cfg.data !== undefined ? _this.processData( cfg ) : _this.getChartData( cfg );\n\n\t\t\t\t// HEADER\n\t\t\t\tif ( cfg.withHeader ) {\n\t\t\t\t\tbuffer = [];\n\t\t\t\t\tfor ( col in cols ) {\n\t\t\t\t\t\tif ( !isNaN( col ) ) {\n\t\t\t\t\t\t\tbuffer.push( enchant( cols[ col ] ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdata.push( buffer );\n\t\t\t\t}\n\n\t\t\t\t// BODY\n\t\t\t\tfor ( row in cfg.data ) {\n\t\t\t\t\tbuffer = [];\n\t\t\t\t\tif ( !isNaN( row ) ) {\n\t\t\t\t\t\tfor ( col in cols ) {\n\t\t\t\t\t\t\tif ( !isNaN( col ) ) {\n\t\t\t\t\t\t\t\tvar col = cols[ col ];\n\t\t\t\t\t\t\t\tvar value = cfg.data[ row ][ col ];\n\t\t\t\t\t\t\t\tif ( value == null ) {\n\t\t\t\t\t\t\t\t\tvalue = \"\";\n\t\t\t\t\t\t\t\t} else if ( cfg.stringify ) {\n\t\t\t\t\t\t\t\t\tvalue = String( value );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvalue = value;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbuffer.push( enchant( value ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata.push( buffer );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates byte array with given base64 datastring; returns byte array\n\t\t\t */\n\t\t\ttoByteArray: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\t// NUFFIN\n\t\t\t\t}, options || {} );\n\t\t\t\tvar Arr = ( typeof Uint8Array !== 'undefined' ) ? Uint8Array : Array\n\t\t\t\tvar PLUS = '+'.charCodeAt( 0 )\n\t\t\t\tvar SLASH = '/'.charCodeAt( 0 )\n\t\t\t\tvar NUMBER = '0'.charCodeAt( 0 )\n\t\t\t\tvar LOWER = 'a'.charCodeAt( 0 )\n\t\t\t\tvar UPPER = 'A'.charCodeAt( 0 )\n\t\t\t\tvar data = b64ToByteArray( cfg.data );\n\n\t\t\t\tfunction decode( elt ) {\n\t\t\t\t\tvar code = elt.charCodeAt( 0 )\n\t\t\t\t\tif ( code === PLUS )\n\t\t\t\t\t\treturn 62 // '+'\n\t\t\t\t\tif ( code === SLASH )\n\t\t\t\t\t\treturn 63 // '/'\n\t\t\t\t\tif ( code < NUMBER )\n\t\t\t\t\t\treturn -1 //no match\n\t\t\t\t\tif ( code < NUMBER + 10 )\n\t\t\t\t\t\treturn code - NUMBER + 26 + 26\n\t\t\t\t\tif ( code < UPPER + 26 )\n\t\t\t\t\t\treturn code - UPPER\n\t\t\t\t\tif ( code < LOWER + 26 )\n\t\t\t\t\t\treturn code - LOWER + 26\n\t\t\t\t}\n\n\t\t\t\tfunction b64ToByteArray( b64 ) {\n\t\t\t\t\tvar i, j, l, tmp, placeHolders, arr\n\n\t\t\t\t\tif ( b64.length % 4 > 0 ) {\n\t\t\t\t\t\tthrow new Error( 'Invalid string. Length must be a multiple of 4' )\n\t\t\t\t\t}\n\n\t\t\t\t\t// THE NUMBER OF EQUAL SIGNS (PLACE HOLDERS)\n\t\t\t\t\t// IF THERE ARE TWO PLACEHOLDERS, THAN THE TWO CHARACTERS BEFORE IT\n\t\t\t\t\t// REPRESENT ONE BYTE\n\t\t\t\t\t// IF THERE IS ONLY ONE, THEN THE THREE CHARACTERS BEFORE IT REPRESENT 2 BYTES\n\t\t\t\t\t// THIS IS JUST A CHEAP HACK TO NOT DO INDEXOF TWICE\n\t\t\t\t\tvar len = b64.length\n\t\t\t\t\tplaceHolders = '=' === b64.charAt( len - 2 ) ? 2 : '=' === b64.charAt( len - 1 ) ? 1 : 0\n\n\t\t\t\t\t// BASE64 IS 4/3 + UP TO TWO CHARACTERS OF THE ORIGINAL DATA\n\t\t\t\t\tarr = new Arr( b64.length * 3 / 4 - placeHolders )\n\n\t\t\t\t\t// IF THERE ARE PLACEHOLDERS, ONLY GET UP TO THE LAST COMPLETE 4 CHARS\n\t\t\t\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length\n\n\t\t\t\t\tvar L = 0\n\n\t\t\t\t\tfunction push( v ) {\n\t\t\t\t\t\tarr[ L++ ] = v\n\t\t\t\t\t}\n\n\t\t\t\t\tfor ( i = 0, j = 0; i < l; i += 4, j += 3 ) {\n\t\t\t\t\t\ttmp = ( decode( b64.charAt( i ) ) << 18 ) | ( decode( b64.charAt( i + 1 ) ) << 12 ) | ( decode( b64.charAt( i + 2 ) ) << 6 ) | decode( b64.charAt( i + 3 ) )\n\t\t\t\t\t\tpush( ( tmp & 0xFF0000 ) >> 16 )\n\t\t\t\t\t\tpush( ( tmp & 0xFF00 ) >> 8 )\n\t\t\t\t\t\tpush( tmp & 0xFF )\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( placeHolders === 2 ) {\n\t\t\t\t\t\ttmp = ( decode( b64.charAt( i ) ) << 2 ) | ( decode( b64.charAt( i + 1 ) ) >> 4 )\n\t\t\t\t\t\tpush( tmp & 0xFF )\n\t\t\t\t\t} else if ( placeHolders === 1 ) {\n\t\t\t\t\t\ttmp = ( decode( b64.charAt( i ) ) << 10 ) | ( decode( b64.charAt( i + 1 ) ) << 4 ) | ( decode( b64.charAt( i + 2 ) ) >> 2 )\n\t\t\t\t\t\tpush( ( tmp >> 8 ) & 0xFF )\n\t\t\t\t\t\tpush( tmp & 0xFF )\n\t\t\t\t\t}\n\n\t\t\t\t\treturn arr\n\t\t\t\t}\n\n\t\t\t\t// TRIGGER CALLBACK\n\t\t\t\t_this.handleCallback( callback, data, cfg );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Callback handler; injects additional arguments to callback\n\t\t\t */\n\t\t\thandleCallback: function( callback ) {\n\t\t\t\tvar i1, data = Array();\n\t\t\t\tif ( callback && callback instanceof Function ) {\n\t\t\t\t\tfor ( i1 = 0; i1 < arguments.length; i1++ ) {\n\t\t\t\t\t\tif ( i1 > 0 ) {\n\t\t\t\t\t\t\tdata.push( arguments[ i1 ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn callback.apply( _this, data );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Logger\n\t\t\t */\n\t\t\thandleLog: function( msg ) {\n\t\t\t\tif ( _this.config.debug === true ) {\n\t\t\t\t\tconsole.log( msg );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Namespace checker; delays given callback until the dependency is available\n\t\t\t */\n\t\t\thandleNamespace: function( namespace, opts ) {\n\t\t\t\tvar scope = _this.config.scope || window;\n\t\t\t\tvar exists = false;\n\t\t\t\tvar startTS = Number( new Date() );\n\t\t\t\tvar timer;\n\n\t\t\t\t// SIMPLE CHECK\n\t\t\t\texists = !!( namespace in scope );\n\n\t\t\t\t// RESURSIVE DEPENDENCY CHECK\n\t\t\t\tfunction waitForIt() {\n\t\t\t\t\tvar tmpTS = Number( new Date() );\n\n\t\t\t\t\t// SIMPLE CHECK\n\t\t\t\t\texists = !!( namespace in scope );\n\n\t\t\t\t\t// PDFMAKE EXCEPTION; WAIT ADDITIONALLY FOR FONTS\n\t\t\t\t\tif ( namespace == \"pdfMake\" && exists ) {\n\t\t\t\t\t\texists = scope.pdfMake.vfs;\n\t\t\t\t\t}\n\n\t\t\t\t\t// FOUND TRIGGER GIVEN CALLBACK\n\t\t\t\t\tif ( exists ) {\n\t\t\t\t\t\tclearTimeout( timer );\n\t\t\t\t\t\topts.cb.apply( opts.scope, opts.args );\n\t\t\t\t\t\t_this.handleLog( [ \"AmCharts [export]: Namespace \\\"\", namespace, \"\\\" showed up in: \", String( scope ) ].join( \"\" ) );\n\n\t\t\t\t\t\t// NOT FOUND SCHEDULE RECHECK\n\t\t\t\t\t} else if ( tmpTS - startTS < _this.libs.loadTimeout ) {\n\t\t\t\t\t\ttimer = setTimeout( waitForIt, 250 );\n\n\t\t\t\t\t\t// LIBS TIMEOUT REACHED\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_this.handleLog( [ \"AmCharts [export]: Gave up waiting for \\\"\", namespace, \"\\\" in: \", String( scope ) ].join( \"\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// THROW MESSAGE IF IT DOESNT EXIST\n\t\t\t\tif ( !exists ) {\n\t\t\t\t\t_this.handleLog( [ \"AmCharts [export]: Could not find \\\"\", namespace, \"\\\" in: \", String( scope ) ].join( \"\" ) );\n\t\t\t\t\twaitForIt();\n\t\t\t\t}\n\n\t\t\t\treturn exists;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Border handler; injects additional border to canvas\n\t\t\t */\n\t\t\thandleBorder: function( options ) {\n\t\t\t\tif ( _this.config.border instanceof Object ) {\n\t\t\t\t\tvar cfg = _this.deepMerge( _this.defaults.fabric.border, options.border || {}, true );\n\t\t\t\t\tvar border = new fabric.Rect();\n\n\t\t\t\t\tcfg.width = _this.setup.fabric.width - cfg.strokeWidth;\n\t\t\t\t\tcfg.height = _this.setup.fabric.height - cfg.strokeWidth;\n\n\t\t\t\t\tborder.set( cfg );\n\n\t\t\t\t\t_this.setup.fabric.add( border );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Handles drag/drop events; loads given imagery\n\t\t\t */\n\t\t\thandleDropbox: function( e ) {\n\t\t\t\tif ( _this.drawing.enabled ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\n\t\t\t\t\t// DRAG OVER\n\t\t\t\t\tif ( e.type == \"dragover\" ) {\n\t\t\t\t\t\t_this.setup.wrapper.setAttribute( \"class\", _this.setup.chart.classNamePrefix + \"-export-canvas active dropbox\" );\n\n\t\t\t\t\t\t// DRAGLEAVE; DROP\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_this.setup.wrapper.setAttribute( \"class\", _this.setup.chart.classNamePrefix + \"-export-canvas active\" );\n\n\t\t\t\t\t\tif ( e.type == \"drop\" && e.dataTransfer.files.length ) {\n\t\t\t\t\t\t\tfor ( var i1 = 0; i1 < e.dataTransfer.files.length; i1++ ) {\n\t\t\t\t\t\t\t\tvar reader = new FileReader();\n\t\t\t\t\t\t\t\treader.onloadend = ( function( index ) {\n\t\t\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\t\t\t_this.drawing.handler.add( {\n\t\t\t\t\t\t\t\t\t\t\turl: reader.result,\n\t\t\t\t\t\t\t\t\t\t\ttop: e.layerY - ( index * 10 ),\n\t\t\t\t\t\t\t\t\t\t\tleft: e.layerX - ( index * 10 )\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )( i1 );\n\t\t\t\t\t\t\t\treader.readAsDataURL( e.dataTransfer.files[ i1 ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Calls ready callback when dependencies are available within window scope\n\t\t\t */\n\t\t\thandleReady: function( callback ) {\n\t\t\t\tvar t1, t2;\n\t\t\t\tvar _this = this;\n\t\t\t\tvar tsStart = Number( new Date() );\n\n\t\t\t\t// READY FOR DATA EXPORT\n\t\t\t\t_this.handleCallback( callback, \"data\", false );\n\n\t\t\t\t// READY CALLBACK FOR EACH DEPENDENCY\n\t\t\t\tfor ( filename in _this.libs.namespaces ) {\n\t\t\t\t\tvar namespace = _this.libs.namespaces[ filename ];\n\n\t\t\t\t\t( function( namespace ) {\n\t\t\t\t\t\tvar t1 = setInterval( function() {\n\t\t\t\t\t\t\tvar tsEnd = Number( new Date() );\n\n\t\t\t\t\t\t\tif ( tsEnd - tsStart > _this.libs.loadTimeout || namespace in window ) {\n\t\t\t\t\t\t\t\tclearTimeout( t1 );\n\t\t\t\t\t\t\t\t_this.handleCallback( callback, namespace, tsEnd - tsStart > _this.libs.loadTimeout );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, AmCharts.updateRate )\n\t\t\t\t\t} )( namespace );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Gathers chart data according to its type\n\t\t\t */\n\t\t\tgetChartData: function( options ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdata: [],\n\t\t\t\t\ttitles: {},\n\t\t\t\t\tdateFields: [],\n\t\t\t\t\tdataFields: [],\n\t\t\t\t\tdataFieldsMap: {},\n\t\t\t\t\texportTitles: _this.config.exportTitles,\n\t\t\t\t\texportFields: _this.config.exportFields,\n\t\t\t\t\texportSelection: _this.config.exportSelection,\n\t\t\t\t\tcolumnNames: _this.config.columnNames\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar uid, i1, i2, i3;\n\t\t\t\tvar lookupFields = [ \"valueField\", \"openField\", \"closeField\", \"highField\", \"lowField\", \"xField\", \"yField\" ];\n\t\t\t\tvar buffer;\n\n\t\t\t\t// HANDLE FIELDS\n\t\t\t\tfunction addField( field, title, type ) {\n\n\t\t\t\t\tfunction checkExistance( field, type ) {\n\t\t\t\t\t\tif ( cfg.dataFields.indexOf( field ) != -1 ) {\n\t\t\t\t\t\t\treturn checkExistance( [ field, \".\", type ].join( \"\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn field;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( field && cfg.exportTitles && _this.setup.chart.type != \"gantt\" ) {\n\t\t\t\t\t\tuid = checkExistance( field, type );\n\t\t\t\t\t\tcfg.dataFieldsMap[ uid ] = field;\n\t\t\t\t\t\tcfg.dataFields.push( uid );\n\t\t\t\t\t\tcfg.titles[ uid ] = title || uid;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( cfg.data.length == 0 ) {\n\n\t\t\t\t\t// STOCK DATA; GATHER COMPARED GRAPHS\n\t\t\t\t\tif ( _this.setup.chart.type == \"stock\" ) {\n\t\t\t\t\t\tcfg.data = _this.cloneObject( _this.setup.chart.mainDataSet.dataProvider );\n\n\t\t\t\t\t\t// CATEGORY AXIS\n\t\t\t\t\t\taddField( _this.setup.chart.mainDataSet.categoryField );\n\t\t\t\t\t\tcfg.dateFields.push( _this.setup.chart.mainDataSet.categoryField );\n\n\t\t\t\t\t\t// WALKTHROUGH GRAPHS\n\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.setup.chart.mainDataSet.fieldMappings.length; i1++ ) {\n\t\t\t\t\t\t\tvar fieldMap = _this.setup.chart.mainDataSet.fieldMappings[ i1 ];\n\t\t\t\t\t\t\tfor ( i2 = 0; i2 < _this.setup.chart.panels.length; i2++ ) {\n\t\t\t\t\t\t\t\tvar panel = _this.setup.chart.panels[ i2 ]\n\t\t\t\t\t\t\t\tfor ( i3 = 0; i3 < panel.stockGraphs.length; i3++ ) {\n\t\t\t\t\t\t\t\t\tvar graph = panel.stockGraphs[ i3 ];\n\n\t\t\t\t\t\t\t\t\tfor ( i4 = 0; i4 < lookupFields.length; i4++ ) {\n\t\t\t\t\t\t\t\t\t\tif ( graph[ lookupFields[ i4 ] ] == fieldMap.toField ) {\n\t\t\t\t\t\t\t\t\t\t\taddField( fieldMap.fromField, graph.title, lookupFields[ i4 ] );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// MERGE DATA OF COMPARED GRAPHS IN RIGHT PLACE\n\t\t\t\t\t\tif ( _this.setup.chart.comparedGraphs.length ) {\n\n\t\t\t\t\t\t\t// BUFFER DATES FROM MAIN DATA SET\n\t\t\t\t\t\t\tbuffer = [];\n\t\t\t\t\t\t\tfor ( i1 = 0; i1 < cfg.data.length; i1++ ) {\n\t\t\t\t\t\t\t\tbuffer.push( cfg.data[ i1 ][ _this.setup.chart.mainDataSet.categoryField ] );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// WALKTHROUGH COMPARISON AND MERGE IT'S DATA\n\t\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.setup.chart.comparedGraphs.length; i1++ ) {\n\t\t\t\t\t\t\t\tvar graph = _this.setup.chart.comparedGraphs[ i1 ];\n\t\t\t\t\t\t\t\tfor ( i2 = 0; i2 < graph.dataSet.dataProvider.length; i2++ ) {\n\t\t\t\t\t\t\t\t\tvar categoryField = graph.dataSet.categoryField;\n\t\t\t\t\t\t\t\t\tvar categoryValue = graph.dataSet.dataProvider[ i2 ][ categoryField ];\n\t\t\t\t\t\t\t\t\tvar comparedIndex = buffer.indexOf( categoryValue );\n\n\t\t\t\t\t\t\t\t\t// PLACE IN RIGHT PLACE\n\t\t\t\t\t\t\t\t\tif ( comparedIndex != -1 ) {\n\t\t\t\t\t\t\t\t\t\tfor ( i3 = 0; i3 < graph.dataSet.fieldMappings.length; i3++ ) {\n\t\t\t\t\t\t\t\t\t\t\tvar fieldMap = graph.dataSet.fieldMappings[ i3 ];\n\t\t\t\t\t\t\t\t\t\t\tvar uid = graph.dataSet.id + \"_\" + fieldMap.toField;\n\n\t\t\t\t\t\t\t\t\t\t\tcfg.data[ comparedIndex ][ uid ] = graph.dataSet.dataProvider[ i2 ][ fieldMap.fromField ];\n\n\t\t\t\t\t\t\t\t\t\t\t// UNIQUE TITLE\n\t\t\t\t\t\t\t\t\t\t\tif ( !cfg.titles[ uid ] ) {\n\t\t\t\t\t\t\t\t\t\t\t\taddField( uid, graph.dataSet.title )\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GANTT DATA; FLATTEN SEGMENTS\n\t\t\t\t\t} else if ( _this.setup.chart.type == \"gantt\" ) {\n\t\t\t\t\t\t// CATEGORY AXIS\n\t\t\t\t\t\taddField( _this.setup.chart.categoryField );\n\n\t\t\t\t\t\tvar field = _this.setup.chart.segmentsField;\n\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.setup.chart.dataProvider.length; i1++ ) {\n\t\t\t\t\t\t\tvar dataItem = _this.setup.chart.dataProvider[ i1 ];\n\t\t\t\t\t\t\tif ( dataItem[ field ] ) {\n\t\t\t\t\t\t\t\tfor ( i2 = 0; i2 < dataItem[ field ].length; i2++ ) {\n\t\t\t\t\t\t\t\t\tdataItem[ field ][ i2 ][ _this.setup.chart.categoryField ] = dataItem[ _this.setup.chart.categoryField ];\n\t\t\t\t\t\t\t\t\tcfg.data.push( dataItem[ field ][ i2 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GRAPHS\n\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.setup.chart.graphs.length; i1++ ) {\n\t\t\t\t\t\t\tvar graph = _this.setup.chart.graphs[ i1 ];\n\n\t\t\t\t\t\t\tfor ( i2 = 0; i2 < lookupFields.length; i2++ ) {\n\t\t\t\t\t\t\t\tvar dataField = lookupFields[ i2 ];\n\t\t\t\t\t\t\t\tvar graphField = graph[ dataField ];\n\t\t\t\t\t\t\t\tvar title = graph.title;\n\n\t\t\t\t\t\t\t\taddField( graphField, graph.title, dataField );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// PIE/FUNNEL DATA;\n\t\t\t\t\t} else if ( [ \"pie\", \"funnel\" ].indexOf( _this.setup.chart.type ) != -1 ) {\n\t\t\t\t\t\tcfg.data = _this.setup.chart.dataProvider;\n\n\t\t\t\t\t\t// CATEGORY AXIS\n\t\t\t\t\t\taddField( _this.setup.chart.titleField );\n\t\t\t\t\t\tcfg.dateFields.push( _this.setup.chart.titleField );\n\n\t\t\t\t\t\t// VALUE\n\t\t\t\t\t\taddField( _this.setup.chart.valueField );\n\n\t\t\t\t\t\t// DEFAULT DATA;\n\t\t\t\t\t} else if ( _this.setup.chart.type != \"map\" ) {\n\t\t\t\t\t\tcfg.data = _this.setup.chart.dataProvider;\n\n\t\t\t\t\t\t// CATEGORY AXIS\n\t\t\t\t\t\tif ( _this.setup.chart.categoryAxis ) {\n\t\t\t\t\t\t\taddField( _this.setup.chart.categoryField, _this.setup.chart.categoryAxis.title );\n\t\t\t\t\t\t\tif ( _this.setup.chart.categoryAxis.parseDates !== false ) {\n\t\t\t\t\t\t\t\tcfg.dateFields.push( _this.setup.chart.categoryField );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// GRAPHS\n\t\t\t\t\t\tfor ( i1 = 0; i1 < _this.setup.chart.graphs.length; i1++ ) {\n\t\t\t\t\t\t\tvar graph = _this.setup.chart.graphs[ i1 ];\n\n\t\t\t\t\t\t\tfor ( i2 = 0; i2 < lookupFields.length; i2++ ) {\n\t\t\t\t\t\t\t\tvar dataField = lookupFields[ i2 ];\n\t\t\t\t\t\t\t\tvar graphField = graph[ dataField ];\n\n\t\t\t\t\t\t\t\taddField( graphField, graph.title, dataField );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn _this.processData( cfg );\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Returns embedded annotations in an array\n\t\t\t */\n\t\t\tgetAnnotations: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\t// For the future\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar i1;\n\t\t\t\tvar data = [];\n\n\t\t\t\t// Collect annotations\n\t\t\t\tfor ( i1 = 0; i1 < _this.setup.fabric._objects.length; i1++ ) {\n\n\t\t\t\t\t// Internal flag to distinguish between annotations and \"core\" elements\n\t\t\t\t\tif ( !_this.setup.fabric._objects[ i1 ].isCoreElement ) {\n\t\t\t\t\t\tvar obj = _this.setup.fabric._objects[ i1 ].toJSON();\n\n\t\t\t\t\t\t// Revive before adding to allow modifying the object\n\t\t\t\t\t\t_this.handleCallback( cfg.reviver, obj, i1 );\n\n\t\t\t\t\t\t// Push into output\n\t\t\t\t\t\tdata.push( obj );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t_this.handleCallback( callback, data );\n\n\t\t\t\treturn data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Inserts the given annotations\n\t\t\t */\n\t\t\tsetAnnotations: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdata: []\n\t\t\t\t}, options || {}, true );\n\n\t\t\t\t// Convert annotations objects into fabric instances\n\t\t\t\tfabric.util.enlivenObjects( cfg.data, function( enlivenedObjects ) {\n\t\t\t\t\tenlivenedObjects.forEach( function( obj, i1 ) {\n\n\t\t\t\t\t\t// Revive before adding to allow modifying the object\n\t\t\t\t\t\t_this.handleCallback( cfg.reviver, obj, i1 );\n\n\t\t\t\t\t\t// Add into active instance canvas\n\t\t\t\t\t\t_this.setup.fabric.add( obj );\n\t\t\t\t\t} );\n\n\t\t\t\t\t_this.handleCallback( callback, cfg );\n\t\t\t\t} );\n\n\t\t\t\treturn cfg.data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Walkthrough data to format dates and titles\n\t\t\t */\n\t\t\tprocessData: function( options ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdata: [],\n\t\t\t\t\ttitles: {},\n\t\t\t\t\tdateFields: [],\n\t\t\t\t\tdataFields: [],\n\t\t\t\t\tdataFieldsMap: {},\n\t\t\t\t\tdataFieldsTitlesMap: {},\n\t\t\t\t\tdataDateFormat: _this.setup.chart.dataDateFormat,\n\t\t\t\t\tdateFormat: _this.config.dateFormat || _this.setup.chart.dataDateFormat || \"YYYY-MM-DD\",\n\t\t\t\t\texportTitles: _this.config.exportTitles,\n\t\t\t\t\texportFields: _this.config.exportFields,\n\t\t\t\t\texportSelection: _this.config.exportSelection,\n\t\t\t\t\tcolumnNames: _this.config.columnNames,\n\t\t\t\t\tprocessData: _this.config.processData\n\t\t\t\t}, options || {}, true );\n\t\t\t\tvar i1, i2;\n\n\t\t\t\tif ( cfg.data.length ) {\n\t\t\t\t\t// GATHER MISSING FIELDS\n\t\t\t\t\tfor ( i1 = 0; i1 < cfg.data.length; i1++ ) {\n\t\t\t\t\t\tfor ( i2 in cfg.data[ i1 ] ) {\n\t\t\t\t\t\t\tif ( cfg.dataFields.indexOf( i2 ) == -1 ) {\n\t\t\t\t\t\t\t\tcfg.dataFields.push( i2 );\n\t\t\t\t\t\t\t\tcfg.dataFieldsMap[ i2 ] = i2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// REMOVE FIELDS SELECTIVELY\n\t\t\t\t\tif ( cfg.exportFields !== undefined ) {\n\t\t\t\t\t\tcfg.dataFields = cfg.exportFields.filter( function( n ) {\n\t\t\t\t\t\t\treturn cfg.dataFields.indexOf( n ) != -1;\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\n\t\t\t\t\t// REBUILD DATA\n\t\t\t\t\tvar buffer = [];\n\t\t\t\t\tfor ( i1 = 0; i1 < cfg.data.length; i1++ ) {\n\t\t\t\t\t\tvar tmp = {};\n\t\t\t\t\t\tvar skip = false;\n\t\t\t\t\t\tfor ( i2 = 0; i2 < cfg.dataFields.length; i2++ ) {\n\t\t\t\t\t\t\tvar uniqueField = cfg.dataFields[ i2 ];\n\t\t\t\t\t\t\tvar dataField = cfg.dataFieldsMap[ uniqueField ];\n\t\t\t\t\t\t\tvar title = ( cfg.columnNames && cfg.columnNames[ uniqueField ] ) || cfg.titles[ uniqueField ] || uniqueField;\n\t\t\t\t\t\t\tvar value = cfg.data[ i1 ][ dataField ];\n\n\t\t\t\t\t\t\t// SKIP NULL ONES\n\t\t\t\t\t\t\tif ( value == null ) {\n\t\t\t\t\t\t\t\tvalue = undefined;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// TITLEFY\n\t\t\t\t\t\t\tif ( cfg.exportTitles && _this.setup.chart.type != \"gantt\" ) {\n\t\t\t\t\t\t\t\tif ( title in tmp ) {\n\t\t\t\t\t\t\t\t\ttitle += [ \"( \", uniqueField, \" )\" ].join( \"\" );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// PROCESS CATEGORY\n\t\t\t\t\t\t\tif ( cfg.dateFields.indexOf( dataField ) != -1 ) {\n\n\t\t\t\t\t\t\t\t// CONVERT DATESTRING TO DATE OBJECT\n\t\t\t\t\t\t\t\tif ( cfg.dataDateFormat && ( value instanceof String || typeof value == \"string\" ) ) {\n\t\t\t\t\t\t\t\t\tvalue = AmCharts.stringToDate( value, cfg.dataDateFormat );\n\n\t\t\t\t\t\t\t\t\t// CONVERT TIMESTAMP TO DATE OBJECT\n\t\t\t\t\t\t\t\t} else if ( cfg.dateFormat && ( value instanceof Number || typeof value == \"number\" ) ) {\n\t\t\t\t\t\t\t\t\tvalue = new Date( value );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// CATEGORY RANGE\n\t\t\t\t\t\t\t\tif ( cfg.exportSelection ) {\n\t\t\t\t\t\t\t\t\tif ( value instanceof Date ) {\n\t\t\t\t\t\t\t\t\t\tif ( value < chart.startDate || value > chart.endDate ) {\n\t\t\t\t\t\t\t\t\t\t\tskip = true;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t} else if ( i1 < chart.startIndex || i1 > chart.endIndex ) {\n\t\t\t\t\t\t\t\t\t\tskip = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// CATEGORY FORMAT\n\t\t\t\t\t\t\t\tif ( cfg.dateFormat && cfg.dateFormat != \"dateObject\" && value instanceof Date ) {\n\t\t\t\t\t\t\t\t\tvalue = AmCharts.formatDate( value, cfg.dateFormat );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcfg.dataFieldsTitlesMap[ dataField ] = title;\n\n\t\t\t\t\t\t\ttmp[ title ] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !skip ) {\n\t\t\t\t\t\t\tbuffer.push( tmp );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcfg.data = buffer;\n\t\t\t\t}\n\n\t\t\t\tif ( cfg.processData !== undefined ) {\n\t\t\t\t\tcfg.data = _this.handleCallback( cfg.processData, cfg.data, cfg );\n\t\t\t\t}\n\n\t\t\t\treturn cfg.data;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Prettifies string\n\t\t\t */\n\t\t\tcapitalize: function( string ) {\n\t\t\t\treturn string.charAt( 0 ).toUpperCase() + string.slice( 1 ).toLowerCase();\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Generates export menu; returns UL node\n\t\t\t */\n\t\t\tcreateMenu: function( list, container ) {\n\t\t\t\tvar div;\n\t\t\t\tvar buffer = [];\n\n\t\t\t\tfunction buildList( list, container ) {\n\t\t\t\t\tvar i1, i2, ul = document.createElement( \"ul\" );\n\t\t\t\t\tfor ( i1 = 0; i1 < list.length; i1++ ) {\n\t\t\t\t\t\tvar item = typeof list[ i1 ] === \"string\" ? {\n\t\t\t\t\t\t\tformat: list[ i1 ]\n\t\t\t\t\t\t} : list[ i1 ];\n\t\t\t\t\t\tvar li = document.createElement( \"li\" );\n\t\t\t\t\t\tvar a = document.createElement( \"a\" );\n\t\t\t\t\t\tvar img = document.createElement( \"img\" );\n\t\t\t\t\t\tvar span = document.createElement( \"span\" );\n\t\t\t\t\t\tvar action = String( item.action ? item.action : item.format ).toLowerCase();\n\n\t\t\t\t\t\titem.format = String( item.format ).toUpperCase();\n\n\t\t\t\t\t\t// REMOVE ACTIVE CLASS ON MOUSELEAVE\n\t\t\t\t\t\tli.addEventListener(\"mouseleave\",function(e) {\n\t\t\t\t\t\t\tthis.classList.remove(\"active\");\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// LISTEN ON FOCUS; NON-TOUCH DEVICES ONLY\n\t\t\t\t\t\ta.addEventListener( \"focus\", function( e ) {\n\t\t\t\t\t\t\tif ( !_this.setup.hasTouch ) {\n\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem = this;\n\t\t\t\t\t\t\t\tvar list = this.parentNode;\n\n\t\t\t\t\t\t\t\tif ( list.tagName != \"UL\" ) {\n\t\t\t\t\t\t\t\t\tlist = list.parentNode;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// REMOVE ACTIVE CLASSES\n\t\t\t\t\t\t\t\tvar items = list.getElementsByTagName(\"li\");\n\t\t\t\t\t\t\t\tfor ( i1 = 0; i1 < items.length; i1++ ) {\n\t\t\t\t\t\t\t\t\titems[i1].classList.remove(\"active\");\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tthis.parentNode.classList.add( \"active\" );\n\t\t\t\t\t\t\t\tthis.parentNode.parentNode.parentNode.classList.add( \"active\" );\t\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t// MERGE WITH GIVEN FORMAT\n\t\t\t\t\t\tif ( _this.config.formats[ item.format ] ) {\n\t\t\t\t\t\t\titem = _this.deepMerge( {\n\t\t\t\t\t\t\t\tlabel: item.icon ? \"\" : item.format,\n\t\t\t\t\t\t\t\tformat: item.format,\n\t\t\t\t\t\t\t\tmimeType: _this.config.formats[ item.format ].mimeType,\n\t\t\t\t\t\t\t\textension: _this.config.formats[ item.format ].extension,\n\t\t\t\t\t\t\t\tcapture: _this.config.formats[ item.format ].capture,\n\t\t\t\t\t\t\t\taction: _this.config.action,\n\t\t\t\t\t\t\t\tfileName: _this.config.fileName\n\t\t\t\t\t\t\t}, item );\n\t\t\t\t\t\t} else if ( !item.label ) {\n\t\t\t\t\t\t\titem.label = item.label ? item.label : _this.i18l( \"menu.label.\" + action );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// FILTER; TOGGLE FLAG\n\t\t\t\t\t\tif ( [ \"CSV\", \"JSON\", \"XLSX\" ].indexOf( item.format ) != -1 && [ \"map\", \"gauge\" ].indexOf( _this.setup.chart.type ) != -1 ) {\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\t// BLOB EXCEPTION\n\t\t\t\t\t\t} else if ( !_this.setup.hasBlob && item.format != \"UNDEFINED\" ) {\n\t\t\t\t\t\t\tif ( item.mimeType && item.mimeType.split( \"/\" )[ 0 ] != \"image\" && item.mimeType != \"text/plain\" ) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// DRAWING\n\t\t\t\t\t\tif ( item.action == \"draw\" ) {\n\t\t\t\t\t\t\tif ( _this.config.fabric.drawing.enabled ) {\n\t\t\t\t\t\t\t\titem.menu = item.menu ? item.menu : _this.config.fabric.drawing.menu;\n\t\t\t\t\t\t\t\titem.click = ( function( item ) {\n\t\t\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\t\t\tthis.capture( item, function() {\n\t\t\t\t\t\t\t\t\t\t\tthis.createMenu( item.menu );\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )( item );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\titem.menu = [];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// DRAWING CHOICES\n\t\t\t\t\t\t} else if ( !item.populated && item.action && item.action.indexOf( \"draw.\" ) != -1 ) {\n\t\t\t\t\t\t\tvar type = item.action.split( \".\" )[ 1 ];\n\t\t\t\t\t\t\tvar items = item[ type ] || _this.config.fabric.drawing[ type ] || [];\n\n\t\t\t\t\t\t\titem.menu = [];\n\t\t\t\t\t\t\titem.populated = true;\n\n\t\t\t\t\t\t\tfor ( i2 = 0; i2 < items.length; i2++ ) {\n\t\t\t\t\t\t\t\tvar tmp = {\n\t\t\t\t\t\t\t\t\t\"label\": items[ i2 ]\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif ( type == \"shapes\" ) {\n\t\t\t\t\t\t\t\t\tvar io = items[ i2 ].indexOf( \"//\" ) == -1;\n\t\t\t\t\t\t\t\t\tvar url = ( io ? _this.config.path + \"shapes/\" : \"\" ) + items[ i2 ];\n\n\t\t\t\t\t\t\t\t\ttmp.action = \"add\";\n\t\t\t\t\t\t\t\t\ttmp.url = url;\n\t\t\t\t\t\t\t\t\ttmp.icon = url;\n\t\t\t\t\t\t\t\t\ttmp.ignore = io;\n\t\t\t\t\t\t\t\t\ttmp[ \"class\" ] = \"export-drawing-shape\";\n\n\t\t\t\t\t\t\t\t} else if ( type == \"colors\" ) {\n\t\t\t\t\t\t\t\t\ttmp.style = \"background-color: \" + items[ i2 ];\n\t\t\t\t\t\t\t\t\ttmp.action = \"change\";\n\t\t\t\t\t\t\t\t\ttmp.color = items[ i2 ];\n\t\t\t\t\t\t\t\t\ttmp[ \"class\" ] = \"export-drawing-color\";\n\n\t\t\t\t\t\t\t\t} else if ( type == \"widths\" ) {\n\t\t\t\t\t\t\t\t\ttmp.action = \"change\";\n\t\t\t\t\t\t\t\t\ttmp.width = items[ i2 ];\n\t\t\t\t\t\t\t\t\ttmp.label = document.createElement( \"span\" );\n\n\t\t\t\t\t\t\t\t\ttmp.label.style.width = _this.numberToPx( items[ i2 ] );\n\t\t\t\t\t\t\t\t\ttmp.label.style.height = _this.numberToPx( items[ i2 ] );\n\t\t\t\t\t\t\t\t\ttmp[ \"class\" ] = \"export-drawing-width\";\n\t\t\t\t\t\t\t\t} else if ( type == \"opacities\" ) {\n\t\t\t\t\t\t\t\t\ttmp.style = \"opacity: \" + items[ i2 ];\n\t\t\t\t\t\t\t\t\ttmp.action = \"change\";\n\t\t\t\t\t\t\t\t\ttmp.opacity = items[ i2 ];\n\t\t\t\t\t\t\t\t\ttmp.label = ( items[ i2 ] * 100 ) + \"%\";\n\t\t\t\t\t\t\t\t\ttmp[ \"class\" ] = \"export-drawing-opacity\";\n\t\t\t\t\t\t\t\t} else if ( type == \"modes\" ) {\n\t\t\t\t\t\t\t\t\ttmp.label = _this.i18l( \"menu.label.draw.modes.\" + items[ i2 ] );\n\t\t\t\t\t\t\t\t\ttmp.click = ( function( mode ) {\n\t\t\t\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\t\t\t\t_this.drawing.mode = mode;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} )( items[ i2 ] );\n\t\t\t\t\t\t\t\t\ttmp[ \"class\" ] = \"export-drawing-mode\";\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\titem.menu.push( tmp );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// ADD CLICK HANDLER\n\t\t\t\t\t\t} else if ( !item.click && !item.menu && !item.items ) {\n\t\t\t\t\t\t\t// DRAWING METHODS\n\t\t\t\t\t\t\tif ( _this.drawing.handler[ action ] instanceof Function ) {\n\t\t\t\t\t\t\t\titem.action = action;\n\t\t\t\t\t\t\t\titem.click = ( function( item ) {\n\t\t\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\t\t\tthis.drawing.handler[ item.action ]( item );\n\n\t\t\t\t\t\t\t\t\t\tif ( item.action != \"cancel\" ) {\n\t\t\t\t\t\t\t\t\t\t\tthis.createMenu( this.config.fabric.drawing.menu );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )( item );\n\n\t\t\t\t\t\t\t\t// DRAWING\n\t\t\t\t\t\t\t} else if ( _this.drawing.enabled ) {\n\t\t\t\t\t\t\t\titem.click = ( function( item ) {\n\t\t\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\t\t\tif ( this.config.drawing.autoClose ) {\n\t\t\t\t\t\t\t\t\t\t\tthis.drawing.handler.done();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tthis[ \"to\" + item.format ]( item, function( data ) {\n\t\t\t\t\t\t\t\t\t\t\tif ( item.action == \"download\" ) {\n\t\t\t\t\t\t\t\t\t\t\t\tthis.download( data, item.mimeType, [ item.fileName, item.extension ].join( \".\" ) );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )( item );\n\n\t\t\t\t\t\t\t\t// REGULAR\n\t\t\t\t\t\t\t} else if ( item.format != \"UNDEFINED\" ) {\n\t\t\t\t\t\t\t\titem.click = ( function( item ) {\n\t\t\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\t\t\tif ( item.capture || item.action == \"print\" || item.format == \"PRINT\" ) {\n\t\t\t\t\t\t\t\t\t\t\tthis.capture( item, function() {\n\t\t\t\t\t\t\t\t\t\t\t\tthis.drawing.handler.done();\n\t\t\t\t\t\t\t\t\t\t\t\tthis[ \"to\" + item.format ]( item, function( data ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( item.action == \"download\" ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis.download( data, item.mimeType, [ item.fileName, item.extension ].join( \".\" ) );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis.createMenu( this.config.menu );\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t\t} )\n\n\t\t\t\t\t\t\t\t\t\t} else if ( this[ \"to\" + item.format ] ) {\n\t\t\t\t\t\t\t\t\t\t\tthis[ \"to\" + item.format ]( item, function( data ) {\n\t\t\t\t\t\t\t\t\t\t\t\tthis.download( data, item.mimeType, [ item.fileName, item.extension ].join( \".\" ) );\n\t\t\t\t\t\t\t\t\t\t\t\tthis.createMenu( this.config.menu );\n\t\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tthrow new Error( 'Invalid format. Could not determine output type.' );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} )( item );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// HIDE EMPTY ONES\n\t\t\t\t\t\tif ( item.menu !== undefined && !item.menu.length ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// ADD LINK ATTR\n\t\t\t\t\t\ta.setAttribute( \"href\", \"#\" );\n\t\t\t\t\t\ta.addEventListener( \"click\", ( function( callback, item ) {\n\t\t\t\t\t\t\treturn function( e ) {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tvar args = [ e, item ];\n\n\t\t\t\t\t\t\t\t// DELAYED\n\t\t\t\t\t\t\t\tif ( ( item.action == \"draw\" || item.format == \"PRINT\" || ( item.format != \"UNDEFINED\" && item.capture ) ) && !_this.drawing.enabled ) {\n\n\t\t\t\t\t\t\t\t\t// VALIDATE DELAY\n\t\t\t\t\t\t\t\t\tif ( !isNaN( item.delay ) || !isNaN( _this.config.delay ) ) {\n\t\t\t\t\t\t\t\t\t\titem.delay = !isNaN( item.delay ) ? item.delay : _this.config.delay;\n\t\t\t\t\t\t\t\t\t\t_this.delay( item, callback );\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcallback.apply( _this, args );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} )( item.click || function( e ) {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}, item ) );\n\n\t\t\t\t\t\t// ENABLE MANUAL ACTIVE STATE ON TOUCH DEVICES\n\t\t\t\t\t\tif ( _this.setup.hasTouch && li.classList ) {\n\t\t\t\t\t\t\ta.addEventListener( \"click\", ( function( item ) {\n\t\t\t\t\t\t\t\treturn function( e ) {\n\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\tvar li = item.elements.li;\n\t\t\t\t\t\t\t\t\tvar parentIsActive = hasActiveParent( li );\n\t\t\t\t\t\t\t\t\tvar siblingIsActive = hasActiveSibling( li );\n\t\t\t\t\t\t\t\t\tvar childHasSubmenu = hasSubmenu( li );\n\n\t\t\t\t\t\t\t\t\t// CHECK IF PARENT IS ACTIVE\n\t\t\t\t\t\t\t\t\tfunction hasActiveParent( elm ) {\n\t\t\t\t\t\t\t\t\t\tvar parentNode = elm.parentNode.parentNode;\n\t\t\t\t\t\t\t\t\t\tvar classList = parentNode.classList;\n\n\t\t\t\t\t\t\t\t\t\tif ( parentNode.tagName == \"LI\" && classList.contains( \"active\" ) ) {\n\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// CHECK IF ANY SIBLING IS ACTIVE\n\t\t\t\t\t\t\t\t\tfunction hasActiveSibling( elm ) {\n\t\t\t\t\t\t\t\t\t\tvar siblings = elm.parentNode.children;\n\n\t\t\t\t\t\t\t\t\t\tfor ( i1 = 0; i1 < siblings.length; i1++ ) {\n\t\t\t\t\t\t\t\t\t\t\tvar sibling = siblings[ i1 ];\n\t\t\t\t\t\t\t\t\t\t\tvar classList = sibling.classList;\n\t\t\t\t\t\t\t\t\t\t\tif ( sibling !== elm && classList.contains( \"active\" ) ) {\n\t\t\t\t\t\t\t\t\t\t\t\tclassList.remove( \"active\" );\n\t\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// CHECK IF SUBEMNU EXIST\n\t\t\t\t\t\t\t\t\tfunction hasSubmenu( elm ) {\n\t\t\t\t\t\t\t\t\t\treturn elm.getElementsByTagName( \"ul\" ).length > 0;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// CHECK FOR ROOT ITEMS\n\t\t\t\t\t\t\t\t\tfunction isRoot( elm ) {\n\t\t\t\t\t\t\t\t\t\treturn elm.classList.contains( \"export-main\" ) || elm.classList.contains( \"export-drawing\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// TOGGLE MAIN MENU\n\t\t\t\t\t\t\t\t\tif ( isRoot( li ) || !childHasSubmenu ) {\n\t\t\t\t\t\t\t\t\t\t_this.setup.menu.classList.toggle( \"active\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// UNTOGGLE BUFFERED ITEMS\n\t\t\t\t\t\t\t\t\tif ( !parentIsActive || !childHasSubmenu ) {\n\t\t\t\t\t\t\t\t\t\twhile ( buffer.length ) {\n\t\t\t\t\t\t\t\t\t\t\tvar tmp = buffer.pop();\n\t\t\t\t\t\t\t\t\t\t\tvar tmpRoot = isRoot( tmp );\n\t\t\t\t\t\t\t\t\t\t\tvar tmpOdd = tmp !== li;\n\n\t\t\t\t\t\t\t\t\t\t\tif ( tmpRoot ) {\n\t\t\t\t\t\t\t\t\t\t\t\tif ( !childHasSubmenu ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttmp.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else if ( tmpOdd ) {\n\t\t\t\t\t\t\t\t\t\t\t\ttmp.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// BUFFER ITEMS\n\t\t\t\t\t\t\t\t\tbuffer.push( li );\n\n\t\t\t\t\t\t\t\t\t// TOGGLE CLASS\n\t\t\t\t\t\t\t\t\tif ( childHasSubmenu ) {\n\t\t\t\t\t\t\t\t\t\tli.classList.toggle( \"active\" );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} )( item ) );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tli.appendChild( a );\n\n\t\t\t\t\t\t// ADD LABEL\n\t\t\t\t\t\tif ( _this.isElement( item.label ) ) {\n\t\t\t\t\t\t\tspan.appendChild( item.label );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tspan.innerHTML = item.label;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// APPEND ITEMS\n\t\t\t\t\t\tif ( item[ \"class\" ] ) {\n\t\t\t\t\t\t\tli.className = item[ \"class\" ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( item.style ) {\n\t\t\t\t\t\t\tli.setAttribute( \"style\", item.style );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( item.icon ) {\n\t\t\t\t\t\t\timg.setAttribute( \"src\", ( !item.ignore && item.icon.slice( 0, 10 ).indexOf( \"//\" ) == -1 ? chart.pathToImages : \"\" ) + item.icon );\n\t\t\t\t\t\t\ta.appendChild( img );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( item.label ) {\n\t\t\t\t\t\t\ta.appendChild( span );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( item.title ) {\n\t\t\t\t\t\t\ta.setAttribute( \"title\", item.title );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// CALLBACK; REVIVER FOR MENU ITEMS\n\t\t\t\t\t\tif ( _this.config.menuReviver ) {\n\t\t\t\t\t\t\tli = _this.config.menuReviver.apply( _this, [ item, li ] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// ADD ELEMENTS FOR EASY ACCESS\n\t\t\t\t\t\titem.elements = {\n\t\t\t\t\t\t\tli: li,\n\t\t\t\t\t\t\ta: a,\n\t\t\t\t\t\t\timg: img,\n\t\t\t\t\t\t\tspan: span\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// ADD SUBLIST; JUST WITH ENTRIES\n\t\t\t\t\t\tif ( ( item.menu || item.items ) && item.action != \"draw\" ) {\n\t\t\t\t\t\t\tif ( buildList( item.menu || item.items, li ).childNodes.length ) {\n\t\t\t\t\t\t\t\tul.appendChild( li );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tul.appendChild( li );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// JUST ADD THOSE WITH ENTRIES\n\t\t\t\t\tif ( ul.childNodes.length ) {\n\t\t\t\t\t\tcontainer.appendChild( ul );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn ul;\n\t\t\t\t}\n\n\t\t\t\t// DETERMINE CONTAINER\n\t\t\t\tif ( !container ) {\n\t\t\t\t\tif ( typeof _this.config.divId == \"string\" ) {\n\t\t\t\t\t\t_this.config.divId = container = document.getElementById( _this.config.divId );\n\t\t\t\t\t} else if ( _this.isElement( _this.config.divId ) ) {\n\t\t\t\t\t\tcontainer = _this.config.divId;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontainer = _this.setup.chart.containerDiv;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// CREATE / RESET MENU CONTAINER\n\t\t\t\tif ( _this.isElement( _this.setup.menu ) ) {\n\t\t\t\t\t_this.setup.menu.innerHTML = \"\";\n\t\t\t\t} else {\n\t\t\t\t\t_this.setup.menu = document.createElement( \"div\" );\n\t\t\t\t}\n\t\t\t\t_this.setup.menu.setAttribute( \"class\", _this.setup.chart.classNamePrefix + \"-export-menu \" + _this.setup.chart.classNamePrefix + \"-export-menu-\" + _this.config.position + \" amExportButton\" );\n\n\t\t\t\t// CALLBACK; REPLACES THE MENU WALKER\n\t\t\t\tif ( _this.config.menuWalker ) {\n\t\t\t\t\tbuildList = _this.config.menuWalker;\n\t\t\t\t}\n\t\t\t\tbuildList.apply( this, [ list, _this.setup.menu ] );\n\n\t\t\t\t// JUST ADD THOSE WITH ENTRIES\n\t\t\t\tif ( _this.setup.menu.childNodes.length ) {\n\t\t\t\t\tcontainer.appendChild( _this.setup.menu );\n\t\t\t\t}\n\n\t\t\t\treturn _this.setup.menu;\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Method to trigger the callback delayed\n\t\t\t */\n\t\t\tdelay: function( options, callback ) {\n\t\t\t\tvar cfg = _this.deepMerge( {\n\t\t\t\t\tdelay: 3,\n\t\t\t\t\tprecision: 2\n\t\t\t\t}, options || {} );\n\t\t\t\tvar t1, t2, start = Number( new Date() );\n\t\t\t\tvar menu = _this.createMenu( [ {\n\t\t\t\t\tlabel: _this.i18l( \"capturing.delayed.menu.label\" ).replace( \"{{duration}}\", AmCharts.toFixed( cfg.delay, cfg.precision ) ),\n\t\t\t\t\ttitle: _this.i18l( \"capturing.delayed.menu.title\" ),\n\t\t\t\t\t\"class\": \"export-delayed-capturing\",\n\t\t\t\t\tclick: function() {\n\t\t\t\t\t\tclearTimeout( t1 );\n\t\t\t\t\t\tclearTimeout( t2 );\n\t\t\t\t\t\t_this.createMenu( _this.config.menu );\n\t\t\t\t\t}\n\t\t\t\t} ] );\n\t\t\t\tvar label = menu.getElementsByTagName( \"a\" )[ 0 ];\n\n\t\t\t\t// MENU UPDATE\n\t\t\t\tt1 = setInterval( function() {\n\t\t\t\t\tvar diff = cfg.delay - ( Number( new Date() ) - start ) / 1000;\n\t\t\t\t\tif ( diff <= 0 ) {\n\t\t\t\t\t\tclearTimeout( t1 );\n\t\t\t\t\t\tif ( cfg.action != \"draw\" ) {\n\t\t\t\t\t\t\t_this.createMenu( _this.config.menu );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( label ) {\n\t\t\t\t\t\tlabel.innerHTML = _this.i18l( \"capturing.delayed.menu.label\" ).replace( \"{{duration}}\", AmCharts.toFixed( diff, 2 ) );\n\t\t\t\t\t}\n\t\t\t\t}, AmCharts.updateRate );\n\n\t\t\t\t// CALLBACK\n\t\t\t\tt2 = setTimeout( function() {\n\t\t\t\t\tcallback.apply( _this, arguments );\n\t\t\t\t}, cfg.delay * 1000 );\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Migration method to support old export setup\n\t\t\t */\n\t\t\tmigrateSetup: function( setup ) {\n\t\t\t\tvar cfg = {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tmigrated: true,\n\t\t\t\t\tlibs: {\n\t\t\t\t\t\tautoLoad: true\n\t\t\t\t\t},\n\t\t\t\t\tmenu: []\n\t\t\t\t};\n\n\t\t\t\tfunction crawler( object ) {\n\t\t\t\t\tvar key;\n\t\t\t\t\tfor ( key in object ) {\n\t\t\t\t\t\tvar value = object[ key ];\n\n\t\t\t\t\t\tif ( key.slice( 0, 6 ) == \"export\" && value ) {\n\t\t\t\t\t\t\tcfg.menu.push( key.slice( 6 ) );\n\t\t\t\t\t\t} else if ( key == \"userCFG\" ) {\n\t\t\t\t\t\t\tcrawler( value );\n\t\t\t\t\t\t} else if ( key == \"menuItems\" ) {\n\t\t\t\t\t\t\tcfg.menu = value;\n\t\t\t\t\t\t} else if ( key == \"libs\" ) {\n\t\t\t\t\t\t\tcfg.libs = value;\n\t\t\t\t\t\t} else if ( typeof key == \"string\" ) {\n\t\t\t\t\t\t\tcfg[ key ] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcrawler( setup );\n\n\t\t\t\treturn cfg;\n\t\t\t},\n\n\t\t\tclear: function() {\n\t\t\t\t_this.setup = undefined;\n\t\t\t\tif ( _this.docListener ) {\n\t\t\t\t\tdocument.removeEventListener( \"keydown\", _this.docListener );\n\t\t\t\t}\n\t\t\t\tvar listenersToRemove = _this.listenersToRemove;\n\t\t\t\tif ( listenersToRemove ) {\n\t\t\t\t\tfor ( var i = 0; i < listenersToRemove.length; i++ ) {\n\t\t\t\t\t\tvar listenerToRemove = listenersToRemove[ i ];\n\t\t\t\t\t\tlistenerToRemove.node.removeEventListener( listenerToRemove.event, listenerToRemove.method )\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_this.listenersToRemove = [];\n\t\t\t},\n\n\t\t\t/*\n\t\t\t ** Add event listener\n\t\t\t */\n\t\t\tloadListeners: function() {\n\t\t\t\tfunction handleClone( clone ) {\n\t\t\t\t\tif ( clone ) {\n\t\t\t\t\t\tclone.set( {\n\t\t\t\t\t\t\ttop: clone.top + 10,\n\t\t\t\t\t\t\tleft: clone.left + 10\n\t\t\t\t\t\t} );\n\t\t\t\t\t\t_this.setup.fabric.add( clone );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\n\t\t\t\t// OBSERVE; KEY LISTENER; DRAWING FEATURES\n\t\t\t\tif ( _this.config.keyListener && _this.config.keyListener != \"attached\" ) {\n\n\t\t\t\t\t_this.docListener = function( e ) {\n\t\t\t\t\t\tvar current = _this.drawing.buffer.target;\n\t\t\t\t\t\tvar KEY_WHITELIST = [ 37, 38, 39, 40, 13, 9, 27 ];\n\t\t\t\t\t\tvar MENU_LEFT = [ \"top-left\", \"bottom-left\" ].indexOf( _this.config.position ) != -1;\n\t\t\t\t\t\tvar MENU_RIGHT = [ \"top-right\", \"bottom-right\" ].indexOf( _this.config.position ) != -1;\n\n\t\t\t\t\t\t// FOCUS FIRST ITEM IN MENU\n\t\t\t\t\t\tfunction focusFirst( list, throughTab ) {\n\t\t\t\t\t\t\tfor ( i1 = 0; i1 < list.length; i1++ ) {\n\t\t\t\t\t\t\t\tvar item = list[ i1 ];\n\t\t\t\t\t\t\t\titem.parentNode.classList.remove( \"active\" );\n\n\t\t\t\t\t\t\t\t// DO NOT THAT THROUGH TAB COMMANDS\n\t\t\t\t\t\t\t\tif ( i1 == 0 && !throughTab ) {\n\t\t\t\t\t\t\t\t\titem.focus();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// FOCUS NEXT MENU\n\t\t\t\t\t\tfunction focusNext( throughTab ) {\n\t\t\t\t\t\t\tif ( _this.setup.focusedMenuItem && _this.setup.focusedMenuItem.nextSibling ) {\n\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.add( \"active\" );\n\t\t\t\t\t\t\t\tfocusFirst( _this.setup.focusedMenuItem.nextSibling.getElementsByTagName( \"a\" ), throughTab );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// FOCUS PREVIOUS MENU\n\t\t\t\t\t\tfunction focusPrev( throughTab ) {\n\t\t\t\t\t\t\tif ( _this.setup.focusedMenuItem && _this.setup.focusedMenuItem.parentNode.parentNode.parentNode ) {\n\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.add( \"active\" );\n\t\t\t\t\t\t\t\tfocusFirst( _this.setup.focusedMenuItem.parentNode.parentNode.parentNode.getElementsByTagName( \"a\" ), throughTab );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// FOCUS NEXT ITEM\n\t\t\t\t\t\tfunction focusDown( throughTab ) {\n\t\t\t\t\t\t\tif ( _this.setup.focusedMenuItem && _this.setup.focusedMenuItem.parentNode.nextSibling ) {\n\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\tfocusFirst( _this.setup.focusedMenuItem.parentNode.nextSibling.getElementsByTagName( \"a\" ), throughTab );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// FOCUS PREVIOUS ITEM\n\t\t\t\t\t\tfunction focusUp( throughTab ) {\n\t\t\t\t\t\t\tif ( _this.setup.focusedMenuItem && _this.setup.focusedMenuItem.parentNode.previousSibling ) {\n\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\tfocusFirst( _this.setup.focusedMenuItem.parentNode.previousSibling.getElementsByTagName( \"a\" ), throughTab );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// BLUR EVERYTHING\n\t\t\t\t\t\tfunction blurAll() {\n\t\t\t\t\t\t\tfunction unselectParents( elm ) {\n\t\t\t\t\t\t\t\tif ( _this.isElement(elm) ) {\n\t\t\t\t\t\t\t\t\telm.blur();\n\n\t\t\t\t\t\t\t\t\t// BLUR PARENT\n\t\t\t\t\t\t\t\t\tif ( elm.parentNode ) {\n\t\t\t\t\t\t\t\t\t\telm.parentNode.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// ENOUGH; EXIT ON MENU WRAPPER\n\t\t\t\t\t\t\t\t\tif ( !elm.classList.contains( \"amExportButton\" ) ) {\n\t\t\t\t\t\t\t\t\t\tunselectParents( elm.parentNode );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// TRIGGER PRIV. FUNC. ONLY ON FOCUSED ELEMENT\n\t\t\t\t\t\t\tif ( _this.setup.focusedMenuItem ) {\n\t\t\t\t\t\t\t\tunselectParents( _this.setup.focusedMenuItem );\n\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem = undefined;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// IF WE'VE A FOCUSED ELEMENT\n\t\t\t\t\t\tif ( _this.setup.focusedMenuItem && KEY_WHITELIST.indexOf( e.keyCode ) != -1 ) {\n\n\t\t\t\t\t\t\t// TAB (focusedMenuItem holds the previous selected element)\n\t\t\t\t\t\t\tif ( e.keyCode == 9 ) {\n\n\t\t\t\t\t\t\t\t// NEXT ITEM AVAILABLE?\n\t\t\t\t\t\t\t\tif ( !_this.setup.focusedMenuItem.nextSibling ) {\n\t\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.remove( \"active\" );\n\n\t\t\t\t\t\t\t\t\t// NEXT PARENT ITEM AVAILABLE?\n\t\t\t\t\t\t\t\t\tif ( !_this.setup.focusedMenuItem.parentNode.nextSibling ) {\n\t\t\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.parentNode.parentNode.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// SHIFT\n\t\t\t\t\t\t\t\t} else if ( e.shiftKey ) {\n\t\t\t\t\t\t\t\t\t_this.setup.focusedMenuItem.parentNode.classList.remove( \"active\" );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// ENTER\n\t\t\t\t\t\t\tif ( e.keyCode == 13 && _this.setup.focusedMenuItem.nextSibling ) {\n\t\t\t\t\t\t\t\tfocusNext();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// LEFT\n\t\t\t\t\t\t\tif ( e.keyCode == 37 ) {\n\t\t\t\t\t\t\t\tif ( MENU_RIGHT ) {\n\t\t\t\t\t\t\t\t\tfocusNext();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfocusPrev();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// RIGHT\n\t\t\t\t\t\t\tif ( e.keyCode == 39 ) {\n\t\t\t\t\t\t\t\tif ( MENU_RIGHT ) {\n\t\t\t\t\t\t\t\t\tfocusPrev();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfocusNext();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// DOWN\n\t\t\t\t\t\t\tif ( e.keyCode == 40 ) {\n\t\t\t\t\t\t\t\tfocusDown();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// UP\n\t\t\t\t\t\t\tif ( e.keyCode == 38 ) {\n\t\t\t\t\t\t\t\tfocusUp();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// ESC\n\t\t\t\t\t\t\tif ( e.keyCode == 27 ) {\n\t\t\t\t\t\t\t\tblurAll();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// REMOVE; key: BACKSPACE / DELETE\n\t\t\t\t\t\tif ( ( e.keyCode == 8 || e.keyCode == 46 ) && current ) {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t_this.setup.fabric.remove( current );\n\n\t\t\t\t\t\t\t// ESCAPE DRAWIN MODE; key: escape\n\t\t\t\t\t\t} else if ( e.keyCode == 27 && _this.drawing.enabled ) {\n\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t// DESELECT ACTIVE OBJECTS\n\t\t\t\t\t\t\tif ( _this.drawing.buffer.isSelected ) {\n\t\t\t\t\t\t\t\t_this.setup.fabric.discardActiveObject();\n\n\t\t\t\t\t\t\t\t// QUIT DRAWING MODE\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t_this.drawing.handler.done();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// COPY; key: C\n\t\t\t\t\t\t} else if ( e.keyCode == 67 && ( e.metaKey || e.ctrlKey ) && current ) {\n\t\t\t\t\t\t\t_this.drawing.buffer.copy = current;\n\n\t\t\t\t\t\t\t// CUT; key: X\n\t\t\t\t\t\t} else if ( e.keyCode == 88 && ( e.metaKey || e.ctrlKey ) && current ) {\n\t\t\t\t\t\t\t_this.drawing.buffer.copy = current;\n\t\t\t\t\t\t\t_this.setup.fabric.remove( current );\n\n\t\t\t\t\t\t\t// PASTE; key: V\n\t\t\t\t\t\t} else if ( e.keyCode == 86 && ( e.metaKey || e.ctrlKey ) ) {\n\t\t\t\t\t\t\tif ( _this.drawing.buffer.copy ) {\n\t\t\t\t\t\t\t\thandleClone( _this.drawing.buffer.copy.clone( handleClone ) )\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// UNDO / REDO; key: Z\n\t\t\t\t\t\t} else if ( e.keyCode == 90 && ( e.metaKey || e.ctrlKey ) ) {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tif ( e.shiftKey ) {\n\t\t\t\t\t\t\t\t_this.drawing.handler.redo();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t_this.drawing.handler.undo();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t_this.config.keyListener = \"attached\";\n\n\t\t\t\t\tdocument.addEventListener( \"keydown\", _this.docListener );\n\t\t\t\t}\n\n\t\t\t\t// OBSERVE; DRAG AND DROP LISTENER; DRAWING FEATURE\n\t\t\t\tif ( _this.config.fileListener ) {\n\t\t\t\t\t_this.setup.chart.containerDiv.addEventListener( \"dragover\", _this.handleDropbox );\n\t\t\t\t\t_this.setup.chart.containerDiv.addEventListener( \"dragleave\", _this.handleDropbox );\n\t\t\t\t\t_this.setup.chart.containerDiv.addEventListener( \"drop\", _this.handleDropbox );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Initiate export menu; waits for chart container to place menu\n\t\t\t */\n\t\t\tinit: function() {\n\t\t\t\tclearTimeout( _timer );\n\n\t\t\t\t_timer = setInterval( function() {\n\t\t\t\t\tif ( _this.setup && _this.setup.chart.containerDiv ) {\n\t\t\t\t\t\tclearTimeout( _timer );\n\n\t\t\t\t\t\tif ( _this.config.enabled ) {\n\t\t\t\t\t\t\t// CREATE REFERENCE\n\t\t\t\t\t\t\t_this.setup.chart.AmExport = _this;\n\n\t\t\t\t\t\t\t// OVERWRITE PARENT OVERFLOW\n\t\t\t\t\t\t\tif ( _this.config.overflow ) {\n\t\t\t\t\t\t\t\t_this.setup.chart.div.style.overflow = \"visible\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// ATTACH EVENTS\n\t\t\t\t\t\t\t_this.loadListeners();\n\n\t\t\t\t\t\t\t// CREATE MENU\n\t\t\t\t\t\t\t_this.createMenu( _this.config.menu );\n\n\t\t\t\t\t\t\t_this.handleReady( _this.config.onReady );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, AmCharts.updateRate );\n\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Initiates export instance; merges given config; attaches event listener\n\t\t\t */\n\t\t\tconstruct: function() {\n\t\t\t\t// ANNOTATION; MAP \"DONE\"\n\t\t\t\t_this.drawing.handler.cancel = _this.drawing.handler.done;\n\n\t\t\t\t// CHECK BLOB CONSTRUCTOR\n\t\t\t\ttry {\n\t\t\t\t\t_this.setup.hasBlob = !!new Blob;\n\t\t\t\t} catch ( e ) {}\n\n\t\t\t\t// WORK AROUND TO BYPASS FILESAVER CHECK TRYING TO OPEN THE BLOB URL IN SAFARI BROWSER\n\t\t\t\twindow.safari = window.safari ? window.safari : {};\n\n\t\t\t\t// OVERTAKE CHART FONTSIZE IF GIVEN\n\t\t\t\t_this.defaults.fabric.drawing.fontSize = _this.setup.chart.fontSize || 11;\n\n\t\t\t\t// MERGE SETTINGS\n\t\t\t\t_this.config.drawing = _this.deepMerge( _this.defaults.fabric.drawing, _this.config.drawing || {}, true );\n\t\t\t\tif ( _this.config.border ) {\n\t\t\t\t\t_this.config.border = _this.deepMerge( _this.defaults.fabric.border, _this.config.border || {}, true );\n\t\t\t\t}\n\t\t\t\t_this.deepMerge( _this.defaults.fabric, _this.config, true );\n\t\t\t\t_this.deepMerge( _this.defaults.fabric, _this.config.fabric || {}, true );\n\t\t\t\t_this.deepMerge( _this.defaults.pdfMake, _this.config, true );\n\t\t\t\t_this.deepMerge( _this.defaults.pdfMake, _this.config.pdfMake || {}, true );\n\t\t\t\t_this.deepMerge( _this.libs, _this.config.libs || {}, true );\n\n\t\t\t\t// UPDATE CONFIG\n\t\t\t\t_this.config.drawing = _this.defaults.fabric.drawing;\n\t\t\t\t_this.config.fabric = _this.defaults.fabric;\n\t\t\t\t_this.config.pdfMake = _this.defaults.pdfMake;\n\t\t\t\t_this.config = _this.deepMerge( _this.defaults, _this.config, true );\n\n\t\t\t\t// MERGE; SETUP DRAWING MENU\n\t\t\t\tif ( _this.config.fabric.drawing.enabled ) {\n\t\t\t\t\tif ( _this.config.fabric.drawing.menu === undefined ) {\n\t\t\t\t\t\t_this.config.fabric.drawing.menu = [];\n\t\t\t\t\t\t_this.deepMerge( _this.config.fabric.drawing.menu, [ {\n\t\t\t\t\t\t\t\"class\": \"export-drawing\",\n\t\t\t\t\t\t\tmenu: [ {\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.add\" ),\n\t\t\t\t\t\t\t\tmenu: [ {\n\t\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.shapes\" ),\n\t\t\t\t\t\t\t\t\taction: \"draw.shapes\"\n\t\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.text\" ),\n\t\t\t\t\t\t\t\t\taction: \"text\"\n\t\t\t\t\t\t\t\t} ]\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.change\" ),\n\t\t\t\t\t\t\t\tmenu: [ {\n\t\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.modes\" ),\n\t\t\t\t\t\t\t\t\taction: \"draw.modes\"\n\t\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.colors\" ),\n\t\t\t\t\t\t\t\t\taction: \"draw.colors\"\n\t\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.widths\" ),\n\t\t\t\t\t\t\t\t\taction: \"draw.widths\"\n\t\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw.opacities\" ),\n\t\t\t\t\t\t\t\t\taction: \"draw.opacities\"\n\t\t\t\t\t\t\t\t}, \"UNDO\", \"REDO\" ]\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.save.image\" ),\n\t\t\t\t\t\t\t\tmenu: [ \"PNG\", \"JPG\", \"SVG\", \"PDF\" ]\n\t\t\t\t\t\t\t}, \"PRINT\", \"CANCEL\" ]\n\t\t\t\t\t\t} ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// MERGE; SETUP MAIN MENU\n\t\t\t\tif ( _this.config.menu === undefined ) {\n\t\t\t\t\t_this.config.menu = [];\n\t\t\t\t\t// PARENT MENU\n\t\t\t\t\t_this.deepMerge( _this.config, {\n\t\t\t\t\t\tmenu: [ {\n\t\t\t\t\t\t\t\"class\": \"export-main\",\n\t\t\t\t\t\t\tmenu: [ {\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.save.image\" ),\n\t\t\t\t\t\t\t\tmenu: [ \"PNG\", \"JPG\", \"SVG\", \"PDF\" ]\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.save.data\" ),\n\t\t\t\t\t\t\t\tmenu: [ \"CSV\", \"XLSX\", \"JSON\" ]\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.draw\" ),\n\t\t\t\t\t\t\t\taction: \"draw\",\n\t\t\t\t\t\t\t\tmenu: _this.config.fabric.drawing.menu\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tformat: \"PRINT\",\n\t\t\t\t\t\t\t\tlabel: _this.i18l( \"menu.label.print\" )\n\t\t\t\t\t\t\t} ]\n\t\t\t\t\t\t} ]\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\t// ADD MISSING PATH\n\t\t\t\tif ( !_this.libs.path ) {\n\t\t\t\t\t_this.libs.path = _this.config.path + \"libs/\";\n\t\t\t\t}\n\n\t\t\t\t// CHECK ACCEPTANCE\n\t\t\t\tif ( _this.isSupported() ) {\n\t\t\t\t\t// LOAD DEPENDENCIES\n\t\t\t\t\t_this.loadDependencies( _this.libs.resources, _this.libs.reload );\n\t\t\t\t\t// ADD CLASSNAMES\n\t\t\t\t\t_this.setup.chart.addClassNames = true;\n\t\t\t\t\t// REFERENCE\n\t\t\t\t\t_this.setup.chart[ _this.name ] = _this;\n\t\t\t\t\t// INIT MENU; WAIT FOR CHART INSTANCE\n\t\t\t\t\t_this.init();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// USE GIVEN CONFIG\n\t\tif ( config ) {\n\t\t\t_this.config = config;\n\n\t\t\t// USE CHART EXPORT CONFIG\n\t\t} else if ( _this.setup.chart[ _this.name ] ) {\n\t\t\t_this.config = _this.setup.chart[ _this.name ];\n\n\t\t\t// MIGRATE OLD EXPORT CHART CONFIG\n\t\t} else if ( _this.setup.chart.amExport || _this.setup.chart.exportConfig ) {\n\t\t\t_this.config = _this.migrateSetup( _this.setup.chart.amExport || _this.setup.chart.exportConfig );\n\n\t\t\t// EXIT; NO CONFIG\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\t// CONSTRUCT INSTANCE\n\t\t_this.construct();\n\n\t\t// EXPORT SCOPE\n\t\treturn _this.deepMerge( this, _this );\n\t}\n} )();\n\n/**\n * Set init handler\n */\nAmCharts.addInitHandler( function( chart ) {\n\tnew AmCharts[ \"export\" ]( chart );\n}, [ \"pie\", \"serial\", \"xy\", \"funnel\", \"radar\", \"gauge\", \"stock\", \"map\", \"gantt\" ] );"],"x_google_ignoreList":[]}