diff --git a/dist/plotly-cartesian.min.js b/dist/plotly-cartesian.min.js deleted file mode 100644 index eff4475b12c..00000000000 --- a/dist/plotly-cartesian.min.js +++ /dev/null @@ -1,28 +0,0 @@ -/** -* plotly.js (cartesian - minified) v1.20.2-d26 -* Copyright 2012-2016, Plotly, Inc. -* All rights reserved. -* Licensed under the MIT license -*/ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Plotly=t()}}(function(){var t;return function t(e,r,n){function a(i,l){if(!r[i]){if(!e[i]){var s="function"==typeof require&&require;if(!l&&s)return s(i,!0);if(o)return o(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var u=r[i]={exports:{}};e[i][0].call(u.exports,function(t){var r=e[i][1][t];return a(r?r:t)},u,u.exports,t,e,r,n)}return r[i].exports}for(var o="function"==typeof require&&require,i=0;ie?1:t>=e?0:NaN}function o(t){return null===t?NaN:+t}function i(t){return!isNaN(t)}function l(t){return{left:function(e,r,n,a){for(arguments.length<3&&(n=0),arguments.length<4&&(a=e.length);n>>1;t(e[o],r)<0?n=o+1:a=o}return n},right:function(e,r,n,a){for(arguments.length<3&&(n=0),arguments.length<4&&(a=e.length);n>>1;t(e[o],r)>0?a=o:n=o+1}return n}}}function s(t){return t.length}function c(t){for(var e=1;t*e%1;)e*=10;return e}function u(t,e){for(var r in e)Object.defineProperty(t.prototype,r,{value:e[r],enumerable:!1})}function f(){this._=Object.create(null)}function d(t){return(t+="")===_i||t[0]===wi?wi+t:t}function h(t){return(t+="")[0]===wi?t.slice(1):t}function p(t){return d(t)in this._}function g(t){return(t=d(t))in this._&&delete this._[t]}function m(){var t=[];for(var e in this._)t.push(h(e));return t}function v(){var t=0;for(var e in this._)++t;return t}function y(){for(var t in this._)return!1;return!0}function x(){this._=Object.create(null)}function b(t){return t}function _(t,e,r){return function(){var n=r.apply(e,arguments);return n===e?t:n}}function w(t,e){if(e in t)return e;e=e.charAt(0).toUpperCase()+e.slice(1);for(var r=0,n=ki.length;r=e&&(e=a+1);!(i=l[e])&&++e0&&(t=t.slice(0,l));var c=Pi.get(t);return c&&(t=c,s=Q),l?e?a:n:e?k:o}function W(t,e){return function(r){var n=ui.event;ui.event=r,e[0]=this.__data__;try{t.apply(this,e)}finally{ui.event=n}}}function Q(t,e){var r=W(t,e);return function(t){var e=this,n=t.relatedTarget;n&&(n===e||8&n.compareDocumentPosition(e))||r.call(e,t)}}function $(t){var r=".dragsuppress-"+ ++Ei,a="click"+r,o=ui.select(n(t)).on("touchmove"+r,T).on("dragstart"+r,T).on("selectstart"+r,T);if(null==Ni&&(Ni=!("onselectstart"in t)&&w(t.style,"userSelect")),Ni){var i=e(t).style,l=i[Ni];i[Ni]="none"}return function(t){if(o.on(r,null),Ni&&(i[Ni]=l),t){var e=function(){o.on(a,null)};o.on(a,function(){T(),e()},!0),setTimeout(e,0)}}}function J(t,e){e.changedTouches&&(e=e.changedTouches[0]);var r=t.ownerSVGElement||t;if(r.createSVGPoint){var a=r.createSVGPoint();if(Ii<0){var o=n(t);if(o.scrollX||o.scrollY){r=ui.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var i=r[0][0].getScreenCTM();Ii=!(i.f||i.e),r.remove()}}return Ii?(a.x=e.pageX,a.y=e.pageY):(a.x=e.clientX,a.y=e.clientY),a=a.matrixTransform(t.getScreenCTM().inverse()),[a.x,a.y]}var l=t.getBoundingClientRect();return[e.clientX-l.left-t.clientLeft,e.clientY-l.top-t.clientTop]}function K(){return ui.event.changedTouches[0].identifier}function tt(t){return t>0?1:t<0?-1:0}function et(t,e,r){return(e[0]-t[0])*(r[1]-t[1])-(e[1]-t[1])*(r[0]-t[0])}function rt(t){return t>1?0:t<-1?ji:Math.acos(t)}function nt(t){return t>1?Hi:t<-1?-Hi:Math.asin(t)}function at(t){return((t=Math.exp(t))-1/t)/2}function ot(t){return((t=Math.exp(t))+1/t)/2}function it(t){return((t=Math.exp(2*t))-1)/(t+1)}function lt(t){return(t=Math.sin(t/2))*t}function st(){}function ct(t,e,r){return this instanceof ct?(this.h=+t,this.s=+e,void(this.l=+r)):arguments.length<2?t instanceof ct?new ct(t.h,t.s,t.l):kt(""+t,Mt,ct):new ct(t,e,r)}function ut(t,e,r){function n(t){return t>360?t-=360:t<0&&(t+=360),t<60?o+(i-o)*t/60:t<180?i:t<240?o+(i-o)*(240-t)/60:o}function a(t){return Math.round(255*n(t))}var o,i;return t=isNaN(t)?0:(t%=360)<0?t+360:t,e=isNaN(e)?0:e<0?0:e>1?1:e,r=r<0?0:r>1?1:r,i=r<=.5?r*(1+e):r+e-r*e,o=2*r-i,new xt(a(t+120),a(t),a(t-120))}function ft(t,e,r){return this instanceof ft?(this.h=+t,this.c=+e,void(this.l=+r)):arguments.length<2?t instanceof ft?new ft(t.h,t.c,t.l):t instanceof ht?gt(t.l,t.a,t.b):gt((t=At((t=ui.rgb(t)).r,t.g,t.b)).l,t.a,t.b):new ft(t,e,r)}function dt(t,e,r){return isNaN(t)&&(t=0),isNaN(e)&&(e=0),new ht(r,Math.cos(t*=Vi)*e,Math.sin(t)*e)}function ht(t,e,r){return this instanceof ht?(this.l=+t,this.a=+e,void(this.b=+r)):arguments.length<2?t instanceof ht?new ht(t.l,t.a,t.b):t instanceof ft?dt(t.h,t.c,t.l):At((t=xt(t)).r,t.g,t.b):new ht(t,e,r)}function pt(t,e,r){var n=(t+16)/116,a=n+e/500,o=n-r/200;return a=mt(a)*tl,n=mt(n)*el,o=mt(o)*rl,new xt(yt(3.2404542*a-1.5371385*n-.4985314*o),yt(-.969266*a+1.8760108*n+.041556*o),yt(.0556434*a-.2040259*n+1.0572252*o))}function gt(t,e,r){return t>0?new ft(Math.atan2(r,e)*Zi,Math.sqrt(e*e+r*r),t):new ft(NaN,NaN,t)}function mt(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function vt(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function yt(t){return Math.round(255*(t<=.00304?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function xt(t,e,r){return this instanceof xt?(this.r=~~t,this.g=~~e,void(this.b=~~r)):arguments.length<2?t instanceof xt?new xt(t.r,t.g,t.b):kt(""+t,xt,ut):new xt(t,e,r)}function bt(t){return new xt(t>>16,t>>8&255,255&t)}function _t(t){return bt(t)+""}function wt(t){return t<16?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function kt(t,e,r){var n,a,o,i=0,l=0,s=0;if(n=/([a-z]+)\((.*)\)/.exec(t=t.toLowerCase()))switch(a=n[2].split(","),n[1]){case"hsl":return r(parseFloat(a[0]),parseFloat(a[1])/100,parseFloat(a[2])/100);case"rgb":return e(Lt(a[0]),Lt(a[1]),Lt(a[2]))}return(o=ol.get(t))?e(o.r,o.g,o.b):(null==t||"#"!==t.charAt(0)||isNaN(o=parseInt(t.slice(1),16))||(4===t.length?(i=(3840&o)>>4,i|=i>>4,l=240&o,l|=l>>4,s=15&o,s|=s<<4):7===t.length&&(i=(16711680&o)>>16,l=(65280&o)>>8,s=255&o)),e(i,l,s))}function Mt(t,e,r){var n,a,o=Math.min(t/=255,e/=255,r/=255),i=Math.max(t,e,r),l=i-o,s=(i+o)/2;return l?(a=s<.5?l/(i+o):l/(2-i-o),n=t==i?(e-r)/l+(e0&&s<1?0:n),new ct(n,a,s)}function At(t,e,r){t=Tt(t),e=Tt(e),r=Tt(r);var n=vt((.4124564*t+.3575761*e+.1804375*r)/tl),a=vt((.2126729*t+.7151522*e+.072175*r)/el),o=vt((.0193339*t+.119192*e+.9503041*r)/rl);return ht(116*a-16,500*(n-a),200*(a-o))}function Tt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Lt(t){var e=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*e):e}function zt(t){return"function"==typeof t?t:function(){return t}}function Ct(t){return function(e,r,n){return 2===arguments.length&&"function"==typeof r&&(n=r,r=null),St(e,r,t,n)}}function St(t,e,r,n){function a(){var t,e=s.status;if(!e&&Dt(s)||e>=200&&e<300||304===e){try{t=r.call(o,s)}catch(t){return void i.error.call(o,t)}i.load.call(o,t)}else i.error.call(o,s)}var o={},i=ui.dispatch("beforesend","progress","load","error"),l={},s=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=a:s.onreadystatechange=function(){s.readyState>3&&a()},s.onprogress=function(t){var e=ui.event;ui.event=t;try{i.progress.call(o,s)}finally{ui.event=e}},o.header=function(t,e){return t=(t+"").toLowerCase(),arguments.length<2?l[t]:(null==e?delete l[t]:l[t]=e+"",o)},o.mimeType=function(t){return arguments.length?(e=null==t?null:t+"",o):e},o.responseType=function(t){return arguments.length?(c=t,o):c},o.response=function(t){return r=t,o},["get","post"].forEach(function(t){o[t]=function(){return o.send.apply(o,[t].concat(di(arguments)))}}),o.send=function(r,n,a){if(2===arguments.length&&"function"==typeof n&&(a=n,n=null),s.open(r,t,!0),null==e||"accept"in l||(l.accept=e+",*/*"),s.setRequestHeader)for(var u in l)s.setRequestHeader(u,l[u]);return null!=e&&s.overrideMimeType&&s.overrideMimeType(e),null!=c&&(s.responseType=c),null!=a&&o.on("error",a).on("load",function(t){a(null,t)}),i.beforesend.call(o,s),s.send(null==n?null:n),o},o.abort=function(){return s.abort(),o},ui.rebind(o,i,"on"),null==n?o:o.get(Ot(n))}function Ot(t){return 1===t.length?function(e,r){t(null==e?r:null)}:t}function Dt(t){var e=t.responseType;return e&&"text"!==e?t.response:t.responseText}function Pt(t,e,r){var n=arguments.length;n<2&&(e=0),n<3&&(r=Date.now());var a=r+e,o={c:t,t:a,n:null};return ll?ll.n=o:il=o,ll=o,sl||(cl=clearTimeout(cl),sl=1,ul(Nt)),o}function Nt(){var t=Et(),e=It()-t;e>24?(isFinite(e)&&(clearTimeout(cl),cl=setTimeout(Nt,e)),sl=0):(sl=1,ul(Nt))}function Et(){for(var t=Date.now(),e=il;e;)t>=e.t&&e.c(t-e.t)&&(e.c=null),e=e.n;return t}function It(){for(var t,e=il,r=1/0;e;)e.c?(e.t8?function(t){return t/r}:function(t){return t*r},symbol:t}}function jt(t){var e=t.decimal,r=t.thousands,n=t.grouping,a=t.currency,o=n&&r?function(t,e){for(var a=t.length,o=[],i=0,l=n[0],s=0;a>0&&l>0&&(s+l+1>e&&(l=Math.max(1,e-s)),o.push(t.substring(a-=l,a+l)),!((s+=l+1)>e));)l=n[i=(i+1)%n.length];return o.reverse().join(r)}:b;return function(t){var r=dl.exec(t),n=r[1]||" ",i=r[2]||">",l=r[3]||"-",s=r[4]||"",c=r[5],u=+r[6],f=r[7],d=r[8],h=r[9],p=1,g="",m="",v=!1,y=!0;switch(d&&(d=+d.substring(1)),(c||"0"===n&&"="===i)&&(c=n="0",i="="),h){case"n":f=!0,h="g";break;case"%":p=100,m="%",h="f";break;case"p":p=100,m="%",h="r";break;case"b":case"o":case"x":case"X":"#"===s&&(g="0"+h.toLowerCase());case"c":y=!1;case"d":v=!0,d=0;break;case"s":p=-1,h="r"}"$"===s&&(g=a[0],m=a[1]),"r"!=h||d||(h="g"),null!=d&&("g"==h?d=Math.max(1,Math.min(21,d)):"e"!=h&&"f"!=h||(d=Math.max(0,Math.min(20,d)))),h=hl.get(h)||qt;var x=c&&f;return function(t){var r=m;if(v&&t%1)return"";var a=t<0||0===t&&1/t<0?(t=-t,"-"):"-"===l?"":l;if(p<0){var s=ui.formatPrefix(t,d);t=s.scale(t),r=s.symbol+m}else t*=p;t=h(t,d);var b,_,w=t.lastIndexOf(".");if(w<0){var k=y?t.lastIndexOf("e"):-1;k<0?(b=t,_=""):(b=t.substring(0,k),_=t.substring(k))}else b=t.substring(0,w),_=e+t.substring(w+1);!c&&f&&(b=o(b,1/0));var M=g.length+b.length+_.length+(x?0:a.length),A=M"===i?A+a+t:"^"===i?A.substring(0,M>>=1)+a+t+A.substring(M):a+(x?t:A+t))+r}}}function qt(t){return t+""}function Bt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ht(t,e,r){function n(e){var r=t(e),n=o(r,1);return e-r1)for(;i=c)return-1;if(a=e.charCodeAt(l++),37===a){if(i=e.charAt(l++),o=C[i in vl?e.charAt(l++):i],!o||(n=o(t,r,n))<0)return-1}else if(a!=r.charCodeAt(n++))return-1}return n}function n(t,e,r){w.lastIndex=0;var n=w.exec(e.slice(r));return n?(t.w=k.get(n[0].toLowerCase()),r+n[0].length):-1}function a(t,e,r){b.lastIndex=0;var n=b.exec(e.slice(r));return n?(t.w=_.get(n[0].toLowerCase()),r+n[0].length):-1}function o(t,e,r){T.lastIndex=0;var n=T.exec(e.slice(r));return n?(t.m=L.get(n[0].toLowerCase()),r+n[0].length):-1}function i(t,e,r){M.lastIndex=0;var n=M.exec(e.slice(r));return n?(t.m=A.get(n[0].toLowerCase()),r+n[0].length):-1}function l(t,e,n){return r(t,z.c.toString(),e,n)}function s(t,e,n){return r(t,z.x.toString(),e,n)}function c(t,e,n){return r(t,z.X.toString(),e,n)}function u(t,e,r){var n=x.get(e.slice(r,r+=2).toLowerCase());return null==n?-1:(t.p=n,r)}var f=t.dateTime,d=t.date,h=t.time,p=t.periods,g=t.days,m=t.shortDays,v=t.months,y=t.shortMonths;e.utc=function(t){function r(t){try{gl=Bt;var e=new gl;return e._=t,n(e)}finally{gl=Date}}var n=e(t);return r.parse=function(t){try{gl=Bt;var e=n.parse(t);return e&&e._}finally{gl=Date}},r.toString=n.toString,r},e.multi=e.utc.multi=ue;var x=ui.map(),b=Ut(g),_=Yt(g),w=Ut(m),k=Yt(m),M=Ut(v),A=Yt(v),T=Ut(y),L=Yt(y);p.forEach(function(t,e){x.set(t.toLowerCase(),e)});var z={a:function(t){return m[t.getDay()]},A:function(t){return g[t.getDay()]},b:function(t){return y[t.getMonth()]},B:function(t){return v[t.getMonth()]},c:e(f),d:function(t,e){return Xt(t.getDate(),e,2)},e:function(t,e){return Xt(t.getDate(),e,2)},H:function(t,e){return Xt(t.getHours(),e,2)},I:function(t,e){return Xt(t.getHours()%12||12,e,2)},j:function(t,e){return Xt(1+pl.dayOfYear(t),e,3)},L:function(t,e){return Xt(t.getMilliseconds(),e,3)},m:function(t,e){return Xt(t.getMonth()+1,e,2)},M:function(t,e){return Xt(t.getMinutes(),e,2)},p:function(t){return p[+(t.getHours()>=12)]},S:function(t,e){return Xt(t.getSeconds(),e,2)},U:function(t,e){return Xt(pl.sundayOfYear(t),e,2)},w:function(t){return t.getDay()},W:function(t,e){return Xt(pl.mondayOfYear(t),e,2)},x:e(d),X:e(h),y:function(t,e){return Xt(t.getFullYear()%100,e,2)},Y:function(t,e){return Xt(t.getFullYear()%1e4,e,4)},Z:se,"%":function(){return"%"}},C={a:n,A:a,b:o,B:i,c:l,d:re,e:re,H:ae,I:ae,j:ne,L:le,m:ee,M:oe,p:u,S:ie,U:Wt,w:Gt,W:Qt,x:s,X:c,y:Jt,Y:$t,Z:Kt,"%":ce};return e}function Xt(t,e,r){var n=t<0?"-":"",a=(n?-t:t)+"",o=a.length;return n+(o68?1900:2e3)}function ee(t,e,r){yl.lastIndex=0;var n=yl.exec(e.slice(r,r+2));return n?(t.m=n[0]-1,r+n[0].length):-1}function re(t,e,r){yl.lastIndex=0;var n=yl.exec(e.slice(r,r+2));return n?(t.d=+n[0],r+n[0].length):-1}function ne(t,e,r){ -yl.lastIndex=0;var n=yl.exec(e.slice(r,r+3));return n?(t.j=+n[0],r+n[0].length):-1}function ae(t,e,r){yl.lastIndex=0;var n=yl.exec(e.slice(r,r+2));return n?(t.H=+n[0],r+n[0].length):-1}function oe(t,e,r){yl.lastIndex=0;var n=yl.exec(e.slice(r,r+2));return n?(t.M=+n[0],r+n[0].length):-1}function ie(t,e,r){yl.lastIndex=0;var n=yl.exec(e.slice(r,r+2));return n?(t.S=+n[0],r+n[0].length):-1}function le(t,e,r){yl.lastIndex=0;var n=yl.exec(e.slice(r,r+3));return n?(t.L=+n[0],r+n[0].length):-1}function se(t){var e=t.getTimezoneOffset(),r=e>0?"-":"+",n=bi(e)/60|0,a=bi(e)%60;return r+Xt(n,"0",2)+Xt(a,"0",2)}function ce(t,e,r){xl.lastIndex=0;var n=xl.exec(e.slice(r,r+1));return n?r+n[0].length:-1}function ue(t){for(var e=t.length,r=-1;++r=0?1:-1,l=i*r,s=Math.cos(e),c=Math.sin(e),u=o*c,f=a*s+u*Math.cos(l),d=u*i*Math.sin(l);Al.add(Math.atan2(d,f)),n=t,a=s,o=c}var e,r,n,a,o;Tl.point=function(i,l){Tl.point=t,n=(e=i)*Vi,a=Math.cos(l=(r=l)*Vi/2+ji/4),o=Math.sin(l)},Tl.lineEnd=function(){t(e,r)}}function ve(t){var e=t[0],r=t[1],n=Math.cos(r);return[n*Math.cos(e),n*Math.sin(e),Math.sin(r)]}function ye(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function xe(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function be(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function _e(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function we(t){var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}function ke(t){return[Math.atan2(t[1],t[0]),nt(t[2])]}function Me(t,e){return bi(t[0]-e[0])=0;--l)a.point((f=u[l])[0],f[1])}else n(h.x,h.p.x,-1,a);h=h.p}h=h.o,u=h.z,p=!p}while(!h.v);a.lineEnd()}}}function Pe(t){if(e=t.length){for(var e,r,n=0,a=t[0];++n0){for(_||(o.polygonStart(),_=!0),o.lineStart();++i1&&2&e&&r.push(r.pop().concat(r.shift())),h.push(r.filter(Ie))}var h,p,g,m=e(o),v=a.invert(n[0],n[1]),y={point:i,lineStart:s,lineEnd:c,polygonStart:function(){y.point=u,y.lineStart=f,y.lineEnd=d,h=[],p=[]},polygonEnd:function(){y.point=i,y.lineStart=s,y.lineEnd=c,h=ui.merge(h);var t=He(v,p);h.length?(_||(o.polygonStart(),_=!0),De(h,Fe,t,r,o)):t&&(_||(o.polygonStart(),_=!0),o.lineStart(),r(null,null,1,o),o.lineEnd()),_&&(o.polygonEnd(),_=!1),h=p=null},sphere:function(){o.polygonStart(),o.lineStart(),r(null,null,1,o),o.lineEnd(),o.polygonEnd()}},x=Re(),b=e(x),_=!1;return y}}function Ie(t){return t.length>1}function Re(){var t,e=[];return{lineStart:function(){e.push(t=[])},point:function(e,r){t.push([e,r])},lineEnd:k,buffer:function(){var r=e;return e=[],t=null,r},rejoin:function(){e.length>1&&e.push(e.pop().concat(e.shift()))}}}function Fe(t,e){return((t=t.x)[0]<0?t[1]-Hi-Ri:Hi-t[1])-((e=e.x)[0]<0?e[1]-Hi-Ri:Hi-e[1])}function je(t){var e,r=NaN,n=NaN,a=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(o,i){var l=o>0?ji:-ji,s=bi(o-r);bi(s-ji)0?Hi:-Hi),t.point(a,n),t.lineEnd(),t.lineStart(),t.point(l,n),t.point(o,n),e=0):a!==l&&s>=ji&&(bi(r-a)Ri?Math.atan((Math.sin(e)*(o=Math.cos(n))*Math.sin(r)-Math.sin(n)*(a=Math.cos(e))*Math.sin(t))/(a*o*i)):(e+n)/2}function Be(t,e,r,n){var a;if(null==t)a=r*Hi,n.point(-ji,a),n.point(0,a),n.point(ji,a),n.point(ji,0),n.point(ji,-a),n.point(0,-a),n.point(-ji,-a),n.point(-ji,0),n.point(-ji,a);else if(bi(t[0]-e[0])>Ri){var o=t[0]=0?1:-1,k=w*_,M=k>ji,A=p*x;if(Al.add(Math.atan2(A*w*Math.sin(k),g*b+A*Math.cos(k))),o+=M?_+w*qi:_,M^d>=r^v>=r){var T=xe(ve(f),ve(t));we(T);var L=xe(a,T);we(L);var z=(M^_>=0?-1:1)*nt(L[2]);(n>z||n===z&&(T[0]||T[1]))&&(i+=M^_>=0?1:-1)}if(!m++)break;d=v,p=x,g=b,f=t}}return(o<-Ri||oo}function r(t){var r,o,s,c,u;return{lineStart:function(){c=s=!1,u=1},point:function(f,d){var h,p=[f,d],g=e(f,d),m=i?g?0:a(f,d):g?a(f+(f<0?ji:-ji),d):0;if(!r&&(c=s=g)&&t.lineStart(),g!==s&&(h=n(r,p),(Me(r,h)||Me(p,h))&&(p[0]+=Ri,p[1]+=Ri,g=e(p[0],p[1]))),g!==s)u=0,g?(t.lineStart(),h=n(p,r),t.point(h[0],h[1])):(h=n(r,p),t.point(h[0],h[1]),t.lineEnd()),r=h;else if(l&&r&&i^g){var v;m&o||!(v=n(p,r,!0))||(u=0,i?(t.lineStart(),t.point(v[0][0],v[0][1]),t.point(v[1][0],v[1][1]),t.lineEnd()):(t.point(v[1][0],v[1][1]),t.lineEnd(),t.lineStart(),t.point(v[0][0],v[0][1])))}!g||r&&Me(r,p)||t.point(p[0],p[1]),r=p,s=g,o=m},lineEnd:function(){s&&t.lineEnd(),r=null},clean:function(){return u|(c&&s)<<1}}}function n(t,e,r){var n=ve(t),a=ve(e),i=[1,0,0],l=xe(n,a),s=ye(l,l),c=l[0],u=s-c*c;if(!u)return!r&&t;var f=o*s/u,d=-o*c/u,h=xe(i,l),p=_e(i,f),g=_e(l,d);be(p,g);var m=h,v=ye(p,m),y=ye(m,m),x=v*v-y*(ye(p,p)-1);if(!(x<0)){var b=Math.sqrt(x),_=_e(m,(-v-b)/y);if(be(_,p),_=ke(_),!r)return _;var w,k=t[0],M=e[0],A=t[1],T=e[1];M0^_[1]<(bi(_[0]-k)ji^(k<=_[0]&&_[0]<=M)){var S=_e(m,(-v+b)/y);return be(S,p),[_,ke(S)]}}}function a(e,r){var n=i?t:ji-t,a=0;return e<-n?a|=1:e>n&&(a|=2),r<-n?a|=4:r>n&&(a|=8),a}var o=Math.cos(t),i=o>0,l=bi(o)>Ri,s=mr(t,6*Vi);return Ee(e,r,s,i?[0,-t]:[-ji,t-ji])}function Ze(t,e,r,n){return function(a){var o,i=a.a,l=a.b,s=i.x,c=i.y,u=l.x,f=l.y,d=0,h=1,p=u-s,g=f-c;if(o=t-s,p||!(o>0)){if(o/=p,p<0){if(o0){if(o>h)return;o>d&&(d=o)}if(o=r-s,p||!(o<0)){if(o/=p,p<0){if(o>h)return;o>d&&(d=o)}else if(p>0){if(o0)){if(o/=g,g<0){if(o0){if(o>h)return;o>d&&(d=o)}if(o=n-c,g||!(o<0)){if(o/=g,g<0){if(o>h)return;o>d&&(d=o)}else if(g>0){if(o0&&(a.a={x:s+d*p,y:c+d*g}),h<1&&(a.b={x:s+h*p,y:c+h*g}),a}}}}}}function Xe(t,e,r,n){function a(n,a){return bi(n[0]-t)0?0:3:bi(n[0]-r)0?2:1:bi(n[1]-e)0?1:0:a>0?3:2}function o(t,e){return i(t.x,e.x)}function i(t,e){var r=a(t,1),n=a(e,1);return r!==n?r-n:0===r?e[1]-t[1]:1===r?t[0]-e[0]:2===r?t[1]-e[1]:e[0]-t[0]}return function(l){function s(t){for(var e=0,r=m.length,n=t[1],a=0;an&&et(c,o,t)>0&&++e:o[1]<=n&&et(c,o,t)<0&&--e,c=o;return 0!==e}function c(o,l,s,c){var u=0,f=0;if(null==o||(u=a(o,s))!==(f=a(l,s))||i(o,l)<0^s>0){do c.point(0===u||3===u?t:r,u>1?n:e);while((u=(u+s+4)%4)!==f)}else c.point(l[0],l[1])}function u(a,o){return t<=a&&a<=r&&e<=o&&o<=n}function f(t,e){u(t,e)&&l.point(t,e)}function d(){C.point=p,m&&m.push(v=[]),M=!0,k=!1,_=w=NaN}function h(){g&&(p(y,x),b&&k&&L.rejoin(),g.push(L.buffer())),C.point=f,k&&l.lineEnd()}function p(t,e){t=Math.max(-ql,Math.min(ql,t)),e=Math.max(-ql,Math.min(ql,e));var r=u(t,e);if(m&&v.push([t,e]),M)y=t,x=e,b=r,M=!1,r&&(l.lineStart(),l.point(t,e));else if(r&&k)l.point(t,e);else{var n={a:{x:_,y:w},b:{x:t,y:e}};z(n)?(k||(l.lineStart(),l.point(n.a.x,n.a.y)),l.point(n.b.x,n.b.y),r||l.lineEnd(),A=!1):r&&(l.lineStart(),l.point(t,e),A=!1)}_=t,w=e,k=r}var g,m,v,y,x,b,_,w,k,M,A,T=l,L=Re(),z=Ze(t,e,r,n),C={point:f,lineStart:d,lineEnd:h,polygonStart:function(){l=L,g=[],m=[],A=!0},polygonEnd:function(){l=T,g=ui.merge(g);var e=s([t,n]),r=A&&e,a=g.length;(r||a)&&(l.polygonStart(),r&&(l.lineStart(),c(null,null,1,l),l.lineEnd()),a&&De(g,o,e,c,l),l.polygonEnd()),g=m=v=null}};return C}}function Ue(t){var e=0,r=ji/3,n=sr(t),a=n(e,r);return a.parallels=function(t){return arguments.length?n(e=t[0]*ji/180,r=t[1]*ji/180):[e/ji*180,r/ji*180]},a}function Ye(t,e){function r(t,e){var r=Math.sqrt(o-2*a*Math.sin(e))/a;return[r*Math.sin(t*=a),i-r*Math.cos(t)]}var n=Math.sin(t),a=(n+Math.sin(e))/2,o=1+n*(2*a-n),i=Math.sqrt(o)/a;return r.invert=function(t,e){var r=i-e;return[Math.atan2(t,r)/a,nt((o-(t*t+r*r)*a*a)/(2*a))]},r}function Ge(){function t(t,e){Hl+=a*t-n*e,n=t,a=e}var e,r,n,a;Yl.point=function(o,i){Yl.point=t,e=n=o,r=a=i},Yl.lineEnd=function(){t(e,r)}}function We(t,e){tXl&&(Xl=t),eUl&&(Ul=e)}function Qe(){function t(t,e){i.push("M",t,",",e,o)}function e(t,e){i.push("M",t,",",e),l.point=r}function r(t,e){i.push("L",t,",",e)}function n(){l.point=t}function a(){i.push("Z")}var o=$e(4.5),i=[],l={point:t,lineStart:function(){l.point=e},lineEnd:n,polygonStart:function(){l.lineEnd=a},polygonEnd:function(){l.lineEnd=n,l.point=t},pointRadius:function(t){return o=$e(t),l},result:function(){if(i.length){var t=i.join("");return i=[],t}}};return l}function $e(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Je(t,e){Cl+=t,Sl+=e,++Ol}function Ke(){function t(t,n){var a=t-e,o=n-r,i=Math.sqrt(a*a+o*o);Dl+=i*(e+t)/2,Pl+=i*(r+n)/2,Nl+=i,Je(e=t,r=n)}var e,r;Wl.point=function(n,a){Wl.point=t,Je(e=n,r=a)}}function tr(){Wl.point=Je}function er(){function t(t,e){var r=t-n,o=e-a,i=Math.sqrt(r*r+o*o);Dl+=i*(n+t)/2,Pl+=i*(a+e)/2,Nl+=i,i=a*t-n*e,El+=i*(n+t),Il+=i*(a+e),Rl+=3*i,Je(n=t,a=e)}var e,r,n,a;Wl.point=function(o,i){Wl.point=t,Je(e=n=o,r=a=i)},Wl.lineEnd=function(){t(e,r)}}function rr(t){function e(e,r){t.moveTo(e+i,r),t.arc(e,r,i,0,qi)}function r(e,r){t.moveTo(e,r),l.point=n}function n(e,r){t.lineTo(e,r)}function a(){l.point=e}function o(){t.closePath()}var i=4.5,l={point:e,lineStart:function(){l.point=r},lineEnd:a,polygonStart:function(){l.lineEnd=o},polygonEnd:function(){l.lineEnd=a,l.point=e},pointRadius:function(t){return i=t,l},result:k};return l}function nr(t){function e(t){return(l?n:r)(t)}function r(e){return ir(e,function(r,n){r=t(r,n),e.point(r[0],r[1])})}function n(e){function r(r,n){r=t(r,n),e.point(r[0],r[1])}function n(){x=NaN,M.point=o,e.lineStart()}function o(r,n){var o=ve([r,n]),i=t(r,n);a(x,b,y,_,w,k,x=i[0],b=i[1],y=r,_=o[0],w=o[1],k=o[2],l,e),e.point(x,b)}function i(){M.point=r,e.lineEnd()}function s(){n(),M.point=c,M.lineEnd=u}function c(t,e){o(f=t,d=e),h=x,p=b,g=_,m=w,v=k,M.point=o}function u(){a(x,b,y,_,w,k,h,p,f,g,m,v,l,e),M.lineEnd=i,i()}var f,d,h,p,g,m,v,y,x,b,_,w,k,M={point:r,lineStart:n,lineEnd:i,polygonStart:function(){e.polygonStart(),M.lineStart=s},polygonEnd:function(){e.polygonEnd(),M.lineStart=n}};return M}function a(e,r,n,l,s,c,u,f,d,h,p,g,m,v){var y=u-e,x=f-r,b=y*y+x*x;if(b>4*o&&m--){var _=l+h,w=s+p,k=c+g,M=Math.sqrt(_*_+w*w+k*k),A=Math.asin(k/=M),T=bi(bi(k)-1)o||bi((y*S+x*O)/b-.5)>.3||l*h+s*p+c*g0&&16,e):Math.sqrt(o)},e}function ar(t){var e=nr(function(e,r){return t([e*Zi,r*Zi])});return function(t){return cr(e(t))}}function or(t){this.stream=t}function ir(t,e){return{point:e,sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}function lr(t){return sr(function(){return t})()}function sr(t){function e(t){return t=l(t[0]*Vi,t[1]*Vi),[t[0]*d+s,c-t[1]*d]}function r(t){return t=l.invert((t[0]-s)/d,(c-t[1])/d),t&&[t[0]*Zi,t[1]*Zi]}function n(){l=Se(i=dr(v,y,x),o);var t=o(g,m);return s=h-t[0]*d,c=p+t[1]*d,a()}function a(){return u&&(u.valid=!1,u=null),e}var o,i,l,s,c,u,f=nr(function(t,e){return t=o(t,e),[t[0]*d+s,c-t[1]*d]}),d=150,h=480,p=250,g=0,m=0,v=0,y=0,x=0,_=jl,w=b,k=null,M=null;return e.stream=function(t){return u&&(u.valid=!1),u=cr(_(i,f(w(t)))),u.valid=!0,u},e.clipAngle=function(t){return arguments.length?(_=null==t?(k=t,jl):Ve((k=+t)*Vi),a()):k},e.clipExtent=function(t){return arguments.length?(M=t,w=t?Xe(t[0][0],t[0][1],t[1][0],t[1][1]):b,a()):M},e.scale=function(t){return arguments.length?(d=+t,n()):d},e.translate=function(t){return arguments.length?(h=+t[0],p=+t[1],n()):[h,p]},e.center=function(t){return arguments.length?(g=t[0]%360*Vi,m=t[1]%360*Vi,n()):[g*Zi,m*Zi]},e.rotate=function(t){return arguments.length?(v=t[0]%360*Vi,y=t[1]%360*Vi,x=t.length>2?t[2]%360*Vi:0,n()):[v*Zi,y*Zi,x*Zi]},ui.rebind(e,f,"precision"),function(){return o=t.apply(this,arguments),e.invert=o.invert&&r,n()}}function cr(t){return ir(t,function(e,r){t.point(e*Vi,r*Vi)})}function ur(t,e){return[t,e]}function fr(t,e){return[t>ji?t-qi:t<-ji?t+qi:t,e]}function dr(t,e,r){return t?e||r?Se(pr(t),gr(e,r)):pr(t):e||r?gr(e,r):fr}function hr(t){return function(e,r){return e+=t,[e>ji?e-qi:e<-ji?e+qi:e,r]}}function pr(t){var e=hr(t);return e.invert=hr(-t),e}function gr(t,e){function r(t,e){var r=Math.cos(e),l=Math.cos(t)*r,s=Math.sin(t)*r,c=Math.sin(e),u=c*n+l*a;return[Math.atan2(s*o-u*i,l*n-c*a),nt(u*o+s*i)]}var n=Math.cos(t),a=Math.sin(t),o=Math.cos(e),i=Math.sin(e);return r.invert=function(t,e){var r=Math.cos(e),l=Math.cos(t)*r,s=Math.sin(t)*r,c=Math.sin(e),u=c*o-s*i;return[Math.atan2(s*o+c*i,l*n+u*a),nt(u*n-l*a)]},r}function mr(t,e){var r=Math.cos(t),n=Math.sin(t);return function(a,o,i,l){var s=i*e;null!=a?(a=vr(r,a),o=vr(r,o),(i>0?ao)&&(a+=i*qi)):(a=t+i*qi,o=t-.5*s);for(var c,u=a;i>0?u>o:u0?e<-Hi+Ri&&(e=-Hi+Ri):e>Hi-Ri&&(e=Hi-Ri);var r=i/Math.pow(a(e),o);return[r*Math.sin(o*t),i-r*Math.cos(o*t)]}var n=Math.cos(t),a=function(t){return Math.tan(ji/4+t/2)},o=t===e?Math.sin(t):Math.log(n/Math.cos(e))/Math.log(a(e)/a(t)),i=n*Math.pow(a(t),o)/o;return o?(r.invert=function(t,e){var r=i-e,n=tt(o)*Math.sqrt(t*t+r*r);return[Math.atan2(t,r)/o,2*Math.atan(Math.pow(i/n,1/o))-Hi]},r):Lr}function Tr(t,e){function r(t,e){var r=o-e;return[r*Math.sin(a*t),o-r*Math.cos(a*t)]}var n=Math.cos(t),a=t===e?Math.sin(t):(n-Math.cos(e))/(e-t),o=n/a+t;return bi(a)1&&et(t[r[n-2]],t[r[n-1]],t[a])<=0;)--n;r[n++]=a}return r.slice(0,n)}function Pr(t,e){return t[0]-e[0]||t[1]-e[1]}function Nr(t,e,r){return(r[0]-e[0])*(t[1]-e[1])<(r[1]-e[1])*(t[0]-e[0])}function Er(t,e,r,n){var a=t[0],o=r[0],i=e[0]-a,l=n[0]-o,s=t[1],c=r[1],u=e[1]-s,f=n[1]-c,d=(l*(s-c)-f*(a-o))/(f*i-l*u);return[a+d*i,s+d*u]}function Ir(t){var e=t[0],r=t[t.length-1];return!(e[0]-r[0]||e[1]-r[1])}function Rr(){an(this),this.edge=this.site=this.circle=null}function Fr(t){var e=cs.pop()||new Rr;return e.site=t,e}function jr(t){Wr(t),is.remove(t),cs.push(t),an(t)}function qr(t){var e=t.circle,r=e.x,n=e.cy,a={x:r,y:n},o=t.P,i=t.N,l=[t];jr(t);for(var s=o;s.circle&&bi(r-s.circle.x)Ri)l=l.L;else{if(a=o-Vr(l,i),!(a>Ri)){n>-Ri?(e=l.P,r=l):a>-Ri?(e=l,r=l.N):e=r=l;break}if(!l.R){e=l;break}l=l.R}var s=Fr(t);if(is.insert(e,s),e||r){if(e===r)return Wr(e),r=Fr(e.site),is.insert(s,r),s.edge=r.edge=Kr(e.site,s.site),Gr(e),void Gr(r);if(!r)return void(s.edge=Kr(e.site,s.site));Wr(e),Wr(r);var c=e.site,u=c.x,f=c.y,d=t.x-u,h=t.y-f,p=r.site,g=p.x-u,m=p.y-f,v=2*(d*m-h*g),y=d*d+h*h,x=g*g+m*m,b={x:(m*y-h*x)/v+u,y:(d*x-g*y)/v+f};en(r.edge,c,p,b),s.edge=Kr(c,t,null,b),r.edge=Kr(t,p,null,b),Gr(e),Gr(r)}}function Hr(t,e){var r=t.site,n=r.x,a=r.y,o=a-e;if(!o)return n;var i=t.P;if(!i)return-(1/0);r=i.site;var l=r.x,s=r.y,c=s-e;if(!c)return l;var u=l-n,f=1/o-1/c,d=u/c;return f?(-d+Math.sqrt(d*d-2*f*(u*u/(-2*c)-s+c/2+a-o/2)))/f+n:(n+l)/2}function Vr(t,e){var r=t.N;if(r)return Hr(r,e);var n=t.site;return n.y===e?n.x:1/0}function Zr(t){this.site=t,this.edges=[]}function Xr(t){for(var e,r,n,a,o,i,l,s,c,u,f=t[0][0],d=t[1][0],h=t[0][1],p=t[1][1],g=os,m=g.length;m--;)if(o=g[m],o&&o.prepare())for(l=o.edges,s=l.length,i=0;iRi||bi(a-r)>Ri)&&(l.splice(i,0,new rn(tn(o.site,u,bi(n-f)Ri?{x:f,y:bi(e-f)Ri?{x:bi(r-p)Ri?{x:d,y:bi(e-d)Ri?{x:bi(r-h)=-Fi)){var h=s*s+c*c,p=u*u+f*f,g=(f*h-c*p)/d,m=(s*p-u*h)/d,f=m+l,v=us.pop()||new Yr;v.arc=t,v.site=a,v.x=g+i,v.y=f+Math.sqrt(g*g+m*m),v.cy=f,t.circle=v;for(var y=null,x=ss._;x;)if(v.y=l)return;if(d>p){if(o){if(o.y>=c)return}else o={x:m,y:s};r={x:m,y:c}}else{if(o){if(o.y1)if(d>p){if(o){if(o.y>=c)return}else o={x:(s-a)/n,y:s};r={x:(c-a)/n,y:c}}else{if(o){if(o.y=l)return}else o={x:i,y:n*i+a};r={x:l,y:n*l+a}}else{if(o){if(o.xo||f>i||d=b,k=r>=_,M=k<<1|w,A=M+4;Mo&&(a=e.slice(o,a),l[i]?l[i]+=a:l[++i]=a),(r=r[0])===(n=n[0])?l[i]?l[i]+=n:l[++i]=n:(l[++i]=null,s.push({i:i,x:xn(r,n)})),o=hs.lastIndex;return o=0&&!(r=ui.interpolators[n](t,e)););return r}function wn(t,e){var r,n=[],a=[],o=t.length,i=e.length,l=Math.min(t.length,e.length);for(r=0;r=1?1:t(e)}}function Mn(t){return function(e){return 1-t(1-e)}}function An(t){return function(e){return.5*(e<.5?t(2*e):2-t(2-2*e))}}function Tn(t){return t*t}function Ln(t){return t*t*t}function zn(t){if(t<=0)return 0;if(t>=1)return 1;var e=t*t,r=e*t;return 4*(t<.5?r:3*(t-e)+r-.75)}function Cn(t){return function(e){return Math.pow(e,t)}}function Sn(t){return 1-Math.cos(t*Hi)}function On(t){return Math.pow(2,10*(t-1))}function Dn(t){return 1-Math.sqrt(1-t*t)}function Pn(t,e){var r;return arguments.length<2&&(e=.45),arguments.length?r=e/qi*Math.asin(1/t):(t=1,r=e/4),function(n){return 1+t*Math.pow(2,-10*n)*Math.sin((n-r)*qi/e)}}function Nn(t){return t||(t=1.70158),function(e){return e*e*((t+1)*e-t)}}function En(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function In(t,e){t=ui.hcl(t),e=ui.hcl(e);var r=t.h,n=t.c,a=t.l,o=e.h-r,i=e.c-n,l=e.l-a;return isNaN(i)&&(i=0,n=isNaN(n)?e.c:n),isNaN(o)?(o=0,r=isNaN(r)?e.h:r):o>180?o-=360:o<-180&&(o+=360),function(t){return dt(r+o*t,n+i*t,a+l*t)+""}}function Rn(t,e){t=ui.hsl(t),e=ui.hsl(e);var r=t.h,n=t.s,a=t.l,o=e.h-r,i=e.s-n,l=e.l-a;return isNaN(i)&&(i=0,n=isNaN(n)?e.s:n),isNaN(o)?(o=0,r=isNaN(r)?e.h:r):o>180?o-=360:o<-180&&(o+=360),function(t){return ut(r+o*t,n+i*t,a+l*t)+""}}function Fn(t,e){t=ui.lab(t),e=ui.lab(e);var r=t.l,n=t.a,a=t.b,o=e.l-r,i=e.a-n,l=e.b-a;return function(t){return pt(r+o*t,n+i*t,a+l*t)+""}}function jn(t,e){return e-=t,function(r){return Math.round(t+e*r)}}function qn(t){var e=[t.a,t.b],r=[t.c,t.d],n=Hn(e),a=Bn(e,r),o=Hn(Vn(r,e,-a))||0;e[0]*r[1]180?e+=360:e-t>180&&(t+=360),n.push({i:r.push(Zn(r)+"rotate(",null,")")-2,x:xn(t,e)})):e&&r.push(Zn(r)+"rotate("+e+")")}function Yn(t,e,r,n){t!==e?n.push({i:r.push(Zn(r)+"skewX(",null,")")-2,x:xn(t,e)}):e&&r.push(Zn(r)+"skewX("+e+")")}function Gn(t,e,r,n){if(t[0]!==e[0]||t[1]!==e[1]){var a=r.push(Zn(r)+"scale(",null,",",null,")");n.push({i:a-4,x:xn(t[0],e[0])},{i:a-2,x:xn(t[1],e[1])})}else 1===e[0]&&1===e[1]||r.push(Zn(r)+"scale("+e+")")}function Wn(t,e){var r=[],n=[];return t=ui.transform(t),e=ui.transform(e),Xn(t.translate,e.translate,r,n),Un(t.rotate,e.rotate,r,n),Yn(t.skew,e.skew,r,n),Gn(t.scale,e.scale,r,n),t=e=null,function(t){for(var e,a=-1,o=n.length;++a=0;)r.push(a[n])}function sa(t,e){for(var r=[t],n=[];null!=(t=r.pop());)if(n.push(t),(o=t.children)&&(a=o.length))for(var a,o,i=-1;++ia&&(n=r,a=e);return n}function xa(t){return t.reduce(ba,0)}function ba(t,e){return t+e[1]}function _a(t,e){return wa(t,Math.ceil(Math.log(e.length)/Math.LN2+1))}function wa(t,e){for(var r=-1,n=+t[0],a=(t[1]-n)/e,o=[];++r<=e;)o[r]=a*r+n;return o}function ka(t){return[ui.min(t),ui.max(t)]}function Ma(t,e){return t.value-e.value}function Aa(t,e){var r=t._pack_next;t._pack_next=e,e._pack_prev=t,e._pack_next=r,r._pack_prev=e}function Ta(t,e){t._pack_next=e,e._pack_prev=t}function La(t,e){var r=e.x-t.x,n=e.y-t.y,a=t.r+e.r;return.999*a*a>r*r+n*n}function za(t){function e(t){u=Math.min(t.x-t.r,u),f=Math.max(t.x+t.r,f),d=Math.min(t.y-t.r,d),h=Math.max(t.y+t.r,h)}if((r=t.children)&&(c=r.length)){var r,n,a,o,i,l,s,c,u=1/0,f=-(1/0),d=1/0,h=-(1/0);if(r.forEach(Ca),n=r[0], -n.x=-n.r,n.y=0,e(n),c>1&&(a=r[1],a.x=a.r,a.y=0,e(a),c>2))for(o=r[2],Da(n,a,o),e(o),Aa(n,o),n._pack_prev=o,Aa(o,a),a=n._pack_next,i=3;i=0;)e=a[o],e.z+=r,e.m+=r,r+=e.s+(n+=e.c)}function Fa(t,e,r){return t.a.parent===e.parent?t.a:r}function ja(t){return 1+ui.max(t,function(t){return t.y})}function qa(t){return t.reduce(function(t,e){return t+e.x},0)/t.length}function Ba(t){var e=t.children;return e&&e.length?Ba(e[0]):t}function Ha(t){var e,r=t.children;return r&&(e=r.length)?Ha(r[e-1]):t}function Va(t){return{x:t.x,y:t.y,dx:t.dx,dy:t.dy}}function Za(t,e){var r=t.x+e[3],n=t.y+e[0],a=t.dx-e[1]-e[3],o=t.dy-e[0]-e[2];return a<0&&(r+=a/2,a=0),o<0&&(n+=o/2,o=0),{x:r,y:n,dx:a,dy:o}}function Xa(t){var e=t[0],r=t[t.length-1];return e2?Qa:Ya,s=n?$n:Qn;return i=a(t,e,s,r),l=a(e,t,s,_n),o}function o(t){return i(t)}var i,l;return o.invert=function(t){return l(t)},o.domain=function(e){return arguments.length?(t=e.map(Number),a()):t},o.range=function(t){return arguments.length?(e=t,a()):e},o.rangeRound=function(t){return o.range(t).interpolate(jn)},o.clamp=function(t){return arguments.length?(n=t,a()):n},o.interpolate=function(t){return arguments.length?(r=t,a()):r},o.ticks=function(e){return eo(t,e)},o.tickFormat=function(e,r){return ro(t,e,r)},o.nice=function(e){return Ka(t,e),a()},o.copy=function(){return $a(t,e,r,n)},a()}function Ja(t,e){return ui.rebind(t,e,"range","rangeRound","interpolate","clamp")}function Ka(t,e){return Ga(t,Wa(to(t,e)[2])),Ga(t,Wa(to(t,e)[2])),t}function to(t,e){null==e&&(e=10);var r=Xa(t),n=r[1]-r[0],a=Math.pow(10,Math.floor(Math.log(n/e)/Math.LN10)),o=e/n*a;return o<=.15?a*=10:o<=.35?a*=5:o<=.75&&(a*=2),r[0]=Math.ceil(r[0]/a)*a,r[1]=Math.floor(r[1]/a)*a+.5*a,r[2]=a,r}function eo(t,e){return ui.range.apply(ui,to(t,e))}function ro(t,e,r){var n=to(t,e);if(r){var a=dl.exec(r);if(a.shift(),"s"===a[8]){var o=ui.formatPrefix(Math.max(bi(n[0]),bi(n[1])));return a[7]||(a[7]="."+no(o.scale(n[2]))),a[8]="f",r=ui.format(a.join("")),function(t){return r(o.scale(t))+o.symbol}}a[7]||(a[7]="."+ao(a[8],n)),r=a.join("")}else r=",."+no(n[2])+"f";return ui.format(r)}function no(t){return-Math.floor(Math.log(t)/Math.LN10+.01)}function ao(t,e){var r=no(e[2]);return t in As?Math.abs(r-no(Math.max(bi(e[0]),bi(e[1]))))+ +("e"!==t):r-2*("%"===t)}function oo(t,e,r,n){function a(t){return(r?Math.log(t<0?0:t):-Math.log(t>0?0:-t))/Math.log(e)}function o(t){return r?Math.pow(e,t):-Math.pow(e,-t)}function i(e){return t(a(e))}return i.invert=function(e){return o(t.invert(e))},i.domain=function(e){return arguments.length?(r=e[0]>=0,t.domain((n=e.map(Number)).map(a)),i):n},i.base=function(r){return arguments.length?(e=+r,t.domain(n.map(a)),i):e},i.nice=function(){var e=Ga(n.map(a),r?Math:Ls);return t.domain(e),n=e.map(o),i},i.ticks=function(){var t=Xa(n),i=[],l=t[0],s=t[1],c=Math.floor(a(l)),u=Math.ceil(a(s)),f=e%1?2:e;if(isFinite(u-c)){if(r){for(;c0;d--)i.push(o(c)*d);for(c=0;i[c]s;u--);i=i.slice(c,u)}return i},i.tickFormat=function(t,r){if(!arguments.length)return Ts;arguments.length<2?r=Ts:"function"!=typeof r&&(r=ui.format(r));var n=Math.max(1,e*t/i.ticks().length);return function(t){var i=t/o(Math.round(a(t)));return i*e0?l[r-1]:t[0],r0?0:1}function _o(t,e,r,n,a){var o=t[0]-e[0],i=t[1]-e[1],l=(a?n:-n)/Math.sqrt(o*o+i*i),s=l*i,c=-l*o,u=t[0]+s,f=t[1]+c,d=e[0]+s,h=e[1]+c,p=(u+d)/2,g=(f+h)/2,m=d-u,v=h-f,y=m*m+v*v,x=r-n,b=u*h-d*f,_=(v<0?-1:1)*Math.sqrt(Math.max(0,x*x*y-b*b)),w=(b*v-m*_)/y,k=(-b*m-v*_)/y,M=(b*v+m*_)/y,A=(-b*m+v*_)/y,T=w-p,L=k-g,z=M-p,C=A-g;return T*T+L*L>z*z+C*C&&(w=M,k=A),[[w-s,k-c],[w*r/x,k*r/x]]}function wo(t){function e(e){function i(){c.push("M",o(t(u),l))}for(var s,c=[],u=[],f=-1,d=e.length,h=zt(r),p=zt(n);++f1?t.join("L"):t+"Z"}function Mo(t){return t.join("L")+"Z"}function Ao(t){for(var e=0,r=t.length,n=t[0],a=[n[0],",",n[1]];++e1&&a.push("H",n[0]),a.join("")}function To(t){for(var e=0,r=t.length,n=t[0],a=[n[0],",",n[1]];++e1){l=e[1],o=t[s],s++,n+="C"+(a[0]+i[0])+","+(a[1]+i[1])+","+(o[0]-l[0])+","+(o[1]-l[1])+","+o[0]+","+o[1];for(var c=2;c9&&(a=3*e/Math.sqrt(a),i[l]=a*r,i[l+1]=a*n));for(l=-1;++l<=s;)a=(t[Math.min(s,l+1)][0]-t[Math.max(0,l-1)][0])/(6*(1+i[l]*i[l])),o.push([a||0,i[l]*a||0]);return o}function Ho(t){return t.length<3?ko(t):t[0]+Oo(t,Bo(t))}function Vo(t){for(var e,r,n,a=-1,o=t.length;++a0;)h[--l].call(t,i);if(o>=1)return g.event&&g.event.end.call(t,t.__data__,e),--p.count?delete p[n]:delete t[r],1}var s,c,u,d,h,p=t[r]||(t[r]={active:0,count:0}),g=p[n];g||(s=a.time,c=Pt(o,0,s),g=p[n]={tween:new f,time:s,timer:c,delay:a.delay,duration:a.duration,ease:a.ease,index:e},a=null,++p.count)}function ni(t,e,r){t.attr("transform",function(t){var n=e(t);return"translate("+(isFinite(n)?n:r(t))+",0)"})}function ai(t,e,r){t.attr("transform",function(t){var n=e(t);return"translate(0,"+(isFinite(n)?n:r(t))+")"})}function oi(t){return t.toISOString()}function ii(t,e,r){function n(e){return t(e)}function a(t,r){var n=t[1]-t[0],a=n/r,o=ui.bisect(Js,a);return o==Js.length?[e.year,to(t.map(function(t){return t/31536e6}),r)[2]]:o?e[a/Js[o-1]1?{floor:function(e){for(;r(e=t.floor(e));)e=li(e-1);return e},ceil:function(e){for(;r(e=t.ceil(e));)e=li(+e+1);return e}}:t))},n.ticks=function(t,e){var r=Xa(n.domain()),o=null==t?a(r,10):"number"==typeof t?a(r,t):!t.range&&[{range:t},e];return o&&(t=o[0],e=o[1]),t.range(r[0],li(+r[1]+1),e<1?1:e)},n.tickFormat=function(){return r},n.copy=function(){return ii(t.copy(),e,r)},Ja(n,t)}function li(t){return new Date(t)}function si(t){return JSON.parse(t.responseText)}function ci(t){var e=hi.createRange();return e.selectNode(hi.body),e.createContextualFragment(t.responseText)}var ui={version:"3.5.17"},fi=[].slice,di=function(t){return fi.call(t)},hi=this.document;if(hi)try{di(hi.documentElement.childNodes)[0].nodeType}catch(t){di=function(t){for(var e=t.length,r=new Array(e);e--;)r[e]=t[e];return r}}if(Date.now||(Date.now=function(){return+new Date}),hi)try{hi.createElement("DIV").style.setProperty("opacity",0,"")}catch(t){var pi=this.Element.prototype,gi=pi.setAttribute,mi=pi.setAttributeNS,vi=this.CSSStyleDeclaration.prototype,yi=vi.setProperty;pi.setAttribute=function(t,e){gi.call(this,t,e+"")},pi.setAttributeNS=function(t,e,r){mi.call(this,t,e,r+"")},vi.setProperty=function(t,e,r){yi.call(this,t,e+"",r)}}ui.ascending=a,ui.descending=function(t,e){return et?1:e>=t?0:NaN},ui.min=function(t,e){var r,n,a=-1,o=t.length;if(1===arguments.length){for(;++a=n){r=n;break}for(;++an&&(r=n)}else{for(;++a=n){r=n;break}for(;++an&&(r=n)}return r},ui.max=function(t,e){var r,n,a=-1,o=t.length;if(1===arguments.length){for(;++a=n){r=n;break}for(;++ar&&(r=n)}else{for(;++a=n){r=n;break}for(;++ar&&(r=n)}return r},ui.extent=function(t,e){var r,n,a,o=-1,i=t.length;if(1===arguments.length){for(;++o=n){r=a=n;break}for(;++on&&(r=n),a=n){r=a=n;break}for(;++on&&(r=n),a1)return s/(u-1)},ui.deviation=function(){var t=ui.variance.apply(this,arguments);return t?Math.sqrt(t):t};var xi=l(a);ui.bisectLeft=xi.left,ui.bisect=ui.bisectRight=xi.right,ui.bisector=function(t){return l(1===t.length?function(e,r){return a(t(e),r)}:t)},ui.shuffle=function(t,e,r){(o=arguments.length)<3&&(r=t.length,o<2&&(e=0));for(var n,a,o=r-e;o;)a=Math.random()*o--|0,n=t[o+e],t[o+e]=t[a+e],t[a+e]=n;return t},ui.permute=function(t,e){for(var r=e.length,n=new Array(r);r--;)n[r]=t[e[r]];return n},ui.pairs=function(t){for(var e,r=0,n=t.length-1,a=t[0],o=new Array(n<0?0:n);r=0;)for(n=t[a],e=n.length;--e>=0;)r[--i]=n[e];return r};var bi=Math.abs;ui.range=function(t,e,r){if(arguments.length<3&&(r=1,arguments.length<2&&(e=t,t=0)),(e-t)/r===1/0)throw new Error("infinite range");var n,a=[],o=c(bi(r)),i=-1;if(t*=o,e*=o,r*=o,r<0)for(;(n=t+r*++i)>e;)a.push(n/o);else for(;(n=t+r*++i)=o.length)return n?n.call(a,i):r?i.sort(r):i;for(var s,c,u,d,h=-1,p=i.length,g=o[l++],m=new f;++h=o.length)return t;var n=[],a=i[r++];return t.forEach(function(t,a){n.push({key:t,values:e(a,r)})}),a?n.sort(function(t,e){return a(t.key,e.key)}):n}var r,n,a={},o=[],i=[];return a.map=function(e,r){return t(r,e,0)},a.entries=function(r){return e(t(ui.map,r,0),0)},a.key=function(t){return o.push(t),a},a.sortKeys=function(t){return i[o.length-1]=t,a},a.sortValues=function(t){return r=t,a},a.rollup=function(t){return n=t,a},a},ui.set=function(t){var e=new x;if(t)for(var r=0,n=t.length;r=0&&(n=t.slice(r+1),t=t.slice(0,r)),t)return arguments.length<2?this[t].on(n):this[t].on(n,e);if(2===arguments.length){if(null==e)for(t in this)this.hasOwnProperty(t)&&this[t].on(n,null);return this}},ui.event=null,ui.requote=function(t){return t.replace(Mi,"\\$&")};var Mi=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,Ai={}.__proto__?function(t,e){t.__proto__=e}:function(t,e){for(var r in e)t[r]=e[r]},Ti=function(t,e){return e.querySelector(t)},Li=function(t,e){return e.querySelectorAll(t)},zi=function(t,e){var r=t.matches||t[w(t,"matchesSelector")];return(zi=function(t,e){return r.call(t,e)})(t,e)};"function"==typeof Sizzle&&(Ti=function(t,e){return Sizzle(t,e)[0]||null},Li=Sizzle,zi=Sizzle.matchesSelector),ui.selection=function(){return ui.select(hi.documentElement)};var Ci=ui.selection.prototype=[];Ci.select=function(t){var e,r,n,a,o=[];t=S(t);for(var i=-1,l=this.length;++i=0&&"xmlns"!==(r=t.slice(0,e))&&(t=t.slice(e+1)),Oi.hasOwnProperty(r)?{space:Oi[r],local:t}:t}},Ci.attr=function(t,e){if(arguments.length<2){if("string"==typeof t){var r=this.node();return t=ui.ns.qualify(t),t.local?r.getAttributeNS(t.space,t.local):r.getAttribute(t)}for(e in t)this.each(D(e,t[e]));return this}return this.each(D(t,e))},Ci.classed=function(t,e){if(arguments.length<2){if("string"==typeof t){var r=this.node(),n=(t=E(t)).length,a=-1;if(e=r.classList){for(;++a=0;)(r=n[a])&&(o&&o!==r.nextSibling&&o.parentNode.insertBefore(r,o),o=r);return this},Ci.sort=function(t){t=Z.apply(this,arguments);for(var e=-1,r=this.length;++e0&&(e=e.transition().duration(C)),e.call(t.event)}function l(){_&&_.domain(b.range().map(function(t){return(t-M.x)/M.k}).map(b.invert)),k&&k.domain(w.range().map(function(t){return(t-M.y)/M.k}).map(w.invert))}function s(t){S++||t({type:"zoomstart"})}function c(t){l(),t({type:"zoom",scale:M.k,translate:[M.x,M.y]})}function u(t){--S||(t({type:"zoomend"}),m=null)}function f(){function t(){l=1,o(ui.mouse(a),d),c(i)}function r(){f.on(D,null).on(P,null),h(l),u(i)}var a=this,i=E.of(a,arguments),l=0,f=ui.select(n(a)).on(D,t).on(P,r),d=e(ui.mouse(a)),h=$(a);Hs.call(a),s(i)}function d(){function t(){var t=ui.touches(p);return h=M.k,t.forEach(function(t){t.identifier in m&&(m[t.identifier]=e(t))}),t}function r(){var e=ui.event.target;ui.select(e).on(b,n).on(_,l),w.push(e);for(var r=ui.event.changedTouches,a=0,o=r.length;a1){var u=s[0],f=s[1],d=u[0]-f[0],h=u[1]-f[1];v=d*d+h*h}}function n(){var t,e,r,n,i=ui.touches(p);Hs.call(p);for(var l=0,s=i.length;l=c)return i;if(a)return a=!1,o;var e=u;if(34===t.charCodeAt(e)){for(var r=e;r++=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,hl=ui.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,e){return t.toPrecision(e)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},r:function(t,e){return(t=ui.round(t,Rt(t,e))).toFixed(Math.max(0,Math.min(20,Rt(t*(1+1e-15),e))))}}),pl=ui.time={},gl=Date;Bt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){ml.setUTCDate.apply(this._,arguments)},setDay:function(){ml.setUTCDay.apply(this._,arguments)},setFullYear:function(){ml.setUTCFullYear.apply(this._,arguments)},setHours:function(){ml.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){ml.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){ml.setUTCMinutes.apply(this._,arguments)},setMonth:function(){ml.setUTCMonth.apply(this._,arguments)},setSeconds:function(){ml.setUTCSeconds.apply(this._,arguments)},setTime:function(){ml.setTime.apply(this._,arguments)}};var ml=Date.prototype;pl.year=Ht(function(t){return t=pl.day(t),t.setMonth(0,1),t},function(t,e){t.setFullYear(t.getFullYear()+e)},function(t){return t.getFullYear()}),pl.years=pl.year.range,pl.years.utc=pl.year.utc.range,pl.day=Ht(function(t){var e=new gl(2e3,0);return e.setFullYear(t.getFullYear(),t.getMonth(),t.getDate()),e},function(t,e){t.setDate(t.getDate()+e)},function(t){return t.getDate()-1}),pl.days=pl.day.range,pl.days.utc=pl.day.utc.range,pl.dayOfYear=function(t){var e=pl.year(t);return Math.floor((t-e-6e4*(t.getTimezoneOffset()-e.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(t,e){e=7-e;var r=pl[t]=Ht(function(t){return(t=pl.day(t)).setDate(t.getDate()-(t.getDay()+e)%7),t},function(t,e){t.setDate(t.getDate()+7*Math.floor(e))},function(t){var r=pl.year(t).getDay();return Math.floor((pl.dayOfYear(t)+(r+e)%7)/7)-(r!==e)});pl[t+"s"]=r.range,pl[t+"s"].utc=r.utc.range,pl[t+"OfYear"]=function(t){var r=pl.year(t).getDay();return Math.floor((pl.dayOfYear(t)+(r+e)%7)/7)}}),pl.week=pl.sunday,pl.weeks=pl.sunday.range,pl.weeks.utc=pl.sunday.utc.range,pl.weekOfYear=pl.sundayOfYear;var vl={"-":"",_:" ",0:"0"},yl=/^\s*\d+/,xl=/^%/;ui.locale=function(t){return{numberFormat:jt(t),timeFormat:Zt(t)}};var bl=ui.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ui.format=bl.numberFormat,ui.geo={},fe.prototype={s:0,t:0,add:function(t){de(t,this.t,_l),de(_l.s,this.s,this),this.s?this.t+=_l.t:this.s=_l.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var _l=new fe;ui.geo.stream=function(t,e){t&&wl.hasOwnProperty(t.type)?wl[t.type](t,e):he(t,e)};var wl={Feature:function(t,e){he(t.geometry,e)},FeatureCollection:function(t,e){for(var r=t.features,n=-1,a=r.length;++nh&&(h=e)}function e(e,r){var n=ve([e*Vi,r*Vi]);if(v){var a=xe(v,n),o=[a[1],-a[0],0],i=xe(o,a);we(i),i=ke(i);var s=e-p,c=s>0?1:-1,g=i[0]*Zi*c,m=bi(s)>180;if(m^(c*ph&&(h=y)}else if(g=(g+360)%360-180,m^(c*ph&&(h=r);m?el(u,d)&&(d=e):l(e,d)>l(u,d)&&(u=e):d>=u?(ed&&(d=e)):e>p?l(u,e)>l(u,d)&&(d=e):l(e,d)>l(u,d)&&(u=e)}else t(e,r);v=n,p=e}function r(){_.point=e}function n(){b[0]=u,b[1]=d,_.point=t,v=null}function a(t,r){if(v){var n=t-p;y+=bi(n)>180?n+(n>0?360:-360):n}else g=t,m=r;Tl.point(t,r),e(t,r)}function o(){Tl.lineStart()}function i(){a(g,m),Tl.lineEnd(),bi(y)>Ri&&(u=-(d=180)),b[0]=u,b[1]=d,v=null}function l(t,e){return(e-=t)<0?e+360:e}function s(t,e){return t[0]-e[0]}function c(t,e){return e[0]<=e[1]?e[0]<=t&&t<=e[1]:tRi?h=90:y<-Ri&&(f=-90),b[0]=u,b[1]=d}};return function(t){h=d=-(u=f=1/0),x=[],ui.geo.stream(t,_);var e=x.length;if(e){x.sort(s);for(var r,n=1,a=x[0],o=[a];nl(a[0],a[1])&&(a[1]=r[1]),l(r[0],a[1])>l(a[0],a[1])&&(a[0]=r[0])):o.push(a=r);for(var i,r,p=-(1/0),e=o.length-1,n=0,a=o[e];n<=e;a=r,++n)r=o[n],(i=l(a[1],r[0]))>p&&(p=i,u=r[0],d=a[1])}return x=b=null,u===1/0||f===1/0?[[NaN,NaN],[NaN,NaN]]:[[u,f],[d,h]]}}(),ui.geo.centroid=function(t){Ll=zl=Cl=Sl=Ol=Dl=Pl=Nl=El=Il=Rl=0,ui.geo.stream(t,Fl);var e=El,r=Il,n=Rl,a=e*e+r*r+n*n;return a=.12&&a<.234&&n>=-.425&&n<-.214?i:a>=.166&&a<.234&&n>=-.214&&n<-.115?l:o).invert(t)},t.stream=function(t){var e=o.stream(t),r=i.stream(t),n=l.stream(t);return{point:function(t,a){e.point(t,a),r.point(t,a),n.point(t,a)},sphere:function(){e.sphere(),r.sphere(),n.sphere()},lineStart:function(){e.lineStart(),r.lineStart(),n.lineStart()},lineEnd:function(){e.lineEnd(),r.lineEnd(),n.lineEnd()},polygonStart:function(){e.polygonStart(),r.polygonStart(),n.polygonStart()},polygonEnd:function(){e.polygonEnd(),r.polygonEnd(),n.polygonEnd()}}},t.precision=function(e){return arguments.length?(o.precision(e),i.precision(e),l.precision(e),t):o.precision()},t.scale=function(e){return arguments.length?(o.scale(e),i.scale(.35*e),l.scale(e),t.translate(o.translate())):o.scale()},t.translate=function(e){if(!arguments.length)return o.translate();var c=o.scale(),u=+e[0],f=+e[1];return r=o.translate(e).clipExtent([[u-.455*c,f-.238*c],[u+.455*c,f+.238*c]]).stream(s).point,n=i.translate([u-.307*c,f+.201*c]).clipExtent([[u-.425*c+Ri,f+.12*c+Ri],[u-.214*c-Ri,f+.234*c-Ri]]).stream(s).point,a=l.translate([u-.205*c,f+.212*c]).clipExtent([[u-.214*c+Ri,f+.166*c+Ri],[u-.115*c-Ri,f+.234*c-Ri]]).stream(s).point,t},t.scale(1070)};var Bl,Hl,Vl,Zl,Xl,Ul,Yl={point:k,lineStart:k,lineEnd:k,polygonStart:function(){Hl=0,Yl.lineStart=Ge},polygonEnd:function(){Yl.lineStart=Yl.lineEnd=Yl.point=k,Bl+=bi(Hl/2)}},Gl={point:We,lineStart:k,lineEnd:k,polygonStart:k,polygonEnd:k},Wl={point:Je,lineStart:Ke,lineEnd:tr,polygonStart:function(){Wl.lineStart=er},polygonEnd:function(){Wl.point=Je,Wl.lineStart=Ke,Wl.lineEnd=tr}};ui.geo.path=function(){function t(t){return t&&("function"==typeof l&&o.pointRadius(+l.apply(this,arguments)),i&&i.valid||(i=a(o)),ui.geo.stream(t,i)),o.result()}function e(){return i=null,t}var r,n,a,o,i,l=4.5;return t.area=function(t){return Bl=0,ui.geo.stream(t,a(Yl)),Bl},t.centroid=function(t){return Cl=Sl=Ol=Dl=Pl=Nl=El=Il=Rl=0,ui.geo.stream(t,a(Wl)),Rl?[El/Rl,Il/Rl]:Nl?[Dl/Nl,Pl/Nl]:Ol?[Cl/Ol,Sl/Ol]:[NaN,NaN]},t.bounds=function(t){return Xl=Ul=-(Vl=Zl=1/0),ui.geo.stream(t,a(Gl)),[[Vl,Zl],[Xl,Ul]]},t.projection=function(t){return arguments.length?(a=(r=t)?t.stream||ar(t):b,e()):r},t.context=function(t){return arguments.length?(o=null==(n=t)?new Qe:new rr(t),"function"!=typeof l&&o.pointRadius(l),e()):n},t.pointRadius=function(e){return arguments.length?(l="function"==typeof e?e:(o.pointRadius(+e),+e),t):l},t.projection(ui.geo.albersUsa()).context(null)},ui.geo.transform=function(t){return{stream:function(e){var r=new or(e);for(var n in t)r[n]=t[n];return r}}},or.prototype={point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ui.geo.projection=lr,ui.geo.projectionMutator=sr,(ui.geo.equirectangular=function(){return lr(ur)}).raw=ur.invert=ur,ui.geo.rotation=function(t){function e(e){return e=t(e[0]*Vi,e[1]*Vi),e[0]*=Zi,e[1]*=Zi,e}return t=dr(t[0]%360*Vi,t[1]*Vi,t.length>2?t[2]*Vi:0),e.invert=function(e){return e=t.invert(e[0]*Vi,e[1]*Vi),e[0]*=Zi,e[1]*=Zi,e},e},fr.invert=ur,ui.geo.circle=function(){function t(){var t="function"==typeof n?n.apply(this,arguments):n,e=dr(-t[0]*Vi,-t[1]*Vi,0).invert,a=[];return r(null,null,1,{point:function(t,r){a.push(t=e(t,r)),t[0]*=Zi,t[1]*=Zi}}),{type:"Polygon",coordinates:[a]}}var e,r,n=[0,0],a=6;return t.origin=function(e){return arguments.length?(n=e,t):n},t.angle=function(n){return arguments.length?(r=mr((e=+n)*Vi,a*Vi),t):e},t.precision=function(n){return arguments.length?(r=mr(e*Vi,(a=+n)*Vi),t):a},t.angle(90)},ui.geo.distance=function(t,e){var r,n=(e[0]-t[0])*Vi,a=t[1]*Vi,o=e[1]*Vi,i=Math.sin(n),l=Math.cos(n),s=Math.sin(a),c=Math.cos(a),u=Math.sin(o),f=Math.cos(o);return Math.atan2(Math.sqrt((r=f*i)*r+(r=c*u-s*f*l)*r),s*u+c*f*l)},ui.geo.graticule=function(){function t(){return{type:"MultiLineString",coordinates:e()}}function e(){return ui.range(Math.ceil(o/m)*m,a,m).map(d).concat(ui.range(Math.ceil(c/v)*v,s,v).map(h)).concat(ui.range(Math.ceil(n/p)*p,r,p).filter(function(t){return bi(t%m)>Ri}).map(u)).concat(ui.range(Math.ceil(l/g)*g,i,g).filter(function(t){return bi(t%v)>Ri}).map(f))}var r,n,a,o,i,l,s,c,u,f,d,h,p=10,g=p,m=90,v=360,y=2.5;return t.lines=function(){return e().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[d(o).concat(h(s).slice(1),d(a).reverse().slice(1),h(c).reverse().slice(1))]}},t.extent=function(e){return arguments.length?t.majorExtent(e).minorExtent(e):t.minorExtent()},t.majorExtent=function(e){return arguments.length?(o=+e[0][0],a=+e[1][0],c=+e[0][1],s=+e[1][1],o>a&&(e=o,o=a,a=e),c>s&&(e=c,c=s,s=e),t.precision(y)):[[o,c],[a,s]]},t.minorExtent=function(e){return arguments.length?(n=+e[0][0],r=+e[1][0],l=+e[0][1],i=+e[1][1],n>r&&(e=n,n=r,r=e),l>i&&(e=l,l=i,i=e),t.precision(y)):[[n,l],[r,i]]},t.step=function(e){return arguments.length?t.majorStep(e).minorStep(e):t.minorStep()},t.majorStep=function(e){return arguments.length?(m=+e[0],v=+e[1],t):[m,v]},t.minorStep=function(e){return arguments.length?(p=+e[0],g=+e[1],t):[p,g]},t.precision=function(e){return arguments.length?(y=+e,u=yr(l,i,90),f=xr(n,r,y),d=yr(c,s,90),h=xr(o,a,y),t):y},t.majorExtent([[-180,-90+Ri],[180,90-Ri]]).minorExtent([[-180,-80-Ri],[180,80+Ri]])},ui.geo.greatArc=function(){function t(){return{type:"LineString",coordinates:[e||n.apply(this,arguments),r||a.apply(this,arguments)]}}var e,r,n=br,a=_r;return t.distance=function(){return ui.geo.distance(e||n.apply(this,arguments),r||a.apply(this,arguments))},t.source=function(r){return arguments.length?(n=r,e="function"==typeof r?null:r,t):n},t.target=function(e){return arguments.length?(a=e,r="function"==typeof e?null:e,t):a},t.precision=function(){return arguments.length?t:0},t},ui.geo.interpolate=function(t,e){return wr(t[0]*Vi,t[1]*Vi,e[0]*Vi,e[1]*Vi)},ui.geo.length=function(t){return Ql=0,ui.geo.stream(t,$l),Ql};var Ql,$l={sphere:k,point:k,lineStart:kr,lineEnd:k,polygonStart:k,polygonEnd:k},Jl=Mr(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(ui.geo.azimuthalEqualArea=function(){return lr(Jl)}).raw=Jl;var Kl=Mr(function(t){var e=Math.acos(t);return e&&e/Math.sin(e)},b);(ui.geo.azimuthalEquidistant=function(){return lr(Kl)}).raw=Kl,(ui.geo.conicConformal=function(){return Ue(Ar)}).raw=Ar,(ui.geo.conicEquidistant=function(){return Ue(Tr)}).raw=Tr;var ts=Mr(function(t){return 1/t},Math.atan);(ui.geo.gnomonic=function(){return lr(ts)}).raw=ts,Lr.invert=function(t,e){return[t,2*Math.atan(Math.exp(e))-Hi]},(ui.geo.mercator=function(){return zr(Lr)}).raw=Lr;var es=Mr(function(){return 1},Math.asin);(ui.geo.orthographic=function(){return lr(es)}).raw=es;var rs=Mr(function(t){return 1/(1+t)},function(t){return 2*Math.atan(t)});(ui.geo.stereographic=function(){return lr(rs)}).raw=rs,Cr.invert=function(t,e){return[-e,2*Math.atan(Math.exp(t))-Hi]},(ui.geo.transverseMercator=function(){var t=zr(Cr),e=t.center,r=t.rotate;return t.center=function(t){return t?e([-t[1],t[0]]):(t=e(),[t[1],-t[0]])},t.rotate=function(t){return t?r([t[0],t[1],t.length>2?t[2]+90:90]):(t=r(),[t[0],t[1],t[2]-90])},r([0,0,90])}).raw=Cr,ui.geom={},ui.geom.hull=function(t){function e(t){if(t.length<3)return[];var e,a=zt(r),o=zt(n),i=t.length,l=[],s=[];for(e=0;e=0;--e)h.push(t[l[c[e]][2]]);for(e=+f;e=n&&c.x<=o&&c.y>=a&&c.y<=i?[[n,i],[o,i],[o,a],[n,a]]:[];u.point=t[l]}),e}function r(t){return t.map(function(t,e){return{x:Math.round(o(t,e)/Ri)*Ri,y:Math.round(i(t,e)/Ri)*Ri,i:e}})}var n=Sr,a=Or,o=n,i=a,l=fs;return t?e(t):(e.links=function(t){return cn(r(t)).edges.filter(function(t){return t.l&&t.r}).map(function(e){return{source:t[e.l.i],target:t[e.r.i]}})},e.triangles=function(t){var e=[];return cn(r(t)).cells.forEach(function(r,n){for(var a,o,i=r.site,l=r.edges.sort(Ur),s=-1,c=l.length,u=l[c-1].edge,f=u.l===i?u.r:u.l;++s=c,d=n>=u,h=d<<1|f;t.leaf=!1,t=t.nodes[h]||(t.nodes[h]=pn()),f?a=c:l=c,d?i=u:s=u,o(t,e,r,n,a,i,l,s)}var u,f,d,h,p,g,m,v,y,x=zt(l),b=zt(s);if(null!=e)g=e,m=r,v=n,y=a;else if(v=y=-(g=m=1/0),f=[],d=[],p=t.length,i)for(h=0;hv&&(v=u.x),u.y>y&&(y=u.y),f.push(u.x),d.push(u.y);else for(h=0;hv&&(v=_),w>y&&(y=w),f.push(_),d.push(w)}var k=v-g,M=y-m;k>M?y=m+k:v=g+M;var A=pn();if(A.add=function(t){o(A,t,+x(t,++h),+b(t,h),g,m,v,y)},A.visit=function(t){gn(t,A,g,m,v,y)},A.find=function(t){return mn(A,t[0],t[1],g,m,v,y)},h=-1,null==e){for(;++h=0?t.slice(0,e):t,n=e>=0?t.slice(e+1):"in";return r=gs.get(r)||ps,n=ms.get(n)||b,kn(n(r.apply(null,fi.call(arguments,1))))},ui.interpolateHcl=In,ui.interpolateHsl=Rn,ui.interpolateLab=Fn,ui.interpolateRound=jn,ui.transform=function(t){var e=hi.createElementNS(ui.ns.prefix.svg,"g");return(ui.transform=function(t){if(null!=t){e.setAttribute("transform",t);var r=e.transform.baseVal.consolidate()}return new qn(r?r.matrix:vs)})(t)},qn.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"; -};var vs={a:1,b:0,c:0,d:1,e:0,f:0};ui.interpolateTransform=Wn,ui.layout={},ui.layout.bundle=function(){return function(t){for(var e=[],r=-1,n=t.length;++r0?a=t:(r.c=null,r.t=NaN,r=null,c.end({type:"end",alpha:a=0})):t>0&&(c.start({type:"start",alpha:a=t}),r=Pt(s.tick)),s):a},s.start=function(){function t(t,n){if(!r){for(r=new Array(a),s=0;s=0;)i.push(u=c[s]),u.parent=o,u.depth=o.depth+1;n&&(o.value=0),o.children=c}else n&&(o.value=+n.call(t,o,o.depth)||0),delete o.children;return sa(a,function(t){var r,a;e&&(r=t.children)&&r.sort(e),n&&(a=t.parent)&&(a.value+=t.value)}),l}var e=fa,r=ca,n=ua;return t.sort=function(r){return arguments.length?(e=r,t):e},t.children=function(e){return arguments.length?(r=e,t):r},t.value=function(e){return arguments.length?(n=e,t):n},t.revalue=function(e){return n&&(la(e,function(t){t.children&&(t.value=0)}),sa(e,function(e){var r;e.children||(e.value=+n.call(t,e,e.depth)||0),(r=e.parent)&&(r.value+=e.value)})),e},t},ui.layout.partition=function(){function t(e,r,n,a){var o=e.children;if(e.x=r,e.y=e.depth*a,e.dx=n,e.dy=a,o&&(i=o.length)){var i,l,s,c=-1;for(n=e.value?n/e.value:0;++cl&&(l=n),i.push(n)}for(r=0;r0)for(o=-1;++o=u[0]&&l<=u[1]&&(i=s[ui.bisect(f,l,1,h)-1],i.y+=p,i.push(t[o]));return s}var e=!0,r=Number,n=ka,a=_a;return t.value=function(e){return arguments.length?(r=e,t):r},t.range=function(e){return arguments.length?(n=zt(e),t):n},t.bins=function(e){return arguments.length?(a="number"==typeof e?function(t){return wa(t,e)}:zt(e),t):a},t.frequency=function(r){return arguments.length?(e=!!r,t):e},t},ui.layout.pack=function(){function t(t,o){var i=r.call(this,t,o),l=i[0],s=a[0],c=a[1],u=null==e?Math.sqrt:"function"==typeof e?e:function(){return e};if(l.x=l.y=0,sa(l,function(t){t.r=+u(t.value)}),sa(l,za),n){var f=n*(e?1:Math.max(2*l.r/s,2*l.r/c))/2;sa(l,function(t){t.r+=f}),sa(l,za),sa(l,function(t){t.r-=f})}return Oa(l,s/2,c/2,e?1:1/Math.max(2*l.r/s,2*l.r/c)),i}var e,r=ui.layout.hierarchy().sort(Ma),n=0,a=[1,1];return t.size=function(e){return arguments.length?(a=e,t):a},t.radius=function(r){return arguments.length?(e=null==r||"function"==typeof r?r:+r,t):e},t.padding=function(e){return arguments.length?(n=+e,t):n},ia(t,r)},ui.layout.tree=function(){function t(t,a){var u=i.call(this,t,a),f=u[0],d=e(f);if(sa(d,r),d.parent.m=-d.z,la(d,n),c)la(f,o);else{var h=f,p=f,g=f;la(f,function(t){t.xp.x&&(p=t),t.depth>g.depth&&(g=t)});var m=l(h,p)/2-h.x,v=s[0]/(p.x+l(p,h)/2+m),y=s[1]/(g.depth||1);la(f,function(t){t.x=(t.x+m)*v,t.y=t.depth*y})}return u}function e(t){for(var e,r={A:null,children:[t]},n=[r];null!=(e=n.pop());)for(var a,o=e.children,i=0,l=o.length;i0&&(Ia(Fa(i,t,r),t,n),c+=n,u+=n),f+=i.m,c+=a.m,d+=s.m,u+=o.m;i&&!Ea(o)&&(o.t=i,o.m+=f-u),a&&!Na(s)&&(s.t=a,s.m+=c-d,r=t)}return r}function o(t){t.x*=s[0],t.y=t.depth*s[1]}var i=ui.layout.hierarchy().sort(null).value(null),l=Pa,s=[1,1],c=null;return t.separation=function(e){return arguments.length?(l=e,t):l},t.size=function(e){return arguments.length?(c=null==(s=e)?o:null,t):c?null:s},t.nodeSize=function(e){return arguments.length?(c=null==(s=e)?null:o,t):c?s:null},ia(t,i)},ui.layout.cluster=function(){function t(t,o){var i,l=e.call(this,t,o),s=l[0],c=0;sa(s,function(t){var e=t.children;e&&e.length?(t.x=qa(e),t.y=ja(e)):(t.x=i?c+=r(t,i):0,t.y=0,i=t)});var u=Ba(s),f=Ha(s),d=u.x-r(u,f)/2,h=f.x+r(f,u)/2;return sa(s,a?function(t){t.x=(t.x-s.x)*n[0],t.y=(s.y-t.y)*n[1]}:function(t){t.x=(t.x-d)/(h-d)*n[0],t.y=(1-(s.y?t.y/s.y:1))*n[1]}),l}var e=ui.layout.hierarchy().sort(null).value(null),r=Pa,n=[1,1],a=!1;return t.separation=function(e){return arguments.length?(r=e,t):r},t.size=function(e){return arguments.length?(a=null==(n=e),t):a?null:n},t.nodeSize=function(e){return arguments.length?(a=null!=(n=e),t):a?n:null},ia(t,e)},ui.layout.treemap=function(){function t(t,e){for(var r,n,a=-1,o=t.length;++a0;)u.push(i=d[s-1]),u.area+=i.area,"squarify"!==h||(l=n(u,g))<=p?(d.pop(),p=l):(u.area-=u.pop().area,a(u,g,c,!1),g=Math.min(c.dx,c.dy),u.length=u.area=0,p=1/0);u.length&&(a(u,g,c,!0),u.length=u.area=0),o.forEach(e)}}function r(e){var n=e.children;if(n&&n.length){var o,i=f(e),l=n.slice(),s=[];for(t(l,i.dx*i.dy/e.value),s.area=0;o=l.pop();)s.push(o),s.area+=o.area,null!=o.z&&(a(s,o.z?i.dx:i.dy,i,!l.length),s.length=s.area=0);n.forEach(r)}}function n(t,e){for(var r,n=t.area,a=0,o=1/0,i=-1,l=t.length;++ia&&(a=r));return n*=n,e*=e,n?Math.max(e*a*p/n,n/(e*o*p)):1/0}function a(t,e,r,n){var a,o=-1,i=t.length,l=r.x,c=r.y,u=e?s(t.area/e):0;if(e==r.dx){for((n||u>r.dy)&&(u=r.dy);++or.dx)&&(u=r.dx);++o1);return t+e*r*Math.sqrt(-2*Math.log(a)/a)}},logNormal:function(){var t=ui.random.normal.apply(ui,arguments);return function(){return Math.exp(t())}},bates:function(t){var e=ui.random.irwinHall(t);return function(){return e()/t}},irwinHall:function(t){return function(){for(var e=0,r=0;rf?0:1;if(c=Bi)return e(c,h)+(t?e(t,1-h):"")+"Z";var p,g,m,v,y,x,b,_,w,k,M,A,T=0,L=0,z=[];if((v=(+s.apply(this,arguments)||0)/2)&&(m=o===Ds?Math.sqrt(t*t+c*c):+o.apply(this,arguments),h||(L*=-1),c&&(L=nt(m/c*Math.sin(v))),t&&(T=nt(m/t*Math.sin(v)))),c){y=c*Math.cos(u+L),x=c*Math.sin(u+L),b=c*Math.cos(f-L),_=c*Math.sin(f-L);var C=Math.abs(f-u-2*L)<=ji?0:1;if(L&&bo(y,x,b,_)===h^C){var S=(u+f)/2;y=c*Math.cos(S),x=c*Math.sin(S),b=_=null}}else y=x=0;if(t){w=t*Math.cos(f-T),k=t*Math.sin(f-T),M=t*Math.cos(u+T),A=t*Math.sin(u+T);var O=Math.abs(u-f+2*T)<=ji?0:1;if(T&&bo(w,k,M,A)===1-h^O){var D=(u+f)/2;w=t*Math.cos(D),k=t*Math.sin(D),M=A=null}}else w=k=0;if(d>Ri&&(p=Math.min(Math.abs(c-t)/2,+a.apply(this,arguments)))>.001){g=tji)+",1 "+e}function a(t,e,r,n){return"Q 0,0 "+n}var o=br,i=_r,l=Xo,s=vo,c=yo;return t.radius=function(e){return arguments.length?(l=zt(e),t):l},t.source=function(e){return arguments.length?(o=zt(e),t):o},t.target=function(e){return arguments.length?(i=zt(e),t):i},t.startAngle=function(e){return arguments.length?(s=zt(e),t):s},t.endAngle=function(e){return arguments.length?(c=zt(e),t):c},t},ui.svg.diagonal=function(){function t(t,a){var o=e.call(this,t,a),i=r.call(this,t,a),l=(o.y+i.y)/2,s=[o,{x:o.x,y:l},{x:i.x,y:l},i];return s=s.map(n),"M"+s[0]+"C"+s[1]+" "+s[2]+" "+s[3]}var e=br,r=_r,n=Uo;return t.source=function(r){return arguments.length?(e=zt(r),t):e},t.target=function(e){return arguments.length?(r=zt(e),t):r},t.projection=function(e){return arguments.length?(n=e,t):n},t},ui.svg.diagonal.radial=function(){var t=ui.svg.diagonal(),e=Uo,r=t.projection;return t.projection=function(t){return arguments.length?r(Yo(e=t)):e},t},ui.svg.symbol=function(){function t(t,n){return(Rs.get(e.call(this,t,n))||Qo)(r.call(this,t,n))}var e=Wo,r=Go;return t.type=function(r){return arguments.length?(e=zt(r),t):e},t.size=function(e){return arguments.length?(r=zt(e),t):r},t};var Rs=ui.map({circle:Qo,cross:function(t){var e=Math.sqrt(t/5)/2;return"M"+-3*e+","+-e+"H"+-e+"V"+-3*e+"H"+e+"V"+-e+"H"+3*e+"V"+e+"H"+e+"V"+3*e+"H"+-e+"V"+e+"H"+-3*e+"Z"},diamond:function(t){var e=Math.sqrt(t/(2*js)),r=e*js;return"M0,"+-e+"L"+r+",0 0,"+e+" "+-r+",0Z"},square:function(t){var e=Math.sqrt(t)/2;return"M"+-e+","+-e+"L"+e+","+-e+" "+e+","+e+" "+-e+","+e+"Z"},"triangle-down":function(t){var e=Math.sqrt(t/Fs),r=e*Fs/2;return"M0,"+r+"L"+e+","+-r+" "+-e+","+-r+"Z"},"triangle-up":function(t){var e=Math.sqrt(t/Fs),r=e*Fs/2;return"M0,"+-r+"L"+e+","+r+" "+-e+","+r+"Z"}});ui.svg.symbolTypes=Rs.keys();var Fs=Math.sqrt(3),js=Math.tan(30*Vi);Ci.transition=function(t){for(var e,r,n=qs||++Zs,a=ei(t),o=[],i=Bs||{time:Date.now(),ease:zn,delay:0,duration:250},l=-1,s=this.length;++lrect,.s>rect").attr("width",f[1]-f[0])}function a(t){t.select(".extent").attr("y",d[0]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",d[1]-d[0])}function o(){function o(){32==ui.event.keyCode&&(C||(x=null,O[0]-=f[1],O[1]-=d[1],C=2),T())}function g(){32==ui.event.keyCode&&2==C&&(O[0]+=f[1],O[1]+=d[1],C=0,T())}function m(){var t=ui.mouse(_),n=!1;b&&(t[0]+=b[0],t[1]+=b[1]),C||(ui.event.altKey?(x||(x=[(f[0]+f[1])/2,(d[0]+d[1])/2]),O[0]=f[+(t[0]0&&this._events[t].length>r&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace())),this},n.prototype.on=n.prototype.addListener,n.prototype.once=function(t,e){function r(){this.removeListener(t,r),n||(n=!0,e.apply(this,arguments))}if(!a(e))throw TypeError("listener must be a function");var n=!1;return r.listener=e,this.on(t,r),this},n.prototype.removeListener=function(t,e){var r,n,o,l;if(!a(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(r=this._events[t],o=r.length,n=-1,r===e||a(r.listener)&&r.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(i(r)){for(l=o;l-- >0;)if(r[l]===e||r[l].listener&&r[l].listener===e){n=l;break}if(n<0)return this;1===r.length?(r.length=0,delete this._events[t]):r.splice(n,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},n.prototype.removeAllListeners=function(t){var e,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(r=this._events[t],a(r))this.removeListener(t,r);else if(r)for(;r.length;)this.removeListener(t,r[r.length-1]);return delete this._events[t],this},n.prototype.listeners=function(t){var e;return e=this._events&&this._events[t]?a(this._events[t])?[this._events[t]]:this._events[t].slice():[]},n.prototype.listenerCount=function(t){if(this._events){var e=this._events[t];if(a(e))return 1;if(e)return e.length}return 0},n.listenerCount=function(t,e){return t.listenerCount(e)}},{}],17:[function(t,e,r){"use strict";function n(t){for(var e,r=t.length,n=0;n13)&&32!==e&&133!==e&&160!==e&&5760!==e&&6158!==e&&(e<8192||e>8205)&&8232!==e&&8233!==e&&8239!==e&&8287!==e&&8288!==e&&12288!==e&&65279!==e)return!1;return!0}e.exports=function(t){var e=typeof t;if("string"===e){var r=t;if(t=+t,0===t&&n(r))return!1}else if("number"!==e)return!1;return t-t<1}},{}],18:[function(t,e,r){function n(t,e){var r=e[0],n=e[1],a=e[2],o=e[3],i=r+r,l=n+n,s=a+a,c=r*i,u=n*i,f=n*l,d=a*i,h=a*l,p=a*s,g=o*i,m=o*l,v=o*s;return t[0]=1-f-p,t[1]=u+v,t[2]=d-m,t[3]=0,t[4]=u-v,t[5]=1-c-p,t[6]=h+g,t[7]=0,t[8]=d+m,t[9]=h-g,t[10]=1-c-f,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}e.exports=n},{}],19:[function(t,e,r){function n(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function o(t){if(f===setTimeout)return setTimeout(t,0);if((f===n||!f)&&setTimeout)return f=setTimeout,setTimeout(t,0);try{return f(t,0)}catch(e){try{return f.call(null,t,0)}catch(e){return f.call(this,t,0)}}}function i(t){if(d===clearTimeout)return clearTimeout(t);if((d===a||!d)&&clearTimeout)return d=clearTimeout,clearTimeout(t);try{return d(t)}catch(e){try{return d.call(null,t)}catch(e){return d.call(this,t)}}}function l(){m&&p&&(m=!1,p.length?g=p.concat(g):v=-1,g.length&&s())}function s(){if(!m){var t=o(l);m=!0;for(var e=g.length;e;){for(p=g,g=[];++v1)for(var r=1;r.5?s/(2-o-i):s/(o+i),o){case t:n=(e-r)/s+(e1&&(r-=1),r<1/6?t+6*(e-t)*r:r<.5?e:r<2/3?t+(e-t)*(2/3-r)*6:t}var a,o,i;if(t=z(t,360),e=z(e,100),r=z(r,100),0===e)a=o=i=r;else{var l=r<.5?r*(1+e):r+e-r*e,s=2*r-l;a=n(s,l,t+1/3),o=n(s,l,t),i=n(s,l,t-1/3)}return{r:255*a,g:255*o,b:255*i}}function s(t,e,r){t=z(t,255),e=z(e,255),r=z(r,255);var n,a,o=X(t,e,r),i=Z(t,e,r),l=o,s=o-i;if(a=0===o?0:s/o,o==i)n=0;else{switch(o){case t:n=(e-r)/s+(e>1)+720)%360;--e;)a.h=(a.h+o)%360,i.push(n(a));return i}function A(t,e){e=e||6;for(var r=n(t).toHsv(),a=r.h,o=r.s,i=r.v,l=[],s=1/e;e--;)l.push(n({h:a,s:o,v:i})),i=(i+s)%1;return l}function T(t){var e={};for(var r in t)t.hasOwnProperty(r)&&(e[t[r]]=r);return e}function L(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function z(t,r){O(t)&&(t="100%");var n=D(t);return t=Z(r,X(0,parseFloat(t))),n&&(t=parseInt(t*r,10)/100),e.abs(t-r)<1e-6?1:t%r/parseFloat(r)}function C(t){return Z(1,X(0,t))}function S(t){return parseInt(t,16)}function O(t){return"string"==typeof t&&t.indexOf(".")!=-1&&1===parseFloat(t)}function D(t){return"string"==typeof t&&t.indexOf("%")!=-1}function P(t){return 1==t.length?"0"+t:""+t}function N(t){return t<=1&&(t=100*t+"%"),t}function E(t){return e.round(255*parseFloat(t)).toString(16)}function I(t){return S(t)/255}function R(t){return!!W.CSS_UNIT.exec(t)}function F(t){t=t.replace(q,"").replace(B,"").toLowerCase();var e=!1;if(Y[t])t=Y[t],e=!0;else if("transparent"==t)return{r:0,g:0,b:0,a:0,format:"name"};var r;return(r=W.rgb.exec(t))?{r:r[1],g:r[2],b:r[3]}:(r=W.rgba.exec(t))?{r:r[1],g:r[2],b:r[3],a:r[4]}:(r=W.hsl.exec(t))?{h:r[1],s:r[2],l:r[3]}:(r=W.hsla.exec(t))?{h:r[1],s:r[2],l:r[3],a:r[4]}:(r=W.hsv.exec(t))?{h:r[1],s:r[2],v:r[3]}:(r=W.hsva.exec(t))?{h:r[1],s:r[2],v:r[3],a:r[4]}:(r=W.hex8.exec(t))?{r:S(r[1]),g:S(r[2]),b:S(r[3]),a:I(r[4]),format:e?"name":"hex8"}:(r=W.hex6.exec(t))?{r:S(r[1]),g:S(r[2]),b:S(r[3]),format:e?"name":"hex"}:(r=W.hex4.exec(t))?{r:S(r[1]+""+r[1]),g:S(r[2]+""+r[2]),b:S(r[3]+""+r[3]),a:I(r[4]+""+r[4]),format:e?"name":"hex8"}:!!(r=W.hex3.exec(t))&&{r:S(r[1]+""+r[1]),g:S(r[2]+""+r[2]),b:S(r[3]+""+r[3]),format:e?"name":"hex"}}function j(t){var e,r;return t=t||{level:"AA",size:"small"},e=(t.level||"AA").toUpperCase(),r=(t.size||"small").toLowerCase(),"AA"!==e&&"AAA"!==e&&(e="AA"),"small"!==r&&"large"!==r&&(r="small"),{level:e,size:r}}var q=/^\s+/,B=/\s+$/,H=0,V=e.round,Z=e.min,X=e.max,U=e.random;n.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var t,r,n,a,o,i,l=this.toRgb();return t=l.r/255,r=l.g/255,n=l.b/255,a=t<=.03928?t/12.92:e.pow((t+.055)/1.055,2.4),o=r<=.03928?r/12.92:e.pow((r+.055)/1.055,2.4),i=n<=.03928?n/12.92:e.pow((n+.055)/1.055,2.4),.2126*a+.7152*o+.0722*i},setAlpha:function(t){return this._a=L(t),this._roundA=V(100*this._a)/100,this},toHsv:function(){var t=s(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=s(this._r,this._g,this._b),e=V(360*t.h),r=V(100*t.s),n=V(100*t.v);return 1==this._a?"hsv("+e+", "+r+"%, "+n+"%)":"hsva("+e+", "+r+"%, "+n+"%, "+this._roundA+")"},toHsl:function(){var t=i(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=i(this._r,this._g,this._b),e=V(360*t.h),r=V(100*t.s),n=V(100*t.l);return 1==this._a?"hsl("+e+", "+r+"%, "+n+"%)":"hsla("+e+", "+r+"%, "+n+"%, "+this._roundA+")"},toHex:function(t){return u(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return f(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:V(this._r),g:V(this._g),b:V(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+V(this._r)+", "+V(this._g)+", "+V(this._b)+")":"rgba("+V(this._r)+", "+V(this._g)+", "+V(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:V(100*z(this._r,255))+"%",g:V(100*z(this._g,255))+"%",b:V(100*z(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+V(100*z(this._r,255))+"%, "+V(100*z(this._g,255))+"%, "+V(100*z(this._b,255))+"%)":"rgba("+V(100*z(this._r,255))+"%, "+V(100*z(this._g,255))+"%, "+V(100*z(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(G[u(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var e="#"+d(this._r,this._g,this._b,this._a),r=e,a=this._gradientType?"GradientType = 1, ":"";if(t){var o=n(t);r="#"+d(o._r,o._g,o._b,o._a)}return"progid:DXImageTransform.Microsoft.gradient("+a+"startColorstr="+e+",endColorstr="+r+")"},toString:function(t){var e=!!t;t=t||this._format;var r=!1,n=this._a<1&&this._a>=0,a=!e&&n&&("hex"===t||"hex6"===t||"hex3"===t||"hex4"===t||"hex8"===t||"name"===t);return a?"name"===t&&0===this._a?this.toName():this.toRgbString():("rgb"===t&&(r=this.toRgbString()),"prgb"===t&&(r=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(r=this.toHexString()),"hex3"===t&&(r=this.toHexString(!0)),"hex4"===t&&(r=this.toHex8String(!0)),"hex8"===t&&(r=this.toHex8String()),"name"===t&&(r=this.toName()),"hsl"===t&&(r=this.toHslString()),"hsv"===t&&(r=this.toHsvString()),r||this.toHexString())},clone:function(){return n(this.toString())},_applyModification:function(t,e){var r=t.apply(null,[this].concat([].slice.call(e)));return this._r=r._r,this._g=r._g,this._b=r._b,this.setAlpha(r._a),this},lighten:function(){return this._applyModification(m,arguments)},brighten:function(){return this._applyModification(v,arguments)},darken:function(){return this._applyModification(y,arguments)},desaturate:function(){return this._applyModification(h,arguments)},saturate:function(){return this._applyModification(p,arguments)},greyscale:function(){return this._applyModification(g,arguments)},spin:function(){return this._applyModification(x,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(M,arguments)},complement:function(){return this._applyCombination(b,arguments)},monochromatic:function(){return this._applyCombination(A,arguments)},splitcomplement:function(){return this._applyCombination(k,arguments)},triad:function(){return this._applyCombination(_,arguments)},tetrad:function(){return this._applyCombination(w,arguments)}},n.fromRatio=function(t,e){if("object"==typeof t){var r={};for(var a in t)t.hasOwnProperty(a)&&("a"===a?r[a]=t[a]:r[a]=N(t[a]));t=r}return n(t,e)},n.equals=function(t,e){return!(!t||!e)&&n(t).toRgbString()==n(e).toRgbString()},n.random=function(){return n.fromRatio({r:U(),g:U(),b:U()})},n.mix=function(t,e,r){r=0===r?0:r||50;var a=n(t).toRgb(),o=n(e).toRgb(),i=r/100,l={r:(o.r-a.r)*i+a.r,g:(o.g-a.g)*i+a.g,b:(o.b-a.b)*i+a.b,a:(o.a-a.a)*i+a.a};return n(l)},n.readability=function(t,r){var a=n(t),o=n(r);return(e.max(a.getLuminance(),o.getLuminance())+.05)/(e.min(a.getLuminance(),o.getLuminance())+.05)},n.isReadable=function(t,e,r){var a,o,i=n.readability(t,e);switch(o=!1,a=j(r),a.level+a.size){case"AAsmall":case"AAAlarge":o=i>=4.5;break;case"AAlarge":o=i>=3;break;case"AAAsmall":o=i>=7}return o},n.mostReadable=function(t,e,r){var a,o,i,l,s=null,c=0;r=r||{},o=r.includeFallbackColors,i=r.level,l=r.size;for(var u=0;uc&&(c=a,s=n(e[u]));return n.isReadable(t,s,{level:i,size:l})||!o?s:(r.includeFallbackColors=!1,n.mostReadable(t,["#fff","#000"],r))};var Y=n.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},G=n.hexNames=T(Y),W=function(){var t="[-\\+]?\\d+%?",e="[-\\+]?\\d*\\.\\d+%?",r="(?:"+e+")|(?:"+t+")",n="[\\s|\\(]+("+r+")[,|\\s]+("+r+")[,|\\s]+("+r+")\\s*\\)?",a="[\\s|\\(]+("+r+")[,|\\s]+("+r+")[,|\\s]+("+r+")[,|\\s]+("+r+")\\s*\\)?";return{CSS_UNIT:new RegExp(r),rgb:new RegExp("rgb"+n),rgba:new RegExp("rgba"+a),hsl:new RegExp("hsl"+n),hsla:new RegExp("hsla"+a),hsv:new RegExp("hsv"+n),hsva:new RegExp("hsva"+a),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof r&&r.exports?r.exports=n:"function"==typeof t&&t.amd?t(function(){return n}):window.tinycolor=n}(Math)},{}],21:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("../color"),o=t("../../plots/cartesian/axes"),i=t("./attributes");e.exports=function(t,e,r,l,s){function c(r,a){return n.coerce(t,e,i,r,a); -}l=l||{},s=s||{};var u=c("visible",!s.itemIsNotPlainObject);if(!u)return e;c("opacity"),c("align"),c("bgcolor");var f=c("bordercolor"),d=a.opacity(f);c("borderpad");var h=c("borderwidth"),p=c("showarrow");c("text",p?" ":"new text"),c("textangle"),n.coerceFont(c,"font",r.font);for(var g=["x","y"],m=[-10,-30],v={_fullLayout:r},y=0;y<2;y++){var x=g[y],b=o.coerceRef(t,e,v,x,"","paper");if(o.coercePosition(e,v,c,b,x,.5),p){var _="a"+x,w=o.coerceRef(t,e,v,_,"pixel");"pixel"!==w&&w!==b&&(w=e[_]="pixel");var k="pixel"===w?m[y]:.4;o.coercePosition(e,v,c,w,_,k)}else c(x+"anchor")}return n.noneOrAll(t,e,["x","y"]),p&&(c("arrowcolor",d?e.bordercolor:a.defaultLine),c("arrowhead"),c("arrowsize"),c("arrowwidth",2*(d&&h||1)),n.noneOrAll(t,e,["ax","ay"])),t.classes&&(e.classes=t.classes),e}},{"../../lib":122,"../../plots/cartesian/axes":149,"../color":30,"./attributes":23}],22:[function(t,e,r){"use strict";e.exports=["",{path:"M-2.4,-3V3L0.6,0Z",backoff:.6},{path:"M-3.7,-2.5V2.5L1.3,0Z",backoff:1.3},{path:"M-4.45,-3L-1.65,-0.2V0.2L-4.45,3L1.55,0Z",backoff:1.55},{path:"M-2.2,-2.2L-0.2,-0.2V0.2L-2.2,2.2L-1.4,3L1.6,0L-1.4,-3Z",backoff:1.6},{path:"M-4.4,-2.1L-0.6,-0.2V0.2L-4.4,2.1L-4,3L2,0L-4,-3Z",backoff:2},{path:"M2,0A2,2 0 1,1 0,-2A2,2 0 0,1 2,0Z",backoff:0},{path:"M2,2V-2H-2V2Z",backoff:0}]},{}],23:[function(t,e,r){"use strict";var n=t("./arrow_paths"),a=t("../../plots/font_attributes"),o=t("../../plots/cartesian/constants"),i=t("../../lib/extend").extendFlat;e.exports={_isLinkedToArray:"annotation",visible:{valType:"boolean",dflt:!0},text:{valType:"string"},textangle:{valType:"angle",dflt:0},font:i({},a,{}),opacity:{valType:"number",min:0,max:1,dflt:1},align:{valType:"enumerated",values:["left","center","right"],dflt:"center"},bgcolor:{valType:"color",dflt:"rgba(0,0,0,0)"},bordercolor:{valType:"color",dflt:"rgba(0,0,0,0)"},borderpad:{valType:"number",min:0,dflt:1},borderwidth:{valType:"number",min:0,dflt:1},showarrow:{valType:"boolean",dflt:!0},arrowcolor:{valType:"color"},arrowhead:{valType:"integer",min:0,max:n.length,dflt:1},arrowsize:{valType:"number",min:.3,dflt:1},arrowwidth:{valType:"number",min:.1},ax:{valType:"any"},ay:{valType:"any"},axref:{valType:"enumerated",dflt:"pixel",values:["pixel",o.idRegex.x.toString()]},ayref:{valType:"enumerated",dflt:"pixel",values:["pixel",o.idRegex.y.toString()]},xref:{valType:"enumerated",values:["paper",o.idRegex.x.toString()]},x:{valType:"any"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"auto"},yref:{valType:"enumerated",values:["paper",o.idRegex.y.toString()]},y:{valType:"any"},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"auto"},_deprecated:{ref:{valType:"string"}}}},{"../../lib/extend":119,"../../plots/cartesian/constants":154,"../../plots/font_attributes":169,"./arrow_paths":22}],24:[function(t,e,r){"use strict";function n(t){var e=t._fullLayout;e.annotations.forEach(function(e){var r=o.getFromId(t,e.xref),n=o.getFromId(t,e.yref);if(r||n){var a=(e._xsize||0)/2,i=e._xshift||0,l=(e._ysize||0)/2,s=e._yshift||0,c=a-i,u=a+i,f=l-s,d=l+s;if(e.showarrow){var h=3*e.arrowsize*e.arrowwidth;c=Math.max(c,h),u=Math.max(u,h),f=Math.max(f,h),d=Math.max(d,h)}r&&r.autorange&&o.expand(r,[r.l2c(r.r2l(e.x))],{ppadplus:u,ppadminus:c}),n&&n.autorange&&o.expand(n,[n.l2c(n.r2l(e.y))],{ppadplus:d,ppadminus:f})}})}var a=t("../../lib"),o=t("../../plots/cartesian/axes"),i=t("./draw").draw;e.exports=function(t){var e=t._fullLayout,r=a.filterVisible(e.annotations);if(r.length&&t._fullData.length){var l={};r.forEach(function(t){l[t.xref]=!0,l[t.yref]=!0});var s=o.list(t).filter(function(t){return t.autorange&&l[t._id]});if(s.length)return a.syncOrAsync([i,n],t)}}},{"../../lib":122,"../../plots/cartesian/axes":149,"./draw":26}],25:[function(t,e,r){"use strict";var n=t("../../plots/array_container_defaults"),a=t("./annotation_defaults");e.exports=function(t,e){var r={name:"annotations",handleItemDefaults:a};n(t,e,r)}},{"../../plots/array_container_defaults":146,"./annotation_defaults":21}],26:[function(t,e,r){"use strict";function n(t){var e=t._fullLayout;e._infolayer.selectAll(".annotation").remove();for(var r=0;r2/3?"right":"center"),{center:0,middle:0,left:.5,bottom:-.5,right:-.5,top:.5}[e]}nt.selectAll("tspan.line").attr({y:0,x:0});var n=$.select(".annotation-math-group"),a=!n.empty(),l=h.bBox((a?n:nt).node()),c=l.width,p=l.height,v=Math.round(c+2*tt),y=Math.round(p+2*tt);Z._w=c,Z._h=p;var b=!1;if(["x","y"].forEach(function(e){var n,a=Z[e+"ref"]||e,o=f.getFromId(t,a),i=(G+("x"===e?0:90))*Math.PI/180,l=v*Math.abs(Math.cos(i))+y*Math.abs(Math.sin(i)),s=Z[e+"anchor"];if(o){var c=o.r2fraction(Z[e]);if(!o.autorange&&(c<0||c>1)&&(Z["a"+e+"ref"]===a?(c=o.r2fraction(Z["a"+e]),(c<0||c>1)&&(b=!0)):b=!0,b))return;Y[e]=o._offset+o.r2p(Z[e]),n=.5}else n=Z[e],"y"===e&&(n=1-n),Y[e]="x"===e?O.l+O.w*n:O.t+O.h*n;var u=0;Z["a"+e+"ref"]===a?Y["aa"+e]=o._offset+o.r2p(Z["a"+e]):(u=Z.showarrow?Z["a"+e]:l*r(n,s),Y[e]+=u),Z["_"+e+"type"]=o&&o.type,Z["_"+e+"size"]=l,Z["_"+e+"shift"]=u}),b)return void $.remove();var _,w;Z.showarrow&&(_=Z.axref===Z.xref?Y.x:u.constrain(Y.x-Z.ax,1,M.width-1),w=Z.ayref===Z.yref?Y.y:u.constrain(Y.y-Z.ay,1,M.height-1)),Y.x=u.constrain(Y.x,1,M.width-1),Y.y=u.constrain(Y.y,1,M.height-1);var k=tt-l.top,A=tt-l.left;a?n.select("svg").attr({x:tt-1,y:tt}):(nt.attr({x:A,y:k}),nt.selectAll("tspan.line").attr({y:k,x:A})),et.call(h.setRect,J/2,J/2,v-J,y-J);var T=0,L=0;T=Z.axref===Z.xref?Math.round(Y.aax-v/2):Math.round(Y.x-v/2),L=Z.ayref===Z.yref?Math.round(Y.aay-y/2):Math.round(Y.y-y/2),$.call(u.setTranslate,T,L);var z="annotations["+e+"]",C=function(r,n){i.select(t).selectAll('.annotation-arrow-g[data-index="'+e+'"]').remove();var a,l;a=Z.axref===Z.xref?Y.aax+r:Y.x+r,l=Z.ayref===Z.yref?Y.aay+n:Y.y+n;var c=u.rotationXYMatrix(G,a,l),f=u.apply2DTransform(c),h=u.apply2DTransform2(c),p=et.attr("width")/2,g=et.attr("height")/2,v=[[a-p,l-g,a-p,l+g],[a-p,l+g,a+p,l+g],[a+p,l+g,a+p,l-g],[a+p,l-g,a-p,l-g]].map(h);if(!v.reduce(function(t,e){return t^!!o(_,w,_+1e6,w+1e6,e[0],e[1],e[2],e[3])},!1)){v.forEach(function(t){var e=o(a,l,_,w,t[0],t[1],t[2],t[3]);e&&(a=e.x,l=e.y)});var y=Z.arrowwidth,b=Z.arrowcolor,k=W.append("g").style({opacity:d.opacity(b)}).classed("annotation-arrow-g",!0).attr("data-index",String(e)),M=k.append("path").attr("d","M"+a+","+l+"L"+_+","+w).style("stroke-width",y+"px").call(d.stroke,d.rgb(b));x(M,Z.arrowhead,"end",Z.arrowsize);var A=k.append("path").classed("annotation",!0).classed("anndrag",!0).attr({"data-index":String(e),d:"M3,3H-3V-3H3ZM0,0L"+(a-_)+","+(l-w),transform:"translate("+_+","+w+")"}).style("stroke-width",y+6+"px").call(d.stroke,"rgba(0,0,0,0)").call(d.fill,"rgba(0,0,0,0)");if(t._context.editable){var T,L,C;m.init({element:A.node(),prepFn:function(){var t=u.getTranslate($);L=t.x,C=t.y,T={},X&&X.autorange&&(T[X._name+".autorange"]=!0),U&&U.autorange&&(T[U._name+".autorange"]=!0)},moveFn:function(t,e){k.attr("transform","translate("+t+","+e+")");var r=f(L,C),n=r[0]+t,a=r[1]+e;$.call(u.setTranslate,n,a),T[z+".x"]=X?X.p2r(X.r2p(Z.x)+t):(_+t-O.l)/O.w,T[z+".y"]=U?U.p2r(U.r2p(Z.y)+e):1-(w+e-O.t)/O.h,Z.axref===Z.xref&&(T[z+".ax"]=X?X.p2r(X.r2p(Z.ax)+t):(_+t-O.l)/O.w),Z.ayref===Z.yref&&(T[z+".ay"]=U?U.p2r(U.r2p(Z.ay)+e):1-(w+e-O.t)/O.h),Q.attr({transform:"rotate("+G+","+n+","+a+")"})},doneFn:function(e){if(e){s.relayout(t,T);var r=document.querySelector(".js-notes-box-panel");r&&r.redraw(r.selectedObj)}}})}}};Z.showarrow&&C(0,0);var S=u.rotationXYMatrix(G,Y.x,Y.y),D=u.apply2DTransform(S);if(t._context.editable){var P,N,E;m.init({element:$.node(),prepFn:function(){var t=u.getTranslate($);P=t.x,N=t.y,E={}},moveFn:function(t,e){$.call(u.setTranslate,P+t,N+e);var r="pointer";if(Z.showarrow)Z.axref===Z.xref?E[z+".ax"]=X.p2r(X.r2p(Z.ax)+t):E[z+".ax"]=Z.ax+t,Z.ayref===Z.yref?E[z+".ay"]=U.p2r(U.r2p(Z.ay)+e):E[z+".ay"]=Z.ay+e,C(t,e);else{if(X)E[z+".x"]=Z.x+t/X._m;else{var n=Z._xsize/O.w,a=Z.x+Z._xshift/O.w-n/2;E[z+".x"]=m.align(a+t/O.w,n,0,1,Z.xanchor)}if(U)E[z+".y"]=Z.y+e/U._m;else{var o=Z._ysize/O.h,i=Z.y-Z._yshift/O.h-o/2;E[z+".y"]=m.align(i-e/O.h,o,0,1,Z.yanchor)}X&&U||(r=m.getCursor(X?.5:E[z+".x"],U?.5:E[z+".y"],Z.xanchor,Z.yanchor))}var l=D(P,N),s=l[0]+t,c=l[1]+e;$.call(u.setTranslate,P+t,N+e),Q.attr({transform:"rotate("+G+","+s+","+c+")"}),g($,r)},doneFn:function(e){if(g($),e){s.relayout(t,E);var r=document.querySelector(".js-notes-box-panel");r&&r.redraw(r.selectedObj)}}})}}var w,k=t.layout,M=t._fullLayout;if(!l(e)||e===-1){if(!e&&Array.isArray(c))return k.annotations=c,y(k,M),void n(t);if("remove"===c)return delete k.annotations,M.annotations=[],void n(t);if(r&&"add"!==c){for(w=0;we;w--)M._infolayer.selectAll('.annotation[data-index="'+(w-1)+'"]').attr("data-index",String(w)),a(t,w)}}M._infolayer.selectAll('.annotation[data-index="'+e+'"]').remove();var T=k.annotations[e],L=M.annotations[e];if(T){var z={};"string"==typeof r&&r?z[r]=c:u.isPlainObject(r)&&(z=r);var C=Object.keys(z);for(w=0;w4/3&&(R=H)}}else I&&(j&&(R<1/3?R+=B:R>2/3&&(R-=B)),R=(R-I.domain[0])/(I.domain[1]-I.domain[0]),R=I.fraction2r(R))}I&&I===E&&F&&("log"===F&&"log"!==I.type?R=Math.pow(10,R):"log"!==F&&"log"===I.type&&(R=R>0?Math.log(R)/Math.LN10:void 0)),T[N]=R}}var Z={};v(T,Z,M),M.annotations[e]=Z;var X=f.getFromId(t,Z.xref),U=f.getFromId(t,Z.yref),Y={x:0,y:0},G=+Z.textangle||0,W=M._infolayer.append("g").classed("annotation",!0).attr("data-index",String(e)).style("opacity",Z.opacity).on("click",function(){t._dragging=!1,t.emit("plotly_clickannotation",{index:e,annotation:T,fullAnnotation:Z})});Z.classes&&W.classed(Z.classes,!0);var Q=W.append("g").classed("annotation-text-g",!0).attr("data-index",String(e)),$=Q.append("g"),J=Z.borderwidth,K=Z.borderpad,tt=J+K,et=$.append("rect").attr("class","bg").style("stroke-width",J+"px").call(d.stroke,Z.bordercolor).call(d.fill,Z.bgcolor),rt=Z.font,nt=$.append("text").classed("annotation",!0).attr("data-unformatted",Z.text).text(Z.text);t._context.editable?nt.call(p.makeEditable,$).call(b).on("edit",function(r){Z.text=r,this.attr({"data-unformatted":Z.text}),this.call(b);var n={};n["annotations["+e+"].text"]=Z.text,X&&X.autorange&&(n[X._name+".autorange"]=!0),U&&U.autorange&&(n[U._name+".autorange"]=!0),s.relayout(t,n)}):nt.call(b),Q.attr({transform:"rotate("+G+","+Y.x+","+Y.y+")"}).call(h.setPosition,Y.x,Y.y)}}}function o(t,e,r,n,a,o,i,l){var s=r-t,c=a-t,u=i-a,f=n-e,d=o-e,h=l-o,p=s*h-u*f;if(0===p)return null;var g=(c*h-u*d)/p,m=(c*f-s*d)/p;return m<0||m>1||g<0||g>1?null:{x:t+s*g,y:e+f*g}}var i=t("d3"),l=t("fast-isnumeric"),s=t("../../plotly"),c=t("../../plots/plots"),u=t("../../lib"),f=t("../../plots/cartesian/axes"),d=t("../color"),h=t("../drawing"),p=t("../../lib/svg_text_utils"),g=t("../../lib/setcursor"),m=t("../dragelement"),v=t("./annotation_defaults"),y=t("./defaults"),x=t("./draw_arrow_head");e.exports={draw:n,drawOne:a}},{"../../lib":122,"../../lib/setcursor":132,"../../lib/svg_text_utils":134,"../../plotly":144,"../../plots/cartesian/axes":149,"../../plots/plots":173,"../color":30,"../dragelement":51,"../drawing":53,"./annotation_defaults":21,"./defaults":25,"./draw_arrow_head":27,d3:14,"fast-isnumeric":17}],27:[function(t,e,r){"use strict";var n=t("d3"),a=t("fast-isnumeric"),o=t("../color"),i=t("../drawing"),l=t("./arrow_paths");e.exports=function(t,e,r,s){a(s)||(s=1);var c=t.node(),u=l[e||0];if(u){"string"==typeof r&&r||(r="end");var f,d,h,p,g=(i.getPx(t,"stroke-width")||1)*s,m=t.style("stroke")||o.defaultLine,v=t.style("stroke-opacity")||1,y=r.indexOf("start")>=0,x=r.indexOf("end")>=0,b=u.backoff*g;if("line"===c.nodeName){if(f={x:+t.attr("x1"),y:+t.attr("y1")},d={x:+t.attr("x2"),y:+t.attr("y2")},h=Math.atan2(f.y-d.y,f.x-d.x),p=h+Math.PI,b){var _=b*Math.cos(h),w=b*Math.sin(h);y&&(f.x-=_,f.y-=w,t.attr({x1:f.x,y1:f.y})),x&&(d.x+=_,d.y+=w,t.attr({x2:d.x,y2:d.y}))}}else if("path"===c.nodeName){var k=c.getTotalLength(),M="";if(y){var A=c.getPointAtLength(0),T=c.getPointAtLength(.1);h=Math.atan2(A.y-T.y,A.x-T.x),f=c.getPointAtLength(Math.min(b,k)),b&&(M="0px,"+b+"px,")}if(x){var L=c.getPointAtLength(k),z=c.getPointAtLength(k-.1);if(p=Math.atan2(L.y-z.y,L.x-z.x),d=c.getPointAtLength(Math.max(0,k-b)),b){var C=M?2*b:b;M+=k-C+"px,"+k+"px"}}else M&&(M+=k+"px");M&&t.style("stroke-dasharray",M)}var S=function(r,a){e>5&&(a=0),n.select(c.parentElement).append("path").attr({class:t.attr("class"),d:u.path,transform:"translate("+r.x+","+r.y+")rotate("+180*a/Math.PI+")scale("+g+")"}).style({fill:m,opacity:v,"stroke-width":0})};y&&S(f,h),x&&S(d,p)}}},{"../color":30,"../drawing":53,"./arrow_paths":22,d3:14,"fast-isnumeric":17}],28:[function(t,e,r){"use strict";var n=t("./draw");e.exports={moduleType:"component",name:"annotations",layoutAttributes:t("./attributes"),supplyLayoutDefaults:t("./defaults"),calcAutorange:t("./calc_autorange"),draw:n.draw,drawOne:n.drawOne}},{"./attributes":23,"./calc_autorange":24,"./defaults":25,"./draw":26}],29:[function(t,e,r){"use strict";r.defaults=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],r.defaultLine="#444",r.lightLine="#eee",r.background="#fff",r.borderLine="#BEC8D9",r.lightFraction=1e3/11},{}],30:[function(t,e,r){"use strict";function n(t){if(o(t)||"string"!=typeof t)return t;var e=t.trim();if("rgb"!==e.substr(0,3))return t;var r=e.match(/^rgba?\s*\(([^()]*)\)$/);if(!r)return t;var n=r[1].trim().split(/\s*[\s,]\s*/),a="a"===e.charAt(3)&&4===n.length;if(!a&&3!==n.length)return t;for(var i=0;i=0))return t;if(3===i)n[i]>1&&(n[i]=1);else if(n[i]>=1)return t}var l=Math.round(255*n[0])+", "+Math.round(255*n[1])+", "+Math.round(255*n[2]);return a?"rgba("+l+", "+n[3]+")":"rgb("+l+")"}var a=t("tinycolor2"),o=t("fast-isnumeric"),i=e.exports={},l=t("./attributes");i.defaults=l.defaults,i.defaultLine=l.defaultLine,i.lightLine=l.lightLine,i.background=l.background,i.overrideColorDefaults=function(t){return"undefined"==typeof t?i.defaults:void(i.defaults=t)},i.tinyRGB=function(t){var e=t.toRgb();return"rgb("+Math.round(e.r)+", "+Math.round(e.g)+", "+Math.round(e.b)+")"},i.rgb=function(t){return i.tinyRGB(a(t))},i.opacity=function(t){return t?a(t).getAlpha():0},i.addOpacity=function(t,e){var r=a(t).toRgb();return"rgba("+Math.round(r.r)+", "+Math.round(r.g)+", "+Math.round(r.b)+", "+e+")"},i.combine=function(t,e){var r=a(t).toRgb();if(1===r.a)return a(t).toRgbString();var n=a(e||i.background).toRgb(),o=1===n.a?n:{r:255*(1-n.a)+n.r*n.a,g:255*(1-n.a)+n.g*n.a,b:255*(1-n.a)+n.b*n.a},l={r:o.r*(1-r.a)+r.r*r.a,g:o.g*(1-r.a)+r.g*r.a,b:o.b*(1-r.a)+r.b*r.a};return a(l).toRgbString()},i.contrast=function(t,e,r){var n=a(t),o=n.isLight()?n.darken(r):n.lighten(e);return o.toString()},i.stroke=function(t,e){var r=a(e);t.style({stroke:i.tinyRGB(r),"stroke-opacity":r.getAlpha()})},i.fill=function(t,e){var r=a(e);t.style({fill:i.tinyRGB(r),"fill-opacity":r.getAlpha()})},i.clean=function(t){if(t&&"object"==typeof t){var e,r,a,o,l=Object.keys(t);for(e=0;el&&(o[1]-=(lt-l)/2)):r.node()&&!r.classed("js-placeholder")&&(lt=h.bBox(e.node()).height),lt){if(lt+=5,"top"===_.titleside)K.domain[1]-=lt/T.h,o[1]*=-1;else{K.domain[0]+=lt/T.h;var c=Math.max(1,r.selectAll("tspan.line").size());o[1]+=(1-c)*l}e.attr("transform","translate("+o+")"),K.setScale()}}ot.selectAll(".cbfills,.cblines,.cbaxis").attr("transform","translate(0,"+Math.round(T.h*(1-K.domain[1]))+")");var f=ot.select(".cbfills").selectAll("rect.cbfill").data(S);f.enter().append("rect").classed("cbfill",!0).style("stroke","none"),f.exit().remove(),f.each(function(t,e){var r=[0===e?z[0]:(S[e]+S[e-1])/2,e===S.length-1?z[1]:(S[e]+S[e+1])/2].map(K.c2p).map(Math.round);e!==S.length-1&&(r[1]+=r[1]>r[0]?1:-1);var o=D(t).replace("e-",""),i=a(o).toHexString();n.select(this).attr({x:Y,width:Math.max(q,2),y:n.min(r),height:Math.max(n.max(r)-n.min(r),2),fill:i})});var d=ot.select(".cblines").selectAll("path.cbline").data(_.line.color&&_.line.width?C:[]);return d.enter().append("path").classed("cbline",!0),d.exit().remove(),d.each(function(t){n.select(this).attr("d","M"+Y+","+(Math.round(K.c2p(t))+_.line.width/2%1)+"h"+q).call(h.lineGroupStyle,_.line.width,O(t),_.line.dash)}),K._axislayer.selectAll("g."+K._id+"tick,path").remove(),K._pos=Y+q+(_.outlinewidth||0)/2-("outside"===_.ticks?1:0),K.side="right",u.syncOrAsync([function(){return s.doTicks(t,K,!0)},function(){if(["top","bottom"].indexOf(_.titleside)===-1){var e=K.titlefont.size,r=K._offset+K._length/2,a=T.l+(K.position||0)*T.w+("right"===K.side?10+e*(K.showticklabels?1:.5):-10-e*(K.showticklabels?.5:0));k("h"+K._id+"title",{avoid:{selection:n.select(t).selectAll("g."+K._id+"tick"),side:_.titleside,offsetLeft:T.l,offsetTop:T.t,maxShift:A.width},attributes:{x:a,y:r,"text-anchor":"middle"},transform:{rotate:"-90",offset:0}})}}])}function k(e,r){var n,a=b();n=l.traceIs(a,"markerColorscale")?"marker.colorbar.title":"colorbar.title";var o={propContainer:K,propName:n,traceIndex:a.index,dfltName:"colorscale",containerGroup:ot.select(".cbtitle")},i="h"===e.charAt(0)?e.substr(1):"h"+e;ot.selectAll("."+i+",."+i+"-math-group").remove(),g.draw(t,e,f(o,r||{}))}function M(){var r=q+_.outlinewidth/2+h.bBox(K._axislayer.node()).width;if(R=it.select("text"),R.node()&&!R.classed("js-placeholder")){var n,a=it.select(".h"+K._id+"title-math-group").node();n=a&&["top","bottom"].indexOf(_.titleside)!==-1?h.bBox(a).width:h.bBox(it.node()).right-Y-T.l,r=Math.max(r,n)}var o=2*_.xpad+r+_.borderwidth+_.outlinewidth/2,l=Q-$;ot.select(".cbbg").attr({x:Y-_.xpad-(_.borderwidth+_.outlinewidth)/2,y:$-X,width:Math.max(o,2),height:Math.max(l+2*X,2)}).call(p.fill,_.bgcolor).call(p.stroke,_.bordercolor).style({"stroke-width":_.borderwidth}),ot.selectAll(".cboutline").attr({x:Y,y:$+_.ypad+("top"===_.titleside?lt:0),width:Math.max(q,2),height:Math.max(l-2*_.ypad-lt,2)}).call(p.stroke,_.outlinecolor).style({fill:"None","stroke-width":_.outlinewidth});var s=({center:.5,right:1}[_.xanchor]||0)*o;ot.attr("transform","translate("+(T.l-s)+","+T.t+")"),i.autoMargin(t,e,{x:_.x,y:_.y,l:o*({right:1,center:.5}[_.xanchor]||0),r:o*({left:1,center:.5}[_.xanchor]||0),t:l*({bottom:1,middle:.5}[_.yanchor]||0),b:l*({top:1,middle:.5}[_.yanchor]||0)})}var A=t._fullLayout,T=A._size;if("function"!=typeof _.fillcolor&&"function"!=typeof _.line.color)return void A._infolayer.selectAll("g."+e).remove();var L,z=n.extent(("function"==typeof _.fillcolor?_.fillcolor:_.line.color).domain()),C=[],S=[],O="function"==typeof _.line.color?_.line.color:function(){return _.line.color},D="function"==typeof _.fillcolor?_.fillcolor:function(){return _.fillcolor},P=_.levels.end+_.levels.size/100,N=_.levels.size,E=1.001*z[0]-.001*z[1],I=1.001*z[1]-.001*z[0];for(L=_.levels.start;(L-P)*N<0;L+=N)L>E&&Lz[0]&&L1){var at=Math.pow(10,Math.floor(Math.log(nt)/Math.LN10));et*=at*u.roundUp(nt/at,[2,5,10]),(Math.abs(_.levels.start)/_.levels.size+1e-6)%1<2e-6&&(K.tick0=0)}K.dtick=et}K.domain=[W+U,W+V-U],K.setScale();var ot=A._infolayer.selectAll("g."+e).data([0]);ot.enter().append("g").classed(e,!0).each(function(){var t=n.select(this);t.append("rect").classed("cbbg",!0),t.append("g").classed("cbfills",!0),t.append("g").classed("cblines",!0),t.append("g").classed("cbaxis",!0).classed("crisp",!0),t.append("g").classed("cbtitleunshift",!0).append("g").classed("cbtitle",!0),t.append("rect").classed("cboutline",!0),t.select(".cbtitle").datum(0)}),ot.attr("transform","translate("+Math.round(T.l)+","+Math.round(T.t)+")");var it=ot.select(".cbtitleunshift").attr("transform","translate(-"+Math.round(T.l)+",-"+Math.round(T.t)+")");K._axislayer=ot.select(".cbaxis");var lt=0;if(["top","bottom"].indexOf(_.titleside)!==-1){var st,ct=T.l+(_.x+Z)*T.w,ut=K.titlefont.size;st="top"===_.titleside?(1-(W+V-U))*T.h+T.t+3+.75*ut:(1-(W+U))*T.h+T.t-3-.25*ut,k(K._id+"title",{attributes:{x:ct,y:st,"text-anchor":"start"}})}var ft=u.syncOrAsync([i.previousPromises,w,i.previousPromises,M],t);if(ft&&ft.then&&(t._promises||[]).push(ft),t._context.editable){var dt,ht,pt;c.init({element:ot.node(),prepFn:function(){dt=ot.attr("transform"),d(ot)},moveFn:function(t,e){ot.attr("transform",dt+" translate("+t+","+e+")"),ht=c.align(G+t/T.w,B,0,1,_.xanchor),pt=c.align(W-e/T.h,V,0,1,_.yanchor);var r=c.getCursor(ht,pt,_.xanchor,_.yanchor);d(ot,r)},doneFn:function(e){d(ot),e&&void 0!==ht&&void 0!==pt&&o.restyle(t,{"colorbar.x":ht,"colorbar.y":pt},b().index)}})}return ft}function b(){var r,n,a=e.substr(2);for(r=0;r=0?a.Reds:a.Blues,s.colorscale=d,l.reversescale&&(d=o(d)),l.colorscale=d)}},{"../../lib":122,"./flip_scale":41,"./scales":48}],37:[function(t,e,r){"use strict";var n=t("./attributes"),a=t("../../lib/extend").extendDeep;t("./scales.js");e.exports=function(t){return{color:{valType:"color",arrayOk:!0},colorscale:a({},n.colorscale,{}),cauto:a({},n.zauto,{}),cmax:a({},n.zmax,{}),cmin:a({},n.zmin,{}),autocolorscale:a({},n.autocolorscale,{}),reversescale:a({},n.reversescale,{})}}},{"../../lib/extend":119,"./attributes":35,"./scales.js":48}],38:[function(t,e,r){"use strict";var n=t("./scales");e.exports=n.RdBu},{"./scales":48}],39:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../lib"),o=t("../colorbar/has_colorbar"),i=t("../colorbar/defaults"),l=t("./is_valid_scale"),s=t("./flip_scale");e.exports=function(t,e,r,c,u){var f=u.prefix,d=u.cLetter,h=f.slice(0,f.length-1),p=f?a.nestedProperty(t,h).get()||{}:t,g=f?a.nestedProperty(e,h).get()||{}:e,m=p[d+"min"],v=p[d+"max"],y=p.colorscale,x=n(m)&&n(v)&&m=0;a--,o++)e=t[a],n[o]=[1-e[0],e[1]];return n}},{}],42:[function(t,e,r){"use strict";var n=t("./scales"),a=t("./default_scale"),o=t("./is_valid_scale_array");e.exports=function(t,e){function r(){try{t=n[t]||JSON.parse(t)}catch(r){t=e}}return e||(e=a),t?("string"==typeof t&&(r(),"string"==typeof t&&r()),o(t)?t:e):e}},{"./default_scale":38,"./is_valid_scale_array":46,"./scales":48}],43:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../lib"),o=t("./is_valid_scale");e.exports=function(t,e){var r=e?a.nestedProperty(t,e).get()||{}:t,i=r.color,l=!1;if(Array.isArray(i))for(var s=0;s4/3-l?i:l}},{}],50:[function(t,e,r){"use strict";var n=t("../../lib"),a=[["sw-resize","s-resize","se-resize"],["w-resize","move","e-resize"],["nw-resize","n-resize","ne-resize"]];e.exports=function(t,e,r,o){return t="left"===r?0:"center"===r?1:"right"===r?2:n.constrain(Math.floor(3*t),0,2),e="bottom"===o?0:"middle"===o?1:"top"===o?2:n.constrain(Math.floor(3*e),0,2),a[e][t]}},{"../../lib":122}],51:[function(t,e,r){"use strict";function n(){var t=document.createElement("div");t.className="dragcover";var e=t.style;return e.position="fixed",e.left=0,e.right=0,e.top=0,e.bottom=0,e.zIndex=999999999,e.background="none",document.body.appendChild(t),t}function a(t){t._dragging=!1,t._replotPending&&o.plot(t)}var o=t("../../plotly"),i=t("../../lib"),l=t("../../plots/cartesian/constants"),s=e.exports={};s.align=t("./align"),s.getCursor=t("./cursor");var c=t("./unhover");s.unhover=c.wrapped,s.unhoverRaw=c.raw,s.init=function(t){function e(e){return t.element.onmousemove=p,g._dragged=!1,g._dragging=!0,c=e.clientX,u=e.clientY,h=e.target,f=(new Date).getTime(),f-g._mouseDownTimev&&(m=Math.max(m-1,1)),t.doneFn&&t.doneFn(g._dragged,m),!g._dragged){var r=document.createEvent("MouseEvents");r.initMouseEvent("click",e.bubbles,e.cancelable,e.view,0,0,0,0,0,!1,!1,!1,!1,e.button,null),h.dispatchEvent(r)}return a(g),g._dragged=!1,i.pauseEvent(e)}var c,u,f,d,h,p,g=i.getPlotDiv(t.element)||{},m=1,v=l.DBLCLICKDELAY;g._mouseDownTime||(g._mouseDownTime=0),p=t.element.onmousemove,t.setCursor&&(t.element.onmousemove=t.setCursor),t.element.onmousedown=e,t.element.style.pointerEvents="all"},s.coverSlip=n},{"../../lib":122,"../../plotly":144,"../../plots/cartesian/constants":154,"./align":49,"./cursor":50,"./unhover":52}],52:[function(t,e,r){"use strict";var n=t("../../lib/events"),a=e.exports={};a.wrapped=function(t,e,r){"string"==typeof t&&(t=document.getElementById(t)),t._hoverTimer&&(clearTimeout(t._hoverTimer),t._hoverTimer=void 0),a.raw(t,e,r)},a.raw=function(t,e){var r=t._fullLayout;e||(e={}),e.target&&n.triggerHandler(t,"plotly_beforehover",e)===!1||(r._hoverlayer.selectAll("g").remove(),e.target&&t._hoverdata&&t.emit("plotly_unhover",{points:t._hoverdata}),t._hoverdata=void 0)}},{"../../lib/events":118}],53:[function(t,e,r){"use strict";function n(t,e,r,n,a,o,i){if(l.traceIs(r,"symbols")){var c=p(r);e.attr("d",function(t){var e;e="various"===t.ms||"various"===o.size?3:h.isBubble(r)?c(t.ms):(o.size||6)/2,t.mrc=e;var n=g.symbolNumber(t.mx||o.symbol)||0,a=n%100;return t.om=n%200>=100,g.symbolFuncs[a](e)+(n>=200?y:"")}).style("opacity",function(t){return(t.mo+1||o.opacity+1)-1})}var u,f,d;t.so?(d=i.outlierwidth,f=i.outliercolor,u=o.outliercolor):(d=(t.mlw+1||i.width+1||(t.trace?t.trace.marker.line.width:0)+1)-1,f="mlc"in t?t.mlcc=a(t.mlc):Array.isArray(i.color)?s.defaultLine:i.color,u="mc"in t?t.mcc=n(t.mc):Array.isArray(o.color)?s.defaultLine:o.color||"rgba(0,0,0,0)"),t.om?e.call(s.stroke,u).style({"stroke-width":(d||1)+"px",fill:"none"}):(e.style("stroke-width",d+"px").call(s.fill,u),d&&e.call(s.stroke,f))}function a(t,e,r,n){var a=t[0]-e[0],i=t[1]-e[1],l=r[0]-e[0],s=r[1]-e[1],c=Math.pow(a*a+i*i,_/2),u=Math.pow(l*l+s*s,_/2),f=(u*u*a-c*c*l)*n,d=(u*u*i-c*c*s)*n,h=3*u*(c+u),p=3*c*(c+u);return[[o.round(e[0]+(h&&f/h),2),o.round(e[1]+(h&&d/h),2)],[o.round(e[0]-(p&&f/p),2),o.round(e[1]-(p&&d/p),2)]]}var o=t("d3"),i=t("fast-isnumeric"),l=t("../../registry"),s=t("../color"),c=t("../colorscale"),u=t("../../lib"),f=t("../../lib/svg_text_utils"),d=t("../../constants/xmlns_namespaces"),h=t("../../traces/scatter/subtypes"),p=t("../../traces/scatter/make_bubble_size_func"),g=e.exports={};g.font=function(t,e,r,n){e&&e.family&&(n=e.color,r=e.size,e=e.family),e&&t.style("font-family",e),r+1&&t.style("font-size",r+"px"),n&&t.call(s.fill,n)},g.setPosition=function(t,e,r){t.attr("x",e).attr("y",r)},g.setSize=function(t,e,r){t.attr("width",e).attr("height",r)},g.setRect=function(t,e,r,n,a){t.call(g.setPosition,e,r).call(g.setSize,n,a)},g.translatePoint=function(t,e,r,n){var a=t.xp||r.c2p(t.x),o=t.yp||n.c2p(t.y);i(a)&&i(o)?"text"===e.node().nodeName?e.attr("x",a).attr("y",o):e.attr("transform","translate("+a+","+o+")"):e.remove()},g.translatePoints=function(t,e,r,n){t.each(function(t){var a=o.select(this);g.translatePoint(t,a,e,r,n)})},g.getPx=function(t,e){return Number(t.style(e).replace(/px$/,""))},g.crispRound=function(t,e,r){return e&&i(e)?t._context.staticPlot?e:e<1?1:Math.round(e):r||0},g.singleLineStyle=function(t,e,r,n,a){e.style("fill","none");var o=(((t||[])[0]||{}).trace||{}).line||{},i=r||o.width||0,l=a||o.dash||"";s.stroke(e,n||o.color),g.dashLine(e,l,i)},g.lineGroupStyle=function(t,e,r,n){t.style("fill","none").each(function(t){var a=(((t||[])[0]||{}).trace||{}).line||{},i=e||a.width||0,l=n||a.dash||"";o.select(this).call(s.stroke,r||a.color).call(g.dashLine,l,i)})},g.dashLine=function(t,e,r){var n=Math.max(r,3);"solid"===e?e="":"dot"===e?e=n+"px,"+n+"px":"dash"===e?e=3*n+"px,"+3*n+"px":"longdash"===e?e=5*n+"px,"+5*n+"px":"dashdot"===e?e=3*n+"px,"+n+"px,"+n+"px,"+n+"px":"longdashdot"===e&&(e=5*n+"px,"+2*n+"px,"+n+"px,"+2*n+"px"),t.style({"stroke-dasharray":e,"stroke-width":r+"px"})},g.fillGroupStyle=function(t){t.style("stroke-width",0).each(function(e){var r=o.select(this);try{r.call(s.fill,e[0].trace.fillcolor)}catch(e){u.error(e,t),r.remove()}})};var m=t("./symbol_defs");g.symbolNames=[],g.symbolFuncs=[],g.symbolNeedLines={},g.symbolNoDot={},g.symbolList=[],Object.keys(m).forEach(function(t){var e=m[t];g.symbolList=g.symbolList.concat([e.n,t,e.n+100,t+"-open"]),g.symbolNames[e.n]=t,g.symbolFuncs[e.n]=e.f,e.needLine&&(g.symbolNeedLines[e.n]=!0),e.noDot?g.symbolNoDot[e.n]=!0:g.symbolList=g.symbolList.concat([e.n+200,t+"-dot",e.n+300,t+"-open-dot"])});var v=g.symbolNames.length,y="M0,0.5L0.5,0L0,-0.5L-0.5,0Z";g.symbolNumber=function(t){if("string"==typeof t){var e=0;t.indexOf("-open")>0&&(e=100,t=t.replace("-open","")),t.indexOf("-dot")>0&&(e+=200,t=t.replace("-dot","")),t=g.symbolNames.indexOf(t),t>=0&&(t+=e)}return t%100>=v||t>=400?0:Math.floor(Math.max(t,0))},g.singlePointStyle=function(t,e,r){var a=r.marker,o=a.line,i=g.tryColorscale(a,""),l=g.tryColorscale(a,"line");n(t,e,r,i,l,a,o)},g.pointStyle=function(t,e){if(t.size()){var r=e.marker,n=g.tryColorscale(r,""),a=g.tryColorscale(r,"line");t.each(function(t){g.singlePointStyle(t,o.select(this),e,n,a)})}},g.tryColorscale=function(t,e){var r=e?u.nestedProperty(t,e).get():t,n=r.colorscale,a=r.color;return n&&Array.isArray(a)?c.makeColorScaleFunc(c.extractScale(n,r.cmin,r.cmax)):u.identity};var x={start:1,end:-1,middle:0,bottom:1,top:-1},b=1.3;g.textPointStyle=function(t,e){t.each(function(t){var r=o.select(this),n=t.tx||e.text;if(!n||Array.isArray(n))return void r.remove();var a=t.tp||e.textposition,l=a.indexOf("top")!==-1?"top":a.indexOf("bottom")!==-1?"bottom":"middle",s=a.indexOf("left")!==-1?"end":a.indexOf("right")!==-1?"start":"middle",c=t.ts||e.textfont.size,u=t.mrc?t.mrc/.8+1:0;c=i(c)&&c>0?c:0,r.call(g.font,t.tf||e.textfont.family,c,t.tc||e.textfont.color).attr("text-anchor",s).text(n).call(f.convertToTspans);var d=o.select(this.parentNode),h=r.selectAll("tspan.line"),p=((h[0].length||1)-1)*b+1,m=x[s]*u,v=.75*c+x[l]*u+(x[l]-1)*p*c/2;d.attr("transform","translate("+m+","+v+")"),p>1&&h.attr({x:r.attr("x"),y:r.attr("y")})})};var _=.5;g.smoothopen=function(t,e){if(t.length<3)return"M"+t.join("L");var r,n="M"+t[0],o=[];for(r=1;r=A&&(o.selectAll("[data-bb]").attr("data-bb",null),M=[]),t.setAttribute("data-bb",M.length),M.push(s),u.extendFlat({},s)},g.setClipUrl=function(t,e){if(!e)return void t.attr("clip-path",null);var r="#"+e,n=o.select("base");n.size()&&n.attr("href")&&(r=window.location.href+r),t.attr("clip-path","url("+r+")")}},{"../../constants/xmlns_namespaces":112,"../../lib":122,"../../lib/svg_text_utils":134,"../../registry":188,"../../traces/scatter/make_bubble_size_func":286,"../../traces/scatter/subtypes":291,"../color":30,"../colorscale":44,"./symbol_defs":54,d3:14,"fast-isnumeric":17}],54:[function(t,e,r){"use strict";var n=t("d3");e.exports={circle:{n:0,f:function(t){var e=n.round(t,2);return"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"}},square:{n:1,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"}},diamond:{n:2,f:function(t){var e=n.round(1.3*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"Z"}},cross:{n:3,f:function(t){var e=n.round(.4*t,2),r=n.round(1.2*t,2);return"M"+r+","+e+"H"+e+"V"+r+"H-"+e+"V"+e+"H-"+r+"V-"+e+"H-"+e+"V-"+r+"H"+e+"V-"+e+"H"+r+"Z"}},x:{n:4,f:function(t){var e=n.round(.8*t/Math.sqrt(2),2),r="l"+e+","+e,a="l"+e+",-"+e,o="l-"+e+",-"+e,i="l-"+e+","+e;return"M0,"+e+r+a+o+a+o+i+o+i+r+i+r+"Z"}},"triangle-up":{n:5,f:function(t){var e=n.round(2*t/Math.sqrt(3),2),r=n.round(t/2,2),a=n.round(t,2);return"M-"+e+","+r+"H"+e+"L0,-"+a+"Z"}},"triangle-down":{n:6,f:function(t){var e=n.round(2*t/Math.sqrt(3),2),r=n.round(t/2,2),a=n.round(t,2);return"M-"+e+",-"+r+"H"+e+"L0,"+a+"Z"}},"triangle-left":{n:7,f:function(t){var e=n.round(2*t/Math.sqrt(3),2),r=n.round(t/2,2),a=n.round(t,2);return"M"+r+",-"+e+"V"+e+"L-"+a+",0Z"}},"triangle-right":{n:8,f:function(t){var e=n.round(2*t/Math.sqrt(3),2),r=n.round(t/2,2),a=n.round(t,2);return"M-"+r+",-"+e+"V"+e+"L"+a+",0Z"}},"triangle-ne":{n:9,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M-"+r+",-"+e+"H"+e+"V"+r+"Z"}},"triangle-se":{n:10,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M"+e+",-"+r+"V"+e+"H-"+r+"Z"}},"triangle-sw":{n:11,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M"+r+","+e+"H-"+e+"V-"+r+"Z"}},"triangle-nw":{n:12,f:function(t){var e=n.round(.6*t,2),r=n.round(1.2*t,2);return"M-"+e+","+r+"V-"+e+"H"+r+"Z"}},pentagon:{n:13,f:function(t){var e=n.round(.951*t,2),r=n.round(.588*t,2),a=n.round(-t,2),o=n.round(t*-.309,2),i=n.round(.809*t,2);return"M"+e+","+o+"L"+r+","+i+"H-"+r+"L-"+e+","+o+"L0,"+a+"Z"}},hexagon:{n:14,f:function(t){var e=n.round(t,2),r=n.round(t/2,2),a=n.round(t*Math.sqrt(3)/2,2);return"M"+a+",-"+r+"V"+r+"L0,"+e+"L-"+a+","+r+"V-"+r+"L0,-"+e+"Z"}},hexagon2:{n:15,f:function(t){var e=n.round(t,2),r=n.round(t/2,2),a=n.round(t*Math.sqrt(3)/2,2);return"M-"+r+","+a+"H"+r+"L"+e+",0L"+r+",-"+a+"H-"+r+"L-"+e+",0Z"}},octagon:{n:16,f:function(t){var e=n.round(.924*t,2),r=n.round(.383*t,2);return"M-"+r+",-"+e+"H"+r+"L"+e+",-"+r+"V"+r+"L"+r+","+e+"H-"+r+"L-"+e+","+r+"V-"+r+"Z"}},star:{n:17,f:function(t){var e=1.4*t,r=n.round(.225*e,2),a=n.round(.951*e,2),o=n.round(.363*e,2),i=n.round(.588*e,2),l=n.round(-e,2),s=n.round(e*-.309,2),c=n.round(.118*e,2),u=n.round(.809*e,2),f=n.round(.382*e,2);return"M"+r+","+s+"H"+a+"L"+o+","+c+"L"+i+","+u+"L0,"+f+"L-"+i+","+u+"L-"+o+","+c+"L-"+a+","+s+"H-"+r+"L0,"+l+"Z"}},hexagram:{n:18,f:function(t){var e=n.round(.66*t,2),r=n.round(.38*t,2),a=n.round(.76*t,2);return"M-"+a+",0l-"+r+",-"+e+"h"+a+"l"+r+",-"+e+"l"+r+","+e+"h"+a+"l-"+r+","+e+"l"+r+","+e+"h-"+a+"l-"+r+","+e+"l-"+r+",-"+e+"h-"+a+"Z"}},"star-triangle-up":{n:19,f:function(t){var e=n.round(t*Math.sqrt(3)*.8,2),r=n.round(.8*t,2),a=n.round(1.6*t,2),o=n.round(4*t,2),i="A "+o+","+o+" 0 0 1 ";return"M-"+e+","+r+i+e+","+r+i+"0,-"+a+i+"-"+e+","+r+"Z"}},"star-triangle-down":{n:20,f:function(t){var e=n.round(t*Math.sqrt(3)*.8,2),r=n.round(.8*t,2),a=n.round(1.6*t,2),o=n.round(4*t,2),i="A "+o+","+o+" 0 0 1 ";return"M"+e+",-"+r+i+"-"+e+",-"+r+i+"0,"+a+i+e+",-"+r+"Z"}},"star-square":{n:21,f:function(t){var e=n.round(1.1*t,2),r=n.round(2*t,2),a="A "+r+","+r+" 0 0 1 ";return"M-"+e+",-"+e+a+"-"+e+","+e+a+e+","+e+a+e+",-"+e+a+"-"+e+",-"+e+"Z"}},"star-diamond":{n:22,f:function(t){var e=n.round(1.4*t,2),r=n.round(1.9*t,2),a="A "+r+","+r+" 0 0 1 ";return"M-"+e+",0"+a+"0,"+e+a+e+",0"+a+"0,-"+e+a+"-"+e+",0Z"}},"diamond-tall":{n:23,f:function(t){var e=n.round(.7*t,2),r=n.round(1.4*t,2);return"M0,"+r+"L"+e+",0L0,-"+r+"L-"+e+",0Z"}},"diamond-wide":{n:24,f:function(t){var e=n.round(1.4*t,2),r=n.round(.7*t,2);return"M0,"+r+"L"+e+",0L0,-"+r+"L-"+e+",0Z"}},hourglass:{n:25,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"H-"+e+"L"+e+",-"+e+"H-"+e+"Z"},noDot:!0},bowtie:{n:26,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"V-"+e+"L-"+e+","+e+"V-"+e+"Z"},noDot:!0},"circle-cross":{n:27,f:function(t){var e=n.round(t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"},needLine:!0,noDot:!0},"circle-x":{n:28,f:function(t){var e=n.round(t,2),r=n.round(t/Math.sqrt(2),2);return"M"+r+","+r+"L-"+r+",-"+r+"M"+r+",-"+r+"L-"+r+","+r+"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"},needLine:!0,noDot:!0},"square-cross":{n:29,f:function(t){var e=n.round(t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"},needLine:!0,noDot:!0},"square-x":{n:30,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e+"M"+e+",-"+e+"L-"+e+","+e+"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"},needLine:!0,noDot:!0},"diamond-cross":{n:31,f:function(t){var e=n.round(1.3*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"ZM0,-"+e+"V"+e+"M-"+e+",0H"+e},needLine:!0,noDot:!0},"diamond-x":{n:32,f:function(t){var e=n.round(1.3*t,2),r=n.round(.65*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"ZM-"+r+",-"+r+"L"+r+","+r+"M-"+r+","+r+"L"+r+",-"+r},needLine:!0,noDot:!0},"cross-thin":{n:33,f:function(t){var e=n.round(1.4*t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e},needLine:!0,noDot:!0},"x-thin":{n:34,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e+"M"+e+",-"+e+"L-"+e+","+e},needLine:!0,noDot:!0},asterisk:{n:35,f:function(t){var e=n.round(1.2*t,2),r=n.round(.85*t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+r+","+r+"L-"+r+",-"+r+"M"+r+",-"+r+"L-"+r+","+r},needLine:!0,noDot:!0},hash:{n:36,f:function(t){var e=n.round(t/2,2),r=n.round(t,2);return"M"+e+","+r+"V-"+r+"m-"+r+",0V"+r+"M"+r+","+e+"H-"+r+"m0,-"+r+"H"+r},needLine:!0},"y-up":{n:37,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),a=n.round(.8*t,2);return"M-"+e+","+a+"L0,0M"+e+","+a+"L0,0M0,-"+r+"L0,0"},needLine:!0,noDot:!0},"y-down":{n:38,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),a=n.round(.8*t,2);return"M-"+e+",-"+a+"L0,0M"+e+",-"+a+"L0,0M0,"+r+"L0,0"},needLine:!0,noDot:!0},"y-left":{n:39,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),a=n.round(.8*t,2);return"M"+a+","+e+"L0,0M"+a+",-"+e+"L0,0M-"+r+",0L0,0"},needLine:!0,noDot:!0},"y-right":{n:40,f:function(t){var e=n.round(1.2*t,2),r=n.round(1.6*t,2),a=n.round(.8*t,2);return"M-"+a+","+e+"L0,0M-"+a+",-"+e+"L0,0M"+r+",0L0,0"},needLine:!0,noDot:!0},"line-ew":{n:41,f:function(t){var e=n.round(1.4*t,2);return"M"+e+",0H-"+e},needLine:!0,noDot:!0},"line-ns":{n:42,f:function(t){var e=n.round(1.4*t,2);return"M0,"+e+"V-"+e},needLine:!0,noDot:!0},"line-ne":{n:43,f:function(t){var e=n.round(t,2);return"M"+e+",-"+e+"L-"+e+","+e},needLine:!0,noDot:!0},"line-nw":{n:44,f:function(t){var e=n.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e},needLine:!0,noDot:!0}}},{d3:14}],55:[function(t,e,r){"use strict";e.exports={visible:{valType:"boolean"},type:{valType:"enumerated",values:["percent","constant","sqrt","data"]},symmetric:{valType:"boolean"},array:{valType:"data_array"},arrayminus:{valType:"data_array"},value:{valType:"number",min:0,dflt:10},valueminus:{valType:"number",min:0,dflt:10},traceref:{valType:"integer",min:0,dflt:0},tracerefminus:{valType:"integer",min:0,dflt:0},copy_ystyle:{valType:"boolean"},copy_zstyle:{valType:"boolean"},color:{valType:"color"},thickness:{valType:"number",min:0,dflt:2},width:{valType:"number",min:0},_deprecated:{opacity:{valType:"number"}}}},{}],56:[function(t,e,r){"use strict";function n(t,e,r,n){var o=e["error_"+n]||{},s=o.visible&&["linear","log"].indexOf(r.type)!==-1,c=[];if(s){for(var u=l(o),f=0;f0;t.each(function(t){var e,f=t[0].trace,d=f.error_x||{},h=f.error_y||{};f.ids&&(e=function(t){return t.id});var p=i.hasMarkers(f)&&f.marker.maxdisplayed>0;if(h.visible||d.visible){var g=a.select(this).selectAll("g.errorbar").data(t,e);g.exit().remove(),g.style("opacity",1);var m=g.enter().append("g").classed("errorbar",!0);u&&m.style("opacity",0).transition().duration(r.duration).style("opacity",1),g.each(function(t){var e=a.select(this),i=n(t,s,c);if(!p||t.vis){var f;if(h.visible&&o(i.x)&&o(i.yh)&&o(i.ys)){var g=h.width;f="M"+(i.x-g)+","+i.yh+"h"+2*g+"m-"+g+",0V"+i.ys,i.noYS||(f+="m-"+g+",0h"+2*g);var m=e.select("path.yerror");l=!m.size(),l?m=e.append("path").classed("yerror",!0):u&&(m=m.transition().duration(r.duration).ease(r.easing)),m.attr("d",f)}if(d.visible&&o(i.y)&&o(i.xh)&&o(i.xs)){var v=(d.copy_ystyle?h:d).width;f="M"+i.xh+","+(i.y-v)+"v"+2*v+"m0,-"+v+"H"+i.xs,i.noXS||(f+="m0,-"+v+"v"+2*v);var y=e.select("path.xerror");l=!y.size(),l?y=e.append("path").classed("xerror",!0):u&&(y=y.transition().duration(r.duration).ease(r.easing)),y.attr("d",f)}}})}})}},{"../../traces/scatter/subtypes":291,d3:14,"fast-isnumeric":17}],61:[function(t,e,r){"use strict";var n=t("d3"),a=t("../color");e.exports=function(t){t.each(function(t){var e=t[0].trace,r=e.error_y||{},o=e.error_x||{},i=n.select(this);i.selectAll("path.yerror").style("stroke-width",r.thickness+"px").call(a.stroke,r.color),o.copy_ystyle&&(o=r),i.selectAll("path.xerror").style("stroke-width",o.thickness+"px").call(a.stroke,o.color)})}},{"../color":30,d3:14}],62:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/constants");e.exports={_isLinkedToArray:"image",visible:{valType:"boolean",dflt:!0},source:{valType:"string"},layer:{valType:"enumerated",values:["below","above"],dflt:"above"},sizex:{valType:"number",dflt:0},sizey:{valType:"number",dflt:0},sizing:{valType:"enumerated",values:["fill","contain","stretch"],dflt:"contain"},opacity:{valType:"number",min:0,max:1,dflt:1},x:{valType:"any",dflt:0},y:{valType:"any",dflt:0},xanchor:{valType:"enumerated",values:["left","center","right"],dflt:"left"},yanchor:{valType:"enumerated",values:["top","middle","bottom"],dflt:"top"},xref:{valType:"enumerated",values:["paper",n.idRegex.x.toString()],dflt:"paper"},yref:{valType:"enumerated",values:["paper",n.idRegex.y.toString()],dflt:"paper"}}},{"../../plots/cartesian/constants":154}],63:[function(t,e,r){"use strict";function n(t,e,r){function n(r,n){return a.coerce(t,e,l,r,n)}var i=n("source"),s=n("visible",!!i);if(!s)return e;n("layer"),n("x"),n("y"),n("xanchor"),n("yanchor"),n("sizex"),n("sizey"),n("sizing"),n("opacity");for(var c={_fullLayout:r},u=["x","y"],f=0;f<2;f++)o.coerceRef(t,e,c,u[f],"paper");return e}var a=t("../../lib"),o=t("../../plots/cartesian/axes"),i=t("../../plots/array_container_defaults"),l=t("./attributes"),s="images";e.exports=function(t,e){var r={name:s,handleItemDefaults:n};i(t,e,r)}},{"../../lib":122,"../../plots/array_container_defaults":146,"../../plots/cartesian/axes":149,"./attributes":62}],64:[function(t,e,r){"use strict";var n=t("d3"),a=t("../drawing"),o=t("../../plots/cartesian/axes"),i=t("../../constants/xmlns_namespaces");e.exports=function(t){function e(e){var r=n.select(this);if(!this.img||this.img.src!==e.source){r.attr("xmlns",i.svg);var a=new Promise(function(t){function n(){r.remove(),t()}var a=new Image;this.img=a,a.setAttribute("crossOrigin","anonymous"),a.onerror=n,a.onload=function(){var t=document.createElement("canvas");t.width=this.width,t.height=this.height;var e=t.getContext("2d");e.drawImage(this,0,0);var n=t.toDataURL("image/png");r.attr("xlink:href",n)},r.on("error",n),r.on("load",t),a.src=e.source}.bind(this));t._promises.push(a)}}function r(e){var r=n.select(this),i=o.getFromId(t,e.xref),s=o.getFromId(t,e.yref),c=l._size,u=i?Math.abs(i.l2p(e.sizex)-i.l2p(0)):e.sizex*c.w,f=s?Math.abs(s.l2p(e.sizey)-s.l2p(0)):e.sizey*c.h,d=u*h.x[e.xanchor].offset,p=f*h.y[e.yanchor].offset,g=h.x[e.xanchor].sizing+h.y[e.yanchor].sizing,m=(i?i.r2p(e.x)+i._offset:e.x*c.w+c.l)+d,v=(s?s.r2p(e.y)+s._offset:c.h-e.y*c.h+c.t)+p;switch(e.sizing){case"fill":g+=" slice";break;case"stretch":g="none"}r.attr({x:m,y:v,width:u,height:f,preserveAspectRatio:g,opacity:e.opacity});var y=i?i._id:"",x=s?s._id:"",b=y+x;b&&r.call(a.setClipUrl,"clip"+l._uid+b)}for(var l=t._fullLayout,s=[],c=[],u=[],f=0;f=2/3},r.isCenterAnchor=function(t){return"center"===t.xanchor||"auto"===t.xanchor&&t.x>1/3&&t.x<2/3},r.isBottomAnchor=function(t){return"bottom"===t.yanchor||"auto"===t.yanchor&&t.y<=1/3},r.isMiddleAnchor=function(t){ -return"middle"===t.yanchor||"auto"===t.yanchor&&t.y>1/3&&t.y<2/3}},{}],67:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),a=t("../color/attributes"),o=t("../../lib/extend").extendFlat;e.exports={bgcolor:{valType:"color"},bordercolor:{valType:"color",dflt:a.defaultLine},borderwidth:{valType:"number",min:0,dflt:0},font:o({},n,{}),orientation:{valType:"enumerated",values:["v","h"],dflt:"v"},traceorder:{valType:"flaglist",flags:["reversed","grouped"],extras:["normal"]},tracegroupgap:{valType:"number",min:0,dflt:10},x:{valType:"number",min:-2,max:3,dflt:1.02},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left"},y:{valType:"number",min:-2,max:3,dflt:1},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"auto"}}},{"../../lib/extend":119,"../../plots/font_attributes":169,"../color/attributes":29}],68:[function(t,e,r){"use strict";e.exports={scrollBarWidth:4,scrollBarHeight:20,scrollBarColor:"#808BA4",scrollBarMargin:4}},{}],69:[function(t,e,r){"use strict";var n=t("../../registry"),a=t("../../lib"),o=t("./attributes"),i=t("../../plots/layout_attributes"),l=t("./helpers");e.exports=function(t,e,r){function s(t,e){return a.coerce(h,p,o,t,e)}for(var c,u,f,d,h=t.legend||{},p=e.legend={},g=0,m="normal",v=0;v1);if(x!==!1){if(s("bgcolor",e.paper_bgcolor),s("bordercolor"),s("borderwidth"),a.coerceFont(s,"font",e.font),s("orientation"),"h"===p.orientation){var b=t.xaxis;b&&b.rangeslider&&b.rangeslider.visible?(c=0,f="left",u=1.1,d="bottom"):(c=0,f="left",u=-.1,d="top")}s("traceorder",m),l.isGrouped(e.legend)&&s("tracegroupgap"),s("x",c),s("xanchor",f),s("y",u),s("yanchor",d),a.noneOrAll(h,p,["x","y"])}}},{"../../lib":122,"../../plots/layout_attributes":171,"../../registry":188,"./attributes":67,"./helpers":72}],70:[function(t,e,r){"use strict";function n(t,e){function r(r){v.convertToTspans(r,function(){r.selectAll("tspan.line").attr({x:r.attr("x")}),t.call(o,e)})}var n=t.data()[0][0],a=e._fullLayout,i=n.trace,l=h.traceIs(i,"pie"),s=i.index,c=l?n.label:i.name,f=t.selectAll("text.legendtext").data([0]);f.enter().append("text").classed("legendtext",!0),f.attr({x:40,y:0,"data-unformatted":c}).style("text-anchor","start").classed("user-select-none",!0).call(g.font,a.legend.font).text(c),e._context.editable&&!l?f.call(v.makeEditable).call(r).on("edit",function(t){this.attr({"data-unformatted":t}),this.text(t).call(r),this.text()||(t=" ");var a,o=n.trace._fullInput||{};if(["ohlc","candlestick"].indexOf(o.type)!==-1){var i=n.trace.transforms,l=i[i.length-1].direction;a=l+".legenditem.name"}else a="name";u.restyle(e,a,t,s)}):f.call(r)}function a(t,e){var r=e._fullLayout.hiddenlabels?e._fullLayout.hiddenlabels.slice():[],n=t.selectAll("rect").data([0]);n.enter().append("rect").classed("legendtoggle",!0).style("cursor","pointer").attr("pointer-events","all").call(m.fill,"rgba(0,0,0,0)"),n.on("click",function(){if(!e._dragged){var n,a,o=t.data()[0][0],i=e._fullData,l=o.trace,s=l.legendgroup,c=[];if(h.traceIs(l,"pie")){var f=o.label,d=r.indexOf(f);d===-1?r.push(f):r.splice(d,1),u.relayout(e,"hiddenlabels",r)}else{if(""===s)c=[l.index];else for(var p=0;ptspan"),d=u[0].length||1;r=l*d,n=c.node()&&g.bBox(c.node()).width;var h=l*(.3+(1-d)/2);c.attr("y",h),u.attr("y",h)}r=Math.max(r,16)+3,a.height=r,a.width=n}function i(t,e,r){var n=t._fullLayout,a=n.legend,o=a.borderwidth,i=_.isGrouped(a);if(_.isVertical(a))i&&e.each(function(t,e){f.setTranslate(this,0,e*a.tracegroupgap)}),a.width=0,a.height=0,r.each(function(t){var e=t[0],r=e.height,n=e.width;f.setTranslate(this,o,5+o+a.height+r/2),a.height+=r,a.width=Math.max(a.width,n)}),a.width+=45+2*o,a.height+=10+2*o,i&&(a.height+=(a._lgroupsLength-1)*a.tracegroupgap),a.width=Math.ceil(a.width),a.height=Math.ceil(a.height),r.each(function(e){var r=e[0],n=c.select(this).select(".legendtoggle");n.call(g.setRect,0,-r.height/2,(t._context.editable?0:a.width)+40,r.height)});else if(i){a.width=0,a.height=0;for(var l=[a.width],s=e.data(),u=0,d=s.length;un.width-(n.margin.r+n.margin.l)&&(x=0,m+=v,a.height=a.height+v,v=0),f.setTranslate(this,o+x,5+o+e.height/2+m),a.width+=i+r,a.height=Math.max(a.height,e.height),x+=i+r,v=Math.max(e.height,v)}),a.width+=2*o,a.height+=10+2*o,a.width=Math.ceil(a.width),a.height=Math.ceil(a.height),r.each(function(e){var r=e[0],n=c.select(this).select(".legendtoggle");n.call(g.setRect,0,-r.height/2,t._context.editable?0:a.width,r.height)})}}function l(t){var e=t._fullLayout,r=e.legend,n="left";w.isRightAnchor(r)?n="right":w.isCenterAnchor(r)&&(n="center");var a="top";w.isBottomAnchor(r)?a="bottom":w.isMiddleAnchor(r)&&(a="middle"),d.autoMargin(t,"legend",{x:r.x,y:r.y,l:r.width*({right:1,center:.5}[n]||0),r:r.width*({left:1,center:.5}[n]||0),b:r.height*({top:1,middle:.5}[a]||0),t:r.height*({bottom:1,middle:.5}[a]||0)})}function s(t){var e=t._fullLayout,r=e.legend,n="left";w.isRightAnchor(r)?n="right":w.isCenterAnchor(r)&&(n="center"),d.autoMargin(t,"legend",{x:r.x,y:.5,l:r.width*({right:1,center:.5}[n]||0),r:r.width*({left:1,center:.5}[n]||0),b:0,t:0})}var c=t("d3"),u=t("../../plotly"),f=t("../../lib"),d=t("../../plots/plots"),h=t("../../registry"),p=t("../dragelement"),g=t("../drawing"),m=t("../color"),v=t("../../lib/svg_text_utils"),y=t("./constants"),x=t("./get_legend_data"),b=t("./style"),_=t("./helpers"),w=t("./anchor_utils");e.exports=function(t){function e(t,e){L.attr("data-scroll",e).call(f.setTranslate,0,e),z.call(g.setRect,j,t,y.scrollBarWidth,y.scrollBarHeight),A.select("rect").attr({y:v.borderwidth-e})}var r=t._fullLayout,o="legend"+r._uid;if(r._infolayer&&t.calcdata){var v=r.legend,_=r.showlegend&&x(t.calcdata,v),k=r.hiddenlabels||[];if(!r.showlegend||!_.length)return r._infolayer.selectAll(".legend").remove(),r._topdefs.select("#"+o).remove(),void d.autoMargin(t,"legend");var M=r._infolayer.selectAll("g.legend").data([0]);M.enter().append("g").attr({class:"legend","pointer-events":"all"});var A=r._topdefs.selectAll("#"+o).data([0]);A.enter().append("clipPath").attr("id",o).append("rect");var T=M.selectAll("rect.bg").data([0]);T.enter().append("rect").attr({class:"bg","shape-rendering":"crispEdges"}),T.call(m.stroke,v.bordercolor),T.call(m.fill,v.bgcolor),T.style("stroke-width",v.borderwidth+"px");var L=M.selectAll("g.scrollbox").data([0]);L.enter().append("g").attr("class","scrollbox");var z=M.selectAll("rect.scrollbar").data([0]);z.enter().append("rect").attr({class:"scrollbar",rx:20,ry:2,width:0,height:0}).call(m.fill,"#808BA4");var C=L.selectAll("g.groups").data(_);C.enter().append("g").attr("class","groups"),C.exit().remove();var S=C.selectAll("g.traces").data(f.identity);S.enter().append("g").attr("class","traces"),S.exit().remove(),S.call(b).style("opacity",function(t){var e=t[0].trace;return h.traceIs(e,"pie")?k.indexOf(t[0].label)!==-1?.5:1:"legendonly"===e.visible?.5:1}).each(function(){c.select(this).call(n,t).call(a,t)});var O=0!==M.enter().size();O&&(i(t,C,S),l(t));var D=0,P=r.width,N=0,E=r.height;i(t,C,S),v.height>E?s(t):l(t);var I=r._size,R=I.l+I.w*v.x,F=I.t+I.h*(1-v.y);w.isRightAnchor(v)?R-=v.width:w.isCenterAnchor(v)&&(R-=v.width/2),w.isBottomAnchor(v)?F-=v.height:w.isMiddleAnchor(v)&&(F-=v.height/2);var j=v.width;I.w;R+j>P&&(R=P-j),RB?(F=I.t,q=B):(F+q>E&&(F=E-q),Fr[1])return r[1]}return a}function r(t){return t[0]}var n,a,o=t[0],i=o.trace,l=h.hasMarkers(i),c=h.hasText(i),d=h.hasLines(i);if(l||c||d){var p={},g={};l&&(p.mc=e("marker.color",r),p.mo=e("marker.opacity",u.mean,[.2,1]),p.ms=e("marker.size",u.mean,[2,16]),p.mlc=e("marker.line.color",r),p.mlw=e("marker.line.width",u.mean,[0,5]),g.marker={sizeref:1,sizemin:1,sizemode:"diameter"}),d&&(g.line={width:e("line.width",r,[0,10])}),c&&(p.tx="Aa",p.tp=e("textposition",r),p.ts=10,p.tc=e("textfont.color",r),p.tf=e("textfont.family",r)),n=[u.minExtend(o,p)],a=u.minExtend(i,g)}var m=s.select(this).select("g.legendpoints"),v=m.selectAll("path.scatterpts").data(l?n:[]);v.enter().append("path").classed("scatterpts",!0).attr("transform","translate(20,0)"),v.exit().remove(),v.call(f.pointStyle,a),l&&(n[0].mrc=3);var y=m.selectAll("g.pointtext").data(c?n:[]);y.enter().append("g").classed("pointtext",!0).append("text").attr("transform","translate(20,0)"),y.exit().remove(),y.selectAll("text").call(f.textPointStyle,a)}function o(t){var e=t[0].trace,r=e.marker||{},n=r.line||{},a=s.select(this).select("g.legendpoints").selectAll("path.legendbar").data(c.traceIs(e,"bar")?[t]:[]);a.enter().append("path").classed("legendbar",!0).attr("d","M6,6H-6V-6H6Z").attr("transform","translate(20,0)"),a.exit().remove(),a.each(function(t){var e=(t.mlw+1||n.width+1)-1,a=s.select(this);a.style("stroke-width",e+"px").call(d.fill,t.mc||r.color),e&&a.call(d.stroke,t.mlc||n.color)})}function i(t){var e=t[0].trace,r=s.select(this).select("g.legendpoints").selectAll("path.legendbox").data(c.traceIs(e,"box")&&e.visible?[t]:[]);r.enter().append("path").classed("legendbox",!0).attr("d","M6,6H-6V-6H6Z").attr("transform","translate(20,0)"),r.exit().remove(),r.each(function(t){var r=(t.lw+1||e.line.width+1)-1,n=s.select(this);n.style("stroke-width",r+"px").call(d.fill,t.fc||e.fillcolor),r&&n.call(d.stroke,t.lc||e.line.color)})}function l(t){var e=t[0].trace,r=s.select(this).select("g.legendpoints").selectAll("path.legendpie").data(c.traceIs(e,"pie")&&e.visible?[t]:[]);r.enter().append("path").classed("legendpie",!0).attr("d","M6,6H-6V-6H6Z").attr("transform","translate(20,0)"),r.exit().remove(),r.size()&&r.call(p,t[0],e)}var s=t("d3"),c=t("../../registry"),u=t("../../lib"),f=t("../drawing"),d=t("../color"),h=t("../../traces/scatter/subtypes"),p=t("../../traces/pie/style_one");e.exports=function(t){t.each(function(t){var e=s.select(this),r=e.selectAll("g.legendfill").data([t]);r.enter().append("g").classed("legendfill",!0);var n=e.selectAll("g.legendlines").data([t]);n.enter().append("g").classed("legendlines",!0);var a=e.selectAll("g.legendsymbols").data([t]);a.enter().append("g").classed("legendsymbols",!0),a.style("opacity",t[0].trace.opacity),a.selectAll("g.legendpoints").data([t]).enter().append("g").classed("legendpoints",!0)}).each(o).each(i).each(l).each(n).each(a)}},{"../../lib":122,"../../registry":188,"../../traces/pie/style_one":269,"../../traces/scatter/subtypes":291,"../color":30,"../drawing":53,d3:14}],75:[function(t,e,r){"use strict";function n(t,e){var r=e.currentTarget,n=r.getAttribute("data-attr"),a=r.getAttribute("data-val")||!0,o=t._fullLayout,i={};if("zoom"===n){for(var l,s,u="in"===a?.5:2,d=(1+u)/2,h=(1-u)/2,p=f.list(t,null,!0),g=0;g1)return n(["resetViews","toggleHover"]),i(m,r);u&&(n(["zoom3d","pan3d","orbitRotation","tableRotation"]),n(["resetCameraDefault3d","resetCameraLastSave3d"]),n(["hoverClosest3d"])),d&&(n(["zoomInGeo","zoomOutGeo","resetGeo"]),n(["hoverClosestGeo"]));var v=a(l),y=[];return((c||p)&&!v||g)&&(y=["zoom2d","pan2d"]),(c||g)&&o(s)&&(y.push("select2d"),y.push("lasso2d")),y.length&&n(y),!c&&!p||v||g||n(["zoomIn2d","zoomOut2d","autoScale2d","resetScale2d"]),c&&h?n(["toggleHover"]):p?n(["hoverClosestGl2d"]):c?n(["hoverClosestCartesian","hoverCompareCartesian"]):h&&n(["hoverClosestPie"]),i(m,r)}function a(t){for(var e=s.list({_fullLayout:t},null,!0),r=!0,n=0;n0);if(p){var g=a(e,r,s);u("x",g[0]),u("y",g[1]),o.noneOrAll(t,e,["x","y"]),u("xanchor"),u("yanchor"),o.coerceFont(u,"font",r.font);var m=u("bgcolor");u("activecolor",i.contrast(m,c.lightAmount,c.darkAmount)),u("bordercolor"),u("borderwidth")}}},{"../../lib":122,"../color":30,"./attributes":79,"./button_attributes":80,"./constants":81}],83:[function(t,e,r){"use strict";function n(t){for(var e=v.list(t,"x",!0),r=[],n=0;np&&(p=d)));return p>=h?[h,p]:void 0}}var a=t("../../lib"),o=t("../../plots/cartesian/axes"),i=t("./constants"),l=t("./helpers");e.exports=function(t){var e=t._fullLayout,r=a.filterVisible(e.shapes);if(r.length&&t._fullData.length)for(var l=0;le;o--)f(t,o).selectAll('[data-index="'+(o-1)+'"]').attr("data-index",o),a(t,o)}function u(t,e,r,n){function a(r){var n={"data-index":e,"fill-rule":"evenodd",d:h(t,z)},a=z.line.width?z.line.color:"rgba(0,0,0,0)",o=r.append("path").attr(n).style("opacity",z.opacity).call(y.stroke,a).call(y.fill,z.fillcolor).call(x.dashLine,z.line.dash,z.line.width);z.classes&&o.classed(z.classes,!0),C&&o.call(x.setClipUrl,"clip"+t._fullLayout._uid+C)}var o,i;f(t,e).selectAll('[data-index="'+e+'"]').remove();var l=t.layout.shapes[e];if(l){var s={};"string"==typeof r&&r?s[r]=n:m.isPlainObject(r)&&(s=r);var c=Object.keys(s);for(o=0;ol&&(t="X"),t});return n>l&&(s=s.replace(/[\s,]*X.*/,""),m.log("Ignoring extra params in segment "+t)),a+s})}var g=t("fast-isnumeric"),m=(t("../../plotly"),t("../../lib")),v=t("../../plots/cartesian/axes"),y=t("../color"),x=t("../drawing"),b=(t("../dragelement"),t("../../lib/setcursor"),t("./constants")),_=t("./helpers"),w=t("./shape_defaults"),k=t("./defaults");e.exports={draw:n,drawOne:a}},{"../../lib":122,"../../lib/setcursor":132,"../../plotly":144,"../../plots/cartesian/axes":149,"../color":30,"../dragelement":51,"../drawing":53,"./constants":93,"./defaults":94,"./helpers":96,"./shape_defaults":98,"fast-isnumeric":17}],96:[function(t,e,r){"use strict";r.rangeToShapePosition=function(t){return"log"===t.type?t.r2d:function(t){return t}},r.shapePositionToRange=function(t){return"log"===t.type?t.d2r:function(t){return t}},r.decodeDate=function(t){return function(e){return e.replace&&(e=e.replace("_"," ")),t(e)}},r.encodeDate=function(t){return function(e){return t(e).replace(" ","_")}},r.getDataToPixel=function(t,e,n){var a,o=t._fullLayout._size;if(e){var i=r.shapePositionToRange(e);a=function(t){return e._offset+e.r2p(i(t,!0))},"date"===e.type&&(a=r.decodeDate(a))}else a=n?function(t){return o.t+o.h*(1-t)}:function(t){return o.l+o.w*t};return a},r.getPixelToData=function(t,e,n){var a,o=t._fullLayout._size;if(e){var i=r.rangeToShapePosition(e);a=function(t){return i(e.p2r(t-e._offset))}}else a=n?function(t){return 1-(t-o.t)/o.h}:function(t){return(t-o.l)/o.w};return a}},{}],97:[function(t,e,r){"use strict";var n=t("./draw");e.exports={moduleType:"component",name:"shapes",layoutAttributes:t("./attributes"),supplyLayoutDefaults:t("./defaults"),calcAutorange:t("./calc_autorange"),draw:n.draw,drawOne:n.drawOne}},{"./attributes":91,"./calc_autorange":92,"./defaults":94,"./draw":95}],98:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("../../plots/cartesian/axes"),o=t("./attributes"),i=t("./helpers");e.exports=function(t,e,r,l,s){function c(r,a){return n.coerce(t,e,o,r,a)}l=l||{},s=s||{};var u=c("visible",!s.itemIsNotPlainObject);if(!u)return e;c("layer"),c("opacity"),c("fillcolor"),c("line.color"),c("line.width"),c("line.dash");for(var f=t.path?"path":"rect",d=c("type",f),h=["x","y"],p=0;p<2;p++){var g=h[p],m={_fullLayout:r},v=a.coerceRef(t,e,m,g,"","paper");if("path"!==d){var y,x,b,_=.25,w=.75;"paper"!==v?(y=a.getFromId(m,v),b=i.rangeToShapePosition(y),x=i.shapePositionToRange(y)):x=b=n.identity;var k=g+"0",M=g+"1",A=t[k],T=t[M];t[k]=x(t[k],!0),t[M]=x(t[M],!0),a.coercePosition(e,m,c,v,k,_),a.coercePosition(e,m,c,v,M,w),e[k]=b(e[k]),e[M]=b(e[M]),t[k]=A,t[M]=T}}return"path"===d?c("path"):n.noneOrAll(t,e,["x0","x1","y0","y1"]),t.classes&&(e.classes=t.classes),e}},{"../../lib":122,"../../plots/cartesian/axes":149,"./attributes":91,"./helpers":96}],99:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),a=t("../../plots/pad_attributes"),o=t("../../lib/extend").extendFlat,i=t("../../lib/extend").extendDeep,l=t("../../plots/animation_attributes"),s=t("./constants"),c={_isLinkedToArray:"step",method:{valType:"enumerated",values:["restyle","relayout","animate","update"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string"},value:{valType:"string"}};e.exports={_isLinkedToArray:"slider",visible:{valType:"boolean",dflt:!0},active:{valType:"number",min:0,dflt:0},steps:c,lenmode:{valType:"enumerated",values:["fraction","pixels"],dflt:"fraction"},len:{valType:"number",min:0,dflt:1},x:{valType:"number",min:-2,max:3,dflt:0},pad:i({},a,{},{t:{dflt:20}}),xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left"},y:{valType:"number",min:-2,max:3,dflt:0},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},transition:{duration:{valType:"number",min:0,dflt:150},easing:{valType:"enumerated",values:l.transition.easing.values,dflt:"cubic-in-out"}},currentvalue:{visible:{valType:"boolean",dflt:!0},xanchor:{valType:"enumerated",values:["left","center","right"],dflt:"left"},offset:{valType:"number",dflt:10},prefix:{valType:"string"},suffix:{valType:"string"},font:o({},n,{})},font:o({},n,{}),activebgcolor:{valType:"color",dflt:s.gripBgActiveColor},bgcolor:{valType:"color",dflt:s.railBgColor},bordercolor:{valType:"color",dflt:s.railBorderColor},borderwidth:{valType:"number",min:0,dflt:s.railBorderWidth},ticklen:{valType:"number",min:0,dflt:s.tickLength},tickcolor:{valType:"color",dflt:s.tickColor},tickwidth:{valType:"number",min:0,dflt:1},minorticklen:{valType:"number",min:0,dflt:s.minorTickLength}}},{"../../lib/extend":119,"../../plots/animation_attributes":145,"../../plots/font_attributes":169,"../../plots/pad_attributes":172,"./constants":100}],100:[function(t,e,r){"use strict";e.exports={name:"sliders",containerClassName:"slider-container",groupClassName:"slider-group",inputAreaClass:"slider-input-area",railRectClass:"slider-rail-rect",railTouchRectClass:"slider-rail-touch-rect",gripRectClass:"slider-grip-rect",tickRectClass:"slider-tick-rect",inputProxyClass:"slider-input-proxy",labelsClass:"slider-labels",labelGroupClass:"slider-label-group",labelClass:"slider-label",currentValueClass:"slider-current-value",railHeight:5,menuIndexAttrName:"slider-active-index",autoMarginIdRoot:"slider-",minWidth:30,minHeight:30,textPadX:40,fontSizeToHeight:1.3,arrowOffsetX:4,railRadius:2,railWidth:5,railBorder:4,railBorderWidth:1,railBorderColor:"#bec8d9",railBgColor:"#f8fafc",railInset:8,stepInset:10,gripRadius:10,gripWidth:20,gripHeight:20,gripBorder:20,gripBorderWidth:1,gripBorderColor:"#bec8d9",gripBgColor:"#f6f8fa",gripBgActiveColor:"#dbdde0",labelPadding:8,labelOffset:0,tickWidth:1,tickColor:"#333",tickOffset:25,tickLength:7,minorTickOffset:25,minorTickColor:"#333",minorTickLength:4,currentValuePadding:8,currentValueInset:0}},{}],101:[function(t,e,r){"use strict";function n(t,e,r){function n(r,n){return o.coerce(t,e,l,r,n)}var i=a(t,e),s=n("visible",i.length>0);if(s){n("active"),n("x"),n("y"),o.noneOrAll(t,e,["x","y"]),n("xanchor"),n("yanchor"),n("len"),n("lenmode"),n("pad.t"),n("pad.r"),n("pad.b"),n("pad.l"),o.coerceFont(n,"font",r.font);var c=n("currentvalue.visible");c&&(n("currentvalue.xanchor"),n("currentvalue.prefix"),n("currentvalue.suffix"),n("currentvalue.offset"),o.coerceFont(n,"currentvalue.font",e.font)),n("transition.duration"),n("transition.easing"),n("bgcolor"),n("activebgcolor"),n("bordercolor"),n("borderwidth"),n("ticklen"),n("tickwidth"),n("tickcolor"),n("minorticklen")}}function a(t,e){function r(t,e){return o.coerce(n,a,u,t,e)}for(var n,a,i=t.steps||[],l=e.steps=[],s=0;s0&&(i=i.transition().duration(e.transition.duration).ease(e.transition.easing)),i.attr("transform","translate("+(o-.5*C.gripWidth)+","+e.currentValueTotalHeight+")")}}function v(t,e){return t.inputAreaStart+C.stepInset+(t.inputAreaLength-2*C.stepInset)*Math.min(1,Math.max(0,e))}function y(t,e){return Math.min(1,Math.max(0,(e-C.stepInset-t.inputAreaStart)/(t.inputAreaLength-2*C.stepInset-2*t.inputAreaStart)))}function x(t,e,r){var n=t.selectAll("rect."+C.railTouchRectClass).data([0]);n.enter().append("rect").classed(C.railTouchRectClass,!0).call(h,e,t,r).style("pointer-events","all"),n.attr({width:r.inputAreaLength,height:Math.max(r.inputAreaWidth,C.tickOffset+r.ticklen+r.labelHeight)}).call(A.fill,r.bgcolor).attr("opacity",0),M.setTranslate(n,0,r.currentValueTotalHeight)}function b(t,e){var r=t.selectAll("rect."+C.railRectClass).data([0]);r.enter().append("rect").classed(C.railRectClass,!0);var n=e.inputAreaLength-2*C.railInset;r.attr({width:n,height:C.railWidth,rx:C.railRadius,ry:C.railRadius,"shape-rendering":"crispEdges"}).call(A.stroke,e.bordercolor).call(A.fill,e.bgcolor).style("stroke-width",e.borderwidth+"px"),M.setTranslate(r,C.railInset,.5*(e.inputAreaWidth-C.railWidth)+e.currentValueTotalHeight); -}function _(t){for(var e=t._fullLayout._pushmargin||{},r=Object.keys(e),n=0;n0?[0]:[]);if(l.enter().append("g").classed(C.containerClassName,!0).style("cursor","ew-resize"),l.exit().remove(),l.exit().size()&&_(t),0!==r.length){var s=l.selectAll("g."+C.groupClassName).data(r,a);s.enter().append("g").classed(C.groupClassName,!0),s.exit().each(function(e){w.select(this).remove(),e._commandObserver.remove(),delete e._commandObserver,k.autoMargin(t,C.autoMarginIdRoot+e._index)});for(var c=0;c0||d<0){var h={left:[-r,0],right:[r,0],top:[0,-r],bottom:[0,r]}[x.side];e.attr("transform","translate("+h+")")}}}function p(){L=0,z=!0,C=O,k._infolayer.select("."+e).attr({"data-unformatted":C}).text(C).on("mouseover.opacity",function(){n.select(this).transition().duration(100).style("opacity",1)}).on("mouseout.opacity",function(){n.select(this).transition().duration(1e3).style("opacity",0)})}var g=r.propContainer,m=r.propName,v=r.traceIndex,y=r.dfltName,x=r.avoid||{},b=r.attributes,_=r.transform,w=r.containerGroup,k=t._fullLayout,M=g.titlefont.family,A=g.titlefont.size,T=g.titlefont.color,L=1,z=!1,C=g.title.trim();""===C&&(L=0),C.match(/Click to enter .+ title/)&&(L=.2,z=!0),w||(w=k._infolayer.selectAll(".g-"+e).data([0]),w.enter().append("g").classed("g-"+e,!0));var S=w.selectAll("text").data([0]);S.enter().append("text"),S.text(C).attr("class",e),S.attr({"data-unformatted":C}).call(f);var O="Click to enter "+y+" title",D=t._context.editable;D&&(g===k?D=t._context.editableMainTitle:g===k.xaxis?D=t._context.editableAxisXTitle:g===k.yaxis?D=t._context.editableAxisYTitle:g===k.yaxis2?D=t._context.editableAxisY2Title:g===k.xaxis2&&(D=t._context.editableAxisX2Title)),D?(C||p(),S.call(u.makeEditable).on("edit",function(e){void 0!==v?o.restyle(t,m,e,v):o.relayout(t,m,e)}).on("cancel",function(){this.text(this.attr("data-unformatted")).call(f)}).on("input",function(t){this.text(t||" ").attr(b).selectAll("tspan.line").attr(b)})):C&&!C.match(/Click to enter .+ title/)||S.remove(),S.classed("js-placeholder",z),g._titleElement=S}},{"../../lib":122,"../../lib/svg_text_utils":134,"../../plotly":144,"../../plots/plots":173,"../color":30,"../drawing":53,d3:14,"fast-isnumeric":17}],105:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),a=t("../color/attributes"),o=t("../../lib/extend").extendFlat,i=t("../../plots/pad_attributes"),l={_isLinkedToArray:"button",method:{valType:"enumerated",values:["restyle","relayout","animate","update"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string",dflt:""}};e.exports={_isLinkedToArray:"updatemenu",visible:{valType:"boolean"},type:{valType:"enumerated",values:["dropdown","buttons"],dflt:"dropdown"},direction:{valType:"enumerated",values:["left","right","up","down"],dflt:"down"},active:{valType:"integer",min:-1,dflt:0},showactive:{valType:"boolean",dflt:!0},buttons:l,x:{valType:"number",min:-2,max:3,dflt:-.05},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"right"},y:{valType:"number",min:-2,max:3,dflt:1},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},pad:o({},i,{}),font:o({},n,{}),bgcolor:{valType:"color"},bordercolor:{valType:"color",dflt:a.borderLine},borderwidth:{valType:"number",min:0,dflt:1}}},{"../../lib/extend":119,"../../plots/font_attributes":169,"../../plots/pad_attributes":172,"../color/attributes":29}],106:[function(t,e,r){"use strict";e.exports={name:"updatemenus",containerClassName:"updatemenu-container",headerGroupClassName:"updatemenu-header-group",headerClassName:"updatemenu-header",headerArrowClassName:"updatemenu-header-arrow",dropdownButtonGroupClassName:"updatemenu-dropdown-button-group",dropdownButtonClassName:"updatemenu-dropdown-button",buttonClassName:"updatemenu-button",itemRectClassName:"updatemenu-item-rect",itemTextClassName:"updatemenu-item-text",menuIndexAttrName:"updatemenu-active-index",autoMarginIdRoot:"updatemenu-",blankHeaderOpts:{label:" "},minWidth:30,minHeight:30,textPadX:24,arrowPadX:16,fontSizeToHeight:1.3,rx:2,ry:2,textOffsetX:12,textOffsetY:3,arrowOffsetX:4,gapButtonHeader:5,gapButton:2,activeColor:"#F4FAFF",hoverColor:"#F4FAFF"}},{}],107:[function(t,e,r){"use strict";function n(t,e,r){function n(r,n){return o.coerce(t,e,l,r,n)}var i=a(t,e),s=n("visible",i.length>0);s&&(n("active"),n("direction"),n("type"),n("showactive"),n("x"),n("y"),o.noneOrAll(t,e,["x","y"]),n("xanchor"),n("yanchor"),n("pad.t"),n("pad.r"),n("pad.b"),n("pad.l"),o.coerceFont(n,"font",r.font),n("bgcolor",r.paper_bgcolor),n("bordercolor"),n("borderwidth"))}function a(t,e){function r(t,e){return o.coerce(n,a,u,t,e)}for(var n,a,i=t.buttons||[],l=e.buttons=[],s=0;s0?[0]:[]);if(c.enter().append("g").classed(T.containerClassName,!0).style("cursor","pointer"),c.exit().remove(),c.exit().size()&&y(t),0!==r.length){var u=c.selectAll("g."+T.headerGroupClassName).data(r,a);u.enter().append("g").classed(T.headerGroupClassName,!0);var f=c.selectAll("g."+T.dropdownButtonGroupClassName).data([0]);f.enter().append("g").classed(T.dropdownButtonGroupClassName,!0).style("pointer-events","all"),u.enter().size()&&f.call(v).attr(T.menuIndexAttrName,"-1"),u.exit().each(function(e){x.select(this).remove(),f.call(v).attr(T.menuIndexAttrName,"-1"),b.autoMargin(t,T.autoMarginIdRoot+e._index)});for(var d=0;d",nbsp:"\xa0",times:"\xd7",plusmn:"\xb1",deg:"\xb0"},unicodeToEntity:{"&":"amp","<":"lt",">":"gt",'"':"quot","'":"#x27","/":"#x2F"}}},{}],112:[function(t,e,r){"use strict";r.xmlns="http://www.w3.org/2000/xmlns/",r.svg="http://www.w3.org/2000/svg",r.xlink="http://www.w3.org/1999/xlink",r.svgAttrs={xmlns:r.svg,"xmlns:xlink":r.xlink}},{}],113:[function(t,e,r){"use strict";var n=t("./plotly");r.version="1.20.2-d26",t("es6-promise").polyfill(),t("../build/plotcss"),t("./fonts/mathjax_config"),r.plot=n.plot,r.newPlot=n.newPlot,r.restyle=n.restyle,r.relayout=n.relayout,r.redraw=n.redraw,r.update=n.update,r.extendTraces=n.extendTraces,r.prependTraces=n.prependTraces,r.addTraces=n.addTraces,r.deleteTraces=n.deleteTraces,r.moveTraces=n.moveTraces,r.purge=n.purge,r.setPlotConfig=t("./plot_api/set_plot_config"),r.register=t("./plot_api/register"),r.toImage=t("./plot_api/to_image"),r.downloadImage=t("./snapshot/download"),r.validate=t("./plot_api/validate"),r.addFrames=n.addFrames,r.deleteFrames=n.deleteFrames,r.animate=n.animate,r.register(t("./traces/scatter")),r.register([t("./components/legend"),t("./components/annotations"),t("./components/shapes"),t("./components/images"),t("./components/updatemenus"),t("./components/sliders"),t("./components/rangeslider"),t("./components/rangeselector")]),r.Icons=t("../build/ploticon"),r.Plots=n.Plots,r.Fx=n.Fx,r.Snapshot=t("./snapshot"),r.PlotSchema=t("./plot_api/plot_schema"),r.Queue=t("./lib/queue");var a=t("./components/color");r.colorDefaults=a.overrideColorDefaults,r.d3=t("d3")},{"../build/plotcss":1,"../build/ploticon":2,"./components/annotations":28,"./components/color":30,"./components/images":65,"./components/legend":73,"./components/rangeselector":85,"./components/rangeslider":90,"./components/shapes":97,"./components/sliders":103,"./components/updatemenus":109,"./fonts/mathjax_config":114,"./lib/queue":130,"./plot_api/plot_schema":138,"./plot_api/register":139,"./plot_api/set_plot_config":140,"./plot_api/to_image":142,"./plot_api/validate":143,"./plotly":144,"./snapshot":193,"./snapshot/download":190,"./traces/scatter":281,d3:14,"es6-promise":15}],114:[function(t,e,r){"use strict";"undefined"!=typeof MathJax?(r.MathJax=!0,MathJax.Hub.Config({messageStyle:"none",skipStartupTypeset:!0,displayAlign:"left",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]]}}),MathJax.Hub.Configured()):r.MathJax=!1},{}],115:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../constants/numerical").BADNUM,o=/^['"%,$#\s']+/,i=/['"%,$#\s']+$/;e.exports=function(t){return"string"==typeof t&&(t=t.replace(o,"").replace(i,"")),n(t)?Number(t):a}},{"../constants/numerical":110,"fast-isnumeric":17}],116:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("tinycolor2"),o=t("../components/colorscale/get_scale"),i=(Object.keys(t("../components/colorscale/scales")),t("./nested_property")),l=/^([2-9]|[1-9][0-9]+)$/;r.valObjects={data_array:{coerceFunction:function(t,e,r){Array.isArray(t)?e.set(t):void 0!==r&&e.set(r)}},enumerated:{coerceFunction:function(t,e,r,n){n.coerceNumber&&(t=+t),n.values.indexOf(t)===-1?e.set(r):e.set(t)}},boolean:{coerceFunction:function(t,e,r){t===!0||t===!1?e.set(t):e.set(r)}},number:{coerceFunction:function(t,e,r,a){!n(t)||void 0!==a.min&&ta.max?e.set(r):e.set(+t)}},integer:{coerceFunction:function(t,e,r,a){t%1||!n(t)||void 0!==a.min&&ta.max?e.set(r):e.set(+t)}},string:{coerceFunction:function(t,e,r,n){if("string"!=typeof t){var a="number"==typeof t;n.strict!==!0&&a?e.set(String(t)):e.set(r)}else n.noBlank&&!t?e.set(r):e.set(t)}},color:{coerceFunction:function(t,e,r){a(t).isValid()?e.set(t):e.set(r)}},colorscale:{coerceFunction:function(t,e,r){e.set(o(t,r))}},angle:{coerceFunction:function(t,e,r){"auto"===t?e.set("auto"):n(t)?(Math.abs(t)>180&&(t-=360*Math.round(t/360)),e.set(+t)):e.set(r)}},subplotid:{coerceFunction:function(t,e,r){var n=r.length;return"string"==typeof t&&t.substr(0,n)===r&&l.test(t.substr(n))?void e.set(t):void e.set(r)},validateFunction:function(t,e){var r=e.dflt,n=r.length;return t===r||"string"==typeof t&&!(t.substr(0,n)!==r||!l.test(t.substr(n)))}},flaglist:{coerceFunction:function(t,e,r,n){if("string"!=typeof t)return void e.set(r);if((n.extras||[]).indexOf(t)!==-1)return void e.set(t);for(var a=t.split("+"),o=0;o=h&&t<=p?t:s;if("string"!=typeof t&&"number"!=typeof t)return s;var e,n,a,i,l=String(t).trim().split(" ");if(l.length>2)return s;var c=l[0].split("-"),u=!0;""===c[0]&&(u=!1,c.splice(0,1));var g=c.length;if(g>3||3!==g&&l[1]||!g)return s;if(4===c[0].length)e=Number(c[0]);else{if(2!==c[0].length)return s;if(!u)return s;var m=(new Date).getFullYear();e=((Number(c[0])-m+70)%100+200)%100+m-70}if(!o(e))return s;var v=new Date(0,0,1);if(v.setFullYear(u?e:-e),c.length>1){if(n=Number(c[1])-1,c[1].length>2||!(n>=0&&n<=11))return s;if(v.setMonth(n),c.length>2){if(a=Number(c[2]),c[2].length>2||!(a>=1&&a<=31))return s;if(v.setDate(a),v.getDate()!==a)return s;if(l[1]){if(c=l[1].split(":"),c.length>3)return s;if(i=Number(c[0]),c[0].length>2||!c[0].length||!(i>=0&&i<=23))return s;if(v.setHours(i),v.getHours()!==i)return s;if(c.length>1)return a=v.getTime(),n=Number(c[1]),2===c[1].length&&n>=0&&n<=59?(a+=f*n,2===c.length?a:2!==c[2].split(".")[0].length?s:(t=Number(c[2]),t>=0&&t<60?a+t*d:s)):s}}}return v.getTime()},h=r.MIN_MS=r.dateTime2ms("-9999"),p=r.MAX_MS=r.dateTime2ms("9999-12-31 23:59:59.9999"),r.isDateTime=function(t){return r.dateTime2ms(t)!==s};var g=90*c,m=3*u,v=5*f;r.ms2DateTime=function(t,e){if("number"!=typeof t||!(t>=h&&t<=p))return s;e||(e=0);var r=new Date(Math.floor(t)),o=a.time.format("%Y-%m-%d")(r),i=er?Math.max(r,Math.min(e,t)):Math.max(e,Math.min(r,t))},a.bBoxIntersect=function(t,e,r){return r=r||0,t.left<=e.right+r&&e.left<=t.right+r&&t.top<=e.bottom+r&&e.top<=t.bottom+r},a.identity=function(t){return t},a.noop=function(){},a.randstr=function t(e,r,n){if(n||(n=16),void 0===r&&(r=24),r<=0)return"0";var a,o,i,l=Math.log(Math.pow(2,r))/Math.log(n),s="";for(a=2;l===1/0;a*=2)l=Math.log(Math.pow(2,r/a))/Math.log(n)*a;var c=l-Math.floor(l);for(a=0;a-1||u!==1/0&&u>=Math.pow(2,r)?t(e,r,n):s},a.OptionControl=function(t,e){t||(t={}),e||(e="opt");var r={};return r.optionList=[],r._newoption=function(n){n[e]=t,r[n.name]=n,r.optionList.push(n)},r["_"+e]=t,r},a.smooth=function(t,e){if(e=Math.round(e)||0,e<2)return t;var r,n,a,o,i=t.length,l=2*i,s=2*e-1,c=new Array(s),u=new Array(i);for(r=0;r=l&&(a-=l*Math.floor(a/l)),a<0?a=-1-a:a>=i&&(a=l-1-a),o+=t[a]*c[n];u[r]=o}return u},a.syncOrAsync=function(t,e,r){function n(){return a.syncOrAsync(t,e,r)}for(var o,i;t.length;)if(i=t.splice(0,1)[0],o=i(e),o&&o.then)return o.then(n).then(void 0,a.promiseError);return r&&r(e)},a.stripTrailingSlash=function(t){return"/"===t.substr(-1)?t.substr(0,t.length-1):t},a.noneOrAll=function(t,e,r){if(t){var n,a,o=!1,i=!0;for(n=0;n1?a+i[1]:"";if(o&&(i.length>1||l.length>4||r))for(;n.test(l);)l=l.replace(n,"$1"+o+"$2");return l+s}},{"./clean_number":115,"./coerce":116,"./dates":117,"./extend":119,"./filter_unique":120,"./filter_visible":121,"./is_array":123,"./is_plain_object":124,"./loggers":125,"./matrix":126,"./nested_property":127,"./notifier":128,"./search":131,"./stats":133,d3:14}],123:[function(t,e,r){"use strict";e.exports=function(t){return Array.isArray(t)||ArrayBuffer.isView(t)}},{}],124:[function(t,e,r){"use strict";e.exports=function(t){return window&&window.process&&window.process.versions?"[object Object]"===Object.prototype.toString.call(t):"[object Object]"===Object.prototype.toString.call(t)&&Object.getPrototypeOf(t)===Object.prototype}},{}],125:[function(t,e,r){"use strict";var n=t("../plot_api/plot_config"),a=e.exports={};a.log=function(){if(n.logging>1){for(var t=["LOG:"],e=0;e0){for(var t=["WARN:"],e=0;e0){for(var t=["ERROR:"],e=0;e=0;e--){if(n=t[e],i=!1,d(n))for(r=n.length-1;r>=0;r--)c(n[r])?i?n[r]=void 0:n.pop():i=!0;else if("object"==typeof n&&null!==n)for(o=Object.keys(n),i=!1,r=o.length-1;r>=0;r--)c(n[o[r]])&&!a(n[o[r]],o[r])?delete n[o[r]]:i=!0;if(i)return}}function c(t){return void 0===t||null===t||"object"==typeof t&&(d(t)?!t.length:!Object.keys(t).length)}function u(t,e,r){return{set:function(){throw"bad container"},get:function(){},astr:e,parts:r,obj:t}}var f=t("fast-isnumeric"),d=t("./is_array");e.exports=function(t,e){if(f(e))e=String(e);else if("string"!=typeof e||"[-1]"===e.substr(e.length-4))throw"bad property string";for(var r,a,i,l=0,s=e.split(".");lo||nl)&&(!e||!c(t))}function r(t,e){var r=t[0],s=t[1];if(ro||sl)return!1;var c,u,f,d,h,p=n.length,g=n[0][0],m=n[0][1],v=0;for(c=1;cMath.max(u,g)||s>Math.max(f,m)))if(su||Math.abs(n(i,d))>a)return!0;return!1};a.filter=function(t,e){function r(r){t.push(r);var l=n.length,s=a;n.splice(i+1);for(var c=s+1;c1){var l=t.pop();r(l)}return{addPt:r,raw:t,filtered:n}}},{"./matrix":126}],130:[function(t,e,r){"use strict";function n(t,e){for(var r,n=[],o=0;oo.queueLength&&(t.undoQueue.queue.shift(),t.undoQueue.index--)))},i.startSequence=function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!0,t.undoQueue.beginSequence=!0},i.stopSequence=function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!1,t.undoQueue.beginSequence=!1},i.undo=function(t){var e,r;if(t.framework&&t.framework.isPolar)return void t.framework.undo();if(!(void 0===t.undoQueue||isNaN(t.undoQueue.index)||t.undoQueue.index<=0)){for(t.undoQueue.index--,e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;r=t.undoQueue.queue.length)){for(e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;re}function i(t,e){return t>=e}var l=t("fast-isnumeric"),s=t("./loggers");r.findBin=function(t,e,r){if(l(e.start))return r?Math.ceil((t-e.start)/e.size)-1:Math.floor((t-e.start)/e.size);var c,u,f=0,d=e.length,h=0;for(u=e[e.length-1]>=e[0]?r?n:a:r?i:o;f90&&s.log("Long binary search..."),f-1},r.sorterAsc=function(t,e){return t-e},r.sorterDes=function(t,e){return e-t},r.distinctVals=function(t){var e=t.slice();e.sort(r.sorterAsc);for(var n=e.length-1,a=e[n]-e[0]||1,o=a/(n||1)/1e4,i=[e[0]],l=0;le[l]+o&&(a=Math.min(a,e[l+1]-e[l]),i.push(e[l+1]));return{vals:i,minDiff:a}},r.roundUp=function(t,e,r){for(var n,a=0,o=e.length-1,i=0,l=r?0:1,s=r?1:0,c=r?Math.ceil:Math.floor;at.length-1)return t[t.length-1];var r=e%1;return r*t[Math.ceil(e)]+(1-r)*t[Math.floor(e)]}},{"fast-isnumeric":17}],134:[function(t,e,r){"use strict";function n(t,e){return t.node().getBoundingClientRect()[e]}function a(t){return t.replace(/(<|<|<)/g,"\\lt ").replace(/(>|>|>)/g,"\\gt ")}function o(t,e,r){var n="math-output-"+d.randstr([],64),o=f.select("body").append("div").attr({id:n}).style({visibility:"hidden",position:"absolute"}).style({"font-size":e.fontSize+"px"}).text(a(t));MathJax.Hub.Queue(["Typeset",MathJax.Hub,o.node()],function(){var e=f.select("body").select("#MathJax_SVG_glyphs");if(o.select(".MathJax_SVG").empty()||!o.select("svg").node())d.log("There was an error in the tex syntax.",t),r();else{var n=o.select("svg").node().getBoundingClientRect();r(o.select(".MathJax_SVG"),e,n)}o.remove()})}function i(t,e){for(var r=t||"",n=0;n]*>)/).map(function(t){var e=t.match(/<(\/?)([^ >]*)\s*(.*)>/i),n=e&&e[2].toLowerCase(),a=g[n];if(void 0!==a){var o=e[1],i=e[3],l=i.match(/^style\s*=\s*"([^"]+)"\s*/i);if("a"===n){if(o)return"";if("href"!==i.substr(0,4).toLowerCase())return"";var c=i.substr(4).replace(/["']/g,"").replace(/=/,""),u=document.createElement("a");return u.href=c,m.indexOf(u.protocol)===-1?"":''}if("br"===n)return"
";if(o)return"sup"===n?'':"sub"===n?'':"";var f=""}return r.xml_entity_encode(t).replace(/");a>0;a=e.indexOf("
",a+1))n.push(a);var o=0;n.forEach(function(t){for(var r=t+o,n=e.slice(0,r),a="",i=n.length-1;i>=0;i--){var l=n[i].match(/<(\/?).*>/i);if(l&&"
"!==n[i]){l[1]||(a=n[i]);break}}a&&(e.splice(r+1,0,a),e.splice(r,0,""),o+=2)});var i=e.join(""),c=i.split(/
/gi);return c.length>1&&(e=c.map(function(t,e){return''+t+""})),e.join("")}function u(t,e,r){var n,a,o,i=r.horizontalAlign,l=r.verticalAlign||"top",s=t.node().getBoundingClientRect(),c=e.node().getBoundingClientRect();return a="bottom"===l?function(){return s.bottom-n.height}:"middle"===l?function(){return s.top+(s.height-n.height)/2}:function(){return s.top},o="right"===i?function(){return s.right-n.width}:"center"===i?function(){return s.left+(s.width-n.width)/2}:function(){return s.left},function(){return n=this.node().getBoundingClientRect(),this.style({top:a()-c.top+"px",left:o()-c.left+"px","z-index":1e3}),this}}var f=t("d3"),d=t("../lib"),h=t("../constants/xmlns_namespaces"),p=t("../constants/string_mappings");f.selection.prototype.appendSVG=function(t){for(var e=['',t,""].join(""),r=(new DOMParser).parseFromString(e,"application/xml"),n=r.documentElement.firstChild;n;)this.node().appendChild(this.node().ownerDocument.importNode(n,!0)),n=n.nextSibling;return r.querySelector("parsererror")?(d.log(r.querySelector("parsererror div").textContent),null):f.select(this.node().lastChild)},r.html_entity_decode=function(t){var e=f.select("body").append("div").style({display:"none"}).html(""),r=t.replace(/(&[^;]*;)/gi,function(t){return"<"===t?"<":"&rt;"===t?">":e.html(t).text()});return e.remove(),r},r.xml_entity_encode=function(t){return t.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g,"&")},r.convertToTspans=function(t,e){function r(){h.empty()||(p=l.attr("class")+"-math",h.select("svg."+p).remove()),t.text("").style({visibility:"inherit","white-space":"pre"}),u=t.appendSVG(i),u||t.text(a),t.select("a").size()&&t.style("pointer-events","all"),e&&e.call(l)}var a=t.text(),i=c(a),l=t,s=!l.attr("data-notex")&&i.match(/([^$]*)([$]+[^$]*[$]+)([^$]*)/),u=a,h=f.select(l.node().parentNode);if(!h.empty()){var p=l.attr("class")?l.attr("class").split(" ")[0]:"text";p+="-math",h.selectAll("svg."+p).remove(),h.selectAll("g."+p+"-group").remove(),t.style({visibility:null});for(var g=t.node();g&&g.removeAttribute;g=g.parentNode)g.removeAttribute("data-bb");if(s){var m=d.getPlotDiv(l.node());(m&&m._promises||[]).push(new Promise(function(t){l.style({visibility:"hidden"});var a={fontSize:parseInt(l.style("font-size"),10)};o(s[2],a,function(a,o,i){h.selectAll("svg."+p).remove(),h.selectAll("g."+p+"-group").remove();var s=a&&a.select("svg");if(!s||!s.node())return r(),void t();var c=h.append("g").classed(p+"-group",!0).attr({"pointer-events":"none"});c.node().appendChild(s.node()),o&&o.node()&&s.node().insertBefore(o.node().cloneNode(!0),s.node().firstChild),s.attr({class:p,height:i.height,preserveAspectRatio:"xMinYMin meet"}).style({overflow:"visible","pointer-events":"none"});var u=l.style("fill")||"black";s.select("g").attr({fill:u,stroke:u});var f=n(s,"width"),d=n(s,"height"),g=+l.attr("x")-f*{start:0,middle:.5,end:1}[l.attr("text-anchor")||"start"],m=parseInt(l.style("font-size"),10)||n(l,"height"),v=-m/4;"y"===p[0]?(c.attr({transform:"rotate("+[-90,+l.attr("x"),+l.attr("y")]+") translate("+[-f/2,v-d/2]+")"}),s.attr({x:+l.attr("x"),y:+l.attr("y")})):"l"===p[0]?s.attr({x:l.attr("x"),y:v-d/2}):"a"===p[0]?s.attr({x:0,y:v}):s.attr({x:g,y:+l.attr("y")+v-d/2}),e&&e.call(l,c),t(c)})}))}else r();return t}};var g={sup:'font-size:70%" dy="-0.6em',sub:'font-size:70%" dy="0.3em',b:"font-weight:bold",i:"font-style:italic",a:"",span:"",br:"",em:"font-style:italic;font-weight:bold"},m=["http:","https:","mailto:"],v=new RegExp("]*)?/?>","g"),y=Object.keys(p.entityToUnicode).map(function(t){return{regExp:new RegExp("&"+t+";","g"),sub:p.entityToUnicode[t]}}),x=Object.keys(p.unicodeToEntity).map(function(t){return{regExp:new RegExp(t,"g"),sub:"&"+p.unicodeToEntity[t]+";"}});r.plainText=function(t){return(t||"").replace(v," ")},r.makeEditable=function(t,e,r){function n(){o(),i.style({opacity:0});var t,e=c.attr("class");t=e?"."+e.split(" ")[0]+"-math-group":"[class*=-math-group]",t&&f.select(i.node().parentNode).select(t).style({opacity:0})}function a(t){var e=t.node(),r=document.createRange();r.selectNodeContents(e);var n=window.getSelection();n.removeAllRanges(),n.addRange(r),e.focus()}function o(){var t=f.select(d.getPlotDiv(i.node())),e=t.select(".svg-container"),n=e.append("div");n.classed("plugin-editable editable",!0).style({position:"absolute","font-family":i.style("font-family")||"Arial","font-size":i.style("font-size")||12,color:r.fill||i.style("fill")||"black",opacity:1,"background-color":r.background||"transparent",outline:"#ffffff33 1px solid",margin:[-parseFloat(i.style("font-size"))/8+1,0,0,-1].join("px ")+"px",padding:"0","box-sizing":"border-box"}).attr({contenteditable:!0}).text(r.text||i.attr("data-unformatted")).call(u(i,e,r)).on("blur",function(){i.text(this.textContent).style({opacity:1});var t,e=f.select(this).attr("class");t=e?"."+e.split(" ")[0]+"-math-group":"[class*=-math-group]",t&&f.select(i.node().parentNode).select(t).style({opacity:0});var r=this.textContent;f.select(this).transition().duration(0).remove(),f.select(document).on("mouseup",null),l.edit.call(i,r)}).on("focus",function(){var t=this;f.select(document).on("mouseup",function(){return f.event.target!==t&&void(document.activeElement===n.node()&&n.node().blur())})}).on("keyup",function(){27===f.event.which?(i.style({opacity:1}),f.select(this).style({opacity:0}).on("blur",function(){return!1}).transition().remove(),l.cancel.call(i,this.textContent)):(l.input.call(i,this.textContent),f.select(this).call(u(i,e,r)))}).on("keydown",function(){13===f.event.which&&this.blur()}).call(a)}r||(r={});var i=this,l=f.dispatch("edit","input","cancel"),s=f.select(this.node()).style({"pointer-events":"all"}),c=e||s;return e&&s.style({"pointer-events":"none"}),r.immediate?n():c.on("click",n),f.rebind(this,l,"on")}},{"../constants/string_mappings":111,"../constants/xmlns_namespaces":112,"../lib":122,d3:14}],135:[function(t,e,r){"use strict";function n(t,e){var r=t[e],n=e.charAt(0);r&&"paper"!==r&&(t[e]=f.cleanId(r,n))}function a(t){var e="middle",r="center";return t.indexOf("top")!==-1?e="top":t.indexOf("bottom")!==-1&&(e="bottom"),t.indexOf("left")!==-1?r="left":t.indexOf("right")!==-1&&(r="right"),e+" "+r}function o(t,e){return e in t&&"object"==typeof t[e]&&0===Object.keys(t[e]).length}var i=t("fast-isnumeric"),l=t("gl-mat4/fromQuat"),s=t("../registry"),c=t("../lib"),u=t("../plots/plots"),f=t("../plots/cartesian/axes"),d=t("../components/color");r.getGraphDiv=function(t){var e;if("string"==typeof t){if(e=document.getElementById(t),null===e)throw new Error("No DOM element with id '"+t+"' exists on the page.");return e}if(null===t||void 0===t)throw new Error("DOM element provided is null or undefined");return t},r.clearPromiseQueue=function(t){Array.isArray(t._promises)&&t._promises.length>0&&c.log("Clearing previous rejected promises from queue."),t._promises=[]},r.cleanLayout=function(t){var e,r;t||(t={}),t.xaxis1&&(t.xaxis||(t.xaxis=t.xaxis1),delete t.xaxis1),t.yaxis1&&(t.yaxis||(t.yaxis=t.yaxis1),delete t.yaxis1);var a=f.list({_fullLayout:t});for(e=0;e3?(m.x=1.02,m.xanchor="left"):m.x<-2&&(m.x=-.02,m.xanchor="right"),m.y>3?(m.y=1.02,m.yanchor="bottom"):m.y<-2&&(m.y=-.02,m.yanchor="top")),"rotate"===t.dragmode&&(t.dragmode="orbit"),t.scene1&&(t.scene||(t.scene=t.scene1),delete t.scene1);var v=u.getSubplotIds(t,"gl3d");for(e=0;e=t.data.length||a<-t.data.length)throw new Error(r+" must be valid indices for gd.data.");if(e.indexOf(a,n+1)>-1||a>=0&&e.indexOf(-t.data.length+a)>-1||a<0&&e.indexOf(t.data.length+a)>-1)throw new Error("each index in "+r+" must be unique.")}}function s(t,e,r){if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if("undefined"==typeof e)throw new Error("currentIndices is a required argument.");if(Array.isArray(e)||(e=[e]),l(t,e,"currentIndices"),"undefined"==typeof r||Array.isArray(r)||(r=[r]),"undefined"!=typeof r&&l(t,r,"newIndices"),"undefined"!=typeof r&&e.length!==r.length)throw new Error("current and new indices must be of equal length.")}function c(t,e,r){var n,a;if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if("undefined"==typeof e)throw new Error("traces must be defined.");for(Array.isArray(e)||(e=[e]),n=0;n=0&&sO.range[0]?[1,2]:[2,1]);else{var D=O.range[0],P=O.range[1];"log"===b?(D<=0&&P<=0&&r(L+".autorange",!0),D<=0?D=P/1e6:P<=0&&(P=D/1e6),r(L+".range[0]",Math.log(D)/Math.LN10),r(L+".range[1]",Math.log(P)/Math.LN10)):(r(L+".range[0]",Math.pow(10,D)),r(L+".range[1]",Math.pow(10,P)))}else r(L+".autorange",!0)}if("reverse"===A)z.range?z.range.reverse():(r(L+".autorange",!0),z.range=[1,0]),C.autorange?h.docalc=!0:h.doplot=!0;else if("annotations"===v.parts[0]||"shapes"===v.parts[0]){var N=v.parts[1],E=v.parts[0],I=o[E]||[],R=I[N]||{};2===v.parts.length&&(null===b&&(e[m]="remove"),"add"===e[m]||x.isPlainObject(e[m])?g[m]="remove":"remove"===e[m]?N===-1?(g[E]=I,delete g[m]):g[m]=R:x.log("???",e)),!n(R,"x")&&!n(R,"y")||x.containsAny(m,["color","opacity","align","dash"])||(h.docalc=!0);var F=w.getComponentMethod(E,"drawOne");F(t,N,v.parts.slice(2).join("."),e[m]),delete e[m]}else if(k.layoutArrayContainers.indexOf(v.parts[0])!==-1||"mapbox"===v.parts[0]&&"layers"===v.parts[1])S.manageArrayContainers(v,b,g),h.doplot=!0;else{var j=String(v.parts[1]||"");0===v.parts[0].indexOf("scene")?h.doplot=!0:0===v.parts[0].indexOf("geo")?h.doplot=!0:0===v.parts[0].indexOf("ternary")?h.doplot=!0:"paper_bgcolor"===m?h.doplot=!0:!i._has("gl2d")||m.indexOf("axis")===-1&&"plot_bgcolor"!==v.parts[0]?"hiddenlabels"===m?h.docalc=!0:v.parts[0].indexOf("legend")!==-1?h.dolegend=!0:m.indexOf("title")!==-1?h.doticks=!0:v.parts[0].indexOf("bgcolor")!==-1?h.dolayoutstyle=!0:v.parts.length>1&&x.containsAny(j,["tick","exponent","grid","zeroline"])?h.doticks=!0:m.indexOf(".linewidth")!==-1&&m.indexOf("axis")!==-1?h.doticks=h.dolayoutstyle=!0:v.parts.length>1&&j.indexOf("line")!==-1?h.dolayoutstyle=!0:v.parts.length>1&&"mirror"===j?h.doticks=h.dolayoutstyle=!0:"margin.pad"===m?h.doticks=h.dolayoutstyle=!0:"margin"===v.parts[0]||"autorange"===v.parts[1]||"rangemode"===v.parts[1]||"type"===v.parts[1]||"domain"===v.parts[1]||m.match(/^(bar|box|font)/)?h.docalc=!0:["hovermode","dragmode"].indexOf(m)!==-1?h.domodebar=!0:["hovermode","dragmode","height","width","autosize"].indexOf(m)===-1&&(h.doplot=!0):h.doplot=!0,v.set(b)}}}var q=t._fullLayout.width,B=t._fullLayout.height;k.supplyDefaults(t),t.layout.autosize&&k.plotAutoSize(t,t.layout,t._fullLayout);var H=e.height||e.width||t._fullLayout.width!==q||t._fullLayout.height!==B;return H&&(h.docalc=!0),(h.doplot||h.docalc)&&(h.layoutReplot=!0),{flags:h,undoit:g,redoit:p,eventData:x.extendDeep({},p)}}function g(t){var e=m.select(t),r=t._fullLayout;if(r._container=e.selectAll(".plot-container").data([0]),r._container.enter().insert("div",":first-child").classed("plot-container",!0).classed("plotly",!0),r._paperdiv=r._container.selectAll(".svg-container").data([0]),r._paperdiv.enter().append("div").classed("svg-container",!0).style("position","relative"),r._glcontainer=r._paperdiv.selectAll(".gl-container").data([0]),r._glcontainer.enter().append("div").classed("gl-container",!0),r._geocontainer=r._paperdiv.selectAll(".geo-container").data([0]),r._geocontainer.enter().append("div").classed("geo-container",!0),r._paperdiv.selectAll(".main-svg").remove(),r._paper=r._paperdiv.insert("svg",":first-child").classed("main-svg",!0),r._toppaper=r._paperdiv.append("svg").classed("main-svg",!0),!r._uid){var n=[];m.selectAll("defs").each(function(){this.id&&n.push(this.id.split("-")[1])}),r._uid=x.randstr(n)}r._paperdiv.selectAll(".main-svg").attr(z.svgAttrs),r._defs=r._paper.append("defs").attr("id","defs-"+r._uid),r._topdefs=r._toppaper.append("defs").attr("id","topdefs-"+r._uid),r._draggers=r._paper.append("g").classed("draglayer",!0);var a=r._paper.append("g").classed("layer-below",!0);r._imageLowerLayer=a.append("g").classed("imagelayer",!0),r._shapeLowerLayer=a.append("g").classed("shapelayer",!0),r._cartesianlayer=r._paper.append("g").classed("cartesianlayer",!0),r._ternarylayer=r._paper.append("g").classed("ternarylayer",!0);var o=r._paper.append("g").classed("layer-above",!0);r._imageUpperLayer=o.append("g").classed("imagelayer",!0),r._shapeUpperLayer=o.append("g").classed("shapelayer",!0),r._pielayer=r._paper.append("g").classed("pielayer",!0),r._glimages=r._paper.append("g").classed("glimages",!0),r._geoimages=r._paper.append("g").classed("geoimages",!0),r._infolayer=r._toppaper.append("g").classed("infolayer",!0),r._zoomlayer=r._toppaper.append("g").classed("zoomlayer",!0),r._hoverlayer=r._toppaper.append("g").classed("hoverlayer",!0),t.emit("plotly_framework")}var m=t("d3"),v=t("fast-isnumeric"),y=t("../plotly"),x=t("../lib"),b=t("../lib/events"),_=t("../lib/queue"),w=t("../registry"),k=t("../plots/plots"),M=t("../plots/cartesian/graph_interact"),A=t("../plots/polar"),T=t("../components/drawing"),L=t("../components/errorbars"),z=t("../constants/xmlns_namespaces"),C=t("../lib/svg_text_utils"),S=t("./helpers"),O=t("./subroutines");y.plot=function(t,e,r,n){function i(){if(_)return y.addFrames(t,_)}function l(){for(var e=D._basePlotModules,r=0;r=l.length?l[0]:l[t]:l}function a(t){return Array.isArray(s)?t>=s.length?s[0]:s[t]:s}function o(t,e){var r=0;return function(){if(t&&++r===e)return t()}}if(t=S.getGraphDiv(t),!x.isPlotDiv(t))throw new Error("This element is not a Plotly plot: "+t+". It's likely that you've failed to create a plot before animating it. For more details, see https://plot.ly/javascript/animations/");var i=t._transitionData;i._frameQueue||(i._frameQueue=[]),r=k.supplyAnimationDefaults(r);var l=r.transition,s=r.frame;return void 0===i._frameWaitingCnt&&(i._frameWaitingCnt=0),new Promise(function(s,c){function u(){if(0!==i._frameQueue.length){for(;i._frameQueue.length;){var e=i._frameQueue.pop();e.onInterrupt&&e.onInterrupt()}t.emit("plotly_animationinterrupted",[])}}function f(e){if(0!==e.length){for(var l=0;li._timeToNext&&h()};e()}function g(t){return Array.isArray(l)?y>=l.length?t.transitionOpts=l[y]:t.transitionOpts=l[0]:t.transitionOpts=l,y++,t}var m,v,y=0,b=[],_=void 0===e||null===e,w=Array.isArray(e),M=!_&&!w&&x.isPlainObject(e);if(M)b.push({type:"object",data:g(x.extendFlat({},e))});else if(_||"string"==typeof e)for(m=0;m0&&LL)&&z.push(v);b=z}}b.length>0?f(b):(t.emit("plotly_animated"),s())})},y.addFrames=function(t,e,r){if(t=S.getGraphDiv(t),null===e||void 0===e)return Promise.resolve();if(!x.isPlotDiv(t))throw new Error("This element is not a Plotly plot: "+t+". It's likely that you've failed to create a plot before adding frames. For more details, see https://plot.ly/javascript/animations/");var n,a,o,i,l=t._transitionData._frames,s=t._transitionData._frameHash;if(!Array.isArray(e))throw new Error("addFrames failure: frameList must be an Array of frame definitions"+e);var c=l.length+2*e.length,u=[];for(n=e.length-1;n>=0;n--)u.push({frame:k.supplyFrameDefaults(e[n]),index:r&&void 0!==r[n]&&null!==r[n]?r[n]:c+n});u.sort(function(t,e){return t.index>e.index?-1:t.index=0;n--){if(a=u[n].frame,!a.name)for(;s[a.name="frame "+t._transitionData._counter++];);if(s[a.name]){for(o=0;o=0;r--)n=e[r],o.push({type:"delete",index:n}),i.unshift({type:"insert",index:n,value:a[n]});var l=k.modifyFrames,s=k.modifyFrames,c=[t,i],u=[t,o];return _&&_.add(t,l,c,s,u),k.modifyFrames(t,o)},y.purge=function(t){t=S.getGraphDiv(t);var e=t._fullLayout||{},r=t._fullData||[];return k.cleanPlot([],{},r,e),k.purge(t),b.purge(t),e._container&&e._container.remove(),delete t._context,delete t._replotPending,delete t._mouseDownTime,delete t._hmpixcount,delete t._hmlumcount,t}},{"../components/drawing":53,"../components/errorbars":59,"../constants/xmlns_namespaces":112,"../lib":122,"../lib/events":118,"../lib/queue":130,"../lib/svg_text_utils":134,"../plotly":144,"../plots/cartesian/graph_interact":156,"../plots/plots":173,"../plots/polar":176,"../registry":188,"./helpers":135,"./subroutines":141,d3:14,"fast-isnumeric":17}],137:[function(t,e,r){"use strict";function n(t,r){try{t._fullLayout._paper.style("background",r)}catch(t){e.exports.logging>0&&console.error(t)}}e.exports={staticPlot:!1,editable:!1,editableMainTitle:!0,editableAxisXTitle:!0,editableAxisX2Title:!0,editableAxisYTitle:!0,editableAxisY2Title:!0,autosizable:!1,queueLength:0,fillFrame:!1,frameMargins:0,scrollZoom:!1,doubleClick:"reset+autosize",showTips:!0,showLink:!1,sendData:!0,linkText:"Edit chart",showSources:!1,displayModeBar:"hover",modeBarButtonsToRemove:[],modeBarButtonsToAdd:[],modeBarButtons:!1,displaylogo:!0,plotGlPixelRatio:2,setBackground:n,topojsonURL:"https://cdn.plot.ly/",mapboxAccessToken:null,logging:!1,globalTransforms:[]}},{}],138:[function(t,e,r){"use strict";function n(t){var e,r;"area"===t?(e={attributes:y},r={}):(e=d.modules[t]._module,r=e.basePlotModule);var n={};n.type=null,_(n,p),_(n,e.attributes),r.attributes&&_(n,r.attributes),n.type=t;var a={meta:e.meta||{},attributes:i(n)};if(e.layoutAttributes){var o={};_(o,e.layoutAttributes),a.layoutAttributes=i(o)}return a}function a(){var t={};return _(t,g),Object.keys(d.subplotsRegistry).forEach(function(e){var r=d.subplotsRegistry[e];if(r.layoutAttributes)if("cartesian"===r.name)u(t,r,"xaxis"),u(t,r,"yaxis");else{var n="subplot"===r.attr?r.name:r.attr;u(t,r,n)}}),t=c(t),Object.keys(d.componentsRegistry).forEach(function(e){var r=d.componentsRegistry[e];r.layoutAttributes&&(Array.isArray(r.layoutNodes)?r.layoutNodes.forEach(function(e){f(t,r,e+r.name)}):f(t,r,r.name))}),{layoutAttributes:i(t)}}function o(t){var e=d.transformsRegistry[t];return{attributes:i(e.attributes)}}function i(t){return l(t),s(t),t}function l(t){function e(t){return{valType:"string"}}function n(t,n,a){r.isValObject(t)?"data_array"===t.valType?(t.role="data",a[n+"src"]=e(n)):t.arrayOk===!0&&(a[n+"src"]=e(n)):h.isPlainObject(t)&&(t.role="object")}r.crawl(t,n)}function s(t){function e(t,e,r){if(t){var n=t[k];n&&(delete t[k],r[e]={items:{}},r[e].items[n]=t,r[e].role="object")}}r.crawl(t,e)}function c(t){return b(t,{radialaxis:x.radialaxis,angularaxis:x.angularaxis}),b(t,x.layout),t}function u(t,e,r){var n=h.nestedProperty(t,r),a=_({},e.layoutAttributes);a[w]=!0,n.set(a)}function f(t,e,r){var n=h.nestedProperty(t,r),a=_(n.get()||{},e.layoutAttributes);n.set(a)}var d=t("../registry"),h=t("../lib"),p=t("../plots/attributes"),g=t("../plots/layout_attributes"),m=t("../plots/frame_attributes"),v=t("../plots/animation_attributes"),y=t("../plots/polar/area_attributes"),x=t("../plots/polar/axis_attributes"),b=h.extendFlat,_=h.extendDeep,w="_isSubplotObj",k="_isLinkedToArray",M="_deprecated",A=[w,k,M];r.IS_SUBPLOT_OBJ=w,r.IS_LINKED_TO_ARRAY=k,r.DEPRECATED=M,r.UNDERSCORE_ATTRS=A,r.get=function(){var t={};d.allTypes.concat("area").forEach(function(e){t[e]=n(e)});var e={};return Object.keys(d.transformsRegistry).forEach(function(t){e[t]=o(t)}),{defs:{valObjects:h.valObjects,metaKeys:A.concat.role},traces:t,layout:a(),transforms:e,frames:i(m),animation:i(v)}},r.crawl=function(t,e,n){var a=n||0;Object.keys(t).forEach(function(n){var o=t[n];A.indexOf(n)===-1&&(e(o,n,t,a),r.isValObject(o)||h.isPlainObject(o)&&r.crawl(o,e,a+1))})},r.isValObject=function(t){return t&&void 0!==t.valType},r.findArrayAttributes=function(t){function e(e,r,i,l){o=o.slice(0,l).concat([r]);var s="data_array"===e.valType||e.arrayOk===!0;if(s){var c=n(o),u=h.nestedProperty(t,c).get();Array.isArray(u)&&a.push(c)}}function n(t){return t.join(".")}var a=[],o=[];if(r.crawl(t._module.attributes,e),t.transforms)for(var i=t.transforms,l=0;l1)};d(e.width)&&d(e.height)||n(new Error("Height and width should be pixel values."));var h=s(t,{format:"png",height:e.height,width:e.width}),p=h.gd;p.style.position="absolute",p.style.left="-5000px",document.body.appendChild(p);var g=l.getRedrawFunc(p);o.plot(p,h.data,h.layout,h.config).then(g).then(f).then(function(t){r(t)}).catch(function(t){n(t)})});return r}var a=t("fast-isnumeric"),o=t("../plotly"),i=t("../lib"),l=t("../snapshot/helpers"),s=t("../snapshot/cloneplot"),c=t("../snapshot/tosvg"),u=t("../snapshot/svgtoimg");e.exports=n},{"../lib":122,"../plotly":144,"../snapshot/cloneplot":189,"../snapshot/helpers":192,"../snapshot/svgtoimg":194,"../snapshot/tosvg":196,"fast-isnumeric":17}],143:[function(t,e,r){"use strict";function n(t,e,r,a,o,c){c=c||[];for(var u=Object.keys(t),d=0;d1&&s.push(i("object","layout"))),d.supplyDefaults(c);for(var u=c._fullData,m=r.length,v=0;vu&&e10||"01-01"!==n.substr(5)?t._tickround="d":t._tickround=+e.substr(1)%12===0?"y":"m";else if(e>=O&&a<=10||e>=15*O)t._tickround="d";else if(e>=P&&a<=16||e>=D)t._tickround="M";else if(e>=N&&a<=19||e>=P)t._tickround="S";else{var o=w.ms2DateTime(r+e).replace(/^-/,"").length;t._tickround=Math.max(a,o)-20}}else if(x(e)||"L"===e.charAt(0)){var i=t.range.map(t.r2d||Number);x(e)||(e=Number(e.substr(1))),t._tickround=2-Math.floor(Math.log(e)/Math.LN10+.01);var l=Math.max(Math.abs(i[0]),Math.abs(i[1])),s=Math.floor(Math.log(l)/Math.LN10+.01);Math.abs(s)>3&&("SI"===t.exponentformat||"B"===t.exponentformat?t._tickexponent=3*Math.round((s-1)/3):t._tickexponent=s)}else t._tickround=null}function i(t,e){var r=t.match(W),n=new Date(e);if(r){var a=Math.min(+r[1]||6,6),o=String(e/1e3%1+2.0000005).substr(2,a).replace(/0+$/,"")||"0";return y.time.format(t.replace(W,o))(n)}return y.time.format(t)(n)}function l(t,e,r){var n=t.tickfont||t._gd._fullLayout.font;return{x:e,dx:0,dy:0,text:r||"",fontSize:n.size,font:n.family,fontColor:n.color}}function s(t,e,r,n){var a,o,l=e.x,s=t._tickround,c=s,u=new Date(l);r&&t.hoverformat?o=i(t.hoverformat,l):t.tickformat?o=i(t.tickformat,l):(n&&(x(s)?s+=2:s={y:"m",m:"d",d:"M",M:"S",S:2}[s]),"y"===s?o=V(u):"m"===s?o=Z(u):"d"===s?(r||(a="
"+V(u)),o=X(u)):(r||(a="
"+U(u)),o=Y(u),"M"!==s?(o+=G(u),"S"!==s&&(o+=d(y.round(v(l/1e3,1),4),t,"none",r).substr(1))):"d"===c&&(o=X(u)+" "+o))),!a||t._inCalcTicks&&a===t._prevSuffix||(o+=a,t._prevSuffix=a),e.text=o}function c(t,e,r,n,a){var o=t.dtick,i=e.x;if(!n||"string"==typeof o&&"L"===o.charAt(0)||(o="L3"),t.tickformat||"string"==typeof o&&"L"===o.charAt(0))e.text=d(Math.pow(10,i),t,a,n);else if(x(o)||"D"===o.charAt(0)&&v(i+.01,1)<.1)if(["e","E","power"].indexOf(t.exponentformat)!==-1){var l=Math.round(i);0===l?e.text=1:1===l?e.text="10":l>1?e.text="10"+l+"":e.text="10\u2212"+-l+"",e.fontSize*=1.25}else e.text=d(Math.pow(10,i),t,"","fakehover"),"D1"===o&&"y"===t._id.charAt(0)&&(e.dy-=e.fontSize/6);else{if("D"!==o.charAt(0))throw"unrecognized dtick "+String(o);e.text=String(Math.round(Math.pow(10,v(i,1)))),e.fontSize*=.75}if("D1"===t.dtick){var s=String(e.text).charAt(0);"0"!==s&&"1"!==s||("y"===t._id.charAt(0)?e.dx-=e.fontSize/4:(e.dy+=e.fontSize/2,e.dx+=(t.range[1]>t.range[0]?1:-1)*e.fontSize*(i<0?.5:.25)))}}function u(t,e){var r=t._categories[Math.round(e.x)];void 0===r&&(r=""),e.text=String(r)}function f(t,e,r,n,a){"all"===t.showexponent&&Math.abs(e.x/t.dtick)<1e-6&&(a="hide"),e.text=d(e.x,t,a,n)}function d(t,e,r,n){var a=t<0,i=e._tickround,l=r||e.exponentformat||"B",s=e._tickexponent,c=e.tickformat,u=e.separatethousands;if(n){var f={exponentformat:e.exponentformat,dtick:"none"===e.showexponent?e.dtick:x(t)?Math.abs(t)||1:1,range:"none"===e.showexponent?e.range.map(e.r2d):[0,t||1]};o(f),i=(Number(f._tickround)||0)+4,s=f._tickexponent,e.hoverformat&&(c=e.hoverformat)}if(c)return y.format(c)(t).replace(/-/g,"\u2212");var d=Math.pow(10,-i)/2;if("none"===l&&(s=0),t=Math.abs(t),t12||s<-15)?t+="e"+g:"E"===l?t+="E"+g:"power"===l?t+="\xd710"+g+"":"B"===l&&9===s?t+="B":"SI"!==l&&"B"!==l||(t+=Q[s/3+5])}return a?"\u2212"+t:t}function h(t,e){var r,n,a=[];for(r=0;r1)for(n=1;n2e-6||((r-t._forceTick0)/t._minDtick%1+1.000001)%1>2e-6)&&(t._minDtick=0)):t._minDtick=0},E.getAutoRange=function(t){var e,r=[],n=t._min[0].val,a=t._max[0].val;for(e=1;e0&&u>0&&f/u>d&&(s=i,c=l,d=f/u);if(n===a){var g=n-1,m=n+1;r="tozero"===t.rangemode?n<0?[g,0]:[0,m]:"nonnegative"===t.rangemode?[Math.max(0,g),Math.max(0,m)]:[g,m]}else d&&("linear"!==t.type&&"-"!==t.type||("tozero"===t.rangemode?(s.val>=0&&(s={val:0,pad:0}),c.val<=0&&(c={val:0,pad:0})):"nonnegative"===t.rangemode&&(s.val-d*s.pad<0&&(s={val:0,pad:0}),c.val<0&&(c={val:1,pad:0})),d=(c.val-s.val)/(t._length-s.pad-c.pad)),r=[s.val-d*s.pad,c.val+d*c.pad]);return r[0]===r[1]&&("tozero"===t.rangemode?r=r[0]<0?[r[0],0]:r[0]>0?[0,r[0]]:[0,1]:(r=[r[0]-1,r[0]+1],"nonnegative"===t.rangemode&&(r[0]=Math.max(0,r[0])))),h&&r.reverse(),r.map(t.l2r||Number)},E.doAutoRange=function(t){t._length||t.setScale();var e=t._min&&t._max&&t._min.length&&t._max.length;if(t.autorange&&e){t.range=E.getAutoRange(t);var r=t._gd.layout[t._name];r||(t._gd.layout[t._name]=r={}),r!==t&&(r.range=t.range.slice(),r.autorange=t.autorange)}},E.saveRangeInitial=function(t,e){for(var r=E.list(t,"",!0),n=!1,a=0;a=d?h=!1:l.val>=c&&l.pad<=d&&(t._min.splice(i,1),i--);h&&t._min.push({val:c,pad:y&&0===c?0:d})}if(n(u)){for(h=!0,i=0;i=u&&l.pad>=f?h=!1:l.val<=u&&l.pad<=f&&(t._max.splice(i,1),i--);h&&t._max.push({val:u,pad:y&&0===u?0:f})}}}if((t.autorange||t._needsExpand)&&e){t._min||(t._min=[]),t._max||(t._max=[]),r||(r={}),t._m||t.setScale();var o,i,l,s,c,u,f,d,h,p,g,m=e.length,v=r.padded?.05*t._length:0,y=r.tozero&&("linear"===t.type||"-"===t.type),b=n((t._m>0?r.ppadplus:r.ppadminus)||r.ppad||0),_=n((t._m>0?r.ppadminus:r.ppadplus)||r.ppad||0),w=n(r.vpadplus||r.vpad),k=n(r.vpadminus||r.vpad);for(o=0;o<6;o++)a(o);for(o=m-1;o>5;o--)a(o)}},E.autoBin=function(t,e,r,n){function a(t){return(1+100*(t-h)/f.dtick)%100<2}var o=w.aggNums(Math.min,null,t),i=w.aggNums(Math.max,null,t);if("category"===e.type)return{start:o-.5,end:i+.5,size:1};var l;if(r)l=(i-o)/r;else{var s=w.distinctVals(t),c=Math.pow(10,Math.floor(Math.log(s.minDiff)/Math.LN10)),u=c*w.roundUp(s.minDiff/c,[.9,1.9,4.9,9.9],!0);l=Math.max(u,2*w.stdev(t)/Math.pow(t.length,n?.25:.4))}var f;f="log"===e.type?{type:"linear",range:[o,i],r2l:Number}:{type:e.type,range:[o,i].map(e.l2r),r2l:e.r2l},E.autoTicks(f,l);var d,h=E.tickIncrement(E.tickFirst(f),f.dtick,"reverse");if("number"==typeof f.dtick){for(var p=0,g=0,m=0,v=0,y=0;y.3*b||a(o)||a(i))){var _=f.dtick/2;h+=h+_0&&t.dtick<2*t._minDtick&&(t.dtick=t._minDtick,t.tick0=t.l2r(t._forceTick0))}t.tick0||(t.tick0="date"===t.type?"2000-01-01":0),o(t),t._tmin=E.tickFirst(t);var i=e[1]=s:c<=s)&&(l.push(c),!(l.length>1e3));c=E.tickIncrement(c,t.dtick,i));t._tmax=l[l.length-1],t._prevSuffix="",t._inCalcTicks=!0;for(var u=new Array(l.length),f=0;fC?(e/=C,r=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick="M"+12*a(e,r,R)):n>S?(e/=S,t.dtick="M"+a(e,1,F)):n>O?(t.dtick=a(e,O,q),t.tick0="2000-01-02"):n>D?t.dtick=a(e,D,F):n>P?t.dtick=a(e,P,j):n>N?t.dtick=a(e,N,j):(r=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick=a(e,r,R))}else if("log"===t.type){t.tick0=0;var o=t.range.map(t.r2l);if(e>.7)t.dtick=Math.ceil(e);else if(Math.abs(o[1]-o[0])<1){var i=1.5*Math.abs((o[1]-o[0])/e);e=Math.abs(Math.pow(10,o[1])-Math.pow(10,o[0]))/i,r=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick="L"+a(e,r,R)}else t.dtick=e>.3?"D2":"D1"}else"category"===t.type?(t.tick0=0,t.dtick=Math.ceil(Math.max(e,1))):(t.tick0=0,r=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick=a(e,r,R));if(0===t.dtick&&(t.dtick=1),!x(t.dtick)&&"string"!=typeof t.dtick){var l=t.dtick;throw t.dtick=1,"ax.dtick error: "+String(l)}},E.tickIncrement=function(t,e,r){var n=r?-1:1;if(x(e))return t+n*e;var a=e.charAt(0),o=n*Number(e.substr(1));if("M"===a){var i=new Date(t);return i.setMonth(i.getMonth()+o)}if("L"===a)return Math.log(Math.pow(10,t)+o)/Math.LN10;if("D"===a){var l="D2"===e?H:B,s=t+.01*n,c=w.roundUp(v(s,1),l,r);return Math.floor(s)+Math.log(y.round(Math.pow(10,c),1))/Math.LN10}throw"unrecognized dtick "+String(e)},E.tickFirst=function(t){var e=t.r2l||Number,r=t.range.map(e),n=r[1]o:f1&&en){var o=t.text,i=Math.round(n/(a/o.length)),l=Math.floor(i/2),s=i-l-1;o=o.substr(0,l)+"\u2026"+o.substr(-s);var c=e.select("text");c.text(o),e.insert("title","text").text(t.text)}})}function u(){var e,r,n=c._boundingBox,a=0,o=0;if("x"===c._id.charAt(0)?(e="height","2"===c._id.charAt(1)?(o=1,r="t"):r="b"):"y"===c._id.charAt(0)&&(e="width","2"===c._id.charAt(1)?(a=1,r="r"):r="l"),e&&r){var i=n[e];if(c._titleElement){var l=c._titleElement.node().getBoundingClientRect();i+=l[e]+2}var s=.5*t._fullLayout[e];i=Math.min(i,s);var u={x:a,y:o,l:0,r:0,b:0,t:0};u[r]=i,_.autoMargin(t,c._name,u)}}function f(){c._boundingBox=r.node().getBoundingClientRect()}r.style("pointer-events","all");var d=r.selectAll("g."+C).data(L,z);if(!c.showticklabels||!x(n))return d.remove(),void i(e);var p,v,b,M,A;"x"===m?(A="bottom"===B?1:-1,p=function(t){return t.dx+N*A},M=n+(P+D)*A,v=function(t){return t.dy+M+t.fontSize*("bottom"===B?1:-.5)},b=function(t){return x(t)&&0!==t&&180!==t?t*A<0?"end":"start":"middle"}):(A="right"===B?1:-1,v=function(t){return t.dy+t.fontSize/2-N*A},p=function(t){return t.dx+n+(P+D+(90===Math.abs(c.tickangle)?t.fontSize/2:0))*A},b=function(t){return x(t)&&90===Math.abs(t)?"middle":"right"===B?"start":"end"});var S=0,O=0,E=[],I=d.enter().append("g").classed(C,1);I.append("text").attr("text-anchor","middle").each(function(e){var r=y.select(this),n=t._promises.length;r.call(T.setPosition,p(e),v(e)).call(T.font,e.font,e.fontSize,e.fontColor).text(e.text).call(k.convertToTspans),n=t._promises[n],n?E.push(t._promises.pop().then(function(){a(r,c.tickangle)})):a(r,c.tickangle)}),d.exit().remove(),d.each(function(t){S=Math.max(S,t.fontSize)}),a(d,c._lastangle||c.tickangle);var R=w.syncOrAsync([o,l,f,u]);return R&&R.then&&t._promises.push(R),R}function i(e){if(!r){var n,a,o,i,l=I.getFromId(t,e),s=y.select(t).selectAll("g."+e+"tick"),c={selection:s,side:l.side},f=e.charAt(0),d=t._fullLayout._size,h=1.5,p=l.titlefont.size;if(s.size()){var g=y.select(s.node().parentNode).attr("transform").match(/translate\(([-\.\d]+),([-\.\d]+)\)/);g&&(c.offsetLeft=+g[1],c.offsetTop=+g[2])}"x"===f?(a="free"===l.anchor?{_offset:d.t+(1-(l.position||0))*d.h,_length:0}:I.getFromId(t,l.anchor),o=l._offset+l._length/2,i=a._offset+("top"===l.side?-10-p*(h+(l.showticklabels?1:0)):a._length+10+p*(h+(l.showticklabels?1.5:.5))),l.rangeslider&&l.rangeslider.visible&&l._boundingBox&&(i+=(u.height-u.margin.b-u.margin.t)*l.rangeslider.thickness+l._boundingBox.height),c.side||(c.side="bottom")):(a="free"===l.anchor?{_offset:d.l+(l.position||0)*d.w,_length:0}:I.getFromId(t,l.anchor),i=l._offset+l._length/2,o=a._offset+("right"===l.side?a._length+10+p*(h+(l.showticklabels?1:.5)):-10-p*(h+(l.showticklabels?.5:0))),n={rotate:"-90",offset:0},c.side||(c.side="left")),M.draw(t,e+"title",{propContainer:l,propName:l._name+".title",dfltName:f.toUpperCase()+" axis",avoid:c,transform:n,attributes:{x:o,y:i,"text-anchor":"middle"}})}}function l(t,e){return t.visible===!0&&t.xaxis+t.yaxis===e&&(!(!b.traceIs(t,"bar")||t.orientation!=={x:"h",y:"v"}[m])||t.fill&&t.fill.charAt(t.fill.length-1)===m)}function s(e,r,a){var o=e.gridlayer,i=e.zerolinelayer,s=e["hidegrid"+m]?[]:V,u=c._gridpath||"M0,0"+("x"===m?"v":"h")+r._length,f=o.selectAll("path."+S).data(c.showgrid===!1?[]:s,z); -if(f.enter().append("path").classed(S,1).classed("crisp",1).attr("d",u).each(function(t){c.zeroline&&("linear"===c.type||"-"===c.type)&&Math.abs(t.x)2*n}function o(t){for(var e,r=Math.max(1,(t.length-1)/1e3),n=0,a=0,o=0;o2*n}var i=t("fast-isnumeric"),l=t("../../lib"),s=t("../../constants/numerical").BADNUM;e.exports=function(t){return a(t)?"date":o(t)?"category":n(t)?"linear":"-"}},{"../../constants/numerical":110,"../../lib":122,"fast-isnumeric":17}],151:[function(t,e,r){"use strict";function n(t,e){if("-"===t.type){var r=t._id,n=r.charAt(0);r.indexOf("scene")!==-1&&(r=n);var l=i(e,r,n);if(l){if("histogram"===l.type&&n==={v:"y",h:"x"}[l.orientation||"v"])return void(t.type="linear");if(o(l,n)){for(var s,u=a(l),f=[],d=0;d0;o&&(n="array");var i=r("categoryorder",n);"array"===i&&r("categoryarray"),o||"array"!==i||(e.categoryorder="trace")}}},{}],154:[function(t,e,r){"use strict";e.exports={idRegex:{x:/^x([2-9]|[1-9][0-9]+)?$/,y:/^y([2-9]|[1-9][0-9]+)?$/},attrRegex:{x:/^xaxis([2-9]|[1-9][0-9]+)?$/,y:/^yaxis([2-9]|[1-9][0-9]+)?$/},xAxisMatch:/^xaxis[0-9]*$/,yAxisMatch:/^yaxis[0-9]*$/,AX_ID_PATTERN:/^[xyz][0-9]*$/,AX_NAME_PATTERN:/^[xyz]axis[0-9]*$/,DBLCLICKDELAY:300,MINDRAG:8,MINSELECT:12,MINZOOM:20,DRAGGERSIZE:20,MAXDIST:20,YANGLE:60,HOVERARROWSIZE:6,HOVERTEXTPAD:3,HOVERFONTSIZE:13,HOVERFONT:"Arial, sans-serif",HOVERMINTIME:50,BENDPX:1.5,REDRAWDELAY:50,DFLTRANGEX:[-1,6],DFLTRANGEY:[-1,4],DFLTRANGEDATE:["2000-01-01","2001-01-01"]}},{}],155:[function(t,e,r){"use strict";function n(t,e){var r,n=t.range[e],a=Math.abs(n-t.range[1-e]);return"date"===t.type?n:"log"===t.type?(r=Math.ceil(Math.max(0,-Math.log(a)/Math.LN10))+3,l.format("."+r+"g")(Math.pow(10,n))):(r=Math.floor(Math.log(Math.abs(n))/Math.LN10)-Math.floor(Math.log(a)/Math.LN10)+4,l.format("."+String(r)+"g")(n))}function a(t,e){return t?"nsew"===t?"pan"===e?"move":"crosshair":t.toLowerCase()+"-resize":"pointer"}function o(t){l.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}function i(t){var e=["lasso","select"];return e.indexOf(t)!==-1}var l=t("d3"),s=t("tinycolor2"),c=t("../../plotly"),u=t("../../registry"),f=t("../../lib"),d=t("../../lib/svg_text_utils"),h=t("../../components/color"),p=t("../../components/drawing"),g=t("../../lib/setcursor"),m=t("../../components/dragelement"),v=t("./axes"),y=t("./select"),x=t("./constants"),b=!0;e.exports=function(t,e,r,l,_,w,k,M){function A(t,e){for(var r=0;r.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("transform","translate("+gt+", "+mt+")").attr("d",ct+"Z"),ht=pt.append("path").attr("class","zoombox-corners").style({fill:h.background,stroke:h.defaultLine,"stroke-width":1,opacity:0}).attr("transform","translate("+gt+", "+mt+")").attr("d","M0,0Z"),z()}function z(){pt.selectAll(".select-outline").remove()}function C(e,r){if(t._transitioningWithDuration)return!1;var n=Math.max(0,Math.min(V,e+ot)),a=Math.max(0,Math.min(Z,r+it)),o=Math.abs(n-ot),i=Math.abs(a-it),l=Math.floor(Math.min(i,o,U)/2);lt.l=Math.min(ot,n),lt.r=Math.max(ot,n),lt.t=Math.min(it,a),lt.b=Math.max(it,a),!K||i.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),ht.transition().style("opacity",1).duration(200),ut=!0)}function S(t,e,r){var n,a,o,i=[];for(n=0;nzoom back out","long"),b=!1),l.pre=!1,t.emit("plotly_zoom",l))}function D(e,r){var a=1===(k+M).length;if(e)R();else if(2!==r||a){if(1===r&&a){var o=k?H[0]:B[0],i="s"===k||"w"===M?0:1,l=o._name+".range["+i+"]",s=n(o,i),u="left",f="middle";if(o.fixedrange)return;k?(f="n"===k?"top":"bottom","right"===o.side&&(u="right")):"e"===M&&(u="right"),rt.call(d.makeEditable,null,{immediate:!0,background:j.paper_bgcolor,text:String(s),fill:o.tickfont?o.tickfont.color:"#444",horizontalAlign:u,verticalAlign:f}).on("edit",function(e){var r=o.d2r(e);void 0!==r&&c.relayout(t,l,r)})}}else I()}function P(e){function r(t,e,r){function n(e){return t.l2r(o+(e-o)*r)}if(!t.fixedrange){var a=t.range.map(t.r2l),o=a[0]+(a[1]-a[0])*e;t.range=a.map(n)}}if(t._context.scrollZoom||j._enablescrollzoom){if(t._transitioningWithDuration)return f.pauseEvent(e);var n=t.querySelector(".plotly");if(T(),!(n.scrollHeight-n.clientHeight>10||n.scrollWidth-n.clientWidth>10)){clearTimeout(yt);var a=-e.deltaY;if(isFinite(a)||(a=e.wheelDelta/10),!isFinite(a))return void f.log("Did not find wheel motion attributes: ",e);var o,i=Math.exp(-Math.min(Math.max(a,-20),20)/100),l=bt.draglayer.select(".nsewdrag").node().getBoundingClientRect(),s=(e.clientX-l.left)/l.width,c=vt[0]+vt[2]*s,u=(l.bottom-e.clientY)/l.height,d=vt[1]+vt[3]*(1-u);if(M){for(o=0;o=0?Math.min(t,.9):1/(1/Math.max(t,-.3)+3.222))}function o(t,e,r){for(var n,o,i=1-e,l=0;l0;n--)r.push(e);return r}function a(t,e){for(var r=[],n=0;nG.width||Y<0||Y>G.height)return _.unhoverRaw(t,e)}else U="xpx"in e?e.xpx:M[0]._length/2,Y="ypx"in e?e.ypx:A[0]._length/2;if(O="xval"in e?n(o,e.xval):a(M,U),D="yval"in e?n(o,e.yval):a(A,Y),!g(O[0])||!g(D[0]))return m.warn("Fx.hover failed",e,t),_.unhoverRaw(t,e)}var W=1/0;for(N=0;N1||I.hoverinfo.indexOf("name")!==-1?I.name:void 0,index:!1,distance:Math.min(W,k.MAXDIST),color:x.defaultLine,x0:void 0,x1:void 0,y0:void 0,y1:void 0,xLabelVal:void 0,yLabelVal:void 0,zLabelVal:void 0,text:void 0},i[R]&&(H.subplot=i[R]._subplot),V=Z.length,"array"===j){var Q=e[N];"pointNumber"in Q?(H.index=Q.pointNumber,j="closest"):(j="","xval"in Q&&(q=Q.xval,j="x"),"yval"in Q&&(B=Q.yval,j=j?"closest":"y"))}else q=O[F],B=D[F];if(I._module&&I._module.hoverPoints){var $=I._module.hoverPoints(H,q,B,j);if($)for(var J,K=0;K<$.length;K++)J=$[K],g(J.x0)&&g(J.y0)&&Z.push(s(J,S))}else m.log("Unrecognized trace type in hover:",I);"closest"===S&&Z.length>V&&(Z.splice(0,V),W=Z[0].distance)}if(0===Z.length)return _.unhoverRaw(t,e);var tt="y"===S&&X.length>1;Z.sort(function(t,e){return t.distance-e.distance});var et=x.combine(i.plot_bgcolor||x.background,i.paper_bgcolor),rt={hovermode:S,rotateLabels:tt,bgColor:et,container:i._hoverlayer,outerContainer:i._paperdiv},nt=c(Z,rt,e,t.layout.hoverFollowsMouse);u(Z,tt?"xa":"ya"),f(nt,tt);var at=t._hoverdata,ot=[];for(P=0;P128?"#000":x.background;if(t.name&&void 0===t.zLabelVal){var d=document.createElement("p");d.innerHTML=t.name,a=d.textContent||"",a.length>15&&(a=a.substr(0,12)+"...")}void 0!==t.extraText&&(o+=t.extraText),void 0!==t.zLabel?(void 0!==t.xLabel&&(o+="x: "+t.xLabel+"
"),void 0!==t.yLabel&&(o+="y: "+t.yLabel+"
"),o+=(o?"z: ":"")+t.zLabel):z&&t[i+"Label"]===v?o=t[("x"===i?"y":"x")+"Label"]||"":void 0===t.xLabel?void 0!==t.yLabel&&(o=t.yLabel):o=void 0===t.yLabel?t.xLabel:"("+t.xLabel+", "+t.yLabel+")",t.text&&!Array.isArray(t.text)&&(o+=(o?"
":"")+t.text),""===o&&(""===a&&e.remove(),o=a);var g=e.select("text.nums").style("fill",f).call(b.setPosition,0,0).text(o).attr("data-notex",1).call(y.convertToTspans);g.selectAll("tspan.line").call(b.setPosition,0,0);var m=e.select("text.name"),_=0;a&&a!==o?(m.style("fill",u).text(a).call(b.setPosition,0,0).attr("data-notex",1).call(y.convertToTspans),m.selectAll("tspan.line").call(b.setPosition,0,0),_=m.node().getBoundingClientRect().width+2*P):(m.remove(),e.select("rect").remove()),e.select("path").style({fill:u,stroke:f});var w,k,C=g.node().getBoundingClientRect(),S=t.xa._offset+(t.x0+t.x1)/2,O=t.ya._offset+(t.y0+t.y1)/2,N=Math.abs(t.x1-t.x0),E=Math.abs(t.y1-t.y0),I=C.width+D+P+_;t.ty0=M-C.top,t.bx=C.width+2*P,t.by=C.height+2*P,t.anchor="start",t.txwidth=C.width,t.tx2width=_,t.offset=0,n&&"closest"===i&&r&&r.layerX&&r.layerY&&(S=r.layerX,O=r.layerY),l?(t.pos=S,w=O+E/2+I<=T,k=O-E/2-I>=0,"top"!==t.idealAlign&&w||!k?w?(O+=E/2,t.anchor="start"):t.anchor="middle":(O-=E/2,t.anchor="end")):(t.pos=O,w=S+N/2+I<=A,k=S-N/2-I>=0,"left"!==t.idealAlign&&w||!k?w?(S+=N/2,t.anchor="start"):t.anchor="middle":(S-=N/2,t.anchor="end")),g.attr("text-anchor",t.anchor),_&&m.attr("text-anchor",t.anchor),e.attr("transform","translate("+S+","+O+")"+(l?"rotate("+L+")":""))}),O}function u(t,e){function r(t){var e=t[0],r=t[t.length-1];if(a=e.pmin-e.pos-e.dp+e.size,o=r.pos+r.dp+r.size-e.pmax,a>.01){for(l=t.length-1;l>=0;l--)t[l].dp+=a;n=!1}if(!(o<.01)){if(a<-.01){for(l=t.length-1;l>=0;l--)t[l].dp-=o;n=!1}if(n){var c=0;for(i=0;ie.pmax&&c++;for(i=t.length-1;i>=0&&!(c<=0);i--)s=t[i],s.pos>e.pmax-1&&(s.del=!0,c--);for(i=0;i=0;l--)t[l].dp-=o;for(i=t.length-1;i>=0&&!(c<=0);i--)s=t[i],s.pos+s.dp+s.size>e.pmax&&(s.del=!0,c--)}}}for(var n,a,o,i,l,s,c,u=0,f=t.map(function(t,r){var n=t[e];return[{i:r,dp:0,pos:t.pos,posref:t.posref,size:t.by*("x"===n._id.charAt(0)?C:1)/2,pmin:n._offset,pmax:n._offset+n._length}]}).sort(function(t,e){return t[0].posref-e[0].posref});!n&&u<=t.length;){for(u++,n=!0,i=0;i.01&&p.pmin===g.pmin&&p.pmax===g.pmax){for(l=h.length-1;l>=0;l--)h[l].dp+=a;for(d.push.apply(d,h),f.splice(i+1,1),c=0,l=d.length-1;l>=0;l--)c+=d[l].dp;for(o=c/d.length,l=d.length-1;l>=0;l--)d[l].dp-=o;n=!1}else i++}f.forEach(r)}for(i=f.length-1;i>=0;i--){var m=f[i];for(l=m.length-1;l>=0;l--){var v=m[l],y=t[v.i];y.offset=v.dp,y.del=v.del}}}function f(t,e){t.each(function(t){var r=h.select(this);if(t.del)return void r.remove();var n="end"===t.anchor?-1:1,a=r.select("text.nums"),o={start:1,end:-1,middle:0}[t.anchor],i=o*(D+P),l=i+o*(t.txwidth+P),s=0,c=t.offset;"middle"===t.anchor&&(i-=t.tx2width/2,l-=t.tx2width/2),e&&(c*=-O,s=t.offset*S),r.select("path").attr("d","middle"===t.anchor?"M-"+t.bx/2+",-"+t.by/2+"h"+t.bx+"v"+t.by+"h-"+t.bx+"Z":"M0,0L"+(n*D+s)+","+(D+c)+"v"+(t.by/2-D)+"h"+n*t.bx+"v-"+t.by+"H"+(n*D+s)+"V"+(c-D)+"Z"),a.call(b.setPosition,i+s,c+t.ty0-t.by/2+P).selectAll("tspan.line").attr({x:a.attr("x"),y:a.attr("y")}),t.tx2width&&(r.select("text.name, text.name tspan.line").call(b.setPosition,l+o*P+s,c+t.ty0-t.by/2+P),r.select("rect").call(b.setRect,l+(o-1)*t.tx2width/2+s,c-t.by/2-1,t.tx2width,t.by+2))})}function d(t,e,r){if(!e.target)return!1;if(!r||r.length!==t._hoverdata.length)return!0;for(var n=r.length-1;n>=0;n--){var a=r[n],o=t._hoverdata[n];if(a.curveNumber!==o.curveNumber||String(a.pointNumber)!==String(o.pointNumber))return!0}return!1}var h=t("d3"),p=t("tinycolor2"),g=t("fast-isnumeric"),m=t("../../lib"),v=t("../../lib/events"),y=t("../../lib/svg_text_utils"),x=t("../../components/color"),b=t("../../components/drawing"),_=t("../../components/dragelement"),w=t("./axes"),k=t("./constants"),M=t("./dragbox"),A=t("../layout_attributes"),T=e.exports={};T.unhover=_.unhover,T.layoutAttributes={},T.supplyLayoutDefaults=function(t,e,r){function n(r,n){return m.coerce(t,e,A,r,n)}n("dragmode");var a;if(e._has("cartesian")){var o=e._isHoriz=T.isHoriz(r);a=o?"y":"x"}else a="closest";n("hovermode",a)},T.isHoriz=function(t){for(var e=!0,r=0;rt._lastHoverTime+k.HOVERMINTIME?(i(t,e,r),void(t._lastHoverTime=Date.now())):void(t._hoverTimer=setTimeout(function(){i(t,e,r),t._lastHoverTime=Date.now(),t._hoverTimer=void 0},k.HOVERMINTIME))},T.getDistanceFunction=function(t,e,r,n){return"closest"===t?n||o(e,r):"x"===t?e:r},T.getClosest=function(t,e,r){if(r.index!==!1)r.index>=0&&r.indexf[1]-.01&&(e.domain=[0,1]),a.noneOrAll(t.domain,e.domain,[0,1])}return e}},{"../../lib":122,"fast-isnumeric":17}],162:[function(t,e,r){"use strict";function n(t){return t._id}var a=t("../../lib/polygon"),o=t("../../components/color"),i=t("./axes"),l=t("./constants"),s=a.filter,c=a.tester,u=l.MINSELECT;e.exports=function(t,e,r,a,f){function d(t){var e="y"===t._id.charAt(0)?1:0;return function(r){return t.p2d(r[e])}}function h(t,e){return t-e}var p,g=a.gd._fullLayout._zoomlayer,m=a.element.getBoundingClientRect(),v=a.plotinfo.xaxis._offset,y=a.plotinfo.yaxis._offset,x=e-m.left,b=r-m.top,_=x,w=b,k="M"+x+","+b,M=a.xaxes[0]._length,A=a.yaxes[0]._length,T=a.xaxes.map(n),L=a.yaxes.map(n),z=a.xaxes.concat(a.yaxes);"lasso"===f&&(p=s([[x,b]],l.BENDPX));var C=g.selectAll("path.select-outline").data([1,2]);C.enter().append("path").attr("class",function(t){return"select-outline select-outline-"+t}).attr("transform","translate("+v+", "+y+")").attr("d",k+"Z");var S,O,D,P,N,E=g.append("path").attr("class","zoombox-corners").style({fill:o.background,stroke:o.defaultLine,"stroke-width":1}).attr("transform","translate("+v+", "+y+")").attr("d","M0,0Z"),I=[],R=a.gd,F=[];for(S=0;S0)return Math.log(e)/Math.LN10;if(e<=0&&r&&t.range&&2===t.range.length){var n=t.range[0],a=t.range[1];return.5*(n+a-3*f*Math.abs(n-a))}return s}function r(t){return Math.pow(10,t)}function i(t){return a(t)?(t=Number(t),t<-l||t>l?s:a(t)?Number(t):s):s}var f=10;t.c2l="log"===t.type?e:i,t.l2c="log"===t.type?r:i,t.l2d=function(e){return t.c2d(t.l2c(e))},t.p2d=function(e){return t.l2d(t.p2l(e))},t.cleanRange=function(e){e||(e="range");var r,n,i=t[e],s=(t._id||"x").charAt(0);if(n="date"===t.type?c.DFLTRANGEDATE:"y"===s?c.DFLTRANGEY:c.DFLTRANGEX,n=n.slice(),!i||2!==i.length)return void(t[e]=n);for("date"===t.type&&(i[0]=o.cleanDate(i[0]),i[1]=o.cleanDate(i[1])),r=0;r<2;r++)if("date"===t.type){if(!o.isDateTime(i[r])){t[e]=n;break}if(i[r]o.MAX_MS&&(i[r]=o.MAX_MS),t.r2l(i[0])===t.r2l(i[1])){var u=o.constrain(t.r2l(i[0]),o.MIN_MS+1e3,o.MAX_MS-1e3);i[0]=t.l2r(u-1e3),i[1]=t.l2r(u+1e3);break}}else{if(!a(i[r])){if(!a(i[1-r])){t[e]=n;break}i[r]=i[1-r]*(r?10:.1)}if(i[r]<-l?i[r]=-l:i[r]>l&&(i[r]=l),i[0]===i[1]){var f=Math.max(1,Math.abs(1e-6*i[0]));i[0]-=f,i[1]+=f}}},t.fraction2r=function(e){var r=t.r2l(t.range[0]),n=t.r2l(t.range[1]);return t.l2r(r+e*(n-r))},t.r2fraction=function(e){var r=t.r2l(t.range[0]),n=t.r2l(t.range[1]);return(t.r2l(e)-r)/(n-r)},t.setScale=function(e){var r=t._gd._fullLayout._size,n=t._id.charAt(0);if(t._categories||(t._categories=[]),t.overlaying){var a=u.getFromId(t._gd,t.overlaying);t.domain=a.domain}var i=e&&t._r?"_r":"range";t.cleanRange(i);var l=t.r2l(t[i][0]),s=t.r2l(t[i][1]);if("y"===n?(t._offset=r.t+(1-t.domain[1])*r.h,t._length=r.h*(t.domain[1]-t.domain[0]),t._m=t._length/(l-s),t._b=-t._m*s):(t._offset=r.l+t.domain[0]*r.w,t._length=r.w*(t.domain[1]-t.domain[0]),t._m=t._length/(s-l),t._b=-t._m*l),!isFinite(t._m)||!isFinite(t._b))throw o.notifier("Something went wrong with axis scaling","long"),t._gd._replotting=!1,new Error("axis scaling")},t.l2p=function(e){return a(e)?n.round(t._b+t._m*e,2):s},t.p2l=function(e){return(e-t._b)/t._m},t.c2p=function(e,r){return t.l2p(t.c2l(e,r))},t.p2c=function(e){return t.l2c(t.p2l(e))},t.r2p=function(e,r){return t.l2p(t.r2l(e,r))},t.p2r=function(e){return t.l2r(t.p2l(e))},t.r2c=function(e){return t.l2c(t.r2l(e))},t.c2r=function(e){return t.l2r(t.c2l(e))},["linear","log","-"].indexOf(t.type)!==-1?(t.c2d=i,t.d2c=o.cleanNumber,"log"===t.type?(t.d2l=function(e,r){return t.c2l(t.d2c(e),r)},t.d2r=t.d2l,t.r2d=t.l2d):(t.d2l=o.cleanNumber,t.d2r=o.cleanNumber,t.r2d=i),t.r2l=i,t.l2r=i):"date"===t.type?(t.c2d=o.ms2DateTime,t.d2c=function(t){var e=o.dateTime2ms(t);if(e===s){if(!a(t))return s;e=Number(t)}return o.constrain(e,o.MIN_MS,o.MAX_MS)},t.d2l=t.d2c,t.r2l=t.d2c,t.l2r=t.c2d,t.d2r=o.identity,t.r2d=o.identity,t.cleanr=function(e){return t.c2d(t.d2c(e))}):"category"===t.type&&(t.c2d=function(e){return t._categories[Math.round(e)]},t.d2c=function(e){null!==e&&void 0!==e&&t._categories.indexOf(e)===-1&&t._categories.push(e);var r=t._categories.indexOf(e);return r===-1?s:r},t.d2l=t.d2c,t.r2l=i,t.l2r=i,t.d2r=t.d2c,t.r2d=t.c2d),t.makeCalcdata=function(e,r){var n,a,o;if(r in e)for(n=e[r],a=new Array(n.length),o=0;o0?Number(u):c;else if("string"!=typeof u)e.dtick=c;else{var f=u.charAt(0),d=u.substr(1);d=n(d)?Number(d):0,(d<=0||!("date"===i&&"M"===f&&d===Math.round(d)||"log"===i&&"L"===f||"log"===i&&"D"===f&&(1===d||2===d)))&&(e.dtick=c)}var h="date"===i?"2000-01-01":0,p=r("tick0",h);"date"===i?e.tick0=a.cleanDate(p,h):n(p)&&"D1"!==u&&"D2"!==u?e.tick0=Number(p):e.tick0=h}else{var g=r("tickvals");void 0===g?e.tickmode="auto":r("ticktext")}}},{"../../constants/numerical":110,"../../lib":122,"fast-isnumeric":17}],167:[function(t,e,r){"use strict";var n=t("d3"),a=t("../../plotly"),o=t("../../registry"),i=t("../../lib"),l=t("./axes"),s=/((x|y)([2-9]|[1-9][0-9]+)?)axis$/;e.exports=function(t,e,r,c){function u(t){var e,r,n,a,o,i={};for(e in t)if(r=e.split("."),n=r[0].match(s)){var l=n[1],c=l+"axis";if(a=y[c],o={},Array.isArray(t[e])?o.to=t[e].slice(0):Array.isArray(t[e].range)&&(o.to=t[e].range.slice(0)),!o.to)continue;o.axisName=c,o.length=a._length,x.push(l),i[l]=o}return i}function f(t,e,r){var n,a,o,i=t._plots,l=[];for(n in i){var s=i[n];if(l.indexOf(s)===-1){var c=s.xaxis._id,u=s.yaxis._id,f=s.xaxis.range,d=s.yaxis.range;s.xaxis._r=s.xaxis.range.slice(),s.yaxis._r=s.yaxis.range.slice(),a=r[c]?r[c].to:f,o=r[u]?r[u].to:d,f[0]===a[0]&&f[1]===a[1]&&d[0]===o[0]&&d[1]===o[1]||e.indexOf(c)===-1&&e.indexOf(u)===-1||l.push(s)}}return l}function d(e,r){function n(e,r){for(a=0;ar.duration?(g(),T=window.cancelAnimationFrame(v)):T=window.requestAnimationFrame(v)}var y=t._fullLayout,x=[],b=u(e),_=Object.keys(b),w=f(y,_,b);if(!w.length)return!1;var k;c&&(k=c());var M,A,T,L=n.ease(r.easing);return t._transitionData._interruptCallbacks.push(function(){return window.cancelAnimationFrame(T),T=null,m()}),M=Date.now(),T=window.requestAnimationFrame(v),Promise.resolve()}},{"../../lib":122,"../../plotly":144,"../../registry":188,"./axes":149,d3:14}],168:[function(t,e,r){"use strict";function n(t,e,r){var n,a,o,i=!1;if("data"===e.type)n=t._fullData[null!==e.traces?e.traces[0]:0];else{if("layout"!==e.type)return!1;n=t._fullLayout}return a=c.nestedProperty(n,e.prop).get(),o=r[e.type]=r[e.type]||{},o.hasOwnProperty(e.prop)&&o[e.prop]!==a&&(i=!0),o[e.prop]=a,{changed:i,value:a}}function a(t,e){return Array.isArray(e[0])&&1===e[0].length&&"string"==typeof e[0][0]?[{type:"layout",prop:"_currentFrame",value:e[0][0]}]:[]}function o(t,e){var r=[],n=e[0],a={};if("string"==typeof n)a[n]=e[1];else{if(!c.isPlainObject(n))return r;a=n}return l(a,function(t,e,n){r.push({type:"layout",prop:t,value:n})},"",0),r}function i(t,e){var r,n,a,o,i=[];if(n=e[0],a=e[1],r=e[2],o={},"string"==typeof n)o[n]=a;else{if(!c.isPlainObject(n))return i;o=n,void 0===r&&(r=a)}return void 0===r&&(r=null),l(o,function(e,n,a){var o;if(Array.isArray(a)){var l=Math.min(a.length,t.data.length);r&&(l=Math.min(l,r.length)),o=[];for(var s=0;s0?".":"")+a;c.isPlainObject(o)?l(o,e,i,n+1):e(i,a,o)}})}var s=t("../plotly"),c=t("../lib");r.manageCommandObserver=function(t,e,a,o){var i={},l=!0;e&&e._commandObserver&&(i=e._commandObserver),i.cache||(i.cache={}),i.lookupTable={};var s=r.hasSimpleAPICommandBindings(t,a,i.lookupTable);if(e&&e._commandObserver){if(s)return i;if(e._commandObserver.remove)return e._commandObserver.remove(),e._commandObserver=null,i}if(s){n(t,s,i.cache),i.check=function(){if(l){var e=n(t,s,i.cache);return e.changed&&o&&void 0!==i.lookupTable[e.value]&&(i.disable(),Promise.resolve(o({value:e.value,type:s.type,prop:s.prop,traces:s.traces,index:i.lookupTable[e.value]})).then(i.enable,i.enable)),e.changed}};for(var u=["plotly_relayout","plotly_redraw","plotly_restyle","plotly_update","plotly_animatingframe","plotly_afterplot"],f=0;f=e.width-20?(o["text-anchor"]="start",o.x=5):(o["text-anchor"]="end",o.x=e._paper.attr("width")-7),r.attr(o);var i=r.select(".js-link-to-tool"),l=r.select(".js-link-spacer"),c=r.select(".js-sourcelinks");t._context.showSources&&t._context.showSources(t),t._context.showLink&&n(t,i),l.text(i.text()&&c.text()?" - ":"")},p.sendDataToCloud=function(t){t.emit("plotly_beforeexport");var e=window.PLOTLYENV&&window.PLOTLYENV.BASE_URL||"https://plot.ly",r=s.select(t).append("div").attr("id","hiddenform").style("display","none"),n=r.append("form").attr({action:e+"/external",method:"post",target:"_blank"}),a=n.append("input").attr({type:"text",name:"data"});return a.node().value=p.graphJson(t,!1,"keepdata"),n.node().submit(),r.remove(),t.emit("plotly_afterexport"),!1},p.supplyDefaults=function(t){var e,r=t._fullLayout||{},n=t._fullLayout={},o=t.layout||{},i=t._fullData||[],l=t._fullData=[],s=t.data||[];if(t._transitionData||p.createTransitionData(t),r._initialAutoSizeIsDone){var c=r.width,f=r.height;p.supplyLayoutGlobalDefaults(o,n),o.width||(n.width=c),o.height||(n.height=f)}else{p.supplyLayoutGlobalDefaults(o,n);var d=!o.width||!o.height,h=n.autosize,g=t._context&&t._context.autosizable,m=d&&(h||g);m?p.plotAutoSize(t,o,n):d&&p.sanitizeMargins(t),!h&&d&&(o.width=n.width,o.height=n.height)}n._initialAutoSizeIsDone=!0,n._dataLength=s.length,n._globalTransforms=(t._context||{}).globalTransforms,p.supplyDataDefaults(s,l,o,n),n._has=p._hasPlotType.bind(n);var v=n._modules;for(e=0;e0){var u=l(t._boundingBoxMargins),f=u.left+u.right,h=u.bottom+u.top,g=1-2*i,m=r._container&&r._container.node?r._container.node().getBoundingClientRect():{width:r.width,height:r.height};n=Math.round(g*(m.width-f)),a=Math.round(g*(m.height-h))}else{var v=s?window.getComputedStyle(t):{};n=parseFloat(v.width)||r.width,a=parseFloat(v.height)||r.height}var y=p.layoutAttributes.width.min,x=p.layoutAttributes.height.min;n1,_=!e.height&&Math.abs(r.height-a)>1;(_||b)&&(b&&(r.width=n),_&&(r.height=a)),t._initialAutoSize||(t._initialAutoSize={width:n,height:a}),p.sanitizeMargins(r)},p.supplyLayoutModuleDefaults=function(t,e,r,n){var a,o;u.Axes.supplyLayoutDefaults(t,e,r);var i=e._basePlotModules;for(a=0;a.5*n.width&&(r.l=r.r=0),r.b+r.t>.5*n.height&&(r.b=r.t=0),n._pushmargin[e]={l:{val:r.x,size:r.l+a},r:{val:r.x,size:r.r+a},b:{val:r.y,size:r.b+a},t:{val:r.y,size:r.t+a}}}else delete n._pushmargin[e];t._replotting||p.doAutoMargin(t)}},p.doAutoMargin=function(t){var e=t._fullLayout;e._size||(e._size={}),e._pushmargin||(e._pushmargin={});var r=e._size,n=JSON.stringify(r),a=Math.max(e.margin.l||0,0),o=Math.max(e.margin.r||0,0),i=Math.max(e.margin.t||0,0),l=Math.max(e.margin.b||0,0),s=e._pushmargin;if(e.margin.autoexpand!==!1&&(s.base={l:{val:0,size:a},r:{val:1,size:o},t:{val:1,size:i},b:{val:0,size:l}},Object.keys(s).forEach(function(t){var r=s[t].l||{},n=s[t].b||{},u=r.val,f=r.size,d=n.val,h=n.size;Object.keys(s).forEach(function(t){if(c(f)&&s[t].r){var r=s[t].r.val,n=s[t].r.size;if(r>u){var p=(f*r+(n-e.width)*u)/(r-u),g=(n*(1-u)+(f-e.width)*(1-r))/(r-u);p>=0&&g>=0&&p+g>a+o&&(a=p,o=g)}}if(c(h)&&s[t].t){var m=s[t].t.val,v=s[t].t.size;if(m>d){var y=(h*m+(v-e.height)*d)/(m-d),x=(v*(1-d)+(h-e.height)*(1-m))/(m-d);y>=0&&x>=0&&y+x>l+i&&(l=y,i=x)}}})})),r.l=Math.round(a),r.r=Math.round(o),r.t=Math.round(i),r.b=Math.round(l),r.p=Math.round(e.margin.pad),r.w=Math.round(e.width)-r.l-r.r,r.h=Math.round(e.height)-r.t-r.b,!t._replotting&&"{}"!==n&&n!==JSON.stringify(e._size))return u.plot(t)},p.graphJson=function(t,e,r,n,a){function o(t){if("function"==typeof t)return null;if(d.isPlainObject(t)){var e,n,a={};for(e in t)if("function"!=typeof t[e]&&["_","["].indexOf(e.charAt(0))===-1){if("keepdata"===r){if("src"===e.substr(e.length-3))continue}else if("keepstream"===r){if(n=t[e+"src"],"string"==typeof n&&n.indexOf(":")>0&&!d.isPlainObject(t.stream))continue}else if("keepall"!==r&&(n=t[e+"src"],"string"==typeof n&&n.indexOf(":")>0))continue;a[e]=o(t[e])}return a}return Array.isArray(t)?t.map(o):d.isJSDate(t)?d.ms2DateTime(+t):t}(a&&e&&!t._fullData||a&&!e&&!t._fullLayout)&&p.supplyDefaults(t);var i=a?t._fullData:t.data,l=a?t._fullLayout:t.layout,s={data:(i||[]).map(function(t){var r=o(t);return e&&delete r.fit,r})};return e||(s.layout=o(l)),t.framework&&t.framework.isPolar&&(s=t.framework.getConfig()),"object"===n?s:JSON.stringify(s)},p.modifyFrames=function(t,e){var r,n,a,o=t._transitionData._frames,i=t._transitionData._frameHash;for(r=0;r0&&(t._transitioningWithDuration=!0),t._transitionData._interruptCallbacks.push(function(){_=!0}),a.redraw&&t._transitionData._interruptCallbacks.push(function(){return u.redraw(t)}),t._transitionData._interruptCallbacks.push(function(){t.emit("plotly_transitioninterrupted",[])});var i,l,s=0,c=0,h=t._fullLayout._basePlotModules,p=!1;if(r)for(l=0;l=0,C=z?f.angularAxis.domain:n.extent(M),S=Math.abs(M[1]-M[0]);T&&!A&&(S=0);var O=C.slice();L&&A&&(O[1]+=S);var D=f.angularAxis.ticksCount||4;D>8&&(D=D/(D/8)+D%8),f.angularAxis.ticksStep&&(D=(O[1]-O[0])/D);var P=f.angularAxis.ticksStep||(O[1]-O[0])/(D*(f.minorTicks+1));k&&(P=Math.max(Math.round(P),1)),O[2]||(O[2]=P);var N=n.range.apply(this,O);if(N=N.map(function(t,e){return parseFloat(t.toPrecision(12))}),l=n.scale.linear().domain(O.slice(0,2)).range("clockwise"===f.direction?[0,360]:[360,0]),u.layout.angularAxis.domain=l.domain(),u.layout.angularAxis.endPadding=L?S:0,e=n.select(this).select("svg.chart-root"),"undefined"==typeof e||e.empty()){var E="' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '",I=(new DOMParser).parseFromString(E,"application/xml"),R=this.appendChild(this.ownerDocument.importNode(I.documentElement,!0));e=n.select(R)}e.select(".guides-group").style({"pointer-events":"none"}),e.select(".angular.axis-group").style({"pointer-events":"none"}),e.select(".radial.axis-group").style({"pointer-events":"none"});var F,j=e.select(".chart-group"),q={fill:"none",stroke:f.tickColor},B={"font-size":f.font.size,"font-family":f.font.family,fill:f.font.color,"text-shadow":["-1px 0px","1px -1px","-1px 1px","1px 1px"].map(function(t,e){return" "+t+" 0 "+f.font.outlineColor}).join(",")};if(f.showLegend){F=e.select(".legend-group").attr({transform:"translate("+[x,f.margin.top]+")"}).style({display:"block"});var H=h.map(function(t,e){var r=i.util.cloneJson(t);return r.symbol="DotPlot"===t.geometry?t.dotType||"circle":"LinePlot"!=t.geometry?"square":"line",r.visibleInLegend="undefined"==typeof t.visibleInLegend||t.visibleInLegend,r.color="LinePlot"===t.geometry?t.strokeColor:t.color,r});i.Legend().config({data:h.map(function(t,e){return t.name||"Element"+e}),legendConfig:o({},i.Legend.defaultConfig().legendConfig,{container:F,elements:H,reverseOrder:f.legend.reverseOrder})})();var V=F.node().getBBox();x=Math.min(f.width-V.width-f.margin.left-f.margin.right,f.height-f.margin.top-f.margin.bottom)/2,x=Math.max(10,x),_=[f.margin.left+x,f.margin.top+x],a.range([0,x]),u.layout.radialAxis.domain=a.domain(),F.attr("transform","translate("+[_[0]+x,_[1]-x]+")")}else F=e.select(".legend-group").style({display:"none"});e.attr({width:f.width,height:f.height}).style({opacity:f.opacity}),j.attr("transform","translate("+_+")").style({cursor:"crosshair"});var Z=[(f.width-(f.margin.left+f.margin.right+2*x+(V?V.width:0)))/2,(f.height-(f.margin.top+f.margin.bottom+2*x))/2];if(Z[0]=Math.max(0,Z[0]),Z[1]=Math.max(0,Z[1]),e.select(".outer-group").attr("transform","translate("+Z+")"),f.title){var X=e.select("g.title-group text").style(B).text(f.title),U=X.node().getBBox();X.attr({x:_[0]-U.width/2,y:_[1]-x-20})}var Y=e.select(".radial.axis-group");if(f.radialAxis.gridLinesVisible){var G=Y.selectAll("circle.grid-circle").data(a.ticks(5));G.enter().append("circle").attr({class:"grid-circle"}).style(q),G.attr("r",a),G.exit().remove()}Y.select("circle.outside-circle").attr({r:x}).style(q);var W=e.select("circle.background-circle").attr({r:x}).style({fill:f.backgroundColor,stroke:f.stroke});if(f.radialAxis.visible){var Q=n.svg.axis().scale(a).ticks(5).tickSize(5);Y.call(Q).attr({transform:"rotate("+f.radialAxis.orientation+")"}),Y.selectAll(".domain").style(q),Y.selectAll("g>text").text(function(t,e){return this.textContent+f.radialAxis.ticksSuffix}).style(B).style({"text-anchor":"start"}).attr({x:0,y:0,dx:0,dy:0,transform:function(t,e){return"horizontal"===f.radialAxis.tickOrientation?"rotate("+-f.radialAxis.orientation+") translate("+[0,B["font-size"]]+")":"translate("+[0,B["font-size"]]+")"}}),Y.selectAll("g>line").style({stroke:"black"})}var $=e.select(".angular.axis-group").selectAll("g.angular-tick").data(N),J=$.enter().append("g").classed("angular-tick",!0);$.attr({transform:function(t,e){return"rotate("+s(t,e)+")"}}).style({display:f.angularAxis.visible?"block":"none"}),$.exit().remove(),J.append("line").classed("grid-line",!0).classed("major",function(t,e){return e%(f.minorTicks+1)==0}).classed("minor",function(t,e){return!(e%(f.minorTicks+1)==0)}).style(q),J.selectAll(".minor").style({stroke:f.minorTickColor}),$.select("line.grid-line").attr({x1:f.tickLength?x-f.tickLength:0,x2:x}).style({display:f.angularAxis.gridLinesVisible?"block":"none"}),J.append("text").classed("axis-text",!0).style(B);var K=$.select("text.axis-text").attr({x:x+f.labelOffset,dy:".35em",transform:function(t,e){var r=s(t,e),n=x+f.labelOffset,a=f.angularAxis.tickOrientation;return"horizontal"==a?"rotate("+-r+" "+n+" 0)":"radial"==a?r<270&&r>90?"rotate(180 "+n+" 0)":null:"rotate("+(r<=180&&r>0?-90:90)+" "+n+" 0)"}}).style({"text-anchor":"middle",display:f.angularAxis.labelsVisible?"block":"none"}).text(function(t,e){return e%(f.minorTicks+1)!=0?"":k?k[t]+f.angularAxis.ticksSuffix:t+f.angularAxis.ticksSuffix}).style(B);f.angularAxis.rewriteTicks&&K.text(function(t,e){return e%(f.minorTicks+1)!=0?"":f.angularAxis.rewriteTicks(this.textContent,e)});var tt=n.max(j.selectAll(".angular-tick text")[0].map(function(t,e){return t.getCTM().e+t.getBBox().width}));F.attr({transform:"translate("+[x+tt,f.margin.top]+")"});var et=e.select("g.geometry-group").selectAll("g").size()>0,rt=e.select("g.geometry-group").selectAll("g.geometry").data(h);if(rt.enter().append("g").attr({class:function(t,e){return"geometry geometry"+e}}),rt.exit().remove(),h[0]||et){var nt=[];h.forEach(function(t,e){var r={};r.radialScale=a,r.angularScale=l,r.container=rt.filter(function(t,r){return r==e}),r.geometry=t.geometry,r.orientation=f.orientation,r.direction=f.direction,r.index=e,nt.push({data:t,geometryConfig:r})});var at=n.nest().key(function(t,e){return"undefined"!=typeof t.data.groupId||"unstacked"}).entries(nt),ot=[];at.forEach(function(t,e){"unstacked"===t.key?ot=ot.concat(t.values.map(function(t,e){return[t]})):ot.push(t.values)}),ot.forEach(function(t,e){var r;r=Array.isArray(t)?t[0].geometryConfig.geometry:t.geometryConfig.geometry;var n=t.map(function(t,e){return o(i[r].defaultConfig(),t)});i[r]().config(n)()})}var it,lt,st=e.select(".guides-group"),ct=e.select(".tooltips-group"),ut=i.tooltipPanel().config({container:ct,fontSize:8})(),ft=i.tooltipPanel().config({container:ct,fontSize:8})(),dt=i.tooltipPanel().config({container:ct,hasTick:!0})();if(!A){var ht=st.select("line").attr({x1:0,y1:0,y2:0}).style({stroke:"grey","pointer-events":"none"});j.on("mousemove.angular-guide",function(t,e){var r=i.util.getMousePos(W).angle;ht.attr({x2:-x,transform:"rotate("+r+")"}).style({opacity:.5});var n=(r+180+360-f.orientation)%360;it=l.invert(n);var a=i.util.convertToCartesian(x+12,r+180);ut.text(i.util.round(it)).move([a[0]+_[0],a[1]+_[1]])}).on("mouseout.angular-guide",function(t,e){st.select("line").style({opacity:0})})}var pt=st.select("circle").style({stroke:"grey",fill:"none"});j.on("mousemove.radial-guide",function(t,e){var r=i.util.getMousePos(W).radius;pt.attr({r:r}).style({opacity:.5}),lt=a.invert(i.util.getMousePos(W).radius);var n=i.util.convertToCartesian(r,f.radialAxis.orientation);ft.text(i.util.round(lt)).move([n[0]+_[0],n[1]+_[1]])}).on("mouseout.radial-guide",function(t,e){pt.style({opacity:0}),dt.hide(),ut.hide(),ft.hide()}),e.selectAll(".geometry-group .mark").on("mouseover.tooltip",function(t,r){var a=n.select(this),o=a.style("fill"),l="black",s=a.style("opacity")||1;if(a.attr({"data-opacity":s}),"none"!=o){a.attr({"data-fill":o}),l=n.hsl(o).darker().toString(),a.style({fill:l,opacity:1});var c={t:i.util.round(t[0]),r:i.util.round(t[1])};A&&(c.t=k[t[0]]);var u="t: "+c.t+", r: "+c.r,f=this.getBoundingClientRect(),d=e.node().getBoundingClientRect(),h=[f.left+f.width/2-Z[0]-d.left,f.top+f.height/2-Z[1]-d.top];dt.config({color:l}).text(u),dt.move(h)}else o=a.style("stroke"),a.attr({"data-stroke":o}),l=n.hsl(o).darker().toString(),a.style({stroke:l,opacity:1})}).on("mousemove.tooltip",function(t,e){return 0==n.event.which&&void(n.select(this).attr("data-fill")&&dt.show())}).on("mouseout.tooltip",function(t,e){dt.hide();var r=n.select(this),a=r.attr("data-fill");a?r.style({fill:a,opacity:r.attr("data-opacity")}):r.style({stroke:r.attr("data-stroke"),opacity:r.attr("data-opacity")})})}),d}var e,r,a,l,s={data:[],layout:{}},c={},u={},f=n.dispatch("hover"),d={};return d.render=function(e){return t(e),this},d.config=function(t){if(!arguments.length)return s;var e=i.util.cloneJson(t);return e.data.forEach(function(t,e){s.data[e]||(s.data[e]={}),o(s.data[e],i.Axis.defaultConfig().data[0]),o(s.data[e],t)}),o(s.layout,i.Axis.defaultConfig().layout),o(s.layout,e.layout),this},d.getLiveConfig=function(){return u},d.getinputConfig=function(){return c},d.radialScale=function(t){return a},d.angularScale=function(t){return l},d.svg=function(){return e},n.rebind(d,f,"on"),d},i.Axis.defaultConfig=function(t,e){var r={data:[{t:[1,2,3,4],r:[10,11,12,13],name:"Line1",geometry:"LinePlot",color:null,strokeDash:"solid",strokeColor:null,strokeSize:"1",visibleInLegend:!0,opacity:1}],layout:{defaultColorRange:n.scale.category10().range(),title:null,height:450,width:500,margin:{top:40,right:40,bottom:40,left:40},font:{size:12,color:"gray",outlineColor:"white",family:"Tahoma, sans-serif"},direction:"clockwise",orientation:0,labelOffset:10,radialAxis:{domain:null,orientation:-45,ticksSuffix:"", -visible:!0,gridLinesVisible:!0,tickOrientation:"horizontal",rewriteTicks:null},angularAxis:{domain:[0,360],ticksSuffix:"",visible:!0,gridLinesVisible:!0,labelsVisible:!0,tickOrientation:"horizontal",rewriteTicks:null,ticksCount:null,ticksStep:null},minorTicks:0,tickLength:null,tickColor:"silver",minorTickColor:"#eee",backgroundColor:"none",needsEndSpacing:null,showLegend:!0,legend:{reverseOrder:!1},opacity:1}};return r},i.util={},i.DATAEXTENT="dataExtent",i.AREA="AreaChart",i.LINE="LinePlot",i.DOT="DotPlot",i.BAR="BarChart",i.util._override=function(t,e){for(var r in t)r in e&&(e[r]=t[r])},i.util._extend=function(t,e){for(var r in t)e[r]=t[r]},i.util._rndSnd=function(){return 2*Math.random()-1+(2*Math.random()-1)+(2*Math.random()-1)},i.util.dataFromEquation2=function(t,e){var r=e||6,a=n.range(0,360+r,r).map(function(e,r){var n=e*Math.PI/180,a=t(n);return[e,a]});return a},i.util.dataFromEquation=function(t,e,r){var a=e||6,o=[],i=[];n.range(0,360+a,a).forEach(function(e,r){var n=e*Math.PI/180,a=t(n);o.push(e),i.push(a)});var l={t:o,r:i};return r&&(l.name=r),l},i.util.ensureArray=function(t,e){if("undefined"==typeof t)return null;var r=[].concat(t);return n.range(e).map(function(t,e){return r[e]||r[0]})},i.util.fillArrays=function(t,e,r){return e.forEach(function(e,n){t[e]=i.util.ensureArray(t[e],r)}),t},i.util.cloneJson=function(t){return JSON.parse(JSON.stringify(t))},i.util.validateKeys=function(t,e){"string"==typeof e&&(e=e.split("."));var r=e.shift();return t[r]&&(!e.length||objHasKeys(t[r],e))},i.util.sumArrays=function(t,e){return n.zip(t,e).map(function(t,e){return n.sum(t)})},i.util.arrayLast=function(t){return t[t.length-1]},i.util.arrayEqual=function(t,e){for(var r=Math.max(t.length,e.length,1);r-- >=0&&t[r]===e[r];);return r===-2},i.util.flattenArray=function(t){for(var e=[];!i.util.arrayEqual(e,t);)e=t,t=[].concat.apply([],t);return t},i.util.deduplicate=function(t){return t.filter(function(t,e,r){return r.indexOf(t)==e})},i.util.convertToCartesian=function(t,e){var r=e*Math.PI/180,n=t*Math.cos(r),a=t*Math.sin(r);return[n,a]},i.util.round=function(t,e){var r=e||2,n=Math.pow(10,r);return Math.round(t*n)/n},i.util.getMousePos=function(t){var e=n.mouse(t.node()),r=e[0],a=e[1],o={};return o.x=r,o.y=a,o.pos=e,o.angle=180*(Math.atan2(a,r)+Math.PI)/Math.PI,o.radius=Math.sqrt(r*r+a*a),o},i.util.duplicatesCount=function(t){for(var e,r={},n={},a=0,o=t.length;a0)){var l=n.select(this.parentNode).selectAll("path.line").data([0]);l.enter().insert("path"),l.attr({class:"line",d:d(i),transform:function(e,r){return"rotate("+(t.orientation+90)+")"},"pointer-events":"none"}).style({fill:function(t,e){return m.fill(r,a,o)},"fill-opacity":0,stroke:function(t,e){return m.stroke(r,a,o)},"stroke-width":function(t,e){return m["stroke-width"](r,a,o)},"stroke-dasharray":function(t,e){return m["stroke-dasharray"](r,a,o)},opacity:function(t,e){return m.opacity(r,a,o)},display:function(t,e){return m.display(r,a,o)}})}};var h=t.angularScale.range(),p=Math.abs(h[1]-h[0])/s[0].length*Math.PI/180,g=n.svg.arc().startAngle(function(t){return-p/2}).endAngle(function(t){return p/2}).innerRadius(function(e){return t.radialScale(u+(e[2]||0))}).outerRadius(function(e){return t.radialScale(u+(e[2]||0))+t.radialScale(e[1])});f.arc=function(e,r,a){n.select(this).attr({class:"mark arc",d:g,transform:function(e,r){return"rotate("+(t.orientation+c(e[0])+90)+")"}})};var m={fill:function(t,r,n){return e[n].data.color},stroke:function(t,r,n){return e[n].data.strokeColor},"stroke-width":function(t,r,n){return e[n].data.strokeSize+"px"},"stroke-dasharray":function(t,r,n){return l[e[n].data.strokeDash]},opacity:function(t,r,n){return e[n].data.opacity},display:function(t,r,n){return"undefined"==typeof e[n].data.visible||e[n].data.visible?"block":"none"}},v=n.select(this).selectAll("g.layer").data(s);v.enter().append("g").attr({class:"layer"});var y=v.selectAll("path.mark").data(function(t,e){return t});y.enter().append("path").attr({class:"mark"}),y.style(m).each(f[t.geometryType]),y.exit().remove(),v.exit().remove()})}var e,r=[i.PolyChart.defaultConfig()],a=n.dispatch("hover"),l={solid:"none",dash:[5,2],dot:[2,5]};return t.config=function(t){return arguments.length?(t.forEach(function(t,e){r[e]||(r[e]={}),o(r[e],i.PolyChart.defaultConfig()),o(r[e],t)}),this):r},t.getColorScale=function(){return e},n.rebind(t,a,"on"),t},i.PolyChart.defaultConfig=function(){var t={data:{name:"geom1",t:[[1,2,3,4]],r:[[1,2,3,4]],dotType:"circle",dotSize:64,dotVisible:!1,barWidth:20,color:"#ffa500",strokeSize:1,strokeColor:"silver",strokeDash:"solid",opacity:1,index:0,visible:!0,visibleInLegend:!0},geometryConfig:{geometry:"LinePlot",geometryType:"arc",direction:"clockwise",orientation:0,container:"body",radialScale:null,angularScale:null,colorScale:n.scale.category20()}};return t},i.BarChart=function(){return i.PolyChart()},i.BarChart.defaultConfig=function(){var t={geometryConfig:{geometryType:"bar"}};return t},i.AreaChart=function(){return i.PolyChart()},i.AreaChart.defaultConfig=function(){var t={geometryConfig:{geometryType:"arc"}};return t},i.DotPlot=function(){return i.PolyChart()},i.DotPlot.defaultConfig=function(){var t={geometryConfig:{geometryType:"dot",dotType:"circle"}};return t},i.LinePlot=function(){return i.PolyChart()},i.LinePlot.defaultConfig=function(){var t={geometryConfig:{geometryType:"line"}};return t},i.Legend=function(){function t(){var r=e.legendConfig,a=e.data.map(function(t,e){return[].concat(t).map(function(t,n){var a=o({},r.elements[e]);return a.name=t,a.color=[].concat(r.elements[e].color)[n],a})}),i=n.merge(a);i=i.filter(function(t,e){return r.elements[e]&&(r.elements[e].visibleInLegend||"undefined"==typeof r.elements[e].visibleInLegend)}),r.reverseOrder&&(i=i.reverse());var l=r.container;("string"==typeof l||l.nodeName)&&(l=n.select(l));var s=i.map(function(t,e){return t.color}),c=r.fontSize,u=null==r.isContinuous?"number"==typeof i[0]:r.isContinuous,f=u?r.height:c*i.length,d=l.classed("legend-group",!0),h=d.selectAll("svg").data([0]),p=h.enter().append("svg").attr({width:300,height:f+c,xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",version:"1.1"});p.append("g").classed("legend-axis",!0),p.append("g").classed("legend-marks",!0);var g=n.range(i.length),m=n.scale[u?"linear":"ordinal"]().domain(g).range(s),v=n.scale[u?"linear":"ordinal"]().domain(g)[u?"range":"rangePoints"]([0,f]),y=function(t,e){var r=3*e;return"line"===t?"M"+[[-e/2,-e/12],[e/2,-e/12],[e/2,e/12],[-e/2,e/12]]+"Z":n.svg.symbolTypes.indexOf(t)!=-1?n.svg.symbol().type(t).size(r)():n.svg.symbol().type("square").size(r)()};if(u){var x=h.select(".legend-marks").append("defs").append("linearGradient").attr({id:"grad1",x1:"0%",y1:"0%",x2:"0%",y2:"100%"}).selectAll("stop").data(s);x.enter().append("stop"),x.attr({offset:function(t,e){return e/(s.length-1)*100+"%"}}).style({"stop-color":function(t,e){return t}}),h.append("rect").classed("legend-mark",!0).attr({height:r.height,width:r.colorBandWidth,fill:"url(#grad1)"})}else{var b=h.select(".legend-marks").selectAll("path.legend-mark").data(i);b.enter().append("path").classed("legend-mark",!0),b.attr({transform:function(t,e){return"translate("+[c/2,v(e)+c/2]+")"},d:function(t,e){var r=t.symbol;return y(r,c)},fill:function(t,e){return m(e)}}),b.exit().remove()}var _=n.svg.axis().scale(v).orient("right"),w=h.select("g.legend-axis").attr({transform:"translate("+[u?r.colorBandWidth:c,c/2]+")"}).call(_);return w.selectAll(".domain").style({fill:"none",stroke:"none"}),w.selectAll("line").style({fill:"none",stroke:u?r.textColor:"none"}),w.selectAll("text").style({fill:r.textColor,"font-size":r.fontSize}).text(function(t,e){return i[e].name}),t}var e=i.Legend.defaultConfig(),r=n.dispatch("hover");return t.config=function(t){return arguments.length?(o(e,t),this):e},n.rebind(t,r,"on"),t},i.Legend.defaultConfig=function(t,e){var r={data:["a","b","c"],legendConfig:{elements:[{symbol:"line",color:"red"},{symbol:"square",color:"yellow"},{symbol:"diamond",color:"limegreen"}],height:150,colorBandWidth:30,fontSize:12,container:"body",isContinuous:null,textColor:"grey",reverseOrder:!1}};return r},i.tooltipPanel=function(){var t,e,r,a={container:null,hasTick:!1,fontSize:12,color:"white",padding:5},l="tooltip-"+i.tooltipPanel.uid++,s=10,c=function(){t=a.container.selectAll("g."+l).data([0]);var n=t.enter().append("g").classed(l,!0).style({"pointer-events":"none",display:"none"});return r=n.append("path").style({fill:"white","fill-opacity":.9}).attr({d:"M0 0"}),e=n.append("text").attr({dx:a.padding+s,dy:.3*+a.fontSize}),c};return c.text=function(o){var i=n.hsl(a.color).l,l=i>=.5?"#aaa":"white",u=i>=.5?"black":"white",f=o||"";e.style({fill:u,"font-size":a.fontSize+"px"}).text(f);var d=a.padding,h=e.node().getBBox(),p={fill:a.color,stroke:l,"stroke-width":"2px"},g=h.width+2*d+s,m=h.height+2*d;return r.attr({d:"M"+[[s,-m/2],[s,-m/4],[a.hasTick?0:s,0],[s,m/4],[s,m/2],[g,m/2],[g,-m/2]].join("L")+"Z"}).style(p),t.attr({transform:"translate("+[s,-m/2+2*d]+")"}),t.style({display:"block"}),c},c.move=function(e){if(t)return t.attr({transform:"translate("+[e[0],e[1]]+")"}).style({display:"block"}),c},c.hide=function(){if(t)return t.style({display:"none"}),c},c.show=function(){if(t)return t.style({display:"block"}),c},c.config=function(t){return o(a,t),c},c},i.tooltipPanel.uid=1,i.adapter={},i.adapter.plotly=function(){var t={};return t.convert=function(t,e){var r={};if(t.data&&(r.data=t.data.map(function(t,r){var n=o({},t),a=[[n,["marker","color"],["color"]],[n,["marker","opacity"],["opacity"]],[n,["marker","line","color"],["strokeColor"]],[n,["marker","line","dash"],["strokeDash"]],[n,["marker","line","width"],["strokeSize"]],[n,["marker","symbol"],["dotType"]],[n,["marker","size"],["dotSize"]],[n,["marker","barWidth"],["barWidth"]],[n,["line","interpolation"],["lineInterpolation"]],[n,["showlegend"],["visibleInLegend"]]];return a.forEach(function(t,r){i.util.translator.apply(null,t.concat(e))}),e||delete n.marker,e&&delete n.groupId,e?("LinePlot"===n.geometry?(n.type="scatter",n.dotVisible===!0?(delete n.dotVisible,n.mode="lines+markers"):n.mode="lines"):"DotPlot"===n.geometry?(n.type="scatter",n.mode="markers"):"AreaChart"===n.geometry?n.type="area":"BarChart"===n.geometry&&(n.type="bar"),delete n.geometry):("scatter"===n.type?"lines"===n.mode?n.geometry="LinePlot":"markers"===n.mode?n.geometry="DotPlot":"lines+markers"===n.mode&&(n.geometry="LinePlot",n.dotVisible=!0):"area"===n.type?n.geometry="AreaChart":"bar"===n.type&&(n.geometry="BarChart"),delete n.mode,delete n.type),n}),!e&&t.layout&&"stack"===t.layout.barmode)){var a=i.util.duplicates(r.data.map(function(t,e){return t.geometry}));r.data.forEach(function(t,e){var n=a.indexOf(t.geometry);n!=-1&&(r.data[e].groupId=n)})}if(t.layout){var l=o({},t.layout),s=[[l,["plot_bgcolor"],["backgroundColor"]],[l,["showlegend"],["showLegend"]],[l,["radialaxis"],["radialAxis"]],[l,["angularaxis"],["angularAxis"]],[l.angularaxis,["showline"],["gridLinesVisible"]],[l.angularaxis,["showticklabels"],["labelsVisible"]],[l.angularaxis,["nticks"],["ticksCount"]],[l.angularaxis,["tickorientation"],["tickOrientation"]],[l.angularaxis,["ticksuffix"],["ticksSuffix"]],[l.angularaxis,["range"],["domain"]],[l.angularaxis,["endpadding"],["endPadding"]],[l.radialaxis,["showline"],["gridLinesVisible"]],[l.radialaxis,["tickorientation"],["tickOrientation"]],[l.radialaxis,["ticksuffix"],["ticksSuffix"]],[l.radialaxis,["range"],["domain"]],[l.angularAxis,["showline"],["gridLinesVisible"]],[l.angularAxis,["showticklabels"],["labelsVisible"]],[l.angularAxis,["nticks"],["ticksCount"]],[l.angularAxis,["tickorientation"],["tickOrientation"]],[l.angularAxis,["ticksuffix"],["ticksSuffix"]],[l.angularAxis,["range"],["domain"]],[l.angularAxis,["endpadding"],["endPadding"]],[l.radialAxis,["showline"],["gridLinesVisible"]],[l.radialAxis,["tickorientation"],["tickOrientation"]],[l.radialAxis,["ticksuffix"],["ticksSuffix"]],[l.radialAxis,["range"],["domain"]],[l.font,["outlinecolor"],["outlineColor"]],[l.legend,["traceorder"],["reverseOrder"]],[l,["labeloffset"],["labelOffset"]],[l,["defaultcolorrange"],["defaultColorRange"]]];if(s.forEach(function(t,r){i.util.translator.apply(null,t.concat(e))}),e?("undefined"!=typeof l.tickLength&&(l.angularaxis.ticklen=l.tickLength,delete l.tickLength),l.tickColor&&(l.angularaxis.tickcolor=l.tickColor,delete l.tickColor)):(l.angularAxis&&"undefined"!=typeof l.angularAxis.ticklen&&(l.tickLength=l.angularAxis.ticklen),l.angularAxis&&"undefined"!=typeof l.angularAxis.tickcolor&&(l.tickColor=l.angularAxis.tickcolor)),l.legend&&"boolean"!=typeof l.legend.reverseOrder&&(l.legend.reverseOrder="normal"!=l.legend.reverseOrder),l.legend&&"boolean"==typeof l.legend.traceorder&&(l.legend.traceorder=l.legend.traceorder?"reversed":"normal",delete l.legend.reverseOrder),l.margin&&"undefined"!=typeof l.margin.t){var c=["t","r","b","l","pad"],u=["top","right","bottom","left","pad"],f={};n.entries(l.margin).forEach(function(t,e){f[u[c.indexOf(t.key)]]=t.value}),l.margin=f}e&&(delete l.needsEndSpacing,delete l.minorTickColor,delete l.minorTicks,delete l.angularaxis.ticksCount,delete l.angularaxis.ticksCount,delete l.angularaxis.ticksStep,delete l.angularaxis.rewriteTicks,delete l.angularaxis.nticks,delete l.radialaxis.ticksCount,delete l.radialaxis.ticksCount,delete l.radialaxis.ticksStep,delete l.radialaxis.rewriteTicks,delete l.radialaxis.nticks),r.layout=l}return r},t}},{"../../lib":122,d3:14}],178:[function(t,e,r){"use strict";var n=t("d3"),a=t("../../lib"),o=t("../../components/color"),i=t("./micropolar"),l=t("./undo_manager"),s=a.extendDeepAll,c=e.exports={};c.framework=function(t){function e(e,a){return a&&(f=a),n.select(n.select(f).node().parentNode).selectAll(".svg-container>*:not(.chart-root)").remove(),r=r?s(r,e):e,o||(o=i.Axis()),u=i.adapter.plotly().convert(r),o.config(u).render(f),t.data=r.data,t.layout=r.layout,c.fillLayout(t),r}var r,a,o,u,f,d=new l;return e.isPolar=!0,e.svg=function(){return o.svg()},e.getConfig=function(){return r},e.getLiveConfig=function(){return i.adapter.plotly().convert(o.getLiveConfig(),!0)},e.getLiveScales=function(){return{t:o.angularScale(),r:o.radialScale()}},e.setUndoPoint=function(){var t=this,e=i.util.cloneJson(r);!function(e,r){d.add({undo:function(){r&&t(r)},redo:function(){t(e)}})}(e,a),a=i.util.cloneJson(e)},e.undo=function(){d.undo()},e.redo=function(){d.redo()},e},c.fillLayout=function(t){var e=n.select(t).selectAll(".plot-container"),r=e.selectAll(".svg-container"),a=t.framework&&t.framework.svg&&t.framework.svg(),i={width:800,height:600,paper_bgcolor:o.background,_container:e,_paperdiv:r,_paper:a};t._fullLayout=s(i,t.layout)}},{"../../components/color":30,"../../lib":122,"./micropolar":177,"./undo_manager":179,d3:14}],179:[function(t,e,r){"use strict";e.exports=function(){function t(t,e){return t?(a=!0,t[e](),a=!1,this):this}var e,r=[],n=-1,a=!1;return{add:function(t){return a?this:(r.splice(n+1,r.length-n),r.push(t),n=r.length-1,this)},setCallback:function(t){e=t},undo:function(){var a=r[n];return a?(t(a,"undo"),n-=1,e&&e(a.undo),this):this},redo:function(){var a=r[n+1];return a?(t(a,"redo"),n+=1,e&&e(a.redo),this):this},clear:function(){r=[],n=-1},hasUndo:function(){return n!==-1},hasRedo:function(){return n=i&&(h.min=0,p.min=0,g.min=0,t.aaxis&&delete t.aaxis.min,t.baxis&&delete t.baxis.min,t.caxis&&delete t.caxis.min)}var a=t("../../../components/color"),o=t("../../subplot_defaults"),i=t("./layout_attributes"),l=t("./axis_defaults"),s=["aaxis","baxis","caxis"];e.exports=function(t,e,r){o(t,e,r,{type:"ternary",attributes:i,handleDefaults:n,font:e.font,paper_bgcolor:e.paper_bgcolor})}},{"../../../components/color":30,"../../subplot_defaults":180,"./axis_defaults":184,"./layout_attributes":186}],186:[function(t,e,r){"use strict";var n=t("../../../components/color/attributes"),a=t("./axis_attributes");e.exports={domain:{x:{valType:"info_array",items:[{valType:"number",min:0,max:1},{valType:"number",min:0,max:1}],dflt:[0,1]},y:{valType:"info_array",items:[{valType:"number",min:0,max:1},{valType:"number",min:0,max:1}],dflt:[0,1]}},bgcolor:{valType:"color",dflt:n.background},sum:{valType:"number",dflt:1,min:0},aaxis:a,baxis:a,caxis:a}},{"../../../components/color/attributes":29,"./axis_attributes":183}],187:[function(t,e,r){"use strict";function n(t,e){this.id=t.id,this.graphDiv=t.graphDiv,this.init(e),this.makeFramework()}function a(t){o.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}var o=t("d3"),i=t("tinycolor2"),l=t("../../plotly"),s=t("../../lib"),c=t("../../components/color"),u=t("../../components/drawing"),f=t("../cartesian/set_convert"),d=t("../../lib/extend").extendFlat,h=t("../cartesian/axes"),p=t("../../components/dragelement"),g=t("../../components/titles"),m=t("../cartesian/select"),v=t("../cartesian/constants"),y=t("../cartesian/graph_interact");e.exports=n;var x=n.prototype;x.init=function(t){this.container=t._ternarylayer,this.defs=t._defs,this.layoutId=t._uid,this.traceHash={}},x.plot=function(t,e){var r,n=this,a=e[n.id],o=e._size;s.getPlotDiv(n.plotContainer.node())!==n.graphDiv&&(n.init(n.graphDiv._fullLayout),n.makeFramework()),n.adjustLayout(a,o);var i=n.traceHash,l={};for(r=0;rb*y?(o=y,a=o*b):(a=v,o=a/b),i=g*a/v,l=m*o/y,r=e.l+e.w*h-a/2,n=e.t+e.h*(1-p)-o/2,s.x0=r,s.y0=n,s.w=a,s.h=o,s.sum=x,s.xaxis={type:"linear",range:[_+2*k-x,x-_-2*w],domain:[h-i/2,h+i/2],_id:"x",_gd:s.graphDiv},f(s.xaxis),s.xaxis.setScale(),s.yaxis={type:"linear",range:[_,x-w-k],domain:[p-l/2,p+l/2],_id:"y",_gd:s.graphDiv},f(s.yaxis),s.yaxis.setScale();var M=s.yaxis.domain[0],A=s.aaxis=d({},t.aaxis,{range:[_,x-w-k],side:"left",_counterangle:30,tickangle:(+t.aaxis.tickangle||0)-30,domain:[M,M+l*b],_axislayer:s.layers.aaxis,_gridlayer:s.layers.agrid,_pos:0,_gd:s.graphDiv,_id:"y",_length:a,_gridpath:"M0,0l"+o+",-"+a/2});f(A);var T=s.baxis=d({},t.baxis,{range:[x-_-k,w],side:"bottom",_counterangle:30,domain:s.xaxis.domain,_axislayer:s.layers.baxis,_gridlayer:s.layers.bgrid,_counteraxis:s.aaxis,_pos:0,_gd:s.graphDiv,_id:"x",_length:a,_gridpath:"M0,0l-"+a/2+",-"+o});f(T),A._counteraxis=T;var L=s.caxis=d({},t.caxis,{range:[x-_-w,k],side:"right",_counterangle:30,tickangle:(+t.caxis.tickangle||0)+30,domain:[M,M+l*b],_axislayer:s.layers.caxis,_gridlayer:s.layers.cgrid,_counteraxis:s.baxis,_pos:0,_gd:s.graphDiv,_id:"y",_length:a,_gridpath:"M0,0l-"+o+","+a/2});f(L);var z="M"+r+","+(n+o)+"h"+a+"l-"+a/2+",-"+o+"Z";s.clipDef.select("path").attr("d",z),s.layers.plotbg.select("path").attr("d",z);var C="translate("+r+","+n+")";s.plotContainer.selectAll(".scatterlayer,.maplayer,.zoom").attr("transform",C);var S="translate("+r+","+(n+o)+")";s.layers.baxis.attr("transform",S),s.layers.bgrid.attr("transform",S);var O="translate("+(r+a/2)+","+n+")rotate(30)";s.layers.aaxis.attr("transform",O),s.layers.agrid.attr("transform",O);var D="translate("+(r+a/2)+","+n+")rotate(-30)";s.layers.caxis.attr("transform",D),s.layers.cgrid.attr("transform",D),s.drawAxes(!0),s.plotContainer.selectAll(".crisp").classed("crisp",!1);var P=s.layers.axlines;P.select(".aline").attr("d",A.showline?"M"+r+","+(n+o)+"l"+a/2+",-"+o:"M0,0").call(c.stroke,A.linecolor||"#000").style("stroke-width",(A.linewidth||0)+"px"),P.select(".bline").attr("d",T.showline?"M"+r+","+(n+o)+"h"+a:"M0,0").call(c.stroke,T.linecolor||"#000").style("stroke-width",(T.linewidth||0)+"px"),P.select(".cline").attr("d",L.showline?"M"+(r+a/2)+","+n+"l"+a/2+","+o:"M0,0").call(c.stroke,L.linecolor||"#000").style("stroke-width",(L.linewidth||0)+"px")},x.drawAxes=function(t){var e=this,r=e.graphDiv,n=e.id.substr(7)+"title",a=e.aaxis,o=e.baxis,i=e.caxis;if(h.doTicks(r,a,!0),h.doTicks(r,o,!0),h.doTicks(r,i,!0),t){var l=Math.max(a.showticklabels?a.tickfont.size/2:0,(i.showticklabels?.75*i.tickfont.size:0)+("outside"===i.ticks?.87*i.ticklen:0));g.draw(r,"a"+n,{propContainer:a,propName:e.id+".aaxis.title",dfltName:"Component A",attributes:{x:e.x0+e.w/2,y:e.y0-a.titlefont.size/3-l,"text-anchor":"middle"}});var s=(o.showticklabels?o.tickfont.size:0)+("outside"===o.ticks?o.ticklen:0)+3;g.draw(r,"b"+n,{propContainer:o,propName:e.id+".baxis.title",dfltName:"Component B",attributes:{x:e.x0-s,y:e.y0+e.h+.83*o.titlefont.size+s,"text-anchor":"middle"}}),g.draw(r,"c"+n,{propContainer:i,propName:e.id+".caxis.title",dfltName:"Component C",attributes:{x:e.x0+e.w+s,y:e.y0+e.h+.83*i.titlefont.size+s,"text-anchor":"middle"}})}};var _=v.MINZOOM/2+.87,w="m-0.87,.5h"+_+"v3h-"+(_+5.2)+"l"+(_/2+2.6)+",-"+(.87*_+4.5)+"l2.6,1.5l-"+_/2+","+.87*_+"Z",k="m0.87,.5h-"+_+"v3h"+(_+5.2)+"l-"+(_/2+2.6)+",-"+(.87*_+4.5)+"l-2.6,1.5l"+_/2+","+.87*_+"Z",M="m0,1l"+_/2+","+.87*_+"l2.6,-1.5l-"+(_/2+2.6)+",-"+(.87*_+4.5)+"l-"+(_/2+2.6)+","+(.87*_+4.5)+"l2.6,1.5l"+_/2+",-"+.87*_+"Z",A="m0.5,0.5h5v-2h-5v-5h-2v5h-5v2h5v5h2Z",T=!0;x.initInteractions=function(){function t(t,e,r){var n=R.getBoundingClientRect();_=e-n.left,L=r-n.top,z={a:I.aaxis.range[0],b:I.baxis.range[1],c:I.caxis.range[1]},S=z,C=I.aaxis.range[1]-z.a,O=i(I.graphDiv._fullLayout[I.id].bgcolor).getLuminance(),D="M0,"+I.h+"L"+I.w/2+", 0L"+I.w+","+I.h+"Z",P=!1,N=j.append("path").attr("class","zoombox").style({fill:O>.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("d",D),E=j.append("path").attr("class","zoombox-corners").style({fill:c.background,stroke:c.defaultLine,"stroke-width":1,opacity:0}).attr("d","M0,0Z"),g()}function e(t,e){return 1-e/I.h}function r(t,e){return 1-(t+(I.h-e)/Math.sqrt(3))/I.w}function n(t,e){return(t-(I.h-e)/Math.sqrt(3))/I.w}function o(t,a){var o=_+t,i=L+a,l=Math.max(0,Math.min(1,e(_,L),e(o,i))),s=Math.max(0,Math.min(1,r(_,L),r(o,i))),c=Math.max(0,Math.min(1,n(_,L),n(o,i))),u=(l/2+c)*I.w,f=(1-l/2-s)*I.w,d=(u+f)/2,h=f-u,p=(1-l)*I.h,g=p-h/b;h.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),E.transition().style("opacity",1).duration(200),P=!0)}function u(t,e){if(S===z)return 2===e&&x(),a(F);a(F);var r={};r[I.id+".aaxis.min"]=S.a,r[I.id+".baxis.min"]=S.b,r[I.id+".caxis.min"]=S.c,l.relayout(F,r),T&&F.data&&F._context.showTips&&(s.notifier("Double-click to
zoom back out","long"),T=!1)}function f(){z={a:I.aaxis.range[0],b:I.baxis.range[1],c:I.caxis.range[1]},S=z}function d(t,e){var r=t/I.xaxis._m,n=e/I.yaxis._m;S={a:z.a-n,b:z.b+(r+n)/2,c:z.c-(r-n)/2};var a=[S.a,S.b,S.c].sort(),o={a:a.indexOf(S.a),b:a.indexOf(S.b),c:a.indexOf(S.c)};a[0]<0&&(a[1]+a[0]/2<0?(a[2]+=a[0]+a[1],a[0]=a[1]=0):(a[2]+=a[0]/2,a[1]+=a[0]/2,a[0]=0),S={a:a[o.a],b:a[o.b],c:a[o.c]},e=(z.a-S.a)*I.yaxis._m,t=(z.c-S.c-z.b+S.b)*I.xaxis._m);var i="translate("+(I.x0+t)+","+(I.y0+e)+")";I.plotContainer.selectAll(".scatterlayer,.maplayer").attr("transform",i),I.aaxis.range=[S.a,I.sum-S.b-S.c],I.baxis.range=[I.sum-S.a-S.c,S.b],I.caxis.range=[I.sum-S.a-S.b,S.c],I.drawAxes(!1),I.plotContainer.selectAll(".crisp").classed("crisp",!1)}function h(t,e){if(t){var r={};r[I.id+".aaxis.min"]=S.a,r[I.id+".baxis.min"]=S.b,r[I.id+".caxis.min"]=S.c,l.relayout(F,r)}else 2===e&&x()}function g(){I.plotContainer.selectAll(".select-outline").remove()}function x(){var t={};t[I.id+".aaxis.min"]=0,t[I.id+".baxis.min"]=0,t[I.id+".caxis.min"]=0,F.emit("plotly_doubleclick",null),l.relayout(F,t)}var _,L,z,C,S,O,D,P,N,E,I=this,R=I.layers.plotbg.select("path").node(),F=I.graphDiv,j=I.layers.zoom,q={element:R,gd:F,plotinfo:{plot:j},doubleclick:x,subplot:I.id,prepFn:function(e,r,n){q.xaxes=[I.xaxis],q.yaxes=[I.yaxis];var a=F._fullLayout.dragmode;e.shiftKey&&(a="pan"===a?"zoom":"pan"),"lasso"===a?q.minDrag=1:q.minDrag=void 0,"zoom"===a?(q.moveFn=o,q.doneFn=u,t(e,r,n)):"pan"===a?(q.moveFn=d,q.doneFn=h,f(),g()):"select"!==a&&"lasso"!==a||m(e,r,n,q,a)}};R.onmousemove=function(t){y.hover(F,t,I.id),F._fullLayout._lasthover=R,F._fullLayout._hoversubplot=I.id},R.onmouseout=function(t){F._dragging||p.unhover(F,t)},R.onclick=function(t){y.click(F,t)},p.init(q)}},{"../../components/color":30,"../../components/dragelement":51,"../../components/drawing":53,"../../components/titles":104,"../../lib":122,"../../lib/extend":119,"../../plotly":144,"../cartesian/axes":149, -"../cartesian/constants":154,"../cartesian/graph_interact":156,"../cartesian/select":162,"../cartesian/set_convert":163,d3:14,tinycolor2:20}],188:[function(t,e,r){"use strict";function n(t){return"object"==typeof t&&(t=t.type),t}var a=t("./lib"),o=t("./plots/attributes");r.modules={},r.allCategories={},r.allTypes=[],r.subplotsRegistry={},r.transformsRegistry={},r.componentsRegistry={},r.layoutArrayContainers=[],r.register=function(t,e,n,o){if(r.modules[e])return void a.log("Type "+e+" already registered");for(var i={},l=0;l-1}var o=t("../lib"),i=t("../plots/plots"),l=o.extendFlat,s=o.extendDeep;e.exports=function(t,e){t.framework&&t.framework.isPolar&&(t=t.framework.getConfig());var r,o=t.data,c=t.layout,u=s([],o),f=s({},c,n(e.tileClass));if(e.width&&(f.width=e.width),e.height&&(f.height=e.height),"thumbnail"===e.tileClass||"themes__thumb"===e.tileClass){f.annotations=[];var d=Object.keys(f);for(r=0;r=2?o(t):t>e?Math.ceil(t):Math.floor(t)}var m,v,y,x,b=e.p+(h?d[r]:d),_=b+(g?p[r]:p),w=e.b,k=w+e.s;if("h"===l.orientation?(y=u.c2p(b,!0),x=u.c2p(_,!0),m=c.c2p(w,!0),v=c.c2p(k,!0)):(m=c.c2p(b,!0),v=c.c2p(_,!0),y=u.c2p(w,!0),x=u.c2p(k,!0)),!(a(m)&&a(v)&&a(y)&&a(x)&&m!==v&&y!==x))return void n.select(this).remove();var M=(e.mlw+1||l.marker.line.width+1||(e.trace?e.trace.marker.line.width:0)+1)-1,A=n.round(M/2%1,2);if(!t._context.staticPlot){var T=i.opacity(e.mc||l.marker.color),L=T<1||M>.01?o:s;m=L(m,v),v=L(v,m),y=L(y,x),x=L(x,y)}n.select(this).attr("d","M"+m+","+y+"V"+x+"H"+v+"V"+y+"Z")})}),d.call(l.plot,e)}},{"../../components/color":30,"../../components/errorbars":59,"../../lib":122,"./arrays_to_calcdata":197,d3:14,"fast-isnumeric":17}],206:[function(t,e,r){"use strict";function n(t,e,r,n){if(n.length){var l,s,c,u,f,d=t._fullLayout.barmode,h="overlay"===d,p="group"===d;if(h)a(t,e,r,n);else if(p){for(l=[],s=[],c=0;cs+i&&(c=!0,s=y)),v(e.c2l(g))&&(gs+i&&(c=!0,s=g))}}x.expand(e,[l,s],{tozero:!0,padded:c})}function m(t){return t._id.charAt(0)}var v=t("fast-isnumeric"),y=t("../../registry"),x=t("../../plots/cartesian/axes"),b=t("./sieve.js");e.exports=function(t,e){var r,a=e.xaxis,o=e.yaxis,i=t._fullData,l=t.calcdata,s=[],c=[];for(r=0;r1||0===l.bargap&&0===l.bargroupgap&&!t[0].trace.marker.line.width)&&n.select(this).attr("shape-rendering","crispEdges")}),e.selectAll("g.points").each(function(t){var e=t[0].trace,r=e.marker,i=r.line,l=o.tryColorscale(r,""),s=o.tryColorscale(r,"line");n.select(this).selectAll("path").each(function(t){var e,o,c=(t.mlw+1||i.width+1)-1,u=n.select(this);e="mc"in t?t.mcc=l(t.mc):Array.isArray(r.color)?a.defaultLine:r.color,u.style("stroke-width",c+"px").call(a.fill,e),c&&(o="mlc"in t?t.mlcc=s(t.mlc):Array.isArray(i.color)?a.defaultLine:i.color,u.call(a.stroke,o))})}),e.call(i.style)}},{"../../components/color":30,"../../components/drawing":53,"../../components/errorbars":59,d3:14}],209:[function(t,e,r){"use strict";var n=t("../../components/color"),a=t("../../components/colorscale/has_colorscale"),o=t("../../components/colorscale/defaults");e.exports=function(t,e,r,i,l){r("marker.color",i),a(t,"marker")&&o(t,e,l,r,{prefix:"marker.",cLetter:"c"}),r("marker.line.color",n.defaultLine),a(t,"marker.line")&&o(t,e,l,r,{prefix:"marker.line.",cLetter:"c"}),r("marker.line.width")}},{"../../components/color":30,"../../components/colorscale/defaults":39,"../../components/colorscale/has_colorscale":43}],210:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),a=t("../../components/color/attributes"),o=t("../../lib/extend").extendFlat,i=n.marker,l=i.line;e.exports={y:{valType:"data_array"},x:{valType:"data_array"},x0:{valType:"any"},y0:{valType:"any"},whiskerwidth:{valType:"number",min:0,max:1,dflt:.5},boxpoints:{valType:"enumerated",values:["all","outliers","suspectedoutliers",!1],dflt:"outliers"},boxmean:{valType:"enumerated",values:[!0,"sd",!1],dflt:!1},jitter:{valType:"number",min:0,max:1},pointpos:{valType:"number",min:-2,max:2},orientation:{valType:"enumerated",values:["v","h"]},marker:{outliercolor:{valType:"color",dflt:"rgba(0, 0, 0, 0)"},symbol:o({},i.symbol,{arrayOk:!1}),opacity:o({},i.opacity,{arrayOk:!1,dflt:1}),size:o({},i.size,{arrayOk:!1}),color:o({},i.color,{arrayOk:!1}),line:{color:o({},l.color,{arrayOk:!1,dflt:a.defaultLine}),width:o({},l.width,{arrayOk:!1,dflt:0}),outliercolor:{valType:"color"},outlierwidth:{valType:"number",min:0,dflt:1}}},line:{color:{valType:"color"},width:{valType:"number",min:0,dflt:2}},fillcolor:n.fillcolor}},{"../../components/color/attributes":29,"../../lib/extend":119,"../scatter/attributes":271}],211:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../lib"),o=t("../../plots/cartesian/axes");e.exports=function(t,e){function r(t,e,r,o,i){var l;return r in e?p=o.makeCalcdata(e,r):(l=r+"0"in e?e[r+"0"]:"name"in e&&("category"===o.type||n(e.name)&&["linear","log"].indexOf(o.type)!==-1||a.isDateTime(e.name)&&"date"===o.type)?e.name:t.numboxes,l=o.d2c(l),p=i.map(function(){return l})),p}function i(t,e,r,o,i){var l,s,c,u,f=o.length,d=e.length,h=[],p=[];for(l=0;l=0&&c1,v=r.dPos*(1-d.boxgap)*(1-d.boxgroupgap)/(m?t.numboxes:1),y=m?2*r.dPos*(-.5+(r.boxnum+.5)/t.numboxes)*(1-d.boxgap):0,x=v*g.whiskerwidth;return g.visible!==!0||r.emptybox?void o.select(this).remove():("h"===g.orientation?(s=p,f=h):(s=h,f=p),r.bPos=y,r.bdPos=v,n(),o.select(this).selectAll("path.box").data(i.identity).enter().append("path").attr("class","box").each(function(t){var e=s.c2p(t.pos+y,!0),r=s.c2p(t.pos+y-v,!0),n=s.c2p(t.pos+y+v,!0),a=s.c2p(t.pos+y-x,!0),l=s.c2p(t.pos+y+x,!0),c=f.c2p(t.q1,!0),u=f.c2p(t.q3,!0),d=i.constrain(f.c2p(t.med,!0),Math.min(c,u)+1,Math.max(c,u)-1),h=f.c2p(g.boxpoints===!1?t.min:t.lf,!0),p=f.c2p(g.boxpoints===!1?t.max:t.uf,!0);"h"===g.orientation?o.select(this).attr("d","M"+d+","+r+"V"+n+"M"+c+","+r+"V"+n+"H"+u+"V"+r+"ZM"+c+","+e+"H"+h+"M"+u+","+e+"H"+p+(0===g.whiskerwidth?"":"M"+h+","+a+"V"+l+"M"+p+","+a+"V"+l)):o.select(this).attr("d","M"+r+","+d+"H"+n+"M"+r+","+c+"H"+n+"V"+u+"H"+r+"ZM"+e+","+c+"V"+h+"M"+e+","+u+"V"+p+(0===g.whiskerwidth?"":"M"+a+","+h+"H"+l+"M"+a+","+p+"H"+l))}),g.boxpoints&&o.select(this).selectAll("g.points").data(function(t){return t.forEach(function(t){t.t=r,t.trace=g}),t}).enter().append("g").attr("class","points").selectAll("path").data(function(t){var e,r,n,o,l,s,f,d="all"===g.boxpoints?t.val:t.val.filter(function(e){return et.uf}),h=Math.max((t.max-t.min)/10,t.q3-t.q1),p=1e-9*h,m=h*u,x=[],b=0;if(g.jitter){if(0===h)for(b=1,x=new Array(d.length),e=0;et.lo&&(n.so=!0),n})}).enter().append("path").call(l.translatePoints,h,p),void(g.boxmean&&o.select(this).selectAll("path.mean").data(i.identity).enter().append("path").attr("class","mean").style("fill","none").each(function(t){var e=s.c2p(t.pos+y,!0),r=s.c2p(t.pos+y-v,!0),n=s.c2p(t.pos+y+v,!0),a=f.c2p(t.mean,!0),i=f.c2p(t.mean-t.sd,!0),l=f.c2p(t.mean+t.sd,!0);"h"===g.orientation?o.select(this).attr("d","M"+a+","+r+"V"+n+("sd"!==g.boxmean?"":"m0,0L"+i+","+e+"L"+a+","+r+"L"+l+","+e+"Z")):o.select(this).attr("d","M"+r+","+a+"H"+n+("sd"!==g.boxmean?"":"m0,0L"+e+","+i+"L"+r+","+a+"L"+e+","+l+"Z")); -})))})}},{"../../components/drawing":53,"../../lib":122,d3:14}],218:[function(t,e,r){"use strict";var n=t("../../registry"),a=t("../../plots/cartesian/axes"),o=t("../../lib");e.exports=function(t,e){var r,i,l,s,c=t._fullLayout,u=e.xaxis,f=e.yaxis,d=["v","h"];for(i=0;it?0:1)+(e[0][1]>t?0:2)+(e[1][1]>t?0:4)+(e[1][0]>t?0:8);if(5===r||10===r){var n=(e[0][0]+e[0][1]+e[1][0]+e[1][1])/4;return t>n?5===r?713:1114:5===r?104:208}return 15===r?0:r}function i(t){var e,r,n,a,i,l,s,c,u,f=t[0].z,d=f.length,h=f[0].length,p=2===d||2===h;for(r=0;r20?(l=C[l][(s[0]||s[1])<0?0:1],t.crossings[i]=S[l]):delete t.crossings[i],s=z[l],!s){_.log("Found bad marching index:",l,e,t.level);break}if(h.push(d(t,e,s)),e[0]+=s[0],e[1]+=s[1],u(h[h.length-1],h[h.length-2])&&h.pop(),i=e.join(","),i===o&&s.join(",")===p||r&&(s[0]&&(e[0]<0||e[0]>m-2)||s[1]&&(e[1]<0||e[1]>g-2)))break;l=t.crossings[i]}1e4===a&&_.log("Infinite loop in contour?");var v,y,x,b,w,k,M,A=u(h[0],h[h.length-1]),T=0,L=.2*t.smoothing,O=[],D=0;for(a=1;a=D;a--)if(v=O[a],v=D&&v+O[y]20&&e?208===t||1114===t?n=0===r[0]?1:-1:a=0===r[1]?1:-1:M.indexOf(t)!==-1?a=1:T.indexOf(t)!==-1?n=1:A.indexOf(t)!==-1?a=-1:n=-1,[n,a]}function u(t,e){return Math.abs(t[0]-e[0])<.01&&Math.abs(t[1]-e[1])<.01}function f(t,e){var r=t[0]-e[0],n=t[1]-e[1];return Math.sqrt(r*r+n*n)}function d(t,e,r){var n=e[0]+Math.max(r[0],0),a=e[1]+Math.max(r[1],0),o=t.z[a][n],i=t.xaxis,l=t.yaxis;if(r[1]){var s=(t.level-o)/(t.z[a][n+1]-o);return[i.c2p((1-s)*t.x[n]+s*t.x[n+1],!0),l.c2p(t.y[a],!0)]}var c=(t.level-o)/(t.z[a+1][n]-o);return[i.c2p(t.x[n],!0),l.c2p((1-c)*t.y[a]+c*t.y[a+1],!0)]}function h(t,e,r){var n=t.plot.select(".maplayer").selectAll("g.contour."+r).data(e);return n.enter().append("g").classed("contour",!0).classed(r,!0),n.exit().remove(),n}function p(t,e,r){var n=t.selectAll("g.contourbg").data([0]);n.enter().append("g").classed("contourbg",!0);var a=n.selectAll("path").data("fill"===r.coloring?[0]:[]);a.enter().append("path"),a.exit().remove(),a.attr("d","M"+e.join("L")+"Z").style("stroke","none")}function g(t,e,r,n){var a=t.selectAll("g.contourfill").data([0]);a.enter().append("g").classed("contourfill",!0);var o=a.selectAll("path").data("fill"===n.coloring?e:[]);o.enter().append("path"),o.exit().remove(),o.each(function(t){var e=m(t,r);e?b.select(this).attr("d",e).style("stroke","none"):b.select(this).remove()})}function m(t,e){function r(t){return Math.abs(t[1]-e[0][1])<.01}function n(t){return Math.abs(t[1]-e[2][1])<.01}function a(t){return Math.abs(t[0]-e[0][0])<.01}function o(t){return Math.abs(t[0]-e[2][0])<.01}for(var i,l,s,c,u,f,d=t.edgepaths.length||t.z[0][0]=0&&(l=m,c=u):Math.abs(i[1]-l[1])<.01?Math.abs(i[1]-m[1])<.01&&(m[0]-i[0])*(l[0]-m[0])>=0&&(l=m,c=u):_.log("endpt to newendpt is not vert. or horz.",i,l,m)}if(i=l,c>=0)break;d+="L"+l}if(c===t.edgepaths.length){_.log("unclosed perimeter path");break}h=c,g=p.indexOf(h)===-1,g&&(h=p[0],d+="Z")}for(h=0;h1;if(p&&!d&&"category"!==o.type){var g=e.length;if(!(g<=a))return f?e.slice(0,a):e.slice(0,a+1);if(f||h)c=e.slice(0,a);else if(1===a)c=[e[0]-.5,e[0]+.5];else{for(c=[1.5*e[0]-.5*e[1]],s=1;sy;n++)i=s(t,e,o(i));return i>y&&f.log("interp2d didn't converge quickly",i),t}function l(t){var e,r,n,a,o,i,l,s,c=[],u={},f=[],d=t[0],h=[],p=[0,0,0],g=v(t);for(r=0;r=0;o--)a=f[o],r=a[0],n=a[1],i=((u[[r-1,n]]||p)[2]+(u[[r+1,n]]||p)[2]+(u[[r,n-1]]||p)[2]+(u[[r,n+1]]||p)[2])/20,i&&(l[a]=[r,n,i],f.splice(o,1),s=!0);if(!s)throw"findEmpties iterated with no new neighbors";for(a in l)u[a]=l[a],c.push(l[a])}return c.sort(function(t,e){return e[2]-t[2]})}function s(t,e,r){var n,a,o,i,l,s,c,u,f,d,h,p,g,m=0;for(i=0;ip&&(m=Math.max(m,Math.abs(t[a][o]-h)/(g-p))))}return m}var c=t("fast-isnumeric"),u=t("../../registry"),f=t("../../lib"),d=t("../../plots/cartesian/axes"),h=t("../histogram2d/calc"),p=t("../../components/colorscale/calc"),g=t("./has_columns"),m=t("./convert_column_xyz"),v=t("./max_row_length");e.exports=function(t,e){function r(t){z=e._input.zsmooth=e.zsmooth=!1,f.notifier("cannot fast-zsmooth: "+t)}var o,s,c,y,x,b,_,w,k=d.getFromId(t,e.xaxis||"x"),M=d.getFromId(t,e.yaxis||"y"),A=u.traceIs(e,"contour"),T=u.traceIs(e,"histogram"),L=u.traceIs(e,"gl2d"),z=A?"best":e.zsmooth;if(k._minDtick=0,M._minDtick=0,T){var C=h(t,e);o=C.x,s=C.x0,c=C.dx,y=C.y,x=C.y0,b=C.dy,_=C.z}else g(e)&&m(e,k,M),o=e.x?k.makeCalcdata(e,"x"):[],y=e.y?M.makeCalcdata(e,"y"):[],s=e.x0||0,c=e.dx||1,x=e.y0||0,b=e.dy||1,_=n(e),(A||e.connectgaps)&&(e._emptypoints=l(_),e._interpz=i(_,e._emptypoints,e._interpz));if("fast"===z)if("log"===k.type||"log"===M.type)r("log axis found");else if(!T){if(o.length){var S=(o[o.length-1]-o[0])/(o.length-1),O=Math.abs(S/100);for(w=0;wO){r("x scale is not linear");break}}if(y.length&&"fast"===z){var D=(y[y.length-1]-y[0])/(y.length-1),P=Math.abs(D/100);for(w=0;wP){r("y scale is not linear");break}}}var N=v(_),E="scaled"===e.xtype?"":o,I=a(e,E,s,c,N,k),R="scaled"===e.ytype?"":y,F=a(e,R,x,b,_.length,M);L||(d.expand(k,I),d.expand(M,F));var j={x:I,y:F,z:_};if(p(e,_,"","z"),A&&e.contours&&"heatmap"===e.contours.coloring){var q="contour"===e.type?"heatmap":"histogram2d";j.xfill=a(q,E,s,c,N,k),j.yfill=a(q,R,x,b,_.length,M)}return[j]};var y=.01,x=[[-1,0],[1,0],[0,-1],[0,1]]},{"../../components/colorscale/calc":36,"../../lib":122,"../../plots/cartesian/axes":149,"../../registry":188,"../histogram2d/calc":243,"./convert_column_xyz":233,"./has_columns":235,"./max_row_length":238,"fast-isnumeric":17}],232:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../lib"),o=t("../../plots/plots"),i=t("../../components/colorscale"),l=t("../../components/colorbar/draw");e.exports=function(t,e){var r=e[0].trace,s="cb"+r.uid,c=r.zmin,u=r.zmax;if(n(c)||(c=a.aggNums(Math.min,null,r.z)),n(u)||(u=a.aggNums(Math.max,null,r.z)),t._fullLayout._infolayer.selectAll("."+s).remove(),!r.showscale)return void o.autoMargin(t,s);var f=e[0].t.cb=l(t,s),d=i.makeColorScaleFunc(i.extractScale(r.colorscale,c,u),{noNumericCheck:!0});f.fillcolor(d).filllevels({start:c,end:u,size:(u-c)/254}).options(r.colorbar)()}},{"../../components/colorbar/draw":33,"../../components/colorscale":44,"../../lib":122,"../../plots/plots":173,"fast-isnumeric":17}],233:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e,r){var a,o=t.x.slice(),i=t.y.slice(),l=t.z,s=t.text,c=Math.min(o.length,i.length,l.length),u=void 0!==s&&!Array.isArray(s[0]);for(c=y[0].length||f<0||f>y.length)return}else{if(n.inbox(e-m[0],e-m[m.length-1])>o||n.inbox(r-v[0],r-v[v.length-1])>o)return;if(l){var w;for(b=[2*m[0]-m[1]],w=1;w0&&o0&&l0;)_=m.c2p(L[A]),A--;for(_0;)M=v.c2p(z[A]),A--;if(M0&&(n=!0);for(var l=0;ly&&g.splice(y,g.length-y),v.length>y&&v.splice(y,v.length-y),!e.autobinx&&"xbins"in e||(e.xbins=a.autoBin(g,p,e.nbinsx,"2d"),"histogram2dcontour"===e.type&&(e.xbins.start=p.c2r(a.tickIncrement(p.r2c(e.xbins.start),e.xbins.size,!0)),e.xbins.end=p.c2r(a.tickIncrement(p.r2c(e.xbins.end),e.xbins.size))),e._input.xbins=e.xbins),!e.autobiny&&"ybins"in e||(e.ybins=a.autoBin(v,m,e.nbinsy,"2d"),"histogram2dcontour"===e.type&&(e.ybins.start=m.c2r(a.tickIncrement(m.r2c(e.ybins.start),e.ybins.size,!0)),e.ybins.end=m.c2r(a.tickIncrement(m.r2c(e.ybins.end),e.ybins.size))),e._input.ybins=e.ybins),d=[];var x,b,_=[],w=[],k="string"==typeof e.xbins.size?[]:e.xbins,M="string"==typeof e.xbins.size?[]:e.ybins,A=0,T=[],L=e.histnorm,z=e.histfunc,C=L.indexOf("density")!==-1,S="max"===z||"min"===z,O=S?null:0,D=o.count,P=i[L],N=!1,E=[],I=[],R="z"in e?e.z:"marker"in e&&Array.isArray(e.marker.color)?e.marker.color:"";R&&"count"!==z&&(N="avg"===z,D=o[z]);var F=e.xbins,j=p.r2c(F.start),q=p.r2c(F.end)+(j-a.tickIncrement(j,F.size))/1e6;for(h=j;h=0&&x=0&&bo)return r[t]=o,o-r[t]}return 0},max:function(t,e,r,a){var o=a[e];if(n(o)){if(o=Number(o),!n(r[t]))return r[t]=o,o;if(r[t]=0&&yR;r--)if(f[r]){F=r;break}for(r=R;r<=F;r++)n(u[r])&&n(f[r])&&I.push({p:u[r],s:f[r],b:0});return I}}},{"../../lib":122,"../../plots/cartesian/axes":149,"./average":251,"./bin_functions":253,"./clean_bins":255,"./norm_functions":258,"fast-isnumeric":17}],255:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../lib").cleanDate,o=t("../../constants/numerical").ONEDAY;e.exports=function(t,e,r){var i=e.type,l=r+"bins",s=t[l];s||(s=t[l]={});var c="date"===i?function(t){return t||0===t?a(t):null}:function(t){return n(t)?Number(t):null};s.start=c(s.start),s.end=c(s.end);var u="date"===i?o:1,f=s.size;if(n(f))s.size=f>0?Number(f):u;else if("string"!=typeof f)s.size=u;else{var d=f.charAt(0),h=f.substr(1);h=n(h)?Number(h):0,(h<=0||"date"!==i||"M"!==d||h!==Math.round(h))&&(s.size=u)}var p="autobin"+r;"boolean"!=typeof t[p]&&(t[p]=!((s.start||0===s.start)&&(s.end||0===s.end))),t[p]||delete t["nbins"+r]}},{"../../constants/numerical":110,"../../lib":122,"fast-isnumeric":17}],256:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("../../components/color"),o=t("./bin_defaults"),i=t("../bar/style_defaults"),l=t("../../components/errorbars/defaults"),s=t("./attributes");e.exports=function(t,e,r,c){function u(r,a){return n.coerce(t,e,s,r,a)}var f=u("x"),d=u("y");u("text");var h=u("orientation",d&&!f?"h":"v"),p=e["v"===h?"x":"y"];if(!p||!p.length)return void(e.visible=!1);var g=e["h"===h?"x":"y"];g&&u("histfunc");var m="h"===h?["y"]:["x"];o(t,e,u,m),i(t,e,u,r,c),l(t,e,a.defaultLine,{axis:"y"}),l(t,e,a.defaultLine,{axis:"x",inherit:"y"})}},{"../../components/color":30,"../../components/errorbars/defaults":58,"../../lib":122,"../bar/style_defaults":209,"./attributes":250,"./bin_defaults":252}],257:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.layoutAttributes=t("../bar/layout_attributes"),n.supplyDefaults=t("./defaults"),n.supplyLayoutDefaults=t("../bar/layout_defaults"),n.calc=t("./calc"),n.setPositions=t("../bar/set_positions"),n.plot=t("../bar/plot"),n.style=t("../bar/style"),n.colorbar=t("../scatter/colorbar"),n.hoverPoints=t("../bar/hover"),n.moduleType="trace",n.name="histogram",n.basePlotModule=t("../../plots/cartesian"),n.categories=["cartesian","bar","histogram","oriented","errorBarsOK","showLegend"],n.meta={},e.exports=n},{"../../plots/cartesian":157,"../bar/hover":201,"../bar/layout_attributes":203,"../bar/layout_defaults":204,"../bar/plot":205,"../bar/set_positions":206,"../bar/style":208,"../scatter/colorbar":274,"./attributes":250,"./calc":254,"./defaults":256}],258:[function(t,e,r){"use strict";e.exports={percent:function(t,e){for(var r=t.length,n=100/e,a=0;a")}return g};var s},{"../../components/color":30,"./helpers":263,"fast-isnumeric":17,tinycolor2:20}],262:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("./attributes");e.exports=function(t,e,r,o){function i(r,o){return n.coerce(t,e,a,r,o)}var l=n.coerceFont,s=i("values");if(!Array.isArray(s)||!s.length)return void(e.visible=!1);var c=i("labels");Array.isArray(c)||(i("label0"),i("dlabel"));var u=i("marker.line.width");u&&i("marker.line.color");var f=i("marker.colors");Array.isArray(f)||(e.marker.colors=[]),i("scalegroup");var d=i("text"),h=i("textinfo",Array.isArray(d)?"text+percent":"percent");if(i("hoverinfo",1===o._dataLength?"label+text+value+percent":void 0),h&&"none"!==h){var p=i("textposition"),g=Array.isArray(p)||"auto"===p,m=g||"inside"===p,v=g||"outside"===p;if(m||v){var y=l(i,"textfont",o.font);m&&l(i,"insidetextfont",y),v&&l(i,"outsidetextfont",y)}}i("domain.x"),i("domain.y"),i("hole"),i("sort"),i("direction"),i("rotation"),i("pull")}},{"../../lib":122,"./attributes":259}],263:[function(t,e,r){"use strict";var n=t("../../lib");r.formatPiePercent=function(t,e){var r=(100*t).toPrecision(3);return r.lastIndexOf(".")!==-1&&(r=r.replace(/[.]?0+$/,"")),n.numSeparate(r,e)+"%"},r.formatPieValue=function(t,e){var r=t.toPrecision(10);return r.lastIndexOf(".")!==-1&&(r=r.replace(/[.]?0+$/,"")),n.numSeparate(r,e)}},{"../../lib":122}],264:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.supplyLayoutDefaults=t("./layout_defaults"),n.layoutAttributes=t("./layout_attributes"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("./style"),n.styleOne=t("./style_one"),n.moduleType="trace",n.name="pie",n.basePlotModule=t("./base_plot"),n.categories=["pie","showLegend"],n.meta={},e.exports=n},{"./attributes":259,"./base_plot":260,"./calc":261,"./defaults":262,"./layout_attributes":265,"./layout_defaults":266,"./plot":267,"./style":268,"./style_one":269}],265:[function(t,e,r){"use strict";e.exports={hiddenlabels:{valType:"data_array"}}},{}],266:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("./layout_attributes");e.exports=function(t,e){function r(r,o){return n.coerce(t,e,a,r,o)}r("hiddenlabels")}},{"../../lib":122,"./layout_attributes":265}],267:[function(t,e,r){"use strict";function n(t,e,r){var n=Math.sqrt(t.width*t.width+t.height*t.height),o=t.width/t.height,i=Math.PI*Math.min(e.v/r.vTotal,.5),l=1-r.trace.hole,s=a(e,r),c={scale:s*r.r*2/n,rCenter:1-s,rotate:0};if(c.scale>=1)return c;var u=o+1/(2*Math.tan(i)),f=r.r*Math.min(1/(Math.sqrt(u*u+.5)+u),l/(Math.sqrt(o*o+l/2)+o)),d={scale:2*f/t.height,rCenter:Math.cos(f/r.r)-f*o/r.r,rotate:(180/Math.PI*e.midangle+720)%180-90},h=1/o,p=h+1/(2*Math.tan(i)),g=r.r*Math.min(1/(Math.sqrt(p*p+.5)+p),l/(Math.sqrt(h*h+l/2)+h)),m={scale:2*g/t.width,rCenter:Math.cos(g/r.r)-g/o/r.r,rotate:(180/Math.PI*e.midangle+810)%180-90},v=m.scale>d.scale?m:d;return c.scale<1&&v.scale>c.scale?v:c}function a(t,e){if(t.v===e.vTotal&&!e.trace.hole)return 1;var r=Math.PI*Math.min(t.v/e.vTotal,.5);return Math.min(1/(1+1/Math.sin(r)),(1-e.trace.hole)/2)}function o(t,e){var r=e.pxmid[0],n=e.pxmid[1],a=t.width/2,o=t.height/2;return r<0&&(a*=-1),n<0&&(o*=-1),{scale:1,rCenter:1,rotate:0,x:a+Math.abs(o)*(a>0?1:-1)/2,y:o/(1+r*r/(n*n)),outside:!0}}function i(t,e){function r(t,e){return t.pxmid[1]-e.pxmid[1]}function n(t,e){return e.pxmid[1]-t.pxmid[1]}function a(t,r){r||(r={});var n,a,o,l,d,h,g=r.labelExtraY+(i?r.yLabelMax:r.yLabelMin),m=i?t.yLabelMin:t.yLabelMax,v=i?t.yLabelMax:t.yLabelMin,y=t.cyFinal+c(t.px0[1],t.px1[1]),x=g-m;if(x*f>0&&(t.labelExtraY=x),Array.isArray(e.pull))for(a=0;a=e.pull[o.i]||((t.pxmid[1]-o.pxmid[1])*f>0?(l=o.cyFinal+c(o.px0[1],o.px1[1]),x=l-m-t.labelExtraY,x*f>0&&(t.labelExtraY+=x)):(v+t.labelExtraY-y)*f>0&&(n=3*u*Math.abs(a-p.indexOf(t)),d=o.cxFinal+s(o.px0[0],o.px1[0]),h=d+n-(t.cxFinal+t.pxmid[0])-t.labelExtraX,h*u>0&&(t.labelExtraX+=h)))}var o,i,l,s,c,u,f,d,h,p,g,m,v;for(i=0;i<2;i++)for(l=i?r:n,c=i?Math.max:Math.min,f=i?1:-1,o=0;o<2;o++){for(s=o?Math.max:Math.min,u=o?1:-1,d=t[i][o],d.sort(l),h=t[1-i][o],p=h.concat(d),m=[],g=0;gu&&(u=l.pull[o]);i.r=Math.min(r/c(l.tilt,Math.sin(s),l.depth),n/c(l.tilt,Math.cos(s),l.depth))/(2+2*u),i.cx=e.l+e.w*(l.domain.x[1]+l.domain.x[0])/2,i.cy=e.t+e.h*(2-l.domain.y[1]-l.domain.y[0])/2,l.scalegroup&&h.indexOf(l.scalegroup)===-1&&h.push(l.scalegroup)}for(o=0;of.vTotal/2?1:0)}function c(t,e,r){if(!t)return 1;var n=Math.sin(t*Math.PI/180);return Math.max(.01,r*n*Math.abs(e)+2*Math.sqrt(1-n*n*e*e))}var u=t("d3"),f=t("../../plots/cartesian/graph_interact"),d=t("../../components/color"),h=t("../../components/drawing"),p=t("../../lib/svg_text_utils"),g=t("./helpers");e.exports=function(t,e){var r=t._fullLayout;l(e,r._size);var c=r._pielayer.selectAll("g.trace").data(e);c.enter().append("g").attr({"stroke-linejoin":"round",class:"trace"}),c.exit().remove(),c.order(),c.each(function(e){var l=u.select(this),c=e[0],m=c.trace,v=0,y=(m.depth||0)*c.r*Math.sin(v)/2,x=m.tiltaxis||0,b=x*Math.PI/180,_=[y*Math.sin(b),y*Math.cos(b)],w=c.r*Math.cos(v),k=l.selectAll("g.part").data(m.tilt?["top","sides"]:["top"]);k.enter().append("g").attr("class",function(t){return t+" part"}),k.exit().remove(),k.order(),s(e),l.selectAll(".top").each(function(){var l=u.select(this).selectAll("g.slice").data(e);l.enter().append("g").classed("slice",!0),l.exit().remove();var s=[[[],[]],[[],[]]],v=!1;l.each(function(i){function l(e){var n=t._fullLayout,o=t._fullData[m.index],l=o.hoverinfo;if("all"===l&&(l="label+text+value+percent+name"),!t._dragging&&n.hovermode!==!1&&"none"!==l&&"skip"!==l&&l){var s=a(i,c),u=k+i.pxmid[0]*(1-s),d=M+i.pxmid[1]*(1-s),h=r.separators,p=[];l.indexOf("label")!==-1&&p.push(i.label),o.text&&o.text[i.i]&&l.indexOf("text")!==-1&&p.push(o.text[i.i]),l.indexOf("value")!==-1&&p.push(g.formatPieValue(i.v,h)),l.indexOf("percent")!==-1&&p.push(g.formatPiePercent(i.v/c.vTotal,h)),f.loneHover({x0:u-s*c.r,x1:u+s*c.r,y:d,text:p.join("
"),name:l.indexOf("name")!==-1?o.name:void 0,color:i.color,idealAlign:i.pxmid[0]<0?"left":"right"},{container:n._hoverlayer.node(),outerContainer:n._paper.node()}),f.hover(t,e,"pie"),L=!0}}function d(e){t.emit("plotly_unhover",{points:[e]}),L&&(f.loneUnhover(r._hoverlayer.node()),L=!1)}function y(){t._hoverdata=[i],i.curveNumber=e[0].trace.index,t._hoverdata.trace=e[0].trace,f.click(t,window.event||{target:!0})}function b(t,e,r,n){return"a"+n*c.r+","+n*w+" "+x+" "+i.largeArc+(r?" 1 ":" 0 ")+n*(e[0]-t[0])+","+n*(e[1]-t[1])}if(i.hidden)return void u.select(this).selectAll("path,g").remove();s[i.pxmid[1]<0?0:1][i.pxmid[0]<0?0:1].push(i);var k=c.cx+_[0],M=c.cy+_[1],A=u.select(this),T=A.selectAll("path.surface").data([i]),L=!1;if(T.enter().append("path").classed("surface",!0).style({"pointer-events":"all"}),A.select("path.textline").remove(),A.on("mouseover",l).on("mouseout",d).on("click",y).on("contextmenu",y),m.pull){var z=+(Array.isArray(m.pull)?m.pull[i.i]:m.pull)||0;z>0&&(k+=z*i.pxmid[0],M+=z*i.pxmid[1])}i.cxFinal=k,i.cyFinal=M;var C=m.hole;if(i.v===c.vTotal){var S="M"+(k+i.px0[0])+","+(M+i.px0[1])+b(i.px0,i.pxmid,!0,1)+b(i.pxmid,i.px0,!0,1)+"Z";C?T.attr("d","M"+(k+C*i.px0[0])+","+(M+C*i.px0[1])+b(i.px0,i.pxmid,!1,C)+b(i.pxmid,i.px0,!1,C)+"Z"+S):T.attr("d",S)}else{var O=b(i.px0,i.px1,!0,1);if(C){var D=1-C;T.attr("d","M"+(k+C*i.px1[0])+","+(M+C*i.px1[1])+b(i.px1,i.px0,!1,C)+"l"+D*i.px0[0]+","+D*i.px0[1]+O+"Z")}else T.attr("d","M"+k+","+M+"l"+i.px0[0]+","+i.px0[1]+O+"Z")}var P=Array.isArray(m.textposition)?m.textposition[i.i]:m.textposition,N=A.selectAll("g.slicetext").data(i.text&&"none"!==P?[0]:[]);N.enter().append("g").classed("slicetext",!0),N.exit().remove(),N.each(function(){var t=u.select(this).selectAll("text").data([0]);t.enter().append("text").attr("data-notex",1),t.exit().remove(),t.text(i.text).attr({class:"slicetext",transform:"","data-bb":"","text-anchor":"middle",x:0,y:0}).call(h.font,"outside"===P?m.outsidetextfont:m.insidetextfont).call(p.convertToTspans),t.selectAll("tspan.line").attr({x:0,y:0});var e,r=h.bBox(t.node());"outside"===P?e=o(r,i):(e=n(r,i,c),"auto"===P&&e.scale<1&&(t.call(h.font,m.outsidetextfont),m.outsidetextfont.family===m.insidetextfont.family&&m.outsidetextfont.size===m.insidetextfont.size||(t.attr({"data-bb":""}),r=h.bBox(t.node())),e=o(r,i)));var a=k+i.pxmid[0]*e.rCenter+(e.x||0),l=M+i.pxmid[1]*e.rCenter+(e.y||0);e.outside&&(i.yLabelMin=l-r.height/2,i.yLabelMid=l,i.yLabelMax=l+r.height/2,i.labelExtraX=0,i.labelExtraY=0,v=!0),t.attr("transform","translate("+a+","+l+")"+(e.scale<1?"scale("+e.scale+")":"")+(e.rotate?"rotate("+e.rotate+")":"")+"translate("+-(r.left+r.right)/2+","+-(r.top+r.bottom)/2+")")})}),v&&i(s,m),l.each(function(t){if(t.labelExtraX||t.labelExtraY){var e=u.select(this),r=e.select("g.slicetext text");r.attr("transform","translate("+t.labelExtraX+","+t.labelExtraY+")"+r.attr("transform"));var n=t.cxFinal+t.pxmid[0],a=t.cyFinal+t.pxmid[1],o="M"+n+","+a,i=(t.yLabelMax-t.yLabelMin)*(t.pxmid[0]<0?-1:1)/4;if(t.labelExtraX){var l=t.labelExtraX*t.pxmid[1]/t.pxmid[0],s=t.yLabelMid+t.labelExtraY-(t.cyFinal+t.pxmid[1]);o+=Math.abs(l)>Math.abs(s)?"l"+s*t.pxmid[0]/t.pxmid[1]+","+s+"H"+(n+t.labelExtraX+i):"l"+t.labelExtraX+","+l+"v"+(s-l)+"h"+i}else o+="V"+(t.yLabelMid+t.labelExtraY)+"h"+i;e.append("path").classed("textline",!0).call(d.stroke,m.outsidetextfont.color).attr({"stroke-width":Math.min(2,m.outsidetextfont.size/8),d:o,fill:"none"})}})})}),setTimeout(function(){c.selectAll("tspan").each(function(){var t=u.select(this);t.attr("dy")&&t.attr("dy",t.attr("dy"))})},0)}},{"../../components/color":30,"../../components/drawing":53,"../../lib/svg_text_utils":134,"../../plots/cartesian/graph_interact":156,"./helpers":263,d3:14}],268:[function(t,e,r){"use strict";var n=t("d3"),a=t("./style_one");e.exports=function(t){t._fullLayout._pielayer.selectAll(".trace").each(function(t){var e=t[0],r=e.trace,o=n.select(this);o.style({opacity:r.opacity}),o.selectAll(".top path.surface").each(function(t){n.select(this).call(a,t,r)})})}},{"./style_one":269,d3:14}],269:[function(t,e,r){"use strict";var n=t("../../components/color");e.exports=function(t,e,r){var a=r.marker.line.color;Array.isArray(a)&&(a=a[e.i]||n.defaultLine);var o=r.marker.line.width||0;Array.isArray(o)&&(o=o[e.i]||0),t.style({"stroke-width":o,fill:e.color}).call(n.stroke,a)}},{"../../components/color":30}],270:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t){var e=t[0].trace,r=e.marker;if(n.mergeArray(e.text,t,"tx"),n.mergeArray(e.textposition,t,"tp"),e.textfont&&(n.mergeArray(e.textfont.size,t,"ts"),n.mergeArray(e.textfont.color,t,"tc"),n.mergeArray(e.textfont.family,t,"tf")),r&&r.line){var a=r.line;n.mergeArray(r.opacity,t,"mo"),n.mergeArray(r.symbol,t,"mx"),n.mergeArray(r.color,t,"mc"),n.mergeArray(a.color,t,"mlc"),n.mergeArray(a.width,t,"mlw")}}},{"../../lib":122}],271:[function(t,e,r){"use strict";var n=t("../../components/colorscale/color_attributes"),a=t("../../components/errorbars/attributes"),o=t("../../components/colorbar/attributes"),i=t("../../components/drawing"),l=(t("./constants"),t("../../lib/extend").extendFlat);e.exports={x:{valType:"data_array"},x0:{valType:"any",dflt:0},dx:{valType:"number",dflt:1},y:{valType:"data_array"},y0:{valType:"any",dflt:0},dy:{valType:"number",dflt:1},ids:{valType:"data_array"},text:{valType:"string",dflt:"",arrayOk:!0},mode:{valType:"flaglist",flags:["lines","markers","text"],extras:["none"]},hoveron:{valType:"flaglist",flags:["points","fills"]},line:{color:{valType:"color"},width:{valType:"number",min:0,dflt:2},shape:{valType:"enumerated",values:["linear","spline","hv","vh","hvh","vhv"],dflt:"linear"},smoothing:{valType:"number",min:0,max:1.3,dflt:1},dash:{valType:"string",values:["solid","dot","dash","longdash","dashdot","longdashdot"],dflt:"solid"},simplify:{valType:"boolean",dflt:!0}},connectgaps:{valType:"boolean",dflt:!1},fill:{valType:"enumerated",values:["none","tozeroy","tozerox","tonexty","tonextx","toself","tonext"],dflt:"none"},fillcolor:{valType:"color"},marker:l({},{symbol:{valType:"enumerated",values:i.symbolList,dflt:"circle",arrayOk:!0},opacity:{valType:"number",min:0,max:1,arrayOk:!0},size:{valType:"number",min:0,dflt:6,arrayOk:!0},maxdisplayed:{valType:"number",min:0,dflt:0},sizeref:{valType:"number",dflt:1},sizemin:{valType:"number",min:0,dflt:0},sizemode:{valType:"enumerated",values:["diameter","area"],dflt:"diameter"},showscale:{valType:"boolean",dflt:!1},colorbar:o,line:l({},{width:{valType:"number",min:0,arrayOk:!0}},n("marker.line"))},n("marker")),textposition:{valType:"enumerated",values:["top left","top center","top right","middle left","middle center","middle right","bottom left","bottom center","bottom right"],dflt:"middle center",arrayOk:!0},textfont:{family:{valType:"string",noBlank:!0,strict:!0,arrayOk:!0},size:{valType:"number",min:1,arrayOk:!0},color:{valType:"color",arrayOk:!0}},r:{valType:"data_array"},t:{valType:"data_array"},error_y:a,error_x:a}},{"../../components/colorbar/attributes":31,"../../components/colorscale/color_attributes":37,"../../components/drawing":53,"../../components/errorbars/attributes":55,"../../lib/extend":119,"./constants":276}],272:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../plots/cartesian/axes"),o=t("../../lib"),i=t("./subtypes"),l=t("./colorscale_calc");e.exports=function(t,e){var r,s,c,u=a.getFromId(t,e.xaxis||"x"),f=a.getFromId(t,e.yaxis||"y"),d=u.makeCalcdata(e,"x"),h=f.makeCalcdata(e,"y"),p=Math.min(d.length,h.length);u._minDtick=0,f._minDtick=0,d.length>p&&d.splice(p,d.length-p),h.length>p&&h.splice(p,h.length-p);var g={padded:!0},m={padded:!0};if(i.hasMarkers(e)){if(r=e.marker,s=r.size,Array.isArray(s)){var v={type:"linear"};a.setConvert(v),s=v.makeCalcdata(e.marker,"size"),s.length>p&&s.splice(p,s.length-p)}var y,x=1.6*(e.marker.sizeref||1);y="area"===e.marker.sizemode?function(t){return Math.max(Math.sqrt((t||0)/x),3)}:function(t){return Math.max((t||0)/x,3)},g.ppad=m.ppad=Array.isArray(s)?s.map(y):y(s)}l(e),!("tozerox"===e.fill||"tonextx"===e.fill&&t.firstscatter)||d[0]===d[p-1]&&h[0]===h[p-1]?e.error_y.visible||["tonexty","tozeroy"].indexOf(e.fill)===-1&&(i.hasMarkers(e)||i.hasText(e))||(g.padded=!1,g.ppad=0):g.tozero=!0,!("tozeroy"===e.fill||"tonexty"===e.fill&&t.firstscatter)||d[0]===d[p-1]&&h[0]===h[p-1]?["tonextx","tozerox"].indexOf(e.fill)!==-1&&(m.padded=!1):m.tozero=!0,a.expand(u,d,g),a.expand(f,h,m);var b=new Array(p);for(c=0;c=0;a--){var o=t[a];if("scatter"===o.type&&o.xaxis===r.xaxis&&o.yaxis===r.yaxis){o.opacity=void 0;break}}}}}},{}],274:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),a=t("../../lib"),o=t("../../plots/plots"),i=t("../../components/colorscale"),l=t("../../components/colorbar/draw");e.exports=function(t,e){var r=e[0].trace,s=r.marker,c="cb"+r.uid;if(t._fullLayout._infolayer.selectAll("."+c).remove(),void 0===s||!s.showscale)return void o.autoMargin(t,c);var u=s.color,f=s.cmin,d=s.cmax;n(f)||(f=a.aggNums(Math.min,null,u)),n(d)||(d=a.aggNums(Math.max,null,u));var h=e[0].t.cb=l(t,c),p=i.makeColorScaleFunc(i.extractScale(s.colorscale,f,d),{noNumericCheck:!0});h.fillcolor(p).filllevels({start:f,end:d,size:(d-f)/254}).options(s.colorbar)()}},{"../../components/colorbar/draw":33,"../../components/colorscale":44,"../../lib":122,"../../plots/plots":173,"fast-isnumeric":17}],275:[function(t,e,r){"use strict";var n=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/calc"),o=t("./subtypes");e.exports=function(t){o.hasLines(t)&&n(t,"line")&&a(t,t.line.color,"line","c"),o.hasMarkers(t)&&(n(t,"marker")&&a(t,t.marker.color,"marker","c"),n(t,"marker.line")&&a(t,t.marker.line.color,"marker.line","c"))}},{"../../components/colorscale/calc":36,"../../components/colorscale/has_colorscale":43,"./subtypes":291}],276:[function(t,e,r){"use strict";e.exports={PTS_LINESONLY:20}},{}],277:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("./attributes"),o=t("./constants"),i=t("./subtypes"),l=t("./xy_defaults"),s=t("./marker_defaults"),c=t("./line_defaults"),u=t("./line_shape_defaults"),f=t("./text_defaults"),d=t("./fillcolor_defaults"),h=t("../../components/errorbars/defaults");e.exports=function(t,e,r,p){function g(r,o){return n.coerce(t,e,a,r,o)}var m=l(t,e,g),v=my[x].x0&&ey[x].y0&&rV!=E>=V&&(D=S[z-1][0],P=S[z][0],O=D+(P-D)*(V-N)/(E-N),j=Math.min(j,O),q=Math.max(q,O));j=Math.max(j,0),q=Math.min(q,d._length);var Z=s.defaultLine;return s.opacity(f.fillcolor)?Z=f.fillcolor:s.opacity((f.line||{}).color)&&(Z=f.line.color),n.extendFlat(t,{distance:o.MAXDIST+10,x0:j,x1:q,y0:V,y1:V,color:Z}),delete t.index,f.text&&!Array.isArray(f.text)?t.text=String(f.text):t.text=f.name,[t]}}}},{"../../components/color":30,"../../components/errorbars":59,"../../lib":122,"../../plots/cartesian/constants":154,"../../plots/cartesian/graph_interact":156,"./get_trace_color":279}],281:[function(t,e,r){"use strict";var n={},a=t("./subtypes");n.hasLines=a.hasLines,n.hasMarkers=a.hasMarkers,n.hasText=a.hasText,n.isBubble=a.isBubble,n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.cleanData=t("./clean_data"),n.calc=t("./calc"),n.arraysToCalcdata=t("./arrays_to_calcdata"),n.plot=t("./plot"),n.colorbar=t("./colorbar"),n.style=t("./style"),n.hoverPoints=t("./hover"),n.selectPoints=t("./select"),n.animatable=!0,n.moduleType="trace",n.name="scatter",n.basePlotModule=t("../../plots/cartesian"),n.categories=["cartesian","symbols","markerColorscale","errorBarsOK","showLegend"],n.meta={},e.exports=n},{"../../plots/cartesian":157,"./arrays_to_calcdata":270,"./attributes":271,"./calc":272,"./clean_data":273,"./colorbar":274,"./defaults":277,"./hover":280,"./plot":288,"./select":289,"./style":290,"./subtypes":291}],282:[function(t,e,r){"use strict";var n=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/defaults");e.exports=function(t,e,r,o,i){var l=(t.marker||{}).color;if(i("line.color",r),n(t,"line"))a(t,e,o,i,{prefix:"line.",cLetter:"c"});else{var s=!Array.isArray(l)&&l||r;i("line.color",s)}i("line.width"),i("line.dash")}},{"../../components/colorscale/defaults":39,"../../components/colorscale/has_colorscale":43}],283:[function(t,e,r){"use strict";var n=t("../../constants/numerical").BADNUM;e.exports=function(t,e){function r(e){var r=w.c2p(t[e].x),a=k.c2p(t[e].y);return r!==n&&a!==n&&[r,a]}function a(t){var e=t[0]/w._length,r=t[1]/k._length;return(1+10*Math.max(0,-e,e-1,-r,r-1))*T}function o(t,e){var r=t[0]-e[0],n=t[1]-e[1];return Math.sqrt(r*r+n*n)}var i,l,s,c,u,f,d,h,p,g,m,v,y,x,b,_,w=e.xaxis,k=e.yaxis,M=e.simplify,A=e.connectGaps,T=e.baseTolerance,L=e.linear,z=[],C=.2,S=new Array(t.length),O=0;for(M||(T=C=-1),i=0;ia(f))break;s=f,y=g[0]*p[0]+g[1]*p[1],y>m?(m=y,c=f,h=!1):y=t.length||!f)break;S[O++]=f,l=f}}else S[O++]=c}z.push(S.slice(0,O))}return z}},{"../../constants/numerical":110}],284:[function(t,e,r){"use strict";e.exports=function(t,e,r){var n=r("line.shape");"spline"===n&&r("line.smoothing")}},{}],285:[function(t,e,r){"use strict";e.exports=function(t,e,r){for(var n,a,o=null,i=0;i0?Math.max(e,a):0}}},{"fast-isnumeric":17}],287:[function(t,e,r){"use strict";var n=t("../../components/color"),a=t("../../components/colorscale/has_colorscale"),o=t("../../components/colorscale/defaults"),i=t("./subtypes");e.exports=function(t,e,r,l,s){var c,u=i.isBubble(t),f=(t.line||{}).color;f&&(r=f),s("marker.symbol"),s("marker.opacity",u?.7:1),s("marker.size"),s("marker.color",r),a(t,"marker")&&o(t,e,l,s,{prefix:"marker.",cLetter:"c"}),c=f&&!Array.isArray(f)&&e.marker.color!==f?f:u?n.background:n.defaultLine,s("marker.line.color",c),a(t,"marker.line")&&o(t,e,l,s,{prefix:"marker.line.",cLetter:"c"}),s("marker.line.width",u?1:0),u&&(s("marker.sizeref"),s("marker.sizemin"),s("marker.sizemode"))}},{"../../components/color":30,"../../components/colorscale/defaults":39,"../../components/colorscale/has_colorscale":43,"./subtypes":291}],288:[function(t,e,r){"use strict";function n(t,e){var r;e.selectAll("g.trace").each(function(t){var e=i.select(this);if(r=t[0].trace,r._nexttrace){if(r._nextFill=e.select(".js-fill.js-tonext"),!r._nextFill.size()){var n=":first-child";e.select(".js-fill.js-tozero").size()&&(n+=" + *"),r._nextFill=e.insert("path",n).attr("class","js-fill js-tonext")}}else e.selectAll(".js-fill.js-tonext").remove(),r._nextFill=null;r.fill&&("tozero"===r.fill.substr(0,6)||"toself"===r.fill||"to"===r.fill.substr(0,2)&&!r._prevtrace)?(r._ownFill=e.select(".js-fill.js-tozero"),r._ownFill.size()||(r._ownFill=e.insert("path",":first-child").attr("class","js-fill js-tozero"))):(e.selectAll(".js-fill.js-tozero").remove(),r._ownFill=null)})}function a(t,e,r,n,a,h,g){function m(t){return M?t.transition():t}function v(t){return t.filter(function(t){return t.vis})}function y(t){return t.id}function x(t){if(t.ids)return y}function b(){return!1}function _(t){var e,r,n=t[0].trace,a=i.select(this),o=u.hasMarkers(n),c=u.hasText(n),f=x(n),d=b,h=b;o&&(d=n.marker.maxdisplayed?v:l.identity),c&&(h=n.marker.maxdisplayed?v:l.identity),r=a.selectAll("path.point"),e=r.data(d,f);var p=e.enter().append("path").classed("point",!0);p.call(s.pointStyle,n).call(s.translatePoints,A,T,n),M&&p.style("opacity",0).transition().style("opacity",1),e.each(function(t){var e=m(i.select(this));s.translatePoint(t,e,A,T),s.singlePointStyle(t,e,n)}),M?e.exit().transition().style("opacity",0).remove():e.exit().remove(),r=a.selectAll("g"),e=r.data(h,f),e.enter().append("g").append("text"),e.each(function(t){var e=m(i.select(this).select("text"));s.translatePoint(t,e,A,T)}),e.selectAll("text").call(s.textPointStyle,n).each(function(t){var e=t.xp||A.c2p(t.x),r=t.yp||T.c2p(t.y);i.select(this).selectAll("tspan").each(function(){m(i.select(this)).attr({x:e,y:r})})}),e.exit().remove()}var w,k;o(t,e,r,n,a);var M=!!g&&g.duration>0,A=r.xaxis,T=r.yaxis,L=n[0].trace,z=L.line,C=i.select(h);if(C.call(c.plot,r,g),L.visible===!0){m(C).style("opacity",L.opacity);var S,O,D=L.fill.charAt(L.fill.length-1);"x"!==D&&"y"!==D&&(D=""),n[0].node3=C,f(n);var P="",N=[],E=L._prevtrace;E&&(P=E._prevRevpath||"",O=E._nextFill,N=E._polygons);var I,R,F,j,q,B,H,V,Z,X="",U="",Y=[],G=[],W=l.noop;if(S=L._ownFill,u.hasLines(L)||"none"!==L.fill){for(O&&O.datum(n),["hv","vh","hvh","vhv"].indexOf(z.shape)!==-1?(F=s.steps(z.shape),j=s.steps(z.shape.split("").reverse().join(""))):F=j="spline"===z.shape?function(t){var e=t[t.length-1];return t[0][0]===e[0]&&t[0][1]===e[1]?s.smoothclosed(t.slice(1),z.smoothing):s.smoothopen(t,z.smoothing)}:function(t){return"M"+t.join("L")},q=function(t){return j(t.reverse())},Y=d(n,{xaxis:A,yaxis:T,connectGaps:L.connectgaps,baseTolerance:Math.max(z.width||1,3)/4,linear:"linear"===z.shape,simplify:z.simplify}),Z=L._polygons=new Array(Y.length),k=0;k1}),W=function(t){return function(e){if(I=F(e),R=q(e),X?D?(X+="L"+I.substr(1),U=R+("L"+U.substr(1))):(X+="Z"+I,U=R+"Z"+U):(X=I,U=R),u.hasLines(L)&&e.length>1){var r=i.select(this);if(r.datum(n),t)m(r.style("opacity",0).attr("d",I).call(s.lineGroupStyle)).style("opacity",1);else{var a=m(r);a.attr("d",I),s.singleLineStyle(n,a)}}}}}var Q=C.selectAll(".js-line").data(G);m(Q.exit()).style("opacity",0).remove(),Q.each(W(!1)),Q.enter().append("path").classed("js-line",!0).style("vector-effect","non-scaling-stroke").call(s.lineGroupStyle).each(W(!0)),Y.length&&(S?B&&V&&(D?("y"===D?B[1]=V[1]=T.c2p(0,!0):"x"===D&&(B[0]=V[0]=A.c2p(0,!0)),m(S).attr("d","M"+V+"L"+B+"L"+X.substr(1))):m(S).attr("d",X+"Z")):"tonext"===L.fill.substr(0,6)&&X&&P&&("tonext"===L.fill?m(O).attr("d",X+"Z"+P+"Z"):m(O).attr("d",X+"L"+P.substr(1)+"Z"),L._polygons=L._polygons.concat(N)),L._prevRevpath=U,L._prevPolygons=Z);var $=C.selectAll(".points");w=$.data([n]),$.each(_),w.enter().append("g").classed("points",!0).each(_),w.exit().remove()}}function o(t,e,r,n,a){var o=r.xaxis,l=r.yaxis,s=i.extent(o.range.map(o.r2l).map(o.l2c)),c=i.extent(l.range.map(l.r2l).map(l.l2c)),f=n[0].trace;if(u.hasMarkers(f)){var d=f.marker.maxdisplayed;if(0!==d){var h=n.filter(function(t){return t.x>=s[0]&&t.x<=s[1]&&t.y>=c[0]&&t.y<=c[1]}),p=Math.ceil(h.length/d),g=0;a.forEach(function(t,r){var n=t[0].trace;u.hasMarkers(n)&&n.marker.maxdisplayed>0&&r0;for(u=p.selectAll("g.trace"),f=u.data(r,function(t){return t[0].trace.uid}),f.enter().append("g").attr("class",function(t){return"trace scatter trace"+t[0].trace.uid}).style("stroke-miterlimit",2),h(t,e,r),n(t,p),s=0,c=[];sn?1:-1}),m){l&&(d=l());var v=i.transition().duration(o.duration).ease(o.easing).each("end",function(){d&&d()}).each("interrupt",function(){d&&d()});v.each(function(){p.selectAll("g.trace").each(function(n,i){a(t,i,e,n,r,this,o)})})}else p.selectAll("g.trace").each(function(n,i){a(t,i,e,n,r,this,o)});g&&f.exit().remove(),p.selectAll("path:not([d])").remove()}},{"../../components/drawing":53,"../../components/errorbars":59,"../../lib":122,"../../lib/polygon":129,"./arrays_to_calcdata":270,"./line_points":283,"./link_traces":285,"./subtypes":291,d3:14}],289:[function(t,e,r){"use strict";var n=t("./subtypes"),a=.2;e.exports=function(t,e){var r,o,i,l,s=t.cd,c=t.xaxis,u=t.yaxis,f=[],d=s[0].trace,h=d.index,p=d.marker,g=!n.hasMarkers(d)&&!n.hasText(d);if(d.visible===!0&&!g){var m=Array.isArray(p.opacity)?1:p.opacity;if(e===!1)for(r=0;rM&&L.splice(M,L.length-M)}return l(e),"undefined"!=typeof L&&o.mergeArray(L,A,"ms"),A}},{"../../lib":122,"../../plots/cartesian/axes":149,"../scatter/colorscale_calc":275,"../scatter/subtypes":291,"fast-isnumeric":17}],296:[function(t,e,r){"use strict";var n=t("../../lib"),a=t("../scatter/constants"),o=t("../scatter/subtypes"),i=t("../scatter/marker_defaults"),l=t("../scatter/line_defaults"),s=t("../scatter/line_shape_defaults"),c=t("../scatter/text_defaults"),u=t("../scatter/fillcolor_defaults"),f=t("./attributes");e.exports=function(t,e,r,d){function h(r,a){return n.coerce(t,e,f,r,a)}var p,g=h("a"),m=h("b"),v=h("c");if(g?(p=g.length,m?(p=Math.min(p,m.length),v&&(p=Math.min(p,v.length))):p=v?Math.min(p,v.length):0):m&&v&&(p=Math.min(m.length,v.length)),!p)return void(e.visible=!1);g&&p"),l}}},{"../../plots/cartesian/axes":149,"../scatter/hover":280}],298:[function(t,e,r){"use strict";var n={};n.attributes=t("./attributes"),n.supplyDefaults=t("./defaults"),n.colorbar=t("../scatter/colorbar"),n.calc=t("./calc"),n.plot=t("./plot"),n.style=t("./style"),n.hoverPoints=t("./hover"),n.selectPoints=t("./select"),n.moduleType="trace",n.name="scatterternary",n.basePlotModule=t("../../plots/ternary"),n.categories=["ternary","symbols","markerColorscale","showLegend"],n.meta={},e.exports=n},{"../../plots/ternary":181,"../scatter/colorbar":274,"./attributes":294,"./calc":295,"./defaults":296,"./hover":297,"./plot":299,"./select":300,"./style":301}],299:[function(t,e,r){"use strict";var n=t("../scatter/plot");e.exports=function(t,e){var r=t.plotContainer;r.select(".scatterlayer").selectAll("*").remove();for(var a={xaxis:t.xaxis,yaxis:t.yaxis,plot:r},o=new Array(e.length),i=t.graphDiv.calcdata,l=0;l b ? 1 : a >= b ? 0 : NaN; + } + d3.descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + }; + d3.min = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && a > b) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; + } + return a; + }; + d3.max = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && b > a) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; + } + return a; + }; + d3.extent = function(array, f) { + var i = -1, n = array.length, a, b, c; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = c = b; + break; + } + while (++i < n) if ((b = array[i]) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = c = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } + return [ a, c ]; + }; + function d3_number(x) { + return x === null ? NaN : +x; + } + function d3_numeric(x) { + return !isNaN(x); + } + d3.sum = function(array, f) { + var s = 0, n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = +array[i])) s += a; + } else { + while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; + } + return s; + }; + d3.mean = function(array, f) { + var s = 0, n = array.length, a, i = -1, j = n; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; + } + if (j) return s / j; + }; + d3.quantile = function(values, p) { + var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; + return e ? v + e * (values[h] - v) : v; + }; + d3.median = function(array, f) { + var numbers = [], n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); + } + if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); + }; + d3.variance = function(array, f) { + var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; + if (arguments.length === 1) { + while (++i < n) { + if (d3_numeric(a = d3_number(array[i]))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } else { + while (++i < n) { + if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } + if (j > 1) return s / (j - 1); + }; + d3.deviation = function() { + var v = d3.variance.apply(this, arguments); + return v ? Math.sqrt(v) : v; + }; + function d3_bisector(compare) { + return { + left: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; + } + return lo; + } + }; + } + var d3_bisect = d3_bisector(d3_ascending); + d3.bisectLeft = d3_bisect.left; + d3.bisect = d3.bisectRight = d3_bisect.right; + d3.bisector = function(f) { + return d3_bisector(f.length === 1 ? function(d, x) { + return d3_ascending(f(d), x); + } : f); + }; + d3.shuffle = function(array, i0, i1) { + if ((m = arguments.length) < 3) { + i1 = array.length; + if (m < 2) i0 = 0; + } + var m = i1 - i0, t, i; + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; + } + return array; + }; + d3.permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; + }; + d3.pairs = function(array) { + var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; + return pairs; + }; + d3.transpose = function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { + row[j] = matrix[j][i]; + } + } + return transpose; + }; + function d3_transposeLength(d) { + return d.length; + } + d3.zip = function() { + return d3.transpose(arguments); + }; + d3.keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; + }; + d3.values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; + }; + d3.entries = function(map) { + var entries = []; + for (var key in map) entries.push({ + key: key, + value: map[key] + }); + return entries; + }; + d3.merge = function(arrays) { + var n = arrays.length, m, i = -1, j = 0, merged, array; + while (++i < n) j += arrays[i].length; + merged = new Array(j); + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + return merged; + }; + var abs = Math.abs; + d3.range = function(start, stop, step) { + if (arguments.length < 3) { + step = 1; + if (arguments.length < 2) { + stop = start; + start = 0; + } + } + if ((stop - start) / step === Infinity) throw new Error("infinite range"); + var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; + start *= k, stop *= k, step *= k; + if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); + return range; + }; + function d3_range_integerScale(x) { + var k = 1; + while (x * k % 1) k *= 10; + return k; + } + function d3_class(ctor, properties) { + for (var key in properties) { + Object.defineProperty(ctor.prototype, key, { + value: properties[key], + enumerable: false + }); + } + } + d3.map = function(object, f) { + var map = new d3_Map(); + if (object instanceof d3_Map) { + object.forEach(function(key, value) { + map.set(key, value); + }); + } else if (Array.isArray(object)) { + var i = -1, n = object.length, o; + if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); + } else { + for (var key in object) map.set(key, object[key]); + } + return map; + }; + function d3_Map() { + this._ = Object.create(null); + } + var d3_map_proto = "__proto__", d3_map_zero = "\x00"; + d3_class(d3_Map, { + has: d3_map_has, + get: function(key) { + return this._[d3_map_escape(key)]; + }, + set: function(key, value) { + return this._[d3_map_escape(key)] = value; + }, + remove: d3_map_remove, + keys: d3_map_keys, + values: function() { + var values = []; + for (var key in this._) values.push(this._[key]); + return values; + }, + entries: function() { + var entries = []; + for (var key in this._) entries.push({ + key: d3_map_unescape(key), + value: this._[key] + }); + return entries; + }, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); + } + }); + function d3_map_escape(key) { + return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; + } + function d3_map_unescape(key) { + return (key += "")[0] === d3_map_zero ? key.slice(1) : key; + } + function d3_map_has(key) { + return d3_map_escape(key) in this._; + } + function d3_map_remove(key) { + return (key = d3_map_escape(key)) in this._ && delete this._[key]; + } + function d3_map_keys() { + var keys = []; + for (var key in this._) keys.push(d3_map_unescape(key)); + return keys; + } + function d3_map_size() { + var size = 0; + for (var key in this._) ++size; + return size; + } + function d3_map_empty() { + for (var key in this._) return false; + return true; + } + d3.nest = function() { + var nest = {}, keys = [], sortKeys = [], sortValues, rollup; + function map(mapType, array, depth) { + if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; + var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(object = array[i]))) { + values.push(object); + } else { + valuesByKey.set(keyValue, [ object ]); + } + } + if (mapType) { + object = mapType(); + setter = function(keyValue, values) { + object.set(keyValue, map(mapType, values, depth)); + }; + } else { + object = {}; + setter = function(keyValue, values) { + object[keyValue] = map(mapType, values, depth); + }; + } + valuesByKey.forEach(setter); + return object; + } + function entries(map, depth) { + if (depth >= keys.length) return map; + var array = [], sortKey = sortKeys[depth++]; + map.forEach(function(key, keyMap) { + array.push({ + key: key, + values: entries(keyMap, depth) + }); + }); + return sortKey ? array.sort(function(a, b) { + return sortKey(a.key, b.key); + }) : array; + } + nest.map = function(array, mapType) { + return map(mapType, array, 0); + }; + nest.entries = function(array) { + return entries(map(d3.map, array, 0), 0); + }; + nest.key = function(d) { + keys.push(d); + return nest; + }; + nest.sortKeys = function(order) { + sortKeys[keys.length - 1] = order; + return nest; + }; + nest.sortValues = function(order) { + sortValues = order; + return nest; + }; + nest.rollup = function(f) { + rollup = f; + return nest; + }; + return nest; + }; + d3.set = function(array) { + var set = new d3_Set(); + if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); + return set; + }; + function d3_Set() { + this._ = Object.create(null); + } + d3_class(d3_Set, { + has: d3_map_has, + add: function(key) { + this._[d3_map_escape(key += "")] = true; + return key; + }, + remove: d3_map_remove, + values: d3_map_keys, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key)); + } + }); + d3.behavior = {}; + function d3_identity(d) { + return d; + } + d3.rebind = function(target, source) { + var i = 1, n = arguments.length, method; + while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); + return target; + }; + function d3_rebind(target, source, method) { + return function() { + var value = method.apply(source, arguments); + return value === source ? target : value; + }; + } + function d3_vendorSymbol(object, name) { + if (name in object) return name; + name = name.charAt(0).toUpperCase() + name.slice(1); + for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { + var prefixName = d3_vendorPrefixes[i] + name; + if (prefixName in object) return prefixName; + } + } + var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; + function d3_noop() {} + d3.dispatch = function() { + var dispatch = new d3_dispatch(), i = -1, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + return dispatch; + }; + function d3_dispatch() {} + d3_dispatch.prototype.on = function(type, listener) { + var i = type.indexOf("."), name = ""; + if (i >= 0) { + name = type.slice(i + 1); + type = type.slice(0, i); + } + if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); + if (arguments.length === 2) { + if (listener == null) for (type in this) { + if (this.hasOwnProperty(type)) this[type].on(name, null); + } + return this; + } + }; + function d3_dispatch_event(dispatch) { + var listeners = [], listenerByName = new d3_Map(); + function event() { + var z = listeners, i = -1, n = z.length, l; + while (++i < n) if (l = z[i].on) l.apply(this, arguments); + return dispatch; + } + event.on = function(name, listener) { + var l = listenerByName.get(name), i; + if (arguments.length < 2) return l && l.on; + if (l) { + l.on = null; + listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); + listenerByName.remove(name); + } + if (listener) listeners.push(listenerByName.set(name, { + on: listener + })); + return dispatch; + }; + return event; + } + d3.event = null; + function d3_eventPreventDefault() { + d3.event.preventDefault(); + } + function d3_eventSource() { + var e = d3.event, s; + while (s = e.sourceEvent) e = s; + return e; + } + function d3_eventDispatch(target) { + var dispatch = new d3_dispatch(), i = 0, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + dispatch.of = function(thiz, argumentz) { + return function(e1) { + try { + var e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; + } + }; + }; + return dispatch; + } + d3.requote = function(s) { + return s.replace(d3_requote_re, "\\$&"); + }; + var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + var d3_subclass = {}.__proto__ ? function(object, prototype) { + object.__proto__ = prototype; + } : function(object, prototype) { + for (var property in prototype) object[property] = prototype[property]; + }; + function d3_selection(groups) { + d3_subclass(groups, d3_selectionPrototype); + return groups; + } + var d3_select = function(s, n) { + return n.querySelector(s); + }, d3_selectAll = function(s, n) { + return n.querySelectorAll(s); + }, d3_selectMatches = function(n, s) { + var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; + d3_selectMatches = function(n, s) { + return d3_selectMatcher.call(n, s); + }; + return d3_selectMatches(n, s); + }; + if (typeof Sizzle === "function") { + d3_select = function(s, n) { + return Sizzle(s, n)[0] || null; + }; + d3_selectAll = Sizzle; + d3_selectMatches = Sizzle.matchesSelector; + } + d3.selection = function() { + return d3.select(d3_document.documentElement); + }; + var d3_selectionPrototype = d3.selection.prototype = []; + d3_selectionPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, group, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(subnode = selector.call(node, node.__data__, i, j)); + if (subnode && "__data__" in node) subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selector(selector) { + return typeof selector === "function" ? selector : function() { + return d3_select(selector, this); + }; + } + d3_selectionPrototype.selectAll = function(selector) { + var subgroups = [], subgroup, node; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); + subgroup.parentNode = node; + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selectorAll(selector) { + return typeof selector === "function" ? selector : function() { + return d3_selectAll(selector, this); + }; + } + var d3_nsXhtml = "http://www.w3.org/1999/xhtml"; + var d3_nsPrefix = { + svg: "http://www.w3.org/2000/svg", + xhtml: d3_nsXhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + d3.ns = { + prefix: d3_nsPrefix, + qualify: function(name) { + var i = name.indexOf(":"), prefix = name; + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return d3_nsPrefix.hasOwnProperty(prefix) ? { + space: d3_nsPrefix[prefix], + local: name + } : name; + } + }; + d3_selectionPrototype.attr = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(); + name = d3.ns.qualify(name); + return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); + } + for (value in name) this.each(d3_selection_attr(value, name[value])); + return this; + } + return this.each(d3_selection_attr(name, value)); + }; + function d3_selection_attr(name, value) { + name = d3.ns.qualify(name); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrConstant() { + this.setAttribute(name, value); + } + function attrConstantNS() { + this.setAttributeNS(name.space, name.local, value); + } + function attrFunction() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); + } + function attrFunctionNS() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); + } + return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; + } + function d3_collapse(s) { + return s.trim().replace(/\s+/g, " "); + } + d3_selectionPrototype.classed = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; + if (value = node.classList) { + while (++i < n) if (!value.contains(name[i])) return false; + } else { + value = node.getAttribute("class"); + while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; + } + return true; + } + for (value in name) this.each(d3_selection_classed(value, name[value])); + return this; + } + return this.each(d3_selection_classed(name, value)); + }; + function d3_selection_classedRe(name) { + return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); + } + function d3_selection_classes(name) { + return (name + "").trim().split(/^|\s+/); + } + function d3_selection_classed(name, value) { + name = d3_selection_classes(name).map(d3_selection_classedName); + var n = name.length; + function classedConstant() { + var i = -1; + while (++i < n) name[i](this, value); + } + function classedFunction() { + var i = -1, x = value.apply(this, arguments); + while (++i < n) name[i](this, x); + } + return typeof value === "function" ? classedFunction : classedConstant; + } + function d3_selection_classedName(name) { + var re = d3_selection_classedRe(name); + return function(node, value) { + if (c = node.classList) return value ? c.add(name) : c.remove(name); + var c = node.getAttribute("class") || ""; + if (value) { + re.lastIndex = 0; + if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); + } else { + node.setAttribute("class", d3_collapse(c.replace(re, " "))); + } + }; + } + d3_selectionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); + return this; + } + if (n < 2) { + var node = this.node(); + return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); + } + priority = ""; + } + return this.each(d3_selection_style(name, value, priority)); + }; + function d3_selection_style(name, value, priority) { + function styleNull() { + this.style.removeProperty(name); + } + function styleConstant() { + this.style.setProperty(name, value, priority); + } + function styleFunction() { + var x = value.apply(this, arguments); + if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); + } + return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; + } + d3_selectionPrototype.property = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") return this.node()[name]; + for (value in name) this.each(d3_selection_property(value, name[value])); + return this; + } + return this.each(d3_selection_property(name, value)); + }; + function d3_selection_property(name, value) { + function propertyNull() { + delete this[name]; + } + function propertyConstant() { + this[name] = value; + } + function propertyFunction() { + var x = value.apply(this, arguments); + if (x == null) delete this[name]; else this[name] = x; + } + return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; + } + d3_selectionPrototype.text = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + } : value == null ? function() { + this.textContent = ""; + } : function() { + this.textContent = value; + }) : this.node().textContent; + }; + d3_selectionPrototype.html = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + } : value == null ? function() { + this.innerHTML = ""; + } : function() { + this.innerHTML = value; + }) : this.node().innerHTML; + }; + d3_selectionPrototype.append = function(name) { + name = d3_selection_creator(name); + return this.select(function() { + return this.appendChild(name.apply(this, arguments)); + }); + }; + function d3_selection_creator(name) { + function create() { + var document = this.ownerDocument, namespace = this.namespaceURI; + return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name); + } + function createNS() { + return this.ownerDocument.createElementNS(name.space, name.local); + } + return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; + } + d3_selectionPrototype.insert = function(name, before) { + name = d3_selection_creator(name); + before = d3_selection_selector(before); + return this.select(function() { + return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); + }); + }; + d3_selectionPrototype.remove = function() { + return this.each(d3_selectionRemove); + }; + function d3_selectionRemove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); + } + d3_selectionPrototype.data = function(value, key) { + var i = -1, n = this.length, group, node; + if (!arguments.length) { + value = new Array(n = (group = this[0]).length); + while (++i < n) { + if (node = group[i]) { + value[i] = node.__data__; + } + } + return value; + } + function bind(group, groupData) { + var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; + if (key) { + var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; + for (i = -1; ++i < n; ) { + if (node = group[i]) { + if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { + exitNodes[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + keyValues[i] = keyValue; + } + } + for (i = -1; ++i < m; ) { + if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { + enterNodes[i] = d3_selection_dataNode(nodeData); + } else if (node !== true) { + updateNodes[i] = node; + node.__data__ = nodeData; + } + nodeByKeyValue.set(keyValue, true); + } + for (i = -1; ++i < n; ) { + if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { + exitNodes[i] = group[i]; + } + } + } else { + for (i = -1; ++i < n0; ) { + node = group[i]; + nodeData = groupData[i]; + if (node) { + node.__data__ = nodeData; + updateNodes[i] = node; + } else { + enterNodes[i] = d3_selection_dataNode(nodeData); + } + } + for (;i < m; ++i) { + enterNodes[i] = d3_selection_dataNode(groupData[i]); + } + for (;i < n; ++i) { + exitNodes[i] = group[i]; + } + } + enterNodes.update = updateNodes; + enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; + enter.push(enterNodes); + update.push(updateNodes); + exit.push(exitNodes); + } + var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); + if (typeof value === "function") { + while (++i < n) { + bind(group = this[i], value.call(group, group.parentNode.__data__, i)); + } + } else { + while (++i < n) { + bind(group = this[i], value); + } + } + update.enter = function() { + return enter; + }; + update.exit = function() { + return exit; + }; + return update; + }; + function d3_selection_dataNode(data) { + return { + __data__: data + }; + } + d3_selectionPrototype.datum = function(value) { + return arguments.length ? this.property("__data__", value) : this.property("__data__"); + }; + d3_selectionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_filter(selector) { + return function() { + return d3_selectMatches(this, selector); + }; + } + d3_selectionPrototype.order = function() { + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + return this; + }; + d3_selectionPrototype.sort = function(comparator) { + comparator = d3_selection_sortComparator.apply(this, arguments); + for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); + return this.order(); + }; + function d3_selection_sortComparator(comparator) { + if (!arguments.length) comparator = d3_ascending; + return function(a, b) { + return a && b ? comparator(a.__data__, b.__data__) : !a - !b; + }; + } + d3_selectionPrototype.each = function(callback) { + return d3_selection_each(this, function(node, i, j) { + callback.call(node, node.__data__, i, j); + }); + }; + function d3_selection_each(groups, callback) { + for (var j = 0, m = groups.length; j < m; j++) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { + if (node = group[i]) callback(node, i, j); + } + } + return groups; + } + d3_selectionPrototype.call = function(callback) { + var args = d3_array(arguments); + callback.apply(args[0] = this, args); + return this; + }; + d3_selectionPrototype.empty = function() { + return !this.node(); + }; + d3_selectionPrototype.node = function() { + for (var j = 0, m = this.length; j < m; j++) { + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + var node = group[i]; + if (node) return node; + } + } + return null; + }; + d3_selectionPrototype.size = function() { + var n = 0; + d3_selection_each(this, function() { + ++n; + }); + return n; + }; + function d3_selection_enter(selection) { + d3_subclass(selection, d3_selection_enterPrototype); + return selection; + } + var d3_selection_enterPrototype = []; + d3.selection.enter = d3_selection_enter; + d3.selection.enter.prototype = d3_selection_enterPrototype; + d3_selection_enterPrototype.append = d3_selectionPrototype.append; + d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; + d3_selection_enterPrototype.node = d3_selectionPrototype.node; + d3_selection_enterPrototype.call = d3_selectionPrototype.call; + d3_selection_enterPrototype.size = d3_selectionPrototype.size; + d3_selection_enterPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, upgroup, group, node; + for (var j = -1, m = this.length; ++j < m; ) { + upgroup = (group = this[j]).update; + subgroups.push(subgroup = []); + subgroup.parentNode = group.parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); + subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + d3_selection_enterPrototype.insert = function(name, before) { + if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); + return d3_selectionPrototype.insert.call(this, name, before); + }; + function d3_selection_enterInsertBefore(enter) { + var i0, j0; + return function(d, i, j) { + var group = enter[j].update, n = group.length, node; + if (j != j0) j0 = j, i0 = 0; + if (i >= i0) i0 = i + 1; + while (!(node = group[i0]) && ++i0 < n) ; + return node; + }; + } + d3.select = function(node) { + var group; + if (typeof node === "string") { + group = [ d3_select(node, d3_document) ]; + group.parentNode = d3_document.documentElement; + } else { + group = [ node ]; + group.parentNode = d3_documentElement(node); + } + return d3_selection([ group ]); + }; + d3.selectAll = function(nodes) { + var group; + if (typeof nodes === "string") { + group = d3_array(d3_selectAll(nodes, d3_document)); + group.parentNode = d3_document.documentElement; + } else { + group = d3_array(nodes); + group.parentNode = null; + } + return d3_selection([ group ]); + }; + d3_selectionPrototype.on = function(type, listener, capture) { + var n = arguments.length; + if (n < 3) { + if (typeof type !== "string") { + if (n < 2) listener = false; + for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); + return this; + } + if (n < 2) return (n = this.node()["__on" + type]) && n._; + capture = false; + } + return this.each(d3_selection_on(type, listener, capture)); + }; + function d3_selection_on(type, listener, capture) { + var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; + if (i > 0) type = type.slice(0, i); + var filter = d3_selection_onFilters.get(type); + if (filter) type = filter, wrap = d3_selection_onFilter; + function onRemove() { + var l = this[name]; + if (l) { + this.removeEventListener(type, l, l.$); + delete this[name]; + } + } + function onAdd() { + var l = wrap(listener, d3_array(arguments)); + onRemove.call(this); + this.addEventListener(type, this[name] = l, l.$ = capture); + l._ = listener; + } + function removeAll() { + var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; + for (var name in this) { + if (match = name.match(re)) { + var l = this[name]; + this.removeEventListener(match[1], l, l.$); + delete this[name]; + } + } + } + return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; + } + var d3_selection_onFilters = d3.map({ + mouseenter: "mouseover", + mouseleave: "mouseout" + }); + if (d3_document) { + d3_selection_onFilters.forEach(function(k) { + if ("on" + k in d3_document) d3_selection_onFilters.remove(k); + }); + } + function d3_selection_onListener(listener, argumentz) { + return function(e) { + var o = d3.event; + d3.event = e; + argumentz[0] = this.__data__; + try { + listener.apply(this, argumentz); + } finally { + d3.event = o; + } + }; + } + function d3_selection_onFilter(listener, argumentz) { + var l = d3_selection_onListener(listener, argumentz); + return function(e) { + var target = this, related = e.relatedTarget; + if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { + l.call(target, e); + } + }; + } + var d3_event_dragSelect, d3_event_dragId = 0; + function d3_event_dragSuppress(node) { + var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); + if (d3_event_dragSelect == null) { + d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); + } + if (d3_event_dragSelect) { + var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; + style[d3_event_dragSelect] = "none"; + } + return function(suppressClick) { + w.on(name, null); + if (d3_event_dragSelect) style[d3_event_dragSelect] = select; + if (suppressClick) { + var off = function() { + w.on(click, null); + }; + w.on(click, function() { + d3_eventPreventDefault(); + off(); + }, true); + setTimeout(off, 0); + } + }; + } + d3.mouse = function(container) { + return d3_mousePoint(container, d3_eventSource()); + }; + var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; + function d3_mousePoint(container, e) { + if (e.changedTouches) e = e.changedTouches[0]; + var svg = container.ownerSVGElement || container; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + if (d3_mouse_bug44083 < 0) { + var window = d3_window(container); + if (window.scrollX || window.scrollY) { + svg = d3.select("body").append("svg").style({ + position: "absolute", + top: 0, + left: 0, + margin: 0, + padding: 0, + border: "none" + }, "important"); + var ctm = svg[0][0].getScreenCTM(); + d3_mouse_bug44083 = !(ctm.f || ctm.e); + svg.remove(); + } + } + if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, + point.y = e.clientY; + point = point.matrixTransform(container.getScreenCTM().inverse()); + return [ point.x, point.y ]; + } + var rect = container.getBoundingClientRect(); + return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; + } + d3.touch = function(container, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; + if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return d3_mousePoint(container, touch); + } + } + }; + d3.behavior.drag = function() { + var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); + function drag() { + this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); + } + function dragstart(id, position, subject, move, end) { + return function() { + var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); + if (origin) { + dragOffset = origin.apply(that, arguments); + dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; + } else { + dragOffset = [ 0, 0 ]; + } + dispatch({ + type: "dragstart" + }); + function moved() { + var position1 = position(parent, dragId), dx, dy; + if (!position1) return; + dx = position1[0] - position0[0]; + dy = position1[1] - position0[1]; + dragged |= dx | dy; + position0 = position1; + dispatch({ + type: "drag", + x: position1[0] + dragOffset[0], + y: position1[1] + dragOffset[1], + dx: dx, + dy: dy + }); + } + function ended() { + if (!position(parent, dragId)) return; + dragSubject.on(move + dragName, null).on(end + dragName, null); + dragRestore(dragged); + dispatch({ + type: "dragend" + }); + } + }; + } + drag.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return drag; + }; + return d3.rebind(drag, event, "on"); + }; + function d3_behavior_dragTouchId() { + return d3.event.changedTouches[0].identifier; + } + d3.touches = function(container, touches) { + if (arguments.length < 2) touches = d3_eventSource().touches; + return touches ? d3_array(touches).map(function(touch) { + var point = d3_mousePoint(container, touch); + point.identifier = touch.identifier; + return point; + }) : []; + }; + var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; + function d3_sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + function d3_cross2d(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); + } + function d3_acos(x) { + return x > 1 ? 0 : x < -1 ? π : Math.acos(x); + } + function d3_asin(x) { + return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); + } + function d3_sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; + } + function d3_cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; + } + function d3_tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); + } + function d3_haversin(x) { + return (x = Math.sin(x / 2)) * x; + } + var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; + d3.interpolateZoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; + if (d2 < ε2) { + S = Math.log(w1 / w0) / ρ; + i = function(t) { + return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; + }; + } else { + var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / ρ; + i = function(t) { + var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); + return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; + }; + } + i.duration = S * 1e3; + return i; + }; + d3.behavior.zoom = function() { + var view = { + x: 0, + y: 0, + k: 1 + }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; + if (!d3_behavior_zoomWheel) { + d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); + }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return d3.event.wheelDelta; + }, "mousewheel") : (d3_behavior_zoomDelta = function() { + return -d3.event.detail; + }, "MozMousePixelScroll"); + } + function zoom(g) { + g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); + } + zoom.event = function(g) { + g.each(function() { + var dispatch = event.of(this, arguments), view1 = view; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.zoom", function() { + view = this.__chart__ || { + x: 0, + y: 0, + k: 1 + }; + zoomstarted(dispatch); + }).tween("zoom:zoom", function() { + var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); + return function(t) { + var l = i(t), k = dx / l[2]; + this.__chart__ = view = { + x: cx - l[0] * k, + y: cy - l[1] * k, + k: k + }; + zoomed(dispatch); + }; + }).each("interrupt.zoom", function() { + zoomended(dispatch); + }).each("end.zoom", function() { + zoomended(dispatch); + }); + } else { + this.__chart__ = view; + zoomstarted(dispatch); + zoomed(dispatch); + zoomended(dispatch); + } + }); + }; + zoom.translate = function(_) { + if (!arguments.length) return [ view.x, view.y ]; + view = { + x: +_[0], + y: +_[1], + k: view.k + }; + rescale(); + return zoom; + }; + zoom.scale = function(_) { + if (!arguments.length) return view.k; + view = { + x: view.x, + y: view.y, + k: null + }; + scaleTo(+_); + rescale(); + return zoom; + }; + zoom.scaleExtent = function(_) { + if (!arguments.length) return scaleExtent; + scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; + return zoom; + }; + zoom.center = function(_) { + if (!arguments.length) return center; + center = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.size = function(_) { + if (!arguments.length) return size; + size = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.duration = function(_) { + if (!arguments.length) return duration; + duration = +_; + return zoom; + }; + zoom.x = function(z) { + if (!arguments.length) return x1; + x1 = z; + x0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + zoom.y = function(z) { + if (!arguments.length) return y1; + y1 = z; + y0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + function location(p) { + return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; + } + function point(l) { + return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; + } + function scaleTo(s) { + view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); + } + function translateTo(p, l) { + l = point(l); + view.x += p[0] - l[0]; + view.y += p[1] - l[1]; + } + function zoomTo(that, p, l, k) { + that.__chart__ = { + x: view.x, + y: view.y, + k: view.k + }; + scaleTo(Math.pow(2, k)); + translateTo(center0 = p, l); + that = d3.select(that); + if (duration > 0) that = that.transition().duration(duration); + that.call(zoom.event); + } + function rescale() { + if (x1) x1.domain(x0.range().map(function(x) { + return (x - view.x) / view.k; + }).map(x0.invert)); + if (y1) y1.domain(y0.range().map(function(y) { + return (y - view.y) / view.k; + }).map(y0.invert)); + } + function zoomstarted(dispatch) { + if (!zooming++) dispatch({ + type: "zoomstart" + }); + } + function zoomed(dispatch) { + rescale(); + dispatch({ + type: "zoom", + scale: view.k, + translate: [ view.x, view.y ] + }); + } + function zoomended(dispatch) { + if (!--zooming) dispatch({ + type: "zoomend" + }), center0 = null; + } + function mousedowned() { + var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); + d3_selection_interrupt.call(that); + zoomstarted(dispatch); + function moved() { + dragged = 1; + translateTo(d3.mouse(that), location0); + zoomed(dispatch); + } + function ended() { + subject.on(mousemove, null).on(mouseup, null); + dragRestore(dragged); + zoomended(dispatch); + } + } + function touchstarted() { + var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); + started(); + zoomstarted(dispatch); + subject.on(mousedown, null).on(touchstart, started); + function relocate() { + var touches = d3.touches(that); + scale0 = view.k; + touches.forEach(function(t) { + if (t.identifier in locations0) locations0[t.identifier] = location(t); + }); + return touches; + } + function started() { + var target = d3.event.target; + d3.select(target).on(touchmove, moved).on(touchend, ended); + targets.push(target); + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + locations0[changed[i].identifier] = null; + } + var touches = relocate(), now = Date.now(); + if (touches.length === 1) { + if (now - touchtime < 500) { + var p = touches[0]; + zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); + d3_eventPreventDefault(); + } + touchtime = now; + } else if (touches.length > 1) { + var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; + distance0 = dx * dx + dy * dy; + } + } + function moved() { + var touches = d3.touches(that), p0, l0, p1, l1; + d3_selection_interrupt.call(that); + for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { + p1 = touches[i]; + if (l1 = locations0[p1.identifier]) { + if (l0) break; + p0 = p1, l0 = l1; + } + } + if (l1) { + var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); + p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; + l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; + scaleTo(scale1 * scale0); + } + touchtime = null; + translateTo(p0, l0); + zoomed(dispatch); + } + function ended() { + if (d3.event.touches.length) { + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + delete locations0[changed[i].identifier]; + } + for (var identifier in locations0) { + return void relocate(); + } + } + d3.selectAll(targets).on(zoomName, null); + subject.on(mousedown, mousedowned).on(touchstart, touchstarted); + dragRestore(); + zoomended(dispatch); + } + } + function mousewheeled() { + var dispatch = event.of(this, arguments); + if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), + translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); + mousewheelTimer = setTimeout(function() { + mousewheelTimer = null; + zoomended(dispatch); + }, 50); + d3_eventPreventDefault(); + scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); + translateTo(center0, translate0); + zoomed(dispatch); + } + function dblclicked() { + var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; + zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); + } + return d3.rebind(zoom, event, "on"); + }; + var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; + d3.color = d3_color; + function d3_color() {} + d3_color.prototype.toString = function() { + return this.rgb() + ""; + }; + d3.hsl = d3_hsl; + function d3_hsl(h, s, l) { + return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); + } + var d3_hslPrototype = d3_hsl.prototype = new d3_color(); + d3_hslPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, this.l / k); + }; + d3_hslPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, k * this.l); + }; + d3_hslPrototype.rgb = function() { + return d3_hsl_rgb(this.h, this.s, this.l); + }; + function d3_hsl_rgb(h, s, l) { + var m1, m2; + h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; + s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; + l = l < 0 ? 0 : l > 1 ? 1 : l; + m2 = l <= .5 ? l * (1 + s) : l + s - l * s; + m1 = 2 * l - m2; + function v(h) { + if (h > 360) h -= 360; else if (h < 0) h += 360; + if (h < 60) return m1 + (m2 - m1) * h / 60; + if (h < 180) return m2; + if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; + return m1; + } + function vv(h) { + return Math.round(v(h) * 255); + } + return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); + } + d3.hcl = d3_hcl; + function d3_hcl(h, c, l) { + return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); + } + var d3_hclPrototype = d3_hcl.prototype = new d3_color(); + d3_hclPrototype.brighter = function(k) { + return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.darker = function(k) { + return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.rgb = function() { + return d3_hcl_lab(this.h, this.c, this.l).rgb(); + }; + function d3_hcl_lab(h, c, l) { + if (isNaN(h)) h = 0; + if (isNaN(c)) c = 0; + return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); + } + d3.lab = d3_lab; + function d3_lab(l, a, b) { + return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); + } + var d3_lab_K = 18; + var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; + var d3_labPrototype = d3_lab.prototype = new d3_color(); + d3_labPrototype.brighter = function(k) { + return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.darker = function(k) { + return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.rgb = function() { + return d3_lab_rgb(this.l, this.a, this.b); + }; + function d3_lab_rgb(l, a, b) { + var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; + x = d3_lab_xyz(x) * d3_lab_X; + y = d3_lab_xyz(y) * d3_lab_Y; + z = d3_lab_xyz(z) * d3_lab_Z; + return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); + } + function d3_lab_hcl(l, a, b) { + return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); + } + function d3_lab_xyz(x) { + return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; + } + function d3_xyz_lab(x) { + return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; + } + function d3_xyz_rgb(r) { + return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); + } + d3.rgb = d3_rgb; + function d3_rgb(r, g, b) { + return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); + } + function d3_rgbNumber(value) { + return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); + } + function d3_rgbString(value) { + return d3_rgbNumber(value) + ""; + } + var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); + d3_rgbPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + var r = this.r, g = this.g, b = this.b, i = 30; + if (!r && !g && !b) return new d3_rgb(i, i, i); + if (r && r < i) r = i; + if (g && g < i) g = i; + if (b && b < i) b = i; + return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); + }; + d3_rgbPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_rgb(k * this.r, k * this.g, k * this.b); + }; + d3_rgbPrototype.hsl = function() { + return d3_rgb_hsl(this.r, this.g, this.b); + }; + d3_rgbPrototype.toString = function() { + return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); + }; + function d3_rgb_hex(v) { + return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); + } + function d3_rgb_parse(format, rgb, hsl) { + var r = 0, g = 0, b = 0, m1, m2, color; + m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); + if (m1) { + m2 = m1[2].split(","); + switch (m1[1]) { + case "hsl": + { + return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); + } + + case "rgb": + { + return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); + } + } + } + if (color = d3_rgb_names.get(format)) { + return rgb(color.r, color.g, color.b); + } + if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { + if (format.length === 4) { + r = (color & 3840) >> 4; + r = r >> 4 | r; + g = color & 240; + g = g >> 4 | g; + b = color & 15; + b = b << 4 | b; + } else if (format.length === 7) { + r = (color & 16711680) >> 16; + g = (color & 65280) >> 8; + b = color & 255; + } + } + return rgb(r, g, b); + } + function d3_rgb_hsl(r, g, b) { + var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; + if (d) { + s = l < .5 ? d / (max + min) : d / (2 - max - min); + if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; + h *= 60; + } else { + h = NaN; + s = l > 0 && l < 1 ? 0 : h; + } + return new d3_hsl(h, s, l); + } + function d3_rgb_lab(r, g, b) { + r = d3_rgb_xyz(r); + g = d3_rgb_xyz(g); + b = d3_rgb_xyz(b); + var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); + return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); + } + function d3_rgb_xyz(r) { + return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); + } + function d3_rgb_parseNumber(c) { + var f = parseFloat(c); + return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; + } + var d3_rgb_names = d3.map({ + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }); + d3_rgb_names.forEach(function(key, value) { + d3_rgb_names.set(key, d3_rgbNumber(value)); + }); + function d3_functor(v) { + return typeof v === "function" ? v : function() { + return v; + }; + } + d3.functor = d3_functor; + d3.xhr = d3_xhrType(d3_identity); + function d3_xhrType(response) { + return function(url, mimeType, callback) { + if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, + mimeType = null; + return d3_xhr(url, mimeType, response, callback); + }; + } + function d3_xhr(url, mimeType, response, callback) { + var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; + if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); + "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { + request.readyState > 3 && respond(); + }; + function respond() { + var status = request.status, result; + if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { + try { + result = response.call(xhr, request); + } catch (e) { + dispatch.error.call(xhr, e); + return; + } + dispatch.load.call(xhr, result); + } else { + dispatch.error.call(xhr, request); + } + } + request.onprogress = function(event) { + var o = d3.event; + d3.event = event; + try { + dispatch.progress.call(xhr, request); + } finally { + d3.event = o; + } + }; + xhr.header = function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers[name]; + if (value == null) delete headers[name]; else headers[name] = value + ""; + return xhr; + }; + xhr.mimeType = function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return xhr; + }; + xhr.responseType = function(value) { + if (!arguments.length) return responseType; + responseType = value; + return xhr; + }; + xhr.response = function(value) { + response = value; + return xhr; + }; + [ "get", "post" ].forEach(function(method) { + xhr[method] = function() { + return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); + }; + }); + xhr.send = function(method, data, callback) { + if (arguments.length === 2 && typeof data === "function") callback = data, data = null; + request.open(method, url, true); + if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; + if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); + if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); + if (responseType != null) request.responseType = responseType; + if (callback != null) xhr.on("error", callback).on("load", function(request) { + callback(null, request); + }); + dispatch.beforesend.call(xhr, request); + request.send(data == null ? null : data); + return xhr; + }; + xhr.abort = function() { + request.abort(); + return xhr; + }; + d3.rebind(xhr, dispatch, "on"); + return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); + } + function d3_xhr_fixCallback(callback) { + return callback.length === 1 ? function(error, request) { + callback(error == null ? request : null); + } : callback; + } + function d3_xhrHasResponse(request) { + var type = request.responseType; + return type && type !== "text" ? request.response : request.responseText; + } + d3.dsv = function(delimiter, mimeType) { + var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); + function dsv(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); + xhr.row = function(_) { + return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; + }; + return xhr; + } + function response(request) { + return dsv.parse(request.responseText); + } + function typedResponse(f) { + return function(request) { + return dsv.parse(request.responseText, f); + }; + } + dsv.parse = function(text, f) { + var o; + return dsv.parseRows(text, function(row, i) { + if (o) return o(row, i - 1); + var a = new Function("d", "return {" + row.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); + o = f ? function(row, i) { + return f(a(row), i); + } : a; + }); + }; + dsv.parseRows = function(text, f) { + var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; + function token() { + if (I >= N) return EOF; + if (eol) return eol = false, EOL; + var j = I; + if (text.charCodeAt(j) === 34) { + var i = j; + while (i++ < N) { + if (text.charCodeAt(i) === 34) { + if (text.charCodeAt(i + 1) !== 34) break; + ++i; + } + } + I = i + 2; + var c = text.charCodeAt(i + 1); + if (c === 13) { + eol = true; + if (text.charCodeAt(i + 2) === 10) ++I; + } else if (c === 10) { + eol = true; + } + return text.slice(j + 1, i).replace(/""/g, '"'); + } + while (I < N) { + var c = text.charCodeAt(I++), k = 1; + if (c === 10) eol = true; else if (c === 13) { + eol = true; + if (text.charCodeAt(I) === 10) ++I, ++k; + } else if (c !== delimiterCode) continue; + return text.slice(j, I - k); + } + return text.slice(j); + } + while ((t = token()) !== EOF) { + var a = []; + while (t !== EOL && t !== EOF) { + a.push(t); + t = token(); + } + if (f && (a = f(a, n++)) == null) continue; + rows.push(a); + } + return rows; + }; + dsv.format = function(rows) { + if (Array.isArray(rows[0])) return dsv.formatRows(rows); + var fieldSet = new d3_Set(), fields = []; + rows.forEach(function(row) { + for (var field in row) { + if (!fieldSet.has(field)) { + fields.push(fieldSet.add(field)); + } + } + }); + return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { + return fields.map(function(field) { + return formatValue(row[field]); + }).join(delimiter); + })).join("\n"); + }; + dsv.formatRows = function(rows) { + return rows.map(formatRow).join("\n"); + }; + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + function formatValue(text) { + return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; + } + return dsv; + }; + d3.csv = d3.dsv(",", "text/csv"); + d3.tsv = d3.dsv(" ", "text/tab-separated-values"); + var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { + setTimeout(callback, 17); + }; + d3.timer = function() { + d3_timer.apply(this, arguments); + }; + function d3_timer(callback, delay, then) { + var n = arguments.length; + if (n < 2) delay = 0; + if (n < 3) then = Date.now(); + var time = then + delay, timer = { + c: callback, + t: time, + n: null + }; + if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; + d3_timer_queueTail = timer; + if (!d3_timer_interval) { + d3_timer_timeout = clearTimeout(d3_timer_timeout); + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + return timer; + } + function d3_timer_step() { + var now = d3_timer_mark(), delay = d3_timer_sweep() - now; + if (delay > 24) { + if (isFinite(delay)) { + clearTimeout(d3_timer_timeout); + d3_timer_timeout = setTimeout(d3_timer_step, delay); + } + d3_timer_interval = 0; + } else { + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + } + d3.timer.flush = function() { + d3_timer_mark(); + d3_timer_sweep(); + }; + function d3_timer_mark() { + var now = Date.now(), timer = d3_timer_queueHead; + while (timer) { + if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; + timer = timer.n; + } + return now; + } + function d3_timer_sweep() { + var t0, t1 = d3_timer_queueHead, time = Infinity; + while (t1) { + if (t1.c) { + if (t1.t < time) time = t1.t; + t1 = (t0 = t1).n; + } else { + t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; + } + } + d3_timer_queueTail = t0; + return time; + } + function d3_format_precision(x, p) { + return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); + } + d3.round = function(x, n) { + return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); + }; + var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); + d3.formatPrefix = function(value, precision) { + var i = 0; + if (value = +value) { + if (value < 0) value *= -1; + if (precision) value = d3.round(value, d3_format_precision(value, precision)); + i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); + i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); + } + return d3_formatPrefixes[8 + i / 3]; + }; + function d3_formatPrefix(d, i) { + var k = Math.pow(10, abs(8 - i) * 3); + return { + scale: i > 8 ? function(d) { + return d / k; + } : function(d) { + return d * k; + }, + symbol: d + }; + } + function d3_locale_numberFormat(locale) { + var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { + var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; + while (i > 0 && g > 0) { + if (length + g + 1 > width) g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) break; + g = locale_grouping[j = (j + 1) % locale_grouping.length]; + } + return t.reverse().join(locale_thousands); + } : d3_identity; + return function(specifier) { + var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; + if (precision) precision = +precision.substring(1); + if (zfill || fill === "0" && align === "=") { + zfill = fill = "0"; + align = "="; + } + switch (type) { + case "n": + comma = true; + type = "g"; + break; + + case "%": + scale = 100; + suffix = "%"; + type = "f"; + break; + + case "p": + scale = 100; + suffix = "%"; + type = "r"; + break; + + case "b": + case "o": + case "x": + case "X": + if (symbol === "#") prefix = "0" + type.toLowerCase(); + + case "c": + exponent = false; + + case "d": + integer = true; + precision = 0; + break; + + case "s": + scale = -1; + type = "r"; + break; + } + if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; + if (type == "r" && !precision) type = "g"; + if (precision != null) { + if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); + } + type = d3_format_types.get(type) || d3_format_typeDefault; + var zcomma = zfill && comma; + return function(value) { + var fullSuffix = suffix; + if (integer && value % 1) return ""; + var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; + if (scale < 0) { + var unit = d3.formatPrefix(value, precision); + value = unit.scale(value); + fullSuffix = unit.symbol + suffix; + } else { + value *= scale; + } + value = type(value, precision); + var i = value.lastIndexOf("."), before, after; + if (i < 0) { + var j = exponent ? value.lastIndexOf("e") : -1; + if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); + } else { + before = value.substring(0, i); + after = locale_decimal + value.substring(i + 1); + } + if (!zfill && comma) before = formatGroup(before, Infinity); + var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; + if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); + negative += prefix; + value = before + after; + return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; + }; + }; + } + var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; + var d3_format_types = d3.map({ + b: function(x) { + return x.toString(2); + }, + c: function(x) { + return String.fromCharCode(x); + }, + o: function(x) { + return x.toString(8); + }, + x: function(x) { + return x.toString(16); + }, + X: function(x) { + return x.toString(16).toUpperCase(); + }, + g: function(x, p) { + return x.toPrecision(p); + }, + e: function(x, p) { + return x.toExponential(p); + }, + f: function(x, p) { + return x.toFixed(p); + }, + r: function(x, p) { + return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); + } + }); + function d3_format_typeDefault(x) { + return x + ""; + } + var d3_time = d3.time = {}, d3_date = Date; + function d3_date_utc() { + this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); + } + d3_date_utc.prototype = { + getDate: function() { + return this._.getUTCDate(); + }, + getDay: function() { + return this._.getUTCDay(); + }, + getFullYear: function() { + return this._.getUTCFullYear(); + }, + getHours: function() { + return this._.getUTCHours(); + }, + getMilliseconds: function() { + return this._.getUTCMilliseconds(); + }, + getMinutes: function() { + return this._.getUTCMinutes(); + }, + getMonth: function() { + return this._.getUTCMonth(); + }, + getSeconds: function() { + return this._.getUTCSeconds(); + }, + getTime: function() { + return this._.getTime(); + }, + getTimezoneOffset: function() { + return 0; + }, + valueOf: function() { + return this._.valueOf(); + }, + setDate: function() { + d3_time_prototype.setUTCDate.apply(this._, arguments); + }, + setDay: function() { + d3_time_prototype.setUTCDay.apply(this._, arguments); + }, + setFullYear: function() { + d3_time_prototype.setUTCFullYear.apply(this._, arguments); + }, + setHours: function() { + d3_time_prototype.setUTCHours.apply(this._, arguments); + }, + setMilliseconds: function() { + d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); + }, + setMinutes: function() { + d3_time_prototype.setUTCMinutes.apply(this._, arguments); + }, + setMonth: function() { + d3_time_prototype.setUTCMonth.apply(this._, arguments); + }, + setSeconds: function() { + d3_time_prototype.setUTCSeconds.apply(this._, arguments); + }, + setTime: function() { + d3_time_prototype.setTime.apply(this._, arguments); + } + }; + var d3_time_prototype = Date.prototype; + function d3_time_interval(local, step, number) { + function round(date) { + var d0 = local(date), d1 = offset(d0, 1); + return date - d0 < d1 - date ? d0 : d1; + } + function ceil(date) { + step(date = local(new d3_date(date - 1)), 1); + return date; + } + function offset(date, k) { + step(date = new d3_date(+date), k); + return date; + } + function range(t0, t1, dt) { + var time = ceil(t0), times = []; + if (dt > 1) { + while (time < t1) { + if (!(number(time) % dt)) times.push(new Date(+time)); + step(time, 1); + } + } else { + while (time < t1) times.push(new Date(+time)), step(time, 1); + } + return times; + } + function range_utc(t0, t1, dt) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = t0; + return range(utc, t1, dt); + } finally { + d3_date = Date; + } + } + local.floor = local; + local.round = round; + local.ceil = ceil; + local.offset = offset; + local.range = range; + var utc = local.utc = d3_time_interval_utc(local); + utc.floor = utc; + utc.round = d3_time_interval_utc(round); + utc.ceil = d3_time_interval_utc(ceil); + utc.offset = d3_time_interval_utc(offset); + utc.range = range_utc; + return local; + } + function d3_time_interval_utc(method) { + return function(date, k) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = date; + return method(utc, k)._; + } finally { + d3_date = Date; + } + }; + } + d3_time.year = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setMonth(0, 1); + return date; + }, function(date, offset) { + date.setFullYear(date.getFullYear() + offset); + }, function(date) { + return date.getFullYear(); + }); + d3_time.years = d3_time.year.range; + d3_time.years.utc = d3_time.year.utc.range; + d3_time.day = d3_time_interval(function(date) { + var day = new d3_date(2e3, 0); + day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + return day; + }, function(date, offset) { + date.setDate(date.getDate() + offset); + }, function(date) { + return date.getDate() - 1; + }); + d3_time.days = d3_time.day.range; + d3_time.days.utc = d3_time.day.utc.range; + d3_time.dayOfYear = function(date) { + var year = d3_time.year(date); + return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); + }; + [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { + i = 7 - i; + var interval = d3_time[day] = d3_time_interval(function(date) { + (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); + return date; + }, function(date, offset) { + date.setDate(date.getDate() + Math.floor(offset) * 7); + }, function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); + }); + d3_time[day + "s"] = interval.range; + d3_time[day + "s"].utc = interval.utc.range; + d3_time[day + "OfYear"] = function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); + }; + }); + d3_time.week = d3_time.sunday; + d3_time.weeks = d3_time.sunday.range; + d3_time.weeks.utc = d3_time.sunday.utc.range; + d3_time.weekOfYear = d3_time.sundayOfYear; + function d3_locale_timeFormat(locale) { + var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; + function d3_time_format(template) { + var n = template.length; + function format(date) { + var string = [], i = -1, j = 0, c, p, f; + while (++i < n) { + if (template.charCodeAt(i) === 37) { + string.push(template.slice(j, i)); + if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); + if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); + string.push(c); + j = i + 1; + } + } + string.push(template.slice(j, i)); + return string.join(""); + } + format.parse = function(string) { + var d = { + y: 1900, + m: 0, + d: 1, + H: 0, + M: 0, + S: 0, + L: 0, + Z: null + }, i = d3_time_parse(d, template, string, 0); + if (i != string.length) return null; + if ("p" in d) d.H = d.H % 12 + d.p * 12; + var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); + if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + date.setFullYear(d.y, 0, 1); + date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); + } else date.setFullYear(d.y, d.m, d.d); + date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); + return localZ ? date._ : date; + }; + format.toString = function() { + return template; + }; + return format; + } + function d3_time_parse(date, template, string, j) { + var c, p, t, i = 0, n = template.length, m = string.length; + while (i < n) { + if (j >= m) return -1; + c = template.charCodeAt(i++); + if (c === 37) { + t = template.charAt(i++); + p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; + if (!p || (j = p(date, string, j)) < 0) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + return j; + } + d3_time_format.utc = function(template) { + var local = d3_time_format(template); + function format(date) { + try { + d3_date = d3_date_utc; + var utc = new d3_date(); + utc._ = date; + return local(utc); + } finally { + d3_date = Date; + } + } + format.parse = function(string) { + try { + d3_date = d3_date_utc; + var date = local.parse(string); + return date && date._; + } finally { + d3_date = Date; + } + }; + format.toString = local.toString; + return format; + }; + d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; + var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); + locale_periods.forEach(function(p, i) { + d3_time_periodLookup.set(p.toLowerCase(), i); + }); + var d3_time_formats = { + a: function(d) { + return locale_shortDays[d.getDay()]; + }, + A: function(d) { + return locale_days[d.getDay()]; + }, + b: function(d) { + return locale_shortMonths[d.getMonth()]; + }, + B: function(d) { + return locale_months[d.getMonth()]; + }, + c: d3_time_format(locale_dateTime), + d: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + e: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + H: function(d, p) { + return d3_time_formatPad(d.getHours(), p, 2); + }, + I: function(d, p) { + return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); + }, + j: function(d, p) { + return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); + }, + L: function(d, p) { + return d3_time_formatPad(d.getMilliseconds(), p, 3); + }, + m: function(d, p) { + return d3_time_formatPad(d.getMonth() + 1, p, 2); + }, + M: function(d, p) { + return d3_time_formatPad(d.getMinutes(), p, 2); + }, + p: function(d) { + return locale_periods[+(d.getHours() >= 12)]; + }, + S: function(d, p) { + return d3_time_formatPad(d.getSeconds(), p, 2); + }, + U: function(d, p) { + return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); + }, + w: function(d) { + return d.getDay(); + }, + W: function(d, p) { + return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); + }, + x: d3_time_format(locale_date), + X: d3_time_format(locale_time), + y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 100, p, 2); + }, + Y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); + }, + Z: d3_time_zone, + "%": function() { + return "%"; + } + }; + var d3_time_parsers = { + a: d3_time_parseWeekdayAbbrev, + A: d3_time_parseWeekday, + b: d3_time_parseMonthAbbrev, + B: d3_time_parseMonth, + c: d3_time_parseLocaleFull, + d: d3_time_parseDay, + e: d3_time_parseDay, + H: d3_time_parseHour24, + I: d3_time_parseHour24, + j: d3_time_parseDayOfYear, + L: d3_time_parseMilliseconds, + m: d3_time_parseMonthNumber, + M: d3_time_parseMinutes, + p: d3_time_parseAmPm, + S: d3_time_parseSeconds, + U: d3_time_parseWeekNumberSunday, + w: d3_time_parseWeekdayNumber, + W: d3_time_parseWeekNumberMonday, + x: d3_time_parseLocaleDate, + X: d3_time_parseLocaleTime, + y: d3_time_parseYear, + Y: d3_time_parseFullYear, + Z: d3_time_parseZone, + "%": d3_time_parseLiteralPercent + }; + function d3_time_parseWeekdayAbbrev(date, string, i) { + d3_time_dayAbbrevRe.lastIndex = 0; + var n = d3_time_dayAbbrevRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseWeekday(date, string, i) { + d3_time_dayRe.lastIndex = 0; + var n = d3_time_dayRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonthAbbrev(date, string, i) { + d3_time_monthAbbrevRe.lastIndex = 0; + var n = d3_time_monthAbbrevRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonth(date, string, i) { + d3_time_monthRe.lastIndex = 0; + var n = d3_time_monthRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseLocaleFull(date, string, i) { + return d3_time_parse(date, d3_time_formats.c.toString(), string, i); + } + function d3_time_parseLocaleDate(date, string, i) { + return d3_time_parse(date, d3_time_formats.x.toString(), string, i); + } + function d3_time_parseLocaleTime(date, string, i) { + return d3_time_parse(date, d3_time_formats.X.toString(), string, i); + } + function d3_time_parseAmPm(date, string, i) { + var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); + return n == null ? -1 : (date.p = n, i); + } + return d3_time_format; + } + var d3_time_formatPads = { + "-": "", + _: " ", + "0": "0" + }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; + function d3_time_formatPad(value, fill, width) { + var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); + } + function d3_time_formatRe(names) { + return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); + } + function d3_time_formatLookup(names) { + var map = new d3_Map(), i = -1, n = names.length; + while (++i < n) map.set(names[i].toLowerCase(), i); + return map; + } + function d3_time_parseWeekdayNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 1)); + return n ? (date.w = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberSunday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.U = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberMonday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.W = +n[0], i + n[0].length) : -1; + } + function d3_time_parseFullYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 4)); + return n ? (date.y = +n[0], i + n[0].length) : -1; + } + function d3_time_parseYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; + } + function d3_time_parseZone(date, string, i) { + return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, + i + 5) : -1; + } + function d3_time_expandYear(d) { + return d + (d > 68 ? 1900 : 2e3); + } + function d3_time_parseMonthNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.m = n[0] - 1, i + n[0].length) : -1; + } + function d3_time_parseDay(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.d = +n[0], i + n[0].length) : -1; + } + function d3_time_parseDayOfYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.j = +n[0], i + n[0].length) : -1; + } + function d3_time_parseHour24(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.H = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMinutes(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.M = +n[0], i + n[0].length) : -1; + } + function d3_time_parseSeconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.S = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMilliseconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.L = +n[0], i + n[0].length) : -1; + } + function d3_time_zone(d) { + var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; + return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); + } + function d3_time_parseLiteralPercent(date, string, i) { + d3_time_percentRe.lastIndex = 0; + var n = d3_time_percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; + } + function d3_time_formatMulti(formats) { + var n = formats.length, i = -1; + while (++i < n) formats[i][0] = this(formats[i][0]); + return function(date) { + var i = 0, f = formats[i]; + while (!f[1](date)) f = formats[++i]; + return f[0](date); + }; + } + d3.locale = function(locale) { + return { + numberFormat: d3_locale_numberFormat(locale), + timeFormat: d3_locale_timeFormat(locale) + }; + }; + var d3_locale_enUS = d3.locale({ + decimal: ".", + thousands: ",", + grouping: [ 3 ], + currency: [ "$", "" ], + dateTime: "%a %b %e %X %Y", + date: "%m/%d/%Y", + time: "%H:%M:%S", + periods: [ "AM", "PM" ], + days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], + months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], + shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] + }); + d3.format = d3_locale_enUS.numberFormat; + d3.geo = {}; + function d3_adder() {} + d3_adder.prototype = { + s: 0, + t: 0, + add: function(y) { + d3_adderSum(y, this.t, d3_adderTemp); + d3_adderSum(d3_adderTemp.s, this.s, this); + if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; + }, + reset: function() { + this.s = this.t = 0; + }, + valueOf: function() { + return this.s; + } + }; + var d3_adderTemp = new d3_adder(); + function d3_adderSum(a, b, o) { + var x = o.s = a + b, bv = x - a, av = x - bv; + o.t = a - av + (b - bv); + } + d3.geo.stream = function(object, listener) { + if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { + d3_geo_streamObjectType[object.type](object, listener); + } else { + d3_geo_streamGeometry(object, listener); + } + }; + function d3_geo_streamGeometry(geometry, listener) { + if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { + d3_geo_streamGeometryType[geometry.type](geometry, listener); + } + } + var d3_geo_streamObjectType = { + Feature: function(feature, listener) { + d3_geo_streamGeometry(feature.geometry, listener); + }, + FeatureCollection: function(object, listener) { + var features = object.features, i = -1, n = features.length; + while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); + } + }; + var d3_geo_streamGeometryType = { + Sphere: function(object, listener) { + listener.sphere(); + }, + Point: function(object, listener) { + object = object.coordinates; + listener.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); + }, + LineString: function(object, listener) { + d3_geo_streamLine(object.coordinates, listener, 0); + }, + MultiLineString: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); + }, + Polygon: function(object, listener) { + d3_geo_streamPolygon(object.coordinates, listener); + }, + MultiPolygon: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); + }, + GeometryCollection: function(object, listener) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) d3_geo_streamGeometry(geometries[i], listener); + } + }; + function d3_geo_streamLine(coordinates, listener, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + listener.lineStart(); + while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); + listener.lineEnd(); + } + function d3_geo_streamPolygon(coordinates, listener) { + var i = -1, n = coordinates.length; + listener.polygonStart(); + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); + listener.polygonEnd(); + } + d3.geo.area = function(object) { + d3_geo_areaSum = 0; + d3.geo.stream(object, d3_geo_area); + return d3_geo_areaSum; + }; + var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); + var d3_geo_area = { + sphere: function() { + d3_geo_areaSum += 4 * π; + }, + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_areaRingSum.reset(); + d3_geo_area.lineStart = d3_geo_areaRingStart; + }, + polygonEnd: function() { + var area = 2 * d3_geo_areaRingSum; + d3_geo_areaSum += area < 0 ? 4 * π + area : area; + d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; + } + }; + function d3_geo_areaRingStart() { + var λ00, φ00, λ0, cosφ0, sinφ0; + d3_geo_area.point = function(λ, φ) { + d3_geo_area.point = nextPoint; + λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), + sinφ0 = Math.sin(φ); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + φ = φ * d3_radians / 2 + π / 4; + var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); + d3_geo_areaRingSum.add(Math.atan2(v, u)); + λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; + } + d3_geo_area.lineEnd = function() { + nextPoint(λ00, φ00); + }; + } + function d3_geo_cartesian(spherical) { + var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); + return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; + } + function d3_geo_cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + function d3_geo_cartesianCross(a, b) { + return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; + } + function d3_geo_cartesianAdd(a, b) { + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; + } + function d3_geo_cartesianScale(vector, k) { + return [ vector[0] * k, vector[1] * k, vector[2] * k ]; + } + function d3_geo_cartesianNormalize(d) { + var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l; + d[1] /= l; + d[2] /= l; + } + function d3_geo_spherical(cartesian) { + return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; + } + function d3_geo_sphericalEqual(a, b) { + return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; + } + d3.geo.bounds = function() { + var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; + var bound = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + bound.point = ringPoint; + bound.lineStart = ringStart; + bound.lineEnd = ringEnd; + dλSum = 0; + d3_geo_area.polygonStart(); + }, + polygonEnd: function() { + d3_geo_area.polygonEnd(); + bound.point = point; + bound.lineStart = lineStart; + bound.lineEnd = lineEnd; + if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; + range[0] = λ0, range[1] = λ1; + } + }; + function point(λ, φ) { + ranges.push(range = [ λ0 = λ, λ1 = λ ]); + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + function linePoint(λ, φ) { + var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); + if (p0) { + var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); + d3_geo_cartesianNormalize(inflection); + inflection = d3_geo_spherical(inflection); + var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; + if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = inflection[1] * d3_degrees; + if (φi > φ1) φ1 = φi; + } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = -inflection[1] * d3_degrees; + if (φi < φ0) φ0 = φi; + } else { + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + if (antimeridian) { + if (λ < λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } else { + if (λ1 >= λ0) { + if (λ < λ0) λ0 = λ; + if (λ > λ1) λ1 = λ; + } else { + if (λ > λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } + } + } else { + point(λ, φ); + } + p0 = p, λ_ = λ; + } + function lineStart() { + bound.point = linePoint; + } + function lineEnd() { + range[0] = λ0, range[1] = λ1; + bound.point = point; + p0 = null; + } + function ringPoint(λ, φ) { + if (p0) { + var dλ = λ - λ_; + dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; + } else λ__ = λ, φ__ = φ; + d3_geo_area.point(λ, φ); + linePoint(λ, φ); + } + function ringStart() { + d3_geo_area.lineStart(); + } + function ringEnd() { + ringPoint(λ__, φ__); + d3_geo_area.lineEnd(); + if (abs(dλSum) > ε) λ0 = -(λ1 = 180); + range[0] = λ0, range[1] = λ1; + p0 = null; + } + function angle(λ0, λ1) { + return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; + } + function compareRanges(a, b) { + return a[0] - b[0]; + } + function withinRange(x, range) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + } + return function(feature) { + φ1 = λ1 = -(λ0 = φ0 = Infinity); + ranges = []; + d3.geo.stream(feature, bound); + var n = ranges.length; + if (n) { + ranges.sort(compareRanges); + for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { + b = ranges[i]; + if (withinRange(b[0], a) || withinRange(b[1], a)) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); + } + } + var best = -Infinity, dλ; + for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { + b = merged[i]; + if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; + } + } + ranges = range = null; + return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; + }; + }(); + d3.geo.centroid = function(object) { + d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, d3_geo_centroid); + var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; + if (m < ε2) { + x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; + if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; + m = x * x + y * y + z * z; + if (m < ε2) return [ NaN, NaN ]; + } + return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; + }; + var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; + var d3_geo_centroid = { + sphere: d3_noop, + point: d3_geo_centroidPoint, + lineStart: d3_geo_centroidLineStart, + lineEnd: d3_geo_centroidLineEnd, + polygonStart: function() { + d3_geo_centroid.lineStart = d3_geo_centroidRingStart; + }, + polygonEnd: function() { + d3_geo_centroid.lineStart = d3_geo_centroidLineStart; + } + }; + function d3_geo_centroidPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); + } + function d3_geo_centroidPointXYZ(x, y, z) { + ++d3_geo_centroidW0; + d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; + d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; + d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; + } + function d3_geo_centroidLineStart() { + var x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroid.point = nextPoint; + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_centroidLineEnd() { + d3_geo_centroid.point = d3_geo_centroidPoint; + } + function d3_geo_centroidRingStart() { + var λ00, φ00, x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ00 = λ, φ00 = φ; + d3_geo_centroid.point = nextPoint; + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + d3_geo_centroid.lineEnd = function() { + nextPoint(λ00, φ00); + d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; + d3_geo_centroid.point = d3_geo_centroidPoint; + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); + d3_geo_centroidX2 += v * cx; + d3_geo_centroidY2 += v * cy; + d3_geo_centroidZ2 += v * cz; + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_compose(a, b) { + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + return compose; + } + function d3_true() { + return true; + } + function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { + var subject = [], clip = []; + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n]; + if (d3_geo_sphericalEqual(p0, p1)) { + listener.lineStart(); + for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); + listener.lineEnd(); + return; + } + var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); + a.o = b; + subject.push(a); + clip.push(b); + a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); + b = new d3_geo_clipPolygonIntersection(p1, null, a, true); + a.o = b; + subject.push(a); + clip.push(b); + }); + clip.sort(compare); + d3_geo_clipPolygonLinkCircular(subject); + d3_geo_clipPolygonLinkCircular(clip); + if (!subject.length) return; + for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { + clip[i].e = entry = !entry; + } + var start = subject[0], points, point; + while (1) { + var current = start, isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + listener.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, listener); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, listener); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + listener.lineEnd(); + } + } + function d3_geo_clipPolygonLinkCircular(array) { + if (!(n = array.length)) return; + var n, i = 0, a = array[0], b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; + } + function d3_geo_clipPolygonIntersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; + this.e = entry; + this.v = false; + this.n = this.p = null; + } + function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { + return function(rotate, listener) { + var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = d3.merge(segments); + var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); + if (segments.length) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); + } else if (clipStartInside) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (polygonStarted) listener.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + listener.polygonStart(); + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + listener.polygonEnd(); + } + }; + function point(λ, φ) { + var point = rotate(λ, φ); + if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); + } + function pointLine(λ, φ) { + var point = rotate(λ, φ); + line.point(point[0], point[1]); + } + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + var segments; + var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; + function pointRing(λ, φ) { + ring.push([ λ, φ ]); + var point = rotate(λ, φ); + ringListener.point(point[0], point[1]); + } + function ringStart() { + ringListener.lineStart(); + ring = []; + } + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringListener.lineEnd(); + var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; + ring.pop(); + polygon.push(ring); + ring = null; + if (!n) return; + if (clean & 1) { + segment = ringSegments[0]; + var n = segment.length - 1, i = -1, point; + if (n > 0) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + while (++i < n) listener.point((point = segment[i])[0], point[1]); + listener.lineEnd(); + } + return; + } + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); + } + return clip; + }; + } + function d3_geo_clipSegmentLength1(segment) { + return segment.length > 1; + } + function d3_geo_clipBufferListener() { + var lines = [], line; + return { + lineStart: function() { + lines.push(line = []); + }, + point: function(λ, φ) { + line.push([ λ, φ ]); + }, + lineEnd: d3_noop, + buffer: function() { + var buffer = lines; + lines = []; + line = null; + return buffer; + }, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + } + }; + } + function d3_geo_clipSort(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); + } + var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); + function d3_geo_clipAntimeridianLine(listener) { + var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; + return { + lineStart: function() { + listener.lineStart(); + clean = 1; + }, + point: function(λ1, φ1) { + var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); + if (abs(dλ - π) < ε) { + listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + listener.point(λ1, φ0); + clean = 0; + } else if (sλ0 !== sλ1 && dλ >= π) { + if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; + if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; + φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + clean = 0; + } + listener.point(λ0 = λ1, φ0 = φ1); + sλ0 = sλ1; + }, + lineEnd: function() { + listener.lineEnd(); + λ0 = φ0 = NaN; + }, + clean: function() { + return 2 - clean; + } + }; + } + function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { + var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); + return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; + } + function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { + var φ; + if (from == null) { + φ = direction * halfπ; + listener.point(-π, φ); + listener.point(0, φ); + listener.point(π, φ); + listener.point(π, 0); + listener.point(π, -φ); + listener.point(0, -φ); + listener.point(-π, -φ); + listener.point(-π, 0); + listener.point(-π, φ); + } else if (abs(from[0] - to[0]) > ε) { + var s = from[0] < to[0] ? π : -π; + φ = direction * s / 2; + listener.point(-s, φ); + listener.point(0, φ); + listener.point(s, φ); + } else { + listener.point(to[0], to[1]); + } + } + function d3_geo_pointInPolygon(point, polygon) { + var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; + d3_geo_areaRingSum.reset(); + for (var i = 0, n = polygon.length; i < n; ++i) { + var ring = polygon[i], m = ring.length; + if (!m) continue; + var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; + while (true) { + if (j === m) j = 0; + point = ring[j]; + var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; + d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); + polarAngle += antimeridian ? dλ + sdλ * τ : dλ; + if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { + var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); + d3_geo_cartesianNormalize(arc); + var intersection = d3_geo_cartesianCross(meridianNormal, arc); + d3_geo_cartesianNormalize(intersection); + var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); + if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { + winding += antimeridian ^ dλ >= 0 ? 1 : -1; + } + } + if (!j++) break; + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; + } + } + return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1; + } + function d3_geo_clipCircle(radius) { + var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); + return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); + function visible(λ, φ) { + return Math.cos(λ) * Math.cos(φ) > cr; + } + function clipLine(listener) { + var point0, c0, v0, v00, clean; + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(λ, φ) { + var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; + if (!point0 && (v00 = v0 = v)) listener.lineStart(); + if (v !== v0) { + point2 = intersect(point0, point1); + if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { + point1[0] += ε; + point1[1] += ε; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + listener.lineStart(); + point2 = intersect(point1, point0); + listener.point(point2[0], point2[1]); + } else { + point2 = intersect(point0, point1); + listener.point(point2[0], point2[1]); + listener.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + } else { + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { + listener.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) listener.lineEnd(); + point0 = null; + }, + clean: function() { + return clean | (v00 && v0) << 1; + } + }; + } + function intersect(a, b, two) { + var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); + var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; + if (!determinant) return !two && a; + var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); + d3_geo_cartesianAdd(A, B); + var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); + if (t2 < 0) return; + var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); + d3_geo_cartesianAdd(q, A); + q = d3_geo_spherical(q); + if (!two) return q; + var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; + if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; + var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; + if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; + if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { + var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); + d3_geo_cartesianAdd(q1, A); + return [ q, d3_geo_spherical(q1) ]; + } + } + function code(λ, φ) { + var r = smallRadius ? radius : π - radius, code = 0; + if (λ < -r) code |= 1; else if (λ > r) code |= 2; + if (φ < -r) code |= 4; else if (φ > r) code |= 8; + return code; + } + } + function d3_geom_clipLine(x0, y0, x1, y1) { + return function(line) { + var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + if (t0 > 0) line.a = { + x: ax + t0 * dx, + y: ay + t0 * dy + }; + if (t1 < 1) line.b = { + x: ax + t1 * dx, + y: ay + t1 * dy + }; + return line; + }; + } + var d3_geo_clipExtentMAX = 1e9; + d3.geo.clipExtent = function() { + var x0, y0, x1, y1, stream, clip, clipExtent = { + stream: function(output) { + if (stream) stream.valid = false; + stream = clip(output); + stream.valid = true; + return stream; + }, + extent: function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); + if (stream) stream.valid = false, stream = null; + return clipExtent; + } + }; + return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); + }; + function d3_geo_clipExtent(x0, y0, x1, y1) { + return function(listener) { + var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + listener = bufferListener; + segments = []; + polygon = []; + clean = true; + }, + polygonEnd: function() { + listener = listener_; + segments = d3.merge(segments); + var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; + if (inside || visible) { + listener.polygonStart(); + if (inside) { + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (visible) { + d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); + } + listener.polygonEnd(); + } + segments = polygon = ring = null; + } + }; + function insidePolygon(p) { + var wn = 0, n = polygon.length, y = p[1]; + for (var i = 0; i < n; ++i) { + for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { + b = v[j]; + if (a[1] <= y) { + if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; + } else { + if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; + } + a = b; + } + } + return wn !== 0; + } + function interpolate(from, to, direction, listener) { + var a = 0, a1 = 0; + if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { + do { + listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + } while ((a = (a + direction + 4) % 4) !== a1); + } else { + listener.point(to[0], to[1]); + } + } + function pointVisible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + function point(x, y) { + if (pointVisible(x, y)) listener.point(x, y); + } + var x__, y__, v__, x_, y_, v_, first, clean; + function lineStart() { + clip.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferListener.rejoin(); + segments.push(bufferListener.buffer()); + } + clip.point = point; + if (v_) listener.lineEnd(); + } + function linePoint(x, y) { + x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); + y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); + var v = pointVisible(x, y); + if (polygon) ring.push([ x, y ]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + listener.lineStart(); + listener.point(x, y); + } + } else { + if (v && v_) listener.point(x, y); else { + var l = { + a: { + x: x_, + y: y_ + }, + b: { + x: x, + y: y + } + }; + if (clipLine(l)) { + if (!v_) { + listener.lineStart(); + listener.point(l.a.x, l.a.y); + } + listener.point(l.b.x, l.b.y); + if (!v) listener.lineEnd(); + clean = false; + } else if (v) { + listener.lineStart(); + listener.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + return clip; + }; + function corner(p, direction) { + return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; + } + function compare(a, b) { + return comparePoints(a.x, b.x); + } + function comparePoints(a, b) { + var ca = corner(a, 1), cb = corner(b, 1); + return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; + } + } + function d3_geo_conic(projectAt) { + var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); + p.parallels = function(_) { + if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; + return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); + }; + return p; + } + function d3_geo_conicEqualArea(φ0, φ1) { + var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; + function forward(λ, φ) { + var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; + return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = ρ0 - y; + return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; + }; + return forward; + } + (d3.geo.conicEqualArea = function() { + return d3_geo_conic(d3_geo_conicEqualArea); + }).raw = d3_geo_conicEqualArea; + d3.geo.albers = function() { + return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); + }; + d3.geo.albersUsa = function() { + var lower48 = d3.geo.albers(); + var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); + var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); + var point, pointStream = { + point: function(x, y) { + point = [ x, y ]; + } + }, lower48Point, alaskaPoint, hawaiiPoint; + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + point = null; + (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); + return point; + } + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; + return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); + }; + albersUsa.stream = function(stream) { + var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); + return { + point: function(x, y) { + lower48Stream.point(x, y); + alaskaStream.point(x, y); + hawaiiStream.point(x, y); + }, + sphere: function() { + lower48Stream.sphere(); + alaskaStream.sphere(); + hawaiiStream.sphere(); + }, + lineStart: function() { + lower48Stream.lineStart(); + alaskaStream.lineStart(); + hawaiiStream.lineStart(); + }, + lineEnd: function() { + lower48Stream.lineEnd(); + alaskaStream.lineEnd(); + hawaiiStream.lineEnd(); + }, + polygonStart: function() { + lower48Stream.polygonStart(); + alaskaStream.polygonStart(); + hawaiiStream.polygonStart(); + }, + polygonEnd: function() { + lower48Stream.polygonEnd(); + alaskaStream.polygonEnd(); + hawaiiStream.polygonEnd(); + } + }; + }; + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_); + alaska.precision(_); + hawaii.precision(_); + return albersUsa; + }; + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_); + alaska.scale(_ * .35); + hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; + alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + return albersUsa; + }; + return albersUsa.scale(1070); + }; + var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_pathAreaPolygon = 0; + d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; + }, + polygonEnd: function() { + d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; + d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); + } + }; + function d3_geo_pathAreaRingStart() { + var x00, y00, x0, y0; + d3_geo_pathArea.point = function(x, y) { + d3_geo_pathArea.point = nextPoint; + x00 = x0 = x, y00 = y0 = y; + }; + function nextPoint(x, y) { + d3_geo_pathAreaPolygon += y0 * x - x0 * y; + x0 = x, y0 = y; + } + d3_geo_pathArea.lineEnd = function() { + nextPoint(x00, y00); + }; + } + var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; + var d3_geo_pathBounds = { + point: d3_geo_pathBoundsPoint, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_pathBoundsPoint(x, y) { + if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; + if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; + if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; + if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; + } + function d3_geo_pathBuffer() { + var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointCircle = d3_geo_pathBufferCircle(_); + return stream; + }, + result: function() { + if (buffer.length) { + var result = buffer.join(""); + buffer = []; + return result; + } + } + }; + function point(x, y) { + buffer.push("M", x, ",", y, pointCircle); + } + function pointLineStart(x, y) { + buffer.push("M", x, ",", y); + stream.point = pointLine; + } + function pointLine(x, y) { + buffer.push("L", x, ",", y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + buffer.push("Z"); + } + return stream; + } + function d3_geo_pathBufferCircle(radius) { + return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; + } + var d3_geo_pathCentroid = { + point: d3_geo_pathCentroidPoint, + lineStart: d3_geo_pathCentroidLineStart, + lineEnd: d3_geo_pathCentroidLineEnd, + polygonStart: function() { + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; + }, + polygonEnd: function() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; + d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; + } + }; + function d3_geo_pathCentroidPoint(x, y) { + d3_geo_centroidX0 += x; + d3_geo_centroidY0 += y; + ++d3_geo_centroidZ0; + } + function d3_geo_pathCentroidLineStart() { + var x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + } + function d3_geo_pathCentroidLineEnd() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + } + function d3_geo_pathCentroidRingStart() { + var x00, y00, x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + z = y0 * x - x0 * y; + d3_geo_centroidX2 += z * (x0 + x); + d3_geo_centroidY2 += z * (y0 + y); + d3_geo_centroidZ2 += z * 3; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + d3_geo_pathCentroid.lineEnd = function() { + nextPoint(x00, y00); + }; + } + function d3_geo_pathContext(context) { + var pointRadius = 4.5; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointRadius = _; + return stream; + }, + result: d3_noop + }; + function point(x, y) { + context.moveTo(x + pointRadius, y); + context.arc(x, y, pointRadius, 0, τ); + } + function pointLineStart(x, y) { + context.moveTo(x, y); + stream.point = pointLine; + } + function pointLine(x, y) { + context.lineTo(x, y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + context.closePath(); + } + return stream; + } + function d3_geo_resample(project) { + var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; + function resample(stream) { + return (maxDepth ? resampleRecursive : resampleNone)(stream); + } + function resampleNone(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + }); + } + function resampleRecursive(stream) { + var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; + var resample = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + stream.polygonStart(); + resample.lineStart = ringStart; + }, + polygonEnd: function() { + stream.polygonEnd(); + resample.lineStart = lineStart; + } + }; + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + function lineStart() { + x0 = NaN; + resample.point = linePoint; + stream.lineStart(); + } + function linePoint(λ, φ) { + var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); + resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + function lineEnd() { + resample.point = point; + stream.lineEnd(); + } + function ringStart() { + lineStart(); + resample.point = ringPoint; + resample.lineEnd = ringEnd; + } + function ringPoint(λ, φ) { + linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resample.point = linePoint; + } + function ringEnd() { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); + resample.lineEnd = lineEnd; + lineEnd(); + } + return resample; + } + function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; + if (d2 > 4 * δ2 && depth--) { + var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); + } + } + } + resample.precision = function(_) { + if (!arguments.length) return Math.sqrt(δ2); + maxDepth = (δ2 = _ * _) > 0 && 16; + return resample; + }; + return resample; + } + d3.geo.path = function() { + var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); + d3.geo.stream(object, cacheStream); + } + return contextStream.result(); + } + path.area = function(object) { + d3_geo_pathAreaSum = 0; + d3.geo.stream(object, projectStream(d3_geo_pathArea)); + return d3_geo_pathAreaSum; + }; + path.centroid = function(object) { + d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); + return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; + }; + path.bounds = function(object) { + d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); + d3.geo.stream(object, projectStream(d3_geo_pathBounds)); + return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; + }; + path.projection = function(_) { + if (!arguments.length) return projection; + projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; + return reset(); + }; + path.context = function(_) { + if (!arguments.length) return context; + contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return reset(); + }; + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + function reset() { + cacheStream = null; + return path; + } + return path.projection(d3.geo.albersUsa()).context(null); + }; + function d3_geo_pathProjectStream(project) { + var resample = d3_geo_resample(function(x, y) { + return project([ x * d3_degrees, y * d3_degrees ]); + }); + return function(stream) { + return d3_geo_projectionRadians(resample(stream)); + }; + } + d3.geo.transform = function(methods) { + return { + stream: function(stream) { + var transform = new d3_geo_transform(stream); + for (var k in methods) transform[k] = methods[k]; + return transform; + } + }; + }; + function d3_geo_transform(stream) { + this.stream = stream; + } + d3_geo_transform.prototype = { + point: function(x, y) { + this.stream.point(x, y); + }, + sphere: function() { + this.stream.sphere(); + }, + lineStart: function() { + this.stream.lineStart(); + }, + lineEnd: function() { + this.stream.lineEnd(); + }, + polygonStart: function() { + this.stream.polygonStart(); + }, + polygonEnd: function() { + this.stream.polygonEnd(); + } + }; + function d3_geo_transformPoint(stream, point) { + return { + point: point, + sphere: function() { + stream.sphere(); + }, + lineStart: function() { + stream.lineStart(); + }, + lineEnd: function() { + stream.lineEnd(); + }, + polygonStart: function() { + stream.polygonStart(); + }, + polygonEnd: function() { + stream.polygonEnd(); + } + }; + } + d3.geo.projection = d3_geo_projection; + d3.geo.projectionMutator = d3_geo_projectionMutator; + function d3_geo_projection(project) { + return d3_geo_projectionMutator(function() { + return project; + })(); + } + function d3_geo_projectionMutator(projectAt) { + var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { + x = project(x, y); + return [ x[0] * k + δx, δy - x[1] * k ]; + }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; + function projection(point) { + point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); + return [ point[0] * k + δx, δy - point[1] * k ]; + } + function invert(point) { + point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); + return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; + } + projection.stream = function(output) { + if (stream) stream.valid = false; + stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); + stream.valid = true; + return stream; + }; + projection.clipAngle = function(_) { + if (!arguments.length) return clipAngle; + preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); + return invalidate(); + }; + projection.clipExtent = function(_) { + if (!arguments.length) return clipExtent; + clipExtent = _; + postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; + return invalidate(); + }; + projection.scale = function(_) { + if (!arguments.length) return k; + k = +_; + return reset(); + }; + projection.translate = function(_) { + if (!arguments.length) return [ x, y ]; + x = +_[0]; + y = +_[1]; + return reset(); + }; + projection.center = function(_) { + if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; + λ = _[0] % 360 * d3_radians; + φ = _[1] % 360 * d3_radians; + return reset(); + }; + projection.rotate = function(_) { + if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; + δλ = _[0] % 360 * d3_radians; + δφ = _[1] % 360 * d3_radians; + δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; + return reset(); + }; + d3.rebind(projection, projectResample, "precision"); + function reset() { + projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); + var center = project(λ, φ); + δx = x - center[0] * k; + δy = y + center[1] * k; + return invalidate(); + } + function invalidate() { + if (stream) stream.valid = false, stream = null; + return projection; + } + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return reset(); + }; + } + function d3_geo_projectionRadians(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + stream.point(x * d3_radians, y * d3_radians); + }); + } + function d3_geo_equirectangular(λ, φ) { + return [ λ, φ ]; + } + (d3.geo.equirectangular = function() { + return d3_geo_projection(d3_geo_equirectangular); + }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; + d3.geo.rotation = function(rotate) { + rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); + function forward(coordinates) { + coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + } + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + }; + return forward; + }; + function d3_geo_identityRotation(λ, φ) { + return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + } + d3_geo_identityRotation.invert = d3_geo_equirectangular; + function d3_geo_rotation(δλ, δφ, δγ) { + return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; + } + function d3_geo_forwardRotationλ(δλ) { + return function(λ, φ) { + return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + }; + } + function d3_geo_rotationλ(δλ) { + var rotation = d3_geo_forwardRotationλ(δλ); + rotation.invert = d3_geo_forwardRotationλ(-δλ); + return rotation; + } + function d3_geo_rotationφγ(δφ, δγ) { + var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); + function rotation(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; + return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; + } + rotation.invert = function(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; + return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; + }; + return rotation; + } + d3.geo.circle = function() { + var origin = [ 0, 0 ], angle, precision = 6, interpolate; + function circle() { + var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; + interpolate(null, null, 1, { + point: function(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= d3_degrees, x[1] *= d3_degrees; + } + }); + return { + type: "Polygon", + coordinates: [ ring ] + }; + } + circle.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return circle; + }; + circle.angle = function(x) { + if (!arguments.length) return angle; + interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); + return circle; + }; + circle.precision = function(_) { + if (!arguments.length) return precision; + interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); + return circle; + }; + return circle.angle(90); + }; + function d3_geo_circleInterpolate(radius, precision) { + var cr = Math.cos(radius), sr = Math.sin(radius); + return function(from, to, direction, listener) { + var step = direction * precision; + if (from != null) { + from = d3_geo_circleAngle(cr, from); + to = d3_geo_circleAngle(cr, to); + if (direction > 0 ? from < to : from > to) from += direction * τ; + } else { + from = radius + direction * τ; + to = radius - .5 * step; + } + for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { + listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); + } + }; + } + function d3_geo_circleAngle(cr, point) { + var a = d3_geo_cartesian(point); + a[0] -= cr; + d3_geo_cartesianNormalize(a); + var angle = d3_acos(-a[1]); + return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); + } + d3.geo.distance = function(a, b) { + var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; + return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); + }; + d3.geo.graticule = function() { + var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; + function graticule() { + return { + type: "MultiLineString", + coordinates: lines() + }; + } + function lines() { + return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { + return abs(x % DX) > ε; + }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { + return abs(y % DY) > ε; + }).map(y)); + } + graticule.lines = function() { + return lines().map(function(coordinates) { + return { + type: "LineString", + coordinates: coordinates + }; + }); + }; + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] + }; + }; + graticule.extent = function(_) { + if (!arguments.length) return graticule.minorExtent(); + return graticule.majorExtent(_).minorExtent(_); + }; + graticule.majorExtent = function(_) { + if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + graticule.minorExtent = function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + graticule.step = function(_) { + if (!arguments.length) return graticule.minorStep(); + return graticule.majorStep(_).minorStep(_); + }; + graticule.majorStep = function(_) { + if (!arguments.length) return [ DX, DY ]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + graticule.minorStep = function(_) { + if (!arguments.length) return [ dx, dy ]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = d3_geo_graticuleX(y0, y1, 90); + y = d3_geo_graticuleY(x0, x1, precision); + X = d3_geo_graticuleX(Y0, Y1, 90); + Y = d3_geo_graticuleY(X0, X1, precision); + return graticule; + }; + return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); + }; + function d3_geo_graticuleX(y0, y1, dy) { + var y = d3.range(y0, y1 - ε, dy).concat(y1); + return function(x) { + return y.map(function(y) { + return [ x, y ]; + }); + }; + } + function d3_geo_graticuleY(x0, x1, dx) { + var x = d3.range(x0, x1 - ε, dx).concat(x1); + return function(y) { + return x.map(function(x) { + return [ x, y ]; + }); + }; + } + function d3_source(d) { + return d.source; + } + function d3_target(d) { + return d.target; + } + d3.geo.greatArc = function() { + var source = d3_source, source_, target = d3_target, target_; + function greatArc() { + return { + type: "LineString", + coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] + }; + } + greatArc.distance = function() { + return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); + }; + greatArc.source = function(_) { + if (!arguments.length) return source; + source = _, source_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.target = function(_) { + if (!arguments.length) return target; + target = _, target_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.precision = function() { + return arguments.length ? greatArc : 0; + }; + return greatArc; + }; + d3.geo.interpolate = function(source, target) { + return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); + }; + function d3_geo_interpolate(x0, y0, x1, y1) { + var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); + var interpolate = d ? function(t) { + var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; + return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; + } : function() { + return [ x0 * d3_degrees, y0 * d3_degrees ]; + }; + interpolate.distance = d; + return interpolate; + } + d3.geo.length = function(object) { + d3_geo_lengthSum = 0; + d3.geo.stream(object, d3_geo_length); + return d3_geo_lengthSum; + }; + var d3_geo_lengthSum; + var d3_geo_length = { + sphere: d3_noop, + point: d3_noop, + lineStart: d3_geo_lengthLineStart, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_lengthLineStart() { + var λ0, sinφ0, cosφ0; + d3_geo_length.point = function(λ, φ) { + λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); + d3_geo_length.point = nextPoint; + }; + d3_geo_length.lineEnd = function() { + d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; + }; + function nextPoint(λ, φ) { + var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); + d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; + } + } + function d3_geo_azimuthal(scale, angle) { + function azimuthal(λ, φ) { + var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); + return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; + } + azimuthal.invert = function(x, y) { + var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); + return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; + }; + return azimuthal; + } + var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { + return Math.sqrt(2 / (1 + cosλcosφ)); + }, function(ρ) { + return 2 * Math.asin(ρ / 2); + }); + (d3.geo.azimuthalEqualArea = function() { + return d3_geo_projection(d3_geo_azimuthalEqualArea); + }).raw = d3_geo_azimuthalEqualArea; + var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { + var c = Math.acos(cosλcosφ); + return c && c / Math.sin(c); + }, d3_identity); + (d3.geo.azimuthalEquidistant = function() { + return d3_geo_projection(d3_geo_azimuthalEquidistant); + }).raw = d3_geo_azimuthalEquidistant; + function d3_geo_conicConformal(φ0, φ1) { + var cosφ0 = Math.cos(φ0), t = function(φ) { + return Math.tan(π / 4 + φ / 2); + }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; + if (!n) return d3_geo_mercator; + function forward(λ, φ) { + if (F > 0) { + if (φ < -halfπ + ε) φ = -halfπ + ε; + } else { + if (φ > halfπ - ε) φ = halfπ - ε; + } + var ρ = F / Math.pow(t(φ), n); + return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); + return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; + }; + return forward; + } + (d3.geo.conicConformal = function() { + return d3_geo_conic(d3_geo_conicConformal); + }).raw = d3_geo_conicConformal; + function d3_geo_conicEquidistant(φ0, φ1) { + var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; + if (abs(n) < ε) return d3_geo_equirectangular; + function forward(λ, φ) { + var ρ = G - φ; + return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var ρ0_y = G - y; + return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; + }; + return forward; + } + (d3.geo.conicEquidistant = function() { + return d3_geo_conic(d3_geo_conicEquidistant); + }).raw = d3_geo_conicEquidistant; + var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / cosλcosφ; + }, Math.atan); + (d3.geo.gnomonic = function() { + return d3_geo_projection(d3_geo_gnomonic); + }).raw = d3_geo_gnomonic; + function d3_geo_mercator(λ, φ) { + return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; + } + d3_geo_mercator.invert = function(x, y) { + return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; + }; + function d3_geo_mercatorProjection(project) { + var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; + m.scale = function() { + var v = scale.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.translate = function() { + var v = translate.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.clipExtent = function(_) { + var v = clipExtent.apply(m, arguments); + if (v === m) { + if (clipAuto = _ == null) { + var k = π * scale(), t = translate(); + clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); + } + } else if (clipAuto) { + v = null; + } + return v; + }; + return m.clipExtent(null); + } + (d3.geo.mercator = function() { + return d3_geo_mercatorProjection(d3_geo_mercator); + }).raw = d3_geo_mercator; + var d3_geo_orthographic = d3_geo_azimuthal(function() { + return 1; + }, Math.asin); + (d3.geo.orthographic = function() { + return d3_geo_projection(d3_geo_orthographic); + }).raw = d3_geo_orthographic; + var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / (1 + cosλcosφ); + }, function(ρ) { + return 2 * Math.atan(ρ); + }); + (d3.geo.stereographic = function() { + return d3_geo_projection(d3_geo_stereographic); + }).raw = d3_geo_stereographic; + function d3_geo_transverseMercator(λ, φ) { + return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; + } + d3_geo_transverseMercator.invert = function(x, y) { + return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; + }; + (d3.geo.transverseMercator = function() { + var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; + projection.center = function(_) { + return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); + }; + projection.rotate = function(_) { + return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), + [ _[0], _[1], _[2] - 90 ]); + }; + return rotate([ 0, 0, 90 ]); + }).raw = d3_geo_transverseMercator; + d3.geom = {}; + function d3_geom_pointX(d) { + return d[0]; + } + function d3_geom_pointY(d) { + return d[1]; + } + d3.geom.hull = function(vertices) { + var x = d3_geom_pointX, y = d3_geom_pointY; + if (arguments.length) return hull(vertices); + function hull(data) { + if (data.length < 3) return []; + var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; + for (i = 0; i < n; i++) { + points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); + } + points.sort(d3_geom_hullOrder); + for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); + var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); + var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; + for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); + for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); + return polygon; + } + hull.x = function(_) { + return arguments.length ? (x = _, hull) : x; + }; + hull.y = function(_) { + return arguments.length ? (y = _, hull) : y; + }; + return hull; + }; + function d3_geom_hullUpper(points) { + var n = points.length, hull = [ 0, 1 ], hs = 2; + for (var i = 2; i < n; i++) { + while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; + hull[hs++] = i; + } + return hull.slice(0, hs); + } + function d3_geom_hullOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; + } + d3.geom.polygon = function(coordinates) { + d3_subclass(coordinates, d3_geom_polygonPrototype); + return coordinates; + }; + var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; + d3_geom_polygonPrototype.area = function() { + var i = -1, n = this.length, a, b = this[n - 1], area = 0; + while (++i < n) { + a = b; + b = this[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + return area * .5; + }; + d3_geom_polygonPrototype.centroid = function(k) { + var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; + if (!arguments.length) k = -1 / (6 * this.area()); + while (++i < n) { + a = b; + b = this[i]; + c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + return [ x * k, y * k ]; + }; + d3_geom_polygonPrototype.clip = function(subject) { + var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; + while (++i < n) { + input = subject.slice(); + subject.length = 0; + b = this[i]; + c = input[(m = input.length - closed) - 1]; + j = -1; + while (++j < m) { + d = input[j]; + if (d3_geom_polygonInside(d, a, b)) { + if (!d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + subject.push(d); + } else if (d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + c = d; + } + if (closed) subject.push(subject[0]); + a = b; + } + return subject; + }; + function d3_geom_polygonInside(p, a, b) { + return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); + } + function d3_geom_polygonIntersect(c, d, a, b) { + var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); + return [ x1 + ua * x21, y1 + ua * y21 ]; + } + function d3_geom_polygonClosed(coordinates) { + var a = coordinates[0], b = coordinates[coordinates.length - 1]; + return !(a[0] - b[0] || a[1] - b[1]); + } + var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; + function d3_geom_voronoiBeach() { + d3_geom_voronoiRedBlackNode(this); + this.edge = this.site = this.circle = null; + } + function d3_geom_voronoiCreateBeach(site) { + var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); + beach.site = site; + return beach; + } + function d3_geom_voronoiDetachBeach(beach) { + d3_geom_voronoiDetachCircle(beach); + d3_geom_voronoiBeaches.remove(beach); + d3_geom_voronoiBeachPool.push(beach); + d3_geom_voronoiRedBlackNode(beach); + } + function d3_geom_voronoiRemoveBeach(beach) { + var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { + x: x, + y: y + }, previous = beach.P, next = beach.N, disappearing = [ beach ]; + d3_geom_voronoiDetachBeach(beach); + var lArc = previous; + while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { + previous = lArc.P; + disappearing.unshift(lArc); + d3_geom_voronoiDetachBeach(lArc); + lArc = previous; + } + disappearing.unshift(lArc); + d3_geom_voronoiDetachCircle(lArc); + var rArc = next; + while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { + next = rArc.N; + disappearing.push(rArc); + d3_geom_voronoiDetachBeach(rArc); + rArc = next; + } + disappearing.push(rArc); + d3_geom_voronoiDetachCircle(rArc); + var nArcs = disappearing.length, iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiAddBeach(site) { + var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; + while (node) { + dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; + if (dxl > ε) node = node.L; else { + dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); + if (dxr > ε) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -ε) { + lArc = node.P; + rArc = node; + } else if (dxr > -ε) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + var newArc = d3_geom_voronoiCreateBeach(site); + d3_geom_voronoiBeaches.insert(lArc, newArc); + if (!lArc && !rArc) return; + if (lArc === rArc) { + d3_geom_voronoiDetachCircle(lArc); + rArc = d3_geom_voronoiCreateBeach(lArc.site); + d3_geom_voronoiBeaches.insert(newArc, rArc); + newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + return; + } + if (!rArc) { + newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + return; + } + d3_geom_voronoiDetachCircle(lArc); + d3_geom_voronoiDetachCircle(rArc); + var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { + x: (cy * hb - by * hc) / d + ax, + y: (bx * hc - cx * hb) / d + ay + }; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); + rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiLeftBreakPoint(arc, directrix) { + var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; + if (!pby2) return rfocx; + var lArc = arc.P; + if (!lArc) return -Infinity; + site = lArc.site; + var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; + if (!plby2) return lfocx; + var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + return (rfocx + lfocx) / 2; + } + function d3_geom_voronoiRightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); + var site = arc.site; + return site.y === directrix ? site.x : Infinity; + } + function d3_geom_voronoiCell(site) { + this.site = site; + this.edges = []; + } + d3_geom_voronoiCell.prototype.prepare = function() { + var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; + while (iHalfEdge--) { + edge = halfEdges[iHalfEdge].edge; + if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); + } + halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); + return halfEdges.length; + }; + function d3_geom_voronoiCloseCells(extent) { + var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; + while (iCell--) { + cell = cells[iCell]; + if (!cell || !cell.prepare()) continue; + halfEdges = cell.edges; + nHalfEdges = halfEdges.length; + iHalfEdge = 0; + while (iHalfEdge < nHalfEdges) { + end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; + start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; + if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { + halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { + x: x0, + y: abs(x2 - x0) < ε ? y2 : y1 + } : abs(y3 - y1) < ε && x1 - x3 > ε ? { + x: abs(y2 - y1) < ε ? x2 : x1, + y: y1 + } : abs(x3 - x1) < ε && y3 - y0 > ε ? { + x: x1, + y: abs(x2 - x1) < ε ? y2 : y0 + } : abs(y3 - y0) < ε && x3 - x0 > ε ? { + x: abs(y2 - y0) < ε ? x2 : x0, + y: y0 + } : null), cell.site, null)); + ++nHalfEdges; + } + } + } + } + function d3_geom_voronoiHalfEdgeOrder(a, b) { + return b.angle - a.angle; + } + function d3_geom_voronoiCircle() { + d3_geom_voronoiRedBlackNode(this); + this.x = this.y = this.arc = this.site = this.cy = null; + } + function d3_geom_voronoiAttachCircle(arc) { + var lArc = arc.P, rArc = arc.N; + if (!lArc || !rArc) return; + var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; + if (lSite === rSite) return; + var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; + var d = 2 * (ax * cy - ay * cx); + if (d >= -ε2) return; + var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; + var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = cy + Math.sqrt(x * x + y * y); + circle.cy = cy; + arc.circle = circle; + var before = null, node = d3_geom_voronoiCircles._; + while (node) { + if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { + if (node.L) node = node.L; else { + before = node.P; + break; + } + } else { + if (node.R) node = node.R; else { + before = node; + break; + } + } + } + d3_geom_voronoiCircles.insert(before, circle); + if (!before) d3_geom_voronoiFirstCircle = circle; + } + function d3_geom_voronoiDetachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; + d3_geom_voronoiCircles.remove(circle); + d3_geom_voronoiCirclePool.push(circle); + d3_geom_voronoiRedBlackNode(circle); + arc.circle = null; + } + } + function d3_geom_voronoiClipEdges(extent) { + var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; + while (i--) { + e = edges[i]; + if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { + e.a = e.b = null; + edges.splice(i, 1); + } + } + } + function d3_geom_voronoiConnectEdge(edge, extent) { + var vb = edge.b; + if (vb) return true; + var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!va) va = { + x: fx, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: fx, + y: y1 + }; + } else { + if (!va) va = { + x: fx, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: fx, + y: y0 + }; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!va) va = { + x: (y0 - fb) / fm, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: (y1 - fb) / fm, + y: y1 + }; + } else { + if (!va) va = { + x: (y1 - fb) / fm, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: (y0 - fb) / fm, + y: y0 + }; + } + } else { + if (ly < ry) { + if (!va) va = { + x: x0, + y: fm * x0 + fb + }; else if (va.x >= x1) return; + vb = { + x: x1, + y: fm * x1 + fb + }; + } else { + if (!va) va = { + x: x1, + y: fm * x1 + fb + }; else if (va.x < x0) return; + vb = { + x: x0, + y: fm * x0 + fb + }; + } + } + } + edge.a = va; + edge.b = vb; + return true; + } + function d3_geom_voronoiEdge(lSite, rSite) { + this.l = lSite; + this.r = rSite; + this.a = this.b = null; + } + function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, rSite); + d3_geom_voronoiEdges.push(edge); + if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); + if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); + d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); + d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); + return edge; + } + function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, null); + edge.a = va; + edge.b = vb; + d3_geom_voronoiEdges.push(edge); + return edge; + } + function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { + if (!edge.a && !edge.b) { + edge.a = vertex; + edge.l = lSite; + edge.r = rSite; + } else if (edge.l === rSite) { + edge.b = vertex; + } else { + edge.a = vertex; + } + } + function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { + var va = edge.a, vb = edge.b; + this.edge = edge; + this.site = lSite; + this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); + } + d3_geom_voronoiHalfEdge.prototype = { + start: function() { + return this.edge.l === this.site ? this.edge.a : this.edge.b; + }, + end: function() { + return this.edge.l === this.site ? this.edge.b : this.edge.a; + } + }; + function d3_geom_voronoiRedBlackTree() { + this._ = null; + } + function d3_geom_voronoiRedBlackNode(node) { + node.U = node.C = node.L = node.R = node.P = node.N = null; + } + d3_geom_voronoiRedBlackTree.prototype = { + insert: function(after, node) { + var parent, grandpa, uncle; + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = d3_geom_voronoiRedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + d3_geom_voronoiRedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + d3_geom_voronoiRedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + var parent = node.U, sibling, left = node.L, right = node.R, next, red; + if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); + if (parent) { + if (parent.L === node) parent.L = next; else parent.R = next; + } else { + this._ = next; + } + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + if (node) node.U = parent; + if (red) return; + if (node && node.C) { + node.C = false; + return; + } + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateRight(this, parent); + sibling = parent.L; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + d3_geom_voronoiRedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + if (node) node.C = false; + } + }; + function d3_geom_voronoiRedBlackRotateLeft(tree, node) { + var p = node, q = node.R, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; + } + function d3_geom_voronoiRedBlackRotateRight(tree, node) { + var p = node, q = node.L, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; + } + function d3_geom_voronoiRedBlackFirst(node) { + while (node.L) node = node.L; + return node; + } + function d3_geom_voronoi(sites, bbox) { + var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; + d3_geom_voronoiEdges = []; + d3_geom_voronoiCells = new Array(sites.length); + d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); + d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); + while (true) { + circle = d3_geom_voronoiFirstCircle; + if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { + if (site.x !== x0 || site.y !== y0) { + d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); + d3_geom_voronoiAddBeach(site); + x0 = site.x, y0 = site.y; + } + site = sites.pop(); + } else if (circle) { + d3_geom_voronoiRemoveBeach(circle.arc); + } else { + break; + } + } + if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); + var diagram = { + cells: d3_geom_voronoiCells, + edges: d3_geom_voronoiEdges + }; + d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; + return diagram; + } + function d3_geom_voronoiVertexOrder(a, b) { + return b.y - a.y || b.x - a.x; + } + d3.geom.voronoi = function(points) { + var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; + if (points) return voronoi(points); + function voronoi(data) { + var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; + d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { + var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { + var s = e.start(); + return [ s.x, s.y ]; + }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; + polygon.point = data[i]; + }); + return polygons; + } + function sites(data) { + return data.map(function(d, i) { + return { + x: Math.round(fx(d, i) / ε) * ε, + y: Math.round(fy(d, i) / ε) * ε, + i: i + }; + }); + } + voronoi.links = function(data) { + return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { + return edge.l && edge.r; + }).map(function(edge) { + return { + source: data[edge.l.i], + target: data[edge.r.i] + }; + }); + }; + voronoi.triangles = function(data) { + var triangles = []; + d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { + var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; + while (++j < m) { + e0 = e1; + s0 = s1; + e1 = edges[j].edge; + s1 = e1.l === site ? e1.r : e1.l; + if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { + triangles.push([ data[i], data[s0.i], data[s1.i] ]); + } + } + }); + return triangles; + }; + voronoi.x = function(_) { + return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; + }; + voronoi.y = function(_) { + return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; + }; + voronoi.clipExtent = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; + clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; + return voronoi; + }; + voronoi.size = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; + return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); + }; + return voronoi; + }; + var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; + function d3_geom_voronoiTriangleArea(a, b, c) { + return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); + } + d3.geom.delaunay = function(vertices) { + return d3.geom.voronoi().triangles(vertices); + }; + d3.geom.quadtree = function(points, x1, y1, x2, y2) { + var x = d3_geom_pointX, y = d3_geom_pointY, compat; + if (compat = arguments.length) { + x = d3_geom_quadtreeCompatX; + y = d3_geom_quadtreeCompatY; + if (compat === 3) { + y2 = y1; + x2 = x1; + y1 = x1 = 0; + } + return quadtree(points); + } + function quadtree(data) { + var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; + if (x1 != null) { + x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; + } else { + x2_ = y2_ = -(x1_ = y1_ = Infinity); + xs = [], ys = []; + n = data.length; + if (compat) for (i = 0; i < n; ++i) { + d = data[i]; + if (d.x < x1_) x1_ = d.x; + if (d.y < y1_) y1_ = d.y; + if (d.x > x2_) x2_ = d.x; + if (d.y > y2_) y2_ = d.y; + xs.push(d.x); + ys.push(d.y); + } else for (i = 0; i < n; ++i) { + var x_ = +fx(d = data[i], i), y_ = +fy(d, i); + if (x_ < x1_) x1_ = x_; + if (y_ < y1_) y1_ = y_; + if (x_ > x2_) x2_ = x_; + if (y_ > y2_) y2_ = y_; + xs.push(x_); + ys.push(y_); + } + } + var dx = x2_ - x1_, dy = y2_ - y1_; + if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; + function insert(n, d, x, y, x1, y1, x2, y2) { + if (isNaN(x) || isNaN(y)) return; + if (n.leaf) { + var nx = n.x, ny = n.y; + if (nx != null) { + if (abs(nx - x) + abs(ny - y) < .01) { + insertChild(n, d, x, y, x1, y1, x2, y2); + } else { + var nPoint = n.point; + n.x = n.y = n.point = null; + insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } else { + n.x = x, n.y = y, n.point = d; + } + } else { + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } + function insertChild(n, d, x, y, x1, y1, x2, y2) { + var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; + n.leaf = false; + n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); + if (right) x1 = xm; else x2 = xm; + if (below) y1 = ym; else y2 = ym; + insert(n, d, x, y, x1, y1, x2, y2); + } + var root = d3_geom_quadtreeNode(); + root.add = function(d) { + insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); + }; + root.visit = function(f) { + d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); + }; + root.find = function(point) { + return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); + }; + i = -1; + if (x1 == null) { + while (++i < n) { + insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); + } + --i; + } else data.forEach(root.add); + xs = ys = data = d = null; + return root; + } + quadtree.x = function(_) { + return arguments.length ? (x = _, quadtree) : x; + }; + quadtree.y = function(_) { + return arguments.length ? (y = _, quadtree) : y; + }; + quadtree.extent = function(_) { + if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], + y2 = +_[1][1]; + return quadtree; + }; + quadtree.size = function(_) { + if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; + return quadtree; + }; + return quadtree; + }; + function d3_geom_quadtreeCompatX(d) { + return d.x; + } + function d3_geom_quadtreeCompatY(d) { + return d.y; + } + function d3_geom_quadtreeNode() { + return { + leaf: true, + nodes: [], + point: null, + x: null, + y: null + }; + } + function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { + if (!f(node, x1, y1, x2, y2)) { + var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; + if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); + if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); + if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); + if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); + } + } + function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { + var minDistance2 = Infinity, closestPoint; + (function find(node, x1, y1, x2, y2) { + if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; + if (point = node.point) { + var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; + if (distance2 < minDistance2) { + var distance = Math.sqrt(minDistance2 = distance2); + x0 = x - distance, y0 = y - distance; + x3 = x + distance, y3 = y + distance; + closestPoint = point; + } + } + var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; + for (var i = below << 1 | right, j = i + 4; i < j; ++i) { + if (node = children[i & 3]) switch (i & 3) { + case 0: + find(node, x1, y1, xm, ym); + break; + + case 1: + find(node, xm, y1, x2, ym); + break; + + case 2: + find(node, x1, ym, xm, y2); + break; + + case 3: + find(node, xm, ym, x2, y2); + break; + } + } + })(root, x0, y0, x3, y3); + return closestPoint; + } + d3.interpolateRgb = d3_interpolateRgb; + function d3_interpolateRgb(a, b) { + a = d3.rgb(a); + b = d3.rgb(b); + var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; + return function(t) { + return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); + }; + } + d3.interpolateObject = d3_interpolateObject; + function d3_interpolateObject(a, b) { + var i = {}, c = {}, k; + for (k in a) { + if (k in b) { + i[k] = d3_interpolate(a[k], b[k]); + } else { + c[k] = a[k]; + } + } + for (k in b) { + if (!(k in a)) { + c[k] = b[k]; + } + } + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; + } + d3.interpolateNumber = d3_interpolateNumber; + function d3_interpolateNumber(a, b) { + a = +a, b = +b; + return function(t) { + return a * (1 - t) + b * t; + }; + } + d3.interpolateString = d3_interpolateString; + function d3_interpolateString(a, b) { + var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a = a + "", b = b + ""; + while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) s[i] += bm; else s[++i] = bm; + } else { + s[++i] = null; + q.push({ + i: i, + x: d3_interpolateNumber(am, bm) + }); + } + bi = d3_interpolate_numberB.lastIndex; + } + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { + return b(t) + ""; + }) : function() { + return b; + } : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); + d3.interpolate = d3_interpolate; + function d3_interpolate(a, b) { + var i = d3.interpolators.length, f; + while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; + return f; + } + d3.interpolators = [ function(a, b) { + var t = typeof b; + return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); + } ]; + d3.interpolateArray = d3_interpolateArray; + function d3_interpolateArray(a, b) { + var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; + for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); + for (;i < na; ++i) c[i] = a[i]; + for (;i < nb; ++i) c[i] = b[i]; + return function(t) { + for (i = 0; i < n0; ++i) c[i] = x[i](t); + return c; + }; + } + var d3_ease_default = function() { + return d3_identity; + }; + var d3_ease = d3.map({ + linear: d3_ease_default, + poly: d3_ease_poly, + quad: function() { + return d3_ease_quad; + }, + cubic: function() { + return d3_ease_cubic; + }, + sin: function() { + return d3_ease_sin; + }, + exp: function() { + return d3_ease_exp; + }, + circle: function() { + return d3_ease_circle; + }, + elastic: d3_ease_elastic, + back: d3_ease_back, + bounce: function() { + return d3_ease_bounce; + } + }); + var d3_ease_mode = d3.map({ + "in": d3_identity, + out: d3_ease_reverse, + "in-out": d3_ease_reflect, + "out-in": function(f) { + return d3_ease_reflect(d3_ease_reverse(f)); + } + }); + d3.ease = function(name) { + var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; + t = d3_ease.get(t) || d3_ease_default; + m = d3_ease_mode.get(m) || d3_identity; + return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); + }; + function d3_ease_clamp(f) { + return function(t) { + return t <= 0 ? 0 : t >= 1 ? 1 : f(t); + }; + } + function d3_ease_reverse(f) { + return function(t) { + return 1 - f(1 - t); + }; + } + function d3_ease_reflect(f) { + return function(t) { + return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); + }; + } + function d3_ease_quad(t) { + return t * t; + } + function d3_ease_cubic(t) { + return t * t * t; + } + function d3_ease_cubicInOut(t) { + if (t <= 0) return 0; + if (t >= 1) return 1; + var t2 = t * t, t3 = t2 * t; + return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); + } + function d3_ease_poly(e) { + return function(t) { + return Math.pow(t, e); + }; + } + function d3_ease_sin(t) { + return 1 - Math.cos(t * halfπ); + } + function d3_ease_exp(t) { + return Math.pow(2, 10 * (t - 1)); + } + function d3_ease_circle(t) { + return 1 - Math.sqrt(1 - t * t); + } + function d3_ease_elastic(a, p) { + var s; + if (arguments.length < 2) p = .45; + if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; + return function(t) { + return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); + }; + } + function d3_ease_back(s) { + if (!s) s = 1.70158; + return function(t) { + return t * t * ((s + 1) * t - s); + }; + } + function d3_ease_bounce(t) { + return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; + } + d3.interpolateHcl = d3_interpolateHcl; + function d3_interpolateHcl(a, b) { + a = d3.hcl(a); + b = d3.hcl(b); + var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; + if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; + }; + } + d3.interpolateHsl = d3_interpolateHsl; + function d3_interpolateHsl(a, b) { + a = d3.hsl(a); + b = d3.hsl(b); + var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; + if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; + }; + } + d3.interpolateLab = d3_interpolateLab; + function d3_interpolateLab(a, b) { + a = d3.lab(a); + b = d3.lab(b); + var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; + return function(t) { + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; + }; + } + d3.interpolateRound = d3_interpolateRound; + function d3_interpolateRound(a, b) { + b -= a; + return function(t) { + return Math.round(a + b * t); + }; + } + d3.transform = function(string) { + var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); + return (d3.transform = function(string) { + if (string != null) { + g.setAttribute("transform", string); + var t = g.transform.baseVal.consolidate(); + } + return new d3_transform(t ? t.matrix : d3_transformIdentity); + })(string); + }; + function d3_transform(m) { + var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; + if (r0[0] * r1[1] < r1[0] * r0[1]) { + r0[0] *= -1; + r0[1] *= -1; + kx *= -1; + kz *= -1; + } + this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; + this.translate = [ m.e, m.f ]; + this.scale = [ kx, ky ]; + this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; + } + d3_transform.prototype.toString = function() { + return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; + }; + function d3_transformDot(a, b) { + return a[0] * b[0] + a[1] * b[1]; + } + function d3_transformNormalize(a) { + var k = Math.sqrt(d3_transformDot(a, a)); + if (k) { + a[0] /= k; + a[1] /= k; + } + return k; + } + function d3_transformCombine(a, b, k) { + a[0] += k * b[0]; + a[1] += k * b[1]; + return a; + } + var d3_transformIdentity = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 + }; + d3.interpolateTransform = d3_interpolateTransform; + function d3_interpolateTransformPop(s) { + return s.length ? s.pop() + "," : ""; + } + function d3_interpolateTranslate(ta, tb, s, q) { + if (ta[0] !== tb[0] || ta[1] !== tb[1]) { + var i = s.push("translate(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ta[0], tb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ta[1], tb[1]) + }); + } else if (tb[0] || tb[1]) { + s.push("translate(" + tb + ")"); + } + } + function d3_interpolateRotate(ra, rb, s, q) { + if (ra !== rb) { + if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, + x: d3_interpolateNumber(ra, rb) + }); + } else if (rb) { + s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); + } + } + function d3_interpolateSkew(wa, wb, s, q) { + if (wa !== wb) { + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, + x: d3_interpolateNumber(wa, wb) + }); + } else if (wb) { + s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); + } + } + function d3_interpolateScale(ka, kb, s, q) { + if (ka[0] !== kb[0] || ka[1] !== kb[1]) { + var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ka[0], kb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ka[1], kb[1]) + }); + } else if (kb[0] !== 1 || kb[1] !== 1) { + s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); + } + } + function d3_interpolateTransform(a, b) { + var s = [], q = []; + a = d3.transform(a), b = d3.transform(b); + d3_interpolateTranslate(a.translate, b.translate, s, q); + d3_interpolateRotate(a.rotate, b.rotate, s, q); + d3_interpolateSkew(a.skew, b.skew, s, q); + d3_interpolateScale(a.scale, b.scale, s, q); + a = b = null; + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + } + function d3_uninterpolateNumber(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return (x - a) / b; + }; + } + function d3_uninterpolateClamp(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return Math.max(0, Math.min(1, (x - a) / b)); + }; + } + d3.layout = {}; + d3.layout.bundle = function() { + return function(links) { + var paths = [], i = -1, n = links.length; + while (++i < n) paths.push(d3_layout_bundlePath(links[i])); + return paths; + }; + }; + function d3_layout_bundlePath(link) { + var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; + while (start !== lca) { + start = start.parent; + points.push(start); + } + var k = points.length; + while (end !== lca) { + points.splice(k, 0, end); + end = end.parent; + } + return points; + } + function d3_layout_bundleAncestors(node) { + var ancestors = [], parent = node.parent; + while (parent != null) { + ancestors.push(node); + node = parent; + parent = parent.parent; + } + ancestors.push(node); + return ancestors; + } + function d3_layout_bundleLeastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; + while (aNode === bNode) { + sharedNode = aNode; + aNode = aNodes.pop(); + bNode = bNodes.pop(); + } + return sharedNode; + } + d3.layout.chord = function() { + var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; + function relayout() { + var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; + chords = []; + groups = []; + k = 0, i = -1; + while (++i < n) { + x = 0, j = -1; + while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(d3.range(n)); + k += x; + } + if (sortGroups) { + groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + } + if (sortSubgroups) { + subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + } + k = (τ - padding * n) / k; + x = 0, i = -1; + while (++i < n) { + x0 = x, j = -1; + while (++j < n) { + var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; + subgroups[di + "-" + dj] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += padding; + } + i = -1; + while (++i < n) { + j = i - 1; + while (++j < n) { + var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; + if (source.value || target.value) { + chords.push(source.value < target.value ? { + source: target, + target: source + } : { + source: source, + target: target + }); + } + } + } + if (sortChords) resort(); + } + function resort() { + chords.sort(function(a, b) { + return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); + }); + } + chord.matrix = function(x) { + if (!arguments.length) return matrix; + n = (matrix = x) && matrix.length; + chords = groups = null; + return chord; + }; + chord.padding = function(x) { + if (!arguments.length) return padding; + padding = x; + chords = groups = null; + return chord; + }; + chord.sortGroups = function(x) { + if (!arguments.length) return sortGroups; + sortGroups = x; + chords = groups = null; + return chord; + }; + chord.sortSubgroups = function(x) { + if (!arguments.length) return sortSubgroups; + sortSubgroups = x; + chords = null; + return chord; + }; + chord.sortChords = function(x) { + if (!arguments.length) return sortChords; + sortChords = x; + if (chords) resort(); + return chord; + }; + chord.chords = function() { + if (!chords) relayout(); + return chords; + }; + chord.groups = function() { + if (!groups) relayout(); + return groups; + }; + return chord; + }; + d3.layout.force = function() { + var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; + function repulse(node) { + return function(quad, x1, _, x2) { + if (quad.point !== node) { + var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; + if (dw * dw / theta2 < dn) { + if (dn < chargeDistance2) { + var k = quad.charge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + return true; + } + if (quad.point && dn && dn < chargeDistance2) { + var k = quad.pointCharge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + } + return !quad.charge; + }; + } + force.tick = function() { + if ((alpha *= .99) < .005) { + timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + return true; + } + var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; + for (i = 0; i < m; ++i) { + o = links[i]; + s = o.source; + t = o.target; + x = t.x - s.x; + y = t.y - s.y; + if (l = x * x + y * y) { + l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; + x *= l; + y *= l; + t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; + } + } + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; + if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } + } + if (charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); + i = -1; + while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o)); + } + } + } + i = -1; + while (++i < n) { + o = nodes[i]; + if (o.fixed) { + o.x = o.px; + o.y = o.py; + } else { + o.x -= (o.px - (o.px = o.x)) * friction; + o.y -= (o.py - (o.py = o.y)) * friction; + } + } + event.tick({ + type: "tick", + alpha: alpha + }); + }; + force.nodes = function(x) { + if (!arguments.length) return nodes; + nodes = x; + return force; + }; + force.links = function(x) { + if (!arguments.length) return links; + links = x; + return force; + }; + force.size = function(x) { + if (!arguments.length) return size; + size = x; + return force; + }; + force.linkDistance = function(x) { + if (!arguments.length) return linkDistance; + linkDistance = typeof x === "function" ? x : +x; + return force; + }; + force.distance = force.linkDistance; + force.linkStrength = function(x) { + if (!arguments.length) return linkStrength; + linkStrength = typeof x === "function" ? x : +x; + return force; + }; + force.friction = function(x) { + if (!arguments.length) return friction; + friction = +x; + return force; + }; + force.charge = function(x) { + if (!arguments.length) return charge; + charge = typeof x === "function" ? x : +x; + return force; + }; + force.chargeDistance = function(x) { + if (!arguments.length) return Math.sqrt(chargeDistance2); + chargeDistance2 = x * x; + return force; + }; + force.gravity = function(x) { + if (!arguments.length) return gravity; + gravity = +x; + return force; + }; + force.theta = function(x) { + if (!arguments.length) return Math.sqrt(theta2); + theta2 = x * x; + return force; + }; + force.alpha = function(x) { + if (!arguments.length) return alpha; + x = +x; + if (alpha) { + if (x > 0) { + alpha = x; + } else { + timer.c = null, timer.t = NaN, timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + } + } else if (x > 0) { + event.start({ + type: "start", + alpha: alpha = x + }); + timer = d3_timer(force.tick); + } + return force; + }; + force.start = function() { + var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; + for (i = 0; i < n; ++i) { + (o = nodes[i]).index = i; + o.weight = 0; + } + for (i = 0; i < m; ++i) { + o = links[i]; + if (typeof o.source == "number") o.source = nodes[o.source]; + if (typeof o.target == "number") o.target = nodes[o.target]; + ++o.source.weight; + ++o.target.weight; + } + for (i = 0; i < n; ++i) { + o = nodes[i]; + if (isNaN(o.x)) o.x = position("x", w); + if (isNaN(o.y)) o.y = position("y", h); + if (isNaN(o.px)) o.px = o.x; + if (isNaN(o.py)) o.py = o.y; + } + distances = []; + if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; + strengths = []; + if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; + charges = []; + if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; + function position(dimension, size) { + if (!neighbors) { + neighbors = new Array(n); + for (j = 0; j < n; ++j) { + neighbors[j] = []; + } + for (j = 0; j < m; ++j) { + var o = links[j]; + neighbors[o.source.index].push(o.target); + neighbors[o.target.index].push(o.source); + } + } + var candidates = neighbors[i], j = -1, l = candidates.length, x; + while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; + return Math.random() * size; + } + return force.resume(); + }; + force.resume = function() { + return force.alpha(.1); + }; + force.stop = function() { + return force.alpha(0); + }; + force.drag = function() { + if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); + if (!arguments.length) return drag; + this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); + }; + function dragmove(d) { + d.px = d3.event.x, d.py = d3.event.y; + force.resume(); + } + return d3.rebind(force, event, "on"); + }; + function d3_layout_forceDragstart(d) { + d.fixed |= 2; + } + function d3_layout_forceDragend(d) { + d.fixed &= ~6; + } + function d3_layout_forceMouseover(d) { + d.fixed |= 4; + d.px = d.x, d.py = d.y; + } + function d3_layout_forceMouseout(d) { + d.fixed &= ~4; + } + function d3_layout_forceAccumulate(quad, alpha, charges) { + var cx = 0, cy = 0; + quad.charge = 0; + if (!quad.leaf) { + var nodes = quad.nodes, n = nodes.length, i = -1, c; + while (++i < n) { + c = nodes[i]; + if (c == null) continue; + d3_layout_forceAccumulate(c, alpha, charges); + quad.charge += c.charge; + cx += c.charge * c.cx; + cy += c.charge * c.cy; + } + } + if (quad.point) { + if (!quad.leaf) { + quad.point.x += Math.random() - .5; + quad.point.y += Math.random() - .5; + } + var k = alpha * charges[quad.point.index]; + quad.charge += quad.pointCharge = k; + cx += k * quad.point.x; + cy += k * quad.point.y; + } + quad.cx = cx / quad.charge; + quad.cy = cy / quad.charge; + } + var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; + d3.layout.hierarchy = function() { + var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; + function hierarchy(root) { + var stack = [ root ], nodes = [], node; + root.depth = 0; + while ((node = stack.pop()) != null) { + nodes.push(node); + if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { + var n, childs, child; + while (--n >= 0) { + stack.push(child = childs[n]); + child.parent = node; + child.depth = node.depth + 1; + } + if (value) node.value = 0; + node.children = childs; + } else { + if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; + delete node.children; + } + } + d3_layout_hierarchyVisitAfter(root, function(node) { + var childs, parent; + if (sort && (childs = node.children)) childs.sort(sort); + if (value && (parent = node.parent)) parent.value += node.value; + }); + return nodes; + } + hierarchy.sort = function(x) { + if (!arguments.length) return sort; + sort = x; + return hierarchy; + }; + hierarchy.children = function(x) { + if (!arguments.length) return children; + children = x; + return hierarchy; + }; + hierarchy.value = function(x) { + if (!arguments.length) return value; + value = x; + return hierarchy; + }; + hierarchy.revalue = function(root) { + if (value) { + d3_layout_hierarchyVisitBefore(root, function(node) { + if (node.children) node.value = 0; + }); + d3_layout_hierarchyVisitAfter(root, function(node) { + var parent; + if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; + if (parent = node.parent) parent.value += node.value; + }); + } + return root; + }; + return hierarchy; + }; + function d3_layout_hierarchyRebind(object, hierarchy) { + d3.rebind(object, hierarchy, "sort", "children", "value"); + object.nodes = object; + object.links = d3_layout_hierarchyLinks; + return object; + } + function d3_layout_hierarchyVisitBefore(node, callback) { + var nodes = [ node ]; + while ((node = nodes.pop()) != null) { + callback(node); + if ((children = node.children) && (n = children.length)) { + var n, children; + while (--n >= 0) nodes.push(children[n]); + } + } + } + function d3_layout_hierarchyVisitAfter(node, callback) { + var nodes = [ node ], nodes2 = []; + while ((node = nodes.pop()) != null) { + nodes2.push(node); + if ((children = node.children) && (n = children.length)) { + var i = -1, n, children; + while (++i < n) nodes.push(children[i]); + } + } + while ((node = nodes2.pop()) != null) { + callback(node); + } + } + function d3_layout_hierarchyChildren(d) { + return d.children; + } + function d3_layout_hierarchyValue(d) { + return d.value; + } + function d3_layout_hierarchySort(a, b) { + return b.value - a.value; + } + function d3_layout_hierarchyLinks(nodes) { + return d3.merge(nodes.map(function(parent) { + return (parent.children || []).map(function(child) { + return { + source: parent, + target: child + }; + }); + })); + } + d3.layout.partition = function() { + var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; + function position(node, x, dx, dy) { + var children = node.children; + node.x = x; + node.y = node.depth * dy; + node.dx = dx; + node.dy = dy; + if (children && (n = children.length)) { + var i = -1, n, c, d; + dx = node.value ? dx / node.value : 0; + while (++i < n) { + position(c = children[i], x, d = c.value * dx, dy); + x += d; + } + } + } + function depth(node) { + var children = node.children, d = 0; + if (children && (n = children.length)) { + var i = -1, n; + while (++i < n) d = Math.max(d, depth(children[i])); + } + return 1 + d; + } + function partition(d, i) { + var nodes = hierarchy.call(this, d, i); + position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); + return nodes; + } + partition.size = function(x) { + if (!arguments.length) return size; + size = x; + return partition; + }; + return d3_layout_hierarchyRebind(partition, hierarchy); + }; + d3.layout.pie = function() { + var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; + function pie(data) { + var n = data.length, values = data.map(function(d, i) { + return +value.call(pie, d, i); + }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; + if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { + return values[j] - values[i]; + } : function(i, j) { + return sort(data[i], data[j]); + }); + index.forEach(function(i) { + arcs[i] = { + data: data[i], + value: v = values[i], + startAngle: a, + endAngle: a += v * k + pa, + padAngle: p + }; + }); + return arcs; + } + pie.value = function(_) { + if (!arguments.length) return value; + value = _; + return pie; + }; + pie.sort = function(_) { + if (!arguments.length) return sort; + sort = _; + return pie; + }; + pie.startAngle = function(_) { + if (!arguments.length) return startAngle; + startAngle = _; + return pie; + }; + pie.endAngle = function(_) { + if (!arguments.length) return endAngle; + endAngle = _; + return pie; + }; + pie.padAngle = function(_) { + if (!arguments.length) return padAngle; + padAngle = _; + return pie; + }; + return pie; + }; + var d3_layout_pieSortByValue = {}; + d3.layout.stack = function() { + var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; + function stack(data, index) { + if (!(n = data.length)) return data; + var series = data.map(function(d, i) { + return values.call(stack, d, i); + }); + var points = series.map(function(d) { + return d.map(function(v, i) { + return [ x.call(stack, v, i), y.call(stack, v, i) ]; + }); + }); + var orders = order.call(stack, points, index); + series = d3.permute(series, orders); + points = d3.permute(points, orders); + var offsets = offset.call(stack, points, index); + var m = series[0].length, n, i, j, o; + for (j = 0; j < m; ++j) { + out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); + for (i = 1; i < n; ++i) { + out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); + } + } + return data; + } + stack.values = function(x) { + if (!arguments.length) return values; + values = x; + return stack; + }; + stack.order = function(x) { + if (!arguments.length) return order; + order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; + return stack; + }; + stack.offset = function(x) { + if (!arguments.length) return offset; + offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; + return stack; + }; + stack.x = function(z) { + if (!arguments.length) return x; + x = z; + return stack; + }; + stack.y = function(z) { + if (!arguments.length) return y; + y = z; + return stack; + }; + stack.out = function(z) { + if (!arguments.length) return out; + out = z; + return stack; + }; + return stack; + }; + function d3_layout_stackX(d) { + return d.x; + } + function d3_layout_stackY(d) { + return d.y; + } + function d3_layout_stackOut(d, y0, y) { + d.y0 = y0; + d.y = y; + } + var d3_layout_stackOrders = d3.map({ + "inside-out": function(data) { + var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { + return max[a] - max[b]; + }), top = 0, bottom = 0, tops = [], bottoms = []; + for (i = 0; i < n; ++i) { + j = index[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + return bottoms.reverse().concat(tops); + }, + reverse: function(data) { + return d3.range(data.length).reverse(); + }, + "default": d3_layout_stackOrderDefault + }); + var d3_layout_stackOffsets = d3.map({ + silhouette: function(data) { + var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o > max) max = o; + sums.push(o); + } + for (j = 0; j < m; ++j) { + y0[j] = (max - sums[j]) / 2; + } + return y0; + }, + wiggle: function(data) { + var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; + y0[0] = o = o0 = 0; + for (j = 1; j < m; ++j) { + for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; + for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { + for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { + s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; + } + s2 += s3 * data[i][j][1]; + } + y0[j] = o -= s1 ? s2 / s1 * dx : 0; + if (o < o0) o0 = o; + } + for (j = 0; j < m; ++j) y0[j] -= o0; + return y0; + }, + expand: function(data) { + var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }, + zero: d3_layout_stackOffsetZero + }); + function d3_layout_stackOrderDefault(data) { + return d3.range(data.length); + } + function d3_layout_stackOffsetZero(data) { + var j = -1, m = data[0].length, y0 = []; + while (++j < m) y0[j] = 0; + return y0; + } + function d3_layout_stackMaxIndex(array) { + var i = 1, j = 0, v = array[0][1], k, n = array.length; + for (;i < n; ++i) { + if ((k = array[i][1]) > v) { + j = i; + v = k; + } + } + return j; + } + function d3_layout_stackReduceSum(d) { + return d.reduce(d3_layout_stackSum, 0); + } + function d3_layout_stackSum(p, d) { + return p + d[1]; + } + d3.layout.histogram = function() { + var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; + function histogram(data, i) { + var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; + while (++i < m) { + bin = bins[i] = []; + bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); + bin.y = 0; + } + if (m > 0) { + i = -1; + while (++i < n) { + x = values[i]; + if (x >= range[0] && x <= range[1]) { + bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; + bin.y += k; + bin.push(data[i]); + } + } + } + return bins; + } + histogram.value = function(x) { + if (!arguments.length) return valuer; + valuer = x; + return histogram; + }; + histogram.range = function(x) { + if (!arguments.length) return ranger; + ranger = d3_functor(x); + return histogram; + }; + histogram.bins = function(x) { + if (!arguments.length) return binner; + binner = typeof x === "number" ? function(range) { + return d3_layout_histogramBinFixed(range, x); + } : d3_functor(x); + return histogram; + }; + histogram.frequency = function(x) { + if (!arguments.length) return frequency; + frequency = !!x; + return histogram; + }; + return histogram; + }; + function d3_layout_histogramBinSturges(range, values) { + return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); + } + function d3_layout_histogramBinFixed(range, n) { + var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; + while (++x <= n) f[x] = m * x + b; + return f; + } + function d3_layout_histogramRange(values) { + return [ d3.min(values), d3.max(values) ]; + } + d3.layout.pack = function() { + var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; + function pack(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { + return radius; + }; + root.x = root.y = 0; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r = +r(d.value); + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + if (padding) { + var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r += dr; + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r -= dr; + }); + } + d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); + return nodes; + } + pack.size = function(_) { + if (!arguments.length) return size; + size = _; + return pack; + }; + pack.radius = function(_) { + if (!arguments.length) return radius; + radius = _ == null || typeof _ === "function" ? _ : +_; + return pack; + }; + pack.padding = function(_) { + if (!arguments.length) return padding; + padding = +_; + return pack; + }; + return d3_layout_hierarchyRebind(pack, hierarchy); + }; + function d3_layout_packSort(a, b) { + return a.value - b.value; + } + function d3_layout_packInsert(a, b) { + var c = a._pack_next; + a._pack_next = b; + b._pack_prev = a; + b._pack_next = c; + c._pack_prev = b; + } + function d3_layout_packSplice(a, b) { + a._pack_next = b; + b._pack_prev = a; + } + function d3_layout_packIntersects(a, b) { + var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; + return .999 * dr * dr > dx * dx + dy * dy; + } + function d3_layout_packSiblings(node) { + if (!(nodes = node.children) || !(n = nodes.length)) return; + var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; + function bound(node) { + xMin = Math.min(node.x - node.r, xMin); + xMax = Math.max(node.x + node.r, xMax); + yMin = Math.min(node.y - node.r, yMin); + yMax = Math.max(node.y + node.r, yMax); + } + nodes.forEach(d3_layout_packLink); + a = nodes[0]; + a.x = -a.r; + a.y = 0; + bound(a); + if (n > 1) { + b = nodes[1]; + b.x = b.r; + b.y = 0; + bound(b); + if (n > 2) { + c = nodes[2]; + d3_layout_packPlace(a, b, c); + bound(c); + d3_layout_packInsert(a, c); + a._pack_prev = c; + d3_layout_packInsert(c, b); + b = a._pack_next; + for (i = 3; i < n; i++) { + d3_layout_packPlace(a, b, c = nodes[i]); + var isect = 0, s1 = 1, s2 = 1; + for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { + if (d3_layout_packIntersects(j, c)) { + isect = 1; + break; + } + } + if (isect == 1) { + for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { + if (d3_layout_packIntersects(k, c)) { + break; + } + } + } + if (isect) { + if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); + i--; + } else { + d3_layout_packInsert(a, c); + b = c; + bound(c); + } + } + } + } + var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; + for (i = 0; i < n; i++) { + c = nodes[i]; + c.x -= cx; + c.y -= cy; + cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); + } + node.r = cr; + nodes.forEach(d3_layout_packUnlink); + } + function d3_layout_packLink(node) { + node._pack_next = node._pack_prev = node; + } + function d3_layout_packUnlink(node) { + delete node._pack_next; + delete node._pack_prev; + } + function d3_layout_packTransform(node, x, y, k) { + var children = node.children; + node.x = x += k * node.x; + node.y = y += k * node.y; + node.r *= k; + if (children) { + var i = -1, n = children.length; + while (++i < n) d3_layout_packTransform(children[i], x, y, k); + } + } + function d3_layout_packPlace(a, b, c) { + var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; + if (db && (dx || dy)) { + var da = b.r + c.r, dc = dx * dx + dy * dy; + da *= da; + db *= db; + var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = a.x + x * dx + y * dy; + c.y = a.y + x * dy - y * dx; + } else { + c.x = a.x + db; + c.y = a.y; + } + } + d3.layout.tree = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; + function tree(d, i) { + var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); + d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; + d3_layout_hierarchyVisitBefore(root1, secondWalk); + if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { + var left = root0, right = root0, bottom = root0; + d3_layout_hierarchyVisitBefore(root0, function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); + d3_layout_hierarchyVisitBefore(root0, function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + return nodes; + } + function wrapTree(root0) { + var root1 = { + A: null, + children: [ root0 ] + }, queue = [ root1 ], node1; + while ((node1 = queue.pop()) != null) { + for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { + queue.push((children[i] = child = { + _: children[i], + parent: node1, + children: (child = children[i].children) && child.slice() || [], + A: null, + a: null, + z: 0, + m: 0, + c: 0, + s: 0, + t: null, + i: i + }).a = child); + } + } + return root1.children[0]; + } + function firstWalk(v) { + var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; + if (children.length) { + d3_layout_treeShift(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + function apportion(v, w, ancestor) { + if (w) { + var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; + while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { + vom = d3_layout_treeLeft(vom); + vop = d3_layout_treeRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !d3_layout_treeRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !d3_layout_treeLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + function sizeNode(node) { + node.x *= size[0]; + node.y = node.depth * size[1]; + } + tree.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return tree; + }; + tree.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null ? sizeNode : null; + return tree; + }; + tree.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) == null ? null : sizeNode; + return tree; + }; + return d3_layout_hierarchyRebind(tree, hierarchy); + }; + function d3_layout_treeSeparation(a, b) { + return a.parent == b.parent ? 1 : 2; + } + function d3_layout_treeLeft(v) { + var children = v.children; + return children.length ? children[0] : v.t; + } + function d3_layout_treeRight(v) { + var children = v.children, n; + return (n = children.length) ? children[n - 1] : v.t; + } + function d3_layout_treeMove(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; + } + function d3_layout_treeShift(v) { + var shift = 0, change = 0, children = v.children, i = children.length, w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } + } + function d3_layout_treeAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; + } + d3.layout.cluster = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; + function cluster(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; + d3_layout_hierarchyVisitAfter(root, function(node) { + var children = node.children; + if (children && children.length) { + node.x = d3_layout_clusterX(children); + node.y = d3_layout_clusterY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; + d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { + node.x = (node.x - root.x) * size[0]; + node.y = (root.y - node.y) * size[1]; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * size[0]; + node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; + }); + return nodes; + } + cluster.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return cluster; + }; + cluster.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null; + return cluster; + }; + cluster.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) != null; + return cluster; + }; + return d3_layout_hierarchyRebind(cluster, hierarchy); + }; + function d3_layout_clusterY(children) { + return 1 + d3.max(children, function(child) { + return child.y; + }); + } + function d3_layout_clusterX(children) { + return children.reduce(function(x, child) { + return x + child.x; + }, 0) / children.length; + } + function d3_layout_clusterLeft(node) { + var children = node.children; + return children && children.length ? d3_layout_clusterLeft(children[0]) : node; + } + function d3_layout_clusterRight(node) { + var children = node.children, n; + return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; + } + d3.layout.treemap = function() { + var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); + function scale(children, k) { + var i = -1, n = children.length, child, area; + while (++i < n) { + area = (child = children[i]).value * (k < 0 ? 0 : k); + child.area = isNaN(area) || area <= 0 ? 0 : area; + } + } + function squarify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while ((n = remaining.length) > 0) { + row.push(child = remaining[n - 1]); + row.area += child.area; + if (mode !== "squarify" || (score = worst(row, u)) <= best) { + remaining.pop(); + best = score; + } else { + row.area -= row.pop().area; + position(row, u, rect, false); + u = Math.min(rect.dx, rect.dy); + row.length = row.area = 0; + best = Infinity; + } + } + if (row.length) { + position(row, u, rect, true); + row.length = row.area = 0; + } + children.forEach(squarify); + } + } + function stickify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), remaining = children.slice(), child, row = []; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while (child = remaining.pop()) { + row.push(child); + row.area += child.area; + if (child.z != null) { + position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); + row.length = row.area = 0; + } + } + children.forEach(stickify); + } + } + function worst(row, u) { + var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; + while (++i < n) { + if (!(r = row[i].area)) continue; + if (r < rmin) rmin = r; + if (r > rmax) rmax = r; + } + s *= s; + u *= u; + return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; + } + function position(row, u, rect, flush) { + var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; + if (u == rect.dx) { + if (flush || v > rect.dy) v = rect.dy; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dy = v; + x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); + } + o.z = true; + o.dx += rect.x + rect.dx - x; + rect.y += v; + rect.dy -= v; + } else { + if (flush || v > rect.dx) v = rect.dx; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dx = v; + y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); + } + o.z = false; + o.dy += rect.y + rect.dy - y; + rect.x += v; + rect.dx -= v; + } + } + function treemap(d) { + var nodes = stickies || hierarchy(d), root = nodes[0]; + root.x = root.y = 0; + if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; + if (stickies) hierarchy.revalue(root); + scale([ root ], root.dx * root.dy / root.value); + (stickies ? stickify : squarify)(root); + if (sticky) stickies = nodes; + return nodes; + } + treemap.size = function(x) { + if (!arguments.length) return size; + size = x; + return treemap; + }; + treemap.padding = function(x) { + if (!arguments.length) return padding; + function padFunction(node) { + var p = x.call(treemap, node, node.depth); + return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); + } + function padConstant(node) { + return d3_layout_treemapPad(node, x); + } + var type; + pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], + padConstant) : padConstant; + return treemap; + }; + treemap.round = function(x) { + if (!arguments.length) return round != Number; + round = x ? Math.round : Number; + return treemap; + }; + treemap.sticky = function(x) { + if (!arguments.length) return sticky; + sticky = x; + stickies = null; + return treemap; + }; + treemap.ratio = function(x) { + if (!arguments.length) return ratio; + ratio = x; + return treemap; + }; + treemap.mode = function(x) { + if (!arguments.length) return mode; + mode = x + ""; + return treemap; + }; + return d3_layout_hierarchyRebind(treemap, hierarchy); + }; + function d3_layout_treemapPadNull(node) { + return { + x: node.x, + y: node.y, + dx: node.dx, + dy: node.dy + }; + } + function d3_layout_treemapPad(node, padding) { + var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; + if (dx < 0) { + x += dx / 2; + dx = 0; + } + if (dy < 0) { + y += dy / 2; + dy = 0; + } + return { + x: x, + y: y, + dx: dx, + dy: dy + }; + } + d3.random = { + normal: function(µ, σ) { + var n = arguments.length; + if (n < 2) σ = 1; + if (n < 1) µ = 0; + return function() { + var x, y, r; + do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); + }; + }, + logNormal: function() { + var random = d3.random.normal.apply(d3, arguments); + return function() { + return Math.exp(random()); + }; + }, + bates: function(m) { + var random = d3.random.irwinHall(m); + return function() { + return random() / m; + }; + }, + irwinHall: function(m) { + return function() { + for (var s = 0, j = 0; j < m; j++) s += Math.random(); + return s; + }; + } + }; + d3.scale = {}; + function d3_scaleExtent(domain) { + var start = domain[0], stop = domain[domain.length - 1]; + return start < stop ? [ start, stop ] : [ stop, start ]; + } + function d3_scaleRange(scale) { + return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); + } + function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { + var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); + return function(x) { + return i(u(x)); + }; + } + function d3_scale_nice(domain, nice) { + var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; + if (x1 < x0) { + dx = i0, i0 = i1, i1 = dx; + dx = x0, x0 = x1, x1 = dx; + } + domain[i0] = nice.floor(x0); + domain[i1] = nice.ceil(x1); + return domain; + } + function d3_scale_niceStep(step) { + return step ? { + floor: function(x) { + return Math.floor(x / step) * step; + }, + ceil: function(x) { + return Math.ceil(x / step) * step; + } + } : d3_scale_niceIdentity; + } + var d3_scale_niceIdentity = { + floor: d3_identity, + ceil: d3_identity + }; + function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { + var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; + if (domain[k] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); + } + while (++j <= k) { + u.push(uninterpolate(domain[j - 1], domain[j])); + i.push(interpolate(range[j - 1], range[j])); + } + return function(x) { + var j = d3.bisect(domain, x, 1, k) - 1; + return i[j](u[j](x)); + }; + } + d3.scale.linear = function() { + return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); + }; + function d3_scale_linear(domain, range, interpolate, clamp) { + var output, input; + function rescale() { + var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; + output = linear(domain, range, uninterpolate, interpolate); + input = linear(range, domain, uninterpolate, d3_interpolate); + return scale; + } + function scale(x) { + return output(x); + } + scale.invert = function(y) { + return input(y); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(Number); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.rangeRound = function(x) { + return scale.range(x).interpolate(d3_interpolateRound); + }; + scale.clamp = function(x) { + if (!arguments.length) return clamp; + clamp = x; + return rescale(); + }; + scale.interpolate = function(x) { + if (!arguments.length) return interpolate; + interpolate = x; + return rescale(); + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + d3_scale_linearNice(domain, m); + return rescale(); + }; + scale.copy = function() { + return d3_scale_linear(domain, range, interpolate, clamp); + }; + return rescale(); + } + function d3_scale_linearRebind(scale, linear) { + return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); + } + function d3_scale_linearNice(domain, m) { + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + return domain; + } + function d3_scale_linearTickRange(domain, m) { + if (m == null) m = 10; + var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; + if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; + extent[0] = Math.ceil(extent[0] / step) * step; + extent[1] = Math.floor(extent[1] / step) * step + step * .5; + extent[2] = step; + return extent; + } + function d3_scale_linearTicks(domain, m) { + return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); + } + function d3_scale_linearTickFormat(domain, m, format) { + var range = d3_scale_linearTickRange(domain, m); + if (format) { + var match = d3_format_re.exec(format); + match.shift(); + if (match[8] === "s") { + var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); + if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); + match[8] = "f"; + format = d3.format(match.join("")); + return function(d) { + return format(prefix.scale(d)) + prefix.symbol; + }; + } + if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); + format = match.join(""); + } else { + format = ",." + d3_scale_linearPrecision(range[2]) + "f"; + } + return d3.format(format); + } + var d3_scale_linearFormatSignificant = { + s: 1, + g: 1, + p: 1, + r: 1, + e: 1 + }; + function d3_scale_linearPrecision(value) { + return -Math.floor(Math.log(value) / Math.LN10 + .01); + } + function d3_scale_linearFormatPrecision(type, range) { + var p = d3_scale_linearPrecision(range[2]); + return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; + } + d3.scale.log = function() { + return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); + }; + function d3_scale_log(linear, base, positive, domain) { + function log(x) { + return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); + } + function pow(x) { + return positive ? Math.pow(base, x) : -Math.pow(base, -x); + } + function scale(x) { + return linear(log(x)); + } + scale.invert = function(x) { + return pow(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + positive = x[0] >= 0; + linear.domain((domain = x.map(Number)).map(log)); + return scale; + }; + scale.base = function(_) { + if (!arguments.length) return base; + base = +_; + linear.domain(domain.map(log)); + return scale; + }; + scale.nice = function() { + var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); + linear.domain(niced); + domain = niced.map(pow); + return scale; + }; + scale.ticks = function() { + var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; + if (isFinite(j - i)) { + if (positive) { + for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); + ticks.push(pow(i)); + } else { + ticks.push(pow(i)); + for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); + } + for (i = 0; ticks[i] < u; i++) {} + for (j = ticks.length; ticks[j - 1] > v; j--) {} + ticks = ticks.slice(i, j); + } + return ticks; + }; + scale.tickFormat = function(n, format) { + if (!arguments.length) return d3_scale_logFormat; + if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); + var k = Math.max(1, base * n / scale.ticks().length); + return function(d) { + var i = d / pow(Math.round(log(d))); + if (i * base < base - .5) i *= base; + return i <= k ? format(d) : ""; + }; + }; + scale.copy = function() { + return d3_scale_log(linear.copy(), base, positive, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { + floor: function(x) { + return -Math.ceil(-x); + }, + ceil: function(x) { + return -Math.floor(-x); + } + }; + d3.scale.pow = function() { + return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); + }; + function d3_scale_pow(linear, exponent, domain) { + var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); + function scale(x) { + return linear(powp(x)); + } + scale.invert = function(x) { + return powb(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + linear.domain((domain = x.map(Number)).map(powp)); + return scale; + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + return scale.domain(d3_scale_linearNice(domain, m)); + }; + scale.exponent = function(x) { + if (!arguments.length) return exponent; + powp = d3_scale_powPow(exponent = x); + powb = d3_scale_powPow(1 / exponent); + linear.domain(domain.map(powp)); + return scale; + }; + scale.copy = function() { + return d3_scale_pow(linear.copy(), exponent, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_scale_powPow(e) { + return function(x) { + return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); + }; + } + d3.scale.sqrt = function() { + return d3.scale.pow().exponent(.5); + }; + d3.scale.ordinal = function() { + return d3_scale_ordinal([], { + t: "range", + a: [ [] ] + }); + }; + function d3_scale_ordinal(domain, ranger) { + var index, range, rangeBand; + function scale(x) { + return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; + } + function steps(start, step) { + return d3.range(domain.length).map(function(i) { + return start + step * i; + }); + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = []; + index = new d3_Map(); + var i = -1, n = x.length, xi; + while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); + return scale[ranger.t].apply(scale, ranger.a); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + rangeBand = 0; + ranger = { + t: "range", + a: arguments + }; + return scale; + }; + scale.rangePoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, + 0) : (stop - start) / (domain.length - 1 + padding); + range = steps(start + step * padding / 2, step); + rangeBand = 0; + ranger = { + t: "rangePoints", + a: arguments + }; + return scale; + }; + scale.rangeRoundPoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), + 0) : (stop - start) / (domain.length - 1 + padding) | 0; + range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); + rangeBand = 0; + ranger = { + t: "rangeRoundPoints", + a: arguments + }; + return scale; + }; + scale.rangeBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); + range = steps(start + step * outerPadding, step); + if (reverse) range.reverse(); + rangeBand = step * (1 - padding); + ranger = { + t: "rangeBands", + a: arguments + }; + return scale; + }; + scale.rangeRoundBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); + range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); + if (reverse) range.reverse(); + rangeBand = Math.round(step * (1 - padding)); + ranger = { + t: "rangeRoundBands", + a: arguments + }; + return scale; + }; + scale.rangeBand = function() { + return rangeBand; + }; + scale.rangeExtent = function() { + return d3_scaleExtent(ranger.a[0]); + }; + scale.copy = function() { + return d3_scale_ordinal(domain, ranger); + }; + return scale.domain(domain); + } + d3.scale.category10 = function() { + return d3.scale.ordinal().range(d3_category10); + }; + d3.scale.category20 = function() { + return d3.scale.ordinal().range(d3_category20); + }; + d3.scale.category20b = function() { + return d3.scale.ordinal().range(d3_category20b); + }; + d3.scale.category20c = function() { + return d3.scale.ordinal().range(d3_category20c); + }; + var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); + var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); + var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); + var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); + d3.scale.quantile = function() { + return d3_scale_quantile([], []); + }; + function d3_scale_quantile(domain, range) { + var thresholds; + function rescale() { + var k = 0, q = range.length; + thresholds = []; + while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); + return scale; + } + function scale(x) { + if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.quantiles = function() { + return thresholds; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; + }; + scale.copy = function() { + return d3_scale_quantile(domain, range); + }; + return rescale(); + } + d3.scale.quantize = function() { + return d3_scale_quantize(0, 1, [ 0, 1 ]); + }; + function d3_scale_quantize(x0, x1, range) { + var kx, i; + function scale(x) { + return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; + } + function rescale() { + kx = range.length / (x1 - x0); + i = range.length - 1; + return scale; + } + scale.domain = function(x) { + if (!arguments.length) return [ x0, x1 ]; + x0 = +x[0]; + x1 = +x[x.length - 1]; + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + y = y < 0 ? NaN : y / kx + x0; + return [ y, y + 1 / kx ]; + }; + scale.copy = function() { + return d3_scale_quantize(x0, x1, range); + }; + return rescale(); + } + d3.scale.threshold = function() { + return d3_scale_threshold([ .5 ], [ 0, 1 ]); + }; + function d3_scale_threshold(domain, range) { + function scale(x) { + if (x <= x) return range[d3.bisect(domain, x)]; + } + scale.domain = function(_) { + if (!arguments.length) return domain; + domain = _; + return scale; + }; + scale.range = function(_) { + if (!arguments.length) return range; + range = _; + return scale; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return [ domain[y - 1], domain[y] ]; + }; + scale.copy = function() { + return d3_scale_threshold(domain, range); + }; + return scale; + } + d3.scale.identity = function() { + return d3_scale_identity([ 0, 1 ]); + }; + function d3_scale_identity(domain) { + function identity(x) { + return +x; + } + identity.invert = identity; + identity.domain = identity.range = function(x) { + if (!arguments.length) return domain; + domain = x.map(identity); + return identity; + }; + identity.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + identity.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + identity.copy = function() { + return d3_scale_identity(domain); + }; + return identity; + } + d3.svg = {}; + function d3_zero() { + return 0; + } + d3.svg.arc = function() { + var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; + function arc() { + var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; + if (r1 < r0) rc = r1, r1 = r0, r0 = rc; + if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; + var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; + if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { + rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); + if (!cw) p1 *= -1; + if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); + if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); + } + if (r1) { + x0 = r1 * Math.cos(a0 + p1); + y0 = r1 * Math.sin(a0 + p1); + x1 = r1 * Math.cos(a1 - p1); + y1 = r1 * Math.sin(a1 - p1); + var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; + if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { + var h1 = (a0 + a1) / 2; + x0 = r1 * Math.cos(h1); + y0 = r1 * Math.sin(h1); + x1 = y1 = null; + } + } else { + x0 = y0 = 0; + } + if (r0) { + x2 = r0 * Math.cos(a1 - p0); + y2 = r0 * Math.sin(a1 - p0); + x3 = r0 * Math.cos(a0 + p0); + y3 = r0 * Math.sin(a0 + p0); + var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; + if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { + var h0 = (a0 + a1) / 2; + x2 = r0 * Math.cos(h0); + y2 = r0 * Math.sin(h0); + x3 = y3 = null; + } + } else { + x2 = y2 = 0; + } + if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { + cr = r0 < r1 ^ cw ? 0 : 1; + var rc1 = rc, rc0 = rc; + if (da < π) { + var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); + rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); + } + if (x1 != null) { + var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); + if (rc === rc1) { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); + } else { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); + } + } else { + path.push("M", x0, ",", y0); + } + if (x3 != null) { + var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); + if (rc === rc0) { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } else { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } + } else { + path.push("L", x2, ",", y2); + } + } else { + path.push("M", x0, ",", y0); + if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); + path.push("L", x2, ",", y2); + if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); + } + path.push("Z"); + return path.join(""); + } + function circleSegment(r1, cw) { + return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; + } + arc.innerRadius = function(v) { + if (!arguments.length) return innerRadius; + innerRadius = d3_functor(v); + return arc; + }; + arc.outerRadius = function(v) { + if (!arguments.length) return outerRadius; + outerRadius = d3_functor(v); + return arc; + }; + arc.cornerRadius = function(v) { + if (!arguments.length) return cornerRadius; + cornerRadius = d3_functor(v); + return arc; + }; + arc.padRadius = function(v) { + if (!arguments.length) return padRadius; + padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); + return arc; + }; + arc.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return arc; + }; + arc.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return arc; + }; + arc.padAngle = function(v) { + if (!arguments.length) return padAngle; + padAngle = d3_functor(v); + return arc; + }; + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; + return [ Math.cos(a) * r, Math.sin(a) * r ]; + }; + return arc; + }; + var d3_svg_arcAuto = "auto"; + function d3_svg_arcInnerRadius(d) { + return d.innerRadius; + } + function d3_svg_arcOuterRadius(d) { + return d.outerRadius; + } + function d3_svg_arcStartAngle(d) { + return d.startAngle; + } + function d3_svg_arcEndAngle(d) { + return d.endAngle; + } + function d3_svg_arcPadAngle(d) { + return d && d.padAngle; + } + function d3_svg_arcSweep(x0, y0, x1, y1) { + return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; + } + function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { + var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; + } + function d3_svg_line(projection) { + var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; + function line(data) { + var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); + function segment() { + segments.push("M", interpolate(projection(points), tension)); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); + } else if (points.length) { + segment(); + points = []; + } + } + if (points.length) segment(); + return segments.length ? segments.join("") : null; + } + line.x = function(_) { + if (!arguments.length) return x; + x = _; + return line; + }; + line.y = function(_) { + if (!arguments.length) return y; + y = _; + return line; + }; + line.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return line; + }; + line.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + return line; + }; + line.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return line; + }; + return line; + } + d3.svg.line = function() { + return d3_svg_line(d3_identity); + }; + var d3_svg_lineInterpolators = d3.map({ + linear: d3_svg_lineLinear, + "linear-closed": d3_svg_lineLinearClosed, + step: d3_svg_lineStep, + "step-before": d3_svg_lineStepBefore, + "step-after": d3_svg_lineStepAfter, + basis: d3_svg_lineBasis, + "basis-open": d3_svg_lineBasisOpen, + "basis-closed": d3_svg_lineBasisClosed, + bundle: d3_svg_lineBundle, + cardinal: d3_svg_lineCardinal, + "cardinal-open": d3_svg_lineCardinalOpen, + "cardinal-closed": d3_svg_lineCardinalClosed, + monotone: d3_svg_lineMonotone + }); + d3_svg_lineInterpolators.forEach(function(key, value) { + value.key = key; + value.closed = /-closed$/.test(key); + }); + function d3_svg_lineLinear(points) { + return points.length > 1 ? points.join("L") : points + "Z"; + } + function d3_svg_lineLinearClosed(points) { + return points.join("L") + "Z"; + } + function d3_svg_lineStep(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); + if (n > 1) path.push("H", p[0]); + return path.join(""); + } + function d3_svg_lineStepBefore(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); + return path.join(""); + } + function d3_svg_lineStepAfter(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); + return path.join(""); + } + function d3_svg_lineCardinalOpen(points, tension) { + return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineCardinalClosed(points, tension) { + return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), + points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); + } + function d3_svg_lineCardinal(points, tension) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineHermite(points, tangents) { + if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { + return d3_svg_lineLinear(points); + } + var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; + if (quad) { + path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; + p0 = points[1]; + pi = 2; + } + if (tangents.length > 1) { + t = tangents[1]; + p = points[pi]; + pi++; + path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + for (var i = 2; i < tangents.length; i++, pi++) { + p = points[pi]; + t = tangents[i]; + path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + } + } + if (quad) { + var lp = points[pi]; + path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; + } + return path; + } + function d3_svg_lineCardinalTangents(points, tension) { + var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; + while (++i < n) { + p0 = p1; + p1 = p2; + p2 = points[i]; + tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); + } + return tangents; + } + function d3_svg_lineBasis(points) { + if (points.length < 3) return d3_svg_lineLinear(points); + var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + points.push(points[n - 1]); + while (++i <= n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + points.pop(); + path.push("L", pi); + return path.join(""); + } + function d3_svg_lineBasisOpen(points) { + if (points.length < 4) return d3_svg_lineLinear(points); + var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; + while (++i < 3) { + pi = points[i]; + px.push(pi[0]); + py.push(pi[1]); + } + path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); + --i; + while (++i < n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBasisClosed(points) { + var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; + while (++i < 4) { + pi = points[i % n]; + px.push(pi[0]); + py.push(pi[1]); + } + path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + --i; + while (++i < m) { + pi = points[i % n]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBundle(points, tension) { + var n = points.length - 1; + if (n) { + var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; + while (++i <= n) { + p = points[i]; + t = i / n; + p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); + p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); + } + } + return d3_svg_lineBasis(points); + } + function d3_svg_lineDot4(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + } + var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; + function d3_svg_lineBasisBezier(path, x, y) { + path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); + } + function d3_svg_lineSlope(p0, p1) { + return (p1[1] - p0[1]) / (p1[0] - p0[0]); + } + function d3_svg_lineFiniteDifferences(points) { + var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); + while (++i < j) { + m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; + } + m[i] = d; + return m; + } + function d3_svg_lineMonotoneTangents(points) { + var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; + while (++i < j) { + d = d3_svg_lineSlope(points[i], points[i + 1]); + if (abs(d) < ε) { + m[i] = m[i + 1] = 0; + } else { + a = m[i] / d; + b = m[i + 1] / d; + s = a * a + b * b; + if (s > 9) { + s = d * 3 / Math.sqrt(s); + m[i] = s * a; + m[i + 1] = s * b; + } + } + } + i = -1; + while (++i <= j) { + s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); + tangents.push([ s || 0, m[i] * s || 0 ]); + } + return tangents; + } + function d3_svg_lineMonotone(points) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); + } + d3.svg.line.radial = function() { + var line = d3_svg_line(d3_svg_lineRadial); + line.radius = line.x, delete line.x; + line.angle = line.y, delete line.y; + return line; + }; + function d3_svg_lineRadial(points) { + var point, i = -1, n = points.length, r, a; + while (++i < n) { + point = points[i]; + r = point[0]; + a = point[1] - halfπ; + point[0] = r * Math.cos(a); + point[1] = r * Math.sin(a); + } + return points; + } + function d3_svg_area(projection) { + var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; + function area(data) { + var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { + return x; + } : d3_functor(x1), fy1 = y0 === y1 ? function() { + return y; + } : d3_functor(y1), x, y; + function segment() { + segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); + points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); + } else if (points0.length) { + segment(); + points0 = []; + points1 = []; + } + } + if (points0.length) segment(); + return segments.length ? segments.join("") : null; + } + area.x = function(_) { + if (!arguments.length) return x1; + x0 = x1 = _; + return area; + }; + area.x0 = function(_) { + if (!arguments.length) return x0; + x0 = _; + return area; + }; + area.x1 = function(_) { + if (!arguments.length) return x1; + x1 = _; + return area; + }; + area.y = function(_) { + if (!arguments.length) return y1; + y0 = y1 = _; + return area; + }; + area.y0 = function(_) { + if (!arguments.length) return y0; + y0 = _; + return area; + }; + area.y1 = function(_) { + if (!arguments.length) return y1; + y1 = _; + return area; + }; + area.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return area; + }; + area.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + interpolateReverse = interpolate.reverse || interpolate; + L = interpolate.closed ? "M" : "L"; + return area; + }; + area.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return area; + }; + return area; + } + d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; + d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; + d3.svg.area = function() { + return d3_svg_area(d3_identity); + }; + d3.svg.area.radial = function() { + var area = d3_svg_area(d3_svg_lineRadial); + area.radius = area.x, delete area.x; + area.innerRadius = area.x0, delete area.x0; + area.outerRadius = area.x1, delete area.x1; + area.angle = area.y, delete area.y; + area.startAngle = area.y0, delete area.y0; + area.endAngle = area.y1, delete area.y1; + return area; + }; + d3.svg.chord = function() { + var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; + function chord(d, i) { + var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); + return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; + } + function subgroup(self, f, d, i) { + var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; + return { + r: r, + a0: a0, + a1: a1, + p0: [ r * Math.cos(a0), r * Math.sin(a0) ], + p1: [ r * Math.cos(a1), r * Math.sin(a1) ] + }; + } + function equals(a, b) { + return a.a0 == b.a0 && a.a1 == b.a1; + } + function arc(r, p, a) { + return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; + } + function curve(r0, p0, r1, p1) { + return "Q 0,0 " + p1; + } + chord.radius = function(v) { + if (!arguments.length) return radius; + radius = d3_functor(v); + return chord; + }; + chord.source = function(v) { + if (!arguments.length) return source; + source = d3_functor(v); + return chord; + }; + chord.target = function(v) { + if (!arguments.length) return target; + target = d3_functor(v); + return chord; + }; + chord.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return chord; + }; + chord.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return chord; + }; + return chord; + }; + function d3_svg_chordRadius(d) { + return d.radius; + } + d3.svg.diagonal = function() { + var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; + function diagonal(d, i) { + var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { + x: p0.x, + y: m + }, { + x: p3.x, + y: m + }, p3 ]; + p = p.map(projection); + return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; + } + diagonal.source = function(x) { + if (!arguments.length) return source; + source = d3_functor(x); + return diagonal; + }; + diagonal.target = function(x) { + if (!arguments.length) return target; + target = d3_functor(x); + return diagonal; + }; + diagonal.projection = function(x) { + if (!arguments.length) return projection; + projection = x; + return diagonal; + }; + return diagonal; + }; + function d3_svg_diagonalProjection(d) { + return [ d.x, d.y ]; + } + d3.svg.diagonal.radial = function() { + var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; + diagonal.projection = function(x) { + return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; + }; + return diagonal; + }; + function d3_svg_diagonalRadialProjection(projection) { + return function() { + var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; + return [ r * Math.cos(a), r * Math.sin(a) ]; + }; + } + d3.svg.symbol = function() { + var type = d3_svg_symbolType, size = d3_svg_symbolSize; + function symbol(d, i) { + return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); + } + symbol.type = function(x) { + if (!arguments.length) return type; + type = d3_functor(x); + return symbol; + }; + symbol.size = function(x) { + if (!arguments.length) return size; + size = d3_functor(x); + return symbol; + }; + return symbol; + }; + function d3_svg_symbolSize() { + return 64; + } + function d3_svg_symbolType() { + return "circle"; + } + function d3_svg_symbolCircle(size) { + var r = Math.sqrt(size / π); + return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; + } + var d3_svg_symbols = d3.map({ + circle: d3_svg_symbolCircle, + cross: function(size) { + var r = Math.sqrt(size / 5) / 2; + return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; + }, + diamond: function(size) { + var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; + return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; + }, + square: function(size) { + var r = Math.sqrt(size) / 2; + return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; + }, + "triangle-down": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; + }, + "triangle-up": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; + } + }); + d3.svg.symbolTypes = d3_svg_symbols.keys(); + var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); + d3_selectionPrototype.transition = function(name) { + var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { + time: Date.now(), + ease: d3_ease_cubicInOut, + delay: 0, + duration: 250 + }; + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); + subgroup.push(node); + } + } + return d3_transition(subgroups, ns, id); + }; + d3_selectionPrototype.interrupt = function(name) { + return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); + }; + var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); + function d3_selection_interruptNS(ns) { + return function() { + var lock, activeId, active; + if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { + active.timer.c = null; + active.timer.t = NaN; + if (--lock.count) delete lock[activeId]; else delete this[ns]; + lock.active += .5; + active.event && active.event.interrupt.call(this, this.__data__, active.index); + } + }; + } + function d3_transition(groups, ns, id) { + d3_subclass(groups, d3_transitionPrototype); + groups.namespace = ns; + groups.id = id; + return groups; + } + var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; + d3_transitionPrototype.call = d3_selectionPrototype.call; + d3_transitionPrototype.empty = d3_selectionPrototype.empty; + d3_transitionPrototype.node = d3_selectionPrototype.node; + d3_transitionPrototype.size = d3_selectionPrototype.size; + d3.transition = function(selection, name) { + return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); + }; + d3.transition.prototype = d3_transitionPrototype; + d3_transitionPrototype.select = function(selector) { + var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + d3_transitionNode(subnode, i, ns, id, node[ns][id]); + subgroup.push(subnode); + } else { + subgroup.push(null); + } + } + } + return d3_transition(subgroups, ns, id); + }; + d3_transitionPrototype.selectAll = function(selector) { + var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + transition = node[ns][id]; + subnodes = selector.call(node, node.__data__, i, j); + subgroups.push(subgroup = []); + for (var k = -1, o = subnodes.length; ++k < o; ) { + if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); + subgroup.push(subnode); + } + } + } + } + return d3_transition(subgroups, ns, id); + }; + d3_transitionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_transition(subgroups, this.namespace, this.id); + }; + d3_transitionPrototype.tween = function(name, tween) { + var id = this.id, ns = this.namespace; + if (arguments.length < 2) return this.node()[ns][id].tween.get(name); + return d3_selection_each(this, tween == null ? function(node) { + node[ns][id].tween.remove(name); + } : function(node) { + node[ns][id].tween.set(name, tween); + }); + }; + function d3_transition_tween(groups, name, value, tween) { + var id = groups.id, ns = groups.namespace; + return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { + node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); + } : (value = tween(value), function(node) { + node[ns][id].tween.set(name, value); + })); + } + d3_transitionPrototype.attr = function(nameNS, value) { + if (arguments.length < 2) { + for (value in nameNS) this.attr(value, nameNS[value]); + return this; + } + var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrTween(b) { + return b == null ? attrNull : (b += "", function() { + var a = this.getAttribute(name), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttribute(name, i(t)); + }); + }); + } + function attrTweenNS(b) { + return b == null ? attrNullNS : (b += "", function() { + var a = this.getAttributeNS(name.space, name.local), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttributeNS(name.space, name.local, i(t)); + }); + }); + } + return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.attrTween = function(nameNS, tween) { + var name = d3.ns.qualify(nameNS); + function attrTween(d, i) { + var f = tween.call(this, d, i, this.getAttribute(name)); + return f && function(t) { + this.setAttribute(name, f(t)); + }; + } + function attrTweenNS(d, i) { + var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); + return f && function(t) { + this.setAttributeNS(name.space, name.local, f(t)); + }; + } + return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.style(priority, name[priority], value); + return this; + } + priority = ""; + } + function styleNull() { + this.style.removeProperty(name); + } + function styleString(b) { + return b == null ? styleNull : (b += "", function() { + var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; + return a !== b && (i = d3_interpolate(a, b), function(t) { + this.style.setProperty(name, i(t), priority); + }); + }); + } + return d3_transition_tween(this, "style." + name, value, styleString); + }; + d3_transitionPrototype.styleTween = function(name, tween, priority) { + if (arguments.length < 3) priority = ""; + function styleTween(d, i) { + var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); + return f && function(t) { + this.style.setProperty(name, f(t), priority); + }; + } + return this.tween("style." + name, styleTween); + }; + d3_transitionPrototype.text = function(value) { + return d3_transition_tween(this, "text", value, d3_transition_text); + }; + function d3_transition_text(b) { + if (b == null) b = ""; + return function() { + this.textContent = b; + }; + } + d3_transitionPrototype.remove = function() { + var ns = this.namespace; + return this.each("end.transition", function() { + var p; + if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); + }); + }; + d3_transitionPrototype.ease = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].ease; + if (typeof value !== "function") value = d3.ease.apply(d3, arguments); + return d3_selection_each(this, function(node) { + node[ns][id].ease = value; + }); + }; + d3_transitionPrototype.delay = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].delay; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node[ns][id].delay = +value.call(node, node.__data__, i, j); + } : (value = +value, function(node) { + node[ns][id].delay = value; + })); + }; + d3_transitionPrototype.duration = function(value) { + var id = this.id, ns = this.namespace; + if (arguments.length < 1) return this.node()[ns][id].duration; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); + } : (value = Math.max(1, value), function(node) { + node[ns][id].duration = value; + })); + }; + d3_transitionPrototype.each = function(type, listener) { + var id = this.id, ns = this.namespace; + if (arguments.length < 2) { + var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; + try { + d3_transitionInheritId = id; + d3_selection_each(this, function(node, i, j) { + d3_transitionInherit = node[ns][id]; + type.call(node, node.__data__, i, j); + }); + } finally { + d3_transitionInherit = inherit; + d3_transitionInheritId = inheritId; + } + } else { + d3_selection_each(this, function(node) { + var transition = node[ns][id]; + (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); + }); + } + return this; + }; + d3_transitionPrototype.transition = function() { + var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if (node = group[i]) { + transition = node[ns][id0]; + d3_transitionNode(node, i, ns, id1, { + time: transition.time, + ease: transition.ease, + delay: transition.delay + transition.duration, + duration: transition.duration + }); + } + subgroup.push(node); + } + } + return d3_transition(subgroups, ns, id1); + }; + function d3_transitionNamespace(name) { + return name == null ? "__transition__" : "__transition_" + name + "__"; + } + function d3_transitionNode(node, i, ns, id, inherit) { + var lock = node[ns] || (node[ns] = { + active: 0, + count: 0 + }), transition = lock[id], time, timer, duration, ease, tweens; + function schedule(elapsed) { + var delay = transition.delay; + timer.t = delay + time; + if (delay <= elapsed) return start(elapsed - delay); + timer.c = start; + } + function start(elapsed) { + var activeId = lock.active, active = lock[activeId]; + if (active) { + active.timer.c = null; + active.timer.t = NaN; + --lock.count; + delete lock[activeId]; + active.event && active.event.interrupt.call(node, node.__data__, active.index); + } + for (var cancelId in lock) { + if (+cancelId < id) { + var cancel = lock[cancelId]; + cancel.timer.c = null; + cancel.timer.t = NaN; + --lock.count; + delete lock[cancelId]; + } + } + timer.c = tick; + d3_timer(function() { + if (timer.c && tick(elapsed || 1)) { + timer.c = null; + timer.t = NaN; + } + return 1; + }, 0, time); + lock.active = id; + transition.event && transition.event.start.call(node, node.__data__, i); + tweens = []; + transition.tween.forEach(function(key, value) { + if (value = value.call(node, node.__data__, i)) { + tweens.push(value); + } + }); + ease = transition.ease; + duration = transition.duration; + } + function tick(elapsed) { + var t = elapsed / duration, e = ease(t), n = tweens.length; + while (n > 0) { + tweens[--n].call(node, e); + } + if (t >= 1) { + transition.event && transition.event.end.call(node, node.__data__, i); + if (--lock.count) delete lock[id]; else delete node[ns]; + return 1; + } + } + if (!transition) { + time = inherit.time; + timer = d3_timer(schedule, 0, time); + transition = lock[id] = { + tween: new d3_Map(), + time: time, + timer: timer, + delay: inherit.delay, + duration: inherit.duration, + ease: inherit.ease, + index: i + }; + inherit = null; + ++lock.count; + } + } + d3.svg.axis = function() { + var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; + function axis(g) { + g.each(function() { + var g = d3.select(this); + var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); + var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; + var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), + d3.transition(path)); + tickEnter.append("line"); + tickEnter.append("text"); + var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; + if (orient === "bottom" || orient === "top") { + tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; + text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); + pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); + } else { + tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; + text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); + pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); + } + lineEnter.attr(y2, sign * innerTickSize); + textEnter.attr(y1, sign * tickSpacing); + lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); + textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); + if (scale1.rangeBand) { + var x = scale1, dx = x.rangeBand() / 2; + scale0 = scale1 = function(d) { + return x(d) + dx; + }; + } else if (scale0.rangeBand) { + scale0 = scale1; + } else { + tickExit.call(tickTransform, scale1, scale0); + } + tickEnter.call(tickTransform, scale0, scale1); + tickUpdate.call(tickTransform, scale1, scale1); + }); + } + axis.scale = function(x) { + if (!arguments.length) return scale; + scale = x; + return axis; + }; + axis.orient = function(x) { + if (!arguments.length) return orient; + orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; + return axis; + }; + axis.ticks = function() { + if (!arguments.length) return tickArguments_; + tickArguments_ = d3_array(arguments); + return axis; + }; + axis.tickValues = function(x) { + if (!arguments.length) return tickValues; + tickValues = x; + return axis; + }; + axis.tickFormat = function(x) { + if (!arguments.length) return tickFormat_; + tickFormat_ = x; + return axis; + }; + axis.tickSize = function(x) { + var n = arguments.length; + if (!n) return innerTickSize; + innerTickSize = +x; + outerTickSize = +arguments[n - 1]; + return axis; + }; + axis.innerTickSize = function(x) { + if (!arguments.length) return innerTickSize; + innerTickSize = +x; + return axis; + }; + axis.outerTickSize = function(x) { + if (!arguments.length) return outerTickSize; + outerTickSize = +x; + return axis; + }; + axis.tickPadding = function(x) { + if (!arguments.length) return tickPadding; + tickPadding = +x; + return axis; + }; + axis.tickSubdivide = function() { + return arguments.length && axis; + }; + return axis; + }; + var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { + top: 1, + right: 1, + bottom: 1, + left: 1 + }; + function d3_svg_axisX(selection, x0, x1) { + selection.attr("transform", function(d) { + var v0 = x0(d); + return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; + }); + } + function d3_svg_axisY(selection, y0, y1) { + selection.attr("transform", function(d) { + var v0 = y0(d); + return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; + }); + } + d3.svg.brush = function() { + var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; + function brush(g) { + g.each(function() { + var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); + var background = g.selectAll(".background").data([ 0 ]); + background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); + g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); + var resize = g.selectAll(".resize").data(resizes, d3_identity); + resize.exit().remove(); + resize.enter().append("g").attr("class", function(d) { + return "resize " + d; + }).style("cursor", function(d) { + return d3_svg_brushCursor[d]; + }).append("rect").attr("x", function(d) { + return /[ew]$/.test(d) ? -3 : null; + }).attr("y", function(d) { + return /^[ns]/.test(d) ? -3 : null; + }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); + resize.style("display", brush.empty() ? "none" : null); + var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; + if (x) { + range = d3_scaleRange(x); + backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); + redrawX(gUpdate); + } + if (y) { + range = d3_scaleRange(y); + backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); + redrawY(gUpdate); + } + redraw(gUpdate); + }); + } + brush.event = function(g) { + g.each(function() { + var event_ = event.of(this, arguments), extent1 = { + x: xExtent, + y: yExtent, + i: xExtentDomain, + j: yExtentDomain + }, extent0 = this.__chart__ || extent1; + this.__chart__ = extent1; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.brush", function() { + xExtentDomain = extent0.i; + yExtentDomain = extent0.j; + xExtent = extent0.x; + yExtent = extent0.y; + event_({ + type: "brushstart" + }); + }).tween("brush:brush", function() { + var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); + xExtentDomain = yExtentDomain = null; + return function(t) { + xExtent = extent1.x = xi(t); + yExtent = extent1.y = yi(t); + event_({ + type: "brush", + mode: "resize" + }); + }; + }).each("end.brush", function() { + xExtentDomain = extent1.i; + yExtentDomain = extent1.j; + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + }); + } else { + event_({ + type: "brushstart" + }); + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + } + }); + }; + function redraw(g) { + g.selectAll(".resize").attr("transform", function(d) { + return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; + }); + } + function redrawX(g) { + g.select(".extent").attr("x", xExtent[0]); + g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); + } + function redrawY(g) { + g.select(".extent").attr("y", yExtent[0]); + g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); + } + function brushstart() { + var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; + var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); + if (d3.event.changedTouches) { + w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); + } else { + w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); + } + g.interrupt().selectAll("*").interrupt(); + if (dragging) { + origin[0] = xExtent[0] - origin[0]; + origin[1] = yExtent[0] - origin[1]; + } else if (resizing) { + var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); + offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; + origin[0] = xExtent[ex]; + origin[1] = yExtent[ey]; + } else if (d3.event.altKey) center = origin.slice(); + g.style("pointer-events", "none").selectAll(".resize").style("display", null); + d3.select("body").style("cursor", eventTarget.style("cursor")); + event_({ + type: "brushstart" + }); + brushmove(); + function keydown() { + if (d3.event.keyCode == 32) { + if (!dragging) { + center = null; + origin[0] -= xExtent[1]; + origin[1] -= yExtent[1]; + dragging = 2; + } + d3_eventPreventDefault(); + } + } + function keyup() { + if (d3.event.keyCode == 32 && dragging == 2) { + origin[0] += xExtent[1]; + origin[1] += yExtent[1]; + dragging = 0; + d3_eventPreventDefault(); + } + } + function brushmove() { + var point = d3.mouse(target), moved = false; + if (offset) { + point[0] += offset[0]; + point[1] += offset[1]; + } + if (!dragging) { + if (d3.event.altKey) { + if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; + origin[0] = xExtent[+(point[0] < center[0])]; + origin[1] = yExtent[+(point[1] < center[1])]; + } else center = null; + } + if (resizingX && move1(point, x, 0)) { + redrawX(g); + moved = true; + } + if (resizingY && move1(point, y, 1)) { + redrawY(g); + moved = true; + } + if (moved) { + redraw(g); + event_({ + type: "brush", + mode: dragging ? "move" : "resize" + }); + } + } + function move1(point, scale, i) { + var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; + if (dragging) { + r0 -= position; + r1 -= size + position; + } + min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; + if (dragging) { + max = (min += position) + size; + } else { + if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); + if (position < min) { + max = min; + min = position; + } else { + max = position; + } + } + if (extent[0] != min || extent[1] != max) { + if (i) yExtentDomain = null; else xExtentDomain = null; + extent[0] = min; + extent[1] = max; + return true; + } + } + function brushend() { + brushmove(); + g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); + d3.select("body").style("cursor", null); + w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); + dragRestore(); + event_({ + type: "brushend" + }); + } + } + brush.x = function(z) { + if (!arguments.length) return x; + x = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.y = function(z) { + if (!arguments.length) return y; + y = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.clamp = function(z) { + if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; + if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; + return brush; + }; + brush.extent = function(z) { + var x0, x1, y0, y1, t; + if (!arguments.length) { + if (x) { + if (xExtentDomain) { + x0 = xExtentDomain[0], x1 = xExtentDomain[1]; + } else { + x0 = xExtent[0], x1 = xExtent[1]; + if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + } + } + if (y) { + if (yExtentDomain) { + y0 = yExtentDomain[0], y1 = yExtentDomain[1]; + } else { + y0 = yExtent[0], y1 = yExtent[1]; + if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + } + } + return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; + } + if (x) { + x0 = z[0], x1 = z[1]; + if (y) x0 = x0[0], x1 = x1[0]; + xExtentDomain = [ x0, x1 ]; + if (x.invert) x0 = x(x0), x1 = x(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; + } + if (y) { + y0 = z[0], y1 = z[1]; + if (x) y0 = y0[1], y1 = y1[1]; + yExtentDomain = [ y0, y1 ]; + if (y.invert) y0 = y(y0), y1 = y(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; + } + return brush; + }; + brush.clear = function() { + if (!brush.empty()) { + xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; + xExtentDomain = yExtentDomain = null; + } + return brush; + }; + brush.empty = function() { + return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; + }; + return d3.rebind(brush, event, "on"); + }; + var d3_svg_brushCursor = { + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }; + var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; + var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; + var d3_time_formatUtc = d3_time_format.utc; + var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); + d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; + function d3_time_formatIsoNative(date) { + return date.toISOString(); + } + d3_time_formatIsoNative.parse = function(string) { + var date = new Date(string); + return isNaN(date) ? null : date; + }; + d3_time_formatIsoNative.toString = d3_time_formatIso.toString; + d3_time.second = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 1e3) * 1e3); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 1e3); + }, function(date) { + return date.getSeconds(); + }); + d3_time.seconds = d3_time.second.range; + d3_time.seconds.utc = d3_time.second.utc.range; + d3_time.minute = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 6e4) * 6e4); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 6e4); + }, function(date) { + return date.getMinutes(); + }); + d3_time.minutes = d3_time.minute.range; + d3_time.minutes.utc = d3_time.minute.utc.range; + d3_time.hour = d3_time_interval(function(date) { + var timezone = date.getTimezoneOffset() / 60; + return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 36e5); + }, function(date) { + return date.getHours(); + }); + d3_time.hours = d3_time.hour.range; + d3_time.hours.utc = d3_time.hour.utc.range; + d3_time.month = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setDate(1); + return date; + }, function(date, offset) { + date.setMonth(date.getMonth() + offset); + }, function(date) { + return date.getMonth(); + }); + d3_time.months = d3_time.month.range; + d3_time.months.utc = d3_time.month.utc.range; + function d3_time_scale(linear, methods, format) { + function scale(x) { + return linear(x); + } + scale.invert = function(x) { + return d3_time_scaleDate(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return linear.domain().map(d3_time_scaleDate); + linear.domain(x); + return scale; + }; + function tickMethod(extent, count) { + var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); + return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { + return d / 31536e6; + }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; + } + scale.nice = function(interval, skip) { + var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); + if (method) interval = method[0], skip = method[1]; + function skipped(date) { + return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; + } + return scale.domain(d3_scale_nice(domain, skip > 1 ? { + floor: function(date) { + while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); + return date; + }, + ceil: function(date) { + while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); + return date; + } + } : interval)); + }; + scale.ticks = function(interval, skip) { + var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { + range: interval + }, skip ]; + if (method) interval = method[0], skip = method[1]; + return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); + }; + scale.tickFormat = function() { + return format; + }; + scale.copy = function() { + return d3_time_scale(linear.copy(), methods, format); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_time_scaleDate(t) { + return new Date(t); + } + var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; + var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; + var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { + return d.getMilliseconds(); + } ], [ ":%S", function(d) { + return d.getSeconds(); + } ], [ "%I:%M", function(d) { + return d.getMinutes(); + } ], [ "%I %p", function(d) { + return d.getHours(); + } ], [ "%a %d", function(d) { + return d.getDay() && d.getDate() != 1; + } ], [ "%b %d", function(d) { + return d.getDate() != 1; + } ], [ "%B", function(d) { + return d.getMonth(); + } ], [ "%Y", d3_true ] ]); + var d3_time_scaleMilliseconds = { + range: function(start, stop, step) { + return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); + }, + floor: d3_identity, + ceil: d3_identity + }; + d3_time_scaleLocalMethods.year = d3_time.year; + d3_time.scale = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); + }; + var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { + return [ m[0].utc, m[1] ]; + }); + var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { + return d.getUTCMilliseconds(); + } ], [ ":%S", function(d) { + return d.getUTCSeconds(); + } ], [ "%I:%M", function(d) { + return d.getUTCMinutes(); + } ], [ "%I %p", function(d) { + return d.getUTCHours(); + } ], [ "%a %d", function(d) { + return d.getUTCDay() && d.getUTCDate() != 1; + } ], [ "%b %d", function(d) { + return d.getUTCDate() != 1; + } ], [ "%B", function(d) { + return d.getUTCMonth(); + } ], [ "%Y", d3_true ] ]); + d3_time_scaleUtcMethods.year = d3_time.year.utc; + d3_time.scale.utc = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); + }; + d3.text = d3_xhrType(function(request) { + return request.responseText; + }); + d3.json = function(url, callback) { + return d3_xhr(url, "application/json", d3_json, callback); + }; + function d3_json(request) { + return JSON.parse(request.responseText); + } + d3.html = function(url, callback) { + return d3_xhr(url, "text/html", d3_html, callback); + }; + function d3_html(request) { + var range = d3_document.createRange(); + range.selectNode(d3_document.body); + return range.createContextualFragment(request.responseText); + } + d3.xml = d3_xhrType(function(request) { + return request.responseXML; + }); + if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; +}(); +},{}],11:[function(require,module,exports){ +(function (process,global){ +/*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version 3.3.1 + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.ES6Promise = factory()); +}(this, (function () { 'use strict'; + +function objectOrFunction(x) { + return typeof x === 'function' || typeof x === 'object' && x !== null; +} + +function isFunction(x) { + return typeof x === 'function'; +} + +var _isArray = undefined; +if (!Array.isArray) { + _isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; +} else { + _isArray = Array.isArray; +} + +var isArray = _isArray; + +var len = 0; +var vertxNext = undefined; +var customSchedulerFn = undefined; + +var asap = function asap(callback, arg) { + queue[len] = callback; + queue[len + 1] = arg; + len += 2; + if (len === 2) { + // If len is 2, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + if (customSchedulerFn) { + customSchedulerFn(flush); + } else { + scheduleFlush(); + } + } +}; + +function setScheduler(scheduleFn) { + customSchedulerFn = scheduleFn; +} + +function setAsap(asapFn) { + asap = asapFn; +} + +var browserWindow = typeof window !== 'undefined' ? window : undefined; +var browserGlobal = browserWindow || {}; +var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; +var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; + +// test for web worker but not in IE10 +var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; + +// node +function useNextTick() { + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // see https://github.com/cujojs/when/issues/410 for details + return function () { + return process.nextTick(flush); + }; +} + +// vertx +function useVertxTimer() { + return function () { + vertxNext(flush); + }; +} + +function useMutationObserver() { + var iterations = 0; + var observer = new BrowserMutationObserver(flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + + return function () { + node.data = iterations = ++iterations % 2; + }; +} + +// web worker +function useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = flush; + return function () { + return channel.port2.postMessage(0); + }; +} + +function useSetTimeout() { + // Store setTimeout reference so es6-promise will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + var globalSetTimeout = setTimeout; + return function () { + return globalSetTimeout(flush, 1); + }; +} + +var queue = new Array(1000); +function flush() { + for (var i = 0; i < len; i += 2) { + var callback = queue[i]; + var arg = queue[i + 1]; + + callback(arg); + + queue[i] = undefined; + queue[i + 1] = undefined; + } + + len = 0; +} + +function attemptVertx() { + try { + var r = require; + var vertx = r('vertx'); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch (e) { + return useSetTimeout(); + } +} + +var scheduleFlush = undefined; +// Decide what async method to use to triggering processing of queued callbacks: +if (isNode) { + scheduleFlush = useNextTick(); +} else if (BrowserMutationObserver) { + scheduleFlush = useMutationObserver(); +} else if (isWorker) { + scheduleFlush = useMessageChannel(); +} else if (browserWindow === undefined && typeof require === 'function') { + scheduleFlush = attemptVertx(); +} else { + scheduleFlush = useSetTimeout(); +} + +function then(onFulfillment, onRejection) { + var _arguments = arguments; + + var parent = this; + + var child = new this.constructor(noop); + + if (child[PROMISE_ID] === undefined) { + makePromise(child); + } + + var _state = parent._state; + + if (_state) { + (function () { + var callback = _arguments[_state - 1]; + asap(function () { + return invokeCallback(_state, child, callback, parent._result); + }); + })(); + } else { + subscribe(parent, child, onFulfillment, onRejection); + } + + return child; +} + +/** + `Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @static + @param {Any} value value that the returned promise will be resolved with + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` +*/ +function resolve(object) { + /*jshint validthis:true */ + var Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + var promise = new Constructor(noop); + _resolve(promise, object); + return promise; +} + +var PROMISE_ID = Math.random().toString(36).substring(16); + +function noop() {} + +var PENDING = void 0; +var FULFILLED = 1; +var REJECTED = 2; + +var GET_THEN_ERROR = new ErrorObject(); + +function selfFulfillment() { + return new TypeError("You cannot resolve a promise with itself"); +} + +function cannotReturnOwn() { + return new TypeError('A promises callback cannot return that same promise.'); +} + +function getThen(promise) { + try { + return promise.then; + } catch (error) { + GET_THEN_ERROR.error = error; + return GET_THEN_ERROR; + } +} + +function tryThen(then, value, fulfillmentHandler, rejectionHandler) { + try { + then.call(value, fulfillmentHandler, rejectionHandler); + } catch (e) { + return e; + } +} + +function handleForeignThenable(promise, thenable, then) { + asap(function (promise) { + var sealed = false; + var error = tryThen(then, thenable, function (value) { + if (sealed) { + return; + } + sealed = true; + if (thenable !== value) { + _resolve(promise, value); + } else { + fulfill(promise, value); + } + }, function (reason) { + if (sealed) { + return; + } + sealed = true; + + _reject(promise, reason); + }, 'Settle: ' + (promise._label || ' unknown promise')); + + if (!sealed && error) { + sealed = true; + _reject(promise, error); + } + }, promise); +} + +function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + _reject(promise, thenable._result); + } else { + subscribe(thenable, undefined, function (value) { + return _resolve(promise, value); + }, function (reason) { + return _reject(promise, reason); + }); + } +} + +function handleMaybeThenable(promise, maybeThenable, then$$) { + if (maybeThenable.constructor === promise.constructor && then$$ === then && maybeThenable.constructor.resolve === resolve) { + handleOwnThenable(promise, maybeThenable); + } else { + if (then$$ === GET_THEN_ERROR) { + _reject(promise, GET_THEN_ERROR.error); + } else if (then$$ === undefined) { + fulfill(promise, maybeThenable); + } else if (isFunction(then$$)) { + handleForeignThenable(promise, maybeThenable, then$$); + } else { + fulfill(promise, maybeThenable); + } + } +} + +function _resolve(promise, value) { + if (promise === value) { + _reject(promise, selfFulfillment()); + } else if (objectOrFunction(value)) { + handleMaybeThenable(promise, value, getThen(value)); + } else { + fulfill(promise, value); + } +} + +function publishRejection(promise) { + if (promise._onerror) { + promise._onerror(promise._result); + } + + publish(promise); +} + +function fulfill(promise, value) { + if (promise._state !== PENDING) { + return; + } + + promise._result = value; + promise._state = FULFILLED; + + if (promise._subscribers.length !== 0) { + asap(publish, promise); + } +} + +function _reject(promise, reason) { + if (promise._state !== PENDING) { + return; + } + promise._state = REJECTED; + promise._result = reason; + + asap(publishRejection, promise); +} + +function subscribe(parent, child, onFulfillment, onRejection) { + var _subscribers = parent._subscribers; + var length = _subscribers.length; + + parent._onerror = null; + + _subscribers[length] = child; + _subscribers[length + FULFILLED] = onFulfillment; + _subscribers[length + REJECTED] = onRejection; + + if (length === 0 && parent._state) { + asap(publish, parent); + } +} + +function publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; + + if (subscribers.length === 0) { + return; + } + + var child = undefined, + callback = undefined, + detail = promise._result; + + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + + if (child) { + invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } + + promise._subscribers.length = 0; +} + +function ErrorObject() { + this.error = null; +} + +var TRY_CATCH_ERROR = new ErrorObject(); + +function tryCatch(callback, detail) { + try { + return callback(detail); + } catch (e) { + TRY_CATCH_ERROR.error = e; + return TRY_CATCH_ERROR; + } +} + +function invokeCallback(settled, promise, callback, detail) { + var hasCallback = isFunction(callback), + value = undefined, + error = undefined, + succeeded = undefined, + failed = undefined; + + if (hasCallback) { + value = tryCatch(callback, detail); + + if (value === TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value = null; + } else { + succeeded = true; + } + + if (promise === value) { + _reject(promise, cannotReturnOwn()); + return; + } + } else { + value = detail; + succeeded = true; + } + + if (promise._state !== PENDING) { + // noop + } else if (hasCallback && succeeded) { + _resolve(promise, value); + } else if (failed) { + _reject(promise, error); + } else if (settled === FULFILLED) { + fulfill(promise, value); + } else if (settled === REJECTED) { + _reject(promise, value); + } +} + +function initializePromise(promise, resolver) { + try { + resolver(function resolvePromise(value) { + _resolve(promise, value); + }, function rejectPromise(reason) { + _reject(promise, reason); + }); + } catch (e) { + _reject(promise, e); + } +} + +var id = 0; +function nextId() { + return id++; +} + +function makePromise(promise) { + promise[PROMISE_ID] = id++; + promise._state = undefined; + promise._result = undefined; + promise._subscribers = []; +} + +function Enumerator(Constructor, input) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop); + + if (!this.promise[PROMISE_ID]) { + makePromise(this.promise); + } + + if (isArray(input)) { + this._input = input; + this.length = input.length; + this._remaining = input.length; + + this._result = new Array(this.length); + + if (this.length === 0) { + fulfill(this.promise, this._result); + } else { + this.length = this.length || 0; + this._enumerate(); + if (this._remaining === 0) { + fulfill(this.promise, this._result); + } + } + } else { + _reject(this.promise, validationError()); + } +} + +function validationError() { + return new Error('Array Methods must be provided an Array'); +}; + +Enumerator.prototype._enumerate = function () { + var length = this.length; + var _input = this._input; + + for (var i = 0; this._state === PENDING && i < length; i++) { + this._eachEntry(_input[i], i); + } +}; + +Enumerator.prototype._eachEntry = function (entry, i) { + var c = this._instanceConstructor; + var resolve$$ = c.resolve; + + if (resolve$$ === resolve) { + var _then = getThen(entry); + + if (_then === then && entry._state !== PENDING) { + this._settledAt(entry._state, i, entry._result); + } else if (typeof _then !== 'function') { + this._remaining--; + this._result[i] = entry; + } else if (c === Promise) { + var promise = new c(noop); + handleMaybeThenable(promise, entry, _then); + this._willSettleAt(promise, i); + } else { + this._willSettleAt(new c(function (resolve$$) { + return resolve$$(entry); + }), i); + } + } else { + this._willSettleAt(resolve$$(entry), i); + } +}; + +Enumerator.prototype._settledAt = function (state, i, value) { + var promise = this.promise; + + if (promise._state === PENDING) { + this._remaining--; + + if (state === REJECTED) { + _reject(promise, value); + } else { + this._result[i] = value; + } + } + + if (this._remaining === 0) { + fulfill(promise, this._result); + } +}; + +Enumerator.prototype._willSettleAt = function (promise, i) { + var enumerator = this; + + subscribe(promise, undefined, function (value) { + return enumerator._settledAt(FULFILLED, i, value); + }, function (reason) { + return enumerator._settledAt(REJECTED, i, reason); + }); +}; + +/** + `Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + let promise1 = resolve(1); + let promise2 = reject(new Error("2")); + let promise3 = reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static +*/ +function all(entries) { + return new Enumerator(this, entries).promise; +} + +/** + `Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} promises array of promises to observe + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. +*/ +function race(entries) { + /*jshint validthis:true */ + var Constructor = this; + + if (!isArray(entries)) { + return new Constructor(function (_, reject) { + return reject(new TypeError('You must pass an array to race.')); + }); + } else { + return new Constructor(function (resolve, reject) { + var length = entries.length; + for (var i = 0; i < length; i++) { + Constructor.resolve(entries[i]).then(resolve, reject); + } + }); + } +} + +/** + `Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + let promise = new Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {Any} reason value that the returned promise will be rejected with. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. +*/ +function reject(reason) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(noop); + _reject(promise, reason); + return promise; +} + +function needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); +} + +function needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); +} + +/** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise's eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @param {function} resolver + Useful for tooling. + @constructor +*/ +function Promise(resolver) { + this[PROMISE_ID] = nextId(); + this._result = this._state = undefined; + this._subscribers = []; + + if (noop !== resolver) { + typeof resolver !== 'function' && needsResolver(); + this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + } +} + +Promise.all = all; +Promise.race = race; +Promise.resolve = resolve; +Promise.reject = reject; +Promise._setScheduler = setScheduler; +Promise._setAsap = setAsap; +Promise._asap = asap; + +Promise.prototype = { + constructor: Promise, + + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + + Chaining + -------- + + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we're unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + + Assimilation + ------------ + + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + + If the assimliated promise rejects, then the downstream promise will also reject. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + + Simple Example + -------------- + + Synchronous Example + + ```javascript + let result; + + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + + Promise Example; + + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + + Advanced Example + -------------- + + Synchronous Example + + ```javascript + let author, books; + + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + + function foundBooks(books) { + + } + + function failure(reason) { + + } + + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + + Promise Example; + + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + + @method then + @param {Function} onFulfilled + @param {Function} onRejected + Useful for tooling. + @return {Promise} + */ + then: then, + + /** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + + ```js + function findAuthor(){ + throw new Error('couldn't find that author'); + } + + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + + @method catch + @param {Function} onRejection + Useful for tooling. + @return {Promise} + */ + 'catch': function _catch(onRejection) { + return this.then(null, onRejection); + } +}; + +function polyfill() { + var local = undefined; + + if (typeof global !== 'undefined') { + local = global; + } else if (typeof self !== 'undefined') { + local = self; + } else { + try { + local = Function('return this')(); + } catch (e) { + throw new Error('polyfill failed because global object is unavailable in this environment'); + } + } + + var P = local.Promise; + + if (P) { + var promiseToString = null; + try { + promiseToString = Object.prototype.toString.call(P.resolve()); + } catch (e) { + // silently ignored + } + + if (promiseToString === '[object Promise]' && !P.cast) { + return; + } + } + + local.Promise = Promise; +} + +polyfill(); +// Strange compat.. +Promise.polyfill = polyfill; +Promise.Promise = Promise; + +return Promise; + +}))); + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":15}],12:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); + err.context = er; + throw err; + } + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + args = Array.prototype.slice.call(arguments, 1); + handler.apply(this, args); + } + } else if (isObject(handler)) { + args = Array.prototype.slice.call(arguments, 1); + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.prototype.listenerCount = function(type) { + if (this._events) { + var evlistener = this._events[type]; + + if (isFunction(evlistener)) + return 1; + else if (evlistener) + return evlistener.length; + } + return 0; +}; + +EventEmitter.listenerCount = function(emitter, type) { + return emitter.listenerCount(type); +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],13:[function(require,module,exports){ +/** + * inspired by is-number + * but significantly simplified and sped up by ignoring number and string constructors + * ie these return false: + * new Number(1) + * new String('1') + */ + +'use strict'; + +/** + * Is this string all whitespace? + * This solution kind of makes my brain hurt, but it's significantly faster + * than !str.trim() or any other solution I could find. + * + * whitespace codes from: http://en.wikipedia.org/wiki/Whitespace_character + * and verified with: + * + * for(var i = 0; i < 65536; i++) { + * var s = String.fromCharCode(i); + * if(+s===0 && !s.trim()) console.log(i, s); + * } + * + * which counts a couple of these as *not* whitespace, but finds nothing else + * that *is* whitespace. Note that charCodeAt stops at 16 bits, but it appears + * that there are no whitespace characters above this, and code points above + * this do not map onto white space characters. + */ +function allBlankCharCodes(str){ + var l = str.length, + a; + for(var i = 0; i < l; i++) { + a = str.charCodeAt(i); + if((a < 9 || a > 13) && (a !== 32) && (a !== 133) && (a !== 160) && + (a !== 5760) && (a !== 6158) && (a < 8192 || a > 8205) && + (a !== 8232) && (a !== 8233) && (a !== 8239) && (a !== 8287) && + (a !== 8288) && (a !== 12288) && (a !== 65279)) { + return false; + } + } + return true; +} + +module.exports = function(n) { + var type = typeof n; + if(type === 'string') { + var original = n; + n = +n; + // whitespace strings cast to zero - filter them out + if(n===0 && allBlankCharCodes(original)) return false; + } + else if(type !== 'number') return false; + + return n - n < 1; +}; + +},{}],14:[function(require,module,exports){ +module.exports = fromQuat; + +/** + * Creates a matrix from a quaternion rotation. + * + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @returns {mat4} out + */ +function fromQuat(out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, + + xx = x * x2, + yx = y * x2, + yy = y * y2, + zx = z * x2, + zy = z * y2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; + + out[0] = 1 - yy - zz; + out[1] = yx + wz; + out[2] = zx - wy; + out[3] = 0; + + out[4] = yx - wz; + out[5] = 1 - xx - zz; + out[6] = zy + wx; + out[7] = 0; + + out[8] = zx + wy; + out[9] = zy - wx; + out[10] = 1 - xx - yy; + out[11] = 0; + + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + + return out; +}; +},{}],15:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],16:[function(require,module,exports){ +// TinyColor v1.4.1 +// https://github.com/bgrins/TinyColor +// Brian Grinstead, MIT License + +(function(Math) { + +var trimLeft = /^\s+/, + trimRight = /\s+$/, + tinyCounter = 0, + mathRound = Math.round, + mathMin = Math.min, + mathMax = Math.max, + mathRandom = Math.random; + +function tinycolor (color, opts) { + + color = (color) ? color : ''; + opts = opts || { }; + + // If input is already a tinycolor, return itself + if (color instanceof tinycolor) { + return color; + } + // If we are called as a function, call using new instead + if (!(this instanceof tinycolor)) { + return new tinycolor(color, opts); + } + + var rgb = inputToRGB(color); + this._originalInput = color, + this._r = rgb.r, + this._g = rgb.g, + this._b = rgb.b, + this._a = rgb.a, + this._roundA = mathRound(100*this._a) / 100, + this._format = opts.format || rgb.format; + this._gradientType = opts.gradientType; + + // Don't let the range of [0,255] come back in [0,1]. + // Potentially lose a little bit of precision here, but will fix issues where + // .5 gets interpreted as half of the total, instead of half of 1 + // If it was supposed to be 128, this was already taken care of by `inputToRgb` + if (this._r < 1) { this._r = mathRound(this._r); } + if (this._g < 1) { this._g = mathRound(this._g); } + if (this._b < 1) { this._b = mathRound(this._b); } + + this._ok = rgb.ok; + this._tc_id = tinyCounter++; +} + +tinycolor.prototype = { + isDark: function() { + return this.getBrightness() < 128; + }, + isLight: function() { + return !this.isDark(); + }, + isValid: function() { + return this._ok; + }, + getOriginalInput: function() { + return this._originalInput; + }, + getFormat: function() { + return this._format; + }, + getAlpha: function() { + return this._a; + }, + getBrightness: function() { + //http://www.w3.org/TR/AERT#color-contrast + var rgb = this.toRgb(); + return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; + }, + getLuminance: function() { + //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + var rgb = this.toRgb(); + var RsRGB, GsRGB, BsRGB, R, G, B; + RsRGB = rgb.r/255; + GsRGB = rgb.g/255; + BsRGB = rgb.b/255; + + if (RsRGB <= 0.03928) {R = RsRGB / 12.92;} else {R = Math.pow(((RsRGB + 0.055) / 1.055), 2.4);} + if (GsRGB <= 0.03928) {G = GsRGB / 12.92;} else {G = Math.pow(((GsRGB + 0.055) / 1.055), 2.4);} + if (BsRGB <= 0.03928) {B = BsRGB / 12.92;} else {B = Math.pow(((BsRGB + 0.055) / 1.055), 2.4);} + return (0.2126 * R) + (0.7152 * G) + (0.0722 * B); + }, + setAlpha: function(value) { + this._a = boundAlpha(value); + this._roundA = mathRound(100*this._a) / 100; + return this; + }, + toHsv: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; + }, + toHsvString: function() { + var hsv = rgbToHsv(this._r, this._g, this._b); + var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); + return (this._a == 1) ? + "hsv(" + h + ", " + s + "%, " + v + "%)" : + "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; + }, + toHsl: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; + }, + toHslString: function() { + var hsl = rgbToHsl(this._r, this._g, this._b); + var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); + return (this._a == 1) ? + "hsl(" + h + ", " + s + "%, " + l + "%)" : + "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; + }, + toHex: function(allow3Char) { + return rgbToHex(this._r, this._g, this._b, allow3Char); + }, + toHexString: function(allow3Char) { + return '#' + this.toHex(allow3Char); + }, + toHex8: function(allow4Char) { + return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char); + }, + toHex8String: function(allow4Char) { + return '#' + this.toHex8(allow4Char); + }, + toRgb: function() { + return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; + }, + toRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : + "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; + }, + toPercentageRgb: function() { + return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; + }, + toPercentageRgbString: function() { + return (this._a == 1) ? + "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : + "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; + }, + toName: function() { + if (this._a === 0) { + return "transparent"; + } + + if (this._a < 1) { + return false; + } + + return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; + }, + toFilter: function(secondColor) { + var hex8String = '#' + rgbaToArgbHex(this._r, this._g, this._b, this._a); + var secondHex8String = hex8String; + var gradientType = this._gradientType ? "GradientType = 1, " : ""; + + if (secondColor) { + var s = tinycolor(secondColor); + secondHex8String = '#' + rgbaToArgbHex(s._r, s._g, s._b, s._a); + } + + return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; + }, + toString: function(format) { + var formatSet = !!format; + format = format || this._format; + + var formattedString = false; + var hasAlpha = this._a < 1 && this._a >= 0; + var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); + + if (needsAlphaFormat) { + // Special case for "transparent", all other non-alpha formats + // will return rgba when there is transparency. + if (format === "name" && this._a === 0) { + return this.toName(); + } + return this.toRgbString(); + } + if (format === "rgb") { + formattedString = this.toRgbString(); + } + if (format === "prgb") { + formattedString = this.toPercentageRgbString(); + } + if (format === "hex" || format === "hex6") { + formattedString = this.toHexString(); + } + if (format === "hex3") { + formattedString = this.toHexString(true); + } + if (format === "hex4") { + formattedString = this.toHex8String(true); + } + if (format === "hex8") { + formattedString = this.toHex8String(); + } + if (format === "name") { + formattedString = this.toName(); + } + if (format === "hsl") { + formattedString = this.toHslString(); + } + if (format === "hsv") { + formattedString = this.toHsvString(); + } + + return formattedString || this.toHexString(); + }, + clone: function() { + return tinycolor(this.toString()); + }, + + _applyModification: function(fn, args) { + var color = fn.apply(null, [this].concat([].slice.call(args))); + this._r = color._r; + this._g = color._g; + this._b = color._b; + this.setAlpha(color._a); + return this; + }, + lighten: function() { + return this._applyModification(lighten, arguments); + }, + brighten: function() { + return this._applyModification(brighten, arguments); + }, + darken: function() { + return this._applyModification(darken, arguments); + }, + desaturate: function() { + return this._applyModification(desaturate, arguments); + }, + saturate: function() { + return this._applyModification(saturate, arguments); + }, + greyscale: function() { + return this._applyModification(greyscale, arguments); + }, + spin: function() { + return this._applyModification(spin, arguments); + }, + + _applyCombination: function(fn, args) { + return fn.apply(null, [this].concat([].slice.call(args))); + }, + analogous: function() { + return this._applyCombination(analogous, arguments); + }, + complement: function() { + return this._applyCombination(complement, arguments); + }, + monochromatic: function() { + return this._applyCombination(monochromatic, arguments); + }, + splitcomplement: function() { + return this._applyCombination(splitcomplement, arguments); + }, + triad: function() { + return this._applyCombination(triad, arguments); + }, + tetrad: function() { + return this._applyCombination(tetrad, arguments); + } +}; + +// If input is an object, force 1 into "1.0" to handle ratios properly +// String input requires "1.0" as input, so 1 will be treated as 1 +tinycolor.fromRatio = function(color, opts) { + if (typeof color == "object") { + var newColor = {}; + for (var i in color) { + if (color.hasOwnProperty(i)) { + if (i === "a") { + newColor[i] = color[i]; + } + else { + newColor[i] = convertToPercentage(color[i]); + } + } + } + color = newColor; + } + + return tinycolor(color, opts); +}; + +// Given a string or object, convert that input to RGB +// Possible string inputs: +// +// "red" +// "#f00" or "f00" +// "#ff0000" or "ff0000" +// "#ff000000" or "ff000000" +// "rgb 255 0 0" or "rgb (255, 0, 0)" +// "rgb 1.0 0 0" or "rgb (1, 0, 0)" +// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" +// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" +// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" +// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" +// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" +// +function inputToRGB(color) { + + var rgb = { r: 0, g: 0, b: 0 }; + var a = 1; + var s = null; + var v = null; + var l = null; + var ok = false; + var format = false; + + if (typeof color == "string") { + color = stringInputToObject(color); + } + + if (typeof color == "object") { + if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { + rgb = rgbToRgb(color.r, color.g, color.b); + ok = true; + format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { + s = convertToPercentage(color.s); + v = convertToPercentage(color.v); + rgb = hsvToRgb(color.h, s, v); + ok = true; + format = "hsv"; + } + else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { + s = convertToPercentage(color.s); + l = convertToPercentage(color.l); + rgb = hslToRgb(color.h, s, l); + ok = true; + format = "hsl"; + } + + if (color.hasOwnProperty("a")) { + a = color.a; + } + } + + a = boundAlpha(a); + + return { + ok: ok, + format: color.format || format, + r: mathMin(255, mathMax(rgb.r, 0)), + g: mathMin(255, mathMax(rgb.g, 0)), + b: mathMin(255, mathMax(rgb.b, 0)), + a: a + }; +} + + +// Conversion Functions +// -------------------- + +// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: +// + +// `rgbToRgb` +// Handle bounds / percentage checking to conform to CSS color spec +// +// *Assumes:* r, g, b in [0, 255] or [0, 1] +// *Returns:* { r, g, b } in [0, 255] +function rgbToRgb(r, g, b){ + return { + r: bound01(r, 255) * 255, + g: bound01(g, 255) * 255, + b: bound01(b, 255) * 255 + }; +} + +// `rgbToHsl` +// Converts an RGB color value to HSL. +// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] +// *Returns:* { h, s, l } in [0,1] +function rgbToHsl(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, l = (max + min) / 2; + + if(max == min) { + h = s = 0; // achromatic + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + + h /= 6; + } + + return { h: h, s: s, l: l }; +} + +// `hslToRgb` +// Converts an HSL color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] +function hslToRgb(h, s, l) { + var r, g, b; + + h = bound01(h, 360); + s = bound01(s, 100); + l = bound01(l, 100); + + function hue2rgb(p, q, t) { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + if(s === 0) { + r = g = b = l; // achromatic + } + else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// `rgbToHsv` +// Converts an RGB color value to HSV +// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] +// *Returns:* { h, s, v } in [0,1] +function rgbToHsv(r, g, b) { + + r = bound01(r, 255); + g = bound01(g, 255); + b = bound01(b, 255); + + var max = mathMax(r, g, b), min = mathMin(r, g, b); + var h, s, v = max; + + var d = max - min; + s = max === 0 ? 0 : d / max; + + if(max == min) { + h = 0; // achromatic + } + else { + switch(max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h, s: s, v: v }; +} + +// `hsvToRgb` +// Converts an HSV color value to RGB. +// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] +// *Returns:* { r, g, b } in the set [0, 255] + function hsvToRgb(h, s, v) { + + h = bound01(h, 360) * 6; + s = bound01(s, 100); + v = bound01(v, 100); + + var i = Math.floor(h), + f = h - i, + p = v * (1 - s), + q = v * (1 - f * s), + t = v * (1 - (1 - f) * s), + mod = i % 6, + r = [v, q, p, p, t, v][mod], + g = [t, v, v, q, p, p][mod], + b = [p, p, t, v, v, q][mod]; + + return { r: r * 255, g: g * 255, b: b * 255 }; +} + +// `rgbToHex` +// Converts an RGB color to hex +// Assumes r, g, and b are contained in the set [0, 255] +// Returns a 3 or 6 character hex +function rgbToHex(r, g, b, allow3Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + // Return a 3 character hex if possible + if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); + } + + return hex.join(""); +} + +// `rgbaToHex` +// Converts an RGBA color plus alpha transparency to hex +// Assumes r, g, b are contained in the set [0, 255] and +// a in [0, 1]. Returns a 4 or 8 character rgba hex +function rgbaToHex(r, g, b, a, allow4Char) { + + var hex = [ + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)), + pad2(convertDecimalToHex(a)) + ]; + + // Return a 4 character hex if possible + if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { + return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); + } + + return hex.join(""); +} + +// `rgbaToArgbHex` +// Converts an RGBA color to an ARGB Hex8 string +// Rarely used, but required for "toFilter()" +function rgbaToArgbHex(r, g, b, a) { + + var hex = [ + pad2(convertDecimalToHex(a)), + pad2(mathRound(r).toString(16)), + pad2(mathRound(g).toString(16)), + pad2(mathRound(b).toString(16)) + ]; + + return hex.join(""); +} + +// `equals` +// Can be called with any tinycolor input +tinycolor.equals = function (color1, color2) { + if (!color1 || !color2) { return false; } + return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); +}; + +tinycolor.random = function() { + return tinycolor.fromRatio({ + r: mathRandom(), + g: mathRandom(), + b: mathRandom() + }); +}; + + +// Modification Functions +// ---------------------- +// Thanks to less.js for some of the basics here +// + +function desaturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s -= amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function saturate(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.s += amount / 100; + hsl.s = clamp01(hsl.s); + return tinycolor(hsl); +} + +function greyscale(color) { + return tinycolor(color).desaturate(100); +} + +function lighten (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l += amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +function brighten(color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var rgb = tinycolor(color).toRgb(); + rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); + rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); + rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); + return tinycolor(rgb); +} + +function darken (color, amount) { + amount = (amount === 0) ? 0 : (amount || 10); + var hsl = tinycolor(color).toHsl(); + hsl.l -= amount / 100; + hsl.l = clamp01(hsl.l); + return tinycolor(hsl); +} + +// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. +// Values outside of this range will be wrapped into this range. +function spin(color, amount) { + var hsl = tinycolor(color).toHsl(); + var hue = (hsl.h + amount) % 360; + hsl.h = hue < 0 ? 360 + hue : hue; + return tinycolor(hsl); +} + +// Combination Functions +// --------------------- +// Thanks to jQuery xColor for some of the ideas behind these +// + +function complement(color) { + var hsl = tinycolor(color).toHsl(); + hsl.h = (hsl.h + 180) % 360; + return tinycolor(hsl); +} + +function triad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function tetrad(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), + tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) + ]; +} + +function splitcomplement(color) { + var hsl = tinycolor(color).toHsl(); + var h = hsl.h; + return [ + tinycolor(color), + tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), + tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) + ]; +} + +function analogous(color, results, slices) { + results = results || 6; + slices = slices || 30; + + var hsl = tinycolor(color).toHsl(); + var part = 360 / slices; + var ret = [tinycolor(color)]; + + for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { + hsl.h = (hsl.h + part) % 360; + ret.push(tinycolor(hsl)); + } + return ret; +} + +function monochromatic(color, results) { + results = results || 6; + var hsv = tinycolor(color).toHsv(); + var h = hsv.h, s = hsv.s, v = hsv.v; + var ret = []; + var modification = 1 / results; + + while (results--) { + ret.push(tinycolor({ h: h, s: s, v: v})); + v = (v + modification) % 1; + } + + return ret; +} + +// Utility Functions +// --------------------- + +tinycolor.mix = function(color1, color2, amount) { + amount = (amount === 0) ? 0 : (amount || 50); + + var rgb1 = tinycolor(color1).toRgb(); + var rgb2 = tinycolor(color2).toRgb(); + + var p = amount / 100; + + var rgba = { + r: ((rgb2.r - rgb1.r) * p) + rgb1.r, + g: ((rgb2.g - rgb1.g) * p) + rgb1.g, + b: ((rgb2.b - rgb1.b) * p) + rgb1.b, + a: ((rgb2.a - rgb1.a) * p) + rgb1.a + }; + + return tinycolor(rgba); +}; + + +// Readability Functions +// --------------------- +// false +// tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false +tinycolor.isReadable = function(color1, color2, wcag2) { + var readability = tinycolor.readability(color1, color2); + var wcag2Parms, out; + + out = false; + + wcag2Parms = validateWCAG2Parms(wcag2); + switch (wcag2Parms.level + wcag2Parms.size) { + case "AAsmall": + case "AAAlarge": + out = readability >= 4.5; + break; + case "AAlarge": + out = readability >= 3; + break; + case "AAAsmall": + out = readability >= 7; + break; + } + return out; + +}; + +// `mostReadable` +// Given a base color and a list of possible foreground or background +// colors for that base, returns the most readable color. +// Optionally returns Black or White if the most readable color is unreadable. +// *Example* +// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" +// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" +// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" +// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" +tinycolor.mostReadable = function(baseColor, colorList, args) { + var bestColor = null; + var bestScore = 0; + var readability; + var includeFallbackColors, level, size ; + args = args || {}; + includeFallbackColors = args.includeFallbackColors ; + level = args.level; + size = args.size; + + for (var i= 0; i < colorList.length ; i++) { + readability = tinycolor.readability(baseColor, colorList[i]); + if (readability > bestScore) { + bestScore = readability; + bestColor = tinycolor(colorList[i]); + } + } + + if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) { + return bestColor; + } + else { + args.includeFallbackColors=false; + return tinycolor.mostReadable(baseColor,["#fff", "#000"],args); + } +}; + + +// Big List of Colors +// ------------------ +// +var names = tinycolor.names = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + burntsienna: "ea7e5d", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "f0f", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + grey: "808080", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + rebeccapurple: "663399", + red: "f00", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32" +}; + +// Make it easy to access colors via `hexNames[hex]` +var hexNames = tinycolor.hexNames = flip(names); + + +// Utilities +// --------- + +// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` +function flip(o) { + var flipped = { }; + for (var i in o) { + if (o.hasOwnProperty(i)) { + flipped[o[i]] = i; + } + } + return flipped; +} + +// Return a valid alpha value [0,1] with all invalid values being set to 1 +function boundAlpha(a) { + a = parseFloat(a); + + if (isNaN(a) || a < 0 || a > 1) { + a = 1; + } + + return a; +} + +// Take input from [0, n] and return it as [0, 1] +function bound01(n, max) { + if (isOnePointZero(n)) { n = "100%"; } + + var processPercent = isPercentage(n); + n = mathMin(max, mathMax(0, parseFloat(n))); + + // Automatically convert percentage into number + if (processPercent) { + n = parseInt(n * max, 10) / 100; + } + + // Handle floating point rounding errors + if ((Math.abs(n - max) < 0.000001)) { + return 1; + } + + // Convert into [0, 1] range if it isn't already + return (n % max) / parseFloat(max); +} + +// Force a number between 0 and 1 +function clamp01(val) { + return mathMin(1, mathMax(0, val)); +} + +// Parse a base-16 hex value into a base-10 integer +function parseIntFromHex(val) { + return parseInt(val, 16); +} + +// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 +// +function isOnePointZero(n) { + return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; +} + +// Check to see if string passed in is a percentage +function isPercentage(n) { + return typeof n === "string" && n.indexOf('%') != -1; +} + +// Force a hex value to have 2 characters +function pad2(c) { + return c.length == 1 ? '0' + c : '' + c; +} + +// Replace a decimal with it's percentage value +function convertToPercentage(n) { + if (n <= 1) { + n = (n * 100) + "%"; + } + + return n; +} + +// Converts a decimal to a hex value +function convertDecimalToHex(d) { + return Math.round(parseFloat(d) * 255).toString(16); +} +// Converts a hex value to a decimal +function convertHexToDecimal(h) { + return (parseIntFromHex(h) / 255); +} + +var matchers = (function() { + + // + var CSS_INTEGER = "[-\\+]?\\d+%?"; + + // + var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; + + // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. + var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; + + // Actual matching. + // Parentheses and commas are optional, but not required. + // Whitespace can take the place of commas or opening paren + var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; + + return { + CSS_UNIT: new RegExp(CSS_UNIT), + rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), + rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), + hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), + hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), + hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), + hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), + hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, + hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, + hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ + }; +})(); + +// `isValidCSSUnit` +// Take in a single string / number and check to see if it looks like a CSS unit +// (see `matchers` above for definition). +function isValidCSSUnit(color) { + return !!matchers.CSS_UNIT.exec(color); +} + +// `stringInputToObject` +// Permissive string parsing. Take in a number of formats, and output an object +// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` +function stringInputToObject(color) { + + color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); + var named = false; + if (names[color]) { + color = names[color]; + named = true; + } + else if (color == 'transparent') { + return { r: 0, g: 0, b: 0, a: 0, format: "name" }; + } + + // Try to match string input using regular expressions. + // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] + // Just return an object and let the conversion functions handle that. + // This way the result will be the same whether the tinycolor is initialized with string or object. + var match; + if ((match = matchers.rgb.exec(color))) { + return { r: match[1], g: match[2], b: match[3] }; + } + if ((match = matchers.rgba.exec(color))) { + return { r: match[1], g: match[2], b: match[3], a: match[4] }; + } + if ((match = matchers.hsl.exec(color))) { + return { h: match[1], s: match[2], l: match[3] }; + } + if ((match = matchers.hsla.exec(color))) { + return { h: match[1], s: match[2], l: match[3], a: match[4] }; + } + if ((match = matchers.hsv.exec(color))) { + return { h: match[1], s: match[2], v: match[3] }; + } + if ((match = matchers.hsva.exec(color))) { + return { h: match[1], s: match[2], v: match[3], a: match[4] }; + } + if ((match = matchers.hex8.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + a: convertHexToDecimal(match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex6.exec(color))) { + return { + r: parseIntFromHex(match[1]), + g: parseIntFromHex(match[2]), + b: parseIntFromHex(match[3]), + format: named ? "name" : "hex" + }; + } + if ((match = matchers.hex4.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + a: convertHexToDecimal(match[4] + '' + match[4]), + format: named ? "name" : "hex8" + }; + } + if ((match = matchers.hex3.exec(color))) { + return { + r: parseIntFromHex(match[1] + '' + match[1]), + g: parseIntFromHex(match[2] + '' + match[2]), + b: parseIntFromHex(match[3] + '' + match[3]), + format: named ? "name" : "hex" + }; + } + + return false; +} + +function validateWCAG2Parms(parms) { + // return valid WCAG2 parms for isReadable. + // If input parms are invalid, return {"level":"AA", "size":"small"} + var level, size; + parms = parms || {"level":"AA", "size":"small"}; + level = (parms.level || "AA").toUpperCase(); + size = (parms.size || "small").toLowerCase(); + if (level !== "AA" && level !== "AAA") { + level = "AA"; + } + if (size !== "small" && size !== "large") { + size = "small"; + } + return {"level":level, "size":size}; +} + +// Node: Export function +if (typeof module !== "undefined" && module.exports) { + module.exports = tinycolor; +} +// AMD/requirejs: Define the module +else if (typeof define === 'function' && define.amd) { + define(function () {return tinycolor;}); +} +// Browser: Expose to window +else { + window.tinycolor = tinycolor; +} + +})(Math); + +},{}],17:[function(require,module,exports){ +// https://github.com/topojson/topojson-client Version 2.1.0. Copyright 2016 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.topojson = global.topojson || {}))); +}(this, (function (exports) { 'use strict'; + +var identity = function(x) { + return x; +}; + +var transform = function(topology) { + if ((transform = topology.transform) == null) return identity; + var transform, + x0, + y0, + kx = transform.scale[0], + ky = transform.scale[1], + dx = transform.translate[0], + dy = transform.translate[1]; + return function(point, i) { + if (!i) x0 = y0 = 0; + point[0] = (x0 += point[0]) * kx + dx; + point[1] = (y0 += point[1]) * ky + dy; + return point; + }; +}; + +var bbox = function(topology) { + var bbox = topology.bbox; + + function bboxPoint(p0) { + p1[0] = p0[0], p1[1] = p0[1], t(p1); + if (p1[0] < x0) x0 = p1[0]; + if (p1[0] > x1) x1 = p1[0]; + if (p1[1] < y0) y0 = p1[1]; + if (p1[1] > y1) y1 = p1[1]; + } + + function bboxGeometry(o) { + switch (o.type) { + case "GeometryCollection": o.geometries.forEach(bboxGeometry); break; + case "Point": bboxPoint(o.coordinates); break; + case "MultiPoint": o.coordinates.forEach(bboxPoint); break; + } + } + + if (!bbox) { + var t = transform(topology), p0, p1 = new Array(2), name, + x0 = Infinity, y0 = x0, x1 = -x0, y1 = -x0; + + topology.arcs.forEach(function(arc) { + var i = -1, n = arc.length; + while (++i < n) { + p0 = arc[i], p1[0] = p0[0], p1[1] = p0[1], t(p1, i); + if (p1[0] < x0) x0 = p1[0]; + if (p1[0] > x1) x1 = p1[0]; + if (p1[1] < y0) y0 = p1[1]; + if (p1[1] > y1) y1 = p1[1]; + } + }); + + for (name in topology.objects) { + bboxGeometry(topology.objects[name]); + } + + bbox = topology.bbox = [x0, y0, x1, y1]; + } + + return bbox; +}; + +var reverse = function(array, n) { + var t, j = array.length, i = j - n; + while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; +}; + +var feature = function(topology, o) { + return o.type === "GeometryCollection" + ? {type: "FeatureCollection", features: o.geometries.map(function(o) { return feature$1(topology, o); })} + : feature$1(topology, o); +}; + +function feature$1(topology, o) { + var id = o.id, + bbox = o.bbox, + properties = o.properties == null ? {} : o.properties, + geometry = object(topology, o); + return id == null && bbox == null ? {type: "Feature", properties: properties, geometry: geometry} + : bbox == null ? {type: "Feature", id: id, properties: properties, geometry: geometry} + : {type: "Feature", id: id, bbox: bbox, properties: properties, geometry: geometry}; +} + +function object(topology, o) { + var transformPoint = transform(topology), + arcs = topology.arcs; + + function arc(i, points) { + if (points.length) points.pop(); + for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) { + points.push(transformPoint(a[k].slice(), k)); + } + if (i < 0) reverse(points, n); + } + + function point(p) { + return transformPoint(p.slice()); + } + + function line(arcs) { + var points = []; + for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); + if (points.length < 2) points.push(points[0].slice()); + return points; + } + + function ring(arcs) { + var points = line(arcs); + while (points.length < 4) points.push(points[0].slice()); + return points; + } + + function polygon(arcs) { + return arcs.map(ring); + } + + function geometry(o) { + var type = o.type, coordinates; + switch (type) { + case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)}; + case "Point": coordinates = point(o.coordinates); break; + case "MultiPoint": coordinates = o.coordinates.map(point); break; + case "LineString": coordinates = line(o.arcs); break; + case "MultiLineString": coordinates = o.arcs.map(line); break; + case "Polygon": coordinates = polygon(o.arcs); break; + case "MultiPolygon": coordinates = o.arcs.map(polygon); break; + default: return null; + } + return {type: type, coordinates: coordinates}; + } + + return geometry(o); +} + +var stitch = function(topology, arcs) { + var stitchedArcs = {}, + fragmentByStart = {}, + fragmentByEnd = {}, + fragments = [], + emptyIndex = -1; + + // Stitch empty arcs first, since they may be subsumed by other arcs. + arcs.forEach(function(i, j) { + var arc = topology.arcs[i < 0 ? ~i : i], t; + if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { + t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; + } + }); + + arcs.forEach(function(i) { + var e = ends(i), + start = e[0], + end = e[1], + f, g; + + if (f = fragmentByEnd[start]) { + delete fragmentByEnd[f.end]; + f.push(i); + f.end = end; + if (g = fragmentByStart[end]) { + delete fragmentByStart[g.start]; + var fg = g === f ? f : f.concat(g); + fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; + } else { + fragmentByStart[f.start] = fragmentByEnd[f.end] = f; + } + } else if (f = fragmentByStart[end]) { + delete fragmentByStart[f.start]; + f.unshift(i); + f.start = start; + if (g = fragmentByEnd[start]) { + delete fragmentByEnd[g.end]; + var gf = g === f ? f : g.concat(f); + fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; + } else { + fragmentByStart[f.start] = fragmentByEnd[f.end] = f; + } + } else { + f = [i]; + fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; + } + }); + + function ends(i) { + var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; + if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); + else p1 = arc[arc.length - 1]; + return i < 0 ? [p1, p0] : [p0, p1]; + } + + function flush(fragmentByEnd, fragmentByStart) { + for (var k in fragmentByEnd) { + var f = fragmentByEnd[k]; + delete fragmentByStart[f.start]; + delete f.start; + delete f.end; + f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); + fragments.push(f); + } + } + + flush(fragmentByEnd, fragmentByStart); + flush(fragmentByStart, fragmentByEnd); + arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); + + return fragments; +}; + +var mesh = function(topology) { + return object(topology, meshArcs.apply(this, arguments)); +}; + +function meshArcs(topology, object$$1, filter) { + var arcs, i, n; + if (arguments.length > 1) arcs = extractArcs(topology, object$$1, filter); + else for (i = 0, arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i; + return {type: "MultiLineString", arcs: stitch(topology, arcs)}; +} + +function extractArcs(topology, object$$1, filter) { + var arcs = [], + geomsByArc = [], + geom; + + function extract0(i) { + var j = i < 0 ? ~i : i; + (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); + } + + function extract1(arcs) { + arcs.forEach(extract0); + } + + function extract2(arcs) { + arcs.forEach(extract1); + } + + function extract3(arcs) { + arcs.forEach(extract2); + } + + function geometry(o) { + switch (geom = o, o.type) { + case "GeometryCollection": o.geometries.forEach(geometry); break; + case "LineString": extract1(o.arcs); break; + case "MultiLineString": case "Polygon": extract2(o.arcs); break; + case "MultiPolygon": extract3(o.arcs); break; + } + } + + geometry(object$$1); + + geomsByArc.forEach(filter == null + ? function(geoms) { arcs.push(geoms[0].i); } + : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); + + return arcs; +} + +function planarRingArea(ring) { + var i = -1, n = ring.length, a, b = ring[n - 1], area = 0; + while (++i < n) a = b, b = ring[i], area += a[0] * b[1] - a[1] * b[0]; + return Math.abs(area); // Note: doubled area! +} + +var merge = function(topology) { + return object(topology, mergeArcs.apply(this, arguments)); +}; + +function mergeArcs(topology, objects) { + var polygonsByArc = {}, + polygons = [], + groups = []; + + objects.forEach(geometry); + + function geometry(o) { + switch (o.type) { + case "GeometryCollection": o.geometries.forEach(geometry); break; + case "Polygon": extract(o.arcs); break; + case "MultiPolygon": o.arcs.forEach(extract); break; + } + } + + function extract(polygon) { + polygon.forEach(function(ring) { + ring.forEach(function(arc) { + (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); + }); + }); + polygons.push(polygon); + } + + function area(ring) { + return planarRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]); + } + + polygons.forEach(function(polygon) { + if (!polygon._) { + var group = [], + neighbors = [polygon]; + polygon._ = 1; + groups.push(group); + while (polygon = neighbors.pop()) { + group.push(polygon); + polygon.forEach(function(ring) { + ring.forEach(function(arc) { + polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { + if (!polygon._) { + polygon._ = 1; + neighbors.push(polygon); + } + }); + }); + }); + } + } + }); + + polygons.forEach(function(polygon) { + delete polygon._; + }); + + return { + type: "MultiPolygon", + arcs: groups.map(function(polygons) { + var arcs = [], n; + + // Extract the exterior (unique) arcs. + polygons.forEach(function(polygon) { + polygon.forEach(function(ring) { + ring.forEach(function(arc) { + if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { + arcs.push(arc); + } + }); + }); + }); + + // Stitch the arcs into one or more rings. + arcs = stitch(topology, arcs); + + // If more than one ring is returned, + // at most one of these rings can be the exterior; + // choose the one with the greatest absolute area. + if ((n = arcs.length) > 1) { + for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { + if ((ki = area(arcs[i])) > k) { + t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; + } + } + } + + return arcs; + }) + }; +} + +var bisect = function(a, x) { + var lo = 0, hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (a[mid] < x) lo = mid + 1; + else hi = mid; + } + return lo; +}; + +var neighbors = function(objects) { + var indexesByArc = {}, // arc index -> array of object indexes + neighbors = objects.map(function() { return []; }); + + function line(arcs, i) { + arcs.forEach(function(a) { + if (a < 0) a = ~a; + var o = indexesByArc[a]; + if (o) o.push(i); + else indexesByArc[a] = [i]; + }); + } + + function polygon(arcs, i) { + arcs.forEach(function(arc) { line(arc, i); }); + } + + function geometry(o, i) { + if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); + else if (o.type in geometryType) geometryType[o.type](o.arcs, i); + } + + var geometryType = { + LineString: line, + MultiLineString: polygon, + Polygon: polygon, + MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } + }; + + objects.forEach(geometry); + + for (var i in indexesByArc) { + for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { + for (var k = j + 1; k < m; ++k) { + var ij = indexes[j], ik = indexes[k], n; + if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); + if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); + } + } + } + + return neighbors; +}; + +var quantize = function(topology, n) { + if (!((n = Math.floor(n)) >= 2)) throw new Error("n must be ≥2"); + if (topology.transform) throw new Error("already quantized"); + var bb = bbox(topology), name, + dx = bb[0], kx = (bb[2] - dx) / (n - 1) || 1, + dy = bb[1], ky = (bb[3] - dy) / (n - 1) || 1; + + function quantizePoint(p) { + p[0] = Math.round((p[0] - dx) / kx); + p[1] = Math.round((p[1] - dy) / ky); + } + + function quantizeGeometry(o) { + switch (o.type) { + case "GeometryCollection": o.geometries.forEach(quantizeGeometry); break; + case "Point": quantizePoint(o.coordinates); break; + case "MultiPoint": o.coordinates.forEach(quantizePoint); break; + } + } + + topology.arcs.forEach(function(arc) { + var i = 1, + j = 1, + n = arc.length, + pi = arc[0], + x0 = pi[0] = Math.round((pi[0] - dx) / kx), + y0 = pi[1] = Math.round((pi[1] - dy) / ky), + pj, + x1, + y1; + + for (; i < n; ++i) { + pi = arc[i]; + x1 = Math.round((pi[0] - dx) / kx); + y1 = Math.round((pi[1] - dy) / ky); + if (x1 !== x0 || y1 !== y0) { + pj = arc[j++]; + pj[0] = x1 - x0, x0 = x1; + pj[1] = y1 - y0, y0 = y1; + } + } + + if (j < 2) { + pj = arc[j++]; + pj[0] = 0; + pj[1] = 0; + } + + arc.length = j; + }); + + for (name in topology.objects) { + quantizeGeometry(topology.objects[name]); + } + + topology.transform = { + scale: [kx, ky], + translate: [dx, dy] + }; + + return topology; +}; + +var untransform = function(topology) { + if ((transform = topology.transform) == null) return identity; + var transform, + x0, + y0, + kx = transform.scale[0], + ky = transform.scale[1], + dx = transform.translate[0], + dy = transform.translate[1]; + return function(point, i) { + if (!i) x0 = y0 = 0; + var x1 = Math.round((point[0] - dx) / kx), + y1 = Math.round((point[1] - dy) / ky); + point[0] = x1 - x0, x0 = x1; + point[1] = y1 - y0, y0 = y1; + return point; + }; +}; + +exports.bbox = bbox; +exports.feature = feature; +exports.mesh = mesh; +exports.meshArcs = meshArcs; +exports.merge = merge; +exports.mergeArcs = mergeArcs; +exports.neighbors = neighbors; +exports.quantize = quantize; +exports.transform = transform; +exports.untransform = untransform; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],18:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var Color = require('../color'); +var Axes = require('../../plots/cartesian/axes'); + +var attributes = require('./attributes'); + + +module.exports = function handleAnnotationDefaults(annIn, annOut, fullLayout, opts, itemOpts) { + opts = opts || {}; + itemOpts = itemOpts || {}; + + function coerce(attr, dflt) { + return Lib.coerce(annIn, annOut, attributes, attr, dflt); + } + + var visible = coerce('visible', !itemOpts.itemIsNotPlainObject); + + if(!visible) return annOut; + + coerce('opacity'); + coerce('align'); + coerce('bgcolor'); + + var borderColor = coerce('bordercolor'), + borderOpacity = Color.opacity(borderColor); + + coerce('borderpad'); + + var borderWidth = coerce('borderwidth'); + var showArrow = coerce('showarrow'); + + coerce('text', showArrow ? ' ' : 'new text'); + coerce('textangle'); + Lib.coerceFont(coerce, 'font', fullLayout.font); + + // positioning + var axLetters = ['x', 'y'], + arrowPosDflt = [-10, -30], + gdMock = {_fullLayout: fullLayout}; + for(var i = 0; i < 2; i++) { + var axLetter = axLetters[i]; + + // xref, yref + var axRef = Axes.coerceRef(annIn, annOut, gdMock, axLetter, '', 'paper'); + + // x, y + Axes.coercePosition(annOut, gdMock, coerce, axRef, axLetter, 0.5); + + if(showArrow) { + var arrowPosAttr = 'a' + axLetter, + // axref, ayref + aaxRef = Axes.coerceRef(annIn, annOut, gdMock, arrowPosAttr, 'pixel'); + + // for now the arrow can only be on the same axis or specified as pixels + // TODO: sometime it might be interesting to allow it to be on *any* axis + // but that would require updates to drawing & autorange code and maybe more + if(aaxRef !== 'pixel' && aaxRef !== axRef) { + aaxRef = annOut[arrowPosAttr] = 'pixel'; + } + + // ax, ay + var aDflt = (aaxRef === 'pixel') ? arrowPosDflt[i] : 0.4; + Axes.coercePosition(annOut, gdMock, coerce, aaxRef, arrowPosAttr, aDflt); + } + + // xanchor, yanchor + else coerce(axLetter + 'anchor'); + } + + // if you have one coordinate you should have both + Lib.noneOrAll(annIn, annOut, ['x', 'y']); + + if(showArrow) { + coerce('arrowcolor', borderOpacity ? annOut.bordercolor : Color.defaultLine); + coerce('arrowhead'); + coerce('arrowsize'); + coerce('arrowwidth', ((borderOpacity && borderWidth) || 1) * 2); + + // if you have one part of arrow length you should have both + Lib.noneOrAll(annIn, annOut, ['ax', 'ay']); + } + + if (annIn.classes) { + annOut.classes = annIn.classes; + } + + return annOut; +}; + +},{"../../lib":122,"../../plots/cartesian/axes":150,"../color":27,"./attributes":20}],19:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * centerx is a center of scaling tuned for maximum scalability of + * the arrowhead ie throughout mag=0.3..3 the head is joined smoothly + * to the line, but the endpoint moves. + * backoff is the distance to move the arrowhead, and the end of the + * line, in order to end at the right place + * + * TODO: option to have the pointed-to point a little in front of the + * end of the line, as people tend to want a bit of a gap there... + */ + +module.exports = [ + // no arrow + '', + // wide with flat back + { + path: 'M-2.4,-3V3L0.6,0Z', + backoff: 0.6 + }, + // narrower with flat back + { + path: 'M-3.7,-2.5V2.5L1.3,0Z', + backoff: 1.3 + }, + // barbed + { + path: 'M-4.45,-3L-1.65,-0.2V0.2L-4.45,3L1.55,0Z', + backoff: 1.55 + }, + // wide line-drawn + { + path: 'M-2.2,-2.2L-0.2,-0.2V0.2L-2.2,2.2L-1.4,3L1.6,0L-1.4,-3Z', + backoff: 1.6 + }, + // narrower line-drawn + { + path: 'M-4.4,-2.1L-0.6,-0.2V0.2L-4.4,2.1L-4,3L2,0L-4,-3Z', + backoff: 2 + }, + // circle + { + path: 'M2,0A2,2 0 1,1 0,-2A2,2 0 0,1 2,0Z', + backoff: 0 + }, + // square + { + path: 'M2,2V-2H-2V2Z', + backoff: 0 + } +]; + +},{}],20:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var ARROWPATHS = require('./arrow_paths'); +var fontAttrs = require('../../plots/font_attributes'); +var cartesianConstants = require('../../plots/cartesian/constants'); +var extendFlat = require('../../lib/extend').extendFlat; + + +module.exports = { + _isLinkedToArray: 'annotation', + + visible: { + valType: 'boolean', + + dflt: true, + + }, + + text: { + valType: 'string', + + + }, + textangle: { + valType: 'angle', + dflt: 0, + + + }, + font: extendFlat({}, fontAttrs, { + + }), + opacity: { + valType: 'number', + min: 0, + max: 1, + dflt: 1, + + + }, + align: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'center', + + + }, + bgcolor: { + valType: 'color', + dflt: 'rgba(0,0,0,0)', + + + }, + bordercolor: { + valType: 'color', + dflt: 'rgba(0,0,0,0)', + + + }, + borderpad: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + // arrow + showarrow: { + valType: 'boolean', + dflt: true, + + + }, + arrowcolor: { + valType: 'color', + + + }, + arrowhead: { + valType: 'integer', + min: 0, + max: ARROWPATHS.length, + dflt: 1, + + + }, + arrowsize: { + valType: 'number', + min: 0.3, + dflt: 1, + + + }, + arrowwidth: { + valType: 'number', + min: 0.1, + + + }, + ax: { + valType: 'any', + + + }, + ay: { + valType: 'any', + + + }, + axref: { + valType: 'enumerated', + dflt: 'pixel', + values: [ + 'pixel', + cartesianConstants.idRegex.x.toString() + ], + + + }, + ayref: { + valType: 'enumerated', + dflt: 'pixel', + values: [ + 'pixel', + cartesianConstants.idRegex.y.toString() + ], + + + }, + // positioning + xref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.x.toString() + ], + + + }, + x: { + valType: 'any', + + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'auto', + + + }, + yref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.y.toString() + ], + + + }, + y: { + valType: 'any', + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'auto', + + + }, + + _deprecated: { + ref: { + valType: 'string', + + + } + } +}; + +},{"../../lib/extend":117,"../../plots/cartesian/constants":155,"../../plots/font_attributes":170,"./arrow_paths":19}],21:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var Axes = require('../../plots/cartesian/axes'); + +var draw = require('./draw').draw; + + +module.exports = function calcAutorange(gd) { + var fullLayout = gd._fullLayout, + annotationList = Lib.filterVisible(fullLayout.annotations); + + if(!annotationList.length || !gd._fullData.length) return; + + var annotationAxes = {}; + annotationList.forEach(function(ann) { + annotationAxes[ann.xref] = true; + annotationAxes[ann.yref] = true; + }); + + var autorangedAnnos = Axes.list(gd).filter(function(ax) { + return ax.autorange && annotationAxes[ax._id]; + }); + if(!autorangedAnnos.length) return; + + return Lib.syncOrAsync([ + draw, + annAutorange + ], gd); +}; + +function annAutorange(gd) { + var fullLayout = gd._fullLayout; + + // find the bounding boxes for each of these annotations' + // relative to their anchor points + // use the arrow and the text bg rectangle, + // as the whole anno may include hidden text in its bbox + fullLayout.annotations.forEach(function(ann) { + var xa = Axes.getFromId(gd, ann.xref), + ya = Axes.getFromId(gd, ann.yref); + + if(!(xa || ya)) return; + + var halfWidth = (ann._xsize || 0) / 2, + xShift = ann._xshift || 0, + halfHeight = (ann._ysize || 0) / 2, + yShift = ann._yshift || 0, + leftSize = halfWidth - xShift, + rightSize = halfWidth + xShift, + topSize = halfHeight - yShift, + bottomSize = halfHeight + yShift; + + if(ann.showarrow) { + var headSize = 3 * ann.arrowsize * ann.arrowwidth; + leftSize = Math.max(leftSize, headSize); + rightSize = Math.max(rightSize, headSize); + topSize = Math.max(topSize, headSize); + bottomSize = Math.max(bottomSize, headSize); + } + + if(xa && xa.autorange) { + Axes.expand(xa, [xa.l2c(xa.r2l(ann.x))], { + ppadplus: rightSize, + ppadminus: leftSize + }); + } + + if(ya && ya.autorange) { + Axes.expand(ya, [ya.l2c(ya.r2l(ann.y))], { + ppadplus: bottomSize, + ppadminus: topSize + }); + } + }); +} + +},{"../../lib":122,"../../plots/cartesian/axes":150,"./draw":23}],22:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); +var handleAnnotationDefaults = require('./annotation_defaults'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + var opts = { + name: 'annotations', + handleItemDefaults: handleAnnotationDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + +},{"../../plots/array_container_defaults":147,"./annotation_defaults":18}],23:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Plotly = require('../../plotly'); +var Plots = require('../../plots/plots'); +var Lib = require('../../lib'); +var Axes = require('../../plots/cartesian/axes'); +var Color = require('../color'); +var Drawing = require('../drawing'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var setCursor = require('../../lib/setcursor'); +var dragElement = require('../dragelement'); + +var handleAnnotationDefaults = require('./annotation_defaults'); +var supplyLayoutDefaults = require('./defaults'); +var arrowhead = require('./draw_arrow_head'); + + +// Annotations are stored in gd.layout.annotations, an array of objects +// index can point to one item in this array, +// or non-numeric to simply add a new one +// or -1 to modify all existing +// opt can be the full options object, or one key (to be set to value) +// or undefined to simply redraw +// if opt is blank, val can be 'add' or a full options object to add a new +// annotation at that point in the array, or 'remove' to delete this one + +module.exports = { + draw: draw, + drawOne: drawOne +}; + +function draw(gd) { + var fullLayout = gd._fullLayout; + + fullLayout._infolayer.selectAll('.annotation').remove(); + + for(var i = 0; i < fullLayout.annotations.length; i++) { + if(fullLayout.annotations[i].visible) { + drawOne(gd, i); + } + } + + return Plots.previousPromises(gd); +} + +function drawOne(gd, index, opt, value) { + var layout = gd.layout, + fullLayout = gd._fullLayout, + i; + + if(!isNumeric(index) || index === -1) { + + // no index provided - we're operating on ALL annotations + if(!index && Array.isArray(value)) { + // a whole annotation array is passed in + // (as in, redo of delete all) + layout.annotations = value; + supplyLayoutDefaults(layout, fullLayout); + draw(gd); + return; + } + else if(value === 'remove') { + // delete all + delete layout.annotations; + fullLayout.annotations = []; + draw(gd); + return; + } + else if(opt && value !== 'add') { + // make the same change to all annotations + for(i = 0; i < fullLayout.annotations.length; i++) { + drawOne(gd, i, opt, value); + } + return; + } + else { + // add a new empty annotation + index = fullLayout.annotations.length; + fullLayout.annotations.push({}); + } + } + + if(!opt && value) { + if(value === 'remove') { + fullLayout._infolayer.selectAll('.annotation[data-index="' + index + '"]') + .remove(); + fullLayout.annotations.splice(index, 1); + layout.annotations.splice(index, 1); + for(i = index; i < fullLayout.annotations.length; i++) { + fullLayout._infolayer + .selectAll('.annotation[data-index="' + (i + 1) + '"]') + .attr('data-index', String(i)); + + // redraw all annotations past the removed one, + // so they bind to the right events + drawOne(gd, i); + } + return; + } + else if(value === 'add' || Lib.isPlainObject(value)) { + fullLayout.annotations.splice(index, 0, {}); + + var rule = Lib.isPlainObject(value) ? + Lib.extendFlat({}, value) : + {text: 'New text'}; + + if(layout.annotations) { + layout.annotations.splice(index, 0, rule); + } else { + layout.annotations = [rule]; + } + + for(i = fullLayout.annotations.length - 1; i > index; i--) { + fullLayout._infolayer + .selectAll('.annotation[data-index="' + (i - 1) + '"]') + .attr('data-index', String(i)); + drawOne(gd, i); + } + } + } + + // remove the existing annotation if there is one + fullLayout._infolayer.selectAll('.annotation[data-index="' + index + '"]').remove(); + + // remember a few things about what was already there, + var optionsIn = layout.annotations[index], + oldPrivate = fullLayout.annotations[index]; + + // not sure how we're getting here... but C12 is seeing a bug + // where we fail here when they add/remove annotations + if(!optionsIn) return; + + // alter the input annotation as requested + var optionsEdit = {}; + if(typeof opt === 'string' && opt) optionsEdit[opt] = value; + else if(Lib.isPlainObject(opt)) optionsEdit = opt; + + var optionKeys = Object.keys(optionsEdit); + for(i = 0; i < optionKeys.length; i++) { + var k = optionKeys[i]; + Lib.nestedProperty(optionsIn, k).set(optionsEdit[k]); + } + + // return early in visible: false updates + if(optionsIn.visible === false) return; + + var gs = fullLayout._size; + var oldRef = {xref: optionsIn.xref, yref: optionsIn.yref}; + + var axLetters = ['x', 'y']; + for(i = 0; i < 2; i++) { + var axLetter = axLetters[i]; + // if we don't have an explicit position already, + // don't set one just because we're changing references + // or axis type. + // the defaults will be consistent most of the time anyway, + // except in log/linear changes + if(optionsEdit[axLetter] !== undefined || + optionsIn[axLetter] === undefined) { + continue; + } + + var axOld = Axes.getFromId(gd, Axes.coerceRef(oldRef, {}, gd, axLetter, '', 'paper')), + axNew = Axes.getFromId(gd, Axes.coerceRef(optionsIn, {}, gd, axLetter, '', 'paper')), + position = optionsIn[axLetter], + axTypeOld = oldPrivate['_' + axLetter + 'type']; + + if(optionsEdit[axLetter + 'ref'] !== undefined) { + + // TODO: include ax / ay / axref / ayref here if not 'pixel' + // or even better, move all of this machinery out of here and into + // streambed as extra attributes to a regular relayout call + // we should do this after v2.0 when it can work equivalently for + // annotations, shapes, and images. + + var autoAnchor = optionsIn[axLetter + 'anchor'] === 'auto', + plotSize = (axLetter === 'x' ? gs.w : gs.h), + halfSizeFrac = (oldPrivate['_' + axLetter + 'size'] || 0) / + (2 * plotSize); + if(axOld && axNew) { // data -> different data + // go to the same fraction of the axis length + // whether or not these axes share a domain + + position = axNew.fraction2r(axOld.r2fraction(position)); + } + else if(axOld) { // data -> paper + // first convert to fraction of the axis + position = axOld.r2fraction(position); + + // next scale the axis to the whole plot + position = axOld.domain[0] + + position * (axOld.domain[1] - axOld.domain[0]); + + // finally see if we need to adjust auto alignment + // because auto always means middle / center alignment for data, + // but it changes for page alignment based on the closest side + if(autoAnchor) { + var posPlus = position + halfSizeFrac, + posMinus = position - halfSizeFrac; + if(position + posMinus < 2 / 3) position = posMinus; + else if(position + posPlus > 4 / 3) position = posPlus; + } + } + else if(axNew) { // paper -> data + // first see if we need to adjust auto alignment + if(autoAnchor) { + if(position < 1 / 3) position += halfSizeFrac; + else if(position > 2 / 3) position -= halfSizeFrac; + } + + // next convert to fraction of the axis + position = (position - axNew.domain[0]) / + (axNew.domain[1] - axNew.domain[0]); + + // finally convert to data coordinates + position = axNew.fraction2r(position); + } + } + + if(axNew && axNew === axOld && axTypeOld) { + if(axTypeOld === 'log' && axNew.type !== 'log') { + position = Math.pow(10, position); + } + else if(axTypeOld !== 'log' && axNew.type === 'log') { + position = (position > 0) ? + Math.log(position) / Math.LN10 : undefined; + } + } + + optionsIn[axLetter] = position; + } + + var options = {}; + handleAnnotationDefaults(optionsIn, options, fullLayout); + fullLayout.annotations[index] = options; + + var xa = Axes.getFromId(gd, options.xref), + ya = Axes.getFromId(gd, options.yref), + annPosPx = {x: 0, y: 0}, + textangle = +options.textangle || 0; + + // create the components + // made a single group to contain all, so opacity can work right + // with border/arrow together this could handle a whole bunch of + // cleanup at this point, but works for now + var anngroup = fullLayout._infolayer.append('g') + .classed('annotation', true) + .attr('data-index', String(index)) + .style('opacity', options.opacity) + .on('click', function() { + gd._dragging = false; + gd.emit('plotly_clickannotation', { + index: index, + annotation: optionsIn, + fullAnnotation: options + }); + }); + + if (options.classes) { + anngroup.classed(options.classes, true); + } + + // another group for text+background so that they can rotate together + var anng = anngroup.append('g') + .classed('annotation-text-g', true) + .attr('data-index', String(index)); + + var ann = anng.append('g'); + + var borderwidth = options.borderwidth, + borderpad = options.borderpad, + borderfull = borderwidth + borderpad; + + var annbg = ann.append('rect') + .attr('class', 'bg') + .style('stroke-width', borderwidth + 'px') + .call(Color.stroke, options.bordercolor) + .call(Color.fill, options.bgcolor); + + var font = options.font; + + var anntext = ann.append('text') + .classed('annotation', true) + .attr('data-unformatted', options.text) + .text(options.text); + + function textLayout(s) { + s.call(Drawing.font, font) + .attr({ + 'text-anchor': { + left: 'start', + right: 'end' + }[options.align] || 'middle' + }); + + svgTextUtils.convertToTspans(s, drawGraphicalElements); + return s; + } + + function drawGraphicalElements() { + + // make sure lines are aligned the way they will be + // at the end, even if their position changes + anntext.selectAll('tspan.line').attr({y: 0, x: 0}); + + var mathjaxGroup = ann.select('.annotation-math-group'), + hasMathjax = !mathjaxGroup.empty(), + anntextBB = Drawing.bBox( + (hasMathjax ? mathjaxGroup : anntext).node()), + annwidth = anntextBB.width, + annheight = anntextBB.height, + outerwidth = Math.round(annwidth + 2 * borderfull), + outerheight = Math.round(annheight + 2 * borderfull); + + + // save size in the annotation object for use by autoscale + options._w = annwidth; + options._h = annheight; + + function shiftFraction(v, anchor) { + if(anchor === 'auto') { + if(v < 1 / 3) anchor = 'left'; + else if(v > 2 / 3) anchor = 'right'; + else anchor = 'center'; + } + return { + center: 0, + middle: 0, + left: 0.5, + bottom: -0.5, + right: -0.5, + top: 0.5 + }[anchor]; + } + + var annotationIsOffscreen = false; + ['x', 'y'].forEach(function(axLetter) { + var axRef = options[axLetter + 'ref'] || axLetter, + ax = Axes.getFromId(gd, axRef), + dimAngle = (textangle + (axLetter === 'x' ? 0 : 90)) * Math.PI / 180, + annSize = outerwidth * Math.abs(Math.cos(dimAngle)) + + outerheight * Math.abs(Math.sin(dimAngle)), + anchor = options[axLetter + 'anchor'], + alignPosition; + + // calculate pixel position + if(ax) { + // hide the annotation if it's pointing + // outside the visible plot (as long as the axis + // isn't autoranged - then we need to draw it + // anyway to get its bounding box) + var posFraction = ax.r2fraction(options[axLetter]); + if(!ax.autorange && (posFraction < 0 || posFraction > 1)) { + if(options['a' + axLetter + 'ref'] === axRef) { + posFraction = ax.r2fraction(options['a' + axLetter]); + if(posFraction < 0 || posFraction > 1) { + annotationIsOffscreen = true; + } + } + else { + annotationIsOffscreen = true; + } + + if(annotationIsOffscreen) return; + } + annPosPx[axLetter] = ax._offset + ax.r2p(options[axLetter]); + alignPosition = 0.5; + } + else { + alignPosition = options[axLetter]; + if(axLetter === 'y') alignPosition = 1 - alignPosition; + annPosPx[axLetter] = (axLetter === 'x') ? + (gs.l + gs.w * alignPosition) : + (gs.t + gs.h * alignPosition); + } + + var alignShift = 0; + if(options['a' + axLetter + 'ref'] === axRef) { + annPosPx['aa' + axLetter] = ax._offset + ax.r2p(options['a' + axLetter]); + } else { + if(options.showarrow) { + alignShift = options['a' + axLetter]; + } + else { + alignShift = annSize * shiftFraction(alignPosition, anchor); + } + annPosPx[axLetter] += alignShift; + } + + // save the current axis type for later log/linear changes + options['_' + axLetter + 'type'] = ax && ax.type; + + // save the size and shift in this dim for autorange + options['_' + axLetter + 'size'] = annSize; + options['_' + axLetter + 'shift'] = alignShift; + }); + + if(annotationIsOffscreen) { + ann.remove(); + return; + } + + var arrowX, arrowY; + + // make sure the arrowhead (if there is one) + // and the annotation center are visible + if(options.showarrow) { + if(options.axref === options.xref) { + // we don't want to constrain if the tail is absolute + // or the slope (which is meaningful) will change. + arrowX = annPosPx.x; + } else { + arrowX = Lib.constrain(annPosPx.x - options.ax, 1, fullLayout.width - 1); + } + + if(options.ayref === options.yref) { + // we don't want to constrain if the tail is absolute + // or the slope (which is meaningful) will change. + arrowY = annPosPx.y; + } else { + arrowY = Lib.constrain(annPosPx.y - options.ay, 1, fullLayout.height - 1); + } + } + annPosPx.x = Lib.constrain(annPosPx.x, 1, fullLayout.width - 1); + annPosPx.y = Lib.constrain(annPosPx.y, 1, fullLayout.height - 1); + + var texty = borderfull - anntextBB.top, + textx = borderfull - anntextBB.left; + + if(hasMathjax) { + mathjaxGroup.select('svg').attr({x: borderfull - 1, y: borderfull}); + } + else { + anntext.attr({x: textx, y: texty}); + anntext.selectAll('tspan.line').attr({y: texty, x: textx}); + } + + annbg.call(Drawing.setRect, borderwidth / 2, borderwidth / 2, + outerwidth - borderwidth, outerheight - borderwidth); + + var annX = 0, annY = 0; + if(options.axref === options.xref) { + annX = Math.round(annPosPx.aax - outerwidth / 2); + } else { + annX = Math.round(annPosPx.x - outerwidth / 2); + } + + if(options.ayref === options.yref) { + annY = Math.round(annPosPx.aay - outerheight / 2); + } else { + annY = Math.round(annPosPx.y - outerheight / 2); + } + + ann.call(Lib.setTranslate, annX, annY); + + var annbase = 'annotations[' + index + ']'; + + // add the arrow + // uses options[arrowwidth,arrowcolor,arrowhead] for styling + var drawArrow = function(dx, dy) { + d3.select(gd) + .selectAll('.annotation-arrow-g[data-index="' + index + '"]') + .remove(); + // find where to start the arrow: + // at the border of the textbox, if that border is visible, + // or at the edge of the lines of text, if the border is hidden + // TODO: tspan bounding box fails in chrome + // looks like there may be a cross-browser solution, see + // http://stackoverflow.com/questions/5364980/ + // how-to-get-the-width-of-an-svg-tspan-element + var arrowX0, arrowY0; + + if(options.axref === options.xref) { + arrowX0 = annPosPx.aax + dx; + } else { + arrowX0 = annPosPx.x + dx; + } + + if(options.ayref === options.yref) { + arrowY0 = annPosPx.aay + dy; + } else { + arrowY0 = annPosPx.y + dy; + } + + // create transform matrix and related functions + var transform = + Lib.rotationXYMatrix(textangle, arrowX0, arrowY0), + applyTransform = Lib.apply2DTransform(transform), + applyTransform2 = Lib.apply2DTransform2(transform), + + // calculate and transform bounding box + xHalf = annbg.attr('width') / 2, + yHalf = annbg.attr('height') / 2, + edges = [ + [arrowX0 - xHalf, arrowY0 - yHalf, arrowX0 - xHalf, arrowY0 + yHalf], + [arrowX0 - xHalf, arrowY0 + yHalf, arrowX0 + xHalf, arrowY0 + yHalf], + [arrowX0 + xHalf, arrowY0 + yHalf, arrowX0 + xHalf, arrowY0 - yHalf], + [arrowX0 + xHalf, arrowY0 - yHalf, arrowX0 - xHalf, arrowY0 - yHalf] + ].map(applyTransform2); + + // Remove the line if it ends inside the box. Use ray + // casting for rotated boxes: see which edges intersect a + // line from the arrowhead to far away and reduce with xor + // to get the parity of the number of intersections. + if(edges.reduce(function(a, x) { + return a ^ + !!lineIntersect(arrowX, arrowY, arrowX + 1e6, arrowY + 1e6, + x[0], x[1], x[2], x[3]); + }, false)) { + // no line or arrow - so quit drawArrow now + return; + } + + edges.forEach(function(x) { + var p = lineIntersect(arrowX0, arrowY0, arrowX, arrowY, + x[0], x[1], x[2], x[3]); + if(p) { + arrowX0 = p.x; + arrowY0 = p.y; + } + }); + + var strokewidth = options.arrowwidth, + arrowColor = options.arrowcolor; + + var arrowgroup = anngroup.append('g') + .style({opacity: Color.opacity(arrowColor)}) + .classed('annotation-arrow-g', true) + .attr('data-index', String(index)); + + var arrow = arrowgroup.append('path') + .attr('d', 'M' + arrowX0 + ',' + arrowY0 + 'L' + arrowX + ',' + arrowY) + .style('stroke-width', strokewidth + 'px') + .call(Color.stroke, Color.rgb(arrowColor)); + + arrowhead(arrow, options.arrowhead, 'end', options.arrowsize); + + var arrowdrag = arrowgroup.append('path') + .classed('annotation', true) + .classed('anndrag', true) + .attr({ + 'data-index': String(index), + d: 'M3,3H-3V-3H3ZM0,0L' + (arrowX0 - arrowX) + ',' + (arrowY0 - arrowY), + transform: 'translate(' + arrowX + ',' + arrowY + ')' + }) + .style('stroke-width', (strokewidth + 6) + 'px') + .call(Color.stroke, 'rgba(0,0,0,0)') + .call(Color.fill, 'rgba(0,0,0,0)'); + + if(gd._context.editable) { + var update, + annx0, + anny0; + + dragElement.init({ + element: arrowdrag.node(), + prepFn: function() { + var pos = Lib.getTranslate(ann); + + annx0 = pos.x; + anny0 = pos.y; + update = {}; + if(xa && xa.autorange) { + update[xa._name + '.autorange'] = true; + } + if(ya && ya.autorange) { + update[ya._name + '.autorange'] = true; + } + }, + moveFn: function(dx, dy) { + arrowgroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); + + var annxy0 = applyTransform(annx0, anny0), + xcenter = annxy0[0] + dx, + ycenter = annxy0[1] + dy; + ann.call(Lib.setTranslate, xcenter, ycenter); + + update[annbase + '.x'] = xa ? + xa.p2r(xa.r2p(options.x) + dx) : + ((arrowX + dx - gs.l) / gs.w); + update[annbase + '.y'] = ya ? + ya.p2r(ya.r2p(options.y) + dy) : + (1 - ((arrowY + dy - gs.t) / gs.h)); + + if(options.axref === options.xref) { + update[annbase + '.ax'] = xa ? + xa.p2r(xa.r2p(options.ax) + dx) : + ((arrowX + dx - gs.l) / gs.w); + } + + if(options.ayref === options.yref) { + update[annbase + '.ay'] = ya ? + ya.p2r(ya.r2p(options.ay) + dy) : + (1 - ((arrowY + dy - gs.t) / gs.h)); + } + + anng.attr({ + transform: 'rotate(' + textangle + ',' + + xcenter + ',' + ycenter + ')' + }); + }, + doneFn: function(dragged) { + if(dragged) { + Plotly.relayout(gd, update); + var notesBox = document.querySelector('.js-notes-box-panel'); + if(notesBox) notesBox.redraw(notesBox.selectedObj); + } + } + }); + } + }; + + if(options.showarrow) drawArrow(0, 0); + + // create transform matrix and related functions + var transform = Lib.rotationXYMatrix(textangle, + annPosPx.x, annPosPx.y), + applyTransform = Lib.apply2DTransform(transform); + + // user dragging the annotation (text, not arrow) + if(gd._context.editable) { + var x0, + y0, + update; + + dragElement.init({ + element: ann.node(), + prepFn: function() { + var pos = Lib.getTranslate(ann); + + x0 = pos.x; + y0 = pos.y; + update = {}; + }, + moveFn: function(dx, dy) { + ann.call(Lib.setTranslate, x0 + dx, y0 + dy); + var csr = 'pointer'; + if(options.showarrow) { + if(options.axref === options.xref) { + update[annbase + '.ax'] = xa.p2r(xa.r2p(options.ax) + dx); + } else { + update[annbase + '.ax'] = options.ax + dx; + } + + if(options.ayref === options.yref) { + update[annbase + '.ay'] = ya.p2r(ya.r2p(options.ay) + dy); + } else { + update[annbase + '.ay'] = options.ay + dy; + } + + drawArrow(dx, dy); + } + else { + if(xa) update[annbase + '.x'] = options.x + dx / xa._m; + else { + var widthFraction = options._xsize / gs.w, + xLeft = options.x + options._xshift / gs.w - widthFraction / 2; + + update[annbase + '.x'] = dragElement.align(xLeft + dx / gs.w, + widthFraction, 0, 1, options.xanchor); + } + + if(ya) update[annbase + '.y'] = options.y + dy / ya._m; + else { + var heightFraction = options._ysize / gs.h, + yBottom = options.y - options._yshift / gs.h - heightFraction / 2; + + update[annbase + '.y'] = dragElement.align(yBottom - dy / gs.h, + heightFraction, 0, 1, options.yanchor); + } + if(!xa || !ya) { + csr = dragElement.getCursor( + xa ? 0.5 : update[annbase + '.x'], + ya ? 0.5 : update[annbase + '.y'], + options.xanchor, options.yanchor + ); + } + } + + var xy1 = applyTransform(x0, y0), + x1 = xy1[0] + dx, + y1 = xy1[1] + dy; + + ann.call(Lib.setTranslate, x0 + dx, y0 + dy); + + anng.attr({ + transform: 'rotate(' + textangle + ',' + + x1 + ',' + y1 + ')' + }); + + setCursor(ann, csr); + }, + doneFn: function(dragged) { + setCursor(ann); + if(dragged) { + Plotly.relayout(gd, update); + var notesBox = document.querySelector('.js-notes-box-panel'); + if(notesBox) notesBox.redraw(notesBox.selectedObj); + } + } + }); + } + } + + if(gd._context.editable) { + anntext.call(svgTextUtils.makeEditable, ann) + .call(textLayout) + .on('edit', function(_text) { + options.text = _text; + this.attr({'data-unformatted': options.text}); + this.call(textLayout); + var update = {}; + update['annotations[' + index + '].text'] = options.text; + if(xa && xa.autorange) { + update[xa._name + '.autorange'] = true; + } + if(ya && ya.autorange) { + update[ya._name + '.autorange'] = true; + } + Plotly.relayout(gd, update); + }); + } + else anntext.call(textLayout); + + // rotate and position text and background + anng.attr({transform: 'rotate(' + textangle + ',' + + annPosPx.x + ',' + annPosPx.y + ')'}) + .call(Drawing.setPosition, annPosPx.x, annPosPx.y); +} + +// look for intersection of two line segments +// (1->2 and 3->4) - returns array [x,y] if they do, null if not +function lineIntersect(x1, y1, x2, y2, x3, y3, x4, y4) { + var a = x2 - x1, + b = x3 - x1, + c = x4 - x3, + d = y2 - y1, + e = y3 - y1, + f = y4 - y3, + det = a * f - c * d; + // parallel lines? intersection is undefined + // ignore the case where they are colinear + if(det === 0) return null; + var t = (b * f - c * e) / det, + u = (b * d - a * e) / det; + // segments do not intersect? + if(u < 0 || u > 1 || t < 0 || t > 1) return null; + + return {x: x1 + a * t, y: y1 + d * t}; +} + +},{"../../lib":122,"../../lib/setcursor":132,"../../lib/svg_text_utils":134,"../../plotly":145,"../../plots/cartesian/axes":150,"../../plots/plots":186,"../color":27,"../dragelement":48,"../drawing":50,"./annotation_defaults":18,"./defaults":22,"./draw_arrow_head":24,"d3":10,"fast-isnumeric":13}],24:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Color = require('../color'); +var Drawing = require('../drawing'); + +var ARROWPATHS = require('./arrow_paths'); + +// add arrowhead(s) to a path or line d3 element el3 +// style: 1-6, first 5 are pointers, 6 is circle, 7 is square, 8 is none +// ends is 'start', 'end' (default), 'start+end' +// mag is magnification vs. default (default 1) + +module.exports = function drawArrowHead(el3, style, ends, mag) { + if(!isNumeric(mag)) mag = 1; + var el = el3.node(), + headStyle = ARROWPATHS[style||0]; + if(!headStyle) return; + + if(typeof ends !== 'string' || !ends) ends = 'end'; + + var scale = (Drawing.getPx(el3, 'stroke-width') || 1) * mag, + stroke = el3.style('stroke') || Color.defaultLine, + opacity = el3.style('stroke-opacity') || 1, + doStart = ends.indexOf('start') >= 0, + doEnd = ends.indexOf('end') >= 0, + backOff = headStyle.backoff * scale, + start, + end, + startRot, + endRot; + + if(el.nodeName === 'line') { + start = {x: +el3.attr('x1'), y: +el3.attr('y1')}; + end = {x: +el3.attr('x2'), y: +el3.attr('y2')}; + startRot = Math.atan2(start.y - end.y, start.x - end.x); + endRot = startRot + Math.PI; + if(backOff) { + var backOffX = backOff * Math.cos(startRot), + backOffY = backOff * Math.sin(startRot); + + if(doStart) { + start.x -= backOffX; + start.y -= backOffY; + el3.attr({x1: start.x, y1: start.y}); + } + if(doEnd) { + end.x += backOffX; + end.y += backOffY; + el3.attr({x2: end.x, y2: end.y}); + } + } + } + else if(el.nodeName === 'path') { + var pathlen = el.getTotalLength(), + // using dash to hide the backOff region of the path. + // if we ever allow dash for the arrow we'll have to + // do better than this hack... maybe just manually + // combine the two + dashArray = ''; + + if(doStart) { + var start0 = el.getPointAtLength(0), + dstart = el.getPointAtLength(0.1); + startRot = Math.atan2(start0.y - dstart.y, start0.x - dstart.x); + start = el.getPointAtLength(Math.min(backOff, pathlen)); + if(backOff) dashArray = '0px,' + backOff + 'px,'; + } + + if(doEnd) { + var end0 = el.getPointAtLength(pathlen), + dend = el.getPointAtLength(pathlen - 0.1); + endRot = Math.atan2(end0.y - dend.y, end0.x - dend.x); + end = el.getPointAtLength(Math.max(0, pathlen - backOff)); + + if(backOff) { + var shortening = dashArray ? 2 * backOff : backOff; + dashArray += (pathlen - shortening) + 'px,' + pathlen + 'px'; + } + } + else if(dashArray) dashArray += pathlen + 'px'; + + if(dashArray) el3.style('stroke-dasharray', dashArray); + } + + var drawhead = function(p, rot) { + if(style > 5) rot = 0; // don't rotate square or circle + d3.select(el.parentElement).append('path') + .attr({ + 'class': el3.attr('class'), + d: headStyle.path, + transform: + 'translate(' + p.x + ',' + p.y + ')' + + 'rotate(' + (rot * 180 / Math.PI) + ')' + + 'scale(' + scale + ')' + }) + .style({ + fill: stroke, + opacity: opacity, + 'stroke-width': 0 + }); + }; + + if(doStart) drawhead(start, startRot); + if(doEnd) drawhead(end, endRot); +}; + +},{"../color":27,"../drawing":50,"./arrow_paths":19,"d3":10,"fast-isnumeric":13}],25:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var drawModule = require('./draw'); + +module.exports = { + moduleType: 'component', + name: 'annotations', + + layoutAttributes: require('./attributes'), + supplyLayoutDefaults: require('./defaults'), + + calcAutorange: require('./calc_autorange'), + draw: drawModule.draw, + drawOne: drawModule.drawOne +}; + +},{"./attributes":20,"./calc_autorange":21,"./defaults":22,"./draw":23}],26:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +// IMPORTANT - default colors should be in hex for compatibility +exports.defaults = [ + '#1f77b4', // muted blue + '#ff7f0e', // safety orange + '#2ca02c', // cooked asparagus green + '#d62728', // brick red + '#9467bd', // muted purple + '#8c564b', // chestnut brown + '#e377c2', // raspberry yogurt pink + '#7f7f7f', // middle gray + '#bcbd22', // curry yellow-green + '#17becf' // blue-teal +]; + +exports.defaultLine = '#444'; + +exports.lightLine = '#eee'; + +exports.background = '#fff'; + +exports.borderLine = '#BEC8D9'; + +// with axis.color and Color.interp we aren't using lightLine +// itself anymore, instead interpolating between axis.color +// and the background color using tinycolor.mix. lightFraction +// gives back exactly lightLine if the other colors are defaults. +exports.lightFraction = 100 * (0xe - 0x4) / (0xf - 0x4); + +},{}],27:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var tinycolor = require('tinycolor2'); +var isNumeric = require('fast-isnumeric'); + +var color = module.exports = {}; + +var colorAttrs = require('./attributes'); +color.defaults = colorAttrs.defaults; +color.defaultLine = colorAttrs.defaultLine; +color.lightLine = colorAttrs.lightLine; +color.background = colorAttrs.background; + + +color.overrideColorDefaults = function(ca) { + if (typeof ca === 'undefined') { + return color.defaults; + } else { + color.defaults = ca; + } +} + +color.tinyRGB = function(tc) { + var c = tc.toRgb(); + return 'rgb(' + Math.round(c.r) + ', ' + + Math.round(c.g) + ', ' + Math.round(c.b) + ')'; +}; + +color.rgb = function(cstr) { return color.tinyRGB(tinycolor(cstr)); }; + +color.opacity = function(cstr) { return cstr ? tinycolor(cstr).getAlpha() : 0; }; + +color.addOpacity = function(cstr, op) { + var c = tinycolor(cstr).toRgb(); + return 'rgba(' + Math.round(c.r) + ', ' + + Math.round(c.g) + ', ' + Math.round(c.b) + ', ' + op + ')'; +}; + +// combine two colors into one apparent color +// if back has transparency or is missing, +// color.background is assumed behind it +color.combine = function(front, back) { + var fc = tinycolor(front).toRgb(); + if(fc.a === 1) return tinycolor(front).toRgbString(); + + var bc = tinycolor(back || color.background).toRgb(), + bcflat = bc.a === 1 ? bc : { + r: 255 * (1 - bc.a) + bc.r * bc.a, + g: 255 * (1 - bc.a) + bc.g * bc.a, + b: 255 * (1 - bc.a) + bc.b * bc.a + }, + fcflat = { + r: bcflat.r * (1 - fc.a) + fc.r * fc.a, + g: bcflat.g * (1 - fc.a) + fc.g * fc.a, + b: bcflat.b * (1 - fc.a) + fc.b * fc.a + }; + return tinycolor(fcflat).toRgbString(); +}; + +color.contrast = function(cstr, lightAmount, darkAmount) { + var tc = tinycolor(cstr); + + var newColor = tc.isLight() ? + tc.darken(darkAmount) : + tc.lighten(lightAmount); + + return newColor.toString(); +}; + +color.stroke = function(s, c) { + var tc = tinycolor(c); + s.style({'stroke': color.tinyRGB(tc), 'stroke-opacity': tc.getAlpha()}); +}; + +color.fill = function(s, c) { + var tc = tinycolor(c); + s.style({ + 'fill': color.tinyRGB(tc), + 'fill-opacity': tc.getAlpha() + }); +}; + +// search container for colors with the deprecated rgb(fractions) format +// and convert them to rgb(0-255 values) +color.clean = function(container) { + if(!container || typeof container !== 'object') return; + + var keys = Object.keys(container), + i, + j, + key, + val; + + for(i = 0; i < keys.length; i++) { + key = keys[i]; + val = container[key]; + + // only sanitize keys that end in "color" or "colorscale" + if(key.substr(key.length - 5) === 'color') { + if(Array.isArray(val)) { + for(j = 0; j < val.length; j++) val[j] = cleanOne(val[j]); + } + else container[key] = cleanOne(val); + } + else if(key.substr(key.length - 10) === 'colorscale' && Array.isArray(val)) { + // colorscales have the format [[0, color1], [frac, color2], ... [1, colorN]] + for(j = 0; j < val.length; j++) { + if(Array.isArray(val[j])) val[j][1] = cleanOne(val[j][1]); + } + } + // recurse into arrays of objects, and plain objects + else if(Array.isArray(val)) { + var el0 = val[0]; + if(!Array.isArray(el0) && el0 && typeof el0 === 'object') { + for(j = 0; j < val.length; j++) color.clean(val[j]); + } + } + else if(val && typeof val === 'object') color.clean(val); + } +}; + +function cleanOne(val) { + if(isNumeric(val) || typeof val !== 'string') return val; + + var valTrim = val.trim(); + if(valTrim.substr(0, 3) !== 'rgb') return val; + + var match = valTrim.match(/^rgba?\s*\(([^()]*)\)$/); + if(!match) return val; + + var parts = match[1].trim().split(/\s*[\s,]\s*/), + rgba = valTrim.charAt(3) === 'a' && parts.length === 4; + if(!rgba && parts.length !== 3) return val; + + for(var i = 0; i < parts.length; i++) { + if(!parts[i].length) return val; + parts[i] = Number(parts[i]); + + // all parts must be non-negative numbers + if(!(parts[i] >= 0)) return val; + // alpha>1 gets clipped to 1 + if(i === 3) { + if(parts[i] > 1) parts[i] = 1; + } + // r, g, b must be < 1 (ie 1 itself is not allowed) + else if(parts[i] >= 1) return val; + } + + var rgbStr = Math.round(parts[0] * 255) + ', ' + + Math.round(parts[1] * 255) + ', ' + + Math.round(parts[2] * 255); + + if(rgba) return 'rgba(' + rgbStr + ', ' + parts[3] + ')'; + return 'rgb(' + rgbStr + ')'; +} + +},{"./attributes":26,"fast-isnumeric":13,"tinycolor2":16}],28:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var axesAttrs = require('../../plots/cartesian/layout_attributes'); +var fontAttrs = require('../../plots/font_attributes'); +var extendFlat = require('../../lib/extend').extendFlat; + + +module.exports = { +// TODO: only right is supported currently +// orient: { +// valType: 'enumerated', +// +// values: ['left', 'right', 'top', 'bottom'], +// dflt: 'right', +// +// }, + thicknessmode: { + valType: 'enumerated', + values: ['fraction', 'pixels'], + + dflt: 'pixels', + + }, + thickness: { + valType: 'number', + + min: 0, + dflt: 30, + + }, + lenmode: { + valType: 'enumerated', + values: ['fraction', 'pixels'], + + dflt: 'fraction', + + }, + len: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + x: { + valType: 'number', + dflt: 1.02, + min: -2, + max: 3, + + + }, + xanchor: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'left', + + + }, + xpad: { + valType: 'number', + + min: 0, + dflt: 10, + + }, + y: { + valType: 'number', + + dflt: 0.5, + min: -2, + max: 3, + + }, + yanchor: { + valType: 'enumerated', + values: ['top', 'middle', 'bottom'], + + dflt: 'middle', + + }, + ypad: { + valType: 'number', + + min: 0, + dflt: 10, + + }, + // a possible line around the bar itself + outlinecolor: axesAttrs.linecolor, + outlinewidth: axesAttrs.linewidth, + // Should outlinewidth have {dflt: 0} ? + // another possible line outside the padding and tick labels + bordercolor: axesAttrs.linecolor, + borderwidth: { + valType: 'number', + + min: 0, + dflt: 0, + + }, + bgcolor: { + valType: 'color', + + dflt: 'rgba(0,0,0,0)', + + }, + // tick and title properties named and function exactly as in axes + tickmode: axesAttrs.tickmode, + nticks: axesAttrs.nticks, + tick0: axesAttrs.tick0, + dtick: axesAttrs.dtick, + tickvals: axesAttrs.tickvals, + ticktext: axesAttrs.ticktext, + ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}), + ticklen: axesAttrs.ticklen, + tickwidth: axesAttrs.tickwidth, + tickcolor: axesAttrs.tickcolor, + showticklabels: axesAttrs.showticklabels, + tickfont: axesAttrs.tickfont, + tickangle: axesAttrs.tickangle, + tickformat: axesAttrs.tickformat, + tickprefix: axesAttrs.tickprefix, + showtickprefix: axesAttrs.showtickprefix, + ticksuffix: axesAttrs.ticksuffix, + showticksuffix: axesAttrs.showticksuffix, + separatethousands: axesAttrs.separatethousands, + exponentformat: axesAttrs.exponentformat, + showexponent: axesAttrs.showexponent, + title: { + valType: 'string', + + dflt: 'Click to enter colorscale title', + + }, + titlefont: extendFlat({}, fontAttrs, { + + }), + titleside: { + valType: 'enumerated', + values: ['right', 'top', 'bottom'], + + dflt: 'top', + + } +}; + +},{"../../lib/extend":117,"../../plots/cartesian/layout_attributes":159,"../../plots/font_attributes":170}],29:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var handleTickValueDefaults = require('../../plots/cartesian/tick_value_defaults'); +var handleTickMarkDefaults = require('../../plots/cartesian/tick_mark_defaults'); +var handleTickLabelDefaults = require('../../plots/cartesian/tick_label_defaults'); + +var attributes = require('./attributes'); + + +module.exports = function colorbarDefaults(containerIn, containerOut, layout) { + var colorbarOut = containerOut.colorbar = {}, + colorbarIn = containerIn.colorbar || {}; + + function coerce(attr, dflt) { + return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt); + } + + var thicknessmode = coerce('thicknessmode'); + coerce('thickness', (thicknessmode === 'fraction') ? + 30 / (layout.width - layout.margin.l - layout.margin.r) : + 30 + ); + + var lenmode = coerce('lenmode'); + coerce('len', (lenmode === 'fraction') ? + 1 : + layout.height - layout.margin.t - layout.margin.b + ); + + coerce('x'); + coerce('xanchor'); + coerce('xpad'); + coerce('y'); + coerce('yanchor'); + coerce('ypad'); + Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']); + + coerce('outlinecolor'); + coerce('outlinewidth'); + coerce('bordercolor'); + coerce('borderwidth'); + coerce('bgcolor'); + + handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear'); + + handleTickLabelDefaults(colorbarIn, colorbarOut, coerce, 'linear', + {outerTicks: false, font: layout.font, noHover: true}); + + handleTickMarkDefaults(colorbarIn, colorbarOut, coerce, 'linear', + {outerTicks: false, font: layout.font, noHover: true}); + + coerce('title'); + Lib.coerceFont(coerce, 'titlefont', layout.font); + coerce('titleside'); +}; + +},{"../../lib":122,"../../plots/cartesian/tick_label_defaults":165,"../../plots/cartesian/tick_mark_defaults":166,"../../plots/cartesian/tick_value_defaults":167,"./attributes":28}],30:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var tinycolor = require('tinycolor2'); + +var Plotly = require('../../plotly'); +var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); +var Axes = require('../../plots/cartesian/axes'); +var dragElement = require('../dragelement'); +var Lib = require('../../lib'); +var extendFlat = require('../../lib/extend').extendFlat; +var setCursor = require('../../lib/setcursor'); +var Drawing = require('../drawing'); +var Color = require('../color'); +var Titles = require('../titles'); + +var handleAxisDefaults = require('../../plots/cartesian/axis_defaults'); +var handleAxisPositionDefaults = require('../../plots/cartesian/position_defaults'); +var axisLayoutAttrs = require('../../plots/cartesian/layout_attributes'); + +var attributes = require('./attributes'); + + +module.exports = function draw(gd, id) { + // opts: options object, containing everything from attributes + // plus a few others that are the equivalent of the colorbar "data" + var opts = {}; + Object.keys(attributes).forEach(function(k) { + opts[k] = null; + }); + // fillcolor can be a d3 scale, domain is z values, range is colors + // or leave it out for no fill, + // or set to a string constant for single-color fill + opts.fillcolor = null; + // line.color has the same options as fillcolor + opts.line = {color: null, width: null, dash: null}; + // levels of lines to draw. + // note that this DOES NOT determine the extent of the bar + // that's given by the domain of fillcolor + // (or line.color if no fillcolor domain) + opts.levels = {start: null, end: null, size: null}; + // separate fill levels (for example, heatmap coloring of a + // contour map) if this is omitted, fillcolors will be + // evaluated halfway between levels + opts.filllevels = null; + + function component() { + var fullLayout = gd._fullLayout, + gs = fullLayout._size; + if((typeof opts.fillcolor !== 'function') && + (typeof opts.line.color !== 'function')) { + fullLayout._infolayer.selectAll('g.' + id).remove(); + return; + } + var zrange = d3.extent(((typeof opts.fillcolor === 'function') ? + opts.fillcolor : opts.line.color).domain()), + linelevels = [], + filllevels = [], + l, + linecolormap = typeof opts.line.color === 'function' ? + opts.line.color : function() { return opts.line.color; }, + fillcolormap = typeof opts.fillcolor === 'function' ? + opts.fillcolor : function() { return opts.fillcolor; }; + + var l0 = opts.levels.end + opts.levels.size / 100, + ls = opts.levels.size, + zr0 = (1.001 * zrange[0] - 0.001 * zrange[1]), + zr1 = (1.001 * zrange[1] - 0.001 * zrange[0]); + for(l = opts.levels.start; (l - l0) * ls < 0; l += ls) { + if(l > zr0 && l < zr1) linelevels.push(l); + } + + if(typeof opts.fillcolor === 'function') { + if(opts.filllevels) { + l0 = opts.filllevels.end + opts.filllevels.size / 100; + ls = opts.filllevels.size; + for(l = opts.filllevels.start; (l - l0) * ls < 0; l += ls) { + if(l > zrange[0] && l < zrange[1]) filllevels.push(l); + } + } + else { + filllevels = linelevels.map(function(v) { + return v - opts.levels.size / 2; + }); + filllevels.push(filllevels[filllevels.length - 1] + + opts.levels.size); + } + } + else if(opts.fillcolor && typeof opts.fillcolor === 'string') { + // doesn't matter what this value is, with a single value + // we'll make a single fill rect covering the whole bar + filllevels = [0]; + } + + if(opts.levels.size < 0) { + linelevels.reverse(); + filllevels.reverse(); + } + + // now make a Plotly Axes object to scale with and draw ticks + // TODO: does not support orientation other than right + + // we calculate pixel sizes based on the specified graph size, + // not the actual (in case something pushed the margins around) + // which is a little odd but avoids an odd iterative effect + // when the colorbar itself is pushing the margins. + // but then the fractional size is calculated based on the + // actual graph size, so that the axes will size correctly. + var originalPlotHeight = fullLayout.height - fullLayout.margin.t - fullLayout.margin.b, + originalPlotWidth = fullLayout.width - fullLayout.margin.l - fullLayout.margin.r, + thickPx = Math.round(opts.thickness * + (opts.thicknessmode === 'fraction' ? originalPlotWidth : 1)), + thickFrac = thickPx / gs.w, + lenPx = Math.round(opts.len * + (opts.lenmode === 'fraction' ? originalPlotHeight : 1)), + lenFrac = lenPx / gs.h, + xpadFrac = opts.xpad / gs.w, + yExtraPx = (opts.borderwidth + opts.outlinewidth) / 2, + ypadFrac = opts.ypad / gs.h, + + // x positioning: do it initially just for left anchor, + // then fix at the end (since we don't know the width yet) + xLeft = Math.round(opts.x * gs.w + opts.xpad), + // for dragging... this is getting a little muddled... + xLeftFrac = opts.x - thickFrac * + ({middle: 0.5, right: 1}[opts.xanchor]||0), + + // y positioning we can do correctly from the start + yBottomFrac = opts.y + lenFrac * + (({top: -0.5, bottom: 0.5}[opts.yanchor] || 0) - 0.5), + yBottomPx = Math.round(gs.h * (1 - yBottomFrac)), + yTopPx = yBottomPx - lenPx, + titleEl, + cbAxisIn = { + type: 'linear', + range: zrange, + tickmode: opts.tickmode, + nticks: opts.nticks, + tick0: opts.tick0, + dtick: opts.dtick, + tickvals: opts.tickvals, + ticktext: opts.ticktext, + ticks: opts.ticks, + ticklen: opts.ticklen, + tickwidth: opts.tickwidth, + tickcolor: opts.tickcolor, + showticklabels: opts.showticklabels, + tickfont: opts.tickfont, + tickangle: opts.tickangle, + tickformat: opts.tickformat, + exponentformat: opts.exponentformat, + separatethousands: opts.separatethousands, + showexponent: opts.showexponent, + showtickprefix: opts.showtickprefix, + tickprefix: opts.tickprefix, + showticksuffix: opts.showticksuffix, + ticksuffix: opts.ticksuffix, + title: opts.title, + titlefont: opts.titlefont, + anchor: 'free', + position: 1 + }, + cbAxisOut = {}, + axisOptions = { + letter: 'y', + font: fullLayout.font, + noHover: true + }; + + // Coerce w.r.t. Axes layoutAttributes: + // re-use axes.js logic without updating _fullData + function coerce(attr, dflt) { + return Lib.coerce(cbAxisIn, cbAxisOut, axisLayoutAttrs, attr, dflt); + } + + // Prepare the Plotly axis object + handleAxisDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions); + handleAxisPositionDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions); + + cbAxisOut._id = 'y' + id; + cbAxisOut._gd = gd; + + // position can't go in through supplyDefaults + // because that restricts it to [0,1] + cbAxisOut.position = opts.x + xpadFrac + thickFrac; + + // save for other callers to access this axis + component.axis = cbAxisOut; + + if(['top', 'bottom'].indexOf(opts.titleside) !== -1) { + cbAxisOut.titleside = opts.titleside; + cbAxisOut.titlex = opts.x + xpadFrac; + cbAxisOut.titley = yBottomFrac + + (opts.titleside === 'top' ? lenFrac - ypadFrac : ypadFrac); + } + + if(opts.line.color && opts.tickmode === 'auto') { + cbAxisOut.tickmode = 'linear'; + cbAxisOut.tick0 = opts.levels.start; + var dtick = opts.levels.size; + // expand if too many contours, so we don't get too many ticks + var autoNtick = Lib.constrain( + (yBottomPx - yTopPx) / 50, 4, 15) + 1, + dtFactor = (zrange[1] - zrange[0]) / + ((opts.nticks || autoNtick) * dtick); + if(dtFactor > 1) { + var dtexp = Math.pow(10, Math.floor( + Math.log(dtFactor) / Math.LN10)); + dtick *= dtexp * Lib.roundUp(dtFactor / dtexp, [2, 5, 10]); + // if the contours are at round multiples, reset tick0 + // so they're still at round multiples. Otherwise, + // keep the first label on the first contour level + if((Math.abs(opts.levels.start) / + opts.levels.size + 1e-6) % 1 < 2e-6) { + cbAxisOut.tick0 = 0; + } + } + cbAxisOut.dtick = dtick; + } + + // set domain after init, because we may want to + // allow it outside [0,1] + cbAxisOut.domain = [ + yBottomFrac + ypadFrac, + yBottomFrac + lenFrac - ypadFrac + ]; + cbAxisOut.setScale(); + + // now draw the elements + var container = fullLayout._infolayer.selectAll('g.' + id).data([0]); + container.enter().append('g').classed(id, true) + .each(function() { + var s = d3.select(this); + s.append('rect').classed('cbbg', true); + s.append('g').classed('cbfills', true); + s.append('g').classed('cblines', true); + s.append('g').classed('cbaxis', true).classed('crisp', true); + s.append('g').classed('cbtitleunshift', true) + .append('g').classed('cbtitle', true); + s.append('rect').classed('cboutline', true); + s.select('.cbtitle').datum(0); + }); + container.attr('transform', 'translate(' + Math.round(gs.l) + + ',' + Math.round(gs.t) + ')'); + // TODO: this opposite transform is a hack until we make it + // more rational which items get this offset + var titleCont = container.select('.cbtitleunshift') + .attr('transform', 'translate(-' + + Math.round(gs.l) + ',-' + + Math.round(gs.t) + ')'); + + cbAxisOut._axislayer = container.select('.cbaxis'); + var titleHeight = 0; + if(['top', 'bottom'].indexOf(opts.titleside) !== -1) { + // draw the title so we know how much room it needs + // when we squish the axis. This one only applies to + // top or bottom titles, not right side. + var x = gs.l + (opts.x + xpadFrac) * gs.w, + fontSize = cbAxisOut.titlefont.size, + y; + + if(opts.titleside === 'top') { + y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h + + gs.t + 3 + fontSize * 0.75; + } + else { + y = (1 - (yBottomFrac + ypadFrac)) * gs.h + + gs.t - 3 - fontSize * 0.25; + } + drawTitle(cbAxisOut._id + 'title', { + attributes: {x: x, y: y, 'text-anchor': 'start'} + }); + } + + function drawAxis() { + if(['top', 'bottom'].indexOf(opts.titleside) !== -1) { + // squish the axis top to make room for the title + var titleGroup = container.select('.cbtitle'), + titleText = titleGroup.select('text'), + titleTrans = + [-opts.outlinewidth / 2, opts.outlinewidth / 2], + mathJaxNode = titleGroup + .select('.h' + cbAxisOut._id + 'title-math-group') + .node(), + lineSize = 15.6; + if(titleText.node()) { + lineSize = + parseInt(titleText.style('font-size'), 10) * 1.3; + } + if(mathJaxNode) { + titleHeight = Drawing.bBox(mathJaxNode).height; + if(titleHeight > lineSize) { + // not entirely sure how mathjax is doing + // vertical alignment, but this seems to work. + titleTrans[1] -= (titleHeight - lineSize) / 2; + } + } + else if(titleText.node() && + !titleText.classed('js-placeholder')) { + titleHeight = Drawing.bBox( + titleGroup.node()).height; + } + if(titleHeight) { + // buffer btwn colorbar and title + // TODO: configurable + titleHeight += 5; + + if(opts.titleside === 'top') { + cbAxisOut.domain[1] -= titleHeight / gs.h; + titleTrans[1] *= -1; + } + else { + cbAxisOut.domain[0] += titleHeight / gs.h; + var nlines = Math.max(1, + titleText.selectAll('tspan.line').size()); + titleTrans[1] += (1 - nlines) * lineSize; + } + + titleGroup.attr('transform', + 'translate(' + titleTrans + ')'); + + cbAxisOut.setScale(); + } + } + + container.selectAll('.cbfills,.cblines,.cbaxis') + .attr('transform', 'translate(0,' + + Math.round(gs.h * (1 - cbAxisOut.domain[1])) + ')'); + + var fills = container.select('.cbfills') + .selectAll('rect.cbfill') + .data(filllevels); + fills.enter().append('rect') + .classed('cbfill', true) + .style('stroke', 'none'); + fills.exit().remove(); + fills.each(function(d, i) { + var z = [ + (i === 0) ? zrange[0] : + (filllevels[i] + filllevels[i - 1]) / 2, + (i === filllevels.length - 1) ? zrange[1] : + (filllevels[i] + filllevels[i + 1]) / 2 + ] + .map(cbAxisOut.c2p) + .map(Math.round); + + // offset the side adjoining the next rectangle so they + // overlap, to prevent antialiasing gaps + if(i !== filllevels.length - 1) { + z[1] += (z[1] > z[0]) ? 1 : -1; + } + + + // Tinycolor can't handle exponents and + // at this scale, removing it makes no difference. + var colorString = fillcolormap(d).replace('e-', ''), + opaqueColor = tinycolor(colorString).toHexString(); + + // Colorbar cannot currently support opacities so we + // use an opaque fill even when alpha channels present + d3.select(this).attr({ + x: xLeft, + width: Math.max(thickPx, 2), + y: d3.min(z), + height: Math.max(d3.max(z) - d3.min(z), 2), + fill: opaqueColor + }); + }); + + var lines = container.select('.cblines') + .selectAll('path.cbline') + .data(opts.line.color && opts.line.width ? + linelevels : []); + lines.enter().append('path') + .classed('cbline', true); + lines.exit().remove(); + lines.each(function(d) { + d3.select(this) + .attr('d', 'M' + xLeft + ',' + + (Math.round(cbAxisOut.c2p(d)) + (opts.line.width / 2) % 1) + + 'h' + thickPx) + .call(Drawing.lineGroupStyle, + opts.line.width, linecolormap(d), opts.line.dash); + }); + + // force full redraw of labels and ticks + cbAxisOut._axislayer.selectAll('g.' + cbAxisOut._id + 'tick,path') + .remove(); + + cbAxisOut._pos = xLeft + thickPx + + (opts.outlinewidth||0) / 2 - (opts.ticks === 'outside' ? 1 : 0); + cbAxisOut.side = 'right'; + + // separate out axis and title drawing, + // so we don't need such complicated logic in Titles.draw + // if title is on the top or bottom, we've already drawn it + // this title call only handles side=right + return Lib.syncOrAsync([ + function() { + return Axes.doTicks(gd, cbAxisOut, true); + }, + function() { + if(['top', 'bottom'].indexOf(opts.titleside) === -1) { + var fontSize = cbAxisOut.titlefont.size, + y = cbAxisOut._offset + cbAxisOut._length / 2, + x = gs.l + (cbAxisOut.position || 0) * gs.w + ((cbAxisOut.side === 'right') ? + 10 + fontSize * ((cbAxisOut.showticklabels ? 1 : 0.5)) : + -10 - fontSize * ((cbAxisOut.showticklabels ? 0.5 : 0))); + + // the 'h' + is a hack to get around the fact that + // convertToTspans rotates any 'y...' class by 90 degrees. + // TODO: find a better way to control this. + drawTitle('h' + cbAxisOut._id + 'title', { + avoid: { + selection: d3.select(gd).selectAll('g.' + cbAxisOut._id + 'tick'), + side: opts.titleside, + offsetLeft: gs.l, + offsetTop: gs.t, + maxShift: fullLayout.width + }, + attributes: {x: x, y: y, 'text-anchor': 'middle'}, + transform: {rotate: '-90', offset: 0} + }); + } + }]); + } + + function drawTitle(titleClass, titleOpts) { + var trace = getTrace(), + propName; + if(Registry.traceIs(trace, 'markerColorscale')) { + propName = 'marker.colorbar.title'; + } + else propName = 'colorbar.title'; + + var dfltTitleOpts = { + propContainer: cbAxisOut, + propName: propName, + traceIndex: trace.index, + dfltName: 'colorscale', + containerGroup: container.select('.cbtitle') + }; + + // this class-to-rotate thing with convertToTspans is + // getting hackier and hackier... delete groups with the + // wrong class (in case earlier the colorbar was drawn on + // a different side, I think?) + var otherClass = titleClass.charAt(0) === 'h' ? + titleClass.substr(1) : ('h' + titleClass); + container.selectAll('.' + otherClass + ',.' + otherClass + '-math-group') + .remove(); + + Titles.draw(gd, titleClass, + extendFlat(dfltTitleOpts, titleOpts || {})); + } + + function positionCB() { + // wait for the axis & title to finish rendering before + // continuing positioning + // TODO: why are we redrawing multiple times now with this? + // I guess autoMargin doesn't like being post-promise? + var innerWidth = thickPx + opts.outlinewidth / 2 + + Drawing.bBox(cbAxisOut._axislayer.node()).width; + titleEl = titleCont.select('text'); + if(titleEl.node() && !titleEl.classed('js-placeholder')) { + var mathJaxNode = titleCont + .select('.h' + cbAxisOut._id + 'title-math-group') + .node(), + titleWidth; + if(mathJaxNode && + ['top', 'bottom'].indexOf(opts.titleside) !== -1) { + titleWidth = Drawing.bBox(mathJaxNode).width; + } + else { + // note: the formula below works for all titlesides, + // (except for top/bottom mathjax, above) + // but the weird gs.l is because the titleunshift + // transform gets removed by Drawing.bBox + titleWidth = + Drawing.bBox(titleCont.node()).right - + xLeft - gs.l; + } + innerWidth = Math.max(innerWidth, titleWidth); + } + + var outerwidth = 2 * opts.xpad + innerWidth + + opts.borderwidth + opts.outlinewidth / 2, + outerheight = yBottomPx - yTopPx; + + container.select('.cbbg').attr({ + x: xLeft - opts.xpad - + (opts.borderwidth + opts.outlinewidth) / 2, + y: yTopPx - yExtraPx, + width: Math.max(outerwidth, 2), + height: Math.max(outerheight + 2 * yExtraPx, 2) + }) + .call(Color.fill, opts.bgcolor) + .call(Color.stroke, opts.bordercolor) + .style({'stroke-width': opts.borderwidth}); + + container.selectAll('.cboutline').attr({ + x: xLeft, + y: yTopPx + opts.ypad + + (opts.titleside === 'top' ? titleHeight : 0), + width: Math.max(thickPx, 2), + height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2) + }) + .call(Color.stroke, opts.outlinecolor) + .style({ + fill: 'None', + 'stroke-width': opts.outlinewidth + }); + + // fix positioning for xanchor!='left' + var xoffset = ({center: 0.5, right: 1}[opts.xanchor] || 0) * + outerwidth; + container.attr('transform', + 'translate(' + (gs.l - xoffset) + ',' + gs.t + ')'); + + // auto margin adjustment + Plots.autoMargin(gd, id, { + x: opts.x, + y: opts.y, + l: outerwidth * ({right: 1, center: 0.5}[opts.xanchor] || 0), + r: outerwidth * ({left: 1, center: 0.5}[opts.xanchor] || 0), + t: outerheight * ({bottom: 1, middle: 0.5}[opts.yanchor] || 0), + b: outerheight * ({top: 1, middle: 0.5}[opts.yanchor] || 0) + }); + } + + var cbDone = Lib.syncOrAsync([ + Plots.previousPromises, + drawAxis, + Plots.previousPromises, + positionCB + ], gd); + + if(cbDone && cbDone.then) (gd._promises || []).push(cbDone); + + // dragging... + if(gd._context.editable) { + var t0, + xf, + yf; + + dragElement.init({ + element: container.node(), + prepFn: function() { + t0 = container.attr('transform'); + setCursor(container); + }, + moveFn: function(dx, dy) { + container.attr('transform', + t0 + ' ' + 'translate(' + dx + ',' + dy + ')'); + + xf = dragElement.align(xLeftFrac + (dx / gs.w), thickFrac, + 0, 1, opts.xanchor); + yf = dragElement.align(yBottomFrac - (dy / gs.h), lenFrac, + 0, 1, opts.yanchor); + + var csr = dragElement.getCursor(xf, yf, + opts.xanchor, opts.yanchor); + setCursor(container, csr); + }, + doneFn: function(dragged) { + setCursor(container); + + if(dragged && xf !== undefined && yf !== undefined) { + Plotly.restyle(gd, + {'colorbar.x': xf, 'colorbar.y': yf}, + getTrace().index); + } + } + }); + } + return cbDone; + } + + function getTrace() { + var idNum = id.substr(2), + i, + trace; + for(i = 0; i < gd._fullData.length; i++) { + trace = gd._fullData[i]; + if(trace.uid === idNum) return trace; + } + } + + // setter/getters for every item defined in opts + Object.keys(opts).forEach(function(name) { + component[name] = function(v) { + // getter + if(!arguments.length) return opts[name]; + + // setter - for multi-part properties, + // set only the parts that are provided + opts[name] = Lib.isPlainObject(opts[name]) ? + Lib.extendFlat(opts[name], v) : + v; + + return component; + }; + }); + + // or use .options to set multiple options at once via a dictionary + component.options = function(o) { + Object.keys(o).forEach(function(name) { + // in case something random comes through + // that's not an option, ignore it + if(typeof component[name] === 'function') { + component[name](o[name]); + } + }); + return component; + }; + + component._opts = opts; + + return component; +}; + +},{"../../lib":122,"../../lib/extend":117,"../../lib/setcursor":132,"../../plotly":145,"../../plots/cartesian/axes":150,"../../plots/cartesian/axis_defaults":152,"../../plots/cartesian/layout_attributes":159,"../../plots/cartesian/position_defaults":162,"../../plots/plots":186,"../../registry":194,"../color":27,"../dragelement":48,"../drawing":50,"../titles":101,"./attributes":28,"d3":10,"tinycolor2":16}],31:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + + +module.exports = function hasColorbar(container) { + return Lib.isPlainObject(container.colorbar); +}; + +},{"../../lib":122}],32:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + zauto: { + valType: 'boolean', + + dflt: true, + + }, + zmin: { + valType: 'number', + + dflt: null, + + }, + zmax: { + valType: 'number', + + dflt: null, + + }, + colorscale: { + valType: 'colorscale', + + + }, + autocolorscale: { + valType: 'boolean', + + dflt: true, // gets overrode in 'heatmap' & 'surface' for backwards comp. + + }, + reversescale: { + valType: 'boolean', + + dflt: false, + + }, + showscale: { + valType: 'boolean', + + dflt: true, + + } +}; + +},{}],33:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + +var scales = require('./scales'); +var flipScale = require('./flip_scale'); + + +module.exports = function calc(trace, vals, containerStr, cLetter) { + var container, inputContainer; + + if(containerStr) { + container = Lib.nestedProperty(trace, containerStr).get(); + inputContainer = Lib.nestedProperty(trace._input, containerStr).get(); + } + else { + container = trace; + inputContainer = trace._input; + } + + var auto = container[cLetter + 'auto'], + min = container[cLetter + 'min'], + max = container[cLetter + 'max'], + scl = container.colorscale; + + if(auto !== false || min === undefined) { + min = Lib.aggNums(Math.min, null, vals); + } + + if(auto !== false || max === undefined) { + max = Lib.aggNums(Math.max, null, vals); + } + + if(min === max) { + min -= 0.5; + max += 0.5; + } + + container[cLetter + 'min'] = min; + container[cLetter + 'max'] = max; + + inputContainer[cLetter + 'min'] = min; + inputContainer[cLetter + 'max'] = max; + + if(container.autocolorscale) { + if(min * max < 0) scl = scales.RdBu; + else if(min >= 0) scl = scales.Reds; + else scl = scales.Blues; + + // reversescale is handled at the containerOut level + inputContainer.colorscale = scl; + if(container.reversescale) scl = flipScale(scl); + container.colorscale = scl; + } +}; + +},{"../../lib":122,"./flip_scale":38,"./scales":45}],34:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorScaleAttributes = require('./attributes'); +var extendDeep = require('../../lib/extend').extendDeep; +var palettes = require('./scales.js'); + +module.exports = function makeColorScaleAttributes(context) { + return { + color: { + valType: 'color', + arrayOk: true, + + + }, + colorscale: extendDeep({}, colorScaleAttributes.colorscale, { + + }), + cauto: extendDeep({}, colorScaleAttributes.zauto, { + + }), + cmax: extendDeep({}, colorScaleAttributes.zmax, { + + }), + cmin: extendDeep({}, colorScaleAttributes.zmin, { + + }), + autocolorscale: extendDeep({}, colorScaleAttributes.autocolorscale, { + + }), + reversescale: extendDeep({}, colorScaleAttributes.reversescale, { + + }) + }; +}; + +},{"../../lib/extend":117,"./attributes":32,"./scales.js":45}],35:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scales = require('./scales'); + + +module.exports = scales.RdBu; + +},{"./scales":45}],36:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); + +var hasColorbar = require('../colorbar/has_colorbar'); +var colorbarDefaults = require('../colorbar/defaults'); +var isValidScale = require('./is_valid_scale'); +var flipScale = require('./flip_scale'); + + +module.exports = function colorScaleDefaults(traceIn, traceOut, layout, coerce, opts) { + var prefix = opts.prefix, + cLetter = opts.cLetter, + containerStr = prefix.slice(0, prefix.length - 1), + containerIn = prefix ? + Lib.nestedProperty(traceIn, containerStr).get() || {} : + traceIn, + containerOut = prefix ? + Lib.nestedProperty(traceOut, containerStr).get() || {} : + traceOut, + minIn = containerIn[cLetter + 'min'], + maxIn = containerIn[cLetter + 'max'], + sclIn = containerIn.colorscale; + + var validMinMax = isNumeric(minIn) && isNumeric(maxIn) && (minIn < maxIn); + coerce(prefix + cLetter + 'auto', !validMinMax); + coerce(prefix + cLetter + 'min'); + coerce(prefix + cLetter + 'max'); + + // handles both the trace case (autocolorscale is false by default) and + // the marker and marker.line case (autocolorscale is true by default) + var autoColorscaleDftl; + if(sclIn !== undefined) autoColorscaleDftl = !isValidScale(sclIn); + coerce(prefix + 'autocolorscale', autoColorscaleDftl); + var sclOut = coerce(prefix + 'colorscale'); + + // reversescale is handled at the containerOut level + var reverseScale = coerce(prefix + 'reversescale'); + if(reverseScale) containerOut.colorscale = flipScale(sclOut); + + // ... until Scatter.colorbar can handle marker line colorbars + if(prefix === 'marker.line.') return; + + // handle both the trace case where the dflt is listed in attributes and + // the marker case where the dflt is determined by hasColorbar + var showScaleDftl; + if(prefix) showScaleDftl = hasColorbar(containerIn); + var showScale = coerce(prefix + 'showscale', showScaleDftl); + + if(showScale) colorbarDefaults(containerIn, containerOut, layout); +}; + +},{"../../lib":122,"../colorbar/defaults":29,"../colorbar/has_colorbar":31,"./flip_scale":38,"./is_valid_scale":42,"fast-isnumeric":13}],37:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/** + * Extract colorscale into numeric domain and color range. + * + * @param {array} scl colorscale array of arrays + * @param {number} cmin minimum color value (used to clamp scale) + * @param {number} cmax maximum color value (used to clamp scale) + */ +module.exports = function extractScale(scl, cmin, cmax) { + var N = scl.length, + domain = new Array(N), + range = new Array(N); + + for(var i = 0; i < N; i++) { + var si = scl[i]; + + domain[i] = cmin + si[0] * (cmax - cmin); + range[i] = si[1]; + } + + return { + domain: domain, + range: range + }; +}; + +},{}],38:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = function flipScale(scl) { + var N = scl.length, + sclNew = new Array(N), + si; + + for(var i = N - 1, j = 0; i >= 0; i--, j++) { + si = scl[i]; + sclNew[j] = [1 - si[0], si[1]]; + } + + return sclNew; +}; + +},{}],39:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scales = require('./scales'); +var defaultScale = require('./default_scale'); +var isValidScaleArray = require('./is_valid_scale_array'); + + +module.exports = function getScale(scl, dflt) { + if(!dflt) dflt = defaultScale; + if(!scl) return dflt; + + function parseScale() { + try { + scl = scales[scl] || JSON.parse(scl); + } + catch(e) { + scl = dflt; + } + } + + if(typeof scl === 'string') { + parseScale(); + // occasionally scl is double-JSON encoded... + if(typeof scl === 'string') parseScale(); + } + + if(!isValidScaleArray(scl)) return dflt; + return scl; +}; + +},{"./default_scale":35,"./is_valid_scale_array":43,"./scales":45}],40:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); + +var isValidScale = require('./is_valid_scale'); + + +module.exports = function hasColorscale(trace, containerStr) { + var container = containerStr ? + Lib.nestedProperty(trace, containerStr).get() || {} : + trace, + color = container.color, + isArrayWithOneNumber = false; + + if(Array.isArray(color)) { + for(var i = 0; i < color.length; i++) { + if(isNumeric(color[i])) { + isArrayWithOneNumber = true; + break; + } + } + } + + return ( + Lib.isPlainObject(container) && ( + isArrayWithOneNumber || + container.showscale === true || + (isNumeric(container.cmin) && isNumeric(container.cmax)) || + isValidScale(container.colorscale) || + Lib.isPlainObject(container.colorbar) + ) + ); +}; + +},{"../../lib":122,"./is_valid_scale":42,"fast-isnumeric":13}],41:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.scales = require('./scales'); + +exports.defaultScale = require('./default_scale'); + +exports.attributes = require('./attributes'); + +exports.handleDefaults = require('./defaults'); + +exports.calc = require('./calc'); + +exports.hasColorscale = require('./has_colorscale'); + +exports.isValidScale = require('./is_valid_scale'); + +exports.getScale = require('./get_scale'); + +exports.flipScale = require('./flip_scale'); + +exports.extractScale = require('./extract_scale'); + +exports.makeColorScaleFunc = require('./make_color_scale_func'); + +},{"./attributes":32,"./calc":33,"./default_scale":35,"./defaults":36,"./extract_scale":37,"./flip_scale":38,"./get_scale":39,"./has_colorscale":40,"./is_valid_scale":42,"./make_color_scale_func":44,"./scales":45}],42:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var scales = require('./scales'); +var isValidScaleArray = require('./is_valid_scale_array'); + + +module.exports = function isValidScale(scl) { + if(scales[scl] !== undefined) return true; + else return isValidScaleArray(scl); +}; + +},{"./is_valid_scale_array":43,"./scales":45}],43:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var tinycolor = require('tinycolor2'); + + +module.exports = function isValidScaleArray(scl) { + var highestVal = 0; + + if(!Array.isArray(scl) || scl.length < 2) return false; + + if(!scl[0] || !scl[scl.length - 1]) return false; + + if(+scl[0][0] !== 0 || +scl[scl.length - 1][0] !== 1) return false; + + for(var i = 0; i < scl.length; i++) { + var si = scl[i]; + + if(si.length !== 2 || +si[0] < highestVal || !tinycolor(si[1]).isValid()) { + return false; + } + + highestVal = +si[0]; + } + + return true; +}; + +},{"tinycolor2":16}],44:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var tinycolor = require('tinycolor2'); +var isNumeric = require('fast-isnumeric'); + +var Color = require('../color'); + +/** + * General colorscale function generator. + * + * @param {object} specs output of Colorscale.extractScale or precomputed domain, range. + * - domain {array} + * - range {array} + * + * @param {object} opts + * - noNumericCheck {boolean} if true, scale func bypasses numeric checks + * - returnArray {boolean} if true, scale func return 4-item array instead of color strings + * + * @return {function} + */ +module.exports = function makeColorScaleFunc(specs, opts) { + opts = opts || {}; + + var domain = specs.domain, + range = specs.range, + N = range.length, + _range = new Array(N); + + for(var i = 0; i < N; i++) { + var rgba = tinycolor(range[i]).toRgb(); + _range[i] = [rgba.r, rgba.g, rgba.b, rgba.a]; + } + + var _sclFunc = d3.scale.linear() + .domain(domain) + .range(_range) + .clamp(true); + + var noNumericCheck = opts.noNumericCheck, + returnArray = opts.returnArray, + sclFunc; + + if(noNumericCheck && returnArray) { + sclFunc = _sclFunc; + } + else if(noNumericCheck) { + sclFunc = function(v) { + return colorArray2rbga(_sclFunc(v)); + }; + } + else if(returnArray) { + sclFunc = function(v) { + if(isNumeric(v)) return _sclFunc(v); + else if(tinycolor(v).isValid()) return v; + else return Color.defaultLine; + }; + } + else { + sclFunc = function(v) { + if(isNumeric(v)) return colorArray2rbga(_sclFunc(v)); + else if(tinycolor(v).isValid()) return v; + else return Color.defaultLine; + }; + } + + // colorbar draw looks into the d3 scale closure for domain and range + + sclFunc.domain = _sclFunc.domain; + + sclFunc.range = function() { return range; }; + + return sclFunc; +}; + +function colorArray2rbga(colorArray) { + var colorObj = { + r: colorArray[0], + g: colorArray[1], + b: colorArray[2], + a: colorArray[3] + }; + + return tinycolor(colorObj).toRgbString(); +} + +},{"../color":27,"d3":10,"fast-isnumeric":13,"tinycolor2":16}],45:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + 'Greys': [ + [0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)'] + ], + + 'YlGnBu': [ + [0, 'rgb(8,29,88)'], [0.125, 'rgb(37,52,148)'], + [0.25, 'rgb(34,94,168)'], [0.375, 'rgb(29,145,192)'], + [0.5, 'rgb(65,182,196)'], [0.625, 'rgb(127,205,187)'], + [0.75, 'rgb(199,233,180)'], [0.875, 'rgb(237,248,217)'], + [1, 'rgb(255,255,217)'] + ], + + 'Greens': [ + [0, 'rgb(0,68,27)'], [0.125, 'rgb(0,109,44)'], + [0.25, 'rgb(35,139,69)'], [0.375, 'rgb(65,171,93)'], + [0.5, 'rgb(116,196,118)'], [0.625, 'rgb(161,217,155)'], + [0.75, 'rgb(199,233,192)'], [0.875, 'rgb(229,245,224)'], + [1, 'rgb(247,252,245)'] + ], + + 'YlOrRd': [ + [0, 'rgb(128,0,38)'], [0.125, 'rgb(189,0,38)'], + [0.25, 'rgb(227,26,28)'], [0.375, 'rgb(252,78,42)'], + [0.5, 'rgb(253,141,60)'], [0.625, 'rgb(254,178,76)'], + [0.75, 'rgb(254,217,118)'], [0.875, 'rgb(255,237,160)'], + [1, 'rgb(255,255,204)'] + ], + + 'Bluered': [ + [0, 'rgb(0,0,255)'], [1, 'rgb(255,0,0)'] + ], + + // modified RdBu based on + // www.sandia.gov/~kmorel/documents/ColorMaps/ColorMapsExpanded.pdf + 'RdBu': [ + [0, 'rgb(5,10,172)'], [0.35, 'rgb(106,137,247)'], + [0.5, 'rgb(190,190,190)'], [0.6, 'rgb(220,170,132)'], + [0.7, 'rgb(230,145,90)'], [1, 'rgb(178,10,28)'] + ], + + // Scale for non-negative numeric values + 'Reds': [ + [0, 'rgb(220,220,220)'], [0.2, 'rgb(245,195,157)'], + [0.4, 'rgb(245,160,105)'], [1, 'rgb(178,10,28)'] + ], + + // Scale for non-positive numeric values + 'Blues': [ + [0, 'rgb(5,10,172)'], [0.35, 'rgb(40,60,190)'], + [0.5, 'rgb(70,100,245)'], [0.6, 'rgb(90,120,245)'], + [0.7, 'rgb(106,137,247)'], [1, 'rgb(220,220,220)'] + ], + + 'Picnic': [ + [0, 'rgb(0,0,255)'], [0.1, 'rgb(51,153,255)'], + [0.2, 'rgb(102,204,255)'], [0.3, 'rgb(153,204,255)'], + [0.4, 'rgb(204,204,255)'], [0.5, 'rgb(255,255,255)'], + [0.6, 'rgb(255,204,255)'], [0.7, 'rgb(255,153,255)'], + [0.8, 'rgb(255,102,204)'], [0.9, 'rgb(255,102,102)'], + [1, 'rgb(255,0,0)'] + ], + + 'Rainbow': [ + [0, 'rgb(150,0,90)'], [0.125, 'rgb(0,0,200)'], + [0.25, 'rgb(0,25,255)'], [0.375, 'rgb(0,152,255)'], + [0.5, 'rgb(44,255,150)'], [0.625, 'rgb(151,255,0)'], + [0.75, 'rgb(255,234,0)'], [0.875, 'rgb(255,111,0)'], + [1, 'rgb(255,0,0)'] + ], + + 'Portland': [ + [0, 'rgb(12,51,131)'], [0.25, 'rgb(10,136,186)'], + [0.5, 'rgb(242,211,56)'], [0.75, 'rgb(242,143,56)'], + [1, 'rgb(217,30,30)'] + ], + + 'Jet': [ + [0, 'rgb(0,0,131)'], [0.125, 'rgb(0,60,170)'], + [0.375, 'rgb(5,255,255)'], [0.625, 'rgb(255,255,0)'], + [0.875, 'rgb(250,0,0)'], [1, 'rgb(128,0,0)'] + ], + + 'Hot': [ + [0, 'rgb(0,0,0)'], [0.3, 'rgb(230,0,0)'], + [0.6, 'rgb(255,210,0)'], [1, 'rgb(255,255,255)'] + ], + + 'Blackbody': [ + [0, 'rgb(0,0,0)'], [0.2, 'rgb(230,0,0)'], + [0.4, 'rgb(230,210,0)'], [0.7, 'rgb(255,255,255)'], + [1, 'rgb(160,200,255)'] + ], + + 'Earth': [ + [0, 'rgb(0,0,130)'], [0.1, 'rgb(0,180,180)'], + [0.2, 'rgb(40,210,40)'], [0.4, 'rgb(230,230,50)'], + [0.6, 'rgb(120,70,20)'], [1, 'rgb(255,255,255)'] + ], + + 'Electric': [ + [0, 'rgb(0,0,0)'], [0.15, 'rgb(30,0,100)'], + [0.4, 'rgb(120,0,100)'], [0.6, 'rgb(160,90,0)'], + [0.8, 'rgb(230,200,0)'], [1, 'rgb(255,250,220)'] + ], + + 'Viridis': [ + [0, '#440154'], [0.06274509803921569, '#48186a'], + [0.12549019607843137, '#472d7b'], [0.18823529411764706, '#424086'], + [0.25098039215686274, '#3b528b'], [0.3137254901960784, '#33638d'], + [0.3764705882352941, '#2c728e'], [0.4392156862745098, '#26828e'], + [0.5019607843137255, '#21918c'], [0.5647058823529412, '#1fa088'], + [0.6274509803921569, '#28ae80'], [0.6901960784313725, '#3fbc73'], + [0.7529411764705882, '#5ec962'], [0.8156862745098039, '#84d44b'], + [0.8784313725490196, '#addc30'], [0.9411764705882353, '#d8e219'], + [1, '#fde725'] + ] +}; + +},{}],46:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +// for automatic alignment on dragging, <1/3 means left align, +// >2/3 means right, and between is center. Pick the right fraction +// based on where you are, and return the fraction corresponding to +// that position on the object +module.exports = function align(v, dv, v0, v1, anchor) { + var vmin = (v - v0) / (v1 - v0), + vmax = vmin + dv / (v1 - v0), + vc = (vmin + vmax) / 2; + + // explicitly specified anchor + if(anchor === 'left' || anchor === 'bottom') return vmin; + if(anchor === 'center' || anchor === 'middle') return vc; + if(anchor === 'right' || anchor === 'top') return vmax; + + // automatic based on position + if(vmin < (2 / 3) - vc) return vmin; + if(vmax > (4 / 3) - vc) return vmax; + return vc; +}; + +},{}],47:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + + +// set cursors pointing toward the closest corner/side, +// to indicate alignment +// x and y are 0-1, fractions of the plot area +var cursorset = [ + ['sw-resize', 's-resize', 'se-resize'], + ['w-resize', 'move', 'e-resize'], + ['nw-resize', 'n-resize', 'ne-resize'] +]; + +module.exports = function getCursor(x, y, xanchor, yanchor) { + if(xanchor === 'left') x = 0; + else if(xanchor === 'center') x = 1; + else if(xanchor === 'right') x = 2; + else x = Lib.constrain(Math.floor(x * 3), 0, 2); + + if(yanchor === 'bottom') y = 0; + else if(yanchor === 'middle') y = 1; + else if(yanchor === 'top') y = 2; + else y = Lib.constrain(Math.floor(y * 3), 0, 2); + + return cursorset[y][x]; +}; + +},{"../../lib":122}],48:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Plotly = require('../../plotly'); +var Lib = require('../../lib'); + +var constants = require('../../plots/cartesian/constants'); + + +var dragElement = module.exports = {}; + +dragElement.align = require('./align'); +dragElement.getCursor = require('./cursor'); + +var unhover = require('./unhover'); +dragElement.unhover = unhover.wrapped; +dragElement.unhoverRaw = unhover.raw; + +/** + * Abstracts click & drag interactions + * @param {object} options with keys: + * element (required) the DOM element to drag + * prepFn (optional) function(event, startX, startY) + * executed on mousedown + * startX and startY are the clientX and clientY pixel position + * of the mousedown event + * moveFn (optional) function(dx, dy, dragged) + * executed on move + * dx and dy are the net pixel offset of the drag, + * dragged is true/false, has the mouse moved enough to + * constitute a drag + * doneFn (optional) function(dragged, numClicks) + * executed on mouseup, or mouseout of window since + * we don't get events after that + * dragged is as in moveFn + * numClicks is how many clicks we've registered within + * a doubleclick time + * setCursor (optional) function(event) + * executed on mousemove before mousedown + * the purpose of this callback is to update the mouse cursor before + * the click & drag interaction has been initiated + */ +dragElement.init = function init(options) { + var gd = Lib.getPlotDiv(options.element) || {}, + numClicks = 1, + DBLCLICKDELAY = constants.DBLCLICKDELAY, + startX, + startY, + newMouseDownTime, + dragCover, + initialTarget, + initialOnMouseMove; + + if(!gd._mouseDownTime) gd._mouseDownTime = 0; + + function onStart(e) { + // disable call to options.setCursor(evt) + options.element.onmousemove = initialOnMouseMove; + + // make dragging and dragged into properties of gd + // so that others can look at and modify them + gd._dragged = false; + gd._dragging = true; + startX = e.clientX; + startY = e.clientY; + initialTarget = e.target; + + newMouseDownTime = (new Date()).getTime(); + if(newMouseDownTime - gd._mouseDownTime < DBLCLICKDELAY) { + // in a click train + numClicks += 1; + } + else { + // new click train + numClicks = 1; + gd._mouseDownTime = newMouseDownTime; + } + + if(options.prepFn) options.prepFn(e, startX, startY); + + dragCover = coverSlip(); + + dragCover.onmousemove = onMove; + dragCover.onmouseup = onDone; + dragCover.onmouseout = onDone; + + dragCover.style.cursor = window.getComputedStyle(options.element).cursor; + + return Lib.pauseEvent(e); + } + + function onMove(e) { + var dx = e.clientX - startX, + dy = e.clientY - startY, + minDrag = options.minDrag || constants.MINDRAG; + + if(Math.abs(dx) < minDrag) dx = 0; + if(Math.abs(dy) < minDrag) dy = 0; + if(dx || dy) { + gd._dragged = true; + dragElement.unhover(gd); + } + + if(options.moveFn) options.moveFn(dx, dy, gd._dragged); + + return Lib.pauseEvent(e); + } + + function onDone(e) { + // re-enable call to options.setCursor(evt) + initialOnMouseMove = options.element.onmousemove; + if(options.setCursor) options.element.onmousemove = options.setCursor; + + dragCover.onmousemove = null; + dragCover.onmouseup = null; + dragCover.onmouseout = null; + Lib.removeElement(dragCover); + + if(!gd._dragging) { + gd._dragged = false; + return; + } + gd._dragging = false; + + // don't count as a dblClick unless the mouseUp is also within + // the dblclick delay + if((new Date()).getTime() - gd._mouseDownTime > DBLCLICKDELAY) { + numClicks = Math.max(numClicks - 1, 1); + } + + if(options.doneFn) options.doneFn(gd._dragged, numClicks); + + if(!gd._dragged) { + var e2 = document.createEvent('MouseEvents'); + e2.initMouseEvent("click", e.bubbles, e.cancelable, e.view, 0, 0, 0, 0, 0, false, false, false, false, e.button, null); + initialTarget.dispatchEvent(e2); + } + + finishDrag(gd); + + gd._dragged = false; + + return Lib.pauseEvent(e); + } + + // enable call to options.setCursor(evt) + initialOnMouseMove = options.element.onmousemove; + if(options.setCursor) options.element.onmousemove = options.setCursor; + + options.element.onmousedown = onStart; + options.element.style.pointerEvents = 'all'; +}; + +function coverSlip() { + var cover = document.createElement('div'); + + cover.className = 'dragcover'; + var cStyle = cover.style; + cStyle.position = 'fixed'; + cStyle.left = 0; + cStyle.right = 0; + cStyle.top = 0; + cStyle.bottom = 0; + cStyle.zIndex = 999999999; + cStyle.background = 'none'; + + document.body.appendChild(cover); + + return cover; +} + +dragElement.coverSlip = coverSlip; + +function finishDrag(gd) { + gd._dragging = false; + if(gd._replotPending) Plotly.plot(gd); +} + +},{"../../lib":122,"../../plotly":145,"../../plots/cartesian/constants":155,"./align":46,"./cursor":47,"./unhover":49}],49:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +var Events = require('../../lib/events'); + + +var unhover = module.exports = {}; + + +unhover.wrapped = function(gd, evt, subplot) { + if(typeof gd === 'string') gd = document.getElementById(gd); + + // Important, clear any queued hovers + if(gd._hoverTimer) { + clearTimeout(gd._hoverTimer); + gd._hoverTimer = undefined; + } + + unhover.raw(gd, evt, subplot); +}; + + +// remove hover effects on mouse out, and emit unhover event +unhover.raw = function unhoverRaw(gd, evt) { + var fullLayout = gd._fullLayout; + + if(!evt) evt = {}; + if(evt.target && + Events.triggerHandler(gd, 'plotly_beforehover', evt) === false) { + return; + } + + fullLayout._hoverlayer.selectAll('g').remove(); + + if(evt.target && gd._hoverdata) { + gd.emit('plotly_unhover', {points: gd._hoverdata}); + } + + gd._hoverdata = undefined; +}; + +},{"../../lib/events":116}],50:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Registry = require('../../registry'); +var Color = require('../color'); +var Colorscale = require('../colorscale'); +var Lib = require('../../lib'); +var svgTextUtils = require('../../lib/svg_text_utils'); + +var xmlnsNamespaces = require('../../constants/xmlns_namespaces'); +var subTypes = require('../../traces/scatter/subtypes'); +var makeBubbleSizeFn = require('../../traces/scatter/make_bubble_size_func'); + +var drawing = module.exports = {}; + +// ----------------------------------------------------- +// styling functions for plot elements +// ----------------------------------------------------- + +drawing.font = function(s, family, size, color) { + // also allow the form font(s, {family, size, color}) + if(family && family.family) { + color = family.color; + size = family.size; + family = family.family; + } + if(family) s.style('font-family', family); + if(size + 1) s.style('font-size', size + 'px'); + if(color) s.call(Color.fill, color); +}; + +drawing.setPosition = function(s, x, y) { s.attr('x', x).attr('y', y); }; +drawing.setSize = function(s, w, h) { s.attr('width', w).attr('height', h); }; +drawing.setRect = function(s, x, y, w, h) { + s.call(drawing.setPosition, x, y).call(drawing.setSize, w, h); +}; + +drawing.translatePoint = function(d, sel, xa, ya) { + // put xp and yp into d if pixel scaling is already done + var x = d.xp || xa.c2p(d.x), + y = d.yp || ya.c2p(d.y); + + if(isNumeric(x) && isNumeric(y)) { + // for multiline text this works better + if(sel.node().nodeName === 'text') { + sel.attr('x', x).attr('y', y); + } else { + sel.attr('transform', 'translate(' + x + ',' + y + ')'); + } + } + else sel.remove(); +}; + +drawing.translatePoints = function(s, xa, ya, trace) { + s.each(function(d) { + var sel = d3.select(this); + drawing.translatePoint(d, sel, xa, ya, trace); + }); +}; + +drawing.getPx = function(s, styleAttr) { + // helper to pull out a px value from a style that may contain px units + // s is a d3 selection (will pull from the first one) + return Number(s.style(styleAttr).replace(/px$/, '')); +}; + +drawing.crispRound = function(gd, lineWidth, dflt) { + // for lines that disable antialiasing we want to + // make sure the width is an integer, and at least 1 if it's nonzero + + if(!lineWidth || !isNumeric(lineWidth)) return dflt || 0; + + // but not for static plots - these don't get antialiased anyway. + if(gd._context.staticPlot) return lineWidth; + + if(lineWidth < 1) return 1; + return Math.round(lineWidth); +}; + +drawing.singleLineStyle = function(d, s, lw, lc, ld) { + s.style('fill', 'none'); + var line = (((d || [])[0] || {}).trace || {}).line || {}, + lw1 = lw || line.width||0, + dash = ld || line.dash || ''; + + Color.stroke(s, lc || line.color); + drawing.dashLine(s, dash, lw1); +}; + +drawing.lineGroupStyle = function(s, lw, lc, ld) { + s.style('fill', 'none') + .each(function(d) { + var line = (((d || [])[0] || {}).trace || {}).line || {}, + lw1 = lw || line.width||0, + dash = ld || line.dash || ''; + + d3.select(this) + .call(Color.stroke, lc || line.color) + .call(drawing.dashLine, dash, lw1); + }); +}; + +drawing.dashLine = function(s, dash, lineWidth) { + var dlw = Math.max(lineWidth, 3); + + if(dash === 'solid') dash = ''; + else if(dash === 'dot') dash = dlw + 'px,' + dlw + 'px'; + else if(dash === 'dash') dash = (3 * dlw) + 'px,' + (3 * dlw) + 'px'; + else if(dash === 'longdash') dash = (5 * dlw) + 'px,' + (5 * dlw) + 'px'; + else if(dash === 'dashdot') { + dash = (3 * dlw) + 'px,' + dlw + 'px,' + dlw + 'px,' + dlw + 'px'; + } + else if(dash === 'longdashdot') { + dash = (5 * dlw) + 'px,' + (2 * dlw) + 'px,' + dlw + 'px,' + (2 * dlw) + 'px'; + } + // otherwise user wrote the dasharray themselves - leave it be + + s.style({ + 'stroke-dasharray': dash, + 'stroke-width': lineWidth + 'px' + }); +}; + +drawing.fillGroupStyle = function(s) { + s.style('stroke-width', 0) + .each(function(d) { + var shape = d3.select(this); + try { + shape.call(Color.fill, d[0].trace.fillcolor); + } + catch(e) { + Lib.error(e, s); + shape.remove(); + } + }); +}; + +var SYMBOLDEFS = require('./symbol_defs'); + +drawing.symbolNames = []; +drawing.symbolFuncs = []; +drawing.symbolNeedLines = {}; +drawing.symbolNoDot = {}; +drawing.symbolList = []; + +Object.keys(SYMBOLDEFS).forEach(function(k) { + var symDef = SYMBOLDEFS[k]; + drawing.symbolList = drawing.symbolList.concat( + [symDef.n, k, symDef.n + 100, k + '-open']); + drawing.symbolNames[symDef.n] = k; + drawing.symbolFuncs[symDef.n] = symDef.f; + if(symDef.needLine) { + drawing.symbolNeedLines[symDef.n] = true; + } + if(symDef.noDot) { + drawing.symbolNoDot[symDef.n] = true; + } + else { + drawing.symbolList = drawing.symbolList.concat( + [symDef.n + 200, k + '-dot', symDef.n + 300, k + '-open-dot']); + } +}); +var MAXSYMBOL = drawing.symbolNames.length, + // add a dot in the middle of the symbol + DOTPATH = 'M0,0.5L0.5,0L0,-0.5L-0.5,0Z'; + +drawing.symbolNumber = function(v) { + if(typeof v === 'string') { + var vbase = 0; + if(v.indexOf('-open') > 0) { + vbase = 100; + v = v.replace('-open', ''); + } + if(v.indexOf('-dot') > 0) { + vbase += 200; + v = v.replace('-dot', ''); + } + v = drawing.symbolNames.indexOf(v); + if(v >= 0) { v += vbase; } + } + if((v % 100 >= MAXSYMBOL) || v >= 400) { return 0; } + return Math.floor(Math.max(v, 0)); +}; + +function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerLine) { + // only scatter & box plots get marker path and opacity + // bars, histograms don't + if(Registry.traceIs(trace, 'symbols')) { + var sizeFn = makeBubbleSizeFn(trace); + + sel.attr('d', function(d) { + var r; + + // handle multi-trace graph edit case + if(d.ms === 'various' || marker.size === 'various') r = 3; + else { + r = subTypes.isBubble(trace) ? + sizeFn(d.ms) : (marker.size || 6) / 2; + } + + // store the calculated size so hover can use it + d.mrc = r; + + // turn the symbol into a sanitized number + var x = drawing.symbolNumber(d.mx || marker.symbol) || 0, + xBase = x % 100; + + // save if this marker is open + // because that impacts how to handle colors + d.om = x % 200 >= 100; + + return drawing.symbolFuncs[xBase](r) + + (x >= 200 ? DOTPATH : ''); + }) + .style('opacity', function(d) { + return (d.mo + 1 || marker.opacity + 1) - 1; + }); + } + + // 'so' is suspected outliers, for box plots + var fillColor, + lineColor, + lineWidth; + if(d.so) { + lineWidth = markerLine.outlierwidth; + lineColor = markerLine.outliercolor; + fillColor = marker.outliercolor; + } + else { + lineWidth = (d.mlw + 1 || markerLine.width + 1 || + // TODO: we need the latter for legends... can we get rid of it? + (d.trace ? d.trace.marker.line.width : 0) + 1) - 1; + + if('mlc' in d) lineColor = d.mlcc = lineScale(d.mlc); + // weird case: array wasn't long enough to apply to every point + else if(Array.isArray(markerLine.color)) lineColor = Color.defaultLine; + else lineColor = markerLine.color; + + if('mc' in d) fillColor = d.mcc = markerScale(d.mc); + else if(Array.isArray(marker.color)) fillColor = Color.defaultLine; + else fillColor = marker.color || 'rgba(0,0,0,0)'; + } + + if(d.om) { + // open markers can't have zero linewidth, default to 1px, + // and use fill color as stroke color + sel.call(Color.stroke, fillColor) + .style({ + 'stroke-width': (lineWidth || 1) + 'px', + fill: 'none' + }); + } + else { + sel.style('stroke-width', lineWidth + 'px') + .call(Color.fill, fillColor); + if(lineWidth) { + sel.call(Color.stroke, lineColor); + } + } +} + +drawing.singlePointStyle = function(d, sel, trace) { + var marker = trace.marker, + markerLine = marker.line; + + // allow array marker and marker line colors to be + // scaled by given max and min to colorscales + var markerScale = drawing.tryColorscale(marker, ''), + lineScale = drawing.tryColorscale(marker, 'line'); + + singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerLine); + +}; + +drawing.pointStyle = function(s, trace) { + if(!s.size()) return; + + // allow array marker and marker line colors to be + // scaled by given max and min to colorscales + var marker = trace.marker; + var markerScale = drawing.tryColorscale(marker, ''), + lineScale = drawing.tryColorscale(marker, 'line'); + + s.each(function(d) { + drawing.singlePointStyle(d, d3.select(this), trace, markerScale, lineScale); + }); +}; + +drawing.tryColorscale = function(marker, prefix) { + var cont = prefix ? Lib.nestedProperty(marker, prefix).get() : marker, + scl = cont.colorscale, + colorArray = cont.color; + + if(scl && Array.isArray(colorArray)) { + return Colorscale.makeColorScaleFunc( + Colorscale.extractScale(scl, cont.cmin, cont.cmax) + ); + } + else return Lib.identity; +}; + +// draw text at points +var TEXTOFFSETSIGN = {start: 1, end: -1, middle: 0, bottom: 1, top: -1}, + LINEEXPAND = 1.3; +drawing.textPointStyle = function(s, trace) { + s.each(function(d) { + var p = d3.select(this), + text = d.tx || trace.text; + + if(!text || Array.isArray(text)) { + // isArray test handles the case of (intentionally) missing + // or empty text within a text array + p.remove(); + return; + } + + var pos = d.tp || trace.textposition, + v = pos.indexOf('top') !== -1 ? 'top' : + pos.indexOf('bottom') !== -1 ? 'bottom' : 'middle', + h = pos.indexOf('left') !== -1 ? 'end' : + pos.indexOf('right') !== -1 ? 'start' : 'middle', + fontSize = d.ts || trace.textfont.size, + // if markers are shown, offset a little more than + // the nominal marker size + // ie 2/1.6 * nominal, bcs some markers are a bit bigger + r = d.mrc ? (d.mrc / 0.8 + 1) : 0; + + fontSize = (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; + + p.call(drawing.font, + d.tf || trace.textfont.family, + fontSize, + d.tc || trace.textfont.color) + .attr('text-anchor', h) + .text(text) + .call(svgTextUtils.convertToTspans); + var pgroup = d3.select(this.parentNode), + tspans = p.selectAll('tspan.line'), + numLines = ((tspans[0].length || 1) - 1) * LINEEXPAND + 1, + dx = TEXTOFFSETSIGN[h] * r, + dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + + (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; + + // fix the overall text group position + pgroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); + + // then fix multiline text + if(numLines > 1) { + tspans.attr({ x: p.attr('x'), y: p.attr('y') }); + } + }); +}; + +// generalized Catmull-Rom splines, per +// http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf +var CatmullRomExp = 0.5; +drawing.smoothopen = function(pts, smoothness) { + if(pts.length < 3) { return 'M' + pts.join('L');} + var path = 'M' + pts[0], + tangents = [], i; + for(i = 1; i < pts.length - 1; i++) { + tangents.push(makeTangent(pts[i - 1], pts[i], pts[i + 1], smoothness)); + } + path += 'Q' + tangents[0][0] + ' ' + pts[1]; + for(i = 2; i < pts.length - 1; i++) { + path += 'C' + tangents[i - 2][1] + ' ' + tangents[i - 1][0] + ' ' + pts[i]; + } + path += 'Q' + tangents[pts.length - 3][1] + ' ' + pts[pts.length - 1]; + return path; +}; + +drawing.smoothclosed = function(pts, smoothness) { + if(pts.length < 3) { return 'M' + pts.join('L') + 'Z'; } + var path = 'M' + pts[0], + pLast = pts.length - 1, + tangents = [makeTangent(pts[pLast], + pts[0], pts[1], smoothness)], + i; + for(i = 1; i < pLast; i++) { + tangents.push(makeTangent(pts[i - 1], pts[i], pts[i + 1], smoothness)); + } + tangents.push( + makeTangent(pts[pLast - 1], pts[pLast], pts[0], smoothness) + ); + + for(i = 1; i <= pLast; i++) { + path += 'C' + tangents[i - 1][1] + ' ' + tangents[i][0] + ' ' + pts[i]; + } + path += 'C' + tangents[pLast][1] + ' ' + tangents[0][0] + ' ' + pts[0] + 'Z'; + return path; +}; + +function makeTangent(prevpt, thispt, nextpt, smoothness) { + var d1x = prevpt[0] - thispt[0], + d1y = prevpt[1] - thispt[1], + d2x = nextpt[0] - thispt[0], + d2y = nextpt[1] - thispt[1], + d1a = Math.pow(d1x * d1x + d1y * d1y, CatmullRomExp / 2), + d2a = Math.pow(d2x * d2x + d2y * d2y, CatmullRomExp / 2), + numx = (d2a * d2a * d1x - d1a * d1a * d2x) * smoothness, + numy = (d2a * d2a * d1y - d1a * d1a * d2y) * smoothness, + denom1 = 3 * d2a * (d1a + d2a), + denom2 = 3 * d1a * (d1a + d2a); + return [ + [ + d3.round(thispt[0] + (denom1 && numx / denom1), 2), + d3.round(thispt[1] + (denom1 && numy / denom1), 2) + ], [ + d3.round(thispt[0] - (denom2 && numx / denom2), 2), + d3.round(thispt[1] - (denom2 && numy / denom2), 2) + ] + ]; +} + +// step paths - returns a generator function for paths +// with the given step shape +var STEPPATH = { + hv: function(p0, p1) { + return 'H' + d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2); + }, + vh: function(p0, p1) { + return 'V' + d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2); + }, + hvh: function(p0, p1) { + return 'H' + d3.round((p0[0] + p1[0]) / 2, 2) + 'V' + + d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2); + }, + vhv: function(p0, p1) { + return 'V' + d3.round((p0[1] + p1[1]) / 2, 2) + 'H' + + d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2); + } +}; +var STEPLINEAR = function(p0, p1) { + return 'L' + d3.round(p1[0], 2) + ',' + d3.round(p1[1], 2); +}; +drawing.steps = function(shape) { + var onestep = STEPPATH[shape] || STEPLINEAR; + return function(pts) { + var path = 'M' + d3.round(pts[0][0], 2) + ',' + d3.round(pts[0][1], 2); + for(var i = 1; i < pts.length; i++) { + path += onestep(pts[i - 1], pts[i]); + } + return path; + }; +}; + +// off-screen svg render testing element, shared by the whole page +// uses the id 'js-plotly-tester' and stores it in gd._tester +// makes a hash of cached text items in tester.node()._cache +// so we can add references to rendered text (including all info +// needed to fully determine its bounding rect) +drawing.makeTester = function(gd) { + var tester = d3.select('body') + .selectAll('#js-plotly-tester') + .data([0]); + + tester.enter().append('svg') + .attr('id', 'js-plotly-tester') + .attr(xmlnsNamespaces.svgAttrs) + .style({ + position: 'absolute', + left: '-10000px', + top: '-10000px', + width: '9000px', + height: '9000px', + 'z-index': '1' + }); + + // browsers differ on how they describe the bounding rect of + // the svg if its contents spill over... so make a 1x1px + // reference point we can measure off of. + var testref = tester.selectAll('.js-reference-point').data([0]); + testref.enter().append('path') + .classed('js-reference-point', true) + .attr('d', 'M0,0H1V1H0Z') + .style({ + 'stroke-width': 0, + fill: 'black' + }); + + if(!tester.node()._cache) { + tester.node()._cache = {}; + } + + gd._tester = tester; + gd._testref = testref; +}; + +// use our offscreen tester to get a clientRect for an element, +// in a reference frame where it isn't translated and its anchor +// point is at (0,0) +// always returns a copy of the bbox, so the caller can modify it safely +var savedBBoxes = [], + maxSavedBBoxes = 10000; +drawing.bBox = function(node) { + // cache elements we've already measured so we don't have to + // remeasure the same thing many times + var saveNum = node.attributes['data-bb']; + if(saveNum && saveNum.value) { + return Lib.extendFlat({}, savedBBoxes[saveNum.value]); + } + + var test3 = d3.select('#js-plotly-tester'), + tester = test3.node(); + + // copy the node to test into the tester + var testNode = node.cloneNode(true); + tester.appendChild(testNode); + // standardize its position... do we really want to do this? + d3.select(testNode).attr({ + x: 0, + y: 0, + transform: '' + }); + + var testRect = testNode.getBoundingClientRect(), + refRect = test3.select('.js-reference-point') + .node().getBoundingClientRect(); + + tester.removeChild(testNode); + + var bb = { + height: testRect.height, + width: testRect.width, + left: testRect.left - refRect.left, + top: testRect.top - refRect.top, + right: testRect.right - refRect.left, + bottom: testRect.bottom - refRect.top + }; + + // make sure we don't have too many saved boxes, + // or a long session could overload on memory + // by saving boxes for long-gone elements + if(savedBBoxes.length >= maxSavedBBoxes) { + d3.selectAll('[data-bb]').attr('data-bb', null); + savedBBoxes = []; + } + + // cache this bbox + node.setAttribute('data-bb', savedBBoxes.length); + savedBBoxes.push(bb); + + return Lib.extendFlat({}, bb); +}; + +/* + * make a robust clipPath url from a local id + * note! We'd better not be exporting from a page + * with a or the svg will not be portable! + */ +drawing.setClipUrl = function(s, localId) { + if(!localId) { + s.attr('clip-path', null); + return; + } + + var url = '#' + localId, + base = d3.select('base'); + + if(base.size() && base.attr('href')) url = window.location.href + url; + s.attr('clip-path', 'url(' + url + ')'); +}; + +},{"../../constants/xmlns_namespaces":109,"../../lib":122,"../../lib/svg_text_utils":134,"../../registry":194,"../../traces/scatter/make_bubble_size_func":249,"../../traces/scatter/subtypes":254,"../color":27,"../colorscale":41,"./symbol_defs":51,"d3":10,"fast-isnumeric":13}],51:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +/** Marker symbol definitions + * users can specify markers either by number or name + * add 100 (or '-open') and you get an open marker + * open markers have no fill and use line color as the stroke color + * add 200 (or '-dot') and you get a dot in the middle + * add both and you get both + */ + +module.exports = { + circle: { + n: 0, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; + } + }, + square: { + n: 1, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; + } + }, + diamond: { + n: 2, + f: function(r) { + var rd = d3.round(r * 1.3, 2); + return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z'; + } + }, + cross: { + n: 3, + f: function(r) { + var rc = d3.round(r * 0.4, 2), + rc2 = d3.round(r * 1.2, 2); + return 'M' + rc2 + ',' + rc + 'H' + rc + 'V' + rc2 + 'H-' + rc + + 'V' + rc + 'H-' + rc2 + 'V-' + rc + 'H-' + rc + 'V-' + rc2 + + 'H' + rc + 'V-' + rc + 'H' + rc2 + 'Z'; + } + }, + x: { + n: 4, + f: function(r) { + var rx = d3.round(r * 0.8 / Math.sqrt(2), 2), + ne = 'l' + rx + ',' + rx, + se = 'l' + rx + ',-' + rx, + sw = 'l-' + rx + ',-' + rx, + nw = 'l-' + rx + ',' + rx; + return 'M0,' + rx + ne + se + sw + se + sw + nw + sw + nw + ne + nw + ne + 'Z'; + } + }, + 'triangle-up': { + n: 5, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M-' + rt + ',' + r2 + 'H' + rt + 'L0,-' + rs + 'Z'; + } + }, + 'triangle-down': { + n: 6, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M-' + rt + ',-' + r2 + 'H' + rt + 'L0,' + rs + 'Z'; + } + }, + 'triangle-left': { + n: 7, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M' + r2 + ',-' + rt + 'V' + rt + 'L-' + rs + ',0Z'; + } + }, + 'triangle-right': { + n: 8, + f: function(r) { + var rt = d3.round(r * 2 / Math.sqrt(3), 2), + r2 = d3.round(r / 2, 2), + rs = d3.round(r, 2); + return 'M-' + r2 + ',-' + rt + 'V' + rt + 'L' + rs + ',0Z'; + } + }, + 'triangle-ne': { + n: 9, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M-' + r2 + ',-' + r1 + 'H' + r1 + 'V' + r2 + 'Z'; + } + }, + 'triangle-se': { + n: 10, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M' + r1 + ',-' + r2 + 'V' + r1 + 'H-' + r2 + 'Z'; + } + }, + 'triangle-sw': { + n: 11, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M' + r2 + ',' + r1 + 'H-' + r1 + 'V-' + r2 + 'Z'; + } + }, + 'triangle-nw': { + n: 12, + f: function(r) { + var r1 = d3.round(r * 0.6, 2), + r2 = d3.round(r * 1.2, 2); + return 'M-' + r1 + ',' + r2 + 'V-' + r1 + 'H' + r2 + 'Z'; + } + }, + pentagon: { + n: 13, + f: function(r) { + var x1 = d3.round(r * 0.951, 2), + x2 = d3.round(r * 0.588, 2), + y0 = d3.round(-r, 2), + y1 = d3.round(r * -0.309, 2), + y2 = d3.round(r * 0.809, 2); + return 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2 + 'H-' + x2 + + 'L-' + x1 + ',' + y1 + 'L0,' + y0 + 'Z'; + } + }, + hexagon: { + n: 14, + f: function(r) { + var y0 = d3.round(r, 2), + y1 = d3.round(r / 2, 2), + x = d3.round(r * Math.sqrt(3) / 2, 2); + return 'M' + x + ',-' + y1 + 'V' + y1 + 'L0,' + y0 + + 'L-' + x + ',' + y1 + 'V-' + y1 + 'L0,-' + y0 + 'Z'; + } + }, + hexagon2: { + n: 15, + f: function(r) { + var x0 = d3.round(r, 2), + x1 = d3.round(r / 2, 2), + y = d3.round(r * Math.sqrt(3) / 2, 2); + return 'M-' + x1 + ',' + y + 'H' + x1 + 'L' + x0 + + ',0L' + x1 + ',-' + y + 'H-' + x1 + 'L-' + x0 + ',0Z'; + } + }, + octagon: { + n: 16, + f: function(r) { + var a = d3.round(r * 0.924, 2), + b = d3.round(r * 0.383, 2); + return 'M-' + b + ',-' + a + 'H' + b + 'L' + a + ',-' + b + 'V' + b + + 'L' + b + ',' + a + 'H-' + b + 'L-' + a + ',' + b + 'V-' + b + 'Z'; + } + }, + star: { + n: 17, + f: function(r) { + var rs = r * 1.4, + x1 = d3.round(rs * 0.225, 2), + x2 = d3.round(rs * 0.951, 2), + x3 = d3.round(rs * 0.363, 2), + x4 = d3.round(rs * 0.588, 2), + y0 = d3.round(-rs, 2), + y1 = d3.round(rs * -0.309, 2), + y3 = d3.round(rs * 0.118, 2), + y4 = d3.round(rs * 0.809, 2), + y5 = d3.round(rs * 0.382, 2); + return 'M' + x1 + ',' + y1 + 'H' + x2 + 'L' + x3 + ',' + y3 + + 'L' + x4 + ',' + y4 + 'L0,' + y5 + 'L-' + x4 + ',' + y4 + + 'L-' + x3 + ',' + y3 + 'L-' + x2 + ',' + y1 + 'H-' + x1 + + 'L0,' + y0 + 'Z'; + } + }, + hexagram: { + n: 18, + f: function(r) { + var y = d3.round(r * 0.66, 2), + x1 = d3.round(r * 0.38, 2), + x2 = d3.round(r * 0.76, 2); + return 'M-' + x2 + ',0l-' + x1 + ',-' + y + 'h' + x2 + + 'l' + x1 + ',-' + y + 'l' + x1 + ',' + y + 'h' + x2 + + 'l-' + x1 + ',' + y + 'l' + x1 + ',' + y + 'h-' + x2 + + 'l-' + x1 + ',' + y + 'l-' + x1 + ',-' + y + 'h-' + x2 + 'Z'; + } + }, + 'star-triangle-up': { + n: 19, + f: function(r) { + var x = d3.round(r * Math.sqrt(3) * 0.8, 2), + y1 = d3.round(r * 0.8, 2), + y2 = d3.round(r * 1.6, 2), + rc = d3.round(r * 4, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M-' + x + ',' + y1 + aPart + x + ',' + y1 + + aPart + '0,-' + y2 + aPart + '-' + x + ',' + y1 + 'Z'; + } + }, + 'star-triangle-down': { + n: 20, + f: function(r) { + var x = d3.round(r * Math.sqrt(3) * 0.8, 2), + y1 = d3.round(r * 0.8, 2), + y2 = d3.round(r * 1.6, 2), + rc = d3.round(r * 4, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M' + x + ',-' + y1 + aPart + '-' + x + ',-' + y1 + + aPart + '0,' + y2 + aPart + x + ',-' + y1 + 'Z'; + } + }, + 'star-square': { + n: 21, + f: function(r) { + var rp = d3.round(r * 1.1, 2), + rc = d3.round(r * 2, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M-' + rp + ',-' + rp + aPart + '-' + rp + ',' + rp + + aPart + rp + ',' + rp + aPart + rp + ',-' + rp + + aPart + '-' + rp + ',-' + rp + 'Z'; + } + }, + 'star-diamond': { + n: 22, + f: function(r) { + var rp = d3.round(r * 1.4, 2), + rc = d3.round(r * 1.9, 2), + aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; + return 'M-' + rp + ',0' + aPart + '0,' + rp + + aPart + rp + ',0' + aPart + '0,-' + rp + + aPart + '-' + rp + ',0' + 'Z'; + } + }, + 'diamond-tall': { + n: 23, + f: function(r) { + var x = d3.round(r * 0.7, 2), + y = d3.round(r * 1.4, 2); + return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z'; + } + }, + 'diamond-wide': { + n: 24, + f: function(r) { + var x = d3.round(r * 1.4, 2), + y = d3.round(r * 0.7, 2); + return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z'; + } + }, + hourglass: { + n: 25, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'H-' + rs + 'L' + rs + ',-' + rs + 'H-' + rs + 'Z'; + }, + noDot: true + }, + bowtie: { + n: 26, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'V-' + rs + 'L-' + rs + ',' + rs + 'V-' + rs + 'Z'; + }, + noDot: true + }, + 'circle-cross': { + n: 27, + f: function(r) { + var rs = d3.round(r, 2); + return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs + + 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; + }, + needLine: true, + noDot: true + }, + 'circle-x': { + n: 28, + f: function(r) { + var rs = d3.round(r, 2), + rc = d3.round(r / Math.sqrt(2), 2); + return 'M' + rc + ',' + rc + 'L-' + rc + ',-' + rc + + 'M' + rc + ',-' + rc + 'L-' + rc + ',' + rc + + 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; + }, + needLine: true, + noDot: true + }, + 'square-cross': { + n: 29, + f: function(r) { + var rs = d3.round(r, 2); + return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs + + 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; + }, + needLine: true, + noDot: true + }, + 'square-x': { + n: 30, + f: function(r) { + var rs = d3.round(r, 2); + return 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs + + 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs + + 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; + }, + needLine: true, + noDot: true + }, + 'diamond-cross': { + n: 31, + f: function(r) { + var rd = d3.round(r * 1.3, 2); + return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' + + 'M0,-' + rd + 'V' + rd + 'M-' + rd + ',0H' + rd; + }, + needLine: true, + noDot: true + }, + 'diamond-x': { + n: 32, + f: function(r) { + var rd = d3.round(r * 1.3, 2), + r2 = d3.round(r * 0.65, 2); + return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' + + 'M-' + r2 + ',-' + r2 + 'L' + r2 + ',' + r2 + + 'M-' + r2 + ',' + r2 + 'L' + r2 + ',-' + r2; + }, + needLine: true, + noDot: true + }, + 'cross-thin': { + n: 33, + f: function(r) { + var rc = d3.round(r * 1.4, 2); + return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc; + }, + needLine: true, + noDot: true + }, + 'x-thin': { + n: 34, + f: function(r) { + var rx = d3.round(r, 2); + return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx + + 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx; + }, + needLine: true, + noDot: true + }, + asterisk: { + n: 35, + f: function(r) { + var rc = d3.round(r * 1.2, 2); + var rs = d3.round(r * 0.85, 2); + return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc + + 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs + + 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs; + }, + needLine: true, + noDot: true + }, + hash: { + n: 36, + f: function(r) { + var r1 = d3.round(r / 2, 2), + r2 = d3.round(r, 2); + return 'M' + r1 + ',' + r2 + 'V-' + r2 + + 'm-' + r2 + ',0V' + r2 + + 'M' + r2 + ',' + r1 + 'H-' + r2 + + 'm0,-' + r2 + 'H' + r2; + }, + needLine: true + }, + 'y-up': { + n: 37, + f: function(r) { + var x = d3.round(r * 1.2, 2), + y0 = d3.round(r * 1.6, 2), + y1 = d3.round(r * 0.8, 2); + return 'M-' + x + ',' + y1 + 'L0,0M' + x + ',' + y1 + 'L0,0M0,-' + y0 + 'L0,0'; + }, + needLine: true, + noDot: true + }, + 'y-down': { + n: 38, + f: function(r) { + var x = d3.round(r * 1.2, 2), + y0 = d3.round(r * 1.6, 2), + y1 = d3.round(r * 0.8, 2); + return 'M-' + x + ',-' + y1 + 'L0,0M' + x + ',-' + y1 + 'L0,0M0,' + y0 + 'L0,0'; + }, + needLine: true, + noDot: true + }, + 'y-left': { + n: 39, + f: function(r) { + var y = d3.round(r * 1.2, 2), + x0 = d3.round(r * 1.6, 2), + x1 = d3.round(r * 0.8, 2); + return 'M' + x1 + ',' + y + 'L0,0M' + x1 + ',-' + y + 'L0,0M-' + x0 + ',0L0,0'; + }, + needLine: true, + noDot: true + }, + 'y-right': { + n: 40, + f: function(r) { + var y = d3.round(r * 1.2, 2), + x0 = d3.round(r * 1.6, 2), + x1 = d3.round(r * 0.8, 2); + return 'M-' + x1 + ',' + y + 'L0,0M-' + x1 + ',-' + y + 'L0,0M' + x0 + ',0L0,0'; + }, + needLine: true, + noDot: true + }, + 'line-ew': { + n: 41, + f: function(r) { + var rc = d3.round(r * 1.4, 2); + return 'M' + rc + ',0H-' + rc; + }, + needLine: true, + noDot: true + }, + 'line-ns': { + n: 42, + f: function(r) { + var rc = d3.round(r * 1.4, 2); + return 'M0,' + rc + 'V-' + rc; + }, + needLine: true, + noDot: true + }, + 'line-ne': { + n: 43, + f: function(r) { + var rx = d3.round(r, 2); + return 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx; + }, + needLine: true, + noDot: true + }, + 'line-nw': { + n: 44, + f: function(r) { + var rx = d3.round(r, 2); + return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx; + }, + needLine: true, + noDot: true + } +}; + +},{"d3":10}],52:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + visible: { + valType: 'boolean', + + + }, + type: { + valType: 'enumerated', + values: ['percent', 'constant', 'sqrt', 'data'], + + + }, + symmetric: { + valType: 'boolean', + + + }, + array: { + valType: 'data_array', + + }, + arrayminus: { + valType: 'data_array', + + }, + value: { + valType: 'number', + min: 0, + dflt: 10, + + + }, + valueminus: { + valType: 'number', + min: 0, + dflt: 10, + + + }, + traceref: { + valType: 'integer', + min: 0, + dflt: 0, + + }, + tracerefminus: { + valType: 'integer', + min: 0, + dflt: 0, + + }, + copy_ystyle: { + valType: 'boolean', + + }, + copy_zstyle: { + valType: 'boolean', + + }, + color: { + valType: 'color', + + + }, + thickness: { + valType: 'number', + min: 0, + dflt: 2, + + + }, + width: { + valType: 'number', + min: 0, + + + }, + + _deprecated: { + opacity: { + valType: 'number', + + + } + } +}; + +},{}],53:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Registry = require('../../registry'); +var Axes = require('../../plots/cartesian/axes'); + +var makeComputeError = require('./compute_error'); + + +module.exports = function calc(gd) { + var calcdata = gd.calcdata; + + for(var i = 0; i < calcdata.length; i++) { + var calcTrace = calcdata[i], + trace = calcTrace[0].trace; + + if(!Registry.traceIs(trace, 'errorBarsOK')) continue; + + var xa = Axes.getFromId(gd, trace.xaxis), + ya = Axes.getFromId(gd, trace.yaxis); + + calcOneAxis(calcTrace, trace, xa, 'x'); + calcOneAxis(calcTrace, trace, ya, 'y'); + } +}; + +function calcOneAxis(calcTrace, trace, axis, coord) { + var opts = trace['error_' + coord] || {}, + isVisible = (opts.visible && ['linear', 'log'].indexOf(axis.type) !== -1), + vals = []; + + if(!isVisible) return; + + var computeError = makeComputeError(opts); + + for(var i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i], + calcCoord = calcPt[coord]; + + if(!isNumeric(axis.c2l(calcCoord))) continue; + + var errors = computeError(calcCoord, i); + if(isNumeric(errors[0]) && isNumeric(errors[1])) { + var shoe = calcPt[coord + 's'] = calcCoord - errors[0], + hat = calcPt[coord + 'h'] = calcCoord + errors[1]; + vals.push(shoe, hat); + } + } + + Axes.expand(axis, vals, {padded: true}); +} + +},{"../../plots/cartesian/axes":150,"../../registry":194,"./compute_error":54,"fast-isnumeric":13}],54:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +/** + * Error bar computing function generator + * + * N.B. The generated function does not clean the dataPt entries. Non-numeric + * entries result in undefined error magnitudes. + * + * @param {object} opts error bar attributes + * + * @return {function} : + * @param {numeric} dataPt data point from where to compute the error magnitude + * @param {number} index index of dataPt in its corresponding data array + * @return {array} + * - error[0] : error magnitude in the negative direction + * - error[1] : " " " " positive " + */ +module.exports = function makeComputeError(opts) { + var type = opts.type, + symmetric = opts.symmetric; + + if(type === 'data') { + var array = opts.array, + arrayminus = opts.arrayminus; + + if(symmetric || arrayminus === undefined) { + return function computeError(dataPt, index) { + var val = +(array[index]); + return [val, val]; + }; + } + else { + return function computeError(dataPt, index) { + return [+arrayminus[index], +array[index]]; + }; + } + } + else { + var computeErrorValue = makeComputeErrorValue(type, opts.value), + computeErrorValueMinus = makeComputeErrorValue(type, opts.valueminus); + + if(symmetric || opts.valueminus === undefined) { + return function computeError(dataPt) { + var val = computeErrorValue(dataPt); + return [val, val]; + }; + } + else { + return function computeError(dataPt) { + return [ + computeErrorValueMinus(dataPt), + computeErrorValue(dataPt) + ]; + }; + } + } +}; + +/** + * Compute error bar magnitude (for all types except data) + * + * @param {string} type error bar type + * @param {numeric} value error bar value + * + * @return {function} : + * @param {numeric} dataPt + */ +function makeComputeErrorValue(type, value) { + if(type === 'percent') { + return function(dataPt) { + return Math.abs(dataPt * value / 100); + }; + } + if(type === 'constant') { + return function() { + return Math.abs(value); + }; + } + if(type === 'sqrt') { + return function(dataPt) { + return Math.sqrt(Math.abs(dataPt)); + }; + } +} + +},{}],55:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Registry = require('../../registry'); +var Lib = require('../../lib'); + +var attributes = require('./attributes'); + + +module.exports = function(traceIn, traceOut, defaultColor, opts) { + var objName = 'error_' + opts.axis, + containerOut = traceOut[objName] = {}, + containerIn = traceIn[objName] || {}; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + var hasErrorBars = ( + containerIn.array !== undefined || + containerIn.value !== undefined || + containerIn.type === 'sqrt' + ); + + var visible = coerce('visible', hasErrorBars); + + if(visible === false) return; + + var type = coerce('type', 'array' in containerIn ? 'data' : 'percent'), + symmetric = true; + + if(type !== 'sqrt') { + symmetric = coerce('symmetric', + !((type === 'data' ? 'arrayminus' : 'valueminus') in containerIn)); + } + + if(type === 'data') { + var array = coerce('array'); + if(!array) containerOut.array = []; + coerce('traceref'); + if(!symmetric) { + var arrayminus = coerce('arrayminus'); + if(!arrayminus) containerOut.arrayminus = []; + coerce('tracerefminus'); + } + } + else if(type === 'percent' || type === 'constant') { + coerce('value'); + if(!symmetric) coerce('valueminus'); + } + + var copyAttr = 'copy_' + opts.inherit + 'style'; + if(opts.inherit) { + var inheritObj = traceOut['error_' + opts.inherit]; + if((inheritObj || {}).visible) { + coerce(copyAttr, !(containerIn.color || + isNumeric(containerIn.thickness) || + isNumeric(containerIn.width))); + } + } + if(!opts.inherit || !containerOut[copyAttr]) { + coerce('color', defaultColor); + coerce('thickness'); + coerce('width', Registry.traceIs(traceOut, 'gl3d') ? 0 : 4); + } +}; + +},{"../../lib":122,"../../registry":194,"./attributes":52,"fast-isnumeric":13}],56:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var errorBars = module.exports = {}; + +errorBars.attributes = require('./attributes'); + +errorBars.supplyDefaults = require('./defaults'); + +errorBars.calc = require('./calc'); + +errorBars.calcFromTrace = function(trace, layout) { + var x = trace.x || [], + y = trace.y, + len = x.length || y.length; + + var calcdataMock = new Array(len); + + for(var i = 0; i < len; i++) { + calcdataMock[i] = { + x: x[i], + y: y[i] + }; + } + + calcdataMock[0].trace = trace; + + errorBars.calc({ + calcdata: [calcdataMock], + _fullLayout: layout + }); + + return calcdataMock; +}; + +errorBars.plot = require('./plot'); + +errorBars.style = require('./style'); + +errorBars.hoverInfo = function(calcPoint, trace, hoverPoint) { + if((trace.error_y || {}).visible) { + hoverPoint.yerr = calcPoint.yh - calcPoint.y; + if(!trace.error_y.symmetric) hoverPoint.yerrneg = calcPoint.y - calcPoint.ys; + } + if((trace.error_x || {}).visible) { + hoverPoint.xerr = calcPoint.xh - calcPoint.x; + if(!trace.error_x.symmetric) hoverPoint.xerrneg = calcPoint.x - calcPoint.xs; + } +}; + +},{"./attributes":52,"./calc":53,"./defaults":55,"./plot":57,"./style":58}],57:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var subTypes = require('../../traces/scatter/subtypes'); + +module.exports = function plot(traces, plotinfo, transitionOpts) { + var isNew; + + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + var hasAnimation = transitionOpts && transitionOpts.duration > 0; + + traces.each(function(d) { + var trace = d[0].trace, + // || {} is in case the trace (specifically scatterternary) + // doesn't support error bars at all, but does go through + // the scatter.plot mechanics, which calls ErrorBars.plot + // internally + xObj = trace.error_x || {}, + yObj = trace.error_y || {}; + + var keyFunc; + + if(trace.ids) { + keyFunc = function(d) {return d.id;}; + } + + var sparse = ( + subTypes.hasMarkers(trace) && + trace.marker.maxdisplayed > 0 + ); + + if(!yObj.visible && !xObj.visible) return; + + var errorbars = d3.select(this).selectAll('g.errorbar') + .data(d, keyFunc); + + errorbars.exit().remove(); + + errorbars.style('opacity', 1); + + var enter = errorbars.enter().append('g') + .classed('errorbar', true); + + if(hasAnimation) { + enter.style('opacity', 0).transition() + .duration(transitionOpts.duration) + .style('opacity', 1); + } + + errorbars.each(function(d) { + var errorbar = d3.select(this); + var coords = errorCoords(d, xa, ya); + + if(sparse && !d.vis) return; + + var path; + + if(yObj.visible && isNumeric(coords.x) && + isNumeric(coords.yh) && + isNumeric(coords.ys)) { + var yw = yObj.width; + + path = 'M' + (coords.x - yw) + ',' + + coords.yh + 'h' + (2 * yw) + // hat + 'm-' + yw + ',0V' + coords.ys; // bar + + + if(!coords.noYS) path += 'm-' + yw + ',0h' + (2 * yw); // shoe + + var yerror = errorbar.select('path.yerror'); + + isNew = !yerror.size(); + + if(isNew) { + yerror = errorbar.append('path') + .classed('yerror', true); + } else if(hasAnimation) { + yerror = yerror + .transition() + .duration(transitionOpts.duration) + .ease(transitionOpts.easing); + } + + yerror.attr('d', path); + } + + if(xObj.visible && isNumeric(coords.y) && + isNumeric(coords.xh) && + isNumeric(coords.xs)) { + var xw = (xObj.copy_ystyle ? yObj : xObj).width; + + path = 'M' + coords.xh + ',' + + (coords.y - xw) + 'v' + (2 * xw) + // hat + 'm0,-' + xw + 'H' + coords.xs; // bar + + if(!coords.noXS) path += 'm0,-' + xw + 'v' + (2 * xw); // shoe + + var xerror = errorbar.select('path.xerror'); + + isNew = !xerror.size(); + + if(isNew) { + xerror = errorbar.append('path') + .classed('xerror', true); + } else if(hasAnimation) { + xerror = xerror + .transition() + .duration(transitionOpts.duration) + .ease(transitionOpts.easing); + } + + xerror.attr('d', path); + } + }); + }); +}; + +// compute the coordinates of the error-bar objects +function errorCoords(d, xa, ya) { + var out = { + x: xa.c2p(d.x), + y: ya.c2p(d.y) + }; + + // calculate the error bar size and hat and shoe locations + if(d.yh !== undefined) { + out.yh = ya.c2p(d.yh); + out.ys = ya.c2p(d.ys); + + // if the shoes go off-scale (ie log scale, error bars past zero) + // clip the bar and hide the shoes + if(!isNumeric(out.ys)) { + out.noYS = true; + out.ys = ya.c2p(d.ys, true); + } + } + + if(d.xh !== undefined) { + out.xh = xa.c2p(d.xh); + out.xs = xa.c2p(d.xs); + + if(!isNumeric(out.xs)) { + out.noXS = true; + out.xs = xa.c2p(d.xs, true); + } + } + + return out; +} + +},{"../../traces/scatter/subtypes":254,"d3":10,"fast-isnumeric":13}],58:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Color = require('../color'); + + +module.exports = function style(traces) { + traces.each(function(d) { + var trace = d[0].trace, + yObj = trace.error_y || {}, + xObj = trace.error_x || {}; + + var s = d3.select(this); + + s.selectAll('path.yerror') + .style('stroke-width', yObj.thickness + 'px') + .call(Color.stroke, yObj.color); + + if(xObj.copy_ystyle) xObj = yObj; + + s.selectAll('path.xerror') + .style('stroke-width', xObj.thickness + 'px') + .call(Color.stroke, xObj.color); + }); +}; + +},{"../color":27,"d3":10}],59:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var cartesianConstants = require('../../plots/cartesian/constants'); + + +module.exports = { + _isLinkedToArray: 'image', + + visible: { + valType: 'boolean', + + dflt: true, + + }, + + source: { + valType: 'string', + + + }, + + layer: { + valType: 'enumerated', + values: ['below', 'above'], + dflt: 'above', + + + }, + + sizex: { + valType: 'number', + + dflt: 0, + + }, + + sizey: { + valType: 'number', + + dflt: 0, + + }, + + sizing: { + valType: 'enumerated', + values: ['fill', 'contain', 'stretch'], + dflt: 'contain', + + + }, + + opacity: { + valType: 'number', + + min: 0, + max: 1, + dflt: 1, + + }, + + x: { + valType: 'any', + + dflt: 0, + + }, + + y: { + valType: 'any', + + dflt: 0, + + }, + + xanchor: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'left', + + + }, + + yanchor: { + valType: 'enumerated', + values: ['top', 'middle', 'bottom'], + dflt: 'top', + + + }, + + xref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.x.toString() + ], + dflt: 'paper', + + + }, + + yref: { + valType: 'enumerated', + values: [ + 'paper', + cartesianConstants.idRegex.y.toString() + ], + dflt: 'paper', + + + } +}; + +},{"../../plots/cartesian/constants":155}],60:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var Axes = require('../../plots/cartesian/axes'); +var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); + +var attributes = require('./attributes'); +var name = 'images'; + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + var opts = { + name: name, + handleItemDefaults: imageDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + + +function imageDefaults(imageIn, imageOut, fullLayout) { + + function coerce(attr, dflt) { + return Lib.coerce(imageIn, imageOut, attributes, attr, dflt); + } + + var source = coerce('source'); + var visible = coerce('visible', !!source); + + if(!visible) return imageOut; + + coerce('layer'); + coerce('x'); + coerce('y'); + coerce('xanchor'); + coerce('yanchor'); + coerce('sizex'); + coerce('sizey'); + coerce('sizing'); + coerce('opacity'); + + var gdMock = { _fullLayout: fullLayout }, + axLetters = ['x', 'y']; + + for(var i = 0; i < 2; i++) { + // 'paper' is the fallback axref + Axes.coerceRef(imageIn, imageOut, gdMock, axLetters[i], 'paper'); + } + + return imageOut; +} + +},{"../../lib":122,"../../plots/array_container_defaults":147,"../../plots/cartesian/axes":150,"./attributes":59}],61:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = require('d3'); +var Drawing = require('../drawing'); +var Axes = require('../../plots/cartesian/axes'); +var xmlnsNamespaces = require('../../constants/xmlns_namespaces'); + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout, + imageDataAbove = [], + imageDataSubplot = [], + imageDataBelow = []; + + // Sort into top, subplot, and bottom layers + for(var i = 0; i < fullLayout.images.length; i++) { + var img = fullLayout.images[i]; + + if(img.visible) { + if(img.layer === 'below' && img.xref !== 'paper' && img.yref !== 'paper') { + imageDataSubplot.push(img); + } else if(img.layer === 'above') { + imageDataAbove.push(img); + } else { + imageDataBelow.push(img); + } + } + } + + + var anchors = { + x: { + left: { sizing: 'xMin', offset: 0 }, + center: { sizing: 'xMid', offset: -1 / 2 }, + right: { sizing: 'xMax', offset: -1 } + }, + y: { + top: { sizing: 'YMin', offset: 0 }, + middle: { sizing: 'YMid', offset: -1 / 2 }, + bottom: { sizing: 'YMax', offset: -1 } + } + }; + + + // Images must be converted to dataURL's for exporting. + function setImage(d) { + var thisImage = d3.select(this); + + if(this.img && this.img.src === d.source) { + return; + } + + thisImage.attr('xmlns', xmlnsNamespaces.svg); + + var imagePromise = new Promise(function(resolve) { + + var img = new Image(); + this.img = img; + + // If not set, a `tainted canvas` error is thrown + img.setAttribute('crossOrigin', 'anonymous'); + img.onerror = errorHandler; + img.onload = function() { + var canvas = document.createElement('canvas'); + canvas.width = this.width; + canvas.height = this.height; + + var ctx = canvas.getContext('2d'); + ctx.drawImage(this, 0, 0); + + var dataURL = canvas.toDataURL('image/png'); + + thisImage.attr('xlink:href', dataURL); + }; + + + thisImage.on('error', errorHandler); + thisImage.on('load', resolve); + + img.src = d.source; + + function errorHandler() { + thisImage.remove(); + resolve(); + } + }.bind(this)); + + gd._promises.push(imagePromise); + } + + function applyAttributes(d) { + var thisImage = d3.select(this); + + // Axes if specified + var xa = Axes.getFromId(gd, d.xref), + ya = Axes.getFromId(gd, d.yref); + + var size = fullLayout._size, + width = xa ? Math.abs(xa.l2p(d.sizex) - xa.l2p(0)) : d.sizex * size.w, + height = ya ? Math.abs(ya.l2p(d.sizey) - ya.l2p(0)) : d.sizey * size.h; + + // Offsets for anchor positioning + var xOffset = width * anchors.x[d.xanchor].offset, + yOffset = height * anchors.y[d.yanchor].offset; + + var sizing = anchors.x[d.xanchor].sizing + anchors.y[d.yanchor].sizing; + + // Final positions + var xPos = (xa ? xa.r2p(d.x) + xa._offset : d.x * size.w + size.l) + xOffset, + yPos = (ya ? ya.r2p(d.y) + ya._offset : size.h - d.y * size.h + size.t) + yOffset; + + + // Construct the proper aspectRatio attribute + switch(d.sizing) { + case 'fill': + sizing += ' slice'; + break; + + case 'stretch': + sizing = 'none'; + break; + } + + thisImage.attr({ + x: xPos, + y: yPos, + width: width, + height: height, + preserveAspectRatio: sizing, + opacity: d.opacity + }); + + + // Set proper clipping on images + var xId = xa ? xa._id : '', + yId = ya ? ya._id : '', + clipAxes = xId + yId; + + if(clipAxes) { + thisImage.call(Drawing.setClipUrl, 'clip' + fullLayout._uid + clipAxes); + } + } + + var imagesBelow = fullLayout._imageLowerLayer.selectAll('image') + .data(imageDataBelow), + imagesSubplot = fullLayout._imageSubplotLayer.selectAll('image') + .data(imageDataSubplot), + imagesAbove = fullLayout._imageUpperLayer.selectAll('image') + .data(imageDataAbove); + + imagesBelow.enter().append('image'); + imagesSubplot.enter().append('image'); + imagesAbove.enter().append('image'); + + imagesBelow.exit().remove(); + imagesSubplot.exit().remove(); + imagesAbove.exit().remove(); + + imagesBelow.each(function(d) { + setImage.bind(this)(d); + applyAttributes.bind(this)(d); + }); + imagesSubplot.each(function(d) { + setImage.bind(this)(d); + applyAttributes.bind(this)(d); + }); + imagesAbove.each(function(d) { + setImage.bind(this)(d); + applyAttributes.bind(this)(d); + }); +}; + +},{"../../constants/xmlns_namespaces":109,"../../plots/cartesian/axes":150,"../drawing":50,"d3":10}],62:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'component', + name: 'images', + + layoutAttributes: require('./attributes'), + supplyLayoutDefaults: require('./defaults'), + + draw: require('./draw') +}; + +},{"./attributes":59,"./defaults":60,"./draw":61}],63:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +/** + * Determine the position anchor property of x/y xanchor/yanchor components. + * + * - values < 1/3 align the low side at that fraction, + * - values [1/3, 2/3] align the center at that fraction, + * - values > 2/3 align the right at that fraction. + */ + +exports.isRightAnchor = function isRightAnchor(opts) { + return ( + opts.xanchor === 'right' || + (opts.xanchor === 'auto' && opts.x >= 2 / 3) + ); +}; + +exports.isCenterAnchor = function isCenterAnchor(opts) { + return ( + opts.xanchor === 'center' || + (opts.xanchor === 'auto' && opts.x > 1 / 3 && opts.x < 2 / 3) + ); +}; + +exports.isBottomAnchor = function isBottomAnchor(opts) { + return ( + opts.yanchor === 'bottom' || + (opts.yanchor === 'auto' && opts.y <= 1 / 3) + ); +}; + +exports.isMiddleAnchor = function isMiddleAnchor(opts) { + return ( + opts.yanchor === 'middle' || + (opts.yanchor === 'auto' && opts.y > 1 / 3 && opts.y < 2 / 3) + ); +}; + +},{}],64:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = require('../../plots/font_attributes'); +var colorAttrs = require('../color/attributes'); +var extendFlat = require('../../lib/extend').extendFlat; + + +module.exports = { + bgcolor: { + valType: 'color', + + + }, + bordercolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 0, + + + }, + font: extendFlat({}, fontAttrs, { + + }), + orientation: { + valType: 'enumerated', + values: ['v', 'h'], + dflt: 'v', + + + }, + traceorder: { + valType: 'flaglist', + flags: ['reversed', 'grouped'], + extras: ['normal'], + + + }, + tracegroupgap: { + valType: 'number', + min: 0, + dflt: 10, + + + }, + x: { + valType: 'number', + min: -2, + max: 3, + dflt: 1.02, + + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'left', + + + }, + y: { + valType: 'number', + min: -2, + max: 3, + dflt: 1, + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'auto', + + + } +}; + +},{"../../lib/extend":117,"../../plots/font_attributes":170,"../color/attributes":26}],65:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + scrollBarWidth: 4, + scrollBarHeight: 20, + scrollBarColor: '#808BA4', + scrollBarMargin: 4 +}; + +},{}],66:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = require('../../registry'); +var Lib = require('../../lib'); + +var attributes = require('./attributes'); +var basePlotLayoutAttributes = require('../../plots/layout_attributes'); +var helpers = require('./helpers'); + + +module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { + var containerIn = layoutIn.legend || {}, + containerOut = layoutOut.legend = {}; + + var visibleTraces = 0, + defaultOrder = 'normal', + defaultX, + defaultY, + defaultXAnchor, + defaultYAnchor; + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(helpers.legendGetsTrace(trace)) { + visibleTraces++; + // always show the legend by default if there's a pie + if(Registry.traceIs(trace, 'pie')) visibleTraces++; + } + + if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') || + ['tonextx', 'tonexty'].indexOf(trace.fill) !== -1) { + defaultOrder = helpers.isGrouped({traceorder: defaultOrder}) ? + 'grouped+reversed' : 'reversed'; + } + + if(trace.legendgroup !== undefined && trace.legendgroup !== '') { + defaultOrder = helpers.isReversed({traceorder: defaultOrder}) ? + 'reversed+grouped' : 'grouped'; + } + } + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + var showLegend = Lib.coerce(layoutIn, layoutOut, + basePlotLayoutAttributes, 'showlegend', visibleTraces > 1); + + if(showLegend === false) return; + + coerce('bgcolor', layoutOut.paper_bgcolor); + coerce('bordercolor'); + coerce('borderwidth'); + Lib.coerceFont(coerce, 'font', layoutOut.font); + + coerce('orientation'); + if(containerOut.orientation === 'h') { + var xaxis = layoutIn.xaxis; + if(xaxis && xaxis.rangeslider && xaxis.rangeslider.visible) { + defaultX = 0; + defaultXAnchor = 'left'; + defaultY = 1.1; + defaultYAnchor = 'bottom'; + } + else { + defaultX = 0; + defaultXAnchor = 'left'; + defaultY = -0.1; + defaultYAnchor = 'top'; + } + } + + coerce('traceorder', defaultOrder); + if(helpers.isGrouped(layoutOut.legend)) coerce('tracegroupgap'); + + coerce('x', defaultX); + coerce('xanchor', defaultXAnchor); + coerce('y', defaultY); + coerce('yanchor', defaultYAnchor); + Lib.noneOrAll(containerIn, containerOut, ['x', 'y']); +}; + +},{"../../lib":122,"../../plots/layout_attributes":184,"../../registry":194,"./attributes":64,"./helpers":69}],67:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Plotly = require('../../plotly'); +var Lib = require('../../lib'); +var Plots = require('../../plots/plots'); +var Registry = require('../../registry'); +var dragElement = require('../dragelement'); +var Drawing = require('../drawing'); +var Color = require('../color'); +var svgTextUtils = require('../../lib/svg_text_utils'); + +var constants = require('./constants'); +var getLegendData = require('./get_legend_data'); +var style = require('./style'); +var helpers = require('./helpers'); +var anchorUtils = require('./anchor_utils'); + + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout; + var clipId = 'legend' + fullLayout._uid; + + if(!fullLayout._infolayer || !gd.calcdata) return; + + var opts = fullLayout.legend, + legendData = fullLayout.showlegend && getLegendData(gd.calcdata, opts), + hiddenSlices = fullLayout.hiddenlabels || []; + + if(!fullLayout.showlegend || !legendData.length) { + fullLayout._infolayer.selectAll('.legend').remove(); + fullLayout._topdefs.select('#' + clipId).remove(); + + Plots.autoMargin(gd, 'legend'); + return; + } + + var legend = fullLayout._infolayer.selectAll('g.legend') + .data([0]); + + legend.enter().append('g') + .attr({ + 'class': 'legend', + 'pointer-events': 'all' + }); + + var clipPath = fullLayout._topdefs.selectAll('#' + clipId) + .data([0]); + + clipPath.enter().append('clipPath') + .attr('id', clipId) + .append('rect'); + + var bg = legend.selectAll('rect.bg') + .data([0]); + + bg.enter().append('rect').attr({ + 'class': 'bg', + 'shape-rendering': 'crispEdges' + }); + + bg.call(Color.stroke, opts.bordercolor); + bg.call(Color.fill, opts.bgcolor); + bg.style('stroke-width', opts.borderwidth + 'px'); + + var scrollBox = legend.selectAll('g.scrollbox') + .data([0]); + + scrollBox.enter().append('g') + .attr('class', 'scrollbox'); + + var scrollBar = legend.selectAll('rect.scrollbar') + .data([0]); + + scrollBar.enter().append('rect') + .attr({ + 'class': 'scrollbar', + 'rx': 20, + 'ry': 2, + 'width': 0, + 'height': 0 + }) + .call(Color.fill, '#808BA4'); + + var groups = scrollBox.selectAll('g.groups') + .data(legendData); + + groups.enter().append('g') + .attr('class', 'groups'); + + groups.exit().remove(); + + var traces = groups.selectAll('g.traces') + .data(Lib.identity); + + traces.enter().append('g').attr('class', 'traces'); + traces.exit().remove(); + + traces.call(style) + .style('opacity', function(d) { + var trace = d[0].trace; + if(Registry.traceIs(trace, 'pie')) { + return hiddenSlices.indexOf(d[0].label) !== -1 ? 0.5 : 1; + } else { + return trace.visible === 'legendonly' ? 0.5 : 1; + } + }) + .each(function() { + d3.select(this) + .call(drawTexts, gd) + .call(setupTraceToggle, gd); + }); + + var firstRender = legend.enter().size() !== 0; + if(firstRender) { + computeLegendDimensions(gd, groups, traces); + expandMargin(gd); + } + + // Position and size the legend + var lxMin = 0, + lxMax = fullLayout.width, + lyMin = 0, + lyMax = fullLayout.height; + + computeLegendDimensions(gd, groups, traces); + + if(opts.height > lyMax) { + // If the legend doesn't fit in the plot area, + // do not expand the vertical margins. + expandHorizontalMargin(gd); + } else { + expandMargin(gd); + } + + // Scroll section must be executed after repositionLegend. + // It requires the legend width, height, x and y to position the scrollbox + // and these values are mutated in repositionLegend. + var gs = fullLayout._size, + lx = gs.l + gs.w * opts.x, + ly = gs.t + gs.h * (1 - opts.y); + + if(anchorUtils.isRightAnchor(opts)) { + lx -= opts.width; + } + else if(anchorUtils.isCenterAnchor(opts)) { + lx -= opts.width / 2; + } + + if(anchorUtils.isBottomAnchor(opts)) { + ly -= opts.height; + } + else if(anchorUtils.isMiddleAnchor(opts)) { + ly -= opts.height / 2; + } + + // Make sure the legend left and right sides are visible + var legendWidth = opts.width, + legendWidthMax = gs.w; + + // aburato: temp fix + // if(legendWidth > legendWidthMax) { + // lx = gs.l; + // legendWidth = legendWidthMax; + // } + // else { + if(lx + legendWidth > lxMax) lx = lxMax - legendWidth; + if(lx < lxMin) lx = lxMin; + legendWidth = Math.min(lxMax - lx, opts.width); + // } + + // Make sure the legend top and bottom are visible + // (legends with a scroll bar are not allowed to stretch beyond the extended + // margins) + var legendHeight = opts.height, + legendHeightMax = gs.h; + + if(legendHeight > legendHeightMax) { + ly = gs.t; + legendHeight = legendHeightMax; + } + else { + if(ly + legendHeight > lyMax) ly = lyMax - legendHeight; + if(ly < lyMin) ly = lyMin; + legendHeight = Math.min(lyMax - ly, opts.height); + } + + // Set size and position of all the elements that make up a legend: + // legend, background and border, scroll box and scroll bar + Lib.setTranslate(legend, lx, ly); + + var scrollBarYMax = legendHeight - + constants.scrollBarHeight - + 2 * constants.scrollBarMargin, + scrollBoxYMax = opts.height - legendHeight, + scrollBarY, + scrollBoxY; + + if(opts.height <= legendHeight || gd._context.staticPlot) { + // if scrollbar should not be shown. + bg.attr({ + width: legendWidth - opts.borderwidth, + height: legendHeight - opts.borderwidth, + x: opts.borderwidth / 2, + y: opts.borderwidth / 2 + }); + + Lib.setTranslate(scrollBox, 0, 0); + + clipPath.select('rect').attr({ + width: legendWidth - 2 * opts.borderwidth, + height: legendHeight - 2 * opts.borderwidth, + x: opts.borderwidth, + y: opts.borderwidth + }); + + scrollBox.call(Drawing.setClipUrl, clipId); + } + else { + scrollBarY = constants.scrollBarMargin, + scrollBoxY = scrollBox.attr('data-scroll') || 0; + + // increase the background and clip-path width + // by the scrollbar width and margin + bg.attr({ + width: legendWidth - + 2 * opts.borderwidth + + constants.scrollBarWidth + + constants.scrollBarMargin, + height: legendHeight - opts.borderwidth, + x: opts.borderwidth / 2, + y: opts.borderwidth / 2 + }); + + clipPath.select('rect').attr({ + width: legendWidth - + 2 * opts.borderwidth + + constants.scrollBarWidth + + constants.scrollBarMargin, + height: legendHeight - 2 * opts.borderwidth, + x: opts.borderwidth, + y: opts.borderwidth - scrollBoxY + }); + + scrollBox.call(Drawing.setClipUrl, clipId); + + if(firstRender) scrollHandler(scrollBarY, scrollBoxY); + + legend.on('wheel', null); // to be safe, remove previous listeners + legend.on('wheel', function() { + scrollBoxY = Lib.constrain( + scrollBox.attr('data-scroll') - + d3.event.deltaY / scrollBarYMax * scrollBoxYMax, + -scrollBoxYMax, 0); + scrollBarY = constants.scrollBarMargin - + scrollBoxY / scrollBoxYMax * scrollBarYMax; + scrollHandler(scrollBarY, scrollBoxY); + d3.event.preventDefault(); + }); + + // to be safe, remove previous listeners + scrollBar.on('.drag', null); + scrollBox.on('.drag', null); + + var drag = d3.behavior.drag().on('drag', function() { + scrollBarY = Lib.constrain( + d3.event.y - constants.scrollBarHeight / 2, + constants.scrollBarMargin, + constants.scrollBarMargin + scrollBarYMax); + scrollBoxY = - (scrollBarY - constants.scrollBarMargin) / + scrollBarYMax * scrollBoxYMax; + scrollHandler(scrollBarY, scrollBoxY); + }); + + scrollBar.call(drag); + scrollBox.call(drag); + } + + + function scrollHandler(scrollBarY, scrollBoxY) { + scrollBox + .attr('data-scroll', scrollBoxY) + .call(Lib.setTranslate, 0, scrollBoxY); + + scrollBar.call( + Drawing.setRect, + legendWidth, + scrollBarY, + constants.scrollBarWidth, + constants.scrollBarHeight + ); + clipPath.select('rect').attr({ + y: opts.borderwidth - scrollBoxY + }); + } + + if(gd._context.editable) { + var xf, yf, x0, y0; + + legend.classed('cursor-move', true); + + dragElement.init({ + element: legend.node(), + prepFn: function() { + var transform = Lib.getTranslate(legend); + + x0 = transform.x; + y0 = transform.y; + }, + moveFn: function(dx, dy) { + var newX = x0 + dx, + newY = y0 + dy; + + Lib.setTranslate(legend, newX, newY); + + xf = dragElement.align(newX, 0, gs.l, gs.l + gs.w, opts.xanchor); + yf = dragElement.align(newY, 0, gs.t + gs.h, gs.t, opts.yanchor); + }, + doneFn: function(dragged) { + if(dragged && xf !== undefined && yf !== undefined) { + Plotly.relayout(gd, {'legend.x': xf, 'legend.y': yf}); + } + } + }); + } +}; + +function drawTexts(g, gd) { + var legendItem = g.data()[0][0], + fullLayout = gd._fullLayout, + trace = legendItem.trace, + isPie = Registry.traceIs(trace, 'pie'), + traceIndex = trace.index, + name = isPie ? legendItem.label : trace.name; + + var text = g.selectAll('text.legendtext') + .data([0]); + text.enter().append('text').classed('legendtext', true); + text.attr({ + x: 40, + y: 0, + 'data-unformatted': name + }) + .style('text-anchor', 'start') + .classed('user-select-none', true) + .call(Drawing.font, fullLayout.legend.font) + .text(name); + + function textLayout(s) { + svgTextUtils.convertToTspans(s, function() { + s.selectAll('tspan.line').attr({x: s.attr('x')}); + g.call(computeTextDimensions, gd); + }); + } + + if(gd._context.editable && !isPie) { + text.call(svgTextUtils.makeEditable) + .call(textLayout) + .on('edit', function(text) { + this.attr({'data-unformatted': text}); + + this.text(text) + .call(textLayout); + + if(!this.text()) text = ' \u0020\u0020 '; + + var fullInput = legendItem.trace._fullInput || {}, + astr; + + // N.B. this block isn't super clean, + // is unfortunately untested at the moment, + // and only works for for 'ohlc' and 'candlestick', + // but should be generalized for other one-to-many transforms + if(['ohlc', 'candlestick'].indexOf(fullInput.type) !== -1) { + var transforms = legendItem.trace.transforms, + direction = transforms[transforms.length - 1].direction; + + astr = direction + '.legenditem.name'; + } + else astr = 'name'; + + Plotly.restyle(gd, astr, text, traceIndex); + }); + } + else text.call(textLayout); +} + +function setupTraceToggle(g, gd) { + var hiddenSlices = gd._fullLayout.hiddenlabels ? + gd._fullLayout.hiddenlabels.slice() : + []; + + var traceToggle = g.selectAll('rect') + .data([0]); + + traceToggle.enter().append('rect') + .classed('legendtoggle', true) + .style('cursor', 'pointer') + .attr('pointer-events', 'all') + .call(Color.fill, 'rgba(0,0,0,0)'); + + traceToggle.on('click', function() { + if(gd._dragged) return; + + var legendItem = g.data()[0][0], + fullData = gd._fullData, + trace = legendItem.trace, + legendgroup = trace.legendgroup, + traceIndicesInGroup = [], + tracei, + newVisible; + + if(Registry.traceIs(trace, 'pie')) { + var thisLabel = legendItem.label, + thisLabelIndex = hiddenSlices.indexOf(thisLabel); + + if(thisLabelIndex === -1) hiddenSlices.push(thisLabel); + else hiddenSlices.splice(thisLabelIndex, 1); + + Plotly.relayout(gd, 'hiddenlabels', hiddenSlices); + } else { + if(legendgroup === '') { + traceIndicesInGroup = [trace.index]; + } else { + for(var i = 0; i < fullData.length; i++) { + tracei = fullData[i]; + if(tracei.legendgroup === legendgroup) { + traceIndicesInGroup.push(tracei.index); + } + } + } + + newVisible = trace.visible === true ? 'legendonly' : true; + Plotly.restyle(gd, 'visible', newVisible, traceIndicesInGroup); + + gd.emit('plotly_legend_toggleVisible', {traceIndices: traceIndicesInGroup, visible: newVisible}); + } + }); +} + +function computeTextDimensions(g, gd) { + var legendItem = g.data()[0][0], + mathjaxGroup = g.select('g[class*=math-group]'), + opts = gd._fullLayout.legend, + lineHeight = opts.font.size * 1.3, + height, + width; + + if(!legendItem.trace.showlegend) { + g.remove(); + return; + } + + if(mathjaxGroup.node()) { + var mathjaxBB = Drawing.bBox(mathjaxGroup.node()); + + height = mathjaxBB.height; + width = mathjaxBB.width; + + Lib.setTranslate(mathjaxGroup, 0, (height / 4)); + } + else { + var text = g.selectAll('.legendtext'), + textSpans = g.selectAll('.legendtext>tspan'), + textLines = textSpans[0].length || 1; + + height = lineHeight * textLines; + width = text.node() && Drawing.bBox(text.node()).width; + + // approximation to height offset to center the font + // to avoid getBoundingClientRect + var textY = lineHeight * (0.3 + (1 - textLines) / 2); + text.attr('y', textY); + textSpans.attr('y', textY); + } + + height = Math.max(height, 16) + 3; + + legendItem.height = height; + legendItem.width = width; +} + +function computeLegendDimensions(gd, groups, traces) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend, + borderwidth = opts.borderwidth, + isGrouped = helpers.isGrouped(opts); + + if(helpers.isVertical(opts)) { + if(isGrouped) { + groups.each(function(d, i) { + Lib.setTranslate(this, 0, i * opts.tracegroupgap); + }); + } + + opts.width = 0; + opts.height = 0; + + traces.each(function(d) { + var legendItem = d[0], + textHeight = legendItem.height, + textWidth = legendItem.width; + + Lib.setTranslate(this, + borderwidth, + (5 + borderwidth + opts.height + textHeight / 2)); + + opts.height += textHeight; + opts.width = Math.max(opts.width, textWidth); + }); + + opts.width += 45 + borderwidth * 2; + opts.height += 10 + borderwidth * 2; + + if(isGrouped) { + opts.height += (opts._lgroupsLength - 1) * opts.tracegroupgap; + } + + // make sure we're only getting full pixels + opts.width = Math.ceil(opts.width); + opts.height = Math.ceil(opts.height); + + traces.each(function(d) { + var legendItem = d[0], + bg = d3.select(this).select('.legendtoggle'); + + bg.call(Drawing.setRect, + 0, + -legendItem.height / 2, + (gd._context.editable ? 0 : opts.width) + 40, + legendItem.height + ); + }); + } + else if(isGrouped) { + opts.width = 0; + opts.height = 0; + + var groupXOffsets = [opts.width], + groupData = groups.data(); + + for(var i = 0, n = groupData.length; i < n; i++) { + var textWidths = groupData[i].map(function(legendItemArray) { + return legendItemArray[0].width; + }); + + var groupWidth = 40 + Math.max.apply(null, textWidths); + + opts.width += opts.tracegroupgap + groupWidth; + + groupXOffsets.push(opts.width); + } + + groups.each(function(d, i) { + Lib.setTranslate(this, groupXOffsets[i], 0); + }); + + groups.each(function() { + var group = d3.select(this), + groupTraces = group.selectAll('g.traces'), + groupHeight = 0; + + groupTraces.each(function(d) { + var legendItem = d[0], + textHeight = legendItem.height; + + Lib.setTranslate(this, + 0, + (5 + borderwidth + groupHeight + textHeight / 2)); + + groupHeight += textHeight; + }); + + opts.height = Math.max(opts.height, groupHeight); + }); + + opts.height += 10 + borderwidth * 2; + opts.width += borderwidth * 2; + + // make sure we're only getting full pixels + opts.width = Math.ceil(opts.width); + opts.height = Math.ceil(opts.height); + + traces.each(function(d) { + var legendItem = d[0], + bg = d3.select(this).select('.legendtoggle'); + + bg.call(Drawing.setRect, + 0, + -legendItem.height / 2, + (gd._context.editable ? 0 : opts.width), + legendItem.height + ); + }); + } + else { + opts.width = 0; + opts.height = 0; + var rowHeight = 0, + maxTraceHeight = 0, + maxTraceWidth = 0, + offsetX = 0; + + // calculate largest width for traces and use for width of all legend items + traces.each(function(d) { + maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth); + }); + + traces.each(function(d) { + var legendItem = d[0], + traceWidth = maxTraceWidth, + traceGap = opts.tracegroupgap || 5; + + if((borderwidth + offsetX + traceGap + traceWidth) > (fullLayout.width - (fullLayout.margin.r + fullLayout.margin.l))) { + offsetX = 0; + rowHeight = rowHeight + maxTraceHeight; + opts.height = opts.height + maxTraceHeight; + // reset for next row + maxTraceHeight = 0; + } + + Lib.setTranslate(this, + (borderwidth + offsetX), + (5 + borderwidth + legendItem.height / 2) + rowHeight); + + opts.width += traceGap + traceWidth; + opts.height = Math.max(opts.height, legendItem.height); + + // keep track of tallest trace in group + offsetX += traceGap + traceWidth; + maxTraceHeight = Math.max(legendItem.height, maxTraceHeight); + }); + + opts.width += borderwidth * 2; + opts.height += 10 + borderwidth * 2; + + // make sure we're only getting full pixels + opts.width = Math.ceil(opts.width); + opts.height = Math.ceil(opts.height); + + traces.each(function(d) { + var legendItem = d[0], + bg = d3.select(this).select('.legendtoggle'); + + bg.call(Drawing.setRect, + 0, + -legendItem.height / 2, + (gd._context.editable ? 0 : opts.width), + legendItem.height + ); + }); + } +} + +function expandMargin(gd) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + xanchor = 'right'; + } + else if(anchorUtils.isCenterAnchor(opts)) { + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(opts)) { + yanchor = 'bottom'; + } + else if(anchorUtils.isMiddleAnchor(opts)) { + yanchor = 'middle'; + } + + // lastly check if the margin auto-expand has changed + Plots.autoMargin(gd, 'legend', { + x: opts.x, + y: opts.y, + l: opts.width * ({right: 1, center: 0.5}[xanchor] || 0), + r: opts.width * ({left: 1, center: 0.5}[xanchor] || 0), + b: opts.height * ({top: 1, middle: 0.5}[yanchor] || 0), + t: opts.height * ({bottom: 1, middle: 0.5}[yanchor] || 0) + }); +} + +function expandHorizontalMargin(gd) { + var fullLayout = gd._fullLayout, + opts = fullLayout.legend; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + xanchor = 'right'; + } + else if(anchorUtils.isCenterAnchor(opts)) { + xanchor = 'center'; + } + + // lastly check if the margin auto-expand has changed + Plots.autoMargin(gd, 'legend', { + x: opts.x, + y: 0.5, + l: opts.width * ({right: 1, center: 0.5}[xanchor] || 0), + r: opts.width * ({left: 1, center: 0.5}[xanchor] || 0), + b: 0, + t: 0 + }); +} + +},{"../../lib":122,"../../lib/svg_text_utils":134,"../../plotly":145,"../../plots/plots":186,"../../registry":194,"../color":27,"../dragelement":48,"../drawing":50,"./anchor_utils":63,"./constants":65,"./get_legend_data":68,"./helpers":69,"./style":71,"d3":10}],68:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = require('../../registry'); +var helpers = require('./helpers'); + + +module.exports = function getLegendData(calcdata, opts) { + var lgroupToTraces = {}, + lgroups = [], + hasOneNonBlankGroup = false, + slicesShown = {}, + lgroupi = 0; + + var i, j; + + function addOneItem(legendGroup, legendItem) { + // each '' legend group is treated as a separate group + if(legendGroup === '' || !helpers.isGrouped(opts)) { + var uniqueGroup = '~~i' + lgroupi; // TODO: check this against fullData legendgroups? + + lgroups.push(uniqueGroup); + lgroupToTraces[uniqueGroup] = [[legendItem]]; + lgroupi++; + } + else if(lgroups.indexOf(legendGroup) === -1) { + lgroups.push(legendGroup); + hasOneNonBlankGroup = true; + lgroupToTraces[legendGroup] = [[legendItem]]; + } + else lgroupToTraces[legendGroup].push([legendItem]); + } + + // build an { legendgroup: [cd0, cd0], ... } object + for(i = 0; i < calcdata.length; i++) { + var cd = calcdata[i], + cd0 = cd[0], + trace = cd0.trace, + lgroup = trace.legendgroup; + + if(!helpers.legendGetsTrace(trace) || !trace.showlegend) continue; + + if(Registry.traceIs(trace, 'pie')) { + if(!slicesShown[lgroup]) slicesShown[lgroup] = {}; + + for(j = 0; j < cd.length; j++) { + var labelj = cd[j].label; + + if(!slicesShown[lgroup][labelj]) { + addOneItem(lgroup, { + label: labelj, + color: cd[j].color, + i: cd[j].i, + trace: trace + }); + + slicesShown[lgroup][labelj] = true; + } + } + } + + else addOneItem(lgroup, cd0); + } + + // won't draw a legend in this case + if(!lgroups.length) return []; + + // rearrange lgroupToTraces into a d3-friendly array of arrays + var lgroupsLength = lgroups.length, + ltraces, + legendData; + + if(hasOneNonBlankGroup && helpers.isGrouped(opts)) { + legendData = new Array(lgroupsLength); + + for(i = 0; i < lgroupsLength; i++) { + ltraces = lgroupToTraces[lgroups[i]]; + legendData[i] = helpers.isReversed(opts) ? ltraces.reverse() : ltraces; + } + } + else { + // collapse all groups into one if all groups are blank + legendData = [new Array(lgroupsLength)]; + + for(i = 0; i < lgroupsLength; i++) { + ltraces = lgroupToTraces[lgroups[i]][0]; + legendData[0][helpers.isReversed(opts) ? lgroupsLength - i - 1 : i] = ltraces; + } + lgroupsLength = 1; + } + + // needed in repositionLegend + opts._lgroupsLength = lgroupsLength; + return legendData; +}; + +},{"../../registry":194,"./helpers":69}],69:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = require('../../registry'); + + +exports.legendGetsTrace = function legendGetsTrace(trace) { + return trace.visible && Registry.traceIs(trace, 'showLegend'); +}; + +exports.isGrouped = function isGrouped(legendLayout) { + return (legendLayout.traceorder || '').indexOf('grouped') !== -1; +}; + +exports.isVertical = function isVertical(legendLayout) { + return legendLayout.orientation !== 'h'; +}; + +exports.isReversed = function isReversed(legendLayout) { + return (legendLayout.traceorder || '').indexOf('reversed') !== -1; +}; + +},{"../../registry":194}],70:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + moduleType: 'component', + name: 'legend', + + layoutAttributes: require('./attributes'), + supplyLayoutDefaults: require('./defaults'), + + draw: require('./draw'), + style: require('./style') +}; + +},{"./attributes":64,"./defaults":66,"./draw":67,"./style":71}],71:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Registry = require('../../registry'); +var Lib = require('../../lib'); +var Drawing = require('../drawing'); +var Color = require('../color'); + +var subTypes = require('../../traces/scatter/subtypes'); +var stylePie = require('../../traces/pie/style_one'); + + +module.exports = function style(s) { + s.each(function(d) { + var traceGroup = d3.select(this); + + var fill = traceGroup + .selectAll('g.legendfill') + .data([d]); + fill.enter().append('g') + .classed('legendfill', true); + + var line = traceGroup + .selectAll('g.legendlines') + .data([d]); + line.enter().append('g') + .classed('legendlines', true); + + var symbol = traceGroup + .selectAll('g.legendsymbols') + .data([d]); + symbol.enter().append('g') + .classed('legendsymbols', true); + symbol.style('opacity', d[0].trace.opacity); + + symbol.selectAll('g.legendpoints') + .data([d]) + .enter().append('g') + .classed('legendpoints', true); + }) + .each(styleBars) + .each(styleBoxes) + .each(stylePies) + .each(styleLines) + .each(stylePoints); +}; + +function styleLines(d) { + var trace = d[0].trace, + showFill = trace.visible && trace.fill && trace.fill !== 'none', + showLine = subTypes.hasLines(trace); + + var fill = d3.select(this).select('.legendfill').selectAll('path') + .data(showFill ? [d] : []); + fill.enter().append('path').classed('js-fill', true); + fill.exit().remove(); + fill.attr('d', 'M5,0h30v6h-30z') + .call(Drawing.fillGroupStyle); + + var line = d3.select(this).select('.legendlines').selectAll('path') + .data(showLine ? [d] : []); + line.enter().append('path').classed('js-line', true) + .attr('d', 'M5,0h30'); + line.exit().remove(); + line.call(Drawing.lineGroupStyle); +} + +function stylePoints(d) { + var d0 = d[0], + trace = d0.trace, + showMarkers = subTypes.hasMarkers(trace), + showText = subTypes.hasText(trace), + showLines = subTypes.hasLines(trace); + + var dMod, tMod; + + // 'scatter3d' and 'scattergeo' don't use gd.calcdata yet; + // use d0.trace to infer arrayOk attributes + + function boundVal(attrIn, arrayToValFn, bounds) { + var valIn = Lib.nestedProperty(trace, attrIn).get(), + valToBound = (Array.isArray(valIn) && arrayToValFn) ? + arrayToValFn(valIn) : valIn; + + if(bounds) { + if(valToBound < bounds[0]) return bounds[0]; + else if(valToBound > bounds[1]) return bounds[1]; + } + return valToBound; + } + + function pickFirst(array) { return array[0]; } + + // constrain text, markers, etc so they'll fit on the legend + if(showMarkers || showText || showLines) { + var dEdit = {}, + tEdit = {}; + + if(showMarkers) { + dEdit.mc = boundVal('marker.color', pickFirst); + dEdit.mo = boundVal('marker.opacity', Lib.mean, [0.2, 1]); + dEdit.ms = boundVal('marker.size', Lib.mean, [2, 16]); + dEdit.mlc = boundVal('marker.line.color', pickFirst); + dEdit.mlw = boundVal('marker.line.width', Lib.mean, [0, 5]); + tEdit.marker = { + sizeref: 1, + sizemin: 1, + sizemode: 'diameter' + }; + } + + if(showLines) { + tEdit.line = { + width: boundVal('line.width', pickFirst, [0, 10]) + }; + } + + if(showText) { + dEdit.tx = 'Aa'; + dEdit.tp = boundVal('textposition', pickFirst); + dEdit.ts = 10; + dEdit.tc = boundVal('textfont.color', pickFirst); + dEdit.tf = boundVal('textfont.family', pickFirst); + } + + dMod = [Lib.minExtend(d0, dEdit)]; + tMod = Lib.minExtend(trace, tEdit); + } + + var ptgroup = d3.select(this).select('g.legendpoints'); + + var pts = ptgroup.selectAll('path.scatterpts') + .data(showMarkers ? dMod : []); + pts.enter().append('path').classed('scatterpts', true) + .attr('transform', 'translate(20,0)'); + pts.exit().remove(); + pts.call(Drawing.pointStyle, tMod); + + // 'mrc' is set in pointStyle and used in textPointStyle: + // constrain it here + if(showMarkers) dMod[0].mrc = 3; + + var txt = ptgroup.selectAll('g.pointtext') + .data(showText ? dMod : []); + txt.enter() + .append('g').classed('pointtext', true) + .append('text').attr('transform', 'translate(20,0)'); + txt.exit().remove(); + txt.selectAll('text').call(Drawing.textPointStyle, tMod); +} + +function styleBars(d) { + var trace = d[0].trace, + marker = trace.marker || {}, + markerLine = marker.line || {}, + barpath = d3.select(this).select('g.legendpoints') + .selectAll('path.legendbar') + .data(Registry.traceIs(trace, 'bar') ? [d] : []); + barpath.enter().append('path').classed('legendbar', true) + .attr('d', 'M6,6H-6V-6H6Z') + .attr('transform', 'translate(20,0)'); + barpath.exit().remove(); + barpath.each(function(d) { + var w = (d.mlw + 1 || markerLine.width + 1) - 1, + p = d3.select(this); + + p.style('stroke-width', w + 'px') + .call(Color.fill, d.mc || marker.color); + + if(w) { + p.call(Color.stroke, d.mlc || markerLine.color); + } + }); +} + +function styleBoxes(d) { + var trace = d[0].trace, + pts = d3.select(this).select('g.legendpoints') + .selectAll('path.legendbox') + .data(Registry.traceIs(trace, 'box') && trace.visible ? [d] : []); + pts.enter().append('path').classed('legendbox', true) + // if we want the median bar, prepend M6,0H-6 + .attr('d', 'M6,6H-6V-6H6Z') + .attr('transform', 'translate(20,0)'); + pts.exit().remove(); + pts.each(function(d) { + var w = (d.lw + 1 || trace.line.width + 1) - 1, + p = d3.select(this); + + p.style('stroke-width', w + 'px') + .call(Color.fill, d.fc || trace.fillcolor); + + if(w) { + p.call(Color.stroke, d.lc || trace.line.color); + } + }); +} + +function stylePies(d) { + var trace = d[0].trace, + pts = d3.select(this).select('g.legendpoints') + .selectAll('path.legendpie') + .data(Registry.traceIs(trace, 'pie') && trace.visible ? [d] : []); + pts.enter().append('path').classed('legendpie', true) + .attr('d', 'M6,6H-6V-6H6Z') + .attr('transform', 'translate(20,0)'); + pts.exit().remove(); + + if(pts.size()) pts.call(stylePie, d[0], trace); +} + +},{"../../lib":122,"../../registry":194,"../../traces/pie/style_one":232,"../../traces/scatter/subtypes":254,"../color":27,"../drawing":50,"d3":10}],72:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Plotly = require('../../plotly'); +var Plots = require('../../plots/plots'); +var Axes = require('../../plots/cartesian/axes'); +var Lib = require('../../lib'); +var downloadImage = require('../../snapshot/download'); +var Icons = require('../../../build/ploticon'); + + +var modeBarButtons = module.exports = {}; + +/** + * ModeBar buttons configuration + * + * @param {string} name + * name / id of the buttons (for tracking) + * @param {string} title + * text that appears while hovering over the button, + * enter null, false or '' for no hover text + * @param {string} icon + * svg icon object associated with the button + * can be linked to Plotly.Icons to use the default plotly icons + * @param {string} [gravity] + * icon positioning + * @param {function} click + * click handler associated with the button, a function of + * 'gd' (the main graph object) and + * 'ev' (the event object) + * @param {string} [attr] + * attribute associated with button, + * use this with 'val' to keep track of the state + * @param {*} [val] + * initial 'attr' value, can be a function of gd + * @param {boolean} [toggle] + * is the button a toggle button? + */ + +modeBarButtons.toImage = { + name: 'toImage', + title: 'Download plot as a png', + icon: Icons.camera, + click: function(gd) { + var format = 'png'; + + Lib.notifier('Taking snapshot - this may take a few seconds', 'long'); + + if(Lib.isIE()) { + Lib.notifier('IE only supports svg. Changing format to svg.', 'long'); + format = 'svg'; + } + + downloadImage(gd, {'format': format}) + .then(function(filename) { + Lib.notifier('Snapshot succeeded - ' + filename, 'long'); + }) + .catch(function() { + Lib.notifier('Sorry there was a problem downloading your snapshot!', 'long'); + }); + } +}; + +modeBarButtons.sendDataToCloud = { + name: 'sendDataToCloud', + title: 'Save and edit plot in cloud', + icon: Icons.disk, + click: function(gd) { + Plots.sendDataToCloud(gd); + } +}; + +modeBarButtons.zoom2d = { + name: 'zoom2d', + title: 'Zoom', + attr: 'dragmode', + val: 'zoom', + icon: Icons.zoombox, + click: handleCartesian +}; + +modeBarButtons.pan2d = { + name: 'pan2d', + title: 'Pan', + attr: 'dragmode', + val: 'pan', + icon: Icons.pan, + click: handleCartesian +}; + +modeBarButtons.select2d = { + name: 'select2d', + title: 'Box Select', + attr: 'dragmode', + val: 'select', + icon: Icons.selectbox, + click: handleCartesian +}; + +modeBarButtons.lasso2d = { + name: 'lasso2d', + title: 'Lasso Select', + attr: 'dragmode', + val: 'lasso', + icon: Icons.lasso, + click: handleCartesian +}; + +modeBarButtons.zoomIn2d = { + name: 'zoomIn2d', + title: 'Zoom in', + attr: 'zoom', + val: 'in', + icon: Icons.zoom_plus, + click: handleCartesian +}; + +modeBarButtons.zoomOut2d = { + name: 'zoomOut2d', + title: 'Zoom out', + attr: 'zoom', + val: 'out', + icon: Icons.zoom_minus, + click: handleCartesian +}; + +modeBarButtons.autoScale2d = { + name: 'autoScale2d', + title: 'Autoscale', + attr: 'zoom', + val: 'auto', + icon: Icons.autoscale, + click: handleCartesian +}; + +modeBarButtons.resetScale2d = { + name: 'resetScale2d', + title: 'Reset axes', + attr: 'zoom', + val: 'reset', + icon: Icons.home, + click: handleCartesian +}; + +modeBarButtons.hoverClosestCartesian = { + name: 'hoverClosestCartesian', + title: 'Show closest data on hover', + attr: 'hovermode', + val: 'closest', + icon: Icons.tooltip_basic, + gravity: 'ne', + click: handleCartesian +}; + +modeBarButtons.hoverCompareCartesian = { + name: 'hoverCompareCartesian', + title: 'Compare data on hover', + attr: 'hovermode', + val: function(gd) { + return gd._fullLayout._isHoriz ? 'y' : 'x'; + }, + icon: Icons.tooltip_compare, + gravity: 'ne', + click: handleCartesian +}; + +function handleCartesian(gd, ev) { + var button = ev.currentTarget, + astr = button.getAttribute('data-attr'), + val = button.getAttribute('data-val') || true, + fullLayout = gd._fullLayout, + aobj = {}; + + if(astr === 'zoom') { + var mag = (val === 'in') ? 0.5 : 2, + r0 = (1 + mag) / 2, + r1 = (1 - mag) / 2, + axList = Axes.list(gd, null, true); + + var ax, axName; + + for(var i = 0; i < axList.length; i++) { + ax = axList[i]; + + if(!ax.fixedrange) { + axName = ax._name; + if(val === 'auto') aobj[axName + '.autorange'] = true; + else if(val === 'reset') { + if(ax._rangeInitial === undefined) { + aobj[axName + '.autorange'] = true; + } + else { + var rangeInitial = ax._rangeInitial.slice(); + aobj[axName + '.range[0]'] = rangeInitial[0]; + aobj[axName + '.range[1]'] = rangeInitial[1]; + } + } + else { + var rangeNow = [ + ax.r2l(ax.range[0]), + ax.r2l(ax.range[1]), + ]; + + var rangeNew = [ + r0 * rangeNow[0] + r1 * rangeNow[1], + r0 * rangeNow[1] + r1 * rangeNow[0] + ]; + + aobj[axName + '.range[0]'] = ax.l2r(rangeNew[0]); + aobj[axName + '.range[1]'] = ax.l2r(rangeNew[1]); + } + } + } + } + else { + // if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y' + if(astr === 'hovermode' && (val === 'x' || val === 'y')) { + val = fullLayout._isHoriz ? 'y' : 'x'; + button.setAttribute('data-val', val); + } + + aobj[astr] = val; + } + + Plotly.relayout(gd, aobj); +} + +modeBarButtons.zoom3d = { + name: 'zoom3d', + title: 'Zoom', + attr: 'scene.dragmode', + val: 'zoom', + icon: Icons.zoombox, + click: handleDrag3d +}; + +modeBarButtons.pan3d = { + name: 'pan3d', + title: 'Pan', + attr: 'scene.dragmode', + val: 'pan', + icon: Icons.pan, + click: handleDrag3d +}; + +modeBarButtons.orbitRotation = { + name: 'orbitRotation', + title: 'orbital rotation', + attr: 'scene.dragmode', + val: 'orbit', + icon: Icons['3d_rotate'], + click: handleDrag3d +}; + +modeBarButtons.tableRotation = { + name: 'tableRotation', + title: 'turntable rotation', + attr: 'scene.dragmode', + val: 'turntable', + icon: Icons['z-axis'], + click: handleDrag3d +}; + +function handleDrag3d(gd, ev) { + var button = ev.currentTarget, + attr = button.getAttribute('data-attr'), + val = button.getAttribute('data-val') || true, + fullLayout = gd._fullLayout, + sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'), + layoutUpdate = {}; + + var parts = attr.split('.'); + + for(var i = 0; i < sceneIds.length; i++) { + layoutUpdate[sceneIds[i] + '.' + parts[1]] = val; + } + + Plotly.relayout(gd, layoutUpdate); +} + +modeBarButtons.resetCameraDefault3d = { + name: 'resetCameraDefault3d', + title: 'Reset camera to default', + attr: 'resetDefault', + icon: Icons.home, + click: handleCamera3d +}; + +modeBarButtons.resetCameraLastSave3d = { + name: 'resetCameraLastSave3d', + title: 'Reset camera to last save', + attr: 'resetLastSave', + icon: Icons.movie, + click: handleCamera3d +}; + +function handleCamera3d(gd, ev) { + var button = ev.currentTarget, + attr = button.getAttribute('data-attr'), + fullLayout = gd._fullLayout, + sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'); + + for(var i = 0; i < sceneIds.length; i++) { + var sceneId = sceneIds[i], + fullSceneLayout = fullLayout[sceneId], + scene = fullSceneLayout._scene; + + if(attr === 'resetDefault') scene.setCameraToDefault(); + else if(attr === 'resetLastSave') { + // This handler looks in the un-updated fullLayout.scene.camera object to reset the camera + // to the last saved position. + scene.setCamera(fullSceneLayout.camera); + } + } +} + +modeBarButtons.hoverClosest3d = { + name: 'hoverClosest3d', + title: 'Toggle show closest data on hover', + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: handleHover3d +}; + +function handleHover3d(gd, ev) { + var button = ev.currentTarget, + val = button._previousVal || false, + layout = gd.layout, + fullLayout = gd._fullLayout, + sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'); + + var axes = ['xaxis', 'yaxis', 'zaxis'], + spikeAttrs = ['showspikes', 'spikesides', 'spikethickness', 'spikecolor']; + + // initialize 'current spike' object to be stored in the DOM + var currentSpikes = {}, + axisSpikes = {}, + layoutUpdate = {}; + + if(val) { + layoutUpdate = Lib.extendDeep(layout, val); + button._previousVal = null; + } + else { + layoutUpdate = { + 'allaxes.showspikes': false + }; + + for(var i = 0; i < sceneIds.length; i++) { + var sceneId = sceneIds[i], + sceneLayout = fullLayout[sceneId], + sceneSpikes = currentSpikes[sceneId] = {}; + + sceneSpikes.hovermode = sceneLayout.hovermode; + layoutUpdate[sceneId + '.hovermode'] = false; + + // copy all the current spike attrs + for(var j = 0; j < 3; j++) { + var axis = axes[j]; + axisSpikes = sceneSpikes[axis] = {}; + + for(var k = 0; k < spikeAttrs.length; k++) { + var spikeAttr = spikeAttrs[k]; + axisSpikes[spikeAttr] = sceneLayout[axis][spikeAttr]; + } + } + } + + button._previousVal = Lib.extendDeep({}, currentSpikes); + } + + Plotly.relayout(gd, layoutUpdate); +} + +modeBarButtons.zoomInGeo = { + name: 'zoomInGeo', + title: 'Zoom in', + attr: 'zoom', + val: 'in', + icon: Icons.zoom_plus, + click: handleGeo +}; + +modeBarButtons.zoomOutGeo = { + name: 'zoomOutGeo', + title: 'Zoom out', + attr: 'zoom', + val: 'out', + icon: Icons.zoom_minus, + click: handleGeo +}; + +modeBarButtons.resetGeo = { + name: 'resetGeo', + title: 'Reset', + attr: 'reset', + val: null, + icon: Icons.autoscale, + click: handleGeo +}; + +modeBarButtons.hoverClosestGeo = { + name: 'hoverClosestGeo', + title: 'Toggle show closest data on hover', + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: toggleHover +}; + +function handleGeo(gd, ev) { + var button = ev.currentTarget, + attr = button.getAttribute('data-attr'), + val = button.getAttribute('data-val') || true, + fullLayout = gd._fullLayout, + geoIds = Plots.getSubplotIds(fullLayout, 'geo'); + + for(var i = 0; i < geoIds.length; i++) { + var geo = fullLayout[geoIds[i]]._subplot; + + if(attr === 'zoom') { + var scale = geo.projection.scale(); + var newScale = (val === 'in') ? 2 * scale : 0.5 * scale; + geo.projection.scale(newScale); + geo.zoom.scale(newScale); + geo.render(); + } + else if(attr === 'reset') geo.zoomReset(); + } +} + +modeBarButtons.hoverClosestGl2d = { + name: 'hoverClosestGl2d', + title: 'Toggle show closest data on hover', + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: toggleHover +}; + +modeBarButtons.hoverClosestPie = { + name: 'hoverClosestPie', + title: 'Toggle show closest data on hover', + attr: 'hovermode', + val: 'closest', + icon: Icons.tooltip_basic, + gravity: 'ne', + click: toggleHover +}; + +function toggleHover(gd) { + var fullLayout = gd._fullLayout; + + var onHoverVal; + if(fullLayout._has('cartesian')) { + onHoverVal = fullLayout._isHoriz ? 'y' : 'x'; + } + else onHoverVal = 'closest'; + + var newHover = gd._fullLayout.hovermode ? false : onHoverVal; + + Plotly.relayout(gd, 'hovermode', newHover); +} + +// buttons when more then one plot types are present + +modeBarButtons.toggleHover = { + name: 'toggleHover', + title: 'Toggle show closest data on hover', + attr: 'hovermode', + val: null, + toggle: true, + icon: Icons.tooltip_basic, + gravity: 'ne', + click: function(gd, ev) { + toggleHover(gd); + + // the 3d hovermode update must come + // last so that layout.hovermode update does not + // override scene?.hovermode?.layout. + handleHover3d(gd, ev); + } +}; + +modeBarButtons.resetViews = { + name: 'resetViews', + title: 'Reset views', + icon: Icons.home, + click: function(gd, ev) { + var button = ev.currentTarget; + + button.setAttribute('data-attr', 'zoom'); + button.setAttribute('data-val', 'reset'); + handleCartesian(gd, ev); + + button.setAttribute('data-attr', 'resetLastSave'); + handleCamera3d(gd, ev); + + // N.B handleCamera3d also triggers a replot for + // geo subplots. + } +}; + +},{"../../../build/ploticon":2,"../../lib":122,"../../plotly":145,"../../plots/cartesian/axes":150,"../../plots/plots":186,"../../snapshot/download":196}],73:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.manage = require('./manage'); + +},{"./manage":74}],74:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Axes = require('../../plots/cartesian/axes'); +var scatterSubTypes = require('../../traces/scatter/subtypes'); + +var createModeBar = require('./modebar'); +var modeBarButtons = require('./buttons'); + +/** + * ModeBar wrapper around 'create' and 'update', + * chooses buttons to pass to ModeBar constructor based on + * plot type and plot config. + * + * @param {object} gd main plot object + * + */ +module.exports = function manageModeBar(gd) { + var fullLayout = gd._fullLayout, + context = gd._context, + modeBar = fullLayout._modeBar; + + if(!context.displayModeBar) { + if(modeBar) { + modeBar.destroy(); + delete fullLayout._modeBar; + } + return; + } + + if(!Array.isArray(context.modeBarButtonsToRemove)) { + throw new Error([ + '*modeBarButtonsToRemove* configuration options', + 'must be an array.' + ].join(' ')); + } + + if(!Array.isArray(context.modeBarButtonsToAdd)) { + throw new Error([ + '*modeBarButtonsToAdd* configuration options', + 'must be an array.' + ].join(' ')); + } + + var customButtons = context.modeBarButtons; + var buttonGroups; + + if(Array.isArray(customButtons) && customButtons.length) { + buttonGroups = fillCustomButton(customButtons); + } + else { + buttonGroups = getButtonGroups( + gd, + context.modeBarButtonsToRemove, + context.modeBarButtonsToAdd + ); + } + + if(modeBar) modeBar.update(gd, buttonGroups); + else fullLayout._modeBar = createModeBar(gd, buttonGroups); +}; + +// logic behind which buttons are displayed by default +function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) { + var fullLayout = gd._fullLayout, + fullData = gd._fullData; + + var hasCartesian = fullLayout._has('cartesian'), + hasGL3D = fullLayout._has('gl3d'), + hasGeo = fullLayout._has('geo'), + hasPie = fullLayout._has('pie'), + hasGL2D = fullLayout._has('gl2d'), + hasTernary = fullLayout._has('ternary'); + + var groups = []; + + function addGroup(newGroup) { + var out = []; + + for(var i = 0; i < newGroup.length; i++) { + var button = newGroup[i]; + if(buttonsToRemove.indexOf(button) !== -1) continue; + out.push(modeBarButtons[button]); + } + + groups.push(out); + } + + // buttons common to all plot types + addGroup(['toImage', 'sendDataToCloud']); + + // graphs with more than one plot types get 'union buttons' + // which reset the view or toggle hover labels across all subplots. + if((hasCartesian || hasGL2D || hasPie || hasTernary) + hasGeo + hasGL3D > 1) { + addGroup(['resetViews', 'toggleHover']); + return appendButtonsToGroups(groups, buttonsToAdd); + } + + if(hasGL3D) { + addGroup(['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation']); + addGroup(['resetCameraDefault3d', 'resetCameraLastSave3d']); + addGroup(['hoverClosest3d']); + } + + if(hasGeo) { + addGroup(['zoomInGeo', 'zoomOutGeo', 'resetGeo']); + addGroup(['hoverClosestGeo']); + } + + var allAxesFixed = areAllAxesFixed(fullLayout), + dragModeGroup = []; + + if(((hasCartesian || hasGL2D) && !allAxesFixed) || hasTernary) { + dragModeGroup = ['zoom2d', 'pan2d']; + } + if((hasCartesian || hasTernary) && isSelectable(fullData)) { + dragModeGroup.push('select2d'); + dragModeGroup.push('lasso2d'); + } + if(dragModeGroup.length) addGroup(dragModeGroup); + + if((hasCartesian || hasGL2D) && !allAxesFixed && !hasTernary) { + addGroup(['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d']); + } + + if(hasCartesian && hasPie) { + addGroup(['toggleHover']); + } + else if(hasGL2D) { + addGroup(['hoverClosestGl2d']); + } + else if(hasCartesian) { + addGroup(['hoverClosestCartesian', 'hoverCompareCartesian']); + } + else if(hasPie) { + addGroup(['hoverClosestPie']); + } + + return appendButtonsToGroups(groups, buttonsToAdd); +} + +function areAllAxesFixed(fullLayout) { + var axList = Axes.list({_fullLayout: fullLayout}, null, true); + var allFixed = true; + + for(var i = 0; i < axList.length; i++) { + if(!axList[i].fixedrange) { + allFixed = false; + break; + } + } + + return allFixed; +} + +// look for traces that support selection +// to be updated as we add more selectPoints handlers +function isSelectable(fullData) { + var selectable = false; + + for(var i = 0; i < fullData.length; i++) { + if(selectable) break; + + var trace = fullData[i]; + + if(!trace._module || !trace._module.selectPoints) continue; + + if(trace.type === 'scatter' || trace.type === 'scatterternary') { + if(scatterSubTypes.hasMarkers(trace) || scatterSubTypes.hasText(trace)) { + selectable = true; + } + } + // assume that in general if the trace module has selectPoints, + // then it's selectable. Scatter is an exception to this because it must + // have markers or text, not just be a scatter type. + else selectable = true; + } + + return selectable; +} + +function appendButtonsToGroups(groups, buttons) { + if(buttons.length) { + if(Array.isArray(buttons[0])) { + for(var i = 0; i < buttons.length; i++) { + groups.push(buttons[i]); + } + } + else groups.push(buttons); + } + + return groups; +} + +// fill in custom buttons referring to default mode bar buttons +function fillCustomButton(customButtons) { + for(var i = 0; i < customButtons.length; i++) { + var buttonGroup = customButtons[i]; + + for(var j = 0; j < buttonGroup.length; j++) { + var button = buttonGroup[j]; + + if(typeof button === 'string') { + if(modeBarButtons[button] !== undefined) { + customButtons[i][j] = modeBarButtons[button]; + } + else { + throw new Error([ + '*modeBarButtons* configuration options', + 'invalid button name' + ].join(' ')); + } + } + } + } + + return customButtons; +} + +},{"../../plots/cartesian/axes":150,"../../traces/scatter/subtypes":254,"./buttons":72,"./modebar":75}],75:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Lib = require('../../lib'); +var Icons = require('../../../build/ploticon'); + + +/** + * UI controller for interactive plots + * @Class + * @Param {object} opts + * @Param {object} opts.buttons nested arrays of grouped buttons config objects + * @Param {object} opts.container container div to append modeBar + * @Param {object} opts.graphInfo primary plot object containing data and layout + */ +function ModeBar(opts) { + this.container = opts.container; + this.element = document.createElement('div'); + + this.update(opts.graphInfo, opts.buttons); + + this.container.appendChild(this.element); +} + +var proto = ModeBar.prototype; + +/** + * Update modeBar (buttons and logo) + * + * @param {object} graphInfo primary plot object containing data and layout + * @param {array of arrays} buttons nested arrays of grouped buttons to initialize + * + */ +proto.update = function(graphInfo, buttons) { + this.graphInfo = graphInfo; + + var context = this.graphInfo._context; + + if(context.displayModeBar === 'hover') { + this.element.className = 'modebar modebar--hover'; + } + else this.element.className = 'modebar'; + + // if buttons or logo have changed, redraw modebar interior + var needsNewButtons = !this.hasButtons(buttons), + needsNewLogo = (this.hasLogo !== context.displaylogo); + + if(needsNewButtons || needsNewLogo) { + this.removeAllButtons(); + + this.updateButtons(buttons); + + if(context.displaylogo) { + this.element.appendChild(this.getLogo()); + this.hasLogo = true; + } + } + + this.updateActiveButton(); +}; + +proto.updateButtons = function(buttons) { + var _this = this; + + this.buttons = buttons; + this.buttonElements = []; + this.buttonsNames = []; + + this.buttons.forEach(function(buttonGroup) { + var group = _this.createGroup(); + + buttonGroup.forEach(function(buttonConfig) { + var buttonName = buttonConfig.name; + if(!buttonName) { + throw new Error('must provide button \'name\' in button config'); + } + if(_this.buttonsNames.indexOf(buttonName) !== -1) { + throw new Error('button name \'' + buttonName + '\' is taken'); + } + _this.buttonsNames.push(buttonName); + + var button = _this.createButton(buttonConfig); + _this.buttonElements.push(button); + group.appendChild(button); + }); + + _this.element.appendChild(group); + }); +}; + +/** + * Empty div for containing a group of buttons + * @Return {HTMLelement} + */ +proto.createGroup = function() { + var group = document.createElement('div'); + group.className = 'modebar-group'; + + return group; +}; + +/** + * Create a new button div and set constant and configurable attributes + * @Param {object} config (see ./buttons.js for more info) + * @Return {HTMLelement} + */ +proto.createButton = function(config) { + var _this = this, + button = document.createElement('a'); + + button.setAttribute('rel', 'tooltip'); + button.className = 'modebar-btn'; + + var title = config.title; + if(title === undefined) title = config.name; + if(title || title === 0) button.setAttribute('data-title', title); + + if(config.attr !== undefined) button.setAttribute('data-attr', config.attr); + + var val = config.val; + if(val !== undefined) { + if(typeof val === 'function') val = val(this.graphInfo); + button.setAttribute('data-val', val); + } + + var click = config.click; + if(typeof click !== 'function') { + throw new Error('must provide button \'click\' function in button config'); + } + else { + button.addEventListener('click', function(ev) { + config.click(_this.graphInfo, ev); + + // only needed for 'hoverClosestGeo' which does not call relayout + _this.updateActiveButton(ev.currentTarget); + }); + } + + button.setAttribute('data-toggle', config.toggle || false); + if(config.toggle) button.classList.add('active'); + + button.appendChild(this.createIcon(config.icon || Icons.question)); + button.setAttribute('data-gravity', config.gravity || 'n'); + + return button; +}; + +/** + * Add an icon to a button + * @Param {object} thisIcon + * @Param {number} thisIcon.width + * @Param {string} thisIcon.path + * @Return {HTMLelement} + */ +proto.createIcon = function(thisIcon) { + var iconHeight = thisIcon.ascent - thisIcon.descent, + svgNS = 'http://www.w3.org/2000/svg', + icon = document.createElementNS(svgNS, 'svg'), + path = document.createElementNS(svgNS, 'path'); + + icon.setAttribute('height', '1em'); + icon.setAttribute('width', (thisIcon.width / iconHeight) + 'em'); + icon.setAttribute('viewBox', [0, 0, thisIcon.width, iconHeight].join(' ')); + + path.setAttribute('d', thisIcon.path); + path.setAttribute('transform', 'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')'); + icon.appendChild(path); + + return icon; +}; + +/** + * Updates active button with attribute specified in layout + * @Param {object} graphInfo plot object containing data and layout + * @Return {HTMLelement} + */ +proto.updateActiveButton = function(buttonClicked) { + var fullLayout = this.graphInfo._fullLayout, + dataAttrClicked = (buttonClicked !== undefined) ? + buttonClicked.getAttribute('data-attr') : + null; + + this.buttonElements.forEach(function(button) { + var thisval = button.getAttribute('data-val') || true, + dataAttr = button.getAttribute('data-attr'), + isToggleButton = (button.getAttribute('data-toggle') === 'true'), + button3 = d3.select(button); + + // Use 'data-toggle' and 'buttonClicked' to toggle buttons + // that have no one-to-one equivalent in fullLayout + if(isToggleButton) { + if(dataAttr === dataAttrClicked) { + button3.classed('active', !button3.classed('active')); + } + } + else { + var val = (dataAttr === null) ? + dataAttr : + Lib.nestedProperty(fullLayout, dataAttr).get(); + + button3.classed('active', val === thisval); + } + + }); +}; + +/** + * Check if modeBar is configured as button configuration argument + * + * @Param {object} buttons 2d array of grouped button config objects + * @Return {boolean} + */ +proto.hasButtons = function(buttons) { + var currentButtons = this.buttons; + + if(!currentButtons) return false; + + if(buttons.length !== currentButtons.length) return false; + + for(var i = 0; i < buttons.length; ++i) { + if(buttons[i].length !== currentButtons[i].length) return false; + for(var j = 0; j < buttons[i].length; j++) { + if(buttons[i][j].name !== currentButtons[i][j].name) return false; + } + } + + return true; +}; + +/** + * @return {HTMLDivElement} The logo image wrapped in a group + */ +proto.getLogo = function() { + var group = this.createGroup(), + a = document.createElement('a'); + + a.href = 'https://plot.ly/'; + a.target = '_blank'; + a.setAttribute('data-title', 'Produced with Plotly'); + a.className = 'modebar-btn plotlyjsicon modebar-btn--logo'; + + a.appendChild(this.createIcon(Icons.plotlylogo)); + + group.appendChild(a); + return group; +}; + +proto.removeAllButtons = function() { + while(this.element.firstChild) { + this.element.removeChild(this.element.firstChild); + } + + this.hasLogo = false; +}; + +proto.destroy = function() { + Lib.removeElement(this.container.querySelector('.modebar')); +}; + +function createModeBar(gd, buttons) { + var fullLayout = gd._fullLayout; + + var modeBar = new ModeBar({ + graphInfo: gd, + container: fullLayout._paperdiv.node(), + buttons: buttons + }); + + if(fullLayout._privateplot) { + d3.select(modeBar.element).append('span') + .classed('badge-private float--left', true) + .text('PRIVATE'); + } + + return modeBar; +} + +module.exports = createModeBar; + +},{"../../../build/ploticon":2,"../../lib":122,"d3":10}],76:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = require('../../plots/font_attributes'); +var colorAttrs = require('../color/attributes'); +var extendFlat = require('../../lib/extend').extendFlat; +var buttonAttrs = require('./button_attributes'); + +buttonAttrs = extendFlat(buttonAttrs, { + _isLinkedToArray: 'button', + + +}); + +module.exports = { + visible: { + valType: 'boolean', + + + }, + + buttons: buttonAttrs, + + x: { + valType: 'number', + min: -2, + max: 3, + + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'left', + + + }, + y: { + valType: 'number', + min: -2, + max: 3, + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'bottom', + + + }, + + font: extendFlat({}, fontAttrs, { + + }), + + bgcolor: { + valType: 'color', + dflt: colorAttrs.lightLine, + + + }, + activecolor: { + valType: 'color', + + + }, + bordercolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 0, + + + } +}; + +},{"../../lib/extend":117,"../../plots/font_attributes":170,"../color/attributes":26,"./button_attributes":77}],77:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + step: { + valType: 'enumerated', + + values: ['month', 'year', 'day', 'hour', 'minute', 'second', 'all'], + dflt: 'month', + + }, + stepmode: { + valType: 'enumerated', + + values: ['backward', 'todate'], + dflt: 'backward', + + }, + count: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + label: { + valType: 'string', + + + } +}; + +},{}],78:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + + // 'y' position pad above counter axis domain + yPad: 0.02, + + // minimum button width (regardless of text size) + minButtonWidth: 30, + + // buttons rect radii + rx: 3, + ry: 3, + + // light fraction used to compute the 'activecolor' default + lightAmount: 25, + darkAmount: 10 +}; + +},{}],79:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var Color = require('../color'); + +var attributes = require('./attributes'); +var buttonAttrs = require('./button_attributes'); +var constants = require('./constants'); + + +module.exports = function handleDefaults(containerIn, containerOut, layout, counterAxes) { + var selectorIn = containerIn.rangeselector || {}, + selectorOut = containerOut.rangeselector = {}; + + function coerce(attr, dflt) { + return Lib.coerce(selectorIn, selectorOut, attributes, attr, dflt); + } + + var buttons = buttonsDefaults(selectorIn, selectorOut); + + var visible = coerce('visible', buttons.length > 0); + if(!visible) return; + + var posDflt = getPosDflt(containerOut, layout, counterAxes); + coerce('x', posDflt[0]); + coerce('y', posDflt[1]); + Lib.noneOrAll(containerIn, containerOut, ['x', 'y']); + + coerce('xanchor'); + coerce('yanchor'); + + Lib.coerceFont(coerce, 'font', layout.font); + + var bgColor = coerce('bgcolor'); + coerce('activecolor', Color.contrast(bgColor, constants.lightAmount, constants.darkAmount)); + coerce('bordercolor'); + coerce('borderwidth'); +}; + +function buttonsDefaults(containerIn, containerOut) { + var buttonsIn = containerIn.buttons || [], + buttonsOut = containerOut.buttons = []; + + var buttonIn, buttonOut; + + function coerce(attr, dflt) { + return Lib.coerce(buttonIn, buttonOut, buttonAttrs, attr, dflt); + } + + for(var i = 0; i < buttonsIn.length; i++) { + buttonIn = buttonsIn[i]; + buttonOut = {}; + + if(!Lib.isPlainObject(buttonIn)) continue; + + var step = coerce('step'); + if(step !== 'all') { + coerce('stepmode'); + coerce('count'); + } + + coerce('label'); + + buttonOut._index = i; + buttonsOut.push(buttonOut); + } + + return buttonsOut; +} + +function getPosDflt(containerOut, layout, counterAxes) { + var anchoredList = counterAxes.filter(function(ax) { + return layout[ax].anchor === containerOut._id; + }); + + var posY = 0; + for(var i = 0; i < anchoredList.length; i++) { + var domain = layout[anchoredList[i]].domain; + if(domain) posY = Math.max(domain[1], posY); + } + + return [containerOut.domain[0], posY + constants.yPad]; +} + +},{"../../lib":122,"../color":27,"./attributes":76,"./button_attributes":77,"./constants":78}],80:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Plotly = require('../../plotly'); +var Plots = require('../../plots/plots'); +var Color = require('../color'); +var Drawing = require('../drawing'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var axisIds = require('../../plots/cartesian/axis_ids'); +var anchorUtils = require('../legend/anchor_utils'); + +var constants = require('./constants'); +var getUpdateObject = require('./get_update_object'); + + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout; + + var selectors = fullLayout._infolayer.selectAll('.rangeselector') + .data(makeSelectorData(gd), selectorKeyFunc); + + selectors.enter().append('g') + .classed('rangeselector', true); + + selectors.exit().remove(); + + selectors.style({ + cursor: 'pointer', + 'pointer-events': 'all' + }); + + selectors.each(function(d) { + var selector = d3.select(this), + axisLayout = d, + selectorLayout = axisLayout.rangeselector; + + var buttons = selector.selectAll('g.button') + .data(selectorLayout.buttons); + + buttons.enter().append('g') + .classed('button', true); + + buttons.exit().remove(); + + buttons.each(function(d) { + var button = d3.select(this); + var update = getUpdateObject(axisLayout, d); + + d.isActive = isActive(axisLayout, d, update); + + button.call(drawButtonRect, selectorLayout, d); + button.call(drawButtonText, selectorLayout, d); + + button.on('click', function() { + if(gd._dragged) return; + + Plotly.relayout(gd, update); + }); + + button.on('mouseover', function() { + d.isHovered = true; + button.call(drawButtonRect, selectorLayout, d); + }); + + button.on('mouseout', function() { + d.isHovered = false; + button.call(drawButtonRect, selectorLayout, d); + }); + }); + + // N.B. this mutates selectorLayout + reposition(gd, buttons, selectorLayout, axisLayout._name); + + selector.attr('transform', 'translate(' + + selectorLayout.lx + ',' + selectorLayout.ly + + ')'); + }); + +}; + +function makeSelectorData(gd) { + var axes = axisIds.list(gd, 'x', true); + var data = []; + + for(var i = 0; i < axes.length; i++) { + var axis = axes[i]; + + if(axis.rangeselector && axis.rangeselector.visible) { + data.push(axis); + } + } + + return data; +} + +function selectorKeyFunc(d) { + return d._id; +} + +function isActive(axisLayout, opts, update) { + if(opts.step === 'all') { + return axisLayout.autorange === true; + } + else { + var keys = Object.keys(update); + + return ( + axisLayout.range[0] === update[keys[0]] && + axisLayout.range[1] === update[keys[1]] + ); + } +} + +function drawButtonRect(button, selectorLayout, d) { + var rect = button.selectAll('rect') + .data([0]); + + rect.enter().append('rect') + .classed('selector-rect', true); + + rect.attr('shape-rendering', 'crispEdges'); + + rect.attr({ + 'rx': constants.rx, + 'ry': constants.ry + }); + + rect.call(Color.stroke, selectorLayout.bordercolor) + .call(Color.fill, getFillColor(selectorLayout, d)) + .style('stroke-width', selectorLayout.borderwidth + 'px'); +} + +function getFillColor(selectorLayout, d) { + return (d.isActive || d.isHovered) ? + selectorLayout.activecolor : + selectorLayout.bgcolor; +} + +function drawButtonText(button, selectorLayout, d) { + function textLayout(s) { + svgTextUtils.convertToTspans(s); + + // TODO do we need anything else here? + } + + var text = button.selectAll('text') + .data([0]); + + text.enter().append('text') + .classed('selector-text', true) + .classed('user-select-none', true); + + text.attr('text-anchor', 'middle'); + + text.call(Drawing.font, selectorLayout.font) + .text(getLabel(d)) + .call(textLayout); +} + +function getLabel(opts) { + if(opts.label) return opts.label; + + if(opts.step === 'all') return 'all'; + + return opts.count + opts.step.charAt(0); +} + +function reposition(gd, buttons, opts, axName) { + opts.width = 0; + opts.height = 0; + + var borderWidth = opts.borderwidth; + + buttons.each(function() { + var button = d3.select(this), + text = button.select('.selector-text'), + tspans = text.selectAll('tspan'); + + var tHeight = opts.font.size * 1.3, + tLines = tspans[0].length || 1, + hEff = Math.max(tHeight * tLines, 16) + 3; + + opts.height = Math.max(opts.height, hEff); + }); + + buttons.each(function() { + var button = d3.select(this), + rect = button.select('.selector-rect'), + text = button.select('.selector-text'), + tspans = text.selectAll('tspan'); + + var tWidth = text.node() && Drawing.bBox(text.node()).width, + tHeight = opts.font.size * 1.3, + tLines = tspans[0].length || 1; + + var wEff = Math.max(tWidth + 10, constants.minButtonWidth); + + // TODO add MathJax support + + // TODO add buttongap attribute + + button.attr('transform', 'translate(' + + (borderWidth + opts.width) + ',' + borderWidth + + ')'); + + rect.attr({ + x: 0, + y: 0, + width: wEff, + height: opts.height + }); + + var textAttrs = { + x: wEff / 2, + y: opts.height / 2 - ((tLines - 1) * tHeight / 2) + 3 + }; + + text.attr(textAttrs); + tspans.attr(textAttrs); + + opts.width += wEff + 5; + }); + + buttons.selectAll('rect').attr('height', opts.height); + + var graphSize = gd._fullLayout._size; + opts.lx = graphSize.l + graphSize.w * opts.x; + opts.ly = graphSize.t + graphSize.h * (1 - opts.y); + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(opts)) { + opts.lx -= opts.width; + xanchor = 'right'; + } + if(anchorUtils.isCenterAnchor(opts)) { + opts.lx -= opts.width / 2; + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(opts)) { + opts.ly -= opts.height; + yanchor = 'bottom'; + } + if(anchorUtils.isMiddleAnchor(opts)) { + opts.ly -= opts.height / 2; + yanchor = 'middle'; + } + + opts.width = Math.ceil(opts.width); + opts.height = Math.ceil(opts.height); + opts.lx = Math.round(opts.lx); + opts.ly = Math.round(opts.ly); + + Plots.autoMargin(gd, axName + '-range-selector', { + x: opts.x, + y: opts.y, + l: opts.width * ({right: 1, center: 0.5}[xanchor] || 0), + r: opts.width * ({left: 1, center: 0.5}[xanchor] || 0), + b: opts.height * ({top: 1, middle: 0.5}[yanchor] || 0), + t: opts.height * ({bottom: 1, middle: 0.5}[yanchor] || 0) + }); +} + +},{"../../lib/svg_text_utils":134,"../../plotly":145,"../../plots/cartesian/axis_ids":153,"../../plots/plots":186,"../color":27,"../drawing":50,"../legend/anchor_utils":63,"./constants":78,"./get_update_object":81,"d3":10}],81:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Lib = require('../../lib'); + + +module.exports = function getUpdateObject(axisLayout, buttonLayout) { + var axName = axisLayout._name; + var update = {}; + + if(buttonLayout.step === 'all') { + update[axName + '.autorange'] = true; + } + else { + var xrange = getXRange(axisLayout, buttonLayout); + + update[axName + '.range[0]'] = xrange[0]; + update[axName + '.range[1]'] = xrange[1]; + } + + return update; +}; + +function getXRange(axisLayout, buttonLayout) { + var currentRange = axisLayout.range; + var base = new Date(Lib.dateTime2ms(currentRange[1])); + + var step = buttonLayout.step, + count = buttonLayout.count; + + var range0; + + switch(buttonLayout.stepmode) { + case 'backward': + range0 = Lib.ms2DateTime(+d3.time[step].offset(base, -count)); + break; + + case 'todate': + var base2 = d3.time[step].offset(base, -count); + + range0 = Lib.ms2DateTime(+d3.time[step].ceil(base2)); + break; + } + + var range1 = currentRange[1]; + + return [range0, range1]; +} + +},{"../../lib":122,"d3":10}],82:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'component', + name: 'rangeselector', + + layoutNodes: ['xaxis.'], + layoutAttributes: require('./attributes'), + handleDefaults: require('./defaults'), + + draw: require('./draw') +}; + +},{"./attributes":76,"./defaults":79,"./draw":80}],83:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttributes = require('../color/attributes'); + +module.exports = { + bgcolor: { + valType: 'color', + dflt: colorAttributes.background, + + + }, + bordercolor: { + valType: 'color', + dflt: colorAttributes.defaultLine, + + + }, + borderwidth: { + valType: 'integer', + dflt: 0, + min: 0, + + + }, + range: { + valType: 'info_array', + + items: [ + {valType: 'any'}, + {valType: 'any'} + ], + + }, + thickness: { + valType: 'number', + dflt: 0.15, + min: 0, + max: 1, + + + }, + visible: { + valType: 'boolean', + dflt: true, + + + } +}; + +},{"../color/attributes":26}],84:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + + // attribute container name + name: 'rangeslider', + + // class names + + containerClassName: 'rangeslider-container', + bgClassName: 'rangeslider-bg', + rangePlotClassName: 'rangeslider-rangeplot', + + maskMinClassName: 'rangeslider-mask-min', + maskMaxClassName: 'rangeslider-mask-max', + slideBoxClassName: 'rangeslider-slidebox', + + grabberMinClassName: 'rangeslider-grabber-min', + grabAreaMinClassName: 'rangeslider-grabarea-min', + handleMinClassName: 'rangeslider-handle-min', + + grabberMaxClassName: 'rangeslider-grabber-max', + grabAreaMaxClassName: 'rangeslider-grabarea-max', + handleMaxClassName: 'rangeslider-handle-max', + + // style constants + + maskColor: 'rgba(0,0,0,0.4)', + + slideBoxFill: 'transparent', + slideBoxCursor: 'ew-resize', + + grabAreaFill: 'transparent', + grabAreaCursor: 'col-resize', + grabAreaWidth: 10, + grabAreaMinOffset: -6, + grabAreaMaxOffset: -2, + + handleWidth: 2, + handleRadius: 1, + handleFill: '#fff', + handleStroke: '#666', +}; + +},{}],85:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var attributes = require('./attributes'); + + +module.exports = function handleDefaults(layoutIn, layoutOut, axName, counterAxes) { + if(!layoutIn[axName].rangeslider) return; + + // not super proud of this (maybe store _ in axis object instead + if(!Lib.isPlainObject(layoutIn[axName].rangeslider)) { + layoutIn[axName].rangeslider = {}; + } + + var containerIn = layoutIn[axName].rangeslider, + axOut = layoutOut[axName], + containerOut = axOut.rangeslider = {}; + + function coerce(attr, dflt) { + return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); + } + + coerce('bgcolor', layoutOut.plot_bgcolor); + coerce('bordercolor'); + coerce('borderwidth'); + coerce('thickness'); + coerce('visible'); + coerce('range'); + + // Expand slider range to the axis range + if(containerOut.range && !axOut.autorange) { + var outRange = containerOut.range, + axRange = axOut.range, + l2r = axOut.l2r, + r2l = axOut.r2l; + + outRange[0] = l2r(Math.min(r2l(outRange[0]), r2l(axRange[0]))); + outRange[1] = l2r(Math.max(r2l(outRange[1]), r2l(axRange[1]))); + } else { + axOut._needsExpand = true; + } + + if(containerOut.visible) { + counterAxes.forEach(function(ax) { + var opposing = layoutOut[ax] || {}; + opposing.fixedrange = true; + layoutOut[ax] = opposing; + }); + } + + // to map back range slider (auto) range + containerOut._input = containerIn; +}; + +},{"../../lib":122,"./attributes":83}],86:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = require('d3'); + +var Plotly = require('../../plotly'); +var Plots = require('../../plots/plots'); + +var Lib = require('../../lib'); +var Drawing = require('../drawing'); +var Color = require('../color'); + +var Cartesian = require('../../plots/cartesian'); +var Axes = require('../../plots/cartesian/axes'); + +var dragElement = require('../dragelement'); +var setCursor = require('../../lib/setcursor'); + +var constants = require('./constants'); + + +module.exports = function(gd) { + var fullLayout = gd._fullLayout, + rangeSliderData = makeRangeSliderData(fullLayout); + + /* + * + * + * < .... range plot /> + * + * + * + * + * + * + * + * + * + * + * ... + */ + + function keyFunction(axisOpts) { + return axisOpts._name; + } + + var rangeSliders = fullLayout._infolayer + .selectAll('g.' + constants.containerClassName) + .data(rangeSliderData, keyFunction); + + rangeSliders.enter().append('g') + .classed(constants.containerClassName, true) + .attr('pointer-events', 'all'); + + // remove exiting sliders and their corresponding clip paths + rangeSliders.exit().each(function(axisOpts) { + var rangeSlider = d3.select(this), + opts = axisOpts[constants.name]; + + rangeSlider.remove(); + fullLayout._topdefs.select('#' + opts._clipId).remove(); + }); + + // remove push margin object(s) + if(rangeSliders.exit().size()) clearPushMargins(gd); + + // return early if no range slider is visible + if(rangeSliderData.length === 0) return; + + // for all present range sliders + rangeSliders.each(function(axisOpts) { + var rangeSlider = d3.select(this), + opts = axisOpts[constants.name]; + + // compute new slider range using axis autorange if necessary + // copy back range to input range slider container to skip + // this step in subsequent draw calls + if(!opts.range) { + opts._input.range = opts.range = Axes.getAutoRange(axisOpts); + } + + // update range slider dimensions + + var margin = fullLayout.margin, + graphSize = fullLayout._size, + domain = axisOpts.domain; + + opts._id = constants.name + axisOpts._id; + opts._clipId = opts._id + '-' + fullLayout._uid; + + opts._width = graphSize.w * (domain[1] - domain[0]); + opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness; + opts._offsetShift = Math.floor(opts.borderwidth / 2); + + var x = margin.l + (graphSize.w * domain[0]), + y = fullLayout.height - opts._height - margin.b; + + rangeSlider.attr('transform', 'translate(' + x + ',' + y + ')'); + + // update data <--> pixel coordinate conversion methods + + var range0 = axisOpts.r2l(opts.range[0]), + range1 = axisOpts.r2l(opts.range[1]), + dist = range1 - range0; + + opts.p2d = function(v) { + return (v / opts._width) * dist + range0; + }; + + opts.d2p = function(v) { + return (v - range0) / dist * opts._width; + }; + + opts._rl = [range0, range1]; + + // update inner nodes + + rangeSlider + .call(drawBg, gd, axisOpts, opts) + .call(addClipPath, gd, axisOpts, opts) + .call(drawRangePlot, gd, axisOpts, opts) + .call(drawMasks, gd, axisOpts, opts) + .call(drawSlideBox, gd, axisOpts, opts) + .call(drawGrabbers, gd, axisOpts, opts); + + // setup drag element + setupDragElement(rangeSlider, gd, axisOpts, opts); + + // update current range + setPixelRange(rangeSlider, gd, axisOpts, opts); + + // update margins + + var bb = axisOpts._boundingBox ? axisOpts._boundingBox.height : 0; + + Plots.autoMargin(gd, opts._id, { + x: 0, y: 0, l: 0, r: 0, t: 0, + b: opts._height + fullLayout.margin.b + bb, + pad: 15 + opts._offsetShift * 2 + }); + }); +}; + +function makeRangeSliderData(fullLayout) { + if(!fullLayout.xaxis) return []; + if(!fullLayout.xaxis[constants.name]) return []; + if(!fullLayout.xaxis[constants.name].visible) return []; + if(fullLayout._has('gl2d')) return []; + + return [fullLayout.xaxis]; +} + +function setupDragElement(rangeSlider, gd, axisOpts, opts) { + var slideBox = rangeSlider.select('rect.' + constants.slideBoxClassName).node(), + grabAreaMin = rangeSlider.select('rect.' + constants.grabAreaMinClassName).node(), + grabAreaMax = rangeSlider.select('rect.' + constants.grabAreaMaxClassName).node(); + + rangeSlider.on('mousedown', function() { + var event = d3.event, + target = event.target, + startX = event.clientX, + offsetX = startX - rangeSlider.node().getBoundingClientRect().left, + minVal = opts.d2p(axisOpts._rl[0]), + maxVal = opts.d2p(axisOpts._rl[1]); + + var dragCover = dragElement.coverSlip(); + + dragCover.addEventListener('mousemove', mouseMove); + dragCover.addEventListener('mouseup', mouseUp); + + function mouseMove(e) { + var delta = +e.clientX - startX; + var pixelMin, pixelMax, cursor; + + switch(target) { + case slideBox: + cursor = 'ew-resize'; + pixelMin = minVal + delta; + pixelMax = maxVal + delta; + break; + + case grabAreaMin: + cursor = 'col-resize'; + pixelMin = minVal + delta; + pixelMax = maxVal; + break; + + case grabAreaMax: + cursor = 'col-resize'; + pixelMin = minVal; + pixelMax = maxVal + delta; + break; + + default: + cursor = 'ew-resize'; + pixelMin = offsetX; + pixelMax = offsetX + delta; + break; + } + + if(pixelMax < pixelMin) { + var tmp = pixelMax; + pixelMax = pixelMin; + pixelMin = tmp; + } + + opts._pixelMin = pixelMin; + opts._pixelMax = pixelMax; + + setCursor(d3.select(dragCover), cursor); + setDataRange(rangeSlider, gd, axisOpts, opts); + } + + function mouseUp() { + dragCover.removeEventListener('mousemove', mouseMove); + dragCover.removeEventListener('mouseup', mouseUp); + Lib.removeElement(dragCover); + } + }); +} + +function setDataRange(rangeSlider, gd, axisOpts, opts) { + + function clamp(v) { + return axisOpts.l2r(Lib.constrain(v, opts._rl[0], opts._rl[1])); + } + + var dataMin = clamp(opts.p2d(opts._pixelMin)), + dataMax = clamp(opts.p2d(opts._pixelMax)); + + window.requestAnimationFrame(function() { + Plotly.relayout(gd, 'xaxis.range', [dataMin, dataMax]); + }); +} + +function setPixelRange(rangeSlider, gd, axisOpts, opts) { + + function clamp(v) { + return Lib.constrain(v, 0, opts._width); + } + + var pixelMin = clamp(opts.d2p(axisOpts._rl[0])), + pixelMax = clamp(opts.d2p(axisOpts._rl[1])); + + rangeSlider.select('rect.' + constants.slideBoxClassName) + .attr('x', pixelMin) + .attr('width', pixelMax - pixelMin); + + rangeSlider.select('rect.' + constants.maskMinClassName) + .attr('width', pixelMin); + + rangeSlider.select('rect.' + constants.maskMaxClassName) + .attr('x', pixelMax) + .attr('width', opts._width - pixelMax); + + rangeSlider.select('g.' + constants.grabberMinClassName) + .attr('transform', 'translate(' + (pixelMin - constants.handleWidth - 1) + ',0)'); + + rangeSlider.select('g.' + constants.grabberMaxClassName) + .attr('transform', 'translate(' + pixelMax + ',0)'); +} + +function drawBg(rangeSlider, gd, axisOpts, opts) { + var bg = rangeSlider.selectAll('rect.' + constants.bgClassName) + .data([0]); + + bg.enter().append('rect') + .classed(constants.bgClassName, true) + .attr({ + x: 0, + y: 0, + 'shape-rendering': 'crispEdges' + }); + + var borderCorrect = (opts.borderwidth % 2) === 0 ? + opts.borderwidth : + opts.borderwidth - 1; + + var offsetShift = -opts._offsetShift; + + bg.attr({ + width: opts._width + borderCorrect, + height: opts._height + borderCorrect, + transform: 'translate(' + offsetShift + ',' + offsetShift + ')', + fill: opts.bgcolor, + stroke: opts.bordercolor, + 'stroke-width': opts.borderwidth, + }); +} + +function addClipPath(rangeSlider, gd, axisOpts, opts) { + var fullLayout = gd._fullLayout; + + var clipPath = fullLayout._topdefs.selectAll('#' + opts._clipId) + .data([0]); + + clipPath.enter().append('clipPath') + .attr('id', opts._clipId) + .append('rect') + .attr({ x: 0, y: 0 }); + + clipPath.select('rect').attr({ + width: opts._width, + height: opts._height + }); +} + +function drawRangePlot(rangeSlider, gd, axisOpts, opts) { + var subplotData = Axes.getSubplots(gd, axisOpts), + calcData = gd.calcdata; + + var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName) + .data(subplotData, Lib.identity); + + rangePlots.enter().append('g') + .attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; }) + .call(Drawing.setClipUrl, opts._clipId); + + rangePlots.order(); + + rangePlots.exit().remove(); + + var mainplotinfo; + + rangePlots.each(function(id, i) { + var plotgroup = d3.select(this), + isMainPlot = (i === 0); + + var oppAxisOpts = Axes.getFromId(gd, id, 'y'), + oppAxisName = oppAxisOpts._name; + + var mockFigure = { + data: [], + layout: { + xaxis: { + type: axisOpts.type, + domain: [0, 1], + range: opts.range.slice() + }, + width: opts._width, + height: opts._height, + margin: { t: 0, b: 0, l: 0, r: 0 } + } + }; + + mockFigure.layout[oppAxisName] = { + domain: [0, 1], + range: oppAxisOpts.range.slice() + }; + + Plots.supplyDefaults(mockFigure); + + var xa = mockFigure._fullLayout.xaxis, + ya = mockFigure._fullLayout[oppAxisName]; + + var plotinfo = { + id: id, + plotgroup: plotgroup, + xaxis: xa, + yaxis: ya + }; + + if(isMainPlot) mainplotinfo = plotinfo; + else { + plotinfo.mainplot = 'xy'; + plotinfo.mainplotinfo = mainplotinfo; + } + + Cartesian.rangePlot(gd, plotinfo, filterRangePlotCalcData(calcData, id)); + + if(isMainPlot) plotinfo.bg.call(Color.fill, opts.bgcolor); + }); +} + +function filterRangePlotCalcData(calcData, subplotId) { + var out = []; + + for(var i = 0; i < calcData.length; i++) { + var calcTrace = calcData[i], + trace = calcTrace[0].trace; + + if(trace.xaxis + trace.yaxis === subplotId) { + out.push(calcTrace); + } + } + + return out; +} + +function drawMasks(rangeSlider, gd, axisOpts, opts) { + var maskMin = rangeSlider.selectAll('rect.' + constants.maskMinClassName) + .data([0]); + + maskMin.enter().append('rect') + .classed(constants.maskMinClassName, true) + .attr({ x: 0, y: 0 }); + + maskMin.attr({ + height: opts._height, + fill: constants.maskColor + }); + + var maskMax = rangeSlider.selectAll('rect.' + constants.maskMaxClassName) + .data([0]); + + maskMax.enter().append('rect') + .classed(constants.maskMaxClassName, true) + .attr('y', 0); + + maskMax.attr({ + height: opts._height, + fill: constants.maskColor + }); +} + +function drawSlideBox(rangeSlider, gd, axisOpts, opts) { + var slideBox = rangeSlider.selectAll('rect.' + constants.slideBoxClassName) + .data([0]); + + slideBox.enter().append('rect') + .classed(constants.slideBoxClassName, true) + .attr('y', 0) + .attr('cursor', constants.slideBoxCursor); + + slideBox.attr({ + height: opts._height, + fill: constants.slideBoxFill + }); +} + +function drawGrabbers(rangeSlider, gd, axisOpts, opts) { + + // + + var grabberMin = rangeSlider.selectAll('g.' + constants.grabberMinClassName) + .data([0]); + grabberMin.enter().append('g') + .classed(constants.grabberMinClassName, true); + + var grabberMax = rangeSlider.selectAll('g.' + constants.grabberMaxClassName) + .data([0]); + grabberMax.enter().append('g') + .classed(constants.grabberMaxClassName, true); + + // + + var handleFixAttrs = { + x: 0, + width: constants.handleWidth, + rx: constants.handleRadius, + fill: constants.handleFill, + stroke: constants.handleStroke, + 'shape-rendering': 'crispEdges' + }; + + var handleDynamicAttrs = { + y: opts._height / 4, + height: opts._height / 2, + }; + + var handleMin = grabberMin.selectAll('rect.' + constants.handleMinClassName) + .data([0]); + handleMin.enter().append('rect') + .classed(constants.handleMinClassName, true) + .attr(handleFixAttrs); + handleMin.attr(handleDynamicAttrs); + + var handleMax = grabberMax.selectAll('rect.' + constants.handleMaxClassName) + .data([0]); + handleMax.enter().append('rect') + .classed(constants.handleMaxClassName, true) + .attr(handleFixAttrs); + handleMax.attr(handleDynamicAttrs); + + // + + var grabAreaFixAttrs = { + width: constants.grabAreaWidth, + y: 0, + fill: constants.grabAreaFill, + cursor: constants.grabAreaCursor + }; + + var grabAreaMin = grabberMin.selectAll('rect.' + constants.grabAreaMinClassName) + .data([0]); + grabAreaMin.enter().append('rect') + .classed(constants.grabAreaMinClassName, true) + .attr(grabAreaFixAttrs); + grabAreaMin.attr({ + x: constants.grabAreaMinOffset, + height: opts._height + }); + + var grabAreaMax = grabberMax.selectAll('rect.' + constants.grabAreaMaxClassName) + .data([0]); + grabAreaMax.enter().append('rect') + .classed(constants.grabAreaMaxClassName, true) + .attr(grabAreaFixAttrs); + grabAreaMax.attr({ + x: constants.grabAreaMaxOffset, + height: opts._height + }); +} + +function clearPushMargins(gd) { + var pushMargins = gd._fullLayout._pushmargin || {}, + keys = Object.keys(pushMargins); + + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + + if(k.indexOf(constants.name) !== -1) { + Plots.autoMargin(gd, k); + } + } +} + +},{"../../lib":122,"../../lib/setcursor":132,"../../plotly":145,"../../plots/cartesian":158,"../../plots/cartesian/axes":150,"../../plots/plots":186,"../color":27,"../dragelement":48,"../drawing":50,"./constants":84,"d3":10}],87:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + moduleType: 'component', + name: 'rangeslider', + + layoutNodes: ['xaxis.'], + layoutAttributes: require('./attributes'), + handleDefaults: require('./defaults'), + + draw: require('./draw') +}; + +},{"./attributes":83,"./defaults":85,"./draw":86}],88:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var annAttrs = require('../annotations/attributes'); +var scatterAttrs = require('../../traces/scatter/attributes'); +var extendFlat = require('../../lib/extend').extendFlat; + +var scatterLineAttrs = scatterAttrs.line; + +module.exports = { + _isLinkedToArray: 'shape', + + visible: { + valType: 'boolean', + + dflt: true, + + }, + + type: { + valType: 'enumerated', + values: ['circle', 'rect', 'path', 'line'], + + + }, + + layer: { + valType: 'enumerated', + values: ['below', 'above'], + dflt: 'above', + + + }, + + xref: extendFlat({}, annAttrs.xref, { + + }), + x0: { + valType: 'any', + + + }, + x1: { + valType: 'any', + + + }, + + yref: extendFlat({}, annAttrs.yref, { + + }), + y0: { + valType: 'any', + + + }, + y1: { + valType: 'any', + + + }, + + path: { + valType: 'string', + + + }, + + opacity: { + valType: 'number', + min: 0, + max: 1, + dflt: 1, + + + }, + line: { + color: scatterLineAttrs.color, + width: scatterLineAttrs.width, + dash: scatterLineAttrs.dash, + + }, + fillcolor: { + valType: 'color', + dflt: 'rgba(0,0,0,0)', + + + } +}; + +},{"../../lib/extend":117,"../../traces/scatter/attributes":234,"../annotations/attributes":20}],89:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var Axes = require('../../plots/cartesian/axes'); + +var constants = require('./constants'); +var helpers = require('./helpers'); + + +module.exports = function calcAutorange(gd) { + var fullLayout = gd._fullLayout, + shapeList = Lib.filterVisible(fullLayout.shapes); + + if(!shapeList.length || !gd._fullData.length) return; + + for(var i = 0; i < shapeList.length; i++) { + var shape = shapeList[i], + ppad = shape.line.width / 2; + + var ax, bounds; + + if(shape.xref !== 'paper') { + ax = Axes.getFromId(gd, shape.xref); + bounds = shapeBounds(ax, shape.x0, shape.x1, shape.path, constants.paramIsX); + if(bounds) Axes.expand(ax, bounds, {ppad: ppad}); + } + + if(shape.yref !== 'paper') { + ax = Axes.getFromId(gd, shape.yref); + bounds = shapeBounds(ax, shape.y0, shape.y1, shape.path, constants.paramIsY); + if(bounds) Axes.expand(ax, bounds, {ppad: ppad}); + } + } +}; + +function shapeBounds(ax, v0, v1, path, paramsToUse) { + var convertVal = (ax.type === 'category') ? Number : ax.d2c; + + if(v0 !== undefined) return [convertVal(v0), convertVal(v1)]; + if(!path) return; + + var min = Infinity, + max = -Infinity, + segments = path.match(constants.segmentRE), + i, + segment, + drawnParam, + params, + val; + + if(ax.type === 'date') convertVal = helpers.decodeDate(convertVal); + + for(i = 0; i < segments.length; i++) { + segment = segments[i]; + drawnParam = paramsToUse[segment.charAt(0)].drawn; + if(drawnParam === undefined) continue; + + params = segments[i].substr(1).match(constants.paramRE); + if(!params || params.length < drawnParam) continue; + + val = convertVal(params[drawnParam]); + if(val < min) min = val; + if(val > max) max = val; + } + if(max >= min) return [min, max]; +} + +},{"../../lib":122,"../../plots/cartesian/axes":150,"./constants":90,"./helpers":93}],90:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + segmentRE: /[MLHVQCTSZ][^MLHVQCTSZ]*/g, + paramRE: /[^\s,]+/g, + + // which numbers in each path segment are x (or y) values + // drawn is which param is a drawn point, as opposed to a + // control point (which doesn't count toward autorange. + // TODO: this means curved paths could extend beyond the + // autorange bounds. This is a bit tricky to get right + // unless we revert to bounding boxes, but perhaps there's + // a calculation we could do...) + paramIsX: { + M: {0: true, drawn: 0}, + L: {0: true, drawn: 0}, + H: {0: true, drawn: 0}, + V: {}, + Q: {0: true, 2: true, drawn: 2}, + C: {0: true, 2: true, 4: true, drawn: 4}, + T: {0: true, drawn: 0}, + S: {0: true, 2: true, drawn: 2}, + // A: {0: true, 5: true}, + Z: {} + }, + + paramIsY: { + M: {1: true, drawn: 1}, + L: {1: true, drawn: 1}, + H: {}, + V: {0: true, drawn: 0}, + Q: {1: true, 3: true, drawn: 3}, + C: {1: true, 3: true, 5: true, drawn: 5}, + T: {1: true, drawn: 1}, + S: {1: true, 3: true, drawn: 5}, + // A: {1: true, 6: true}, + Z: {} + }, + + numParams: { + M: 2, + L: 2, + H: 1, + V: 1, + Q: 4, + C: 6, + T: 2, + S: 4, + // A: 7, + Z: 0 + } +}; + +},{}],91:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); +var handleShapeDefaults = require('./shape_defaults'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + var opts = { + name: 'shapes', + handleItemDefaults: handleShapeDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + +},{"../../plots/array_container_defaults":147,"./shape_defaults":95}],92:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Plotly = require('../../plotly'); +var Lib = require('../../lib'); +var Axes = require('../../plots/cartesian/axes'); +var Color = require('../color'); +var Drawing = require('../drawing'); + +var dragElement = require('../dragelement'); +var setCursor = require('../../lib/setcursor'); + +var constants = require('./constants'); +var helpers = require('./helpers'); +var handleShapeDefaults = require('./shape_defaults'); +var supplyLayoutDefaults = require('./defaults'); + + +// Shapes are stored in gd.layout.shapes, an array of objects +// index can point to one item in this array, +// or non-numeric to simply add a new one +// or -1 to modify all existing +// opt can be the full options object, or one key (to be set to value) +// or undefined to simply redraw +// if opt is blank, val can be 'add' or a full options object to add a new +// annotation at that point in the array, or 'remove' to delete this one + +module.exports = { + draw: draw, + drawOne: drawOne +}; + +function draw(gd) { + var fullLayout = gd._fullLayout; + + // Remove previous shapes before drawing new in shapes in fullLayout.shapes + fullLayout._shapeUpperLayer.selectAll('path').remove(); + fullLayout._shapeLowerLayer.selectAll('path').remove(); + fullLayout._shapeSubplotLayer.selectAll('path').remove(); + + for(var i = 0; i < fullLayout.shapes.length; i++) { + if(fullLayout.shapes[i].visible) { + drawOne(gd, i); + } + } + + // may need to resurrect this if we put text (LaTeX) in shapes + // return Plots.previousPromises(gd); +} + +function drawOne(gd, index, opt, value) { + if(!isNumeric(index) || index === -1) { + + // no index provided - we're operating on ALL shapes + if(!index && Array.isArray(value)) { + replaceAllShapes(gd, value); + return; + } + else if(value === 'remove') { + deleteAllShapes(gd); + return; + } + else if(opt && value !== 'add') { + updateAllShapes(gd, opt, value); + return; + } + else { + // add a new empty annotation + index = gd._fullLayout.shapes.length; + gd._fullLayout.shapes.push({}); + } + } + + if(!opt && value) { + if(value === 'remove') { + deleteShape(gd, index); + return; + } + else if(value === 'add' || Lib.isPlainObject(value)) { + insertShape(gd, index, value); + } + } + + updateShape(gd, index, opt, value); +} + +function replaceAllShapes(gd, newShapes) { + gd.layout.shapes = newShapes; + supplyLayoutDefaults(gd.layout, gd._fullLayout); + draw(gd); +} + +function deleteAllShapes(gd) { + delete gd.layout.shapes; + gd._fullLayout.shapes = []; + draw(gd); +} + +function updateAllShapes(gd, opt, value) { + for(var i = 0; i < gd._fullLayout.shapes.length; i++) { + drawOne(gd, i, opt, value); + } +} + +function deleteShape(gd, index) { + getShapeLayer(gd, index) + .selectAll('[data-index="' + index + '"]') + .remove(); + + gd._fullLayout.shapes.splice(index, 1); + + gd.layout.shapes.splice(index, 1); + + for(var i = index; i < gd._fullLayout.shapes.length; i++) { + // redraw all shapes past the removed one, + // so they bind to the right events + getShapeLayer(gd, i) + .selectAll('[data-index="' + (i + 1) + '"]') + .attr('data-index', i); + drawOne(gd, i); + } +} + +function insertShape(gd, index, newShape) { + gd._fullLayout.shapes.splice(index, 0, {}); + + var rule = Lib.isPlainObject(newShape) ? + Lib.extendFlat({}, newShape) : + {text: 'New text'}; + + if(gd.layout.shapes) { + gd.layout.shapes.splice(index, 0, rule); + } else { + gd.layout.shapes = [rule]; + } + + // there is no need to call shapes.draw(gd, index), + // because updateShape() is called from within shapes.draw() + + for(var i = gd._fullLayout.shapes.length - 1; i > index; i--) { + getShapeLayer(gd, i) + .selectAll('[data-index="' + (i - 1) + '"]') + .attr('data-index', i); + drawOne(gd, i); + } +} + +function updateShape(gd, index, opt, value) { + var i, n; + + // remove the existing shape if there is one + getShapeLayer(gd, index) + .selectAll('[data-index="' + index + '"]') + .remove(); + + // remember a few things about what was already there, + var optionsIn = gd.layout.shapes[index]; + + // (from annos...) not sure how we're getting here... but C12 is seeing a bug + // where we fail here when they add/remove annotations + // TODO: clean this up and remove it. + if(!optionsIn) return; + + // alter the input shape as requested + var optionsEdit = {}; + if(typeof opt === 'string' && opt) optionsEdit[opt] = value; + else if(Lib.isPlainObject(opt)) optionsEdit = opt; + + var optionKeys = Object.keys(optionsEdit); + for(i = 0; i < optionKeys.length; i++) { + var k = optionKeys[i]; + Lib.nestedProperty(optionsIn, k).set(optionsEdit[k]); + } + + // return early in visible: false updates + if(optionsIn.visible === false) return; + + var oldRef = {xref: optionsIn.xref, yref: optionsIn.yref}, + posAttrs = ['x0', 'x1', 'y0', 'y1']; + + for(i = 0; i < 4; i++) { + var posAttr = posAttrs[i]; + // if we don't have an explicit position already, + // don't set one just because we're changing references + // or axis type. + // the defaults will be consistent most of the time anyway, + // except in log/linear changes + if(optionsEdit[posAttr] !== undefined || + optionsIn[posAttr] === undefined) { + continue; + } + + var axLetter = posAttr.charAt(0), + axOld = Axes.getFromId(gd, + Axes.coerceRef(oldRef, {}, gd, axLetter, '', 'paper')), + axNew = Axes.getFromId(gd, + Axes.coerceRef(optionsIn, {}, gd, axLetter, '', 'paper')), + position = optionsIn[posAttr], + rangePosition; + + if(optionsEdit[axLetter + 'ref'] !== undefined) { + // first convert to fraction of the axis + if(axOld) { + rangePosition = helpers.shapePositionToRange(axOld)(position); + position = axOld.r2fraction(rangePosition); + } else { + position = (position - axNew.domain[0]) / + (axNew.domain[1] - axNew.domain[0]); + } + + if(axNew) { + // then convert to new data coordinates at the same fraction + rangePosition = axNew.fraction2r(position); + position = helpers.rangeToShapePosition(axNew)(rangePosition); + } else { + // or scale to the whole plot + position = axOld.domain[0] + + position * (axOld.domain[1] - axOld.domain[0]); + } + } + + optionsIn[posAttr] = position; + } + + var options = {}; + handleShapeDefaults(optionsIn, options, gd._fullLayout); + gd._fullLayout.shapes[index] = options; + + var clipAxes; + if(options.layer !== 'below') { + clipAxes = (options.xref + options.yref).replace(/paper/g, ''); + drawShape(gd._fullLayout._shapeUpperLayer); + } + else if(options.xref === 'paper' && options.yref === 'paper') { + clipAxes = ''; + drawShape(gd._fullLayout._shapeLowerLayer); + } + else { + var plots = gd._fullLayout._plots || {}, + subplots = Object.keys(plots), + plotinfo; + + for(i = 0, n = subplots.length; i < n; i++) { + plotinfo = plots[subplots[i]]; + clipAxes = subplots[i]; + + if(isShapeInSubplot(gd, options, plotinfo)) { + drawShape(plotinfo.shapelayer); + } + } + } + + function drawShape(shapeLayer) { + var attrs = { + 'data-index': index, + 'fill-rule': 'evenodd', + d: getPathString(gd, options) + }, + lineColor = options.line.width ? + options.line.color : 'rgba(0,0,0,0)'; + + var path = shapeLayer.append('path') + .attr(attrs) + .style('opacity', options.opacity) + .call(Color.stroke, lineColor) + .call(Color.fill, options.fillcolor) + .call(Drawing.dashLine, options.line.dash, options.line.width); + + if (options.classes) { + path.classed(options.classes, true); + } + + if(clipAxes) { + path.call(Drawing.setClipUrl, + 'clip' + gd._fullLayout._uid + clipAxes); + } + + // if(gd._context.editable) setupDragElement(gd, path, options, index); + } +} + +function setupDragElement(gd, shapePath, shapeOptions, index) { + var MINWIDTH = 10, + MINHEIGHT = 10; + + var update; + var x0, y0, x1, y1, astrX0, astrY0, astrX1, astrY1; + var n0, s0, w0, e0, astrN, astrS, astrW, astrE, optN, optS, optW, optE; + var pathIn, astrPath; + + var xa, ya, x2p, y2p, p2x, p2y; + + var dragOptions = { + setCursor: updateDragMode, + element: shapePath.node(), + prepFn: startDrag, + doneFn: endDrag + }, + dragBBox = dragOptions.element.getBoundingClientRect(), + dragMode; + + dragElement.init(dragOptions); + + function updateDragMode(evt) { + // choose 'move' or 'resize' + // based on initial position of cursor within the drag element + var w = dragBBox.right - dragBBox.left, + h = dragBBox.bottom - dragBBox.top, + x = evt.clientX - dragBBox.left, + y = evt.clientY - dragBBox.top, + cursor = (w > MINWIDTH && h > MINHEIGHT && !evt.shiftKey) ? + dragElement.getCursor(x / w, 1 - y / h) : + 'move'; + + setCursor(shapePath, cursor); + + // possible values 'move', 'sw', 'w', 'se', 'e', 'ne', 'n', 'nw' and 'w' + dragMode = cursor.split('-')[0]; + } + + function startDrag(evt) { + // setup conversion functions + xa = Axes.getFromId(gd, shapeOptions.xref); + ya = Axes.getFromId(gd, shapeOptions.yref); + + x2p = helpers.getDataToPixel(gd, xa); + y2p = helpers.getDataToPixel(gd, ya, true); + p2x = helpers.getPixelToData(gd, xa); + p2y = helpers.getPixelToData(gd, ya, true); + + // setup update strings and initial values + var astr = 'shapes[' + index + ']'; + if(shapeOptions.type === 'path') { + pathIn = shapeOptions.path; + astrPath = astr + '.path'; + } + else { + x0 = x2p(shapeOptions.x0); + y0 = y2p(shapeOptions.y0); + x1 = x2p(shapeOptions.x1); + y1 = y2p(shapeOptions.y1); + + astrX0 = astr + '.x0'; + astrY0 = astr + '.y0'; + astrX1 = astr + '.x1'; + astrY1 = astr + '.y1'; + } + + if(x0 < x1) { + w0 = x0; astrW = astr + '.x0'; optW = 'x0'; + e0 = x1; astrE = astr + '.x1'; optE = 'x1'; + } + else { + w0 = x1; astrW = astr + '.x1'; optW = 'x1'; + e0 = x0; astrE = astr + '.x0'; optE = 'x0'; + } + if(y0 < y1) { + n0 = y0; astrN = astr + '.y0'; optN = 'y0'; + s0 = y1; astrS = astr + '.y1'; optS = 'y1'; + } + else { + n0 = y1; astrN = astr + '.y1'; optN = 'y1'; + s0 = y0; astrS = astr + '.y0'; optS = 'y0'; + } + + update = {}; + + // setup dragMode and the corresponding handler + updateDragMode(evt); + dragOptions.moveFn = (dragMode === 'move') ? moveShape : resizeShape; + } + + function endDrag(dragged) { + setCursor(shapePath); + if(dragged) { + Plotly.relayout(gd, update); + } + } + + function moveShape(dx, dy) { + if(shapeOptions.type === 'path') { + var moveX = function moveX(x) { return p2x(x2p(x) + dx); }; + if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); + + var moveY = function moveY(y) { return p2y(y2p(y) + dy); }; + if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); + + shapeOptions.path = movePath(pathIn, moveX, moveY); + update[astrPath] = shapeOptions.path; + } + else { + update[astrX0] = shapeOptions.x0 = p2x(x0 + dx); + update[astrY0] = shapeOptions.y0 = p2y(y0 + dy); + update[astrX1] = shapeOptions.x1 = p2x(x1 + dx); + update[astrY1] = shapeOptions.y1 = p2y(y1 + dy); + } + + shapePath.attr('d', getPathString(gd, shapeOptions)); + } + + function resizeShape(dx, dy) { + if(shapeOptions.type === 'path') { + // TODO: implement path resize + var moveX = function moveX(x) { return p2x(x2p(x) + dx); }; + if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); + + var moveY = function moveY(y) { return p2y(y2p(y) + dy); }; + if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); + + shapeOptions.path = movePath(pathIn, moveX, moveY); + update[astrPath] = shapeOptions.path; + } + else { + var newN = (~dragMode.indexOf('n')) ? n0 + dy : n0, + newS = (~dragMode.indexOf('s')) ? s0 + dy : s0, + newW = (~dragMode.indexOf('w')) ? w0 + dx : w0, + newE = (~dragMode.indexOf('e')) ? e0 + dx : e0; + + if(newS - newN > MINHEIGHT) { + update[astrN] = shapeOptions[optN] = p2y(newN); + update[astrS] = shapeOptions[optS] = p2y(newS); + } + + if(newE - newW > MINWIDTH) { + update[astrW] = shapeOptions[optW] = p2x(newW); + update[astrE] = shapeOptions[optE] = p2x(newE); + } + } + + shapePath.attr('d', getPathString(gd, shapeOptions)); + } +} + +function getShapeLayer(gd, index) { + var shape = gd._fullLayout.shapes[index], + shapeLayer = gd._fullLayout._shapeUpperLayer; + + if(!shape) { + Lib.log('getShapeLayer: undefined shape: index', index); + } + else if(shape.layer === 'below') { + shapeLayer = (shape.xref === 'paper' && shape.yref === 'paper') ? + gd._fullLayout._shapeLowerLayer : + gd._fullLayout._shapeSubplotLayer; + } + + return shapeLayer; +} + +function isShapeInSubplot(gd, shape, plotinfo) { + var xa = Axes.getFromId(gd, plotinfo.id, 'x')._id, + ya = Axes.getFromId(gd, plotinfo.id, 'y')._id, + isBelow = shape.layer === 'below', + inSuplotAxis = (xa === shape.xref || ya === shape.yref), + isNotAnOverlaidSubplot = !!plotinfo.shapelayer; + return isBelow && inSuplotAxis && isNotAnOverlaidSubplot; +} + +function getPathString(gd, options) { + var type = options.type, + xa = Axes.getFromId(gd, options.xref), + ya = Axes.getFromId(gd, options.yref), + gs = gd._fullLayout._size, + x2r, + x2p, + y2r, + y2p; + + if(xa) { + x2r = helpers.shapePositionToRange(xa); + x2p = function(v) { return xa._offset + xa.r2p(x2r(v, true)); }; + } + else { + x2p = function(v) { return gs.l + gs.w * v; }; + } + + if(ya) { + y2r = helpers.shapePositionToRange(ya); + y2p = function(v) { return ya._offset + ya.r2p(y2r(v, true)); }; + } + else { + y2p = function(v) { return gs.t + gs.h * (1 - v); }; + } + + if(type === 'path') { + if(xa && xa.type === 'date') x2p = helpers.decodeDate(x2p); + if(ya && ya.type === 'date') y2p = helpers.decodeDate(y2p); + return convertPath(options.path, x2p, y2p); + } + + var x0 = x2p(options.x0), + x1 = x2p(options.x1), + y0 = y2p(options.y0), + y1 = y2p(options.y1); + + if(type === 'line') return 'M' + x0 + ',' + y0 + 'L' + x1 + ',' + y1; + if(type === 'rect') return 'M' + x0 + ',' + y0 + 'H' + x1 + 'V' + y1 + 'H' + x0 + 'Z'; + // circle + var cx = (x0 + x1) / 2, + cy = (y0 + y1) / 2, + rx = Math.abs(cx - x0), + ry = Math.abs(cy - y0), + rArc = 'A' + rx + ',' + ry, + rightPt = (cx + rx) + ',' + cy, + topPt = cx + ',' + (cy - ry); + return 'M' + rightPt + rArc + ' 0 1,1 ' + topPt + + rArc + ' 0 0,1 ' + rightPt + 'Z'; +} + + +function convertPath(pathIn, x2p, y2p) { + // convert an SVG path string from data units to pixels + return pathIn.replace(constants.segmentRE, function(segment) { + var paramNumber = 0, + segmentType = segment.charAt(0), + xParams = constants.paramIsX[segmentType], + yParams = constants.paramIsY[segmentType], + nParams = constants.numParams[segmentType]; + + var paramString = segment.substr(1).replace(constants.paramRE, function(param) { + if(xParams[paramNumber]) param = x2p(param); + else if(yParams[paramNumber]) param = y2p(param); + paramNumber++; + + if(paramNumber > nParams) param = 'X'; + return param; + }); + + if(paramNumber > nParams) { + paramString = paramString.replace(/[\s,]*X.*/, ''); + Lib.log('Ignoring extra params in segment ' + segment); + } + + return segmentType + paramString; + }); +} + +function movePath(pathIn, moveX, moveY) { + return pathIn.replace(constants.segmentRE, function(segment) { + var paramNumber = 0, + segmentType = segment.charAt(0), + xParams = constants.paramIsX[segmentType], + yParams = constants.paramIsY[segmentType], + nParams = constants.numParams[segmentType]; + + var paramString = segment.substr(1).replace(constants.paramRE, function(param) { + if(paramNumber >= nParams) return param; + + if(xParams[paramNumber]) param = moveX(param); + else if(yParams[paramNumber]) param = moveY(param); + + paramNumber++; + + return param; + }); + + return segmentType + paramString; + }); +} + +},{"../../lib":122,"../../lib/setcursor":132,"../../plotly":145,"../../plots/cartesian/axes":150,"../color":27,"../dragelement":48,"../drawing":50,"./constants":90,"./defaults":91,"./helpers":93,"./shape_defaults":95,"fast-isnumeric":13}],93:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// special position conversion functions... category axis positions can't be +// specified by their data values, because they don't make a continuous mapping. +// so these have to be specified in terms of the category serial numbers, +// but can take fractional values. Other axis types we specify position based on +// the actual data values. +// TODO: in V2.0 (when log axis ranges are in data units) range and shape position +// will be identical, so rangeToShapePosition and shapePositionToRange can be +// removed entirely. + +exports.rangeToShapePosition = function(ax) { + return (ax.type === 'log') ? ax.r2d : function(v) { return v; }; +}; + +exports.shapePositionToRange = function(ax) { + return (ax.type === 'log') ? ax.d2r : function(v) { return v; }; +}; + +exports.decodeDate = function(convertToPx) { + return function(v) { + if(v.replace) v = v.replace('_', ' '); + return convertToPx(v); + }; +}; + +exports.encodeDate = function(convertToDate) { + return function(v) { return convertToDate(v).replace(' ', '_'); }; +}; + +exports.getDataToPixel = function(gd, axis, isVertical) { + var gs = gd._fullLayout._size, + dataToPixel; + + if(axis) { + var d2r = exports.shapePositionToRange(axis); + + dataToPixel = function(v) { + return axis._offset + axis.r2p(d2r(v, true)); + }; + + if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); + } + else if(isVertical) { + dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; + } + else { + dataToPixel = function(v) { return gs.l + gs.w * v; }; + } + + return dataToPixel; +}; + +exports.getPixelToData = function(gd, axis, isVertical) { + var gs = gd._fullLayout._size, + pixelToData; + + if(axis) { + var r2d = exports.rangeToShapePosition(axis); + pixelToData = function(p) { return r2d(axis.p2r(p - axis._offset)); }; + } + else if(isVertical) { + pixelToData = function(p) { return 1 - (p - gs.t) / gs.h; }; + } + else { + pixelToData = function(p) { return (p - gs.l) / gs.w; }; + } + + return pixelToData; +}; + +},{}],94:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var drawModule = require('./draw'); + +module.exports = { + moduleType: 'component', + name: 'shapes', + + layoutAttributes: require('./attributes'), + supplyLayoutDefaults: require('./defaults'), + + calcAutorange: require('./calc_autorange'), + draw: drawModule.draw, + drawOne: drawModule.drawOne +}; + +},{"./attributes":88,"./calc_autorange":89,"./defaults":91,"./draw":92}],95:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var Axes = require('../../plots/cartesian/axes'); + +var attributes = require('./attributes'); +var helpers = require('./helpers'); + + +module.exports = function handleShapeDefaults(shapeIn, shapeOut, fullLayout, opts, itemOpts) { + opts = opts || {}; + itemOpts = itemOpts || {}; + + function coerce(attr, dflt) { + return Lib.coerce(shapeIn, shapeOut, attributes, attr, dflt); + } + + var visible = coerce('visible', !itemOpts.itemIsNotPlainObject); + + if(!visible) return shapeOut; + + coerce('layer'); + coerce('opacity'); + coerce('fillcolor'); + coerce('line.color'); + coerce('line.width'); + coerce('line.dash'); + + var dfltType = shapeIn.path ? 'path' : 'rect', + shapeType = coerce('type', dfltType); + + // positioning + var axLetters = ['x', 'y']; + for(var i = 0; i < 2; i++) { + var axLetter = axLetters[i], + gdMock = {_fullLayout: fullLayout}; + + // xref, yref + var axRef = Axes.coerceRef(shapeIn, shapeOut, gdMock, axLetter, '', 'paper'); + + if(shapeType !== 'path') { + var dflt0 = 0.25, + dflt1 = 0.75, + ax, + pos2r, + r2pos; + + if(axRef !== 'paper') { + ax = Axes.getFromId(gdMock, axRef); + r2pos = helpers.rangeToShapePosition(ax); + pos2r = helpers.shapePositionToRange(ax); + } + else { + pos2r = r2pos = Lib.identity; + } + + // hack until V2.0 when log has regular range behavior - make it look like other + // ranges to send to coerce, then put it back after + // this is all to give reasonable default position behavior on log axes, which is + // a pretty unimportant edge case so we could just ignore this. + var attr0 = axLetter + '0', + attr1 = axLetter + '1', + in0 = shapeIn[attr0], + in1 = shapeIn[attr1]; + shapeIn[attr0] = pos2r(shapeIn[attr0], true); + shapeIn[attr1] = pos2r(shapeIn[attr1], true); + + // x0, x1 (and y0, y1) + Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr0, dflt0); + Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr1, dflt1); + + // hack part 2 + shapeOut[attr0] = r2pos(shapeOut[attr0]); + shapeOut[attr1] = r2pos(shapeOut[attr1]); + shapeIn[attr0] = in0; + shapeIn[attr1] = in1; + } + } + + if(shapeType === 'path') { + coerce('path'); + } + else { + Lib.noneOrAll(shapeIn, shapeOut, ['x0', 'x1', 'y0', 'y1']); + } + + if (shapeIn.classes) { + shapeOut.classes = shapeIn.classes; + } + + return shapeOut; +}; + +},{"../../lib":122,"../../plots/cartesian/axes":150,"./attributes":88,"./helpers":93}],96:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = require('../../plots/font_attributes'); +var padAttrs = require('../../plots/pad_attributes'); +var extendFlat = require('../../lib/extend').extendFlat; +var extendDeep = require('../../lib/extend').extendDeep; +var animationAttrs = require('../../plots/animation_attributes'); +var constants = require('./constants'); + +var stepsAttrs = { + _isLinkedToArray: 'step', + + method: { + valType: 'enumerated', + values: ['restyle', 'relayout', 'animate', 'update'], + dflt: 'restyle', + + + }, + args: { + valType: 'info_array', + + freeLength: true, + items: [ + { valType: 'any' }, + { valType: 'any' }, + { valType: 'any' } + ], + + }, + label: { + valType: 'string', + + + }, + value: { + valType: 'string', + + + } +}; + +module.exports = { + _isLinkedToArray: 'slider', + + visible: { + valType: 'boolean', + + dflt: true, + + }, + + active: { + valType: 'number', + + min: 0, + dflt: 0, + + }, + + steps: stepsAttrs, + + lenmode: { + valType: 'enumerated', + values: ['fraction', 'pixels'], + + dflt: 'fraction', + + }, + len: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + x: { + valType: 'number', + min: -2, + max: 3, + dflt: 0, + + + }, + pad: extendDeep({}, padAttrs, { + + }, {t: {dflt: 20}}), + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'left', + + + }, + y: { + valType: 'number', + min: -2, + max: 3, + dflt: 0, + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'top', + + + }, + + transition: { + duration: { + valType: 'number', + + min: 0, + dflt: 150, + + }, + easing: { + valType: 'enumerated', + values: animationAttrs.transition.easing.values, + + dflt: 'cubic-in-out', + + }, + }, + + currentvalue: { + visible: { + valType: 'boolean', + + dflt: true, + + }, + + xanchor: { + valType: 'enumerated', + values: ['left', 'center', 'right'], + dflt: 'left', + + + }, + + offset: { + valType: 'number', + dflt: 10, + + + }, + + prefix: { + valType: 'string', + + + }, + + suffix: { + valType: 'string', + + + }, + + font: extendFlat({}, fontAttrs, { + + }), + }, + + font: extendFlat({}, fontAttrs, { + + }), + + activebgcolor: { + valType: 'color', + + dflt: constants.gripBgActiveColor, + + }, + bgcolor: { + valType: 'color', + + dflt: constants.railBgColor, + + }, + bordercolor: { + valType: 'color', + dflt: constants.railBorderColor, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: constants.railBorderWidth, + + + }, + ticklen: { + valType: 'number', + min: 0, + dflt: constants.tickLength, + + + }, + tickcolor: { + valType: 'color', + dflt: constants.tickColor, + + + }, + tickwidth: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + minorticklen: { + valType: 'number', + min: 0, + dflt: constants.minorTickLength, + + + }, +}; + +},{"../../lib/extend":117,"../../plots/animation_attributes":146,"../../plots/font_attributes":170,"../../plots/pad_attributes":185,"./constants":97}],97:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + + // layout attribute name + name: 'sliders', + + // class names + containerClassName: 'slider-container', + groupClassName: 'slider-group', + inputAreaClass: 'slider-input-area', + railRectClass: 'slider-rail-rect', + railTouchRectClass: 'slider-rail-touch-rect', + gripRectClass: 'slider-grip-rect', + tickRectClass: 'slider-tick-rect', + inputProxyClass: 'slider-input-proxy', + labelsClass: 'slider-labels', + labelGroupClass: 'slider-label-group', + labelClass: 'slider-label', + currentValueClass: 'slider-current-value', + + railHeight: 5, + + // DOM attribute name in button group keeping track + // of active update menu + menuIndexAttrName: 'slider-active-index', + + // id root pass to Plots.autoMargin + autoMarginIdRoot: 'slider-', + + // min item width / height + minWidth: 30, + minHeight: 30, + + // padding around item text + textPadX: 40, + + // font size to height scale + fontSizeToHeight: 1.3, + + // arrow offset off right edge + arrowOffsetX: 4, + + railRadius: 2, + railWidth: 5, + railBorder: 4, + railBorderWidth: 1, + railBorderColor: '#bec8d9', + railBgColor: '#f8fafc', + + // The distance of the rail from the edge of the touchable area + // Slightly less than the step inset because of the curved edges + // of the rail + railInset: 8, + + // The distance from the extremal tick marks to the edge of the + // touchable area. This is basically the same as the grip radius, + // but for other styles it wouldn't really need to be. + stepInset: 10, + + gripRadius: 10, + gripWidth: 20, + gripHeight: 20, + gripBorder: 20, + gripBorderWidth: 1, + gripBorderColor: '#bec8d9', + gripBgColor: '#f6f8fa', + gripBgActiveColor: '#dbdde0', + + labelPadding: 8, + labelOffset: 0, + + tickWidth: 1, + tickColor: '#333', + tickOffset: 25, + tickLength: 7, + + minorTickOffset: 25, + minorTickColor: '#333', + minorTickLength: 4, + + // Extra space below the current value label: + currentValuePadding: 8, + currentValueInset: 0, +}; + +},{}],98:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); + +var attributes = require('./attributes'); +var constants = require('./constants'); + +var name = constants.name; +var stepAttrs = attributes.steps; + + +module.exports = function slidersDefaults(layoutIn, layoutOut) { + var opts = { + name: name, + handleItemDefaults: sliderDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + +function sliderDefaults(sliderIn, sliderOut, layoutOut) { + + function coerce(attr, dflt) { + return Lib.coerce(sliderIn, sliderOut, attributes, attr, dflt); + } + + var steps = stepsDefaults(sliderIn, sliderOut); + + var visible = coerce('visible', steps.length > 0); + if(!visible) return; + + coerce('active'); + + coerce('x'); + coerce('y'); + Lib.noneOrAll(sliderIn, sliderOut, ['x', 'y']); + + coerce('xanchor'); + coerce('yanchor'); + + coerce('len'); + coerce('lenmode'); + + coerce('pad.t'); + coerce('pad.r'); + coerce('pad.b'); + coerce('pad.l'); + + Lib.coerceFont(coerce, 'font', layoutOut.font); + + var currentValueIsVisible = coerce('currentvalue.visible'); + + if(currentValueIsVisible) { + coerce('currentvalue.xanchor'); + coerce('currentvalue.prefix'); + coerce('currentvalue.suffix'); + coerce('currentvalue.offset'); + + Lib.coerceFont(coerce, 'currentvalue.font', sliderOut.font); + } + + coerce('transition.duration'); + coerce('transition.easing'); + + coerce('bgcolor'); + coerce('activebgcolor'); + coerce('bordercolor'); + coerce('borderwidth'); + coerce('ticklen'); + coerce('tickwidth'); + coerce('tickcolor'); + coerce('minorticklen'); +} + +function stepsDefaults(sliderIn, sliderOut) { + var valuesIn = sliderIn.steps || [], + valuesOut = sliderOut.steps = []; + + var valueIn, valueOut; + + function coerce(attr, dflt) { + return Lib.coerce(valueIn, valueOut, stepAttrs, attr, dflt); + } + + for(var i = 0; i < valuesIn.length; i++) { + valueIn = valuesIn[i]; + valueOut = {}; + + if(!Lib.isPlainObject(valueIn) || !Array.isArray(valueIn.args)) { + continue; + } + + coerce('method'); + coerce('args'); + coerce('label', 'step-' + i); + coerce('value', valueOut.label); + + valuesOut.push(valueOut); + } + + return valuesOut; +} + +},{"../../lib":122,"../../plots/array_container_defaults":147,"./attributes":96,"./constants":97}],99:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Plots = require('../../plots/plots'); +var Lib = require('../../lib'); +var Color = require('../color'); +var Drawing = require('../drawing'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var anchorUtils = require('../legend/anchor_utils'); + +var constants = require('./constants'); + + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout, + sliderData = makeSliderData(fullLayout); + + // draw a container for *all* sliders: + var sliders = fullLayout._infolayer + .selectAll('g.' + constants.containerClassName) + .data(sliderData.length > 0 ? [0] : []); + + sliders.enter().append('g') + .classed(constants.containerClassName, true) + .style('cursor', 'ew-resize'); + + sliders.exit().remove(); + + // If no more sliders, clear the margisn: + if(sliders.exit().size()) clearPushMargins(gd); + + // Return early if no menus visible: + if(sliderData.length === 0) return; + + var sliderGroups = sliders.selectAll('g.' + constants.groupClassName) + .data(sliderData, keyFunction); + + sliderGroups.enter().append('g') + .classed(constants.groupClassName, true); + + sliderGroups.exit().each(function(sliderOpts) { + d3.select(this).remove(); + + sliderOpts._commandObserver.remove(); + delete sliderOpts._commandObserver; + + Plots.autoMargin(gd, constants.autoMarginIdRoot + sliderOpts._index); + }); + + // Find the dimensions of the sliders: + for(var i = 0; i < sliderData.length; i++) { + var sliderOpts = sliderData[i]; + findDimensions(gd, sliderOpts); + } + + sliderGroups.each(function(sliderOpts) { + // If it has fewer than two options, it's not really a slider: + if(sliderOpts.steps.length < 2) return; + + var gSlider = d3.select(this); + + computeLabelSteps(sliderOpts); + + Plots.manageCommandObserver(gd, sliderOpts, sliderOpts.steps, function(data) { + if(sliderOpts.active === data.index) return; + if(sliderOpts._dragging) return; + + setActive(gd, gSlider, sliderOpts, data.index, false, true); + }); + + drawSlider(gd, d3.select(this), sliderOpts); + + // makeInputProxy(gd, d3.select(this), sliderOpts); + }); +}; + +/* function makeInputProxy(gd, sliderGroup, sliderOpts) { + sliderOpts.inputProxy = gd._fullLayout._paperdiv.selectAll('input.' + constants.inputProxyClass) + .data([0]); +}*/ + +// This really only just filters by visibility: +function makeSliderData(fullLayout) { + var contOpts = fullLayout[constants.name], + sliderData = []; + + for(var i = 0; i < contOpts.length; i++) { + var item = contOpts[i]; + if(!item.visible || !item.steps.length) continue; + sliderData.push(item); + } + + return sliderData; +} + +// This is set in the defaults step: +function keyFunction(opts) { + return opts._index; +} + +// Compute the dimensions (mutates sliderOpts): +function findDimensions(gd, sliderOpts) { + var sliderLabels = gd._tester.selectAll('g.' + constants.labelGroupClass) + .data(sliderOpts.steps); + + sliderLabels.enter().append('g') + .classed(constants.labelGroupClass, true); + + // loop over fake buttons to find width / height + var maxLabelWidth = 0; + var labelHeight = 0; + sliderLabels.each(function(stepOpts) { + var labelGroup = d3.select(this); + + var text = drawLabel(labelGroup, {step: stepOpts}, sliderOpts); + + var tWidth = (text.node() && Drawing.bBox(text.node()).width) || 0; + + // This just overwrites with the last. Which is fine as long as + // the bounding box (probably incorrectly) measures the text *on + // a single line*: + labelHeight = (text.node() && Drawing.bBox(text.node()).height) || 0; + + maxLabelWidth = Math.max(maxLabelWidth, tWidth); + }); + + sliderLabels.remove(); + + sliderOpts.inputAreaWidth = Math.max( + constants.railWidth, + constants.gripHeight + ); + + sliderOpts.currentValueMaxWidth = 0; + sliderOpts.currentValueHeight = 0; + sliderOpts.currentValueTotalHeight = 0; + + if(sliderOpts.currentvalue.visible) { + // Get the dimensions of the current value label: + var dummyGroup = gd._tester.append('g'); + + sliderLabels.each(function(stepOpts) { + var curValPrefix = drawCurrentValue(dummyGroup, sliderOpts, stepOpts.label); + var curValSize = (curValPrefix.node() && Drawing.bBox(curValPrefix.node())) || {width: 0, height: 0}; + sliderOpts.currentValueMaxWidth = Math.max(sliderOpts.currentValueMaxWidth, Math.ceil(curValSize.width)); + sliderOpts.currentValueHeight = Math.max(sliderOpts.currentValueHeight, Math.ceil(curValSize.height)); + }); + + sliderOpts.currentValueTotalHeight = sliderOpts.currentValueHeight + sliderOpts.currentvalue.offset; + + dummyGroup.remove(); + } + + var graphSize = gd._fullLayout._size; + sliderOpts.lx = graphSize.l + graphSize.w * sliderOpts.x; + sliderOpts.ly = graphSize.t + graphSize.h * (1 - sliderOpts.y); + + if(sliderOpts.lenmode === 'fraction') { + // fraction: + sliderOpts.outerLength = Math.round(graphSize.w * sliderOpts.len); + } else { + // pixels: + sliderOpts.outerLength = sliderOpts.len; + } + + // Set the length-wise padding so that the grip ends up *on* the end of + // the bar when at either extreme + sliderOpts.lenPad = Math.round(constants.gripWidth * 0.5); + + // The length of the rail, *excluding* padding on either end: + sliderOpts.inputAreaStart = 0; + sliderOpts.inputAreaLength = Math.round(sliderOpts.outerLength - sliderOpts.pad.l - sliderOpts.pad.r); + + var textableInputLength = sliderOpts.inputAreaLength - 2 * constants.stepInset; + var availableSpacePerLabel = textableInputLength / (sliderOpts.steps.length - 1); + var computedSpacePerLabel = maxLabelWidth + constants.labelPadding; + sliderOpts.labelStride = Math.max(1, Math.ceil(computedSpacePerLabel / availableSpacePerLabel)); + sliderOpts.labelHeight = labelHeight; + + sliderOpts.height = sliderOpts.currentValueTotalHeight + constants.tickOffset + sliderOpts.ticklen + constants.labelOffset + sliderOpts.labelHeight + sliderOpts.pad.t + sliderOpts.pad.b; + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(sliderOpts)) { + sliderOpts.lx -= sliderOpts.outerLength; + xanchor = 'right'; + } + if(anchorUtils.isCenterAnchor(sliderOpts)) { + sliderOpts.lx -= sliderOpts.outerLength / 2; + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(sliderOpts)) { + sliderOpts.ly -= sliderOpts.height; + yanchor = 'bottom'; + } + if(anchorUtils.isMiddleAnchor(sliderOpts)) { + sliderOpts.ly -= sliderOpts.height / 2; + yanchor = 'middle'; + } + + sliderOpts.outerLength = Math.ceil(sliderOpts.outerLength); + sliderOpts.height = Math.ceil(sliderOpts.height); + sliderOpts.lx = Math.round(sliderOpts.lx); + sliderOpts.ly = Math.round(sliderOpts.ly); + + Plots.autoMargin(gd, constants.autoMarginIdRoot + sliderOpts._index, { + x: sliderOpts.x, + y: sliderOpts.y, + l: sliderOpts.outerLength * ({right: 1, center: 0.5}[xanchor] || 0), + r: sliderOpts.outerLength * ({left: 1, center: 0.5}[xanchor] || 0), + b: sliderOpts.height * ({top: 1, middle: 0.5}[yanchor] || 0), + t: sliderOpts.height * ({bottom: 1, middle: 0.5}[yanchor] || 0) + }); +} + +function drawSlider(gd, sliderGroup, sliderOpts) { + // These are carefully ordered for proper z-ordering: + sliderGroup + .call(drawCurrentValue, sliderOpts) + .call(drawRail, sliderOpts) + .call(drawLabelGroup, sliderOpts) + .call(drawTicks, sliderOpts) + .call(drawTouchRect, gd, sliderOpts) + .call(drawGrip, gd, sliderOpts); + + // Position the rectangle: + Lib.setTranslate(sliderGroup, sliderOpts.lx + sliderOpts.pad.l, sliderOpts.ly + sliderOpts.pad.t); + + sliderGroup.call(setGripPosition, sliderOpts, sliderOpts.active / (sliderOpts.steps.length - 1), false); + sliderGroup.call(drawCurrentValue, sliderOpts); + +} + +function drawCurrentValue(sliderGroup, sliderOpts, valueOverride) { + if(!sliderOpts.currentvalue.visible) return; + + var x0, textAnchor; + var text = sliderGroup.selectAll('text') + .data([0]); + + switch(sliderOpts.currentvalue.xanchor) { + case 'right': + // This is anchored left and adjusted by the width of the longest label + // so that the prefix doesn't move. The goal of this is to emphasize + // what's actually changing and make the update less distracting. + x0 = sliderOpts.inputAreaLength - constants.currentValueInset - sliderOpts.currentValueMaxWidth; + textAnchor = 'left'; + break; + case 'center': + x0 = sliderOpts.inputAreaLength * 0.5; + textAnchor = 'middle'; + break; + default: + x0 = constants.currentValueInset; + textAnchor = 'left'; + } + + text.enter().append('text') + .classed(constants.labelClass, true) + .classed('user-select-none', true) + .attr('text-anchor', textAnchor); + + var str = sliderOpts.currentvalue.prefix ? sliderOpts.currentvalue.prefix : ''; + + if(typeof valueOverride === 'string') { + str += valueOverride; + } else { + var curVal = sliderOpts.steps[sliderOpts.active].label; + str += curVal; + } + + if(sliderOpts.currentvalue.suffix) { + str += sliderOpts.currentvalue.suffix; + } + + text.call(Drawing.font, sliderOpts.currentvalue.font) + .text(str) + .call(svgTextUtils.convertToTspans); + + Lib.setTranslate(text, x0, sliderOpts.currentValueHeight); + + return text; +} + +function drawGrip(sliderGroup, gd, sliderOpts) { + var grip = sliderGroup.selectAll('rect.' + constants.gripRectClass) + .data([0]); + + grip.enter().append('rect') + .classed(constants.gripRectClass, true) + .call(attachGripEvents, gd, sliderGroup, sliderOpts) + .style('pointer-events', 'all'); + + grip.attr({ + width: constants.gripWidth, + height: constants.gripHeight, + rx: constants.gripRadius, + ry: constants.gripRadius, + }) + .call(Color.stroke, sliderOpts.bordercolor) + .call(Color.fill, sliderOpts.bgcolor) + .style('stroke-width', sliderOpts.borderwidth + 'px'); +} + +function drawLabel(item, data, sliderOpts) { + var text = item.selectAll('text') + .data([0]); + + text.enter().append('text') + .classed(constants.labelClass, true) + .classed('user-select-none', true) + .attr('text-anchor', 'middle'); + + text.call(Drawing.font, sliderOpts.font) + .text(data.step.label) + .call(svgTextUtils.convertToTspans); + + return text; +} + +function drawLabelGroup(sliderGroup, sliderOpts) { + var labels = sliderGroup.selectAll('g.' + constants.labelsClass) + .data([0]); + + labels.enter().append('g') + .classed(constants.labelsClass, true); + + var labelItems = labels.selectAll('g.' + constants.labelGroupClass) + .data(sliderOpts.labelSteps); + + labelItems.enter().append('g') + .classed(constants.labelGroupClass, true); + + labelItems.exit().remove(); + + labelItems.each(function(d) { + var item = d3.select(this); + + item.call(drawLabel, d, sliderOpts); + + Lib.setTranslate(item, + normalizedValueToPosition(sliderOpts, d.fraction), + constants.tickOffset + sliderOpts.ticklen + sliderOpts.labelHeight + constants.labelOffset + sliderOpts.currentValueTotalHeight + ); + }); + +} + +function handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, doTransition) { + var quantizedPosition = Math.round(normalizedPosition * (sliderOpts.steps.length - 1)); + + if(quantizedPosition !== sliderOpts.active) { + setActive(gd, sliderGroup, sliderOpts, quantizedPosition, true, doTransition); + } +} + +function setActive(gd, sliderGroup, sliderOpts, index, doCallback, doTransition) { + var previousActive = sliderOpts.active; + sliderOpts._input.active = sliderOpts.active = index; + + var step = sliderOpts.steps[sliderOpts.active]; + + sliderGroup.call(setGripPosition, sliderOpts, sliderOpts.active / (sliderOpts.steps.length - 1), doTransition); + sliderGroup.call(drawCurrentValue, sliderOpts); + + gd.emit('plotly_sliderchange', { + slider: sliderOpts, + step: sliderOpts.steps[sliderOpts.active], + interaction: doCallback, + previousActive: previousActive + }); + + if(step && step.method && doCallback) { + if(sliderGroup._nextMethod) { + // If we've already queued up an update, just overwrite it with the most recent: + sliderGroup._nextMethod.step = step; + sliderGroup._nextMethod.doCallback = doCallback; + sliderGroup._nextMethod.doTransition = doTransition; + } else { + sliderGroup._nextMethod = {step: step, doCallback: doCallback, doTransition: doTransition}; + sliderGroup._nextMethodRaf = window.requestAnimationFrame(function() { + var _step = sliderGroup._nextMethod.step; + if(!_step.method) return; + + Plots.executeAPICommand(gd, _step.method, _step.args); + + sliderGroup._nextMethod = null; + sliderGroup._nextMethodRaf = null; + }); + } + } +} + +function attachGripEvents(item, gd, sliderGroup, sliderOpts) { + var node = sliderGroup.node(); + var $gd = d3.select(gd); + + item.on('mousedown', function() { + gd.emit('plotly_sliderstart', {slider: sliderOpts}); + + var grip = sliderGroup.select('.' + constants.gripRectClass); + + d3.event.stopPropagation(); + d3.event.preventDefault(); + grip.call(Color.fill, sliderOpts.activebgcolor); + + var normalizedPosition = positionToNormalizedValue(sliderOpts, d3.mouse(node)[0]); + handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, true); + sliderOpts._dragging = true; + + $gd.on('mousemove', function() { + var normalizedPosition = positionToNormalizedValue(sliderOpts, d3.mouse(node)[0]); + handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, false); + }); + + $gd.on('mouseup', function() { + sliderOpts._dragging = false; + grip.call(Color.fill, sliderOpts.bgcolor); + $gd.on('mouseup', null); + $gd.on('mousemove', null); + + gd.emit('plotly_sliderend', { + slider: sliderOpts, + step: sliderOpts.steps[sliderOpts.active] + }); + }); + }); +} + +function drawTicks(sliderGroup, sliderOpts) { + var tick = sliderGroup.selectAll('rect.' + constants.tickRectClass) + .data(sliderOpts.steps); + + tick.enter().append('rect') + .classed(constants.tickRectClass, true); + + tick.exit().remove(); + + tick.attr({ + width: sliderOpts.tickwidth + 'px', + 'shape-rendering': 'crispEdges' + }); + + tick.each(function(d, i) { + var isMajor = i % sliderOpts.labelStride === 0; + var item = d3.select(this); + + item + .attr({height: isMajor ? sliderOpts.ticklen : sliderOpts.minorticklen}) + .call(Color.fill, isMajor ? sliderOpts.tickcolor : sliderOpts.tickcolor); + + Lib.setTranslate(item, + normalizedValueToPosition(sliderOpts, i / (sliderOpts.steps.length - 1)) - 0.5 * sliderOpts.tickwidth, + (isMajor ? constants.tickOffset : constants.minorTickOffset) + sliderOpts.currentValueTotalHeight + ); + }); + +} + +function computeLabelSteps(sliderOpts) { + sliderOpts.labelSteps = []; + var i0 = 0; + var nsteps = sliderOpts.steps.length; + + for(var i = i0; i < nsteps; i += sliderOpts.labelStride) { + sliderOpts.labelSteps.push({ + fraction: i / (nsteps - 1), + step: sliderOpts.steps[i] + }); + } +} + +function setGripPosition(sliderGroup, sliderOpts, position, doTransition) { + var grip = sliderGroup.select('rect.' + constants.gripRectClass); + + var x = normalizedValueToPosition(sliderOpts, position); + + // If this is true, then *this component* is already invoking its own command + // and has triggered its own animation. + if(sliderOpts._invokingCommand) return; + + var el = grip; + if(doTransition && sliderOpts.transition.duration > 0) { + el = el.transition() + .duration(sliderOpts.transition.duration) + .ease(sliderOpts.transition.easing); + } + + // Lib.setTranslate doesn't work here becasue of the transition duck-typing. + // It's also not necessary because there are no other transitions to preserve. + el.attr('transform', 'translate(' + (x - constants.gripWidth * 0.5) + ',' + (sliderOpts.currentValueTotalHeight) + ')'); +} + +// Convert a number from [0-1] to a pixel position relative to the slider group container: +function normalizedValueToPosition(sliderOpts, normalizedPosition) { + return sliderOpts.inputAreaStart + constants.stepInset + + (sliderOpts.inputAreaLength - 2 * constants.stepInset) * Math.min(1, Math.max(0, normalizedPosition)); +} + +// Convert a position relative to the slider group to a nubmer in [0, 1] +function positionToNormalizedValue(sliderOpts, position) { + return Math.min(1, Math.max(0, (position - constants.stepInset - sliderOpts.inputAreaStart) / (sliderOpts.inputAreaLength - 2 * constants.stepInset - 2 * sliderOpts.inputAreaStart))); +} + +function drawTouchRect(sliderGroup, gd, sliderOpts) { + var rect = sliderGroup.selectAll('rect.' + constants.railTouchRectClass) + .data([0]); + + rect.enter().append('rect') + .classed(constants.railTouchRectClass, true) + .call(attachGripEvents, gd, sliderGroup, sliderOpts) + .style('pointer-events', 'all'); + + rect.attr({ + width: sliderOpts.inputAreaLength, + height: Math.max(sliderOpts.inputAreaWidth, constants.tickOffset + sliderOpts.ticklen + sliderOpts.labelHeight) + }) + .call(Color.fill, sliderOpts.bgcolor) + .attr('opacity', 0); + + Lib.setTranslate(rect, 0, sliderOpts.currentValueTotalHeight); +} + +function drawRail(sliderGroup, sliderOpts) { + var rect = sliderGroup.selectAll('rect.' + constants.railRectClass) + .data([0]); + + rect.enter().append('rect') + .classed(constants.railRectClass, true); + + var computedLength = sliderOpts.inputAreaLength - constants.railInset * 2; + + rect.attr({ + width: computedLength, + height: constants.railWidth, + rx: constants.railRadius, + ry: constants.railRadius, + 'shape-rendering': 'crispEdges' + }) + .call(Color.stroke, sliderOpts.bordercolor) + .call(Color.fill, sliderOpts.bgcolor) + .style('stroke-width', sliderOpts.borderwidth + 'px'); + + Lib.setTranslate(rect, + constants.railInset, + (sliderOpts.inputAreaWidth - constants.railWidth) * 0.5 + sliderOpts.currentValueTotalHeight + ); +} + +function clearPushMargins(gd) { + var pushMargins = gd._fullLayout._pushmargin || {}, + keys = Object.keys(pushMargins); + + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + + if(k.indexOf(constants.autoMarginIdRoot) !== -1) { + Plots.autoMargin(gd, k); + } + } +} + +},{"../../lib":122,"../../lib/svg_text_utils":134,"../../plots/plots":186,"../color":27,"../drawing":50,"../legend/anchor_utils":63,"./constants":97,"d3":10}],100:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var constants = require('./constants'); + +module.exports = { + moduleType: 'component', + name: constants.name, + + layoutAttributes: require('./attributes'), + supplyLayoutDefaults: require('./defaults'), + + draw: require('./draw') +}; + +},{"./attributes":96,"./constants":97,"./defaults":98,"./draw":99}],101:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Plotly = require('../../plotly'); +var Plots = require('../../plots/plots'); +var Lib = require('../../lib'); +var Drawing = require('../drawing'); +var Color = require('../color'); +var svgTextUtils = require('../../lib/svg_text_utils'); + + +var Titles = module.exports = {}; + +/** + * Titles - (re)draw titles on the axes and plot: + * @param {DOM element} gd - the graphDiv + * @param {string} titleClass - the css class of this title + * @param {object} options - how and what to draw + * propContainer - the layout object containing `title` and `titlefont` + * attributes that apply to this title + * propName - the full name of the title property (for Plotly.relayout) + * [traceIndex] - include only if this property applies to one trace + * (such as a colorbar title) - then editing pipes to Plotly.restyle + * instead of Plotly.relayout + * dfltName - the name of the title in placeholder text + * [avoid] {object} - include if this title should move to avoid other elements + * selection - d3 selection of elements to avoid + * side - which direction to move if there is a conflict + * [offsetLeft] - if these elements are subject to a translation + * wrt the title element + * [offsetTop] + * attributes {object} - position and alignment attributes + * x - pixels + * y - pixels + * text-anchor - start|middle|end + * transform {object} - how to transform the title after positioning + * rotate - degrees + * offset - shift up/down in the rotated frame (unused?) + * containerGroup - if an svg element already exists to hold this + * title, include here. Otherwise it will go in fullLayout._infolayer + */ +Titles.draw = function(gd, titleClass, options) { + var cont = options.propContainer, + prop = options.propName, + traceIndex = options.traceIndex, + name = options.dfltName, + avoid = options.avoid || {}, + attributes = options.attributes, + transform = options.transform, + group = options.containerGroup, + + fullLayout = gd._fullLayout, + font = cont.titlefont.family, + fontSize = cont.titlefont.size, + fontColor = cont.titlefont.color, + + opacity = 1, + isplaceholder = false, + txt = cont.title.trim(); + if(txt === '') opacity = 0; + if(txt.match(/Click to enter .+ title/)) { + opacity = 0.2; + isplaceholder = true; + } + + if(!group) { + group = fullLayout._infolayer.selectAll('.g-' + titleClass) + .data([0]); + group.enter().append('g') + .classed('g-' + titleClass, true); + } + + var el = group.selectAll('text') + .data([0]); + el.enter().append('text'); + el.text(txt) + // this is hacky, but convertToTspans uses the class + // to determine whether to rotate mathJax... + // so we need to clear out any old class and put the + // correct one (only relevant for colorbars, at least + // for now) - ie don't use .classed + .attr('class', titleClass); + + function titleLayout(titleEl) { + Lib.syncOrAsync([drawTitle, scootTitle], titleEl); + } + + function drawTitle(titleEl) { + titleEl.attr('transform', transform ? + 'rotate(' + [transform.rotate, attributes.x, attributes.y] + + ') translate(0, ' + transform.offset + ')' : + null); + + titleEl.style({ + 'font-family': font, + 'font-size': d3.round(fontSize, 2) + 'px', + fill: Color.rgb(fontColor), + opacity: opacity * Color.opacity(fontColor), + 'font-weight': Plots.fontWeight + }) + .attr(attributes) + .call(svgTextUtils.convertToTspans) + .attr(attributes); + + titleEl.selectAll('tspan.line') + .attr(attributes); + return Plots.previousPromises(gd); + } + + function scootTitle(titleElIn) { + var titleGroup = d3.select(titleElIn.node().parentNode); + + if(avoid && avoid.selection && avoid.side && txt) { + titleGroup.attr('transform', null); + + // move toward avoid.side (= left, right, top, bottom) if needed + // can include pad (pixels, default 2) + var shift = 0, + backside = { + left: 'right', + right: 'left', + top: 'bottom', + bottom: 'top' + }[avoid.side], + shiftSign = (['left', 'top'].indexOf(avoid.side) !== -1) ? + -1 : 1, + pad = isNumeric(avoid.pad) ? avoid.pad : 2, + titlebb = Drawing.bBox(titleGroup.node()), + paperbb = { + left: 0, + top: 0, + right: fullLayout.width, + bottom: fullLayout.height + }, + maxshift = avoid.maxShift || ( + (paperbb[avoid.side] - titlebb[avoid.side]) * + ((avoid.side === 'left' || avoid.side === 'top') ? -1 : 1)); + // Prevent the title going off the paper + if(maxshift < 0) shift = maxshift; + else { + // so we don't have to offset each avoided element, + // give the title the opposite offset + titlebb.left -= avoid.offsetLeft; + titlebb.right -= avoid.offsetLeft; + titlebb.top -= avoid.offsetTop; + titlebb.bottom -= avoid.offsetTop; + + // iterate over a set of elements (avoid.selection) + // to avoid collisions with + avoid.selection.each(function() { + var avoidbb = Drawing.bBox(this); + + if(Lib.bBoxIntersect(titlebb, avoidbb, pad)) { + shift = Math.max(shift, shiftSign * ( + avoidbb[avoid.side] - titlebb[backside]) + pad); + } + }); + shift = Math.min(maxshift, shift); + } + if(shift > 0 || maxshift < 0) { + var shiftTemplate = { + left: [-shift, 0], + right: [shift, 0], + top: [0, -shift], + bottom: [0, shift] + }[avoid.side]; + titleGroup.attr('transform', + 'translate(' + shiftTemplate + ')'); + } + } + } + + el.attr({'data-unformatted': txt}) + .call(titleLayout); + + var placeholderText = 'Click to enter ' + name + ' title'; + + function setPlaceholder() { + opacity = 0; + isplaceholder = true; + txt = placeholderText; + fullLayout._infolayer.select('.' + titleClass) + .attr({'data-unformatted': txt}) + .text(txt) + .on('mouseover.opacity', function() { + d3.select(this).transition() + .duration(100).style('opacity', 1); + }) + .on('mouseout.opacity', function() { + d3.select(this).transition() + .duration(1000).style('opacity', 0); + }); + } + + // ABURATO: main title-specific edit settings + var isEditable = gd._context.editable; + + if (isEditable) { + if (cont === fullLayout) { + // MAIN TITLE + isEditable = gd._context.editableMainTitle; + } else if (cont === fullLayout.xaxis) { + isEditable = gd._context.editableAxisXTitle; + } else if (cont === fullLayout.yaxis) { + isEditable = gd._context.editableAxisYTitle; + } else if (cont === fullLayout.yaxis2) { + isEditable = gd._context.editableAxisY2Title; + } else if (cont === fullLayout.xaxis2) { + isEditable = gd._context.editableAxisX2Title; + } + } + + if(isEditable) { + if(!txt) setPlaceholder(); + + el.call(svgTextUtils.makeEditable) + .on('edit', function(text) { + if(traceIndex !== undefined) Plotly.restyle(gd, prop, text, traceIndex); + else Plotly.relayout(gd, prop, text); + }) + .on('cancel', function() { + this.text(this.attr('data-unformatted')) + .call(titleLayout); + }) + .on('input', function(d) { + this.text(d || ' ').attr(attributes) + .selectAll('tspan.line') + .attr(attributes); + }); + } + else if(!txt || txt.match(/Click to enter .+ title/)) { + el.remove(); + } + el.classed('js-placeholder', isplaceholder); + + // ABURATO: storing the title element inside its containing axis object + cont._titleElement = el; +}; + +},{"../../lib":122,"../../lib/svg_text_utils":134,"../../plotly":145,"../../plots/plots":186,"../color":27,"../drawing":50,"d3":10,"fast-isnumeric":13}],102:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = require('../../plots/font_attributes'); +var colorAttrs = require('../color/attributes'); +var extendFlat = require('../../lib/extend').extendFlat; +var padAttrs = require('../../plots/pad_attributes'); + +var buttonsAttrs = { + _isLinkedToArray: 'button', + + method: { + valType: 'enumerated', + values: ['restyle', 'relayout', 'animate', 'update'], + dflt: 'restyle', + + + }, + args: { + valType: 'info_array', + + freeLength: true, + items: [ + { valType: 'any' }, + { valType: 'any' }, + { valType: 'any' } + ], + + }, + label: { + valType: 'string', + + dflt: '', + + } +}; + +module.exports = { + _isLinkedToArray: 'updatemenu', + + visible: { + valType: 'boolean', + + + }, + + type: { + valType: 'enumerated', + values: ['dropdown', 'buttons'], + dflt: 'dropdown', + + + }, + + direction: { + valType: 'enumerated', + values: ['left', 'right', 'up', 'down'], + dflt: 'down', + + + }, + + active: { + valType: 'integer', + + min: -1, + dflt: 0, + + }, + + showactive: { + valType: 'boolean', + + dflt: true, + + }, + + buttons: buttonsAttrs, + + x: { + valType: 'number', + min: -2, + max: 3, + dflt: -0.05, + + + }, + xanchor: { + valType: 'enumerated', + values: ['auto', 'left', 'center', 'right'], + dflt: 'right', + + + }, + y: { + valType: 'number', + min: -2, + max: 3, + dflt: 1, + + + }, + yanchor: { + valType: 'enumerated', + values: ['auto', 'top', 'middle', 'bottom'], + dflt: 'top', + + + }, + + pad: extendFlat({}, padAttrs, { + + }), + + font: extendFlat({}, fontAttrs, { + + }), + + bgcolor: { + valType: 'color', + + + }, + bordercolor: { + valType: 'color', + dflt: colorAttrs.borderLine, + + + }, + borderwidth: { + valType: 'number', + min: 0, + dflt: 1, + + + } +}; + +},{"../../lib/extend":117,"../../plots/font_attributes":170,"../../plots/pad_attributes":185,"../color/attributes":26}],103:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = { + + // layout attribute name + name: 'updatemenus', + + // class names + containerClassName: 'updatemenu-container', + headerGroupClassName: 'updatemenu-header-group', + headerClassName: 'updatemenu-header', + headerArrowClassName: 'updatemenu-header-arrow', + dropdownButtonGroupClassName: 'updatemenu-dropdown-button-group', + dropdownButtonClassName: 'updatemenu-dropdown-button', + buttonClassName: 'updatemenu-button', + itemRectClassName: 'updatemenu-item-rect', + itemTextClassName: 'updatemenu-item-text', + + // DOM attribute name in button group keeping track + // of active update menu + menuIndexAttrName: 'updatemenu-active-index', + + // id root pass to Plots.autoMargin + autoMarginIdRoot: 'updatemenu-', + + // options when 'active: -1' + blankHeaderOpts: { label: ' ' }, + + // min item width / height + minWidth: 30, + minHeight: 30, + + // padding around item text + textPadX: 24, + arrowPadX: 16, + + // font size to height scale + fontSizeToHeight: 1.3, + + // item rect radii + rx: 2, + ry: 2, + + // item text x offset off left edge + textOffsetX: 12, + + // item text y offset (w.r.t. middle) + textOffsetY: 3, + + // arrow offset off right edge + arrowOffsetX: 4, + + // gap between header and buttons + gapButtonHeader: 5, + + // gap between between buttons + gapButton: 2, + + // color given to active buttons + activeColor: '#F4FAFF', + + // color given to hovered buttons + hoverColor: '#F4FAFF' +}; + +},{}],104:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); + +var attributes = require('./attributes'); +var constants = require('./constants'); + +var name = constants.name; +var buttonAttrs = attributes.buttons; + + +module.exports = function updateMenusDefaults(layoutIn, layoutOut) { + var opts = { + name: name, + handleItemDefaults: menuDefaults + }; + + handleArrayContainerDefaults(layoutIn, layoutOut, opts); +}; + +function menuDefaults(menuIn, menuOut, layoutOut) { + + function coerce(attr, dflt) { + return Lib.coerce(menuIn, menuOut, attributes, attr, dflt); + } + + var buttons = buttonsDefaults(menuIn, menuOut); + + var visible = coerce('visible', buttons.length > 0); + if(!visible) return; + + coerce('active'); + coerce('direction'); + coerce('type'); + coerce('showactive'); + + coerce('x'); + coerce('y'); + Lib.noneOrAll(menuIn, menuOut, ['x', 'y']); + + coerce('xanchor'); + coerce('yanchor'); + + coerce('pad.t'); + coerce('pad.r'); + coerce('pad.b'); + coerce('pad.l'); + + Lib.coerceFont(coerce, 'font', layoutOut.font); + + coerce('bgcolor', layoutOut.paper_bgcolor); + coerce('bordercolor'); + coerce('borderwidth'); +} + +function buttonsDefaults(menuIn, menuOut) { + var buttonsIn = menuIn.buttons || [], + buttonsOut = menuOut.buttons = []; + + var buttonIn, buttonOut; + + function coerce(attr, dflt) { + return Lib.coerce(buttonIn, buttonOut, buttonAttrs, attr, dflt); + } + + for(var i = 0; i < buttonsIn.length; i++) { + buttonIn = buttonsIn[i]; + buttonOut = {}; + + if(!Lib.isPlainObject(buttonIn) || !Array.isArray(buttonIn.args)) { + continue; + } + + coerce('method'); + coerce('args'); + coerce('label'); + + buttonOut._index = i; + buttonsOut.push(buttonOut); + } + + return buttonsOut; +} + +},{"../../lib":122,"../../plots/array_container_defaults":147,"./attributes":102,"./constants":103}],105:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Plots = require('../../plots/plots'); +var Lib = require('../../lib'); +var Color = require('../color'); +var Drawing = require('../drawing'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var anchorUtils = require('../legend/anchor_utils'); + +var constants = require('./constants'); + +module.exports = function draw(gd) { + var fullLayout = gd._fullLayout, + menuData = makeMenuData(fullLayout); + + /* Update menu data is bound to the header-group. + * The items in the header group are always present. + * + * Upon clicking on a header its corresponding button + * data is bound to the button-group. + * + * We draw all headers in one group before all buttons + * so that the buttons *always* appear above the headers. + * + * Note that only one set of buttons are visible at once. + * + * + * + * + * + * + * + * + * + * ... + * + * + * + * + * ... + */ + + // draw update menu container + var menus = fullLayout._infolayer + .selectAll('g.' + constants.containerClassName) + .data(menuData.length > 0 ? [0] : []); + + menus.enter().append('g') + .classed(constants.containerClassName, true) + .style('cursor', 'pointer'); + + menus.exit().remove(); + + // remove push margin object(s) + if(menus.exit().size()) clearPushMargins(gd); + + // return early if no update menus are visible + if(menuData.length === 0) return; + + // join header group + var headerGroups = menus.selectAll('g.' + constants.headerGroupClassName) + .data(menuData, keyFunction); + + headerGroups.enter().append('g') + .classed(constants.headerGroupClassName, true); + + // draw dropdown button container + var gButton = menus.selectAll('g.' + constants.dropdownButtonGroupClassName) + .data([0]); + + gButton.enter().append('g') + .classed(constants.dropdownButtonGroupClassName, true) + .style('pointer-events', 'all'); + + // whenever we add new menu, attach 'state' variable to node + // to keep track of the active menu ('-1' means no menu is active) + // and remove all dropped buttons (if any) + if(headerGroups.enter().size()) { + gButton + .call(removeAllButtons) + .attr(constants.menuIndexAttrName, '-1'); + } + + // remove exiting header, remove dropped buttons and reset margins + headerGroups.exit().each(function(menuOpts) { + d3.select(this).remove(); + + gButton + .call(removeAllButtons) + .attr(constants.menuIndexAttrName, '-1'); + + Plots.autoMargin(gd, constants.autoMarginIdRoot + menuOpts._index); + }); + + // find dimensions before plotting anything (this mutates menuOpts) + for(var i = 0; i < menuData.length; i++) { + var menuOpts = menuData[i]; + findDimensions(gd, menuOpts); + } + + // draw headers! + headerGroups.each(function(menuOpts) { + var gHeader = d3.select(this); + + var _gButton = menuOpts.type === 'dropdown' ? gButton : null; + Plots.manageCommandObserver(gd, menuOpts, menuOpts.buttons, function(data) { + setActive(gd, menuOpts, menuOpts.buttons[data.index], gHeader, _gButton, data.index, true); + }); + + if(menuOpts.type === 'dropdown') { + drawHeader(gd, gHeader, gButton, menuOpts); + + // update buttons if they are dropped + if(areMenuButtonsDropped(gButton, menuOpts)) { + drawButtons(gd, gHeader, gButton, menuOpts); + } + } else { + drawButtons(gd, gHeader, null, menuOpts); + } + + }); +}; + +function makeMenuData(fullLayout) { + var contOpts = fullLayout[constants.name], + menuData = []; + + // Filter visible dropdowns and attach '_index' to each + // fullLayout options object to be used for 'object constancy' + // in the data join key function. + + for(var i = 0; i < contOpts.length; i++) { + var item = contOpts[i]; + + if(item.visible) menuData.push(item); + } + + return menuData; +} + +// Note that '_index' is set at the default step, +// it corresponds to the menu index in the user layout update menu container. +// This is a more 'consistent' field than e.g. the index in the menuData. +function keyFunction(opts) { + return opts._index; +} + +function areMenuButtonsDropped(gButton, menuOpts) { + var droppedIndex = +gButton.attr(constants.menuIndexAttrName); + + return droppedIndex === menuOpts._index; +} + +function drawHeader(gd, gHeader, gButton, menuOpts) { + var header = gHeader.selectAll('g.' + constants.headerClassName) + .data([0]); + + header.enter().append('g') + .classed(constants.headerClassName, true) + .style('pointer-events', 'all'); + + var active = menuOpts.active, + headerOpts = menuOpts.buttons[active] || constants.blankHeaderOpts, + posOpts = { y: menuOpts.pad.t, yPad: 0, x: menuOpts.pad.l, xPad: 0, index: 0 }, + positionOverrides = { + width: menuOpts.headerWidth, + height: menuOpts.headerHeight + }; + + header + .call(drawItem, menuOpts, headerOpts) + .call(setItemPosition, menuOpts, posOpts, positionOverrides); + + // draw drop arrow at the right edge + var arrow = gHeader.selectAll('text.' + constants.headerArrowClassName) + .data([0]); + + arrow.enter().append('text') + .classed(constants.headerArrowClassName, true) + .classed('user-select-none', true) + .attr('text-anchor', 'end') + .call(Drawing.font, menuOpts.font) + .text('▼'); + + arrow.attr({ + x: menuOpts.headerWidth - constants.arrowOffsetX + menuOpts.pad.l, + y: menuOpts.headerHeight / 2 + constants.textOffsetY + menuOpts.pad.t + }); + + header.on('click', function() { + gButton.call(removeAllButtons); + + // if clicked index is same as dropped index => fold + // otherwise => drop buttons associated with header + gButton.attr( + constants.menuIndexAttrName, + areMenuButtonsDropped(gButton, menuOpts) ? '-1' : String(menuOpts._index) + ); + + drawButtons(gd, gHeader, gButton, menuOpts); + }); + + header.on('mouseover', function() { + header.call(styleOnMouseOver); + }); + + header.on('mouseout', function() { + header.call(styleOnMouseOut, menuOpts); + }); + + // translate header group + Lib.setTranslate(gHeader, menuOpts.lx, menuOpts.ly); +} + +function drawButtons(gd, gHeader, gButton, menuOpts) { + // If this is a set of buttons, set pointer events = all since we play + // some minor games with which container is which in order to simplify + // the drawing of *either* buttons or menus + if(!gButton) { + gButton = gHeader; + gButton.attr('pointer-events', 'all'); + } + + var buttonData = (gButton.attr(constants.menuIndexAttrName) !== '-1' || menuOpts.type === 'buttons') ? + menuOpts.buttons : + []; + + var klass = menuOpts.type === 'dropdown' ? constants.dropdownButtonClassName : constants.buttonClassName; + + var buttons = gButton.selectAll('g.' + klass) + .data(buttonData); + + var enter = buttons.enter().append('g') + .classed(klass, true); + + var exit = buttons.exit(); + + if(menuOpts.type === 'dropdown') { + enter.attr('opacity', '0') + .transition() + .attr('opacity', '1'); + + exit.transition() + .attr('opacity', '0') + .remove(); + } else { + exit.remove(); + } + + + var x0 = 0; + var y0 = 0; + + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + + if(menuOpts.type === 'dropdown') { + if(isVertical) { + y0 = menuOpts.headerHeight + constants.gapButtonHeader; + } else { + x0 = menuOpts.headerWidth + constants.gapButtonHeader; + } + } + + if(menuOpts.type === 'dropdown' && menuOpts.direction === 'up') { + y0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openHeight; + } + + if(menuOpts.type === 'dropdown' && menuOpts.direction === 'left') { + x0 = -constants.gapButtonHeader + constants.gapButton - menuOpts.openWidth; + } + + var posOpts = { + x: x0 + menuOpts.pad.l, + y: y0 + menuOpts.pad.t, + yPad: constants.gapButton, + xPad: constants.gapButton, + index: 0, + }; + + buttons.each(function(buttonOpts, buttonIndex) { + var button = d3.select(this); + + button + .call(drawItem, menuOpts, buttonOpts) + .call(setItemPosition, menuOpts, posOpts); + + button.on('click', function() { + setActive(gd, menuOpts, buttonOpts, gHeader, gButton, buttonIndex); + + Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args); + + gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active}); + }); + + button.on('mouseover', function() { + button.call(styleOnMouseOver); + }); + + button.on('mouseout', function() { + button.call(styleOnMouseOut, menuOpts); + buttons.call(styleButtons, menuOpts); + }); + }); + + buttons.call(styleButtons, menuOpts); + + // translate button group + Lib.setTranslate(gButton, menuOpts.lx, menuOpts.ly); +} + +function setActive(gd, menuOpts, buttonOpts, gHeader, gButton, buttonIndex, isSilentUpdate) { + // update 'active' attribute in menuOpts + menuOpts._input.active = menuOpts.active = buttonIndex; + + if(menuOpts.type === 'dropdown') { + // fold up buttons and redraw header + gButton.attr(constants.menuIndexAttrName, '-1'); + + drawHeader(gd, gHeader, gButton, menuOpts); + } + + if(!isSilentUpdate || menuOpts.type === 'buttons') { + drawButtons(gd, gHeader, gButton, menuOpts); + } +} + +function drawItem(item, menuOpts, itemOpts) { + item.call(drawItemRect, menuOpts) + .call(drawItemText, menuOpts, itemOpts); +} + +function drawItemRect(item, menuOpts) { + var rect = item.selectAll('rect') + .data([0]); + + rect.enter().append('rect') + .classed(constants.itemRectClassName, true) + .attr({ + rx: constants.rx, + ry: constants.ry, + 'shape-rendering': 'crispEdges' + }); + + rect.call(Color.stroke, menuOpts.bordercolor) + .call(Color.fill, menuOpts.bgcolor) + .style('stroke-width', menuOpts.borderwidth + 'px'); +} + +function drawItemText(item, menuOpts, itemOpts) { + var text = item.selectAll('text') + .data([0]); + + text.enter().append('text') + .classed(constants.itemTextClassName, true) + .classed('user-select-none', true) + .attr('text-anchor', 'start'); + + text.call(Drawing.font, menuOpts.font) + .text(itemOpts.label) + .call(svgTextUtils.convertToTspans); +} + +function styleButtons(buttons, menuOpts) { + var active = menuOpts.active; + + buttons.each(function(buttonOpts, i) { + var button = d3.select(this); + + if(i === active && menuOpts.showactive) { + button.select('rect.' + constants.itemRectClassName) + .call(Color.fill, constants.activeColor); + } + }); +} + +function styleOnMouseOver(item) { + item.select('rect.' + constants.itemRectClassName) + .call(Color.fill, constants.hoverColor); +} + +function styleOnMouseOut(item, menuOpts) { + item.select('rect.' + constants.itemRectClassName) + .call(Color.fill, menuOpts.bgcolor); +} + +// find item dimensions (this mutates menuOpts) +function findDimensions(gd, menuOpts) { + menuOpts.width1 = 0; + menuOpts.height1 = 0; + menuOpts.heights = []; + menuOpts.widths = []; + menuOpts.totalWidth = 0; + menuOpts.totalHeight = 0; + menuOpts.openWidth = 0; + menuOpts.openHeight = 0; + menuOpts.lx = 0; + menuOpts.ly = 0; + + var fakeButtons = gd._tester.selectAll('g.' + constants.dropdownButtonClassName) + .data(menuOpts.buttons); + + fakeButtons.enter().append('g') + .classed(constants.dropdownButtonClassName, true); + + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + + // loop over fake buttons to find width / height + fakeButtons.each(function(buttonOpts, i) { + var button = d3.select(this); + + button.call(drawItem, menuOpts, buttonOpts); + + var text = button.select('.' + constants.itemTextClassName), + tspans = text.selectAll('tspan'); + + // width is given by max width of all buttons + var tWidth = text.node() && Drawing.bBox(text.node()).width, + wEff = Math.max(tWidth + constants.textPadX, constants.minWidth); + + // height is determined by item text + var tHeight = menuOpts.font.size * constants.fontSizeToHeight, + tLines = tspans[0].length || 1, + hEff = Math.max(tHeight * tLines, constants.minHeight) + constants.textOffsetY; + + hEff = Math.ceil(hEff); + wEff = Math.ceil(wEff); + + // Store per-item sizes since a row of horizontal buttons, for example, + // don't all need to be the same width: + menuOpts.widths[i] = wEff; + menuOpts.heights[i] = hEff; + + // Height and width of individual element: + menuOpts.height1 = Math.max(menuOpts.height1, hEff); + menuOpts.width1 = Math.max(menuOpts.width1, wEff); + + if(isVertical) { + menuOpts.totalWidth = Math.max(menuOpts.totalWidth, wEff); + menuOpts.openWidth = menuOpts.totalWidth; + menuOpts.totalHeight += hEff + constants.gapButton; + menuOpts.openHeight += hEff + constants.gapButton; + } else { + menuOpts.totalWidth += wEff + constants.gapButton; + menuOpts.openWidth += wEff + constants.gapButton; + menuOpts.totalHeight = Math.max(menuOpts.totalHeight, hEff); + menuOpts.openHeight = menuOpts.totalHeight; + } + }); + + if(isVertical) { + menuOpts.totalHeight -= constants.gapButton; + } else { + menuOpts.totalWidth -= constants.gapButton; + } + + + menuOpts.headerWidth = menuOpts.width1 + constants.arrowPadX; + menuOpts.headerHeight = menuOpts.height1; + + if(menuOpts.type === 'dropdown') { + if(isVertical) { + menuOpts.width1 += constants.arrowPadX; + menuOpts.totalHeight = menuOpts.height1; + } else { + menuOpts.totalWidth = menuOpts.width1; + } + menuOpts.totalWidth += constants.arrowPadX; + } + + fakeButtons.remove(); + + var paddedWidth = menuOpts.totalWidth + menuOpts.pad.l + menuOpts.pad.r; + var paddedHeight = menuOpts.totalHeight + menuOpts.pad.t + menuOpts.pad.b; + + var graphSize = gd._fullLayout._size; + menuOpts.lx = graphSize.l + graphSize.w * menuOpts.x; + menuOpts.ly = graphSize.t + graphSize.h * (1 - menuOpts.y); + + var xanchor = 'left'; + if(anchorUtils.isRightAnchor(menuOpts)) { + menuOpts.lx -= paddedWidth; + xanchor = 'right'; + } + if(anchorUtils.isCenterAnchor(menuOpts)) { + menuOpts.lx -= paddedWidth / 2; + xanchor = 'center'; + } + + var yanchor = 'top'; + if(anchorUtils.isBottomAnchor(menuOpts)) { + menuOpts.ly -= paddedHeight; + yanchor = 'bottom'; + } + if(anchorUtils.isMiddleAnchor(menuOpts)) { + menuOpts.ly -= paddedHeight / 2; + yanchor = 'middle'; + } + + menuOpts.totalWidth = Math.ceil(menuOpts.totalWidth); + menuOpts.totalHeight = Math.ceil(menuOpts.totalHeight); + menuOpts.lx = Math.round(menuOpts.lx); + menuOpts.ly = Math.round(menuOpts.ly); + + Plots.autoMargin(gd, constants.autoMarginIdRoot + menuOpts._index, { + x: menuOpts.x, + y: menuOpts.y, + l: paddedWidth * ({right: 1, center: 0.5}[xanchor] || 0), + r: paddedWidth * ({left: 1, center: 0.5}[xanchor] || 0), + b: paddedHeight * ({top: 1, middle: 0.5}[yanchor] || 0), + t: paddedHeight * ({bottom: 1, middle: 0.5}[yanchor] || 0) + }); +} + +// set item positions (mutates posOpts) +function setItemPosition(item, menuOpts, posOpts, overrideOpts) { + overrideOpts = overrideOpts || {}; + var rect = item.select('.' + constants.itemRectClassName), + text = item.select('.' + constants.itemTextClassName), + tspans = text.selectAll('tspan'), + borderWidth = menuOpts.borderwidth, + index = posOpts.index; + + Lib.setTranslate(item, borderWidth + posOpts.x, borderWidth + posOpts.y); + + var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; + + rect.attr({ + x: 0, + y: 0, + width: overrideOpts.width || (isVertical ? menuOpts.width1 : menuOpts.widths[index]), + height: overrideOpts.height || (isVertical ? menuOpts.heights[index] : menuOpts.height1) + }); + + var tHeight = menuOpts.font.size * constants.fontSizeToHeight, + tLines = tspans[0].length || 1, + spanOffset = ((tLines - 1) * tHeight / 4); + + var textAttrs = { + x: constants.textOffsetX, + y: menuOpts.heights[index] / 2 - spanOffset + constants.textOffsetY + }; + + text.attr(textAttrs); + tspans.attr(textAttrs); + + if(isVertical) { + posOpts.y += menuOpts.heights[index] + posOpts.yPad; + } else { + posOpts.x += menuOpts.widths[index] + posOpts.xPad; + } + + posOpts.index++; +} + +function removeAllButtons(gButton) { + gButton.selectAll('g.' + constants.dropdownButtonClassName).remove(); +} + +function clearPushMargins(gd) { + var pushMargins = gd._fullLayout._pushmargin || {}, + keys = Object.keys(pushMargins); + + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + + if(k.indexOf(constants.autoMarginIdRoot) !== -1) { + Plots.autoMargin(gd, k); + } + } +} + +},{"../../lib":122,"../../lib/svg_text_utils":134,"../../plots/plots":186,"../color":27,"../drawing":50,"../legend/anchor_utils":63,"./constants":103,"d3":10}],106:[function(require,module,exports){ +arguments[4][100][0].apply(exports,arguments) +},{"./attributes":102,"./constants":103,"./defaults":104,"./draw":105,"dup":100}],107:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + /** + * Standardize all missing data in calcdata to use undefined + * never null or NaN. + * That way we can use !==undefined, or !== BADNUM, + * to test for real data + */ + BADNUM: undefined, + + /* + * Limit certain operations to well below floating point max value + * to avoid glitches: Make sure that even when you multiply it by the + * number of pixels on a giant screen it still works + */ + FP_SAFE: Number.MAX_VALUE / 10000, + + /* + * conversion of date units to milliseconds + * year and month constants are marked "AVG" + * to remind us that not all years and months + * have the same length + */ + ONEAVGYEAR: 31557600000, // 365.25 days + ONEAVGMONTH: 2629800000, // 1/12 of ONEAVGYEAR + ONEDAY: 86400000, + ONEHOUR: 3600000, + ONEMIN: 60000, + ONESEC: 1000 +}; + +},{}],108:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// N.B. HTML entities are listed without the leading '&' and trailing ';' + +module.exports = { + + entityToUnicode: { + 'mu': 'μ', + 'amp': '&', + 'lt': '<', + 'gt': '>', + 'nbsp': ' ', + 'times': '×', + 'plusmn': '±', + 'deg': '°' + }, + + unicodeToEntity: { + '&': 'amp', + '<': 'lt', + '>': 'gt', + '"': 'quot', + '\'': '#x27', + '\/': '#x2F' + } + +}; + +},{}],109:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +exports.xmlns = 'http://www.w3.org/2000/xmlns/'; +exports.svg = 'http://www.w3.org/2000/svg'; +exports.xlink = 'http://www.w3.org/1999/xlink'; + +// the 'old' d3 quirk got fix in v3.5.7 +// https://github.com/mbostock/d3/commit/a6f66e9dd37f764403fc7c1f26be09ab4af24fed +exports.svgAttrs = { + xmlns: exports.svg, + 'xmlns:xlink': exports.xlink +}; + +},{}],110:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * Export the plotly.js API methods. + */ + +var Plotly = require('./plotly'); + +// package version injected by `npm run preprocess` +exports.version = '1.20.2-d27'; + +// inject promise polyfill +require('es6-promise').polyfill(); + +// inject plot css +require('../build/plotcss'); + +// inject default MathJax config +require('./fonts/mathjax_config'); + +// plot api +exports.plot = Plotly.plot; +exports.newPlot = Plotly.newPlot; +exports.restyle = Plotly.restyle; +exports.relayout = Plotly.relayout; +exports.redraw = Plotly.redraw; +exports.update = Plotly.update; +exports.extendTraces = Plotly.extendTraces; +exports.prependTraces = Plotly.prependTraces; +exports.addTraces = Plotly.addTraces; +exports.deleteTraces = Plotly.deleteTraces; +exports.moveTraces = Plotly.moveTraces; +exports.purge = Plotly.purge; +exports.setPlotConfig = require('./plot_api/set_plot_config'); +exports.register = require('./plot_api/register'); +exports.toImage = require('./plot_api/to_image'); +exports.downloadImage = require('./snapshot/download'); +exports.validate = require('./plot_api/validate'); +exports.addFrames = Plotly.addFrames; +exports.deleteFrames = Plotly.deleteFrames; +exports.animate = Plotly.animate; + +// scatter is the only trace included by default +exports.register(require('./traces/scatter')); + +// register all registrable components modules +exports.register([ + require('./components/legend'), + require('./components/annotations'), + require('./components/shapes'), + require('./components/images'), + require('./components/updatemenus'), + require('./components/sliders'), + require('./components/rangeslider'), + require('./components/rangeselector') +]); + +// plot icons +exports.Icons = require('../build/ploticon'); + +// unofficial 'beta' plot methods, use at your own risk +exports.Plots = Plotly.Plots; +exports.Fx = Plotly.Fx; +exports.Snapshot = require('./snapshot'); +exports.PlotSchema = require('./plot_api/plot_schema'); +exports.Queue = require('./lib/queue'); + +var color = require('./components/color'); + +// Unofficial color defaults override +exports.colorDefaults = color.overrideColorDefaults; + +// export d3 used in the bundle +exports.d3 = require('d3'); + +},{"../build/plotcss":1,"../build/ploticon":2,"./components/annotations":25,"./components/color":27,"./components/images":62,"./components/legend":70,"./components/rangeselector":82,"./components/rangeslider":87,"./components/shapes":94,"./components/sliders":100,"./components/updatemenus":106,"./fonts/mathjax_config":111,"./lib/queue":130,"./plot_api/plot_schema":139,"./plot_api/register":140,"./plot_api/set_plot_config":141,"./plot_api/to_image":143,"./plot_api/validate":144,"./plotly":145,"./snapshot":199,"./snapshot/download":196,"./traces/scatter":244,"d3":10,"es6-promise":11}],111:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* global MathJax:false */ + +/** + * Check and configure MathJax + */ +if(typeof MathJax !== 'undefined') { + exports.MathJax = true; + + MathJax.Hub.Config({ + messageStyle: 'none', + skipStartupTypeset: true, + displayAlign: 'left', + tex2jax: { + inlineMath: [['$', '$'], ['\\(', '\\)']] + } + }); + + MathJax.Hub.Configured(); +} else { + exports.MathJax = false; +} + +},{}],112:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// similar to Lib.mergeArray, but using inside a loop +module.exports = function arrayToCalcItem(traceAttr, calcItem, calcAttr, i) { + if(Array.isArray(traceAttr)) calcItem[calcAttr] = traceAttr[i]; +}; + +},{}],113:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var BADNUM = require('../constants/numerical').BADNUM; + +// precompile these regex's for speed +var FRONTJUNK = /^['"%,$#\s']+/; +var ENDJUNK = /['"%,$#\s']+$/; + +/** + * cleanNumber: remove common leading and trailing cruft + * Always returns either a number or BADNUM. + */ +module.exports = function cleanNumber(v) { + if(typeof v === 'string') { + v = v.replace(FRONTJUNK, '').replace(ENDJUNK, ''); + } + + if(isNumeric(v)) return Number(v); + + return BADNUM; +}; + +},{"../constants/numerical":107,"fast-isnumeric":13}],114:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var tinycolor = require('tinycolor2'); + +var getColorscale = require('../components/colorscale/get_scale'); +var colorscaleNames = Object.keys(require('../components/colorscale/scales')); +var nestedProperty = require('./nested_property'); + +var ID_REGEX = /^([2-9]|[1-9][0-9]+)$/; + +exports.valObjects = { + data_array: { + // You can use *dflt=[] to force said array to exist though. + + + + coerceFunction: function(v, propOut, dflt) { + if(Array.isArray(v)) propOut.set(v); + else if(dflt !== undefined) propOut.set(dflt); + } + }, + enumerated: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(opts.coerceNumber) v = +v; + if(opts.values.indexOf(v) === -1) propOut.set(dflt); + else propOut.set(v); + } + }, + 'boolean': { + + + + coerceFunction: function(v, propOut, dflt) { + if(v === true || v === false) propOut.set(v); + else propOut.set(dflt); + } + }, + number: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(!isNumeric(v) || + (opts.min !== undefined && v < opts.min) || + (opts.max !== undefined && v > opts.max)) { + propOut.set(dflt); + } + else propOut.set(+v); + } + }, + integer: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(v % 1 || !isNumeric(v) || + (opts.min !== undefined && v < opts.min) || + (opts.max !== undefined && v > opts.max)) { + propOut.set(dflt); + } + else propOut.set(+v); + } + }, + string: { + + + // TODO 'values shouldn't be in there (edge case: 'dash' in Scatter) + + coerceFunction: function(v, propOut, dflt, opts) { + if(typeof v !== 'string') { + var okToCoerce = (typeof v === 'number'); + + if(opts.strict === true || !okToCoerce) propOut.set(dflt); + else propOut.set(String(v)); + } + else if(opts.noBlank && !v) propOut.set(dflt); + else propOut.set(v); + } + }, + color: { + + + + coerceFunction: function(v, propOut, dflt) { + if(tinycolor(v).isValid()) propOut.set(v); + else propOut.set(dflt); + } + }, + colorscale: { + + + + coerceFunction: function(v, propOut, dflt) { + propOut.set(getColorscale(v, dflt)); + } + }, + angle: { + + + + coerceFunction: function(v, propOut, dflt) { + if(v === 'auto') propOut.set('auto'); + else if(!isNumeric(v)) propOut.set(dflt); + else { + if(Math.abs(v) > 180) v -= Math.round(v / 360) * 360; + propOut.set(+v); + } + } + }, + subplotid: { + + + + coerceFunction: function(v, propOut, dflt) { + var dlen = dflt.length; + if(typeof v === 'string' && v.substr(0, dlen) === dflt && + ID_REGEX.test(v.substr(dlen))) { + propOut.set(v); + return; + } + propOut.set(dflt); + }, + validateFunction: function(v, opts) { + var dflt = opts.dflt, + dlen = dflt.length; + + if(v === dflt) return true; + if(typeof v !== 'string') return false; + if(v.substr(0, dlen) === dflt && ID_REGEX.test(v.substr(dlen))) { + return true; + } + + return false; + } + }, + flaglist: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(typeof v !== 'string') { + propOut.set(dflt); + return; + } + if((opts.extras || []).indexOf(v) !== -1) { + propOut.set(v); + return; + } + var vParts = v.split('+'), + i = 0; + while(i < vParts.length) { + var vi = vParts[i]; + if(opts.flags.indexOf(vi) === -1 || vParts.indexOf(vi) < i) { + vParts.splice(i, 1); + } + else i++; + } + if(!vParts.length) propOut.set(dflt); + else propOut.set(vParts.join('+')); + } + }, + any: { + + + + coerceFunction: function(v, propOut, dflt) { + if(v === undefined) propOut.set(dflt); + else propOut.set(v); + } + }, + info_array: { + + + + coerceFunction: function(v, propOut, dflt, opts) { + if(!Array.isArray(v)) { + propOut.set(dflt); + return; + } + + var items = opts.items, + vOut = []; + dflt = Array.isArray(dflt) ? dflt : []; + + for(var i = 0; i < items.length; i++) { + exports.coerce(v, vOut, items, '[' + i + ']', dflt[i]); + } + + propOut.set(vOut); + }, + validateFunction: function(v, opts) { + if(!Array.isArray(v)) return false; + + var items = opts.items; + + // when free length is off, input and declared lengths must match + if(!opts.freeLength && v.length !== items.length) return false; + + // valid when all input items are valid + for(var i = 0; i < v.length; i++) { + var isItemValid = exports.validate(v[i], opts.items[i]); + + if(!isItemValid) return false; + } + + return true; + } + } +}; + +/** + * Ensures that container[attribute] has a valid value. + * + * attributes[attribute] is an object with possible keys: + * - valType: data_array, enumerated, boolean, ... as in valObjects + * - values: (enumerated only) array of allowed vals + * - min, max: (number, integer only) inclusive bounds on allowed vals + * either or both may be omitted + * - dflt: if attribute is invalid or missing, use this default + * if dflt is provided as an argument to lib.coerce it takes precedence + * as a convenience, returns the value it finally set + */ +exports.coerce = function(containerIn, containerOut, attributes, attribute, dflt) { + var opts = nestedProperty(attributes, attribute).get(), + propIn = nestedProperty(containerIn, attribute), + propOut = nestedProperty(containerOut, attribute), + v = propIn.get(); + + if(dflt === undefined) dflt = opts.dflt; + + /** + * arrayOk: value MAY be an array, then we do no value checking + * at this point, because it can be more complicated than the + * individual form (eg. some array vals can be numbers, even if the + * single values must be color strings) + */ + if(opts.arrayOk && Array.isArray(v)) { + propOut.set(v); + return v; + } + + exports.valObjects[opts.valType].coerceFunction(v, propOut, dflt, opts); + + return propOut.get(); +}; + +/** + * Variation on coerce + * + * Uses coerce to get attribute value if user input is valid, + * returns attribute default if user input it not valid or + * returns false if there is no user input. + */ +exports.coerce2 = function(containerIn, containerOut, attributes, attribute, dflt) { + var propIn = nestedProperty(containerIn, attribute), + propOut = exports.coerce(containerIn, containerOut, attributes, attribute, dflt); + + return propIn.get() ? propOut : false; +}; + +/* + * Shortcut to coerce the three font attributes + * + * 'coerce' is a lib.coerce wrapper with implied first three arguments + */ +exports.coerceFont = function(coerce, attr, dfltObj) { + var out = {}; + + dfltObj = dfltObj || {}; + + out.family = coerce(attr + '.family', dfltObj.family); + out.size = coerce(attr + '.size', dfltObj.size); + out.color = coerce(attr + '.color', dfltObj.color); + + return out; +}; + +exports.validate = function(value, opts) { + var valObject = exports.valObjects[opts.valType]; + + if(opts.arrayOk && Array.isArray(value)) return true; + + if(valObject.validateFunction) { + return valObject.validateFunction(value, opts); + } + + var failed = {}, + out = failed, + propMock = { set: function(v) { out = v; } }; + + // 'failed' just something mutable that won't be === anything else + + valObject.coerceFunction(value, propMock, failed, opts); + return out !== failed; +}; + +},{"../components/colorscale/get_scale":39,"../components/colorscale/scales":45,"./nested_property":127,"fast-isnumeric":13,"tinycolor2":16}],115:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var logError = require('./loggers').error; + +var constants = require('../constants/numerical'); +var BADNUM = constants.BADNUM; +var ONEDAY = constants.ONEDAY; +var ONEHOUR = constants.ONEHOUR; +var ONEMIN = constants.ONEMIN; +var ONESEC = constants.ONESEC; + +// is an object a javascript date? +exports.isJSDate = function(v) { + return typeof v === 'object' && v !== null && typeof v.getTime === 'function'; +}; + +// The absolute limits of our date-time system +// This is a little weird: we use MIN_MS and MAX_MS in dateTime2ms +// but we use dateTime2ms to calculate them (after defining it!) +var MIN_MS, MAX_MS; + +/** + * dateTime2ms - turn a date object or string s of the form + * YYYY-mm-dd HH:MM:SS.sss into milliseconds (relative to 1970-01-01, + * per javascript standard) + * may truncate after any full field, and sss can be any length + * even >3 digits, though javascript dates truncate to milliseconds + * returns BADNUM if it doesn't find a date + * + * Expanded to support negative years to -9999 but you must always + * give 4 digits, except for 2-digit positive years which we assume are + * near the present time. + * Note that we follow ISO 8601:2004: there *is* a year 0, which + * is 1BC/BCE, and -1===2BC etc. + * + * 2-digit to 4-digit year conversion, where to cut off? + * from http://support.microsoft.com/kb/244664: + * 1930-2029 (the most retro of all...) + * but in my mac chrome from eg. d=new Date(Date.parse('8/19/50')): + * 1950-2049 + * by Java, from http://stackoverflow.com/questions/2024273/: + * now-80 - now+19 + * or FileMaker Pro, from + * http://www.filemaker.com/12help/html/add_view_data.4.21.html: + * now-70 - now+29 + * but python strptime etc, via + * http://docs.python.org/py3k/library/time.html: + * 1969-2068 (super forward-looking, but static, not sliding!) + * + * lets go with now-70 to now+29, and if anyone runs into this problem + * they can learn the hard way not to use 2-digit years, as no choice we + * make now will cover all possibilities. mostly this will all be taken + * care of in initial parsing, should only be an issue for hand-entered data + * currently (2016) this range is: + * 1946-2045 + */ + +exports.dateTime2ms = function(s) { + // first check if s is a date object + if(exports.isJSDate(s)) { + s = Number(s); + if(s >= MIN_MS && s <= MAX_MS) return s; + return BADNUM; + } + // otherwise only accept strings and numbers + if(typeof s !== 'string' && typeof s !== 'number') return BADNUM; + + var y, m, d, h; + // split date and time parts + // TODO: we strip leading/trailing whitespace but not other + // characters like we do for numbers - do we want to? + var datetime = String(s).trim().split(' '); + if(datetime.length > 2) return BADNUM; + + var p = datetime[0].split('-'); // date part + + var CE = true; // common era, ie positive year + if(p[0] === '') { + // first part is blank: year starts with a minus sign + CE = false; + p.splice(0, 1); + } + + var plen = p.length; + if(plen > 3 || (plen !== 3 && datetime[1]) || !plen) return BADNUM; + + // year + if(p[0].length === 4) y = Number(p[0]); + else if(p[0].length === 2) { + if(!CE) return BADNUM; + var yNow = new Date().getFullYear(); + y = ((Number(p[0]) - yNow + 70) % 100 + 200) % 100 + yNow - 70; + } + else return BADNUM; + if(!isNumeric(y)) return BADNUM; + + // javascript takes new Date(0..99,m,d) to mean 1900-1999, so + // to support years 0-99 we need to use setFullYear explicitly + var baseDate = new Date(0, 0, 1); + baseDate.setFullYear(CE ? y : -y); + if(p.length > 1) { + + // month - may be 1 or 2 digits + m = Number(p[1]) - 1; // new Date() uses zero-based months + if(p[1].length > 2 || !(m >= 0 && m <= 11)) return BADNUM; + baseDate.setMonth(m); + + if(p.length > 2) { + + // day - may be 1 or 2 digits + d = Number(p[2]); + if(p[2].length > 2 || !(d >= 1 && d <= 31)) return BADNUM; + baseDate.setDate(d); + + // does that date exist in this month? + if(baseDate.getDate() !== d) return BADNUM; + + if(datetime[1]) { + + p = datetime[1].split(':'); + if(p.length > 3) return BADNUM; + + // hour - may be 1 or 2 digits + h = Number(p[0]); + if(p[0].length > 2 || !p[0].length || !(h >= 0 && h <= 23)) return BADNUM; + baseDate.setHours(h); + + // does that hour exist in this day? (Daylight time!) + // (TODO: remove this check when we move to UTC) + if(baseDate.getHours() !== h) return BADNUM; + + if(p.length > 1) { + d = baseDate.getTime(); + + // minute - must be 2 digits + m = Number(p[1]); + if(p[1].length !== 2 || !(m >= 0 && m <= 59)) return BADNUM; + d += ONEMIN * m; + if(p.length === 2) return d; + + // second (and milliseconds) - must have 2-digit seconds + if(p[2].split('.')[0].length !== 2) return BADNUM; + s = Number(p[2]); + if(!(s >= 0 && s < 60)) return BADNUM; + return d + s * ONESEC; + } + } + } + } + return baseDate.getTime(); +}; + +MIN_MS = exports.MIN_MS = exports.dateTime2ms('-9999'); +MAX_MS = exports.MAX_MS = exports.dateTime2ms('9999-12-31 23:59:59.9999'); + +// is string s a date? (see above) +exports.isDateTime = function(s) { + return (exports.dateTime2ms(s) !== BADNUM); +}; + +// pad a number with zeroes, to given # of digits before the decimal point +function lpad(val, digits) { + return String(val + Math.pow(10, digits)).substr(1); +} + +/** + * Turn ms into string of the form YYYY-mm-dd HH:MM:SS.ssss + * Crop any trailing zeros in time, except never stop right after hours + * (we could choose to crop '-01' from date too but for now we always + * show the whole date) + * Optional range r is the data range that applies, also in ms. + * If rng is big, the later parts of time will be omitted + */ +var NINETYDAYS = 90 * ONEDAY; +var THREEHOURS = 3 * ONEHOUR; +var FIVEMIN = 5 * ONEMIN; +exports.ms2DateTime = function(ms, r) { + if(typeof ms !== 'number' || !(ms >= MIN_MS && ms <= MAX_MS)) return BADNUM; + + if(!r) r = 0; + + var d = new Date(Math.floor(ms)), + dateStr = d3.time.format('%Y-%m-%d')(d), + // <90 days: add hours and minutes - never *only* add hours + h = (r < NINETYDAYS) ? d.getHours() : 0, + m = (r < NINETYDAYS) ? d.getMinutes() : 0, + // <3 hours: add seconds + s = (r < THREEHOURS) ? d.getSeconds() : 0, + // <5 minutes: add ms (plus one extra digit, this is msec*10) + msec10 = (r < FIVEMIN) ? Math.round((d.getMilliseconds() + (((ms % 1) + 1) % 1)) * 10) : 0; + + // include each part that has nonzero data in or after it + if(h || m || s || msec10) { + dateStr += ' ' + lpad(h, 2) + ':' + lpad(m, 2); + if(s || msec10) { + dateStr += ':' + lpad(s, 2); + if(msec10) { + var digits = 4; + while(msec10 % 10 === 0) { + digits -= 1; + msec10 /= 10; + } + dateStr += '.' + lpad(msec10, digits); + } + } + } + return dateStr; +}; + +// normalize date format to date string, in case it starts as +// a Date object or milliseconds +// optional dflt is the return value if cleaning fails +exports.cleanDate = function(v, dflt) { + if(exports.isJSDate(v) || typeof v === 'number') { + // NOTE: if someone puts in a year as a number rather than a string, + // this will mistakenly convert it thinking it's milliseconds from 1970 + // that is: '2012' -> Jan. 1, 2012, but 2012 -> 2012 epoch milliseconds + v = exports.ms2DateTime(+v); + if(!v && dflt !== undefined) return dflt; + } + else if(!exports.isDateTime(v)) { + logError('unrecognized date', v); + return dflt; + } + return v; +}; + +},{"../constants/numerical":107,"./loggers":125,"d3":10,"fast-isnumeric":13}],116:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/* global jQuery:false */ + +var EventEmitter = require('events').EventEmitter; + +var Events = { + + init: function(plotObj) { + + /* + * If we have already instantiated an emitter for this plot + * return early. + */ + if(plotObj._ev instanceof EventEmitter) return plotObj; + + var ev = new EventEmitter(); + var internalEv = new EventEmitter(); + + /* + * Assign to plot._ev while we still live in a land + * where plot is a DOM element with stuff attached to it. + * In the future we can make plot the event emitter itself. + */ + plotObj._ev = ev; + + /* + * Create a second event handler that will manage events *internally*. + * This allows parts of plotly to respond to thing like relayout without + * having to use the user-facing event handler. They cannot peacefully + * coexist on the same handler because a user invoking + * plotObj.removeAllListeners() would detach internal events, breaking + * plotly. + */ + plotObj._internalEv = internalEv; + + /* + * Assign bound methods from the ev to the plot object. These methods + * will reference the 'this' of plot._ev even though they are methods + * of plot. This will keep the event machinery away from the plot object + * which currently is often a DOM element but presents an API that will + * continue to function when plot becomes an emitter. Not all EventEmitter + * methods have been bound to `plot` as some do not currently add value to + * the Plotly event API. + */ + plotObj.on = ev.on.bind(ev); + plotObj.once = ev.once.bind(ev); + plotObj.removeListener = ev.removeListener.bind(ev); + plotObj.removeAllListeners = ev.removeAllListeners.bind(ev); + + /* + * Create funtions for managing internal events. These are *only* triggered + * by the mirroring of external events via the emit function. + */ + plotObj._internalOn = internalEv.on.bind(internalEv); + plotObj._internalOnce = internalEv.once.bind(internalEv); + plotObj._removeInternalListener = internalEv.removeListener.bind(internalEv); + plotObj._removeAllInternalListeners = internalEv.removeAllListeners.bind(internalEv); + + /* + * We must wrap emit to continue to support JQuery events. The idea + * is to check to see if the user is using JQuery events, if they are + * we emit JQuery events to trigger user handlers as well as the EventEmitter + * events. + */ + plotObj.emit = function(event, data) { + if(typeof jQuery !== 'undefined') { + jQuery(plotObj).trigger(event, data); + } + + ev.emit(event, data); + internalEv.emit(event, data); + }; + + return plotObj; + }, + + /* + * This function behaves like jQueries triggerHandler. It calls + * all handlers for a particular event and returns the return value + * of the LAST handler. This function also triggers jQuery's + * triggerHandler for backwards compatibility. + * + * Note: triggerHandler has been recommended for deprecation in v2.0.0, + * so the additional behavior of triggerHandler triggering internal events + * is deliberate excluded in order to avoid reinforcing more usage. + */ + triggerHandler: function(plotObj, event, data) { + var jQueryHandlerValue; + var nodeEventHandlerValue; + /* + * If Jquery exists run all its handlers for this event and + * collect the return value of the LAST handler function + */ + if(typeof jQuery !== 'undefined') { + jQueryHandlerValue = jQuery(plotObj).triggerHandler(event, data); + } + + /* + * Now run all the node style event handlers + */ + var ev = plotObj._ev; + if(!ev) return jQueryHandlerValue; + + var handlers = ev._events[event]; + if(!handlers) return jQueryHandlerValue; + + /* + * handlers can be function or an array of functions + */ + if(typeof handlers === 'function') handlers = [handlers]; + var lastHandler = handlers.pop(); + + /* + * Call all the handlers except the last one. + */ + for(var i = 0; i < handlers.length; i++) { + handlers[i](data); + } + + /* + * Now call the final handler and collect its value + */ + nodeEventHandlerValue = lastHandler(data); + + /* + * Return either the jquery handler value if it exists or the + * nodeEventHandler value. Jquery event value superceeds nodejs + * events for backwards compatability reasons. + */ + return jQueryHandlerValue !== undefined ? jQueryHandlerValue : + nodeEventHandlerValue; + }, + + purge: function(plotObj) { + delete plotObj._ev; + delete plotObj.on; + delete plotObj.once; + delete plotObj.removeListener; + delete plotObj.removeAllListeners; + delete plotObj.emit; + + delete plotObj._ev; + delete plotObj._internalEv; + delete plotObj._internalOn; + delete plotObj._internalOnce; + delete plotObj._removeInternalListener; + delete plotObj._removeAllInternalListeners; + + return plotObj; + } + +}; + +module.exports = Events; + +},{"events":12}],117:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isPlainObject = require('./is_plain_object.js'); +var isArray = Array.isArray; + +function primitivesLoopSplice(source, target) { + var i, value; + for(i = 0; i < source.length; i++) { + value = source[i]; + if(value !== null && typeof(value) === 'object') { + return false; + } + if(value !== void(0)) { + target[i] = value; + } + } + return true; +} + +exports.extendFlat = function() { + return _extend(arguments, false, false, false); +}; + +exports.extendDeep = function() { + return _extend(arguments, true, false, false); +}; + +exports.extendDeepAll = function() { + return _extend(arguments, true, true, false); +}; + +exports.extendDeepNoArrays = function() { + return _extend(arguments, true, false, true); +}; + +/* + * Inspired by https://github.com/justmoon/node-extend/blob/master/index.js + * All credit to the jQuery authors for perfecting this amazing utility. + * + * API difference with jQuery version: + * - No optional boolean (true -> deep extend) first argument, + * use `extendFlat` for first-level only extend and + * use `extendDeep` for a deep extend. + * + * Other differences with jQuery version: + * - Uses a modern (and faster) isPlainObject routine. + * - Expected to work with object {} and array [] arguments only. + * - Does not check for circular structure. + * FYI: jQuery only does a check across one level. + * Warning: this might result in infinite loops. + * + */ +function _extend(inputs, isDeep, keepAllKeys, noArrayCopies) { + var target = inputs[0], + length = inputs.length; + + var input, key, src, copy, copyIsArray, clone, allPrimitives; + + if(length === 2 && isArray(target) && isArray(inputs[1]) && target.length === 0) { + + allPrimitives = primitivesLoopSplice(inputs[1], target); + + if(allPrimitives) { + return target; + } else { + target.splice(0, target.length); // reset target and continue to next block + } + } + + for(var i = 1; i < length; i++) { + input = inputs[i]; + + for(key in input) { + src = target[key]; + copy = input[key]; + + // Stop early and just transfer the array if array copies are disallowed: + if(noArrayCopies && isArray(copy)) { + target[key] = copy; + } + + // recurse if we're merging plain objects or arrays + else if(isDeep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if(copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // never move original objects, clone them + target[key] = _extend([clone, copy], isDeep, keepAllKeys, noArrayCopies); + } + + // don't bring in undefined values, except for extendDeepAll + else if(typeof copy !== 'undefined' || keepAllKeys) { + target[key] = copy; + } + } + } + + return target; +} + +},{"./is_plain_object.js":124}],118:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +/** + * Return news array containing only the unique items + * found in input array. + * + * IMPORTANT: Note that items are considered unique + * if `String({})` is unique. For example; + * + * Lib.filterUnique([ { a: 1 }, { b: 2 } ]) + * + * returns [{ a: 1 }] + * + * and + * + * Lib.filterUnique([ '1', 1 ]) + * + * returns ['1'] + * + * + * @param {array} array base array + * @return {array} new filtered array + */ +module.exports = function filterUnique(array) { + var seen = {}, + out = [], + j = 0; + + for(var i = 0; i < array.length; i++) { + var item = array[i]; + + if(seen[item] !== 1) { + seen[item] = 1; + out[j++] = item; + } + } + + return out; +}; + +},{}],119:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/** Filter out object items with visible !== true + * insider array container. + * + * @param {array of objects} container + * @return {array of objects} of length <= container + * + */ +module.exports = function filterVisible(container) { + var out = []; + + for(var i = 0; i < container.length; i++) { + var item = container[i]; + + if(item.visible === true) out.push(item); + } + + return out; +}; + +},{}],120:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var countryRegex = require('country-regex'); +var Lib = require('../lib'); + + +// make list of all country iso3 ids from at runtime +var countryIds = Object.keys(countryRegex); + +var locationmodeToIdFinder = { + 'ISO-3': Lib.identity, + 'USA-states': Lib.identity, + 'country names': countryNameToISO3 +}; + +exports.locationToFeature = function(locationmode, location, features) { + var locationId = getLocationId(locationmode, location); + + if(locationId) { + for(var i = 0; i < features.length; i++) { + var feature = features[i]; + + if(feature.id === locationId) return feature; + } + + Lib.warn([ + 'Location with id', locationId, + 'does not have a matching topojson feature at this resolution.' + ].join(' ')); + } + + return false; +}; + +function getLocationId(locationmode, location) { + var idFinder = locationmodeToIdFinder[locationmode]; + return idFinder(location); +} + +function countryNameToISO3(countryName) { + for(var i = 0; i < countryIds.length; i++) { + var iso3 = countryIds[i], + regex = new RegExp(countryRegex[iso3]); + + if(regex.test(countryName.toLowerCase())) return iso3; + } + + Lib.warn('Unrecognized country name: ' + countryName + '.'); + + return false; +} + +},{"../lib":122,"country-regex":9}],121:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/** + * Convert calcTrace to GeoJSON 'MultiLineString' coordinate arrays + * + * @param {object} calcTrace + * gd.calcdata item. + * Note that calcTrace[i].lonlat is assumed to be defined + * + * @return {array} + * return line coords array (or array of arrays) + * + */ +exports.calcTraceToLineCoords = function(calcTrace) { + var trace = calcTrace[0].trace, + connectgaps = trace.connectgaps; + + var coords = [], + lineString = []; + + for(var i = 0; i < calcTrace.length; i++) { + var calcPt = calcTrace[i]; + + lineString.push(calcPt.lonlat); + + if(!connectgaps && calcPt.gapAfter && lineString.length > 0) { + coords.push(lineString); + lineString = []; + } + } + + coords.push(lineString); + + return coords; +}; + + +/** + * Make line ('LineString' or 'MultiLineString') GeoJSON + * + * @param {array} coords + * results form calcTraceToLineCoords + * @param {object} trace + * (optional) full trace object to be added on to output + * + * @return {object} out + * GeoJSON object + * + */ +exports.makeLine = function(coords, trace) { + var out = {}; + + if(coords.length === 1) { + out = { + type: 'LineString', + coordinates: coords[0] + }; + } + else { + out = { + type: 'MultiLineString', + coordinates: coords + }; + } + + if(trace) out.trace = trace; + + return out; +}; + +/** + * Make polygon ('Polygon' or 'MultiPolygon') GeoJSON + * + * @param {array} coords + * results form calcTraceToLineCoords + * @param {object} trace + * (optional) full trace object to be added on to output + * + * @return {object} out + * GeoJSON object + */ +exports.makePolygon = function(coords, trace) { + var out = {}; + + if(coords.length === 1) { + out = { + type: 'Polygon', + coordinates: coords + }; + } + else { + var _coords = new Array(coords.length); + + for(var i = 0; i < coords.length; i++) { + _coords[i] = [coords[i]]; + } + + out = { + type: 'MultiPolygon', + coordinates: _coords + }; + } + + if(trace) out.trace = trace; + + return out; +}; + +/** + * Make blank GeoJSON + * + * @return {object} + * Blank GeoJSON object + * + */ +exports.makeBlank = function() { + return { + type: 'Point', + coordinates: [] + }; +}; + +},{}],122:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var lib = module.exports = {}; + +lib.nestedProperty = require('./nested_property'); +lib.isPlainObject = require('./is_plain_object'); +lib.isArray = require('./is_array'); + +var coerceModule = require('./coerce'); +lib.valObjects = coerceModule.valObjects; +lib.coerce = coerceModule.coerce; +lib.coerce2 = coerceModule.coerce2; +lib.coerceFont = coerceModule.coerceFont; +lib.validate = coerceModule.validate; + +var datesModule = require('./dates'); +lib.dateTime2ms = datesModule.dateTime2ms; +lib.isDateTime = datesModule.isDateTime; +lib.ms2DateTime = datesModule.ms2DateTime; +lib.cleanDate = datesModule.cleanDate; +lib.isJSDate = datesModule.isJSDate; +lib.MIN_MS = datesModule.MIN_MS; +lib.MAX_MS = datesModule.MAX_MS; + +var searchModule = require('./search'); +lib.findBin = searchModule.findBin; +lib.sorterAsc = searchModule.sorterAsc; +lib.sorterDes = searchModule.sorterDes; +lib.distinctVals = searchModule.distinctVals; +lib.roundUp = searchModule.roundUp; + +var statsModule = require('./stats'); +lib.aggNums = statsModule.aggNums; +lib.len = statsModule.len; +lib.mean = statsModule.mean; +lib.variance = statsModule.variance; +lib.stdev = statsModule.stdev; +lib.interp = statsModule.interp; + +var matrixModule = require('./matrix'); +lib.init2dArray = matrixModule.init2dArray; +lib.transposeRagged = matrixModule.transposeRagged; +lib.dot = matrixModule.dot; +lib.translationMatrix = matrixModule.translationMatrix; +lib.rotationMatrix = matrixModule.rotationMatrix; +lib.rotationXYMatrix = matrixModule.rotationXYMatrix; +lib.apply2DTransform = matrixModule.apply2DTransform; +lib.apply2DTransform2 = matrixModule.apply2DTransform2; + +var extendModule = require('./extend'); +lib.extendFlat = extendModule.extendFlat; +lib.extendDeep = extendModule.extendDeep; +lib.extendDeepAll = extendModule.extendDeepAll; +lib.extendDeepNoArrays = extendModule.extendDeepNoArrays; + +var loggersModule = require('./loggers'); +lib.log = loggersModule.log; +lib.warn = loggersModule.warn; +lib.error = loggersModule.error; + +lib.notifier = require('./notifier'); + +lib.filterUnique = require('./filter_unique'); +lib.filterVisible = require('./filter_visible'); + + +lib.cleanNumber = require('./clean_number'); + +/** + * swap x and y of the same attribute in container cont + * specify attr with a ? in place of x/y + * you can also swap other things than x/y by providing part1 and part2 + */ +lib.swapAttrs = function(cont, attrList, part1, part2) { + if(!part1) part1 = 'x'; + if(!part2) part2 = 'y'; + for(var i = 0; i < attrList.length; i++) { + var attr = attrList[i], + xp = lib.nestedProperty(cont, attr.replace('?', part1)), + yp = lib.nestedProperty(cont, attr.replace('?', part2)), + temp = xp.get(); + xp.set(yp.get()); + yp.set(temp); + } +}; + +/** + * to prevent event bubbling, in particular text selection during drag. + * see http://stackoverflow.com/questions/5429827/ + * how-can-i-prevent-text-element-selection-with-cursor-drag + * for maximum effect use: + * return pauseEvent(e); + */ +lib.pauseEvent = function(e) { + if(e.stopPropagation) e.stopPropagation(); + if(e.preventDefault) e.preventDefault(); + e.cancelBubble = true; + return false; +}; + +// constrain - restrict a number v to be between v0 and v1 +lib.constrain = function(v, v0, v1) { + if(v0 > v1) return Math.max(v1, Math.min(v0, v)); + return Math.max(v0, Math.min(v1, v)); +}; + +/** + * do two bounding boxes from getBoundingClientRect, + * ie {left,right,top,bottom,width,height}, overlap? + * takes optional padding pixels + */ +lib.bBoxIntersect = function(a, b, pad) { + pad = pad || 0; + return (a.left <= b.right + pad && + b.left <= a.right + pad && + a.top <= b.bottom + pad && + b.top <= a.bottom + pad); +}; + +// minor convenience/performance booster for d3... +lib.identity = function(d) { return d; }; + +// minor convenience helper +lib.noop = function() {}; + +// random string generator +lib.randstr = function randstr(existing, bits, base) { + /* + * Include number of bits, the base of the string you want + * and an optional array of existing strings to avoid. + */ + if(!base) base = 16; + if(bits === undefined) bits = 24; + if(bits <= 0) return '0'; + + var digits = Math.log(Math.pow(2, bits)) / Math.log(base), + res = '', + i, + b, + x; + + for(i = 2; digits === Infinity; i *= 2) { + digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; + } + + var rem = digits - Math.floor(digits); + + for(i = 0; i < Math.floor(digits); i++) { + x = Math.floor(Math.random() * base).toString(base); + res = x + res; + } + + if(rem) { + b = Math.pow(base, rem); + x = Math.floor(Math.random() * b).toString(base); + res = x + res; + } + + var parsed = parseInt(res, base); + if((existing && (existing.indexOf(res) > -1)) || + (parsed !== Infinity && parsed >= Math.pow(2, bits))) { + return randstr(existing, bits, base); + } + else return res; +}; + +lib.OptionControl = function(opt, optname) { + /* + * An environment to contain all option setters and + * getters that collectively modify opts. + * + * You can call up opts from any function in new object + * as this.optname || this.opt + * + * See FitOpts for example of usage + */ + if(!opt) opt = {}; + if(!optname) optname = 'opt'; + + var self = {}; + self.optionList = []; + + self._newoption = function(optObj) { + optObj[optname] = opt; + self[optObj.name] = optObj; + self.optionList.push(optObj); + }; + + self['_' + optname] = opt; + return self; +}; + +/** + * lib.smooth: smooth arrayIn by convolving with + * a hann window with given full width at half max + * bounce the ends in, so the output has the same length as the input + */ +lib.smooth = function(arrayIn, FWHM) { + FWHM = Math.round(FWHM) || 0; // only makes sense for integers + if(FWHM < 2) return arrayIn; + + var alen = arrayIn.length, + alen2 = 2 * alen, + wlen = 2 * FWHM - 1, + w = new Array(wlen), + arrayOut = new Array(alen), + i, + j, + k, + v; + + // first make the window array + for(i = 0; i < wlen; i++) { + w[i] = (1 - Math.cos(Math.PI * (i + 1) / FWHM)) / (2 * FWHM); + } + + // now do the convolution + for(i = 0; i < alen; i++) { + v = 0; + for(j = 0; j < wlen; j++) { + k = i + j + 1 - FWHM; + + // multibounce + if(k < -alen) k -= alen2 * Math.round(k / alen2); + else if(k >= alen2) k -= alen2 * Math.floor(k / alen2); + + // single bounce + if(k < 0) k = - 1 - k; + else if(k >= alen) k = alen2 - 1 - k; + + v += arrayIn[k] * w[j]; + } + arrayOut[i] = v; + } + + return arrayOut; +}; + +/** + * syncOrAsync: run a sequence of functions synchronously + * as long as its returns are not promises (ie have no .then) + * includes one argument arg to send to all functions... + * this is mainly just to prevent us having to make wrapper functions + * when the only purpose of the wrapper is to reference gd + * and a final step to be executed at the end + * TODO: if there's an error and everything is sync, + * this doesn't happen yet because we want to make sure + * that it gets reported + */ +lib.syncOrAsync = function(sequence, arg, finalStep) { + var ret, fni; + + function continueAsync() { + return lib.syncOrAsync(sequence, arg, finalStep); + } + + while(sequence.length) { + fni = sequence.splice(0, 1)[0]; + ret = fni(arg); + + if(ret && ret.then) { + return ret.then(continueAsync) + .then(undefined, lib.promiseError); + } + } + + return finalStep && finalStep(arg); +}; + + +/** + * Helper to strip trailing slash, from + * http://stackoverflow.com/questions/6680825/return-string-without-trailing-slash + */ +lib.stripTrailingSlash = function(str) { + if(str.substr(-1) === '/') return str.substr(0, str.length - 1); + return str; +}; + +lib.noneOrAll = function(containerIn, containerOut, attrList) { + /** + * some attributes come together, so if you have one of them + * in the input, you should copy the default values of the others + * to the input as well. + */ + if(!containerIn) return; + + var hasAny = false, + hasAll = true, + i, + val; + + for(i = 0; i < attrList.length; i++) { + val = containerIn[attrList[i]]; + if(val !== undefined && val !== null) hasAny = true; + else hasAll = false; + } + + if(hasAny && !hasAll) { + for(i = 0; i < attrList.length; i++) { + containerIn[attrList[i]] = containerOut[attrList[i]]; + } + } +}; + +/** + * Push array with unique items + * + * @param {array} array + * array to be filled + * @param {any} item + * item to be or not to be inserted + * @return {array} + * ref to array (now possibly containing one more item) + * + */ +lib.pushUnique = function(array, item) { + if(item && array.indexOf(item) === -1) array.push(item); + + return array; +}; + +lib.mergeArray = function(traceAttr, cd, cdAttr) { + if(Array.isArray(traceAttr)) { + var imax = Math.min(traceAttr.length, cd.length); + for(var i = 0; i < imax; i++) cd[i][cdAttr] = traceAttr[i]; + } +}; + +/** + * modified version of jQuery's extend to strip out private objs and functions, + * and cut arrays down to first or 1 elements + * because extend-like algorithms are hella slow + * obj2 is assumed to already be clean of these things (including no arrays) + */ +lib.minExtend = function(obj1, obj2) { + var objOut = {}; + if(typeof obj2 !== 'object') obj2 = {}; + var arrayLen = 3, + keys = Object.keys(obj1), + i, + k, + v; + for(i = 0; i < keys.length; i++) { + k = keys[i]; + v = obj1[k]; + if(k.charAt(0) === '_' || typeof v === 'function') continue; + else if(k === 'module') objOut[k] = v; + else if(Array.isArray(v)) objOut[k] = v.slice(0, arrayLen); + else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]); + else objOut[k] = v; + } + + keys = Object.keys(obj2); + for(i = 0; i < keys.length; i++) { + k = keys[i]; + v = obj2[k]; + if(typeof v !== 'object' || !(k in objOut) || typeof objOut[k] !== 'object') { + objOut[k] = v; + } + } + + return objOut; +}; + +lib.titleCase = function(s) { + return s.charAt(0).toUpperCase() + s.substr(1); +}; + +lib.containsAny = function(s, fragments) { + for(var i = 0; i < fragments.length; i++) { + if(s.indexOf(fragments[i]) !== -1) return true; + } + return false; +}; + +// get the parent Plotly plot of any element. Whoo jquery-free tree climbing! +lib.getPlotDiv = function(el) { + for(; el && el.removeAttribute; el = el.parentNode) { + if(lib.isPlotDiv(el)) return el; + } +}; + +lib.isPlotDiv = function(el) { + var el3 = d3.select(el); + return el3.node() instanceof HTMLElement && + el3.size() && + el3.classed('js-plotly-plot'); +}; + +lib.removeElement = function(el) { + var elParent = el && el.parentNode; + if(elParent) elParent.removeChild(el); +}; + +/** + * for dynamically adding style rules + * makes one stylesheet that contains all rules added + * by all calls to this function + */ +lib.addStyleRule = function(selector, styleString) { + if(!lib.styleSheet) { + var style = document.createElement('style'); + // WebKit hack :( + style.appendChild(document.createTextNode('')); + document.head.appendChild(style); + lib.styleSheet = style.sheet; + } + var styleSheet = lib.styleSheet; + + if(styleSheet.insertRule) { + styleSheet.insertRule(selector + '{' + styleString + '}', 0); + } + else if(styleSheet.addRule) { + styleSheet.addRule(selector, styleString, 0); + } + else lib.warn('addStyleRule failed'); +}; + +lib.getTranslate = function(element) { + + var re = /.*\btranslate\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/, + getter = element.attr ? 'attr' : 'getAttribute', + transform = element[getter]('transform') || ''; + + var translate = transform.replace(re, function(match, p1, p2) { + return [p1, p2].join(' '); + }) + .split(' '); + + return { + x: +translate[0] || 0, + y: +translate[1] || 0 + }; +}; + +lib.setTranslate = function(element, x, y) { + + var re = /(\btranslate\(.*?\);?)/, + getter = element.attr ? 'attr' : 'getAttribute', + setter = element.attr ? 'attr' : 'setAttribute', + transform = element[getter]('transform') || ''; + + x = x || 0; + y = y || 0; + + transform = transform.replace(re, '').trim(); + transform += ' translate(' + x + ', ' + y + ')'; + transform = transform.trim(); + + element[setter]('transform', transform); + + return transform; +}; + +lib.getScale = function(element) { + + var re = /.*\bscale\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/, + getter = element.attr ? 'attr' : 'getAttribute', + transform = element[getter]('transform') || ''; + + var translate = transform.replace(re, function(match, p1, p2) { + return [p1, p2].join(' '); + }) + .split(' '); + + return { + x: +translate[0] || 1, + y: +translate[1] || 1 + }; +}; + +lib.setScale = function(element, x, y) { + + var re = /(\bscale\(.*?\);?)/, + getter = element.attr ? 'attr' : 'getAttribute', + setter = element.attr ? 'attr' : 'setAttribute', + transform = element[getter]('transform') || ''; + + x = x || 1; + y = y || 1; + + transform = transform.replace(re, '').trim(); + transform += ' scale(' + x + ', ' + y + ')'; + transform = transform.trim(); + + element[setter]('transform', transform); + + return transform; +}; + +lib.setPointGroupScale = function(selection, x, y) { + var t, scale, re; + + x = x || 1; + y = y || 1; + + if(x === 1 && y === 1) { + scale = ''; + } else { + // The same scale transform for every point: + scale = ' scale(' + x + ',' + y + ')'; + } + + // A regex to strip any existing scale: + re = /\s*sc.*/; + + selection.each(function() { + // Get the transform: + t = (this.getAttribute('transform') || '').replace(re, ''); + t += scale; + t = t.trim(); + + // Append the scale transform + this.setAttribute('transform', t); + }); + + return scale; +}; + +lib.isIE = function() { + return typeof window.navigator.msSaveBlob !== 'undefined'; +}; + + +/** + * Converts a string path to an object. + * + * When given a string containing an array element, it will create a `null` + * filled array of the given size. + * + * @example + * lib.objectFromPath('nested.test[2].path', 'value'); + * // returns { nested: { test: [null, null, { path: 'value' }]} + * + * @param {string} path to nested value + * @param {*} any value to be set + * + * @return {Object} the constructed object with a full nested path + */ +lib.objectFromPath = function(path, value) { + var keys = path.split('.'), + tmpObj, + obj = tmpObj = {}; + + for(var i = 0; i < keys.length; i++) { + var key = keys[i]; + var el = null; + + var parts = keys[i].match(/(.*)\[([0-9]+)\]/); + + if(parts) { + key = parts[1]; + el = parts[2]; + + tmpObj = tmpObj[key] = []; + + if(i === keys.length - 1) { + tmpObj[el] = value; + } else { + tmpObj[el] = {}; + } + + tmpObj = tmpObj[el]; + } else { + + if(i === keys.length - 1) { + tmpObj[key] = value; + } else { + tmpObj[key] = {}; + } + + tmpObj = tmpObj[key]; + } + } + + return obj; +}; + +/** + * Iterate through an object in-place, converting dotted properties to objects. + * + * Examples: + * + * lib.expandObjectPaths({'nested.test.path': 'value'}); + * => { nested: { test: {path: 'value'}}} + * + * It also handles array notation, e.g.: + * + * lib.expandObjectPaths({'foo[1].bar': 'value'}); + * => { foo: [null, {bar: value}] } + * + * It handles merges the results when two properties are specified in parallel: + * + * lib.expandObjectPaths({'foo[1].bar': 10, 'foo[0].bar': 20}); + * => { foo: [{bar: 10}, {bar: 20}] } + * + * It does NOT, however, merge mulitple mutliply-nested arrays:: + * + * lib.expandObjectPaths({'marker[1].range[1]': 5, 'marker[1].range[0]': 4}) + * => { marker: [null, {range: 4}] } + */ + +// Store this to avoid recompiling regex on *every* prop since this may happen many +// many times for animations. Could maybe be inside the function. Not sure about +// scoping vs. recompilation tradeoff, but at least it's not just inlining it into +// the inner loop. +var dottedPropertyRegex = /^([^\[\.]+)\.(.+)?/; +var indexedPropertyRegex = /^([^\.]+)\[([0-9]+)\](\.)?(.+)?/; + +lib.expandObjectPaths = function(data) { + var match, key, prop, datum, idx, dest, trailingPath; + if(typeof data === 'object' && !Array.isArray(data)) { + for(key in data) { + if(data.hasOwnProperty(key)) { + if((match = key.match(dottedPropertyRegex))) { + datum = data[key]; + prop = match[1]; + + delete data[key]; + + data[prop] = lib.extendDeepNoArrays(data[prop] || {}, lib.objectFromPath(key, lib.expandObjectPaths(datum))[prop]); + } else if((match = key.match(indexedPropertyRegex))) { + datum = data[key]; + + prop = match[1]; + idx = parseInt(match[2]); + + delete data[key]; + + data[prop] = data[prop] || []; + + if(match[3] === '.') { + // This is the case where theere are subsequent properties into which + // we must recurse, e.g. transforms[0].value + trailingPath = match[4]; + dest = data[prop][idx] = data[prop][idx] || {}; + + // NB: Extend deep no arrays prevents this from working on multiple + // nested properties in the same object, e.g. + // + // { + // foo[0].bar[1].range + // foo[0].bar[0].range + // } + // + // In this case, the extendDeepNoArrays will overwrite one array with + // the other, so that both properties *will not* be present in the + // result. Fixing this would require a more intelligent tracking + // of changes and merging than extendDeepNoArrays currently accomplishes. + lib.extendDeepNoArrays(dest, lib.objectFromPath(trailingPath, lib.expandObjectPaths(datum))); + } else { + // This is the case where this property is the end of the line, + // e.g. xaxis.range[0] + data[prop][idx] = lib.expandObjectPaths(datum); + } + } else { + data[key] = lib.expandObjectPaths(data[key]); + } + } + } + } + + return data; +}; + +/** + * Converts value to string separated by the provided separators. + * + * @example + * lib.numSeparate(2016, '.,'); + * // returns '2016' + * + * @example + * lib.numSeparate(3000, '.,', true); + * // returns '3,000' + * + * @example + * lib.numSeparate(1234.56, '|,') + * // returns '1,234|56' + * + * @param {string|number} value the value to be converted + * @param {string} separators string of decimal, then thousands separators + * @param {boolean} separatethousands boolean, 4-digit integers are separated if true + * + * @return {string} the value that has been separated + */ +lib.numSeparate = function(value, separators, separatethousands) { + if(!separatethousands) separatethousands = false; + + if(typeof separators !== 'string' || separators.length === 0) { + throw new Error('Separator string required for formatting!'); + } + + if(typeof value === 'number') { + value = String(value); + } + + var thousandsRe = /(\d+)(\d{3})/, + decimalSep = separators.charAt(0), + thouSep = separators.charAt(1); + + var x = value.split('.'), + x1 = x[0], + x2 = x.length > 1 ? decimalSep + x[1] : ''; + + // Years are ignored for thousands separators + if(thouSep && (x.length > 1 || x1.length > 4 || separatethousands)) { + while(thousandsRe.test(x1)) { + x1 = x1.replace(thousandsRe, '$1' + thouSep + '$2'); + } + } + + return x1 + x2; +}; + +},{"./clean_number":113,"./coerce":114,"./dates":115,"./extend":117,"./filter_unique":118,"./filter_visible":119,"./is_array":123,"./is_plain_object":124,"./loggers":125,"./matrix":126,"./nested_property":127,"./notifier":128,"./search":131,"./stats":133,"d3":10}],123:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/** + * Return true for arrays, whether they're untyped or not. + */ +module.exports = function isArray(a) { + return Array.isArray(a) || ArrayBuffer.isView(a); +}; + +},{}],124:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// more info: http://stackoverflow.com/questions/18531624/isplainobject-thing +module.exports = function isPlainObject(obj) { + + // We need to be a little less strict in the `imagetest` container because + // of how async image requests are handled. + // + // N.B. isPlainObject(new Constructor()) will return true in `imagetest` + if(window && window.process && window.process.versions) { + return Object.prototype.toString.call(obj) === '[object Object]'; + } + + return ( + Object.prototype.toString.call(obj) === '[object Object]' && + Object.getPrototypeOf(obj) === Object.prototype + ); +}; + +},{}],125:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* eslint-disable no-console */ + +var config = require('../plot_api/plot_config'); + +var loggers = module.exports = {}; + +/** + * ------------------------------------------ + * debugging tools + * ------------------------------------------ + */ + +loggers.log = function() { + if(config.logging > 1) { + var messages = ['LOG:']; + + for(var i = 0; i < arguments.length; i++) { + messages.push(arguments[i]); + } + + if(console.trace) { + console.trace.apply(console, messages); + } else { + console.log.apply(console, messages); + } + } +}; + +loggers.warn = function() { + if(config.logging > 0) { + var messages = ['WARN:']; + + for(var i = 0; i < arguments.length; i++) { + messages.push(arguments[i]); + } + + if(console.trace) { + console.trace.apply(console, messages); + } else { + console.log.apply(console, messages); + } + } +}; + +loggers.error = function() { + if(config.logging > 0) { + var messages = ['ERROR:']; + + for(var i = 0; i < arguments.length; i++) { + messages.push(arguments[i]); + } + + console.error.apply(console, arguments); + } +}; + +},{"../plot_api/plot_config":138}],126:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +exports.init2dArray = function(rowLength, colLength) { + var array = new Array(rowLength); + for(var i = 0; i < rowLength; i++) array[i] = new Array(colLength); + return array; +}; + +/** + * transpose a (possibly ragged) 2d array z. inspired by + * http://stackoverflow.com/questions/17428587/ + * transposing-a-2d-array-in-javascript + */ +exports.transposeRagged = function(z) { + var maxlen = 0, + zlen = z.length, + i, + j; + // Maximum row length: + for(i = 0; i < zlen; i++) maxlen = Math.max(maxlen, z[i].length); + + var t = new Array(maxlen); + for(i = 0; i < maxlen; i++) { + t[i] = new Array(zlen); + for(j = 0; j < zlen; j++) t[i][j] = z[j][i]; + } + + return t; +}; + +// our own dot function so that we don't need to include numeric +exports.dot = function(x, y) { + if(!(x.length && y.length) || x.length !== y.length) return null; + + var len = x.length, + out, + i; + + if(x[0].length) { + // mat-vec or mat-mat + out = new Array(len); + for(i = 0; i < len; i++) out[i] = exports.dot(x[i], y); + } + else if(y[0].length) { + // vec-mat + var yTranspose = exports.transposeRagged(y); + out = new Array(yTranspose.length); + for(i = 0; i < yTranspose.length; i++) out[i] = exports.dot(x, yTranspose[i]); + } + else { + // vec-vec + out = 0; + for(i = 0; i < len; i++) out += x[i] * y[i]; + } + + return out; +}; + +// translate by (x,y) +exports.translationMatrix = function(x, y) { + return [[1, 0, x], [0, 1, y], [0, 0, 1]]; +}; + +// rotate by alpha around (0,0) +exports.rotationMatrix = function(alpha) { + var a = alpha * Math.PI / 180; + return [[Math.cos(a), -Math.sin(a), 0], + [Math.sin(a), Math.cos(a), 0], + [0, 0, 1]]; +}; + +// rotate by alpha around (x,y) +exports.rotationXYMatrix = function(a, x, y) { + return exports.dot( + exports.dot(exports.translationMatrix(x, y), + exports.rotationMatrix(a)), + exports.translationMatrix(-x, -y)); +}; + +// applies a 2D transformation matrix to either x and y params or an [x,y] array +exports.apply2DTransform = function(transform) { + return function() { + var args = arguments; + if(args.length === 3) { + args = args[0]; + }// from map + var xy = arguments.length === 1 ? args[0] : [args[0], args[1]]; + return exports.dot(transform, [xy[0], xy[1], 1]).slice(0, 2); + }; +}; + +// applies a 2D transformation matrix to an [x1,y1,x2,y2] array (to transform a segment) +exports.apply2DTransform2 = function(transform) { + var at = exports.apply2DTransform(transform); + return function(xys) { + return at(xys.slice(0, 2)).concat(at(xys.slice(2, 4))); + }; +}; + +},{}],127:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var isArray = require('./is_array'); + +/** + * convert a string s (such as 'xaxis.range[0]') + * representing a property of nested object into set and get methods + * also return the string and object so we don't have to keep track of them + * allows [-1] for an array index, to set a property inside all elements + * of an array + * eg if obj = {arr: [{a: 1}, {a: 2}]} + * you can do p = nestedProperty(obj, 'arr[-1].a') + * but you cannot set the array itself this way, to do that + * just set the whole array. + * eg if obj = {arr: [1, 2, 3]} + * you can't do nestedProperty(obj, 'arr[-1]').set(5) + * but you can do nestedProperty(obj, 'arr').set([5, 5, 5]) + */ +module.exports = function nestedProperty(container, propStr) { + if(isNumeric(propStr)) propStr = String(propStr); + else if(typeof propStr !== 'string' || + propStr.substr(propStr.length - 4) === '[-1]') { + throw 'bad property string'; + } + + var j = 0, + propParts = propStr.split('.'), + indexed, + indices, + i; + + // check for parts of the nesting hierarchy that are numbers (ie array elements) + while(j < propParts.length) { + // look for non-bracket chars, then any number of [##] blocks + indexed = String(propParts[j]).match(/^([^\[\]]*)((\[\-?[0-9]*\])+)$/); + if(indexed) { + if(indexed[1]) propParts[j] = indexed[1]; + // allow propStr to start with bracketed array indices + else if(j === 0) propParts.splice(0, 1); + else throw 'bad property string'; + + indices = indexed[2] + .substr(1, indexed[2].length - 2) + .split(']['); + + for(i = 0; i < indices.length; i++) { + j++; + propParts.splice(j, 0, Number(indices[i])); + } + } + j++; + } + + if(typeof container !== 'object') { + return badContainer(container, propStr, propParts); + } + + return { + set: npSet(container, propParts), + get: npGet(container, propParts), + astr: propStr, + parts: propParts, + obj: container + }; +}; + +function npGet(cont, parts) { + return function() { + var curCont = cont, + curPart, + allSame, + out, + i, + j; + + for(i = 0; i < parts.length - 1; i++) { + curPart = parts[i]; + if(curPart === -1) { + allSame = true; + out = []; + for(j = 0; j < curCont.length; j++) { + out[j] = npGet(curCont[j], parts.slice(i + 1))(); + if(out[j] !== out[0]) allSame = false; + } + return allSame ? out[0] : out; + } + if(typeof curPart === 'number' && !isArray(curCont)) { + return undefined; + } + curCont = curCont[curPart]; + if(typeof curCont !== 'object' || curCont === null) { + return undefined; + } + } + + // only hit this if parts.length === 1 + if(typeof curCont !== 'object' || curCont === null) return undefined; + + out = curCont[parts[i]]; + if(out === null) return undefined; + return out; + }; +} + +/* + * Check known non-data-array arrays (containers). Data arrays only contain scalars, + * so parts[end] values, such as -1 or n, indicate we are not dealing with a dataArray. + * The ONLY case we are looking for is where the entire array is selected, parts[end] === 'x' + * AND the replacement value is an array. + */ +function isDataArray(val, key) { + + var containers = ['annotations', 'shapes', 'range', 'domain', 'buttons'], + isNotAContainer = containers.indexOf(key) === -1; + + return isArray(val) && isNotAContainer; +} + +function npSet(cont, parts) { + return function(val) { + var curCont = cont, + containerLevels = [cont], + toDelete = emptyObj(val) && !isDataArray(val, parts[parts.length - 1]), + curPart, + i; + + for(i = 0; i < parts.length - 1; i++) { + curPart = parts[i]; + + if(typeof curPart === 'number' && !isArray(curCont)) { + throw 'array index but container is not an array'; + } + + // handle special -1 array index + if(curPart === -1) { + toDelete = !setArrayAll(curCont, parts.slice(i + 1), val); + if(toDelete) break; + else return; + } + + if(!checkNewContainer(curCont, curPart, parts[i + 1], toDelete)) { + break; + } + + curCont = curCont[curPart]; + + if(typeof curCont !== 'object' || curCont === null) { + throw 'container is not an object'; + } + + containerLevels.push(curCont); + } + + if(toDelete) { + if(i === parts.length - 1) delete curCont[parts[i]]; + pruneContainers(containerLevels); + } + else curCont[parts[i]] = val; + }; +} + +// handle special -1 array index +function setArrayAll(containerArray, innerParts, val) { + var arrayVal = isArray(val), + allSet = true, + thisVal = val, + deleteThis = arrayVal ? false : emptyObj(val), + firstPart = innerParts[0], + i; + + for(i = 0; i < containerArray.length; i++) { + if(arrayVal) { + thisVal = val[i % val.length]; + deleteThis = emptyObj(thisVal); + } + if(deleteThis) allSet = false; + if(!checkNewContainer(containerArray, i, firstPart, deleteThis)) { + continue; + } + npSet(containerArray[i], innerParts)(thisVal); + } + return allSet; +} + +/** + * make new sub-container as needed. + * returns false if there's no container and none is needed + * because we're only deleting an attribute + */ +function checkNewContainer(container, part, nextPart, toDelete) { + if(container[part] === undefined) { + if(toDelete) return false; + + if(typeof nextPart === 'number') container[part] = []; + else container[part] = {}; + } + return true; +} + +function pruneContainers(containerLevels) { + var i, + j, + curCont, + keys, + remainingKeys; + for(i = containerLevels.length - 1; i >= 0; i--) { + curCont = containerLevels[i]; + remainingKeys = false; + if(isArray(curCont)) { + for(j = curCont.length - 1; j >= 0; j--) { + if(emptyObj(curCont[j])) { + if(remainingKeys) curCont[j] = undefined; + else curCont.pop(); + } + else remainingKeys = true; + } + } + else if(typeof curCont === 'object' && curCont !== null) { + keys = Object.keys(curCont); + remainingKeys = false; + for(j = keys.length - 1; j >= 0; j--) { + if(emptyObj(curCont[keys[j]]) && !isDataArray(curCont[keys[j]], keys[j])) delete curCont[keys[j]]; + else remainingKeys = true; + } + } + if(remainingKeys) return; + } +} + +function emptyObj(obj) { + if(obj === undefined || obj === null) return true; + if(typeof obj !== 'object') return false; // any plain value + if(isArray(obj)) return !obj.length; // [] + return !Object.keys(obj).length; // {} +} + +function badContainer(container, propStr, propParts) { + return { + set: function() { throw 'bad container'; }, + get: function() {}, + astr: propStr, + parts: propParts, + obj: container + }; +} + +},{"./is_array":123,"fast-isnumeric":13}],128:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var NOTEDATA = []; + +/** + * notifier + * @param {String} text The person's user name + * @param {Number} [delay=1000] The delay time in milliseconds + * or 'long' which provides 2000 ms delay time. + * @return {undefined} this function does not return a value + */ +module.exports = function(text, displayLength) { + if(NOTEDATA.indexOf(text) !== -1) return; + + NOTEDATA.push(text); + + var ts = 1000; + if(isNumeric(displayLength)) ts = displayLength; + else if(displayLength === 'long') ts = 3000; + + var notifierContainer = d3.select('body') + .selectAll('.plotly-notifier') + .data([0]); + notifierContainer.enter() + .append('div') + .classed('plotly-notifier', true); + + var notes = notifierContainer.selectAll('.notifier-note').data(NOTEDATA); + + function killNote(transition) { + transition + .duration(700) + .style('opacity', 0) + .each('end', function(thisText) { + var thisIndex = NOTEDATA.indexOf(thisText); + if(thisIndex !== -1) NOTEDATA.splice(thisIndex, 1); + d3.select(this).remove(); + }); + } + + notes.enter().append('div') + .classed('notifier-note', true) + .style('opacity', 0) + .each(function(thisText) { + var note = d3.select(this); + + note.append('button') + .classed('notifier-close', true) + .html('×') + .on('click', function() { + note.transition().call(killNote); + }); + + note.append('p').html(thisText); + + note.transition() + .duration(700) + .style('opacity', 1) + .transition() + .delay(ts) + .call(killNote); + }); +}; + +},{"d3":10,"fast-isnumeric":13}],129:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var dot = require('./matrix').dot; + +var polygon = module.exports = {}; + +/** + * Turn an array of [x, y] pairs into a polygon object + * that can test if points are inside it + * + * @param ptsIn Array of [x, y] pairs + * + * @returns polygon Object {xmin, xmax, ymin, ymax, pts, contains} + * (x|y)(min|max) are the bounding rect of the polygon + * pts is the original array, with the first pair repeated at the end + * contains is a function: (pt, omitFirstEdge) + * pt is the [x, y] pair to test + * omitFirstEdge truthy means points exactly on the first edge don't + * count. This is for use adding one polygon to another so we + * don't double-count the edge where they meet. + * returns boolean: is pt inside the polygon (including on its edges) + */ +polygon.tester = function tester(ptsIn) { + var pts = ptsIn.slice(), + xmin = pts[0][0], + xmax = xmin, + ymin = pts[0][1], + ymax = ymin; + + pts.push(pts[0]); + for(var i = 1; i < pts.length; i++) { + xmin = Math.min(xmin, pts[i][0]); + xmax = Math.max(xmax, pts[i][0]); + ymin = Math.min(ymin, pts[i][1]); + ymax = Math.max(ymax, pts[i][1]); + } + + // do we have a rectangle? Handle this here, so we can use the same + // tester for the rectangular case without sacrificing speed + + var isRect = false, + rectFirstEdgeTest; + + if(pts.length === 5) { + if(pts[0][0] === pts[1][0]) { // vert, horz, vert, horz + if(pts[2][0] === pts[3][0] && + pts[0][1] === pts[3][1] && + pts[1][1] === pts[2][1]) { + isRect = true; + rectFirstEdgeTest = function(pt) { return pt[0] === pts[0][0]; }; + } + } + else if(pts[0][1] === pts[1][1]) { // horz, vert, horz, vert + if(pts[2][1] === pts[3][1] && + pts[0][0] === pts[3][0] && + pts[1][0] === pts[2][0]) { + isRect = true; + rectFirstEdgeTest = function(pt) { return pt[1] === pts[0][1]; }; + } + } + } + + function rectContains(pt, omitFirstEdge) { + var x = pt[0], + y = pt[1]; + + if(x < xmin || x > xmax || y < ymin || y > ymax) { + // pt is outside the bounding box of polygon + return false; + } + if(omitFirstEdge && rectFirstEdgeTest(pt)) return false; + + return true; + } + + function contains(pt, omitFirstEdge) { + var x = pt[0], + y = pt[1]; + + if(x < xmin || x > xmax || y < ymin || y > ymax) { + // pt is outside the bounding box of polygon + return false; + } + + var imax = pts.length, + x1 = pts[0][0], + y1 = pts[0][1], + crossings = 0, + i, + x0, + y0, + xmini, + ycross; + + for(i = 1; i < imax; i++) { + // find all crossings of a vertical line upward from pt with + // polygon segments + // crossings exactly at xmax don't count, unless the point is + // exactly on the segment, then it counts as inside. + x0 = x1; + y0 = y1; + x1 = pts[i][0]; + y1 = pts[i][1]; + xmini = Math.min(x0, x1); + + // outside the bounding box of this segment, it's only a crossing + // if it's below the box. + if(x < xmini || x > Math.max(x0, x1) || y > Math.max(y0, y1)) { + continue; + } + else if(y < Math.min(y0, y1)) { + // don't count the left-most point of the segment as a crossing + // because we don't want to double-count adjacent crossings + // UNLESS the polygon turns past vertical at exactly this x + // Note that this is repeated below, but we can't factor it out + // because + if(x !== xmini) crossings++; + } + // inside the bounding box, check the actual line intercept + else { + // vertical segment - we know already that the point is exactly + // on the segment, so mark the crossing as exactly at the point. + if(x1 === x0) ycross = y; + // any other angle + else ycross = y0 + (x - x0) * (y1 - y0) / (x1 - x0); + + // exactly on the edge: counts as inside the polygon, unless it's the + // first edge and we're omitting it. + if(y === ycross) { + if(i === 1 && omitFirstEdge) return false; + return true; + } + + if(y <= ycross && x !== xmini) crossings++; + } + } + + // if we've gotten this far, odd crossings means inside, even is outside + return crossings % 2 === 1; + } + + return { + xmin: xmin, + xmax: xmax, + ymin: ymin, + ymax: ymax, + pts: pts, + contains: isRect ? rectContains : contains, + isRect: isRect + }; +}; + +/** + * Test if a segment of a points array is bent or straight + * + * @param pts Array of [x, y] pairs + * @param start the index of the proposed start of the straight section + * @param end the index of the proposed end point + * @param tolerance the max distance off the line connecting start and end + * before the line counts as bent + * @returns boolean: true means this segment is bent, false means straight + */ +var isBent = polygon.isSegmentBent = function isBent(pts, start, end, tolerance) { + var startPt = pts[start], + segment = [pts[end][0] - startPt[0], pts[end][1] - startPt[1]], + segmentSquared = dot(segment, segment), + segmentLen = Math.sqrt(segmentSquared), + unitPerp = [-segment[1] / segmentLen, segment[0] / segmentLen], + i, + part, + partParallel; + + for(i = start + 1; i < end; i++) { + part = [pts[i][0] - startPt[0], pts[i][1] - startPt[1]]; + partParallel = dot(part, segment); + + if(partParallel < 0 || partParallel > segmentSquared || + Math.abs(dot(part, unitPerp)) > tolerance) return true; + } + return false; +}; + +/** + * Make a filtering polygon, to minimize the number of segments + * + * @param pts Array of [x, y] pairs (must start with at least 1 pair) + * @param tolerance the maximum deviation from straight allowed for + * removing points to simplify the polygon + * + * @returns Object {addPt, raw, filtered} + * addPt is a function(pt: [x, y] pair) to add a raw point and + * continue filtering + * raw is all the input points + * filtered is the resulting filtered Array of [x, y] pairs + */ +polygon.filter = function filter(pts, tolerance) { + var ptsFiltered = [pts[0]], + doneRawIndex = 0, + doneFilteredIndex = 0; + + function addPt(pt) { + pts.push(pt); + var prevFilterLen = ptsFiltered.length, + iLast = doneRawIndex; + ptsFiltered.splice(doneFilteredIndex + 1); + + for(var i = iLast + 1; i < pts.length; i++) { + if(i === pts.length - 1 || isBent(pts, iLast, i + 1, tolerance)) { + ptsFiltered.push(pts[i]); + if(ptsFiltered.length < prevFilterLen - 2) { + doneRawIndex = i; + doneFilteredIndex = ptsFiltered.length - 1; + } + iLast = i; + } + } + } + + if(pts.length > 1) { + var lastPt = pts.pop(); + addPt(lastPt); + } + + return { + addPt: addPt, + raw: pts, + filtered: ptsFiltered + }; +}; + +},{"./matrix":126}],130:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../lib'); +var config = require('../plot_api/plot_config'); + + +/** + * Copy arg array *without* removing `undefined` values from objects. + * + * @param gd + * @param args + * @returns {Array} + */ +function copyArgArray(gd, args) { + var copy = []; + var arg; + + for(var i = 0; i < args.length; i++) { + arg = args[i]; + + if(arg === gd) copy[i] = arg; + else if(typeof arg === 'object') { + copy[i] = Array.isArray(arg) ? + Lib.extendDeep([], arg) : + Lib.extendDeepAll({}, arg); + } + else copy[i] = arg; + } + + return copy; +} + + +// ----------------------------------------------------- +// Undo/Redo queue for plots +// ----------------------------------------------------- + + +var queue = {}; + +// TODO: disable/enable undo and redo buttons appropriately + +/** + * Add an item to the undoQueue for a graphDiv + * + * @param gd + * @param undoFunc Function undo this operation + * @param undoArgs Args to supply undoFunc with + * @param redoFunc Function to redo this operation + * @param redoArgs Args to supply redoFunc with + */ +queue.add = function(gd, undoFunc, undoArgs, redoFunc, redoArgs) { + var queueObj, + queueIndex; + + // make sure we have the queue and our position in it + gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; + queueIndex = gd.undoQueue.index; + + // if we're already playing an undo or redo, or if this is an auto operation + // (like pane resize... any others?) then we don't save this to the undo queue + if(gd.autoplay) { + if(!gd.undoQueue.inSequence) gd.autoplay = false; + return; + } + + // if we're not in a sequence or are just starting, we need a new queue item + if(!gd.undoQueue.sequence || gd.undoQueue.beginSequence) { + queueObj = {undo: {calls: [], args: []}, redo: {calls: [], args: []}}; + gd.undoQueue.queue.splice(queueIndex, gd.undoQueue.queue.length - queueIndex, queueObj); + gd.undoQueue.index += 1; + } else { + queueObj = gd.undoQueue.queue[queueIndex - 1]; + } + gd.undoQueue.beginSequence = false; + + // we unshift to handle calls for undo in a forward for loop later + if(queueObj) { + queueObj.undo.calls.unshift(undoFunc); + queueObj.undo.args.unshift(undoArgs); + queueObj.redo.calls.push(redoFunc); + queueObj.redo.args.push(redoArgs); + } + + if(gd.undoQueue.queue.length > config.queueLength) { + gd.undoQueue.queue.shift(); + gd.undoQueue.index--; + } +}; + +/** + * Begin a sequence of undoQueue changes + * + * @param gd + */ +queue.startSequence = function(gd) { + gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; + gd.undoQueue.sequence = true; + gd.undoQueue.beginSequence = true; +}; + +/** + * Stop a sequence of undoQueue changes + * + * Call this *after* you're sure your undo chain has ended + * + * @param gd + */ +queue.stopSequence = function(gd) { + gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; + gd.undoQueue.sequence = false; + gd.undoQueue.beginSequence = false; +}; + +/** + * Move one step back in the undo queue, and undo the object there. + * + * @param gd + */ +queue.undo = function undo(gd) { + var queueObj, i; + + if(gd.framework && gd.framework.isPolar) { + gd.framework.undo(); + return; + } + if(gd.undoQueue === undefined || + isNaN(gd.undoQueue.index) || + gd.undoQueue.index <= 0) { + return; + } + + // index is pointing to next *forward* queueObj, point to the one we're undoing + gd.undoQueue.index--; + + // get the queueObj for instructions on how to undo + queueObj = gd.undoQueue.queue[gd.undoQueue.index]; + + // this sequence keeps things from adding to the queue during undo/redo + gd.undoQueue.inSequence = true; + for(i = 0; i < queueObj.undo.calls.length; i++) { + queue.plotDo(gd, queueObj.undo.calls[i], queueObj.undo.args[i]); + } + gd.undoQueue.inSequence = false; + gd.autoplay = false; +}; + +/** + * Redo the current object in the undo, then move forward in the queue. + * + * @param gd + */ +queue.redo = function redo(gd) { + var queueObj, i; + + if(gd.framework && gd.framework.isPolar) { + gd.framework.redo(); + return; + } + if(gd.undoQueue === undefined || + isNaN(gd.undoQueue.index) || + gd.undoQueue.index >= gd.undoQueue.queue.length) { + return; + } + + // get the queueObj for instructions on how to undo + queueObj = gd.undoQueue.queue[gd.undoQueue.index]; + + // this sequence keeps things from adding to the queue during undo/redo + gd.undoQueue.inSequence = true; + for(i = 0; i < queueObj.redo.calls.length; i++) { + queue.plotDo(gd, queueObj.redo.calls[i], queueObj.redo.args[i]); + } + gd.undoQueue.inSequence = false; + gd.autoplay = false; + + // index is pointing to the thing we just redid, move it + gd.undoQueue.index++; +}; + +/** + * Called by undo/redo to make the actual changes. + * + * Not meant to be called publically, but included for mocking out in tests. + * + * @param gd + * @param func + * @param args + */ +queue.plotDo = function(gd, func, args) { + gd.autoplay = true; + + // this *won't* copy gd and it preserves `undefined` properties! + args = copyArgArray(gd, args); + + // call the supplied function + func.apply(null, args); +}; + +module.exports = queue; + +},{"../lib":122,"../plot_api/plot_config":138}],131:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var loggers = require('./loggers'); + + +/** + * findBin - find the bin for val - note that it can return outside the + * bin range any pos. or neg. integer for linear bins, or -1 or + * bins.length-1 for explicit. + * bins is either an object {start,size,end} or an array length #bins+1 + * bins can be either increasing or decreasing but must be monotonic + * for linear bins, we can just calculate. For listed bins, run a binary + * search linelow (truthy) says the bin boundary should be attributed to + * the lower bin rather than the default upper bin + */ +exports.findBin = function(val, bins, linelow) { + if(isNumeric(bins.start)) { + return linelow ? + Math.ceil((val - bins.start) / bins.size) - 1 : + Math.floor((val - bins.start) / bins.size); + } + else { + var n1 = 0, + n2 = bins.length, + c = 0, + n, + test; + if(bins[bins.length - 1] >= bins[0]) { + test = linelow ? lessThan : lessOrEqual; + } else { + test = linelow ? greaterOrEqual : greaterThan; + } + // c is just to avoid infinite loops if there's an error + while(n1 < n2 && c++ < 100) { + n = Math.floor((n1 + n2) / 2); + if(test(bins[n], val)) n1 = n + 1; + else n2 = n; + } + if(c > 90) loggers.log('Long binary search...'); + return n1 - 1; + } +}; + +function lessThan(a, b) { return a < b; } +function lessOrEqual(a, b) { return a <= b; } +function greaterThan(a, b) { return a > b; } +function greaterOrEqual(a, b) { return a >= b; } + +exports.sorterAsc = function(a, b) { return a - b; }; +exports.sorterDes = function(a, b) { return b - a; }; + +/** + * find distinct values in an array, lumping together ones that appear to + * just be off by a rounding error + * return the distinct values and the minimum difference between any two + */ +exports.distinctVals = function(valsIn) { + var vals = valsIn.slice(); // otherwise we sort the original array... + vals.sort(exports.sorterAsc); + + var l = vals.length - 1, + minDiff = (vals[l] - vals[0]) || 1, + errDiff = minDiff / (l || 1) / 10000, + v2 = [vals[0]]; + + for(var i = 0; i < l; i++) { + // make sure values aren't just off by a rounding error + if(vals[i + 1] > vals[i] + errDiff) { + minDiff = Math.min(minDiff, vals[i + 1] - vals[i]); + v2.push(vals[i + 1]); + } + } + + return {vals: v2, minDiff: minDiff}; +}; + +/** + * return the smallest element from (sorted) array arrayIn that's bigger than val, + * or (reverse) the largest element smaller than val + * used to find the best tick given the minimum (non-rounded) tick + * particularly useful for date/time where things are not powers of 10 + * binary search is probably overkill here... + */ +exports.roundUp = function(val, arrayIn, reverse) { + var low = 0, + high = arrayIn.length - 1, + mid, + c = 0, + dlow = reverse ? 0 : 1, + dhigh = reverse ? 1 : 0, + rounded = reverse ? Math.ceil : Math.floor; + // c is just to avoid infinite loops if there's an error + while(low < high && c++ < 100) { + mid = rounded((low + high) / 2); + if(arrayIn[mid] <= val) low = mid + dlow; + else high = mid - dhigh; + } + return arrayIn[low]; +}; + +},{"./loggers":125,"fast-isnumeric":13}],132:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +// works with our CSS cursor classes (see css/_cursor.scss) +// to apply cursors to d3 single-element selections. +// omit cursor to revert to the default. +module.exports = function setCursor(el3, csr) { + (el3.attr('class') || '').split(' ').forEach(function(cls) { + if(cls.indexOf('cursor-') === 0) el3.classed(cls, false); + }); + + if(csr) el3.classed('cursor-' + csr, true); +}; + +},{}],133:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + + +/** + * aggNums() returns the result of an aggregate function applied to an array of + * values, where non-numerical values have been tossed out. + * + * @param {function} f - aggregation function (e.g., Math.min) + * @param {Number} v - initial value (continuing from previous calls) + * if there's no continuing value, use null for selector-type + * functions (max,min), or 0 for summations + * @param {Array} a - array to aggregate (may be nested, we will recurse, + * but all elements must have the same dimension) + * @param {Number} len - maximum length of a to aggregate + * @return {Number} - result of f applied to a starting from v + */ +exports.aggNums = function(f, v, a, len) { + var i, + b; + if(!len) len = a.length; + if(!isNumeric(v)) v = false; + if(Array.isArray(a[0])) { + b = new Array(len); + for(i = 0; i < len; i++) b[i] = exports.aggNums(f, v, a[i]); + a = b; + } + + for(i = 0; i < len; i++) { + if(!isNumeric(v)) v = a[i]; + else if(isNumeric(a[i])) v = f(+v, +a[i]); + } + return v; +}; + +/** + * mean & std dev functions using aggNums, so it handles non-numerics nicely + * even need to use aggNums instead of .length, to toss out non-numerics + */ +exports.len = function(data) { + return exports.aggNums(function(a) { return a + 1; }, 0, data); +}; + +exports.mean = function(data, len) { + if(!len) len = exports.len(data); + return exports.aggNums(function(a, b) { return a + b; }, 0, data) / len; +}; + +exports.variance = function(data, len, mean) { + if(!len) len = exports.len(data); + if(!isNumeric(mean)) mean = exports.mean(data, len); + + return exports.aggNums(function(a, b) { + return a + Math.pow(b - mean, 2); + }, 0, data) / len; +}; + +exports.stdev = function(data, len, mean) { + return Math.sqrt(exports.variance(data, len, mean)); +}; + +/** + * interp() computes a percentile (quantile) for a given distribution. + * We interpolate the distribution (to compute quantiles, we follow method #10 here: + * http://www.amstat.org/publications/jse/v14n3/langford.html). + * Typically the index or rank (n * arr.length) may be non-integer. + * For reference: ends are clipped to the extreme values in the array; + * For box plots: index you get is half a point too high (see + * http://en.wikipedia.org/wiki/Percentile#Nearest_rank) but note that this definition + * indexes from 1 rather than 0, so we subtract 1/2 (instead of add). + * + * @param {Array} arr - This array contains the values that make up the distribution. + * @param {Number} n - Between 0 and 1, n = p/100 is such that we compute the p^th percentile. + * For example, the 50th percentile (or median) corresponds to n = 0.5 + * @return {Number} - percentile + */ +exports.interp = function(arr, n) { + if(!isNumeric(n)) throw 'n should be a finite number'; + n = n * arr.length - 0.5; + if(n < 0) return arr[0]; + if(n > arr.length - 1) return arr[arr.length - 1]; + var frac = n % 1; + return frac * arr[Math.ceil(n)] + (1 - frac) * arr[Math.floor(n)]; +}; + +},{"fast-isnumeric":13}],134:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/* global MathJax:false */ + +var d3 = require('d3'); + +var Lib = require('../lib'); +var xmlnsNamespaces = require('../constants/xmlns_namespaces'); +var stringMappings = require('../constants/string_mappings'); + +// Append SVG + +d3.selection.prototype.appendSVG = function(_svgString) { + var skeleton = [ + '', + _svgString, + '' + ].join(''); + + var dom = new DOMParser().parseFromString(skeleton, 'application/xml'), + childNode = dom.documentElement.firstChild; + + while(childNode) { + this.node().appendChild(this.node().ownerDocument.importNode(childNode, true)); + childNode = childNode.nextSibling; + } + if(dom.querySelector('parsererror')) { + Lib.log(dom.querySelector('parsererror div').textContent); + return null; + } + return d3.select(this.node().lastChild); +}; + +// Text utilities + +exports.html_entity_decode = function(s) { + var hiddenDiv = d3.select('body').append('div').style({display: 'none'}).html(''); + var replaced = s.replace(/(&[^;]*;)/gi, function(d) { + if(d === '<') { return '<'; } // special handling for brackets + if(d === '&rt;') { return '>'; } + return hiddenDiv.html(d).text(); // everything else, let the browser decode it to unicode + }); + hiddenDiv.remove(); + return replaced; +}; + +exports.xml_entity_encode = function(str) { + return str.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g, '&'); +}; + +// text converter + +function getSize(_selection, _dimension) { + return _selection.node().getBoundingClientRect()[_dimension]; +} + +exports.convertToTspans = function(_context, _callback) { + var str = _context.text(); + var converted = convertToSVG(str); + var that = _context; + + // Until we get tex integrated more fully (so it can be used along with non-tex) + // allow some elements to prohibit it by attaching 'data-notex' to the original + var tex = (!that.attr('data-notex')) && converted.match(/([^$]*)([$]+[^$]*[$]+)([^$]*)/); + var result = str; + var parent = d3.select(that.node().parentNode); + if(parent.empty()) return; + var svgClass = (that.attr('class')) ? that.attr('class').split(' ')[0] : 'text'; + svgClass += '-math'; + parent.selectAll('svg.' + svgClass).remove(); + parent.selectAll('g.' + svgClass + '-group').remove(); + _context.style({visibility: null}); + for(var up = _context.node(); up && up.removeAttribute; up = up.parentNode) { + up.removeAttribute('data-bb'); + } + + function showText() { + if(!parent.empty()) { + svgClass = that.attr('class') + '-math'; + parent.select('svg.' + svgClass).remove(); + } + _context.text('') + .style({ + visibility: 'inherit', + 'white-space': 'pre' + }); + + result = _context.appendSVG(converted); + + if(!result) _context.text(str); + + if(_context.select('a').size()) { + // at least in Chrome, pointer-events does not seem + // to be honored in children of elements + // so if we have an anchor, we have to make the + // whole element respond + _context.style('pointer-events', 'all'); + } + + if(_callback) _callback.call(that); + } + + if(tex) { + var gd = Lib.getPlotDiv(that.node()); + ((gd && gd._promises) || []).push(new Promise(function(resolve) { + that.style({visibility: 'hidden'}); + var config = {fontSize: parseInt(that.style('font-size'), 10)}; + + texToSVG(tex[2], config, function(_svgEl, _glyphDefs, _svgBBox) { + parent.selectAll('svg.' + svgClass).remove(); + parent.selectAll('g.' + svgClass + '-group').remove(); + + var newSvg = _svgEl && _svgEl.select('svg'); + if(!newSvg || !newSvg.node()) { + showText(); + resolve(); + return; + } + + var mathjaxGroup = parent.append('g') + .classed(svgClass + '-group', true) + .attr({'pointer-events': 'none'}); + + mathjaxGroup.node().appendChild(newSvg.node()); + + // stitch the glyph defs + if(_glyphDefs && _glyphDefs.node()) { + newSvg.node().insertBefore(_glyphDefs.node().cloneNode(true), + newSvg.node().firstChild); + } + + newSvg.attr({ + 'class': svgClass, + height: _svgBBox.height, + preserveAspectRatio: 'xMinYMin meet' + }) + .style({overflow: 'visible', 'pointer-events': 'none'}); + + var fill = that.style('fill') || 'black'; + newSvg.select('g').attr({fill: fill, stroke: fill}); + + var newSvgW = getSize(newSvg, 'width'), + newSvgH = getSize(newSvg, 'height'), + newX = +that.attr('x') - newSvgW * + {start: 0, middle: 0.5, end: 1}[that.attr('text-anchor') || 'start'], + // font baseline is about 1/4 fontSize below centerline + textHeight = parseInt(that.style('font-size'), 10) || + getSize(that, 'height'), + dy = -textHeight / 4; + + if(svgClass[0] === 'y') { + mathjaxGroup.attr({ + transform: 'rotate(' + [-90, +that.attr('x'), +that.attr('y')] + + ') translate(' + [-newSvgW / 2, dy - newSvgH / 2] + ')' + }); + newSvg.attr({x: +that.attr('x'), y: +that.attr('y')}); + } + else if(svgClass[0] === 'l') { + newSvg.attr({x: that.attr('x'), y: dy - (newSvgH / 2)}); + } + else if(svgClass[0] === 'a') { + newSvg.attr({x: 0, y: dy}); + } + else { + newSvg.attr({x: newX, y: (+that.attr('y') + dy - newSvgH / 2)}); + } + + if(_callback) _callback.call(that, mathjaxGroup); + resolve(mathjaxGroup); + }); + })); + } + else showText(); + + return _context; +}; + + +// MathJax + +function cleanEscapesForTex(s) { + return s.replace(/(<|<|<)/g, '\\lt ') + .replace(/(>|>|>)/g, '\\gt '); +} + +function texToSVG(_texString, _config, _callback) { + var randomID = 'math-output-' + Lib.randstr([], 64); + var tmpDiv = d3.select('body').append('div') + .attr({id: randomID}) + .style({visibility: 'hidden', position: 'absolute'}) + .style({'font-size': _config.fontSize + 'px'}) + .text(cleanEscapesForTex(_texString)); + + MathJax.Hub.Queue(['Typeset', MathJax.Hub, tmpDiv.node()], function() { + var glyphDefs = d3.select('body').select('#MathJax_SVG_glyphs'); + + if(tmpDiv.select('.MathJax_SVG').empty() || !tmpDiv.select('svg').node()) { + Lib.log('There was an error in the tex syntax.', _texString); + _callback(); + } + else { + var svgBBox = tmpDiv.select('svg').node().getBoundingClientRect(); + _callback(tmpDiv.select('.MathJax_SVG'), glyphDefs, svgBBox); + } + + tmpDiv.remove(); + }); +} + +var TAG_STYLES = { + // would like to use baseline-shift but FF doesn't support it yet + // so we need to use dy along with the uber hacky shift-back-to + // baseline below + sup: 'font-size:70%" dy="-0.6em', + sub: 'font-size:70%" dy="0.3em', + b: 'font-weight:bold', + i: 'font-style:italic', + a: '', + span: '', + br: '', + em: 'font-style:italic;font-weight:bold' +}; + +var PROTOCOLS = ['http:', 'https:', 'mailto:']; + +var STRIP_TAGS = new RegExp(']*)?/?>', 'g'); + +var ENTITY_TO_UNICODE = Object.keys(stringMappings.entityToUnicode).map(function(k) { + return { + regExp: new RegExp('&' + k + ';', 'g'), + sub: stringMappings.entityToUnicode[k] + }; +}); + +var UNICODE_TO_ENTITY = Object.keys(stringMappings.unicodeToEntity).map(function(k) { + return { + regExp: new RegExp(k, 'g'), + sub: '&' + stringMappings.unicodeToEntity[k] + ';' + }; +}); + +exports.plainText = function(_str) { + // strip out our pseudo-html so we have a readable + // version to put into text fields + return (_str || '').replace(STRIP_TAGS, ' '); +}; + +function replaceFromMapObject(_str, list) { + var out = _str || ''; + + for(var i = 0; i < list.length; i++) { + var item = list[i]; + out = out.replace(item.regExp, item.sub); + } + + return out; +} + +function convertEntities(_str) { + return replaceFromMapObject(_str, ENTITY_TO_UNICODE); +} + +function encodeForHTML(_str) { + return replaceFromMapObject(_str, UNICODE_TO_ENTITY); +} + +function convertToSVG(_str) { + _str = convertEntities(_str); + + var result = _str + .split(/(<[^<>]*>)/).map(function(d) { + var match = d.match(/<(\/?)([^ >]*)\s*(.*)>/i), + tag = match && match[2].toLowerCase(), + style = TAG_STYLES[tag]; + + if(style !== undefined) { + var close = match[1], + extra = match[3], + /** + * extraStyle: any random extra css (that's supported by svg) + * use this like to change font in the middle + * + * at one point we supported but as this isn't even + * valid HTML anymore and we dropped it accidentally for many months, we will not + * resurrect it. + */ + extraStyle = extra.match(/^style\s*=\s*"([^"]+)"\s*/i); + + // anchor and br are the only ones that don't turn into a tspan + if(tag === 'a') { + if(close) return '
'; + else if(extra.substr(0, 4).toLowerCase() !== 'href') return ''; + else { + // remove quotes, leading '=', replace '&' with '&' + var href = extra.substr(4) + .replace(/["']/g, '') + .replace(/=/, ''); + + // check protocol + var dummyAnchor = document.createElement('a'); + dummyAnchor.href = href; + if(PROTOCOLS.indexOf(dummyAnchor.protocol) === -1) return ''; + + return ''; + } + } + else if(tag === 'br') return '
'; + else if(close) { + // closing tag + + // sub/sup: extra tspan with zero-width space to get back to the right baseline + if(tag === 'sup') return ''; + if(tag === 'sub') return ''; + else return ''; + } + else { + var tspanStart = ''; + } + } + else { + return exports.xml_entity_encode(d).replace(/'); index > 0; index = result.indexOf('
', index + 1)) { + indices.push(index); + } + var count = 0; + indices.forEach(function(d) { + var brIndex = d + count; + var search = result.slice(0, brIndex); + var previousOpenTag = ''; + for(var i2 = search.length - 1; i2 >= 0; i2--) { + var isTag = search[i2].match(/<(\/?).*>/i); + if(isTag && search[i2] !== '
') { + if(!isTag[1]) previousOpenTag = search[i2]; + break; + } + } + if(previousOpenTag) { + result.splice(brIndex + 1, 0, previousOpenTag); + result.splice(brIndex, 0, ''); + count += 2; + } + }); + + var joined = result.join(''); + var splitted = joined.split(/
/gi); + if(splitted.length > 1) { + result = splitted.map(function(d, i) { + // TODO: figure out max font size of this line and alter dy + // this requires either: + // 1) bringing the base font size into convertToTspans, or + // 2) only allowing relative percentage font sizes. + // I think #2 is the way to go + return '' + d + ''; + }); + } + + return result.join(''); +} + +function alignHTMLWith(_base, container, options) { + var alignH = options.horizontalAlign, + alignV = options.verticalAlign || 'top', + bRect = _base.node().getBoundingClientRect(), + cRect = container.node().getBoundingClientRect(), + thisRect, + getTop, + getLeft; + + if(alignV === 'bottom') { + getTop = function() { return bRect.bottom - thisRect.height; }; + } else if(alignV === 'middle') { + getTop = function() { return bRect.top + (bRect.height - thisRect.height) / 2; }; + } else { // default: top + getTop = function() { return bRect.top; }; + } + + if(alignH === 'right') { + getLeft = function() { return bRect.right - thisRect.width; }; + } else if(alignH === 'center') { + getLeft = function() { return bRect.left + (bRect.width - thisRect.width) / 2; }; + } else { // default: left + getLeft = function() { return bRect.left; }; + } + + return function() { + thisRect = this.node().getBoundingClientRect(); + this.style({ + top: (getTop() - cRect.top) + 'px', + left: (getLeft() - cRect.left) + 'px', + 'z-index': 1000 + }); + return this; + }; +} + +// Editable title + +exports.makeEditable = function(context, _delegate, options) { + if(!options) options = {}; + var that = this; + var dispatch = d3.dispatch('edit', 'input', 'cancel'); + var textSelection = d3.select(this.node()) + .style({'pointer-events': 'all'}); + + var handlerElement = _delegate || textSelection; + if(_delegate) textSelection.style({'pointer-events': 'none'}); + + function handleClick() { + appendEditable(); + that.style({opacity: 0}); + // also hide any mathjax svg + var svgClass = handlerElement.attr('class'), + mathjaxClass; + if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group'; + else mathjaxClass = '[class*=-math-group]'; + if(mathjaxClass) { + d3.select(that.node().parentNode).select(mathjaxClass).style({opacity: 0}); + } + } + + function selectElementContents(_el) { + var el = _el.node(); + var range = document.createRange(); + range.selectNodeContents(el); + var sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + el.focus(); + } + + function appendEditable() { + var plotDiv = d3.select(Lib.getPlotDiv(that.node())), + container = plotDiv.select('.svg-container'), + div = container.append('div'); + div.classed('plugin-editable editable', true) + .style({ + position: 'absolute', + 'font-family': that.style('font-family') || 'Arial', + 'font-size': that.style('font-size') || 12, + color: options.fill || that.style('fill') || 'black', + opacity: 1, + 'background-color': options.background || 'transparent', + outline: '#ffffff33 1px solid', + margin: [-parseFloat(that.style('font-size')) / 8 + 1, 0, 0, -1].join('px ') + 'px', + padding: '0', + 'box-sizing': 'border-box' + }) + .attr({contenteditable: true}) + .text(options.text || that.attr('data-unformatted')) + .call(alignHTMLWith(that, container, options)) + .on('blur', function() { + that.text(this.textContent) + .style({opacity: 1}); + var svgClass = d3.select(this).attr('class'), + mathjaxClass; + if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group'; + else mathjaxClass = '[class*=-math-group]'; + if(mathjaxClass) { + d3.select(that.node().parentNode).select(mathjaxClass).style({opacity: 0}); + } + var text = this.textContent; + d3.select(this).transition().duration(0).remove(); + d3.select(document).on('mouseup', null); + dispatch.edit.call(that, text); + }) + .on('focus', function() { + var context = this; + d3.select(document).on('mouseup', function() { + if(d3.event.target === context) return false; + if(document.activeElement === div.node()) div.node().blur(); + }); + }) + .on('keyup', function() { + if(d3.event.which === 27) { + that.style({opacity: 1}); + d3.select(this) + .style({opacity: 0}) + .on('blur', function() { return false; }) + .transition().remove(); + dispatch.cancel.call(that, this.textContent); + } + else { + dispatch.input.call(that, this.textContent); + d3.select(this).call(alignHTMLWith(that, container, options)); + } + }) + .on('keydown', function() { + if(d3.event.which === 13) this.blur(); + }) + .call(selectElementContents); + } + + if(options.immediate) handleClick(); + else handlerElement.on('click', handleClick); + + return d3.rebind(this, dispatch, 'on'); +}; + +},{"../constants/string_mappings":108,"../constants/xmlns_namespaces":109,"../lib":122,"d3":10}],135:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var topojsonUtils = module.exports = {}; + +var locationmodeToLayer = require('../plots/geo/constants').locationmodeToLayer; +var topojsonFeature = require('topojson-client').feature; + + +topojsonUtils.getTopojsonName = function(geoLayout) { + return [ + geoLayout.scope.replace(/ /g, '-'), '_', + geoLayout.resolution.toString(), 'm' + ].join(''); +}; + +topojsonUtils.getTopojsonPath = function(topojsonURL, topojsonName) { + return topojsonURL + topojsonName + '.json'; +}; + +topojsonUtils.getTopojsonFeatures = function(trace, topojson) { + var layer = locationmodeToLayer[trace.locationmode], + obj = topojson.objects[layer]; + + return topojsonFeature(topojson, obj).features; +}; + +},{"../plots/geo/constants":172,"topojson-client":17}],136:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var m4FromQuat = require('gl-mat4/fromQuat'); + +var Registry = require('../registry'); +var Lib = require('../lib'); +var Plots = require('../plots/plots'); +var Axes = require('../plots/cartesian/axes'); +var Color = require('../components/color'); + + +// Get the container div: we store all variables for this plot as +// properties of this div +// some callers send this in by DOM element, others by id (string) +exports.getGraphDiv = function(gd) { + var gdElement; + + if(typeof gd === 'string') { + gdElement = document.getElementById(gd); + + if(gdElement === null) { + throw new Error('No DOM element with id \'' + gd + '\' exists on the page.'); + } + + return gdElement; + } + else if(gd === null || gd === undefined) { + throw new Error('DOM element provided is null or undefined'); + } + + return gd; // otherwise assume that gd is a DOM element +}; + +// clear the promise queue if one of them got rejected +exports.clearPromiseQueue = function(gd) { + if(Array.isArray(gd._promises) && gd._promises.length > 0) { + Lib.log('Clearing previous rejected promises from queue.'); + } + + gd._promises = []; +}; + +// make a few changes to the layout right away +// before it gets used for anything +// backward compatibility and cleanup of nonstandard options +exports.cleanLayout = function(layout) { + var i, j; + + if(!layout) layout = {}; + + // cannot have (x|y)axis1, numbering goes axis, axis2, axis3... + if(layout.xaxis1) { + if(!layout.xaxis) layout.xaxis = layout.xaxis1; + delete layout.xaxis1; + } + if(layout.yaxis1) { + if(!layout.yaxis) layout.yaxis = layout.yaxis1; + delete layout.yaxis1; + } + + var axList = Axes.list({_fullLayout: layout}); + for(i = 0; i < axList.length; i++) { + var ax = axList[i]; + if(ax.anchor && ax.anchor !== 'free') { + ax.anchor = Axes.cleanId(ax.anchor); + } + if(ax.overlaying) ax.overlaying = Axes.cleanId(ax.overlaying); + + // old method of axis type - isdate and islog (before category existed) + if(!ax.type) { + if(ax.isdate) ax.type = 'date'; + else if(ax.islog) ax.type = 'log'; + else if(ax.isdate === false && ax.islog === false) ax.type = 'linear'; + } + if(ax.autorange === 'withzero' || ax.autorange === 'tozero') { + ax.autorange = true; + ax.rangemode = 'tozero'; + } + delete ax.islog; + delete ax.isdate; + delete ax.categories; // replaced by _categories + + // prune empty domain arrays made before the new nestedProperty + if(emptyContainer(ax, 'domain')) delete ax.domain; + + // autotick -> tickmode + if(ax.autotick !== undefined) { + if(ax.tickmode === undefined) { + ax.tickmode = ax.autotick ? 'auto' : 'linear'; + } + delete ax.autotick; + } + } + + var annotationsLen = Array.isArray(layout.annotations) ? layout.annotations.length : 0; + for(i = 0; i < annotationsLen; i++) { + var ann = layout.annotations[i]; + + if(!Lib.isPlainObject(ann)) continue; + + if(ann.ref) { + if(ann.ref === 'paper') { + ann.xref = 'paper'; + ann.yref = 'paper'; + } + else if(ann.ref === 'data') { + ann.xref = 'x'; + ann.yref = 'y'; + } + delete ann.ref; + } + + cleanAxRef(ann, 'xref'); + cleanAxRef(ann, 'yref'); + } + + var shapesLen = Array.isArray(layout.shapes) ? layout.shapes.length : 0; + for(i = 0; i < shapesLen; i++) { + var shape = layout.shapes[i]; + + if(!Lib.isPlainObject(shape)) continue; + + cleanAxRef(shape, 'xref'); + cleanAxRef(shape, 'yref'); + } + + var legend = layout.legend; + if(legend) { + // check for old-style legend positioning (x or y is +/- 100) + if(legend.x > 3) { + legend.x = 1.02; + legend.xanchor = 'left'; + } + else if(legend.x < -2) { + legend.x = -0.02; + legend.xanchor = 'right'; + } + + if(legend.y > 3) { + legend.y = 1.02; + legend.yanchor = 'bottom'; + } + else if(legend.y < -2) { + legend.y = -0.02; + legend.yanchor = 'top'; + } + } + + /* + * Moved from rotate -> orbit for dragmode + */ + if(layout.dragmode === 'rotate') layout.dragmode = 'orbit'; + + // cannot have scene1, numbering goes scene, scene2, scene3... + if(layout.scene1) { + if(!layout.scene) layout.scene = layout.scene1; + delete layout.scene1; + } + + /* + * Clean up Scene layouts + */ + var sceneIds = Plots.getSubplotIds(layout, 'gl3d'); + for(i = 0; i < sceneIds.length; i++) { + var scene = layout[sceneIds[i]]; + + // clean old Camera coords + var cameraposition = scene.cameraposition; + if(Array.isArray(cameraposition) && cameraposition[0].length === 4) { + var rotation = cameraposition[0], + center = cameraposition[1], + radius = cameraposition[2], + mat = m4FromQuat([], rotation), + eye = []; + + for(j = 0; j < 3; ++j) { + eye[j] = center[i] + radius * mat[2 + 4 * j]; + } + + scene.camera = { + eye: {x: eye[0], y: eye[1], z: eye[2]}, + center: {x: center[0], y: center[1], z: center[2]}, + up: {x: mat[1], y: mat[5], z: mat[9]} + }; + + delete scene.cameraposition; + } + } + + // sanitize rgb(fractions) and rgba(fractions) that old tinycolor + // supported, but new tinycolor does not because they're not valid css + Color.clean(layout); + + return layout; +}; + +function cleanAxRef(container, attr) { + var valIn = container[attr], + axLetter = attr.charAt(0); + if(valIn && valIn !== 'paper') { + container[attr] = Axes.cleanId(valIn, axLetter); + } +} + +// Make a few changes to the data right away +// before it gets used for anything +exports.cleanData = function(data, existingData) { + + // Enforce unique IDs + var suids = [], // seen uids --- so we can weed out incoming repeats + uids = data.concat(Array.isArray(existingData) ? existingData : []) + .filter(function(trace) { return 'uid' in trace; }) + .map(function(trace) { return trace.uid; }); + + for(var tracei = 0; tracei < data.length; tracei++) { + var trace = data[tracei]; + var i; + + // assign uids to each trace and detect collisions. + if(!('uid' in trace) || suids.indexOf(trace.uid) !== -1) { + var newUid; + + for(i = 0; i < 100; i++) { + newUid = Lib.randstr(uids); + if(suids.indexOf(newUid) === -1) break; + } + trace.uid = Lib.randstr(uids); + uids.push(trace.uid); + } + // keep track of already seen uids, so that if there are + // doubles we force the trace with a repeat uid to + // acquire a new one + suids.push(trace.uid); + + // BACKWARD COMPATIBILITY FIXES + + // use xbins to bin data in x, and ybins to bin data in y + if(trace.type === 'histogramy' && 'xbins' in trace && !('ybins' in trace)) { + trace.ybins = trace.xbins; + delete trace.xbins; + } + + // error_y.opacity is obsolete - merge into color + if(trace.error_y && 'opacity' in trace.error_y) { + var dc = Color.defaults, + yeColor = trace.error_y.color || + (Registry.traceIs(trace, 'bar') ? Color.defaultLine : dc[tracei % dc.length]); + trace.error_y.color = Color.addOpacity( + Color.rgb(yeColor), + Color.opacity(yeColor) * trace.error_y.opacity); + delete trace.error_y.opacity; + } + + // convert bardir to orientation, and put the data into + // the axes it's eventually going to be used with + if('bardir' in trace) { + if(trace.bardir === 'h' && (Registry.traceIs(trace, 'bar') || + trace.type.substr(0, 9) === 'histogram')) { + trace.orientation = 'h'; + exports.swapXYData(trace); + } + delete trace.bardir; + } + + // now we have only one 1D histogram type, and whether + // it uses x or y data depends on trace.orientation + if(trace.type === 'histogramy') exports.swapXYData(trace); + if(trace.type === 'histogramx' || trace.type === 'histogramy') { + trace.type = 'histogram'; + } + + // scl->scale, reversescl->reversescale + if('scl' in trace) { + trace.colorscale = trace.scl; + delete trace.scl; + } + if('reversescl' in trace) { + trace.reversescale = trace.reversescl; + delete trace.reversescl; + } + + // axis ids x1 -> x, y1-> y + if(trace.xaxis) trace.xaxis = Axes.cleanId(trace.xaxis, 'x'); + if(trace.yaxis) trace.yaxis = Axes.cleanId(trace.yaxis, 'y'); + + // scene ids scene1 -> scene + if(Registry.traceIs(trace, 'gl3d') && trace.scene) { + trace.scene = Plots.subplotsRegistry.gl3d.cleanId(trace.scene); + } + + if(!Registry.traceIs(trace, 'pie')) { + if(Array.isArray(trace.textposition)) { + trace.textposition = trace.textposition.map(cleanTextPosition); + } + else if(trace.textposition) { + trace.textposition = cleanTextPosition(trace.textposition); + } + } + + // fix typo in colorscale definition + if(Registry.traceIs(trace, '2dMap')) { + if(trace.colorscale === 'YIGnBu') trace.colorscale = 'YlGnBu'; + if(trace.colorscale === 'YIOrRd') trace.colorscale = 'YlOrRd'; + } + if(Registry.traceIs(trace, 'markerColorscale') && trace.marker) { + var cont = trace.marker; + if(cont.colorscale === 'YIGnBu') cont.colorscale = 'YlGnBu'; + if(cont.colorscale === 'YIOrRd') cont.colorscale = 'YlOrRd'; + } + + // fix typo in surface 'highlight*' definitions + if(trace.type === 'surface' && Lib.isPlainObject(trace.contours)) { + var dims = ['x', 'y', 'z']; + + for(i = 0; i < dims.length; i++) { + var opts = trace.contours[dims[i]]; + + if(!Lib.isPlainObject(opts)) continue; + + if(opts.highlightColor) { + opts.highlightcolor = opts.highlightColor; + delete opts.highlightColor; + } + + if(opts.highlightWidth) { + opts.highlightwidth = opts.highlightWidth; + delete opts.highlightWidth; + } + } + } + + // transforms backward compatibility fixes + if(Array.isArray(trace.transforms)) { + var transforms = trace.transforms; + + for(i = 0; i < transforms.length; i++) { + var transform = transforms[i]; + + if(!Lib.isPlainObject(transform)) continue; + + if(transform.type === 'filter') { + if(transform.filtersrc) { + transform.target = transform.filtersrc; + delete transform.filtersrc; + } + } + } + } + + // prune empty containers made before the new nestedProperty + if(emptyContainer(trace, 'line')) delete trace.line; + if('marker' in trace) { + if(emptyContainer(trace.marker, 'line')) delete trace.marker.line; + if(emptyContainer(trace, 'marker')) delete trace.marker; + } + + // sanitize rgb(fractions) and rgba(fractions) that old tinycolor + // supported, but new tinycolor does not because they're not valid css + Color.clean(trace); + } +}; + +// textposition - support partial attributes (ie just 'top') +// and incorrect use of middle / center etc. +function cleanTextPosition(textposition) { + var posY = 'middle', + posX = 'center'; + if(textposition.indexOf('top') !== -1) posY = 'top'; + else if(textposition.indexOf('bottom') !== -1) posY = 'bottom'; + + if(textposition.indexOf('left') !== -1) posX = 'left'; + else if(textposition.indexOf('right') !== -1) posX = 'right'; + + return posY + ' ' + posX; +} + +function emptyContainer(outer, innerStr) { + return (innerStr in outer) && + (typeof outer[innerStr] === 'object') && + (Object.keys(outer[innerStr]).length === 0); +} + + +// swap all the data and data attributes associated with x and y +exports.swapXYData = function(trace) { + var i; + Lib.swapAttrs(trace, ['?', '?0', 'd?', '?bins', 'nbins?', 'autobin?', '?src', 'error_?']); + if(Array.isArray(trace.z) && Array.isArray(trace.z[0])) { + if(trace.transpose) delete trace.transpose; + else trace.transpose = true; + } + if(trace.error_x && trace.error_y) { + var errorY = trace.error_y, + copyYstyle = ('copy_ystyle' in errorY) ? errorY.copy_ystyle : + !(errorY.color || errorY.thickness || errorY.width); + Lib.swapAttrs(trace, ['error_?.copy_ystyle']); + if(copyYstyle) { + Lib.swapAttrs(trace, ['error_?.color', 'error_?.thickness', 'error_?.width']); + } + } + if(trace.hoverinfo) { + var hoverInfoParts = trace.hoverinfo.split('+'); + for(i = 0; i < hoverInfoParts.length; i++) { + if(hoverInfoParts[i] === 'x') hoverInfoParts[i] = 'y'; + else if(hoverInfoParts[i] === 'y') hoverInfoParts[i] = 'x'; + } + trace.hoverinfo = hoverInfoParts.join('+'); + } +}; + +// coerce traceIndices input to array of trace indices +exports.coerceTraceIndices = function(gd, traceIndices) { + if(isNumeric(traceIndices)) { + return [traceIndices]; + } + else if(!Array.isArray(traceIndices) || !traceIndices.length) { + return gd.data.map(function(_, i) { return i; }); + } + + return traceIndices; +}; + +/** + * Manages logic around array container item creation / deletion / update + * that nested property along can't handle. + * + * @param {Object} np + * nested property of update attribute string about trace or layout object + * @param {*} newVal + * update value passed to restyle / relayout / update + * @param {Object} undoit + * undo hash (N.B. undoit may be mutated here). + * + */ +exports.manageArrayContainers = function(np, newVal, undoit) { + var obj = np.obj, + parts = np.parts, + pLength = parts.length, + pLast = parts[pLength - 1]; + + var pLastIsNumber = isNumeric(pLast); + + // delete item + if(pLastIsNumber && newVal === null) { + + // Clear item in array container when new value is null + var contPath = parts.slice(0, pLength - 1).join('.'), + cont = Lib.nestedProperty(obj, contPath).get(); + cont.splice(pLast, 1); + + // Note that nested property clears null / undefined at end of + // array container, but not within them. + } + // create item + else if(pLastIsNumber && np.get() === undefined) { + + // When adding a new item, make sure undo command will remove it + if(np.get() === undefined) undoit[np.astr] = null; + + np.set(newVal); + } + // update item + else { + + // If the last part of attribute string isn't a number, + // np.set is all we need. + np.set(newVal); + } +}; + +},{"../components/color":27,"../lib":122,"../plots/cartesian/axes":150,"../plots/plots":186,"../registry":194,"fast-isnumeric":13,"gl-mat4/fromQuat":14}],137:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Plotly = require('../plotly'); +var Lib = require('../lib'); +var Events = require('../lib/events'); +var Queue = require('../lib/queue'); + +var Registry = require('../registry'); +var Plots = require('../plots/plots'); +var Fx = require('../plots/cartesian/graph_interact'); +var Polar = require('../plots/polar'); + +var Drawing = require('../components/drawing'); +var ErrorBars = require('../components/errorbars'); +var xmlnsNamespaces = require('../constants/xmlns_namespaces'); +var svgTextUtils = require('../lib/svg_text_utils'); + +var helpers = require('./helpers'); +var subroutines = require('./subroutines'); + + +/** + * Main plot-creation function + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * @param {array of objects} data + * array of traces, containing the data and display information for each trace + * @param {object} layout + * object describing the overall display of the plot, + * all the stuff that doesn't pertain to any individual trace + * @param {object} config + * configuration options (see ./plot_config.js for more info) + * + */ +Plotly.plot = function(gd, data, layout, config) { + var frames; + + gd = helpers.getGraphDiv(gd); + + // Events.init is idempotent and bails early if gd has already been init'd + Events.init(gd); + + if(Lib.isPlainObject(data)) { + var obj = data; + data = obj.data; + layout = obj.layout; + config = obj.config; + frames = obj.frames; + } + + var okToPlot = Events.triggerHandler(gd, 'plotly_beforeplot', [data, layout, config]); + if(okToPlot === false) return Promise.reject(); + + // if there's no data or layout, and this isn't yet a plotly plot + // container, log a warning to help plotly.js users debug + if(!data && !layout && !Lib.isPlotDiv(gd)) { + Lib.warn('Calling Plotly.plot as if redrawing ' + + 'but this container doesn\'t yet have a plot.', gd); + } + + function addFrames() { + if(frames) { + return Plotly.addFrames(gd, frames); + } + } + + // transfer configuration options to gd until we move over to + // a more OO like model + setPlotContext(gd, config); + + if(!layout) layout = {}; + + // hook class for plots main container (in case of plotly.js + // this won't be #embedded-graph or .js-tab-contents) + d3.select(gd).classed('js-plotly-plot', true); + + // off-screen getBoundingClientRect testing space, + // in #js-plotly-tester (and stored as gd._tester) + // so we can share cached text across tabs + Drawing.makeTester(gd); + + // collect promises for any async actions during plotting + // any part of the plotting code can push to gd._promises, then + // before we move to the next step, we check that they're all + // complete, and empty out the promise list again. + gd._promises = []; + + var graphWasEmpty = ((gd.data || []).length === 0 && Array.isArray(data)); + + // if there is already data on the graph, append the new data + // if you only want to redraw, pass a non-array for data + if(Array.isArray(data)) { + helpers.cleanData(data, gd.data); + + if(graphWasEmpty) gd.data = data; + else gd.data.push.apply(gd.data, data); + + // for routines outside graph_obj that want a clean tab + // (rather than appending to an existing one) gd.empty + // is used to determine whether to make a new tab + gd.empty = false; + } + + if(!gd.layout || graphWasEmpty) gd.layout = helpers.cleanLayout(layout); + + // if the user is trying to drag the axes, allow new data and layout + // to come in but don't allow a replot. + if(gd._dragging && !gd._transitioning) { + // signal to drag handler that after everything else is done + // we need to replot, because something has changed + gd._replotPending = true; + return Promise.reject(); + } else { + // we're going ahead with a replot now + gd._replotPending = false; + } + + Plots.supplyDefaults(gd); + + // Polar plots + if(data && data[0] && data[0].r) return plotPolar(gd, data, layout); + + // so we don't try to re-call Plotly.plot from inside + // legend and colorbar, if margins changed + gd._replotting = true; + + // make or remake the framework if we need to + if(graphWasEmpty) makePlotFramework(gd); + + // polar need a different framework + if(gd.framework !== makePlotFramework) { + gd.framework = makePlotFramework; + makePlotFramework(gd); + } + + // save initial axis range once per graph + if(graphWasEmpty) Plotly.Axes.saveRangeInitial(gd); + + var fullLayout = gd._fullLayout; + + // prepare the data and find the autorange + + // generate calcdata, if we need to + // to force redoing calcdata, just delete it before calling Plotly.plot + var recalc = !gd.calcdata || gd.calcdata.length !== (gd._fullData || []).length; + if(recalc) Plots.doCalcdata(gd); + + // in case it has changed, attach fullData traces to calcdata + for(var i = 0; i < gd.calcdata.length; i++) { + gd.calcdata[i][0].trace = gd._fullData[i]; + } + + /* + * start async-friendly code - now we're actually drawing things + */ + + var oldmargins = JSON.stringify(fullLayout._size); + + // draw framework first so that margin-pushing + // components can position themselves correctly + function drawFramework() { + var basePlotModules = fullLayout._basePlotModules; + + for(var i = 0; i < basePlotModules.length; i++) { + if(basePlotModules[i].drawFramework) { + basePlotModules[i].drawFramework(gd); + } + } + + return Lib.syncOrAsync([ + subroutines.layoutStyles, + drawAxes, + Fx.init + ], gd); + } + + // draw anything that can affect margins. + // currently this is legend and colorbars + function marginPushers() { + var calcdata = gd.calcdata; + var i, cd, trace; + + Registry.getComponentMethod('legend', 'draw')(gd); + Registry.getComponentMethod('rangeselector', 'draw')(gd); + Registry.getComponentMethod('updatemenus', 'draw')(gd); + Registry.getComponentMethod('sliders', 'draw')(gd); + + for(i = 0; i < calcdata.length; i++) { + cd = calcdata[i]; + trace = cd[0].trace; + if(trace.visible !== true || !trace._module.colorbar) { + Plots.autoMargin(gd, 'cb' + trace.uid); + } + else trace._module.colorbar(gd, cd); + } + + Plots.doAutoMargin(gd); + return Plots.previousPromises(gd); + } + + // in case the margins changed, draw margin pushers again + function marginPushersAgain() { + var seq = JSON.stringify(fullLayout._size) === oldmargins ? + [] : + [marginPushers, subroutines.layoutStyles]; + + // re-initialize cartesian interaction, + // which are sometimes cleared during marginPushers + seq = seq.concat(Fx.init); + + return Lib.syncOrAsync(seq, gd); + } + + function positionAndAutorange() { + if(!recalc) return; + + var subplots = Plots.getSubplotIds(fullLayout, 'cartesian'), + modules = fullLayout._modules; + + // position and range calculations for traces that + // depend on each other ie bars (stacked or grouped) + // and boxes (grouped) push each other out of the way + + var subplotInfo, _module; + + for(var i = 0; i < subplots.length; i++) { + subplotInfo = fullLayout._plots[subplots[i]]; + + for(var j = 0; j < modules.length; j++) { + _module = modules[j]; + if(_module.setPositions) _module.setPositions(gd, subplotInfo); + } + } + + // calc and autorange for errorbars + ErrorBars.calc(gd); + + // TODO: autosize extra for text markers + return Lib.syncOrAsync([ + Registry.getComponentMethod('shapes', 'calcAutorange'), + Registry.getComponentMethod('annotations', 'calcAutorange'), + doAutoRange + ], gd); + } + + function doAutoRange() { + if(gd._transitioning) return; + + var axList = Plotly.Axes.list(gd, '', true); + for(var i = 0; i < axList.length; i++) { + Plotly.Axes.doAutoRange(axList[i]); + } + } + + // draw ticks, titles, and calculate axis scaling (._b, ._m) + function drawAxes() { + return Plotly.Axes.doTicks(gd, 'redraw'); + } + + // Now plot the data + function drawData() { + var calcdata = gd.calcdata, + i; + + // in case of traces that were heatmaps or contour maps + // previously, remove them and their colorbars explicitly + for(i = 0; i < calcdata.length; i++) { + var trace = calcdata[i][0].trace, + isVisible = (trace.visible === true), + uid = trace.uid; + + if(!isVisible || !Registry.traceIs(trace, '2dMap')) { + fullLayout._paper.selectAll( + '.hm' + uid + + ',.contour' + uid + + ',#clip' + uid + ).remove(); + } + + if(!isVisible || !trace._module.colorbar) { + fullLayout._infolayer.selectAll('.cb' + uid).remove(); + } + } + + // loop over the base plot modules present on graph + var basePlotModules = fullLayout._basePlotModules; + for(i = 0; i < basePlotModules.length; i++) { + basePlotModules[i].plot(gd); + } + + // keep reference to shape layers in subplots + var layerSubplot = fullLayout._paper.selectAll('.layer-subplot'); + fullLayout._imageSubplotLayer = layerSubplot.selectAll('.imagelayer'); + fullLayout._shapeSubplotLayer = layerSubplot.selectAll('.shapelayer'); + + // styling separate from drawing + Plots.style(gd); + + // show annotations and shapes + Registry.getComponentMethod('shapes', 'draw')(gd); + Registry.getComponentMethod('annoations', 'draw')(gd); + + // source links + Plots.addLinks(gd); + + // Mark the first render as complete + gd._replotting = false; + + return Plots.previousPromises(gd); + } + + // An initial paint must be completed before these components can be + // correctly sized and the whole plot re-margined. gd._replotting must + // be set to false before these will work properly. + function finalDraw() { + Registry.getComponentMethod('shapes', 'draw')(gd); + Registry.getComponentMethod('images', 'draw')(gd); + Registry.getComponentMethod('annotations', 'draw')(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + Registry.getComponentMethod('rangeslider', 'draw')(gd); + Registry.getComponentMethod('rangeselector', 'draw')(gd); + Registry.getComponentMethod('updatemenus', 'draw')(gd); + Registry.getComponentMethod('sliders', 'draw')(gd); + } + + function cleanUp() { + // now we're REALLY TRULY done plotting... + // so mark it as done and let other procedures call a replot + gd.emit('plotly_afterplot'); + } + + Lib.syncOrAsync([ + Plots.previousPromises, + addFrames, + drawFramework, + marginPushers, + marginPushersAgain, + positionAndAutorange, + subroutines.layoutStyles, + drawAxes, + drawData, + finalDraw + ], gd, cleanUp); + + // even if everything we did was synchronous, return a promise + // so that the caller doesn't care which route we took + return Promise.all(gd._promises).then(function() { + return gd; + }); +}; + + +function opaqueSetBackground(gd, bgColor) { + gd._fullLayout._paperdiv.style('background', 'white'); + Plotly.defaultConfig.setBackground(gd, bgColor); +} + +function setPlotContext(gd, config) { + if(!gd._context) gd._context = Lib.extendFlat({}, Plotly.defaultConfig); + var context = gd._context; + + if(config) { + Object.keys(config).forEach(function(key) { + if(key in context) { + if(key === 'setBackground' && config[key] === 'opaque') { + context[key] = opaqueSetBackground; + } + else context[key] = config[key]; + } + }); + + // map plot3dPixelRatio to plotGlPixelRatio for backward compatibility + if(config.plot3dPixelRatio && !context.plotGlPixelRatio) { + context.plotGlPixelRatio = context.plot3dPixelRatio; + } + } + + // staticPlot forces a bunch of others: + if(context.staticPlot) { + context.editable = false; + context.autosizable = false; + context.scrollZoom = false; + context.doubleClick = false; + context.showTips = false; + context.showLink = false; + context.displayModeBar = false; + } +} + +function plotPolar(gd, data, layout) { + // build or reuse the container skeleton + var plotContainer = d3.select(gd).selectAll('.plot-container') + .data([0]); + plotContainer.enter() + .insert('div', ':first-child') + .classed('plot-container plotly', true); + var paperDiv = plotContainer.selectAll('.svg-container') + .data([0]); + paperDiv.enter().append('div') + .classed('svg-container', true) + .style('position', 'relative'); + + // empty it everytime for now + paperDiv.html(''); + + // fulfill gd requirements + if(data) gd.data = data; + if(layout) gd.layout = layout; + Polar.manager.fillLayout(gd); + + // resize canvas + paperDiv.style({ + width: gd._fullLayout.width + 'px', + height: gd._fullLayout.height + 'px' + }); + + // instantiate framework + gd.framework = Polar.manager.framework(gd); + + // plot + gd.framework({data: gd.data, layout: gd.layout}, paperDiv.node()); + + // set undo point + gd.framework.setUndoPoint(); + + // get the resulting svg for extending it + var polarPlotSVG = gd.framework.svg(); + + // editable title + var opacity = 1; + var txt = gd._fullLayout.title; + if(txt === '' || !txt) opacity = 0; + var placeholderText = 'Click to enter title'; + + var titleLayout = function() { + this.call(svgTextUtils.convertToTspans); + // TODO: html/mathjax + // TODO: center title + }; + + var title = polarPlotSVG.select('.title-group text') + .call(titleLayout); + + if(gd._context.editable) { + title.attr({'data-unformatted': txt}); + if(!txt || txt === placeholderText) { + opacity = 0.2; + title.attr({'data-unformatted': placeholderText}) + .text(placeholderText) + .style({opacity: opacity}) + .on('mouseover.opacity', function() { + d3.select(this).transition().duration(100) + .style('opacity', 1); + }) + .on('mouseout.opacity', function() { + d3.select(this).transition().duration(1000) + .style('opacity', 0); + }); + } + + var setContenteditable = function() { + this.call(svgTextUtils.makeEditable) + .on('edit', function(text) { + gd.framework({layout: {title: text}}); + this.attr({'data-unformatted': text}) + .text(text) + .call(titleLayout); + this.call(setContenteditable); + }) + .on('cancel', function() { + var txt = this.attr('data-unformatted'); + this.text(txt).call(titleLayout); + }); + }; + title.call(setContenteditable); + } + + gd._context.setBackground(gd, gd._fullLayout.paper_bgcolor); + Plots.addLinks(gd); + + return Promise.resolve(); +} + +// convenience function to force a full redraw, mostly for use by plotly.js +Plotly.redraw = function(gd) { + gd = helpers.getGraphDiv(gd); + + if(!Lib.isPlotDiv(gd)) { + throw new Error('This element is not a Plotly plot: ' + gd); + } + + helpers.cleanData(gd.data, gd.data); + helpers.cleanLayout(gd.layout); + + gd.calcdata = undefined; + return Plotly.plot(gd).then(function() { + gd.emit('plotly_redraw'); + return gd; + }); +}; + +/** + * Convenience function to make idempotent plot option obvious to users. + * + * @param gd + * @param {Object[]} data + * @param {Object} layout + * @param {Object} config + */ +Plotly.newPlot = function(gd, data, layout, config) { + gd = helpers.getGraphDiv(gd); + + // remove gl contexts + Plots.cleanPlot([], {}, gd._fullData || {}, gd._fullLayout || {}); + + Plots.purge(gd); + return Plotly.plot(gd, data, layout, config); +}; + +/** + * Wrap negative indicies to their positive counterparts. + * + * @param {Number[]} indices An array of indices + * @param {Number} maxIndex The maximum index allowable (arr.length - 1) + */ +function positivifyIndices(indices, maxIndex) { + var parentLength = maxIndex + 1, + positiveIndices = [], + i, + index; + + for(i = 0; i < indices.length; i++) { + index = indices[i]; + if(index < 0) { + positiveIndices.push(parentLength + index); + } else { + positiveIndices.push(index); + } + } + return positiveIndices; +} + +/** + * Ensures that an index array for manipulating gd.data is valid. + * + * Intended for use with addTraces, deleteTraces, and moveTraces. + * + * @param gd + * @param indices + * @param arrayName + */ +function assertIndexArray(gd, indices, arrayName) { + var i, + index; + + for(i = 0; i < indices.length; i++) { + index = indices[i]; + + // validate that indices are indeed integers + if(index !== parseInt(index, 10)) { + throw new Error('all values in ' + arrayName + ' must be integers'); + } + + // check that all indices are in bounds for given gd.data array length + if(index >= gd.data.length || index < -gd.data.length) { + throw new Error(arrayName + ' must be valid indices for gd.data.'); + } + + // check that indices aren't repeated + if(indices.indexOf(index, i + 1) > -1 || + index >= 0 && indices.indexOf(-gd.data.length + index) > -1 || + index < 0 && indices.indexOf(gd.data.length + index) > -1) { + throw new Error('each index in ' + arrayName + ' must be unique.'); + } + } +} + +/** + * Private function used by Plotly.moveTraces to check input args + * + * @param gd + * @param currentIndices + * @param newIndices + */ +function checkMoveTracesArgs(gd, currentIndices, newIndices) { + + // check that gd has attribute 'data' and 'data' is array + if(!Array.isArray(gd.data)) { + throw new Error('gd.data must be an array.'); + } + + // validate currentIndices array + if(typeof currentIndices === 'undefined') { + throw new Error('currentIndices is a required argument.'); + } else if(!Array.isArray(currentIndices)) { + currentIndices = [currentIndices]; + } + assertIndexArray(gd, currentIndices, 'currentIndices'); + + // validate newIndices array if it exists + if(typeof newIndices !== 'undefined' && !Array.isArray(newIndices)) { + newIndices = [newIndices]; + } + if(typeof newIndices !== 'undefined') { + assertIndexArray(gd, newIndices, 'newIndices'); + } + + // check currentIndices and newIndices are the same length if newIdices exists + if(typeof newIndices !== 'undefined' && currentIndices.length !== newIndices.length) { + throw new Error('current and new indices must be of equal length.'); + } + +} +/** + * A private function to reduce the type checking clutter in addTraces. + * + * @param gd + * @param traces + * @param newIndices + */ +function checkAddTracesArgs(gd, traces, newIndices) { + var i, + value; + + // check that gd has attribute 'data' and 'data' is array + if(!Array.isArray(gd.data)) { + throw new Error('gd.data must be an array.'); + } + + // make sure traces exists + if(typeof traces === 'undefined') { + throw new Error('traces must be defined.'); + } + + // make sure traces is an array + if(!Array.isArray(traces)) { + traces = [traces]; + } + + // make sure each value in traces is an object + for(i = 0; i < traces.length; i++) { + value = traces[i]; + if(typeof value !== 'object' || (Array.isArray(value) || value === null)) { + throw new Error('all values in traces array must be non-array objects'); + } + } + + // make sure we have an index for each trace + if(typeof newIndices !== 'undefined' && !Array.isArray(newIndices)) { + newIndices = [newIndices]; + } + if(typeof newIndices !== 'undefined' && newIndices.length !== traces.length) { + throw new Error( + 'if indices is specified, traces.length must equal indices.length' + ); + } +} + +/** + * A private function to reduce the type checking clutter in spliceTraces. + * Get all update Properties from gd.data. Validate inputs and outputs. + * Used by prependTrace and extendTraces + * + * @param gd + * @param update + * @param indices + * @param maxPoints + */ +function assertExtendTracesArgs(gd, update, indices, maxPoints) { + + var maxPointsIsObject = Lib.isPlainObject(maxPoints); + + if(!Array.isArray(gd.data)) { + throw new Error('gd.data must be an array'); + } + if(!Lib.isPlainObject(update)) { + throw new Error('update must be a key:value object'); + } + + if(typeof indices === 'undefined') { + throw new Error('indices must be an integer or array of integers'); + } + + assertIndexArray(gd, indices, 'indices'); + + for(var key in update) { + + /* + * Verify that the attribute to be updated contains as many trace updates + * as indices. Failure must result in throw and no-op + */ + if(!Array.isArray(update[key]) || update[key].length !== indices.length) { + throw new Error('attribute ' + key + ' must be an array of length equal to indices array length'); + } + + /* + * if maxPoints is an object it must match keys and array lengths of 'update' 1:1 + */ + if(maxPointsIsObject && + (!(key in maxPoints) || !Array.isArray(maxPoints[key]) || + maxPoints[key].length !== update[key].length)) { + throw new Error('when maxPoints is set as a key:value object it must contain a 1:1 ' + + 'corrispondence with the keys and number of traces in the update object'); + } + } +} + +/** + * A private function to reduce the type checking clutter in spliceTraces. + * + * @param {Object|HTMLDivElement} gd + * @param {Object} update + * @param {Number[]} indices + * @param {Number||Object} maxPoints + * @return {Object[]} + */ +function getExtendProperties(gd, update, indices, maxPoints) { + + var maxPointsIsObject = Lib.isPlainObject(maxPoints), + updateProps = []; + var trace, target, prop, insert, maxp; + + // allow scalar index to represent a single trace position + if(!Array.isArray(indices)) indices = [indices]; + + // negative indices are wrapped around to their positive value. Equivalent to python indexing. + indices = positivifyIndices(indices, gd.data.length - 1); + + // loop through all update keys and traces and harvest validated data. + for(var key in update) { + + for(var j = 0; j < indices.length; j++) { + + /* + * Choose the trace indexed by the indices map argument and get the prop setter-getter + * instance that references the key and value for this particular trace. + */ + trace = gd.data[indices[j]]; + prop = Lib.nestedProperty(trace, key); + + /* + * Target is the existing gd.data.trace.dataArray value like "x" or "marker.size" + * Target must exist as an Array to allow the extend operation to be performed. + */ + target = prop.get(); + insert = update[key][j]; + + if(!Array.isArray(insert)) { + throw new Error('attribute: ' + key + ' index: ' + j + ' must be an array'); + } + if(!Array.isArray(target)) { + throw new Error('cannot extend missing or non-array attribute: ' + key); + } + + /* + * maxPoints may be an object map or a scalar. If object select the key:value, else + * Use the scalar maxPoints for all key and trace combinations. + */ + maxp = maxPointsIsObject ? maxPoints[key][j] : maxPoints; + + // could have chosen null here, -1 just tells us to not take a window + if(!isNumeric(maxp)) maxp = -1; + + /* + * Wrap the nestedProperty in an object containing required data + * for lengthening and windowing this particular trace - key combination. + * Flooring maxp mirrors the behaviour of floats in the Array.slice JSnative function. + */ + updateProps.push({ + prop: prop, + target: target, + insert: insert, + maxp: Math.floor(maxp) + }); + } + } + + // all target and insertion data now validated + return updateProps; +} + +/** + * A private function to key Extend and Prepend traces DRY + * + * @param {Object|HTMLDivElement} gd + * @param {Object} update + * @param {Number[]} indices + * @param {Number||Object} maxPoints + * @param {Function} lengthenArray + * @param {Function} spliceArray + * @return {Object} + */ +function spliceTraces(gd, update, indices, maxPoints, lengthenArray, spliceArray) { + + assertExtendTracesArgs(gd, update, indices, maxPoints); + + var updateProps = getExtendProperties(gd, update, indices, maxPoints), + remainder = [], + undoUpdate = {}, + undoPoints = {}; + var target, prop, maxp; + + for(var i = 0; i < updateProps.length; i++) { + + /* + * prop is the object returned by Lib.nestedProperties + */ + prop = updateProps[i].prop; + maxp = updateProps[i].maxp; + + target = lengthenArray(updateProps[i].target, updateProps[i].insert); + + /* + * If maxp is set within post-extension trace.length, splice to maxp length. + * Otherwise skip function call as splice op will have no effect anyway. + */ + if(maxp >= 0 && maxp < target.length) remainder = spliceArray(target, maxp); + + /* + * to reverse this operation we need the size of the original trace as the reverse + * operation will need to window out any lengthening operation performed in this pass. + */ + maxp = updateProps[i].target.length; + + /* + * Magic happens here! update gd.data.trace[key] with new array data. + */ + prop.set(target); + + if(!Array.isArray(undoUpdate[prop.astr])) undoUpdate[prop.astr] = []; + if(!Array.isArray(undoPoints[prop.astr])) undoPoints[prop.astr] = []; + + /* + * build the inverse update object for the undo operation + */ + undoUpdate[prop.astr].push(remainder); + + /* + * build the matching maxPoints undo object containing original trace lengths. + */ + undoPoints[prop.astr].push(maxp); + } + + return {update: undoUpdate, maxPoints: undoPoints}; +} + +/** + * extend && prepend traces at indices with update arrays, window trace lengths to maxPoints + * + * Extend and Prepend have identical APIs. Prepend inserts an array at the head while Extend + * inserts an array off the tail. Prepend truncates the tail of the array - counting maxPoints + * from the head, whereas Extend truncates the head of the array, counting backward maxPoints + * from the tail. + * + * If maxPoints is undefined, nonNumeric, negative or greater than extended trace length no + * truncation / windowing will be performed. If its zero, well the whole trace is truncated. + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object} update The key:array map of target attributes to extend + * @param {Number|Number[]} indices The locations of traces to be extended + * @param {Number|Object} [maxPoints] Number of points for trace window after lengthening. + * + */ +Plotly.extendTraces = function extendTraces(gd, update, indices, maxPoints) { + gd = helpers.getGraphDiv(gd); + + var undo = spliceTraces(gd, update, indices, maxPoints, + + /* + * The Lengthen operation extends trace from end with insert + */ + function(target, insert) { + return target.concat(insert); + }, + + /* + * Window the trace keeping maxPoints, counting back from the end + */ + function(target, maxPoints) { + return target.splice(0, target.length - maxPoints); + }); + + var promise = Plotly.redraw(gd); + + var undoArgs = [gd, undo.update, indices, undo.maxPoints]; + Queue.add(gd, Plotly.prependTraces, undoArgs, extendTraces, arguments); + + return promise; +}; + +Plotly.prependTraces = function prependTraces(gd, update, indices, maxPoints) { + gd = helpers.getGraphDiv(gd); + + var undo = spliceTraces(gd, update, indices, maxPoints, + + /* + * The Lengthen operation extends trace by appending insert to start + */ + function(target, insert) { + return insert.concat(target); + }, + + /* + * Window the trace keeping maxPoints, counting forward from the start + */ + function(target, maxPoints) { + return target.splice(maxPoints, target.length); + }); + + var promise = Plotly.redraw(gd); + + var undoArgs = [gd, undo.update, indices, undo.maxPoints]; + Queue.add(gd, Plotly.extendTraces, undoArgs, prependTraces, arguments); + + return promise; +}; + +/** + * Add data traces to an existing graph div. + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object[]} gd.data The array of traces we're adding to + * @param {Object[]|Object} traces The object or array of objects to add + * @param {Number[]|Number} [newIndices=[gd.data.length]] Locations to add traces + * + */ +Plotly.addTraces = function addTraces(gd, traces, newIndices) { + gd = helpers.getGraphDiv(gd); + + var currentIndices = [], + undoFunc = Plotly.deleteTraces, + redoFunc = addTraces, + undoArgs = [gd, currentIndices], + redoArgs = [gd, traces], // no newIndices here + i, + promise; + + // all validation is done elsewhere to remove clutter here + checkAddTracesArgs(gd, traces, newIndices); + + // make sure traces is an array + if(!Array.isArray(traces)) { + traces = [traces]; + } + helpers.cleanData(traces, gd.data); + + // add the traces to gd.data (no redrawing yet!) + for(i = 0; i < traces.length; i += 1) { + gd.data.push(traces[i]); + } + + // to continue, we need to call moveTraces which requires currentIndices + for(i = 0; i < traces.length; i++) { + currentIndices.push(-traces.length + i); + } + + // if the user didn't define newIndices, they just want the traces appended + // i.e., we can simply redraw and be done + if(typeof newIndices === 'undefined') { + promise = Plotly.redraw(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + return promise; + } + + // make sure indices is property defined + if(!Array.isArray(newIndices)) { + newIndices = [newIndices]; + } + + try { + + // this is redundant, but necessary to not catch later possible errors! + checkMoveTracesArgs(gd, currentIndices, newIndices); + } + catch(error) { + + // something went wrong, reset gd to be safe and rethrow error + gd.data.splice(gd.data.length - traces.length, traces.length); + throw error; + } + + // if we're here, the user has defined specific places to place the new traces + // this requires some extra work that moveTraces will do + Queue.startSequence(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + promise = Plotly.moveTraces(gd, currentIndices, newIndices); + Queue.stopSequence(gd); + return promise; +}; + +/** + * Delete traces at `indices` from gd.data array. + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object[]} gd.data The array of traces we're removing from + * @param {Number|Number[]} indices The indices + */ +Plotly.deleteTraces = function deleteTraces(gd, indices) { + gd = helpers.getGraphDiv(gd); + + var traces = [], + undoFunc = Plotly.addTraces, + redoFunc = deleteTraces, + undoArgs = [gd, traces, indices], + redoArgs = [gd, indices], + i, + deletedTrace; + + // make sure indices are defined + if(typeof indices === 'undefined') { + throw new Error('indices must be an integer or array of integers.'); + } else if(!Array.isArray(indices)) { + indices = [indices]; + } + assertIndexArray(gd, indices, 'indices'); + + // convert negative indices to positive indices + indices = positivifyIndices(indices, gd.data.length - 1); + + // we want descending here so that splicing later doesn't affect indexing + indices.sort(Lib.sorterDes); + for(i = 0; i < indices.length; i += 1) { + deletedTrace = gd.data.splice(indices[i], 1)[0]; + traces.push(deletedTrace); + } + + var promise = Plotly.redraw(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return promise; +}; + +/** + * Move traces at currentIndices array to locations in newIndices array. + * + * If newIndices is omitted, currentIndices will be moved to the end. E.g., + * these are equivalent: + * + * Plotly.moveTraces(gd, [1, 2, 3], [-3, -2, -1]) + * Plotly.moveTraces(gd, [1, 2, 3]) + * + * @param {Object|HTMLDivElement} gd The graph div + * @param {Object[]} gd.data The array of traces we're removing from + * @param {Number|Number[]} currentIndices The locations of traces to be moved + * @param {Number|Number[]} [newIndices] The locations to move traces to + * + * Example calls: + * + * // move trace i to location x + * Plotly.moveTraces(gd, i, x) + * + * // move trace i to end of array + * Plotly.moveTraces(gd, i) + * + * // move traces i, j, k to end of array (i != j != k) + * Plotly.moveTraces(gd, [i, j, k]) + * + * // move traces [i, j, k] to [x, y, z] (i != j != k) (x != y != z) + * Plotly.moveTraces(gd, [i, j, k], [x, y, z]) + * + * // reorder all traces (assume there are 5--a, b, c, d, e) + * Plotly.moveTraces(gd, [b, d, e, a, c]) // same as 'move to end' + */ +Plotly.moveTraces = function moveTraces(gd, currentIndices, newIndices) { + gd = helpers.getGraphDiv(gd); + + var newData = [], + movingTraceMap = [], + undoFunc = moveTraces, + redoFunc = moveTraces, + undoArgs = [gd, newIndices, currentIndices], + redoArgs = [gd, currentIndices, newIndices], + i; + + // to reduce complexity here, check args elsewhere + // this throws errors where appropriate + checkMoveTracesArgs(gd, currentIndices, newIndices); + + // make sure currentIndices is an array + currentIndices = Array.isArray(currentIndices) ? currentIndices : [currentIndices]; + + // if undefined, define newIndices to point to the end of gd.data array + if(typeof newIndices === 'undefined') { + newIndices = []; + for(i = 0; i < currentIndices.length; i++) { + newIndices.push(-currentIndices.length + i); + } + } + + // make sure newIndices is an array if it's user-defined + newIndices = Array.isArray(newIndices) ? newIndices : [newIndices]; + + // convert negative indices to positive indices (they're the same length) + currentIndices = positivifyIndices(currentIndices, gd.data.length - 1); + newIndices = positivifyIndices(newIndices, gd.data.length - 1); + + // at this point, we've coerced the index arrays into predictable forms + + // get the traces that aren't being moved around + for(i = 0; i < gd.data.length; i++) { + + // if index isn't in currentIndices, include it in ignored! + if(currentIndices.indexOf(i) === -1) { + newData.push(gd.data[i]); + } + } + + // get a mapping of indices to moving traces + for(i = 0; i < currentIndices.length; i++) { + movingTraceMap.push({newIndex: newIndices[i], trace: gd.data[currentIndices[i]]}); + } + + // reorder this mapping by newIndex, ascending + movingTraceMap.sort(function(a, b) { + return a.newIndex - b.newIndex; + }); + + // now, add the moving traces back in, in order! + for(i = 0; i < movingTraceMap.length; i += 1) { + newData.splice(movingTraceMap[i].newIndex, 0, movingTraceMap[i].trace); + } + + gd.data = newData; + + var promise = Plotly.redraw(gd); + Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return promise; +}; + +/** + * restyle: update trace attributes of an existing plot + * + * Can be called two ways. + * + * Signature 1: + * @param {String | HTMLDivElement} gd + * the id or DOM element of the graph container div + * @param {String} astr + * attribute string (like `'marker.symbol'`) to update + * @param {*} val + * value to give this attribute + * @param {Number[] | Number} [traces] + * integer or array of integers for the traces to alter (all if omitted) + * + * Signature 2: + * @param {String | HTMLDivElement} gd + * (as in signature 1) + * @param {Object} aobj + * attribute object `{astr1: val1, astr2: val2 ...}` + * allows setting multiple attributes simultaneously + * @param {Number[] | Number} [traces] + * (as in signature 1) + * + * `val` (or `val1`, `val2` ... in the object form) can be an array, + * to apply different values to each trace. + * + * If the array is too short, it will wrap around (useful for + * style files that want to specify cyclical default values). + */ +Plotly.restyle = function restyle(gd, astr, val, traces) { + gd = helpers.getGraphDiv(gd); + helpers.clearPromiseQueue(gd); + + var aobj = {}; + if(typeof astr === 'string') aobj[astr] = val; + else if(Lib.isPlainObject(astr)) { + // the 3-arg form + aobj = astr; + if(traces === undefined) traces = val; + } + else { + Lib.warn('Restyle fail.', astr, val, traces); + return Promise.reject(); + } + + if(Object.keys(aobj).length) gd.changed = true; + + var specs = _restyle(gd, aobj, traces), + flags = specs.flags; + + // clear calcdata if required + if(flags.clearCalc) gd.calcdata = undefined; + + // fill in redraw sequence + var seq = []; + + if(flags.fullReplot) { + seq.push(Plotly.plot); + } + else { + seq.push(Plots.previousPromises); + + Plots.supplyDefaults(gd); + + if(flags.dostyle) seq.push(subroutines.doTraceStyle); + if(flags.docolorbars) seq.push(subroutines.doColorBars); + } + + Queue.add(gd, + restyle, [gd, specs.undoit, specs.traces], + restyle, [gd, specs.redoit, specs.traces] + ); + + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(); + + return plotDone.then(function() { + gd.emit('plotly_restyle', specs.eventData); + return gd; + }); +}; + +function _restyle(gd, aobj, _traces) { + var fullLayout = gd._fullLayout, + fullData = gd._fullData, + data = gd.data, + i; + + var traces = helpers.coerceTraceIndices(gd, _traces); + + // initialize flags + var flags = { + docalc: false, + docalcAutorange: false, + doplot: false, + dostyle: false, + docolorbars: false, + autorangeOn: false, + clearCalc: false, + fullReplot: false + }; + + // copies of the change (and previous values of anything affected) + // for the undo / redo queue + var redoit = {}, + undoit = {}, + axlist, + flagAxForDelete = {}; + + // recalcAttrs attributes need a full regeneration of calcdata + // as well as a replot, because the right objects may not exist, + // or autorange may need recalculating + // in principle we generally shouldn't need to redo ALL traces... that's + // harder though. + var recalcAttrs = [ + 'mode', 'visible', 'type', 'orientation', 'fill', + 'histfunc', 'histnorm', 'text', + 'x', 'y', 'z', + 'a', 'b', 'c', + 'open', 'high', 'low', 'close', + 'base', 'width', 'offset', + 'xtype', 'x0', 'dx', 'ytype', 'y0', 'dy', 'xaxis', 'yaxis', + 'line.width', + 'connectgaps', 'transpose', 'zsmooth', + 'showscale', 'marker.showscale', + 'zauto', 'marker.cauto', + 'autocolorscale', 'marker.autocolorscale', + 'colorscale', 'marker.colorscale', + 'reversescale', 'marker.reversescale', + 'autobinx', 'nbinsx', 'xbins', 'xbins.start', 'xbins.end', 'xbins.size', + 'autobiny', 'nbinsy', 'ybins', 'ybins.start', 'ybins.end', 'ybins.size', + 'autocontour', 'ncontours', 'contours', 'contours.coloring', + 'error_y', 'error_y.visible', 'error_y.value', 'error_y.type', + 'error_y.traceref', 'error_y.array', 'error_y.symmetric', + 'error_y.arrayminus', 'error_y.valueminus', 'error_y.tracerefminus', + 'error_x', 'error_x.visible', 'error_x.value', 'error_x.type', + 'error_x.traceref', 'error_x.array', 'error_x.symmetric', + 'error_x.arrayminus', 'error_x.valueminus', 'error_x.tracerefminus', + 'swapxy', 'swapxyaxes', 'orientationaxes', + 'marker.colors', 'values', 'labels', 'label0', 'dlabel', 'sort', + 'textinfo', 'textposition', 'textfont.size', 'textfont.family', 'textfont.color', + 'insidetextfont.size', 'insidetextfont.family', 'insidetextfont.color', + 'outsidetextfont.size', 'outsidetextfont.family', 'outsidetextfont.color', + 'hole', 'scalegroup', 'domain', 'domain.x', 'domain.y', + 'domain.x[0]', 'domain.x[1]', 'domain.y[0]', 'domain.y[1]', + 'tilt', 'tiltaxis', 'depth', 'direction', 'rotation', 'pull', + 'line.showscale', 'line.cauto', 'line.autocolorscale', 'line.reversescale', + 'marker.line.showscale', 'marker.line.cauto', 'marker.line.autocolorscale', 'marker.line.reversescale' + ]; + + for(i = 0; i < traces.length; i++) { + if(Registry.traceIs(fullData[traces[i]], 'box')) { + recalcAttrs.push('name'); + break; + } + } + + // autorangeAttrs attributes need a full redo of calcdata + // only if an axis is autoranged, + // because .calc() is where the autorange gets determined + // TODO: could we break this out as well? + var autorangeAttrs = [ + 'marker', 'marker.size', 'textfont', + 'boxpoints', 'jitter', 'pointpos', 'whiskerwidth', 'boxmean', + 'tickwidth' + ]; + + // replotAttrs attributes need a replot (because different + // objects need to be made) but not a recalc + var replotAttrs = [ + 'zmin', 'zmax', 'zauto', + 'xgap', 'ygap', + 'marker.cmin', 'marker.cmax', 'marker.cauto', + 'line.cmin', 'line.cmax', + 'marker.line.cmin', 'marker.line.cmax', + 'contours.start', 'contours.end', 'contours.size', + 'contours.showlines', + 'line', 'line.smoothing', 'line.shape', + 'error_y.width', 'error_x.width', 'error_x.copy_ystyle', + 'marker.maxdisplayed' + ]; + + // these ones may alter the axis type + // (at least if the first trace is involved) + var axtypeAttrs = [ + 'type', 'x', 'y', 'x0', 'y0', 'orientation', 'xaxis', 'yaxis' + ]; + + var zscl = ['zmin', 'zmax'], + xbins = ['xbins.start', 'xbins.end', 'xbins.size'], + ybins = ['ybins.start', 'ybins.end', 'ybins.size'], + contourAttrs = ['contours.start', 'contours.end', 'contours.size']; + + // At the moment, only cartesian, pie and ternary plot types can afford + // to not go through a full replot + var doPlotWhiteList = ['cartesian', 'pie', 'ternary']; + fullLayout._basePlotModules.forEach(function(_module) { + if(doPlotWhiteList.indexOf(_module.name) === -1) flags.docalc = true; + }); + + // make a new empty vals array for undoit + function a0() { return traces.map(function() { return undefined; }); } + + // for autoranging multiple axes + function addToAxlist(axid) { + var axName = Plotly.Axes.id2name(axid); + if(axlist.indexOf(axName) === -1) axlist.push(axName); + } + + function autorangeAttr(axName) { return 'LAYOUT' + axName + '.autorange'; } + + function rangeAttr(axName) { return 'LAYOUT' + axName + '.range'; } + + // for attrs that interact (like scales & autoscales), save the + // old vals before making the change + // val=undefined will not set a value, just record what the value was. + // val=null will delete the attribute + // attr can be an array to set several at once (all to the same val) + function doextra(attr, val, i) { + if(Array.isArray(attr)) { + attr.forEach(function(a) { doextra(a, val, i); }); + return; + } + // quit if explicitly setting this elsewhere + if(attr in aobj) return; + + var extraparam; + if(attr.substr(0, 6) === 'LAYOUT') { + extraparam = Lib.nestedProperty(gd.layout, attr.replace('LAYOUT', '')); + } else { + extraparam = Lib.nestedProperty(data[traces[i]], attr); + } + + if(!(attr in undoit)) { + undoit[attr] = a0(); + } + if(undoit[attr][i] === undefined) { + undoit[attr][i] = extraparam.get(); + } + if(val !== undefined) { + extraparam.set(val); + } + } + + // now make the changes to gd.data (and occasionally gd.layout) + // and figure out what kind of graphics update we need to do + for(var ai in aobj) { + var vi = aobj[ai], + cont, + contFull, + param, + oldVal, + newVal; + + redoit[ai] = vi; + + if(ai.substr(0, 6) === 'LAYOUT') { + param = Lib.nestedProperty(gd.layout, ai.replace('LAYOUT', '')); + undoit[ai] = [param.get()]; + // since we're allowing val to be an array, allow it here too, + // even though that's meaningless + param.set(Array.isArray(vi) ? vi[0] : vi); + // ironically, the layout attrs in restyle only require replot, + // not relayout + flags.docalc = true; + continue; + } + + // set attribute in gd.data + undoit[ai] = a0(); + for(i = 0; i < traces.length; i++) { + cont = data[traces[i]]; + contFull = fullData[traces[i]]; + param = Lib.nestedProperty(cont, ai); + oldVal = param.get(); + newVal = Array.isArray(vi) ? vi[i % vi.length] : vi; + + if(newVal === undefined) continue; + + // setting bin or z settings should turn off auto + // and setting auto should save bin or z settings + if(zscl.indexOf(ai) !== -1) { + doextra('zauto', false, i); + } + else if(ai === 'colorscale') { + doextra('autocolorscale', false, i); + } + else if(ai === 'autocolorscale') { + doextra('colorscale', undefined, i); + } + else if(ai === 'marker.colorscale') { + doextra('marker.autocolorscale', false, i); + } + else if(ai === 'marker.autocolorscale') { + doextra('marker.colorscale', undefined, i); + } + else if(ai === 'zauto') { + doextra(zscl, undefined, i); + } + else if(xbins.indexOf(ai) !== -1) { + doextra('autobinx', false, i); + } + else if(ai === 'autobinx') { + doextra(xbins, undefined, i); + } + else if(ybins.indexOf(ai) !== -1) { + doextra('autobiny', false, i); + } + else if(ai === 'autobiny') { + doextra(ybins, undefined, i); + } + else if(contourAttrs.indexOf(ai) !== -1) { + doextra('autocontour', false, i); + } + else if(ai === 'autocontour') { + doextra(contourAttrs, undefined, i); + } + // heatmaps: setting x0 or dx, y0 or dy, + // should turn xtype/ytype to 'scaled' if 'array' + else if(['x0', 'dx'].indexOf(ai) !== -1 && + contFull.x && contFull.xtype !== 'scaled') { + doextra('xtype', 'scaled', i); + } + else if(['y0', 'dy'].indexOf(ai) !== -1 && + contFull.y && contFull.ytype !== 'scaled') { + doextra('ytype', 'scaled', i); + } + // changing colorbar size modes, + // make the resulting size not change + // note that colorbar fractional sizing is based on the + // original plot size, before anything (like a colorbar) + // increases the margins + else if(ai === 'colorbar.thicknessmode' && param.get() !== newVal && + ['fraction', 'pixels'].indexOf(newVal) !== -1 && + contFull.colorbar) { + var thicknorm = + ['top', 'bottom'].indexOf(contFull.colorbar.orient) !== -1 ? + (fullLayout.height - fullLayout.margin.t - fullLayout.margin.b) : + (fullLayout.width - fullLayout.margin.l - fullLayout.margin.r); + doextra('colorbar.thickness', contFull.colorbar.thickness * + (newVal === 'fraction' ? 1 / thicknorm : thicknorm), i); + } + else if(ai === 'colorbar.lenmode' && param.get() !== newVal && + ['fraction', 'pixels'].indexOf(newVal) !== -1 && + contFull.colorbar) { + var lennorm = + ['top', 'bottom'].indexOf(contFull.colorbar.orient) !== -1 ? + (fullLayout.width - fullLayout.margin.l - fullLayout.margin.r) : + (fullLayout.height - fullLayout.margin.t - fullLayout.margin.b); + doextra('colorbar.len', contFull.colorbar.len * + (newVal === 'fraction' ? 1 / lennorm : lennorm), i); + } + else if(ai === 'colorbar.tick0' || ai === 'colorbar.dtick') { + doextra('colorbar.tickmode', 'linear', i); + } + else if(ai === 'colorbar.tickmode') { + doextra(['colorbar.tick0', 'colorbar.dtick'], undefined, i); + } + + + if(ai === 'type' && (newVal === 'pie') !== (oldVal === 'pie')) { + var labelsTo = 'x', + valuesTo = 'y'; + if((newVal === 'bar' || oldVal === 'bar') && cont.orientation === 'h') { + labelsTo = 'y'; + valuesTo = 'x'; + } + Lib.swapAttrs(cont, ['?', '?src'], 'labels', labelsTo); + Lib.swapAttrs(cont, ['d?', '?0'], 'label', labelsTo); + Lib.swapAttrs(cont, ['?', '?src'], 'values', valuesTo); + + if(oldVal === 'pie') { + Lib.nestedProperty(cont, 'marker.color') + .set(Lib.nestedProperty(cont, 'marker.colors').get()); + + // super kludgy - but if all pies are gone we won't remove them otherwise + fullLayout._pielayer.selectAll('g.trace').remove(); + } else if(Registry.traceIs(cont, 'cartesian')) { + Lib.nestedProperty(cont, 'marker.colors') + .set(Lib.nestedProperty(cont, 'marker.color').get()); + // look for axes that are no longer in use and delete them + flagAxForDelete[cont.xaxis || 'x'] = true; + flagAxForDelete[cont.yaxis || 'y'] = true; + } + } + + undoit[ai][i] = oldVal; + // set the new value - if val is an array, it's one el per trace + // first check for attributes that get more complex alterations + var swapAttrs = [ + 'swapxy', 'swapxyaxes', 'orientation', 'orientationaxes' + ]; + if(swapAttrs.indexOf(ai) !== -1) { + // setting an orientation: make sure it's changing + // before we swap everything else + if(ai === 'orientation') { + param.set(newVal); + if(param.get() === undoit[ai][i]) continue; + } + // orientationaxes has no value, + // it flips everything and the axes + else if(ai === 'orientationaxes') { + cont.orientation = + {v: 'h', h: 'v'}[contFull.orientation]; + } + helpers.swapXYData(cont); + } + else if(Plots.dataArrayContainers.indexOf(param.parts[0]) !== -1) { + helpers.manageArrayContainers(param, newVal, undoit); + flags.docalc = true; + } + // all the other ones, just modify that one attribute + else param.set(newVal); + + } + + // swap the data attributes of the relevant x and y axes? + if(['swapxyaxes', 'orientationaxes'].indexOf(ai) !== -1) { + Plotly.Axes.swap(gd, traces); + } + + // swap hovermode if set to "compare x/y data" + if(ai === 'orientationaxes') { + var hovermode = Lib.nestedProperty(gd.layout, 'hovermode'); + if(hovermode.get() === 'x') { + hovermode.set('y'); + } else if(hovermode.get() === 'y') { + hovermode.set('x'); + } + } + + // check if we need to call axis type + if((traces.indexOf(0) !== -1) && (axtypeAttrs.indexOf(ai) !== -1)) { + Plotly.Axes.clearTypes(gd, traces); + flags.docalc = true; + } + + // switching from auto to manual binning or z scaling doesn't + // actually do anything but change what you see in the styling + // box. everything else at least needs to apply styles + if((['autobinx', 'autobiny', 'zauto'].indexOf(ai) === -1) || + newVal !== false) { + flags.dostyle = true; + } + if(['colorbar', 'line'].indexOf(param.parts[0]) !== -1 || + param.parts[0] === 'marker' && param.parts[1] === 'colorbar') { + flags.docolorbars = true; + } + + if(recalcAttrs.indexOf(ai) !== -1) { + // major enough changes deserve autoscale, autobin, and + // non-reversed axes so people don't get confused + if(['orientation', 'type'].indexOf(ai) !== -1) { + axlist = []; + for(i = 0; i < traces.length; i++) { + var trace = data[traces[i]]; + + if(Registry.traceIs(trace, 'cartesian')) { + addToAxlist(trace.xaxis || 'x'); + addToAxlist(trace.yaxis || 'y'); + + if(ai === 'type') { + doextra(['autobinx', 'autobiny'], true, i); + } + } + } + + doextra(axlist.map(autorangeAttr), true, 0); + doextra(axlist.map(rangeAttr), [0, 1], 0); + } + flags.docalc = true; + } + else if(replotAttrs.indexOf(ai) !== -1) flags.doplot = true; + else if(autorangeAttrs.indexOf(ai) !== -1) flags.docalcAutorange = true; + } + + // do we need to force a recalc? + Plotly.Axes.list(gd).forEach(function(ax) { + if(ax.autorange) flags.autorangeOn = true; + }); + + // check axes we've flagged for possible deletion + // flagAxForDelete is a hash so we can make sure we only get each axis once + var axListForDelete = Object.keys(flagAxForDelete); + axisLoop: + for(i = 0; i < axListForDelete.length; i++) { + var axId = axListForDelete[i], + axLetter = axId.charAt(0), + axAttr = axLetter + 'axis'; + + for(var j = 0; j < data.length; j++) { + if(Registry.traceIs(data[j], 'cartesian') && + (data[j][axAttr] || axLetter) === axId) { + continue axisLoop; + } + } + + // no data on this axis - delete it. + doextra('LAYOUT' + Plotly.Axes.id2name(axId), null, 0); + } + + // combine a few flags together; + if(flags.docalc || (flags.docalcAutorange && flags.autorangeOn)) { + flags.clearCalc = true; + } + if(flags.docalc || flags.doplot || flags.docalcAutorange) { + flags.fullReplot = true; + } + + return { + flags: flags, + undoit: undoit, + redoit: redoit, + traces: traces, + eventData: Lib.extendDeepNoArrays([], [redoit, traces]) + }; +} + +/** + * relayout: update layout attributes of an existing plot + * + * Can be called two ways: + * + * Signature 1: + * @param {String | HTMLDivElement} gd + * the id or dom element of the graph container div + * @param {String} astr + * attribute string (like `'xaxis.range[0]'`) to update + * @param {*} val + * value to give this attribute + * + * Signature 2: + * @param {String | HTMLDivElement} gd + * (as in signature 1) + * @param {Object} aobj + * attribute object `{astr1: val1, astr2: val2 ...}` + * allows setting multiple attributes simultaneously + */ +Plotly.relayout = function relayout(gd, astr, val) { + gd = helpers.getGraphDiv(gd); + helpers.clearPromiseQueue(gd); + + if(gd.framework && gd.framework.isPolar) { + return Promise.resolve(gd); + } + + var aobj = {}; + if(typeof astr === 'string') aobj[astr] = val; + else if(Lib.isPlainObject(astr)) aobj = astr; + else { + Lib.warn('Relayout fail.', astr, val); + return Promise.reject(); + } + + if(Object.keys(aobj).length) gd.changed = true; + + var specs = _relayout(gd, aobj), + flags = specs.flags; + + // clear calcdata if required + if(flags.docalc) gd.calcdata = undefined; + + // fill in redraw sequence + var seq = []; + + if(flags.layoutReplot) { + seq.push(subroutines.layoutReplot); + } + else if(Object.keys(aobj).length) { + seq.push(Plots.previousPromises); + Plots.supplyDefaults(gd); + + if(flags.dolegend) seq.push(subroutines.doLegend); + if(flags.dolayoutstyle) seq.push(subroutines.layoutStyles); + if(flags.doticks) seq.push(subroutines.doTicksRelayout); + if(flags.domodebar) seq.push(subroutines.doModeBar); + } + + Queue.add(gd, + relayout, [gd, specs.undoit], + relayout, [gd, specs.redoit] + ); + + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); + + return plotDone.then(function() { + gd.emit('plotly_relayout', specs.eventData); + return gd; + }); +}; + +function _relayout(gd, aobj) { + var layout = gd.layout, + fullLayout = gd._fullLayout, + keys = Object.keys(aobj), + axes = Plotly.Axes.list(gd), + i; + + // look for 'allaxes', split out into all axes + // in case of 3D the axis are nested within a scene which is held in _id + for(i = 0; i < keys.length; i++) { + if(keys[i].indexOf('allaxes') === 0) { + for(var j = 0; j < axes.length; j++) { + var scene = axes[j]._id.substr(1), + axisAttr = (scene.indexOf('scene') !== -1) ? (scene + '.') : '', + newkey = keys[i].replace('allaxes', axisAttr + axes[j]._name); + + if(!aobj[newkey]) aobj[newkey] = aobj[keys[i]]; + } + + delete aobj[keys[i]]; + } + } + + // initialize flags + var flags = { + dolegend: false, + doticks: false, + dolayoutstyle: false, + doplot: false, + docalc: false, + domodebar: false, + layoutReplot: false + }; + + // copies of the change (and previous values of anything affected) + // for the undo / redo queue + var redoit = {}, + undoit = {}; + + // for attrs that interact (like scales & autoscales), save the + // old vals before making the change + // val=undefined will not set a value, just record what the value was. + // attr can be an array to set several at once (all to the same val) + function doextra(attr, val) { + if(Array.isArray(attr)) { + attr.forEach(function(a) { doextra(a, val); }); + return; + } + // quit if explicitly setting this elsewhere + if(attr in aobj) return; + + var p = Lib.nestedProperty(layout, attr); + if(!(attr in undoit)) undoit[attr] = p.get(); + if(val !== undefined) p.set(val); + } + + // for editing annotations or shapes - is it on autoscaled axes? + function refAutorange(obj, axletter) { + var axName = Plotly.Axes.id2name(obj[axletter + 'ref'] || axletter); + return (fullLayout[axName] || {}).autorange; + } + + // alter gd.layout + for(var ai in aobj) { + var p = Lib.nestedProperty(layout, ai), + vi = aobj[ai], + plen = p.parts.length, + // p.parts may end with an index integer if the property is an array + pend = typeof p.parts[plen - 1] === 'string' ? (plen - 1) : (plen - 2), + // last property in chain (leaf node) + pleaf = p.parts[pend], + // leaf plus immediate parent + pleafPlus = p.parts[pend - 1] + '.' + pleaf, + // trunk nodes (everything except the leaf) + ptrunk = p.parts.slice(0, pend).join('.'), + parentIn = Lib.nestedProperty(gd.layout, ptrunk).get(), + parentFull = Lib.nestedProperty(fullLayout, ptrunk).get(); + + if(vi === undefined) continue; + + redoit[ai] = vi; + + // axis reverse is special - it is its own inverse + // op and has no flag. + undoit[ai] = (pleaf === 'reverse') ? vi : p.get(); + + // Setting width or height to null must reset the graph's width / height + // back to its initial value as computed during the first pass in Plots.plotAutoSize. + // + // To do so, we must manually set them back here using the _initialAutoSize cache. + if(['width', 'height'].indexOf(ai) !== -1 && vi === null) { + gd._fullLayout[ai] = gd._initialAutoSize[ai]; + } + // check autorange vs range + else if(pleafPlus.match(/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/)) { + doextra(ptrunk + '.autorange', false); + } + else if(pleafPlus.match(/^[xyz]axis[0-9]*\.autorange$/)) { + doextra([ptrunk + '.range[0]', ptrunk + '.range[1]'], + undefined); + } + else if(pleafPlus.match(/^aspectratio\.[xyz]$/)) { + doextra(p.parts[0] + '.aspectmode', 'manual'); + } + else if(pleafPlus.match(/^aspectmode$/)) { + doextra([ptrunk + '.x', ptrunk + '.y', ptrunk + '.z'], undefined); + } + else if(pleaf === 'tick0' || pleaf === 'dtick') { + doextra(ptrunk + '.tickmode', 'linear'); + } + else if(pleaf === 'tickmode') { + doextra([ptrunk + '.tick0', ptrunk + '.dtick'], undefined); + } + else if(/[xy]axis[0-9]*?$/.test(pleaf) && !Object.keys(vi || {}).length) { + flags.docalc = true; + } + else if(/[xy]axis[0-9]*\.categoryorder$/.test(pleafPlus)) { + flags.docalc = true; + } + else if(/[xy]axis[0-9]*\.categoryarray/.test(pleafPlus)) { + flags.docalc = true; + } + + if(pleafPlus.indexOf('rangeslider') !== -1) { + flags.docalc = true; + } + + // toggling log without autorange: need to also recalculate ranges + // logical XOR (ie are we toggling log) + if(pleaf === 'type' && ((parentFull.type === 'log') !== (vi === 'log'))) { + var ax = parentIn; + + if(!ax || !ax.range) { + doextra(ptrunk + '.autorange', true); + } + else if(!parentFull.autorange) { + var r0 = ax.range[0], + r1 = ax.range[1]; + if(vi === 'log') { + // if both limits are negative, autorange + if(r0 <= 0 && r1 <= 0) { + doextra(ptrunk + '.autorange', true); + } + // if one is negative, set it 6 orders below the other. + if(r0 <= 0) r0 = r1 / 1e6; + else if(r1 <= 0) r1 = r0 / 1e6; + // now set the range values as appropriate + doextra(ptrunk + '.range[0]', Math.log(r0) / Math.LN10); + doextra(ptrunk + '.range[1]', Math.log(r1) / Math.LN10); + } + else { + doextra(ptrunk + '.range[0]', Math.pow(10, r0)); + doextra(ptrunk + '.range[1]', Math.pow(10, r1)); + } + } + else if(vi === 'log') { + // just make sure the range is positive and in the right + // order, it'll get recalculated later + ax.range = (ax.range[1] > ax.range[0]) ? [1, 2] : [2, 1]; + } + } + + // handle axis reversal explicitly, as there's no 'reverse' flag + if(pleaf === 'reverse') { + if(parentIn.range) parentIn.range.reverse(); + else { + doextra(ptrunk + '.autorange', true); + parentIn.range = [1, 0]; + } + + if(parentFull.autorange) flags.docalc = true; + else flags.doplot = true; + } + // send annotation and shape mods one-by-one through Annotations.draw(), + // don't set via nestedProperty + // that's because add and remove are special + else if(p.parts[0] === 'annotations' || p.parts[0] === 'shapes') { + var objNum = p.parts[1], + objType = p.parts[0], + objList = layout[objType] || [], + obji = objList[objNum] || {}; + + // if p.parts is just an annotation number, and val is either + // 'add' or an entire annotation to add, the undo is 'remove' + // if val is 'remove' then undo is the whole annotation object + if(p.parts.length === 2) { + + // new API, remove annotation / shape with `null` + if(vi === null) aobj[ai] = 'remove'; + + if(aobj[ai] === 'add' || Lib.isPlainObject(aobj[ai])) { + undoit[ai] = 'remove'; + } + else if(aobj[ai] === 'remove') { + if(objNum === -1) { + undoit[objType] = objList; + delete undoit[ai]; + } + else undoit[ai] = obji; + } + else Lib.log('???', aobj); + } + + if((refAutorange(obji, 'x') || refAutorange(obji, 'y')) && + !Lib.containsAny(ai, ['color', 'opacity', 'align', 'dash'])) { + flags.docalc = true; + } + + // TODO: combine all edits to a given annotation / shape into one call + // as it is we get separate calls for x and y (or ax and ay) on move + + var drawOne = Registry.getComponentMethod(objType, 'drawOne'); + drawOne(gd, objNum, p.parts.slice(2).join('.'), aobj[ai]); + delete aobj[ai]; + } + else if( + Plots.layoutArrayContainers.indexOf(p.parts[0]) !== -1 || + (p.parts[0] === 'mapbox' && p.parts[1] === 'layers') + ) { + helpers.manageArrayContainers(p, vi, undoit); + flags.doplot = true; + } + // alter gd.layout + else { + var pp1 = String(p.parts[1] || ''); + // check whether we can short-circuit a full redraw + // 3d or geo at this point just needs to redraw. + if(p.parts[0].indexOf('scene') === 0) flags.doplot = true; + else if(p.parts[0].indexOf('geo') === 0) flags.doplot = true; + else if(p.parts[0].indexOf('ternary') === 0) flags.doplot = true; + else if(ai === 'paper_bgcolor') flags.doplot = true; + else if(fullLayout._has('gl2d') && + (ai.indexOf('axis') !== -1 || p.parts[0] === 'plot_bgcolor') + ) flags.doplot = true; + else if(ai === 'hiddenlabels') flags.docalc = true; + else if(p.parts[0].indexOf('legend') !== -1) flags.dolegend = true; + else if(ai.indexOf('title') !== -1) flags.doticks = true; + else if(p.parts[0].indexOf('bgcolor') !== -1) flags.dolayoutstyle = true; + else if(p.parts.length > 1 && + Lib.containsAny(pp1, ['tick', 'exponent', 'grid', 'zeroline'])) { + flags.doticks = true; + } + else if(ai.indexOf('.linewidth') !== -1 && + ai.indexOf('axis') !== -1) { + flags.doticks = flags.dolayoutstyle = true; + } + else if(p.parts.length > 1 && pp1.indexOf('line') !== -1) { + flags.dolayoutstyle = true; + } + else if(p.parts.length > 1 && pp1 === 'mirror') { + flags.doticks = flags.dolayoutstyle = true; + } + else if(ai === 'margin.pad') { + flags.doticks = flags.dolayoutstyle = true; + } + else if(p.parts[0] === 'margin' || + p.parts[1] === 'autorange' || + p.parts[1] === 'rangemode' || + p.parts[1] === 'type' || + p.parts[1] === 'domain' || + ai.match(/^(bar|box|font)/)) { + flags.docalc = true; + } + /* + * hovermode and dragmode don't need any redrawing, since they just + * affect reaction to user input, everything else, assume full replot. + * height, width, autosize get dealt with below. Except for the case of + * of subplots - scenes - which require scene.updateFx to be called. + */ + else if(['hovermode', 'dragmode'].indexOf(ai) !== -1) flags.domodebar = true; + else if(['hovermode', 'dragmode', 'height', + 'width', 'autosize'].indexOf(ai) === -1) { + flags.doplot = true; + } + + p.set(vi); + } + } + + var oldWidth = gd._fullLayout.width, + oldHeight = gd._fullLayout.height; + + // coerce the updated layout + Plots.supplyDefaults(gd); + + // calculate autosizing + if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, gd._fullLayout); + + // avoid unnecessary redraws + var hasSizechanged = aobj.height || aobj.width || + (gd._fullLayout.width !== oldWidth) || + (gd._fullLayout.height !== oldHeight); + + if(hasSizechanged) flags.docalc = true; + + if(flags.doplot || flags.docalc) { + flags.layoutReplot = true; + } + + // now all attribute mods are done, as are + // redo and undo so we can save them + + return { + flags: flags, + undoit: undoit, + redoit: redoit, + eventData: Lib.extendDeep({}, redoit) + }; +} + +/** + * update: update trace and layout attributes of an existing plot + * + * @param {String | HTMLDivElement} gd + * the id or DOM element of the graph container div + * @param {Object} traceUpdate + * attribute object `{astr1: val1, astr2: val2 ...}` + * corresponding to updates in the plot's traces + * @param {Object} layoutUpdate + * attribute object `{astr1: val1, astr2: val2 ...}` + * corresponding to updates in the plot's layout + * @param {Number[] | Number} [traces] + * integer or array of integers for the traces to alter (all if omitted) + * + */ +Plotly.update = function update(gd, traceUpdate, layoutUpdate, traces) { + gd = helpers.getGraphDiv(gd); + helpers.clearPromiseQueue(gd); + + if(gd.framework && gd.framework.isPolar) { + return Promise.resolve(gd); + } + + if(!Lib.isPlainObject(traceUpdate)) traceUpdate = {}; + if(!Lib.isPlainObject(layoutUpdate)) layoutUpdate = {}; + + if(Object.keys(traceUpdate).length) gd.changed = true; + if(Object.keys(layoutUpdate).length) gd.changed = true; + + var restyleSpecs = _restyle(gd, traceUpdate, traces), + restyleFlags = restyleSpecs.flags; + + var relayoutSpecs = _relayout(gd, layoutUpdate), + relayoutFlags = relayoutSpecs.flags; + + // clear calcdata if required + if(restyleFlags.clearCalc || relayoutFlags.docalc) gd.calcdata = undefined; + + // fill in redraw sequence + var seq = []; + + if(restyleFlags.fullReplot && relayoutFlags.layoutReplot) { + var data = gd.data, + layout = gd.layout; + + // clear existing data/layout on gd + // so that Plotly.plot doesn't try to extend them + gd.data = undefined; + gd.layout = undefined; + + seq.push(function() { return Plotly.plot(gd, data, layout); }); + } + else if(restyleFlags.fullReplot) { + seq.push(Plotly.plot); + } + else if(relayoutFlags.layoutReplot) { + seq.push(subroutines.layoutReplot); + } + else { + seq.push(Plots.previousPromises); + Plots.supplyDefaults(gd); + + if(restyleFlags.dostyle) seq.push(subroutines.doTraceStyle); + if(restyleFlags.docolorbars) seq.push(subroutines.doColorBars); + if(relayoutFlags.dolegend) seq.push(subroutines.doLegend); + if(relayoutFlags.dolayoutstyle) seq.push(subroutines.layoutStyles); + if(relayoutFlags.doticks) seq.push(subroutines.doTicksRelayout); + if(relayoutFlags.domodebar) seq.push(subroutines.doModeBar); + } + + Queue.add(gd, + update, [gd, restyleSpecs.undoit, relayoutSpecs.undoit, restyleSpecs.traces], + update, [gd, restyleSpecs.redoit, relayoutSpecs.redoit, restyleSpecs.traces] + ); + + var plotDone = Lib.syncOrAsync(seq, gd); + if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); + + return plotDone.then(function() { + gd.emit('plotly_update', { + data: restyleSpecs.eventData, + layout: relayoutSpecs.eventData + }); + + return gd; + }); +}; + +/** + * Animate to a frame, sequence of frame, frame group, or frame definition + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * + * @param {string or object or array of strings or array of objects} frameOrGroupNameOrFrameList + * a single frame, array of frames, or group to which to animate. The intent is + * inferred by the type of the input. Valid inputs are: + * + * - string, e.g. 'groupname': animate all frames of a given `group` in the order + * in which they are defined via `Plotly.addFrames`. + * + * - array of strings, e.g. ['frame1', frame2']: a list of frames by name to which + * to animate in sequence + * + * - object: {data: ...}: a frame definition to which to animate. The frame is not + * and does not need to be added via `Plotly.addFrames`. It may contain any of + * the properties of a frame, including `data`, `layout`, and `traces`. The + * frame is used as provided and does not use the `baseframe` property. + * + * - array of objects, e.g. [{data: ...}, {data: ...}]: a list of frame objects, + * each following the same rules as a single `object`. + * + * @param {object} animationOpts + * configuration for the animation + */ +Plotly.animate = function(gd, frameOrGroupNameOrFrameList, animationOpts) { + gd = helpers.getGraphDiv(gd); + + if(!Lib.isPlotDiv(gd)) { + throw new Error( + 'This element is not a Plotly plot: ' + gd + '. It\'s likely that you\'ve failed ' + + 'to create a plot before animating it. For more details, see ' + + 'https://plot.ly/javascript/animations/' + ); + } + + var trans = gd._transitionData; + + // This is the queue of frames that will be animated as soon as possible. They + // are popped immediately upon the *start* of a transition: + if(!trans._frameQueue) { + trans._frameQueue = []; + } + + animationOpts = Plots.supplyAnimationDefaults(animationOpts); + var transitionOpts = animationOpts.transition; + var frameOpts = animationOpts.frame; + + // Since frames are popped immediately, an empty queue only means all frames have + // *started* to transition, not that the animation is complete. To solve that, + // track a separate counter that increments at the same time as frames are added + // to the queue, but decrements only when the transition is complete. + if(trans._frameWaitingCnt === undefined) { + trans._frameWaitingCnt = 0; + } + + function getTransitionOpts(i) { + if(Array.isArray(transitionOpts)) { + if(i >= transitionOpts.length) { + return transitionOpts[0]; + } else { + return transitionOpts[i]; + } + } else { + return transitionOpts; + } + } + + function getFrameOpts(i) { + if(Array.isArray(frameOpts)) { + if(i >= frameOpts.length) { + return frameOpts[0]; + } else { + return frameOpts[i]; + } + } else { + return frameOpts; + } + } + + // Execute a callback after the wrapper function has been called n times. + // This is used to defer the resolution until a transition has resovled *and* + // the frame has completed. If it's not done this way, then we get a race + // condition in which the animation might resolve before a transition is complete + // or vice versa. + function callbackOnNthTime(cb, n) { + var cnt = 0; + return function() { + if(cb && ++cnt === n) { + return cb(); + } + }; + } + + return new Promise(function(resolve, reject) { + function discardExistingFrames() { + if(trans._frameQueue.length === 0) { + return; + } + + while(trans._frameQueue.length) { + var next = trans._frameQueue.pop(); + if(next.onInterrupt) { + next.onInterrupt(); + } + } + + gd.emit('plotly_animationinterrupted', []); + } + + function queueFrames(frameList) { + if(frameList.length === 0) return; + + for(var i = 0; i < frameList.length; i++) { + var computedFrame; + + if(frameList[i].type === 'byname') { + // If it's a named frame, compute it: + computedFrame = Plots.computeFrame(gd, frameList[i].name); + } else { + // Otherwise we must have been given a simple object, so treat + // the input itself as the computed frame. + computedFrame = frameList[i].data; + } + + var frameOpts = getFrameOpts(i); + var transitionOpts = getTransitionOpts(i); + + // It doesn't make much sense for the transition duration to be greater than + // the frame duration, so limit it: + transitionOpts.duration = Math.min(transitionOpts.duration, frameOpts.duration); + + var nextFrame = { + frame: computedFrame, + name: frameList[i].name, + frameOpts: frameOpts, + transitionOpts: transitionOpts, + }; + if(i === frameList.length - 1) { + // The last frame in this .animate call stores the promise resolve + // and reject callbacks. This is how we ensure that the animation + // loop (which may exist as a result of a *different* .animate call) + // still resolves or rejecdts this .animate call's promise. once it's + // complete. + nextFrame.onComplete = callbackOnNthTime(resolve, 2); + nextFrame.onInterrupt = reject; + } + + trans._frameQueue.push(nextFrame); + } + + // Set it as never having transitioned to a frame. This will cause the animation + // loop to immediately transition to the next frame (which, for immediate mode, + // is the first frame in the list since all others would have been discarded + // below) + if(animationOpts.mode === 'immediate') { + trans._lastFrameAt = -Infinity; + } + + // Only it's not already running, start a RAF loop. This could be avoided in the + // case that there's only one frame, but it significantly complicated the logic + // and only sped things up by about 5% or so for a lorenz attractor simulation. + // It would be a fine thing to implement, but the benefit of that optimization + // doesn't seem worth the extra complexity. + if(!trans._animationRaf) { + beginAnimationLoop(); + } + } + + function stopAnimationLoop() { + gd.emit('plotly_animated'); + + // Be sure to unset also since it's how we know whether a loop is already running: + window.cancelAnimationFrame(trans._animationRaf); + trans._animationRaf = null; + } + + function nextFrame() { + if(trans._currentFrame && trans._currentFrame.onComplete) { + // Execute the callback and unset it to ensure it doesn't + // accidentally get called twice + trans._currentFrame.onComplete(); + } + + var newFrame = trans._currentFrame = trans._frameQueue.shift(); + + if(newFrame) { + gd._fullLayout._currentFrame = newFrame.name; + + trans._lastFrameAt = Date.now(); + trans._timeToNext = newFrame.frameOpts.duration; + + // This is simply called and it's left to .transition to decide how to manage + // interrupting current transitions. That means we don't need to worry about + // how it resolves or what happens after this: + Plots.transition(gd, + newFrame.frame.data, + newFrame.frame.layout, + helpers.coerceTraceIndices(gd, newFrame.frame.traces), + newFrame.frameOpts, + newFrame.transitionOpts + ).then(function() { + if(newFrame.onComplete) { + newFrame.onComplete(); + } + + }); + + gd.emit('plotly_animatingframe', { + name: newFrame.name, + frame: newFrame.frame, + animation: { + frame: newFrame.frameOpts, + transition: newFrame.transitionOpts, + } + }); + } else { + // If there are no more frames, then stop the RAF loop: + stopAnimationLoop(); + } + } + + function beginAnimationLoop() { + gd.emit('plotly_animating'); + + // If no timer is running, then set last frame = long ago so that the next + // frame is immediately transitioned: + trans._lastFrameAt = -Infinity; + trans._timeToNext = 0; + trans._runningTransitions = 0; + trans._currentFrame = null; + + var doFrame = function() { + // This *must* be requested before nextFrame since nextFrame may decide + // to cancel it if there's nothing more to animated: + trans._animationRaf = window.requestAnimationFrame(doFrame); + + // Check if we're ready for a new frame: + if(Date.now() - trans._lastFrameAt > trans._timeToNext) { + nextFrame(); + } + }; + + doFrame(); + } + + // This is an animate-local counter that helps match up option input list + // items with the particular frame. + var configCounter = 0; + function setTransitionConfig(frame) { + if(Array.isArray(transitionOpts)) { + if(configCounter >= transitionOpts.length) { + frame.transitionOpts = transitionOpts[configCounter]; + } else { + frame.transitionOpts = transitionOpts[0]; + } + } else { + frame.transitionOpts = transitionOpts; + } + configCounter++; + return frame; + } + + // Disambiguate what's sort of frames have been received + var i, frame; + var frameList = []; + var allFrames = frameOrGroupNameOrFrameList === undefined || frameOrGroupNameOrFrameList === null; + var isFrameArray = Array.isArray(frameOrGroupNameOrFrameList); + var isSingleFrame = !allFrames && !isFrameArray && Lib.isPlainObject(frameOrGroupNameOrFrameList); + + if(isSingleFrame) { + // In this case, a simple object has been passed to animate. + frameList.push({ + type: 'object', + data: setTransitionConfig(Lib.extendFlat({}, frameOrGroupNameOrFrameList)) + }); + } else if(allFrames || typeof frameOrGroupNameOrFrameList === 'string') { + // In this case, null or undefined has been passed so that we want to + // animate *all* currently defined frames + for(i = 0; i < trans._frames.length; i++) { + frame = trans._frames[i]; + + if(!frame) continue; + + if(allFrames || frame.group === frameOrGroupNameOrFrameList) { + frameList.push({ + type: 'byname', + name: frame.name, + data: setTransitionConfig({name: frame.name}) + }); + } + } + } else if(isFrameArray) { + for(i = 0; i < frameOrGroupNameOrFrameList.length; i++) { + var frameOrName = frameOrGroupNameOrFrameList[i]; + if(['number', 'string'].indexOf(typeof frameOrName) !== -1) { + frameOrName = String(frameOrName); + // In this case, there's an array and this frame is a string name: + frameList.push({ + type: 'byname', + name: frameOrName, + data: setTransitionConfig({name: frameOrName}) + }); + } else if(Lib.isPlainObject(frameOrName)) { + frameList.push({ + type: 'object', + data: setTransitionConfig(Lib.extendFlat({}, frameOrName)) + }); + } + } + } + + // Verify that all of these frames actually exist; return and reject if not: + for(i = 0; i < frameList.length; i++) { + frame = frameList[i]; + if(frame.type === 'byname' && !trans._frameHash[frame.data.name]) { + Lib.warn('animate failure: frame not found: "' + frame.data.name + '"'); + reject(); + return; + } + } + + // If the mode is either next or immediate, then all currently queued frames must + // be dumped and the corresponding .animate promises rejected. + if(['next', 'immediate'].indexOf(animationOpts.mode) !== -1) { + discardExistingFrames(); + } + + if(animationOpts.direction === 'reverse') { + frameList.reverse(); + } + + var currentFrame = gd._fullLayout._currentFrame; + if(currentFrame && animationOpts.fromcurrent) { + var idx = -1; + for(i = 0; i < frameList.length; i++) { + frame = frameList[i]; + if(frame.type === 'byname' && frame.name === currentFrame) { + idx = i; + break; + } + } + + if(idx > 0 && idx < frameList.length - 1) { + var filteredFrameList = []; + for(i = 0; i < frameList.length; i++) { + frame = frameList[i]; + if(frameList[i].type !== 'byname' || i > idx) { + filteredFrameList.push(frame); + } + } + frameList = filteredFrameList; + } + } + + if(frameList.length > 0) { + queueFrames(frameList); + } else { + // This is the case where there were simply no frames. It's a little strange + // since there's not much to do: + gd.emit('plotly_animated'); + resolve(); + } + }); +}; + +/** + * Register new frames + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * + * @param {array of objects} frameList + * list of frame definitions, in which each object includes any of: + * - name: {string} name of frame to add + * - data: {array of objects} trace data + * - layout {object} layout definition + * - traces {array} trace indices + * - baseframe {string} name of frame from which this frame gets defaults + * + * @param {array of integers) indices + * an array of integer indices matching the respective frames in `frameList`. If not + * provided, an index will be provided in serial order. If already used, the frame + * will be overwritten. + */ +Plotly.addFrames = function(gd, frameList, indices) { + gd = helpers.getGraphDiv(gd); + + if(frameList === null || frameList === undefined) { + return Promise.resolve(); + } + + if(!Lib.isPlotDiv(gd)) { + throw new Error( + 'This element is not a Plotly plot: ' + gd + '. It\'s likely that you\'ve failed ' + + 'to create a plot before adding frames. For more details, see ' + + 'https://plot.ly/javascript/animations/' + ); + } + + var i, frame, j, idx; + var _frames = gd._transitionData._frames; + var _hash = gd._transitionData._frameHash; + + + if(!Array.isArray(frameList)) { + throw new Error('addFrames failure: frameList must be an Array of frame definitions' + frameList); + } + + // Create a sorted list of insertions since we run into lots of problems if these + // aren't in ascending order of index: + // + // Strictly for sorting. Make sure this is guaranteed to never collide with any + // already-exisisting indices: + var bigIndex = _frames.length + frameList.length * 2; + + var insertions = []; + for(i = frameList.length - 1; i >= 0; i--) { + insertions.push({ + frame: Plots.supplyFrameDefaults(frameList[i]), + index: (indices && indices[i] !== undefined && indices[i] !== null) ? indices[i] : bigIndex + i + }); + } + + // Sort this, taking note that undefined insertions end up at the end: + insertions.sort(function(a, b) { + if(a.index > b.index) return -1; + if(a.index < b.index) return 1; + return 0; + }); + + var ops = []; + var revops = []; + var frameCount = _frames.length; + + for(i = insertions.length - 1; i >= 0; i--) { + frame = insertions[i].frame; + + if(!frame.name) { + // Repeatedly assign a default name, incrementing the counter each time until + // we get a name that's not in the hashed lookup table: + while(_hash[(frame.name = 'frame ' + gd._transitionData._counter++)]); + } + + if(_hash[frame.name]) { + // If frame is present, overwrite its definition: + for(j = 0; j < _frames.length; j++) { + if((_frames[j] || {}).name === frame.name) break; + } + ops.push({type: 'replace', index: j, value: frame}); + revops.unshift({type: 'replace', index: j, value: _frames[j]}); + } else { + // Otherwise insert it at the end of the list: + idx = Math.max(0, Math.min(insertions[i].index, frameCount)); + + ops.push({type: 'insert', index: idx, value: frame}); + revops.unshift({type: 'delete', index: idx}); + frameCount++; + } + } + + var undoFunc = Plots.modifyFrames, + redoFunc = Plots.modifyFrames, + undoArgs = [gd, revops], + redoArgs = [gd, ops]; + + if(Queue) Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return Plots.modifyFrames(gd, ops); +}; + +/** + * Delete frame + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + * + * @param {array of integers} frameList + * list of integer indices of frames to be deleted + */ +Plotly.deleteFrames = function(gd, frameList) { + gd = helpers.getGraphDiv(gd); + + if(!Lib.isPlotDiv(gd)) { + throw new Error('This element is not a Plotly plot: ' + gd); + } + + var i, idx; + var _frames = gd._transitionData._frames; + var ops = []; + var revops = []; + + frameList = frameList.slice(0); + frameList.sort(); + + for(i = frameList.length - 1; i >= 0; i--) { + idx = frameList[i]; + ops.push({type: 'delete', index: idx}); + revops.unshift({type: 'insert', index: idx, value: _frames[idx]}); + } + + var undoFunc = Plots.modifyFrames, + redoFunc = Plots.modifyFrames, + undoArgs = [gd, revops], + redoArgs = [gd, ops]; + + if(Queue) Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); + + return Plots.modifyFrames(gd, ops); +}; + +/** + * Purge a graph container div back to its initial pre-Plotly.plot state + * + * @param {string id or DOM element} gd + * the id or DOM element of the graph container div + */ +Plotly.purge = function purge(gd) { + gd = helpers.getGraphDiv(gd); + + var fullLayout = gd._fullLayout || {}, + fullData = gd._fullData || []; + + // remove gl contexts + Plots.cleanPlot([], {}, fullData, fullLayout); + + // purge properties + Plots.purge(gd); + + // purge event emitter methods + Events.purge(gd); + + // remove plot container + if(fullLayout._container) fullLayout._container.remove(); + + delete gd._context; + delete gd._replotPending; + delete gd._mouseDownTime; + delete gd._hmpixcount; + delete gd._hmlumcount; + + return gd; +}; + +// ------------------------------------------------------- +// makePlotFramework: Create the plot container and axes +// ------------------------------------------------------- +function makePlotFramework(gd) { + var gd3 = d3.select(gd), + fullLayout = gd._fullLayout; + + // Plot container + fullLayout._container = gd3.selectAll('.plot-container').data([0]); + fullLayout._container.enter().insert('div', ':first-child') + .classed('plot-container', true) + .classed('plotly', true); + + // Make the svg container + fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([0]); + fullLayout._paperdiv.enter().append('div') + .classed('svg-container', true) + .style('position', 'relative'); + + // Make the graph containers + // start fresh each time we get here, so we know the order comes out + // right, rather than enter/exit which can muck up the order + // TODO: sort out all the ordering so we don't have to + // explicitly delete anything + fullLayout._glcontainer = fullLayout._paperdiv.selectAll('.gl-container') + .data([0]); + fullLayout._glcontainer.enter().append('div') + .classed('gl-container', true); + + fullLayout._geocontainer = fullLayout._paperdiv.selectAll('.geo-container') + .data([0]); + fullLayout._geocontainer.enter().append('div') + .classed('geo-container', true); + + fullLayout._paperdiv.selectAll('.main-svg').remove(); + + fullLayout._paper = fullLayout._paperdiv.insert('svg', ':first-child') + .classed('main-svg', true); + + fullLayout._toppaper = fullLayout._paperdiv.append('svg') + .classed('main-svg', true); + + if(!fullLayout._uid) { + var otherUids = []; + d3.selectAll('defs').each(function() { + if(this.id) otherUids.push(this.id.split('-')[1]); + }); + fullLayout._uid = Lib.randstr(otherUids); + } + + fullLayout._paperdiv.selectAll('.main-svg') + .attr(xmlnsNamespaces.svgAttrs); + + fullLayout._defs = fullLayout._paper.append('defs') + .attr('id', 'defs-' + fullLayout._uid); + + fullLayout._topdefs = fullLayout._toppaper.append('defs') + .attr('id', 'topdefs-' + fullLayout._uid); + + fullLayout._draggers = fullLayout._paper.append('g') + .classed('draglayer', true); + + // lower shape layer + // (only for shapes to be drawn below the whole plot) + var layerBelow = fullLayout._paper.append('g') + .classed('layer-below', true); + fullLayout._imageLowerLayer = layerBelow.append('g') + .classed('imagelayer', true); + fullLayout._shapeLowerLayer = layerBelow.append('g') + .classed('shapelayer', true); + + // single cartesian layer for the whole plot + fullLayout._cartesianlayer = fullLayout._paper.append('g').classed('cartesianlayer', true); + + // single ternary layer for the whole plot + fullLayout._ternarylayer = fullLayout._paper.append('g').classed('ternarylayer', true); + + // upper shape layer + // (only for shapes to be drawn above the whole plot, including subplots) + var layerAbove = fullLayout._paper.append('g') + .classed('layer-above', true); + fullLayout._imageUpperLayer = layerAbove.append('g') + .classed('imagelayer', true); + fullLayout._shapeUpperLayer = layerAbove.append('g') + .classed('shapelayer', true); + + // single pie layer for the whole plot + fullLayout._pielayer = fullLayout._paper.append('g').classed('pielayer', true); + + // fill in image server scrape-svg + fullLayout._glimages = fullLayout._paper.append('g').classed('glimages', true); + fullLayout._geoimages = fullLayout._paper.append('g').classed('geoimages', true); + + // lastly info (legend, annotations) and hover layers go on top + // these are in a different svg element normally, but get collapsed into a single + // svg when exporting (after inserting 3D) + fullLayout._infolayer = fullLayout._toppaper.append('g').classed('infolayer', true); + fullLayout._zoomlayer = fullLayout._toppaper.append('g').classed('zoomlayer', true); + fullLayout._hoverlayer = fullLayout._toppaper.append('g').classed('hoverlayer', true); + + gd.emit('plotly_framework'); +} + +},{"../components/drawing":50,"../components/errorbars":56,"../constants/xmlns_namespaces":109,"../lib":122,"../lib/events":116,"../lib/queue":130,"../lib/svg_text_utils":134,"../plotly":145,"../plots/cartesian/graph_interact":157,"../plots/plots":186,"../plots/polar":189,"../registry":194,"./helpers":136,"./subroutines":142,"d3":10,"fast-isnumeric":13}],138:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* eslint-disable no-console */ + +/** + * This will be transferred over to gd and overridden by + * config args to Plotly.plot. + * + * The defaults are the appropriate settings for plotly.js, + * so we get the right experience without any config argument. + */ + +module.exports = { + + // no interactivity, for export or image generation + staticPlot: false, + + // we can edit titles, move annotations, etc + editable: false, + + // if editable is set to true, this can be used to deactivate main title editing ONLY. + editableMainTitle: true, + + // if editable is set to true, this can be used to deactivate X axis title editing ONLY. + editableAxisXTitle: true, + + // if editable is set to true, this can be used to deactivate X2 axis title editing ONLY. + editableAxisX2Title: true, + + // if editable is set to true, this can be used to deactivate Y axis title editing ONLY. + editableAxisYTitle: true, + + // if editable is set to true, this can be used to deactivate Y2 axis title editing ONLY. + editableAxisY2Title: true, + + // DO autosize once regardless of layout.autosize + // (use default width or height values otherwise) + autosizable: false, + + // set the length of the undo/redo queue + queueLength: 0, + + // if we DO autosize, do we fill the container or the screen? + fillFrame: false, + + // if we DO autosize, set the frame margins in percents of plot size + frameMargins: 0, + + // mousewheel or two-finger scroll zooms the plot + scrollZoom: false, + + // double click interaction (false, 'reset', 'autosize' or 'reset+autosize') + doubleClick: 'reset+autosize', + + // new users see some hints about interactivity + showTips: true, + + // link to open this plot in plotly + showLink: false, + + // if we show a link, does it contain data or just link to a plotly file? + sendData: true, + + // text appearing in the sendData link + linkText: 'Edit chart', + + // false or function adding source(s) to linkText + showSources: false, + + // display the mode bar (true, false, or 'hover') + displayModeBar: 'hover', + + // remove mode bar button by name + // (see ./components/modebar/buttons.js for the list of names) + modeBarButtonsToRemove: [], + + // add mode bar button using config objects + // (see ./components/modebar/buttons.js for list of arguments) + modeBarButtonsToAdd: [], + + // fully custom mode bar buttons as nested array, + // where the outer arrays represents button groups, and + // the inner arrays have buttons config objects or names of default buttons + // (see ./components/modebar/buttons.js for more info) + modeBarButtons: false, + + // add the plotly logo on the end of the mode bar + displaylogo: true, + + // increase the pixel ratio for Gl plot images + plotGlPixelRatio: 2, + + // function to add the background color to a different container + // or 'opaque' to ensure there's white behind it + setBackground: defaultSetBackground, + + // URL to topojson files used in geo charts + topojsonURL: 'https://cdn.plot.ly/', + + // Mapbox access token (required to plot mapbox trace types) + // If using an Mapbox Atlas server, set this option to '', + // so that plotly.js won't attempt to authenticate to the public Mapbox server. + mapboxAccessToken: null, + + // Turn all console logging on or off (errors will be thrown) + // This should ONLY be set via Plotly.setPlotConfig + logging: false, + + // Set global transform to be applied to all traces with no + // specification needed + globalTransforms: [] +}; + +// where and how the background gets set can be overridden by context +// so we define the default (plotly.js) behavior here +function defaultSetBackground(gd, bgColor) { + try { + gd._fullLayout._paper.style('background', bgColor); + } + catch(e) { + if(module.exports.logging > 0) { + console.error(e); + } + } +} + +},{}],139:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = require('../registry'); +var Lib = require('../lib'); + +var baseAttributes = require('../plots/attributes'); +var baseLayoutAttributes = require('../plots/layout_attributes'); +var frameAttributes = require('../plots/frame_attributes'); +var animationAttributes = require('../plots/animation_attributes'); + +// polar attributes are not part of the Registry yet +var polarAreaAttrs = require('../plots/polar/area_attributes'); +var polarAxisAttrs = require('../plots/polar/axis_attributes'); + +var extendFlat = Lib.extendFlat; +var extendDeep = Lib.extendDeep; + +var IS_SUBPLOT_OBJ = '_isSubplotObj'; +var IS_LINKED_TO_ARRAY = '_isLinkedToArray'; +var DEPRECATED = '_deprecated'; +var UNDERSCORE_ATTRS = [IS_SUBPLOT_OBJ, IS_LINKED_TO_ARRAY, DEPRECATED]; + +exports.IS_SUBPLOT_OBJ = IS_SUBPLOT_OBJ; +exports.IS_LINKED_TO_ARRAY = IS_LINKED_TO_ARRAY; +exports.DEPRECATED = DEPRECATED; +exports.UNDERSCORE_ATTRS = UNDERSCORE_ATTRS; + +/** Outputs the full plotly.js plot schema + * + * @return {object} + * - defs + * - traces + * - layout + * - transforms + * - frames + * - animations + * - config (coming soon ...) + */ +exports.get = function() { + var traces = {}; + + Registry.allTypes.concat('area').forEach(function(type) { + traces[type] = getTraceAttributes(type); + }); + + var transforms = {}; + + Object.keys(Registry.transformsRegistry).forEach(function(type) { + transforms[type] = getTransformAttributes(type); + }); + + return { + defs: { + valObjects: Lib.valObjects, + metaKeys: UNDERSCORE_ATTRS.concat['description', 'role'] + }, + + traces: traces, + layout: getLayoutAttributes(), + + transforms: transforms, + + frames: formatAttributes(frameAttributes), + animation: formatAttributes(animationAttributes) + }; +}; + +/** + * Crawl the attribute tree, recursively calling a callback function + * + * @param {object} attrs + * The node of the attribute tree (e.g. the root) from which recursion originates + * @param {Function} callback + * A callback function with the signature: + * @callback callback + * @param {object} attr an attribute + * @param {String} attrName name string + * @param {object[]} attrs all the attributes + * @param {Number} level the recursion level, 0 at the root + * @param {Number} [specifiedLevel] + * The level in the tree, in order to let the callback function detect descend or backtrack, + * typically unsupplied (implied 0), just used by the self-recursive call. + * The necessity arises because the tree traversal is not controlled by callback return values. + * The decision to not use callback return values for controlling tree pruning arose from + * the goal of keeping the crawler backwards compatible. Observe that one of the pruning conditions + * precedes the callback call. + * + * @return {object} transformOut + * copy of transformIn that contains attribute defaults + */ +exports.crawl = function(attrs, callback, specifiedLevel) { + var level = specifiedLevel || 0; + + Object.keys(attrs).forEach(function(attrName) { + var attr = attrs[attrName]; + + if(UNDERSCORE_ATTRS.indexOf(attrName) !== -1) return; + + callback(attr, attrName, attrs, level); + + if(exports.isValObject(attr)) return; + + if(Lib.isPlainObject(attr)) exports.crawl(attr, callback, level + 1); + }); +}; + +/** Is object a value object (or a container object)? + * + * @param {object} obj + * @return {boolean} + * returns true for a valid value object and + * false for tree nodes in the attribute hierarchy + */ +exports.isValObject = function(obj) { + return obj && obj.valType !== undefined; +}; + +/** + * Find all data array attributes in a given trace object - including + * `arrayOk` attributes. + * + * @param {object} trace + * full trace object that contains a reference to `_module.attributes` + * + * @return {array} arrayAttributes + * list of array attributes for the given trace + */ +exports.findArrayAttributes = function(trace) { + var arrayAttributes = [], + stack = []; + + function callback(attr, attrName, attrs, level) { + stack = stack.slice(0, level).concat([attrName]); + + var splittableAttr = attr.valType === 'data_array' || attr.arrayOk === true; + if(!splittableAttr) return; + + var astr = toAttrString(stack); + var val = Lib.nestedProperty(trace, astr).get(); + if(!Array.isArray(val)) return; + + arrayAttributes.push(astr); + } + + function toAttrString(stack) { + return stack.join('.'); + } + + exports.crawl(trace._module.attributes, callback); + + if(trace.transforms) { + var transforms = trace.transforms; + + for(var i = 0; i < transforms.length; i++) { + var transform = transforms[i]; + + stack = ['transforms[' + i + ']']; + exports.crawl(transform._module.attributes, callback, 1); + } + } + + // Look into the fullInput module attributes for array attributes + // to make sure that 'custom' array attributes are detected. + // + // At the moment, we need this block to make sure that + // ohlc and candlestick 'open', 'high', 'low', 'close' can be + // used with filter ang groupby transforms. + if(trace._fullInput) { + exports.crawl(trace._fullInput._module.attributes, callback); + + arrayAttributes = Lib.filterUnique(arrayAttributes); + } + + return arrayAttributes; +}; + +function getTraceAttributes(type) { + var _module, basePlotModule; + + if(type === 'area') { + _module = { attributes: polarAreaAttrs }; + basePlotModule = {}; + } + else { + _module = Registry.modules[type]._module, + basePlotModule = _module.basePlotModule; + } + + var attributes = {}; + + // make 'type' the first attribute in the object + attributes.type = null; + + // base attributes (same for all trace types) + extendDeep(attributes, baseAttributes); + + // module attributes + extendDeep(attributes, _module.attributes); + + // subplot attributes + if(basePlotModule.attributes) { + extendDeep(attributes, basePlotModule.attributes); + } + + // 'type' gets overwritten by baseAttributes; reset it here + attributes.type = type; + + var out = { + meta: _module.meta || {}, + attributes: formatAttributes(attributes), + }; + + // trace-specific layout attributes + if(_module.layoutAttributes) { + var layoutAttributes = {}; + + extendDeep(layoutAttributes, _module.layoutAttributes); + out.layoutAttributes = formatAttributes(layoutAttributes); + } + + return out; +} + +function getLayoutAttributes() { + var layoutAttributes = {}; + + // global layout attributes + extendDeep(layoutAttributes, baseLayoutAttributes); + + // add base plot module layout attributes + Object.keys(Registry.subplotsRegistry).forEach(function(k) { + var _module = Registry.subplotsRegistry[k]; + + if(!_module.layoutAttributes) return; + + if(_module.name === 'cartesian') { + handleBasePlotModule(layoutAttributes, _module, 'xaxis'); + handleBasePlotModule(layoutAttributes, _module, 'yaxis'); + } + else { + var astr = _module.attr === 'subplot' ? _module.name : _module.attr; + + handleBasePlotModule(layoutAttributes, _module, astr); + } + }); + + // polar layout attributes + layoutAttributes = assignPolarLayoutAttrs(layoutAttributes); + + // add registered components layout attribute + Object.keys(Registry.componentsRegistry).forEach(function(k) { + var _module = Registry.componentsRegistry[k]; + + if(!_module.layoutAttributes) return; + + if(Array.isArray(_module.layoutNodes)) { + _module.layoutNodes.forEach(function(v) { + handleRegisteredComponent(layoutAttributes, _module, v + _module.name); + }); + } + else { + handleRegisteredComponent(layoutAttributes, _module, _module.name); + } + }); + + return { + layoutAttributes: formatAttributes(layoutAttributes) + }; +} + +function getTransformAttributes(type) { + var _module = Registry.transformsRegistry[type]; + + return { + attributes: formatAttributes(_module.attributes) + }; +} + +function formatAttributes(attrs) { + mergeValTypeAndRole(attrs); + formatArrayContainers(attrs); + + return attrs; +} + +function mergeValTypeAndRole(attrs) { + + function makeSrcAttr(attrName) { + return { + valType: 'string', + + + }; + } + + function callback(attr, attrName, attrs) { + if(exports.isValObject(attr)) { + if(attr.valType === 'data_array') { + // all 'data_array' attrs have role 'data' + attr.role = 'data'; + // all 'data_array' attrs have a corresponding 'src' attr + attrs[attrName + 'src'] = makeSrcAttr(attrName); + } + else if(attr.arrayOk === true) { + // all 'arrayOk' attrs have a corresponding 'src' attr + attrs[attrName + 'src'] = makeSrcAttr(attrName); + } + } + else if(Lib.isPlainObject(attr)) { + // all attrs container objects get role 'object' + attr.role = 'object'; + } + } + + exports.crawl(attrs, callback); +} + +function formatArrayContainers(attrs) { + + function callback(attr, attrName, attrs) { + if(!attr) return; + + var itemName = attr[IS_LINKED_TO_ARRAY]; + + if(!itemName) return; + + delete attr[IS_LINKED_TO_ARRAY]; + + attrs[attrName] = { items: {} }; + attrs[attrName].items[itemName] = attr; + attrs[attrName].role = 'object'; + } + + exports.crawl(attrs, callback); +} + +function assignPolarLayoutAttrs(layoutAttributes) { + extendFlat(layoutAttributes, { + radialaxis: polarAxisAttrs.radialaxis, + angularaxis: polarAxisAttrs.angularaxis + }); + + extendFlat(layoutAttributes, polarAxisAttrs.layout); + + return layoutAttributes; +} + +function handleBasePlotModule(layoutAttributes, _module, astr) { + var np = Lib.nestedProperty(layoutAttributes, astr), + attrs = extendDeep({}, _module.layoutAttributes); + + attrs[IS_SUBPLOT_OBJ] = true; + np.set(attrs); +} + +function handleRegisteredComponent(layoutAttributes, _module, astr) { + var np = Lib.nestedProperty(layoutAttributes, astr), + attrs = extendDeep(np.get() || {}, _module.layoutAttributes); + + np.set(attrs); +} + +},{"../lib":122,"../plots/animation_attributes":146,"../plots/attributes":148,"../plots/frame_attributes":171,"../plots/layout_attributes":184,"../plots/polar/area_attributes":187,"../plots/polar/axis_attributes":188,"../registry":194}],140:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = require('../registry'); +var Lib = require('../lib'); + + +module.exports = function register(_modules) { + if(!_modules) { + throw new Error('No argument passed to Plotly.register.'); + } + else if(_modules && !Array.isArray(_modules)) { + _modules = [_modules]; + } + + for(var i = 0; i < _modules.length; i++) { + var newModule = _modules[i]; + + if(!newModule) { + throw new Error('Invalid module was attempted to be registered!'); + } + + switch(newModule.moduleType) { + case 'trace': + registerTraceModule(newModule); + break; + + case 'transform': + registerTransformModule(newModule); + break; + + case 'component': + registerComponentModule(newModule); + break; + + default: + throw new Error('Invalid module was attempted to be registered!'); + } + } +}; + +function registerTraceModule(newModule) { + Registry.register(newModule, newModule.name, newModule.categories, newModule.meta); + + if(!Registry.subplotsRegistry[newModule.basePlotModule.name]) { + Registry.registerSubplot(newModule.basePlotModule); + } +} + +function registerTransformModule(newModule) { + if(typeof newModule.name !== 'string') { + throw new Error('Transform module *name* must be a string.'); + } + + var prefix = 'Transform module ' + newModule.name; + + var hasTransform = typeof newModule.transform === 'function', + hasCalcTransform = typeof newModule.calcTransform === 'function'; + + + if(!hasTransform && !hasCalcTransform) { + throw new Error(prefix + ' is missing a *transform* or *calcTransform* method.'); + } + + if(hasTransform && hasCalcTransform) { + Lib.log([ + prefix + ' has both a *transform* and *calcTransform* methods.', + 'Please note that all *transform* methods are executed', + 'before all *calcTransform* methods.' + ].join(' ')); + } + + if(!Lib.isPlainObject(newModule.attributes)) { + Lib.log(prefix + ' registered without an *attributes* object.'); + } + + if(typeof newModule.supplyDefaults !== 'function') { + Lib.log(prefix + ' registered without a *supplyDefaults* method.'); + } + + Registry.transformsRegistry[newModule.name] = newModule; +} + +function registerComponentModule(newModule) { + if(typeof newModule.name !== 'string') { + throw new Error('Component module *name* must be a string.'); + } + + Registry.registerComponent(newModule); +} + +},{"../lib":122,"../registry":194}],141:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Plotly = require('../plotly'); +var Lib = require('../lib'); + +/** + * Extends the plot config + * + * @param {object} configObj partial plot configuration object + * to extend the current plot configuration. + * + */ +module.exports = function setPlotConfig(configObj) { + return Lib.extendFlat(Plotly.defaultConfig, configObj); +}; + +},{"../lib":122,"../plotly":145}],142:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Plotly = require('../plotly'); +var Registry = require('../registry'); +var Plots = require('../plots/plots'); +var Lib = require('../lib'); + +var Color = require('../components/color'); +var Drawing = require('../components/drawing'); +var Titles = require('../components/titles'); +var ModeBar = require('../components/modebar'); + + +exports.layoutStyles = function(gd) { + return Lib.syncOrAsync([Plots.doAutoMargin, exports.lsInner], gd); +}; + +exports.lsInner = function(gd) { + var fullLayout = gd._fullLayout, + gs = fullLayout._size, + axList = Plotly.Axes.list(gd), + i; + + // clear axis line positions, to be set in the subplot loop below + for(i = 0; i < axList.length; i++) axList[i]._linepositions = {}; + + fullLayout._paperdiv + .style({ + width: fullLayout.width + 'px', + height: fullLayout.height + 'px' + }) + .selectAll('.main-svg') + .call(Drawing.setSize, fullLayout.width, fullLayout.height); + + gd._context.setBackground(gd, fullLayout.paper_bgcolor); + + var freefinished = []; + fullLayout._paper.selectAll('g.subplot').each(function(subplot) { + var plotinfo = fullLayout._plots[subplot], + xa = Plotly.Axes.getFromId(gd, subplot, 'x'), + ya = Plotly.Axes.getFromId(gd, subplot, 'y'); + + xa.setScale(); // this may already be done... not sure + ya.setScale(); + + if(plotinfo.bg) { + plotinfo.bg + .call(Drawing.setRect, + xa._offset - gs.p, ya._offset - gs.p, + xa._length + 2 * gs.p, ya._length + 2 * gs.p) + .call(Color.fill, fullLayout.plot_bgcolor); + } + + // Clip so that data only shows up on the plot area. + plotinfo.clipId = 'clip' + fullLayout._uid + subplot + 'plot'; + + var plotClip = fullLayout._defs.selectAll('g.clips') + .selectAll('#' + plotinfo.clipId) + .data([0]); + + plotClip.enter().append('clipPath') + .attr({ + 'class': 'plotclip', + 'id': plotinfo.clipId + }) + .append('rect'); + + plotClip.selectAll('rect') + .attr({ + 'width': xa._length, + 'height': ya._length + }); + + + plotinfo.plot.call(Lib.setTranslate, xa._offset, ya._offset); + plotinfo.plot.call(Drawing.setClipUrl, plotinfo.clipId); + + var xlw = Drawing.crispRound(gd, xa.linewidth, 1), + ylw = Drawing.crispRound(gd, ya.linewidth, 1), + xp = gs.p + ylw, + xpathPrefix = 'M' + (-xp) + ',', + xpathSuffix = 'h' + (xa._length + 2 * xp), + showfreex = xa.anchor === 'free' && + freefinished.indexOf(xa._id) === -1, + freeposx = gs.h * (1 - (xa.position||0)) + ((xlw / 2) % 1), + showbottom = + (xa.anchor === ya._id && (xa.mirror || xa.side !== 'top')) || + xa.mirror === 'all' || xa.mirror === 'allticks' || + (xa.mirrors && xa.mirrors[ya._id + 'bottom']), + bottompos = ya._length + gs.p + xlw / 2, + showtop = + (xa.anchor === ya._id && (xa.mirror || xa.side === 'top')) || + xa.mirror === 'all' || xa.mirror === 'allticks' || + (xa.mirrors && xa.mirrors[ya._id + 'top']), + toppos = -gs.p - xlw / 2, + + // shorten y axis lines so they don't overlap x axis lines + yp = gs.p, + // except where there's no x line + // TODO: this gets more complicated with multiple x and y axes + ypbottom = showbottom ? 0 : xlw, + yptop = showtop ? 0 : xlw, + ypathSuffix = ',' + (-yp - yptop) + + 'v' + (ya._length + 2 * yp + yptop + ypbottom), + showfreey = ya.anchor === 'free' && + freefinished.indexOf(ya._id) === -1, + freeposy = gs.w * (ya.position||0) + ((ylw / 2) % 1), + showleft = + (ya.anchor === xa._id && (ya.mirror || ya.side !== 'right')) || + ya.mirror === 'all' || ya.mirror === 'allticks' || + (ya.mirrors && ya.mirrors[xa._id + 'left']), + leftpos = -gs.p - ylw / 2, + showright = + (ya.anchor === xa._id && (ya.mirror || ya.side === 'right')) || + ya.mirror === 'all' || ya.mirror === 'allticks' || + (ya.mirrors && ya.mirrors[xa._id + 'right']), + rightpos = xa._length + gs.p + ylw / 2; + + // save axis line positions for ticks, draggers, etc to reference + // each subplot gets an entry: + // [left or bottom, right or top, free, main] + // main is the position at which to draw labels and draggers, if any + xa._linepositions[subplot] = [ + showbottom ? bottompos : undefined, + showtop ? toppos : undefined, + showfreex ? freeposx : undefined + ]; + if(xa.anchor === ya._id) { + xa._linepositions[subplot][3] = xa.side === 'top' ? + toppos : bottompos; + } + else if(showfreex) { + xa._linepositions[subplot][3] = freeposx; + } + + ya._linepositions[subplot] = [ + showleft ? leftpos : undefined, + showright ? rightpos : undefined, + showfreey ? freeposy : undefined + ]; + if(ya.anchor === xa._id) { + ya._linepositions[subplot][3] = ya.side === 'right' ? + rightpos : leftpos; + } + else if(showfreey) { + ya._linepositions[subplot][3] = freeposy; + } + + // translate all the extra stuff to have the + // same origin as the plot area or axes + var origin = 'translate(' + xa._offset + ',' + ya._offset + ')', + originx = origin, + originy = origin; + if(showfreex) { + originx = 'translate(' + xa._offset + ',' + gs.t + ')'; + toppos += ya._offset - gs.t; + bottompos += ya._offset - gs.t; + } + if(showfreey) { + originy = 'translate(' + gs.l + ',' + ya._offset + ')'; + leftpos += xa._offset - gs.l; + rightpos += xa._offset - gs.l; + } + + plotinfo.xlines + .attr('transform', originx) + .attr('d', ( + (showbottom ? (xpathPrefix + bottompos + xpathSuffix) : '') + + (showtop ? (xpathPrefix + toppos + xpathSuffix) : '') + + (showfreex ? (xpathPrefix + freeposx + xpathSuffix) : '')) || + // so it doesn't barf with no lines shown + 'M0,0') + .style('stroke-width', xlw + 'px') + .call(Color.stroke, xa.showline ? + xa.linecolor : 'rgba(0,0,0,0)'); + plotinfo.ylines + .attr('transform', originy) + .attr('d', ( + (showleft ? ('M' + leftpos + ypathSuffix) : '') + + (showright ? ('M' + rightpos + ypathSuffix) : '') + + (showfreey ? ('M' + freeposy + ypathSuffix) : '')) || + 'M0,0') + .attr('stroke-width', ylw + 'px') + .call(Color.stroke, ya.showline ? + ya.linecolor : 'rgba(0,0,0,0)'); + + plotinfo.xaxislayer.attr('transform', originx); + plotinfo.yaxislayer.attr('transform', originy); + plotinfo.gridlayer.attr('transform', origin); + plotinfo.zerolinelayer.attr('transform', origin); + plotinfo.draglayer.attr('transform', origin); + + // mark free axes as displayed, so we don't draw them again + if(showfreex) { freefinished.push(xa._id); } + if(showfreey) { freefinished.push(ya._id); } + }); + + Plotly.Axes.makeClipPaths(gd); + exports.drawMainTitle(gd); + ModeBar.manage(gd); + + return gd._promises.length && Promise.all(gd._promises); +}; + +exports.drawMainTitle = function(gd) { + var fullLayout = gd._fullLayout; + + Titles.draw(gd, 'gtitle', { + propContainer: fullLayout, + propName: 'title', + dfltName: 'Plot', + attributes: { + x: fullLayout.width / 2, + y: fullLayout._size.t / 2, + 'text-anchor': 'middle' + } + }); + + if (fullLayout._titleElement) { + var titleBB = fullLayout._titleElement.node().getBoundingClientRect(); + var shiftMargins = { + x: 0, + y: 1, + l: 0, + r: 0, + b: 0, + t: titleBB.height + 2 + }; + Plots.autoMargin(gd, "chart_title", shiftMargins); + } +}; + +// First, see if we need to do arraysToCalcdata +// call it regardless of what change we made, in case +// supplyDefaults brought in an array that was already +// in gd.data but not in gd._fullData previously +exports.doTraceStyle = function(gd) { + for(var i = 0; i < gd.calcdata.length; i++) { + var cdi = gd.calcdata[i], + _module = ((cdi[0] || {}).trace || {})._module || {}, + arraysToCalcdata = _module.arraysToCalcdata; + + if(arraysToCalcdata) arraysToCalcdata(cdi); + } + + Plots.style(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + + return Plots.previousPromises(gd); +}; + +exports.doColorBars = function(gd) { + for(var i = 0; i < gd.calcdata.length; i++) { + var cdi0 = gd.calcdata[i][0]; + + if((cdi0.t || {}).cb) { + var trace = cdi0.trace, + cb = cdi0.t.cb; + + if(Registry.traceIs(trace, 'contour')) { + cb.line({ + width: trace.contours.showlines !== false ? + trace.line.width : 0, + dash: trace.line.dash, + color: trace.contours.coloring === 'line' ? + cb._opts.line.color : trace.line.color + }); + } + if(Registry.traceIs(trace, 'markerColorscale')) { + cb.options(trace.marker.colorbar)(); + } + else cb.options(trace.colorbar)(); + } + } + + return Plots.previousPromises(gd); +}; + +// force plot() to redo the layout and replot with the modified layout +exports.layoutReplot = function(gd) { + var layout = gd.layout; + gd.layout = undefined; + return Plotly.plot(gd, '', layout); +}; + +exports.doLegend = function(gd) { + Registry.getComponentMethod('legend', 'draw')(gd); + return Plots.previousPromises(gd); +}; + +exports.doTicksRelayout = function(gd) { + Plotly.Axes.doTicks(gd, 'redraw'); + exports.drawMainTitle(gd); + return Plots.previousPromises(gd); +}; + +exports.doModeBar = function(gd) { + var fullLayout = gd._fullLayout; + var subplotIds, i; + + ModeBar.manage(gd); + Plotly.Fx.supplyLayoutDefaults(gd.layout, gd._fullLayout, gd._fullData); + Plotly.Fx.init(gd); + + subplotIds = Plots.getSubplotIds(fullLayout, 'gl3d'); + for(i = 0; i < subplotIds.length; i++) { + var scene = fullLayout[subplotIds[i]]._scene; + scene.updateFx(fullLayout.dragmode, fullLayout.hovermode); + } + + subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d'); + for(i = 0; i < subplotIds.length; i++) { + var scene2d = fullLayout._plots[subplotIds[i]]._scene2d; + scene2d.updateFx(fullLayout); + } + + subplotIds = Plots.getSubplotIds(fullLayout, 'geo'); + for(i = 0; i < subplotIds.length; i++) { + var geo = fullLayout[subplotIds[i]]._subplot; + geo.updateFx(fullLayout.hovermode); + } + + return Plots.previousPromises(gd); +}; + +},{"../components/color":27,"../components/drawing":50,"../components/modebar":73,"../components/titles":101,"../lib":122,"../plotly":145,"../plots/plots":186,"../registry":194}],143:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Plotly = require('../plotly'); +var Lib = require('../lib'); + +var helpers = require('../snapshot/helpers'); +var clonePlot = require('../snapshot/cloneplot'); +var toSVG = require('../snapshot/tosvg'); +var svgToImg = require('../snapshot/svgtoimg'); + +/** + * @param {object} gd figure Object + * @param {object} opts option object + * @param opts.format 'jpeg' | 'png' | 'webp' | 'svg' + * @param opts.width width of snapshot in px + * @param opts.height height of snapshot in px + */ +function toImage(gd, opts) { + + var promise = new Promise(function(resolve, reject) { + // check for undefined opts + opts = opts || {}; + // default to png + opts.format = opts.format || 'png'; + + var isSizeGood = function(size) { + // undefined and null are valid options + if(size === undefined || size === null) { + return true; + } + + if(isNumeric(size) && size > 1) { + return true; + } + + return false; + }; + + if(!isSizeGood(opts.width) || !isSizeGood(opts.height)) { + reject(new Error('Height and width should be pixel values.')); + } + + // first clone the GD so we can operate in a clean environment + var clone = clonePlot(gd, {format: 'png', height: opts.height, width: opts.width}); + var clonedGd = clone.gd; + + // put the cloned div somewhere off screen before attaching to DOM + clonedGd.style.position = 'absolute'; + clonedGd.style.left = '-5000px'; + document.body.appendChild(clonedGd); + + function wait() { + var delay = helpers.getDelay(clonedGd._fullLayout); + + return new Promise(function(resolve, reject) { + setTimeout(function() { + var svg = toSVG(clonedGd); + + var canvas = document.createElement('canvas'); + canvas.id = Lib.randstr(); + + svgToImg({ + format: opts.format, + width: clonedGd._fullLayout.width, + height: clonedGd._fullLayout.height, + canvas: canvas, + svg: svg, + // ask svgToImg to return a Promise + // rather than EventEmitter + // leave EventEmitter for backward + // compatibility + promise: true + }).then(function(url) { + if(clonedGd) document.body.removeChild(clonedGd); + resolve(url); + }).catch(function(err) { + reject(err); + }); + + }, delay); + }); + } + + var redrawFunc = helpers.getRedrawFunc(clonedGd); + + Plotly.plot(clonedGd, clone.data, clone.layout, clone.config) + .then(redrawFunc) + .then(wait) + .then(function(url) { resolve(url); }) + .catch(function(err) { + reject(err); + }); + }); + + return promise; +} + +module.exports = toImage; + +},{"../lib":122,"../plotly":145,"../snapshot/cloneplot":195,"../snapshot/helpers":198,"../snapshot/svgtoimg":200,"../snapshot/tosvg":202,"fast-isnumeric":13}],144:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +var Lib = require('../lib'); +var Plots = require('../plots/plots'); +var PlotSchema = require('./plot_schema'); + +var isPlainObject = Lib.isPlainObject; +var isArray = Array.isArray; + + +/** + * Validate a data array and layout object. + * + * @param {array} data + * @param {object} layout + * + * @return {array} array of error objects each containing: + * - {string} code + * error code ('object', 'array', 'schema', 'unused', 'invisible' or 'value') + * - {string} container + * container where the error occurs ('data' or 'layout') + * - {number} trace + * trace index of the 'data' container where the error occurs + * - {array} path + * nested path to the key that causes the error + * - {string} astr + * attribute string variant of 'path' compatible with Plotly.restyle and + * Plotly.relayout. + * - {string} msg + * error message (shown in console in logger config argument is enable) + */ +module.exports = function valiate(data, layout) { + var schema = PlotSchema.get(), + errorList = [], + gd = {}; + + var dataIn, layoutIn; + + if(isArray(data)) { + gd.data = Lib.extendDeep([], data); + dataIn = data; + } + else { + gd.data = []; + dataIn = []; + errorList.push(format('array', 'data')); + } + + if(isPlainObject(layout)) { + gd.layout = Lib.extendDeep({}, layout); + layoutIn = layout; + } + else { + gd.layout = {}; + layoutIn = {}; + if(arguments.length > 1) { + errorList.push(format('object', 'layout')); + } + } + + // N.B. dataIn and layoutIn are in general not the same as + // gd.data and gd.layout after supplyDefaults as some attributes + // in gd.data and gd.layout (still) get mutated during this step. + + Plots.supplyDefaults(gd); + + var dataOut = gd._fullData, + len = dataIn.length; + + for(var i = 0; i < len; i++) { + var traceIn = dataIn[i], + base = ['data', i]; + + if(!isPlainObject(traceIn)) { + errorList.push(format('object', base)); + continue; + } + + var traceOut = dataOut[i], + traceType = traceOut.type, + traceSchema = schema.traces[traceType].attributes; + + // PlotSchema does something fancy with trace 'type', reset it here + // to make the trace schema compatible with Lib.validate. + traceSchema.type = { + valType: 'enumerated', + values: [traceType] + }; + + if(traceOut.visible === false && traceIn.visible !== false) { + errorList.push(format('invisible', base)); + } + + crawl(traceIn, traceOut, traceSchema, errorList, base); + + var transformsIn = traceIn.transforms, + transformsOut = traceOut.transforms; + + if(transformsIn) { + if(!isArray(transformsIn)) { + errorList.push(format('array', base, ['transforms'])); + } + + base.push('transforms'); + + for(var j = 0; j < transformsIn.length; j++) { + var path = ['transforms', j], + transformType = transformsIn[j].type; + + if(!isPlainObject(transformsIn[j])) { + errorList.push(format('object', base, path)); + continue; + } + + var transformSchema = schema.transforms[transformType] ? + schema.transforms[transformType].attributes : + {}; + + // add 'type' to transform schema to validate the transform type + transformSchema.type = { + valType: 'enumerated', + values: Object.keys(schema.transforms) + }; + + crawl(transformsIn[j], transformsOut[j], transformSchema, errorList, base, path); + } + } + } + + var layoutOut = gd._fullLayout, + layoutSchema = fillLayoutSchema(schema, dataOut); + + crawl(layoutIn, layoutOut, layoutSchema, errorList, 'layout'); + + // return undefined if no validation errors were found + return (errorList.length === 0) ? void(0) : errorList; +}; + +function crawl(objIn, objOut, schema, list, base, path) { + path = path || []; + + var keys = Object.keys(objIn); + + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + + // transforms are handled separately + if(k === 'transforms') continue; + + var p = path.slice(); + p.push(k); + + var valIn = objIn[k], + valOut = objOut[k]; + + var nestedSchema = getNestedSchema(schema, k), + isInfoArray = (nestedSchema || {}).valType === 'info_array'; + + if(!isInSchema(schema, k)) { + list.push(format('schema', base, p)); + } + else if(isPlainObject(valIn) && isPlainObject(valOut)) { + crawl(valIn, valOut, nestedSchema, list, base, p); + } + else if(nestedSchema.items && !isInfoArray && isArray(valIn)) { + var items = nestedSchema.items, + _nestedSchema = items[Object.keys(items)[0]], + indexList = []; + + var j, _p; + + // loop over valOut items while keeping track of their + // corresponding input container index (given by _index) + for(j = 0; j < valOut.length; j++) { + var _index = valOut[j]._index || j; + + _p = p.slice(); + _p.push(_index); + + if(isPlainObject(valIn[_index]) && isPlainObject(valOut[j])) { + indexList.push(_index); + crawl(valIn[_index], valOut[j], _nestedSchema, list, base, _p); + } + } + + // loop over valIn to determine where it went wrong for some items + for(j = 0; j < valIn.length; j++) { + _p = p.slice(); + _p.push(j); + + if(!isPlainObject(valIn[j])) { + list.push(format('object', base, _p, valIn[j])); + } + else if(indexList.indexOf(j) === -1) { + list.push(format('unused', base, _p)); + } + } + } + else if(!isPlainObject(valIn) && isPlainObject(valOut)) { + list.push(format('object', base, p, valIn)); + } + else if(!isArray(valIn) && isArray(valOut) && !isInfoArray) { + list.push(format('array', base, p, valIn)); + } + else if(!(k in objOut)) { + list.push(format('unused', base, p, valIn)); + } + else if(!Lib.validate(valIn, nestedSchema)) { + list.push(format('value', base, p, valIn)); + } + } + + return list; +} + +// the 'full' layout schema depends on the traces types presents +function fillLayoutSchema(schema, dataOut) { + for(var i = 0; i < dataOut.length; i++) { + var traceType = dataOut[i].type, + traceLayoutAttr = schema.traces[traceType].layoutAttributes; + + if(traceLayoutAttr) { + Lib.extendFlat(schema.layout.layoutAttributes, traceLayoutAttr); + } + } + + return schema.layout.layoutAttributes; +} + +// validation error codes +var code2msgFunc = { + object: function(base, astr) { + var prefix; + + if(base === 'layout' && astr === '') prefix = 'The layout argument'; + else if(base[0] === 'data' && astr === '') { + prefix = 'Trace ' + base[1] + ' in the data argument'; + } + else prefix = inBase(base) + 'key ' + astr; + + return prefix + ' must be linked to an object container'; + }, + array: function(base, astr) { + var prefix; + + if(base === 'data') prefix = 'The data argument'; + else prefix = inBase(base) + 'key ' + astr; + + return prefix + ' must be linked to an array container'; + }, + schema: function(base, astr) { + return inBase(base) + 'key ' + astr + ' is not part of the schema'; + }, + unused: function(base, astr, valIn) { + var target = isPlainObject(valIn) ? 'container' : 'key'; + + return inBase(base) + target + ' ' + astr + ' did not get coerced'; + }, + invisible: function(base) { + return 'Trace ' + base[1] + ' got defaulted to be not visible'; + }, + value: function(base, astr, valIn) { + return [ + inBase(base) + 'key ' + astr, + 'is set to an invalid value (' + valIn + ')' + ].join(' '); + } +}; + +function inBase(base) { + if(isArray(base)) return 'In data trace ' + base[1] + ', '; + + return 'In ' + base + ', '; +} + +function format(code, base, path, valIn) { + path = path || ''; + + var container, trace; + + // container is either 'data' or 'layout + // trace is the trace index if 'data', null otherwise + + if(isArray(base)) { + container = base[0]; + trace = base[1]; + } + else { + container = base; + trace = null; + } + + var astr = convertPathToAttributeString(path), + msg = code2msgFunc[code](base, astr, valIn); + + // log to console if logger config option is enabled + Lib.log(msg); + + return { + code: code, + container: container, + trace: trace, + path: path, + astr: astr, + msg: msg + }; +} + +function isInSchema(schema, key) { + var parts = splitKey(key), + keyMinusId = parts.keyMinusId, + id = parts.id; + + if((keyMinusId in schema) && schema[keyMinusId]._isSubplotObj && id) { + return true; + } + + return (key in schema); +} + +function getNestedSchema(schema, key) { + var parts = splitKey(key); + + return schema[parts.keyMinusId]; +} + +function splitKey(key) { + var idRegex = /([2-9]|[1-9][0-9]+)$/; + + var keyMinusId = key.split(idRegex)[0], + id = key.substr(keyMinusId.length, key.length); + + return { + keyMinusId: keyMinusId, + id: id + }; +} + +function convertPathToAttributeString(path) { + if(!isArray(path)) return String(path); + + var astr = ''; + + for(var i = 0; i < path.length; i++) { + var p = path[i]; + + if(typeof p === 'number') { + astr = astr.substr(0, astr.length - 1) + '[' + p + ']'; + } + else { + astr += p; + } + + if(i < path.length - 1) astr += '.'; + } + + return astr; +} + +},{"../lib":122,"../plots/plots":186,"./plot_schema":139}],145:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * Pack internal modules unto an object. + * + * This object is require'ed in as 'Plotly' in numerous src and test files. + * Require'ing 'Plotly' bypasses circular dependencies. + * + * Future development should move away from this pattern. + * + */ + +// configuration +exports.defaultConfig = require('./plot_api/plot_config'); + +// plots +exports.Plots = require('./plots/plots'); +exports.Axes = require('./plots/cartesian/axes'); +exports.Fx = require('./plots/cartesian/graph_interact'); +exports.ModeBar = require('./components/modebar'); + +// plot api +require('./plot_api/plot_api'); + +},{"./components/modebar":73,"./plot_api/plot_api":137,"./plot_api/plot_config":138,"./plots/cartesian/axes":150,"./plots/cartesian/graph_interact":157,"./plots/plots":186}],146:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + mode: { + valType: 'enumerated', + dflt: 'afterall', + + values: ['immediate', 'next', 'afterall'], + + }, + direction: { + valType: 'enumerated', + + values: ['forward', 'reverse'], + dflt: 'forward', + + }, + fromcurrent: { + valType: 'boolean', + dflt: false, + + + }, + frame: { + duration: { + valType: 'number', + + min: 0, + dflt: 500, + + }, + redraw: { + valType: 'boolean', + + dflt: true, + + }, + }, + transition: { + duration: { + valType: 'number', + + min: 0, + dflt: 500, + + }, + easing: { + valType: 'enumerated', + dflt: 'cubic-in-out', + values: [ + 'linear', + 'quad', + 'cubic', + 'sin', + 'exp', + 'circle', + 'elastic', + 'back', + 'bounce', + 'linear-in', + 'quad-in', + 'cubic-in', + 'sin-in', + 'exp-in', + 'circle-in', + 'elastic-in', + 'back-in', + 'bounce-in', + 'linear-out', + 'quad-out', + 'cubic-out', + 'sin-out', + 'exp-out', + 'circle-out', + 'elastic-out', + 'back-out', + 'bounce-out', + 'linear-in-out', + 'quad-in-out', + 'cubic-in-out', + 'sin-in-out', + 'exp-in-out', + 'circle-in-out', + 'elastic-in-out', + 'back-in-out', + 'bounce-in-out' + ], + + + }, + } +}; + +},{}],147:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../lib'); + + +/** Convenience wrapper for making array container logic DRY and consistent + * + * @param {object} parentObjIn + * user input object where the container in question is linked + * (i.e. either a user trace object or the user layout object) + * + * @param {object} parentObjOut + * full object where the coerced container will be linked + * (i.e. either a full trace object or the full layout object) + * + * @param {object} opts + * options object: + * - name {string} + * name of the key linking the container in question + * - handleItemDefaults {function} + * defaults method to be called on each item in the array container in question + * + * Its arguments are: + * - itemIn {object} item in user layout + * - itemOut {object} item in full layout + * - parentObj {object} (as in closure) + * - opts {object} (as in closure) + * - itemOpts {object} + * - itemIsNotPlainObject {boolean} + * N.B. + * + * - opts is passed to handleItemDefaults so it can also store + * links to supplementary data (e.g. fullData for layout components) + * + */ +module.exports = function handleArrayContainerDefaults(parentObjIn, parentObjOut, opts) { + var name = opts.name; + + var contIn = Array.isArray(parentObjIn[name]) ? parentObjIn[name] : [], + contOut = parentObjOut[name] = []; + + for(var i = 0; i < contIn.length; i++) { + var itemIn = contIn[i], + itemOut = {}, + itemOpts = {}; + + if(!Lib.isPlainObject(itemIn)) { + itemOpts.itemIsNotPlainObject = true; + itemIn = {}; + } + + opts.handleItemDefaults(itemIn, itemOut, parentObjOut, opts, itemOpts); + + itemOut._input = itemIn; + itemOut._index = i; + + contOut.push(itemOut); + } +}; + +},{"../lib":122}],148:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + type: { + valType: 'enumerated', + + values: [], // listed dynamically + dflt: 'scatter' + }, + visible: { + valType: 'enumerated', + values: [true, false, 'legendonly'], + + dflt: true, + + }, + showlegend: { + valType: 'boolean', + + dflt: true, + + }, + legendgroup: { + valType: 'string', + + dflt: '', + + }, + opacity: { + valType: 'number', + + min: 0, + max: 1, + dflt: 1, + + }, + name: { + valType: 'string', + + + }, + uid: { + valType: 'string', + + dflt: '' + }, + hoverinfo: { + valType: 'flaglist', + + flags: ['x', 'y', 'z', 'text', 'name'], + extras: ['all', 'none', 'skip'], + dflt: 'all', + + }, + stream: { + token: { + valType: 'string', + noBlank: true, + strict: true, + + + }, + maxpoints: { + valType: 'number', + min: 0, + max: 10000, + dflt: 500, + + + } + } +}; + +},{}],149:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + xaxis: { + valType: 'subplotid', + + dflt: 'x', + + }, + yaxis: { + valType: 'subplotid', + + dflt: 'y', + + } +}; + +},{}],150:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Registry = require('../../registry'); +var Plots = require('../../plots/plots'); +var Lib = require('../../lib'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var Titles = require('../../components/titles'); +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); + +var constants = require('../../constants/numerical'); +var FP_SAFE = constants.FP_SAFE; +var ONEAVGYEAR = constants.ONEAVGYEAR; +var ONEAVGMONTH = constants.ONEAVGMONTH; +var ONEDAY = constants.ONEDAY; +var ONEHOUR = constants.ONEHOUR; +var ONEMIN = constants.ONEMIN; +var ONESEC = constants.ONESEC; + + +var axes = module.exports = {}; + +axes.layoutAttributes = require('./layout_attributes'); +axes.supplyLayoutDefaults = require('./layout_defaults'); + +axes.setConvert = require('./set_convert'); + +var axisIds = require('./axis_ids'); +axes.id2name = axisIds.id2name; +axes.cleanId = axisIds.cleanId; +axes.list = axisIds.list; +axes.listIds = axisIds.listIds; +axes.getFromId = axisIds.getFromId; +axes.getFromTrace = axisIds.getFromTrace; + + +/* + * find the list of possible axes to reference with an xref or yref attribute + * and coerce it to that list + * + * attr: the attribute we're generating a reference for. Should end in 'x' or 'y' + * but can be prefixed, like 'ax' for annotation's arrow x + * dflt: the default to coerce to, or blank to use the first axis (falling back on + * extraOption if there is no axis) + * extraOption: aside from existing axes with this letter, what non-axis value is allowed? + * Only required if it's different from `dflt` + */ +axes.coerceRef = function(containerIn, containerOut, gd, attr, dflt, extraOption) { + var axLetter = attr.charAt(attr.length - 1), + axlist = gd._fullLayout._has('gl2d') ? [] : axes.listIds(gd, axLetter), + refAttr = attr + 'ref', + attrDef = {}; + + if(!dflt) dflt = axlist[0] || extraOption; + if(!extraOption) extraOption = dflt; + + // data-ref annotations are not supported in gl2d yet + + attrDef[refAttr] = { + valType: 'enumerated', + values: axlist.concat(extraOption ? [extraOption] : []), + dflt: dflt + }; + + // xref, yref + return Lib.coerce(containerIn, containerOut, attrDef, refAttr); +}; + +/* + * coerce position attributes (range-type) that can be either on axes or absolute + * (paper or pixel) referenced. The biggest complication here is that we don't know + * before looking at the axis whether the value must be a number or not (it may be + * a date string), so we can't use the regular valType='number' machinery + * + * axRef (string): the axis this position is referenced to, or: + * paper: fraction of the plot area + * pixel: pixels relative to some starting position + * attr (string): the attribute in containerOut we are coercing + * dflt (number): the default position, as a fraction or pixels. If the attribute + * is to be axis-referenced, this will be converted to an axis data value + * + * Also cleans the values, since the attribute definition itself has to say + * valType: 'any' to handle date axes. This allows us to accept: + * - for category axes: category names, and convert them here into serial numbers. + * Note that this will NOT work for axis range endpoints, because we don't know + * the category list yet (it's set by ax.makeCalcdata during calc) + * but it works for component (note, shape, images) positions. + * - for date axes: JS Dates or milliseconds, and convert to date strings + * - for other types: coerce them to numbers + */ +axes.coercePosition = function(containerOut, gd, coerce, axRef, attr, dflt) { + var pos, + newPos; + + if(axRef === 'paper' || axRef === 'pixel') { + pos = coerce(attr, dflt); + } + else { + var ax = axes.getFromId(gd, axRef); + + dflt = ax.fraction2r(dflt); + pos = coerce(attr, dflt); + + if(ax.type === 'category') { + // if position is given as a category name, convert it to a number + if(typeof pos === 'string' && (ax._categories || []).length) { + newPos = ax._categories.indexOf(pos); + containerOut[attr] = (newPos === -1) ? dflt : newPos; + return; + } + } + else if(ax.type === 'date') { + containerOut[attr] = Lib.cleanDate(pos); + return; + } + } + // finally make sure we have a number (unless date type already returned a string) + containerOut[attr] = isNumeric(pos) ? Number(pos) : dflt; +}; + +// empty out types for all axes containing these traces +// so we auto-set them again +axes.clearTypes = function(gd, traces) { + if(!Array.isArray(traces) || !traces.length) { + traces = (gd._fullData).map(function(d, i) { return i; }); + } + traces.forEach(function(tracenum) { + var trace = gd.data[tracenum]; + delete (axes.getFromId(gd, trace.xaxis) || {}).type; + delete (axes.getFromId(gd, trace.yaxis) || {}).type; + }); +}; + +// get counteraxis letter for this axis (name or id) +// this can also be used as the id for default counter axis +axes.counterLetter = function(id) { + var axLetter = id.charAt(0); + if(axLetter === 'x') return 'y'; + if(axLetter === 'y') return 'x'; +}; + +// incorporate a new minimum difference and first tick into +// forced +// note that _forceTick0 is linearized, so needs to be turned into +// a range value for setting tick0 +axes.minDtick = function(ax, newDiff, newFirst, allow) { + // doesn't make sense to do forced min dTick on log or category axes, + // and the plot itself may decide to cancel (ie non-grouped bars) + if(['log', 'category'].indexOf(ax.type) !== -1 || !allow) { + ax._minDtick = 0; + } + // undefined means there's nothing there yet + else if(ax._minDtick === undefined) { + ax._minDtick = newDiff; + ax._forceTick0 = newFirst; + } + else if(ax._minDtick) { + // existing minDtick is an integer multiple of newDiff + // (within rounding err) + // and forceTick0 can be shifted to newFirst + if((ax._minDtick / newDiff + 1e-6) % 1 < 2e-6 && + (((newFirst - ax._forceTick0) / newDiff % 1) + + 1.000001) % 1 < 2e-6) { + ax._minDtick = newDiff; + ax._forceTick0 = newFirst; + } + // if the converse is true (newDiff is a multiple of minDtick and + // newFirst can be shifted to forceTick0) then do nothing - same + // forcing stands. Otherwise, cancel forced minimum + else if((newDiff / ax._minDtick + 1e-6) % 1 > 2e-6 || + (((newFirst - ax._forceTick0) / ax._minDtick % 1) + + 1.000001) % 1 > 2e-6) { + ax._minDtick = 0; + } + } +}; + +// Find the autorange for this axis +// +// assumes ax._min and ax._max have already been set by calling axes.expand +// using calcdata from all traces. These are arrays of: +// {val: calcdata value, pad: extra pixels beyond this value} +// +// Returns an array of [min, max]. These are calcdata for log and category axes +// and data for linear and date axes. +// +// TODO: we want to change log to data as well, but it's hard to do this +// maintaining backward compatibility. category will always have to use calcdata +// though, because otherwise values between categories (or outside all categories) +// would be impossible. +axes.getAutoRange = function(ax) { + var newRange = []; + + var minmin = ax._min[0].val, + maxmax = ax._max[0].val, + i; + + for(i = 1; i < ax._min.length; i++) { + if(minmin !== maxmax) break; + minmin = Math.min(minmin, ax._min[i].val); + } + for(i = 1; i < ax._max.length; i++) { + if(minmin !== maxmax) break; + maxmax = Math.max(maxmax, ax._max[i].val); + } + + var j, minpt, maxpt, minbest, maxbest, dp, dv, + mbest = 0, + axReverse = false; + + if(ax.range) { + var rng = ax.range.map(ax.r2l); + axReverse = rng[1] < rng[0]; + } + + // one-time setting to easily reverse the axis + // when plotting from code + if(ax.autorange === 'reversed') { + axReverse = true; + ax.autorange = true; + } + + for(i = 0; i < ax._min.length; i++) { + minpt = ax._min[i]; + for(j = 0; j < ax._max.length; j++) { + maxpt = ax._max[j]; + dv = maxpt.val - minpt.val; + dp = ax._length - minpt.pad - maxpt.pad; + if(dv > 0 && dp > 0 && dv / dp > mbest) { + minbest = minpt; + maxbest = maxpt; + mbest = dv / dp; + } + } + } + + if(minmin === maxmax) { + var lower = minmin - 1; + var upper = minmin + 1; + if(ax.rangemode === 'tozero') { + newRange = minmin < 0 ? [lower, 0] : [0, upper]; + } + else if(ax.rangemode === 'nonnegative') { + newRange = [Math.max(0, lower), Math.max(0, upper)]; + } + else { + newRange = [lower, upper]; + } + } + else if(mbest) { + if(ax.type === 'linear' || ax.type === '-') { + if(ax.rangemode === 'tozero') { + if(minbest.val >= 0) { + minbest = {val: 0, pad: 0}; + } + if(maxbest.val <= 0) { + maxbest = {val: 0, pad: 0}; + } + } + else if(ax.rangemode === 'nonnegative') { + if(minbest.val - mbest * minbest.pad < 0) { + minbest = {val: 0, pad: 0}; + } + if(maxbest.val < 0) { + maxbest = {val: 1, pad: 0}; + } + } + + // in case it changed again... + mbest = (maxbest.val - minbest.val) / + (ax._length - minbest.pad - maxbest.pad); + + } + + newRange = [ + minbest.val - mbest * minbest.pad, + maxbest.val + mbest * maxbest.pad + ]; + } + + // don't let axis have zero size, while still respecting tozero and nonnegative + if(newRange[0] === newRange[1]) { + if(ax.rangemode === 'tozero') { + if(newRange[0] < 0) { + newRange = [newRange[0], 0]; + } + else if(newRange[0] > 0) { + newRange = [0, newRange[0]]; + } + else { + newRange = [0, 1]; + } + } + else { + newRange = [newRange[0] - 1, newRange[0] + 1]; + if(ax.rangemode === 'nonnegative') { + newRange[0] = Math.max(0, newRange[0]); + } + } + } + + // maintain reversal + if(axReverse) newRange.reverse(); + + return newRange.map(ax.l2r || Number); +}; + +axes.doAutoRange = function(ax) { + if(!ax._length) ax.setScale(); + + // TODO do we really need this? + var hasDeps = (ax._min && ax._max && ax._min.length && ax._max.length); + + if(ax.autorange && hasDeps) { + ax.range = axes.getAutoRange(ax); + + // doAutoRange will get called on fullLayout, + // but we want to report its results back to layout + var axIn = ax._gd.layout[ax._name]; + + if(!axIn) ax._gd.layout[ax._name] = axIn = {}; + + if(axIn !== ax) { + axIn.range = ax.range.slice(); + axIn.autorange = ax.autorange; + } + } +}; + +// save a copy of the initial axis ranges in fullLayout +// use them in mode bar and dblclick events +axes.saveRangeInitial = function(gd, overwrite) { + var axList = axes.list(gd, '', true), + hasOneAxisChanged = false; + + for(var i = 0; i < axList.length; i++) { + var ax = axList[i]; + + var isNew = (ax._rangeInitial === undefined); + var hasChanged = ( + isNew || !( + ax.range[0] === ax._rangeInitial[0] && + ax.range[1] === ax._rangeInitial[1] + ) + ); + + if((isNew && ax.autorange === false) || (overwrite && hasChanged)) { + ax._rangeInitial = ax.range.slice(); + hasOneAxisChanged = true; + } + } + + return hasOneAxisChanged; +}; + +// axes.expand: if autoranging, include new data in the outer limits +// for this axis +// data is an array of numbers (ie already run through ax.d2c) +// available options: +// vpad: (number or number array) pad values (data value +-vpad) +// ppad: (number or number array) pad pixels (pixel location +-ppad) +// ppadplus, ppadminus, vpadplus, vpadminus: +// separate padding for each side, overrides symmetric +// padded: (boolean) add 5% padding to both ends +// (unless one end is overridden by tozero) +// tozero: (boolean) make sure to include zero if axis is linear, +// and make it a tight bound if possible +axes.expand = function(ax, data, options) { + if(!(ax.autorange || ax._needsExpand) || !data) return; + if(!ax._min) ax._min = []; + if(!ax._max) ax._max = []; + if(!options) options = {}; + if(!ax._m) ax.setScale(); + + var len = data.length, + extrappad = options.padded ? ax._length * 0.05 : 0, + tozero = options.tozero && (ax.type === 'linear' || ax.type === '-'), + i, j, v, di, dmin, dmax, + ppadiplus, ppadiminus, includeThis, vmin, vmax; + + function getPad(item) { + if(Array.isArray(item)) { + return function(i) { return Math.max(Number(item[i]||0), 0); }; + } + else { + var v = Math.max(Number(item||0), 0); + return function() { return v; }; + } + } + var ppadplus = getPad((ax._m > 0 ? + options.ppadplus : options.ppadminus) || options.ppad || 0), + ppadminus = getPad((ax._m > 0 ? + options.ppadminus : options.ppadplus) || options.ppad || 0), + vpadplus = getPad(options.vpadplus || options.vpad), + vpadminus = getPad(options.vpadminus || options.vpad); + + function addItem(i) { + di = data[i]; + if(!isNumeric(di)) return; + ppadiplus = ppadplus(i) + extrappad; + ppadiminus = ppadminus(i) + extrappad; + vmin = di - vpadminus(i); + vmax = di + vpadplus(i); + // special case for log axes: if vpad makes this object span + // more than an order of mag, clip it to one order. This is so + // we don't have non-positive errors or absurdly large lower + // range due to rounding errors + if(ax.type === 'log' && vmin < vmax / 10) { vmin = vmax / 10; } + + dmin = ax.c2l(vmin); + dmax = ax.c2l(vmax); + + if(tozero) { + dmin = Math.min(0, dmin); + dmax = Math.max(0, dmax); + } + + // In order to stop overflow errors, don't consider points + // too close to the limits of js floating point + function goodNumber(v) { + return isNumeric(v) && Math.abs(v) < FP_SAFE; + } + + if(goodNumber(dmin)) { + includeThis = true; + // take items v from ax._min and compare them to the + // presently active point: + // - if the item supercedes the new point, set includethis false + // - if the new pt supercedes the item, delete it from ax._min + for(j = 0; j < ax._min.length && includeThis; j++) { + v = ax._min[j]; + if(v.val <= dmin && v.pad >= ppadiminus) { + includeThis = false; + } + else if(v.val >= dmin && v.pad <= ppadiminus) { + ax._min.splice(j, 1); + j--; + } + } + if(includeThis) { + ax._min.push({ + val: dmin, + pad: (tozero && dmin === 0) ? 0 : ppadiminus + }); + } + } + + if(goodNumber(dmax)) { + includeThis = true; + for(j = 0; j < ax._max.length && includeThis; j++) { + v = ax._max[j]; + if(v.val >= dmax && v.pad >= ppadiplus) { + includeThis = false; + } + else if(v.val <= dmax && v.pad <= ppadiplus) { + ax._max.splice(j, 1); + j--; + } + } + if(includeThis) { + ax._max.push({ + val: dmax, + pad: (tozero && dmax === 0) ? 0 : ppadiplus + }); + } + } + } + + // For efficiency covering monotonic or near-monotonic data, + // check a few points at both ends first and then sweep + // through the middle + for(i = 0; i < 6; i++) addItem(i); + for(i = len - 1; i > 5; i--) addItem(i); + +}; + +axes.autoBin = function(data, ax, nbins, is2d) { + var datamin = Lib.aggNums(Math.min, null, data), + datamax = Lib.aggNums(Math.max, null, data); + if(ax.type === 'category') { + return { + start: datamin - 0.5, + end: datamax + 0.5, + size: 1 + }; + } + + var size0; + if(nbins) size0 = ((datamax - datamin) / nbins); + else { + // totally auto: scale off std deviation so the highest bin is + // somewhat taller than the total number of bins, but don't let + // the size get smaller than the 'nice' rounded down minimum + // difference between values + var distinctData = Lib.distinctVals(data), + msexp = Math.pow(10, Math.floor( + Math.log(distinctData.minDiff) / Math.LN10)), + // TODO: there are some date cases where this will fail... + minSize = msexp * Lib.roundUp( + distinctData.minDiff / msexp, [0.9, 1.9, 4.9, 9.9], true); + size0 = Math.max(minSize, 2 * Lib.stdev(data) / + Math.pow(data.length, is2d ? 0.25 : 0.4)); + } + + // piggyback off autotick code to make "nice" bin sizes + var dummyax; + if(ax.type === 'log') { + dummyax = { + type: 'linear', + range: [datamin, datamax], + r2l: Number + }; + } + else { + dummyax = { + type: ax.type, + // conversion below would be ax.c2r but that's only different from l2r + // for log, and this is the only place (so far?) we would want c2r. + range: [datamin, datamax].map(ax.l2r), + r2l: ax.r2l + }; + } + + axes.autoTicks(dummyax, size0); + var binstart = axes.tickIncrement( + axes.tickFirst(dummyax), dummyax.dtick, 'reverse'), + binend; + + function nearEdge(v) { + // is a value within 1% of a bin edge? + return (1 + (v - binstart) * 100 / dummyax.dtick) % 100 < 2; + } + + // check for too many data points right at the edges of bins + // (>50% within 1% of bin edges) or all data points integral + // and offset the bins accordingly + if(typeof dummyax.dtick === 'number') { + var edgecount = 0, + midcount = 0, + intcount = 0, + blankcount = 0; + for(var i = 0; i < data.length; i++) { + if(data[i] % 1 === 0) intcount++; + else if(!isNumeric(data[i])) blankcount++; + + if(nearEdge(data[i])) edgecount++; + if(nearEdge(data[i] + dummyax.dtick / 2)) midcount++; + } + var datacount = data.length - blankcount; + + if(intcount === datacount && ax.type !== 'date') { + // all integers: if bin size is <1, it's because + // that was specifically requested (large nbins) + // so respect that... but center the bins containing + // integers on those integers + if(dummyax.dtick < 1) { + binstart = datamin - 0.5 * dummyax.dtick; + } + // otherwise start half an integer down regardless of + // the bin size, just enough to clear up endpoint + // ambiguity about which integers are in which bins. + else binstart -= 0.5; + } + else if(midcount < datacount * 0.1) { + if(edgecount > datacount * 0.3 || + nearEdge(datamin) || nearEdge(datamax)) { + // lots of points at the edge, not many in the middle + // shift half a bin + var binshift = dummyax.dtick / 2; + binstart += (binstart + binshift < datamin) ? binshift : -binshift; + } + } + + var bincount = 1 + Math.floor((datamax - binstart) / dummyax.dtick); + binend = binstart + bincount * dummyax.dtick; + } + else { + // calculate the endpoint for nonlinear ticks - you have to + // just increment until you're done + binend = binstart; + while(binend <= datamax) { + binend = axes.tickIncrement(binend, dummyax.dtick); + } + } + + return { + start: ax.c2r(binstart), + end: ax.c2r(binend), + size: dummyax.dtick + }; +}; + + +// ---------------------------------------------------- +// Ticks and grids +// ---------------------------------------------------- + +// calculate the ticks: text, values, positioning +// if ticks are set to automatic, determine the right values (tick0,dtick) +// in any case, set tickround to # of digits to round tick labels to, +// or codes to this effect for log and date scales +axes.calcTicks = function calcTicks(ax) { + if(ax.tickmode === 'array') return arrayTicks(ax); + + var rng = ax.range.map(ax.r2l); + + // calculate max number of (auto) ticks to display based on plot size + if(ax.tickmode === 'auto' || !ax.dtick) { + var nt = ax.nticks, + minPx; + if(!nt) { + if(ax.type === 'category') { + minPx = ax.tickfont ? (ax.tickfont.size || 12) * 1.2 : 15; + nt = ax._length / minPx; + } + else { + minPx = ax._id.charAt(0) === 'y' ? 40 : 80; + nt = Lib.constrain(ax._length / minPx, 4, 9) + 1; + } + } + axes.autoTicks(ax, Math.abs(rng[1] - rng[0]) / nt); + // check for a forced minimum dtick + if(ax._minDtick > 0 && ax.dtick < ax._minDtick * 2) { + ax.dtick = ax._minDtick; + ax.tick0 = ax.l2r(ax._forceTick0); + } + } + + // check for missing tick0 + if(!ax.tick0) { + ax.tick0 = (ax.type === 'date') ? '2000-01-01' : 0; + } + + // now figure out rounding of tick values + autoTickRound(ax); + + // find the first tick + ax._tmin = axes.tickFirst(ax); + + // check for reversed axis + var axrev = (rng[1] < rng[0]); + + // return the full set of tick vals + var vals = [], + // add a tiny bit so we get ticks which may have rounded out + endtick = rng[1] * 1.0001 - rng[0] * 0.0001; + if(ax.type === 'category') { + endtick = (axrev) ? Math.max(-0.5, endtick) : + Math.min(ax._categories.length - 0.5, endtick); + } + for(var x = ax._tmin; + (axrev) ? (x >= endtick) : (x <= endtick); + x = axes.tickIncrement(x, ax.dtick, axrev)) { + vals.push(x); + + // prevent infinite loops + if(vals.length > 1000) break; + } + + // save the last tick as well as first, so we can + // show the exponent only on the last one + ax._tmax = vals[vals.length - 1]; + + // for showing date suffixes: ax._prevSuffix holds what we showed most + // recently. Start with it cleared and mark that we're in calcTicks (ie + // calculating a whole string of these so we should care what the previous + // suffix was!) + ax._prevSuffix = ''; + ax._inCalcTicks = true; + + var ticksOut = new Array(vals.length); + for(var i = 0; i < vals.length; i++) ticksOut[i] = axes.tickText(ax, vals[i]); + + ax._inCalcTicks = false; + + return ticksOut; +}; + +function arrayTicks(ax) { + var vals = ax.tickvals, + text = ax.ticktext, + ticksOut = new Array(vals.length), + rng = ax.range.map(ax.r2l), + r0expanded = rng[0] * 1.0001 - rng[1] * 0.0001, + r1expanded = rng[1] * 1.0001 - rng[0] * 0.0001, + tickMin = Math.min(r0expanded, r1expanded), + tickMax = Math.max(r0expanded, r1expanded), + vali, + i, + j = 0; + + // without a text array, just format the given values as any other ticks + // except with more precision to the numbers + if(!Array.isArray(text)) text = []; + + for(i = 0; i < vals.length; i++) { + vali = ax.d2l(vals[i]); + if(vali > tickMin && vali < tickMax) { + if(text[i] === undefined) ticksOut[j] = axes.tickText(ax, vali); + else ticksOut[j] = tickTextObj(ax, vali, String(text[i])); + j++; + } + } + + if(j < vals.length) ticksOut.splice(j, vals.length - j); + + return ticksOut; +} + +var roundBase10 = [2, 5, 10], + roundBase24 = [1, 2, 3, 6, 12], + roundBase60 = [1, 2, 5, 10, 15, 30], + // 2&3 day ticks are weird, but need something btwn 1&7 + roundDays = [1, 2, 3, 7, 14], + // approx. tick positions for log axes, showing all (1) and just 1, 2, 5 (2) + // these don't have to be exact, just close enough to round to the right value + roundLog1 = [-0.046, 0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1], + roundLog2 = [-0.301, 0, 0.301, 0.699, 1]; + +function roundDTick(roughDTick, base, roundingSet) { + return base * Lib.roundUp(roughDTick / base, roundingSet); +} + +// autoTicks: calculate best guess at pleasant ticks for this axis +// inputs: +// ax - an axis object +// roughDTick - rough tick spacing (to be turned into a nice round number) +// outputs (into ax): +// tick0: starting point for ticks (not necessarily on the graph) +// usually 0 for numeric (=10^0=1 for log) or jan 1, 2000 for dates +// dtick: the actual, nice round tick spacing, usually a little larger than roughDTick +// if the ticks are spaced linearly (linear scale, categories, +// log with only full powers, date ticks < month), +// this will just be a number +// months: M# +// years: M# where # is 12*number of years +// log with linear ticks: L# where # is the linear tick spacing +// log showing powers plus some intermediates: +// D1 shows all digits, D2 shows 2 and 5 +axes.autoTicks = function(ax, roughDTick) { + var base; + + if(ax.type === 'date') { + ax.tick0 = '2000-01-01'; + // the criteria below are all based on the rough spacing we calculate + // being > half of the final unit - so precalculate twice the rough val + var roughX2 = 2 * roughDTick; + + if(roughX2 > ONEAVGYEAR) { + roughDTick /= ONEAVGYEAR; + base = Math.pow(10, Math.floor(Math.log(roughDTick) / Math.LN10)); + ax.dtick = 'M' + (12 * roundDTick(roughDTick, base, roundBase10)); + } + else if(roughX2 > ONEAVGMONTH) { + roughDTick /= ONEAVGMONTH; + ax.dtick = 'M' + roundDTick(roughDTick, 1, roundBase24); + } + else if(roughX2 > ONEDAY) { + ax.dtick = roundDTick(roughDTick, ONEDAY, roundDays); + // get week ticks on sunday + // this will also move the base tick off 2000-01-01 if dtick is + // 2 or 3 days... but that's a weird enough case that we'll ignore it. + ax.tick0 = '2000-01-02'; + } + else if(roughX2 > ONEHOUR) { + ax.dtick = roundDTick(roughDTick, ONEHOUR, roundBase24); + } + else if(roughX2 > ONEMIN) { + ax.dtick = roundDTick(roughDTick, ONEMIN, roundBase60); + } + else if(roughX2 > ONESEC) { + ax.dtick = roundDTick(roughDTick, ONESEC, roundBase60); + } + else { + // milliseconds + base = Math.pow(10, Math.floor(Math.log(roughDTick) / Math.LN10)); + ax.dtick = roundDTick(roughDTick, base, roundBase10); + } + } + else if(ax.type === 'log') { + ax.tick0 = 0; + var rng = ax.range.map(ax.r2l); + + if(roughDTick > 0.7) { + // only show powers of 10 + ax.dtick = Math.ceil(roughDTick); + } + else if(Math.abs(rng[1] - rng[0]) < 1) { + // span is less than one power of 10 + var nt = 1.5 * Math.abs((rng[1] - rng[0]) / roughDTick); + + // ticks on a linear scale, labeled fully + roughDTick = Math.abs(Math.pow(10, rng[1]) - + Math.pow(10, rng[0])) / nt; + base = Math.pow(10, Math.floor(Math.log(roughDTick) / Math.LN10)); + ax.dtick = 'L' + roundDTick(roughDTick, base, roundBase10); + } + else { + // include intermediates between powers of 10, + // labeled with small digits + // ax.dtick = "D2" (show 2 and 5) or "D1" (show all digits) + ax.dtick = (roughDTick > 0.3) ? 'D2' : 'D1'; + } + } + else if(ax.type === 'category') { + ax.tick0 = 0; + ax.dtick = Math.ceil(Math.max(roughDTick, 1)); + } + else { + // auto ticks always start at 0 + ax.tick0 = 0; + base = Math.pow(10, Math.floor(Math.log(roughDTick) / Math.LN10)); + ax.dtick = roundDTick(roughDTick, base, roundBase10); + } + + // prevent infinite loops + if(ax.dtick === 0) ax.dtick = 1; + + // TODO: this is from log axis histograms with autorange off + if(!isNumeric(ax.dtick) && typeof ax.dtick !== 'string') { + var olddtick = ax.dtick; + ax.dtick = 1; + throw 'ax.dtick error: ' + String(olddtick); + } +}; + +// after dtick is already known, find tickround = precision +// to display in tick labels +// for numeric ticks, integer # digits after . to round to +// for date ticks, the last date part to show (y,m,d,H,M,S) +// or an integer # digits past seconds +function autoTickRound(ax) { + var dtick = ax.dtick; + + ax._tickexponent = 0; + if(!isNumeric(dtick) && typeof dtick !== 'string') { + dtick = 1; + } + + if(ax.type === 'category') { + ax._tickround = null; + } + if(ax.type === 'date') { + // If tick0 is unusual, give tickround a bit more information + // not necessarily *all* the information in tick0 though, if it's really odd + // minimal string length for tick0: 'd' is 10, 'M' is 16, 'S' is 19 + // take off a leading minus (year < 0 so length is consistent) + var tick0ms = Lib.dateTime2ms(ax.tick0), + tick0str = Lib.ms2DateTime(tick0ms).replace(/^-/, ''), + tick0len = tick0str.length; + + if(String(dtick).charAt(0) === 'M') { + // any tick0 more specific than a year: alway show the full date + if(tick0len > 10 || tick0str.substr(5) !== '01-01') ax._tickround = 'd'; + // show the month unless ticks are full multiples of a year + else ax._tickround = (+(dtick.substr(1)) % 12 === 0) ? 'y' : 'm'; + } + else if((dtick >= ONEDAY && tick0len <= 10) || (dtick >= ONEDAY * 15)) ax._tickround = 'd'; + else if((dtick >= ONEMIN && tick0len <= 16) || (dtick >= ONEHOUR)) ax._tickround = 'M'; + else if((dtick >= ONESEC && tick0len <= 19) || (dtick >= ONEMIN)) ax._tickround = 'S'; + else { + // of any two adjacent ticks, at least one will have the maximum fractional digits + // of all possible ticks - so take the max. length of tick0 and the next one + var tick1len = Lib.ms2DateTime(tick0ms + dtick).replace(/^-/, '').length; + ax._tickround = Math.max(tick0len, tick1len) - 20; + } + } + else if(isNumeric(dtick) || dtick.charAt(0) === 'L') { + // linear or log (except D1, D2) + var rng = ax.range.map(ax.r2d || Number); + if(!isNumeric(dtick)) dtick = Number(dtick.substr(1)); + // 2 digits past largest digit of dtick + ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); + + var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); + + var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); + if(Math.abs(rangeexp) > 3) { + if(ax.exponentformat === 'SI' || ax.exponentformat === 'B') { + ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); + } + else ax._tickexponent = rangeexp; + } + } + // D1 or D2 (log) + else ax._tickround = null; +} + +// months and years don't have constant millisecond values +// (but a year is always 12 months so we only need months) +// log-scale ticks are also not consistently spaced, except +// for pure powers of 10 +// numeric ticks always have constant differences, other datetime ticks +// can all be calculated as constant number of milliseconds +axes.tickIncrement = function(x, dtick, axrev) { + var axSign = axrev ? -1 : 1; + + // includes all dates smaller than month, and pure 10^n in log + if(isNumeric(dtick)) return x + axSign * dtick; + + var tType = dtick.charAt(0), + dtSigned = axSign * Number(dtick.substr(1)); + + // Dates: months (or years) + if(tType === 'M') { + var y = new Date(x); + // is this browser consistent? setMonth edits a date but + // returns that date's milliseconds + return y.setMonth(y.getMonth() + dtSigned); + } + + // Log scales: Linear, Digits + else if(tType === 'L') return Math.log(Math.pow(10, x) + dtSigned) / Math.LN10; + + // log10 of 2,5,10, or all digits (logs just have to be + // close enough to round) + else if(tType === 'D') { + var tickset = (dtick === 'D2') ? roundLog2 : roundLog1, + x2 = x + axSign * 0.01, + frac = Lib.roundUp(mod(x2, 1), tickset, axrev); + + return Math.floor(x2) + + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; + } + else throw 'unrecognized dtick ' + String(dtick); +}; + +// calculate the first tick on an axis +axes.tickFirst = function(ax) { + var r2l = ax.r2l || Number, + rng = ax.range.map(r2l), + axrev = rng[1] < rng[0], + sRound = axrev ? Math.floor : Math.ceil, + // add a tiny extra bit to make sure we get ticks + // that may have been rounded out + r0 = rng[0] * 1.0001 - rng[1] * 0.0001, + dtick = ax.dtick, + tick0 = r2l(ax.tick0); + + if(isNumeric(dtick)) { + var tmin = sRound((r0 - tick0) / dtick) * dtick + tick0; + + // make sure no ticks outside the category list + if(ax.type === 'category') { + tmin = Lib.constrain(tmin, 0, ax._categories.length - 1); + } + return tmin; + } + + var tType = dtick.charAt(0), + dtNum = Number(dtick.substr(1)), + t0, + mdif, + t1; + + // Dates: months (or years) + if(tType === 'M') { + t0 = new Date(tick0); + r0 = new Date(r0); + mdif = (r0.getFullYear() - t0.getFullYear()) * 12 + + r0.getMonth() - t0.getMonth(); + t1 = t0.setMonth(t0.getMonth() + + (Math.round(mdif / dtNum) + (axrev ? 1 : -1)) * dtNum); + + while(axrev ? t1 > r0 : t1 < r0) { + t1 = axes.tickIncrement(t1, dtick, axrev); + } + return t1; + } + + // Log scales: Linear, Digits + else if(tType === 'L') { + return Math.log(sRound( + (Math.pow(10, r0) - tick0) / dtNum) * dtNum + tick0) / Math.LN10; + } + else if(tType === 'D') { + var tickset = (dtick === 'D2') ? roundLog2 : roundLog1, + frac = Lib.roundUp(mod(r0, 1), tickset, axrev); + + return Math.floor(r0) + + Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; + } + else throw 'unrecognized dtick ' + String(dtick); +}; + +var yearFormat = d3.time.format('%Y'), + monthFormat = d3.time.format('%b %Y'), + dayFormat = d3.time.format('%b %-d'), + yearMonthDayFormat = d3.time.format('%b %-d, %Y'), + minuteFormat = d3.time.format('%H:%M'), + secondFormat = d3.time.format(':%S'); + +// add one item to d3's vocabulary: +// %{n}f where n is the max number of digits +// of fractional seconds +var fracMatch = /%(\d?)f/g; +function modDateFormat(fmt, x) { + var fm = fmt.match(fracMatch), + d = new Date(x); + if(fm) { + var digits = Math.min(+fm[1] || 6, 6), + fracSecs = String((x / 1000 % 1) + 2.0000005) + .substr(2, digits).replace(/0+$/, '') || '0'; + return d3.time.format(fmt.replace(fracMatch, fracSecs))(d); + } + else { + return d3.time.format(fmt)(d); + } +} + +// draw the text for one tick. +// px,py are the location on gd.paper +// prefix is there so the x axis ticks can be dropped a line +// ax is the axis layout, x is the tick value +// hover is a (truthy) flag for whether to show numbers with a bit +// more precision for hovertext +axes.tickText = function(ax, x, hover) { + var out = tickTextObj(ax, x), + hideexp, + arrayMode = ax.tickmode === 'array', + extraPrecision = hover || arrayMode, + i; + + if(arrayMode && Array.isArray(ax.ticktext)) { + var rng = ax.range.map(ax.r2l), + minDiff = Math.abs(rng[1] - rng[0]) / 10000; + for(i = 0; i < ax.ticktext.length; i++) { + if(Math.abs(x - ax.d2l(ax.tickvals[i])) < minDiff) break; + } + if(i < ax.ticktext.length) { + out.text = String(ax.ticktext[i]); + return out; + } + } + + function isHidden(showAttr) { + var first_or_last; + + if(showAttr === undefined) return true; + if(hover) return showAttr === 'none'; + + first_or_last = { + first: ax._tmin, + last: ax._tmax + }[showAttr]; + + return showAttr !== 'all' && x !== first_or_last; + } + + hideexp = ax.exponentformat !== 'none' && isHidden(ax.showexponent) ? 'hide' : ''; + + if(ax.type === 'date') formatDate(ax, out, hover, extraPrecision); + else if(ax.type === 'log') formatLog(ax, out, hover, extraPrecision, hideexp); + else if(ax.type === 'category') formatCategory(ax, out); + else formatLinear(ax, out, hover, extraPrecision, hideexp); + + // add prefix and suffix + if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text; + if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix; + + return out; +}; + +function tickTextObj(ax, x, text) { + var tf = ax.tickfont || ax._gd._fullLayout.font; + + return { + x: x, + dx: 0, + dy: 0, + text: text || '', + fontSize: tf.size, + font: tf.family, + fontColor: tf.color + }; +} + +function formatDate(ax, out, hover, extraPrecision) { + var x = out.x, + tr = ax._tickround, + trOriginal = tr, + d = new Date(x), + // suffix completes the full date info, to be included + // with only the first tick or if any info before what's + // shown has changed + suffix, + tt; + if(hover && ax.hoverformat) { + tt = modDateFormat(ax.hoverformat, x); + } + else if(ax.tickformat) { + tt = modDateFormat(ax.tickformat, x); + // TODO: potentially hunt for ways to automatically add more + // precision to the hover text? + } + else { + if(extraPrecision) { + if(isNumeric(tr)) tr += 2; + else tr = {y: 'm', m: 'd', d: 'M', M: 'S', S: 2}[tr]; + } + if(tr === 'y') tt = yearFormat(d); + else if(tr === 'm') tt = monthFormat(d); + else { + if(tr === 'd') { + if(!hover) suffix = '
' + yearFormat(d); + + tt = dayFormat(d); + } + else { + if(!hover) suffix = '
' + yearMonthDayFormat(d); + + tt = minuteFormat(d); + if(tr !== 'M') { + tt += secondFormat(d); + if(tr !== 'S') { + tt += numFormat(d3.round(mod(x / 1000, 1), 4), ax, 'none', hover) + .substr(1); + } + } + else if(trOriginal === 'd') { + // for hover on axes with day ticks, minuteFormat (which + // only includes %H:%M) isn't enough, you want the date too + tt = dayFormat(d) + ' ' + tt; + } + } + } + } + if(suffix && (!ax._inCalcTicks || (suffix !== ax._prevSuffix))) { + tt += suffix; + ax._prevSuffix = suffix; + } + out.text = tt; +} + +function formatLog(ax, out, hover, extraPrecision, hideexp) { + var dtick = ax.dtick, + x = out.x; + if(extraPrecision && ((typeof dtick !== 'string') || dtick.charAt(0) !== 'L')) dtick = 'L3'; + + if(ax.tickformat || (typeof dtick === 'string' && dtick.charAt(0) === 'L')) { + out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision); + } + else if(isNumeric(dtick) || ((dtick.charAt(0) === 'D') && (mod(x + 0.01, 1) < 0.1))) { + if(['e', 'E', 'power'].indexOf(ax.exponentformat) !== -1) { + var p = Math.round(x); + if(p === 0) out.text = 1; + else if(p === 1) out.text = '10'; + else if(p > 1) out.text = '10' + p + ''; + else out.text = '10\u2212' + -p + ''; + + out.fontSize *= 1.25; + } + else { + out.text = numFormat(Math.pow(10, x), ax, '', 'fakehover'); + if(dtick === 'D1' && ax._id.charAt(0) === 'y') { + out.dy -= out.fontSize / 6; + } + } + } + else if(dtick.charAt(0) === 'D') { + out.text = String(Math.round(Math.pow(10, mod(x, 1)))); + out.fontSize *= 0.75; + } + else throw 'unrecognized dtick ' + String(dtick); + + // if 9's are printed on log scale, move the 10's away a bit + if(ax.dtick === 'D1') { + var firstChar = String(out.text).charAt(0); + if(firstChar === '0' || firstChar === '1') { + if(ax._id.charAt(0) === 'y') { + out.dx -= out.fontSize / 4; + } + else { + out.dy += out.fontSize / 2; + out.dx += (ax.range[1] > ax.range[0] ? 1 : -1) * + out.fontSize * (x < 0 ? 0.5 : 0.25); + } + } + } +} + +function formatCategory(ax, out) { + var tt = ax._categories[Math.round(out.x)]; + if(tt === undefined) tt = ''; + out.text = String(tt); +} + +function formatLinear(ax, out, hover, extraPrecision, hideexp) { + // don't add an exponent to zero if we're showing all exponents + // so the only reason you'd show an exponent on zero is if it's the + // ONLY tick to get an exponent (first or last) + if(ax.showexponent === 'all' && Math.abs(out.x / ax.dtick) < 1e-6) { + hideexp = 'hide'; + } + out.text = numFormat(out.x, ax, hideexp, extraPrecision); +} + +// format a number (tick value) according to the axis settings +// new, more reliable procedure than d3.round or similar: +// add half the rounding increment, then stringify and truncate +// also automatically switch to sci. notation +var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; + +function numFormat(v, ax, fmtoverride, hover) { + // negative? + var isNeg = v < 0, + // max number of digits past decimal point to show + tickRound = ax._tickround, + exponentFormat = fmtoverride || ax.exponentformat || 'B', + exponent = ax._tickexponent, + tickformat = ax.tickformat, + separatethousands = ax.separatethousands; + + // special case for hover: set exponent just for this value, and + // add a couple more digits of precision over tick labels + if(hover) { + // make a dummy axis obj to get the auto rounding and exponent + var ah = { + exponentformat: ax.exponentformat, + dtick: ax.showexponent === 'none' ? ax.dtick : + (isNumeric(v) ? Math.abs(v) || 1 : 1), + // if not showing any exponents, don't change the exponent + // from what we calculate + range: ax.showexponent === 'none' ? ax.range.map(ax.r2d) : [0, v || 1] + }; + autoTickRound(ah); + tickRound = (Number(ah._tickround) || 0) + 4; + exponent = ah._tickexponent; + if(ax.hoverformat) tickformat = ax.hoverformat; + } + + if(tickformat) return d3.format(tickformat)(v).replace(/-/g, '\u2212'); + + // 'epsilon' - rounding increment + var e = Math.pow(10, -tickRound) / 2; + + // exponentFormat codes: + // 'e' (1.2e+6, default) + // 'E' (1.2E+6) + // 'SI' (1.2M) + // 'B' (same as SI except 10^9=B not G) + // 'none' (1200000) + // 'power' (1.2x10^6) + // 'hide' (1.2, use 3rd argument=='hide' to eg + // only show exponent on last tick) + if(exponentFormat === 'none') exponent = 0; + + // take the sign out, put it back manually at the end + // - makes cases easier + v = Math.abs(v); + if(v < e) { + // 0 is just 0, but may get exponent if it's the last tick + v = '0'; + isNeg = false; + } + else { + v += e; + // take out a common exponent, if any + if(exponent) { + v *= Math.pow(10, -exponent); + tickRound += exponent; + } + // round the mantissa + if(tickRound === 0) v = String(Math.floor(v)); + else if(tickRound < 0) { + v = String(Math.round(v)); + v = v.substr(0, v.length + tickRound); + for(var i = tickRound; i < 0; i++) v += '0'; + } + else { + v = String(v); + var dp = v.indexOf('.') + 1; + if(dp) v = v.substr(0, dp + tickRound).replace(/\.?0+$/, ''); + } + // insert appropriate decimal point and thousands separator + v = Lib.numSeparate(v, ax._gd._fullLayout.separators, separatethousands); + } + + // add exponent + if(exponent && exponentFormat !== 'hide') { + var signedExponent; + if(exponent < 0) signedExponent = '\u2212' + -exponent; + else if(exponentFormat !== 'power') signedExponent = '+' + exponent; + else signedExponent = String(exponent); + + if(exponentFormat === 'e' || + ((exponentFormat === 'SI' || exponentFormat === 'B') && + (exponent > 12 || exponent < -15))) { + v += 'e' + signedExponent; + } + else if(exponentFormat === 'E') { + v += 'E' + signedExponent; + } + else if(exponentFormat === 'power') { + v += '×10' + signedExponent + ''; + } + else if(exponentFormat === 'B' && exponent === 9) { + v += 'B'; + } + else if(exponentFormat === 'SI' || exponentFormat === 'B') { + v += SIPREFIXES[exponent / 3 + 5]; + } + } + + // put sign back in and return + // replace standard minus character (which is technically a hyphen) + // with a true minus sign + if(isNeg) return '\u2212' + v; + return v; +} + + +axes.subplotMatch = /^x([0-9]*)y([0-9]*)$/; + +// getSubplots - extract all combinations of axes we need to make plots for +// as an array of items like 'xy', 'x2y', 'x2y2'... +// sorted by x (x,x2,x3...) then y +// optionally restrict to only subplots containing axis object ax +// looks both for combinations of x and y found in the data +// and at axes and their anchors +axes.getSubplots = function(gd, ax) { + var subplots = []; + var i, j, sp; + + // look for subplots in the data + var data = gd._fullData || gd.data || []; + + for(i = 0; i < data.length; i++) { + var trace = data[i]; + + if(trace.visible === false || trace.visible === 'legendonly' || + !(Registry.traceIs(trace, 'cartesian') || Registry.traceIs(trace, 'gl2d')) + ) continue; + + var xId = trace.xaxis || 'x', + yId = trace.yaxis || 'y'; + sp = xId + yId; + + if(subplots.indexOf(sp) === -1) subplots.push(sp); + } + + // look for subplots in the axes/anchors, so that we at least draw all axes + var axesList = axes.list(gd, '', true); + + function hasAx2(sp, ax2) { + return sp.indexOf(ax2._id) !== -1; + } + + for(i = 0; i < axesList.length; i++) { + var ax2 = axesList[i], + ax2Letter = ax2._id.charAt(0), + ax3Id = (ax2.anchor === 'free') ? + ((ax2Letter === 'x') ? 'y' : 'x') : + ax2.anchor, + ax3 = axes.getFromId(gd, ax3Id); + + // look if ax2 is already represented in the data + var foundAx2 = false; + for(j = 0; j < subplots.length; j++) { + if(hasAx2(subplots[j], ax2)) { + foundAx2 = true; + break; + } + } + + // ignore free axes that already represented in the data + if(ax2.anchor === 'free' && foundAx2) continue; + + // ignore anchor-less axes + if(!ax3) continue; + + sp = (ax2Letter === 'x') ? + ax2._id + ax3._id : + ax3._id + ax2._id; + + if(subplots.indexOf(sp) === -1) subplots.push(sp); + } + + // filter invalid subplots + var spMatch = axes.subplotMatch, + allSubplots = []; + + for(i = 0; i < subplots.length; i++) { + sp = subplots[i]; + if(spMatch.test(sp)) allSubplots.push(sp); + } + + // sort the subplot ids + allSubplots.sort(function(a, b) { + var aMatch = a.match(spMatch), + bMatch = b.match(spMatch); + + if(aMatch[1] === bMatch[1]) { + return +(aMatch[2] || 1) - (bMatch[2] || 1); + } + + return +(aMatch[1]||0) - (bMatch[1]||0); + }); + + if(ax) return axes.findSubplotsWithAxis(allSubplots, ax); + return allSubplots; +}; + +// find all subplots with axis 'ax' +axes.findSubplotsWithAxis = function(subplots, ax) { + var axMatch = new RegExp( + (ax._id.charAt(0) === 'x') ? ('^' + ax._id + 'y') : (ax._id + '$') + ); + var subplotsWithAxis = []; + + for(var i = 0; i < subplots.length; i++) { + var sp = subplots[i]; + if(axMatch.test(sp)) subplotsWithAxis.push(sp); + } + + return subplotsWithAxis; +}; + +// makeClipPaths: prepare clipPaths for all single axes and all possible xy pairings +axes.makeClipPaths = function(gd) { + var fullLayout = gd._fullLayout, + defs = fullLayout._defs, + fullWidth = {_offset: 0, _length: fullLayout.width, _id: ''}, + fullHeight = {_offset: 0, _length: fullLayout.height, _id: ''}, + xaList = axes.list(gd, 'x', true), + yaList = axes.list(gd, 'y', true), + clipList = [], + i, + j; + + for(i = 0; i < xaList.length; i++) { + clipList.push({x: xaList[i], y: fullHeight}); + for(j = 0; j < yaList.length; j++) { + if(i === 0) clipList.push({x: fullWidth, y: yaList[j]}); + clipList.push({x: xaList[i], y: yaList[j]}); + } + } + + var defGroup = defs.selectAll('g.clips') + .data([0]); + + defGroup.enter().append('g') + .classed('clips', true); + + // selectors don't work right with camelCase tags, + // have to use class instead + // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I + var axClips = defGroup.selectAll('.axesclip') + .data(clipList, function(d) { return d.x._id + d.y._id; }); + + axClips.enter().append('clipPath') + .classed('axesclip', true) + .attr('id', function(d) { return 'clip' + fullLayout._uid + d.x._id + d.y._id; }) + .append('rect'); + + axClips.exit().remove(); + + axClips.each(function(d) { + d3.select(this).select('rect').attr({ + x: d.x._offset || 0, + y: d.y._offset || 0, + width: d.x._length || 1, + height: d.y._length || 1 + }); + }); +}; + + +// doTicks: draw ticks, grids, and tick labels +// axid: 'x', 'y', 'x2' etc, +// blank to do all, +// 'redraw' to force full redraw, and reset: +// ax._r (stored range for use by zoom/pan) +// ax._rl (stored linearized range for use by zoom/pan) +// or can pass in an axis object directly +axes.doTicks = function(gd, axid, skipTitle) { + var fullLayout = gd._fullLayout, + ax, + independent = false; + + // allow passing an independent axis object instead of id + if(typeof axid === 'object') { + ax = axid; + axid = ax._id; + independent = true; + } + else { + ax = axes.getFromId(gd, axid); + + if(axid === 'redraw') { + fullLayout._paper.selectAll('g.subplot').each(function(subplot) { + var plotinfo = fullLayout._plots[subplot], + xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + plotinfo.xaxislayer + .selectAll('.' + xa._id + 'tick').remove(); + plotinfo.yaxislayer + .selectAll('.' + ya._id + 'tick').remove(); + plotinfo.gridlayer + .selectAll('path').remove(); + plotinfo.zerolinelayer + .selectAll('path').remove(); + }); + } + + if(!axid || axid === 'redraw') { + return Lib.syncOrAsync(axes.list(gd, '', true).map(function(ax) { + return function() { + if(!ax._id) return; + var axDone = axes.doTicks(gd, ax._id); + if(axid === 'redraw') { + ax._r = ax.range.slice(); + ax._rl = ax._r.map(ax.r2l); + } + return axDone; + }; + })); + } + } + + // make sure we only have allowed options for exponents + // (others can make confusing errors) + if(!ax.tickformat) { + if(['none', 'e', 'E', 'power', 'SI', 'B'].indexOf(ax.exponentformat) === -1) { + ax.exponentformat = 'e'; + } + if(['all', 'first', 'last', 'none'].indexOf(ax.showexponent) === -1) { + ax.showexponent = 'all'; + } + } + + // set scaling to pixels + ax.setScale(); + + var axletter = axid.charAt(0), + counterLetter = axes.counterLetter(axid), + vals = axes.calcTicks(ax), + datafn = function(d) { return d.text + d.x + ax.mirror; }, + tcls = axid + 'tick', + gcls = axid + 'grid', + zcls = axid + 'zl', + pad = (ax.linewidth || 1) / 2, + labelStandoff = + (ax.ticks === 'outside' ? ax.ticklen : 1) + (ax.linewidth || 0), + labelShift = 0, + gridWidth = Drawing.crispRound(gd, ax.gridwidth, 1), + zeroLineWidth = Drawing.crispRound(gd, ax.zerolinewidth, gridWidth), + tickWidth = Drawing.crispRound(gd, ax.tickwidth, 1), + sides, transfn, tickpathfn, + i; + + if(ax._counterangle && ax.ticks === 'outside') { + var caRad = ax._counterangle * Math.PI / 180; + labelStandoff = ax.ticklen * Math.cos(caRad) + (ax.linewidth || 0); + labelShift = ax.ticklen * Math.sin(caRad); + } + + // positioning arguments for x vs y axes + if(axletter === 'x') { + sides = ['bottom', 'top']; + transfn = function(d) { + return 'translate(' + ax.l2p(d.x) + ',0)'; + }; + tickpathfn = function(shift, len) { + if(ax._counterangle) { + var caRad = ax._counterangle * Math.PI / 180; + return 'M0,' + shift + 'l' + (Math.sin(caRad) * len) + ',' + (Math.cos(caRad) * len); + } + else return 'M0,' + shift + 'v' + len; + }; + } + else if(axletter === 'y') { + sides = ['left', 'right']; + transfn = function(d) { + return 'translate(0,' + ax.l2p(d.x) + ')'; + }; + tickpathfn = function(shift, len) { + if(ax._counterangle) { + var caRad = ax._counterangle * Math.PI / 180; + return 'M' + shift + ',0l' + (Math.cos(caRad) * len) + ',' + (-Math.sin(caRad) * len); + } + else return 'M' + shift + ',0h' + len; + }; + } + else { + Lib.warn('Unrecognized doTicks axis:', axid); + return; + } + var axside = ax.side || sides[0], + // which direction do the side[0], side[1], and free ticks go? + // then we flip if outside XOR y axis + ticksign = [-1, 1, axside === sides[1] ? 1 : -1]; + if((ax.ticks !== 'inside') === (axletter === 'x')) { + ticksign = ticksign.map(function(v) { return -v; }); + } + + // remove zero lines, grid lines, and inside ticks if they're within + // 1 pixel of the end + // The key case here is removing zero lines when the axis bound is zero. + function clipEnds(d) { + var p = ax.l2p(d.x); + return (p > 1 && p < ax._length - 1); + } + var valsClipped = vals.filter(clipEnds); + + function drawTicks(container, tickpath) { + var ticks = container.selectAll('path.' + tcls) + .data(ax.ticks === 'inside' ? valsClipped : vals, datafn); + if(tickpath && ax.ticks) { + ticks.enter().append('path').classed(tcls, 1).classed('ticks', 1) + .classed('crisp', 1) + .call(Color.stroke, ax.tickcolor) + .style('stroke-width', tickWidth + 'px') + .attr('d', tickpath); + ticks.attr('transform', transfn); + ticks.exit().remove(); + } + else ticks.remove(); + } + + function drawLabels(container, position) { + // tick labels - for now just the main labels. + // TODO: mirror labels, esp for subplots + + // aburato: restore pointer events otherwise title tooltips won't work + container.style('pointer-events', 'all'); + + var tickLabels = container.selectAll('g.' + tcls).data(vals, datafn); + if(!ax.showticklabels || !isNumeric(position)) { + tickLabels.remove(); + drawAxTitle(axid); + return; + } + + var labelx, labely, labelanchor, labelpos0, flipit; + if(axletter === 'x') { + flipit = (axside === 'bottom') ? 1 : -1; + labelx = function(d) { return d.dx + labelShift * flipit; }; + labelpos0 = position + (labelStandoff + pad) * flipit; + labely = function(d) { + return d.dy + labelpos0 + d.fontSize * + ((axside === 'bottom') ? 1 : -0.5); + }; + labelanchor = function(angle) { + if(!isNumeric(angle) || angle === 0 || angle === 180) { + return 'middle'; + } + return (angle * flipit < 0) ? 'end' : 'start'; + }; + } + else { + flipit = (axside === 'right') ? 1 : -1; + labely = function(d) { return d.dy + d.fontSize / 2 - labelShift * flipit; }; + labelx = function(d) { + return d.dx + position + (labelStandoff + pad + + ((Math.abs(ax.tickangle) === 90) ? d.fontSize / 2 : 0)) * flipit; + }; + labelanchor = function(angle) { + if(isNumeric(angle) && Math.abs(angle) === 90) { + return 'middle'; + } + return axside === 'right' ? 'start' : 'end'; + }; + } + var maxFontSize = 0, + autoangle = 0, + labelsReady = []; + + // aburato: store this for later reference + var theG = tickLabels.enter().append('g').classed(tcls, 1); + + theG.append('text') + // only so tex has predictable alignment that we can + // alter later + .attr('text-anchor', 'middle') + .each(function(d) { + var thisLabel = d3.select(this), + newPromise = gd._promises.length; + thisLabel + .call(Drawing.setPosition, labelx(d), labely(d)) + .call(Drawing.font, d.font, d.fontSize, d.fontColor) + .text(d.text) + .call(svgTextUtils.convertToTspans); + newPromise = gd._promises[newPromise]; + if(newPromise) { + // if we have an async label, we'll deal with that + // all here so take it out of gd._promises and + // instead position the label and promise this in + // labelsReady + labelsReady.push(gd._promises.pop().then(function() { + positionLabels(thisLabel, ax.tickangle); + })); + } + else { + // sync label: just position it now. + positionLabels(thisLabel, ax.tickangle); + } + }); + tickLabels.exit().remove(); + + tickLabels.each(function(d) { + maxFontSize = Math.max(maxFontSize, d.fontSize); + }); + + function positionLabels(s, angle) { + s.each(function(d) { + var anchor = labelanchor(angle); + var thisLabel = d3.select(this), + mathjaxGroup = thisLabel.select('.text-math-group'), + transform = transfn(d) + + ((isNumeric(angle) && +angle !== 0) ? + (' rotate(' + angle + ',' + labelx(d) + ',' + + (labely(d) - d.fontSize / 2) + ')') : + ''); + if(mathjaxGroup.empty()) { + var txt = thisLabel.select('text').attr({ + transform: transform, + 'text-anchor': anchor + }); + + if(!txt.empty()) { + txt.selectAll('tspan.line').attr({ + x: txt.attr('x'), + y: txt.attr('y') + }); + } + } + else { + var mjShift = + Drawing.bBox(mathjaxGroup.node()).width * + {end: -0.5, start: 0.5}[anchor]; + mathjaxGroup.attr('transform', transform + + (mjShift ? 'translate(' + mjShift + ',0)' : '')); + } + }); + } + + // make sure all labels are correctly positioned at their base angle + // the positionLabels call above is only for newly drawn labels. + // do this without waiting, using the last calculated angle to + // minimize flicker, then do it again when we know all labels are + // there, putting back the prescribed angle to check for overlaps. + positionLabels(tickLabels, ax._lastangle || ax.tickangle); + + function allLabelsReady() { + return labelsReady.length && Promise.all(labelsReady); + } + + function fixLabelOverlaps() { + positionLabels(tickLabels, ax.tickangle); + + // check for auto-angling if x labels overlap + // don't auto-angle at all for log axes with + // base and digit format + if(axletter === 'x' && !isNumeric(ax.tickangle) && + (ax.type !== 'log' || String(ax.dtick).charAt(0) !== 'D')) { + var lbbArray = []; + tickLabels.each(function(d) { + var s = d3.select(this), + thisLabel = s.select('.text-math-group'), + x = ax.l2p(d.x); + if(thisLabel.empty()) thisLabel = s.select('text'); + + var bb = Drawing.bBox(thisLabel.node()); + + lbbArray.push({ + // ignore about y, just deal with x overlaps + top: 0, + bottom: 10, + height: 10, + left: x - bb.width / 2, + // impose a 2px gap + right: x + bb.width / 2 + 2, + width: bb.width + 2 + }); + }); + for(i = 0; i < lbbArray.length - 1; i++) { + if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1])) { + // any overlap at all - set 30 degrees + autoangle = 30; + break; + } + } + if(autoangle) { + var tickspacing = Math.abs( + (vals[vals.length - 1].x - vals[0].x) * ax._m + ) / (vals.length - 1); + if(tickspacing < maxFontSize * 2.5) { + autoangle = 90; + } + positionLabels(tickLabels, autoangle); + } + ax._lastangle = autoangle; + } + + performLabelEllipsis(); + + // update the axis title + // (so it can move out of the way if needed) + // TODO: separate out scoot so we don't need to do + // a full redraw of the title (mostly relevant for MathJax) + drawAxTitle(axid); + return axid + ' done'; + } + + function performLabelEllipsis() { + var maxLengthtPct = 0.25; // the max percent of the total chart w/h after which labels get the ellipsis. + var maxLengthCap = 200; // we still won't give labels more than this amount of space. + var maxLength = (axletter === "x" ? gd._fullLayout["height"] : gd._fullLayout["width"]) * maxLengthtPct; + maxLength = Math.min(maxLength, maxLengthCap); + + // ellipsis + tickLabels.each(function(d) { + var thisG = d3.select(this); + var bb = Drawing.bBox(thisG.node()); + var labelLength = (axletter === "x" ? bb["height"] : bb["width"]); + + // aburato: if the label is too long perform a middle ellipsis + if (labelLength > maxLength) { + var drawnText = d.text; + var maxCharLength = Math.round(maxLength / (labelLength / drawnText.length)); + var firstLen = Math.floor(maxCharLength / 2); + var lastLen = maxCharLength - firstLen - 1; + drawnText = drawnText.substr(0, firstLen) + '…' + drawnText.substr(-lastLen); + var thisText = thisG.select('text'); + thisText.text(drawnText); + // aburato: use a title element for a free tooltip. + thisG.insert("title", "text").text(d.text); + } + }); + } + + function adjustAutoMarginForLabels() { + var axBB = ax._boundingBox; + var shiftDimension; + var marginDimension; + var x = 0, y = 0; + + if (ax._id.charAt(0) === "x") { + shiftDimension = "height"; + if (ax._id.charAt(1) === "2") { + y = 1; + marginDimension = "t"; + } else { + marginDimension = "b"; + } + } else if (ax._id.charAt(0) === "y") { + shiftDimension = "width"; + if (ax._id.charAt(1) === "2") { + x = 1; + marginDimension = "r"; + } else { + marginDimension = "l"; + } + } + + if (shiftDimension && marginDimension) { + var shiftAmount = axBB[shiftDimension]; + if (ax._titleElement) { + var titleBB = ax._titleElement.node().getBoundingClientRect(); + shiftAmount += (titleBB[shiftDimension] + 2); + } + + var maxAmount = gd._fullLayout[shiftDimension] * 0.5; + shiftAmount = Math.min(shiftAmount, maxAmount); + + var shiftMargins = { + x: x, + y: y, + l: 0, + r: 0, + b: 0, + t: 0 + }; + shiftMargins[marginDimension] = shiftAmount; + Plots.autoMargin(gd, ax._name, shiftMargins); + } + } + + function calcBoundingBox() { + ax._boundingBox = container.node().getBoundingClientRect(); + } + + var done = Lib.syncOrAsync([ + allLabelsReady, + fixLabelOverlaps, + calcBoundingBox, + adjustAutoMarginForLabels + ]); + if(done && done.then) gd._promises.push(done); + return done; + } + + function drawAxTitle(axid) { + if(skipTitle) return; + + // now this only applies to regular cartesian axes; colorbars and + // others ALWAYS call doTicks with skipTitle=true so they can + // configure their own titles. + var ax = axisIds.getFromId(gd, axid), + avoidSelection = d3.select(gd).selectAll('g.' + axid + 'tick'), + avoid = { + selection: avoidSelection, + side: ax.side + }, + axLetter = axid.charAt(0), + gs = gd._fullLayout._size, + offsetBase = 1.5, + fontSize = ax.titlefont.size, + transform, + counterAxis, + x, + y; + if(avoidSelection.size()) { + var avoidTransform = d3.select(avoidSelection.node().parentNode) + .attr('transform') + .match(/translate\(([-\.\d]+),([-\.\d]+)\)/); + if(avoidTransform) { + avoid.offsetLeft = +avoidTransform[1]; + avoid.offsetTop = +avoidTransform[2]; + } + } + + if(axLetter === 'x') { + counterAxis = (ax.anchor === 'free') ? + {_offset: gs.t + (1 - (ax.position || 0)) * gs.h, _length: 0} : + axisIds.getFromId(gd, ax.anchor); + + x = ax._offset + ax._length / 2; + y = counterAxis._offset + ((ax.side === 'top') ? + -10 - fontSize * (offsetBase + (ax.showticklabels ? 1 : 0)) : + counterAxis._length + 10 + + fontSize * (offsetBase + (ax.showticklabels ? 1.5 : 0.5))); + + if(ax.rangeslider && ax.rangeslider.visible && ax._boundingBox) { + y += (fullLayout.height - fullLayout.margin.b - fullLayout.margin.t) * + ax.rangeslider.thickness + ax._boundingBox.height; + } + + if(!avoid.side) avoid.side = 'bottom'; + } + else { + counterAxis = (ax.anchor === 'free') ? + {_offset: gs.l + (ax.position || 0) * gs.w, _length: 0} : + axisIds.getFromId(gd, ax.anchor); + + y = ax._offset + ax._length / 2; + x = counterAxis._offset + ((ax.side === 'right') ? + counterAxis._length + 10 + + fontSize * (offsetBase + (ax.showticklabels ? 1 : 0.5)) : + -10 - fontSize * (offsetBase + (ax.showticklabels ? 0.5 : 0))); + + transform = {rotate: '-90', offset: 0}; + if(!avoid.side) avoid.side = 'left'; + } + + Titles.draw(gd, axid + 'title', { + propContainer: ax, + propName: ax._name + '.title', + dfltName: axLetter.toUpperCase() + ' axis', + avoid: avoid, + transform: transform, + attributes: {x: x, y: y, 'text-anchor': 'middle'} + }); + } + + function traceHasBarsOrFill(trace, subplot) { + if(trace.visible !== true || trace.xaxis + trace.yaxis !== subplot) return false; + if(Registry.traceIs(trace, 'bar') && trace.orientation === {x: 'h', y: 'v'}[axletter]) return true; + return trace.fill && trace.fill.charAt(trace.fill.length - 1) === axletter; + } + + function drawGrid(plotinfo, counteraxis, subplot) { + var gridcontainer = plotinfo.gridlayer, + zlcontainer = plotinfo.zerolinelayer, + gridvals = plotinfo['hidegrid' + axletter] ? [] : valsClipped, + gridpath = ax._gridpath || + 'M0,0' + ((axletter === 'x') ? 'v' : 'h') + counteraxis._length, + grid = gridcontainer.selectAll('path.' + gcls) + .data((ax.showgrid === false) ? [] : gridvals, datafn); + grid.enter().append('path').classed(gcls, 1) + .classed('crisp', 1) + .attr('d', gridpath) + .each(function(d) { + if(ax.zeroline && (ax.type === 'linear' || ax.type === '-') && + Math.abs(d.x) < ax.dtick / 100) { + d3.select(this).remove(); + } + }); + grid.attr('transform', transfn) + .call(Color.stroke, ax.gridcolor || '#ddd') + .style('stroke-width', gridWidth + 'px'); + grid.exit().remove(); + + // zero line + if(zlcontainer) { + var hasBarsOrFill = false; + for(var i = 0; i < gd._fullData.length; i++) { + if(traceHasBarsOrFill(gd._fullData[i], subplot)) { + hasBarsOrFill = true; + break; + } + } + var rng = ax.range.map(ax.r2l), + showZl = (rng[0] * rng[1] <= 0) && ax.zeroline && + (ax.type === 'linear' || ax.type === '-') && gridvals.length && + (hasBarsOrFill || clipEnds({x: 0}) || !ax.showline); + var zl = zlcontainer.selectAll('path.' + zcls) + .data(showZl ? [{x: 0}] : []); + zl.enter().append('path').classed(zcls, 1).classed('zl', 1) + .classed('crisp', 1) + .attr('d', gridpath); + zl.attr('transform', transfn) + .call(Color.stroke, ax.zerolinecolor || Color.defaultLine) + .style('stroke-width', zeroLineWidth + 'px'); + zl.exit().remove(); + } + } + + if(independent) { + drawTicks(ax._axislayer, tickpathfn(ax._pos + pad * ticksign[2], ticksign[2] * ax.ticklen)); + if(ax._counteraxis) { + var fictionalPlotinfo = { + gridlayer: ax._gridlayer, + zerolinelayer: ax._zerolinelayer + }; + drawGrid(fictionalPlotinfo, ax._counteraxis); + } + return drawLabels(ax._axislayer, ax._pos); + } + else { + var alldone = axes.getSubplots(gd, ax).map(function(subplot) { + var plotinfo = fullLayout._plots[subplot]; + + if(!fullLayout._has('cartesian')) return; + + var container = plotinfo[axletter + 'axislayer'], + + // [bottom or left, top or right, free, main] + linepositions = ax._linepositions[subplot] || [], + counteraxis = plotinfo[counterLetter + 'axis'], + mainSubplot = counteraxis._id === ax.anchor, + ticksides = [false, false, false], + tickpath = ''; + + // ticks + if(ax.mirror === 'allticks') ticksides = [true, true, false]; + else if(mainSubplot) { + if(ax.mirror === 'ticks') ticksides = [true, true, false]; + else ticksides[sides.indexOf(axside)] = true; + } + if(ax.mirrors) { + for(i = 0; i < 2; i++) { + var thisMirror = ax.mirrors[counteraxis._id + sides[i]]; + if(thisMirror === 'ticks' || thisMirror === 'labels') { + ticksides[i] = true; + } + } + } + + // free axis ticks + if(linepositions[2] !== undefined) ticksides[2] = true; + + ticksides.forEach(function(showside, sidei) { + var pos = linepositions[sidei], + tsign = ticksign[sidei]; + if(showside && isNumeric(pos)) { + tickpath += tickpathfn(pos + pad * tsign, tsign * ax.ticklen); + } + }); + + drawTicks(container, tickpath); + drawGrid(plotinfo, counteraxis, subplot); + return drawLabels(container, linepositions[3]); + }).filter(function(onedone) { return onedone && onedone.then; }); + + return alldone.length ? Promise.all(alldone) : 0; + } +}; + +// swap all the presentation attributes of the axes showing these traces +axes.swap = function(gd, traces) { + var axGroups = makeAxisGroups(gd, traces); + + for(var i = 0; i < axGroups.length; i++) { + swapAxisGroup(gd, axGroups[i].x, axGroups[i].y); + } +}; + +function makeAxisGroups(gd, traces) { + var groups = [], + i, + j; + + for(i = 0; i < traces.length; i++) { + var groupsi = [], + xi = gd._fullData[traces[i]].xaxis, + yi = gd._fullData[traces[i]].yaxis; + if(!xi || !yi) continue; // not a 2D cartesian trace? + + for(j = 0; j < groups.length; j++) { + if(groups[j].x.indexOf(xi) !== -1 || groups[j].y.indexOf(yi) !== -1) { + groupsi.push(j); + } + } + + if(!groupsi.length) { + groups.push({x: [xi], y: [yi]}); + continue; + } + + var group0 = groups[groupsi[0]], + groupj; + + if(groupsi.length > 1) { + for(j = 1; j < groupsi.length; j++) { + groupj = groups[groupsi[j]]; + mergeAxisGroups(group0.x, groupj.x); + mergeAxisGroups(group0.y, groupj.y); + } + } + mergeAxisGroups(group0.x, [xi]); + mergeAxisGroups(group0.y, [yi]); + } + + return groups; +} + +function mergeAxisGroups(intoSet, fromSet) { + for(var i = 0; i < fromSet.length; i++) { + if(intoSet.indexOf(fromSet[i]) === -1) intoSet.push(fromSet[i]); + } +} + +function swapAxisGroup(gd, xIds, yIds) { + var i, + j, + xFullAxes = [], + yFullAxes = [], + layout = gd.layout; + + for(i = 0; i < xIds.length; i++) xFullAxes.push(axes.getFromId(gd, xIds[i])); + for(i = 0; i < yIds.length; i++) yFullAxes.push(axes.getFromId(gd, yIds[i])); + + var allAxKeys = Object.keys(xFullAxes[0]), + noSwapAttrs = [ + 'anchor', 'domain', 'overlaying', 'position', 'side', 'tickangle' + ], + numericTypes = ['linear', 'log']; + + for(i = 0; i < allAxKeys.length; i++) { + var keyi = allAxKeys[i], + xVal = xFullAxes[0][keyi], + yVal = yFullAxes[0][keyi], + allEqual = true, + coerceLinearX = false, + coerceLinearY = false; + if(keyi.charAt(0) === '_' || typeof xVal === 'function' || + noSwapAttrs.indexOf(keyi) !== -1) { + continue; + } + for(j = 1; j < xFullAxes.length && allEqual; j++) { + var xVali = xFullAxes[j][keyi]; + if(keyi === 'type' && numericTypes.indexOf(xVal) !== -1 && + numericTypes.indexOf(xVali) !== -1 && xVal !== xVali) { + // type is special - if we find a mixture of linear and log, + // coerce them all to linear on flipping + coerceLinearX = true; + } + else if(xVali !== xVal) allEqual = false; + } + for(j = 1; j < yFullAxes.length && allEqual; j++) { + var yVali = yFullAxes[j][keyi]; + if(keyi === 'type' && numericTypes.indexOf(yVal) !== -1 && + numericTypes.indexOf(yVali) !== -1 && yVal !== yVali) { + // type is special - if we find a mixture of linear and log, + // coerce them all to linear on flipping + coerceLinearY = true; + } + else if(yFullAxes[j][keyi] !== yVal) allEqual = false; + } + if(allEqual) { + if(coerceLinearX) layout[xFullAxes[0]._name].type = 'linear'; + if(coerceLinearY) layout[yFullAxes[0]._name].type = 'linear'; + swapAxisAttrs(layout, keyi, xFullAxes, yFullAxes); + } + } + + // now swap x&y for any annotations anchored to these x & y + for(i = 0; i < gd._fullLayout.annotations.length; i++) { + var ann = gd._fullLayout.annotations[i]; + if(xIds.indexOf(ann.xref) !== -1 && + yIds.indexOf(ann.yref) !== -1) { + Lib.swapAttrs(layout.annotations[i], ['?']); + } + } +} + +function swapAxisAttrs(layout, key, xFullAxes, yFullAxes) { + // in case the value is the default for either axis, + // look at the first axis in each list and see if + // this key's value is undefined + var np = Lib.nestedProperty, + xVal = np(layout[xFullAxes[0]._name], key).get(), + yVal = np(layout[yFullAxes[0]._name], key).get(), + i; + if(key === 'title') { + // special handling of placeholder titles + if(xVal === 'Click to enter X axis title') { + xVal = 'Click to enter Y axis title'; + } + if(yVal === 'Click to enter Y axis title') { + yVal = 'Click to enter X axis title'; + } + } + + for(i = 0; i < xFullAxes.length; i++) { + np(layout, xFullAxes[i]._name + '.' + key).set(yVal); + } + for(i = 0; i < yFullAxes.length; i++) { + np(layout, yFullAxes[i]._name + '.' + key).set(xVal); + } +} + +// mod - version of modulus that always restricts to [0,divisor) +// rather than built-in % which gives a negative value for negative v +function mod(v, d) { return ((v % d) + d) % d; } + +},{"../../components/color":27,"../../components/drawing":50,"../../components/titles":101,"../../constants/numerical":107,"../../lib":122,"../../lib/svg_text_utils":134,"../../plots/plots":186,"../../registry":194,"./axis_ids":153,"./layout_attributes":159,"./layout_defaults":160,"./set_convert":164,"d3":10,"fast-isnumeric":13}],151:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var BADNUM = require('../../constants/numerical').BADNUM; + +module.exports = function autoType(array) { + if(moreDates(array)) return 'date'; + if(category(array)) return 'category'; + if(linearOK(array)) return 'linear'; + else return '-'; +}; + +// is there at least one number in array? If not, we should leave +// ax.type empty so it can be autoset later +function linearOK(array) { + if(!array) return false; + + for(var i = 0; i < array.length; i++) { + if(isNumeric(array[i])) return true; + } + + return false; +} + +// does the array a have mostly dates rather than numbers? +// note: some values can be neither (such as blanks, text) +// 2- or 4-digit integers can be both, so require twice as many +// dates as non-dates, to exclude cases with mostly 2 & 4 digit +// numbers and a few dates +function moreDates(a) { + var dcnt = 0, + ncnt = 0, + // test at most 1000 points, evenly spaced + inc = Math.max(1, (a.length - 1) / 1000), + ai; + + for(var i = 0; i < a.length; i += inc) { + ai = a[Math.round(i)]; + if(Lib.isDateTime(ai)) dcnt += 1; + if(isNumeric(ai)) ncnt += 1; + } + + return (dcnt > ncnt * 2); +} + +// are the (x,y)-values in gd.data mostly text? +// require twice as many categories as numbers +function category(a) { + // test at most 1000 points + var inc = Math.max(1, (a.length - 1) / 1000), + curvenums = 0, + curvecats = 0, + ai; + + for(var i = 0; i < a.length; i += inc) { + ai = a[Math.round(i)]; + if(Lib.cleanNumber(ai) !== BADNUM) curvenums++; + else if(typeof ai === 'string' && ai !== '' && ai !== 'None') curvecats++; + } + + return curvecats > curvenums * 2; +} + +},{"../../constants/numerical":107,"../../lib":122,"fast-isnumeric":13}],152:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var colorMix = require('tinycolor2').mix; + +var Registry = require('../../registry'); +var Lib = require('../../lib'); +var lightFraction = require('../../components/color/attributes').lightFraction; + +var layoutAttributes = require('./layout_attributes'); +var handleTickValueDefaults = require('./tick_value_defaults'); +var handleTickMarkDefaults = require('./tick_mark_defaults'); +var handleTickLabelDefaults = require('./tick_label_defaults'); +var handleCategoryOrderDefaults = require('./category_order_defaults'); +var setConvert = require('./set_convert'); +var orderedCategories = require('./ordered_categories'); +var axisIds = require('./axis_ids'); +var autoType = require('./axis_autotype'); + + +/** + * options: object containing: + * + * letter: 'x' or 'y' + * title: name of the axis (ie 'Colorbar') to go in default title + * name: axis object name (ie 'xaxis') if one should be stored + * font: the default font to inherit + * outerTicks: boolean, should ticks default to outside? + * showGrid: boolean, should gridlines be shown by default? + * noHover: boolean, this axis doesn't support hover effects? + * data: the plot data to use in choosing auto type + * bgColor: the plot background color, to calculate default gridline colors + */ +module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, options) { + var letter = options.letter, + font = options.font || {}, + defaultTitle = 'Click to enter ' + + (options.title || (letter.toUpperCase() + ' axis')) + + ' title'; + + function coerce2(attr, dflt) { + return Lib.coerce2(containerIn, containerOut, layoutAttributes, attr, dflt); + } + + // set up some private properties + if(options.name) { + containerOut._name = options.name; + containerOut._id = axisIds.name2id(options.name); + } + + // now figure out type and do some more initialization + var axType = coerce('type'); + if(axType === '-') { + setAutoType(containerOut, options.data); + + if(containerOut.type === '-') { + containerOut.type = 'linear'; + } + else { + // copy autoType back to input axis + // note that if this object didn't exist + // in the input layout, we have to put it in + // this happens in the main supplyDefaults function + axType = containerIn.type = containerOut.type; + } + } + + setConvert(containerOut); + + var dfltColor = coerce('color'); + // if axis.color was provided, use it for fonts too; otherwise, + // inherit from global font color in case that was provided. + var dfltFontColor = (dfltColor === containerIn.color) ? dfltColor : font.color; + + coerce('title', defaultTitle); + Lib.coerceFont(coerce, 'titlefont', { + family: font.family, + size: Math.round(font.size * 1.2), + color: dfltFontColor + }); + + var validRange = ( + (containerIn.range || []).length === 2 && + isNumeric(containerOut.r2l(containerIn.range[0])) && + isNumeric(containerOut.r2l(containerIn.range[1])) + ); + var autoRange = coerce('autorange', !validRange); + + if(autoRange) coerce('rangemode'); + + coerce('range'); + containerOut.cleanRange(); + + coerce('fixedrange'); + + handleTickValueDefaults(containerIn, containerOut, coerce, axType); + handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); + handleTickMarkDefaults(containerIn, containerOut, coerce, options); + handleCategoryOrderDefaults(containerIn, containerOut, coerce); + + var lineColor = coerce2('linecolor', dfltColor), + lineWidth = coerce2('linewidth'), + showLine = coerce('showline', !!lineColor || !!lineWidth); + + if(!showLine) { + delete containerOut.linecolor; + delete containerOut.linewidth; + } + + if(showLine || containerOut.ticks) coerce('mirror'); + + var gridColor = coerce2('gridcolor', colorMix(dfltColor, options.bgColor, lightFraction).toRgbString()), + gridWidth = coerce2('gridwidth'), + showGridLines = coerce('showgrid', options.showGrid || !!gridColor || !!gridWidth); + + if(!showGridLines) { + delete containerOut.gridcolor; + delete containerOut.gridwidth; + } + + var zeroLineColor = coerce2('zerolinecolor', dfltColor), + zeroLineWidth = coerce2('zerolinewidth'), + showZeroLine = coerce('zeroline', options.showGrid || !!zeroLineColor || !!zeroLineWidth); + + if(!showZeroLine) { + delete containerOut.zerolinecolor; + delete containerOut.zerolinewidth; + } + + // fill in categories + containerOut._initialCategories = axType === 'category' ? + orderedCategories(letter, containerOut.categoryorder, containerOut.categoryarray, options.data) : + []; + + return containerOut; +}; + +function setAutoType(ax, data) { + // new logic: let people specify any type they want, + // only autotype if type is '-' + if(ax.type !== '-') return; + + var id = ax._id, + axLetter = id.charAt(0); + + // support 3d + if(id.indexOf('scene') !== -1) id = axLetter; + + var d0 = getFirstNonEmptyTrace(data, id, axLetter); + if(!d0) return; + + // first check for histograms, as the count direction + // should always default to a linear axis + if(d0.type === 'histogram' && + axLetter === {v: 'y', h: 'x'}[d0.orientation || 'v']) { + ax.type = 'linear'; + return; + } + + // check all boxes on this x axis to see + // if they're dates, numbers, or categories + if(isBoxWithoutPositionCoords(d0, axLetter)) { + var posLetter = getBoxPosLetter(d0), + boxPositions = [], + trace; + + for(var i = 0; i < data.length; i++) { + trace = data[i]; + if(!Registry.traceIs(trace, 'box') || + (trace[axLetter + 'axis'] || axLetter) !== id) continue; + + if(trace[posLetter] !== undefined) boxPositions.push(trace[posLetter][0]); + else if(trace.name !== undefined) boxPositions.push(trace.name); + else boxPositions.push('text'); + } + + ax.type = autoType(boxPositions); + } + else { + ax.type = autoType(d0[axLetter] || [d0[axLetter + '0']]); + } +} + +function getBoxPosLetter(trace) { + return {v: 'x', h: 'y'}[trace.orientation || 'v']; +} + +function isBoxWithoutPositionCoords(trace, axLetter) { + var posLetter = getBoxPosLetter(trace); + + return ( + Registry.traceIs(trace, 'box') && + axLetter === posLetter && + trace[posLetter] === undefined && + trace[posLetter + '0'] === undefined + ); +} + +function getFirstNonEmptyTrace(data, id, axLetter) { + for(var i = 0; i < data.length; i++) { + var trace = data[i]; + + if((trace[axLetter + 'axis'] || axLetter) === id) { + if(isBoxWithoutPositionCoords(trace, axLetter)) { + return trace; + } + else if((trace[axLetter] || []).length || trace[axLetter + '0']) { + return trace; + } + } + } +} + +},{"../../components/color/attributes":26,"../../lib":122,"../../registry":194,"./axis_autotype":151,"./axis_ids":153,"./category_order_defaults":154,"./layout_attributes":159,"./ordered_categories":161,"./set_convert":164,"./tick_label_defaults":165,"./tick_mark_defaults":166,"./tick_value_defaults":167,"fast-isnumeric":13,"tinycolor2":16}],153:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = require('../../registry'); +var Plots = require('../plots'); +var Lib = require('../../lib'); + +var constants = require('./constants'); + + +// convert between axis names (xaxis, xaxis2, etc, elements of gd.layout) +// and axis id's (x, x2, etc). Would probably have ditched 'xaxis' +// completely in favor of just 'x' if it weren't ingrained in the API etc. +exports.id2name = function id2name(id) { + if(typeof id !== 'string' || !id.match(constants.AX_ID_PATTERN)) return; + var axNum = id.substr(1); + if(axNum === '1') axNum = ''; + return id.charAt(0) + 'axis' + axNum; +}; + +exports.name2id = function name2id(name) { + if(!name.match(constants.AX_NAME_PATTERN)) return; + var axNum = name.substr(5); + if(axNum === '1') axNum = ''; + return name.charAt(0) + axNum; +}; + +exports.cleanId = function cleanId(id, axLetter) { + if(!id.match(constants.AX_ID_PATTERN)) return; + if(axLetter && id.charAt(0) !== axLetter) return; + + var axNum = id.substr(1).replace(/^0+/, ''); + if(axNum === '1') axNum = ''; + return id.charAt(0) + axNum; +}; + +// get all axis object names +// optionally restricted to only x or y or z by string axLetter +// and optionally 2D axes only, not those inside 3D scenes +function listNames(gd, axLetter, only2d) { + var fullLayout = gd._fullLayout; + if(!fullLayout) return []; + + function filterAxis(obj, extra) { + var keys = Object.keys(obj), + axMatch = /^[xyz]axis[0-9]*/, + out = []; + + for(var i = 0; i < keys.length; i++) { + var k = keys[i]; + if(axLetter && k.charAt(0) !== axLetter) continue; + if(axMatch.test(k)) out.push(extra + k); + } + + return out.sort(); + } + + var names = filterAxis(fullLayout, ''); + if(only2d) return names; + + var sceneIds3D = Plots.getSubplotIds(fullLayout, 'gl3d') || []; + for(var i = 0; i < sceneIds3D.length; i++) { + var sceneId = sceneIds3D[i]; + names = names.concat( + filterAxis(fullLayout[sceneId], sceneId + '.') + ); + } + + return names; +} + +// get all axis objects, as restricted in listNames +exports.list = function(gd, axletter, only2d) { + return listNames(gd, axletter, only2d) + .map(function(axName) { + return Lib.nestedProperty(gd._fullLayout, axName).get(); + }); +}; + +// get all axis ids, optionally restricted by letter +// this only makes sense for 2d axes +exports.listIds = function(gd, axletter) { + return listNames(gd, axletter, true).map(exports.name2id); +}; + +// get an axis object from its id 'x','x2' etc +// optionally, id can be a subplot (ie 'x2y3') and type gets x or y from it +exports.getFromId = function(gd, id, type) { + var fullLayout = gd._fullLayout; + + if(type === 'x') id = id.replace(/y[0-9]*/, ''); + else if(type === 'y') id = id.replace(/x[0-9]*/, ''); + + return fullLayout[exports.id2name(id)]; +}; + +// get an axis object of specified type from the containing trace +exports.getFromTrace = function(gd, fullTrace, type) { + var fullLayout = gd._fullLayout; + var ax = null; + + if(Registry.traceIs(fullTrace, 'gl3d')) { + var scene = fullTrace.scene; + if(scene.substr(0, 5) === 'scene') { + ax = fullLayout[scene][type + 'axis']; + } + } + else { + ax = exports.getFromId(gd, fullTrace[type + 'axis'] || type); + } + + return ax; +}; + +},{"../../lib":122,"../../registry":194,"../plots":186,"./constants":155}],154:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = function handleCategoryOrderDefaults(containerIn, containerOut, coerce) { + if(containerOut.type !== 'category') return; + + var arrayIn = containerIn.categoryarray, + orderDefault; + + var isValidArray = (Array.isArray(arrayIn) && arrayIn.length > 0); + + // override default 'categoryorder' value when non-empty array is supplied + if(isValidArray) orderDefault = 'array'; + + var order = coerce('categoryorder', orderDefault); + + // coerce 'categoryarray' only in array order case + if(order === 'array') coerce('categoryarray'); + + // cannot set 'categoryorder' to 'array' with an invalid 'categoryarray' + if(!isValidArray && order === 'array') { + containerOut.categoryorder = 'trace'; + } +}; + +},{}],155:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + + idRegex: { + x: /^x([2-9]|[1-9][0-9]+)?$/, + y: /^y([2-9]|[1-9][0-9]+)?$/ + }, + + attrRegex: { + x: /^xaxis([2-9]|[1-9][0-9]+)?$/, + y: /^yaxis([2-9]|[1-9][0-9]+)?$/ + }, + + // axis match regular expression + xAxisMatch: /^xaxis[0-9]*$/, + yAxisMatch: /^yaxis[0-9]*$/, + + // pattern matching axis ids and names + AX_ID_PATTERN: /^[xyz][0-9]*$/, + AX_NAME_PATTERN: /^[xyz]axis[0-9]*$/, + + // ms between first mousedown and 2nd mouseup to constitute dblclick... + // we don't seem to have access to the system setting + DBLCLICKDELAY: 300, + + // pixels to move mouse before you stop clamping to starting point + MINDRAG: 8, + + // smallest dimension allowed for a select box + MINSELECT: 12, + + // smallest dimension allowed for a zoombox + MINZOOM: 20, + + // width of axis drag regions + DRAGGERSIZE: 20, + + // max pixels away from mouse to allow a point to highlight + MAXDIST: 20, + + // hover labels for multiple horizontal bars get tilted by this angle + YANGLE: 60, + + // size and display constants for hover text + HOVERARROWSIZE: 6, // pixel size of hover arrows + HOVERTEXTPAD: 3, // pixels padding around text + HOVERFONTSIZE: 13, + HOVERFONT: 'Arial, sans-serif', + + // minimum time (msec) between hover calls + HOVERMINTIME: 50, + + // max pixels off straight before a lasso select line counts as bent + BENDPX: 1.5, + + // delay before a redraw (relayout) after smooth panning and zooming + REDRAWDELAY: 50, + + // last resort axis ranges for x, y, and date axes if we have no data + DFLTRANGEX: [-1, 6], + DFLTRANGEY: [-1, 4], + DFLTRANGEDATE: ['2000-01-01', '2001-01-01'], +}; + +},{}],156:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var tinycolor = require('tinycolor2'); + +var Plotly = require('../../plotly'); +var Registry = require('../../registry'); +var Lib = require('../../lib'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); +var setCursor = require('../../lib/setcursor'); +var dragElement = require('../../components/dragelement'); + +var Axes = require('./axes'); +var prepSelect = require('./select'); +var constants = require('./constants'); + + +// flag for showing "doubleclick to zoom out" only at the beginning +var SHOWZOOMOUTTIP = true; + +// dragBox: create an element to drag one or more axis ends +// inputs: +// plotinfo - which subplot are we making dragboxes on? +// x,y,w,h - left, top, width, height of the box +// ns - how does this drag the vertical axis? +// 'n' - top only +// 's' - bottom only +// 'ns' - top and bottom together, difference unchanged +// ew - same for horizontal axis +module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) { + // mouseDown stores ms of first mousedown event in the last + // DBLCLICKDELAY ms on the drag bars + // numClicks stores how many mousedowns have been seen + // within DBLCLICKDELAY so we can check for click or doubleclick events + // dragged stores whether a drag has occurred, so we don't have to + // redraw unnecessarily, ie if no move bigger than MINDRAG or MINZOOM px + var fullLayout = gd._fullLayout, + // if we're dragging two axes at once, also drag overlays + subplots = [plotinfo].concat((ns && ew) ? plotinfo.overlays : []), + xa = [plotinfo.xaxis], + ya = [plotinfo.yaxis], + pw = xa[0]._length, + ph = ya[0]._length, + MINDRAG = constants.MINDRAG, + MINZOOM = constants.MINZOOM, + isMainDrag = (ns + ew === 'nsew'); + + for(var i = 1; i < subplots.length; i++) { + var subplotXa = subplots[i].xaxis, + subplotYa = subplots[i].yaxis; + if(xa.indexOf(subplotXa) === -1) xa.push(subplotXa); + if(ya.indexOf(subplotYa) === -1) ya.push(subplotYa); + } + + function isDirectionActive(axList, activeVal) { + for(var i = 0; i < axList.length; i++) { + if(!axList[i].fixedrange) return activeVal; + } + return ''; + } + + var allaxes = xa.concat(ya), + xActive = isDirectionActive(xa, ew), + yActive = isDirectionActive(ya, ns), + cursor = getDragCursor(yActive + xActive, fullLayout.dragmode), + dragClass = ns + ew + 'drag'; + + var dragger3 = plotinfo.draglayer.selectAll('.' + dragClass).data([0]); + + dragger3.enter().append('rect') + .classed('drag', true) + .classed(dragClass, true) + .style({fill: 'transparent', 'stroke-width': 0}) + .attr('data-subplot', plotinfo.id); + + dragger3.call(Drawing.setRect, x, y, w, h) + .call(setCursor, cursor); + + var dragger = dragger3.node(); + + // still need to make the element if the axes are disabled + // but nuke its events (except for maindrag which needs them for hover) + // and stop there + if(!yActive && !xActive && !isSelectOrLasso(fullLayout.dragmode)) { + dragger.onmousedown = null; + dragger.style.pointerEvents = isMainDrag ? 'all' : 'none'; + return dragger; + } + + var dragOptions = { + element: dragger, + gd: gd, + plotinfo: plotinfo, + xaxes: xa, + yaxes: ya, + doubleclick: doubleClick, + prepFn: function(e, startX, startY) { + var dragModeNow = gd._fullLayout.dragmode; + + if(isMainDrag) { + // main dragger handles all drag modes, and changes + // to pan (or to zoom if it already is pan) on shift + if(e.shiftKey) { + if(dragModeNow === 'pan') dragModeNow = 'zoom'; + else dragModeNow = 'pan'; + } + } + // all other draggers just pan + else dragModeNow = 'pan'; + + if(dragModeNow === 'lasso') dragOptions.minDrag = 1; + else dragOptions.minDrag = undefined; + + if(dragModeNow === 'zoom') { + dragOptions.moveFn = zoomMove; + dragOptions.doneFn = zoomDone; + zoomPrep(e, startX, startY); + } + else if(dragModeNow === 'pan') { + dragOptions.moveFn = plotDrag; + dragOptions.doneFn = dragDone; + clearSelect(); + } + else if(isSelectOrLasso(dragModeNow)) { + prepSelect(e, startX, startY, dragOptions, dragModeNow); + } + } + }; + + dragElement.init(dragOptions); + + var zoomlayer = gd._fullLayout._zoomlayer, + xs = plotinfo.xaxis._offset, + ys = plotinfo.yaxis._offset, + x0, + y0, + box, + lum, + path0, + dimmed, + zoomMode, + zb, + corners; + + function recomputeAxisLists() { + xa = [plotinfo.xaxis]; + ya = [plotinfo.yaxis]; + pw = xa[0]._length; + ph = ya[0]._length; + + for(var i = 1; i < subplots.length; i++) { + var subplotXa = subplots[i].xaxis, + subplotYa = subplots[i].yaxis; + if(xa.indexOf(subplotXa) === -1) xa.push(subplotXa); + if(ya.indexOf(subplotYa) === -1) ya.push(subplotYa); + } + allaxes = xa.concat(ya); + xActive = isDirectionActive(xa, ew); + yActive = isDirectionActive(ya, ns); + cursor = getDragCursor(yActive + xActive, fullLayout.dragmode); + xs = plotinfo.xaxis._offset; + ys = plotinfo.yaxis._offset; + dragOptions.xa = xa; + dragOptions.ya = ya; + } + + function zoomPrep(e, startX, startY) { + var dragBBox = dragger.getBoundingClientRect(); + x0 = startX - dragBBox.left; + y0 = startY - dragBBox.top; + box = {l: x0, r: x0, w: 0, t: y0, b: y0, h: 0}; + lum = gd._hmpixcount ? + (gd._hmlumcount / gd._hmpixcount) : + tinycolor(gd._fullLayout.plot_bgcolor).getLuminance(); + path0 = 'M0,0H' + pw + 'V' + ph + 'H0V0'; + dimmed = false; + zoomMode = 'xy'; + + zb = zoomlayer.append('path') + .attr('class', 'zoombox') + .style({ + 'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)', + 'stroke-width': 0 + }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', path0 + 'Z'); + + corners = zoomlayer.append('path') + .attr('class', 'zoombox-corners') + .style({ + fill: Color.background, + stroke: Color.defaultLine, + 'stroke-width': 1, + opacity: 0 + }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', 'M0,0Z'); + + clearSelect(); + } + + function clearSelect() { + // until we get around to persistent selections, remove the outline + // here. The selection itself will be removed when the plot redraws + // at the end. + zoomlayer.selectAll('.select-outline').remove(); + } + + function zoomMove(dx0, dy0) { + if(gd._transitioningWithDuration) { + return false; + } + + var x1 = Math.max(0, Math.min(pw, dx0 + x0)), + y1 = Math.max(0, Math.min(ph, dy0 + y0)), + dx = Math.abs(x1 - x0), + dy = Math.abs(y1 - y0), + clen = Math.floor(Math.min(dy, dx, MINZOOM) / 2); + + box.l = Math.min(x0, x1); + box.r = Math.max(x0, x1); + box.t = Math.min(y0, y1); + box.b = Math.max(y0, y1); + + // look for small drags in one direction or the other, + // and only drag the other axis + if(!yActive || dy < Math.min(Math.max(dx * 0.6, MINDRAG), MINZOOM)) { + if(dx < MINDRAG) { + zoomMode = ''; + box.r = box.l; + box.t = box.b; + corners.attr('d', 'M0,0Z'); + } + else { + box.t = 0; + box.b = ph; + zoomMode = 'x'; + corners.attr('d', + 'M' + (box.l - 0.5) + ',' + (y0 - MINZOOM - 0.5) + + 'h-3v' + (2 * MINZOOM + 1) + 'h3ZM' + + (box.r + 0.5) + ',' + (y0 - MINZOOM - 0.5) + + 'h3v' + (2 * MINZOOM + 1) + 'h-3Z'); + } + } + else if(!xActive || dx < Math.min(dy * 0.6, MINZOOM)) { + box.l = 0; + box.r = pw; + zoomMode = 'y'; + corners.attr('d', + 'M' + (x0 - MINZOOM - 0.5) + ',' + (box.t - 0.5) + + 'v-3h' + (2 * MINZOOM + 1) + 'v3ZM' + + (x0 - MINZOOM - 0.5) + ',' + (box.b + 0.5) + + 'v3h' + (2 * MINZOOM + 1) + 'v-3Z'); + } + else { + zoomMode = 'xy'; + corners.attr('d', + 'M' + (box.l - 3.5) + ',' + (box.t - 0.5 + clen) + 'h3v' + (-clen) + + 'h' + clen + 'v-3h-' + (clen + 3) + 'ZM' + + (box.r + 3.5) + ',' + (box.t - 0.5 + clen) + 'h-3v' + (-clen) + + 'h' + (-clen) + 'v-3h' + (clen + 3) + 'ZM' + + (box.r + 3.5) + ',' + (box.b + 0.5 - clen) + 'h-3v' + clen + + 'h' + (-clen) + 'v3h' + (clen + 3) + 'ZM' + + (box.l - 3.5) + ',' + (box.b + 0.5 - clen) + 'h3v' + clen + + 'h' + clen + 'v3h-' + (clen + 3) + 'Z'); + } + box.w = box.r - box.l; + box.h = box.b - box.t; + + // Not sure about the addition of window.scrollX/Y... + // seems to work but doesn't seem robust. + zb.attr('d', + path0 + 'M' + (box.l) + ',' + (box.t) + 'v' + (box.h) + + 'h' + (box.w) + 'v-' + (box.h) + 'h-' + (box.w) + 'Z'); + if(!dimmed) { + zb.transition() + .style('fill', lum > 0.2 ? 'rgba(0,0,0,0.4)' : + 'rgba(255,255,255,0.3)') + .duration(200); + corners.transition() + .style('opacity', 1) + .duration(200); + dimmed = true; + } + } + + function zoomAxRanges(axList, r0Fraction, r1Fraction) { + var i, + axi, + axRangeLinear; + + var zoomInfo = []; + + for (i = 0; i < axList.length; i++) { + axi = axList[i]; + if(axi.fixedrange) continue; + + axRangeLinear = axi.range.map(axi.r2l); + axi.range = [ + axi.l2r(axRangeLinear[0] + (axRangeLinear[1] - axRangeLinear[0]) * r0Fraction), + axi.l2r(axRangeLinear[0] + (axRangeLinear[1] - axRangeLinear[0]) * r1Fraction) + ]; + + zoomInfo.push({ + oldRange: axRange.slice(0), + newRange: axi.range.slice(0), + name: axi._name, + fractionalRange: [r0Fraction, r1Fraction] + }); + } + + return zoomInfo; + } + + function zoomDone(dragged, numClicks) { + if(Math.min(box.h, box.w) < MINDRAG * 2) { + if(numClicks === 2) doubleClick(); + + return removeZoombox(gd); + } + + var axesZoomInfo = []; + + if (zoomMode === 'xy' || zoomMode === 'x') { + var xZoomInfo = zoomAxRanges(xa, box.l / pw, box.r / pw); + axesZoomInfo = axesZoomInfo.concat(xZoomInfo); + } + if (zoomMode === 'xy' || zoomMode === 'y') { + var yZoomInfo = zoomAxRanges(ya, (ph - box.b) / ph, (ph - box.t) / ph); + axesZoomInfo = axesZoomInfo.concat(yZoomInfo); + } + + removeZoombox(gd); + + // Allows listeners to handle the zoom evt manually, thus overriding the built-in behavior. + var args = { zoomMode: zoomMode, box: box, axes: axesZoomInfo, pre: true, userHandled: false }; + gd.emit('plotly_zoom', args); + + if (!args.userHandled) { + dragTail(zoomMode); + if (SHOWZOOMOUTTIP && gd.data && gd._context.showTips) { + Lib.notifier('Double-click to
zoom back out', 'long'); + SHOWZOOMOUTTIP = false; + } + args.pre = false; + gd.emit('plotly_zoom', args); + } + } + + function dragDone(dragged, numClicks) { + var singleEnd = (ns + ew).length === 1; + if(dragged) dragTail(); + else if(numClicks === 2 && !singleEnd) doubleClick(); + else if(numClicks === 1 && singleEnd) { + var ax = ns ? ya[0] : xa[0], + end = (ns === 's' || ew === 'w') ? 0 : 1, + attrStr = ax._name + '.range[' + end + ']', + initialText = getEndText(ax, end), + hAlign = 'left', + vAlign = 'middle'; + + if(ax.fixedrange) return; + + if(ns) { + vAlign = (ns === 'n') ? 'top' : 'bottom'; + if(ax.side === 'right') hAlign = 'right'; + } + else if(ew === 'e') hAlign = 'right'; + + dragger3 + .call(svgTextUtils.makeEditable, null, { + immediate: true, + background: fullLayout.paper_bgcolor, + text: String(initialText), + fill: ax.tickfont ? ax.tickfont.color : '#444', + horizontalAlign: hAlign, + verticalAlign: vAlign + }) + .on('edit', function(text) { + var v = ax.d2r(text); + if(v !== undefined) { + Plotly.relayout(gd, attrStr, v); + } + }); + } + } + + // scroll zoom, on all draggers except corners + var scrollViewBox = [0, 0, pw, ph], + // wait a little after scrolling before redrawing + redrawTimer = null, + REDRAWDELAY = constants.REDRAWDELAY, + mainplot = plotinfo.mainplot ? + fullLayout._plots[plotinfo.mainplot] : plotinfo; + + function zoomWheel(e) { + // deactivate mousewheel scrolling on embedded graphs + // devs can override this with layout._enablescrollzoom, + // but _ ensures this setting won't leave their page + if(!gd._context.scrollZoom && !fullLayout._enablescrollzoom) { + return; + } + + // If a transition is in progress, then disable any behavior: + if(gd._transitioningWithDuration) { + return Lib.pauseEvent(e); + } + + var pc = gd.querySelector('.plotly'); + + recomputeAxisLists(); + + // if the plot has scrollbars (more than a tiny excess) + // disable scrollzoom too. + if(pc.scrollHeight - pc.clientHeight > 10 || + pc.scrollWidth - pc.clientWidth > 10) { + return; + } + + clearTimeout(redrawTimer); + + var wheelDelta = -e.deltaY; + if(!isFinite(wheelDelta)) wheelDelta = e.wheelDelta / 10; + if(!isFinite(wheelDelta)) { + Lib.log('Did not find wheel motion attributes: ', e); + return; + } + + var zoom = Math.exp(-Math.min(Math.max(wheelDelta, -20), 20) / 100), + gbb = mainplot.draglayer.select('.nsewdrag') + .node().getBoundingClientRect(), + xfrac = (e.clientX - gbb.left) / gbb.width, + vbx0 = scrollViewBox[0] + scrollViewBox[2] * xfrac, + yfrac = (gbb.bottom - e.clientY) / gbb.height, + vby0 = scrollViewBox[1] + scrollViewBox[3] * (1 - yfrac), + i; + + function zoomWheelOneAxis(ax, centerFraction, zoom) { + if(ax.fixedrange) return; + + var axRange = ax.range.map(ax.r2l), + v0 = axRange[0] + (axRange[1] - axRange[0]) * centerFraction; + function doZoom(v) { return ax.l2r(v0 + (v - v0) * zoom); } + ax.range = axRange.map(doZoom); + } + + if(ew) { + for(i = 0; i < xa.length; i++) zoomWheelOneAxis(xa[i], xfrac, zoom); + scrollViewBox[2] *= zoom; + scrollViewBox[0] = vbx0 - scrollViewBox[2] * xfrac; + } + if(ns) { + for(i = 0; i < ya.length; i++) zoomWheelOneAxis(ya[i], yfrac, zoom); + scrollViewBox[3] *= zoom; + scrollViewBox[1] = vby0 - scrollViewBox[3] * (1 - yfrac); + } + + // viewbox redraw at first + updateSubplots(scrollViewBox); + ticksAndAnnotations(ns, ew); + + // then replot after a delay to make sure + // no more scrolling is coming + redrawTimer = setTimeout(function() { + scrollViewBox = [0, 0, pw, ph]; + dragTail(); + }, REDRAWDELAY); + + return Lib.pauseEvent(e); + } + + // everything but the corners gets wheel zoom + if(ns.length * ew.length !== 1) { + // still seems to be some confusion about onwheel vs onmousewheel... + if(dragger.onwheel !== undefined) dragger.onwheel = zoomWheel; + else if(dragger.onmousewheel !== undefined) dragger.onmousewheel = zoomWheel; + } + + // plotDrag: move the plot in response to a drag + function plotDrag(dx, dy) { + // If a transition is in progress, then disable any behavior: + if(gd._transitioningWithDuration) { + return; + } + + recomputeAxisLists(); + + function dragAxList(axList, pix) { + for(var i = 0; i < axList.length; i++) { + var axi = axList[i]; + if(!axi.fixedrange) { + axi.range = [ + axi.l2r(axi._rl[0] - pix / axi._m), + axi.l2r(axi._rl[1] - pix / axi._m) + ]; + } + } + } + + if(xActive === 'ew' || yActive === 'ns') { + if(xActive) dragAxList(xa, dx); + if(yActive) dragAxList(ya, dy); + updateSubplots([xActive ? -dx : 0, yActive ? -dy : 0, pw, ph]); + ticksAndAnnotations(yActive, xActive); + return; + } + + // common transform for dragging one end of an axis + // d>0 is compressing scale (cursor is over the plot, + // the axis end should move with the cursor) + // d<0 is expanding (cursor is off the plot, axis end moves + // nonlinearly so you can expand far) + function dZoom(d) { + return 1 - ((d >= 0) ? Math.min(d, 0.9) : + 1 / (1 / Math.max(d, -0.3) + 3.222)); + } + + // dz: set a new value for one end (0 or 1) of an axis array axArray, + // and return a pixel shift for that end for the viewbox + // based on pixel drag distance d + // TODO: this makes (generally non-fatal) errors when you get + // near floating point limits + function dz(axArray, end, d) { + var otherEnd = 1 - end, + movedAx, + newLinearizedEnd; + for(var i = 0; i < axArray.length; i++) { + var axi = axArray[i]; + if(axi.fixedrange) continue; + movedAx = axi; + newLinearizedEnd = axi._rl[otherEnd] + + (axi._rl[end] - axi._rl[otherEnd]) / dZoom(d / axi._length); + var newEnd = axi.l2r(newLinearizedEnd); + + // if l2r comes back false or undefined, it means we've dragged off + // the end of valid ranges - so stop. + if(newEnd !== false && newEnd !== undefined) axi.range[end] = newEnd; + } + return movedAx._length * (movedAx._rl[end] - newLinearizedEnd) / + (movedAx._rl[end] - movedAx._rl[otherEnd]); + } + + if(xActive === 'w') dx = dz(xa, 0, dx); + else if(xActive === 'e') dx = dz(xa, 1, -dx); + else if(!xActive) dx = 0; + + if(yActive === 'n') dy = dz(ya, 1, dy); + else if(yActive === 's') dy = dz(ya, 0, -dy); + else if(!yActive) dy = 0; + + updateSubplots([ + (xActive === 'w') ? dx : 0, + (yActive === 'n') ? dy : 0, + pw - dx, + ph - dy + ]); + ticksAndAnnotations(yActive, xActive); + } + + function ticksAndAnnotations(ns, ew) { + var activeAxIds = [], + i; + + function pushActiveAxIds(axList) { + for(i = 0; i < axList.length; i++) { + if(!axList[i].fixedrange) activeAxIds.push(axList[i]._id); + } + } + + if(ew) pushActiveAxIds(xa); + if(ns) pushActiveAxIds(ya); + + for(i = 0; i < activeAxIds.length; i++) { + Axes.doTicks(gd, activeAxIds[i], true); + } + + function redrawObjs(objArray, method) { + for(i = 0; i < objArray.length; i++) { + var obji = objArray[i]; + + if((ew && activeAxIds.indexOf(obji.xref) !== -1) || + (ns && activeAxIds.indexOf(obji.yref) !== -1)) { + method(gd, i); + } + } + } + + // annotations and shapes 'draw' method is slow, + // use the finer-grained 'drawOne' method instead + + redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne')); + redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne')); + redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw')); + } + + function doubleClick() { + if(gd._transitioningWithDuration) return; + + // Emit pre-zoom reset + var args = { zoomMode: "reset", pre: true, userHandled: false }; + gd.emit('plotly_zoom', args); + + if (args.userHandled) return; + + var doubleClickConfig = gd._context.doubleClick, + axList = (xActive ? xa : []).concat(yActive ? ya : []), + attrs = {}; + + var ax, i, rangeInitial; + + if(doubleClickConfig === 'autosize') { + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + if(!ax.fixedrange) attrs[ax._name + '.autorange'] = true; + } + } + else if(doubleClickConfig === 'reset') { + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + + if(!ax._rangeInitial) { + attrs[ax._name + '.autorange'] = true; + } + else { + rangeInitial = ax._rangeInitial.slice(); + attrs[ax._name + '.range[0]'] = rangeInitial[0]; + attrs[ax._name + '.range[1]'] = rangeInitial[1]; + } + } + } + else if(doubleClickConfig === 'reset+autosize') { + for(i = 0; i < axList.length; i++) { + ax = axList[i]; + + if(ax.fixedrange) continue; + if(ax._rangeInitial === undefined || + ax.range[0] === ax._rangeInitial[0] && + ax.range[1] === ax._rangeInitial[1] + ) { + attrs[ax._name + '.autorange'] = true; + } + else { + rangeInitial = ax._rangeInitial.slice(); + attrs[ax._name + '.range[0]'] = rangeInitial[0]; + attrs[ax._name + '.range[1]'] = rangeInitial[1]; + } + } + } + + gd.emit('plotly_doubleclick', null); + Plotly.relayout(gd, attrs); + + args.pre = false; + gd.emit('plotly_zoom', args); + } + + // dragTail - finish a drag event with a redraw + function dragTail(zoommode) { + var attrs = {}; + // revert to the previous axis settings, then apply the new ones + // through relayout - this lets relayout manage undo/redo + for(var i = 0; i < allaxes.length; i++) { + var axi = allaxes[i]; + if(zoommode && zoommode.indexOf(axi._id.charAt(0)) === -1) { + continue; + } + if(axi._r[0] !== axi.range[0]) attrs[axi._name + '.range[0]'] = axi.range[0]; + if(axi._r[1] !== axi.range[1]) attrs[axi._name + '.range[1]'] = axi.range[1]; + + axi.range = axi._r.slice(); + } + + updateSubplots([0, 0, pw, ph]); + Plotly.relayout(gd, attrs); + } + + // updateSubplots - find all plot viewboxes that should be + // affected by this drag, and update them. look for all plots + // sharing an affected axis (including the one being dragged) + function updateSubplots(viewBox) { + var j; + var plotinfos = fullLayout._plots, + subplots = Object.keys(plotinfos); + + for(var i = 0; i < subplots.length; i++) { + + var subplot = plotinfos[subplots[i]], + xa2 = subplot.xaxis, + ya2 = subplot.yaxis, + editX = ew && !xa2.fixedrange, + editY = ns && !ya2.fixedrange; + + if(editX) { + var isInX = false; + for(j = 0; j < xa.length; j++) { + if(xa[j]._id === xa2._id) { + isInX = true; + break; + } + } + editX = editX && isInX; + } + + if(editY) { + var isInY = false; + for(j = 0; j < ya.length; j++) { + if(ya[j]._id === ya2._id) { + isInY = true; + break; + } + } + editY = editY && isInY; + } + + var xScaleFactor = editX ? xa2._length / viewBox[2] : 1, + yScaleFactor = editY ? ya2._length / viewBox[3] : 1; + + var clipDx = editX ? viewBox[0] : 0, + clipDy = editY ? viewBox[1] : 0; + + var fracDx = editX ? (viewBox[0] / viewBox[2] * xa2._length) : 0, + fracDy = editY ? (viewBox[1] / viewBox[3] * ya2._length) : 0; + + var plotDx = xa2._offset - fracDx, + plotDy = ya2._offset - fracDy; + + fullLayout._defs.selectAll('#' + subplot.clipId) + .call(Lib.setTranslate, clipDx, clipDy) + .call(Lib.setScale, 1 / xScaleFactor, 1 / yScaleFactor); + + subplot.plot + .call(Lib.setTranslate, plotDx, plotDy) + .call(Lib.setScale, xScaleFactor, yScaleFactor) + + // This is specifically directed at scatter traces, applying an inverse + // scale to individual points to counteract the scale of the trace + // as a whole: + .selectAll('.points').selectAll('.point') + .call(Lib.setPointGroupScale, 1 / xScaleFactor, 1 / yScaleFactor); + } + } + + return dragger; +}; + +function getEndText(ax, end) { + var initialVal = ax.range[end], + diff = Math.abs(initialVal - ax.range[1 - end]), + dig; + + // TODO: this should basically be ax.r2d but we're doing extra + // rounding here... can we clean up at all? + if(ax.type === 'date') { + return initialVal; + } + else if(ax.type === 'log') { + dig = Math.ceil(Math.max(0, -Math.log(diff) / Math.LN10)) + 3; + return d3.format('.' + dig + 'g')(Math.pow(10, initialVal)); + } + else { // linear numeric (or category... but just show numbers here) + dig = Math.floor(Math.log(Math.abs(initialVal)) / Math.LN10) - + Math.floor(Math.log(diff) / Math.LN10) + 4; + return d3.format('.' + String(dig) + 'g')(initialVal); + } +} + +function getDragCursor(nsew, dragmode) { + if(!nsew) return 'pointer'; + if(nsew === 'nsew') { + if(dragmode === 'pan') return 'move'; + return 'crosshair'; + } + return nsew.toLowerCase() + '-resize'; +} + +function removeZoombox(gd) { + d3.select(gd) + .selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners') + .remove(); +} + +function isSelectOrLasso(dragmode) { + var modes = ['lasso', 'select']; + + return modes.indexOf(dragmode) !== -1; +} + +},{"../../components/color":27,"../../components/dragelement":48,"../../components/drawing":50,"../../lib":122,"../../lib/setcursor":132,"../../lib/svg_text_utils":134,"../../plotly":145,"../../registry":194,"./axes":150,"./constants":155,"./select":163,"d3":10,"tinycolor2":16}],157:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var tinycolor = require('tinycolor2'); +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Events = require('../../lib/events'); +var svgTextUtils = require('../../lib/svg_text_utils'); +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); +var dragElement = require('../../components/dragelement'); + +var Axes = require('./axes'); +var constants = require('./constants'); +var dragBox = require('./dragbox'); +var layoutAttributes = require('../layout_attributes'); + + +var fx = module.exports = {}; + +// TODO remove this in version 2.0 +// copy on Fx for backward compatible +fx.unhover = dragElement.unhover; + +fx.layoutAttributes = { +}; + +fx.supplyLayoutDefaults = function(layoutIn, layoutOut, fullData) { + + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + + coerce('dragmode'); + + var hovermodeDflt; + if(layoutOut._has('cartesian')) { + // flag for 'horizontal' plots: + // determines the state of the mode bar 'compare' hovermode button + var isHoriz = layoutOut._isHoriz = fx.isHoriz(fullData); + hovermodeDflt = isHoriz ? 'y' : 'x'; + } + else hovermodeDflt = 'closest'; + + coerce('hovermode', hovermodeDflt); +}; + +fx.isHoriz = function(fullData) { + var isHoriz = true; + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + + if(trace.orientation !== 'h') { + isHoriz = false; + break; + } + } + + return isHoriz; +}; + +fx.init = function(gd) { + var fullLayout = gd._fullLayout; + + if(!fullLayout._has('cartesian') || gd._context.staticPlot) return; + + var subplots = Object.keys(fullLayout._plots || {}).sort(function(a, b) { + // sort overlays last, then by x axis number, then y axis number + if((fullLayout._plots[a].mainplot && true) === + (fullLayout._plots[b].mainplot && true)) { + var aParts = a.split('y'), + bParts = b.split('y'); + return (aParts[0] === bParts[0]) ? + (Number(aParts[1] || 1) - Number(bParts[1] || 1)) : + (Number(aParts[0] || 1) - Number(bParts[0] || 1)); + } + return fullLayout._plots[a].mainplot ? 1 : -1; + }); + + subplots.forEach(function(subplot) { + var plotinfo = fullLayout._plots[subplot]; + + if(!fullLayout._has('cartesian')) return; + + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis, + + // the y position of the main x axis line + y0 = (xa._linepositions[subplot] || [])[3], + + // the x position of the main y axis line + x0 = (ya._linepositions[subplot] || [])[3]; + + var DRAGGERSIZE = constants.DRAGGERSIZE; + if(isNumeric(y0) && xa.side === 'top') y0 -= DRAGGERSIZE; + if(isNumeric(x0) && ya.side !== 'right') x0 -= DRAGGERSIZE; + + // main and corner draggers need not be repeated for + // overlaid subplots - these draggers drag them all + if(!plotinfo.mainplot) { + // main dragger goes over the grids and data, so we use its + // mousemove events for all data hover effects + var maindrag = dragBox(gd, plotinfo, 0, 0, + xa._length, ya._length, 'ns', 'ew'); + + maindrag.onmousemove = function(evt) { + fx.hover(gd, evt, subplot); + fullLayout._lasthover = maindrag; + fullLayout._hoversubplot = subplot; + }; + + /* + * IMPORTANT: + * We must check for the presence of the drag cover here. + * If we don't, a 'mouseout' event is triggered on the + * maindrag before each 'click' event, which has the effect + * of clearing the hoverdata; thus, cancelling the click event. + */ + maindrag.onmouseout = function(evt) { + if(gd._dragging) return; + + dragElement.unhover(gd, evt); + }; + + maindrag.onclick = function(evt) { + fx.click(gd, evt); + }; + + // corner draggers + dragBox(gd, plotinfo, -DRAGGERSIZE, -DRAGGERSIZE, + DRAGGERSIZE, DRAGGERSIZE, 'n', 'w'); + dragBox(gd, plotinfo, xa._length, -DRAGGERSIZE, + DRAGGERSIZE, DRAGGERSIZE, 'n', 'e'); + dragBox(gd, plotinfo, -DRAGGERSIZE, ya._length, + DRAGGERSIZE, DRAGGERSIZE, 's', 'w'); + dragBox(gd, plotinfo, xa._length, ya._length, + DRAGGERSIZE, DRAGGERSIZE, 's', 'e'); + } + + // x axis draggers - if you have overlaid plots, + // these drag each axis separately + if(isNumeric(y0)) { + if(xa.anchor === 'free') y0 -= fullLayout._size.h * (1 - ya.domain[1]); + dragBox(gd, plotinfo, xa._length * 0.1, y0, + xa._length * 0.8, DRAGGERSIZE, '', 'ew'); + dragBox(gd, plotinfo, 0, y0, + xa._length * 0.1, DRAGGERSIZE, '', 'w'); + dragBox(gd, plotinfo, xa._length * 0.9, y0, + xa._length * 0.1, DRAGGERSIZE, '', 'e'); + } + // y axis draggers + if(isNumeric(x0)) { + if(ya.anchor === 'free') x0 -= fullLayout._size.w * xa.domain[0]; + dragBox(gd, plotinfo, x0, ya._length * 0.1, + DRAGGERSIZE, ya._length * 0.8, 'ns', ''); + dragBox(gd, plotinfo, x0, ya._length * 0.9, + DRAGGERSIZE, ya._length * 0.1, 's', ''); + dragBox(gd, plotinfo, x0, 0, + DRAGGERSIZE, ya._length * 0.1, 'n', ''); + } + }); + + // In case you mousemove over some hovertext, send it to fx.hover too + // we do this so that we can put the hover text in front of everything, + // but still be able to interact with everything as if it isn't there + var hoverLayer = fullLayout._hoverlayer.node(); + + hoverLayer.onmousemove = function(evt) { + evt.target = fullLayout._lasthover; + fx.hover(gd, evt, fullLayout._hoversubplot); + }; + + hoverLayer.onclick = function(evt) { + evt.target = fullLayout._lasthover; + fx.click(gd, evt); + }; + + // also delegate mousedowns... TODO: does this actually work? + hoverLayer.onmousedown = function(evt) { + fullLayout._lasthover.onmousedown(evt); + }; +}; + +// hover labels for multiple horizontal bars get tilted by some angle, +// then need to be offset differently if they overlap +var YANGLE = constants.YANGLE, + YA_RADIANS = Math.PI * YANGLE / 180, + + // expansion of projected height + YFACTOR = 1 / Math.sin(YA_RADIANS), + + // to make the appropriate post-rotation x offset, + // you need both x and y offsets + YSHIFTX = Math.cos(YA_RADIANS), + YSHIFTY = Math.sin(YA_RADIANS); + +// convenience functions for mapping all relevant axes +function flat(subplots, v) { + var out = []; + for(var i = subplots.length; i > 0; i--) out.push(v); + return out; +} + +function p2c(axArray, v) { + var out = []; + for(var i = 0; i < axArray.length; i++) out.push(axArray[i].p2c(v)); + return out; +} + +function quadrature(dx, dy) { + return function(di) { + var x = dx(di), + y = dy(di); + return Math.sqrt(x * x + y * y); + }; +} + +// size and display constants for hover text +var HOVERARROWSIZE = constants.HOVERARROWSIZE, + HOVERTEXTPAD = constants.HOVERTEXTPAD, + HOVERFONTSIZE = constants.HOVERFONTSIZE, + HOVERFONT = constants.HOVERFONT; + +// fx.hover: highlight data on hover +// evt can be a mousemove event, or an object with data about what points +// to hover on +// {xpx,ypx[,hovermode]} - pixel locations from top left +// (with optional overriding hovermode) +// {xval,yval[,hovermode]} - data values +// [{curveNumber,(pointNumber|xval and/or yval)}] - +// array of specific points to highlight +// pointNumber is a single integer if gd.data[curveNumber] is 1D, +// or a two-element array if it's 2D +// xval and yval are data values, +// 1D data may specify either or both, +// 2D data must specify both +// subplot is an id string (default "xy") +// makes use of gl.hovermode, which can be: +// x (find the points with the closest x values, ie a column), +// closest (find the single closest point) +// internally there are two more that occasionally get used: +// y (pick out a row - only used for multiple horizontal bar charts) +// array (used when the user specifies an explicit +// array of points to hover on) +// +// We wrap the hovers in a timer, to limit their frequency. +// The actual rendering is done by private functions +// hover() and unhover(). + +fx.hover = function(gd, evt, subplot) { + if(typeof gd === 'string') gd = document.getElementById(gd); + if(gd._lastHoverTime === undefined) gd._lastHoverTime = 0; + + // If we have an update queued, discard it now + if(gd._hoverTimer !== undefined) { + clearTimeout(gd._hoverTimer); + gd._hoverTimer = undefined; + } + // Is it more than 100ms since the last update? If so, force + // an update now (synchronously) and exit + if(Date.now() > gd._lastHoverTime + constants.HOVERMINTIME) { + hover(gd, evt, subplot); + gd._lastHoverTime = Date.now(); + return; + } + // Queue up the next hover for 100ms from now (if no further events) + gd._hoverTimer = setTimeout(function() { + hover(gd, evt, subplot); + gd._lastHoverTime = Date.now(); + gd._hoverTimer = undefined; + }, constants.HOVERMINTIME); +}; + +// The actual implementation is here: + +function hover(gd, evt, subplot) { + if(subplot === 'pie') { + gd.emit('plotly_hover', { + points: [evt] + }); + return; + } + + if(!subplot) subplot = 'xy'; + + // if the user passed in an array of subplots, + // use those instead of finding overlayed plots + var subplots = Array.isArray(subplot) ? subplot : [subplot]; + + var fullLayout = gd._fullLayout, + plots = fullLayout._plots || [], + plotinfo = plots[subplot]; + + // list of all overlaid subplots to look at + if(plotinfo) { + var overlayedSubplots = plotinfo.overlays.map(function(pi) { + return pi.id; + }); + + subplots = subplots.concat(overlayedSubplots); + } + + var len = subplots.length, + xaArray = new Array(len), + yaArray = new Array(len); + + for(var i = 0; i < len; i++) { + var spId = subplots[i]; + + // 'cartesian' case + var plotObj = plots[spId]; + if(plotObj) { + + // TODO make sure that fullLayout_plots axis refs + // get updated properly so that we don't have + // to use Axes.getFromId in general. + + xaArray[i] = Axes.getFromId(gd, plotObj.xaxis._id); + yaArray[i] = Axes.getFromId(gd, plotObj.yaxis._id); + continue; + } + + // other subplot types + var _subplot = fullLayout[spId]._subplot; + xaArray[i] = _subplot.xaxis; + yaArray[i] = _subplot.yaxis; + } + + var hovermode = evt.hovermode || fullLayout.hovermode; + + if(['x', 'y', 'closest'].indexOf(hovermode) === -1 || !gd.calcdata || + gd._dragged) { + return dragElement.unhoverRaw(gd, evt); + } + + // hoverData: the set of candidate points we've found to highlight + var hoverData = [], + + // searchData: the data to search in. Mostly this is just a copy of + // gd.calcdata, filtered to the subplot and overlays we're on + // but if a point array is supplied it will be a mapping + // of indicated curves + searchData = [], + + // [x|y]valArray: the axis values of the hover event + // mapped onto each of the currently selected overlaid subplots + xvalArray, + yvalArray, + + // used in loops + itemnum, + curvenum, + cd, + trace, + subplotId, + subploti, + mode, + xval, + yval, + pointData, + closedataPreviousLength; + + // Figure out what we're hovering on: + // mouse location or user-supplied data + + if(Array.isArray(evt)) { + // user specified an array of points to highlight + hovermode = 'array'; + for(itemnum = 0; itemnum < evt.length; itemnum++) { + cd = gd.calcdata[evt[itemnum].curveNumber||0]; + if(cd[0].trace.hoverinfo !== 'skip') { + searchData.push(cd); + } + } + } + else { + for(curvenum = 0; curvenum < gd.calcdata.length; curvenum++) { + cd = gd.calcdata[curvenum]; + trace = cd[0].trace; + if(trace.hoverinfo !== 'skip' && subplots.indexOf(getSubplot(trace)) !== -1) { + searchData.push(cd); + } + } + + // [x|y]px: the pixels (from top left) of the mouse location + // on the currently selected plot area + var xpx, ypx; + + // mouse event? ie is there a target element with + // clientX and clientY values? + if(evt.target && ('clientX' in evt) && ('clientY' in evt)) { + + // fire the beforehover event and quit if it returns false + // note that we're only calling this on real mouse events, so + // manual calls to fx.hover will always run. + if(Events.triggerHandler(gd, 'plotly_beforehover', evt) === false) { + return; + } + + var dbb = evt.target.getBoundingClientRect(); + + xpx = evt.clientX - dbb.left; + ypx = evt.clientY - dbb.top; + + // in case hover was called from mouseout into hovertext, + // it's possible you're not actually over the plot anymore + if(xpx < 0 || xpx > dbb.width || ypx < 0 || ypx > dbb.height) { + return dragElement.unhoverRaw(gd, evt); + } + } + else { + if('xpx' in evt) xpx = evt.xpx; + else xpx = xaArray[0]._length / 2; + + if('ypx' in evt) ypx = evt.ypx; + else ypx = yaArray[0]._length / 2; + } + + if('xval' in evt) xvalArray = flat(subplots, evt.xval); + else xvalArray = p2c(xaArray, xpx); + + if('yval' in evt) yvalArray = flat(subplots, evt.yval); + else yvalArray = p2c(yaArray, ypx); + + if(!isNumeric(xvalArray[0]) || !isNumeric(yvalArray[0])) { + Lib.warn('Fx.hover failed', evt, gd); + return dragElement.unhoverRaw(gd, evt); + } + } + + // the pixel distance to beat as a matching point + // in 'x' or 'y' mode this resets for each trace + var distance = Infinity; + + // find the closest point in each trace + // this is minimum dx and/or dy, depending on mode + // and the pixel position for the label (labelXpx, labelYpx) + for(curvenum = 0; curvenum < searchData.length; curvenum++) { + cd = searchData[curvenum]; + + // filter out invisible or broken data + if(!cd || !cd[0] || !cd[0].trace || cd[0].trace.visible !== true) continue; + + trace = cd[0].trace; + subplotId = getSubplot(trace); + subploti = subplots.indexOf(subplotId); + + // within one trace mode can sometimes be overridden + mode = hovermode; + + // container for new point, also used to pass info into module.hoverPoints + pointData = { + // trace properties + cd: cd, + trace: trace, + xa: xaArray[subploti], + ya: yaArray[subploti], + name: (gd.data.length > 1 || trace.hoverinfo.indexOf('name') !== -1) ? trace.name : undefined, + // point properties - override all of these + index: false, // point index in trace - only used by plotly.js hoverdata consumers + distance: Math.min(distance, constants.MAXDIST), // pixel distance or pseudo-distance + color: Color.defaultLine, // trace color + x0: undefined, + x1: undefined, + y0: undefined, + y1: undefined, + xLabelVal: undefined, + yLabelVal: undefined, + zLabelVal: undefined, + text: undefined + }; + + // add ref to subplot object (non-cartesian case) + if(fullLayout[subplotId]) { + pointData.subplot = fullLayout[subplotId]._subplot; + } + + closedataPreviousLength = hoverData.length; + + // for a highlighting array, figure out what + // we're searching for with this element + if(mode === 'array') { + var selection = evt[curvenum]; + if('pointNumber' in selection) { + pointData.index = selection.pointNumber; + mode = 'closest'; + } + else { + mode = ''; + if('xval' in selection) { + xval = selection.xval; + mode = 'x'; + } + if('yval' in selection) { + yval = selection.yval; + mode = mode ? 'closest' : 'y'; + } + } + } + else { + xval = xvalArray[subploti]; + yval = yvalArray[subploti]; + } + + // Now find the points. + if(trace._module && trace._module.hoverPoints) { + var newPoints = trace._module.hoverPoints(pointData, xval, yval, mode); + if(newPoints) { + var newPoint; + for(var newPointNum = 0; newPointNum < newPoints.length; newPointNum++) { + newPoint = newPoints[newPointNum]; + if(isNumeric(newPoint.x0) && isNumeric(newPoint.y0)) { + hoverData.push(cleanPoint(newPoint, hovermode)); + } + } + } + } + else { + Lib.log('Unrecognized trace type in hover:', trace); + } + + // in closest mode, remove any existing (farther) points + // and don't look any farther than this latest point (or points, if boxes) + if(hovermode === 'closest' && hoverData.length > closedataPreviousLength) { + hoverData.splice(0, closedataPreviousLength); + distance = hoverData[0].distance; + } + } + + // nothing left: remove all labels and quit + if(hoverData.length === 0) return dragElement.unhoverRaw(gd, evt); + + // if there's more than one horz bar trace, + // rotate the labels so they don't overlap + var rotateLabels = hovermode === 'y' && searchData.length > 1; + + hoverData.sort(function(d1, d2) { return d1.distance - d2.distance; }); + + var bgColor = Color.combine( + fullLayout.plot_bgcolor || Color.background, + fullLayout.paper_bgcolor + ); + + var labelOpts = { + hovermode: hovermode, + rotateLabels: rotateLabels, + bgColor: bgColor, + container: fullLayout._hoverlayer, + outerContainer: fullLayout._paperdiv + }; + + var hoverLabels = createHoverText(hoverData, labelOpts, evt, gd.layout.hoverFollowsMouse); + + hoverAvoidOverlaps(hoverData, rotateLabels ? 'xa' : 'ya'); + + alignHoverText(hoverLabels, rotateLabels); + + // lastly, emit custom hover/unhover events + var oldhoverdata = gd._hoverdata, + newhoverdata = []; + + // pull out just the data that's useful to + // other people and send it to the event + for(itemnum = 0; itemnum < hoverData.length; itemnum++) { + var pt = hoverData[itemnum]; + + var out = { + data: pt.trace._input, + fullData: pt.trace, + curveNumber: pt.trace.index, + pointNumber: pt.index + }; + + if(pt.trace._module.eventData) out = pt.trace._module.eventData(out, pt); + else { + out.x = pt.xVal; + out.y = pt.yVal; + out.xaxis = pt.xa; + out.yaxis = pt.ya; + + if(pt.zLabelVal !== undefined) out.z = pt.zLabelVal; + } + + newhoverdata.push(out); + } + + gd._hoverdata = newhoverdata; + + if(!hoverChanged(gd, evt, oldhoverdata)) return; + + if(oldhoverdata) { + gd.emit('plotly_unhover', { points: oldhoverdata }); + } + + gd.emit('plotly_hover', { + points: gd._hoverdata, + xaxes: xaArray, + yaxes: yaArray, + xvals: xvalArray, + yvals: yvalArray + }); +} + +// look for either .subplot (currently just ternary) +// or xaxis and yaxis attributes +function getSubplot(trace) { + return trace.subplot || (trace.xaxis + trace.yaxis) || trace.geo; +} + +fx.getDistanceFunction = function(mode, dx, dy, dxy) { + if(mode === 'closest') return dxy || quadrature(dx, dy); + return mode === 'x' ? dx : dy; +}; + +fx.getClosest = function(cd, distfn, pointData) { + // do we already have a point number? (array mode only) + if(pointData.index !== false) { + if(pointData.index >= 0 && pointData.index < cd.length) { + pointData.distance = 0; + } + else pointData.index = false; + } + else { + // apply the distance function to each data point + // this is the longest loop... if this bogs down, we may need + // to create pre-sorted data (by x or y), not sure how to + // do this for 'closest' + for(var i = 0; i < cd.length; i++) { + var newDistance = distfn(cd[i]); + if(newDistance <= pointData.distance) { + pointData.index = i; + pointData.distance = newDistance; + } + } + } + return pointData; +}; + +function cleanPoint(d, hovermode) { + d.posref = hovermode === 'y' ? (d.x0 + d.x1) / 2 : (d.y0 + d.y1) / 2; + + // then constrain all the positions to be on the plot + d.x0 = Lib.constrain(d.x0, 0, d.xa._length); + d.x1 = Lib.constrain(d.x1, 0, d.xa._length); + d.y0 = Lib.constrain(d.y0, 0, d.ya._length); + d.y1 = Lib.constrain(d.y1, 0, d.ya._length); + + // and convert the x and y label values into objects + // formatted as text, with font info + var logOffScale; + if(d.xLabelVal !== undefined) { + logOffScale = (d.xa.type === 'log' && d.xLabelVal <= 0); + var xLabelObj = Axes.tickText(d.xa, + d.xa.c2l(logOffScale ? -d.xLabelVal : d.xLabelVal), 'hover'); + if(logOffScale) { + if(d.xLabelVal === 0) d.xLabel = '0'; + else d.xLabel = '-' + xLabelObj.text; + } + else d.xLabel = xLabelObj.text; + d.xVal = d.xa.c2d(d.xLabelVal); + } + + if(d.yLabelVal !== undefined) { + logOffScale = (d.ya.type === 'log' && d.yLabelVal <= 0); + var yLabelObj = Axes.tickText(d.ya, + d.ya.c2l(logOffScale ? -d.yLabelVal : d.yLabelVal), 'hover'); + if(logOffScale) { + if(d.yLabelVal === 0) d.yLabel = '0'; + else d.yLabel = '-' + yLabelObj.text; + } + else d.yLabel = yLabelObj.text; + d.yVal = d.ya.c2d(d.yLabelVal); + } + + if(d.zLabelVal !== undefined) d.zLabel = String(d.zLabelVal); + + // for box means and error bars, add the range to the label + if(!isNaN(d.xerr) && !(d.xa.type === 'log' && d.xerr <= 0)) { + var xeText = Axes.tickText(d.xa, d.xa.c2l(d.xerr), 'hover').text; + if(d.xerrneg !== undefined) { + d.xLabel += ' +' + xeText + ' / -' + + Axes.tickText(d.xa, d.xa.c2l(d.xerrneg), 'hover').text; + } + else d.xLabel += ' ± ' + xeText; + + // small distance penalty for error bars, so that if there are + // traces with errors and some without, the error bar label will + // hoist up to the point + if(hovermode === 'x') d.distance += 1; + } + if(!isNaN(d.yerr) && !(d.ya.type === 'log' && d.yerr <= 0)) { + var yeText = Axes.tickText(d.ya, d.ya.c2l(d.yerr), 'hover').text; + if(d.yerrneg !== undefined) { + d.yLabel += ' +' + yeText + ' / -' + + Axes.tickText(d.ya, d.ya.c2l(d.yerrneg), 'hover').text; + } + else d.yLabel += ' ± ' + yeText; + + if(hovermode === 'y') d.distance += 1; + } + + var infomode = d.trace.hoverinfo; + if(infomode !== 'all') { + infomode = infomode.split('+'); + if(infomode.indexOf('x') === -1) d.xLabel = undefined; + if(infomode.indexOf('y') === -1) d.yLabel = undefined; + if(infomode.indexOf('z') === -1) d.zLabel = undefined; + if(infomode.indexOf('text') === -1) d.text = undefined; + if(infomode.indexOf('name') === -1) d.name = undefined; + } + + return d; +} + +fx.loneHover = function(hoverItem, opts) { + // draw a single hover item in a pre-existing svg container somewhere + // hoverItem should have keys: + // - x and y (or x0, x1, y0, and y1): + // the pixel position to mark, relative to opts.container + // - xLabel, yLabel, zLabel, text, and name: + // info to go in the label + // - color: + // the background color for the label. text & outline color will + // be chosen black or white to contrast with this + // opts should have keys: + // - bgColor: + // the background color this is against, used if the trace is + // non-opaque, and for the name, which goes outside the box + // - container: + // a dom element - must be big enough to contain the whole + // hover label + var pointData = { + color: hoverItem.color || Color.defaultLine, + x0: hoverItem.x0 || hoverItem.x || 0, + x1: hoverItem.x1 || hoverItem.x || 0, + y0: hoverItem.y0 || hoverItem.y || 0, + y1: hoverItem.y1 || hoverItem.y || 0, + xLabel: hoverItem.xLabel, + yLabel: hoverItem.yLabel, + zLabel: hoverItem.zLabel, + text: hoverItem.text, + name: hoverItem.name, + idealAlign: hoverItem.idealAlign, + + // filler to make createHoverText happy + trace: { + index: 0, + hoverinfo: '' + }, + xa: {_offset: 0}, + ya: {_offset: 0}, + index: 0 + }; + + var container3 = d3.select(opts.container), + outerContainer3 = opts.outerContainer ? + d3.select(opts.outerContainer) : container3; + + var fullOpts = { + hovermode: 'closest', + rotateLabels: false, + bgColor: opts.bgColor || Color.background, + container: container3, + outerContainer: outerContainer3 + }; + + var hoverLabel = createHoverText([pointData], fullOpts); + alignHoverText(hoverLabel, fullOpts.rotateLabels); + + return hoverLabel.node(); +}; + +fx.loneUnhover = function(containerOrSelection) { + var selection = containerOrSelection instanceof d3.selection ? + containerOrSelection : + d3.select(containerOrSelection); + + selection.selectAll('g.hovertext').remove(); +}; + +function createHoverText(hoverData, opts, evt, hoverFollowsMouse) { + var hovermode = opts.hovermode, + rotateLabels = opts.rotateLabels, + bgColor = opts.bgColor, + container = opts.container, + outerContainer = opts.outerContainer, + + c0 = hoverData[0], + xa = c0.xa, + ya = c0.ya, + commonAttr = hovermode === 'y' ? 'yLabel' : 'xLabel', + t0 = c0[commonAttr], + t00 = (String(t0) || '').split(' ')[0], + outerContainerBB = outerContainer.node().getBoundingClientRect(), + outerTop = outerContainerBB.top, + outerWidth = outerContainerBB.width, + outerHeight = outerContainerBB.height; + + // show the common label, if any, on the axis + // never show a common label in array mode, + // even if sometimes there could be one + var showCommonLabel = c0.distance <= constants.MAXDIST && + (hovermode === 'x' || hovermode === 'y'); + + // all hover traces hoverinfo must contain the hovermode + // to have common labels + var i, traceHoverinfo; + for(i = 0; i < hoverData.length; i++) { + traceHoverinfo = hoverData[i].trace.hoverinfo; + var parts = traceHoverinfo.split('+'); + if(parts.indexOf('all') === -1 && + parts.indexOf(hovermode) === -1) { + showCommonLabel = false; + break; + } + } + + var commonLabel = container.selectAll('g.axistext') + .data(showCommonLabel ? [0] : []); + commonLabel.enter().append('g') + .classed('axistext', true); + commonLabel.exit().remove(); + + commonLabel.each(function() { + var label = d3.select(this), + lpath = label.selectAll('path').data([0]), + ltext = label.selectAll('text').data([0]); + + lpath.enter().append('path') + .style({fill: Color.defaultLine, 'stroke-width': '1px', stroke: Color.background}); + ltext.enter().append('text') + .call(Drawing.font, HOVERFONT, HOVERFONTSIZE, Color.background) + // prohibit tex interpretation until we can handle + // tex and regular text together + .attr('data-notex', 1); + + ltext.text(t0) + .call(svgTextUtils.convertToTspans) + .call(Drawing.setPosition, 0, 0) + .selectAll('tspan.line') + .call(Drawing.setPosition, 0, 0); + label.attr('transform', ''); + + var tbb = ltext.node().getBoundingClientRect(); + if(hovermode === 'x') { + ltext.attr('text-anchor', 'middle') + .call(Drawing.setPosition, 0, (xa.side === 'top' ? + (outerTop - tbb.bottom - HOVERARROWSIZE - HOVERTEXTPAD) : + (outerTop - tbb.top + HOVERARROWSIZE + HOVERTEXTPAD))) + .selectAll('tspan.line') + .attr({ + x: ltext.attr('x'), + y: ltext.attr('y') + }); + + var topsign = xa.side === 'top' ? '-' : ''; + lpath.attr('d', 'M0,0' + + 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE + + 'H' + (HOVERTEXTPAD + tbb.width / 2) + + 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) + + 'H-' + (HOVERTEXTPAD + tbb.width / 2) + + 'V' + topsign + HOVERARROWSIZE + 'H-' + HOVERARROWSIZE + 'Z'); + + label.attr('transform', 'translate(' + + (xa._offset + (c0.x0 + c0.x1) / 2) + ',' + + (ya._offset + (xa.side === 'top' ? 0 : ya._length)) + ')'); + } + else { + ltext.attr('text-anchor', ya.side === 'right' ? 'start' : 'end') + .call(Drawing.setPosition, + (ya.side === 'right' ? 1 : -1) * (HOVERTEXTPAD + HOVERARROWSIZE), + outerTop - tbb.top - tbb.height / 2) + .selectAll('tspan.line') + .attr({ + x: ltext.attr('x'), + y: ltext.attr('y') + }); + + var leftsign = ya.side === 'right' ? '' : '-'; + lpath.attr('d', 'M0,0' + + 'L' + leftsign + HOVERARROWSIZE + ',' + HOVERARROWSIZE + + 'V' + (HOVERTEXTPAD + tbb.height / 2) + + 'h' + leftsign + (HOVERTEXTPAD * 2 + tbb.width) + + 'V-' + (HOVERTEXTPAD + tbb.height / 2) + + 'H' + leftsign + HOVERARROWSIZE + 'V-' + HOVERARROWSIZE + 'Z'); + + label.attr('transform', 'translate(' + + (xa._offset + (ya.side === 'right' ? xa._length : 0)) + ',' + + (ya._offset + (c0.y0 + c0.y1) / 2) + ')'); + } + // remove the "close but not quite" points + // because of error bars, only take up to a space + hoverData = hoverData.filter(function(d) { + return (d.zLabelVal !== undefined) || + (d[commonAttr] || '').split(' ')[0] === t00; + }); + }); + + // show all the individual labels + + // first create the objects + var hoverLabels = container.selectAll('g.hovertext') + .data(hoverData, function(d) { + return [d.trace.index, d.index, d.x0, d.y0, d.name, d.attr, d.xa, d.ya || ''].join(','); + }); + hoverLabels.enter().append('g') + .classed('hovertext', true) + .each(function() { + var g = d3.select(this); + // trace name label (rect and text.name) + g.append('rect') + .call(Color.fill, Color.addOpacity(bgColor, 0.8)); + g.append('text').classed('name', true) + .call(Drawing.font, HOVERFONT, HOVERFONTSIZE); + // trace data label (path and text.nums) + g.append('path') + .style('stroke-width', '1px'); + g.append('text').classed('nums', true) + .call(Drawing.font, HOVERFONT, HOVERFONTSIZE); + }); + hoverLabels.exit().remove(); + + // then put the text in, position the pointer to the data, + // and figure out sizes + hoverLabels.each(function(d) { + var g = d3.select(this).attr('transform', ''), + name = '', + text = '', + // combine possible non-opaque trace color with bgColor + baseColor = Color.opacity(d.color) ? + d.color : Color.defaultLine, + traceColor = Color.combine(baseColor, bgColor), + + // find a contrasting color for border and text + contrastColor = tinycolor(traceColor).getBrightness() > 128 ? + '#000' : Color.background; + + + if(d.name && d.zLabelVal === undefined) { + // strip out any html elements from d.name (if it exists at all) + // Note that this isn't an XSS vector, only because it never gets + // attached to the DOM + var tmp = document.createElement('p'); + tmp.innerHTML = d.name; + name = tmp.textContent || ''; + + if(name.length > 15) name = name.substr(0, 12) + '...'; + } + + // used by other modules (initially just ternary) that + // manage their own hoverinfo independent of cleanPoint + // the rest of this will still apply, so such modules + // can still put things in (x|y|z)Label, text, and name + // and hoverinfo will still determine their visibility + if(d.extraText !== undefined) text += d.extraText; + + if(d.zLabel !== undefined) { + if(d.xLabel !== undefined) text += 'x: ' + d.xLabel + '
'; + if(d.yLabel !== undefined) text += 'y: ' + d.yLabel + '
'; + text += (text ? 'z: ' : '') + d.zLabel; + } + else if(showCommonLabel && d[hovermode + 'Label'] === t0) { + text = d[(hovermode === 'x' ? 'y' : 'x') + 'Label'] || ''; + } + else if(d.xLabel === undefined) { + if(d.yLabel !== undefined) text = d.yLabel; + } + else if(d.yLabel === undefined) text = d.xLabel; + else text = '(' + d.xLabel + ', ' + d.yLabel + ')'; + + if(d.text && !Array.isArray(d.text)) text += (text ? '
' : '') + d.text; + + // if 'text' is empty at this point, + // put 'name' in main label and don't show secondary label + if(text === '') { + // if 'name' is also empty, remove entire label + if(name === '') g.remove(); + text = name; + } + + // main label + var tx = g.select('text.nums') + .style('fill', contrastColor) + .call(Drawing.setPosition, 0, 0) + .text(text) + .attr('data-notex', 1) + .call(svgTextUtils.convertToTspans); + tx.selectAll('tspan.line') + .call(Drawing.setPosition, 0, 0); + + var tx2 = g.select('text.name'), + tx2width = 0; + + // secondary label for non-empty 'name' + if(name && name !== text) { + tx2.style('fill', traceColor) + .text(name) + .call(Drawing.setPosition, 0, 0) + .attr('data-notex', 1) + .call(svgTextUtils.convertToTspans); + tx2.selectAll('tspan.line') + .call(Drawing.setPosition, 0, 0); + tx2width = tx2.node().getBoundingClientRect().width + 2 * HOVERTEXTPAD; + } + else { + tx2.remove(); + g.select('rect').remove(); + } + + g.select('path') + .style({ + fill: traceColor, + stroke: contrastColor + }); + var tbb = tx.node().getBoundingClientRect(), + htx = d.xa._offset + (d.x0 + d.x1) / 2, + hty = d.ya._offset + (d.y0 + d.y1) / 2, + dx = Math.abs(d.x1 - d.x0), + dy = Math.abs(d.y1 - d.y0), + txTotalWidth = tbb.width + HOVERARROWSIZE + HOVERTEXTPAD + tx2width, + anchorStartOK, + anchorEndOK; + + d.ty0 = outerTop - tbb.top; + d.bx = tbb.width + 2 * HOVERTEXTPAD; + d.by = tbb.height + 2 * HOVERTEXTPAD; + d.anchor = 'start'; + d.txwidth = tbb.width; + d.tx2width = tx2width; + d.offset = 0; + + // POSITION HOVER GROUP + if (hoverFollowsMouse && hovermode === 'closest' && evt && evt.layerX && evt.layerY) { + htx = evt.layerX; + hty = evt.layerY; + } + + if(rotateLabels) { + d.pos = htx; + anchorStartOK = hty + dy / 2 + txTotalWidth <= outerHeight; + anchorEndOK = hty - dy / 2 - txTotalWidth >= 0; + if((d.idealAlign === 'top' || !anchorStartOK) && anchorEndOK) { + hty -= dy / 2; + d.anchor = 'end'; + } else if(anchorStartOK) { + hty += dy / 2; + d.anchor = 'start'; + } else d.anchor = 'middle'; + } + else { + d.pos = hty; + anchorStartOK = htx + dx / 2 + txTotalWidth <= outerWidth; + anchorEndOK = htx - dx / 2 - txTotalWidth >= 0; + if((d.idealAlign === 'left' || !anchorStartOK) && anchorEndOK) { + htx -= dx / 2; + d.anchor = 'end'; + } else if(anchorStartOK) { + htx += dx / 2; + d.anchor = 'start'; + } else d.anchor = 'middle'; + } + + tx.attr('text-anchor', d.anchor); + if(tx2width) tx2.attr('text-anchor', d.anchor); + + g.attr('transform', 'translate(' + htx + ',' + hty + ')' + + (rotateLabels ? 'rotate(' + YANGLE + ')' : '')); + }); + + return hoverLabels; +} + +// Make groups of touching points, and within each group +// move each point so that no labels overlap, but the average +// label position is the same as it was before moving. Indicentally, +// this is equivalent to saying all the labels are on equal linear +// springs about their initial position. Initially, each point is +// its own group, but as we find overlaps we will clump the points. +// +// Also, there are hard constraints at the edges of the graphs, +// that push all groups to the middle so they are visible. I don't +// know what happens if the group spans all the way from one edge to +// the other, though it hardly matters - there's just too much +// information then. +function hoverAvoidOverlaps(hoverData, ax) { + var nummoves = 0, + + // make groups of touching points + pointgroups = hoverData + .map(function(d, i) { + var axis = d[ax]; + return [{ + i: i, + dp: 0, + pos: d.pos, + posref: d.posref, + size: d.by * (axis._id.charAt(0) === 'x' ? YFACTOR : 1) / 2, + pmin: axis._offset, + pmax: axis._offset + axis._length + }]; + }) + .sort(function(a, b) { return a[0].posref - b[0].posref; }), + donepositioning, + topOverlap, + bottomOverlap, + i, j, + pti, + sumdp; + + function constrainGroup(grp) { + var minPt = grp[0], + maxPt = grp[grp.length - 1]; + + // overlap with the top - positive vals are overlaps + topOverlap = minPt.pmin - minPt.pos - minPt.dp + minPt.size; + + // overlap with the bottom - positive vals are overlaps + bottomOverlap = maxPt.pos + maxPt.dp + maxPt.size - minPt.pmax; + + // check for min overlap first, so that we always + // see the largest labels + // allow for .01px overlap, so we don't get an + // infinite loop from rounding errors + if(topOverlap > 0.01) { + for(j = grp.length - 1; j >= 0; j--) grp[j].dp += topOverlap; + donepositioning = false; + } + if(bottomOverlap < 0.01) return; + if(topOverlap < -0.01) { + // make sure we're not pushing back and forth + for(j = grp.length - 1; j >= 0; j--) grp[j].dp -= bottomOverlap; + donepositioning = false; + } + if(!donepositioning) return; + + // no room to fix positioning, delete off-screen points + + // first see how many points we need to delete + var deleteCount = 0; + for(i = 0; i < grp.length; i++) { + pti = grp[i]; + if(pti.pos + pti.dp + pti.size > minPt.pmax) deleteCount++; + } + + // start by deleting points whose data is off screen + for(i = grp.length - 1; i >= 0; i--) { + if(deleteCount <= 0) break; + pti = grp[i]; + + // pos has already been constrained to [pmin,pmax] + // so look for points close to that to delete + if(pti.pos > minPt.pmax - 1) { + pti.del = true; + deleteCount--; + } + } + for(i = 0; i < grp.length; i++) { + if(deleteCount <= 0) break; + pti = grp[i]; + + // pos has already been constrained to [pmin,pmax] + // so look for points close to that to delete + if(pti.pos < minPt.pmin + 1) { + pti.del = true; + deleteCount--; + + // shift the whole group minus into this new space + bottomOverlap = pti.size * 2; + for(j = grp.length - 1; j >= 0; j--) grp[j].dp -= bottomOverlap; + } + } + // then delete points that go off the bottom + for(i = grp.length - 1; i >= 0; i--) { + if(deleteCount <= 0) break; + pti = grp[i]; + if(pti.pos + pti.dp + pti.size > minPt.pmax) { + pti.del = true; + deleteCount--; + } + } + } + + // loop through groups, combining them if they overlap, + // until nothing moves + while(!donepositioning && nummoves <= hoverData.length) { + // to avoid infinite loops, don't move more times + // than there are traces + nummoves++; + + // assume nothing will move in this iteration, + // reverse this if it does + donepositioning = true; + i = 0; + while(i < pointgroups.length - 1) { + // the higher (g0) and lower (g1) point group + var g0 = pointgroups[i], + g1 = pointgroups[i + 1], + + // the lowest point in the higher group (p0) + // the highest point in the lower group (p1) + p0 = g0[g0.length - 1], + p1 = g1[0]; + topOverlap = p0.pos + p0.dp + p0.size - p1.pos - p1.dp + p1.size; + + // Only group points that lie on the same axes + if(topOverlap > 0.01 && (p0.pmin === p1.pmin) && (p0.pmax === p1.pmax)) { + // push the new point(s) added to this group out of the way + for(j = g1.length - 1; j >= 0; j--) g1[j].dp += topOverlap; + + // add them to the group + g0.push.apply(g0, g1); + pointgroups.splice(i + 1, 1); + + // adjust for minimum average movement + sumdp = 0; + for(j = g0.length - 1; j >= 0; j--) sumdp += g0[j].dp; + bottomOverlap = sumdp / g0.length; + for(j = g0.length - 1; j >= 0; j--) g0[j].dp -= bottomOverlap; + donepositioning = false; + } + else i++; + } + + // check if we're going off the plot on either side and fix + pointgroups.forEach(constrainGroup); + } + + // now put these offsets into hoverData + for(i = pointgroups.length - 1; i >= 0; i--) { + var grp = pointgroups[i]; + for(j = grp.length - 1; j >= 0; j--) { + var pt = grp[j], + hoverPt = hoverData[pt.i]; + hoverPt.offset = pt.dp; + hoverPt.del = pt.del; + } + } +} + +function alignHoverText(hoverLabels, rotateLabels) { + // finally set the text positioning relative to the data and draw the + // box around it + hoverLabels.each(function(d) { + var g = d3.select(this); + if(d.del) { + g.remove(); + return; + } + var horzSign = d.anchor === 'end' ? -1 : 1, + tx = g.select('text.nums'), + alignShift = {start: 1, end: -1, middle: 0}[d.anchor], + txx = alignShift * (HOVERARROWSIZE + HOVERTEXTPAD), + tx2x = txx + alignShift * (d.txwidth + HOVERTEXTPAD), + offsetX = 0, + offsetY = d.offset; + if(d.anchor === 'middle') { + txx -= d.tx2width / 2; + tx2x -= d.tx2width / 2; + } + if(rotateLabels) { + offsetY *= -YSHIFTY; + offsetX = d.offset * YSHIFTX; + } + + g.select('path').attr('d', d.anchor === 'middle' ? + // middle aligned: rect centered on data + ('M-' + (d.bx / 2) + ',-' + (d.by / 2) + 'h' + d.bx + 'v' + d.by + 'h-' + d.bx + 'Z') : + // left or right aligned: side rect with arrow to data + ('M0,0L' + (horzSign * HOVERARROWSIZE + offsetX) + ',' + (HOVERARROWSIZE + offsetY) + + 'v' + (d.by / 2 - HOVERARROWSIZE) + + 'h' + (horzSign * d.bx) + + 'v-' + d.by + + 'H' + (horzSign * HOVERARROWSIZE + offsetX) + + 'V' + (offsetY - HOVERARROWSIZE) + + 'Z')); + + tx.call(Drawing.setPosition, + txx + offsetX, offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD) + .selectAll('tspan.line') + .attr({ + x: tx.attr('x'), + y: tx.attr('y') + }); + + if(d.tx2width) { + g.select('text.name, text.name tspan.line') + .call(Drawing.setPosition, + tx2x + alignShift * HOVERTEXTPAD + offsetX, + offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD); + g.select('rect') + .call(Drawing.setRect, + tx2x + (alignShift - 1) * d.tx2width / 2 + offsetX, + offsetY - d.by / 2 - 1, + d.tx2width, d.by + 2); + } + }); +} + +function hoverChanged(gd, evt, oldhoverdata) { + // don't emit any events if nothing changed or + // if fx.hover was called manually + if(!evt.target) return false; + if(!oldhoverdata || oldhoverdata.length !== gd._hoverdata.length) return true; + + for(var i = oldhoverdata.length - 1; i >= 0; i--) { + var oldPt = oldhoverdata[i], + newPt = gd._hoverdata[i]; + if(oldPt.curveNumber !== newPt.curveNumber || + String(oldPt.pointNumber) !== String(newPt.pointNumber)) { + return true; + } + } + return false; +} + +// on click +fx.click = function(gd, evt) { + if(gd._hoverdata && evt && evt.target) { + gd.emit('plotly_click', {button: evt.button, points: gd._hoverdata}); + // why do we get a double event without this??? + if(evt.stopImmediatePropagation) evt.stopImmediatePropagation(); + } +}; + + +// for bar charts and others with finite-size objects: you must be inside +// it to see its hover info, so distance is infinite outside. +// But make distance inside be at least 1/4 MAXDIST, and a little bigger +// for bigger bars, to prioritize scatter and smaller bars over big bars + +// note that for closest mode, two inbox's will get added in quadrature +// args are (signed) difference from the two opposite edges +// count one edge as in, so that over continuous ranges you never get a gap +fx.inbox = function(v0, v1) { + if(v0 * v1 < 0 || v0 === 0) { + return constants.MAXDIST * (0.6 - 0.3 / Math.max(3, Math.abs(v0 - v1))); + } + return Infinity; +}; + +},{"../../components/color":27,"../../components/dragelement":48,"../../components/drawing":50,"../../lib":122,"../../lib/events":116,"../../lib/svg_text_utils":134,"../layout_attributes":184,"./axes":150,"./constants":155,"./dragbox":156,"d3":10,"fast-isnumeric":13,"tinycolor2":16}],158:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var Lib = require('../../lib'); +var Plots = require('../plots'); +var Axes = require('./axes'); +var constants = require('./constants'); + +exports.name = 'cartesian'; + +exports.attr = ['xaxis', 'yaxis']; + +exports.idRoot = ['x', 'y']; + +exports.idRegex = constants.idRegex; + +exports.attrRegex = constants.attrRegex; + +exports.attributes = require('./attributes'); + +exports.layoutAttributes = require('./layout_attributes'); + +exports.transitionAxes = require('./transition_axes'); + +exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout, + subplots = Plots.getSubplotIds(fullLayout, 'cartesian'), + calcdata = gd.calcdata, + i; + + // If traces is not provided, then it's a complete replot and missing + // traces are removed + if(!Array.isArray(traces)) { + traces = []; + + for(i = 0; i < calcdata.length; i++) { + traces.push(i); + } + } + + for(i = 0; i < subplots.length; i++) { + var subplot = subplots[i], + subplotInfo = fullLayout._plots[subplot]; + + // Get all calcdata for this subplot: + var cdSubplot = []; + var pcd; + + for(var j = 0; j < calcdata.length; j++) { + var cd = calcdata[j], + trace = cd[0].trace; + + // Skip trace if whitelist provided and it's not whitelisted: + // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue; + if(trace.xaxis + trace.yaxis === subplot) { + // If this trace is specifically requested, add it to the list: + if(traces.indexOf(trace.index) !== -1) { + // Okay, so example: traces 0, 1, and 2 have fill = tonext. You animate + // traces 0 and 2. Trace 1 also needs to be updated, otherwise its fill + // is outdated. So this retroactively adds the previous trace if the + // traces are interdependent. + if(pcd && + ['tonextx', 'tonexty', 'tonext'].indexOf(trace.fill) !== -1 && + cdSubplot.indexOf(pcd) === -1) { + cdSubplot.push(pcd); + } + + cdSubplot.push(cd); + } + + // Track the previous trace on this subplot for the retroactive-add step + // above: + pcd = cd; + } + } + + plotOne(gd, subplotInfo, cdSubplot, transitionOpts, makeOnCompleteCallback); + } +}; + +function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout, + modules = fullLayout._modules; + + // remove old traces, then redraw everything + // + // TODO: scatterlayer is manually excluded from this since it knows how + // to update instead of fully removing and redrawing every time. The + // remaining plot traces should also be able to do this. Once implemented, + // we won't need this - which should sometimes be a big speedup. + if(plotinfo.plot) { + plotinfo.plot.selectAll('g:not(.scatterlayer)').selectAll('g.trace').remove(); + } + + // plot all traces for each module at once + for(var j = 0; j < modules.length; j++) { + var _module = modules[j]; + + // skip over non-cartesian trace modules + if(_module.basePlotModule.name !== 'cartesian') continue; + + // plot all traces of this type on this subplot at once + var cdModule = []; + for(var k = 0; k < cdSubplot.length; k++) { + var cd = cdSubplot[k], + trace = cd[0].trace; + + if((trace._module === _module) && (trace.visible === true)) { + cdModule.push(cd); + } + } + + _module.plot(gd, plotinfo, cdModule, transitionOpts, makeOnCompleteCallback); + } +} + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldModules = oldFullLayout._modules || [], + newModules = newFullLayout._modules || []; + + var hadScatter, hasScatter, i; + + for(i = 0; i < oldModules.length; i++) { + if(oldModules[i].name === 'scatter') { + hadScatter = true; + break; + } + } + + for(i = 0; i < newModules.length; i++) { + if(newModules[i].name === 'scatter') { + hasScatter = true; + break; + } + } + + if(hadScatter && !hasScatter) { + var oldPlots = oldFullLayout._plots, + ids = Object.keys(oldPlots || {}); + + for(i = 0; i < ids.length; i++) { + var subplotInfo = oldPlots[ids[i]]; + + if(subplotInfo.plot) { + subplotInfo.plot.select('g.scatterlayer') + .selectAll('g.trace') + .remove(); + } + } + } + + var hadCartesian = (oldFullLayout._has && oldFullLayout._has('cartesian')); + var hasCartesian = (newFullLayout._has && newFullLayout._has('cartesian')); + + if(hadCartesian && !hasCartesian) { + var subplotLayers = oldFullLayout._cartesianlayer.selectAll('.subplot'); + + subplotLayers.call(purgeSubplotLayers, oldFullLayout); + oldFullLayout._defs.selectAll('.axesclip').remove(); + } +}; + +exports.drawFramework = function(gd) { + var fullLayout = gd._fullLayout, + subplotData = makeSubplotData(gd); + + var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot') + .data(subplotData, Lib.identity); + + subplotLayers.enter().append('g') + .attr('class', function(name) { return 'subplot ' + name; }); + + subplotLayers.order(); + + subplotLayers.exit() + .call(purgeSubplotLayers, fullLayout); + + subplotLayers.each(function(name) { + var plotinfo = fullLayout._plots[name]; + + // keep ref to plot group + plotinfo.plotgroup = d3.select(this); + + // initialize list of overlay subplots + plotinfo.overlays = []; + + makeSubplotLayer(plotinfo); + + // fill in list of overlay subplots + if(plotinfo.mainplot) { + var mainplot = fullLayout._plots[plotinfo.mainplot]; + mainplot.overlays.push(plotinfo); + } + + // make separate drag layers for each subplot, + // but append them to paper rather than the plot groups, + // so they end up on top of the rest + plotinfo.draglayer = joinLayer(fullLayout._draggers, 'g', name); + }); +}; + +exports.rangePlot = function(gd, plotinfo, cdSubplot) { + makeSubplotLayer(plotinfo); + plotOne(gd, plotinfo, cdSubplot); + Plots.style(gd); +}; + +function makeSubplotData(gd) { + var fullLayout = gd._fullLayout, + subplots = Object.keys(fullLayout._plots); + + var subplotData = [], + overlays = []; + + for(var i = 0; i < subplots.length; i++) { + var subplot = subplots[i], + plotinfo = fullLayout._plots[subplot]; + + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + // is this subplot overlaid on another? + // ax.overlaying is the id of another axis of the same + // dimension that this one overlays to be an overlaid subplot, + // the main plot must exist make sure we're not trying to + // overlay on an axis that's already overlaying another + var xa2 = Axes.getFromId(gd, xa.overlaying) || xa; + if(xa2 !== xa && xa2.overlaying) { + xa2 = xa; + xa.overlaying = false; + } + + var ya2 = Axes.getFromId(gd, ya.overlaying) || ya; + if(ya2 !== ya && ya2.overlaying) { + ya2 = ya; + ya.overlaying = false; + } + + var mainplot = xa2._id + ya2._id; + if(mainplot !== subplot && subplots.indexOf(mainplot) !== -1) { + plotinfo.mainplot = mainplot; + plotinfo.mainplotinfo = fullLayout._plots[mainplot]; + overlays.push(subplot); + + // for now force overlays to overlay completely... so they + // can drag together correctly and share backgrounds. + // Later perhaps we make separate axis domain and + // tick/line domain or something, so they can still share + // the (possibly larger) dragger and background but don't + // have to both be drawn over that whole domain + xa.domain = xa2.domain.slice(); + ya.domain = ya2.domain.slice(); + } + else { + subplotData.push(subplot); + } + } + + // main subplots before overlays + subplotData = subplotData.concat(overlays); + + return subplotData; +} + +function makeSubplotLayer(plotinfo) { + var plotgroup = plotinfo.plotgroup, + id = plotinfo.id; + + // Layers to keep plot types in the right order. + // from back to front: + // 1. heatmaps, 2D histos and contour maps + // 2. bars / 1D histos + // 3. errorbars for bars and scatter + // 4. scatter + // 5. box plots + function joinPlotLayers(parent) { + joinLayer(parent, 'g', 'imagelayer'); + joinLayer(parent, 'g', 'maplayer'); + joinLayer(parent, 'g', 'barlayer'); + joinLayer(parent, 'g', 'boxlayer'); + joinLayer(parent, 'g', 'scatterlayer'); + } + + if(!plotinfo.mainplot) { + plotinfo.bg = joinLayer(plotgroup, 'rect', 'bg'); + plotinfo.bg.style('stroke-width', 0); + + var backLayer = joinLayer(plotgroup, 'g', 'layer-subplot'); + plotinfo.shapelayer = joinLayer(backLayer, 'g', 'shapelayer'); + plotinfo.imagelayer = joinLayer(backLayer, 'g', 'imagelayer'); + + plotinfo.gridlayer = joinLayer(plotgroup, 'g', 'gridlayer'); + plotinfo.overgrid = joinLayer(plotgroup, 'g', 'overgrid'); + + plotinfo.zerolinelayer = joinLayer(plotgroup, 'g', 'zerolinelayer'); + plotinfo.overzero = joinLayer(plotgroup, 'g', 'overzero'); + + plotinfo.plot = joinLayer(plotgroup, 'g', 'plot'); + plotinfo.overplot = joinLayer(plotgroup, 'g', 'overplot'); + + plotinfo.xlines = joinLayer(plotgroup, 'path', 'xlines'); + plotinfo.ylines = joinLayer(plotgroup, 'path', 'ylines'); + plotinfo.overlines = joinLayer(plotgroup, 'g', 'overlines'); + + plotinfo.xaxislayer = joinLayer(plotgroup, 'g', 'xaxislayer'); + plotinfo.yaxislayer = joinLayer(plotgroup, 'g', 'yaxislayer'); + plotinfo.overaxes = joinLayer(plotgroup, 'g', 'overaxes'); + } + else { + var mainplotinfo = plotinfo.mainplotinfo; + + // now make the components of overlaid subplots + // overlays don't have backgrounds, and append all + // their other components to the corresponding + // extra groups of their main plots. + + plotinfo.gridlayer = joinLayer(mainplotinfo.overgrid, 'g', id); + plotinfo.zerolinelayer = joinLayer(mainplotinfo.overzero, 'g', id); + + plotinfo.plot = joinLayer(mainplotinfo.overplot, 'g', id); + plotinfo.xlines = joinLayer(mainplotinfo.overlines, 'path', id); + plotinfo.ylines = joinLayer(mainplotinfo.overlines, 'path', id); + plotinfo.xaxislayer = joinLayer(mainplotinfo.overaxes, 'g', id); + plotinfo.yaxislayer = joinLayer(mainplotinfo.overaxes, 'g', id); + } + + // common attributes for all subplots, overlays or not + plotinfo.plot.call(joinPlotLayers); + + plotinfo.xlines + .style('fill', 'none') + .classed('crisp', true); + + plotinfo.ylines + .style('fill', 'none') + .classed('crisp', true); +} + +function purgeSubplotLayers(layers, fullLayout) { + if(!layers) return; + + layers.each(function(subplot) { + var plotgroup = d3.select(this), + clipId = 'clip' + fullLayout._uid + subplot + 'plot'; + + plotgroup.remove(); + fullLayout._draggers.selectAll('g.' + subplot).remove(); + fullLayout._defs.select('#' + clipId).remove(); + + // do not remove individual axis s here + // as other subplots may need them + }); +} + +function joinLayer(parent, nodeType, className) { + var layer = parent.selectAll('.' + className) + .data([0]); + + layer.enter().append(nodeType) + .classed(className, true); + + return layer; +} + +},{"../../lib":122,"../plots":186,"./attributes":149,"./axes":150,"./constants":155,"./layout_attributes":159,"./transition_axes":168,"d3":10}],159:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var fontAttrs = require('../font_attributes'); +var colorAttrs = require('../../components/color/attributes'); +var extendFlat = require('../../lib/extend').extendFlat; + +var constants = require('./constants'); + + +module.exports = { + color: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + + }, + title: { + valType: 'string', + + + }, + titlefont: extendFlat({}, fontAttrs, { + + }), + type: { + valType: 'enumerated', + // '-' means we haven't yet run autotype or couldn't find any data + // it gets turned into linear in gd._fullLayout but not copied back + // to gd.data like the others are. + values: ['-', 'linear', 'log', 'date', 'category'], + dflt: '-', + + + }, + autorange: { + valType: 'enumerated', + values: [true, false, 'reversed'], + dflt: true, + + + }, + rangemode: { + valType: 'enumerated', + values: ['normal', 'tozero', 'nonnegative'], + dflt: 'normal', + + + }, + range: { + valType: 'info_array', + + items: [ + {valType: 'any'}, + {valType: 'any'} + ], + + }, + + fixedrange: { + valType: 'boolean', + dflt: false, + + + }, + // ticks + tickmode: { + valType: 'enumerated', + values: ['auto', 'linear', 'array'], + + + }, + nticks: { + valType: 'integer', + min: 0, + dflt: 0, + + + }, + tick0: { + valType: 'any', + + + }, + dtick: { + valType: 'any', + + + }, + tickvals: { + valType: 'data_array', + + }, + ticktext: { + valType: 'data_array', + + }, + ticks: { + valType: 'enumerated', + values: ['outside', 'inside', ''], + + + }, + mirror: { + valType: 'enumerated', + values: [true, 'ticks', false, 'all', 'allticks'], + dflt: false, + + + }, + ticklen: { + valType: 'number', + min: 0, + dflt: 5, + + + }, + tickwidth: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + tickcolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + + }, + showticklabels: { + valType: 'boolean', + dflt: true, + + + }, + tickfont: extendFlat({}, fontAttrs, { + + }), + tickangle: { + valType: 'angle', + dflt: 'auto', + + + }, + tickprefix: { + valType: 'string', + dflt: '', + + + }, + showtickprefix: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + + }, + ticksuffix: { + valType: 'string', + dflt: '', + + + }, + showticksuffix: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + + }, + showexponent: { + valType: 'enumerated', + values: ['all', 'first', 'last', 'none'], + dflt: 'all', + + + }, + exponentformat: { + valType: 'enumerated', + values: ['none', 'e', 'E', 'power', 'SI', 'B'], + dflt: 'B', + + + }, + separatethousands: { + valType: 'boolean', + dflt: false, + + + }, + tickformat: { + valType: 'string', + dflt: '', + + + }, + hoverformat: { + valType: 'string', + dflt: '', + + + }, + // lines and grids + showline: { + valType: 'boolean', + dflt: false, + + + }, + linecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + + }, + linewidth: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + showgrid: { + valType: 'boolean', + + + }, + gridcolor: { + valType: 'color', + dflt: colorAttrs.lightLine, + + + }, + gridwidth: { + valType: 'number', + min: 0, + dflt: 1, + + + }, + zeroline: { + valType: 'boolean', + + + }, + zerolinecolor: { + valType: 'color', + dflt: colorAttrs.defaultLine, + + + }, + zerolinewidth: { + valType: 'number', + dflt: 1, + + + }, + // positioning attributes + // anchor: not used directly, just put here for reference + // values are any opposite-letter axis id + anchor: { + valType: 'enumerated', + values: [ + 'free', + constants.idRegex.x.toString(), + constants.idRegex.y.toString() + ], + + + }, + // side: not used directly, as values depend on direction + // values are top, bottom for x axes, and left, right for y + side: { + valType: 'enumerated', + values: ['top', 'bottom', 'left', 'right'], + + + }, + // overlaying: not used directly, just put here for reference + // values are false and any other same-letter axis id that's not + // itself overlaying anything + overlaying: { + valType: 'enumerated', + values: [ + 'free', + constants.idRegex.x.toString(), + constants.idRegex.y.toString() + ], + + + }, + domain: { + valType: 'info_array', + + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + + }, + position: { + valType: 'number', + min: 0, + max: 1, + dflt: 0, + + + }, + categoryorder: { + valType: 'enumerated', + values: [ + 'trace', 'category ascending', 'category descending', 'array' + /* , 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later + ], + dflt: 'trace', + + + }, + categoryarray: { + valType: 'data_array', + + + }, + + _deprecated: { + autotick: { + valType: 'boolean', + + + } + } +}; + +},{"../../components/color/attributes":26,"../../lib/extend":117,"../font_attributes":170,"./constants":155}],160:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = require('../../registry'); +var Lib = require('../../lib'); +var Color = require('../../components/color'); +var basePlotLayoutAttributes = require('../layout_attributes'); + +var constants = require('./constants'); +var layoutAttributes = require('./layout_attributes'); +var handleAxisDefaults = require('./axis_defaults'); +var handlePositionDefaults = require('./position_defaults'); +var axisIds = require('./axis_ids'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + var layoutKeys = Object.keys(layoutIn), + xaListCartesian = [], + yaListCartesian = [], + xaListGl2d = [], + yaListGl2d = [], + outerTicks = {}, + noGrids = {}, + i; + + // look for axes in the data + for(i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + var listX, listY; + + if(Registry.traceIs(trace, 'cartesian')) { + listX = xaListCartesian; + listY = yaListCartesian; + } + else if(Registry.traceIs(trace, 'gl2d')) { + listX = xaListGl2d; + listY = yaListGl2d; + } + else continue; + + var xaName = axisIds.id2name(trace.xaxis), + yaName = axisIds.id2name(trace.yaxis); + + // add axes implied by traces + if(xaName && listX.indexOf(xaName) === -1) listX.push(xaName); + if(yaName && listY.indexOf(yaName) === -1) listY.push(yaName); + + // check for default formatting tweaks + if(Registry.traceIs(trace, '2dMap')) { + outerTicks[xaName] = true; + outerTicks[yaName] = true; + } + + if(Registry.traceIs(trace, 'oriented')) { + var positionAxis = trace.orientation === 'h' ? yaName : xaName; + noGrids[positionAxis] = true; + } + } + + // N.B. Ignore orphan axes (i.e. axes that have no data attached to them) + // if gl3d or geo is present on graph. This is retain backward compatible. + // + // TODO drop this in version 2.0 + var ignoreOrphan = (layoutOut._has('gl3d') || layoutOut._has('geo')); + + if(!ignoreOrphan) { + for(i = 0; i < layoutKeys.length; i++) { + var key = layoutKeys[i]; + + // orphan layout axes are considered cartesian subplots + + if(xaListGl2d.indexOf(key) === -1 && + xaListCartesian.indexOf(key) === -1 && + constants.xAxisMatch.test(key)) { + xaListCartesian.push(key); + } + else if(yaListGl2d.indexOf(key) === -1 && + yaListCartesian.indexOf(key) === -1 && + constants.yAxisMatch.test(key)) { + yaListCartesian.push(key); + } + } + } + + // make sure that plots with orphan cartesian axes + // are considered 'cartesian' + if(xaListCartesian.length && yaListCartesian.length) { + Lib.pushUnique(layoutOut._basePlotModules, Registry.subplotsRegistry.cartesian); + } + + function axSort(a, b) { + var aNum = Number(a.substr(5) || 1), + bNum = Number(b.substr(5) || 1); + return aNum - bNum; + } + + var xaList = xaListCartesian.concat(xaListGl2d).sort(axSort), + yaList = yaListCartesian.concat(yaListGl2d).sort(axSort), + axesList = xaList.concat(yaList); + + // plot_bgcolor only makes sense if there's a (2D) plot! + // TODO: bgcolor for each subplot, to inherit from the main one + var plot_bgcolor = Color.background; + if(xaList.length && yaList.length) { + plot_bgcolor = Lib.coerce(layoutIn, layoutOut, basePlotLayoutAttributes, 'plot_bgcolor'); + } + + var bgColor = Color.combine(plot_bgcolor, layoutOut.paper_bgcolor); + + axesList.forEach(function(axName) { + var axLetter = axName.charAt(0), + axLayoutIn = layoutIn[axName] || {}, + axLayoutOut = {}, + defaultOptions = { + letter: axLetter, + font: layoutOut.font, + outerTicks: outerTicks[axName], + showGrid: !noGrids[axName], + name: axName, + data: fullData, + bgColor: bgColor + }, + positioningOptions = { + letter: axLetter, + counterAxes: {x: yaList, y: xaList}[axLetter].map(axisIds.name2id), + overlayableAxes: {x: xaList, y: yaList}[axLetter].filter(function(axName2) { + return axName2 !== axName && !(layoutIn[axName2] || {}).overlaying; + }).map(axisIds.name2id) + }; + + function coerce(attr, dflt) { + return Lib.coerce(axLayoutIn, axLayoutOut, layoutAttributes, attr, dflt); + } + + handleAxisDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions); + handlePositionDefaults(axLayoutIn, axLayoutOut, coerce, positioningOptions); + + layoutOut[axName] = axLayoutOut; + + // so we don't have to repeat autotype unnecessarily, + // copy an autotype back to layoutIn + if(!layoutIn[axName] && axLayoutIn.type !== '-') { + layoutIn[axName] = {type: axLayoutIn.type}; + } + + }); + + // quick second pass for range slider and selector defaults + var rangeSliderDefaults = Registry.getComponentMethod('rangeslider', 'handleDefaults'), + rangeSelectorDefaults = Registry.getComponentMethod('rangeselector', 'handleDefaults'); + + axesList.forEach(function(axName) { + var axLetter = axName.charAt(0), + axLayoutIn = layoutIn[axName], + axLayoutOut = layoutOut[axName], + counterAxes = {x: yaList, y: xaList}[axLetter]; + + rangeSliderDefaults(layoutIn, layoutOut, axName, counterAxes); + + if(axLetter === 'x' && axLayoutOut.type === 'date') { + rangeSelectorDefaults(axLayoutIn, axLayoutOut, layoutOut, counterAxes); + } + }); +}; + +},{"../../components/color":27,"../../lib":122,"../../registry":194,"../layout_attributes":184,"./axis_defaults":152,"./axis_ids":153,"./constants":155,"./layout_attributes":159,"./position_defaults":162}],161:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +// flattenUniqueSort :: String -> Function -> [[String]] -> [String] +function flattenUniqueSort(axisLetter, sortFunction, data) { + + // Bisection based insertion sort of distinct values for logarithmic time complexity. + // Can't use a hashmap, which is O(1), because ES5 maps coerce keys to strings. If it ever becomes a bottleneck, + // code can be separated: a hashmap (JS object) based version if all values encountered are strings; and + // downgrading to this O(log(n)) array on the first encounter of a non-string value. + + var categoryArray = []; + + var traceLines = data.map(function(d) {return d[axisLetter];}); + + var i, j, tracePoints, category, insertionIndex; + + var bisector = d3.bisector(sortFunction).left; + + for(i = 0; i < traceLines.length; i++) { + + tracePoints = traceLines[i]; + + for(j = 0; j < tracePoints.length; j++) { + + category = tracePoints[j]; + + // skip loop: ignore null and undefined categories + if(category === null || category === undefined) continue; + + insertionIndex = bisector(categoryArray, category); + + // skip loop on already encountered values + if(insertionIndex < categoryArray.length && categoryArray[insertionIndex] === category) continue; + + // insert value + categoryArray.splice(insertionIndex, 0, category); + } + } + + return categoryArray; +} + + +/** + * This pure function returns the ordered categories for specified axisLetter, categoryorder, categoryarray and data. + * + * If categoryorder is 'array', the result is a fresh copy of categoryarray, or if unspecified, an empty array. + * + * If categoryorder is 'category ascending' or 'category descending', the result is an array of ascending or descending + * order of the unique categories encountered in the data for specified axisLetter. + * + * See cartesian/layout_attributes.js for the definition of categoryorder and categoryarray + * + */ + +// orderedCategories :: String -> String -> [String] -> [[String]] -> [String] +module.exports = function orderedCategories(axisLetter, categoryorder, categoryarray, data) { + + switch(categoryorder) { + case 'array': return Array.isArray(categoryarray) ? categoryarray.slice() : []; + case 'category ascending': return flattenUniqueSort(axisLetter, d3.ascending, data); + case 'category descending': return flattenUniqueSort(axisLetter, d3.descending, data); + case 'trace': return []; + default: return []; + } +}; + +},{"d3":10}],162:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); + + +module.exports = function handlePositionDefaults(containerIn, containerOut, coerce, options) { + var counterAxes = options.counterAxes || [], + overlayableAxes = options.overlayableAxes || [], + letter = options.letter; + + var anchor = Lib.coerce(containerIn, containerOut, { + anchor: { + valType: 'enumerated', + values: ['free'].concat(counterAxes), + dflt: isNumeric(containerIn.position) ? 'free' : + (counterAxes[0] || 'free') + } + }, 'anchor'); + + if(anchor === 'free') coerce('position'); + + Lib.coerce(containerIn, containerOut, { + side: { + valType: 'enumerated', + values: letter === 'x' ? ['bottom', 'top'] : ['left', 'right'], + dflt: letter === 'x' ? 'bottom' : 'left' + } + }, 'side'); + + var overlaying = false; + if(overlayableAxes.length) { + overlaying = Lib.coerce(containerIn, containerOut, { + overlaying: { + valType: 'enumerated', + values: [false].concat(overlayableAxes), + dflt: false + } + }, 'overlaying'); + } + + if(!overlaying) { + // TODO: right now I'm copying this domain over to overlaying axes + // in ax.setscale()... but this means we still need (imperfect) logic + // in the axes popover to hide domain for the overlaying axis. + // perhaps I should make a private version _domain that all axes get??? + var domain = coerce('domain'); + if(domain[0] > domain[1] - 0.01) containerOut.domain = [0, 1]; + Lib.noneOrAll(containerIn.domain, containerOut.domain, [0, 1]); + } + + return containerOut; +}; + +},{"../../lib":122,"fast-isnumeric":13}],163:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var polygon = require('../../lib/polygon'); +var color = require('../../components/color'); + +var axes = require('./axes'); +var constants = require('./constants'); + +var filteredPolygon = polygon.filter; +var polygonTester = polygon.tester; +var MINSELECT = constants.MINSELECT; + +function getAxId(ax) { return ax._id; } + +module.exports = function prepSelect(e, startX, startY, dragOptions, mode) { + var plot = dragOptions.gd._fullLayout._zoomlayer, + dragBBox = dragOptions.element.getBoundingClientRect(), + xs = dragOptions.plotinfo.xaxis._offset, + ys = dragOptions.plotinfo.yaxis._offset, + x0 = startX - dragBBox.left, + y0 = startY - dragBBox.top, + x1 = x0, + y1 = y0, + path0 = 'M' + x0 + ',' + y0, + pw = dragOptions.xaxes[0]._length, + ph = dragOptions.yaxes[0]._length, + xAxisIds = dragOptions.xaxes.map(getAxId), + yAxisIds = dragOptions.yaxes.map(getAxId), + allAxes = dragOptions.xaxes.concat(dragOptions.yaxes), + pts; + + if(mode === 'lasso') { + pts = filteredPolygon([[x0, y0]], constants.BENDPX); + } + + var outlines = plot.selectAll('path.select-outline').data([1, 2]); + + outlines.enter() + .append('path') + .attr('class', function(d) { return 'select-outline select-outline-' + d; }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', path0 + 'Z'); + + var corners = plot.append('path') + .attr('class', 'zoombox-corners') + .style({ + fill: color.background, + stroke: color.defaultLine, + 'stroke-width': 1 + }) + .attr('transform', 'translate(' + xs + ', ' + ys + ')') + .attr('d', 'M0,0Z'); + + + // find the traces to search for selection points + var searchTraces = [], + gd = dragOptions.gd, + i, + cd, + trace, + searchInfo, + selection = [], + eventData; + for(i = 0; i < gd.calcdata.length; i++) { + cd = gd.calcdata[i]; + trace = cd[0].trace; + if(!trace._module || !trace._module.selectPoints) continue; + + if(dragOptions.subplot) { + if(trace.subplot !== dragOptions.subplot) continue; + + searchTraces.push({ + selectPoints: trace._module.selectPoints, + cd: cd, + xaxis: dragOptions.xaxes[0], + yaxis: dragOptions.yaxes[0] + }); + } + else { + if(xAxisIds.indexOf(trace.xaxis) === -1) continue; + if(yAxisIds.indexOf(trace.yaxis) === -1) continue; + + searchTraces.push({ + selectPoints: trace._module.selectPoints, + cd: cd, + xaxis: axes.getFromId(gd, trace.xaxis), + yaxis: axes.getFromId(gd, trace.yaxis) + }); + } + } + + function axValue(ax) { + var index = (ax._id.charAt(0) === 'y') ? 1 : 0; + return function(v) { return ax.p2d(v[index]); }; + } + + function ascending(a, b) { return a - b; } + + dragOptions.moveFn = function(dx0, dy0) { + var poly, + ax; + x1 = Math.max(0, Math.min(pw, dx0 + x0)); + y1 = Math.max(0, Math.min(ph, dy0 + y0)); + + var dx = Math.abs(x1 - x0), + dy = Math.abs(y1 - y0); + + if(mode === 'select') { + if(dy < Math.min(dx * 0.6, MINSELECT)) { + // horizontal motion: make a vertical box + poly = polygonTester([[x0, 0], [x0, ph], [x1, ph], [x1, 0]]); + // extras to guide users in keeping a straight selection + corners.attr('d', 'M' + poly.xmin + ',' + (y0 - MINSELECT) + + 'h-4v' + (2 * MINSELECT) + 'h4Z' + + 'M' + (poly.xmax - 1) + ',' + (y0 - MINSELECT) + + 'h4v' + (2 * MINSELECT) + 'h-4Z'); + + } + else if(dx < Math.min(dy * 0.6, MINSELECT)) { + // vertical motion: make a horizontal box + poly = polygonTester([[0, y0], [0, y1], [pw, y1], [pw, y0]]); + corners.attr('d', 'M' + (x0 - MINSELECT) + ',' + poly.ymin + + 'v-4h' + (2 * MINSELECT) + 'v4Z' + + 'M' + (x0 - MINSELECT) + ',' + (poly.ymax - 1) + + 'v4h' + (2 * MINSELECT) + 'v-4Z'); + } + else { + // diagonal motion + poly = polygonTester([[x0, y0], [x0, y1], [x1, y1], [x1, y0]]); + corners.attr('d', 'M0,0Z'); + } + outlines.attr('d', 'M' + poly.xmin + ',' + poly.ymin + + 'H' + (poly.xmax - 1) + 'V' + (poly.ymax - 1) + + 'H' + poly.xmin + 'Z'); + } + else if(mode === 'lasso') { + pts.addPt([x1, y1]); + poly = polygonTester(pts.filtered); + outlines.attr('d', 'M' + pts.filtered.join('L') + 'Z'); + } + + selection = []; + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + [].push.apply(selection, searchInfo.selectPoints(searchInfo, poly)); + } + + eventData = {points: selection}; + + if(mode === 'select') { + var ranges = eventData.range = {}, + axLetter; + + for(i = 0; i < allAxes.length; i++) { + ax = allAxes[i]; + axLetter = ax._id.charAt(0); + ranges[ax._id] = [ + ax.p2d(poly[axLetter + 'min']), + ax.p2d(poly[axLetter + 'max'])].sort(ascending); + } + } + else { + var dataPts = eventData.lassoPoints = {}; + + for(i = 0; i < allAxes.length; i++) { + ax = allAxes[i]; + dataPts[ax._id] = pts.filtered.map(axValue(ax)); + } + } + dragOptions.gd.emit('plotly_selecting', eventData); + }; + + dragOptions.doneFn = function(dragged, numclicks) { + corners.remove(); + if(!dragged && numclicks === 2) { + // clear selection on doubleclick + outlines.remove(); + for(i = 0; i < searchTraces.length; i++) { + searchInfo = searchTraces[i]; + searchInfo.selectPoints(searchInfo, false); + } + + gd.emit('plotly_deselect', null); + } + else { + dragOptions.gd.emit('plotly_selected', eventData); + } + }; +}; + +},{"../../components/color":27,"../../lib/polygon":129,"./axes":150,"./constants":155}],164:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var numConstants = require('../../constants/numerical'); +var FP_SAFE = numConstants.FP_SAFE; +var BADNUM = numConstants.BADNUM; + +var constants = require('./constants'); +var axisIds = require('./axis_ids'); + + +/** + * Define the conversion functions for an axis data is used in 5 ways: + * + * d: data, in whatever form it's provided + * c: calcdata: turned into numbers, but not linearized + * l: linearized - same as c except for log axes (and other nonlinear + * mappings later?) this is used when we need to know if it's + * *possible* to show some data on this axis, without caring about + * the current range + * p: pixel value - mapped to the screen with current size and zoom + * r: ranges, tick0, and annotation positions match one of the above + * but are handled differently for different types: + * - linear and date: data format (d) + * - category: calcdata format (c), and will stay that way because + * the data format has no continuous mapping + * - log: linearized (l) format + * TODO: in v2.0 we plan to change it to data format. At that point + * shapes will work the same way as ranges, tick0, and annotations + * so they can use this conversion too. + * + * Creates/updates these conversion functions, as well as cleaner functions: + * ax.d2d and ax.clean2r + * also clears the autorange bounds ._min and ._max + * and the autotick constraints ._minDtick, ._forceTick0 + */ +module.exports = function setConvert(ax) { + + // clipMult: how many axis lengths past the edge do we render? + // for panning, 1-2 would suffice, but for zooming more is nice. + // also, clipping can affect the direction of lines off the edge... + var clipMult = 10; + + function toLog(v, clip) { + if(v > 0) return Math.log(v) / Math.LN10; + + else if(v <= 0 && clip && ax.range && ax.range.length === 2) { + // clip NaN (ie past negative infinity) to clipMult axis + // length past the negative edge + var r0 = ax.range[0], + r1 = ax.range[1]; + return 0.5 * (r0 + r1 - 3 * clipMult * Math.abs(r0 - r1)); + } + + else return BADNUM; + } + + function fromLog(v) { + return Math.pow(10, v); + } + + function num(v) { + if(!isNumeric(v)) return BADNUM; + v = Number(v); + if(v < -FP_SAFE || v > FP_SAFE) return BADNUM; + return isNumeric(v) ? Number(v) : BADNUM; + } + + ax.c2l = (ax.type === 'log') ? toLog : num; + ax.l2c = (ax.type === 'log') ? fromLog : num; + ax.l2d = function(v) { return ax.c2d(ax.l2c(v)); }; + ax.p2d = function(v) { return ax.l2d(ax.p2l(v)); }; + + /* + * fn to make sure range is a couplet of valid & distinct values + * keep numbers away from the limits of floating point numbers, + * and dates away from the ends of our date system (+/- 9999 years) + * + * optional param rangeAttr: operate on a different attribute, like + * ax._r, rather than ax.range + */ + ax.cleanRange = function(rangeAttr) { + if(!rangeAttr) rangeAttr = 'range'; + var range = ax[rangeAttr], + axLetter = (ax._id || 'x').charAt(0), + i, dflt; + + if(ax.type === 'date') dflt = constants.DFLTRANGEDATE; + else if(axLetter === 'y') dflt = constants.DFLTRANGEY; + else dflt = constants.DFLTRANGEX; + + // make sure we don't later mutate the defaults + dflt = dflt.slice(); + + if(!range || range.length !== 2) { + ax[rangeAttr] = dflt; + return; + } + + if(ax.type === 'date') { + // check if milliseconds or js date objects are provided for range + // and convert to date strings + range[0] = Lib.cleanDate(range[0]); + range[1] = Lib.cleanDate(range[1]); + } + + for(i = 0; i < 2; i++) { + if(ax.type === 'date') { + if(!Lib.isDateTime(range[i])) { + ax[rangeAttr] = dflt; + break; + } + + if(range[i] < Lib.MIN_MS) range[i] = Lib.MIN_MS; + if(range[i] > Lib.MAX_MS) range[i] = Lib.MAX_MS; + + if(ax.r2l(range[0]) === ax.r2l(range[1])) { + // split by +/- 1 second + var linCenter = Lib.constrain(ax.r2l(range[0]), + Lib.MIN_MS + 1000, Lib.MAX_MS - 1000); + range[0] = ax.l2r(linCenter - 1000); + range[1] = ax.l2r(linCenter + 1000); + break; + } + } + else { + if(!isNumeric(range[i])) { + if(isNumeric(range[1 - i])) { + range[i] = range[1 - i] * (i ? 10 : 0.1); + } + else { + ax[rangeAttr] = dflt; + break; + } + } + + if(range[i] < -FP_SAFE) range[i] = -FP_SAFE; + else if(range[i] > FP_SAFE) range[i] = FP_SAFE; + + if(range[0] === range[1]) { + // somewhat arbitrary: split by 1 or 1ppm, whichever is bigger + var inc = Math.max(1, Math.abs(range[0] * 1e-6)); + range[0] -= inc; + range[1] += inc; + } + } + } + }; + + // find the range value at the specified (linear) fraction of the axis + ax.fraction2r = function(v) { + var rl0 = ax.r2l(ax.range[0]), + rl1 = ax.r2l(ax.range[1]); + return ax.l2r(rl0 + v * (rl1 - rl0)); + }; + + // find the fraction of the range at the specified range value + ax.r2fraction = function(v) { + var rl0 = ax.r2l(ax.range[0]), + rl1 = ax.r2l(ax.range[1]); + return (ax.r2l(v) - rl0) / (rl1 - rl0); + }; + + // set scaling to pixels + ax.setScale = function(usePrivateRange) { + var gs = ax._gd._fullLayout._size, + axLetter = ax._id.charAt(0); + + // TODO cleaner way to handle this case + if(!ax._categories) ax._categories = []; + + // make sure we have a domain (pull it in from the axis + // this one is overlaying if necessary) + if(ax.overlaying) { + var ax2 = axisIds.getFromId(ax._gd, ax.overlaying); + ax.domain = ax2.domain; + } + + // While transitions are occuring, occurring, we get a double-transform + // issue if we transform the drawn layer *and* use the new axis range to + // draw the data. This allows us to construct setConvert using the pre- + // interaction values of the range: + var rangeAttr = (usePrivateRange && ax._r) ? '_r' : 'range'; + ax.cleanRange(rangeAttr); + + var rl0 = ax.r2l(ax[rangeAttr][0]), + rl1 = ax.r2l(ax[rangeAttr][1]); + + if(axLetter === 'y') { + ax._offset = gs.t + (1 - ax.domain[1]) * gs.h; + ax._length = gs.h * (ax.domain[1] - ax.domain[0]); + ax._m = ax._length / (rl0 - rl1); + ax._b = -ax._m * rl1; + } + else { + ax._offset = gs.l + ax.domain[0] * gs.w; + ax._length = gs.w * (ax.domain[1] - ax.domain[0]); + ax._m = ax._length / (rl1 - rl0); + ax._b = -ax._m * rl0; + } + + if(!isFinite(ax._m) || !isFinite(ax._b)) { + Lib.notifier( + 'Something went wrong with axis scaling', + 'long'); + ax._gd._replotting = false; + throw new Error('axis scaling'); + } + }; + + ax.l2p = function(v) { + if(!isNumeric(v)) return BADNUM; + + // include 2 fractional digits on pixel, for PDF zooming etc + return d3.round(ax._b + ax._m * v, 2); + }; + + ax.p2l = function(px) { return (px - ax._b) / ax._m; }; + + ax.c2p = function(v, clip) { return ax.l2p(ax.c2l(v, clip)); }; + ax.p2c = function(px) { return ax.l2c(ax.p2l(px)); }; + + // clip doesn't do anything here yet, but in v2.0 when log axes get + // refactored it will... so including it now so we don't forget. + ax.r2p = function(v, clip) { return ax.l2p(ax.r2l(v, clip)); }; + ax.p2r = function(px) { return ax.l2r(ax.p2l(px)); }; + + ax.r2c = function(v) { return ax.l2c(ax.r2l(v)); }; + ax.c2r = function(v) { return ax.l2r(ax.c2l(v)); }; + + if(['linear', 'log', '-'].indexOf(ax.type) !== -1) { + ax.c2d = num; + ax.d2c = Lib.cleanNumber; + if(ax.type === 'log') { + ax.d2l = function(v, clip) { + return ax.c2l(ax.d2c(v), clip); + }; + ax.d2r = ax.d2l; + ax.r2d = ax.l2d; + } + else { + ax.d2l = Lib.cleanNumber; + ax.d2r = Lib.cleanNumber; + ax.r2d = num; + } + ax.r2l = num; + ax.l2r = num; + } + else if(ax.type === 'date') { + ax.c2d = Lib.ms2DateTime; + + ax.d2c = function(v) { + // NOTE: Changed this behavior: previously we took any numeric value + // to be a ms, even if it was a string that could be a bare year. + // Now we convert it as a date if at all possible, and only try + // as ms if that fails. + var ms = Lib.dateTime2ms(v); + if(ms === BADNUM) { + if(isNumeric(v)) ms = Number(v); + else return BADNUM; + } + return Lib.constrain(ms, Lib.MIN_MS, Lib.MAX_MS); + }; + + ax.d2l = ax.d2c; + ax.r2l = ax.d2c; + ax.l2r = ax.c2d; + ax.d2r = Lib.identity; + ax.r2d = Lib.identity; + ax.cleanr = function(v) { + /* + * If v is already a date string this is a noop, but running it + * through d2c and back validates the value: + * normalizes Date objects, milliseconds, and out-of-bounds dates + * so we always end up with either a clean date string or BADNUM + */ + return ax.c2d(ax.d2c(v)); + }; + } + else if(ax.type === 'category') { + + ax.c2d = function(v) { + return ax._categories[Math.round(v)]; + }; + + ax.d2c = function(v) { + // create the category list + // this will enter the categories in the order it + // encounters them, ie all the categories from the + // first data set, then all the ones from the second + // that aren't in the first etc. + // it is assumed that this function is being invoked in the + // already sorted category order; otherwise there would be + // a disconnect between the array and the index returned + + if(v !== null && v !== undefined && ax._categories.indexOf(v) === -1) { + ax._categories.push(v); + } + + var c = ax._categories.indexOf(v); + return c === -1 ? BADNUM : c; + }; + + ax.d2l = ax.d2c; + ax.r2l = num; + ax.l2r = num; + ax.d2r = ax.d2c; + ax.r2d = ax.c2d; + } + + // makeCalcdata: takes an x or y array and converts it + // to a position on the axis object "ax" + // inputs: + // trace - a data object from gd.data + // axLetter - a string, either 'x' or 'y', for which item + // to convert (TODO: is this now always the same as + // the first letter of ax._id?) + // in case the expected data isn't there, make a list of + // integers based on the opposite data + ax.makeCalcdata = function(trace, axLetter) { + var arrayIn, arrayOut, i; + + if(axLetter in trace) { + arrayIn = trace[axLetter]; + arrayOut = new Array(arrayIn.length); + + for(i = 0; i < arrayIn.length; i++) arrayOut[i] = ax.d2c(arrayIn[i]); + } + else { + var v0 = ((axLetter + '0') in trace) ? + ax.d2c(trace[axLetter + '0']) : 0, + dv = (trace['d' + axLetter]) ? + Number(trace['d' + axLetter]) : 1; + + // the opposing data, for size if we have x and dx etc + arrayIn = trace[{x: 'y', y: 'x'}[axLetter]]; + arrayOut = new Array(arrayIn.length); + + for(i = 0; i < arrayIn.length; i++) arrayOut[i] = v0 + i * dv; + } + return arrayOut; + }; + + // for autoranging: arrays of objects: + // {val: axis value, pad: pixel padding} + // on the low and high sides + ax._min = []; + ax._max = []; + + // and for bar charts and box plots: reset forced minimum tick spacing + delete ax._minDtick; + delete ax._forceTick0; +}; + +},{"../../constants/numerical":107,"../../lib":122,"./axis_ids":153,"./constants":155,"d3":10,"fast-isnumeric":13}],165:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + + +/** + * options: inherits font, outerTicks, noHover from axes.handleAxisDefaults + */ +module.exports = function handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options) { + var showAttrDflt = getShowAttrDflt(containerIn); + + var tickPrefix = coerce('tickprefix'); + if(tickPrefix) coerce('showtickprefix', showAttrDflt); + + var tickSuffix = coerce('ticksuffix'); + if(tickSuffix) coerce('showticksuffix', showAttrDflt); + + var showTickLabels = coerce('showticklabels'); + if(showTickLabels) { + var font = options.font || {}; + // as with titlefont.color, inherit axis.color only if one was + // explicitly provided + var dfltFontColor = (containerOut.color === containerIn.color) ? + containerOut.color : font.color; + Lib.coerceFont(coerce, 'tickfont', { + family: font.family, + size: font.size, + color: dfltFontColor + }); + coerce('tickangle'); + + if(axType !== 'category') { + var tickFormat = coerce('tickformat'); + if(!tickFormat && axType !== 'date') { + coerce('showexponent', showAttrDflt); + coerce('exponentformat'); + coerce('separatethousands'); + } + } + } + + if(axType !== 'category' && !options.noHover) coerce('hoverformat'); +}; + +/* + * Attributes 'showexponent', 'showtickprefix' and 'showticksuffix' + * share values. + * + * If only 1 attribute is set, + * the remaining attributes inherit that value. + * + * If 2 attributes are set to the same value, + * the remaining attribute inherits that value. + * + * If 2 attributes are set to different values, + * the remaining is set to its dflt value. + * + */ +function getShowAttrDflt(containerIn) { + var showAttrsAll = ['showexponent', + 'showtickprefix', + 'showticksuffix'], + showAttrs = showAttrsAll.filter(function(a) { + return containerIn[a] !== undefined; + }), + sameVal = function(a) { + return containerIn[a] === containerIn[showAttrs[0]]; + }; + + if(showAttrs.every(sameVal) || showAttrs.length === 1) { + return containerIn[showAttrs[0]]; + } +} + +},{"../../lib":122}],166:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + +var layoutAttributes = require('./layout_attributes'); + + +/** + * options: inherits outerTicks from axes.handleAxisDefaults + */ +module.exports = function handleTickDefaults(containerIn, containerOut, coerce, options) { + var tickLen = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'ticklen'), + tickWidth = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickwidth'), + tickColor = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickcolor', containerOut.color), + showTicks = coerce('ticks', (options.outerTicks || tickLen || tickWidth || tickColor) ? 'outside' : ''); + + if(!showTicks) { + delete containerOut.ticklen; + delete containerOut.tickwidth; + delete containerOut.tickcolor; + } +}; + +},{"../../lib":122,"./layout_attributes":159}],167:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var Lib = require('../../lib'); +var ONEDAY = require('../../constants/numerical').ONEDAY; + + +module.exports = function handleTickValueDefaults(containerIn, containerOut, coerce, axType) { + var tickmodeDefault = 'auto'; + + if(containerIn.tickmode === 'array' && + (axType === 'log' || axType === 'date')) { + containerIn.tickmode = 'auto'; + } + + if(Array.isArray(containerIn.tickvals)) tickmodeDefault = 'array'; + else if(containerIn.dtick) { + tickmodeDefault = 'linear'; + } + var tickmode = coerce('tickmode', tickmodeDefault); + + if(tickmode === 'auto') coerce('nticks'); + else if(tickmode === 'linear') { + // dtick is usually a positive number, but there are some + // special strings available for log or date axes + // default is 1 day for dates, otherwise 1 + var dtickDflt = (axType === 'date') ? ONEDAY : 1; + var dtick = coerce('dtick', dtickDflt); + if(isNumeric(dtick)) { + containerOut.dtick = (dtick > 0) ? Number(dtick) : dtickDflt; + } + else if(typeof dtick !== 'string') { + containerOut.dtick = dtickDflt; + } + else { + // date and log special cases are all one character plus a number + var prefix = dtick.charAt(0), + dtickNum = dtick.substr(1); + + dtickNum = isNumeric(dtickNum) ? Number(dtickNum) : 0; + if((dtickNum <= 0) || !( + // "M" gives ticks every (integer) n months + (axType === 'date' && prefix === 'M' && dtickNum === Math.round(dtickNum)) || + // "L" gives ticks linearly spaced in data (not in position) every (float) f + (axType === 'log' && prefix === 'L') || + // "D1" gives powers of 10 with all small digits between, "D2" gives only 2 and 5 + (axType === 'log' && prefix === 'D' && (dtickNum === 1 || dtickNum === 2)) + )) { + containerOut.dtick = dtickDflt; + } + } + + // tick0 can have different valType for different axis types, so + // validate that now. Also for dates, change milliseconds to date strings + var tick0Dflt = (axType === 'date') ? '2000-01-01' : 0; + var tick0 = coerce('tick0', tick0Dflt); + if(axType === 'date') { + containerOut.tick0 = Lib.cleanDate(tick0, tick0Dflt); + } + // Aside from date axes, dtick must be numeric; D1 and D2 modes ignore tick0 entirely + else if(isNumeric(tick0) && dtick !== 'D1' && dtick !== 'D2') { + containerOut.tick0 = Number(tick0); + } + else { + containerOut.tick0 = tick0Dflt; + } + } + else { + var tickvals = coerce('tickvals'); + if(tickvals === undefined) containerOut.tickmode = 'auto'; + else coerce('ticktext'); + } +}; + +},{"../../constants/numerical":107,"../../lib":122,"fast-isnumeric":13}],168:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Plotly = require('../../plotly'); +var Registry = require('../../registry'); +var Lib = require('../../lib'); +var Axes = require('./axes'); +var axisRegex = /((x|y)([2-9]|[1-9][0-9]+)?)axis$/; + +module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCompleteCallback) { + var fullLayout = gd._fullLayout; + var axes = []; + + function computeUpdates(layout) { + var ai, attrList, match, axis, update; + var updates = {}; + + for(ai in layout) { + attrList = ai.split('.'); + match = attrList[0].match(axisRegex); + if(match) { + var axisLetter = match[1]; + var axisName = axisLetter + 'axis'; + axis = fullLayout[axisName]; + update = {}; + + if(Array.isArray(layout[ai])) { + update.to = layout[ai].slice(0); + } else { + if(Array.isArray(layout[ai].range)) { + update.to = layout[ai].range.slice(0); + } + } + if(!update.to) continue; + + update.axisName = axisName; + update.length = axis._length; + + axes.push(axisLetter); + + updates[axisLetter] = update; + } + } + + return updates; + } + + function computeAffectedSubplots(fullLayout, updatedAxisIds, updates) { + var plotName; + var plotinfos = fullLayout._plots; + var affectedSubplots = []; + var toX, toY; + + for(plotName in plotinfos) { + var plotinfo = plotinfos[plotName]; + + if(affectedSubplots.indexOf(plotinfo) !== -1) continue; + + var x = plotinfo.xaxis._id; + var y = plotinfo.yaxis._id; + var fromX = plotinfo.xaxis.range; + var fromY = plotinfo.yaxis.range; + + // Store the initial range at the beginning of this transition: + plotinfo.xaxis._r = plotinfo.xaxis.range.slice(); + plotinfo.yaxis._r = plotinfo.yaxis.range.slice(); + + if(updates[x]) { + toX = updates[x].to; + } else { + toX = fromX; + } + if(updates[y]) { + toY = updates[y].to; + } else { + toY = fromY; + } + + if(fromX[0] === toX[0] && fromX[1] === toX[1] && fromY[0] === toY[0] && fromY[1] === toY[1]) continue; + + if(updatedAxisIds.indexOf(x) !== -1 || updatedAxisIds.indexOf(y) !== -1) { + affectedSubplots.push(plotinfo); + } + } + + return affectedSubplots; + } + + var updates = computeUpdates(newLayout); + var updatedAxisIds = Object.keys(updates); + var affectedSubplots = computeAffectedSubplots(fullLayout, updatedAxisIds, updates); + + if(!affectedSubplots.length) { + return false; + } + + function ticksAndAnnotations(xa, ya) { + var activeAxIds = [], + i; + + activeAxIds = [xa._id, ya._id]; + + for(i = 0; i < activeAxIds.length; i++) { + Axes.doTicks(gd, activeAxIds[i], true); + } + + function redrawObjs(objArray, method) { + for(i = 0; i < objArray.length; i++) { + var obji = objArray[i]; + + if((activeAxIds.indexOf(obji.xref) !== -1) || + (activeAxIds.indexOf(obji.yref) !== -1)) { + method(gd, i); + } + } + } + + // annotations and shapes 'draw' method is slow, + // use the finer-grained 'drawOne' method instead + + redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne')); + redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne')); + redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw')); + } + + function unsetSubplotTransform(subplot) { + var xa2 = subplot.xaxis; + var ya2 = subplot.yaxis; + + fullLayout._defs.selectAll('#' + subplot.clipId) + .call(Lib.setTranslate, 0, 0) + .call(Lib.setScale, 1, 1); + + subplot.plot + .call(Lib.setTranslate, xa2._offset, ya2._offset) + .call(Lib.setScale, 1, 1) + + // This is specifically directed at scatter traces, applying an inverse + // scale to individual points to counteract the scale of the trace + // as a whole: + .selectAll('.points').selectAll('.point') + .call(Lib.setPointGroupScale, 1, 1); + + } + + function updateSubplot(subplot, progress) { + var axis, r0, r1; + var xUpdate = updates[subplot.xaxis._id]; + var yUpdate = updates[subplot.yaxis._id]; + + var viewBox = []; + + if(xUpdate) { + axis = gd._fullLayout[xUpdate.axisName]; + r0 = axis._r; + r1 = xUpdate.to; + viewBox[0] = (r0[0] * (1 - progress) + progress * r1[0] - r0[0]) / (r0[1] - r0[0]) * subplot.xaxis._length; + var dx1 = r0[1] - r0[0]; + var dx2 = r1[1] - r1[0]; + + axis.range[0] = r0[0] * (1 - progress) + progress * r1[0]; + axis.range[1] = r0[1] * (1 - progress) + progress * r1[1]; + + viewBox[2] = subplot.xaxis._length * ((1 - progress) + progress * dx2 / dx1); + } else { + viewBox[0] = 0; + viewBox[2] = subplot.xaxis._length; + } + + if(yUpdate) { + axis = gd._fullLayout[yUpdate.axisName]; + r0 = axis._r; + r1 = yUpdate.to; + viewBox[1] = (r0[1] * (1 - progress) + progress * r1[1] - r0[1]) / (r0[0] - r0[1]) * subplot.yaxis._length; + var dy1 = r0[1] - r0[0]; + var dy2 = r1[1] - r1[0]; + + axis.range[0] = r0[0] * (1 - progress) + progress * r1[0]; + axis.range[1] = r0[1] * (1 - progress) + progress * r1[1]; + + viewBox[3] = subplot.yaxis._length * ((1 - progress) + progress * dy2 / dy1); + } else { + viewBox[1] = 0; + viewBox[3] = subplot.yaxis._length; + } + + ticksAndAnnotations(subplot.xaxis, subplot.yaxis); + + + var xa2 = subplot.xaxis; + var ya2 = subplot.yaxis; + + var editX = !!xUpdate; + var editY = !!yUpdate; + + var xScaleFactor = editX ? xa2._length / viewBox[2] : 1, + yScaleFactor = editY ? ya2._length / viewBox[3] : 1; + + var clipDx = editX ? viewBox[0] : 0, + clipDy = editY ? viewBox[1] : 0; + + var fracDx = editX ? (viewBox[0] / viewBox[2] * xa2._length) : 0, + fracDy = editY ? (viewBox[1] / viewBox[3] * ya2._length) : 0; + + var plotDx = xa2._offset - fracDx, + plotDy = ya2._offset - fracDy; + + fullLayout._defs.selectAll('#' + subplot.clipId) + .call(Lib.setTranslate, clipDx, clipDy) + .call(Lib.setScale, 1 / xScaleFactor, 1 / yScaleFactor); + + subplot.plot + .call(Lib.setTranslate, plotDx, plotDy) + .call(Lib.setScale, xScaleFactor, yScaleFactor) + + // This is specifically directed at scatter traces, applying an inverse + // scale to individual points to counteract the scale of the trace + // as a whole: + .selectAll('.points').selectAll('.point') + .call(Lib.setPointGroupScale, 1 / xScaleFactor, 1 / yScaleFactor); + + } + + var onComplete; + if(makeOnCompleteCallback) { + // This module makes the choice whether or not it notifies Plotly.transition + // about completion: + onComplete = makeOnCompleteCallback(); + } + + function transitionComplete() { + var aobj = {}; + for(var i = 0; i < updatedAxisIds.length; i++) { + var axi = gd._fullLayout[updates[updatedAxisIds[i]].axisName]; + var to = updates[updatedAxisIds[i]].to; + aobj[axi._name + '.range[0]'] = to[0]; + aobj[axi._name + '.range[1]'] = to[1]; + + axi.range = to.slice(); + } + + // Signal that this transition has completed: + onComplete && onComplete(); + + return Plotly.relayout(gd, aobj).then(function() { + for(var i = 0; i < affectedSubplots.length; i++) { + unsetSubplotTransform(affectedSubplots[i]); + } + }); + } + + function transitionInterrupt() { + var aobj = {}; + for(var i = 0; i < updatedAxisIds.length; i++) { + var axi = gd._fullLayout[updatedAxisIds[i] + 'axis']; + aobj[axi._name + '.range[0]'] = axi.range[0]; + aobj[axi._name + '.range[1]'] = axi.range[1]; + + axi.range = axi._r.slice(); + } + + return Plotly.relayout(gd, aobj).then(function() { + for(var i = 0; i < affectedSubplots.length; i++) { + unsetSubplotTransform(affectedSubplots[i]); + } + }); + } + + var t1, t2, raf; + var easeFn = d3.ease(transitionOpts.easing); + + gd._transitionData._interruptCallbacks.push(function() { + window.cancelAnimationFrame(raf); + raf = null; + return transitionInterrupt(); + }); + + function doFrame() { + t2 = Date.now(); + + var tInterp = Math.min(1, (t2 - t1) / transitionOpts.duration); + var progress = easeFn(tInterp); + + for(var i = 0; i < affectedSubplots.length; i++) { + updateSubplot(affectedSubplots[i], progress); + } + + if(t2 - t1 > transitionOpts.duration) { + transitionComplete(); + raf = window.cancelAnimationFrame(doFrame); + } else { + raf = window.requestAnimationFrame(doFrame); + } + } + + t1 = Date.now(); + raf = window.requestAnimationFrame(doFrame); + + return Promise.resolve(); +}; + +},{"../../lib":122,"../../plotly":145,"../../registry":194,"./axes":150,"d3":10}],169:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Plotly = require('../plotly'); +var Lib = require('../lib'); + +/* + * Create or update an observer. This function is designed to be + * idempotent so that it can be called over and over as the component + * updates, and will attach and detach listeners as needed. + * + * @param {optional object} container + * An object on which the observer is stored. This is the mechanism + * by which it is idempotent. If it already exists, another won't be + * added. Each time it's called, the value lookup table is updated. + * @param {array} commandList + * An array of commands, following either `buttons` of `updatemenus` + * or `steps` of `sliders`. + * @param {function} onchange + * A listener called when the value is changed. Receives data object + * with information about the new state. + */ +exports.manageCommandObserver = function(gd, container, commandList, onchange) { + var ret = {}; + var enabled = true; + + if(container && container._commandObserver) { + ret = container._commandObserver; + } + + if(!ret.cache) { + ret.cache = {}; + } + + // Either create or just recompute this: + ret.lookupTable = {}; + + var binding = exports.hasSimpleAPICommandBindings(gd, commandList, ret.lookupTable); + + if(container && container._commandObserver) { + if(!binding) { + // If container exists and there are no longer any bindings, + // remove existing: + if(container._commandObserver.remove) { + container._commandObserver.remove(); + container._commandObserver = null; + return ret; + } + } else { + // If container exists and there *are* bindings, then the lookup + // table should have been updated and check is already attached, + // so there's nothing to be done: + return ret; + + + } + } + + // Determine whether there's anything to do for this binding: + + if(binding) { + // Build the cache: + bindingValueHasChanged(gd, binding, ret.cache); + + ret.check = function check() { + if(!enabled) return; + + var update = bindingValueHasChanged(gd, binding, ret.cache); + + if(update.changed && onchange) { + // Disable checks for the duration of this command in order to avoid + // infinite loops: + if(ret.lookupTable[update.value] !== undefined) { + ret.disable(); + Promise.resolve(onchange({ + value: update.value, + type: binding.type, + prop: binding.prop, + traces: binding.traces, + index: ret.lookupTable[update.value] + })).then(ret.enable, ret.enable); + } + } + + return update.changed; + }; + + var checkEvents = [ + 'plotly_relayout', + 'plotly_redraw', + 'plotly_restyle', + 'plotly_update', + 'plotly_animatingframe', + 'plotly_afterplot' + ]; + + for(var i = 0; i < checkEvents.length; i++) { + gd._internalOn(checkEvents[i], ret.check); + } + + ret.remove = function() { + for(var i = 0; i < checkEvents.length; i++) { + gd._removeInternalListener(checkEvents[i], ret.check); + } + }; + } else { + // TODO: It'd be really neat to actually give a *reason* for this, but at least a warning + // is a start + Lib.warn('Unable to automatically bind plot updates to API command'); + + ret.lookupTable = {}; + ret.remove = function() {}; + } + + ret.disable = function disable() { + enabled = false; + }; + + ret.enable = function enable() { + enabled = true; + }; + + if(container) { + container._commandObserver = ret; + } + + return ret; +}; + +/* + * This function checks to see if an array of objects containing + * method and args properties is compatible with automatic two-way + * binding. The criteria right now are that + * + * 1. multiple traces may be affected + * 2. only one property may be affected + * 3. the same property must be affected by all commands + */ +exports.hasSimpleAPICommandBindings = function(gd, commandList, bindingsByValue) { + var n = commandList.length; + + var refBinding; + + for(var i = 0; i < n; i++) { + var binding; + var command = commandList[i]; + var method = command.method; + var args = command.args; + + // If any command has no method, refuse to bind: + if(!method) { + return false; + } + var bindings = exports.computeAPICommandBindings(gd, method, args); + + // Right now, handle one and *only* one property being set: + if(bindings.length !== 1) { + return false; + } + + if(!refBinding) { + refBinding = bindings[0]; + if(Array.isArray(refBinding.traces)) { + refBinding.traces.sort(); + } + } else { + binding = bindings[0]; + if(binding.type !== refBinding.type) { + return false; + } + if(binding.prop !== refBinding.prop) { + return false; + } + if(Array.isArray(refBinding.traces)) { + if(Array.isArray(binding.traces)) { + binding.traces.sort(); + for(var j = 0; j < refBinding.traces.length; j++) { + if(refBinding.traces[j] !== binding.traces[j]) { + return false; + } + } + } else { + return false; + } + } else { + if(binding.prop !== refBinding.prop) { + return false; + } + } + } + + binding = bindings[0]; + var value = binding.value; + if(Array.isArray(value)) { + value = value[0]; + } + if(bindingsByValue) { + bindingsByValue[value] = i; + } + } + + return refBinding; +}; + +function bindingValueHasChanged(gd, binding, cache) { + var container, value, obj; + var changed = false; + + if(binding.type === 'data') { + // If it's data, we need to get a trace. Based on the limited scope + // of what we cover, we can just take the first trace from the list, + // or otherwise just the first trace: + container = gd._fullData[binding.traces !== null ? binding.traces[0] : 0]; + } else if(binding.type === 'layout') { + container = gd._fullLayout; + } else { + return false; + } + + value = Lib.nestedProperty(container, binding.prop).get(); + + obj = cache[binding.type] = cache[binding.type] || {}; + + if(obj.hasOwnProperty(binding.prop)) { + if(obj[binding.prop] !== value) { + changed = true; + } + } + + obj[binding.prop] = value; + + return { + changed: changed, + value: value + }; +} + +/* + * Execute an API command. There's really not much to this; it just provides + * a common hook so that implementations don't need to be synchronized across + * multiple components with the ability to invoke API commands. + * + * @param {string} method + * The name of the plotly command to execute. Must be one of 'animate', + * 'restyle', 'relayout', 'update'. + * @param {array} args + * A list of arguments passed to the API command + */ +exports.executeAPICommand = function(gd, method, args) { + var apiMethod = Plotly[method]; + + var allArgs = [gd]; + for(var i = 0; i < args.length; i++) { + allArgs.push(args[i]); + } + + return apiMethod.apply(null, allArgs).catch(function(err) { + Lib.warn('API call to Plotly.' + method + ' rejected.', err); + return Promise.reject(err); + }); +}; + +exports.computeAPICommandBindings = function(gd, method, args) { + var bindings; + switch(method) { + case 'restyle': + bindings = computeDataBindings(gd, args); + break; + case 'relayout': + bindings = computeLayoutBindings(gd, args); + break; + case 'update': + bindings = computeDataBindings(gd, [args[0], args[2]]) + .concat(computeLayoutBindings(gd, [args[1]])); + break; + case 'animate': + bindings = computeAnimateBindings(gd, args); + break; + default: + // This is the case where intelligent logic about what affects + // this command is not implemented. It causes no ill effects. + // For example, addFrames simply won't bind to a control component. + bindings = []; + } + return bindings; +}; + +function computeAnimateBindings(gd, args) { + // We'll assume that the only relevant modification an animation + // makes that's meaningfully tracked is the frame: + if(Array.isArray(args[0]) && args[0].length === 1 && typeof args[0][0] === 'string') { + return [{type: 'layout', prop: '_currentFrame', value: args[0][0]}]; + } else { + return []; + } +} + +function computeLayoutBindings(gd, args) { + var bindings = []; + + var astr = args[0]; + var aobj = {}; + if(typeof astr === 'string') { + aobj[astr] = args[1]; + } else if(Lib.isPlainObject(astr)) { + aobj = astr; + } else { + return bindings; + } + + crawl(aobj, function(path, attrName, attr) { + bindings.push({type: 'layout', prop: path, value: attr}); + }, '', 0); + + return bindings; +} + +function computeDataBindings(gd, args) { + var traces, astr, val, aobj; + var bindings = []; + + // Logic copied from Plotly.restyle: + astr = args[0]; + val = args[1]; + traces = args[2]; + aobj = {}; + if(typeof astr === 'string') { + aobj[astr] = val; + } else if(Lib.isPlainObject(astr)) { + // the 3-arg form + aobj = astr; + + if(traces === undefined) { + traces = val; + } + } else { + return bindings; + } + + if(traces === undefined) { + // Explicitly assign this to null instead of undefined: + traces = null; + } + + crawl(aobj, function(path, attrName, attr) { + var thisTraces; + if(Array.isArray(attr)) { + var nAttr = Math.min(attr.length, gd.data.length); + if(traces) { + nAttr = Math.min(nAttr, traces.length); + } + thisTraces = []; + for(var j = 0; j < nAttr; j++) { + thisTraces[j] = traces ? traces[j] : j; + } + } else { + thisTraces = traces ? traces.slice(0) : null; + } + + // Convert [7] to just 7 when traces is null: + if(thisTraces === null) { + if(Array.isArray(attr)) { + attr = attr[0]; + } + } else if(Array.isArray(thisTraces)) { + if(!Array.isArray(attr)) { + var tmp = attr; + attr = []; + for(var i = 0; i < thisTraces.length; i++) { + attr[i] = tmp; + } + } + attr.length = Math.min(thisTraces.length, attr.length); + } + + bindings.push({ + type: 'data', + prop: path, + traces: thisTraces, + value: attr + }); + }, '', 0); + + return bindings; +} + +function crawl(attrs, callback, path, depth) { + Object.keys(attrs).forEach(function(attrName) { + var attr = attrs[attrName]; + + if(attrName[0] === '_') return; + + var thisPath = path + (depth > 0 ? '.' : '') + attrName; + + if(Lib.isPlainObject(attr)) { + crawl(attr, callback, thisPath, depth + 1); + } else { + // Only execute the callback on leaf nodes: + callback(thisPath, attrName, attr); + } + }); +} + +},{"../lib":122,"../plotly":145}],170:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + family: { + valType: 'string', + + noBlank: true, + strict: true, + + }, + size: { + valType: 'number', + + min: 1 + }, + color: { + valType: 'color', + + } +}; + +},{}],171:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + group: { + valType: 'string', + + + }, + name: { + valType: 'string', + + + }, + traces: { + valType: 'data_array', + + }, + baseframe: { + valType: 'string', + + + }, + data: { + valType: 'data_array', + + }, + layout: { + valType: 'any', + + } +}; + +},{}],172:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var params = module.exports = {}; + +// projection names to d3 function name +params.projNames = { + // d3.geo.projection + 'equirectangular': 'equirectangular', + 'mercator': 'mercator', + 'orthographic': 'orthographic', + 'natural earth': 'naturalEarth', + 'kavrayskiy7': 'kavrayskiy7', + 'miller': 'miller', + 'robinson': 'robinson', + 'eckert4': 'eckert4', + 'azimuthal equal area': 'azimuthalEqualArea', + 'azimuthal equidistant': 'azimuthalEquidistant', + 'conic equal area': 'conicEqualArea', + 'conic conformal': 'conicConformal', + 'conic equidistant': 'conicEquidistant', + 'gnomonic': 'gnomonic', + 'stereographic': 'stereographic', + 'mollweide': 'mollweide', + 'hammer': 'hammer', + 'transverse mercator': 'transverseMercator', + 'albers usa': 'albersUsa', + 'winkel tripel': 'winkel3' +}; + +// name of the axes +params.axesNames = ['lonaxis', 'lataxis']; + +// max longitudinal angular span (EXPERIMENTAL) +params.lonaxisSpan = { + 'orthographic': 180, + 'azimuthal equal area': 360, + 'azimuthal equidistant': 360, + 'conic conformal': 180, + 'gnomonic': 160, + 'stereographic': 180, + 'transverse mercator': 180, + '*': 360 +}; + +// max latitudinal angular span (EXPERIMENTAL) +params.lataxisSpan = { + 'conic conformal': 150, + 'stereographic': 179.5, + '*': 180 +}; + +// defaults for each scope +params.scopeDefaults = { + world: { + lonaxisRange: [-180, 180], + lataxisRange: [-90, 90], + projType: 'equirectangular', + projRotate: [0, 0, 0] + }, + usa: { + lonaxisRange: [-180, -50], + lataxisRange: [15, 80], + projType: 'albers usa' + }, + europe: { + lonaxisRange: [-30, 60], + lataxisRange: [30, 80], + projType: 'conic conformal', + projRotate: [15, 0, 0], + projParallels: [0, 60] + }, + asia: { + lonaxisRange: [22, 160], + lataxisRange: [-15, 55], + projType: 'mercator', + projRotate: [0, 0, 0] + }, + africa: { + lonaxisRange: [-30, 60], + lataxisRange: [-40, 40], + projType: 'mercator', + projRotate: [0, 0, 0] + }, + 'north america': { + lonaxisRange: [-180, -45], + lataxisRange: [5, 85], + projType: 'conic conformal', + projRotate: [-100, 0, 0], + projParallels: [29.5, 45.5] + }, + 'south america': { + lonaxisRange: [-100, -30], + lataxisRange: [-60, 15], + projType: 'mercator', + projRotate: [0, 0, 0] + } +}; + +// angular pad to avoid rounding error around clip angles +params.clipPad = 1e-3; + +// map projection precision +params.precision = 0.1; + +// default land and water fill colors +params.landColor = '#F0DC82'; +params.waterColor = '#3399FF'; + +// locationmode to layer name +params.locationmodeToLayer = { + 'ISO-3': 'countries', + 'USA-states': 'subunits', + 'country names': 'countries' +}; + +// SVG element for a sphere (use to frame maps) +params.sphereSVG = {type: 'Sphere'}; + +// N.B. base layer names must be the same as in the topojson files + +// base layer with a fill color +params.fillLayers = ['ocean', 'land', 'lakes']; + +// base layer with a only a line color +params.lineLayers = ['subunits', 'countries', 'coastlines', 'rivers', 'frame']; + +// all base layers - in order +params.baseLayers = [ + 'ocean', 'land', 'lakes', + 'subunits', 'countries', 'coastlines', 'rivers', + 'lataxis', 'lonaxis', + 'frame' +]; + +params.layerNameToAdjective = { + ocean: 'ocean', + land: 'land', + lakes: 'lake', + subunits: 'subunit', + countries: 'country', + coastlines: 'coastline', + rivers: 'river', + frame: 'frame' +}; + +// base layers drawn over choropleth +params.baseLayersOverChoropleth = ['rivers', 'lakes']; + +},{}],173:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +/* global PlotlyGeoAssets:false */ + +var d3 = require('d3'); + +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); +var Axes = require('../../plots/cartesian/axes'); +var Fx = require('../../plots/cartesian/graph_interact'); + +var addProjectionsToD3 = require('./projections'); +var createGeoScale = require('./set_scale'); +var createGeoZoom = require('./zoom'); +var createGeoZoomReset = require('./zoom_reset'); +var constants = require('./constants'); + +var xmlnsNamespaces = require('../../constants/xmlns_namespaces'); +var topojsonUtils = require('../../lib/topojson_utils'); +var topojsonFeature = require('topojson-client').feature; + +// add a few projection types to d3.geo +addProjectionsToD3(d3); + + +function Geo(options, fullLayout) { + this.id = options.id; + this.graphDiv = options.graphDiv; + this.container = options.container; + this.topojsonURL = options.topojsonURL; + + this.hoverContainer = null; + + this.topojsonName = null; + this.topojson = null; + + this.projectionType = null; + this.projection = null; + + this.clipAngle = null; + this.setScale = null; + this.path = null; + + this.zoom = null; + this.zoomReset = null; + + this.xaxis = null; + this.yaxis = null; + + this.makeFramework(); + this.updateFx(fullLayout.hovermode); + + this.traceHash = {}; +} + +module.exports = Geo; + +var proto = Geo.prototype; + +proto.plot = function(geoCalcData, fullLayout, promises) { + var _this = this, + geoLayout = fullLayout[_this.id], + graphSize = fullLayout._size; + + var topojsonNameNew, topojsonPath; + + // N.B. 'geoLayout' is unambiguous, no need for 'user' geo layout here + + // TODO don't reset projection on all graph edits + _this.projection = null; + + _this.setScale = createGeoScale(geoLayout, graphSize); + _this.makeProjection(geoLayout); + _this.makePath(); + _this.adjustLayout(geoLayout, graphSize); + + _this.zoom = createGeoZoom(_this, geoLayout); + _this.zoomReset = createGeoZoomReset(_this, geoLayout); + _this.mockAxis = createMockAxis(fullLayout); + + _this.framework + .call(_this.zoom) + .on('dblclick.zoom', _this.zoomReset); + + _this.framework.on('mousemove', function() { + var mouse = d3.mouse(this), + lonlat = _this.projection.invert(mouse); + + if(isNaN(lonlat[0]) || isNaN(lonlat[1])) return; + + var evt = { + target: true, + xpx: mouse[0], + ypx: mouse[1] + }; + + _this.xaxis.c2p = function() { return mouse[0]; }; + _this.xaxis.p2c = function() { return lonlat[0]; }; + _this.yaxis.c2p = function() { return mouse[1]; }; + _this.yaxis.p2c = function() { return lonlat[1]; }; + + Fx.hover(_this.graphDiv, evt, _this.id); + }); + + _this.framework.on('mouseout', function() { + Fx.loneUnhover(fullLayout._toppaper); + }); + + _this.framework.on('click', function() { + Fx.click(_this.graphDiv, { target: true }); + }); + + topojsonNameNew = topojsonUtils.getTopojsonName(geoLayout); + + if(_this.topojson === null || topojsonNameNew !== _this.topojsonName) { + _this.topojsonName = topojsonNameNew; + + if(PlotlyGeoAssets.topojson[_this.topojsonName] !== undefined) { + _this.topojson = PlotlyGeoAssets.topojson[_this.topojsonName]; + _this.onceTopojsonIsLoaded(geoCalcData, geoLayout); + } + else { + topojsonPath = topojsonUtils.getTopojsonPath( + _this.topojsonURL, + _this.topojsonName + ); + + promises.push(new Promise(function(resolve, reject) { + d3.json(topojsonPath, function(error, topojson) { + if(error) { + if(error.status === 404) { + reject(new Error([ + 'plotly.js could not find topojson file at', + topojsonPath, '.', + 'Make sure the *topojsonURL* plot config option', + 'is set properly.' + ].join(' '))); + } + else { + reject(new Error([ + 'unexpected error while fetching topojson file at', + topojsonPath + ].join(' '))); + } + return; + } + + _this.topojson = topojson; + PlotlyGeoAssets.topojson[_this.topojsonName] = topojson; + + _this.onceTopojsonIsLoaded(geoCalcData, geoLayout); + resolve(); + }); + })); + } + } + else _this.onceTopojsonIsLoaded(geoCalcData, geoLayout); + + // TODO handle topojson-is-loading case + // to avoid making multiple request while streaming +}; + +proto.onceTopojsonIsLoaded = function(geoCalcData, geoLayout) { + var i; + + this.drawLayout(geoLayout); + + var traceHashOld = this.traceHash; + var traceHash = {}; + + for(i = 0; i < geoCalcData.length; i++) { + var calcData = geoCalcData[i], + trace = calcData[0].trace; + + traceHash[trace.type] = traceHash[trace.type] || []; + traceHash[trace.type].push(calcData); + } + + var moduleNamesOld = Object.keys(traceHashOld); + var moduleNames = Object.keys(traceHash); + + // when a trace gets deleted, make sure that its module's + // plot method is called so that it is properly + // removed from the DOM. + for(i = 0; i < moduleNamesOld.length; i++) { + var moduleName = moduleNamesOld[i]; + + if(moduleNames.indexOf(moduleName) === -1) { + var fakeCalcTrace = traceHashOld[moduleName][0], + fakeTrace = fakeCalcTrace[0].trace; + + fakeTrace.visible = false; + traceHash[moduleName] = [fakeCalcTrace]; + } + } + + moduleNames = Object.keys(traceHash); + + for(i = 0; i < moduleNames.length; i++) { + var moduleCalcData = traceHash[moduleNames[i]], + _module = moduleCalcData[0][0].trace._module; + + _module.plot(this, filterVisible(moduleCalcData), geoLayout); + } + + this.traceHash = traceHash; + + this.render(); +}; + +function filterVisible(calcDataIn) { + var calcDataOut = []; + + for(var i = 0; i < calcDataIn.length; i++) { + var calcTrace = calcDataIn[i], + trace = calcTrace[0].trace; + + if(trace.visible === true) calcDataOut.push(calcTrace); + } + + return calcDataOut; +} + +proto.updateFx = function(hovermode) { + this.showHover = (hovermode !== false); + + // TODO should more strict, any layout.hovermode other + // then false will make all geo subplot display hover text. + // Instead each geo should have its own geo.hovermode + // to control hover visibility independently of other subplots. +}; + +proto.makeProjection = function(geoLayout) { + var projLayout = geoLayout.projection, + projType = projLayout.type, + isNew = this.projection === null || projType !== this.projectionType, + projection; + + if(isNew) { + this.projectionType = projType; + projection = this.projection = d3.geo[constants.projNames[projType]](); + } + else projection = this.projection; + + projection + .translate(projLayout._translate0) + .precision(constants.precision); + + if(!geoLayout._isAlbersUsa) { + projection + .rotate(projLayout._rotate) + .center(projLayout._center); + } + + if(geoLayout._clipAngle) { + this.clipAngle = geoLayout._clipAngle; // needed in proto.render + projection + .clipAngle(geoLayout._clipAngle - constants.clipPad); + } + else this.clipAngle = null; // for graph edits + + if(projLayout.parallels) { + projection + .parallels(projLayout.parallels); + } + + if(isNew) this.setScale(projection); + + projection + .translate(projLayout._translate) + .scale(projLayout._scale); +}; + +proto.makePath = function() { + this.path = d3.geo.path().projection(this.projection); +}; + +/* + *
+ *
+ * + * + */ +proto.makeFramework = function() { + var geoDiv = this.geoDiv = d3.select(this.container).append('div'); + geoDiv + .attr('id', this.id) + .style('position', 'absolute'); + + // only choropleth traces use this, + // scattergeo traces use Fx.hover and fullLayout._hoverlayer + var hoverContainer = this.hoverContainer = geoDiv.append('svg'); + hoverContainer + .attr(xmlnsNamespaces.svgAttrs) + .style({ + 'position': 'absolute', + 'z-index': 20, + 'pointer-events': 'none' + }); + + var framework = this.framework = geoDiv.append('svg'); + framework + .attr(xmlnsNamespaces.svgAttrs) + .attr({ + 'position': 'absolute', + 'preserveAspectRatio': 'none' + }); + + framework.append('g').attr('class', 'bglayer') + .append('rect'); + + framework.append('g').attr('class', 'baselayer'); + framework.append('g').attr('class', 'choroplethlayer'); + framework.append('g').attr('class', 'baselayeroverchoropleth'); + framework.append('g').attr('class', 'scattergeolayer'); + + // N.B. disable dblclick zoom default + framework.on('dblclick.zoom', null); + + // TODO use clip paths instead of nested SVG + + this.xaxis = { _id: 'x' }; + this.yaxis = { _id: 'y' }; +}; + +proto.adjustLayout = function(geoLayout, graphSize) { + var domain = geoLayout.domain; + + var left = graphSize.l + graphSize.w * domain.x[0] + geoLayout._marginX, + top = graphSize.t + graphSize.h * (1 - domain.y[1]) + geoLayout._marginY; + + this.geoDiv.style({ + left: left + 'px', + top: top + 'px', + width: geoLayout._width + 'px', + height: geoLayout._height + 'px' + }); + + this.hoverContainer.attr({ + width: geoLayout._width, + height: geoLayout._height + }); + + this.framework.attr({ + width: geoLayout._width, + height: geoLayout._height + }); + + this.framework.select('.bglayer').select('rect') + .attr({ + width: geoLayout._width, + height: geoLayout._height + }) + .call(Color.fill, geoLayout.bgcolor); + + this.xaxis._offset = left; + this.xaxis._length = geoLayout._width; + + this.yaxis._offset = top; + this.yaxis._length = geoLayout._height; +}; + +proto.drawTopo = function(selection, layerName, geoLayout) { + if(geoLayout['show' + layerName] !== true) return; + + var topojson = this.topojson, + datum = layerName === 'frame' ? + constants.sphereSVG : + topojsonFeature(topojson, topojson.objects[layerName]); + + selection.append('g') + .datum(datum) + .attr('class', layerName) + .append('path') + .attr('class', 'basepath'); +}; + +function makeGraticule(lonaxisRange, lataxisRange, step) { + return d3.geo.graticule() + .extent([ + [lonaxisRange[0], lataxisRange[0]], + [lonaxisRange[1], lataxisRange[1]] + ]) + .step(step); +} + +proto.drawGraticule = function(selection, axisName, geoLayout) { + var axisLayout = geoLayout[axisName]; + + if(axisLayout.showgrid !== true) return; + + var scopeDefaults = constants.scopeDefaults[geoLayout.scope], + lonaxisRange = scopeDefaults.lonaxisRange, + lataxisRange = scopeDefaults.lataxisRange, + step = axisName === 'lonaxis' ? + [axisLayout.dtick] : + [0, axisLayout.dtick], + graticule = makeGraticule(lonaxisRange, lataxisRange, step); + + selection.append('g') + .datum(graticule) + .attr('class', axisName + 'graticule') + .append('path') + .attr('class', 'graticulepath'); +}; + +proto.drawLayout = function(geoLayout) { + var gBaseLayer = this.framework.select('g.baselayer'), + baseLayers = constants.baseLayers, + axesNames = constants.axesNames, + layerName; + + // TODO move to more d3-idiomatic pattern (that's work on replot) + // N.B. html('') does not work in IE11 + gBaseLayer.selectAll('*').remove(); + + for(var i = 0; i < baseLayers.length; i++) { + layerName = baseLayers[i]; + + if(axesNames.indexOf(layerName) !== -1) { + this.drawGraticule(gBaseLayer, layerName, geoLayout); + } + else this.drawTopo(gBaseLayer, layerName, geoLayout); + } + + this.styleLayout(geoLayout); +}; + +function styleFillLayer(selection, layerName, geoLayout) { + var layerAdj = constants.layerNameToAdjective[layerName]; + + selection.select('.' + layerName) + .selectAll('path') + .attr('stroke', 'none') + .call(Color.fill, geoLayout[layerAdj + 'color']); +} + +function styleLineLayer(selection, layerName, geoLayout) { + var layerAdj = constants.layerNameToAdjective[layerName]; + + selection.select('.' + layerName) + .selectAll('path') + .attr('fill', 'none') + .call(Color.stroke, geoLayout[layerAdj + 'color']) + .call(Drawing.dashLine, '', geoLayout[layerAdj + 'width']); +} + +function styleGraticule(selection, axisName, geoLayout) { + selection.select('.' + axisName + 'graticule') + .selectAll('path') + .attr('fill', 'none') + .call(Color.stroke, geoLayout[axisName].gridcolor) + .call(Drawing.dashLine, '', geoLayout[axisName].gridwidth); +} + +proto.styleLayer = function(selection, layerName, geoLayout) { + var fillLayers = constants.fillLayers, + lineLayers = constants.lineLayers; + + if(fillLayers.indexOf(layerName) !== -1) { + styleFillLayer(selection, layerName, geoLayout); + } + else if(lineLayers.indexOf(layerName) !== -1) { + styleLineLayer(selection, layerName, geoLayout); + } +}; + +proto.styleLayout = function(geoLayout) { + var gBaseLayer = this.framework.select('g.baselayer'), + baseLayers = constants.baseLayers, + axesNames = constants.axesNames, + layerName; + + for(var i = 0; i < baseLayers.length; i++) { + layerName = baseLayers[i]; + + if(axesNames.indexOf(layerName) !== -1) { + styleGraticule(gBaseLayer, layerName, geoLayout); + } + else this.styleLayer(gBaseLayer, layerName, geoLayout); + } +}; + +proto.isLonLatOverEdges = function(lonlat) { + var clipAngle = this.clipAngle; + + if(clipAngle === null) return false; + + var p = this.projection.rotate(), + angle = d3.geo.distance(lonlat, [-p[0], -p[1]]), + maxAngle = clipAngle * Math.PI / 180; + + return angle > maxAngle; +}; + +// [hot code path] (re)draw all paths which depend on the projection +proto.render = function() { + var _this = this, + framework = _this.framework, + gChoropleth = framework.select('g.choroplethlayer'), + gScatterGeo = framework.select('g.scattergeolayer'), + path = _this.path; + + function translatePoints(d) { + var lonlatPx = _this.projection(d.lonlat); + if(!lonlatPx) return null; + + return 'translate(' + lonlatPx[0] + ',' + lonlatPx[1] + ')'; + } + + // hide paths over edges of clipped projections + function hideShowPoints(d) { + return _this.isLonLatOverEdges(d.lonlat) ? '0' : '1.0'; + } + + framework.selectAll('path.basepath').attr('d', path); + framework.selectAll('path.graticulepath').attr('d', path); + + gChoropleth.selectAll('path.choroplethlocation').attr('d', path); + gChoropleth.selectAll('path.basepath').attr('d', path); + + gScatterGeo.selectAll('path.js-line').attr('d', path); + + if(_this.clipAngle !== null) { + gScatterGeo.selectAll('path.point') + .style('opacity', hideShowPoints) + .attr('transform', translatePoints); + gScatterGeo.selectAll('text') + .style('opacity', hideShowPoints) + .attr('transform', translatePoints); + } + else { + gScatterGeo.selectAll('path.point') + .attr('transform', translatePoints); + gScatterGeo.selectAll('text') + .attr('transform', translatePoints); + } +}; + +// create a mock axis used to format hover text +function createMockAxis(fullLayout) { + var mockAxis = { + type: 'linear', + showexponent: 'all', + exponentformat: Axes.layoutAttributes.exponentformat.dflt, + _gd: { _fullLayout: fullLayout } + }; + + Axes.setConvert(mockAxis); + return mockAxis; +} + +},{"../../components/color":27,"../../components/drawing":50,"../../constants/xmlns_namespaces":109,"../../lib/topojson_utils":135,"../../plots/cartesian/axes":150,"../../plots/cartesian/graph_interact":157,"./constants":172,"./projections":180,"./set_scale":181,"./zoom":182,"./zoom_reset":183,"d3":10,"topojson-client":17}],174:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Geo = require('./geo'); + +var Plots = require('../../plots/plots'); + + +exports.name = 'geo'; + +exports.attr = 'geo'; + +exports.idRoot = 'geo'; + +exports.idRegex = /^geo([2-9]|[1-9][0-9]+)?$/; + +exports.attrRegex = /^geo([2-9]|[1-9][0-9]+)?$/; + +exports.attributes = require('./layout/attributes'); + +exports.layoutAttributes = require('./layout/layout_attributes'); + +exports.supplyLayoutDefaults = require('./layout/defaults'); + +exports.plot = function plotGeo(gd) { + var fullLayout = gd._fullLayout, + calcData = gd.calcdata, + geoIds = Plots.getSubplotIds(fullLayout, 'geo'); + + /** + * If 'plotly-geo-assets.js' is not included, + * initialize object to keep reference to every loaded topojson + */ + if(window.PlotlyGeoAssets === undefined) { + window.PlotlyGeoAssets = { topojson: {} }; + } + + for(var i = 0; i < geoIds.length; i++) { + var geoId = geoIds[i], + geoCalcData = getSubplotCalcData(calcData, geoId), + geo = fullLayout[geoId]._subplot; + + // If geo is not instantiated, create one! + if(geo === undefined) { + geo = new Geo({ + id: geoId, + graphDiv: gd, + container: fullLayout._geocontainer.node(), + topojsonURL: gd._context.topojsonURL + }, + fullLayout + ); + + fullLayout[geoId]._subplot = geo; + } + + geo.plot(geoCalcData, fullLayout, gd._promises); + } +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldGeoKeys = Plots.getSubplotIds(oldFullLayout, 'geo'); + + for(var i = 0; i < oldGeoKeys.length; i++) { + var oldGeoKey = oldGeoKeys[i]; + var oldGeo = oldFullLayout[oldGeoKey]._subplot; + + if(!newFullLayout[oldGeoKey] && !!oldGeo) { + oldGeo.geoDiv.remove(); + } + } +}; + +exports.toSVG = function(gd) { + var fullLayout = gd._fullLayout, + geoIds = Plots.getSubplotIds(fullLayout, 'geo'), + size = fullLayout._size; + + for(var i = 0; i < geoIds.length; i++) { + var geoLayout = fullLayout[geoIds[i]], + domain = geoLayout.domain, + geoFramework = geoLayout._subplot.framework; + + geoFramework.attr('style', null); + geoFramework + .attr({ + x: size.l + size.w * domain.x[0] + geoLayout._marginX, + y: size.t + size.h * (1 - domain.y[1]) + geoLayout._marginY, + width: geoLayout._width, + height: geoLayout._height + }); + + fullLayout._geoimages.node() + .appendChild(geoFramework.node()); + } +}; + +function getSubplotCalcData(calcData, id) { + var subplotCalcData = []; + + for(var i = 0; i < calcData.length; i++) { + var calcTrace = calcData[i], + trace = calcTrace[0].trace; + + if(trace.geo === id) subplotCalcData.push(calcTrace); + } + + return subplotCalcData; +} + +},{"../../plots/plots":186,"./geo":173,"./layout/attributes":175,"./layout/defaults":178,"./layout/layout_attributes":179}],175:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + geo: { + valType: 'subplotid', + + dflt: 'geo', + + } +}; + +},{}],176:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = require('../../../components/color/attributes'); + + +module.exports = { + range: { + valType: 'info_array', + + items: [ + {valType: 'number'}, + {valType: 'number'} + ], + + }, + showgrid: { + valType: 'boolean', + + dflt: false, + + }, + tick0: { + valType: 'number', + + + }, + dtick: { + valType: 'number', + + + }, + gridcolor: { + valType: 'color', + + dflt: colorAttrs.lightLine, + + }, + gridwidth: { + valType: 'number', + + min: 0, + dflt: 1, + + } +}; + +},{"../../../components/color/attributes":26}],177:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../../lib'); +var constants = require('../constants'); +var axisAttributes = require('./axis_attributes'); + + +module.exports = function supplyGeoAxisLayoutDefaults(geoLayoutIn, geoLayoutOut) { + var axesNames = constants.axesNames; + + var axisIn, axisOut; + + function coerce(attr, dflt) { + return Lib.coerce(axisIn, axisOut, axisAttributes, attr, dflt); + } + + function getRangeDflt(axisName) { + var scope = geoLayoutOut.scope; + + var projLayout, projType, projRotation, rotateAngle, dfltSpans, halfSpan; + + if(scope === 'world') { + projLayout = geoLayoutOut.projection; + projType = projLayout.type; + projRotation = projLayout.rotation; + dfltSpans = constants[axisName + 'Span']; + + halfSpan = dfltSpans[projType] !== undefined ? + dfltSpans[projType] / 2 : + dfltSpans['*'] / 2; + rotateAngle = axisName === 'lonaxis' ? + projRotation.lon : + projRotation.lat; + + return [rotateAngle - halfSpan, rotateAngle + halfSpan]; + } + else return constants.scopeDefaults[scope][axisName + 'Range']; + } + + for(var i = 0; i < axesNames.length; i++) { + var axisName = axesNames[i]; + axisIn = geoLayoutIn[axisName] || {}; + axisOut = {}; + + var rangeDflt = getRangeDflt(axisName); + + var range = coerce('range', rangeDflt); + + Lib.noneOrAll(axisIn.range, axisOut.range, [0, 1]); + + coerce('tick0', range[0]); + coerce('dtick', axisName === 'lonaxis' ? 30 : 10); + + var show = coerce('showgrid'); + if(show) { + coerce('gridcolor'); + coerce('gridwidth'); + } + + geoLayoutOut[axisName] = axisOut; + geoLayoutOut[axisName]._fullRange = rangeDflt; + } +}; + +},{"../../../lib":122,"../constants":172,"./axis_attributes":176}],178:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var handleSubplotDefaults = require('../../subplot_defaults'); +var constants = require('../constants'); +var layoutAttributes = require('./layout_attributes'); +var supplyGeoAxisLayoutDefaults = require('./axis_defaults'); + + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { + handleSubplotDefaults(layoutIn, layoutOut, fullData, { + type: 'geo', + attributes: layoutAttributes, + handleDefaults: handleGeoDefaults, + partition: 'y' + }); +}; + +function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) { + var show; + + var scope = coerce('scope'); + var isScoped = (scope !== 'world'); + var scopeParams = constants.scopeDefaults[scope]; + + var resolution = coerce('resolution'); + + var projType = coerce('projection.type', scopeParams.projType); + var isAlbersUsa = projType === 'albers usa'; + var isConic = projType.indexOf('conic') !== -1; + + if(isConic) { + var dfltProjParallels = scopeParams.projParallels || [0, 60]; + coerce('projection.parallels', dfltProjParallels); + } + + if(!isAlbersUsa) { + var dfltProjRotate = scopeParams.projRotate || [0, 0, 0]; + coerce('projection.rotation.lon', dfltProjRotate[0]); + coerce('projection.rotation.lat', dfltProjRotate[1]); + coerce('projection.rotation.roll', dfltProjRotate[2]); + + show = coerce('showcoastlines', !isScoped); + if(show) { + coerce('coastlinecolor'); + coerce('coastlinewidth'); + } + + show = coerce('showocean'); + if(show) coerce('oceancolor'); + } + else geoLayoutOut.scope = 'usa'; + + coerce('projection.scale'); + + show = coerce('showland'); + if(show) coerce('landcolor'); + + show = coerce('showlakes'); + if(show) coerce('lakecolor'); + + show = coerce('showrivers'); + if(show) { + coerce('rivercolor'); + coerce('riverwidth'); + } + + show = coerce('showcountries', isScoped && scope !== 'usa'); + if(show) { + coerce('countrycolor'); + coerce('countrywidth'); + } + + if(scope === 'usa' || (scope === 'north america' && resolution === 50)) { + // Only works for: + // USA states at 110m + // USA states + Canada provinces at 50m + coerce('showsubunits', true); + coerce('subunitcolor'); + coerce('subunitwidth'); + } + + if(!isScoped) { + // Does not work in non-world scopes + show = coerce('showframe', true); + if(show) { + coerce('framecolor'); + coerce('framewidth'); + } + } + + coerce('bgcolor'); + + supplyGeoAxisLayoutDefaults(geoLayoutIn, geoLayoutOut); + + // bind a few helper variables + geoLayoutOut._isHighRes = resolution === 50; + geoLayoutOut._clipAngle = constants.lonaxisSpan[projType] / 2; + geoLayoutOut._isAlbersUsa = isAlbersUsa; + geoLayoutOut._isConic = isConic; + geoLayoutOut._isScoped = isScoped; + + var rotation = geoLayoutOut.projection.rotation || {}; + geoLayoutOut.projection._rotate = [ + -rotation.lon || 0, + -rotation.lat || 0, + rotation.roll || 0 + ]; +} + +},{"../../subplot_defaults":193,"../constants":172,"./axis_defaults":177,"./layout_attributes":179}],179:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = require('../../../components/color/attributes'); +var constants = require('../constants'); +var geoAxesAttrs = require('./axis_attributes'); + + +module.exports = { + domain: { + x: { + valType: 'info_array', + + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + + }, + y: { + valType: 'info_array', + + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + + } + }, + resolution: { + valType: 'enumerated', + values: [110, 50], + + dflt: 110, + coerceNumber: true, + + }, + scope: { + valType: 'enumerated', + + values: Object.keys(constants.scopeDefaults), + dflt: 'world', + + }, + projection: { + type: { + valType: 'enumerated', + + values: Object.keys(constants.projNames), + + }, + rotation: { + lon: { + valType: 'number', + + + }, + lat: { + valType: 'number', + + + }, + roll: { + valType: 'number', + + + } + }, + parallels: { + valType: 'info_array', + + items: [ + {valType: 'number'}, + {valType: 'number'} + ], + + }, + scale: { + valType: 'number', + + min: 0, + max: 10, + dflt: 1, + + } + }, + showcoastlines: { + valType: 'boolean', + + + }, + coastlinecolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + coastlinewidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showland: { + valType: 'boolean', + + dflt: false, + + }, + landcolor: { + valType: 'color', + + dflt: constants.landColor, + + }, + showocean: { + valType: 'boolean', + + dflt: false, + + }, + oceancolor: { + valType: 'color', + + dflt: constants.waterColor, + + }, + showlakes: { + valType: 'boolean', + + dflt: false, + + }, + lakecolor: { + valType: 'color', + + dflt: constants.waterColor, + + }, + showrivers: { + valType: 'boolean', + + dflt: false, + + }, + rivercolor: { + valType: 'color', + + dflt: constants.waterColor, + + }, + riverwidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showcountries: { + valType: 'boolean', + + + }, + countrycolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + countrywidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showsubunits: { + valType: 'boolean', + + + }, + subunitcolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + subunitwidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + showframe: { + valType: 'boolean', + + + }, + framecolor: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + + }, + framewidth: { + valType: 'number', + + min: 0, + dflt: 1, + + }, + bgcolor: { + valType: 'color', + + dflt: colorAttrs.background, + + }, + lonaxis: geoAxesAttrs, + lataxis: geoAxesAttrs +}; + +},{"../../../components/color/attributes":26,"../constants":172,"./axis_attributes":176}],180:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* + * Generated by https://github.com/etpinard/d3-geo-projection-picker + * + * which is hand-picks projection from https://github.com/d3/d3-geo-projection + * + * into a CommonJS require-able module. + */ + +'use strict'; + +/* eslint-disable */ + +function addProjectionsToD3(d3) { + d3.geo.project = function(object, projection) { + var stream = projection.stream; + if (!stream) throw new Error("not yet supported"); + return (object && d3_geo_projectObjectType.hasOwnProperty(object.type) ? d3_geo_projectObjectType[object.type] : d3_geo_projectGeometry)(object, stream); + }; + function d3_geo_projectFeature(object, stream) { + return { + type: "Feature", + id: object.id, + properties: object.properties, + geometry: d3_geo_projectGeometry(object.geometry, stream) + }; + } + function d3_geo_projectGeometry(geometry, stream) { + if (!geometry) return null; + if (geometry.type === "GeometryCollection") return { + type: "GeometryCollection", + geometries: object.geometries.map(function(geometry) { + return d3_geo_projectGeometry(geometry, stream); + }) + }; + if (!d3_geo_projectGeometryType.hasOwnProperty(geometry.type)) return null; + var sink = d3_geo_projectGeometryType[geometry.type]; + d3.geo.stream(geometry, stream(sink)); + return sink.result(); + } + var d3_geo_projectObjectType = { + Feature: d3_geo_projectFeature, + FeatureCollection: function(object, stream) { + return { + type: "FeatureCollection", + features: object.features.map(function(feature) { + return d3_geo_projectFeature(feature, stream); + }) + }; + } + }; + var d3_geo_projectPoints = [], d3_geo_projectLines = []; + var d3_geo_projectPoint = { + point: function(x, y) { + d3_geo_projectPoints.push([ x, y ]); + }, + result: function() { + var result = !d3_geo_projectPoints.length ? null : d3_geo_projectPoints.length < 2 ? { + type: "Point", + coordinates: d3_geo_projectPoints[0] + } : { + type: "MultiPoint", + coordinates: d3_geo_projectPoints + }; + d3_geo_projectPoints = []; + return result; + } + }; + var d3_geo_projectLine = { + lineStart: d3_geo_projectNoop, + point: function(x, y) { + d3_geo_projectPoints.push([ x, y ]); + }, + lineEnd: function() { + if (d3_geo_projectPoints.length) d3_geo_projectLines.push(d3_geo_projectPoints), + d3_geo_projectPoints = []; + }, + result: function() { + var result = !d3_geo_projectLines.length ? null : d3_geo_projectLines.length < 2 ? { + type: "LineString", + coordinates: d3_geo_projectLines[0] + } : { + type: "MultiLineString", + coordinates: d3_geo_projectLines + }; + d3_geo_projectLines = []; + return result; + } + }; + var d3_geo_projectPolygon = { + polygonStart: d3_geo_projectNoop, + lineStart: d3_geo_projectNoop, + point: function(x, y) { + d3_geo_projectPoints.push([ x, y ]); + }, + lineEnd: function() { + var n = d3_geo_projectPoints.length; + if (n) { + do d3_geo_projectPoints.push(d3_geo_projectPoints[0].slice()); while (++n < 4); + d3_geo_projectLines.push(d3_geo_projectPoints), d3_geo_projectPoints = []; + } + }, + polygonEnd: d3_geo_projectNoop, + result: function() { + if (!d3_geo_projectLines.length) return null; + var polygons = [], holes = []; + d3_geo_projectLines.forEach(function(ring) { + if (d3_geo_projectClockwise(ring)) polygons.push([ ring ]); else holes.push(ring); + }); + holes.forEach(function(hole) { + var point = hole[0]; + polygons.some(function(polygon) { + if (d3_geo_projectContains(polygon[0], point)) { + polygon.push(hole); + return true; + } + }) || polygons.push([ hole ]); + }); + d3_geo_projectLines = []; + return !polygons.length ? null : polygons.length > 1 ? { + type: "MultiPolygon", + coordinates: polygons + } : { + type: "Polygon", + coordinates: polygons[0] + }; + } + }; + var d3_geo_projectGeometryType = { + Point: d3_geo_projectPoint, + MultiPoint: d3_geo_projectPoint, + LineString: d3_geo_projectLine, + MultiLineString: d3_geo_projectLine, + Polygon: d3_geo_projectPolygon, + MultiPolygon: d3_geo_projectPolygon, + Sphere: d3_geo_projectPolygon + }; + function d3_geo_projectNoop() {} + function d3_geo_projectClockwise(ring) { + if ((n = ring.length) < 4) return false; + var i = 0, n, area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1]; + while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1]; + return area <= 0; + } + function d3_geo_projectContains(ring, point) { + var x = point[0], y = point[1], contains = false; + for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) { + var pi = ring[i], xi = pi[0], yi = pi[1], pj = ring[j], xj = pj[0], yj = pj[1]; + if (yi > y ^ yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) contains = !contains; + } + return contains; + } + var ε = 1e-6, ε2 = ε * ε, π = Math.PI, halfπ = π / 2, sqrtπ = Math.sqrt(π), radians = π / 180, degrees = 180 / π; + function sinci(x) { + return x ? x / Math.sin(x) : 1; + } + function sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + function asin(x) { + return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); + } + function acos(x) { + return x > 1 ? 0 : x < -1 ? π : Math.acos(x); + } + function asqrt(x) { + return x > 0 ? Math.sqrt(x) : 0; + } + var projection = d3.geo.projection, projectionMutator = d3.geo.projectionMutator; + d3.geo.interrupt = function(project) { + var lobes = [ [ [ [ -π, 0 ], [ 0, halfπ ], [ π, 0 ] ] ], [ [ [ -π, 0 ], [ 0, -halfπ ], [ π, 0 ] ] ] ]; + var bounds; + function forward(λ, φ) { + var sign = φ < 0 ? -1 : +1, hemilobes = lobes[+(φ < 0)]; + for (var i = 0, n = hemilobes.length - 1; i < n && λ > hemilobes[i][2][0]; ++i) ; + var coordinates = project(λ - hemilobes[i][1][0], φ); + coordinates[0] += project(hemilobes[i][1][0], sign * φ > sign * hemilobes[i][0][1] ? hemilobes[i][0][1] : φ)[0]; + return coordinates; + } + function reset() { + bounds = lobes.map(function(hemilobes) { + return hemilobes.map(function(lobe) { + var x0 = project(lobe[0][0], lobe[0][1])[0], x1 = project(lobe[2][0], lobe[2][1])[0], y0 = project(lobe[1][0], lobe[0][1])[1], y1 = project(lobe[1][0], lobe[1][1])[1], t; + if (y0 > y1) t = y0, y0 = y1, y1 = t; + return [ [ x0, y0 ], [ x1, y1 ] ]; + }); + }); + } + if (project.invert) forward.invert = function(x, y) { + var hemibounds = bounds[+(y < 0)], hemilobes = lobes[+(y < 0)]; + for (var i = 0, n = hemibounds.length; i < n; ++i) { + var b = hemibounds[i]; + if (b[0][0] <= x && x < b[1][0] && b[0][1] <= y && y < b[1][1]) { + var coordinates = project.invert(x - project(hemilobes[i][1][0], 0)[0], y); + coordinates[0] += hemilobes[i][1][0]; + return pointEqual(forward(coordinates[0], coordinates[1]), [ x, y ]) ? coordinates : null; + } + } + }; + var projection = d3.geo.projection(forward), stream_ = projection.stream; + projection.stream = function(stream) { + var rotate = projection.rotate(), rotateStream = stream_(stream), sphereStream = (projection.rotate([ 0, 0 ]), + stream_(stream)); + projection.rotate(rotate); + rotateStream.sphere = function() { + d3.geo.stream(sphere(), sphereStream); + }; + return rotateStream; + }; + projection.lobes = function(_) { + if (!arguments.length) return lobes.map(function(lobes) { + return lobes.map(function(lobe) { + return [ [ lobe[0][0] * 180 / π, lobe[0][1] * 180 / π ], [ lobe[1][0] * 180 / π, lobe[1][1] * 180 / π ], [ lobe[2][0] * 180 / π, lobe[2][1] * 180 / π ] ]; + }); + }); + lobes = _.map(function(lobes) { + return lobes.map(function(lobe) { + return [ [ lobe[0][0] * π / 180, lobe[0][1] * π / 180 ], [ lobe[1][0] * π / 180, lobe[1][1] * π / 180 ], [ lobe[2][0] * π / 180, lobe[2][1] * π / 180 ] ]; + }); + }); + reset(); + return projection; + }; + function sphere() { + var ε = 1e-6, coordinates = []; + for (var i = 0, n = lobes[0].length; i < n; ++i) { + var lobe = lobes[0][i], λ0 = lobe[0][0] * 180 / π, φ0 = lobe[0][1] * 180 / π, φ1 = lobe[1][1] * 180 / π, λ2 = lobe[2][0] * 180 / π, φ2 = lobe[2][1] * 180 / π; + coordinates.push(resample([ [ λ0 + ε, φ0 + ε ], [ λ0 + ε, φ1 - ε ], [ λ2 - ε, φ1 - ε ], [ λ2 - ε, φ2 + ε ] ], 30)); + } + for (var i = lobes[1].length - 1; i >= 0; --i) { + var lobe = lobes[1][i], λ0 = lobe[0][0] * 180 / π, φ0 = lobe[0][1] * 180 / π, φ1 = lobe[1][1] * 180 / π, λ2 = lobe[2][0] * 180 / π, φ2 = lobe[2][1] * 180 / π; + coordinates.push(resample([ [ λ2 - ε, φ2 - ε ], [ λ2 - ε, φ1 + ε ], [ λ0 + ε, φ1 + ε ], [ λ0 + ε, φ0 - ε ] ], 30)); + } + return { + type: "Polygon", + coordinates: [ d3.merge(coordinates) ] + }; + } + function resample(coordinates, m) { + var i = -1, n = coordinates.length, p0 = coordinates[0], p1, dx, dy, resampled = []; + while (++i < n) { + p1 = coordinates[i]; + dx = (p1[0] - p0[0]) / m; + dy = (p1[1] - p0[1]) / m; + for (var j = 0; j < m; ++j) resampled.push([ p0[0] + j * dx, p0[1] + j * dy ]); + p0 = p1; + } + resampled.push(p1); + return resampled; + } + function pointEqual(a, b) { + return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; + } + return projection; + }; + function eckert4(λ, φ) { + var k = (2 + halfπ) * Math.sin(φ); + φ /= 2; + for (var i = 0, δ = Infinity; i < 10 && Math.abs(δ) > ε; i++) { + var cosφ = Math.cos(φ); + φ -= δ = (φ + Math.sin(φ) * (cosφ + 2) - k) / (2 * cosφ * (1 + cosφ)); + } + return [ 2 / Math.sqrt(π * (4 + π)) * λ * (1 + Math.cos(φ)), 2 * Math.sqrt(π / (4 + π)) * Math.sin(φ) ]; + } + eckert4.invert = function(x, y) { + var A = .5 * y * Math.sqrt((4 + π) / π), k = asin(A), c = Math.cos(k); + return [ x / (2 / Math.sqrt(π * (4 + π)) * (1 + c)), asin((k + A * (c + 2)) / (2 + halfπ)) ]; + }; + (d3.geo.eckert4 = function() { + return projection(eckert4); + }).raw = eckert4; + var hammerAzimuthalEqualArea = d3.geo.azimuthalEqualArea.raw; + function hammer(A, B) { + if (arguments.length < 2) B = A; + if (B === 1) return hammerAzimuthalEqualArea; + if (B === Infinity) return hammerQuarticAuthalic; + function forward(λ, φ) { + var coordinates = hammerAzimuthalEqualArea(λ / B, φ); + coordinates[0] *= A; + return coordinates; + } + forward.invert = function(x, y) { + var coordinates = hammerAzimuthalEqualArea.invert(x / A, y); + coordinates[0] *= B; + return coordinates; + }; + return forward; + } + function hammerProjection() { + var B = 2, m = projectionMutator(hammer), p = m(B); + p.coefficient = function(_) { + if (!arguments.length) return B; + return m(B = +_); + }; + return p; + } + function hammerQuarticAuthalic(λ, φ) { + return [ λ * Math.cos(φ) / Math.cos(φ /= 2), 2 * Math.sin(φ) ]; + } + hammerQuarticAuthalic.invert = function(x, y) { + var φ = 2 * asin(y / 2); + return [ x * Math.cos(φ / 2) / Math.cos(φ), φ ]; + }; + (d3.geo.hammer = hammerProjection).raw = hammer; + function kavrayskiy7(λ, φ) { + return [ 3 * λ / (2 * π) * Math.sqrt(π * π / 3 - φ * φ), φ ]; + } + kavrayskiy7.invert = function(x, y) { + return [ 2 / 3 * π * x / Math.sqrt(π * π / 3 - y * y), y ]; + }; + (d3.geo.kavrayskiy7 = function() { + return projection(kavrayskiy7); + }).raw = kavrayskiy7; + function miller(λ, φ) { + return [ λ, 1.25 * Math.log(Math.tan(π / 4 + .4 * φ)) ]; + } + miller.invert = function(x, y) { + return [ x, 2.5 * Math.atan(Math.exp(.8 * y)) - .625 * π ]; + }; + (d3.geo.miller = function() { + return projection(miller); + }).raw = miller; + function mollweideBromleyθ(Cp) { + return function(θ) { + var Cpsinθ = Cp * Math.sin(θ), i = 30, δ; + do θ -= δ = (θ + Math.sin(θ) - Cpsinθ) / (1 + Math.cos(θ)); while (Math.abs(δ) > ε && --i > 0); + return θ / 2; + }; + } + function mollweideBromley(Cx, Cy, Cp) { + var θ = mollweideBromleyθ(Cp); + function forward(λ, φ) { + return [ Cx * λ * Math.cos(φ = θ(φ)), Cy * Math.sin(φ) ]; + } + forward.invert = function(x, y) { + var θ = asin(y / Cy); + return [ x / (Cx * Math.cos(θ)), asin((2 * θ + Math.sin(2 * θ)) / Cp) ]; + }; + return forward; + } + var mollweideθ = mollweideBromleyθ(π), mollweide = mollweideBromley(Math.SQRT2 / halfπ, Math.SQRT2, π); + (d3.geo.mollweide = function() { + return projection(mollweide); + }).raw = mollweide; + function naturalEarth(λ, φ) { + var φ2 = φ * φ, φ4 = φ2 * φ2; + return [ λ * (.8707 - .131979 * φ2 + φ4 * (-.013791 + φ4 * (.003971 * φ2 - .001529 * φ4))), φ * (1.007226 + φ2 * (.015085 + φ4 * (-.044475 + .028874 * φ2 - .005916 * φ4))) ]; + } + naturalEarth.invert = function(x, y) { + var φ = y, i = 25, δ; + do { + var φ2 = φ * φ, φ4 = φ2 * φ2; + φ -= δ = (φ * (1.007226 + φ2 * (.015085 + φ4 * (-.044475 + .028874 * φ2 - .005916 * φ4))) - y) / (1.007226 + φ2 * (.015085 * 3 + φ4 * (-.044475 * 7 + .028874 * 9 * φ2 - .005916 * 11 * φ4))); + } while (Math.abs(δ) > ε && --i > 0); + return [ x / (.8707 + (φ2 = φ * φ) * (-.131979 + φ2 * (-.013791 + φ2 * φ2 * φ2 * (.003971 - .001529 * φ2)))), φ ]; + }; + (d3.geo.naturalEarth = function() { + return projection(naturalEarth); + }).raw = naturalEarth; + var robinsonConstants = [ [ .9986, -.062 ], [ 1, 0 ], [ .9986, .062 ], [ .9954, .124 ], [ .99, .186 ], [ .9822, .248 ], [ .973, .31 ], [ .96, .372 ], [ .9427, .434 ], [ .9216, .4958 ], [ .8962, .5571 ], [ .8679, .6176 ], [ .835, .6769 ], [ .7986, .7346 ], [ .7597, .7903 ], [ .7186, .8435 ], [ .6732, .8936 ], [ .6213, .9394 ], [ .5722, .9761 ], [ .5322, 1 ] ]; + robinsonConstants.forEach(function(d) { + d[1] *= 1.0144; + }); + function robinson(λ, φ) { + var i = Math.min(18, Math.abs(φ) * 36 / π), i0 = Math.floor(i), di = i - i0, ax = (k = robinsonConstants[i0])[0], ay = k[1], bx = (k = robinsonConstants[++i0])[0], by = k[1], cx = (k = robinsonConstants[Math.min(19, ++i0)])[0], cy = k[1], k; + return [ λ * (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2), (φ > 0 ? halfπ : -halfπ) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) ]; + } + robinson.invert = function(x, y) { + var yy = y / halfπ, φ = yy * 90, i = Math.min(18, Math.abs(φ / 5)), i0 = Math.max(0, Math.floor(i)); + do { + var ay = robinsonConstants[i0][1], by = robinsonConstants[i0 + 1][1], cy = robinsonConstants[Math.min(19, i0 + 2)][1], u = cy - ay, v = cy - 2 * by + ay, t = 2 * (Math.abs(yy) - by) / u, c = v / u, di = t * (1 - c * t * (1 - 2 * c * t)); + if (di >= 0 || i0 === 1) { + φ = (y >= 0 ? 5 : -5) * (di + i); + var j = 50, δ; + do { + i = Math.min(18, Math.abs(φ) / 5); + i0 = Math.floor(i); + di = i - i0; + ay = robinsonConstants[i0][1]; + by = robinsonConstants[i0 + 1][1]; + cy = robinsonConstants[Math.min(19, i0 + 2)][1]; + φ -= (δ = (y >= 0 ? halfπ : -halfπ) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) - y) * degrees; + } while (Math.abs(δ) > ε2 && --j > 0); + break; + } + } while (--i0 >= 0); + var ax = robinsonConstants[i0][0], bx = robinsonConstants[i0 + 1][0], cx = robinsonConstants[Math.min(19, i0 + 2)][0]; + return [ x / (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2), φ * radians ]; + }; + (d3.geo.robinson = function() { + return projection(robinson); + }).raw = robinson; + function sinusoidal(λ, φ) { + return [ λ * Math.cos(φ), φ ]; + } + sinusoidal.invert = function(x, y) { + return [ x / Math.cos(y), y ]; + }; + (d3.geo.sinusoidal = function() { + return projection(sinusoidal); + }).raw = sinusoidal; + function aitoff(λ, φ) { + var cosφ = Math.cos(φ), sinciα = sinci(acos(cosφ * Math.cos(λ /= 2))); + return [ 2 * cosφ * Math.sin(λ) * sinciα, Math.sin(φ) * sinciα ]; + } + aitoff.invert = function(x, y) { + if (x * x + 4 * y * y > π * π + ε) return; + var λ = x, φ = y, i = 25; + do { + var sinλ = Math.sin(λ), sinλ_2 = Math.sin(λ / 2), cosλ_2 = Math.cos(λ / 2), sinφ = Math.sin(φ), cosφ = Math.cos(φ), sin_2φ = Math.sin(2 * φ), sin2φ = sinφ * sinφ, cos2φ = cosφ * cosφ, sin2λ_2 = sinλ_2 * sinλ_2, C = 1 - cos2φ * cosλ_2 * cosλ_2, E = C ? acos(cosφ * cosλ_2) * Math.sqrt(F = 1 / C) : F = 0, F, fx = 2 * E * cosφ * sinλ_2 - x, fy = E * sinφ - y, δxδλ = F * (cos2φ * sin2λ_2 + E * cosφ * cosλ_2 * sin2φ), δxδφ = F * (.5 * sinλ * sin_2φ - E * 2 * sinφ * sinλ_2), δyδλ = F * .25 * (sin_2φ * sinλ_2 - E * sinφ * cos2φ * sinλ), δyδφ = F * (sin2φ * cosλ_2 + E * sin2λ_2 * cosφ), denominator = δxδφ * δyδλ - δyδφ * δxδλ; + if (!denominator) break; + var δλ = (fy * δxδφ - fx * δyδφ) / denominator, δφ = (fx * δyδλ - fy * δxδλ) / denominator; + λ -= δλ, φ -= δφ; + } while ((Math.abs(δλ) > ε || Math.abs(δφ) > ε) && --i > 0); + return [ λ, φ ]; + }; + (d3.geo.aitoff = function() { + return projection(aitoff); + }).raw = aitoff; + function winkel3(λ, φ) { + var coordinates = aitoff(λ, φ); + return [ (coordinates[0] + λ / halfπ) / 2, (coordinates[1] + φ) / 2 ]; + } + winkel3.invert = function(x, y) { + var λ = x, φ = y, i = 25; + do { + var cosφ = Math.cos(φ), sinφ = Math.sin(φ), sin_2φ = Math.sin(2 * φ), sin2φ = sinφ * sinφ, cos2φ = cosφ * cosφ, sinλ = Math.sin(λ), cosλ_2 = Math.cos(λ / 2), sinλ_2 = Math.sin(λ / 2), sin2λ_2 = sinλ_2 * sinλ_2, C = 1 - cos2φ * cosλ_2 * cosλ_2, E = C ? acos(cosφ * cosλ_2) * Math.sqrt(F = 1 / C) : F = 0, F, fx = .5 * (2 * E * cosφ * sinλ_2 + λ / halfπ) - x, fy = .5 * (E * sinφ + φ) - y, δxδλ = .5 * F * (cos2φ * sin2λ_2 + E * cosφ * cosλ_2 * sin2φ) + .5 / halfπ, δxδφ = F * (sinλ * sin_2φ / 4 - E * sinφ * sinλ_2), δyδλ = .125 * F * (sin_2φ * sinλ_2 - E * sinφ * cos2φ * sinλ), δyδφ = .5 * F * (sin2φ * cosλ_2 + E * sin2λ_2 * cosφ) + .5, denominator = δxδφ * δyδλ - δyδφ * δxδλ, δλ = (fy * δxδφ - fx * δyδφ) / denominator, δφ = (fx * δyδλ - fy * δxδλ) / denominator; + λ -= δλ, φ -= δφ; + } while ((Math.abs(δλ) > ε || Math.abs(δφ) > ε) && --i > 0); + return [ λ, φ ]; + }; + (d3.geo.winkel3 = function() { + return projection(winkel3); + }).raw = winkel3; +} + +module.exports = addProjectionsToD3; + +},{}],181:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var clipPad = require('./constants').clipPad; + +function createGeoScale(geoLayout, graphSize) { + var projLayout = geoLayout.projection, + lonaxisLayout = geoLayout.lonaxis, + lataxisLayout = geoLayout.lataxis, + geoDomain = geoLayout.domain, + frameWidth = geoLayout.framewidth || 0; + + // width & height the geo div + var geoWidth = graphSize.w * (geoDomain.x[1] - geoDomain.x[0]), + geoHeight = graphSize.h * (geoDomain.y[1] - geoDomain.y[0]); + + // add padding around range to avoid aliasing + var lon0 = lonaxisLayout.range[0] + clipPad, + lon1 = lonaxisLayout.range[1] - clipPad, + lat0 = lataxisLayout.range[0] + clipPad, + lat1 = lataxisLayout.range[1] - clipPad, + lonfull0 = lonaxisLayout._fullRange[0] + clipPad, + lonfull1 = lonaxisLayout._fullRange[1] - clipPad, + latfull0 = lataxisLayout._fullRange[0] + clipPad, + latfull1 = lataxisLayout._fullRange[1] - clipPad; + + // initial translation (makes the math easier) + projLayout._translate0 = [ + graphSize.l + geoWidth / 2, graphSize.t + geoHeight / 2 + ]; + + + // center of the projection is given by + // the lon/lat ranges and the rotate angle + var dlon = lon1 - lon0, + dlat = lat1 - lat0, + c0 = [lon0 + dlon / 2, lat0 + dlat / 2], + r = projLayout._rotate; + + projLayout._center = [c0[0] + r[0], c0[1] + r[1]]; + + // needs a initial projection; it is called from makeProjection + var setScale = function(projection) { + var scale0 = projection.scale(), + translate0 = projLayout._translate0, + rangeBox = makeRangeBox(lon0, lat0, lon1, lat1), + fullRangeBox = makeRangeBox(lonfull0, latfull0, lonfull1, latfull1); + + var scale, translate, bounds, fullBounds; + + // Inspired by: http://stackoverflow.com/a/14654988/4068492 + // using the path determine the bounds of the current map and use + // these to determine better values for the scale and translation + + function getScale(bounds) { + return Math.min( + scale0 * geoWidth / (bounds[1][0] - bounds[0][0]), + scale0 * geoHeight / (bounds[1][1] - bounds[0][1]) + ); + } + + // scale projection given how range box get deformed + // by the projection + bounds = getBounds(projection, rangeBox); + scale = getScale(bounds); + + // similarly, get scale at full range + fullBounds = getBounds(projection, fullRangeBox); + projLayout._fullScale = getScale(fullBounds); + + projection.scale(scale); + + // translate the projection so that the top-left corner + // of the range box is at the top-left corner of the viewbox + bounds = getBounds(projection, rangeBox); + translate = [ + translate0[0] - bounds[0][0] + frameWidth, + translate0[1] - bounds[0][1] + frameWidth + ]; + projLayout._translate = translate; + projection.translate(translate); + + // clip regions out of the range box + // (these are clipping along horizontal/vertical lines) + bounds = getBounds(projection, rangeBox); + if(!geoLayout._isAlbersUsa) projection.clipExtent(bounds); + + // adjust scale one more time with the 'scale' attribute + scale = projLayout.scale * scale; + + // set projection scale and save it + projLayout._scale = scale; + + // save the effective width & height of the geo framework + geoLayout._width = Math.round(bounds[1][0]) + frameWidth; + geoLayout._height = Math.round(bounds[1][1]) + frameWidth; + + // save the margin length induced by the map scaling + geoLayout._marginX = (geoWidth - Math.round(bounds[1][0])) / 2; + geoLayout._marginY = (geoHeight - Math.round(bounds[1][1])) / 2; + }; + + return setScale; +} + +module.exports = createGeoScale; + +// polygon GeoJSON corresponding to lon/lat range box +// with well-defined direction +function makeRangeBox(lon0, lat0, lon1, lat1) { + var dlon4 = (lon1 - lon0) / 4; + + // TODO is this enough to handle ALL cases? + // -- this makes scaling less precise than using d3.geo.graticule + // as great circles can overshoot the boundary + // (that's not a big deal I think) + return { + type: 'Polygon', + coordinates: [ + [ [lon0, lat0], + [lon0, lat1], + [lon0 + dlon4, lat1], + [lon0 + 2 * dlon4, lat1], + [lon0 + 3 * dlon4, lat1], + [lon1, lat1], + [lon1, lat0], + [lon1 - dlon4, lat0], + [lon1 - 2 * dlon4, lat0], + [lon1 - 3 * dlon4, lat0], + [lon0, lat0] ] + ] + }; +} + +// bounds array [[top, left], [bottom, right]] +// of the lon/lat range box +function getBounds(projection, rangeBox) { + return d3.geo.path().projection(projection).bounds(rangeBox); +} + +},{"./constants":172,"d3":10}],182:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var radians = Math.PI / 180, + degrees = 180 / Math.PI, + zoomstartStyle = { cursor: 'pointer' }, + zoomendStyle = { cursor: 'auto' }; + + +function createGeoZoom(geo, geoLayout) { + var zoomConstructor; + + if(geoLayout._isScoped) zoomConstructor = zoomScoped; + else if(geoLayout._clipAngle) zoomConstructor = zoomClipped; + else zoomConstructor = zoomNonClipped; + + // TODO add a conic-specific zoom + + return zoomConstructor(geo, geoLayout.projection); +} + +module.exports = createGeoZoom; + +// common to all zoom types +function initZoom(projection, projLayout) { + var fullScale = projLayout._fullScale; + + return d3.behavior.zoom() + .translate(projection.translate()) + .scale(projection.scale()) + .scaleExtent([0.5 * fullScale, 100 * fullScale]); +} + +// zoom for scoped projections +function zoomScoped(geo, projLayout) { + var projection = geo.projection, + zoom = initZoom(projection, projLayout); + + function handleZoomstart() { + d3.select(this).style(zoomstartStyle); + } + + function handleZoom() { + projection + .scale(d3.event.scale) + .translate(d3.event.translate); + + geo.render(); + } + + function handleZoomend() { + d3.select(this).style(zoomendStyle); + } + + zoom + .on('zoomstart', handleZoomstart) + .on('zoom', handleZoom) + .on('zoomend', handleZoomend); + + return zoom; +} + +// zoom for non-clipped projections +function zoomNonClipped(geo, projLayout) { + var projection = geo.projection, + zoom = initZoom(projection, projLayout); + + var INSIDETOLORANCEPXS = 2; + + var mouse0, rotate0, translate0, lastRotate, zoomPoint, + mouse1, rotate1, point1; + + function position(x) { return projection.invert(x); } + + function outside(x) { + var pt = projection(position(x)); + return (Math.abs(pt[0] - x[0]) > INSIDETOLORANCEPXS || + Math.abs(pt[1] - x[1]) > INSIDETOLORANCEPXS); + } + + function handleZoomstart() { + d3.select(this).style(zoomstartStyle); + + mouse0 = d3.mouse(this); + rotate0 = projection.rotate(); + translate0 = projection.translate(); + lastRotate = rotate0; + zoomPoint = position(mouse0); + } + + function handleZoom() { + mouse1 = d3.mouse(this); + + if(outside(mouse0)) { + zoom.scale(projection.scale()); + zoom.translate(projection.translate()); + return; + } + + projection.scale(d3.event.scale); + + projection.translate([translate0[0], d3.event.translate[1]]); + + if(!zoomPoint) { + mouse0 = mouse1; + zoomPoint = position(mouse0); + } + else if(position(mouse1)) { + point1 = position(mouse1); + rotate1 = [lastRotate[0] + (point1[0] - zoomPoint[0]), rotate0[1], rotate0[2]]; + projection.rotate(rotate1); + lastRotate = rotate1; + } + + geo.render(); + } + + function handleZoomend() { + d3.select(this).style(zoomendStyle); + + // or something like + // http://www.jasondavies.com/maps/gilbert/ + // ... a little harder with multiple base layers + } + + zoom + .on('zoomstart', handleZoomstart) + .on('zoom', handleZoom) + .on('zoomend', handleZoomend); + + return zoom; +} + +// zoom for clipped projections +// inspired by https://www.jasondavies.com/maps/d3.geo.zoom.js +function zoomClipped(geo, projLayout) { + var projection = geo.projection, + view = {r: projection.rotate(), k: projection.scale()}, + zoom = initZoom(projection, projLayout), + event = d3_eventDispatch(zoom, 'zoomstart', 'zoom', 'zoomend'), + zooming = 0, + zoomOn = zoom.on; + + var zoomPoint; + + zoom.on('zoomstart', function() { + d3.select(this).style(zoomstartStyle); + + var mouse0 = d3.mouse(this), + rotate0 = projection.rotate(), + lastRotate = rotate0, + translate0 = projection.translate(), + q = quaternionFromEuler(rotate0); + + zoomPoint = position(projection, mouse0); + + zoomOn.call(zoom, 'zoom', function() { + var mouse1 = d3.mouse(this); + + projection.scale(view.k = d3.event.scale); + + if(!zoomPoint) { + // if no zoomPoint, the mouse wasn't over the actual geography yet + // maybe this point is the start... we'll find out next time! + mouse0 = mouse1; + zoomPoint = position(projection, mouse0); + } + // check if the point is on the map + // if not, don't do anything new but scale + // if it is, then we can assume between will exist below + // so we don't need the 'bank' function, whatever that is. + // TODO: is this right? + else if(position(projection, mouse1)) { + // go back to original projection temporarily + // except for scale... that's kind of independent? + projection + .rotate(rotate0) + .translate(translate0); + + // calculate the new params + var point1 = position(projection, mouse1), + between = rotateBetween(zoomPoint, point1), + newEuler = eulerFromQuaternion(multiply(q, between)), + rotateAngles = view.r = unRoll(newEuler, zoomPoint, lastRotate); + + if(!isFinite(rotateAngles[0]) || !isFinite(rotateAngles[1]) || + !isFinite(rotateAngles[2])) { + rotateAngles = lastRotate; + } + + // update the projection + projection.rotate(rotateAngles); + lastRotate = rotateAngles; + } + + zoomed(event.of(this, arguments)); + }); + + zoomstarted(event.of(this, arguments)); + }) + .on('zoomend', function() { + d3.select(this).style(zoomendStyle); + zoomOn.call(zoom, 'zoom', null); + zoomended(event.of(this, arguments)); + }) + .on('zoom.redraw', function() { + geo.render(); + }); + + function zoomstarted(dispatch) { + if(!zooming++) dispatch({type: 'zoomstart'}); + } + + function zoomed(dispatch) { + dispatch({type: 'zoom'}); + } + + function zoomended(dispatch) { + if(!--zooming) dispatch({type: 'zoomend'}); + } + + return d3.rebind(zoom, event, 'on'); +} + +// -- helper functions for zoomClipped + +function position(projection, point) { + var spherical = projection.invert(point); + return spherical && isFinite(spherical[0]) && isFinite(spherical[1]) && cartesian(spherical); +} + +function quaternionFromEuler(euler) { + var lambda = 0.5 * euler[0] * radians, + phi = 0.5 * euler[1] * radians, + gamma = 0.5 * euler[2] * radians, + sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda), + sinPhi = Math.sin(phi), cosPhi = Math.cos(phi), + sinGamma = Math.sin(gamma), cosGamma = Math.cos(gamma); + return [ + cosLambda * cosPhi * cosGamma + sinLambda * sinPhi * sinGamma, + sinLambda * cosPhi * cosGamma - cosLambda * sinPhi * sinGamma, + cosLambda * sinPhi * cosGamma + sinLambda * cosPhi * sinGamma, + cosLambda * cosPhi * sinGamma - sinLambda * sinPhi * cosGamma + ]; +} + +function multiply(a, b) { + var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], + b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + return [ + a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3, + a0 * b1 + a1 * b0 + a2 * b3 - a3 * b2, + a0 * b2 - a1 * b3 + a2 * b0 + a3 * b1, + a0 * b3 + a1 * b2 - a2 * b1 + a3 * b0 + ]; +} + +function rotateBetween(a, b) { + if(!a || !b) return; + var axis = cross(a, b), + norm = Math.sqrt(dot(axis, axis)), + halfgamma = 0.5 * Math.acos(Math.max(-1, Math.min(1, dot(a, b)))), + k = Math.sin(halfgamma) / norm; + return norm && [Math.cos(halfgamma), axis[2] * k, -axis[1] * k, axis[0] * k]; +} + +// input: +// rotateAngles: a calculated set of Euler angles +// pt: a point (cartesian in 3-space) to keep fixed +// roll0: an initial roll, to be preserved +// output: +// a set of Euler angles that preserve the projection of pt +// but set roll (output[2]) equal to roll0 +// note that this doesn't depend on the particular projection, +// just on the rotation angles +function unRoll(rotateAngles, pt, lastRotate) { + // calculate the fixed point transformed by these Euler angles + // but with the desired roll undone + var ptRotated = rotateCartesian(pt, 2, rotateAngles[0]); + ptRotated = rotateCartesian(ptRotated, 1, rotateAngles[1]); + ptRotated = rotateCartesian(ptRotated, 0, rotateAngles[2] - lastRotate[2]); + + var x = pt[0], + y = pt[1], + z = pt[2], + f = ptRotated[0], + g = ptRotated[1], + h = ptRotated[2], + + // the following essentially solves: + // ptRotated = rotateCartesian(rotateCartesian(pt, 2, newYaw), 1, newPitch) + // for newYaw and newPitch, as best it can + theta = Math.atan2(y, x) * degrees, + a = Math.sqrt(x * x + y * y), + b, + newYaw1; + + if(Math.abs(g) > a) { + newYaw1 = (g > 0 ? 90 : -90) - theta; + b = 0; + } else { + newYaw1 = Math.asin(g / a) * degrees - theta; + b = Math.sqrt(a * a - g * g); + } + + var newYaw2 = 180 - newYaw1 - 2 * theta, + newPitch1 = (Math.atan2(h, f) - Math.atan2(z, b)) * degrees, + newPitch2 = (Math.atan2(h, f) - Math.atan2(z, -b)) * degrees; + + // which is closest to lastRotate[0,1]: newYaw/Pitch or newYaw2/Pitch2? + var dist1 = angleDistance(lastRotate[0], lastRotate[1], newYaw1, newPitch1), + dist2 = angleDistance(lastRotate[0], lastRotate[1], newYaw2, newPitch2); + + if(dist1 <= dist2) return [newYaw1, newPitch1, lastRotate[2]]; + else return [newYaw2, newPitch2, lastRotate[2]]; +} + +function angleDistance(yaw0, pitch0, yaw1, pitch1) { + var dYaw = angleMod(yaw1 - yaw0), + dPitch = angleMod(pitch1 - pitch0); + return Math.sqrt(dYaw * dYaw + dPitch * dPitch); +} + +// reduce an angle in degrees to [-180,180] +function angleMod(angle) { + return (angle % 360 + 540) % 360 - 180; +} + +// rotate a cartesian vector +// axis is 0 (x), 1 (y), or 2 (z) +// angle is in degrees +function rotateCartesian(vector, axis, angle) { + var angleRads = angle * radians, + vectorOut = vector.slice(), + ax1 = (axis === 0) ? 1 : 0, + ax2 = (axis === 2) ? 1 : 2, + cosa = Math.cos(angleRads), + sina = Math.sin(angleRads); + + vectorOut[ax1] = vector[ax1] * cosa - vector[ax2] * sina; + vectorOut[ax2] = vector[ax2] * cosa + vector[ax1] * sina; + + return vectorOut; +} +function eulerFromQuaternion(q) { + return [ + Math.atan2(2 * (q[0] * q[1] + q[2] * q[3]), 1 - 2 * (q[1] * q[1] + q[2] * q[2])) * degrees, + Math.asin(Math.max(-1, Math.min(1, 2 * (q[0] * q[2] - q[3] * q[1])))) * degrees, + Math.atan2(2 * (q[0] * q[3] + q[1] * q[2]), 1 - 2 * (q[2] * q[2] + q[3] * q[3])) * degrees + ]; +} + +function cartesian(spherical) { + var lambda = spherical[0] * radians, + phi = spherical[1] * radians, + cosPhi = Math.cos(phi); + return [ + cosPhi * Math.cos(lambda), + cosPhi * Math.sin(lambda), + Math.sin(phi) + ]; +} + +function dot(a, b) { + var s = 0; + for(var i = 0, n = a.length; i < n; ++i) s += a[i] * b[i]; + return s; +} + +function cross(a, b) { + return [ + a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0] + ]; +} + +// Like d3.dispatch, but for custom events abstracting native UI events. These +// events have a target component (such as a brush), a target element (such as +// the svg:g element containing the brush) and the standard arguments `d` (the +// target element's data) and `i` (the selection index of the target element). +function d3_eventDispatch(target) { + var i = 0, + n = arguments.length, + argumentz = []; + + while(++i < n) argumentz.push(arguments[i]); + + var dispatch = d3.dispatch.apply(null, argumentz); + + // Creates a dispatch context for the specified `thiz` (typically, the target + // DOM element that received the source event) and `argumentz` (typically, the + // data `d` and index `i` of the target element). The returned function can be + // used to dispatch an event to any registered listeners; the function takes a + // single argument as input, being the event to dispatch. The event must have + // a "type" attribute which corresponds to a type registered in the + // constructor. This context will automatically populate the "sourceEvent" and + // "target" attributes of the event, as well as setting the `d3.event` global + // for the duration of the notification. + dispatch.of = function(thiz, argumentz) { + return function(e1) { + var e0; + try { + e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; + } + }; + }; + + return dispatch; +} + +},{"d3":10}],183:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = require('../cartesian/graph_interact'); + +function createGeoZoomReset(geo, geoLayout) { + var projection = geo.projection, + zoom = geo.zoom; + + var zoomReset = function() { + geo.makeProjection(geoLayout); + geo.makePath(); + + zoom.scale(projection.scale()); + zoom.translate(projection.translate()); + + Fx.loneUnhover(geo.hoverContainer); + + geo.render(); + }; + + return zoomReset; +} + +module.exports = createGeoZoomReset; + +},{"../cartesian/graph_interact":157}],184:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../lib'); +var extendFlat = Lib.extendFlat; + +var fontAttrs = require('./font_attributes'); +var colorAttrs = require('../components/color/attributes'); + +module.exports = { + font: { + family: extendFlat({}, fontAttrs.family, { + dflt: '"Open Sans", verdana, arial, sans-serif' + }), + size: extendFlat({}, fontAttrs.size, { + dflt: 12 + }), + color: extendFlat({}, fontAttrs.color, { + dflt: colorAttrs.defaultLine + }), + + }, + title: { + valType: 'string', + + dflt: 'Click to enter Plot title', + + }, + titlefont: extendFlat({}, fontAttrs, { + + }), + autosize: { + valType: 'boolean', + + dflt: false, + + }, + width: { + valType: 'number', + + min: 10, + dflt: 700, + + }, + height: { + valType: 'number', + + min: 10, + dflt: 450, + + }, + margin: { + l: { + valType: 'number', + + min: 0, + dflt: 80, + + }, + r: { + valType: 'number', + + min: 0, + dflt: 80, + + }, + t: { + valType: 'number', + + min: 0, + dflt: 100, + + }, + b: { + valType: 'number', + + min: 0, + dflt: 80, + + }, + pad: { + valType: 'number', + + min: 0, + dflt: 0, + + }, + autoexpand: { + valType: 'boolean', + + dflt: true + } + }, + paper_bgcolor: { + valType: 'color', + + dflt: colorAttrs.background, + + }, + plot_bgcolor: { + // defined here, but set in Axes.supplyLayoutDefaults + // because it needs to know if there are (2D) axes or not + valType: 'color', + + dflt: colorAttrs.background, + + }, + separators: { + valType: 'string', + + dflt: '.,', + + }, + hidesources: { + valType: 'boolean', + + dflt: false, + + }, + smith: { + // will become a boolean if/when we implement this + valType: 'enumerated', + + values: [false], + dflt: false + }, + showlegend: { + // handled in legend.supplyLayoutDefaults + // but included here because it's not in the legend object + valType: 'boolean', + + + }, + + dragmode: { + valType: 'enumerated', + + values: ['zoom', 'pan', 'select', 'lasso', 'orbit', 'turntable'], + dflt: 'zoom', + + }, + hovermode: { + valType: 'enumerated', + + values: ['x', 'y', 'closest', false], + + } +}; + +},{"../components/color/attributes":26,"../lib":122,"./font_attributes":170}],185:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + t: { + valType: 'number', + dflt: 0, + + + }, + r: { + valType: 'number', + dflt: 0, + + + }, + b: { + valType: 'number', + dflt: 0, + + + }, + l: { + valType: 'number', + dflt: 0, + + + } +}; + +},{}],186:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Plotly = require('../plotly'); +var Registry = require('../registry'); +var Lib = require('../lib'); +var Color = require('../components/color'); + +var plots = module.exports = {}; + +var animationAttrs = require('./animation_attributes'); +var frameAttrs = require('./frame_attributes'); + +// Expose registry methods on Plots for backward-compatibility +Lib.extendFlat(plots, Registry); + +plots.attributes = require('./attributes'); +plots.attributes.type.values = plots.allTypes; +plots.fontAttrs = require('./font_attributes'); +plots.layoutAttributes = require('./layout_attributes'); + +// TODO make this a plot attribute? +plots.fontWeight = 'normal'; + +var subplotsRegistry = plots.subplotsRegistry; +var transformsRegistry = plots.transformsRegistry; + +var ErrorBars = require('../components/errorbars'); + +var commandModule = require('./command'); +plots.executeAPICommand = commandModule.executeAPICommand; +plots.computeAPICommandBindings = commandModule.computeAPICommandBindings; +plots.manageCommandObserver = commandModule.manageCommandObserver; +plots.hasSimpleAPICommandBindings = commandModule.hasSimpleAPICommandBindings; + +/** + * Find subplot ids in data. + * Meant to be used in the defaults step. + * + * Use plots.getSubplotIds to grab the current + * subplot ids later on in Plotly.plot. + * + * @param {array} data plotly data array + * (intended to be _fullData, but does not have to be). + * @param {string} type subplot type to look for. + * + * @return {array} list of subplot ids (strings). + * N.B. these ids possibly un-ordered. + * + * TODO incorporate cartesian/gl2d axis finders in this paradigm. + */ +plots.findSubplotIds = function findSubplotIds(data, type) { + var subplotIds = []; + + if(plots.subplotsRegistry[type] === undefined) return subplotIds; + + var attr = plots.subplotsRegistry[type].attr; + + for(var i = 0; i < data.length; i++) { + var trace = data[i]; + + if(plots.traceIs(trace, type) && subplotIds.indexOf(trace[attr]) === -1) { + subplotIds.push(trace[attr]); + } + } + + return subplotIds; +}; + +/** + * Get the ids of the current subplots. + * + * @param {object} layout plotly full layout object. + * @param {string} type subplot type to look for. + * + * @return {array} list of ordered subplot ids (strings). + * + */ +plots.getSubplotIds = function getSubplotIds(layout, type) { + var _module = plots.subplotsRegistry[type]; + + if(_module === undefined) return []; + + // layout must be 'fullLayout' here + if(type === 'cartesian' && (!layout._has || !layout._has('cartesian'))) return []; + if(type === 'gl2d' && (!layout._has || !layout._has('gl2d'))) return []; + if(type === 'cartesian' || type === 'gl2d') { + return Object.keys(layout._plots || {}); + } + + var idRegex = _module.idRegex, + layoutKeys = Object.keys(layout), + subplotIds = []; + + for(var i = 0; i < layoutKeys.length; i++) { + var layoutKey = layoutKeys[i]; + + if(idRegex.test(layoutKey)) subplotIds.push(layoutKey); + } + + // order the ids + var idLen = _module.idRoot.length; + subplotIds.sort(function(a, b) { + var aNum = +(a.substr(idLen) || 1), + bNum = +(b.substr(idLen) || 1); + return aNum - bNum; + }); + + return subplotIds; +}; + +/** + * Get the data trace(s) associated with a given subplot. + * + * @param {array} data plotly full data array. + * @param {object} layout plotly full layout object. + * @param {string} subplotId subplot ids to look for. + * + * @return {array} list of trace objects. + * + */ +plots.getSubplotData = function getSubplotData(data, type, subplotId) { + if(plots.subplotsRegistry[type] === undefined) return []; + + var attr = plots.subplotsRegistry[type].attr, + subplotData = [], + trace; + + for(var i = 0; i < data.length; i++) { + trace = data[i]; + + if(type === 'gl2d' && plots.traceIs(trace, 'gl2d')) { + var spmatch = Plotly.Axes.subplotMatch, + subplotX = 'x' + subplotId.match(spmatch)[1], + subplotY = 'y' + subplotId.match(spmatch)[2]; + + if(trace[attr[0]] === subplotX && trace[attr[1]] === subplotY) { + subplotData.push(trace); + } + } + else { + if(trace[attr] === subplotId) subplotData.push(trace); + } + } + + return subplotData; +}; + +// in some cases the browser doesn't seem to know how big +// the text is at first, so it needs to draw it, +// then wait a little, then draw it again +plots.redrawText = function(gd) { + + // do not work if polar is present + if((gd.data && gd.data[0] && gd.data[0].r)) return; + + return new Promise(function(resolve) { + setTimeout(function() { + Registry.getComponentMethod('annotations', 'draw')(gd); + Registry.getComponentMethod('legend', 'draw')(gd); + + (gd.calcdata || []).forEach(function(d) { + if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); + }); + + resolve(plots.previousPromises(gd)); + }, 300); + }); +}; + +// resize plot about the container size +plots.resize = function(gd) { + return new Promise(function(resolve, reject) { + + if(!gd || d3.select(gd).style('display') === 'none') { + reject(new Error('Resize must be passed a plot div element.')); + } + + if(gd._redrawTimer) clearTimeout(gd._redrawTimer); + + gd._redrawTimer = setTimeout(function() { + // return if there is nothing to resize + if(gd.layout.width && gd.layout.height) { + resolve(gd); + return; + } + + delete gd.layout.width; + delete gd.layout.height; + + // autosizing doesn't count as a change that needs saving + var oldchanged = gd.changed; + + // nor should it be included in the undo queue + gd.autoplay = true; + + Plotly.relayout(gd, { autosize: true }).then(function() { + gd.changed = oldchanged; + resolve(gd); + }); + }, 100); + }); +}; + + +// for use in Lib.syncOrAsync, check if there are any +// pending promises in this plot and wait for them +plots.previousPromises = function(gd) { + if((gd._promises || []).length) { + return Promise.all(gd._promises) + .then(function() { gd._promises = []; }); + } +}; + +/** + * Adds the 'Edit chart' link. + * Note that now Plotly.plot() calls this so it can regenerate whenever it replots + * + * Add source links to your graph inside the 'showSources' config argument. + */ +plots.addLinks = function(gd) { + var fullLayout = gd._fullLayout; + + var linkContainer = fullLayout._paper + .selectAll('text.js-plot-link-container').data([0]); + + linkContainer.enter().append('text') + .classed('js-plot-link-container', true) + .style({ + 'font-family': '"Open Sans", Arial, sans-serif', + 'font-size': '12px', + 'fill': Color.defaultLine, + 'pointer-events': 'all' + }) + .each(function() { + var links = d3.select(this); + links.append('tspan').classed('js-link-to-tool', true); + links.append('tspan').classed('js-link-spacer', true); + links.append('tspan').classed('js-sourcelinks', true); + }); + + // The text node inside svg + var text = linkContainer.node(), + attrs = { + y: fullLayout._paper.attr('height') - 9 + }; + + // If text's width is bigger than the layout + // Check that text is a child node or document.body + // because otherwise IE/Edge might throw an exception + // when calling getComputedTextLength(). + // Apparently offsetParent is null for invisibles. + if(document.body.contains(text) && text.getComputedTextLength() >= (fullLayout.width - 20)) { + // Align the text at the left + attrs['text-anchor'] = 'start'; + attrs.x = 5; + } + else { + // Align the text at the right + attrs['text-anchor'] = 'end'; + attrs.x = fullLayout._paper.attr('width') - 7; + } + + linkContainer.attr(attrs); + + var toolspan = linkContainer.select('.js-link-to-tool'), + spacespan = linkContainer.select('.js-link-spacer'), + sourcespan = linkContainer.select('.js-sourcelinks'); + + if(gd._context.showSources) gd._context.showSources(gd); + + // 'view in plotly' link for embedded plots + if(gd._context.showLink) positionPlayWithData(gd, toolspan); + + // separator if we have both sources and tool link + spacespan.text((toolspan.text() && sourcespan.text()) ? ' - ' : ''); +}; + +// note that now this function is only adding the brand in +// iframes and 3rd-party apps +function positionPlayWithData(gd, container) { + container.text(''); + var link = container.append('a') + .attr({ + 'xlink:xlink:href': '#', + 'class': 'link--impt link--embedview', + 'font-weight': 'bold' + }) + .text(gd._context.linkText + ' ' + String.fromCharCode(187)); + + if(gd._context.sendData) { + link.on('click', function() { + plots.sendDataToCloud(gd); + }); + } + else { + var path = window.location.pathname.split('/'); + var query = window.location.search; + link.attr({ + 'xlink:xlink:show': 'new', + 'xlink:xlink:href': '/' + path[2].split('.')[0] + '/' + path[1] + query + }); + } +} + +plots.sendDataToCloud = function(gd) { + gd.emit('plotly_beforeexport'); + + var baseUrl = (window.PLOTLYENV && window.PLOTLYENV.BASE_URL) || 'https://plot.ly'; + + var hiddenformDiv = d3.select(gd) + .append('div') + .attr('id', 'hiddenform') + .style('display', 'none'); + + var hiddenform = hiddenformDiv + .append('form') + .attr({ + action: baseUrl + '/external', + method: 'post', + target: '_blank' + }); + + var hiddenformInput = hiddenform + .append('input') + .attr({ + type: 'text', + name: 'data' + }); + + hiddenformInput.node().value = plots.graphJson(gd, false, 'keepdata'); + hiddenform.node().submit(); + hiddenformDiv.remove(); + + gd.emit('plotly_afterexport'); + return false; +}; + +// Fill in default values: +// +// gd.data, gd.layout: +// are precisely what the user specified, +// these fields shouldn't be modified nor used directly +// after the supply defaults step. +// +// gd._fullData, gd._fullLayout: +// are complete descriptions of how to draw the plot, +// use these fields in all required computations. +// +// gd._fullLayout._modules +// is a list of all the trace modules required to draw the plot. +// +// gd._fullLayout._basePlotModules +// is a list of all the plot modules required to draw the plot. +// +// gd._fullLayout._transformModules +// is a list of all the transform modules invoked. +// +plots.supplyDefaults = function(gd) { + var oldFullLayout = gd._fullLayout || {}, + newFullLayout = gd._fullLayout = {}, + newLayout = gd.layout || {}; + + var oldFullData = gd._fullData || [], + newFullData = gd._fullData = [], + newData = gd.data || []; + + var i; + + // Create all the storage space for frames, but only if doesn't already exist + if(!gd._transitionData) plots.createTransitionData(gd); + + // first fill in what we can of layout without looking at data + // because fullData needs a few things from layout + + if(oldFullLayout._initialAutoSizeIsDone) { + + // coerce the updated layout while preserving width and height + var oldWidth = oldFullLayout.width, + oldHeight = oldFullLayout.height; + + plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout); + + if(!newLayout.width) newFullLayout.width = oldWidth; + if(!newLayout.height) newFullLayout.height = oldHeight; + } + else { + + // coerce the updated layout and autosize if needed + plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout); + + var missingWidthOrHeight = (!newLayout.width || !newLayout.height), + autosize = newFullLayout.autosize, + autosizable = gd._context && gd._context.autosizable, + initialAutoSize = missingWidthOrHeight && (autosize || autosizable); + + if(initialAutoSize) plots.plotAutoSize(gd, newLayout, newFullLayout); + else if(missingWidthOrHeight) plots.sanitizeMargins(gd); + + // for backwards-compatibility with Plotly v1.x.x + if(!autosize && missingWidthOrHeight) { + newLayout.width = newFullLayout.width; + newLayout.height = newFullLayout.height; + } + } + + newFullLayout._initialAutoSizeIsDone = true; + + // keep track of how many traces are inputted + newFullLayout._dataLength = newData.length; + + // then do the data + newFullLayout._globalTransforms = (gd._context || {}).globalTransforms; + plots.supplyDataDefaults(newData, newFullData, newLayout, newFullLayout); + + // attach helper method to check whether a plot type is present on graph + newFullLayout._has = plots._hasPlotType.bind(newFullLayout); + + // special cases that introduce interactions between traces + var _modules = newFullLayout._modules; + for(i = 0; i < _modules.length; i++) { + var _module = _modules[i]; + if(_module.cleanData) _module.cleanData(newFullData); + } + + if(oldFullData.length === newData.length) { + for(i = 0; i < newFullData.length; i++) { + relinkPrivateKeys(newFullData[i], oldFullData[i]); + } + } + + // finally, fill in the pieces of layout that may need to look at data + plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData, gd._transitionData); + + // TODO remove in v2.0.0 + // add has-plot-type refs to fullLayout for backward compatibility + newFullLayout._hasCartesian = newFullLayout._has('cartesian'); + newFullLayout._hasGeo = newFullLayout._has('geo'); + newFullLayout._hasGL3D = newFullLayout._has('gl3d'); + newFullLayout._hasGL2D = newFullLayout._has('gl2d'); + newFullLayout._hasTernary = newFullLayout._has('ternary'); + newFullLayout._hasPie = newFullLayout._has('pie'); + + // clean subplots and other artifacts from previous plot calls + plots.cleanPlot(newFullData, newFullLayout, oldFullData, oldFullLayout); + + // relink / initialize subplot axis objects + plots.linkSubplots(newFullData, newFullLayout, oldFullData, oldFullLayout); + + // relink functions and _ attributes to promote consistency between plots + relinkPrivateKeys(newFullLayout, oldFullLayout); + + // TODO may return a promise + plots.doAutoMargin(gd); + + // can't quite figure out how to get rid of this... each axis needs + // a reference back to the DOM object for just a few purposes + var axList = Plotly.Axes.list(gd); + for(i = 0; i < axList.length; i++) { + var ax = axList[i]; + ax._gd = gd; + ax.setScale(); + } + + // update object references in calcdata + if((gd.calcdata || []).length === newFullData.length) { + for(i = 0; i < newFullData.length; i++) { + var trace = newFullData[i]; + (gd.calcdata[i][0] || {}).trace = trace; + } + } +}; + +// Create storage for all of the data related to frames and transitions: +plots.createTransitionData = function(gd) { + // Set up the default keyframe if it doesn't exist: + if(!gd._transitionData) { + gd._transitionData = {}; + } + + if(!gd._transitionData._frames) { + gd._transitionData._frames = []; + } + + if(!gd._transitionData._frameHash) { + gd._transitionData._frameHash = {}; + } + + if(!gd._transitionData._counter) { + gd._transitionData._counter = 0; + } + + if(!gd._transitionData._interruptCallbacks) { + gd._transitionData._interruptCallbacks = []; + } +}; + +// helper function to be bound to fullLayout to check +// whether a certain plot type is present on plot +plots._hasPlotType = function(category) { + var basePlotModules = this._basePlotModules || []; + + for(var i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; + + if(_module.name === category) return true; + } + + return false; +}; + +plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var i, j; + + var basePlotModules = oldFullLayout._basePlotModules || []; + for(i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; + + if(_module.clean) { + _module.clean(newFullData, newFullLayout, oldFullData, oldFullLayout); + } + } + + var hasPaper = !!oldFullLayout._paper; + var hasInfoLayer = !!oldFullLayout._infolayer; + + oldLoop: + for(i = 0; i < oldFullData.length; i++) { + var oldTrace = oldFullData[i], + oldUid = oldTrace.uid; + + for(j = 0; j < newFullData.length; j++) { + var newTrace = newFullData[j]; + + if(oldUid === newTrace.uid) continue oldLoop; + } + + // clean old heatmap, contour, and scatter traces + // + // Note: This is also how scatter traces (cartesian and scatterternary) get + // removed since otherwise the scatter module is not called (and so the join + // doesn't register the removal) if scatter traces disappear entirely. + if(hasPaper) { + oldFullLayout._paper.selectAll( + '.hm' + oldUid + + ',.contour' + oldUid + + ',#clip' + oldUid + + ',.trace' + oldUid + ).remove(); + } + + // clean old colorbars + if(hasInfoLayer) { + oldFullLayout._infolayer.selectAll('.cb' + oldUid).remove(); + } + } +}; + +/** + * Relink private _keys and keys with a function value from one container + * to the new container. + * Relink means copying if object is pass-by-value and adding a reference + * if object is pass-by-ref. + * This prevents deepCopying massive structures like a webgl context. + */ +function relinkPrivateKeys(toContainer, fromContainer) { + var isPlainObject = Lib.isPlainObject, + isArray = Array.isArray; + + var keys = Object.keys(fromContainer || {}); + + for(var i = 0; i < keys.length; i++) { + var k = keys[i], + fromVal = fromContainer[k], + toVal = toContainer[k]; + + if(k.charAt(0) === '_' || typeof fromVal === 'function') { + + // if it already exists at this point, it's something + // that we recreate each time around, so ignore it + if(k in toContainer) continue; + + toContainer[k] = fromVal; + } + else if(isArray(fromVal) && isArray(toVal) && isPlainObject(fromVal[0])) { + + // recurse into arrays containers + for(var j = 0; j < fromVal.length; j++) { + if(isPlainObject(fromVal[j]) && isPlainObject(toVal[j])) { + relinkPrivateKeys(toVal[j], fromVal[j]); + } + } + } + else if(isPlainObject(fromVal) && isPlainObject(toVal)) { + + // recurse into objects, but only if they still exist + relinkPrivateKeys(toVal, fromVal); + + if(!Object.keys(toVal).length) delete toContainer[k]; + } + } +} + +plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var oldSubplots = oldFullLayout._plots || {}, + newSubplots = newFullLayout._plots = {}; + + var mockGd = { + _fullData: newFullData, + _fullLayout: newFullLayout + }; + + var ids = Plotly.Axes.getSubplots(mockGd); + + for(var i = 0; i < ids.length; i++) { + var id = ids[i], + oldSubplot = oldSubplots[id], + plotinfo; + + if(oldSubplot) { + plotinfo = newSubplots[id] = oldSubplot; + } + else { + plotinfo = newSubplots[id] = {}; + plotinfo.id = id; + } + + plotinfo.xaxis = Plotly.Axes.getFromId(mockGd, id, 'x'); + plotinfo.yaxis = Plotly.Axes.getFromId(mockGd, id, 'y'); + } +}; + +plots.supplyDataDefaults = function(dataIn, dataOut, layout, fullLayout) { + var modules = fullLayout._modules = [], + basePlotModules = fullLayout._basePlotModules = [], + cnt = 0; + + fullLayout._transformModules = []; + + function pushModule(fullTrace) { + dataOut.push(fullTrace); + + var _module = fullTrace._module; + if(!_module) return; + + Lib.pushUnique(modules, _module); + Lib.pushUnique(basePlotModules, fullTrace._module.basePlotModule); + + cnt++; + } + + for(var i = 0; i < dataIn.length; i++) { + var trace = dataIn[i], + fullTrace = plots.supplyTraceDefaults(trace, cnt, fullLayout, i); + + fullTrace.index = i; + fullTrace._input = trace; + fullTrace._expandedIndex = cnt; + + if(fullTrace.transforms && fullTrace.transforms.length) { + var expandedTraces = applyTransforms(fullTrace, dataOut, layout, fullLayout); + + for(var j = 0; j < expandedTraces.length; j++) { + var expandedTrace = expandedTraces[j], + fullExpandedTrace = plots.supplyTraceDefaults(expandedTrace, cnt, fullLayout, i); + + // mutate uid here using parent uid and expanded index + // to promote consistency between update calls + expandedTrace.uid = fullExpandedTrace.uid = fullTrace.uid + j; + + // add info about parent data trace + fullExpandedTrace.index = i; + fullExpandedTrace._input = trace; + fullExpandedTrace._fullInput = fullTrace; + + // add info about the expanded data + fullExpandedTrace._expandedIndex = cnt; + fullExpandedTrace._expandedInput = expandedTrace; + + pushModule(fullExpandedTrace); + } + } + else { + + // add identify refs for consistency with transformed traces + fullTrace._fullInput = fullTrace; + fullTrace._expandedInput = fullTrace; + + pushModule(fullTrace); + } + } +}; + +plots.supplyAnimationDefaults = function(opts) { + opts = opts || {}; + var i; + var optsOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts || {}, optsOut, animationAttrs, attr, dflt); + } + + coerce('mode'); + coerce('direction'); + coerce('fromcurrent'); + + if(Array.isArray(opts.frame)) { + optsOut.frame = []; + for(i = 0; i < opts.frame.length; i++) { + optsOut.frame[i] = plots.supplyAnimationFrameDefaults(opts.frame[i] || {}); + } + } else { + optsOut.frame = plots.supplyAnimationFrameDefaults(opts.frame || {}); + } + + if(Array.isArray(opts.transition)) { + optsOut.transition = []; + for(i = 0; i < opts.transition.length; i++) { + optsOut.transition[i] = plots.supplyAnimationTransitionDefaults(opts.transition[i] || {}); + } + } else { + optsOut.transition = plots.supplyAnimationTransitionDefaults(opts.transition || {}); + } + + return optsOut; +}; + +plots.supplyAnimationFrameDefaults = function(opts) { + var optsOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts || {}, optsOut, animationAttrs.frame, attr, dflt); + } + + coerce('duration'); + coerce('redraw'); + + return optsOut; +}; + +plots.supplyAnimationTransitionDefaults = function(opts) { + var optsOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(opts || {}, optsOut, animationAttrs.transition, attr, dflt); + } + + coerce('duration'); + coerce('easing'); + + return optsOut; +}; + +plots.supplyFrameDefaults = function(frameIn) { + var frameOut = {}; + + function coerce(attr, dflt) { + return Lib.coerce(frameIn, frameOut, frameAttrs, attr, dflt); + } + + coerce('group'); + coerce('name'); + coerce('traces'); + coerce('baseframe'); + coerce('data'); + coerce('layout'); + + return frameOut; +}; + +plots.supplyTraceDefaults = function(traceIn, traceOutIndex, layout, traceInIndex) { + var traceOut = {}, + defaultColor = Color.defaults[traceOutIndex % Color.defaults.length]; + + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, plots.attributes, attr, dflt); + } + + function coerceSubplotAttr(subplotType, subplotAttr) { + if(!plots.traceIs(traceOut, subplotType)) return; + + return Lib.coerce(traceIn, traceOut, + plots.subplotsRegistry[subplotType].attributes, subplotAttr); + } + + var visible = coerce('visible'); + + coerce('type'); + coerce('uid'); + coerce('name', 'trace ' + traceInIndex); + + // coerce subplot attributes of all registered subplot types + var subplotTypes = Object.keys(subplotsRegistry); + for(var i = 0; i < subplotTypes.length; i++) { + var subplotType = subplotTypes[i]; + + // done below (only when visible is true) + // TODO unified this pattern + if(['cartesian', 'gl2d'].indexOf(subplotType) !== -1) continue; + + var attr = subplotsRegistry[subplotType].attr; + + if(attr) coerceSubplotAttr(subplotType, attr); + } + + if(visible) { + var _module = plots.getModule(traceOut); + traceOut._module = _module; + + // gets overwritten in pie, geo and ternary modules + coerce('hoverinfo', (layout._dataLength === 1) ? 'x+y+z+text' : undefined); + + // TODO add per-base-plot-module trace defaults step + + if(_module) _module.supplyDefaults(traceIn, traceOut, defaultColor, layout); + + if(!plots.traceIs(traceOut, 'noOpacity')) coerce('opacity'); + + coerceSubplotAttr('cartesian', 'xaxis'); + coerceSubplotAttr('cartesian', 'yaxis'); + + coerceSubplotAttr('gl2d', 'xaxis'); + coerceSubplotAttr('gl2d', 'yaxis'); + + if(plots.traceIs(traceOut, 'showLegend')) { + coerce('showlegend'); + coerce('legendgroup'); + } + + supplyTransformDefaults(traceIn, traceOut, layout); + } + + return traceOut; +}; + +function supplyTransformDefaults(traceIn, traceOut, layout) { + var globalTransforms = layout._globalTransforms || []; + + if(!Array.isArray(traceIn.transforms) && globalTransforms.length === 0) return; + + var containerIn = traceIn.transforms || [], + transformList = globalTransforms.concat(containerIn), + containerOut = traceOut.transforms = []; + + for(var i = 0; i < transformList.length; i++) { + var transformIn = transformList[i], + type = transformIn.type, + _module = transformsRegistry[type], + transformOut; + + if(!_module) Lib.warn('Unrecognized transform type ' + type + '.'); + + if(_module && _module.supplyDefaults) { + transformOut = _module.supplyDefaults(transformIn, traceOut, layout, traceIn); + transformOut.type = type; + transformOut._module = _module; + + Lib.pushUnique(layout._transformModules, _module); + } + else { + transformOut = Lib.extendFlat({}, transformIn); + } + + containerOut.push(transformOut); + } +} + +function applyTransforms(fullTrace, fullData, layout, fullLayout) { + var container = fullTrace.transforms, + dataOut = [fullTrace]; + + for(var i = 0; i < container.length; i++) { + var transform = container[i], + _module = transformsRegistry[transform.type]; + + if(_module && _module.transform) { + dataOut = _module.transform(dataOut, { + transform: transform, + fullTrace: fullTrace, + fullData: fullData, + layout: layout, + fullLayout: fullLayout, + transformIndex: i + }); + } + } + + return dataOut; +} + +plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, plots.layoutAttributes, attr, dflt); + } + + var globalFont = Lib.coerceFont(coerce, 'font'); + + coerce('title'); + + Lib.coerceFont(coerce, 'titlefont', { + family: globalFont.family, + size: Math.round(globalFont.size * 1.4), + color: globalFont.color + }); + + // Make sure that autosize is defaulted to *true* + // on layouts with no set width and height for backward compatibly, + // in particular https://plot.ly/javascript/responsive-fluid-layout/ + // + // Before https://github.com/plotly/plotly.js/pull/635 , + // layouts with no set width and height were set temporary set to 'initial' + // to pass through the autosize routine + // + // This behavior is subject to change in v2. + coerce('autosize', !(layoutIn.width && layoutIn.height)); + + coerce('width'); + coerce('height'); + coerce('margin.l'); + coerce('margin.r'); + coerce('margin.t'); + coerce('margin.b'); + coerce('margin.pad'); + coerce('margin.autoexpand'); + + if(layoutIn.width && layoutIn.height) plots.sanitizeMargins(layoutOut); + + coerce('paper_bgcolor'); + + coerce('separators'); + coerce('hidesources'); + coerce('smith'); +}; + +plots.plotAutoSize = function plotAutoSize(gd, layout, fullLayout) { + var context = gd._context || {}, + frameMargins = context.frameMargins, + newWidth, + newHeight; + + var isPlotDiv = Lib.isPlotDiv(gd); + + if(isPlotDiv) gd.emit('plotly_autosize'); + + // embedded in an iframe - just take the full iframe size + // if we get to this point, with no aspect ratio restrictions + if(context.fillFrame) { + newWidth = window.innerWidth; + newHeight = window.innerHeight; + + // somehow we get a few extra px height sometimes... + // just hide it + document.body.style.overflow = 'hidden'; + } + else if(isNumeric(frameMargins) && frameMargins > 0) { + var reservedMargins = calculateReservedMargins(gd._boundingBoxMargins), + reservedWidth = reservedMargins.left + reservedMargins.right, + reservedHeight = reservedMargins.bottom + reservedMargins.top, + factor = 1 - 2 * frameMargins; + + var gdBB = fullLayout._container && fullLayout._container.node ? + fullLayout._container.node().getBoundingClientRect() : { + width: fullLayout.width, + height: fullLayout.height + }; + + newWidth = Math.round(factor * (gdBB.width - reservedWidth)); + newHeight = Math.round(factor * (gdBB.height - reservedHeight)); + } + else { + // plotly.js - let the developers do what they want, either + // provide height and width for the container div, + // specify size in layout, or take the defaults, + // but don't enforce any ratio restrictions + var computedStyle = isPlotDiv ? window.getComputedStyle(gd) : {}; + + newWidth = parseFloat(computedStyle.width) || fullLayout.width; + newHeight = parseFloat(computedStyle.height) || fullLayout.height; + } + + var minWidth = plots.layoutAttributes.width.min, + minHeight = plots.layoutAttributes.height.min; + if(newWidth < minWidth) newWidth = minWidth; + if(newHeight < minHeight) newHeight = minHeight; + + var widthHasChanged = !layout.width && + (Math.abs(fullLayout.width - newWidth) > 1), + heightHasChanged = !layout.height && + (Math.abs(fullLayout.height - newHeight) > 1); + + if(heightHasChanged || widthHasChanged) { + if(widthHasChanged) fullLayout.width = newWidth; + if(heightHasChanged) fullLayout.height = newHeight; + } + + // cache initial autosize value, used in relayout when + // width or height values are set to null + if(!gd._initialAutoSize) { + gd._initialAutoSize = { width: newWidth, height: newHeight }; + } + + plots.sanitizeMargins(fullLayout); +}; + +/** + * Reduce all reserved margin objects to a single required margin reservation. + * + * @param {Object} margins + * @returns {{left: number, right: number, bottom: number, top: number}} + */ +function calculateReservedMargins(margins) { + var resultingMargin = {left: 0, right: 0, bottom: 0, top: 0}, + marginName; + + if(margins) { + for(marginName in margins) { + if(margins.hasOwnProperty(marginName)) { + resultingMargin.left += margins[marginName].left || 0; + resultingMargin.right += margins[marginName].right || 0; + resultingMargin.bottom += margins[marginName].bottom || 0; + resultingMargin.top += margins[marginName].top || 0; + } + } + } + return resultingMargin; +} + +plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData, transitionData) { + var i, _module; + + // can't be be part of basePlotModules loop + // in order to handle the orphan axes case + Plotly.Axes.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + + // base plot module layout defaults + var basePlotModules = layoutOut._basePlotModules; + for(i = 0; i < basePlotModules.length; i++) { + _module = basePlotModules[i]; + + // done above already + if(_module.name === 'cartesian') continue; + + // e.g. gl2d does not have a layout-defaults step + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } + } + + // trace module layout defaults + var modules = layoutOut._modules; + for(i = 0; i < modules.length; i++) { + _module = modules[i]; + + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } + } + + // transform module layout defaults + var transformModules = layoutOut._transformModules; + for(i = 0; i < transformModules.length; i++) { + _module = transformModules[i]; + + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData, transitionData); + } + } + + // should FX be a component? + Plotly.Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + + var components = Object.keys(Registry.componentsRegistry); + for(i = 0; i < components.length; i++) { + _module = Registry.componentsRegistry[components[i]]; + + if(_module.supplyLayoutDefaults) { + _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); + } + } +}; + +// Remove all plotly attributes from a div so it can be replotted fresh +// TODO: these really need to be encapsulated into a much smaller set... +plots.purge = function(gd) { + + // note: we DO NOT remove _context because it doesn't change when we insert + // a new plot, and may have been set outside of our scope. + + var fullLayout = gd._fullLayout || {}; + if(fullLayout._glcontainer !== undefined) fullLayout._glcontainer.remove(); + if(fullLayout._geocontainer !== undefined) fullLayout._geocontainer.remove(); + + // remove modebar + if(fullLayout._modeBar) fullLayout._modeBar.destroy(); + + if(gd._transitionData) { + // Ensure any dangling callbacks are simply dropped if the plot is purged. + // This is more or less only actually important for testing. + if(gd._transitionData._interruptCallbacks) { + gd._transitionData._interruptCallbacks.length = 0; + } + + if(gd._transitionData._animationRaf) { + window.cancelAnimationFrame(gd._transitionData._animationRaf); + } + } + + // data and layout + delete gd.data; + delete gd.layout; + delete gd._fullData; + delete gd._fullLayout; + delete gd.calcdata; + delete gd.framework; + delete gd.empty; + + delete gd.fid; + + delete gd.undoqueue; // action queue + delete gd.undonum; + delete gd.autoplay; // are we doing an action that doesn't go in undo queue? + delete gd.changed; + + // these get recreated on Plotly.plot anyway, but just to be safe + // (and to have a record of them...) + delete gd._tester; + delete gd._testref; + delete gd._promises; + delete gd._redrawTimer; + delete gd._replotting; + delete gd.firstscatter; + delete gd.hmlumcount; + delete gd.hmpixcount; + delete gd.numboxes; + delete gd._hoverTimer; + delete gd._lastHoverTime; + delete gd._transitionData; + delete gd._transitioning; + delete gd._initialAutoSize; + + // remove all event listeners + if(gd.removeAllListeners) gd.removeAllListeners(); +}; + +plots.style = function(gd) { + var _modules = gd._fullLayout._modules; + + for(var i = 0; i < _modules.length; i++) { + var _module = _modules[i]; + + if(_module.style) _module.style(gd); + } +}; + +plots.sanitizeMargins = function(fullLayout) { + // polar doesn't do margins... + if(!fullLayout || !fullLayout.margin) return; + + var width = fullLayout.width, + height = fullLayout.height, + margin = fullLayout.margin, + plotWidth = width - (margin.l + margin.r), + plotHeight = height - (margin.t + margin.b), + correction; + + // if margin.l + margin.r = 0 then plotWidth > 0 + // as width >= 10 by supplyDefaults + // similarly for margin.t + margin.b + + if(plotWidth < 0) { + correction = (width - 1) / (margin.l + margin.r); + margin.l = Math.floor(correction * margin.l); + margin.r = Math.floor(correction * margin.r); + } + + if(plotHeight < 0) { + correction = (height - 1) / (margin.t + margin.b); + margin.t = Math.floor(correction * margin.t); + margin.b = Math.floor(correction * margin.b); + } +}; + +// called by legend and colorbar routines to see if we need to +// expand the margins to show them +// o is {x,l,r,y,t,b} where x and y are plot fractions, +// the rest are pixels in each direction +// or leave o out to delete this entry (like if it's hidden) +plots.autoMargin = function(gd, id, o) { + var fullLayout = gd._fullLayout; + + if(!fullLayout._pushmargin) fullLayout._pushmargin = {}; + + if(fullLayout.margin.autoexpand !== false) { + if(!o) delete fullLayout._pushmargin[id]; + else { + var pad = o.pad === undefined ? 12 : o.pad; + + // if the item is too big, just give it enough automargin to + // make sure you can still grab it and bring it back + if(o.l + o.r > fullLayout.width * 0.5) o.l = o.r = 0; + if(o.b + o.t > fullLayout.height * 0.5) o.b = o.t = 0; + + fullLayout._pushmargin[id] = { + l: {val: o.x, size: o.l + pad}, + r: {val: o.x, size: o.r + pad}, + b: {val: o.y, size: o.b + pad}, + t: {val: o.y, size: o.t + pad} + }; + } + + if(!gd._replotting) plots.doAutoMargin(gd); + } +}; + +plots.doAutoMargin = function(gd) { + var fullLayout = gd._fullLayout; + if(!fullLayout._size) fullLayout._size = {}; + if(!fullLayout._pushmargin) fullLayout._pushmargin = {}; + + var gs = fullLayout._size, + oldmargins = JSON.stringify(gs); + + // adjust margins for outside legends and colorbars + // fullLayout.margin is the requested margin, + // fullLayout._size has margins and plotsize after adjustment + var ml = Math.max(fullLayout.margin.l || 0, 0), + mr = Math.max(fullLayout.margin.r || 0, 0), + mt = Math.max(fullLayout.margin.t || 0, 0), + mb = Math.max(fullLayout.margin.b || 0, 0), + pm = fullLayout._pushmargin; + + if(fullLayout.margin.autoexpand !== false) { + // fill in the requested margins + pm.base = { + l: {val: 0, size: ml}, + r: {val: 1, size: mr}, + t: {val: 1, size: mt}, + b: {val: 0, size: mb} + }; + // now cycle through all the combinations of l and r + // (and t and b) to find the required margins + Object.keys(pm).forEach(function(k1) { + var pushleft = pm[k1].l || {}, + pushbottom = pm[k1].b || {}, + fl = pushleft.val, + pl = pushleft.size, + fb = pushbottom.val, + pb = pushbottom.size; + Object.keys(pm).forEach(function(k2) { + if(isNumeric(pl) && pm[k2].r) { + var fr = pm[k2].r.val, + pr = pm[k2].r.size; + if(fr > fl) { + var newl = (pl * fr + + (pr - fullLayout.width) * fl) / (fr - fl), + newr = (pr * (1 - fl) + + (pl - fullLayout.width) * (1 - fr)) / (fr - fl); + if(newl >= 0 && newr >= 0 && newl + newr > ml + mr) { + ml = newl; + mr = newr; + } + } + } + if(isNumeric(pb) && pm[k2].t) { + var ft = pm[k2].t.val, + pt = pm[k2].t.size; + if(ft > fb) { + var newb = (pb * ft + + (pt - fullLayout.height) * fb) / (ft - fb), + newt = (pt * (1 - fb) + + (pb - fullLayout.height) * (1 - ft)) / (ft - fb); + if(newb >= 0 && newt >= 0 && newb + newt > mb + mt) { + mb = newb; + mt = newt; + } + } + } + }); + }); + } + + gs.l = Math.round(ml); + gs.r = Math.round(mr); + gs.t = Math.round(mt); + gs.b = Math.round(mb); + gs.p = Math.round(fullLayout.margin.pad); + gs.w = Math.round(fullLayout.width) - gs.l - gs.r; + gs.h = Math.round(fullLayout.height) - gs.t - gs.b; + + // if things changed and we're not already redrawing, trigger a redraw + if(!gd._replotting && oldmargins !== '{}' && + oldmargins !== JSON.stringify(fullLayout._size)) { + return Plotly.plot(gd); + } +}; + +/** + * JSONify the graph data and layout + * + * This function needs to recurse because some src can be inside + * sub-objects. + * + * It also strips out functions and private (starts with _) elements. + * Therefore, we can add temporary things to data and layout that don't + * get saved. + * + * @param gd The graphDiv + * @param {Boolean} dataonly If true, don't return layout. + * @param {'keepref'|'keepdata'|'keepall'} [mode='keepref'] Filter what's kept + * keepref: remove data for which there's a src present + * eg if there's xsrc present (and xsrc is well-formed, + * ie has : and some chars before it), strip out x + * keepdata: remove all src tags, don't remove the data itself + * keepall: keep data and src + * @param {String} output If you specify 'object', the result will not be stringified + * @param {Boolean} useDefaults If truthy, use _fullLayout and _fullData + * @returns {Object|String} + */ +plots.graphJson = function(gd, dataonly, mode, output, useDefaults) { + // if the defaults aren't supplied yet, we need to do that... + if((useDefaults && dataonly && !gd._fullData) || + (useDefaults && !dataonly && !gd._fullLayout)) { + plots.supplyDefaults(gd); + } + + var data = (useDefaults) ? gd._fullData : gd.data, + layout = (useDefaults) ? gd._fullLayout : gd.layout; + + function stripObj(d) { + if(typeof d === 'function') { + return null; + } + if(Lib.isPlainObject(d)) { + var o = {}, v, src; + for(v in d) { + // remove private elements and functions + // _ is for private, [ is a mistake ie [object Object] + if(typeof d[v] === 'function' || + ['_', '['].indexOf(v.charAt(0)) !== -1) { + continue; + } + + // look for src/data matches and remove the appropriate one + if(mode === 'keepdata') { + // keepdata: remove all ...src tags + if(v.substr(v.length - 3) === 'src') { + continue; + } + } + else if(mode === 'keepstream') { + // keep sourced data if it's being streamed. + // similar to keepref, but if the 'stream' object exists + // in a trace, we will keep the data array. + src = d[v + 'src']; + if(typeof src === 'string' && src.indexOf(':') > 0) { + if(!Lib.isPlainObject(d.stream)) { + continue; + } + } + } + else if(mode !== 'keepall') { + // keepref: remove sourced data but only + // if the source tag is well-formed + src = d[v + 'src']; + if(typeof src === 'string' && src.indexOf(':') > 0) { + continue; + } + } + + // OK, we're including this... recurse into it + o[v] = stripObj(d[v]); + } + return o; + } + + if(Array.isArray(d)) { + return d.map(stripObj); + } + + // convert native dates to date strings... + // mostly for external users exporting to plotly + if(Lib.isJSDate(d)) return Lib.ms2DateTime(+d); + + return d; + } + + var obj = { + data: (data || []).map(function(v) { + var d = stripObj(v); + // fit has some little arrays in it that don't contain data, + // just fit params and meta + if(dataonly) { delete d.fit; } + return d; + }) + }; + if(!dataonly) { obj.layout = stripObj(layout); } + + if(gd.framework && gd.framework.isPolar) obj = gd.framework.getConfig(); + + return (output === 'object') ? obj : JSON.stringify(obj); +}; + +/** + * Modify a keyframe using a list of operations: + * + * @param {array of objects} operations + * Sequence of operations to be performed on the keyframes + */ +plots.modifyFrames = function(gd, operations) { + var i, op, frame; + var _frames = gd._transitionData._frames; + var _hash = gd._transitionData._frameHash; + + for(i = 0; i < operations.length; i++) { + op = operations[i]; + + switch(op.type) { + // No reason this couldn't exist, but is currently unused/untested: + /* case 'rename': + frame = _frames[op.index]; + delete _hash[frame.name]; + _hash[op.name] = frame; + frame.name = op.name; + break;*/ + case 'replace': + frame = op.value; + var oldName = (_frames[op.index] || {}).name; + var newName = frame.name; + _frames[op.index] = _hash[newName] = frame; + + if(newName !== oldName) { + // If name has changed in addition to replacement, then update + // the lookup table: + delete _hash[oldName]; + _hash[newName] = frame; + } + + break; + case 'insert': + frame = op.value; + _hash[frame.name] = frame; + _frames.splice(op.index, 0, frame); + break; + case 'delete': + frame = _frames[op.index]; + delete _hash[frame.name]; + _frames.splice(op.index, 1); + break; + } + } + + return Promise.resolve(); +}; + +/* + * Compute a keyframe. Merge a keyframe into its base frame(s) and + * expand properties. + * + * @param {object} frameLookup + * An object containing frames keyed by name (i.e. gd._transitionData._frameHash) + * @param {string} frame + * The name of the keyframe to be computed + * + * Returns: a new object with the merged content + */ +plots.computeFrame = function(gd, frameName) { + var frameLookup = gd._transitionData._frameHash; + var i, traceIndices, traceIndex, destIndex; + + var framePtr = frameLookup[frameName]; + + // Return false if the name is invalid: + if(!framePtr) { + return false; + } + + var frameStack = [framePtr]; + var frameNameStack = [framePtr.name]; + + // Follow frame pointers: + while((framePtr = frameLookup[framePtr.baseframe])) { + // Avoid infinite loops: + if(frameNameStack.indexOf(framePtr.name) !== -1) break; + + frameStack.push(framePtr); + frameNameStack.push(framePtr.name); + } + + // A new object for the merged result: + var result = {}; + + // Merge, starting with the last and ending with the desired frame: + while((framePtr = frameStack.pop())) { + if(framePtr.layout) { + result.layout = plots.extendLayout(result.layout, framePtr.layout); + } + + if(framePtr.data) { + if(!result.data) { + result.data = []; + } + traceIndices = framePtr.traces; + + if(!traceIndices) { + // If not defined, assume serial order starting at zero + traceIndices = []; + for(i = 0; i < framePtr.data.length; i++) { + traceIndices[i] = i; + } + } + + if(!result.traces) { + result.traces = []; + } + + for(i = 0; i < framePtr.data.length; i++) { + // Loop through this frames data, find out where it should go, + // and merge it! + traceIndex = traceIndices[i]; + if(traceIndex === undefined || traceIndex === null) { + continue; + } + + destIndex = result.traces.indexOf(traceIndex); + if(destIndex === -1) { + destIndex = result.data.length; + result.traces[destIndex] = traceIndex; + } + + result.data[destIndex] = plots.extendTrace(result.data[destIndex], framePtr.data[i]); + } + } + } + + return result; +}; + +/** + * Extend an object, treating container arrays very differently by extracting + * their contents and merging them separately. + * + * This exists so that we can extendDeepNoArrays and avoid stepping into data + * arrays without knowledge of the plot schema, but so that we may also manually + * recurse into known container arrays, such as transforms. + * + * See extendTrace and extendLayout below for usage. + */ +plots.extendObjectWithContainers = function(dest, src, containerPaths) { + var containerProp, containerVal, i, j, srcProp, destProp, srcContainer, destContainer; + var copy = Lib.extendDeepNoArrays({}, src || {}); + var expandedObj = Lib.expandObjectPaths(copy); + var containerObj = {}; + + // Step through and extract any container properties. Otherwise extendDeepNoArrays + // will clobber any existing properties with an empty array and then supplyDefaults + // will reset everything to defaults. + if(containerPaths && containerPaths.length) { + for(i = 0; i < containerPaths.length; i++) { + containerProp = Lib.nestedProperty(expandedObj, containerPaths[i]); + containerVal = containerProp.get(); + + if(containerVal === undefined) { + Lib.nestedProperty(containerObj, containerPaths[i]).set(null); + } + else { + containerProp.set(null); + Lib.nestedProperty(containerObj, containerPaths[i]).set(containerVal); + } + } + } + + dest = Lib.extendDeepNoArrays(dest || {}, expandedObj); + + if(containerPaths && containerPaths.length) { + for(i = 0; i < containerPaths.length; i++) { + srcProp = Lib.nestedProperty(containerObj, containerPaths[i]); + srcContainer = srcProp.get(); + + if(!srcContainer) continue; + + destProp = Lib.nestedProperty(dest, containerPaths[i]); + destContainer = destProp.get(); + + if(!Array.isArray(destContainer)) { + destContainer = []; + destProp.set(destContainer); + } + + for(j = 0; j < srcContainer.length; j++) { + var srcObj = srcContainer[j]; + + if(srcObj === null) destContainer[j] = null; + else { + destContainer[j] = plots.extendObjectWithContainers(destContainer[j], srcObj); + } + } + + destProp.set(destContainer); + } + } + + return dest; +}; + +plots.dataArrayContainers = ['transforms']; +plots.layoutArrayContainers = Registry.layoutArrayContainers; + +/* + * Extend a trace definition. This method: + * + * 1. directly transfers any array references + * 2. manually recurses into container arrays like transforms + * + * The result is the original object reference with the new contents merged in. + */ +plots.extendTrace = function(destTrace, srcTrace) { + return plots.extendObjectWithContainers(destTrace, srcTrace, plots.dataArrayContainers); +}; + +/* + * Extend a layout definition. This method: + * + * 1. directly transfers any array references (not critically important for + * layout since there aren't really data arrays) + * 2. manually recurses into container arrays like annotations + * + * The result is the original object reference with the new contents merged in. + */ +plots.extendLayout = function(destLayout, srcLayout) { + return plots.extendObjectWithContainers(destLayout, srcLayout, plots.layoutArrayContainers); +}; + +/** + * Transition to a set of new data and layout properties + * + * @param {DOM element} gd + * the DOM element of the graph container div + * @param {Object[]} data + * an array of data objects following the normal Plotly data definition format + * @param {Object} layout + * a layout object, following normal Plotly layout format + * @param {Number[]} traces + * indices of the corresponding traces specified in `data` + * @param {Object} frameOpts + * options for the frame (i.e. whether to redraw post-transition) + * @param {Object} transitionOpts + * options for the transition + */ +plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts) { + var i, traceIdx; + + var dataLength = Array.isArray(data) ? data.length : 0; + var traceIndices = traces.slice(0, dataLength); + + var transitionedTraces = []; + + function prepareTransitions() { + var i; + + for(i = 0; i < traceIndices.length; i++) { + var traceIdx = traceIndices[i]; + var trace = gd._fullData[traceIdx]; + var module = trace._module; + + // There's nothing to do if this module is not defined: + if(!module) continue; + + // Don't register the trace as transitioned if it doens't know what to do. + // If it *is* registered, it will receive a callback that it's responsible + // for calling in order to register the transition as having completed. + if(module.animatable) { + transitionedTraces.push(traceIdx); + } + + gd.data[traceIndices[i]] = plots.extendTrace(gd.data[traceIndices[i]], data[i]); + } + + // Follow the same procedure. Clone it so we don't mangle the input, then + // expand any object paths so we can merge deep into gd.layout: + var layoutUpdate = Lib.expandObjectPaths(Lib.extendDeepNoArrays({}, layout)); + + // Before merging though, we need to modify the incoming layout. We only + // know how to *transition* layout ranges, so it's imperative that a new + // range not be sent to the layout before the transition has started. So + // we must remove the things we can transition: + var axisAttrRe = /^[xy]axis[0-9]*$/; + for(var attr in layoutUpdate) { + if(!axisAttrRe.test(attr)) continue; + delete layoutUpdate[attr].range; + } + + plots.extendLayout(gd.layout, layoutUpdate); + + // Supply defaults after applying the incoming properties. Note that any attempt + // to simplify this step and reduce the amount of work resulted in the reconstruction + // of essentially the whole supplyDefaults step, so that it seems sensible to just use + // supplyDefaults even though it's heavier than would otherwise be desired for + // transitions: + plots.supplyDefaults(gd); + + plots.doCalcdata(gd); + + ErrorBars.calc(gd); + + return Promise.resolve(); + } + + function executeCallbacks(list) { + var p = Promise.resolve(); + if(!list) return p; + while(list.length) { + p = p.then((list.shift())); + } + return p; + } + + function flushCallbacks(list) { + if(!list) return; + while(list.length) { + list.shift(); + } + } + + var aborted = false; + + function executeTransitions() { + + gd.emit('plotly_transitioning', []); + + return new Promise(function(resolve) { + // This flag is used to disabled things like autorange: + gd._transitioning = true; + + // When instantaneous updates are coming through quickly, it's too much to simply disable + // all interaction, so store this flag so we can disambiguate whether mouse interactions + // should be fully disabled or not: + if(transitionOpts.duration > 0) { + gd._transitioningWithDuration = true; + } + + + // If another transition is triggered, this callback will be executed simply because it's + // in the interruptCallbacks queue. If this transition completes, it will instead flush + // that queue and forget about this callback. + gd._transitionData._interruptCallbacks.push(function() { + aborted = true; + }); + + if(frameOpts.redraw) { + gd._transitionData._interruptCallbacks.push(function() { + return Plotly.redraw(gd); + }); + } + + // Emit this and make sure it happens last: + gd._transitionData._interruptCallbacks.push(function() { + gd.emit('plotly_transitioninterrupted', []); + }); + + // Construct callbacks that are executed on transition end. This ensures the d3 transitions + // are *complete* before anything else is done. + var numCallbacks = 0; + var numCompleted = 0; + function makeCallback() { + numCallbacks++; + return function() { + numCompleted++; + // When all are complete, perform a redraw: + if(!aborted && numCompleted === numCallbacks) { + completeTransition(resolve); + } + }; + } + + var traceTransitionOpts; + var j; + var basePlotModules = gd._fullLayout._basePlotModules; + var hasAxisTransition = false; + + if(layout) { + for(j = 0; j < basePlotModules.length; j++) { + if(basePlotModules[j].transitionAxes) { + var newLayout = Lib.expandObjectPaths(layout); + hasAxisTransition = basePlotModules[j].transitionAxes(gd, newLayout, transitionOpts, makeCallback) || hasAxisTransition; + } + } + } + + // Here handle the exception that we refuse to animate scales and axes at the same + // time. In other words, if there's an axis transition, then set the data transition + // to instantaneous. + if(hasAxisTransition) { + traceTransitionOpts = Lib.extendFlat({}, transitionOpts); + traceTransitionOpts.duration = 0; + } else { + traceTransitionOpts = transitionOpts; + } + + for(j = 0; j < basePlotModules.length; j++) { + // Note that we pass a callback to *create* the callback that must be invoked on completion. + // This is since not all traces know about transitions, so it greatly simplifies matters if + // the trace is responsible for creating a callback, if needed, and then executing it when + // the time is right. + basePlotModules[j].plot(gd, transitionedTraces, traceTransitionOpts, makeCallback); + } + + // If nothing else creates a callback, then this will trigger the completion in the next tick: + setTimeout(makeCallback()); + + }); + } + + function completeTransition(callback) { + // This a simple workaround for tests which purge the graph before animations + // have completed. That's not a very common case, so this is the simplest + // fix. + if(!gd._transitionData) return; + + flushCallbacks(gd._transitionData._interruptCallbacks); + + return Promise.resolve().then(function() { + if(frameOpts.redraw) { + return Plotly.redraw(gd); + } + }).then(function() { + // Set transitioning false again once the redraw has occurred. This is used, for example, + // to prevent the trailing redraw from autoranging: + gd._transitioning = false; + gd._transitioningWithDuration = false; + + gd.emit('plotly_transitioned', []); + }).then(callback); + } + + function interruptPreviousTransitions() { + // Fail-safe against purged plot: + if(!gd._transitionData) return; + + // If a transition is interrupted, set this to false. At the moment, the only thing that would + // interrupt a transition is another transition, so that it will momentarily be set to true + // again, but this determines whether autorange or dragbox work, so it's for the sake of + // cleanliness: + gd._transitioning = false; + + return executeCallbacks(gd._transitionData._interruptCallbacks); + } + + for(i = 0; i < traceIndices.length; i++) { + traceIdx = traceIndices[i]; + var contFull = gd._fullData[traceIdx]; + var module = contFull._module; + + if(!module) continue; + + if(!module.animatable) { + var thisUpdate = {}; + + for(var ai in data[i]) { + thisUpdate[ai] = [data[i][ai]]; + } + } + } + + var seq = [plots.previousPromises, interruptPreviousTransitions, prepareTransitions, executeTransitions]; + + var transitionStarting = Lib.syncOrAsync(seq, gd); + + if(!transitionStarting || !transitionStarting.then) { + transitionStarting = Promise.resolve(); + } + + return transitionStarting.then(function() { + return gd; + }); +}; + +plots.doCalcdata = function(gd, traces) { + var axList = Plotly.Axes.list(gd), + fullData = gd._fullData, + fullLayout = gd._fullLayout, + i, j; + + // XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without + // *all* needing doCalcdata: + var calcdata = new Array(fullData.length); + var oldCalcdata = (gd.calcdata || []).slice(0); + gd.calcdata = calcdata; + + // extra helper variables + // firstscatter: fill-to-next on the first trace goes to zero + gd.firstscatter = true; + + // how many box plots do we have (in case they're grouped) + gd.numboxes = 0; + + // for calculating avg luminosity of heatmaps + gd._hmpixcount = 0; + gd._hmlumcount = 0; + + // for sharing colors across pies (and for legend) + fullLayout._piecolormap = {}; + fullLayout._piedefaultcolorcount = 0; + + // initialize the category list, if there is one, so we start over + // to be filled in later by ax.d2c + for(i = 0; i < axList.length; i++) { + axList[i]._categories = axList[i]._initialCategories.slice(); + } + + for(i = 0; i < fullData.length; i++) { + // If traces were specified and this trace was not included, then transfer it over from + // the old calcdata: + if(Array.isArray(traces) && traces.indexOf(i) === -1) { + calcdata[i] = oldCalcdata[i]; + continue; + } + + var trace = fullData[i], + cd = []; + + // If traces were specified and this trace was not included, then transfer it over from + // the old calcdata: + if(Array.isArray(traces) && traces.indexOf(i) === -1) { + calcdata[i] = oldCalcdata[i]; + continue; + } + + var _module; + if(trace.visible === true) { + + // call calcTransform method if any + if(trace.transforms) { + + // we need one round of trace module calc before + // the calc transform to 'fill in' the categories list + // used for example in the data-to-coordinate method + _module = trace._module; + if(_module && _module.calc) _module.calc(gd, trace); + + for(j = 0; j < trace.transforms.length; j++) { + var transform = trace.transforms[j]; + + _module = transformsRegistry[transform.type]; + if(_module && _module.calcTransform) { + _module.calcTransform(gd, trace, transform); + } + } + } + + _module = trace._module; + if(_module && _module.calc) cd = _module.calc(gd, trace); + } + + // Make sure there is a first point. + // + // This ensures there is a calcdata item for every trace, + // even if cartesian logic doesn't handle it (for things like legends). + // + // Tag this artificial calc point with 'placeholder: true', + // to make it easier to skip over them in during the plot and hover step. + if(!Array.isArray(cd) || !cd[0]) { + cd = [{x: false, y: false, placeholder: true}]; + } + + // add the trace-wide properties to the first point, + // per point properties to every point + // t is the holder for trace-wide properties + if(!cd[0].t) cd[0].t = {}; + cd[0].trace = trace; + + calcdata[i] = cd; + } +}; + +},{"../components/color":27,"../components/errorbars":56,"../lib":122,"../plotly":145,"../registry":194,"./animation_attributes":146,"./attributes":148,"./command":169,"./font_attributes":170,"./frame_attributes":171,"./layout_attributes":184,"d3":10,"fast-isnumeric":13}],187:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = require('../../traces/scatter/attributes'); +var scatterMarkerAttrs = scatterAttrs.marker; + +module.exports = { + r: scatterAttrs.r, + t: scatterAttrs.t, + marker: { + color: scatterMarkerAttrs.color, + size: scatterMarkerAttrs.size, + symbol: scatterMarkerAttrs.symbol, + opacity: scatterMarkerAttrs.opacity + } +}; + +},{"../../traces/scatter/attributes":234}],188:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var axesAttrs = require('../cartesian/layout_attributes'); +var extendFlat = require('../../lib/extend').extendFlat; + +var domainAttr = extendFlat({}, axesAttrs.domain, { + +}); + +function mergeAttrs(axisName, nonCommonAttrs) { + var commonAttrs = { + showline: { + valType: 'boolean', + + + }, + showticklabels: { + valType: 'boolean', + + + }, + tickorientation: { + valType: 'enumerated', + values: ['horizontal', 'vertical'], + + + }, + ticklen: { + valType: 'number', + min: 0, + + + }, + tickcolor: { + valType: 'color', + + + }, + ticksuffix: { + valType: 'string', + + + }, + endpadding: { + valType: 'number', + + }, + visible: { + valType: 'boolean', + + + } + }; + + return extendFlat({}, nonCommonAttrs, commonAttrs); +} + +module.exports = { + radialaxis: mergeAttrs('radial', { + range: { + valType: 'info_array', + + items: [ + { valType: 'number' }, + { valType: 'number' } + ], + + }, + domain: domainAttr, + orientation: { + valType: 'number', + + + } + }), + + angularaxis: mergeAttrs('angular', { + range: { + valType: 'info_array', + + items: [ + { valType: 'number', dflt: 0 }, + { valType: 'number', dflt: 360 } + ], + + }, + domain: domainAttr + }), + + // attributes that appear at layout root + layout: { + direction: { + valType: 'enumerated', + values: ['clockwise', 'counterclockwise'], + + + }, + orientation: { + valType: 'angle', + + + } + } +}; + +},{"../../lib/extend":117,"../cartesian/layout_attributes":159}],189:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Polar = module.exports = require('./micropolar'); + +Polar.manager = require('./micropolar_manager'); + +},{"./micropolar":190,"./micropolar_manager":191}],190:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +var d3 = require('d3'); +var Lib = require('../../lib'); +var extendDeepAll = Lib.extendDeepAll; + +var µ = module.exports = { version: '0.2.2' }; + +µ.Axis = function module() { + var config = { + data: [], + layout: {} + }, inputConfig = {}, liveConfig = {}; + var svg, container, dispatch = d3.dispatch('hover'), radialScale, angularScale; + var exports = {}; + function render(_container) { + container = _container || container; + var data = config.data; + var axisConfig = config.layout; + if (typeof container == 'string' || container.nodeName) container = d3.select(container); + container.datum(data).each(function(_data, _index) { + var dataOriginal = _data.slice(); + liveConfig = { + data: µ.util.cloneJson(dataOriginal), + layout: µ.util.cloneJson(axisConfig) + }; + var colorIndex = 0; + dataOriginal.forEach(function(d, i) { + if (!d.color) { + d.color = axisConfig.defaultColorRange[colorIndex]; + colorIndex = (colorIndex + 1) % axisConfig.defaultColorRange.length; + } + if (!d.strokeColor) { + d.strokeColor = d.geometry === 'LinePlot' ? d.color : d3.rgb(d.color).darker().toString(); + } + liveConfig.data[i].color = d.color; + liveConfig.data[i].strokeColor = d.strokeColor; + liveConfig.data[i].strokeDash = d.strokeDash; + liveConfig.data[i].strokeSize = d.strokeSize; + }); + var data = dataOriginal.filter(function(d, i) { + var visible = d.visible; + return typeof visible === 'undefined' || visible === true; + }); + var isStacked = false; + var dataWithGroupId = data.map(function(d, i) { + isStacked = isStacked || typeof d.groupId !== 'undefined'; + return d; + }); + if (isStacked) { + var grouped = d3.nest().key(function(d, i) { + return typeof d.groupId != 'undefined' ? d.groupId : 'unstacked'; + }).entries(dataWithGroupId); + var dataYStack = []; + var stacked = grouped.map(function(d, i) { + if (d.key === 'unstacked') return d.values; else { + var prevArray = d.values[0].r.map(function(d, i) { + return 0; + }); + d.values.forEach(function(d, i, a) { + d.yStack = [ prevArray ]; + dataYStack.push(prevArray); + prevArray = µ.util.sumArrays(d.r, prevArray); + }); + return d.values; + } + }); + data = d3.merge(stacked); + } + data.forEach(function(d, i) { + d.t = Array.isArray(d.t[0]) ? d.t : [ d.t ]; + d.r = Array.isArray(d.r[0]) ? d.r : [ d.r ]; + }); + var radius = Math.min(axisConfig.width - axisConfig.margin.left - axisConfig.margin.right, axisConfig.height - axisConfig.margin.top - axisConfig.margin.bottom) / 2; + radius = Math.max(10, radius); + var chartCenter = [ axisConfig.margin.left + radius, axisConfig.margin.top + radius ]; + var extent; + if (isStacked) { + var highestStackedValue = d3.max(µ.util.sumArrays(µ.util.arrayLast(data).r[0], µ.util.arrayLast(dataYStack))); + extent = [ 0, highestStackedValue ]; + } else extent = d3.extent(µ.util.flattenArray(data.map(function(d, i) { + return d.r; + }))); + if (axisConfig.radialAxis.domain != µ.DATAEXTENT) extent[0] = 0; + radialScale = d3.scale.linear().domain(axisConfig.radialAxis.domain != µ.DATAEXTENT && axisConfig.radialAxis.domain ? axisConfig.radialAxis.domain : extent).range([ 0, radius ]); + liveConfig.layout.radialAxis.domain = radialScale.domain(); + var angularDataMerged = µ.util.flattenArray(data.map(function(d, i) { + return d.t; + })); + var isOrdinal = typeof angularDataMerged[0] === 'string'; + var ticks; + if (isOrdinal) { + angularDataMerged = µ.util.deduplicate(angularDataMerged); + ticks = angularDataMerged.slice(); + angularDataMerged = d3.range(angularDataMerged.length); + data = data.map(function(d, i) { + var result = d; + d.t = [ angularDataMerged ]; + if (isStacked) result.yStack = d.yStack; + return result; + }); + } + var hasOnlyLineOrDotPlot = data.filter(function(d, i) { + return d.geometry === 'LinePlot' || d.geometry === 'DotPlot'; + }).length === data.length; + var needsEndSpacing = axisConfig.needsEndSpacing === null ? isOrdinal || !hasOnlyLineOrDotPlot : axisConfig.needsEndSpacing; + var useProvidedDomain = axisConfig.angularAxis.domain && axisConfig.angularAxis.domain != µ.DATAEXTENT && !isOrdinal && axisConfig.angularAxis.domain[0] >= 0; + var angularDomain = useProvidedDomain ? axisConfig.angularAxis.domain : d3.extent(angularDataMerged); + var angularDomainStep = Math.abs(angularDataMerged[1] - angularDataMerged[0]); + if (hasOnlyLineOrDotPlot && !isOrdinal) angularDomainStep = 0; + var angularDomainWithPadding = angularDomain.slice(); + if (needsEndSpacing && isOrdinal) angularDomainWithPadding[1] += angularDomainStep; + var tickCount = axisConfig.angularAxis.ticksCount || 4; + if (tickCount > 8) tickCount = tickCount / (tickCount / 8) + tickCount % 8; + if (axisConfig.angularAxis.ticksStep) { + tickCount = (angularDomainWithPadding[1] - angularDomainWithPadding[0]) / tickCount; + } + var angularTicksStep = axisConfig.angularAxis.ticksStep || (angularDomainWithPadding[1] - angularDomainWithPadding[0]) / (tickCount * (axisConfig.minorTicks + 1)); + if (ticks) angularTicksStep = Math.max(Math.round(angularTicksStep), 1); + if (!angularDomainWithPadding[2]) angularDomainWithPadding[2] = angularTicksStep; + var angularAxisRange = d3.range.apply(this, angularDomainWithPadding); + angularAxisRange = angularAxisRange.map(function(d, i) { + return parseFloat(d.toPrecision(12)); + }); + angularScale = d3.scale.linear().domain(angularDomainWithPadding.slice(0, 2)).range(axisConfig.direction === 'clockwise' ? [ 0, 360 ] : [ 360, 0 ]); + liveConfig.layout.angularAxis.domain = angularScale.domain(); + liveConfig.layout.angularAxis.endPadding = needsEndSpacing ? angularDomainStep : 0; + svg = d3.select(this).select('svg.chart-root'); + if (typeof svg === 'undefined' || svg.empty()) { + var skeleton = "' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '"; + var doc = new DOMParser().parseFromString(skeleton, 'application/xml'); + var newSvg = this.appendChild(this.ownerDocument.importNode(doc.documentElement, true)); + svg = d3.select(newSvg); + } + svg.select('.guides-group').style({ + 'pointer-events': 'none' + }); + svg.select('.angular.axis-group').style({ + 'pointer-events': 'none' + }); + svg.select('.radial.axis-group').style({ + 'pointer-events': 'none' + }); + var chartGroup = svg.select('.chart-group'); + var lineStyle = { + fill: 'none', + stroke: axisConfig.tickColor + }; + var fontStyle = { + 'font-size': axisConfig.font.size, + 'font-family': axisConfig.font.family, + fill: axisConfig.font.color, + 'text-shadow': [ '-1px 0px', '1px -1px', '-1px 1px', '1px 1px' ].map(function(d, i) { + return ' ' + d + ' 0 ' + axisConfig.font.outlineColor; + }).join(',') + }; + var legendContainer; + if (axisConfig.showLegend) { + legendContainer = svg.select('.legend-group').attr({ + transform: 'translate(' + [ radius, axisConfig.margin.top ] + ')' + }).style({ + display: 'block' + }); + var elements = data.map(function(d, i) { + var datumClone = µ.util.cloneJson(d); + datumClone.symbol = d.geometry === 'DotPlot' ? d.dotType || 'circle' : d.geometry != 'LinePlot' ? 'square' : 'line'; + datumClone.visibleInLegend = typeof d.visibleInLegend === 'undefined' || d.visibleInLegend; + datumClone.color = d.geometry === 'LinePlot' ? d.strokeColor : d.color; + return datumClone; + }); + + µ.Legend().config({ + data: data.map(function(d, i) { + return d.name || 'Element' + i; + }), + legendConfig: extendDeepAll({}, + µ.Legend.defaultConfig().legendConfig, + { + container: legendContainer, + elements: elements, + reverseOrder: axisConfig.legend.reverseOrder + } + ) + })(); + + var legendBBox = legendContainer.node().getBBox(); + radius = Math.min(axisConfig.width - legendBBox.width - axisConfig.margin.left - axisConfig.margin.right, axisConfig.height - axisConfig.margin.top - axisConfig.margin.bottom) / 2; + radius = Math.max(10, radius); + chartCenter = [ axisConfig.margin.left + radius, axisConfig.margin.top + radius ]; + radialScale.range([ 0, radius ]); + liveConfig.layout.radialAxis.domain = radialScale.domain(); + legendContainer.attr('transform', 'translate(' + [ chartCenter[0] + radius, chartCenter[1] - radius ] + ')'); + } else { + legendContainer = svg.select('.legend-group').style({ + display: 'none' + }); + } + svg.attr({ + width: axisConfig.width, + height: axisConfig.height + }).style({ + opacity: axisConfig.opacity + }); + chartGroup.attr('transform', 'translate(' + chartCenter + ')').style({ + cursor: 'crosshair' + }); + var centeringOffset = [ (axisConfig.width - (axisConfig.margin.left + axisConfig.margin.right + radius * 2 + (legendBBox ? legendBBox.width : 0))) / 2, (axisConfig.height - (axisConfig.margin.top + axisConfig.margin.bottom + radius * 2)) / 2 ]; + centeringOffset[0] = Math.max(0, centeringOffset[0]); + centeringOffset[1] = Math.max(0, centeringOffset[1]); + svg.select('.outer-group').attr('transform', 'translate(' + centeringOffset + ')'); + if (axisConfig.title) { + var title = svg.select('g.title-group text').style(fontStyle).text(axisConfig.title); + var titleBBox = title.node().getBBox(); + title.attr({ + x: chartCenter[0] - titleBBox.width / 2, + y: chartCenter[1] - radius - 20 + }); + } + var radialAxis = svg.select('.radial.axis-group'); + if (axisConfig.radialAxis.gridLinesVisible) { + var gridCircles = radialAxis.selectAll('circle.grid-circle').data(radialScale.ticks(5)); + gridCircles.enter().append('circle').attr({ + 'class': 'grid-circle' + }).style(lineStyle); + gridCircles.attr('r', radialScale); + gridCircles.exit().remove(); + } + radialAxis.select('circle.outside-circle').attr({ + r: radius + }).style(lineStyle); + var backgroundCircle = svg.select('circle.background-circle').attr({ + r: radius + }).style({ + fill: axisConfig.backgroundColor, + stroke: axisConfig.stroke + }); + function currentAngle(d, i) { + return angularScale(d) % 360 + axisConfig.orientation; + } + if (axisConfig.radialAxis.visible) { + var axis = d3.svg.axis().scale(radialScale).ticks(5).tickSize(5); + radialAxis.call(axis).attr({ + transform: 'rotate(' + axisConfig.radialAxis.orientation + ')' + }); + radialAxis.selectAll('.domain').style(lineStyle); + radialAxis.selectAll('g>text').text(function(d, i) { + return this.textContent + axisConfig.radialAxis.ticksSuffix; + }).style(fontStyle).style({ + 'text-anchor': 'start' + }).attr({ + x: 0, + y: 0, + dx: 0, + dy: 0, + transform: function(d, i) { + if (axisConfig.radialAxis.tickOrientation === 'horizontal') { + return 'rotate(' + -axisConfig.radialAxis.orientation + ') translate(' + [ 0, fontStyle['font-size'] ] + ')'; + } else return 'translate(' + [ 0, fontStyle['font-size'] ] + ')'; + } + }); + radialAxis.selectAll('g>line').style({ + stroke: 'black' + }); + } + var angularAxis = svg.select('.angular.axis-group').selectAll('g.angular-tick').data(angularAxisRange); + var angularAxisEnter = angularAxis.enter().append('g').classed('angular-tick', true); + angularAxis.attr({ + transform: function(d, i) { + return 'rotate(' + currentAngle(d, i) + ')'; + } + }).style({ + display: axisConfig.angularAxis.visible ? 'block' : 'none' + }); + angularAxis.exit().remove(); + angularAxisEnter.append('line').classed('grid-line', true).classed('major', function(d, i) { + return i % (axisConfig.minorTicks + 1) == 0; + }).classed('minor', function(d, i) { + return !(i % (axisConfig.minorTicks + 1) == 0); + }).style(lineStyle); + angularAxisEnter.selectAll('.minor').style({ + stroke: axisConfig.minorTickColor + }); + angularAxis.select('line.grid-line').attr({ + x1: axisConfig.tickLength ? radius - axisConfig.tickLength : 0, + x2: radius + }).style({ + display: axisConfig.angularAxis.gridLinesVisible ? 'block' : 'none' + }); + angularAxisEnter.append('text').classed('axis-text', true).style(fontStyle); + var ticksText = angularAxis.select('text.axis-text').attr({ + x: radius + axisConfig.labelOffset, + dy: '.35em', + transform: function(d, i) { + var angle = currentAngle(d, i); + var rad = radius + axisConfig.labelOffset; + var orient = axisConfig.angularAxis.tickOrientation; + if (orient == 'horizontal') return 'rotate(' + -angle + ' ' + rad + ' 0)'; else if (orient == 'radial') return angle < 270 && angle > 90 ? 'rotate(180 ' + rad + ' 0)' : null; else return 'rotate(' + (angle <= 180 && angle > 0 ? -90 : 90) + ' ' + rad + ' 0)'; + } + }).style({ + 'text-anchor': 'middle', + display: axisConfig.angularAxis.labelsVisible ? 'block' : 'none' + }).text(function(d, i) { + if (i % (axisConfig.minorTicks + 1) != 0) return ''; + if (ticks) { + return ticks[d] + axisConfig.angularAxis.ticksSuffix; + } else return d + axisConfig.angularAxis.ticksSuffix; + }).style(fontStyle); + if (axisConfig.angularAxis.rewriteTicks) ticksText.text(function(d, i) { + if (i % (axisConfig.minorTicks + 1) != 0) return ''; + return axisConfig.angularAxis.rewriteTicks(this.textContent, i); + }); + var rightmostTickEndX = d3.max(chartGroup.selectAll('.angular-tick text')[0].map(function(d, i) { + return d.getCTM().e + d.getBBox().width; + })); + legendContainer.attr({ + transform: 'translate(' + [ radius + rightmostTickEndX, axisConfig.margin.top ] + ')' + }); + var hasGeometry = svg.select('g.geometry-group').selectAll('g').size() > 0; + var geometryContainer = svg.select('g.geometry-group').selectAll('g.geometry').data(data); + geometryContainer.enter().append('g').attr({ + 'class': function(d, i) { + return 'geometry geometry' + i; + } + }); + geometryContainer.exit().remove(); + if (data[0] || hasGeometry) { + var geometryConfigs = []; + data.forEach(function(d, i) { + var geometryConfig = {}; + geometryConfig.radialScale = radialScale; + geometryConfig.angularScale = angularScale; + geometryConfig.container = geometryContainer.filter(function(dB, iB) { + return iB == i; + }); + geometryConfig.geometry = d.geometry; + geometryConfig.orientation = axisConfig.orientation; + geometryConfig.direction = axisConfig.direction; + geometryConfig.index = i; + geometryConfigs.push({ + data: d, + geometryConfig: geometryConfig + }); + }); + var geometryConfigsGrouped = d3.nest().key(function(d, i) { + return typeof d.data.groupId != 'undefined' || 'unstacked'; + }).entries(geometryConfigs); + var geometryConfigsGrouped2 = []; + geometryConfigsGrouped.forEach(function(d, i) { + if (d.key === 'unstacked') geometryConfigsGrouped2 = geometryConfigsGrouped2.concat(d.values.map(function(d, i) { + return [ d ]; + })); else geometryConfigsGrouped2.push(d.values); + }); + geometryConfigsGrouped2.forEach(function(d, i) { + var geometry; + if (Array.isArray(d)) geometry = d[0].geometryConfig.geometry; else geometry = d.geometryConfig.geometry; + var finalGeometryConfig = d.map(function(dB, iB) { + return extendDeepAll(µ[geometry].defaultConfig(), dB); + }); + µ[geometry]().config(finalGeometryConfig)(); + }); + } + var guides = svg.select('.guides-group'); + var tooltipContainer = svg.select('.tooltips-group'); + var angularTooltip = µ.tooltipPanel().config({ + container: tooltipContainer, + fontSize: 8 + })(); + var radialTooltip = µ.tooltipPanel().config({ + container: tooltipContainer, + fontSize: 8 + })(); + var geometryTooltip = µ.tooltipPanel().config({ + container: tooltipContainer, + hasTick: true + })(); + var angularValue, radialValue; + if (!isOrdinal) { + var angularGuideLine = guides.select('line').attr({ + x1: 0, + y1: 0, + y2: 0 + }).style({ + stroke: 'grey', + 'pointer-events': 'none' + }); + chartGroup.on('mousemove.angular-guide', function(d, i) { + var mouseAngle = µ.util.getMousePos(backgroundCircle).angle; + angularGuideLine.attr({ + x2: -radius, + transform: 'rotate(' + mouseAngle + ')' + }).style({ + opacity: .5 + }); + var angleWithOriginOffset = (mouseAngle + 180 + 360 - axisConfig.orientation) % 360; + angularValue = angularScale.invert(angleWithOriginOffset); + var pos = µ.util.convertToCartesian(radius + 12, mouseAngle + 180); + angularTooltip.text(µ.util.round(angularValue)).move([ pos[0] + chartCenter[0], pos[1] + chartCenter[1] ]); + }).on('mouseout.angular-guide', function(d, i) { + guides.select('line').style({ + opacity: 0 + }); + }); + } + var angularGuideCircle = guides.select('circle').style({ + stroke: 'grey', + fill: 'none' + }); + chartGroup.on('mousemove.radial-guide', function(d, i) { + var r = µ.util.getMousePos(backgroundCircle).radius; + angularGuideCircle.attr({ + r: r + }).style({ + opacity: .5 + }); + radialValue = radialScale.invert(µ.util.getMousePos(backgroundCircle).radius); + var pos = µ.util.convertToCartesian(r, axisConfig.radialAxis.orientation); + radialTooltip.text(µ.util.round(radialValue)).move([ pos[0] + chartCenter[0], pos[1] + chartCenter[1] ]); + }).on('mouseout.radial-guide', function(d, i) { + angularGuideCircle.style({ + opacity: 0 + }); + geometryTooltip.hide(); + angularTooltip.hide(); + radialTooltip.hide(); + }); + svg.selectAll('.geometry-group .mark').on('mouseover.tooltip', function(d, i) { + var el = d3.select(this); + var color = el.style('fill'); + var newColor = 'black'; + var opacity = el.style('opacity') || 1; + el.attr({ + 'data-opacity': opacity + }); + if (color != 'none') { + el.attr({ + 'data-fill': color + }); + newColor = d3.hsl(color).darker().toString(); + el.style({ + fill: newColor, + opacity: 1 + }); + var textData = { + t: µ.util.round(d[0]), + r: µ.util.round(d[1]) + }; + if (isOrdinal) textData.t = ticks[d[0]]; + var text = 't: ' + textData.t + ', r: ' + textData.r; + var bbox = this.getBoundingClientRect(); + var svgBBox = svg.node().getBoundingClientRect(); + var pos = [ bbox.left + bbox.width / 2 - centeringOffset[0] - svgBBox.left, bbox.top + bbox.height / 2 - centeringOffset[1] - svgBBox.top ]; + geometryTooltip.config({ + color: newColor + }).text(text); + geometryTooltip.move(pos); + } else { + color = el.style('stroke'); + el.attr({ + 'data-stroke': color + }); + newColor = d3.hsl(color).darker().toString(); + el.style({ + stroke: newColor, + opacity: 1 + }); + } + }).on('mousemove.tooltip', function(d, i) { + if (d3.event.which != 0) return false; + if (d3.select(this).attr('data-fill')) geometryTooltip.show(); + }).on('mouseout.tooltip', function(d, i) { + geometryTooltip.hide(); + var el = d3.select(this); + var fillColor = el.attr('data-fill'); + if (fillColor) el.style({ + fill: fillColor, + opacity: el.attr('data-opacity') + }); else el.style({ + stroke: el.attr('data-stroke'), + opacity: el.attr('data-opacity') + }); + }); + }); + return exports; + } + exports.render = function(_container) { + render(_container); + return this; + }; + exports.config = function(_x) { + if (!arguments.length) return config; + var xClone = µ.util.cloneJson(_x); + xClone.data.forEach(function(d, i) { + if (!config.data[i]) config.data[i] = {}; + extendDeepAll(config.data[i], µ.Axis.defaultConfig().data[0]); + extendDeepAll(config.data[i], d); + }); + extendDeepAll(config.layout, µ.Axis.defaultConfig().layout); + extendDeepAll(config.layout, xClone.layout); + return this; + }; + exports.getLiveConfig = function() { + return liveConfig; + }; + exports.getinputConfig = function() { + return inputConfig; + }; + exports.radialScale = function(_x) { + return radialScale; + }; + exports.angularScale = function(_x) { + return angularScale; + }; + exports.svg = function() { + return svg; + }; + d3.rebind(exports, dispatch, 'on'); + return exports; +}; + +µ.Axis.defaultConfig = function(d, i) { + var config = { + data: [ { + t: [ 1, 2, 3, 4 ], + r: [ 10, 11, 12, 13 ], + name: 'Line1', + geometry: 'LinePlot', + color: null, + strokeDash: 'solid', + strokeColor: null, + strokeSize: '1', + visibleInLegend: true, + opacity: 1 + } ], + layout: { + defaultColorRange: d3.scale.category10().range(), + title: null, + height: 450, + width: 500, + margin: { + top: 40, + right: 40, + bottom: 40, + left: 40 + }, + font: { + size: 12, + color: 'gray', + outlineColor: 'white', + family: 'Tahoma, sans-serif' + }, + direction: 'clockwise', + orientation: 0, + labelOffset: 10, + radialAxis: { + domain: null, + orientation: -45, + ticksSuffix: '', + visible: true, + gridLinesVisible: true, + tickOrientation: 'horizontal', + rewriteTicks: null + }, + angularAxis: { + domain: [ 0, 360 ], + ticksSuffix: '', + visible: true, + gridLinesVisible: true, + labelsVisible: true, + tickOrientation: 'horizontal', + rewriteTicks: null, + ticksCount: null, + ticksStep: null + }, + minorTicks: 0, + tickLength: null, + tickColor: 'silver', + minorTickColor: '#eee', + backgroundColor: 'none', + needsEndSpacing: null, + showLegend: true, + legend: { + reverseOrder: false + }, + opacity: 1 + } + }; + return config; +}; + +µ.util = {}; + +µ.DATAEXTENT = 'dataExtent'; + +µ.AREA = 'AreaChart'; + +µ.LINE = 'LinePlot'; + +µ.DOT = 'DotPlot'; + +µ.BAR = 'BarChart'; + +µ.util._override = function(_objA, _objB) { + for (var x in _objA) if (x in _objB) _objB[x] = _objA[x]; +}; + +µ.util._extend = function(_objA, _objB) { + for (var x in _objA) _objB[x] = _objA[x]; +}; + +µ.util._rndSnd = function() { + return Math.random() * 2 - 1 + (Math.random() * 2 - 1) + (Math.random() * 2 - 1); +}; + +µ.util.dataFromEquation2 = function(_equation, _step) { + var step = _step || 6; + var data = d3.range(0, 360 + step, step).map(function(deg, index) { + var theta = deg * Math.PI / 180; + var radius = _equation(theta); + return [ deg, radius ]; + }); + return data; +}; + +µ.util.dataFromEquation = function(_equation, _step, _name) { + var step = _step || 6; + var t = [], r = []; + d3.range(0, 360 + step, step).forEach(function(deg, index) { + var theta = deg * Math.PI / 180; + var radius = _equation(theta); + t.push(deg); + r.push(radius); + }); + var result = { + t: t, + r: r + }; + if (_name) result.name = _name; + return result; +}; + +µ.util.ensureArray = function(_val, _count) { + if (typeof _val === 'undefined') return null; + var arr = [].concat(_val); + return d3.range(_count).map(function(d, i) { + return arr[i] || arr[0]; + }); +}; + +µ.util.fillArrays = function(_obj, _valueNames, _count) { + _valueNames.forEach(function(d, i) { + _obj[d] = µ.util.ensureArray(_obj[d], _count); + }); + return _obj; +}; + +µ.util.cloneJson = function(json) { + return JSON.parse(JSON.stringify(json)); +}; + +µ.util.validateKeys = function(obj, keys) { + if (typeof keys === 'string') keys = keys.split('.'); + var next = keys.shift(); + return obj[next] && (!keys.length || objHasKeys(obj[next], keys)); +}; + +µ.util.sumArrays = function(a, b) { + return d3.zip(a, b).map(function(d, i) { + return d3.sum(d); + }); +}; + +µ.util.arrayLast = function(a) { + return a[a.length - 1]; +}; + +µ.util.arrayEqual = function(a, b) { + var i = Math.max(a.length, b.length, 1); + while (i-- >= 0 && a[i] === b[i]) ; + return i === -2; +}; + +µ.util.flattenArray = function(arr) { + var r = []; + while (!µ.util.arrayEqual(r, arr)) { + r = arr; + arr = [].concat.apply([], arr); + } + return arr; +}; + +µ.util.deduplicate = function(arr) { + return arr.filter(function(v, i, a) { + return a.indexOf(v) == i; + }); +}; + +µ.util.convertToCartesian = function(radius, theta) { + var thetaRadians = theta * Math.PI / 180; + var x = radius * Math.cos(thetaRadians); + var y = radius * Math.sin(thetaRadians); + return [ x, y ]; +}; + +µ.util.round = function(_value, _digits) { + var digits = _digits || 2; + var mult = Math.pow(10, digits); + return Math.round(_value * mult) / mult; +}; + +µ.util.getMousePos = function(_referenceElement) { + var mousePos = d3.mouse(_referenceElement.node()); + var mouseX = mousePos[0]; + var mouseY = mousePos[1]; + var mouse = {}; + mouse.x = mouseX; + mouse.y = mouseY; + mouse.pos = mousePos; + mouse.angle = (Math.atan2(mouseY, mouseX) + Math.PI) * 180 / Math.PI; + mouse.radius = Math.sqrt(mouseX * mouseX + mouseY * mouseY); + return mouse; +}; + +µ.util.duplicatesCount = function(arr) { + var uniques = {}, val; + var dups = {}; + for (var i = 0, len = arr.length; i < len; i++) { + val = arr[i]; + if (val in uniques) { + uniques[val]++; + dups[val] = uniques[val]; + } else { + uniques[val] = 1; + } + } + return dups; +}; + +µ.util.duplicates = function(arr) { + return Object.keys(µ.util.duplicatesCount(arr)); +}; + +µ.util.translator = function(obj, sourceBranch, targetBranch, reverse) { + if (reverse) { + var targetBranchCopy = targetBranch.slice(); + targetBranch = sourceBranch; + sourceBranch = targetBranchCopy; + } + var value = sourceBranch.reduce(function(previousValue, currentValue) { + if (typeof previousValue != 'undefined') return previousValue[currentValue]; + }, obj); + if (typeof value === 'undefined') return; + sourceBranch.reduce(function(previousValue, currentValue, index) { + if (typeof previousValue == 'undefined') return; + if (index === sourceBranch.length - 1) delete previousValue[currentValue]; + return previousValue[currentValue]; + }, obj); + targetBranch.reduce(function(previousValue, currentValue, index) { + if (typeof previousValue[currentValue] === 'undefined') previousValue[currentValue] = {}; + if (index === targetBranch.length - 1) previousValue[currentValue] = value; + return previousValue[currentValue]; + }, obj); +}; + +µ.PolyChart = function module() { + var config = [ µ.PolyChart.defaultConfig() ]; + var dispatch = d3.dispatch('hover'); + var dashArray = { + solid: 'none', + dash: [ 5, 2 ], + dot: [ 2, 5 ] + }; + var colorScale; + function exports() { + var geometryConfig = config[0].geometryConfig; + var container = geometryConfig.container; + if (typeof container == 'string') container = d3.select(container); + container.datum(config).each(function(_config, _index) { + var isStack = !!_config[0].data.yStack; + var data = _config.map(function(d, i) { + if (isStack) return d3.zip(d.data.t[0], d.data.r[0], d.data.yStack[0]); else return d3.zip(d.data.t[0], d.data.r[0]); + }); + var angularScale = geometryConfig.angularScale; + var domainMin = geometryConfig.radialScale.domain()[0]; + var generator = {}; + generator.bar = function(d, i, pI) { + var dataConfig = _config[pI].data; + var h = geometryConfig.radialScale(d[1]) - geometryConfig.radialScale(0); + var stackTop = geometryConfig.radialScale(d[2] || 0); + var w = dataConfig.barWidth; + d3.select(this).attr({ + 'class': 'mark bar', + d: 'M' + [ [ h + stackTop, -w / 2 ], [ h + stackTop, w / 2 ], [ stackTop, w / 2 ], [ stackTop, -w / 2 ] ].join('L') + 'Z', + transform: function(d, i) { + return 'rotate(' + (geometryConfig.orientation + angularScale(d[0])) + ')'; + } + }); + }; + generator.dot = function(d, i, pI) { + var stackedData = d[2] ? [ d[0], d[1] + d[2] ] : d; + var symbol = d3.svg.symbol().size(_config[pI].data.dotSize).type(_config[pI].data.dotType)(d, i); + d3.select(this).attr({ + 'class': 'mark dot', + d: symbol, + transform: function(d, i) { + var coord = convertToCartesian(getPolarCoordinates(stackedData)); + return 'translate(' + [ coord.x, coord.y ] + ')'; + } + }); + }; + var line = d3.svg.line.radial().interpolate(_config[0].data.lineInterpolation).radius(function(d) { + return geometryConfig.radialScale(d[1]); + }).angle(function(d) { + return geometryConfig.angularScale(d[0]) * Math.PI / 180; + }); + generator.line = function(d, i, pI) { + var lineData = d[2] ? data[pI].map(function(d, i) { + return [ d[0], d[1] + d[2] ]; + }) : data[pI]; + d3.select(this).each(generator['dot']).style({ + opacity: function(dB, iB) { + return +_config[pI].data.dotVisible; + }, + fill: markStyle.stroke(d, i, pI) + }).attr({ + 'class': 'mark dot' + }); + if (i > 0) return; + var lineSelection = d3.select(this.parentNode).selectAll('path.line').data([ 0 ]); + lineSelection.enter().insert('path'); + lineSelection.attr({ + 'class': 'line', + d: line(lineData), + transform: function(dB, iB) { + return 'rotate(' + (geometryConfig.orientation + 90) + ')'; + }, + 'pointer-events': 'none' + }).style({ + fill: function(dB, iB) { + return markStyle.fill(d, i, pI); + }, + 'fill-opacity': 0, + stroke: function(dB, iB) { + return markStyle.stroke(d, i, pI); + }, + 'stroke-width': function(dB, iB) { + return markStyle['stroke-width'](d, i, pI); + }, + 'stroke-dasharray': function(dB, iB) { + return markStyle['stroke-dasharray'](d, i, pI); + }, + opacity: function(dB, iB) { + return markStyle.opacity(d, i, pI); + }, + display: function(dB, iB) { + return markStyle.display(d, i, pI); + } + }); + }; + var angularRange = geometryConfig.angularScale.range(); + var triangleAngle = Math.abs(angularRange[1] - angularRange[0]) / data[0].length * Math.PI / 180; + var arc = d3.svg.arc().startAngle(function(d) { + return -triangleAngle / 2; + }).endAngle(function(d) { + return triangleAngle / 2; + }).innerRadius(function(d) { + return geometryConfig.radialScale(domainMin + (d[2] || 0)); + }).outerRadius(function(d) { + return geometryConfig.radialScale(domainMin + (d[2] || 0)) + geometryConfig.radialScale(d[1]); + }); + generator.arc = function(d, i, pI) { + d3.select(this).attr({ + 'class': 'mark arc', + d: arc, + transform: function(d, i) { + return 'rotate(' + (geometryConfig.orientation + angularScale(d[0]) + 90) + ')'; + } + }); + }; + var markStyle = { + fill: function(d, i, pI) { + return _config[pI].data.color; + }, + stroke: function(d, i, pI) { + return _config[pI].data.strokeColor; + }, + 'stroke-width': function(d, i, pI) { + return _config[pI].data.strokeSize + 'px'; + }, + 'stroke-dasharray': function(d, i, pI) { + return dashArray[_config[pI].data.strokeDash]; + }, + opacity: function(d, i, pI) { + return _config[pI].data.opacity; + }, + display: function(d, i, pI) { + return typeof _config[pI].data.visible === 'undefined' || _config[pI].data.visible ? 'block' : 'none'; + } + }; + var geometryLayer = d3.select(this).selectAll('g.layer').data(data); + geometryLayer.enter().append('g').attr({ + 'class': 'layer' + }); + var geometry = geometryLayer.selectAll('path.mark').data(function(d, i) { + return d; + }); + geometry.enter().append('path').attr({ + 'class': 'mark' + }); + geometry.style(markStyle).each(generator[geometryConfig.geometryType]); + geometry.exit().remove(); + geometryLayer.exit().remove(); + function getPolarCoordinates(d, i) { + var r = geometryConfig.radialScale(d[1]); + var t = (geometryConfig.angularScale(d[0]) + geometryConfig.orientation) * Math.PI / 180; + return { + r: r, + t: t + }; + } + function convertToCartesian(polarCoordinates) { + var x = polarCoordinates.r * Math.cos(polarCoordinates.t); + var y = polarCoordinates.r * Math.sin(polarCoordinates.t); + return { + x: x, + y: y + }; + } + }); + } + exports.config = function(_x) { + if (!arguments.length) return config; + _x.forEach(function(d, i) { + if (!config[i]) config[i] = {}; + extendDeepAll(config[i], µ.PolyChart.defaultConfig()); + extendDeepAll(config[i], d); + }); + return this; + }; + exports.getColorScale = function() { + return colorScale; + }; + d3.rebind(exports, dispatch, 'on'); + return exports; +}; + +µ.PolyChart.defaultConfig = function() { + var config = { + data: { + name: 'geom1', + t: [ [ 1, 2, 3, 4 ] ], + r: [ [ 1, 2, 3, 4 ] ], + dotType: 'circle', + dotSize: 64, + dotVisible: false, + barWidth: 20, + color: '#ffa500', + strokeSize: 1, + strokeColor: 'silver', + strokeDash: 'solid', + opacity: 1, + index: 0, + visible: true, + visibleInLegend: true + }, + geometryConfig: { + geometry: 'LinePlot', + geometryType: 'arc', + direction: 'clockwise', + orientation: 0, + container: 'body', + radialScale: null, + angularScale: null, + colorScale: d3.scale.category20() + } + }; + return config; +}; + +µ.BarChart = function module() { + return µ.PolyChart(); +}; + +µ.BarChart.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'bar' + } + }; + return config; +}; + +µ.AreaChart = function module() { + return µ.PolyChart(); +}; + +µ.AreaChart.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'arc' + } + }; + return config; +}; + +µ.DotPlot = function module() { + return µ.PolyChart(); +}; + +µ.DotPlot.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'dot', + dotType: 'circle' + } + }; + return config; +}; + +µ.LinePlot = function module() { + return µ.PolyChart(); +}; + +µ.LinePlot.defaultConfig = function() { + var config = { + geometryConfig: { + geometryType: 'line' + } + }; + return config; +}; + +µ.Legend = function module() { + var config = µ.Legend.defaultConfig(); + var dispatch = d3.dispatch('hover'); + function exports() { + var legendConfig = config.legendConfig; + var flattenData = config.data.map(function(d, i) { + return [].concat(d).map(function(dB, iB) { + var element = extendDeepAll({}, legendConfig.elements[i]); + element.name = dB; + element.color = [].concat(legendConfig.elements[i].color)[iB]; + return element; + }); + }); + var data = d3.merge(flattenData); + data = data.filter(function(d, i) { + return legendConfig.elements[i] && (legendConfig.elements[i].visibleInLegend || typeof legendConfig.elements[i].visibleInLegend === 'undefined'); + }); + if (legendConfig.reverseOrder) data = data.reverse(); + var container = legendConfig.container; + if (typeof container == 'string' || container.nodeName) container = d3.select(container); + var colors = data.map(function(d, i) { + return d.color; + }); + var lineHeight = legendConfig.fontSize; + var isContinuous = legendConfig.isContinuous == null ? typeof data[0] === 'number' : legendConfig.isContinuous; + var height = isContinuous ? legendConfig.height : lineHeight * data.length; + var legendContainerGroup = container.classed('legend-group', true); + var svg = legendContainerGroup.selectAll('svg').data([ 0 ]); + var svgEnter = svg.enter().append('svg').attr({ + width: 300, + height: height + lineHeight, + xmlns: 'http://www.w3.org/2000/svg', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + version: '1.1' + }); + svgEnter.append('g').classed('legend-axis', true); + svgEnter.append('g').classed('legend-marks', true); + var dataNumbered = d3.range(data.length); + var colorScale = d3.scale[isContinuous ? 'linear' : 'ordinal']().domain(dataNumbered).range(colors); + var dataScale = d3.scale[isContinuous ? 'linear' : 'ordinal']().domain(dataNumbered)[isContinuous ? 'range' : 'rangePoints']([ 0, height ]); + var shapeGenerator = function(_type, _size) { + var squareSize = _size * 3; + if (_type === 'line') { + return 'M' + [ [ -_size / 2, -_size / 12 ], [ _size / 2, -_size / 12 ], [ _size / 2, _size / 12 ], [ -_size / 2, _size / 12 ] ] + 'Z'; + } else if (d3.svg.symbolTypes.indexOf(_type) != -1) return d3.svg.symbol().type(_type).size(squareSize)(); else return d3.svg.symbol().type('square').size(squareSize)(); + }; + if (isContinuous) { + var gradient = svg.select('.legend-marks').append('defs').append('linearGradient').attr({ + id: 'grad1', + x1: '0%', + y1: '0%', + x2: '0%', + y2: '100%' + }).selectAll('stop').data(colors); + gradient.enter().append('stop'); + gradient.attr({ + offset: function(d, i) { + return i / (colors.length - 1) * 100 + '%'; + } + }).style({ + 'stop-color': function(d, i) { + return d; + } + }); + svg.append('rect').classed('legend-mark', true).attr({ + height: legendConfig.height, + width: legendConfig.colorBandWidth, + fill: 'url(#grad1)' + }); + } else { + var legendElement = svg.select('.legend-marks').selectAll('path.legend-mark').data(data); + legendElement.enter().append('path').classed('legend-mark', true); + legendElement.attr({ + transform: function(d, i) { + return 'translate(' + [ lineHeight / 2, dataScale(i) + lineHeight / 2 ] + ')'; + }, + d: function(d, i) { + var symbolType = d.symbol; + return shapeGenerator(symbolType, lineHeight); + }, + fill: function(d, i) { + return colorScale(i); + } + }); + legendElement.exit().remove(); + } + var legendAxis = d3.svg.axis().scale(dataScale).orient('right'); + var axis = svg.select('g.legend-axis').attr({ + transform: 'translate(' + [ isContinuous ? legendConfig.colorBandWidth : lineHeight, lineHeight / 2 ] + ')' + }).call(legendAxis); + axis.selectAll('.domain').style({ + fill: 'none', + stroke: 'none' + }); + axis.selectAll('line').style({ + fill: 'none', + stroke: isContinuous ? legendConfig.textColor : 'none' + }); + axis.selectAll('text').style({ + fill: legendConfig.textColor, + 'font-size': legendConfig.fontSize + }).text(function(d, i) { + return data[i].name; + }); + return exports; + } + exports.config = function(_x) { + if (!arguments.length) return config; + extendDeepAll(config, _x); + return this; + }; + d3.rebind(exports, dispatch, 'on'); + return exports; +}; + +µ.Legend.defaultConfig = function(d, i) { + var config = { + data: [ 'a', 'b', 'c' ], + legendConfig: { + elements: [ { + symbol: 'line', + color: 'red' + }, { + symbol: 'square', + color: 'yellow' + }, { + symbol: 'diamond', + color: 'limegreen' + } ], + height: 150, + colorBandWidth: 30, + fontSize: 12, + container: 'body', + isContinuous: null, + textColor: 'grey', + reverseOrder: false + } + }; + return config; +}; + +µ.tooltipPanel = function() { + var tooltipEl, tooltipTextEl, backgroundEl; + var config = { + container: null, + hasTick: false, + fontSize: 12, + color: 'white', + padding: 5 + }; + var id = 'tooltip-' + µ.tooltipPanel.uid++; + var tickSize = 10; + var exports = function() { + tooltipEl = config.container.selectAll('g.' + id).data([ 0 ]); + var tooltipEnter = tooltipEl.enter().append('g').classed(id, true).style({ + 'pointer-events': 'none', + display: 'none' + }); + backgroundEl = tooltipEnter.append('path').style({ + fill: 'white', + 'fill-opacity': .9 + }).attr({ + d: 'M0 0' + }); + tooltipTextEl = tooltipEnter.append('text').attr({ + dx: config.padding + tickSize, + dy: +config.fontSize * .3 + }); + return exports; + }; + exports.text = function(_text) { + var l = d3.hsl(config.color).l; + var strokeColor = l >= .5 ? '#aaa' : 'white'; + var fillColor = l >= .5 ? 'black' : 'white'; + var text = _text || ''; + tooltipTextEl.style({ + fill: fillColor, + 'font-size': config.fontSize + 'px' + }).text(text); + var padding = config.padding; + var bbox = tooltipTextEl.node().getBBox(); + var boxStyle = { + fill: config.color, + stroke: strokeColor, + 'stroke-width': '2px' + }; + var backGroundW = bbox.width + padding * 2 + tickSize; + var backGroundH = bbox.height + padding * 2; + backgroundEl.attr({ + d: 'M' + [ [ tickSize, -backGroundH / 2 ], [ tickSize, -backGroundH / 4 ], [ config.hasTick ? 0 : tickSize, 0 ], [ tickSize, backGroundH / 4 ], [ tickSize, backGroundH / 2 ], [ backGroundW, backGroundH / 2 ], [ backGroundW, -backGroundH / 2 ] ].join('L') + 'Z' + }).style(boxStyle); + tooltipEl.attr({ + transform: 'translate(' + [ tickSize, -backGroundH / 2 + padding * 2 ] + ')' + }); + tooltipEl.style({ + display: 'block' + }); + return exports; + }; + exports.move = function(_pos) { + if (!tooltipEl) return; + tooltipEl.attr({ + transform: 'translate(' + [ _pos[0], _pos[1] ] + ')' + }).style({ + display: 'block' + }); + return exports; + }; + exports.hide = function() { + if (!tooltipEl) return; + tooltipEl.style({ + display: 'none' + }); + return exports; + }; + exports.show = function() { + if (!tooltipEl) return; + tooltipEl.style({ + display: 'block' + }); + return exports; + }; + exports.config = function(_x) { + extendDeepAll(config, _x); + return exports; + }; + return exports; +}; + +µ.tooltipPanel.uid = 1; + +µ.adapter = {}; + +µ.adapter.plotly = function module() { + var exports = {}; + exports.convert = function(_inputConfig, reverse) { + var outputConfig = {}; + if (_inputConfig.data) { + outputConfig.data = _inputConfig.data.map(function(d, i) { + var r = extendDeepAll({}, d); + var toTranslate = [ + [ r, [ 'marker', 'color' ], [ 'color' ] ], + [ r, [ 'marker', 'opacity' ], [ 'opacity' ] ], + [ r, [ 'marker', 'line', 'color' ], [ 'strokeColor' ] ], + [ r, [ 'marker', 'line', 'dash' ], [ 'strokeDash' ] ], + [ r, [ 'marker', 'line', 'width' ], [ 'strokeSize' ] ], + [ r, [ 'marker', 'symbol' ], [ 'dotType' ] ], + [ r, [ 'marker', 'size' ], [ 'dotSize' ] ], + [ r, [ 'marker', 'barWidth' ], [ 'barWidth' ] ], + [ r, [ 'line', 'interpolation' ], [ 'lineInterpolation' ] ], + [ r, [ 'showlegend' ], [ 'visibleInLegend' ] ] + ]; + toTranslate.forEach(function(d, i) { + µ.util.translator.apply(null, d.concat(reverse)); + }); + + if (!reverse) delete r.marker; + if (reverse) delete r.groupId; + if (!reverse) { + if (r.type === 'scatter') { + if (r.mode === 'lines') r.geometry = 'LinePlot'; else if (r.mode === 'markers') r.geometry = 'DotPlot'; else if (r.mode === 'lines+markers') { + r.geometry = 'LinePlot'; + r.dotVisible = true; + } + } else if (r.type === 'area') r.geometry = 'AreaChart'; else if (r.type === 'bar') r.geometry = 'BarChart'; + delete r.mode; + delete r.type; + } else { + if (r.geometry === 'LinePlot') { + r.type = 'scatter'; + if (r.dotVisible === true) { + delete r.dotVisible; + r.mode = 'lines+markers'; + } else r.mode = 'lines'; + } else if (r.geometry === 'DotPlot') { + r.type = 'scatter'; + r.mode = 'markers'; + } else if (r.geometry === 'AreaChart') r.type = 'area'; else if (r.geometry === 'BarChart') r.type = 'bar'; + delete r.geometry; + } + return r; + }); + if (!reverse && _inputConfig.layout && _inputConfig.layout.barmode === 'stack') { + var duplicates = µ.util.duplicates(outputConfig.data.map(function(d, i) { + return d.geometry; + })); + outputConfig.data.forEach(function(d, i) { + var idx = duplicates.indexOf(d.geometry); + if (idx != -1) outputConfig.data[i].groupId = idx; + }); + } + } + if (_inputConfig.layout) { + var r = extendDeepAll({}, _inputConfig.layout); + var toTranslate = [ + [ r, [ 'plot_bgcolor' ], [ 'backgroundColor' ] ], + [ r, [ 'showlegend' ], [ 'showLegend' ] ], + [ r, [ 'radialaxis' ], [ 'radialAxis' ] ], + [ r, [ 'angularaxis' ], [ 'angularAxis' ] ], + [ r.angularaxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.angularaxis, [ 'showticklabels' ], [ 'labelsVisible' ] ], + [ r.angularaxis, [ 'nticks' ], [ 'ticksCount' ] ], + [ r.angularaxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.angularaxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.angularaxis, [ 'range' ], [ 'domain' ] ], + [ r.angularaxis, [ 'endpadding' ], [ 'endPadding' ] ], + [ r.radialaxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.radialaxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.radialaxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.radialaxis, [ 'range' ], [ 'domain' ] ], + [ r.angularAxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.angularAxis, [ 'showticklabels' ], [ 'labelsVisible' ] ], + [ r.angularAxis, [ 'nticks' ], [ 'ticksCount' ] ], + [ r.angularAxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.angularAxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.angularAxis, [ 'range' ], [ 'domain' ] ], + [ r.angularAxis, [ 'endpadding' ], [ 'endPadding' ] ], + [ r.radialAxis, [ 'showline' ], [ 'gridLinesVisible' ] ], + [ r.radialAxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], + [ r.radialAxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], + [ r.radialAxis, [ 'range' ], [ 'domain' ] ], + [ r.font, [ 'outlinecolor' ], [ 'outlineColor' ] ], + [ r.legend, [ 'traceorder' ], [ 'reverseOrder' ] ], + [ r, [ 'labeloffset' ], [ 'labelOffset' ] ], + [ r, [ 'defaultcolorrange' ], [ 'defaultColorRange' ] ] + ]; + toTranslate.forEach(function(d, i) { + µ.util.translator.apply(null, d.concat(reverse)); + }); + + if (!reverse) { + if (r.angularAxis && typeof r.angularAxis.ticklen !== 'undefined') r.tickLength = r.angularAxis.ticklen; + if (r.angularAxis && typeof r.angularAxis.tickcolor !== 'undefined') r.tickColor = r.angularAxis.tickcolor; + } else { + if (typeof r.tickLength !== 'undefined') { + r.angularaxis.ticklen = r.tickLength; + delete r.tickLength; + } + if (r.tickColor) { + r.angularaxis.tickcolor = r.tickColor; + delete r.tickColor; + } + } + if (r.legend && typeof r.legend.reverseOrder != 'boolean') { + r.legend.reverseOrder = r.legend.reverseOrder != 'normal'; + } + if (r.legend && typeof r.legend.traceorder == 'boolean') { + r.legend.traceorder = r.legend.traceorder ? 'reversed' : 'normal'; + delete r.legend.reverseOrder; + } + if (r.margin && typeof r.margin.t != 'undefined') { + var source = [ 't', 'r', 'b', 'l', 'pad' ]; + var target = [ 'top', 'right', 'bottom', 'left', 'pad' ]; + var margin = {}; + d3.entries(r.margin).forEach(function(dB, iB) { + margin[target[source.indexOf(dB.key)]] = dB.value; + }); + r.margin = margin; + } + if (reverse) { + delete r.needsEndSpacing; + delete r.minorTickColor; + delete r.minorTicks; + delete r.angularaxis.ticksCount; + delete r.angularaxis.ticksCount; + delete r.angularaxis.ticksStep; + delete r.angularaxis.rewriteTicks; + delete r.angularaxis.nticks; + delete r.radialaxis.ticksCount; + delete r.radialaxis.ticksCount; + delete r.radialaxis.ticksStep; + delete r.radialaxis.rewriteTicks; + delete r.radialaxis.nticks; + } + outputConfig.layout = r; + } + return outputConfig; + }; + return exports; +}; + +},{"../../lib":122,"d3":10}],191:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* eslint-disable new-cap */ + +'use strict'; + +var d3 = require('d3'); +var Lib = require('../../lib'); +var Color = require('../../components/color'); + +var micropolar = require('./micropolar'); +var UndoManager = require('./undo_manager'); +var extendDeepAll = Lib.extendDeepAll; + +var manager = module.exports = {}; + +manager.framework = function(_gd) { + var config, previousConfigClone, plot, convertedInput, container; + var undoManager = new UndoManager(); + + function exports(_inputConfig, _container) { + if(_container) container = _container; + d3.select(d3.select(container).node().parentNode).selectAll('.svg-container>*:not(.chart-root)').remove(); + + config = (!config) ? + _inputConfig : + extendDeepAll(config, _inputConfig); + + if(!plot) plot = micropolar.Axis(); + convertedInput = micropolar.adapter.plotly().convert(config); + plot.config(convertedInput).render(container); + _gd.data = config.data; + _gd.layout = config.layout; + manager.fillLayout(_gd); + return config; + } + exports.isPolar = true; + exports.svg = function() { return plot.svg(); }; + exports.getConfig = function() { return config; }; + exports.getLiveConfig = function() { + return micropolar.adapter.plotly().convert(plot.getLiveConfig(), true); + }; + exports.getLiveScales = function() { return {t: plot.angularScale(), r: plot.radialScale()}; }; + exports.setUndoPoint = function() { + var that = this; + var configClone = micropolar.util.cloneJson(config); + (function(_configClone, _previousConfigClone) { + undoManager.add({ + undo: function() { + if(_previousConfigClone) that(_previousConfigClone); + }, + redo: function() { + that(_configClone); + } + }); + })(configClone, previousConfigClone); + previousConfigClone = micropolar.util.cloneJson(configClone); + }; + exports.undo = function() { undoManager.undo(); }; + exports.redo = function() { undoManager.redo(); }; + return exports; +}; + +manager.fillLayout = function(_gd) { + var container = d3.select(_gd).selectAll('.plot-container'), + paperDiv = container.selectAll('.svg-container'), + paper = _gd.framework && _gd.framework.svg && _gd.framework.svg(), + dflts = { + width: 800, + height: 600, + paper_bgcolor: Color.background, + _container: container, + _paperdiv: paperDiv, + _paper: paper + }; + + _gd._fullLayout = extendDeepAll(dflts, _gd.layout); +}; + +},{"../../components/color":27,"../../lib":122,"./micropolar":190,"./undo_manager":192,"d3":10}],192:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +// Modified from https://github.com/ArthurClemens/Javascript-Undo-Manager +// Copyright (c) 2010-2013 Arthur Clemens, arthur@visiblearea.com +module.exports = function UndoManager() { + var undoCommands = [], + index = -1, + isExecuting = false, + callback; + + function execute(command, action) { + if(!command) return this; + + isExecuting = true; + command[action](); + isExecuting = false; + + return this; + } + + return { + add: function(command) { + if(isExecuting) return this; + undoCommands.splice(index + 1, undoCommands.length - index); + undoCommands.push(command); + index = undoCommands.length - 1; + return this; + }, + setCallback: function(callbackFunc) { callback = callbackFunc; }, + undo: function() { + var command = undoCommands[index]; + if(!command) return this; + execute(command, 'undo'); + index -= 1; + if(callback) callback(command.undo); + return this; + }, + redo: function() { + var command = undoCommands[index + 1]; + if(!command) return this; + execute(command, 'redo'); + index += 1; + if(callback) callback(command.redo); + return this; + }, + clear: function() { + undoCommands = []; + index = -1; + }, + hasUndo: function() { return index !== -1; }, + hasRedo: function() { return index < (undoCommands.length - 1); }, + getCommands: function() { return undoCommands; }, + getPreviousCommand: function() { return undoCommands[index - 1]; }, + getIndex: function() { return index; } + }; +}; + +},{}],193:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../lib'); +var Plots = require('./plots'); + + +/** + * Find and supply defaults to all subplots of a given type + * This handles subplots that are contained within one container - so + * gl3d, geo, ternary... but not 2d axes which have separate x and y axes + * finds subplots, coerces their `domain` attributes, then calls the + * given handleDefaults function to fill in everything else. + * + * layoutIn: the complete user-supplied input layout + * layoutOut: the complete finished layout + * fullData: the finished data array, used only to find subplots + * opts: { + * type: subplot type string + * attributes: subplot attributes object + * partition: 'x' or 'y', which direction to divide domain space by default + * (default 'x', ie side-by-side subplots) + * TODO: this option is only here because 3D and geo made opposite + * choices in this regard previously and I didn't want to change it. + * Instead we should do: + * - something consistent + * - something more square (4 cuts 2x2, 5/6 cuts 2x3, etc.) + * - something that includes all subplot types in one arrangement, + * now that we can have them together! + * handleDefaults: function of (subplotLayoutIn, subplotLayoutOut, coerce, opts) + * this opts object is passed through to handleDefaults, so attach any + * additional items needed by this function here as well + * } + */ +module.exports = function handleSubplotDefaults(layoutIn, layoutOut, fullData, opts) { + var subplotType = opts.type, + subplotAttributes = opts.attributes, + handleDefaults = opts.handleDefaults, + partition = opts.partition || 'x'; + + var ids = Plots.findSubplotIds(fullData, subplotType), + idsLength = ids.length; + + var subplotLayoutIn, subplotLayoutOut; + + function coerce(attr, dflt) { + return Lib.coerce(subplotLayoutIn, subplotLayoutOut, subplotAttributes, attr, dflt); + } + + for(var i = 0; i < idsLength; i++) { + var id = ids[i]; + + // ternary traces get a layout ternary for free! + if(layoutIn[id]) subplotLayoutIn = layoutIn[id]; + else subplotLayoutIn = layoutIn[id] = {}; + + layoutOut[id] = subplotLayoutOut = {}; + + coerce('domain.' + partition, [i / idsLength, (i + 1) / idsLength]); + coerce('domain.' + {x: 'y', y: 'x'}[partition]); + + opts.id = id; + handleDefaults(subplotLayoutIn, subplotLayoutOut, coerce, opts); + } +}; + +},{"../lib":122,"./plots":186}],194:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('./lib'); +var basePlotAttributes = require('./plots/attributes'); + +exports.modules = {}; +exports.allCategories = {}; +exports.allTypes = []; +exports.subplotsRegistry = {}; +exports.transformsRegistry = {}; +exports.componentsRegistry = {}; +exports.layoutArrayContainers = []; + +/** + * register a module as the handler for a trace type + * + * @param {object} _module the module that will handle plotting this trace type + * @param {string} thisType + * @param {array of strings} categoriesIn all the categories this type is in, + * tested by calls: traceIs(trace, oneCategory) + * @param {object} meta meta information about the trace type + */ +exports.register = function(_module, thisType, categoriesIn, meta) { + if(exports.modules[thisType]) { + Lib.log('Type ' + thisType + ' already registered'); + return; + } + + var categoryObj = {}; + for(var i = 0; i < categoriesIn.length; i++) { + categoryObj[categoriesIn[i]] = true; + exports.allCategories[categoriesIn[i]] = true; + } + + exports.modules[thisType] = { + _module: _module, + categories: categoryObj + }; + + if(meta && Object.keys(meta).length) { + exports.modules[thisType].meta = meta; + } + + exports.allTypes.push(thisType); +}; + +/** + * register a subplot type + * + * @param {object} _module subplot module: + * + * @param {string or array of strings} attr + * attribute name in traces and layout + * @param {string or array of strings} idRoot + * root of id (setting the possible value for attrName) + * @param {object} attributes + * attribute(s) for traces of this subplot type + * + * In trace objects `attr` is the object key taking a valid `id` as value + * (the set of all valid ids is generated below and stored in idRegex). + * + * In the layout object, a or several valid `attr` name(s) can be keys linked + * to a nested attribute objects + * (the set of all valid attr names is generated below and stored in attrRegex). + */ +exports.registerSubplot = function(_module) { + var plotType = _module.name; + + if(exports.subplotsRegistry[plotType]) { + Lib.log('Plot type ' + plotType + ' already registered.'); + return; + } + + // not sure what's best for the 'cartesian' type at this point + exports.subplotsRegistry[plotType] = _module; +}; + +exports.registerComponent = function(_module) { + var name = _module.name; + + exports.componentsRegistry[name] = _module; + + if(_module.layoutAttributes && _module.layoutAttributes._isLinkedToArray) { + Lib.pushUnique(exports.layoutArrayContainers, name); + } +}; + +/** + * Get registered module using trace object or trace type + * + * @param {object||string} trace + * trace object with prop 'type' or trace type as a string + * @return {object} + * module object corresponding to trace type + */ +exports.getModule = function(trace) { + if(trace.r !== undefined) { + Lib.warn('Tried to put a polar trace ' + + 'on an incompatible graph of cartesian ' + + 'data. Ignoring this dataset.', trace + ); + return false; + } + + var _module = exports.modules[getTraceType(trace)]; + if(!_module) return false; + return _module._module; +}; + +/** + * Determine if this trace type is in a given category + * + * @param {object||string} traceType + * a trace (object) or trace type (string) + * @param {string} category + * category in question + * @return {boolean} + */ +exports.traceIs = function(traceType, category) { + traceType = getTraceType(traceType); + + // old plot.ly workspace hack, nothing to see here + if(traceType === 'various') return false; + + var _module = exports.modules[traceType]; + + if(!_module) { + if(traceType && traceType !== 'area') { + Lib.log('Unrecognized trace type ' + traceType + '.'); + } + + _module = exports.modules[basePlotAttributes.type.dflt]; + } + + return !!_module.categories[category]; +}; + +/** + * Retrieve component module method + * + * @param {string} name + * name of component (as declared in component module) + * @param {string} method + * name of component module method + * @return {function} + */ +exports.getComponentMethod = function(name, method) { + var _module = exports.componentsRegistry[name]; + + if(!_module) return Lib.noop; + return _module[method]; +}; + +function getTraceType(traceType) { + if(typeof traceType === 'object') traceType = traceType.type; + return traceType; +} + +},{"./lib":122,"./plots/attributes":148}],195:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../lib'); +var Plots = require('../plots/plots'); + +var extendFlat = Lib.extendFlat; +var extendDeep = Lib.extendDeep; + +// Put default plotTile layouts here +function cloneLayoutOverride(tileClass) { + var override; + + switch(tileClass) { + case 'themes__thumb': + override = { + autosize: true, + width: 150, + height: 150, + title: '', + showlegend: false, + margin: {l: 5, r: 5, t: 5, b: 5, pad: 0}, + annotations: [] + }; + break; + + case 'thumbnail': + override = { + title: '', + hidesources: true, + showlegend: false, + borderwidth: 0, + bordercolor: '', + margin: {l: 1, r: 1, t: 1, b: 1, pad: 0}, + annotations: [] + }; + break; + + default: + override = {}; + } + + + return override; +} + +function keyIsAxis(keyName) { + var types = ['xaxis', 'yaxis', 'zaxis']; + return (types.indexOf(keyName.slice(0, 5)) > -1); +} + + +module.exports = function clonePlot(graphObj, options) { + + // Polar plot compatibility + if(graphObj.framework && graphObj.framework.isPolar) { + graphObj = graphObj.framework.getConfig(); + } + + var i; + var oldData = graphObj.data; + var oldLayout = graphObj.layout; + var newData = extendDeep([], oldData); + var newLayout = extendDeep({}, oldLayout, cloneLayoutOverride(options.tileClass)); + + if(options.width) newLayout.width = options.width; + if(options.height) newLayout.height = options.height; + + if(options.tileClass === 'thumbnail' || options.tileClass === 'themes__thumb') { + // kill annotations + newLayout.annotations = []; + var keys = Object.keys(newLayout); + + for(i = 0; i < keys.length; i++) { + if(keyIsAxis(keys[i])) { + newLayout[keys[i]].title = ''; + } + } + + // kill colorbar and pie labels + for(i = 0; i < newData.length; i++) { + var trace = newData[i]; + trace.showscale = false; + if(trace.marker) trace.marker.showscale = false; + if(trace.type === 'pie') trace.textposition = 'none'; + } + } + + if(Array.isArray(options.annotations)) { + for(i = 0; i < options.annotations.length; i++) { + newLayout.annotations.push(options.annotations[i]); + } + } + + var sceneIds = Plots.getSubplotIds(newLayout, 'gl3d'); + + if(sceneIds.length) { + var axesImageOverride = {}; + if(options.tileClass === 'thumbnail') { + axesImageOverride = { + title: '', + showaxeslabels: false, + showticklabels: false, + linetickenable: false + }; + } + for(i = 0; i < sceneIds.length; i++) { + var sceneId = sceneIds[i]; + + extendFlat(newLayout[sceneId].xaxis, axesImageOverride); + extendFlat(newLayout[sceneId].yaxis, axesImageOverride); + extendFlat(newLayout[sceneId].zaxis, axesImageOverride); + + // TODO what does this do? + newLayout[sceneId]._scene = null; + } + } + + var gd = document.createElement('div'); + if(options.tileClass) gd.className = options.tileClass; + + var plotTile = { + gd: gd, + td: gd, // for external (image server) compatibility + layout: newLayout, + data: newData, + config: { + staticPlot: (options.staticPlot === undefined) ? + true : + options.staticPlot, + plotGlPixelRatio: (options.plotGlPixelRatio === undefined) ? + 2 : + options.plotGlPixelRatio, + displaylogo: options.displaylogo || false, + showLink: options.showLink || false, + showTips: options.showTips || false + } + }; + + if(options.setBackground !== 'transparent') { + plotTile.config.setBackground = options.setBackground || 'opaque'; + } + + // attaching the default Layout the gd, so you can grab it later + plotTile.gd.defaultLayout = cloneLayoutOverride(options.tileClass); + + return plotTile; +}; + +},{"../lib":122,"../plots/plots":186}],196:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var toImage = require('../plot_api/to_image'); +var Lib = require('../lib'); // for isIE +var fileSaver = require('./filesaver'); + +/** + * @param {object} gd figure Object + * @param {object} opts option object + * @param opts.format 'jpeg' | 'png' | 'webp' | 'svg' + * @param opts.width width of snapshot in px + * @param opts.height height of snapshot in px + * @param opts.filename name of file excluding extension + */ +function downloadImage(gd, opts) { + + // check for undefined opts + opts = opts || {}; + + // default to png + opts.format = opts.format || 'png'; + + return new Promise(function(resolve, reject) { + if(gd._snapshotInProgress) { + reject(new Error('Snapshotting already in progress.')); + } + + // see comments within svgtoimg for additional + // discussion of problems with IE + // can now draw to canvas, but CORS tainted canvas + // does not allow toDataURL + // svg format will work though + if(Lib.isIE() && opts.format !== 'svg') { + reject(new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.')); + } + + gd._snapshotInProgress = true; + var promise = toImage(gd, opts); + + var filename = opts.filename || gd.fn || 'newplot'; + filename += '.' + opts.format; + + promise.then(function(result) { + gd._snapshotInProgress = false; + return fileSaver(result, filename); + }).then(function(name) { + resolve(name); + }).catch(function(err) { + gd._snapshotInProgress = false; + reject(err); + }); + }); +} + +module.exports = downloadImage; + +},{"../lib":122,"../plot_api/to_image":143,"./filesaver":197}],197:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +/* +* substantial portions of this code from FileSaver.js +* https://github.com/eligrey/FileSaver.js +* License: https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md +* FileSaver.js +* A saveAs() FileSaver implementation. +* 1.1.20160328 +* +* By Eli Grey, http://eligrey.com +* License: MIT +* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md +*/ + +'use strict'; + +var fileSaver = function(url, name) { + var saveLink = document.createElement('a'); + var canUseSaveLink = 'download' in saveLink; + var isSafari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent); + var promise = new Promise(function(resolve, reject) { + // IE <10 is explicitly unsupported + if(typeof navigator !== 'undefined' && /MSIE [1-9]\./.test(navigator.userAgent)) { + reject(new Error('IE < 10 unsupported')); + } + + // First try a.download, then web filesystem, then object URLs + if(isSafari) { + // Safari doesn't allow downloading of blob urls + document.location.href = 'data:application/octet-stream' + url.slice(url.search(/[,;]/)); + resolve(name); + } + + if(!name) { + name = 'download'; + } + + if(canUseSaveLink) { + saveLink.href = url; + saveLink.download = name; + document.body.appendChild(saveLink); + saveLink.click(); + document.body.removeChild(saveLink); + resolve(name); + } + + // IE 10+ (native saveAs) + if(typeof navigator !== 'undefined' && navigator.msSaveBlob) { + navigator.msSaveBlob(new Blob([url]), name); + resolve(name); + } + + reject(new Error('download error')); + }); + + return promise; +}; + +module.exports = fileSaver; + +},{}],198:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +exports.getDelay = function(fullLayout) { + + // polar clears fullLayout._has for some reason + if(!fullLayout._has) return 0; + + // maybe we should add a 'gl' (and 'svg') layoutCategory ?? + return (fullLayout._has('gl3d') || fullLayout._has('gl2d')) ? 500 : 0; +}; + +exports.getRedrawFunc = function(gd) { + + // do not work if polar is present + if((gd.data && gd.data[0] && gd.data[0].r)) return; + + return function() { + (gd.calcdata || []).forEach(function(d) { + if(d[0] && d[0].t && d[0].t.cb) d[0].t.cb(); + }); + }; +}; + +},{}],199:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var helpers = require('./helpers'); + +var Snapshot = { + getDelay: helpers.getDelay, + getRedrawFunc: helpers.getRedrawFunc, + clone: require('./cloneplot'), + toSVG: require('./tosvg'), + svgToImg: require('./svgtoimg'), + toImage: require('./toimage'), + downloadImage: require('./download') +}; + +module.exports = Snapshot; + +},{"./cloneplot":195,"./download":196,"./helpers":198,"./svgtoimg":200,"./toimage":201,"./tosvg":202}],200:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../lib'); +var EventEmitter = require('events').EventEmitter; + +function svgToImg(opts) { + + var ev = opts.emitter || new EventEmitter(); + + var promise = new Promise(function(resolve, reject) { + + var Image = window.Image; + + var svg = opts.svg; + var format = opts.format || 'png'; + + // IE is very strict, so we will need to clean + // svg with the following regex + // yes this is messy, but do not know a better way + // Even with this IE will not work due to tainted canvas + // see https://github.com/kangax/fabric.js/issues/1957 + // http://stackoverflow.com/questions/18112047/canvas-todataurl-working-in-all-browsers-except-ie10 + // Leave here just in case the CORS/tainted IE issue gets resolved + if(Lib.isIE()) { + // replace double quote with single quote + svg = svg.replace(/"/gi, '\''); + // url in svg are single quoted + // since we changed double to single + // we'll need to change these to double-quoted + svg = svg.replace(/(\('#)(.*)('\))/gi, '(\"$2\")'); + // font names with spaces will be escaped single-quoted + // we'll need to change these to double-quoted + svg = svg.replace(/(\\')/gi, '\"'); + // IE only support svg + if(format !== 'svg') { + var ieSvgError = new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.'); + reject(ieSvgError); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + return ev.emit('error', ieSvgError); + } else { + return promise; + } + } + } + + var canvas = opts.canvas; + + var ctx = canvas.getContext('2d'); + var img = new Image(); + + // for Safari support, eliminate createObjectURL + // this decision could cause problems if content + // is not restricted to svg + var url = 'data:image/svg+xml,' + encodeURIComponent(svg); + + canvas.height = opts.height || 150; + canvas.width = opts.width || 300; + + img.onload = function() { + var imgData; + + // don't need to draw to canvas if svg + // save some time and also avoid failure on IE + if(format !== 'svg') { + ctx.drawImage(img, 0, 0); + } + + switch(format) { + case 'jpeg': + imgData = canvas.toDataURL('image/jpeg'); + break; + case 'png': + imgData = canvas.toDataURL('image/png'); + break; + case 'webp': + imgData = canvas.toDataURL('image/webp'); + break; + case 'svg': + imgData = url; + break; + default: + reject(new Error('Image format is not jpeg, png or svg')); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + return ev.emit('error', 'Image format is not jpeg, png or svg'); + } + } + resolve(imgData); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + ev.emit('success', imgData); + } + }; + + img.onerror = function(err) { + reject(err); + // eventually remove the ev + // in favor of promises + if(!opts.promise) { + return ev.emit('error', err); + } + }; + + img.src = url; + }); + + // temporary for backward compatibility + // move to only Promise in 2.0.0 + // and eliminate the EventEmitter + if(opts.promise) { + return promise; + } + + return ev; +} + +module.exports = svgToImg; + +},{"../lib":122,"events":12}],201:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var EventEmitter = require('events').EventEmitter; + +var Plotly = require('../plotly'); +var Lib = require('../lib'); + +var helpers = require('./helpers'); +var clonePlot = require('./cloneplot'); +var toSVG = require('./tosvg'); +var svgToImg = require('./svgtoimg'); + + +/** + * @param {object} gd figure Object + * @param {object} opts option object + * @param opts.format 'jpeg' | 'png' | 'webp' | 'svg' + */ +function toImage(gd, opts) { + + // first clone the GD so we can operate in a clean environment + var ev = new EventEmitter(); + + var clone = clonePlot(gd, {format: 'png'}); + var clonedGd = clone.gd; + + // put the cloned div somewhere off screen before attaching to DOM + clonedGd.style.position = 'absolute'; + clonedGd.style.left = '-5000px'; + document.body.appendChild(clonedGd); + + function wait() { + var delay = helpers.getDelay(clonedGd._fullLayout); + + setTimeout(function() { + var svg = toSVG(clonedGd); + + var canvas = document.createElement('canvas'); + canvas.id = Lib.randstr(); + + ev = svgToImg({ + format: opts.format, + width: clonedGd._fullLayout.width, + height: clonedGd._fullLayout.height, + canvas: canvas, + emitter: ev, + svg: svg + }); + + ev.clean = function() { + if(clonedGd) document.body.removeChild(clonedGd); + }; + + }, delay); + } + + var redrawFunc = helpers.getRedrawFunc(clonedGd); + + Plotly.plot(clonedGd, clone.data, clone.layout, clone.config) + .then(redrawFunc) + .then(wait) + .catch(function(err) { + ev.emit('error', err); + }); + + + return ev; +} + +module.exports = toImage; + +},{"../lib":122,"../plotly":145,"./cloneplot":195,"./helpers":198,"./svgtoimg":200,"./tosvg":202,"events":12}],202:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var svgTextUtils = require('../lib/svg_text_utils'); +var Drawing = require('../components/drawing'); +var Color = require('../components/color'); + +var xmlnsNamespaces = require('../constants/xmlns_namespaces'); + + +module.exports = function toSVG(gd, format) { + var fullLayout = gd._fullLayout, + svg = fullLayout._paper, + toppaper = fullLayout._toppaper, + i; + + // make background color a rect in the svg, then revert after scraping + // all other alterations have been dealt with by properly preparing the svg + // in the first place... like setting cursors with css classes so we don't + // have to remove them, and providing the right namespaces in the svg to + // begin with + svg.insert('rect', ':first-child') + .call(Drawing.setRect, 0, 0, fullLayout.width, fullLayout.height) + .call(Color.fill, fullLayout.paper_bgcolor); + + // subplot-specific to-SVG methods + // which notably add the contents of the gl-container + // into the main svg node + var basePlotModules = fullLayout._basePlotModules || []; + for(i = 0; i < basePlotModules.length; i++) { + var _module = basePlotModules[i]; + + if(_module.toSVG) _module.toSVG(gd); + } + + // add top items above them assumes everything in toppaper is either + // a group or a defs, and if it's empty (like hoverlayer) we can ignore it. + if(toppaper) { + var nodes = toppaper.node().childNodes; + + // make copy of nodes as childNodes prop gets mutated in loop below + var topGroups = Array.prototype.slice.call(nodes); + + for(i = 0; i < topGroups.length; i++) { + var topGroup = topGroups[i]; + + if(topGroup.childNodes.length) svg.node().appendChild(topGroup); + } + } + + // remove draglayer for Adobe Illustrator compatibility + if(fullLayout._draggers) { + fullLayout._draggers.remove(); + } + + // in case the svg element had an explicit background color, remove this + // we want the rect to get the color so it's the right size; svg bg will + // fill whatever container it's displayed in regardless of plot size. + svg.node().style.background = ''; + + svg.selectAll('text') + .attr('data-unformatted', null) + .each(function() { + var txt = d3.select(this); + + // hidden text is pre-formatting mathjax, + // the browser ignores it but it can still confuse batik + if(txt.style('visibility') === 'hidden') { + txt.remove(); + return; + } + else { + // force other visibility value to export as visible + // to not potentially confuse non-browser SVG implementations + txt.style('visibility', 'visible'); + } + + // Font family styles break things because of quotation marks, + // so we must remove them *after* the SVG DOM has been serialized + // to a string (browsers convert singles back) + var ff = txt.style('font-family'); + if(ff && ff.indexOf('"') !== -1) { + txt.style('font-family', ff.replace(/"/g, 'TOBESTRIPPED')); + } + }); + + if(format === 'pdf' || format === 'eps') { + // these formats make the extra line MathJax adds around symbols look super thick in some cases + // it looks better if this is removed entirely. + svg.selectAll('#MathJax_SVG_glyphs path') + .attr('stroke-width', 0); + } + + // fix for IE namespacing quirk? + // http://stackoverflow.com/questions/19610089/unwanted-namespaces-on-svg-markup-when-using-xmlserializer-in-javascript-with-ie + svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns', xmlnsNamespaces.svg); + svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns:xlink', xmlnsNamespaces.xlink); + + var s = new window.XMLSerializer().serializeToString(svg.node()); + s = svgTextUtils.html_entity_decode(s); + s = svgTextUtils.xml_entity_encode(s); + + // Fix quotations around font strings + s = s.replace(/("TOBESTRIPPED)|(TOBESTRIPPED")/g, '\''); + + return s; +}; + +},{"../components/color":27,"../components/drawing":50,"../constants/xmlns_namespaces":109,"../lib/svg_text_utils":134,"d3":10}],203:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var mergeArray = require('../../lib').mergeArray; + + +// arrayOk attributes, merge them into calcdata array +module.exports = function arraysToCalcdata(cd) { + var trace = cd[0].trace, + marker = trace.marker; + + mergeArray(trace.text, cd, 'tx'); + + if(marker && marker.line) { + var markerLine = marker.line; + + mergeArray(marker.opacity, cd, 'mo'); + mergeArray(marker.color, cd, 'mc'); + mergeArray(markerLine.color, cd, 'mlc'); + mergeArray(markerLine.width, cd, 'mlw'); + } +}; + +},{"../../lib":122}],204:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = require('../scatter/attributes'); +var colorAttributes = require('../../components/colorscale/color_attributes'); +var errorBarAttrs = require('../../components/errorbars/attributes'); +var colorbarAttrs = require('../../components/colorbar/attributes'); + +var extendFlat = require('../../lib/extend').extendFlat; + +var scatterMarkerAttrs = scatterAttrs.marker; +var scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +var markerLineWidth = extendFlat({}, + scatterMarkerLineAttrs.width, { dflt: 0 }); + +var markerLine = extendFlat({}, { + width: markerLineWidth +}, colorAttributes('marker.line')); + +var marker = extendFlat({}, { + line: markerLine +}, colorAttributes('marker'), { + showscale: scatterMarkerAttrs.showscale, + colorbar: colorbarAttrs +}); + + +module.exports = { + x: scatterAttrs.x, + x0: scatterAttrs.x0, + dx: scatterAttrs.dx, + y: scatterAttrs.y, + y0: scatterAttrs.y0, + dy: scatterAttrs.dy, + text: scatterAttrs.text, + + orientation: { + valType: 'enumerated', + + values: ['v', 'h'], + + }, + + base: { + valType: 'any', + dflt: null, + arrayOk: true, + + + }, + + offset: { + valType: 'number', + dflt: null, + arrayOk: true, + + + }, + + width: { + valType: 'number', + dflt: null, + min: 0, + arrayOk: true, + + + }, + + marker: marker, + + r: scatterAttrs.r, + t: scatterAttrs.t, + + error_y: errorBarAttrs, + error_x: errorBarAttrs, + + _deprecated: { + bardir: { + valType: 'enumerated', + + values: ['v', 'h'], + + } + } +}; + +},{"../../components/colorbar/attributes":28,"../../components/colorscale/color_attributes":34,"../../components/errorbars/attributes":52,"../../lib/extend":117,"../scatter/attributes":234}],205:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Axes = require('../../plots/cartesian/axes'); +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var colorscaleCalc = require('../../components/colorscale/calc'); + + +module.exports = function calc(gd, trace) { + // depending on bar direction, set position and size axes + // and data ranges + // note: this logic for choosing orientation is + // duplicated in graph_obj->setstyles + + var xa = Axes.getFromId(gd, trace.xaxis || 'x'), + ya = Axes.getFromId(gd, trace.yaxis || 'y'), + orientation = trace.orientation || ((trace.x && !trace.y) ? 'h' : 'v'), + sa, pos, size, i; + + if(orientation === 'h') { + sa = xa; + size = xa.makeCalcdata(trace, 'x'); + pos = ya.makeCalcdata(trace, 'y'); + } + else { + sa = ya; + size = ya.makeCalcdata(trace, 'y'); + pos = xa.makeCalcdata(trace, 'x'); + } + + // create the "calculated data" to plot + var serieslen = Math.min(pos.length, size.length), + cd = []; + + // set position + for(i = 0; i < serieslen; i++) { + + // add bars with non-numeric sizes to calcdata + // so that ensure that traces with gaps are + // plotted in the correct order + + if(isNumeric(pos[i])) { + cd.push({p: pos[i]}); + } + } + + // set base + var base = trace.base, + b; + + if(Array.isArray(base)) { + for(i = 0; i < Math.min(base.length, cd.length); i++) { + b = sa.d2c(base[i]); + cd[i].b = (isNumeric(b)) ? b : 0; + } + for(; i < cd.length; i++) { + cd[i].b = 0; + } + } + else { + b = sa.d2c(base); + b = (isNumeric(b)) ? b : 0; + for(i = 0; i < cd.length; i++) { + cd[i].b = b; + } + } + + // set size + for(i = 0; i < cd.length; i++) { + if(isNumeric(size[i])) { + cd[i].s = size[i]; + } + } + + // auto-z and autocolorscale if applicable + if(hasColorscale(trace, 'marker')) { + colorscaleCalc(trace, trace.marker.color, 'marker', 'c'); + } + if(hasColorscale(trace, 'marker.line')) { + colorscaleCalc(trace, trace.marker.line.color, 'marker.line', 'c'); + } + + return cd; +}; + +},{"../../components/colorscale/calc":33,"../../components/colorscale/has_colorscale":40,"../../plots/cartesian/axes":150,"fast-isnumeric":13}],206:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var Color = require('../../components/color'); + +var handleXYDefaults = require('../scatter/xy_defaults'); +var handleStyleDefaults = require('../bar/style_defaults'); +var errorBarsSupplyDefaults = require('../../components/errorbars/defaults'); +var attributes = require('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleXYDefaults(traceIn, traceOut, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v'); + coerce('base'); + coerce('offset'); + coerce('width'); + coerce('text'); + + handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); + + // override defaultColor for error bars with defaultLine + errorBarsSupplyDefaults(traceIn, traceOut, Color.defaultLine, {axis: 'y'}); + errorBarsSupplyDefaults(traceIn, traceOut, Color.defaultLine, {axis: 'x', inherit: 'y'}); +}; + +},{"../../components/color":27,"../../components/errorbars/defaults":55,"../../lib":122,"../bar/style_defaults":215,"../scatter/xy_defaults":256,"./attributes":204}],207:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = require('../../plots/cartesian/graph_interact'); +var ErrorBars = require('../../components/errorbars'); +var Color = require('../../components/color'); + + +module.exports = function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd, + trace = cd[0].trace, + t = cd[0].t, + xa = pointData.xa, + ya = pointData.ya, + barDelta = (hovermode === 'closest') ? + t.barwidth / 2 : + t.bargroupwidth / 2, + barPos; + + if(hovermode !== 'closest') barPos = function(di) { return di.p; }; + else if(trace.orientation === 'h') barPos = function(di) { return di.y; }; + else barPos = function(di) { return di.x; }; + + var dx, dy; + if(trace.orientation === 'h') { + dx = function(di) { + // add a gradient so hovering near the end of a + // bar makes it a little closer match + return Fx.inbox(di.b - xval, di.x - xval) + (di.x - xval) / (di.x - di.b); + }; + dy = function(di) { + var centerPos = barPos(di) - yval; + return Fx.inbox(centerPos - barDelta, centerPos + barDelta); + }; + } + else { + dy = function(di) { + return Fx.inbox(di.b - yval, di.y - yval) + (di.y - yval) / (di.y - di.b); + }; + dx = function(di) { + var centerPos = barPos(di) - xval; + return Fx.inbox(centerPos - barDelta, centerPos + barDelta); + }; + } + + var distfn = Fx.getDistanceFunction(hovermode, dx, dy); + Fx.getClosest(cd, distfn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index === false) return; + + // the closest data point + var di = cd[pointData.index], + mc = di.mcc || trace.marker.color, + mlc = di.mlcc || trace.marker.line.color, + mlw = di.mlw || trace.marker.line.width; + if(Color.opacity(mc)) pointData.color = mc; + else if(Color.opacity(mlc) && mlw) pointData.color = mlc; + + var size = (trace.base) ? di.b + di.s : di.s; + if(trace.orientation === 'h') { + pointData.x0 = pointData.x1 = xa.c2p(di.x, true); + pointData.xLabelVal = size; + + pointData.y0 = ya.c2p(barPos(di) - barDelta, true); + pointData.y1 = ya.c2p(barPos(di) + barDelta, true); + pointData.yLabelVal = di.p; + } + else { + pointData.y0 = pointData.y1 = ya.c2p(di.y, true); + pointData.yLabelVal = size; + + pointData.x0 = xa.c2p(barPos(di) - barDelta, true); + pointData.x1 = xa.c2p(barPos(di) + barDelta, true); + pointData.xLabelVal = di.p; + } + + if(di.tx) pointData.text = di.tx; + + ErrorBars.hoverInfo(di, trace, pointData); + + return [pointData]; +}; + +},{"../../components/color":27,"../../components/errorbars":56,"../../plots/cartesian/graph_interact":157}],208:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Bar = {}; + +Bar.attributes = require('./attributes'); +Bar.layoutAttributes = require('./layout_attributes'); +Bar.supplyDefaults = require('./defaults'); +Bar.supplyLayoutDefaults = require('./layout_defaults'); +Bar.calc = require('./calc'); +Bar.setPositions = require('./set_positions'); +Bar.colorbar = require('../scatter/colorbar'); +Bar.arraysToCalcdata = require('./arrays_to_calcdata'); +Bar.plot = require('./plot'); +Bar.style = require('./style'); +Bar.hoverPoints = require('./hover'); + +Bar.moduleType = 'trace'; +Bar.name = 'bar'; +Bar.basePlotModule = require('../../plots/cartesian'); +Bar.categories = ['cartesian', 'bar', 'oriented', 'markerColorscale', 'errorBarsOK', 'showLegend']; +Bar.meta = { + +}; + +module.exports = Bar; + +},{"../../plots/cartesian":158,"../scatter/colorbar":237,"./arrays_to_calcdata":203,"./attributes":204,"./calc":205,"./defaults":206,"./hover":207,"./layout_attributes":209,"./layout_defaults":210,"./plot":211,"./set_positions":212,"./style":214}],209:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + + +module.exports = { + barmode: { + valType: 'enumerated', + values: ['stack', 'group', 'overlay', 'relative'], + dflt: 'group', + + + }, + barnorm: { + valType: 'enumerated', + values: ['', 'fraction', 'percent'], + dflt: '', + + + }, + bargap: { + valType: 'number', + min: 0, + max: 1, + + + }, + bargroupgap: { + valType: 'number', + min: 0, + max: 1, + dflt: 0, + + + } +}; + +},{}],210:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Registry = require('../../registry'); +var Axes = require('../../plots/cartesian/axes'); +var Lib = require('../../lib'); + +var layoutAttributes = require('./layout_attributes'); + + +module.exports = function(layoutIn, layoutOut, fullData) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + + var hasBars = false, + shouldBeGapless = false, + gappedAnyway = false, + usedSubplots = {}; + + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; + if(Registry.traceIs(trace, 'bar')) hasBars = true; + else continue; + + // if we have at least 2 grouped bar traces on the same subplot, + // we should default to a gap anyway, even if the data is histograms + if(layoutIn.barmode !== 'overlay' && layoutIn.barmode !== 'stack') { + var subploti = trace.xaxis + trace.yaxis; + if(usedSubplots[subploti]) gappedAnyway = true; + usedSubplots[subploti] = true; + } + + if(trace.visible && trace.type === 'histogram') { + var pa = Axes.getFromId({_fullLayout: layoutOut}, + trace[trace.orientation === 'v' ? 'xaxis' : 'yaxis']); + if(pa.type !== 'category') shouldBeGapless = true; + } + } + + if(!hasBars) return; + + var mode = coerce('barmode'); + if(mode !== 'overlay') coerce('barnorm'); + + coerce('bargap', (shouldBeGapless && !gappedAnyway) ? 0 : 0.2); + coerce('bargroupgap'); +}; + +},{"../../lib":122,"../../plots/cartesian/axes":150,"../../registry":194,"./layout_attributes":209}],211:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Color = require('../../components/color'); +var ErrorBars = require('../../components/errorbars'); + +var arraysToCalcdata = require('./arrays_to_calcdata'); + + +module.exports = function plot(gd, plotinfo, cdbar) { + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis, + fullLayout = gd._fullLayout; + + var bartraces = plotinfo.plot.select('.barlayer') + .selectAll('g.trace.bars') + .data(cdbar) + .enter().append('g') + .attr('class', 'trace bars'); + + bartraces.append('g') + .attr('class', 'points') + .each(function(d) { + var t = d[0].t, + trace = d[0].trace, + poffset = t.poffset, + poffsetIsArray = Array.isArray(poffset), + barwidth = t.barwidth, + barwidthIsArray = Array.isArray(barwidth); + + arraysToCalcdata(d); + + d3.select(this).selectAll('path') + .data(Lib.identity) + .enter().append('path') + .each(function(di, i) { + // now display the bar + // clipped xf/yf (2nd arg true): non-positive + // log values go off-screen by plotwidth + // so you see them continue if you drag the plot + var p0 = di.p + ((poffsetIsArray) ? poffset[i] : poffset), + p1 = p0 + ((barwidthIsArray) ? barwidth[i] : barwidth), + s0 = di.b, + s1 = s0 + di.s; + + var x0, x1, y0, y1; + if(trace.orientation === 'h') { + y0 = ya.c2p(p0, true); + y1 = ya.c2p(p1, true); + x0 = xa.c2p(s0, true); + x1 = xa.c2p(s1, true); + } + else { + x0 = xa.c2p(p0, true); + x1 = xa.c2p(p1, true); + y0 = ya.c2p(s0, true); + y1 = ya.c2p(s1, true); + } + + if(!isNumeric(x0) || !isNumeric(x1) || + !isNumeric(y0) || !isNumeric(y1) || + x0 === x1 || y0 === y1) { + d3.select(this).remove(); + return; + } + var lw = (di.mlw + 1 || trace.marker.line.width + 1 || + (di.trace ? di.trace.marker.line.width : 0) + 1) - 1, + offset = d3.round((lw / 2) % 1, 2); + function roundWithLine(v) { + // if there are explicit gaps, don't round, + // it can make the gaps look crappy + return (fullLayout.bargap === 0 && fullLayout.bargroupgap === 0) ? + d3.round(Math.round(v) - offset, 2) : v; + } + function expandToVisible(v, vc) { + // if it's not in danger of disappearing entirely, + // round more precisely + return Math.abs(v - vc) >= 2 ? roundWithLine(v) : + // but if it's very thin, expand it so it's + // necessarily visible, even if it might overlap + // its neighbor + (v > vc ? Math.ceil(v) : Math.floor(v)); + } + if(!gd._context.staticPlot) { + // if bars are not fully opaque or they have a line + // around them, round to integer pixels, mainly for + // safari so we prevent overlaps from its expansive + // pixelation. if the bars ARE fully opaque and have + // no line, expand to a full pixel to make sure we + // can see them + var op = Color.opacity(di.mc || trace.marker.color), + fixpx = (op < 1 || lw > 0.01) ? + roundWithLine : expandToVisible; + x0 = fixpx(x0, x1); + x1 = fixpx(x1, x0); + y0 = fixpx(y0, y1); + y1 = fixpx(y1, y0); + } + d3.select(this).attr('d', + 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z'); + }); + }); + + // error bars are on the top + bartraces.call(ErrorBars.plot, plotinfo); + +}; + +},{"../../components/color":27,"../../components/errorbars":56,"../../lib":122,"./arrays_to_calcdata":203,"d3":10,"fast-isnumeric":13}],212:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Registry = require('../../registry'); +var Axes = require('../../plots/cartesian/axes'); +var Sieve = require('./sieve.js'); + +/* + * Bar chart stacking/grouping positioning and autoscaling calculations + * for each direction separately calculate the ranges and positions + * note that this handles histograms too + * now doing this one subplot at a time + */ + +module.exports = function setPositions(gd, plotinfo) { + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + var fullTraces = gd._fullData, + calcTraces = gd.calcdata, + calcTracesHorizontal = [], + calcTracesVertical = [], + i; + for(i = 0; i < fullTraces.length; i++) { + var fullTrace = fullTraces[i]; + if( + fullTrace.visible === true && + Registry.traceIs(fullTrace, 'bar') && + fullTrace.xaxis === xa._id && + fullTrace.yaxis === ya._id + ) { + if(fullTrace.orientation === 'h') { + calcTracesHorizontal.push(calcTraces[i]); + } + else { + calcTracesVertical.push(calcTraces[i]); + } + } + } + + setGroupPositions(gd, xa, ya, calcTracesVertical); + setGroupPositions(gd, ya, xa, calcTracesHorizontal); +}; + + +function setGroupPositions(gd, pa, sa, calcTraces) { + if(!calcTraces.length) return; + + var barmode = gd._fullLayout.barmode, + overlay = (barmode === 'overlay'), + group = (barmode === 'group'), + excluded, + included, + i, calcTrace, fullTrace; + + if(overlay) { + setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces); + } + else if(group) { + // exclude from the group those traces for which the user set an offset + excluded = []; + included = []; + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + fullTrace = calcTrace[0].trace; + + if(fullTrace.offset === undefined) included.push(calcTrace); + else excluded.push(calcTrace); + } + + if(included.length) { + setGroupPositionsInGroupMode(gd, pa, sa, included); + } + if(excluded.length) { + setGroupPositionsInOverlayMode(gd, pa, sa, excluded); + } + } + else { + // exclude from the stack those traces for which the user set a base + excluded = []; + included = []; + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + fullTrace = calcTrace[0].trace; + + if(fullTrace.base === undefined) included.push(calcTrace); + else excluded.push(calcTrace); + } + + if(included.length) { + setGroupPositionsInStackOrRelativeMode(gd, pa, sa, included); + } + if(excluded.length) { + setGroupPositionsInOverlayMode(gd, pa, sa, excluded); + } + } +} + + +function setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces) { + var barnorm = gd._fullLayout.barnorm, + separateNegativeValues = false, + dontMergeOverlappingData = !barnorm; + + // update position axis and set bar offsets and widths + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i]; + + var sieve = new Sieve( + [calcTrace], separateNegativeValues, dontMergeOverlappingData + ); + + // set bar offsets and widths, and update position axis + setOffsetAndWidth(gd, pa, sieve); + + // set bar bases and sizes, and update size axis + // + // (note that `setGroupPositionsInOverlayMode` handles the case barnorm + // is defined, because this function is also invoked for traces that + // can't be grouped or stacked) + if(barnorm) { + sieveBars(gd, sa, sieve); + normalizeBars(gd, sa, sieve); + } + else { + setBaseAndTop(gd, sa, sieve); + } + } +} + + +function setGroupPositionsInGroupMode(gd, pa, sa, calcTraces) { + var fullLayout = gd._fullLayout, + barnorm = fullLayout.barnorm, + separateNegativeValues = false, + dontMergeOverlappingData = !barnorm, + sieve = new Sieve( + calcTraces, separateNegativeValues, dontMergeOverlappingData + ); + + // set bar offsets and widths, and update position axis + setOffsetAndWidthInGroupMode(gd, pa, sieve); + + // set bar bases and sizes, and update size axis + if(barnorm) { + sieveBars(gd, sa, sieve); + normalizeBars(gd, sa, sieve); + } + else { + setBaseAndTop(gd, sa, sieve); + } +} + + +function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces) { + var fullLayout = gd._fullLayout, + barmode = fullLayout.barmode, + stack = (barmode === 'stack'), + relative = (barmode === 'relative'), + barnorm = gd._fullLayout.barnorm, + separateNegativeValues = relative, + dontMergeOverlappingData = !(barnorm || stack || relative), + sieve = new Sieve( + calcTraces, separateNegativeValues, dontMergeOverlappingData + ); + + // set bar offsets and widths, and update position axis + setOffsetAndWidth(gd, pa, sieve); + + // set bar bases and sizes, and update size axis + stackBars(gd, sa, sieve); +} + + +function setOffsetAndWidth(gd, pa, sieve) { + var fullLayout = gd._fullLayout, + bargap = fullLayout.bargap, + bargroupgap = fullLayout.bargroupgap, + minDiff = sieve.minDiff, + calcTraces = sieve.traces, + i, calcTrace, calcTrace0, + t; + + // set bar offsets and widths + var barGroupWidth = minDiff * (1 - bargap), + barWidthPlusGap = barGroupWidth, + barWidth = barWidthPlusGap * (1 - bargroupgap); + + // computer bar group center and bar offset + var offsetFromCenter = -barWidth / 2; + + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + calcTrace0 = calcTrace[0]; + + // store bar width and offset for this trace + t = calcTrace0.t; + t.barwidth = barWidth; + t.poffset = offsetFromCenter; + t.bargroupwidth = barGroupWidth; + } + + // stack bars that only differ by rounding + sieve.binWidth = calcTraces[0][0].t.barwidth / 100; + + // if defined, apply trace offset and width + applyAttributes(sieve); + + // store the bar center in each calcdata item + setBarCenter(gd, pa, sieve); + + // update position axes + updatePositionAxis(gd, pa, sieve); +} + + +function setOffsetAndWidthInGroupMode(gd, pa, sieve) { + var fullLayout = gd._fullLayout, + bargap = fullLayout.bargap, + bargroupgap = fullLayout.bargroupgap, + positions = sieve.positions, + distinctPositions = sieve.distinctPositions, + minDiff = sieve.minDiff, + calcTraces = sieve.traces, + i, calcTrace, calcTrace0, + t; + + // if there aren't any overlapping positions, + // let them have full width even if mode is group + var overlap = (positions.length !== distinctPositions.length); + + var nTraces = calcTraces.length, + barGroupWidth = minDiff * (1 - bargap), + barWidthPlusGap = (overlap) ? barGroupWidth / nTraces : barGroupWidth, + barWidth = barWidthPlusGap * (1 - bargroupgap); + + for(i = 0; i < nTraces; i++) { + calcTrace = calcTraces[i]; + calcTrace0 = calcTrace[0]; + + // computer bar group center and bar offset + var offsetFromCenter = (overlap) ? + ((2 * i + 1 - nTraces) * barWidthPlusGap - barWidth) / 2 : + -barWidth / 2; + + // store bar width and offset for this trace + t = calcTrace0.t; + t.barwidth = barWidth; + t.poffset = offsetFromCenter; + t.bargroupwidth = barGroupWidth; + } + + // stack bars that only differ by rounding + sieve.binWidth = calcTraces[0][0].t.barwidth / 100; + + // if defined, apply trace width + applyAttributes(sieve); + + // store the bar center in each calcdata item + setBarCenter(gd, pa, sieve); + + // update position axes + updatePositionAxis(gd, pa, sieve, overlap); +} + + +function applyAttributes(sieve) { + var calcTraces = sieve.traces, + i, calcTrace, calcTrace0, fullTrace, + j, + t; + + for(i = 0; i < calcTraces.length; i++) { + calcTrace = calcTraces[i]; + calcTrace0 = calcTrace[0]; + fullTrace = calcTrace0.trace; + t = calcTrace0.t; + + var offset = fullTrace.offset, + initialPoffset = t.poffset, + newPoffset; + + if(Array.isArray(offset)) { + // if offset is an array, then clone it into t.poffset. + newPoffset = offset.slice(0, calcTrace.length); + + // guard against non-numeric items + for(j = 0; j < newPoffset.length; j++) { + if(!isNumeric(newPoffset[j])) { + newPoffset[j] = initialPoffset; + } + } + + // if the length of the array is too short, + // then extend it with the initial value of t.poffset + for(j = newPoffset.length; j < calcTrace.length; j++) { + newPoffset.push(initialPoffset); + } + + t.poffset = newPoffset; + } + else if(offset !== undefined) { + t.poffset = offset; + } + + var width = fullTrace.width, + initialBarwidth = t.barwidth; + + if(Array.isArray(width)) { + // if width is an array, then clone it into t.barwidth. + var newBarwidth = width.slice(0, calcTrace.length); + + // guard against non-numeric items + for(j = 0; j < newBarwidth.length; j++) { + if(!isNumeric(newBarwidth[j])) newBarwidth[j] = initialBarwidth; + } + + // if the length of the array is too short, + // then extend it with the initial value of t.barwidth + for(j = newBarwidth.length; j < calcTrace.length; j++) { + newBarwidth.push(initialBarwidth); + } + + t.barwidth = newBarwidth; + + // if user didn't set offset, + // then correct t.poffset to ensure bars remain centered + if(offset === undefined) { + newPoffset = []; + for(j = 0; j < calcTrace.length; j++) { + newPoffset.push( + initialPoffset + (initialBarwidth - newBarwidth[j]) / 2 + ); + } + t.poffset = newPoffset; + } + } + else if(width !== undefined) { + t.barwidth = width; + + // if user didn't set offset, + // then correct t.poffset to ensure bars remain centered + if(offset === undefined) { + t.poffset = initialPoffset + (initialBarwidth - width) / 2; + } + } + } +} + + +function setBarCenter(gd, pa, sieve) { + var calcTraces = sieve.traces, + pLetter = getAxisLetter(pa); + + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i], + t = calcTrace[0].t, + poffset = t.poffset, + poffsetIsArray = Array.isArray(poffset), + barwidth = t.barwidth, + barwidthIsArray = Array.isArray(barwidth); + + for(var j = 0; j < calcTrace.length; j++) { + var calcBar = calcTrace[j]; + + calcBar[pLetter] = calcBar.p + + ((poffsetIsArray) ? poffset[j] : poffset) + + ((barwidthIsArray) ? barwidth[j] : barwidth) / 2; + } + } +} + + +function updatePositionAxis(gd, pa, sieve, allowMinDtick) { + var calcTraces = sieve.traces, + distinctPositions = sieve.distinctPositions, + distinctPositions0 = distinctPositions[0], + minDiff = sieve.minDiff, + vpad = minDiff / 2; + + Axes.minDtick(pa, minDiff, distinctPositions0, allowMinDtick); + + // If the user set the bar width or the offset, + // then bars can be shifted away from their positions + // and widths can be larger than minDiff. + // + // Here, we compute pMin and pMax to expand the position axis, + // so that all bars are fully within the axis range. + var pMin = Math.min.apply(Math, distinctPositions) - vpad, + pMax = Math.max.apply(Math, distinctPositions) + vpad; + + for(var i = 0; i < calcTraces.length; i++) { + var calcTrace = calcTraces[i], + calcTrace0 = calcTrace[0], + fullTrace = calcTrace0.trace; + + if(fullTrace.width === undefined && fullTrace.offset === undefined) { + continue; + } + + var t = calcTrace0.t, + poffset = t.poffset, + barwidth = t.barwidth, + poffsetIsArray = Array.isArray(poffset), + barwidthIsArray = Array.isArray(barwidth); + + for(var j = 0; j < calcTrace.length; j++) { + var calcBar = calcTrace[j], + calcBarOffset = (poffsetIsArray) ? poffset[j] : poffset, + calcBarWidth = (barwidthIsArray) ? barwidth[j] : barwidth, + p = calcBar.p, + l = p + calcBarOffset, + r = l + calcBarWidth; + + pMin = Math.min(pMin, l); + pMax = Math.max(pMax, r); + } + } + + Axes.expand(pa, [pMin, pMax], {padded: false}); +} + + +function setBaseAndTop(gd, sa, sieve) { + // store these bar bases and tops in calcdata + // and make sure the size axis includes zero, + // along with the bases and tops of each bar. + var traces = sieve.traces, + sLetter = getAxisLetter(sa), + sMax = sa.l2c(sa.c2l(0)), + sMin = sMax; + + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + + for(var j = 0; j < trace.length; j++) { + var bar = trace[j], + barBase = bar.b, + barTop = barBase + bar.s; + + bar[sLetter] = barTop; + + if(isNumeric(sa.c2l(barTop))) { + sMax = Math.max(sMax, barTop); + sMin = Math.min(sMin, barTop); + } + if(isNumeric(sa.c2l(barBase))) { + sMax = Math.max(sMax, barBase); + sMin = Math.min(sMin, barBase); + } + } + } + + Axes.expand(sa, [sMin, sMax], {tozero: true, padded: true}); +} + + +function stackBars(gd, sa, sieve) { + var fullLayout = gd._fullLayout, + barnorm = fullLayout.barnorm, + sLetter = getAxisLetter(sa), + traces = sieve.traces, + i, trace, + j, bar; + + var sMax = sa.l2c(sa.c2l(0)), + sMin = sMax; + + for(i = 0; i < traces.length; i++) { + trace = traces[i]; + + for(j = 0; j < trace.length; j++) { + bar = trace[j]; + + if(!isNumeric(bar.s)) continue; + + // stack current bar and get previous sum + var barBase = sieve.put(bar.p, bar.b + bar.s), + barTop = barBase + bar.b + bar.s; + + // store the bar base and top in each calcdata item + bar.b = barBase; + bar[sLetter] = barTop; + + if(!barnorm) { + if(isNumeric(sa.c2l(barTop))) { + sMax = Math.max(sMax, barTop); + sMin = Math.min(sMin, barTop); + } + if(isNumeric(sa.c2l(barBase))) { + sMax = Math.max(sMax, barBase); + sMin = Math.min(sMin, barBase); + } + } + } + } + + // if barnorm is set, let normalizeBars update the axis range + if(barnorm) { + normalizeBars(gd, sa, sieve); + } + else { + Axes.expand(sa, [sMin, sMax], {tozero: true, padded: true}); + } +} + + +function sieveBars(gd, sa, sieve) { + var traces = sieve.traces; + + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + + for(var j = 0; j < trace.length; j++) { + var bar = trace[j]; + + if(isNumeric(bar.s)) sieve.put(bar.p, bar.b + bar.s); + } + } +} + + +function normalizeBars(gd, sa, sieve) { + // Note: + // + // normalizeBars requires that either sieveBars or stackBars has been + // previously invoked. + + var traces = sieve.traces, + sLetter = getAxisLetter(sa), + sTop = (gd._fullLayout.barnorm === 'fraction') ? 1 : 100, + sTiny = sTop / 1e9, // in case of rounding error in sum + sMin = 0, + sMax = (gd._fullLayout.barmode === 'stack') ? sTop : 0, + padded = false; + + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + + for(var j = 0; j < trace.length; j++) { + var bar = trace[j]; + + if(!isNumeric(bar.s)) continue; + + var scale = Math.abs(sTop / sieve.get(bar.p, bar.s)); + bar.b *= scale; + bar.s *= scale; + + var barBase = bar.b, + barTop = barBase + bar.s; + bar[sLetter] = barTop; + + if(isNumeric(sa.c2l(barTop))) { + if(barTop < sMin - sTiny) { + padded = true; + sMin = barTop; + } + if(barTop > sMax + sTiny) { + padded = true; + sMax = barTop; + } + } + + if(isNumeric(sa.c2l(barBase))) { + if(barBase < sMin - sTiny) { + padded = true; + sMin = barBase; + } + if(barBase > sMax + sTiny) { + padded = true; + sMax = barBase; + } + } + } + } + + // update range of size axis + Axes.expand(sa, [sMin, sMax], {tozero: true, padded: padded}); +} + + +function getAxisLetter(ax) { + return ax._id.charAt(0); +} + +},{"../../plots/cartesian/axes":150,"../../registry":194,"./sieve.js":213,"fast-isnumeric":13}],213:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = Sieve; + +var Lib = require('../../lib'); + +/** + * Helper class to sieve data from traces into bins + * + * @class + * @param {Array} traces + * Array of calculated traces + * @param {boolean} [separateNegativeValues] + * If true, then split data at the same position into a bar + * for positive values and another for negative values + * @param {boolean} [dontMergeOverlappingData] + * If true, then don't merge overlapping bars into a single bar + */ +function Sieve(traces, separateNegativeValues, dontMergeOverlappingData) { + this.traces = traces; + this.separateNegativeValues = separateNegativeValues; + this.dontMergeOverlappingData = dontMergeOverlappingData; + + var positions = []; + for(var i = 0; i < traces.length; i++) { + var trace = traces[i]; + for(var j = 0; j < trace.length; j++) { + var bar = trace[j]; + positions.push(bar.p); + } + } + this.positions = positions; + + var dv = Lib.distinctVals(this.positions); + this.distinctPositions = dv.vals; + this.minDiff = dv.minDiff; + + this.binWidth = this.minDiff; + + this.bins = {}; +} + +/** + * Sieve datum + * + * @method + * @param {number} position + * @param {number} value + * @returns {number} Previous bin value + */ +Sieve.prototype.put = function put(position, value) { + var label = this.getLabel(position, value), + oldValue = this.bins[label] || 0; + + this.bins[label] = oldValue + value; + + return oldValue; +}; + +/** + * Get current bin value for a given datum + * + * @method + * @param {number} position Position of datum + * @param {number} [value] Value of datum + * (required if this.separateNegativeValues is true) + * @returns {number} Current bin value + */ +Sieve.prototype.get = function put(position, value) { + var label = this.getLabel(position, value); + return this.bins[label] || 0; +}; + +/** + * Get bin label for a given datum + * + * @method + * @param {number} position Position of datum + * @param {number} [value] Value of datum + * (required if this.separateNegativeValues is true) + * @returns {string} Bin label + * (prefixed with a 'v' if value is negative and this.separateNegativeValues is + * true; otherwise prefixed with '^') + */ +Sieve.prototype.getLabel = function getLabel(position, value) { + var prefix = (value < 0 && this.separateNegativeValues) ? 'v' : '^', + label = (this.dontMergeOverlappingData) ? + position : + Math.round(position / this.binWidth); + return prefix + label; +}; + +},{"../../lib":122}],214:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); +var ErrorBars = require('../../components/errorbars'); + + +module.exports = function style(gd) { + var s = d3.select(gd).selectAll('g.trace.bars'), + barcount = s.size(), + fullLayout = gd._fullLayout; + + // trace styling + s.style('opacity', function(d) { return d[0].trace.opacity; }) + + // for gapless (either stacked or neighboring grouped) bars use + // crispEdges to turn off antialiasing so an artificial gap + // isn't introduced. + .each(function(d) { + if((fullLayout.barmode === 'stack' && barcount > 1) || + (fullLayout.bargap === 0 && + fullLayout.bargroupgap === 0 && + !d[0].trace.marker.line.width)) { + d3.select(this).attr('shape-rendering', 'crispEdges'); + } + }); + + // then style the individual bars + s.selectAll('g.points').each(function(d) { + var trace = d[0].trace, + marker = trace.marker, + markerLine = marker.line, + markerScale = Drawing.tryColorscale(marker, ''), + lineScale = Drawing.tryColorscale(marker, 'line'); + + d3.select(this).selectAll('path').each(function(d) { + // allow all marker and marker line colors to be scaled + // by given max and min to colorscales + var fillColor, + lineColor, + lineWidth = (d.mlw + 1 || markerLine.width + 1) - 1, + p = d3.select(this); + + if('mc' in d) fillColor = d.mcc = markerScale(d.mc); + else if(Array.isArray(marker.color)) fillColor = Color.defaultLine; + else fillColor = marker.color; + + p.style('stroke-width', lineWidth + 'px') + .call(Color.fill, fillColor); + if(lineWidth) { + if('mlc' in d) lineColor = d.mlcc = lineScale(d.mlc); + // weird case: array wasn't long enough to apply to every point + else if(Array.isArray(markerLine.color)) lineColor = Color.defaultLine; + else lineColor = markerLine.color; + + p.call(Color.stroke, lineColor); + } + }); + // TODO: text markers on bars, either extra text or just bar values + // d3.select(this).selectAll('text') + // .call(Drawing.textPointStyle,d.t||d[0].t); + }); + + s.call(ErrorBars.style); +}; + +},{"../../components/color":27,"../../components/drawing":50,"../../components/errorbars":56,"d3":10}],215:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = require('../../components/color'); +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = require('../../components/colorscale/defaults'); + + +module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout) { + coerce('marker.color', defaultColor); + + if(hasColorscale(traceIn, 'marker')) { + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'} + ); + } + + coerce('marker.line.color', Color.defaultLine); + + if(hasColorscale(traceIn, 'marker.line')) { + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'} + ); + } + + coerce('marker.line.width'); +}; + +},{"../../components/color":27,"../../components/colorscale/defaults":36,"../../components/colorscale/has_colorscale":40}],216:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var ScatterGeoAttrs = require('../scattergeo/attributes'); +var colorscaleAttrs = require('../../components/colorscale/attributes'); +var colorbarAttrs = require('../../components/colorbar/attributes'); +var plotAttrs = require('../../plots/attributes'); + +var extendFlat = require('../../lib/extend').extendFlat; + +var ScatterGeoMarkerLineAttrs = ScatterGeoAttrs.marker.line; + +module.exports = extendFlat({}, { + locations: { + valType: 'data_array', + + }, + locationmode: ScatterGeoAttrs.locationmode, + z: { + valType: 'data_array', + + }, + text: { + valType: 'data_array', + + }, + marker: { + line: { + color: ScatterGeoMarkerLineAttrs.color, + width: ScatterGeoMarkerLineAttrs.width + } + }, + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['location', 'z', 'text', 'name'] + }), +}, + colorscaleAttrs, + { colorbar: colorbarAttrs } +); + +},{"../../components/colorbar/attributes":28,"../../components/colorscale/attributes":32,"../../lib/extend":117,"../../plots/attributes":148,"../scattergeo/attributes":257}],217:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var colorscaleCalc = require('../../components/colorscale/calc'); + + +module.exports = function calc(gd, trace) { + colorscaleCalc(trace, trace.z, '', 'z'); +}; + +},{"../../components/colorscale/calc":33}],218:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + +var colorscaleDefaults = require('../../components/colorscale/defaults'); +var attributes = require('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var locations = coerce('locations'); + + var len; + if(locations) len = locations.length; + + if(!locations || !len) { + traceOut.visible = false; + return; + } + + var z = coerce('z'); + if(!Array.isArray(z)) { + traceOut.visible = false; + return; + } + + if(z.length > len) traceOut.z = z.slice(0, len); + + coerce('locationmode'); + + coerce('text'); + + coerce('marker.line.color'); + coerce('marker.line.width'); + + colorscaleDefaults( + traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'} + ); + + coerce('hoverinfo', (layout._dataLength === 1) ? 'location+z+text' : undefined); +}; + +},{"../../components/colorscale/defaults":36,"../../lib":122,"./attributes":216}],219:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Choropleth = {}; + +Choropleth.attributes = require('./attributes'); +Choropleth.supplyDefaults = require('./defaults'); +Choropleth.colorbar = require('../heatmap/colorbar'); +Choropleth.calc = require('./calc'); +Choropleth.plot = require('./plot').plot; + +// add dummy hover handler to skip Fx.hover w/o warnings +Choropleth.hoverPoints = function() {}; + +Choropleth.moduleType = 'trace'; +Choropleth.name = 'choropleth'; +Choropleth.basePlotModule = require('../../plots/geo'); +Choropleth.categories = ['geo', 'noOpacity']; +Choropleth.meta = { + +}; + +module.exports = Choropleth; + +},{"../../plots/geo":174,"../heatmap/colorbar":221,"./attributes":216,"./calc":217,"./defaults":218,"./plot":220}],220:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Axes = require('../../plots/cartesian/axes'); +var Fx = require('../../plots/cartesian/graph_interact'); +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); +var Colorscale = require('../../components/colorscale'); + +var getTopojsonFeatures = require('../../lib/topojson_utils').getTopojsonFeatures; +var locationToFeature = require('../../lib/geo_location_utils').locationToFeature; +var arrayToCalcItem = require('../../lib/array_to_calc_item'); + +var constants = require('../../plots/geo/constants'); +var attributes = require('./attributes'); + +var plotChoropleth = module.exports = {}; + + +plotChoropleth.calcGeoJSON = function(trace, topojson) { + var cdi = [], + locations = trace.locations, + len = locations.length, + features = getTopojsonFeatures(trace, topojson), + markerLine = (trace.marker || {}).line || {}; + + var feature; + + for(var i = 0; i < len; i++) { + feature = locationToFeature(trace.locationmode, locations[i], features); + + if(!feature) continue; // filter the blank features here + + // 'data_array' attributes + feature.z = trace.z[i]; + if(trace.text !== undefined) feature.tx = trace.text[i]; + + // 'arrayOk' attributes + arrayToCalcItem(markerLine.color, feature, 'mlc', i); + arrayToCalcItem(markerLine.width, feature, 'mlw', i); + + cdi.push(feature); + } + + if(cdi.length > 0) cdi[0].trace = trace; + + return cdi; +}; + +plotChoropleth.plot = function(geo, calcData, geoLayout) { + + function keyFunc(d) { return d[0].trace.uid; } + + var framework = geo.framework, + gChoropleth = framework.select('g.choroplethlayer'), + gBaseLayer = framework.select('g.baselayer'), + gBaseLayerOverChoropleth = framework.select('g.baselayeroverchoropleth'), + baseLayersOverChoropleth = constants.baseLayersOverChoropleth, + layerName; + + var gChoroplethTraces = gChoropleth + .selectAll('g.trace.choropleth') + .data(calcData, keyFunc); + + gChoroplethTraces.enter().append('g') + .attr('class', 'trace choropleth'); + + gChoroplethTraces.exit().remove(); + + gChoroplethTraces.each(function(calcTrace) { + var trace = calcTrace[0].trace, + cdi = plotChoropleth.calcGeoJSON(trace, geo.topojson), + cleanHoverLabelsFunc = makeCleanHoverLabelsFunc(geo, trace), + eventDataFunc = makeEventDataFunc(trace); + + // keep ref to event data in this scope for plotly_unhover + var eventData = null; + + function handleMouseOver(pt, ptIndex) { + if(!geo.showHover) return; + + var xy = geo.projection(pt.properties.ct); + cleanHoverLabelsFunc(pt); + + Fx.loneHover({ + x: xy[0], + y: xy[1], + name: pt.nameLabel, + text: pt.textLabel + }, { + container: geo.hoverContainer.node() + }); + + eventData = eventDataFunc(pt, ptIndex); + + geo.graphDiv.emit('plotly_hover', eventData); + } + + function handleClick(pt, ptIndex) { + geo.graphDiv.emit('plotly_click', eventDataFunc(pt, ptIndex)); + } + + var paths = d3.select(this).selectAll('path.choroplethlocation') + .data(cdi); + + paths.enter().append('path') + .classed('choroplethlocation', true) + .on('mouseover', handleMouseOver) + .on('click', handleClick) + .on('mouseout', function() { + Fx.loneUnhover(geo.hoverContainer); + + geo.graphDiv.emit('plotly_unhover', eventData); + }) + .on('mousedown', function() { + // to simulate the 'zoomon' event + Fx.loneUnhover(geo.hoverContainer); + }) + .on('mouseup', handleMouseOver); // ~ 'zoomend' + + paths.exit().remove(); + }); + + // some baselayers are drawn over choropleth + gBaseLayerOverChoropleth.selectAll('*').remove(); + + for(var i = 0; i < baseLayersOverChoropleth.length; i++) { + layerName = baseLayersOverChoropleth[i]; + gBaseLayer.select('g.' + layerName).remove(); + geo.drawTopo(gBaseLayerOverChoropleth, layerName, geoLayout); + geo.styleLayer(gBaseLayerOverChoropleth, layerName, geoLayout); + } + + plotChoropleth.style(geo); +}; + +plotChoropleth.style = function(geo) { + geo.framework.selectAll('g.trace.choropleth') + .each(function(calcTrace) { + var trace = calcTrace[0].trace, + s = d3.select(this), + marker = trace.marker || {}, + markerLine = marker.line || {}; + + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + trace.colorscale, + trace.zmin, + trace.zmax + ) + ); + + s.selectAll('path.choroplethlocation') + .each(function(pt) { + d3.select(this) + .attr('fill', function(pt) { return sclFunc(pt.z); }) + .call(Color.stroke, pt.mlc || markerLine.color) + .call(Drawing.dashLine, '', pt.mlw || markerLine.width); + }); + }); +}; + +function makeCleanHoverLabelsFunc(geo, trace) { + var hoverinfo = trace.hoverinfo; + + if(hoverinfo === 'none' || hoverinfo === 'skip') { + return function cleanHoverLabelsFunc(pt) { + delete pt.nameLabel; + delete pt.textLabel; + }; + } + + var hoverinfoParts = (hoverinfo === 'all') ? + attributes.hoverinfo.flags : + hoverinfo.split('+'); + + var hasName = (hoverinfoParts.indexOf('name') !== -1), + hasLocation = (hoverinfoParts.indexOf('location') !== -1), + hasZ = (hoverinfoParts.indexOf('z') !== -1), + hasText = (hoverinfoParts.indexOf('text') !== -1), + hasIdAsNameLabel = !hasName && hasLocation; + + function formatter(val) { + var axis = geo.mockAxis; + return Axes.tickText(axis, axis.c2l(val), 'hover').text; + } + + return function cleanHoverLabelsFunc(pt) { + // put location id in name label container + // if name isn't part of hoverinfo + var thisText = []; + + if(hasIdAsNameLabel) pt.nameLabel = pt.id; + else { + if(hasName) pt.nameLabel = trace.name; + if(hasLocation) thisText.push(pt.id); + } + + if(hasZ) thisText.push(formatter(pt.z)); + if(hasText) thisText.push(pt.tx); + + pt.textLabel = thisText.join('
'); + }; +} + +function makeEventDataFunc(trace) { + return function(pt, ptIndex) { + return {points: [{ + data: trace._input, + fullData: trace, + curveNumber: trace.index, + pointNumber: ptIndex, + location: pt.id, + z: pt.z + }]}; + }; +} + +},{"../../components/color":27,"../../components/colorscale":41,"../../components/drawing":50,"../../lib/array_to_calc_item":112,"../../lib/geo_location_utils":120,"../../lib/topojson_utils":135,"../../plots/cartesian/axes":150,"../../plots/cartesian/graph_interact":157,"../../plots/geo/constants":172,"./attributes":216,"d3":10}],221:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Plots = require('../../plots/plots'); +var Colorscale = require('../../components/colorscale'); +var drawColorbar = require('../../components/colorbar/draw'); + + +module.exports = function colorbar(gd, cd) { + var trace = cd[0].trace, + cbId = 'cb' + trace.uid, + zmin = trace.zmin, + zmax = trace.zmax; + + if(!isNumeric(zmin)) zmin = Lib.aggNums(Math.min, null, trace.z); + if(!isNumeric(zmax)) zmax = Lib.aggNums(Math.max, null, trace.z); + + gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); + + if(!trace.showscale) { + Plots.autoMargin(gd, cbId); + return; + } + + var cb = cd[0].t.cb = drawColorbar(gd, cbId); + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + trace.colorscale, + zmin, + zmax + ), + { noNumericCheck: true } + ); + + cb.fillcolor(sclFunc) + .filllevels({start: zmin, end: zmax, size: (zmax - zmin) / 254}) + .options(trace.colorbar)(); +}; + +},{"../../components/colorbar/draw":30,"../../components/colorscale":41,"../../lib":122,"../../plots/plots":186,"fast-isnumeric":13}],222:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttrs = require('../../components/color/attributes'); +var fontAttrs = require('../../plots/font_attributes'); +var plotAttrs = require('../../plots/attributes'); + +var extendFlat = require('../../lib/extend').extendFlat; + + +module.exports = { + labels: { + valType: 'data_array', + + }, + // equivalent of x0 and dx, if label is missing + label0: { + valType: 'number', + + dflt: 0, + + }, + dlabel: { + valType: 'number', + + dflt: 1, + + }, + + values: { + valType: 'data_array', + + }, + + marker: { + colors: { + valType: 'data_array', // TODO 'color_array' ? + + }, + + line: { + color: { + valType: 'color', + + dflt: colorAttrs.defaultLine, + arrayOk: true, + + }, + width: { + valType: 'number', + + min: 0, + dflt: 0, + arrayOk: true, + + } + } + }, + + text: { + valType: 'data_array', + + }, + +// 'see eg:' +// 'https://www.e-education.psu.edu/natureofgeoinfo/sites/www.e-education.psu.edu.natureofgeoinfo/files/image/hisp_pies.gif', +// '(this example involves a map too - may someday be a whole trace type', +// 'of its own. but the point is the size of the whole pie is important.)' + scalegroup: { + valType: 'string', + + dflt: '', + + }, + + // labels (legend is handled by plots.attributes.showlegend and layout.hiddenlabels) + textinfo: { + valType: 'flaglist', + + flags: ['label', 'text', 'value', 'percent'], + extras: ['none'], + + }, + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['label', 'text', 'value', 'percent', 'name'] + }), + textposition: { + valType: 'enumerated', + + values: ['inside', 'outside', 'auto', 'none'], + dflt: 'auto', + arrayOk: true, + + }, + // TODO make those arrayOk? + textfont: extendFlat({}, fontAttrs, { + + }), + insidetextfont: extendFlat({}, fontAttrs, { + + }), + outsidetextfont: extendFlat({}, fontAttrs, { + + }), + + // position and shape + domain: { + x: { + valType: 'info_array', + + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + + }, + y: { + valType: 'info_array', + + items: [ + {valType: 'number', min: 0, max: 1}, + {valType: 'number', min: 0, max: 1} + ], + dflt: [0, 1], + + } + }, + hole: { + valType: 'number', + + min: 0, + max: 1, + dflt: 0, + + }, + + // ordering and direction + sort: { + valType: 'boolean', + + dflt: true, + + }, + direction: { + /** + * there are two common conventions, both of which place the first + * (largest, if sorted) slice with its left edge at 12 o'clock but + * succeeding slices follow either cw or ccw from there. + * + * see http://visage.co/data-visualization-101-pie-charts/ + */ + valType: 'enumerated', + values: ['clockwise', 'counterclockwise'], + + dflt: 'counterclockwise', + + }, + rotation: { + valType: 'number', + + min: -360, + max: 360, + dflt: 0, + + }, + + pull: { + valType: 'number', + + min: 0, + max: 1, + dflt: 0, + arrayOk: true, + + } +}; + +},{"../../components/color/attributes":26,"../../lib/extend":117,"../../plots/attributes":148,"../../plots/font_attributes":170}],223:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Registry = require('../../registry'); + + +exports.name = 'pie'; + +exports.plot = function(gd) { + var Pie = Registry.getModule('pie'); + var cdPie = getCdModule(gd.calcdata, Pie); + + if(cdPie.length) Pie.plot(gd, cdPie); +}; + +exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { + var hadPie = (oldFullLayout._has && oldFullLayout._has('pie')); + var hasPie = (newFullLayout._has && newFullLayout._has('pie')); + + if(hadPie && !hasPie) { + oldFullLayout._pielayer.selectAll('g.trace').remove(); + } +}; + +function getCdModule(calcdata, _module) { + var cdModule = []; + + for(var i = 0; i < calcdata.length; i++) { + var cd = calcdata[i]; + var trace = cd[0].trace; + + if((trace._module === _module) && (trace.visible === true)) { + cdModule.push(cd); + } + } + + return cdModule; +} + +},{"../../registry":194}],224:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var isNumeric = require('fast-isnumeric'); +var tinycolor = require('tinycolor2'); + +var Color = require('../../components/color'); +var helpers = require('./helpers'); + +module.exports = function calc(gd, trace) { + var vals = trace.values, + labels = trace.labels, + cd = [], + fullLayout = gd._fullLayout, + colorMap = fullLayout._piecolormap, + allThisTraceLabels = {}, + needDefaults = false, + vTotal = 0, + hiddenLabels = fullLayout.hiddenlabels || [], + i, + v, + label, + color, + hidden, + pt; + + if(trace.dlabel) { + labels = new Array(vals.length); + for(i = 0; i < vals.length; i++) { + labels[i] = String(trace.label0 + i * trace.dlabel); + } + } + + for(i = 0; i < vals.length; i++) { + v = vals[i]; + if(!isNumeric(v)) continue; + v = +v; + if(v < 0) continue; + + label = labels[i]; + if(label === undefined || label === '') label = i; + label = String(label); + // only take the first occurrence of any given label. + // TODO: perhaps (optionally?) sum values for a repeated label? + if(allThisTraceLabels[label] === undefined) allThisTraceLabels[label] = true; + else continue; + + color = tinycolor(trace.marker.colors[i]); + if(color.isValid()) { + color = Color.addOpacity(color, color.getAlpha()); + if(!colorMap[label]) { + colorMap[label] = color; + } + } + // have we seen this label and assigned a color to it in a previous trace? + else if(colorMap[label]) color = colorMap[label]; + // color needs a default - mark it false, come back after sorting + else { + color = false; + needDefaults = true; + } + + hidden = hiddenLabels.indexOf(label) !== -1; + + if(!hidden) vTotal += v; + + cd.push({ + v: v, + label: label, + color: color, + i: i, + hidden: hidden + }); + } + + if(trace.sort) cd.sort(function(a, b) { return b.v - a.v; }); + + /** + * now go back and fill in colors we're still missing + * this is done after sorting, so we pick defaults + * in the order slices will be displayed + */ + + if(needDefaults) { + for(i = 0; i < cd.length; i++) { + pt = cd[i]; + if(pt.color === false) { + colorMap[pt.label] = pt.color = nextDefaultColor(fullLayout._piedefaultcolorcount); + fullLayout._piedefaultcolorcount++; + } + } + } + + // include the sum of all values in the first point + if(cd[0]) cd[0].vTotal = vTotal; + + // now insert text + if(trace.textinfo && trace.textinfo !== 'none') { + var hasLabel = trace.textinfo.indexOf('label') !== -1, + hasText = trace.textinfo.indexOf('text') !== -1, + hasValue = trace.textinfo.indexOf('value') !== -1, + hasPercent = trace.textinfo.indexOf('percent') !== -1, + separators = fullLayout.separators, + thisText; + + for(i = 0; i < cd.length; i++) { + pt = cd[i]; + thisText = hasLabel ? [pt.label] : []; + if(hasText && trace.text[pt.i]) thisText.push(trace.text[pt.i]); + if(hasValue) thisText.push(helpers.formatPieValue(pt.v, separators)); + if(hasPercent) thisText.push(helpers.formatPiePercent(pt.v / vTotal, separators)); + pt.text = thisText.join('
'); + } + } + + return cd; +}; + +/** + * pick a default color from the main default set, augmented by + * itself lighter then darker before repeating + */ +var pieDefaultColors; + +function nextDefaultColor(index) { + if(!pieDefaultColors) { + // generate this default set on demand (but then it gets saved in the module) + var mainDefaults = Color.defaults; + pieDefaultColors = mainDefaults.slice(); + + var i; + + for(i = 0; i < mainDefaults.length; i++) { + pieDefaultColors.push(tinycolor(mainDefaults[i]).lighten(20).toHexString()); + } + + for(i = 0; i < Color.defaults.length; i++) { + pieDefaultColors.push(tinycolor(mainDefaults[i]).darken(20).toHexString()); + } + } + + return pieDefaultColors[index % pieDefaultColors.length]; +} + +},{"../../components/color":27,"./helpers":226,"fast-isnumeric":13,"tinycolor2":16}],225:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); +var attributes = require('./attributes'); + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var coerceFont = Lib.coerceFont; + + var vals = coerce('values'); + if(!Array.isArray(vals) || !vals.length) { + traceOut.visible = false; + return; + } + + var labels = coerce('labels'); + if(!Array.isArray(labels)) { + coerce('label0'); + coerce('dlabel'); + } + + var lineWidth = coerce('marker.line.width'); + if(lineWidth) coerce('marker.line.color'); + + var colors = coerce('marker.colors'); + if(!Array.isArray(colors)) traceOut.marker.colors = []; // later this will get padded with default colors + + coerce('scalegroup'); + // TODO: tilt, depth, and hole all need to be coerced to the same values within a scaleegroup + // (ideally actually, depth would get set the same *after* scaling, ie the same absolute depth) + // and if colors aren't specified we should match these up - potentially even if separate pies + // are NOT in the same sharegroup + + + var textData = coerce('text'); + var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent'); + + coerce('hoverinfo', (layout._dataLength === 1) ? 'label+text+value+percent' : undefined); + + if(textInfo && textInfo !== 'none') { + var textPosition = coerce('textposition'), + hasBoth = Array.isArray(textPosition) || textPosition === 'auto', + hasInside = hasBoth || textPosition === 'inside', + hasOutside = hasBoth || textPosition === 'outside'; + + if(hasInside || hasOutside) { + var dfltFont = coerceFont(coerce, 'textfont', layout.font); + if(hasInside) coerceFont(coerce, 'insidetextfont', dfltFont); + if(hasOutside) coerceFont(coerce, 'outsidetextfont', dfltFont); + } + } + + coerce('domain.x'); + coerce('domain.y'); + + // 3D attributes commented out until I finish them in a later PR + // var tilt = coerce('tilt'); + // if(tilt) { + // coerce('tiltaxis'); + // coerce('depth'); + // coerce('shading'); + // } + + coerce('hole'); + + coerce('sort'); + coerce('direction'); + coerce('rotation'); + + coerce('pull'); +}; + +},{"../../lib":122,"./attributes":222}],226:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); + +exports.formatPiePercent = function formatPiePercent(v, separators) { + var vRounded = (v * 100).toPrecision(3); + if(vRounded.lastIndexOf('.') !== -1) { + vRounded = vRounded.replace(/[.]?0+$/, ''); + } + return Lib.numSeparate(vRounded, separators) + '%'; +}; + +exports.formatPieValue = function formatPieValue(v, separators) { + var vRounded = v.toPrecision(10); + if(vRounded.lastIndexOf('.') !== -1) { + vRounded = vRounded.replace(/[.]?0+$/, ''); + } + return Lib.numSeparate(vRounded, separators); +}; + +},{"../../lib":122}],227:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Pie = {}; + +Pie.attributes = require('./attributes'); +Pie.supplyDefaults = require('./defaults'); +Pie.supplyLayoutDefaults = require('./layout_defaults'); +Pie.layoutAttributes = require('./layout_attributes'); +Pie.calc = require('./calc'); +Pie.plot = require('./plot'); +Pie.style = require('./style'); +Pie.styleOne = require('./style_one'); + +Pie.moduleType = 'trace'; +Pie.name = 'pie'; +Pie.basePlotModule = require('./base_plot'); +Pie.categories = ['pie', 'showLegend']; +Pie.meta = { + +}; + +module.exports = Pie; + +},{"./attributes":222,"./base_plot":223,"./calc":224,"./defaults":225,"./layout_attributes":228,"./layout_defaults":229,"./plot":230,"./style":231,"./style_one":232}],228:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = { + /** + * hiddenlabels is the pie chart analog of visible:'legendonly' + * but it can contain many labels, and can hide slices + * from several pies simultaneously + */ + hiddenlabels: {valType: 'data_array'} +}; + +},{}],229:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Lib = require('../../lib'); + +var layoutAttributes = require('./layout_attributes'); + +module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { + function coerce(attr, dflt) { + return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); + } + coerce('hiddenlabels'); +}; + +},{"../../lib":122,"./layout_attributes":228}],230:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = require('d3'); + +var Fx = require('../../plots/cartesian/graph_interact'); +var Color = require('../../components/color'); +var Drawing = require('../../components/drawing'); +var svgTextUtils = require('../../lib/svg_text_utils'); + +var helpers = require('./helpers'); + +module.exports = function plot(gd, cdpie) { + var fullLayout = gd._fullLayout; + + scalePies(cdpie, fullLayout._size); + + var pieGroups = fullLayout._pielayer.selectAll('g.trace').data(cdpie); + + pieGroups.enter().append('g') + .attr({ + 'stroke-linejoin': 'round', // TODO: miter might look better but can sometimes cause problems + // maybe miter with a small-ish stroke-miterlimit? + 'class': 'trace' + }); + pieGroups.exit().remove(); + pieGroups.order(); + + pieGroups.each(function(cd) { + var pieGroup = d3.select(this), + cd0 = cd[0], + trace = cd0.trace, + tiltRads = 0, // trace.tilt * Math.PI / 180, + depthLength = (trace.depth||0) * cd0.r * Math.sin(tiltRads) / 2, + tiltAxis = trace.tiltaxis || 0, + tiltAxisRads = tiltAxis * Math.PI / 180, + depthVector = [ + depthLength * Math.sin(tiltAxisRads), + depthLength * Math.cos(tiltAxisRads) + ], + rSmall = cd0.r * Math.cos(tiltRads); + + var pieParts = pieGroup.selectAll('g.part') + .data(trace.tilt ? ['top', 'sides'] : ['top']); + + pieParts.enter().append('g').attr('class', function(d) { + return d + ' part'; + }); + pieParts.exit().remove(); + pieParts.order(); + + setCoords(cd); + + pieGroup.selectAll('.top').each(function() { + var slices = d3.select(this).selectAll('g.slice').data(cd); + + slices.enter().append('g') + .classed('slice', true); + slices.exit().remove(); + + var quadrants = [ + [[], []], // y<0: x<0, x>=0 + [[], []] // y>=0: x<0, x>=0 + ], + hasOutsideText = false; + + slices.each(function(pt) { + if(pt.hidden) { + d3.select(this).selectAll('path,g').remove(); + return; + } + + quadrants[pt.pxmid[1] < 0 ? 0 : 1][pt.pxmid[0] < 0 ? 0 : 1].push(pt); + + var cx = cd0.cx + depthVector[0], + cy = cd0.cy + depthVector[1], + sliceTop = d3.select(this), + slicePath = sliceTop.selectAll('path.surface').data([pt]), + hasHoverData = false; + + function handleMouseOver(evt) { + // in case fullLayout or fullData has changed without a replot + var fullLayout2 = gd._fullLayout, + trace2 = gd._fullData[trace.index], + hoverinfo = trace2.hoverinfo; + + if(hoverinfo === 'all') hoverinfo = 'label+text+value+percent+name'; + + // in case we dragged over the pie from another subplot, + // or if hover is turned off + if(gd._dragging || fullLayout2.hovermode === false || + hoverinfo === 'none' || hoverinfo === 'skip' || !hoverinfo) { + return; + } + + var rInscribed = getInscribedRadiusFraction(pt, cd0), + hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed), + hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed), + separators = fullLayout.separators, + thisText = []; + + if(hoverinfo.indexOf('label') !== -1) thisText.push(pt.label); + if(trace2.text && trace2.text[pt.i] && hoverinfo.indexOf('text') !== -1) { + thisText.push(trace2.text[pt.i]); + } + if(hoverinfo.indexOf('value') !== -1) thisText.push(helpers.formatPieValue(pt.v, separators)); + if(hoverinfo.indexOf('percent') !== -1) thisText.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators)); + + Fx.loneHover({ + x0: hoverCenterX - rInscribed * cd0.r, + x1: hoverCenterX + rInscribed * cd0.r, + y: hoverCenterY, + text: thisText.join('
'), + name: hoverinfo.indexOf('name') !== -1 ? trace2.name : undefined, + color: pt.color, + idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right' + }, { + container: fullLayout2._hoverlayer.node(), + outerContainer: fullLayout2._paper.node() + }); + + Fx.hover(gd, evt, 'pie'); + + hasHoverData = true; + } + + function handleMouseOut(evt) { + gd.emit('plotly_unhover', { + points: [evt] + }); + + if(hasHoverData) { + Fx.loneUnhover(fullLayout._hoverlayer.node()); + hasHoverData = false; + } + } + + function handleClick() { + gd._hoverdata = [pt]; + pt.curveNumber = cd[0].trace.index; + gd._hoverdata.trace = cd[0].trace; + Fx.click(gd, window.event || { target: true }); + } + + slicePath.enter().append('path') + .classed('surface', true) + .style({'pointer-events': 'all'}); + + sliceTop.select('path.textline').remove(); + + sliceTop + .on('mouseover', handleMouseOver) + .on('mouseout', handleMouseOut) + .on('click', handleClick) + .on('contextmenu', handleClick); + + if(trace.pull) { + var pull = +(Array.isArray(trace.pull) ? trace.pull[pt.i] : trace.pull) || 0; + if(pull > 0) { + cx += pull * pt.pxmid[0]; + cy += pull * pt.pxmid[1]; + } + } + + pt.cxFinal = cx; + pt.cyFinal = cy; + + function arc(start, finish, cw, scale) { + return 'a' + (scale * cd0.r) + ',' + (scale * rSmall) + ' ' + tiltAxis + ' ' + + pt.largeArc + (cw ? ' 1 ' : ' 0 ') + + (scale * (finish[0] - start[0])) + ',' + (scale * (finish[1] - start[1])); + } + + var hole = trace.hole; + if(pt.v === cd0.vTotal) { // 100% fails bcs arc start and end are identical + var outerCircle = 'M' + (cx + pt.px0[0]) + ',' + (cy + pt.px0[1]) + + arc(pt.px0, pt.pxmid, true, 1) + + arc(pt.pxmid, pt.px0, true, 1) + 'Z'; + if(hole) { + slicePath.attr('d', + 'M' + (cx + hole * pt.px0[0]) + ',' + (cy + hole * pt.px0[1]) + + arc(pt.px0, pt.pxmid, false, hole) + + arc(pt.pxmid, pt.px0, false, hole) + + 'Z' + outerCircle); + } + else slicePath.attr('d', outerCircle); + } else { + + var outerArc = arc(pt.px0, pt.px1, true, 1); + + if(hole) { + var rim = 1 - hole; + slicePath.attr('d', + 'M' + (cx + hole * pt.px1[0]) + ',' + (cy + hole * pt.px1[1]) + + arc(pt.px1, pt.px0, false, hole) + + 'l' + (rim * pt.px0[0]) + ',' + (rim * pt.px0[1]) + + outerArc + + 'Z'); + } else { + slicePath.attr('d', + 'M' + cx + ',' + cy + + 'l' + pt.px0[0] + ',' + pt.px0[1] + + outerArc + + 'Z'); + } + } + + // add text + var textPosition = Array.isArray(trace.textposition) ? + trace.textposition[pt.i] : trace.textposition, + sliceTextGroup = sliceTop.selectAll('g.slicetext') + .data(pt.text && (textPosition !== 'none') ? [0] : []); + + sliceTextGroup.enter().append('g') + .classed('slicetext', true); + sliceTextGroup.exit().remove(); + + sliceTextGroup.each(function() { + var sliceText = d3.select(this).selectAll('text').data([0]); + + sliceText.enter().append('text') + // prohibit tex interpretation until we can handle + // tex and regular text together + .attr('data-notex', 1); + sliceText.exit().remove(); + + sliceText.text(pt.text) + .attr({ + 'class': 'slicetext', + transform: '', + 'data-bb': '', + 'text-anchor': 'middle', + x: 0, + y: 0 + }) + .call(Drawing.font, textPosition === 'outside' ? + trace.outsidetextfont : trace.insidetextfont) + .call(svgTextUtils.convertToTspans); + sliceText.selectAll('tspan.line').attr({x: 0, y: 0}); + + // position the text relative to the slice + // TODO: so far this only accounts for flat + var textBB = Drawing.bBox(sliceText.node()), + transform; + + if(textPosition === 'outside') { + transform = transformOutsideText(textBB, pt); + } else { + transform = transformInsideText(textBB, pt, cd0); + if(textPosition === 'auto' && transform.scale < 1) { + sliceText.call(Drawing.font, trace.outsidetextfont); + if(trace.outsidetextfont.family !== trace.insidetextfont.family || + trace.outsidetextfont.size !== trace.insidetextfont.size) { + sliceText.attr({'data-bb': ''}); + textBB = Drawing.bBox(sliceText.node()); + } + transform = transformOutsideText(textBB, pt); + } + } + + var translateX = cx + pt.pxmid[0] * transform.rCenter + (transform.x || 0), + translateY = cy + pt.pxmid[1] * transform.rCenter + (transform.y || 0); + + // save some stuff to use later ensure no labels overlap + if(transform.outside) { + pt.yLabelMin = translateY - textBB.height / 2; + pt.yLabelMid = translateY; + pt.yLabelMax = translateY + textBB.height / 2; + pt.labelExtraX = 0; + pt.labelExtraY = 0; + hasOutsideText = true; + } + + sliceText.attr('transform', + 'translate(' + translateX + ',' + translateY + ')' + + (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') + + (transform.rotate ? ('rotate(' + transform.rotate + ')') : '') + + 'translate(' + + (-(textBB.left + textBB.right) / 2) + ',' + + (-(textBB.top + textBB.bottom) / 2) + + ')'); + }); + }); + + // now make sure no labels overlap (at least within one pie) + if(hasOutsideText) scootLabels(quadrants, trace); + slices.each(function(pt) { + if(pt.labelExtraX || pt.labelExtraY) { + // first move the text to its new location + var sliceTop = d3.select(this), + sliceText = sliceTop.select('g.slicetext text'); + + sliceText.attr('transform', 'translate(' + pt.labelExtraX + ',' + pt.labelExtraY + ')' + + sliceText.attr('transform')); + + // then add a line to the new location + var lineStartX = pt.cxFinal + pt.pxmid[0], + lineStartY = pt.cyFinal + pt.pxmid[1], + textLinePath = 'M' + lineStartX + ',' + lineStartY, + finalX = (pt.yLabelMax - pt.yLabelMin) * (pt.pxmid[0] < 0 ? -1 : 1) / 4; + if(pt.labelExtraX) { + var yFromX = pt.labelExtraX * pt.pxmid[1] / pt.pxmid[0], + yNet = pt.yLabelMid + pt.labelExtraY - (pt.cyFinal + pt.pxmid[1]); + + if(Math.abs(yFromX) > Math.abs(yNet)) { + textLinePath += + 'l' + (yNet * pt.pxmid[0] / pt.pxmid[1]) + ',' + yNet + + 'H' + (lineStartX + pt.labelExtraX + finalX); + } else { + textLinePath += 'l' + pt.labelExtraX + ',' + yFromX + + 'v' + (yNet - yFromX) + + 'h' + finalX; + } + } else { + textLinePath += + 'V' + (pt.yLabelMid + pt.labelExtraY) + + 'h' + finalX; + } + + sliceTop.append('path') + .classed('textline', true) + .call(Color.stroke, trace.outsidetextfont.color) + .attr({ + 'stroke-width': Math.min(2, trace.outsidetextfont.size / 8), + d: textLinePath, + fill: 'none' + }); + } + }); + }); + }); + + // This is for a bug in Chrome (as of 2015-07-22, and does not affect FF) + // if insidetextfont and outsidetextfont are different sizes, sometimes the size + // of an "em" gets taken from the wrong element at first so lines are + // spaced wrong. You just have to tell it to try again later and it gets fixed. + // I have no idea why we haven't seen this in other contexts. Also, sometimes + // it gets the initial draw correct but on redraw it gets confused. + setTimeout(function() { + pieGroups.selectAll('tspan').each(function() { + var s = d3.select(this); + if(s.attr('dy')) s.attr('dy', s.attr('dy')); + }); + }, 0); +}; + + +function transformInsideText(textBB, pt, cd0) { + var textDiameter = Math.sqrt(textBB.width * textBB.width + textBB.height * textBB.height), + textAspect = textBB.width / textBB.height, + halfAngle = Math.PI * Math.min(pt.v / cd0.vTotal, 0.5), + ring = 1 - cd0.trace.hole, + rInscribed = getInscribedRadiusFraction(pt, cd0), + + // max size text can be inserted inside without rotating it + // this inscribes the text rectangle in a circle, which is then inscribed + // in the slice, so it will be an underestimate, which some day we may want + // to improve so this case can get more use + transform = { + scale: rInscribed * cd0.r * 2 / textDiameter, + + // and the center position and rotation in this case + rCenter: 1 - rInscribed, + rotate: 0 + }; + + if(transform.scale >= 1) return transform; + + // max size if text is rotated radially + var Qr = textAspect + 1 / (2 * Math.tan(halfAngle)), + maxHalfHeightRotRadial = cd0.r * Math.min( + 1 / (Math.sqrt(Qr * Qr + 0.5) + Qr), + ring / (Math.sqrt(textAspect * textAspect + ring / 2) + textAspect) + ), + radialTransform = { + scale: maxHalfHeightRotRadial * 2 / textBB.height, + rCenter: Math.cos(maxHalfHeightRotRadial / cd0.r) - + maxHalfHeightRotRadial * textAspect / cd0.r, + rotate: (180 / Math.PI * pt.midangle + 720) % 180 - 90 + }, + + // max size if text is rotated tangentially + aspectInv = 1 / textAspect, + Qt = aspectInv + 1 / (2 * Math.tan(halfAngle)), + maxHalfWidthTangential = cd0.r * Math.min( + 1 / (Math.sqrt(Qt * Qt + 0.5) + Qt), + ring / (Math.sqrt(aspectInv * aspectInv + ring / 2) + aspectInv) + ), + tangentialTransform = { + scale: maxHalfWidthTangential * 2 / textBB.width, + rCenter: Math.cos(maxHalfWidthTangential / cd0.r) - + maxHalfWidthTangential / textAspect / cd0.r, + rotate: (180 / Math.PI * pt.midangle + 810) % 180 - 90 + }, + // if we need a rotated transform, pick the biggest one + // even if both are bigger than 1 + rotatedTransform = tangentialTransform.scale > radialTransform.scale ? + tangentialTransform : radialTransform; + + if(transform.scale < 1 && rotatedTransform.scale > transform.scale) return rotatedTransform; + return transform; +} + +function getInscribedRadiusFraction(pt, cd0) { + if(pt.v === cd0.vTotal && !cd0.trace.hole) return 1;// special case of 100% with no hole + + var halfAngle = Math.PI * Math.min(pt.v / cd0.vTotal, 0.5); + return Math.min(1 / (1 + 1 / Math.sin(halfAngle)), (1 - cd0.trace.hole) / 2); +} + +function transformOutsideText(textBB, pt) { + var x = pt.pxmid[0], + y = pt.pxmid[1], + dx = textBB.width / 2, + dy = textBB.height / 2; + + if(x < 0) dx *= -1; + if(y < 0) dy *= -1; + + return { + scale: 1, + rCenter: 1, + rotate: 0, + x: dx + Math.abs(dy) * (dx > 0 ? 1 : -1) / 2, + y: dy / (1 + x * x / (y * y)), + outside: true + }; +} + +function scootLabels(quadrants, trace) { + var xHalf, + yHalf, + equatorFirst, + farthestX, + farthestY, + xDiffSign, + yDiffSign, + thisQuad, + oppositeQuad, + wholeSide, + i, + thisQuadOutside, + firstOppositeOutsidePt; + + function topFirst(a, b) { return a.pxmid[1] - b.pxmid[1]; } + function bottomFirst(a, b) { return b.pxmid[1] - a.pxmid[1]; } + + function scootOneLabel(thisPt, prevPt) { + if(!prevPt) prevPt = {}; + + var prevOuterY = prevPt.labelExtraY + (yHalf ? prevPt.yLabelMax : prevPt.yLabelMin), + thisInnerY = yHalf ? thisPt.yLabelMin : thisPt.yLabelMax, + thisOuterY = yHalf ? thisPt.yLabelMax : thisPt.yLabelMin, + thisSliceOuterY = thisPt.cyFinal + farthestY(thisPt.px0[1], thisPt.px1[1]), + newExtraY = prevOuterY - thisInnerY, + xBuffer, + i, + otherPt, + otherOuterY, + otherOuterX, + newExtraX; + // make sure this label doesn't overlap other labels + // this *only* has us move these labels vertically + if(newExtraY * yDiffSign > 0) thisPt.labelExtraY = newExtraY; + + // make sure this label doesn't overlap any slices + if(!Array.isArray(trace.pull)) return; // this can only happen with array pulls + + for(i = 0; i < wholeSide.length; i++) { + otherPt = wholeSide[i]; + + // overlap can only happen if the other point is pulled more than this one + if(otherPt === thisPt || ((trace.pull[thisPt.i] || 0) >= trace.pull[otherPt.i] || 0)) continue; + + if((thisPt.pxmid[1] - otherPt.pxmid[1]) * yDiffSign > 0) { + // closer to the equator - by construction all of these happen first + // move the text vertically to get away from these slices + otherOuterY = otherPt.cyFinal + farthestY(otherPt.px0[1], otherPt.px1[1]); + newExtraY = otherOuterY - thisInnerY - thisPt.labelExtraY; + + if(newExtraY * yDiffSign > 0) thisPt.labelExtraY += newExtraY; + + } else if((thisOuterY + thisPt.labelExtraY - thisSliceOuterY) * yDiffSign > 0) { + // farther from the equator - happens after we've done all the + // vertical moving we're going to do + // move horizontally to get away from these more polar slices + + // if we're moving horz. based on a slice that's several slices away from this one + // then we need some extra space for the lines to labels between them + xBuffer = 3 * xDiffSign * Math.abs(i - wholeSide.indexOf(thisPt)); + + otherOuterX = otherPt.cxFinal + farthestX(otherPt.px0[0], otherPt.px1[0]); + newExtraX = otherOuterX + xBuffer - (thisPt.cxFinal + thisPt.pxmid[0]) - thisPt.labelExtraX; + + if(newExtraX * xDiffSign > 0) thisPt.labelExtraX += newExtraX; + } + } + } + + for(yHalf = 0; yHalf < 2; yHalf++) { + equatorFirst = yHalf ? topFirst : bottomFirst; + farthestY = yHalf ? Math.max : Math.min; + yDiffSign = yHalf ? 1 : -1; + + for(xHalf = 0; xHalf < 2; xHalf++) { + farthestX = xHalf ? Math.max : Math.min; + xDiffSign = xHalf ? 1 : -1; + + // first sort the array + // note this is a copy of cd, so cd itself doesn't get sorted + // but we can still modify points in place. + thisQuad = quadrants[yHalf][xHalf]; + thisQuad.sort(equatorFirst); + + oppositeQuad = quadrants[1 - yHalf][xHalf]; + wholeSide = oppositeQuad.concat(thisQuad); + + thisQuadOutside = []; + for(i = 0; i < thisQuad.length; i++) { + if(thisQuad[i].yLabelMid !== undefined) thisQuadOutside.push(thisQuad[i]); + } + + firstOppositeOutsidePt = false; + for(i = 0; yHalf && i < oppositeQuad.length; i++) { + if(oppositeQuad[i].yLabelMid !== undefined) { + firstOppositeOutsidePt = oppositeQuad[i]; + break; + } + } + + // each needs to avoid the previous + for(i = 0; i < thisQuadOutside.length; i++) { + var prevPt = i && thisQuadOutside[i - 1]; + // bottom half needs to avoid the first label of the top half + // top half we still need to call scootOneLabel on the first slice + // so we can avoid other slices, but we don't pass a prevPt + if(firstOppositeOutsidePt && !i) prevPt = firstOppositeOutsidePt; + scootOneLabel(thisQuadOutside[i], prevPt); + } + } + } +} + +function scalePies(cdpie, plotSize) { + var pieBoxWidth, + pieBoxHeight, + i, + j, + cd0, + trace, + tiltAxisRads, + maxPull, + scaleGroups = [], + scaleGroup, + minPxPerValUnit; + + // first figure out the center and maximum radius for each pie + for(i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + trace = cd0.trace; + pieBoxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]); + pieBoxHeight = plotSize.h * (trace.domain.y[1] - trace.domain.y[0]); + tiltAxisRads = trace.tiltaxis * Math.PI / 180; + + maxPull = trace.pull; + if(Array.isArray(maxPull)) { + maxPull = 0; + for(j = 0; j < trace.pull.length; j++) { + if(trace.pull[j] > maxPull) maxPull = trace.pull[j]; + } + } + + cd0.r = Math.min( + pieBoxWidth / maxExtent(trace.tilt, Math.sin(tiltAxisRads), trace.depth), + pieBoxHeight / maxExtent(trace.tilt, Math.cos(tiltAxisRads), trace.depth) + ) / (2 + 2 * maxPull); + + cd0.cx = plotSize.l + plotSize.w * (trace.domain.x[1] + trace.domain.x[0]) / 2; + cd0.cy = plotSize.t + plotSize.h * (2 - trace.domain.y[1] - trace.domain.y[0]) / 2; + + if(trace.scalegroup && scaleGroups.indexOf(trace.scalegroup) === -1) { + scaleGroups.push(trace.scalegroup); + } + } + + // Then scale any pies that are grouped + for(j = 0; j < scaleGroups.length; j++) { + minPxPerValUnit = Infinity; + scaleGroup = scaleGroups[j]; + + for(i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + if(cd0.trace.scalegroup === scaleGroup) { + minPxPerValUnit = Math.min(minPxPerValUnit, + cd0.r * cd0.r / cd0.vTotal); + } + } + + for(i = 0; i < cdpie.length; i++) { + cd0 = cdpie[i][0]; + if(cd0.trace.scalegroup === scaleGroup) { + cd0.r = Math.sqrt(minPxPerValUnit * cd0.vTotal); + } + } + } + +} + +function setCoords(cd) { + var cd0 = cd[0], + trace = cd0.trace, + tilt = trace.tilt, + tiltAxisRads, + tiltAxisSin, + tiltAxisCos, + tiltRads, + crossTilt, + inPlane, + currentAngle = trace.rotation * Math.PI / 180, + angleFactor = 2 * Math.PI / cd0.vTotal, + firstPt = 'px0', + lastPt = 'px1', + i, + cdi, + currentCoords; + + if(trace.direction === 'counterclockwise') { + for(i = 0; i < cd.length; i++) { + if(!cd[i].hidden) break; // find the first non-hidden slice + } + if(i === cd.length) return; // all slices hidden + + currentAngle += angleFactor * cd[i].v; + angleFactor *= -1; + firstPt = 'px1'; + lastPt = 'px0'; + } + + if(tilt) { + tiltRads = tilt * Math.PI / 180; + tiltAxisRads = trace.tiltaxis * Math.PI / 180; + crossTilt = Math.sin(tiltAxisRads) * Math.cos(tiltAxisRads); + inPlane = 1 - Math.cos(tiltRads); + tiltAxisSin = Math.sin(tiltAxisRads); + tiltAxisCos = Math.cos(tiltAxisRads); + } + + function getCoords(angle) { + var xFlat = cd0.r * Math.sin(angle), + yFlat = -cd0.r * Math.cos(angle); + + if(!tilt) return [xFlat, yFlat]; + + return [ + xFlat * (1 - inPlane * tiltAxisSin * tiltAxisSin) + yFlat * crossTilt * inPlane, + xFlat * crossTilt * inPlane + yFlat * (1 - inPlane * tiltAxisCos * tiltAxisCos), + Math.sin(tiltRads) * (yFlat * tiltAxisCos - xFlat * tiltAxisSin) + ]; + } + + currentCoords = getCoords(currentAngle); + + for(i = 0; i < cd.length; i++) { + cdi = cd[i]; + if(cdi.hidden) continue; + + cdi[firstPt] = currentCoords; + + currentAngle += angleFactor * cdi.v / 2; + cdi.pxmid = getCoords(currentAngle); + cdi.midangle = currentAngle; + + currentAngle += angleFactor * cdi.v / 2; + currentCoords = getCoords(currentAngle); + + cdi[lastPt] = currentCoords; + + cdi.largeArc = (cdi.v > cd0.vTotal / 2) ? 1 : 0; + } +} + +function maxExtent(tilt, tiltAxisFraction, depth) { + if(!tilt) return 1; + var sinTilt = Math.sin(tilt * Math.PI / 180); + return Math.max(0.01, // don't let it go crazy if you tilt the pie totally on its side + depth * sinTilt * Math.abs(tiltAxisFraction) + + 2 * Math.sqrt(1 - sinTilt * sinTilt * tiltAxisFraction * tiltAxisFraction)); +} + +},{"../../components/color":27,"../../components/drawing":50,"../../lib/svg_text_utils":134,"../../plots/cartesian/graph_interact":157,"./helpers":226,"d3":10}],231:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var d3 = require('d3'); + +var styleOne = require('./style_one'); + +module.exports = function style(gd) { + gd._fullLayout._pielayer.selectAll('.trace').each(function(cd) { + var cd0 = cd[0], + trace = cd0.trace, + traceSelection = d3.select(this); + + traceSelection.style({opacity: trace.opacity}); + + traceSelection.selectAll('.top path.surface').each(function(pt) { + d3.select(this).call(styleOne, pt, trace); + }); + }); +}; + +},{"./style_one":232,"d3":10}],232:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var Color = require('../../components/color'); + +module.exports = function styleOne(s, pt, trace) { + var lineColor = trace.marker.line.color; + if(Array.isArray(lineColor)) lineColor = lineColor[pt.i] || Color.defaultLine; + + var lineWidth = trace.marker.line.width || 0; + if(Array.isArray(lineWidth)) lineWidth = lineWidth[pt.i] || 0; + + s.style({ + 'stroke-width': lineWidth, + fill: pt.color + }) + .call(Color.stroke, lineColor); +}; + +},{"../../components/color":27}],233:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + + +// arrayOk attributes, merge them into calcdata array +module.exports = function arraysToCalcdata(cd) { + var trace = cd[0].trace, + marker = trace.marker; + + Lib.mergeArray(trace.text, cd, 'tx'); + Lib.mergeArray(trace.textposition, cd, 'tp'); + if(trace.textfont) { + Lib.mergeArray(trace.textfont.size, cd, 'ts'); + Lib.mergeArray(trace.textfont.color, cd, 'tc'); + Lib.mergeArray(trace.textfont.family, cd, 'tf'); + } + + if(marker && marker.line) { + var markerLine = marker.line; + Lib.mergeArray(marker.opacity, cd, 'mo'); + Lib.mergeArray(marker.symbol, cd, 'mx'); + Lib.mergeArray(marker.color, cd, 'mc'); + Lib.mergeArray(markerLine.color, cd, 'mlc'); + Lib.mergeArray(markerLine.width, cd, 'mlw'); + } +}; + +},{"../../lib":122}],234:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var colorAttributes = require('../../components/colorscale/color_attributes'); +var errorBarAttrs = require('../../components/errorbars/attributes'); +var colorbarAttrs = require('../../components/colorbar/attributes'); + +var Drawing = require('../../components/drawing'); +var constants = require('./constants'); +var extendFlat = require('../../lib/extend').extendFlat; + +module.exports = { + x: { + valType: 'data_array', + + }, + x0: { + valType: 'any', + dflt: 0, + + + }, + dx: { + valType: 'number', + dflt: 1, + + + }, + y: { + valType: 'data_array', + + }, + y0: { + valType: 'any', + dflt: 0, + + + }, + dy: { + valType: 'number', + dflt: 1, + + + }, + ids: { + valType: 'data_array', + + }, + text: { + valType: 'string', + + dflt: '', + arrayOk: true, + + }, + mode: { + valType: 'flaglist', + flags: ['lines', 'markers', 'text'], + extras: ['none'], + + + }, + hoveron: { + valType: 'flaglist', + flags: ['points', 'fills'], + + + }, + line: { + color: { + valType: 'color', + + + }, + width: { + valType: 'number', + min: 0, + dflt: 2, + + + }, + shape: { + valType: 'enumerated', + values: ['linear', 'spline', 'hv', 'vh', 'hvh', 'vhv'], + dflt: 'linear', + + + }, + smoothing: { + valType: 'number', + min: 0, + max: 1.3, + dflt: 1, + + + }, + dash: { + valType: 'string', + // string type usually doesn't take values... this one should really be + // a special type or at least a special coercion function, from the GUI + // you only get these values but elsewhere the user can supply a list of + // dash lengths in px, and it will be honored + values: ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot'], + dflt: 'solid', + + + }, + simplify: { + valType: 'boolean', + dflt: true, + + + } + }, + connectgaps: { + valType: 'boolean', + dflt: false, + + + }, + fill: { + valType: 'enumerated', + values: ['none', 'tozeroy', 'tozerox', 'tonexty', 'tonextx', 'toself', 'tonext'], + dflt: 'none', + + + }, + fillcolor: { + valType: 'color', + + + }, + marker: extendFlat({}, { + symbol: { + valType: 'enumerated', + values: Drawing.symbolList, + dflt: 'circle', + arrayOk: true, + + + }, + opacity: { + valType: 'number', + min: 0, + max: 1, + arrayOk: true, + + + }, + size: { + valType: 'number', + min: 0, + dflt: 6, + arrayOk: true, + + + }, + maxdisplayed: { + valType: 'number', + min: 0, + dflt: 0, + + + }, + sizeref: { + valType: 'number', + dflt: 1, + + + }, + sizemin: { + valType: 'number', + min: 0, + dflt: 0, + + + }, + sizemode: { + valType: 'enumerated', + values: ['diameter', 'area'], + dflt: 'diameter', + + + }, + + showscale: { + valType: 'boolean', + + dflt: false, + + }, + colorbar: colorbarAttrs, + + line: extendFlat({}, { + width: { + valType: 'number', + min: 0, + arrayOk: true, + + + } + }, + colorAttributes('marker.line') + ) + }, + colorAttributes('marker') + ), + textposition: { + valType: 'enumerated', + values: [ + 'top left', 'top center', 'top right', + 'middle left', 'middle center', 'middle right', + 'bottom left', 'bottom center', 'bottom right' + ], + dflt: 'middle center', + arrayOk: true, + + + }, + textfont: { + family: { + valType: 'string', + + noBlank: true, + strict: true, + arrayOk: true + }, + size: { + valType: 'number', + + min: 1, + arrayOk: true + }, + color: { + valType: 'color', + + arrayOk: true + }, + + }, + + r: { + valType: 'data_array', + + }, + t: { + valType: 'data_array', + + }, + + error_y: errorBarAttrs, + error_x: errorBarAttrs +}; + +},{"../../components/colorbar/attributes":28,"../../components/colorscale/color_attributes":34,"../../components/drawing":50,"../../components/errorbars/attributes":52,"../../lib/extend":117,"./constants":239}],235:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Axes = require('../../plots/cartesian/axes'); +var Lib = require('../../lib'); + +var subTypes = require('./subtypes'); +var calcColorscale = require('./colorscale_calc'); + + +module.exports = function calc(gd, trace) { + var xa = Axes.getFromId(gd, trace.xaxis || 'x'), + ya = Axes.getFromId(gd, trace.yaxis || 'y'); + + var x = xa.makeCalcdata(trace, 'x'), + y = ya.makeCalcdata(trace, 'y'); + + var serieslen = Math.min(x.length, y.length), + marker, + s, + i; + + // cancel minimum tick spacings (only applies to bars and boxes) + xa._minDtick = 0; + ya._minDtick = 0; + + if(x.length > serieslen) x.splice(serieslen, x.length - serieslen); + if(y.length > serieslen) y.splice(serieslen, y.length - serieslen); + + // check whether bounds should be tight, padded, extended to zero... + // most cases both should be padded on both ends, so start with that. + var xOptions = {padded: true}, + yOptions = {padded: true}; + + if(subTypes.hasMarkers(trace)) { + + // Treat size like x or y arrays --- Run d2c + // this needs to go before ppad computation + marker = trace.marker; + s = marker.size; + + if(Array.isArray(s)) { + // I tried auto-type but category and dates dont make much sense. + var ax = {type: 'linear'}; + Axes.setConvert(ax); + s = ax.makeCalcdata(trace.marker, 'size'); + if(s.length > serieslen) s.splice(serieslen, s.length - serieslen); + } + + var sizeref = 1.6 * (trace.marker.sizeref || 1), + markerTrans; + if(trace.marker.sizemode === 'area') { + markerTrans = function(v) { + return Math.max(Math.sqrt((v || 0) / sizeref), 3); + }; + } + else { + markerTrans = function(v) { + return Math.max((v || 0) / sizeref, 3); + }; + } + xOptions.ppad = yOptions.ppad = Array.isArray(s) ? + s.map(markerTrans) : markerTrans(s); + } + + calcColorscale(trace); + + // TODO: text size + + // include zero (tight) and extremes (padded) if fill to zero + // (unless the shape is closed, then it's just filling the shape regardless) + if(((trace.fill === 'tozerox') || + ((trace.fill === 'tonextx') && gd.firstscatter)) && + ((x[0] !== x[serieslen - 1]) || (y[0] !== y[serieslen - 1]))) { + xOptions.tozero = true; + } + + // if no error bars, markers or text, or fill to y=0 remove x padding + else if(!trace.error_y.visible && ( + ['tonexty', 'tozeroy'].indexOf(trace.fill) !== -1 || + (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace)) + )) { + xOptions.padded = false; + xOptions.ppad = 0; + } + + // now check for y - rather different logic, though still mostly padded both ends + // include zero (tight) and extremes (padded) if fill to zero + // (unless the shape is closed, then it's just filling the shape regardless) + if(((trace.fill === 'tozeroy') || ((trace.fill === 'tonexty') && gd.firstscatter)) && + ((x[0] !== x[serieslen - 1]) || (y[0] !== y[serieslen - 1]))) { + yOptions.tozero = true; + } + + // tight y: any x fill + else if(['tonextx', 'tozerox'].indexOf(trace.fill) !== -1) { + yOptions.padded = false; + } + + Axes.expand(xa, x, xOptions); + Axes.expand(ya, y, yOptions); + + // create the "calculated data" to plot + var cd = new Array(serieslen); + for(i = 0; i < serieslen; i++) { + cd[i] = (isNumeric(x[i]) && isNumeric(y[i])) ? + {x: x[i], y: y[i]} : {x: false, y: false}; + + if(trace.ids) { + cd[i].id = String(trace.ids[i]); + } + } + + // this has migrated up from arraysToCalcdata as we have a reference to 's' here + if(typeof s !== 'undefined') Lib.mergeArray(s, cd, 'ms'); + + gd.firstscatter = false; + return cd; +}; + +},{"../../lib":122,"../../plots/cartesian/axes":150,"./colorscale_calc":238,"./subtypes":254,"fast-isnumeric":13}],236:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +// remove opacity for any trace that has a fill or is filled to +module.exports = function cleanData(fullData) { + for(var i = 0; i < fullData.length; i++) { + var tracei = fullData[i]; + if(tracei.type !== 'scatter') continue; + + var filli = tracei.fill; + if(filli === 'none' || filli === 'toself') continue; + + tracei.opacity = undefined; + + if(filli === 'tonexty' || filli === 'tonextx') { + for(var j = i - 1; j >= 0; j--) { + var tracej = fullData[j]; + + if((tracej.type === 'scatter') && + (tracej.xaxis === tracei.xaxis) && + (tracej.yaxis === tracei.yaxis)) { + tracej.opacity = undefined; + break; + } + } + } + } +}; + +},{}],237:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var Lib = require('../../lib'); +var Plots = require('../../plots/plots'); +var Colorscale = require('../../components/colorscale'); +var drawColorbar = require('../../components/colorbar/draw'); + + +module.exports = function colorbar(gd, cd) { + var trace = cd[0].trace, + marker = trace.marker, + cbId = 'cb' + trace.uid; + + gd._fullLayout._infolayer.selectAll('.' + cbId).remove(); + + // TODO unify scatter and heatmap colorbar + // TODO make Colorbar.draw support multiple colorbar per trace + + if((marker === undefined) || !marker.showscale) { + Plots.autoMargin(gd, cbId); + return; + } + + var vals = marker.color, + cmin = marker.cmin, + cmax = marker.cmax; + + if(!isNumeric(cmin)) cmin = Lib.aggNums(Math.min, null, vals); + if(!isNumeric(cmax)) cmax = Lib.aggNums(Math.max, null, vals); + + var cb = cd[0].t.cb = drawColorbar(gd, cbId); + var sclFunc = Colorscale.makeColorScaleFunc( + Colorscale.extractScale( + marker.colorscale, + cmin, + cmax + ), + { noNumericCheck: true } + ); + + cb.fillcolor(sclFunc) + .filllevels({start: cmin, end: cmax, size: (cmax - cmin) / 254}) + .options(marker.colorbar)(); +}; + +},{"../../components/colorbar/draw":30,"../../components/colorscale":41,"../../lib":122,"../../plots/plots":186,"fast-isnumeric":13}],238:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var calcColorscale = require('../../components/colorscale/calc'); + +var subTypes = require('./subtypes'); + + +module.exports = function calcMarkerColorscale(trace) { + if(subTypes.hasLines(trace) && hasColorscale(trace, 'line')) { + calcColorscale(trace, trace.line.color, 'line', 'c'); + } + + if(subTypes.hasMarkers(trace)) { + if(hasColorscale(trace, 'marker')) { + calcColorscale(trace, trace.marker.color, 'marker', 'c'); + } + if(hasColorscale(trace, 'marker.line')) { + calcColorscale(trace, trace.marker.line.color, 'marker.line', 'c'); + } + } +}; + +},{"../../components/colorscale/calc":33,"../../components/colorscale/has_colorscale":40,"./subtypes":254}],239:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +module.exports = { + PTS_LINESONLY: 20 +}; + +},{}],240:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + +var attributes = require('./attributes'); +var constants = require('./constants'); +var subTypes = require('./subtypes'); +var handleXYDefaults = require('./xy_defaults'); +var handleMarkerDefaults = require('./marker_defaults'); +var handleLineDefaults = require('./line_defaults'); +var handleLineShapeDefaults = require('./line_shape_defaults'); +var handleTextDefaults = require('./text_defaults'); +var handleFillColorDefaults = require('./fillcolor_defaults'); +var errorBarsSupplyDefaults = require('../../components/errorbars/defaults'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleXYDefaults(traceIn, traceOut, coerce), + // TODO: default mode by orphan points... + defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + coerce('mode', defaultMode); + coerce('ids'); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + handleLineShapeDefaults(traceIn, traceOut, coerce); + coerce('connectgaps'); + coerce('line.simplify'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + var dfltHoverOn = []; + + if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { + coerce('marker.maxdisplayed'); + dfltHoverOn.push('points'); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); + } + + if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { + dfltHoverOn.push('fills'); + } + coerce('hoveron', dfltHoverOn.join('+') || 'points'); + + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'y'}); + errorBarsSupplyDefaults(traceIn, traceOut, defaultColor, {axis: 'x', inherit: 'y'}); +}; + +},{"../../components/errorbars/defaults":55,"../../lib":122,"./attributes":234,"./constants":239,"./fillcolor_defaults":241,"./line_defaults":245,"./line_shape_defaults":247,"./marker_defaults":250,"./subtypes":254,"./text_defaults":255,"./xy_defaults":256}],241:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = require('../../components/color'); + + +module.exports = function fillColorDefaults(traceIn, traceOut, defaultColor, coerce) { + var inheritColorFromMarker = false; + + if(traceOut.marker) { + // don't try to inherit a color array + var markerColor = traceOut.marker.color, + markerLineColor = (traceOut.marker.line || {}).color; + + if(markerColor && !Array.isArray(markerColor)) { + inheritColorFromMarker = markerColor; + } + else if(markerLineColor && !Array.isArray(markerLineColor)) { + inheritColorFromMarker = markerLineColor; + } + } + + coerce('fillcolor', Color.addOpacity( + (traceOut.line || {}).color || + inheritColorFromMarker || + defaultColor, 0.5 + )); +}; + +},{"../../components/color":27}],242:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = require('../../components/color'); +var subtypes = require('./subtypes'); + + +module.exports = function getTraceColor(trace, di) { + var lc, tc; + + // TODO: text modes + + if(trace.mode === 'lines') { + lc = trace.line.color; + return (lc && Color.opacity(lc)) ? + lc : trace.fillcolor; + } + else if(trace.mode === 'none') { + return trace.fill ? trace.fillcolor : ''; + } + else { + var mc = di.mcc || (trace.marker || {}).color, + mlc = di.mlcc || ((trace.marker || {}).line || {}).color; + + tc = (mc && Color.opacity(mc)) ? mc : + (mlc && Color.opacity(mlc) && + (di.mlw || ((trace.marker || {}).line || {}).width)) ? mlc : ''; + + if(tc) { + // make sure the points aren't TOO transparent + if(Color.opacity(tc) < 0.3) { + return Color.addOpacity(tc, 0.3); + } + else return tc; + } + else { + lc = (trace.line || {}).color; + return (lc && Color.opacity(lc) && + subtypes.hasLines(trace) && trace.line.width) ? + lc : trace.fillcolor; + } + } +}; + +},{"../../components/color":27,"./subtypes":254}],243:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); +var Fx = require('../../plots/cartesian/graph_interact'); +var constants = require('../../plots/cartesian/constants'); +var ErrorBars = require('../../components/errorbars'); +var getTraceColor = require('./get_trace_color'); +var Color = require('../../components/color'); + + +module.exports = function hoverPoints(pointData, xval, yval, hovermode) { + var cd = pointData.cd, + trace = cd[0].trace, + xa = pointData.xa, + ya = pointData.ya, + xpx = xa.c2p(xval), + ypx = ya.c2p(yval), + pt = [xpx, ypx]; + + if(pointData.trace._input.rect){ + var found = false; + var rect = pointData.trace._input.rect; + for(var i=0;i rect[i].x0 && xval < rect[i].x1 && yval > rect[i].y0 && yval < rect[i].y1){ + pointData.index = i; + pointData.text = pointData.trace.text[i]; + found = true; + } + } + + if(!found) return; + } + + // look for points to hover on first, then take fills only if we + // didn't find a point + if(trace.hoveron.indexOf('points') !== -1) { + var dx = function(di) { + // scatter points: d.mrc is the calculated marker radius + // adjust the distance so if you're inside the marker it + // always will show up regardless of point size, but + // prioritize smaller points + var rad = Math.max(3, di.mrc || 0); + return Math.max(Math.abs(xa.c2p(di.x) - xpx) - rad, 1 - 3 / rad); + }, + dy = function(di) { + var rad = Math.max(3, di.mrc || 0); + return Math.max(Math.abs(ya.c2p(di.y) - ypx) - rad, 1 - 3 / rad); + }, + dxy = function(di) { + var rad = Math.max(3, di.mrc || 0), + dx = xa.c2p(di.x) - xpx, + dy = ya.c2p(di.y) - ypx; + return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad); + }, + distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); + + Fx.getClosest(cd, distfn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index !== false) { + + // the closest data point + var di = cd[pointData.index], + xc = xa.c2p(di.x, true), + yc = ya.c2p(di.y, true), + rad = di.mrc || 1; + + Lib.extendFlat(pointData, { + color: getTraceColor(trace, di), + + x0: xc - rad, + x1: xc + rad, + xLabelVal: di.x, + + y0: yc - rad, + y1: yc + rad, + yLabelVal: di.y + }); + + if(di.tx) pointData.text = di.tx; + else if(trace.text) pointData.text = trace.text; + + ErrorBars.hoverInfo(di, trace, pointData); + + return [pointData]; + } + } + + // even if hoveron is 'fills', only use it if we have polygons too + if(trace.hoveron.indexOf('fills') !== -1 && trace._polygons) { + var polygons = trace._polygons, + polygonsIn = [], + inside = false, + xmin = Infinity, + xmax = -Infinity, + ymin = Infinity, + ymax = -Infinity, + i, j, polygon, pts, xCross, x0, x1, y0, y1; + + for(i = 0; i < polygons.length; i++) { + polygon = polygons[i]; + // TODO: this is not going to work right for curved edges, it will + // act as though they're straight. That's probably going to need + // the elements themselves to capture the events. Worth it? + if(polygon.contains(pt)) { + inside = !inside; + // TODO: need better than just the overall bounding box + polygonsIn.push(polygon); + ymin = Math.min(ymin, polygon.ymin); + ymax = Math.max(ymax, polygon.ymax); + } + } + + if(inside) { + // constrain ymin/max to the visible plot, so the label goes + // at the middle of the piece you can see + ymin = Math.max(ymin, 0); + ymax = Math.min(ymax, ya._length); + + // find the overall left-most and right-most points of the + // polygon(s) we're inside at their combined vertical midpoint. + // This is where we will draw the hover label. + // Note that this might not be the vertical midpoint of the + // whole trace, if it's disjoint. + var yAvg = (ymin + ymax) / 2; + for(i = 0; i < polygonsIn.length; i++) { + pts = polygonsIn[i].pts; + for(j = 1; j < pts.length; j++) { + y0 = pts[j - 1][1]; + y1 = pts[j][1]; + if((y0 > yAvg) !== (y1 >= yAvg)) { + x0 = pts[j - 1][0]; + x1 = pts[j][0]; + xCross = x0 + (x1 - x0) * (yAvg - y0) / (y1 - y0); + xmin = Math.min(xmin, xCross); + xmax = Math.max(xmax, xCross); + } + } + } + + // constrain xmin/max to the visible plot now too + xmin = Math.max(xmin, 0); + xmax = Math.min(xmax, xa._length); + + // get only fill or line color for the hover color + var color = Color.defaultLine; + if(Color.opacity(trace.fillcolor)) color = trace.fillcolor; + else if(Color.opacity((trace.line || {}).color)) { + color = trace.line.color; + } + + Lib.extendFlat(pointData, { + // never let a 2D override 1D type as closest point + distance: constants.MAXDIST + 10, + x0: xmin, + x1: xmax, + y0: yAvg, + y1: yAvg, + color: color + }); + + delete pointData.index; + + if(trace.text && !Array.isArray(trace.text)) { + pointData.text = String(trace.text); + } + else pointData.text = trace.name; + + return [pointData]; + } + } +}; + +},{"../../components/color":27,"../../components/errorbars":56,"../../lib":122,"../../plots/cartesian/constants":155,"../../plots/cartesian/graph_interact":157,"./get_trace_color":242}],244:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Scatter = {}; + +var subtypes = require('./subtypes'); +Scatter.hasLines = subtypes.hasLines; +Scatter.hasMarkers = subtypes.hasMarkers; +Scatter.hasText = subtypes.hasText; +Scatter.isBubble = subtypes.isBubble; + +// traces with < this many points are by default shown +// with points and lines, > just get lines +Scatter.attributes = require('./attributes'); +Scatter.supplyDefaults = require('./defaults'); +Scatter.cleanData = require('./clean_data'); +Scatter.calc = require('./calc'); +Scatter.arraysToCalcdata = require('./arrays_to_calcdata'); +Scatter.plot = require('./plot'); +Scatter.colorbar = require('./colorbar'); +Scatter.style = require('./style'); +Scatter.hoverPoints = require('./hover'); +Scatter.selectPoints = require('./select'); +Scatter.animatable = true; + +Scatter.moduleType = 'trace'; +Scatter.name = 'scatter'; +Scatter.basePlotModule = require('../../plots/cartesian'); +Scatter.categories = ['cartesian', 'symbols', 'markerColorscale', 'errorBarsOK', 'showLegend']; +Scatter.meta = { + +}; + +module.exports = Scatter; + +},{"../../plots/cartesian":158,"./arrays_to_calcdata":233,"./attributes":234,"./calc":235,"./clean_data":236,"./colorbar":237,"./defaults":240,"./hover":243,"./plot":251,"./select":252,"./style":253,"./subtypes":254}],245:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = require('../../components/colorscale/defaults'); + + +module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { + var markerColor = (traceIn.marker || {}).color; + + coerce('line.color', defaultColor); + + if(hasColorscale(traceIn, 'line')) { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); + } + else { + var lineColorDflt = (Array.isArray(markerColor) ? false : markerColor) || defaultColor; + coerce('line.color', lineColorDflt); + } + + coerce('line.width'); + coerce('line.dash'); +}; + +},{"../../components/colorscale/defaults":36,"../../components/colorscale/has_colorscale":40}],246:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var BADNUM = require('../../constants/numerical').BADNUM; + + +module.exports = function linePoints(d, opts) { + var xa = opts.xaxis, + ya = opts.yaxis, + simplify = opts.simplify, + connectGaps = opts.connectGaps, + baseTolerance = opts.baseTolerance, + linear = opts.linear, + segments = [], + minTolerance = 0.2, // fraction of tolerance "so close we don't even consider it a new point" + pts = new Array(d.length), + pti = 0, + i, + + // pt variables are pixel coordinates [x,y] of one point + clusterStartPt, // these four are the outputs of clustering on a line + clusterEndPt, + clusterHighPt, + clusterLowPt, + thisPt, // "this" is the next point we're considering adding to the cluster + + clusterRefDist, + clusterHighFirst, // did we encounter the high point first, then a low point, or vice versa? + clusterUnitVector, // the first two points in the cluster determine its unit vector + // so the second is always in the "High" direction + thisVector, // the pixel delta from clusterStartPt + + // val variables are (signed) pixel distances along the cluster vector + clusterHighVal, + clusterLowVal, + thisVal, + + // deviation variables are (signed) pixel distances normal to the cluster vector + clusterMinDeviation, + clusterMaxDeviation, + thisDeviation; + + if(!simplify) { + baseTolerance = minTolerance = -1; + } + + // turn one calcdata point into pixel coordinates + function getPt(index) { + var x = xa.c2p(d[index].x), + y = ya.c2p(d[index].y); + if(x === BADNUM || y === BADNUM) return false; + return [x, y]; + } + + // if we're off-screen, increase tolerance over baseTolerance + function getTolerance(pt) { + var xFrac = pt[0] / xa._length, + yFrac = pt[1] / ya._length; + return (1 + 10 * Math.max(0, -xFrac, xFrac - 1, -yFrac, yFrac - 1)) * baseTolerance; + } + + function ptDist(pt1, pt2) { + var dx = pt1[0] - pt2[0], + dy = pt1[1] - pt2[1]; + return Math.sqrt(dx * dx + dy * dy); + } + + // loop over ALL points in this trace + for(i = 0; i < d.length; i++) { + clusterStartPt = getPt(i); + if(!clusterStartPt) continue; + + pti = 0; + pts[pti++] = clusterStartPt; + + // loop over one segment of the trace + for(i++; i < d.length; i++) { + clusterHighPt = getPt(i); + if(!clusterHighPt) { + if(connectGaps) continue; + else break; + } + + // can't decimate if nonlinear line shape + // TODO: we *could* decimate [hv]{2,3} shapes if we restricted clusters to horz or vert again + // but spline would be verrry awkward to decimate + if(!linear) { + pts[pti++] = clusterHighPt; + continue; + } + + clusterRefDist = ptDist(clusterHighPt, clusterStartPt); + + if(clusterRefDist < getTolerance(clusterHighPt) * minTolerance) continue; + + clusterUnitVector = [ + (clusterHighPt[0] - clusterStartPt[0]) / clusterRefDist, + (clusterHighPt[1] - clusterStartPt[1]) / clusterRefDist + ]; + + clusterLowPt = clusterStartPt; + clusterHighVal = clusterRefDist; + clusterLowVal = clusterMinDeviation = clusterMaxDeviation = 0; + clusterHighFirst = false; + clusterEndPt = clusterHighPt; + + // loop over one cluster of points that collapse onto one line + for(i++; i < d.length; i++) { + thisPt = getPt(i); + if(!thisPt) { + if(connectGaps) continue; + else break; + } + thisVector = [ + thisPt[0] - clusterStartPt[0], + thisPt[1] - clusterStartPt[1] + ]; + // cross product (or dot with normal to the cluster vector) + thisDeviation = thisVector[0] * clusterUnitVector[1] - thisVector[1] * clusterUnitVector[0]; + clusterMinDeviation = Math.min(clusterMinDeviation, thisDeviation); + clusterMaxDeviation = Math.max(clusterMaxDeviation, thisDeviation); + + if(clusterMaxDeviation - clusterMinDeviation > getTolerance(thisPt)) break; + + clusterEndPt = thisPt; + thisVal = thisVector[0] * clusterUnitVector[0] + thisVector[1] * clusterUnitVector[1]; + + if(thisVal > clusterHighVal) { + clusterHighVal = thisVal; + clusterHighPt = thisPt; + clusterHighFirst = false; + } else if(thisVal < clusterLowVal) { + clusterLowVal = thisVal; + clusterLowPt = thisPt; + clusterHighFirst = true; + } + } + + // insert this cluster into pts + // we've already inserted the start pt, now check if we have high and low pts + if(clusterHighFirst) { + pts[pti++] = clusterHighPt; + if(clusterEndPt !== clusterLowPt) pts[pti++] = clusterLowPt; + } else { + if(clusterLowPt !== clusterStartPt) pts[pti++] = clusterLowPt; + if(clusterEndPt !== clusterHighPt) pts[pti++] = clusterHighPt; + } + // and finally insert the end pt + pts[pti++] = clusterEndPt; + + // have we reached the end of this segment? + if(i >= d.length || !thisPt) break; + + // otherwise we have an out-of-cluster point to insert as next clusterStartPt + pts[pti++] = thisPt; + clusterStartPt = thisPt; + } + + segments.push(pts.slice(0, pti)); + } + + return segments; +}; + +},{"../../constants/numerical":107}],247:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +// common to 'scatter' and 'scatterternary' +module.exports = function handleLineShapeDefaults(traceIn, traceOut, coerce) { + var shape = coerce('line.shape'); + if(shape === 'spline') coerce('line.smoothing'); +}; + +},{}],248:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +module.exports = function linkTraces(gd, plotinfo, cdscatter) { + var cd, trace; + var prevtrace = null; + + for(var i = 0; i < cdscatter.length; ++i) { + cd = cdscatter[i]; + trace = cd[0].trace; + + // Note: The check which ensures all cdscatter here are for the same axis and + // are either cartesian or scatterternary has been removed. This code assumes + // the passed scattertraces have been filtered to the proper plot types and + // the proper subplots. + if(trace.visible === true) { + trace._nexttrace = null; + + if(['tonextx', 'tonexty', 'tonext'].indexOf(trace.fill) !== -1) { + trace._prevtrace = prevtrace; + + if(prevtrace) { + prevtrace._nexttrace = trace; + } + } + + prevtrace = trace; + } else { + trace._prevtrace = trace._nexttrace = null; + } + } +}; + +},{}],249:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + + +// used in the drawing step for 'scatter' and 'scattegeo' and +// in the convert step for 'scatter3d' +module.exports = function makeBubbleSizeFn(trace) { + var marker = trace.marker, + sizeRef = marker.sizeref || 1, + sizeMin = marker.sizemin || 0; + + // for bubble charts, allow scaling the provided value linearly + // and by area or diameter. + // Note this only applies to the array-value sizes + + var baseFn = (marker.sizemode === 'area') ? + function(v) { return Math.sqrt(v / sizeRef); } : + function(v) { return v / sizeRef; }; + + // TODO add support for position/negative bubbles? + // TODO add 'sizeoffset' attribute? + return function(v) { + var baseSize = baseFn(v / 2); + + // don't show non-numeric and negative sizes + return (isNumeric(baseSize) && (baseSize > 0)) ? + Math.max(baseSize, sizeMin) : + 0; + }; +}; + +},{"fast-isnumeric":13}],250:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Color = require('../../components/color'); +var hasColorscale = require('../../components/colorscale/has_colorscale'); +var colorscaleDefaults = require('../../components/colorscale/defaults'); + +var subTypes = require('./subtypes'); + + +module.exports = function markerDefaults(traceIn, traceOut, defaultColor, layout, coerce) { + var isBubble = subTypes.isBubble(traceIn), + lineColor = (traceIn.line || {}).color, + defaultMLC; + + // marker.color inherit from line.color (even if line.color is an array) + if(lineColor) defaultColor = lineColor; + + coerce('marker.symbol'); + coerce('marker.opacity', isBubble ? 0.7 : 1); + coerce('marker.size'); + + coerce('marker.color', defaultColor); + if(hasColorscale(traceIn, 'marker')) { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'}); + } + + // if there's a line with a different color than the marker, use + // that line color as the default marker line color + // (except when it's an array) + // mostly this is for transparent markers to behave nicely + if(lineColor && !Array.isArray(lineColor) && (traceOut.marker.color !== lineColor)) { + defaultMLC = lineColor; + } + else if(isBubble) defaultMLC = Color.background; + else defaultMLC = Color.defaultLine; + + coerce('marker.line.color', defaultMLC); + if(hasColorscale(traceIn, 'marker.line')) { + colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'}); + } + + coerce('marker.line.width', isBubble ? 1 : 0); + + if(isBubble) { + coerce('marker.sizeref'); + coerce('marker.sizemin'); + coerce('marker.sizemode'); + } +}; + +},{"../../components/color":27,"../../components/colorscale/defaults":36,"../../components/colorscale/has_colorscale":40,"./subtypes":254}],251:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Lib = require('../../lib'); +var Drawing = require('../../components/drawing'); +var ErrorBars = require('../../components/errorbars'); + +var subTypes = require('./subtypes'); +var arraysToCalcdata = require('./arrays_to_calcdata'); +var linePoints = require('./line_points'); +var linkTraces = require('./link_traces'); +var polygonTester = require('../../lib/polygon').tester; + +module.exports = function plot(gd, plotinfo, cdscatter, transitionOpts, makeOnCompleteCallback) { + var i, uids, selection, join, onComplete; + + var scatterlayer = plotinfo.plot.select('g.scatterlayer'); + + // If transition config is provided, then it is only a partial replot and traces not + // updated are removed. + var isFullReplot = !transitionOpts; + var hasTransition = !!transitionOpts && transitionOpts.duration > 0; + + selection = scatterlayer.selectAll('g.trace'); + + join = selection.data(cdscatter, function(d) { return d[0].trace.uid; }); + + // Append new traces: + join.enter().append('g') + .attr('class', function(d) { + return 'trace scatter trace' + d[0].trace.uid; + }) + .style('stroke-miterlimit', 2); + + // After the elements are created but before they've been draw, we have to perform + // this extra step of linking the traces. This allows appending of fill layers so that + // the z-order of fill layers is correct. + linkTraces(gd, plotinfo, cdscatter); + + createFills(gd, scatterlayer); + + // Sort the traces, once created, so that the ordering is preserved even when traces + // are shown and hidden. This is needed since we're not just wiping everything out + // and recreating on every update. + for(i = 0, uids = []; i < cdscatter.length; i++) { + uids[i] = cdscatter[i][0].trace.uid; + } + + scatterlayer.selectAll('g.trace').sort(function(a, b) { + var idx1 = uids.indexOf(a[0].trace.uid); + var idx2 = uids.indexOf(b[0].trace.uid); + return idx1 > idx2 ? 1 : -1; + }); + + if(hasTransition) { + if(makeOnCompleteCallback) { + // If it was passed a callback to register completion, make a callback. If + // this is created, then it must be executed on completion, otherwise the + // pos-transition redraw will not execute: + onComplete = makeOnCompleteCallback(); + } + + var transition = d3.transition() + .duration(transitionOpts.duration) + .ease(transitionOpts.easing) + .each('end', function() { + onComplete && onComplete(); + }) + .each('interrupt', function() { + onComplete && onComplete(); + }); + + transition.each(function() { + // Must run the selection again since otherwise enters/updates get grouped together + // and these get executed out of order. Except we need them in order! + scatterlayer.selectAll('g.trace').each(function(d, i) { + plotOne(gd, i, plotinfo, d, cdscatter, this, transitionOpts); + }); + }); + } else { + scatterlayer.selectAll('g.trace').each(function(d, i) { + plotOne(gd, i, plotinfo, d, cdscatter, this, transitionOpts); + }); + } + + if(isFullReplot) { + join.exit().remove(); + } + + // remove paths that didn't get used + scatterlayer.selectAll('path:not([d])').remove(); +}; + +function createFills(gd, scatterlayer) { + var trace; + + scatterlayer.selectAll('g.trace').each(function(d) { + var tr = d3.select(this); + + // Loop only over the traces being redrawn: + trace = d[0].trace; + + // make the fill-to-next path now for the NEXT trace, so it shows + // behind both lines. + if(trace._nexttrace) { + trace._nextFill = tr.select('.js-fill.js-tonext'); + if(!trace._nextFill.size()) { + + // If there is an existing tozero fill, we must insert this *after* that fill: + var loc = ':first-child'; + if(tr.select('.js-fill.js-tozero').size()) { + loc += ' + *'; + } + + trace._nextFill = tr.insert('path', loc).attr('class', 'js-fill js-tonext'); + } + } else { + tr.selectAll('.js-fill.js-tonext').remove(); + trace._nextFill = null; + } + + if(trace.fill && (trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' || + (trace.fill.substr(0, 2) === 'to' && !trace._prevtrace))) { + trace._ownFill = tr.select('.js-fill.js-tozero'); + if(!trace._ownFill.size()) { + trace._ownFill = tr.insert('path', ':first-child').attr('class', 'js-fill js-tozero'); + } + } else { + tr.selectAll('.js-fill.js-tozero').remove(); + trace._ownFill = null; + } + }); +} + +function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transitionOpts) { + var join, i; + + // Since this has been reorganized and we're executing this on individual traces, + // we need to pass it the full list of cdscatter as well as this trace's index (idx) + // since it does an internal n^2 loop over comparisons with other traces: + selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll); + + var hasTransition = !!transitionOpts && transitionOpts.duration > 0; + + function transition(selection) { + return hasTransition ? selection.transition() : selection; + } + + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis; + + var trace = cdscatter[0].trace, + line = trace.line, + tr = d3.select(element); + + // (so error bars can find them along with bars) + // error bars are at the bottom + tr.call(ErrorBars.plot, plotinfo, transitionOpts); + + if(trace.visible !== true) return; + + transition(tr).style('opacity', trace.opacity); + + // BUILD LINES AND FILLS + var ownFillEl3, tonext; + var ownFillDir = trace.fill.charAt(trace.fill.length - 1); + if(ownFillDir !== 'x' && ownFillDir !== 'y') ownFillDir = ''; + + // store node for tweaking by selectPoints + cdscatter[0].node3 = tr; + + arraysToCalcdata(cdscatter); + + var prevRevpath = ''; + var prevPolygons = []; + var prevtrace = trace._prevtrace; + + if(prevtrace) { + prevRevpath = prevtrace._prevRevpath || ''; + tonext = prevtrace._nextFill; + prevPolygons = prevtrace._polygons; + } + + var thispath, + thisrevpath, + // fullpath is all paths for this curve, joined together straight + // across gaps, for filling + fullpath = '', + // revpath is fullpath reversed, for fill-to-next + revpath = '', + // functions for converting a point array to a path + pathfn, revpathbase, revpathfn, + // variables used before and after the data join + pt0, lastSegment, pt1, thisPolygons; + + // initialize line join data / method + var segments = [], + lineSegments = [], + makeUpdate = Lib.noop; + + ownFillEl3 = trace._ownFill; + + if(subTypes.hasLines(trace) || trace.fill !== 'none') { + + if(tonext) { + // This tells .style which trace to use for fill information: + tonext.datum(cdscatter); + } + + if(['hv', 'vh', 'hvh', 'vhv'].indexOf(line.shape) !== -1) { + pathfn = Drawing.steps(line.shape); + revpathbase = Drawing.steps( + line.shape.split('').reverse().join('') + ); + } + else if(line.shape === 'spline') { + pathfn = revpathbase = function(pts) { + var pLast = pts[pts.length - 1]; + if(pts[0][0] === pLast[0] && pts[0][1] === pLast[1]) { + // identical start and end points: treat it as a + // closed curve so we don't get a kink + return Drawing.smoothclosed(pts.slice(1), line.smoothing); + } + else { + return Drawing.smoothopen(pts, line.smoothing); + } + }; + } + else { + pathfn = revpathbase = function(pts) { + return 'M' + pts.join('L'); + }; + } + + revpathfn = function(pts) { + // note: this is destructive (reverses pts in place) so can't use pts after this + return revpathbase(pts.reverse()); + }; + + segments = linePoints(cdscatter, { + xaxis: xa, + yaxis: ya, + connectGaps: trace.connectgaps, + baseTolerance: Math.max(line.width || 1, 3) / 4, + linear: line.shape === 'linear', + simplify: line.simplify + }); + + // since we already have the pixel segments here, use them to make + // polygons for hover on fill + // TODO: can we skip this if hoveron!=fills? That would mean we + // need to redraw when you change hoveron... + thisPolygons = trace._polygons = new Array(segments.length); + for(i = 0; i < segments.length; i++) { + trace._polygons[i] = polygonTester(segments[i]); + } + + if(segments.length) { + pt0 = segments[0][0]; + lastSegment = segments[segments.length - 1]; + pt1 = lastSegment[lastSegment.length - 1]; + } + + lineSegments = segments.filter(function(s) { + return s.length > 1; + }); + + makeUpdate = function(isEnter) { + return function(pts) { + thispath = pathfn(pts); + thisrevpath = revpathfn(pts); + if(!fullpath) { + fullpath = thispath; + revpath = thisrevpath; + } + else if(ownFillDir) { + fullpath += 'L' + thispath.substr(1); + revpath = thisrevpath + ('L' + revpath.substr(1)); + } + else { + fullpath += 'Z' + thispath; + revpath = thisrevpath + 'Z' + revpath; + } + + if(subTypes.hasLines(trace) && pts.length > 1) { + var el = d3.select(this); + + // This makes the coloring work correctly: + el.datum(cdscatter); + + if(isEnter) { + transition(el.style('opacity', 0) + .attr('d', thispath) + .call(Drawing.lineGroupStyle)) + .style('opacity', 1); + } else { + var sel = transition(el); + sel.attr('d', thispath); + Drawing.singleLineStyle(cdscatter, sel); + } + } + }; + }; + } + + var lineJoin = tr.selectAll('.js-line').data(lineSegments); + + transition(lineJoin.exit()) + .style('opacity', 0) + .remove(); + + lineJoin.each(makeUpdate(false)); + + lineJoin.enter().append('path') + .classed('js-line', true) + .style('vector-effect', 'non-scaling-stroke') + .call(Drawing.lineGroupStyle) + .each(makeUpdate(true)); + + if(segments.length) { + if(ownFillEl3) { + if(pt0 && pt1) { + if(ownFillDir) { + if(ownFillDir === 'y') { + pt0[1] = pt1[1] = ya.c2p(0, true); + } + else if(ownFillDir === 'x') { + pt0[0] = pt1[0] = xa.c2p(0, true); + } + + // fill to zero: full trace path, plus extension of + // the endpoints to the appropriate axis + // For the sake of animations, wrap the points around so that + // the points on the axes are the first two points. Otherwise + // animations get a little crazy if the number of points changes. + transition(ownFillEl3).attr('d', 'M' + pt1 + 'L' + pt0 + 'L' + fullpath.substr(1)); + } else { + // fill to self: just join the path to itself + transition(ownFillEl3).attr('d', fullpath + 'Z'); + } + } + } + else if(trace.fill.substr(0, 6) === 'tonext' && fullpath && prevRevpath) { + // fill to next: full trace path, plus the previous path reversed + if(trace.fill === 'tonext') { + // tonext: for use by concentric shapes, like manually constructed + // contours, we just add the two paths closed on themselves. + // This makes strange results if one path is *not* entirely + // inside the other, but then that is a strange usage. + transition(tonext).attr('d', fullpath + 'Z' + prevRevpath + 'Z'); + } + else { + // tonextx/y: for now just connect endpoints with lines. This is + // the correct behavior if the endpoints are at the same value of + // y/x, but if they *aren't*, we should ideally do more complicated + // things depending on whether the new endpoint projects onto the + // existing curve or off the end of it + transition(tonext).attr('d', fullpath + 'L' + prevRevpath.substr(1) + 'Z'); + } + trace._polygons = trace._polygons.concat(prevPolygons); + } + trace._prevRevpath = revpath; + trace._prevPolygons = thisPolygons; + } + + + function visFilter(d) { + return d.filter(function(v) { return v.vis; }); + } + + function keyFunc(d) { + return d.id; + } + + // Returns a function if the trace is keyed, otherwise returns undefined + function getKeyFunc(trace) { + if(trace.ids) { + return keyFunc; + } + } + + function hideFilter() { + return false; + } + + function makePoints(d) { + var join, selection; + + var trace = d[0].trace, + s = d3.select(this), + showMarkers = subTypes.hasMarkers(trace), + showText = subTypes.hasText(trace); + + var keyFunc = getKeyFunc(trace), + markerFilter = hideFilter, + textFilter = hideFilter; + + if(showMarkers) { + markerFilter = trace.marker.maxdisplayed ? visFilter : Lib.identity; + } + + if(showText) { + textFilter = trace.marker.maxdisplayed ? visFilter : Lib.identity; + } + + // marker points + + selection = s.selectAll('path.point'); + + join = selection.data(markerFilter, keyFunc); + + var enter = join.enter().append('path') + .classed('point', true); + + enter.call(Drawing.pointStyle, trace) + .call(Drawing.translatePoints, xa, ya, trace); + + if(hasTransition) { + enter.style('opacity', 0).transition() + .style('opacity', 1); + } + + join.each(function(d) { + var sel = transition(d3.select(this)); + Drawing.translatePoint(d, sel, xa, ya); + Drawing.singlePointStyle(d, sel, trace); + }); + + if(hasTransition) { + join.exit().transition() + .style('opacity', 0) + .remove(); + } else { + join.exit().remove(); + } + + // text points + selection = s.selectAll('g'); + join = selection.data(textFilter, keyFunc); + + // each text needs to go in its own 'g' in case + // it gets converted to mathjax + join.enter().append('g').append('text'); + + join.each(function(d) { + var sel = transition(d3.select(this).select('text')); + Drawing.translatePoint(d, sel, xa, ya); + }); + + join.selectAll('text') + .call(Drawing.textPointStyle, trace) + .each(function(d) { + + // This just *has* to be totally custom becuase of SVG text positioning :( + // It's obviously copied from translatePoint; we just can't use that + // + // put xp and yp into d if pixel scaling is already done + var x = d.xp || xa.c2p(d.x), + y = d.yp || ya.c2p(d.y); + + d3.select(this).selectAll('tspan').each(function() { + transition(d3.select(this)).attr({x: x, y: y}); + }); + }); + + join.exit().remove(); + } + + // NB: selectAll is evaluated on instantiation: + var pointSelection = tr.selectAll('.points'); + + // Join with new data + join = pointSelection.data([cdscatter]); + + // Transition existing, but don't defer this to an async .transition since + // there's no timing involved: + pointSelection.each(makePoints); + + join.enter().append('g') + .classed('points', true) + .each(makePoints); + + join.exit().remove(); +} + +function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) { + var xa = plotinfo.xaxis, + ya = plotinfo.yaxis, + xr = d3.extent(xa.range.map(xa.r2l).map(xa.l2c)), + yr = d3.extent(ya.range.map(ya.r2l).map(ya.l2c)); + + var trace = cdscatter[0].trace; + if(!subTypes.hasMarkers(trace)) return; + // if marker.maxdisplayed is used, select a maximum of + // mnum markers to show, from the set that are in the viewport + var mnum = trace.marker.maxdisplayed; + + // TODO: remove some as we get away from the viewport? + if(mnum === 0) return; + + var cd = cdscatter.filter(function(v) { + return v.x >= xr[0] && v.x <= xr[1] && v.y >= yr[0] && v.y <= yr[1]; + }), + inc = Math.ceil(cd.length / mnum), + tnum = 0; + cdscatterAll.forEach(function(cdj, j) { + var tracei = cdj[0].trace; + if(subTypes.hasMarkers(tracei) && + tracei.marker.maxdisplayed > 0 && j < idx) { + tnum++; + } + }); + + // if multiple traces use maxdisplayed, stagger which markers we + // display this formula offsets successive traces by 1/3 of the + // increment, adding an extra small amount after each triplet so + // it's not quite periodic + var i0 = Math.round(tnum * inc / 3 + Math.floor(tnum / 3) * inc / 7.1); + + // for error bars: save in cd which markers to show + // so we don't have to repeat this + cdscatter.forEach(function(v) { delete v.vis; }); + cd.forEach(function(v, i) { + if(Math.round((i + i0) % inc) === 0) v.vis = true; + }); +} + +},{"../../components/drawing":50,"../../components/errorbars":56,"../../lib":122,"../../lib/polygon":129,"./arrays_to_calcdata":233,"./line_points":246,"./link_traces":248,"./subtypes":254,"d3":10}],252:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var subtypes = require('./subtypes'); + +var DESELECTDIM = 0.2; + +module.exports = function selectPoints(searchInfo, polygon) { + var cd = searchInfo.cd, + xa = searchInfo.xaxis, + ya = searchInfo.yaxis, + selection = [], + trace = cd[0].trace, + curveNumber = trace.index, + marker = trace.marker, + i, + di, + x, + y; + + // TODO: include lines? that would require per-segment line properties + var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace)); + if(trace.visible !== true || hasOnlyLines) return; + + var opacity = Array.isArray(marker.opacity) ? 1 : marker.opacity; + + if(polygon === false) { // clear selection + for(i = 0; i < cd.length; i++) cd[i].dim = 0; + } + else { + for(i = 0; i < cd.length; i++) { + di = cd[i]; + x = xa.c2p(di.x); + y = ya.c2p(di.y); + if(polygon.contains([x, y])) { + selection.push({ + curveNumber: curveNumber, + pointNumber: i, + x: di.x, + y: di.y, + id: di.id + }); + di.dim = 0; + } + else di.dim = 1; + } + } + + // do the dimming here, as well as returning the selection + // The logic here duplicates Drawing.pointStyle, but I don't want + // d.dim in pointStyle in case something goes wrong with selection. + cd[0].node3.selectAll('path.point') + .style('opacity', function(d) { + return ((d.mo + 1 || opacity + 1) - 1) * (d.dim ? DESELECTDIM : 1); + }); + cd[0].node3.selectAll('text') + .style('opacity', function(d) { + return d.dim ? DESELECTDIM : 1; + }); + + return selection; +}; + +},{"./subtypes":254}],253:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Drawing = require('../../components/drawing'); +var ErrorBars = require('../../components/errorbars'); + + +module.exports = function style(gd) { + var s = d3.select(gd).selectAll('g.trace.scatter'); + + s.style('opacity', function(d) { + return d[0].trace.opacity; + }); + + s.selectAll('g.points') + .each(function(d) { + d3.select(this).selectAll('path.point') + .call(Drawing.pointStyle, d.trace || d[0].trace); + d3.select(this).selectAll('text') + .call(Drawing.textPointStyle, d.trace || d[0].trace); + }); + + s.selectAll('g.trace path.js-line') + .call(Drawing.lineGroupStyle); + + s.selectAll('g.trace path.js-fill') + .call(Drawing.fillGroupStyle); + + s.call(ErrorBars.style); +}; + +},{"../../components/drawing":50,"../../components/errorbars":56,"d3":10}],254:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + +module.exports = { + hasLines: function(trace) { + return trace.visible && trace.mode && + trace.mode.indexOf('lines') !== -1; + }, + + hasMarkers: function(trace) { + return trace.visible && trace.mode && + trace.mode.indexOf('markers') !== -1; + }, + + hasText: function(trace) { + return trace.visible && trace.mode && + trace.mode.indexOf('text') !== -1; + }, + + isBubble: function(trace) { + return Lib.isPlainObject(trace.marker) && + Array.isArray(trace.marker.size); + } +}; + +},{"../../lib":122}],255:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + + +// common to 'scatter', 'scatter3d' and 'scattergeo' +module.exports = function(traceIn, traceOut, layout, coerce) { + coerce('textposition'); + Lib.coerceFont(coerce, 'textfont', layout.font); +}; + +},{"../../lib":122}],256:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = function handleXYDefaults(traceIn, traceOut, coerce) { + var len, + x = coerce('x'), + y = coerce('y'); + + if(x) { + if(y) { + len = Math.min(x.length, y.length); + // TODO: not sure we should do this here... but I think + // the way it works in calc is wrong, because it'll delete data + // which could be a problem eg in streaming / editing if x and y + // come in at different times + // so we need to revisit calc before taking this out + if(len < x.length) traceOut.x = x.slice(0, len); + if(len < y.length) traceOut.y = y.slice(0, len); + } + else { + len = x.length; + coerce('y0'); + coerce('dy'); + } + } + else { + if(!y) return 0; + + len = traceOut.y.length; + coerce('x0'); + coerce('dx'); + } + return len; +}; + +},{}],257:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +var scatterAttrs = require('../scatter/attributes'); +var plotAttrs = require('../../plots/attributes'); +var colorAttributes = require('../../components/colorscale/color_attributes'); + +var extendFlat = require('../../lib/extend').extendFlat; + +var scatterMarkerAttrs = scatterAttrs.marker, + scatterLineAttrs = scatterAttrs.line, + scatterMarkerLineAttrs = scatterMarkerAttrs.line; + +module.exports = { + lon: { + valType: 'data_array', + + }, + lat: { + valType: 'data_array', + + }, + + locations: { + valType: 'data_array', + + }, + locationmode: { + valType: 'enumerated', + values: ['ISO-3', 'USA-states', 'country names'], + + dflt: 'ISO-3', + + }, + + mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), + + text: extendFlat({}, scatterAttrs.text, { + + }), + textfont: scatterAttrs.textfont, + textposition: scatterAttrs.textposition, + + line: { + color: scatterLineAttrs.color, + width: scatterLineAttrs.width, + dash: scatterLineAttrs.dash + }, + connectgaps: scatterAttrs.connectgaps, + + marker: extendFlat({}, { + symbol: scatterMarkerAttrs.symbol, + opacity: scatterMarkerAttrs.opacity, + size: scatterMarkerAttrs.size, + sizeref: scatterMarkerAttrs.sizeref, + sizemin: scatterMarkerAttrs.sizemin, + sizemode: scatterMarkerAttrs.sizemode, + showscale: scatterMarkerAttrs.showscale, + colorbar: scatterMarkerAttrs.colorbar, + line: extendFlat({}, + {width: scatterMarkerLineAttrs.width}, + colorAttributes('marker.line') + ) + }, + colorAttributes('marker') + ), + + fill: { + valType: 'enumerated', + values: ['none', 'toself'], + dflt: 'none', + + + }, + fillcolor: scatterAttrs.fillcolor, + + hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { + flags: ['lon', 'lat', 'location', 'text', 'name'] + }) +}; + +},{"../../components/colorscale/color_attributes":34,"../../lib/extend":117,"../../plots/attributes":148,"../scatter/attributes":234}],258:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var isNumeric = require('fast-isnumeric'); + +var calcMarkerColorscale = require('../scatter/colorscale_calc'); + + +module.exports = function calc(gd, trace) { + var hasLocationData = Array.isArray(trace.locations), + len = hasLocationData ? trace.locations.length : trace.lon.length; + + var calcTrace = [], + cnt = 0; + + for(var i = 0; i < len; i++) { + var calcPt = {}, + skip; + + if(hasLocationData) { + var loc = trace.locations[i]; + + calcPt.loc = loc; + skip = (typeof loc !== 'string'); + } + else { + var lon = trace.lon[i], + lat = trace.lat[i]; + + calcPt.lonlat = [+lon, +lat]; + skip = (!isNumeric(lon) || !isNumeric(lat)); + } + + if(skip) { + if(cnt > 0) calcTrace[cnt - 1].gapAfter = true; + continue; + } + + cnt++; + + calcTrace.push(calcPt); + } + + calcMarkerColorscale(trace); + + return calcTrace; +}; + +},{"../scatter/colorscale_calc":238,"fast-isnumeric":13}],259:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Lib = require('../../lib'); + +var subTypes = require('../scatter/subtypes'); +var handleMarkerDefaults = require('../scatter/marker_defaults'); +var handleLineDefaults = require('../scatter/line_defaults'); +var handleTextDefaults = require('../scatter/text_defaults'); +var handleFillColorDefaults = require('../scatter/fillcolor_defaults'); + +var attributes = require('./attributes'); + + +module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { + function coerce(attr, dflt) { + return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); + } + + var len = handleLonLatLocDefaults(traceIn, traceOut, coerce); + if(!len) { + traceOut.visible = false; + return; + } + + coerce('text'); + coerce('mode'); + + if(subTypes.hasLines(traceOut)) { + handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); + coerce('connectgaps'); + } + + if(subTypes.hasMarkers(traceOut)) { + handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); + } + + if(subTypes.hasText(traceOut)) { + handleTextDefaults(traceIn, traceOut, layout, coerce); + } + + coerce('fill'); + if(traceOut.fill !== 'none') { + handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); + } + + coerce('hoverinfo', (layout._dataLength === 1) ? 'lon+lat+location+text' : undefined); +}; + +function handleLonLatLocDefaults(traceIn, traceOut, coerce) { + var len = 0, + locations = coerce('locations'); + + var lon, lat; + + if(locations) { + coerce('locationmode'); + len = locations.length; + return len; + } + + lon = coerce('lon') || []; + lat = coerce('lat') || []; + len = Math.min(lon.length, lat.length); + + if(len < lon.length) traceOut.lon = lon.slice(0, len); + if(len < lat.length) traceOut.lat = lat.slice(0, len); + + return len; +} + +},{"../../lib":122,"../scatter/fillcolor_defaults":241,"../scatter/line_defaults":245,"../scatter/marker_defaults":250,"../scatter/subtypes":254,"../scatter/text_defaults":255,"./attributes":257}],260:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + + +module.exports = function eventData(out, pt) { + out.lon = pt.lon; + out.lat = pt.lat; + out.location = pt.lon ? pt.lon : null; + + return out; +}; + +},{}],261:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var Fx = require('../../plots/cartesian/graph_interact'); +var Axes = require('../../plots/cartesian/axes'); + +var getTraceColor = require('../scatter/get_trace_color'); +var attributes = require('./attributes'); + + +module.exports = function hoverPoints(pointData) { + var cd = pointData.cd, + trace = cd[0].trace, + xa = pointData.xa, + ya = pointData.ya, + geo = pointData.subplot; + + if(cd[0].placeholder) return; + + function c2p(lonlat) { + return geo.projection(lonlat); + } + + function distFn(d) { + var lonlat = d.lonlat; + + // this handles the not-found location feature case + if(lonlat[0] === null || lonlat[1] === null) return Infinity; + + if(geo.isLonLatOverEdges(lonlat)) return Infinity; + + var pos = c2p(lonlat); + + var xPx = xa.c2p(), + yPx = ya.c2p(); + + var dx = Math.abs(xPx - pos[0]), + dy = Math.abs(yPx - pos[1]), + rad = Math.max(3, d.mrc || 0); + + // N.B. d.mrc is the calculated marker radius + // which is only set for trace with 'markers' mode. + + return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad); + } + + Fx.getClosest(cd, distFn, pointData); + + // skip the rest (for this trace) if we didn't find a close point + if(pointData.index === false) return; + + var di = cd[pointData.index], + lonlat = di.lonlat, + pos = c2p(lonlat), + rad = di.mrc || 1; + + pointData.x0 = pos[0] - rad; + pointData.x1 = pos[0] + rad; + pointData.y0 = pos[1] - rad; + pointData.y1 = pos[1] + rad; + + pointData.loc = di.loc; + pointData.lat = lonlat[0]; + pointData.lon = lonlat[1]; + + pointData.color = getTraceColor(trace, di); + pointData.extraText = getExtraText(trace, di, geo.mockAxis); + + return [pointData]; +}; + +function getExtraText(trace, pt, axis) { + var hoverinfo = trace.hoverinfo; + + var parts = (hoverinfo === 'all') ? + attributes.hoverinfo.flags : + hoverinfo.split('+'); + + var hasLocation = parts.indexOf('location') !== -1 && Array.isArray(trace.locations), + hasLon = (parts.indexOf('lon') !== -1), + hasLat = (parts.indexOf('lat') !== -1), + hasText = (parts.indexOf('text') !== -1); + + var text = []; + + function format(val) { + return Axes.tickText(axis, axis.c2l(val), 'hover').text + '\u00B0'; + } + + if(hasLocation) text.push(pt.loc); + else if(hasLon && hasLat) { + text.push('(' + format(pt.lonlat[0]) + ', ' + format(pt.lonlat[1]) + ')'); + } + else if(hasLon) text.push('lon: ' + format(pt.lonlat[0])); + else if(hasLat) text.push('lat: ' + format(pt.lonlat[1])); + + if(hasText) text.push(pt.tx || trace.text); + + return text.join('
'); +} + +},{"../../plots/cartesian/axes":150,"../../plots/cartesian/graph_interact":157,"../scatter/get_trace_color":242,"./attributes":257}],262:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var ScatterGeo = {}; + +ScatterGeo.attributes = require('./attributes'); +ScatterGeo.supplyDefaults = require('./defaults'); +ScatterGeo.colorbar = require('../scatter/colorbar'); +ScatterGeo.calc = require('./calc'); +ScatterGeo.plot = require('./plot'); +ScatterGeo.hoverPoints = require('./hover'); +ScatterGeo.eventData = require('./event_data'); + +ScatterGeo.moduleType = 'trace'; +ScatterGeo.name = 'scattergeo'; +ScatterGeo.basePlotModule = require('../../plots/geo'); +ScatterGeo.categories = ['geo', 'symbols', 'markerColorscale', 'showLegend']; +ScatterGeo.meta = { + + +}; + +module.exports = ScatterGeo; + +},{"../../plots/geo":174,"../scatter/colorbar":237,"./attributes":257,"./calc":258,"./defaults":259,"./event_data":260,"./hover":261,"./plot":263}],263:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + + +'use strict'; + +var d3 = require('d3'); + +var Drawing = require('../../components/drawing'); +var Color = require('../../components/color'); + +var Lib = require('../../lib'); +var getTopojsonFeatures = require('../../lib/topojson_utils').getTopojsonFeatures; +var locationToFeature = require('../../lib/geo_location_utils').locationToFeature; +var geoJsonUtils = require('../../lib/geojson_utils'); +var arrayToCalcItem = require('../../lib/array_to_calc_item'); +var subTypes = require('../scatter/subtypes'); + + +module.exports = function plot(geo, calcData) { + + function keyFunc(d) { return d[0].trace.uid; } + + var gScatterGeoTraces = geo.framework.select('.scattergeolayer') + .selectAll('g.trace.scattergeo') + .data(calcData, keyFunc); + + gScatterGeoTraces.enter().append('g') + .attr('class', 'trace scattergeo'); + + gScatterGeoTraces.exit().remove(); + + // TODO find a way to order the inner nodes on update + gScatterGeoTraces.selectAll('*').remove(); + + gScatterGeoTraces.each(function(calcTrace) { + var s = d3.select(this), + trace = calcTrace[0].trace, + convertToLonLatFn = makeConvertToLonLatFn(trace, geo.topojson); + + // skip over placeholder traces + if(calcTrace[0].placeholder) s.remove(); + + // just like calcTrace but w/o not-found location datum + var _calcTrace = []; + + for(var i = 0; i < calcTrace.length; i++) { + var _calcPt = convertToLonLatFn(calcTrace[i]); + + if(_calcPt) { + arrayItemToCalcdata(trace, calcTrace[i], i); + _calcTrace.push(_calcPt); + } + } + + if(subTypes.hasLines(trace) || trace.fill !== 'none') { + var lineCoords = geoJsonUtils.calcTraceToLineCoords(_calcTrace); + + var lineData = (trace.fill !== 'none') ? + geoJsonUtils.makePolygon(lineCoords, trace) : + geoJsonUtils.makeLine(lineCoords, trace); + + s.selectAll('path.js-line') + .data([lineData]) + .enter().append('path') + .classed('js-line', true); + } + + if(subTypes.hasMarkers(trace)) { + s.selectAll('path.point').data(_calcTrace) + .enter().append('path') + .classed('point', true); + } + + if(subTypes.hasText(trace)) { + s.selectAll('g').data(_calcTrace) + .enter().append('g') + .append('text'); + } + }); + + // call style here within topojson request callback + style(geo); +}; + +function makeConvertToLonLatFn(trace, topojson) { + if(!Array.isArray(trace.locations)) return Lib.identity; + + var features = getTopojsonFeatures(trace, topojson), + locationmode = trace.locationmode; + + return function(calcPt) { + var feature = locationToFeature(locationmode, calcPt.loc, features); + + if(feature) { + calcPt.lonlat = feature.properties.ct; + return calcPt; + } + else { + // mutate gd.calcdata so that hoverPoints knows to skip this datum + calcPt.lonlat = [null, null]; + return false; + } + }; +} + +function arrayItemToCalcdata(trace, calcItem, i) { + var marker = trace.marker; + + function merge(traceAttr, calcAttr) { + arrayToCalcItem(traceAttr, calcItem, calcAttr, i); + } + + merge(trace.text, 'tx'); + merge(trace.textposition, 'tp'); + if(trace.textfont) { + merge(trace.textfont.size, 'ts'); + merge(trace.textfont.color, 'tc'); + merge(trace.textfont.family, 'tf'); + } + + if(marker && marker.line) { + var markerLine = marker.line; + merge(marker.opacity, 'mo'); + merge(marker.symbol, 'mx'); + merge(marker.color, 'mc'); + merge(marker.size, 'ms'); + merge(markerLine.color, 'mlc'); + merge(markerLine.width, 'mlw'); + } +} + +function style(geo) { + var selection = geo.framework.selectAll('g.trace.scattergeo'); + + selection.style('opacity', function(calcTrace) { + return calcTrace[0].trace.opacity; + }); + + selection.each(function(calcTrace) { + var trace = calcTrace[0].trace, + group = d3.select(this); + + group.selectAll('path.point') + .call(Drawing.pointStyle, trace); + group.selectAll('text') + .call(Drawing.textPointStyle, trace); + }); + + // this part is incompatible with Drawing.lineGroupStyle + selection.selectAll('path.js-line') + .style('fill', 'none') + .each(function(d) { + var path = d3.select(this), + trace = d.trace, + line = trace.line || {}; + + path.call(Color.stroke, line.color) + .call(Drawing.dashLine, line.dash || '', line.width || 0); + + if(trace.fill !== 'none') { + path.call(Color.fill, trace.fillcolor); + } + }); +} + +},{"../../components/color":27,"../../components/drawing":50,"../../lib":122,"../../lib/array_to_calc_item":112,"../../lib/geo_location_utils":120,"../../lib/geojson_utils":121,"../../lib/topojson_utils":135,"../scatter/subtypes":254,"d3":10}]},{},[6])(6) +}); \ No newline at end of file diff --git a/dist/plotly-ion.min.js b/dist/plotly-ion.min.js new file mode 100644 index 00000000000..5844ca8a1f1 --- /dev/null +++ b/dist/plotly-ion.min.js @@ -0,0 +1,28 @@ +/** +* plotly.js (ion - minified) v1.20.2-d27 +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* Licensed under the MIT license +*/ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Plotly=t()}}(function(){var t;return function t(e,n,r){function a(i,l){if(!n[i]){if(!e[i]){var s="function"==typeof require&&require;if(!l&&s)return s(i,!0);if(o)return o(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[i]={exports:{}};e[i][0].call(u.exports,function(t){var n=e[i][1][t];return a(n?n:t)},u,u.exports,t,e,n,r)}return n[i].exports}for(var o="function"==typeof require&&require,i=0;ie?1:t>=e?0:NaN}function o(t){return null===t?NaN:+t}function i(t){return!isNaN(t)}function l(t){return{left:function(e,n,r,a){for(arguments.length<3&&(r=0),arguments.length<4&&(a=e.length);r>>1;t(e[o],n)<0?r=o+1:a=o}return r},right:function(e,n,r,a){for(arguments.length<3&&(r=0),arguments.length<4&&(a=e.length);r>>1;t(e[o],n)>0?a=o:r=o+1}return r}}}function s(t){return t.length}function c(t){for(var e=1;t*e%1;)e*=10;return e}function u(t,e){for(var n in e)Object.defineProperty(t.prototype,n,{value:e[n],enumerable:!1})}function f(){this._=Object.create(null)}function d(t){return(t+="")===_i||t[0]===wi?wi+t:t}function h(t){return(t+="")[0]===wi?t.slice(1):t}function p(t){return d(t)in this._}function g(t){return(t=d(t))in this._&&delete this._[t]}function m(){var t=[];for(var e in this._)t.push(h(e));return t}function v(){var t=0;for(var e in this._)++t;return t}function y(){for(var t in this._)return!1;return!0}function x(){this._=Object.create(null)}function b(t){return t}function _(t,e,n){return function(){var r=n.apply(e,arguments);return r===e?t:r}}function w(t,e){if(e in t)return e;e=e.charAt(0).toUpperCase()+e.slice(1);for(var n=0,r=Mi.length;n=e&&(e=a+1);!(i=l[e])&&++e0&&(t=t.slice(0,l));var c=Ei.get(t);return c&&(t=c,s=Q),l?e?a:r:e?M:o}function W(t,e){return function(n){var r=ui.event;ui.event=n,e[0]=this.__data__;try{t.apply(this,e)}finally{ui.event=r}}}function Q(t,e){var n=W(t,e);return function(t){var e=this,r=t.relatedTarget;r&&(r===e||8&r.compareDocumentPosition(e))||n.call(e,t)}}function $(t){var n=".dragsuppress-"+ ++Di,a="click"+n,o=ui.select(r(t)).on("touchmove"+n,T).on("dragstart"+n,T).on("selectstart"+n,T);if(null==Ni&&(Ni=!("onselectstart"in t)&&w(t.style,"userSelect")),Ni){var i=e(t).style,l=i[Ni];i[Ni]="none"}return function(t){if(o.on(n,null),Ni&&(i[Ni]=l),t){var e=function(){o.on(a,null)};o.on(a,function(){T(),e()},!0),setTimeout(e,0)}}}function J(t,e){e.changedTouches&&(e=e.changedTouches[0]);var n=t.ownerSVGElement||t;if(n.createSVGPoint){var a=n.createSVGPoint();if(Ri<0){var o=r(t);if(o.scrollX||o.scrollY){n=ui.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var i=n[0][0].getScreenCTM();Ri=!(i.f||i.e),n.remove()}}return Ri?(a.x=e.pageX,a.y=e.pageY):(a.x=e.clientX,a.y=e.clientY),a=a.matrixTransform(t.getScreenCTM().inverse()),[a.x,a.y]}var l=t.getBoundingClientRect();return[e.clientX-l.left-t.clientLeft,e.clientY-l.top-t.clientTop]}function K(){return ui.event.changedTouches[0].identifier}function tt(t){return t>0?1:t<0?-1:0}function et(t,e,n){return(e[0]-t[0])*(n[1]-t[1])-(e[1]-t[1])*(n[0]-t[0])}function nt(t){return t>1?0:t<-1?Fi:Math.acos(t)}function rt(t){return t>1?Hi:t<-1?-Hi:Math.asin(t)}function at(t){return((t=Math.exp(t))-1/t)/2}function ot(t){return((t=Math.exp(t))+1/t)/2}function it(t){return((t=Math.exp(2*t))-1)/(t+1)}function lt(t){return(t=Math.sin(t/2))*t}function st(){}function ct(t,e,n){return this instanceof ct?(this.h=+t,this.s=+e,void(this.l=+n)):arguments.length<2?t instanceof ct?new ct(t.h,t.s,t.l):Mt(""+t,kt,ct):new ct(t,e,n)}function ut(t,e,n){function r(t){return t>360?t-=360:t<0&&(t+=360),t<60?o+(i-o)*t/60:t<180?i:t<240?o+(i-o)*(240-t)/60:o}function a(t){return Math.round(255*r(t))}var o,i;return t=isNaN(t)?0:(t%=360)<0?t+360:t,e=isNaN(e)?0:e<0?0:e>1?1:e,n=n<0?0:n>1?1:n,i=n<=.5?n*(1+e):n+e-n*e,o=2*n-i,new xt(a(t+120),a(t),a(t-120))}function ft(t,e,n){return this instanceof ft?(this.h=+t,this.c=+e,void(this.l=+n)):arguments.length<2?t instanceof ft?new ft(t.h,t.c,t.l):t instanceof ht?gt(t.l,t.a,t.b):gt((t=At((t=ui.rgb(t)).r,t.g,t.b)).l,t.a,t.b):new ft(t,e,n)}function dt(t,e,n){return isNaN(t)&&(t=0),isNaN(e)&&(e=0),new ht(n,Math.cos(t*=Vi)*e,Math.sin(t)*e)}function ht(t,e,n){return this instanceof ht?(this.l=+t,this.a=+e,void(this.b=+n)):arguments.length<2?t instanceof ht?new ht(t.l,t.a,t.b):t instanceof ft?dt(t.h,t.c,t.l):At((t=xt(t)).r,t.g,t.b):new ht(t,e,n)}function pt(t,e,n){var r=(t+16)/116,a=r+e/500,o=r-n/200;return a=mt(a)*tl,r=mt(r)*el,o=mt(o)*nl,new xt(yt(3.2404542*a-1.5371385*r-.4985314*o),yt(-.969266*a+1.8760108*r+.041556*o),yt(.0556434*a-.2040259*r+1.0572252*o))}function gt(t,e,n){return t>0?new ft(Math.atan2(n,e)*Gi,Math.sqrt(e*e+n*n),t):new ft(NaN,NaN,t)}function mt(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function vt(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function yt(t){return Math.round(255*(t<=.00304?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function xt(t,e,n){return this instanceof xt?(this.r=~~t,this.g=~~e,void(this.b=~~n)):arguments.length<2?t instanceof xt?new xt(t.r,t.g,t.b):Mt(""+t,xt,ut):new xt(t,e,n)}function bt(t){return new xt(t>>16,t>>8&255,255&t)}function _t(t){return bt(t)+""}function wt(t){return t<16?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function Mt(t,e,n){var r,a,o,i=0,l=0,s=0;if(r=/([a-z]+)\((.*)\)/.exec(t=t.toLowerCase()))switch(a=r[2].split(","),r[1]){case"hsl":return n(parseFloat(a[0]),parseFloat(a[1])/100,parseFloat(a[2])/100);case"rgb":return e(Lt(a[0]),Lt(a[1]),Lt(a[2]))}return(o=ol.get(t))?e(o.r,o.g,o.b):(null==t||"#"!==t.charAt(0)||isNaN(o=parseInt(t.slice(1),16))||(4===t.length?(i=(3840&o)>>4,i|=i>>4,l=240&o,l|=l>>4,s=15&o,s|=s<<4):7===t.length&&(i=(16711680&o)>>16,l=(65280&o)>>8,s=255&o)),e(i,l,s))}function kt(t,e,n){var r,a,o=Math.min(t/=255,e/=255,n/=255),i=Math.max(t,e,n),l=i-o,s=(i+o)/2;return l?(a=s<.5?l/(i+o):l/(2-i-o),r=t==i?(e-n)/l+(e0&&s<1?0:r),new ct(r,a,s)}function At(t,e,n){t=Tt(t),e=Tt(e),n=Tt(n);var r=vt((.4124564*t+.3575761*e+.1804375*n)/tl),a=vt((.2126729*t+.7151522*e+.072175*n)/el),o=vt((.0193339*t+.119192*e+.9503041*n)/nl);return ht(116*a-16,500*(r-a),200*(a-o))}function Tt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Lt(t){var e=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*e):e}function Ct(t){return"function"==typeof t?t:function(){return t}}function zt(t){return function(e,n,r){return 2===arguments.length&&"function"==typeof n&&(r=n,n=null),St(e,n,t,r)}}function St(t,e,n,r){function a(){var t,e=s.status;if(!e&&Pt(s)||e>=200&&e<300||304===e){try{t=n.call(o,s)}catch(t){return void i.error.call(o,t)}i.load.call(o,t)}else i.error.call(o,s)}var o={},i=ui.dispatch("beforesend","progress","load","error"),l={},s=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=a:s.onreadystatechange=function(){s.readyState>3&&a()},s.onprogress=function(t){var e=ui.event;ui.event=t;try{i.progress.call(o,s)}finally{ui.event=e}},o.header=function(t,e){return t=(t+"").toLowerCase(),arguments.length<2?l[t]:(null==e?delete l[t]:l[t]=e+"",o)},o.mimeType=function(t){return arguments.length?(e=null==t?null:t+"",o):e},o.responseType=function(t){return arguments.length?(c=t,o):c},o.response=function(t){return n=t,o},["get","post"].forEach(function(t){o[t]=function(){return o.send.apply(o,[t].concat(di(arguments)))}}),o.send=function(n,r,a){if(2===arguments.length&&"function"==typeof r&&(a=r,r=null),s.open(n,t,!0),null==e||"accept"in l||(l.accept=e+",*/*"),s.setRequestHeader)for(var u in l)s.setRequestHeader(u,l[u]);return null!=e&&s.overrideMimeType&&s.overrideMimeType(e),null!=c&&(s.responseType=c),null!=a&&o.on("error",a).on("load",function(t){a(null,t)}),i.beforesend.call(o,s),s.send(null==r?null:r),o},o.abort=function(){return s.abort(),o},ui.rebind(o,i,"on"),null==r?o:o.get(Ot(r))}function Ot(t){return 1===t.length?function(e,n){t(null==e?n:null)}:t}function Pt(t){var e=t.responseType;return e&&"text"!==e?t.response:t.responseText}function Et(t,e,n){var r=arguments.length;r<2&&(e=0),r<3&&(n=Date.now());var a=n+e,o={c:t,t:a,n:null};return ll?ll.n=o:il=o,ll=o,sl||(cl=clearTimeout(cl),sl=1,ul(Nt)),o}function Nt(){var t=Dt(),e=Rt()-t;e>24?(isFinite(e)&&(clearTimeout(cl),cl=setTimeout(Nt,e)),sl=0):(sl=1,ul(Nt))}function Dt(){for(var t=Date.now(),e=il;e;)t>=e.t&&e.c(t-e.t)&&(e.c=null),e=e.n;return t}function Rt(){for(var t,e=il,n=1/0;e;)e.c?(e.t8?function(t){return t/n}:function(t){return t*n},symbol:t}}function Ft(t){var e=t.decimal,n=t.thousands,r=t.grouping,a=t.currency,o=r&&n?function(t,e){for(var a=t.length,o=[],i=0,l=r[0],s=0;a>0&&l>0&&(s+l+1>e&&(l=Math.max(1,e-s)),o.push(t.substring(a-=l,a+l)),!((s+=l+1)>e));)l=r[i=(i+1)%r.length];return o.reverse().join(n)}:b;return function(t){var n=dl.exec(t),r=n[1]||" ",i=n[2]||">",l=n[3]||"-",s=n[4]||"",c=n[5],u=+n[6],f=n[7],d=n[8],h=n[9],p=1,g="",m="",v=!1,y=!0;switch(d&&(d=+d.substring(1)),(c||"0"===r&&"="===i)&&(c=r="0",i="="),h){case"n":f=!0,h="g";break;case"%":p=100,m="%",h="f";break;case"p":p=100,m="%",h="r";break;case"b":case"o":case"x":case"X":"#"===s&&(g="0"+h.toLowerCase());case"c":y=!1;case"d":v=!0,d=0;break;case"s":p=-1,h="r"}"$"===s&&(g=a[0],m=a[1]),"r"!=h||d||(h="g"),null!=d&&("g"==h?d=Math.max(1,Math.min(21,d)):"e"!=h&&"f"!=h||(d=Math.max(0,Math.min(20,d)))),h=hl.get(h)||Bt;var x=c&&f;return function(t){var n=m;if(v&&t%1)return"";var a=t<0||0===t&&1/t<0?(t=-t,"-"):"-"===l?"":l;if(p<0){var s=ui.formatPrefix(t,d);t=s.scale(t),n=s.symbol+m}else t*=p;t=h(t,d);var b,_,w=t.lastIndexOf(".");if(w<0){var M=y?t.lastIndexOf("e"):-1; +M<0?(b=t,_=""):(b=t.substring(0,M),_=t.substring(M))}else b=t.substring(0,w),_=e+t.substring(w+1);!c&&f&&(b=o(b,1/0));var k=g.length+b.length+_.length+(x?0:a.length),A=k"===i?A+a+t:"^"===i?A.substring(0,k>>=1)+a+t+A.substring(k):a+(x?t:A+t))+n}}}function Bt(t){return t+""}function qt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ht(t,e,n){function r(e){var n=t(e),r=o(n,1);return e-n1)for(;i=c)return-1;if(a=e.charCodeAt(l++),37===a){if(i=e.charAt(l++),o=z[i in vl?e.charAt(l++):i],!o||(r=o(t,n,r))<0)return-1}else if(a!=n.charCodeAt(r++))return-1}return r}function r(t,e,n){w.lastIndex=0;var r=w.exec(e.slice(n));return r?(t.w=M.get(r[0].toLowerCase()),n+r[0].length):-1}function a(t,e,n){b.lastIndex=0;var r=b.exec(e.slice(n));return r?(t.w=_.get(r[0].toLowerCase()),n+r[0].length):-1}function o(t,e,n){T.lastIndex=0;var r=T.exec(e.slice(n));return r?(t.m=L.get(r[0].toLowerCase()),n+r[0].length):-1}function i(t,e,n){k.lastIndex=0;var r=k.exec(e.slice(n));return r?(t.m=A.get(r[0].toLowerCase()),n+r[0].length):-1}function l(t,e,r){return n(t,C.c.toString(),e,r)}function s(t,e,r){return n(t,C.x.toString(),e,r)}function c(t,e,r){return n(t,C.X.toString(),e,r)}function u(t,e,n){var r=x.get(e.slice(n,n+=2).toLowerCase());return null==r?-1:(t.p=r,n)}var f=t.dateTime,d=t.date,h=t.time,p=t.periods,g=t.days,m=t.shortDays,v=t.months,y=t.shortMonths;e.utc=function(t){function n(t){try{gl=qt;var e=new gl;return e._=t,r(e)}finally{gl=Date}}var r=e(t);return n.parse=function(t){try{gl=qt;var e=r.parse(t);return e&&e._}finally{gl=Date}},n.toString=r.toString,n},e.multi=e.utc.multi=ue;var x=ui.map(),b=Xt(g),_=Yt(g),w=Xt(m),M=Yt(m),k=Xt(v),A=Yt(v),T=Xt(y),L=Yt(y);p.forEach(function(t,e){x.set(t.toLowerCase(),e)});var C={a:function(t){return m[t.getDay()]},A:function(t){return g[t.getDay()]},b:function(t){return y[t.getMonth()]},B:function(t){return v[t.getMonth()]},c:e(f),d:function(t,e){return Ut(t.getDate(),e,2)},e:function(t,e){return Ut(t.getDate(),e,2)},H:function(t,e){return Ut(t.getHours(),e,2)},I:function(t,e){return Ut(t.getHours()%12||12,e,2)},j:function(t,e){return Ut(1+pl.dayOfYear(t),e,3)},L:function(t,e){return Ut(t.getMilliseconds(),e,3)},m:function(t,e){return Ut(t.getMonth()+1,e,2)},M:function(t,e){return Ut(t.getMinutes(),e,2)},p:function(t){return p[+(t.getHours()>=12)]},S:function(t,e){return Ut(t.getSeconds(),e,2)},U:function(t,e){return Ut(pl.sundayOfYear(t),e,2)},w:function(t){return t.getDay()},W:function(t,e){return Ut(pl.mondayOfYear(t),e,2)},x:e(d),X:e(h),y:function(t,e){return Ut(t.getFullYear()%100,e,2)},Y:function(t,e){return Ut(t.getFullYear()%1e4,e,4)},Z:se,"%":function(){return"%"}},z={a:r,A:a,b:o,B:i,c:l,d:ne,e:ne,H:ae,I:ae,j:re,L:le,m:ee,M:oe,p:u,S:ie,U:Wt,w:Zt,W:Qt,x:s,X:c,y:Jt,Y:$t,Z:Kt,"%":ce};return e}function Ut(t,e,n){var r=t<0?"-":"",a=(r?-t:t)+"",o=a.length;return r+(o68?1900:2e3)}function ee(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function ne(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function re(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+3));return r?(t.j=+r[0],n+r[0].length):-1}function ae(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function oe(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function ie(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function le(t,e,n){yl.lastIndex=0;var r=yl.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function se(t){var e=t.getTimezoneOffset(),n=e>0?"-":"+",r=bi(e)/60|0,a=bi(e)%60;return n+Ut(r,"0",2)+Ut(a,"0",2)}function ce(t,e,n){xl.lastIndex=0;var r=xl.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function ue(t){for(var e=t.length,n=-1;++n=0?1:-1,l=i*n,s=Math.cos(e),c=Math.sin(e),u=o*c,f=a*s+u*Math.cos(l),d=u*i*Math.sin(l);Al.add(Math.atan2(d,f)),r=t,a=s,o=c}var e,n,r,a,o;Tl.point=function(i,l){Tl.point=t,r=(e=i)*Vi,a=Math.cos(l=(n=l)*Vi/2+Fi/4),o=Math.sin(l)},Tl.lineEnd=function(){t(e,n)}}function ve(t){var e=t[0],n=t[1],r=Math.cos(n);return[r*Math.cos(e),r*Math.sin(e),Math.sin(n)]}function ye(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function xe(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function be(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function _e(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function we(t){var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}function Me(t){return[Math.atan2(t[1],t[0]),rt(t[2])]}function ke(t,e){return bi(t[0]-e[0])=0;--l)a.point((f=u[l])[0],f[1])}else r(h.x,h.p.x,-1,a);h=h.p}h=h.o,u=h.z,p=!p}while(!h.v);a.lineEnd()}}}function Ee(t){if(e=t.length){for(var e,n,r=0,a=t[0];++r0){for(_||(o.polygonStart(),_=!0),o.lineStart();++i1&&2&e&&n.push(n.pop().concat(n.shift())),h.push(n.filter(Re))}var h,p,g,m=e(o),v=a.invert(r[0],r[1]),y={point:i,lineStart:s,lineEnd:c,polygonStart:function(){y.point=u,y.lineStart=f,y.lineEnd=d,h=[],p=[]},polygonEnd:function(){y.point=i,y.lineStart=s,y.lineEnd=c,h=ui.merge(h);var t=He(v,p);h.length?(_||(o.polygonStart(),_=!0),Pe(h,Ie,t,n,o)):t&&(_||(o.polygonStart(),_=!0),o.lineStart(),n(null,null,1,o),o.lineEnd()),_&&(o.polygonEnd(),_=!1),h=p=null},sphere:function(){o.polygonStart(),o.lineStart(),n(null,null,1,o),o.lineEnd(),o.polygonEnd()}},x=je(),b=e(x),_=!1;return y}}function Re(t){return t.length>1}function je(){var t,e=[];return{lineStart:function(){e.push(t=[])},point:function(e,n){t.push([e,n])},lineEnd:M,buffer:function(){var n=e;return e=[],t=null,n},rejoin:function(){e.length>1&&e.push(e.pop().concat(e.shift()))}}}function Ie(t,e){return((t=t.x)[0]<0?t[1]-Hi-ji:Hi-t[1])-((e=e.x)[0]<0?e[1]-Hi-ji:Hi-e[1])}function Fe(t){var e,n=NaN,r=NaN,a=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(o,i){var l=o>0?Fi:-Fi,s=bi(o-n);bi(s-Fi)0?Hi:-Hi),t.point(a,r),t.lineEnd(),t.lineStart(),t.point(l,r),t.point(o,r),e=0):a!==l&&s>=Fi&&(bi(n-a)ji?Math.atan((Math.sin(e)*(o=Math.cos(r))*Math.sin(n)-Math.sin(r)*(a=Math.cos(e))*Math.sin(t))/(a*o*i)):(e+r)/2}function qe(t,e,n,r){var a;if(null==t)a=n*Hi,r.point(-Fi,a),r.point(0,a),r.point(Fi,a),r.point(Fi,0),r.point(Fi,-a),r.point(0,-a),r.point(-Fi,-a),r.point(-Fi,0),r.point(-Fi,a);else if(bi(t[0]-e[0])>ji){var o=t[0]=0?1:-1,M=w*_,k=M>Fi,A=p*x;if(Al.add(Math.atan2(A*w*Math.sin(M),g*b+A*Math.cos(M))),o+=k?_+w*Bi:_,k^d>=n^v>=n){var T=xe(ve(f),ve(t));we(T);var L=xe(a,T);we(L);var C=(k^_>=0?-1:1)*rt(L[2]);(r>C||r===C&&(T[0]||T[1]))&&(i+=k^_>=0?1:-1)}if(!m++)break;d=v,p=x,g=b,f=t}}return(o<-ji||oo}function n(t){var n,o,s,c,u;return{lineStart:function(){c=s=!1,u=1},point:function(f,d){var h,p=[f,d],g=e(f,d),m=i?g?0:a(f,d):g?a(f+(f<0?Fi:-Fi),d):0;if(!n&&(c=s=g)&&t.lineStart(),g!==s&&(h=r(n,p),(ke(n,h)||ke(p,h))&&(p[0]+=ji,p[1]+=ji,g=e(p[0],p[1]))),g!==s)u=0,g?(t.lineStart(),h=r(p,n),t.point(h[0],h[1])):(h=r(n,p),t.point(h[0],h[1]),t.lineEnd()),n=h;else if(l&&n&&i^g){var v;m&o||!(v=r(p,n,!0))||(u=0,i?(t.lineStart(),t.point(v[0][0],v[0][1]),t.point(v[1][0],v[1][1]),t.lineEnd()):(t.point(v[1][0],v[1][1]),t.lineEnd(),t.lineStart(),t.point(v[0][0],v[0][1])))}!g||n&&ke(n,p)||t.point(p[0],p[1]),n=p,s=g,o=m},lineEnd:function(){s&&t.lineEnd(),n=null},clean:function(){return u|(c&&s)<<1}}}function r(t,e,n){var r=ve(t),a=ve(e),i=[1,0,0],l=xe(r,a),s=ye(l,l),c=l[0],u=s-c*c;if(!u)return!n&&t;var f=o*s/u,d=-o*c/u,h=xe(i,l),p=_e(i,f),g=_e(l,d);be(p,g);var m=h,v=ye(p,m),y=ye(m,m),x=v*v-y*(ye(p,p)-1);if(!(x<0)){var b=Math.sqrt(x),_=_e(m,(-v-b)/y);if(be(_,p),_=Me(_),!n)return _;var w,M=t[0],k=e[0],A=t[1],T=e[1];k0^_[1]<(bi(_[0]-M)Fi^(M<=_[0]&&_[0]<=k)){var S=_e(m,(-v+b)/y);return be(S,p),[_,Me(S)]}}}function a(e,n){var r=i?t:Fi-t,a=0;return e<-r?a|=1:e>r&&(a|=2),n<-r?a|=4:n>r&&(a|=8),a}var o=Math.cos(t),i=o>0,l=bi(o)>ji,s=vn(t,6*Vi);return De(e,n,s,i?[0,-t]:[-Fi,t-Fi])}function Ge(t,e,n,r){return function(a){var o,i=a.a,l=a.b,s=i.x,c=i.y,u=l.x,f=l.y,d=0,h=1,p=u-s,g=f-c;if(o=t-s,p||!(o>0)){if(o/=p,p<0){if(o0){if(o>h)return;o>d&&(d=o)}if(o=n-s,p||!(o<0)){if(o/=p,p<0){if(o>h)return;o>d&&(d=o)}else if(p>0){if(o0)){if(o/=g,g<0){if(o0){if(o>h)return;o>d&&(d=o)}if(o=r-c,g||!(o<0)){if(o/=g,g<0){if(o>h)return;o>d&&(d=o)}else if(g>0){if(o0&&(a.a={x:s+d*p,y:c+d*g}),h<1&&(a.b={x:s+h*p,y:c+h*g}),a}}}}}}function Ue(t,e,n,r){function a(r,a){return bi(r[0]-t)0?0:3:bi(r[0]-n)0?2:1:bi(r[1]-e)0?1:0:a>0?3:2}function o(t,e){return i(t.x,e.x)}function i(t,e){var n=a(t,1),r=a(e,1);return n!==r?n-r:0===n?e[1]-t[1]:1===n?t[0]-e[0]:2===n?t[1]-e[1]:e[0]-t[0]}return function(l){function s(t){for(var e=0,n=m.length,r=t[1],a=0;ar&&et(c,o,t)>0&&++e:o[1]<=r&&et(c,o,t)<0&&--e,c=o;return 0!==e}function c(o,l,s,c){var u=0,f=0;if(null==o||(u=a(o,s))!==(f=a(l,s))||i(o,l)<0^s>0){do c.point(0===u||3===u?t:n,u>1?r:e);while((u=(u+s+4)%4)!==f)}else c.point(l[0],l[1])}function u(a,o){return t<=a&&a<=n&&e<=o&&o<=r}function f(t,e){u(t,e)&&l.point(t,e)}function d(){z.point=p,m&&m.push(v=[]),k=!0,M=!1,_=w=NaN}function h(){g&&(p(y,x),b&&M&&L.rejoin(),g.push(L.buffer())),z.point=f,M&&l.lineEnd()}function p(t,e){t=Math.max(-Bl,Math.min(Bl,t)),e=Math.max(-Bl,Math.min(Bl,e));var n=u(t,e);if(m&&v.push([t,e]),k)y=t,x=e,b=n,k=!1,n&&(l.lineStart(),l.point(t,e));else if(n&&M)l.point(t,e);else{var r={a:{x:_,y:w},b:{x:t,y:e}};C(r)?(M||(l.lineStart(),l.point(r.a.x,r.a.y)),l.point(r.b.x,r.b.y),n||l.lineEnd(),A=!1):n&&(l.lineStart(),l.point(t,e),A=!1)}_=t,w=e,M=n}var g,m,v,y,x,b,_,w,M,k,A,T=l,L=je(),C=Ge(t,e,n,r),z={point:f,lineStart:d,lineEnd:h,polygonStart:function(){l=L,g=[],m=[],A=!0},polygonEnd:function(){l=T,g=ui.merge(g);var e=s([t,r]),n=A&&e,a=g.length;(n||a)&&(l.polygonStart(),n&&(l.lineStart(),c(null,null,1,l),l.lineEnd()),a&&Pe(g,o,e,c,l),l.polygonEnd()),g=m=v=null}};return z}}function Xe(t){var e=0,n=Fi/3,r=cn(t),a=r(e,n);return a.parallels=function(t){return arguments.length?r(e=t[0]*Fi/180,n=t[1]*Fi/180):[e/Fi*180,n/Fi*180]},a}function Ye(t,e){function n(t,e){var n=Math.sqrt(o-2*a*Math.sin(e))/a;return[n*Math.sin(t*=a),i-n*Math.cos(t)]}var r=Math.sin(t),a=(r+Math.sin(e))/2,o=1+r*(2*a-r),i=Math.sqrt(o)/a;return n.invert=function(t,e){var n=i-e;return[Math.atan2(t,n)/a,rt((o-(t*t+n*n)*a*a)/(2*a))]},n}function Ze(){function t(t,e){Hl+=a*t-r*e,r=t,a=e}var e,n,r,a;Yl.point=function(o,i){Yl.point=t,e=r=o,n=a=i},Yl.lineEnd=function(){t(e,n)}}function We(t,e){tUl&&(Ul=t),eXl&&(Xl=e)}function Qe(){function t(t,e){i.push("M",t,",",e,o)}function e(t,e){i.push("M",t,",",e),l.point=n}function n(t,e){i.push("L",t,",",e)}function r(){l.point=t}function a(){i.push("Z")}var o=$e(4.5),i=[],l={point:t,lineStart:function(){l.point=e},lineEnd:r,polygonStart:function(){l.lineEnd=a},polygonEnd:function(){l.lineEnd=r,l.point=t},pointRadius:function(t){return o=$e(t),l},result:function(){if(i.length){var t=i.join("");return i=[],t}}};return l}function $e(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Je(t,e){zl+=t,Sl+=e,++Ol}function Ke(){function t(t,r){var a=t-e,o=r-n,i=Math.sqrt(a*a+o*o);Pl+=i*(e+t)/2,El+=i*(n+r)/2,Nl+=i,Je(e=t,n=r)}var e,n;Wl.point=function(r,a){Wl.point=t,Je(e=r,n=a)}}function tn(){Wl.point=Je}function en(){function t(t,e){var n=t-r,o=e-a,i=Math.sqrt(n*n+o*o);Pl+=i*(r+t)/2,El+=i*(a+e)/2,Nl+=i,i=a*t-r*e,Dl+=i*(r+t),Rl+=i*(a+e),jl+=3*i,Je(r=t,a=e)}var e,n,r,a;Wl.point=function(o,i){Wl.point=t,Je(e=r=o,n=a=i)},Wl.lineEnd=function(){t(e,n)}}function nn(t){function e(e,n){t.moveTo(e+i,n),t.arc(e,n,i,0,Bi)}function n(e,n){t.moveTo(e,n),l.point=r}function r(e,n){t.lineTo(e,n)}function a(){l.point=e}function o(){t.closePath()}var i=4.5,l={point:e,lineStart:function(){l.point=n},lineEnd:a,polygonStart:function(){l.lineEnd=o},polygonEnd:function(){l.lineEnd=a,l.point=e},pointRadius:function(t){return i=t,l},result:M};return l}function rn(t){function e(t){return(l?r:n)(t)}function n(e){return ln(e,function(n,r){n=t(n,r),e.point(n[0],n[1])})}function r(e){function n(n,r){n=t(n,r),e.point(n[0],n[1])}function r(){x=NaN,k.point=o,e.lineStart()}function o(n,r){var o=ve([n,r]),i=t(n,r);a(x,b,y,_,w,M,x=i[0],b=i[1],y=n,_=o[0],w=o[1],M=o[2],l,e),e.point(x,b)}function i(){k.point=n,e.lineEnd()}function s(){r(),k.point=c,k.lineEnd=u}function c(t,e){o(f=t,d=e),h=x,p=b,g=_,m=w,v=M,k.point=o}function u(){a(x,b,y,_,w,M,h,p,f,g,m,v,l,e),k.lineEnd=i,i()}var f,d,h,p,g,m,v,y,x,b,_,w,M,k={point:n,lineStart:r,lineEnd:i,polygonStart:function(){e.polygonStart(),k.lineStart=s},polygonEnd:function(){e.polygonEnd(),k.lineStart=r}};return k}function a(e,n,r,l,s,c,u,f,d,h,p,g,m,v){var y=u-e,x=f-n,b=y*y+x*x;if(b>4*o&&m--){var _=l+h,w=s+p,M=c+g,k=Math.sqrt(_*_+w*w+M*M),A=Math.asin(M/=k),T=bi(bi(M)-1)o||bi((y*S+x*O)/b-.5)>.3||l*h+s*p+c*g0&&16,e):Math.sqrt(o)},e}function an(t){var e=rn(function(e,n){return t([e*Gi,n*Gi])});return function(t){return un(e(t))}}function on(t){this.stream=t}function ln(t,e){return{point:e,sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}function sn(t){return cn(function(){return t})()}function cn(t){function e(t){return t=l(t[0]*Vi,t[1]*Vi),[t[0]*d+s,c-t[1]*d]}function n(t){return t=l.invert((t[0]-s)/d,(c-t[1])/d),t&&[t[0]*Gi,t[1]*Gi]}function r(){l=Se(i=hn(v,y,x),o);var t=o(g,m);return s=h-t[0]*d,c=p+t[1]*d,a()}function a(){return u&&(u.valid=!1,u=null),e}var o,i,l,s,c,u,f=rn(function(t,e){return t=o(t,e),[t[0]*d+s,c-t[1]*d]}),d=150,h=480,p=250,g=0,m=0,v=0,y=0,x=0,_=Fl,w=b,M=null,k=null;return e.stream=function(t){return u&&(u.valid=!1),u=un(_(i,f(w(t)))),u.valid=!0,u},e.clipAngle=function(t){return arguments.length?(_=null==t?(M=t,Fl):Ve((M=+t)*Vi),a()):M},e.clipExtent=function(t){return arguments.length?(k=t,w=t?Ue(t[0][0],t[0][1],t[1][0],t[1][1]):b,a()):k},e.scale=function(t){return arguments.length?(d=+t,r()):d},e.translate=function(t){return arguments.length?(h=+t[0],p=+t[1],r()):[h,p]},e.center=function(t){return arguments.length?(g=t[0]%360*Vi,m=t[1]%360*Vi,r()):[g*Gi,m*Gi]},e.rotate=function(t){return arguments.length?(v=t[0]%360*Vi,y=t[1]%360*Vi,x=t.length>2?t[2]%360*Vi:0,r()):[v*Gi,y*Gi,x*Gi]},ui.rebind(e,f,"precision"),function(){return o=t.apply(this,arguments),e.invert=o.invert&&n,r()}}function un(t){return ln(t,function(e,n){t.point(e*Vi,n*Vi)})}function fn(t,e){return[t,e]}function dn(t,e){return[t>Fi?t-Bi:t<-Fi?t+Bi:t,e]}function hn(t,e,n){return t?e||n?Se(gn(t),mn(e,n)):gn(t):e||n?mn(e,n):dn}function pn(t){return function(e,n){return e+=t,[e>Fi?e-Bi:e<-Fi?e+Bi:e,n]}}function gn(t){var e=pn(t);return e.invert=pn(-t),e}function mn(t,e){function n(t,e){var n=Math.cos(e),l=Math.cos(t)*n,s=Math.sin(t)*n,c=Math.sin(e),u=c*r+l*a;return[Math.atan2(s*o-u*i,l*r-c*a),rt(u*o+s*i)]}var r=Math.cos(t),a=Math.sin(t),o=Math.cos(e),i=Math.sin(e);return n.invert=function(t,e){var n=Math.cos(e),l=Math.cos(t)*n,s=Math.sin(t)*n,c=Math.sin(e),u=c*o-s*i;return[Math.atan2(s*o+c*i,l*r+u*a),rt(u*r-l*a)]},n}function vn(t,e){var n=Math.cos(t),r=Math.sin(t);return function(a,o,i,l){var s=i*e;null!=a?(a=yn(n,a),o=yn(n,o),(i>0?ao)&&(a+=i*Bi)):(a=t+i*Bi,o=t-.5*s);for(var c,u=a;i>0?u>o:u0?e<-Hi+ji&&(e=-Hi+ji):e>Hi-ji&&(e=Hi-ji);var n=i/Math.pow(a(e),o);return[n*Math.sin(o*t),i-n*Math.cos(o*t)]}var r=Math.cos(t),a=function(t){return Math.tan(Fi/4+t/2)},o=t===e?Math.sin(t):Math.log(r/Math.cos(e))/Math.log(a(e)/a(t)),i=r*Math.pow(a(t),o)/o;return o?(n.invert=function(t,e){var n=i-e,r=tt(o)*Math.sqrt(t*t+n*n);return[Math.atan2(t,n)/o,2*Math.atan(Math.pow(i/r,1/o))-Hi]},n):Cn}function Ln(t,e){function n(t,e){var n=o-e;return[n*Math.sin(a*t),o-n*Math.cos(a*t)]}var r=Math.cos(t),a=t===e?Math.sin(t):(r-Math.cos(e))/(e-t),o=r/a+t;return bi(a)1&&et(t[n[r-2]],t[n[r-1]],t[a])<=0;)--r;n[r++]=a}return n.slice(0,r)}function Nn(t,e){return t[0]-e[0]||t[1]-e[1]}function Dn(t,e,n){return(n[0]-e[0])*(t[1]-e[1])<(n[1]-e[1])*(t[0]-e[0])}function Rn(t,e,n,r){var a=t[0],o=n[0],i=e[0]-a,l=r[0]-o,s=t[1],c=n[1],u=e[1]-s,f=r[1]-c,d=(l*(s-c)-f*(a-o))/(f*i-l*u);return[a+d*i,s+d*u]}function jn(t){var e=t[0],n=t[t.length-1];return!(e[0]-n[0]||e[1]-n[1])}function In(){or(this),this.edge=this.site=this.circle=null}function Fn(t){var e=cs.pop()||new In;return e.site=t,e}function Bn(t){Qn(t),is.remove(t),cs.push(t),or(t)}function qn(t){var e=t.circle,n=e.x,r=e.cy,a={x:n,y:r},o=t.P,i=t.N,l=[t];Bn(t);for(var s=o;s.circle&&bi(n-s.circle.x)ji)l=l.L;else{if(a=o-Gn(l,i),!(a>ji)){r>-ji?(e=l.P,n=l):a>-ji?(e=l,n=l.N):e=n=l;break}if(!l.R){e=l;break}l=l.R}var s=Fn(t);if(is.insert(e,s),e||n){if(e===n)return Qn(e),n=Fn(e.site),is.insert(s,n),s.edge=n.edge=tr(e.site,s.site),Wn(e),void Wn(n);if(!n)return void(s.edge=tr(e.site,s.site));Qn(e),Qn(n);var c=e.site,u=c.x,f=c.y,d=t.x-u,h=t.y-f,p=n.site,g=p.x-u,m=p.y-f,v=2*(d*m-h*g),y=d*d+h*h,x=g*g+m*m,b={x:(m*y-h*x)/v+u,y:(d*x-g*y)/v+f};nr(n.edge,c,p,b),s.edge=tr(c,t,null,b),n.edge=tr(t,p,null,b),Wn(e),Wn(n)}}function Vn(t,e){var n=t.site,r=n.x,a=n.y,o=a-e;if(!o)return r;var i=t.P;if(!i)return-(1/0);n=i.site;var l=n.x,s=n.y,c=s-e;if(!c)return l;var u=l-r,f=1/o-1/c,d=u/c;return f?(-d+Math.sqrt(d*d-2*f*(u*u/(-2*c)-s+c/2+a-o/2)))/f+r:(r+l)/2}function Gn(t,e){var n=t.N;if(n)return Vn(n,e);var r=t.site;return r.y===e?r.x:1/0}function Un(t){this.site=t,this.edges=[]}function Xn(t){for(var e,n,r,a,o,i,l,s,c,u,f=t[0][0],d=t[1][0],h=t[0][1],p=t[1][1],g=os,m=g.length;m--;)if(o=g[m],o&&o.prepare())for(l=o.edges,s=l.length,i=0;iji||bi(a-n)>ji)&&(l.splice(i,0,new rr(er(o.site,u,bi(r-f)ji?{x:f,y:bi(e-f)ji?{x:bi(n-p)ji?{x:d,y:bi(e-d)ji?{x:bi(n-h)=-Ii)){var h=s*s+c*c,p=u*u+f*f,g=(f*h-c*p)/d,m=(s*p-u*h)/d,f=m+l,v=us.pop()||new Zn;v.arc=t,v.site=a,v.x=g+i,v.y=f+Math.sqrt(g*g+m*m),v.cy=f,t.circle=v;for(var y=null,x=ss._;x;)if(v.y=l)return;if(d>p){if(o){if(o.y>=c)return}else o={x:m,y:s};n={x:m,y:c}}else{if(o){if(o.y1)if(d>p){if(o){if(o.y>=c)return}else o={x:(s-a)/r,y:s};n={x:(c-a)/r,y:c}}else{if(o){if(o.y=l)return}else o={x:i,y:r*i+a};n={x:l,y:r*l+a}}else{if(o){if(o.xo||f>i||d=b,M=n>=_,k=M<<1|w,A=k+4;ko&&(a=e.slice(o,a),l[i]?l[i]+=a:l[++i]=a),(n=n[0])===(r=r[0])?l[i]?l[i]+=r:l[++i]=r:(l[++i]=null,s.push({i:i,x:xr(n,r)})),o=hs.lastIndex;return o=0&&!(n=ui.interpolators[r](t,e)););return n}function wr(t,e){var n,r=[],a=[],o=t.length,i=e.length,l=Math.min(t.length,e.length);for(n=0;n=1?1:t(e)}}function kr(t){return function(e){return 1-t(1-e)}}function Ar(t){return function(e){return.5*(e<.5?t(2*e):2-t(2-2*e))}}function Tr(t){return t*t}function Lr(t){ +return t*t*t}function Cr(t){if(t<=0)return 0;if(t>=1)return 1;var e=t*t,n=e*t;return 4*(t<.5?n:3*(t-e)+n-.75)}function zr(t){return function(e){return Math.pow(e,t)}}function Sr(t){return 1-Math.cos(t*Hi)}function Or(t){return Math.pow(2,10*(t-1))}function Pr(t){return 1-Math.sqrt(1-t*t)}function Er(t,e){var n;return arguments.length<2&&(e=.45),arguments.length?n=e/Bi*Math.asin(1/t):(t=1,n=e/4),function(r){return 1+t*Math.pow(2,-10*r)*Math.sin((r-n)*Bi/e)}}function Nr(t){return t||(t=1.70158),function(e){return e*e*((t+1)*e-t)}}function Dr(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function Rr(t,e){t=ui.hcl(t),e=ui.hcl(e);var n=t.h,r=t.c,a=t.l,o=e.h-n,i=e.c-r,l=e.l-a;return isNaN(i)&&(i=0,r=isNaN(r)?e.c:r),isNaN(o)?(o=0,n=isNaN(n)?e.h:n):o>180?o-=360:o<-180&&(o+=360),function(t){return dt(n+o*t,r+i*t,a+l*t)+""}}function jr(t,e){t=ui.hsl(t),e=ui.hsl(e);var n=t.h,r=t.s,a=t.l,o=e.h-n,i=e.s-r,l=e.l-a;return isNaN(i)&&(i=0,r=isNaN(r)?e.s:r),isNaN(o)?(o=0,n=isNaN(n)?e.h:n):o>180?o-=360:o<-180&&(o+=360),function(t){return ut(n+o*t,r+i*t,a+l*t)+""}}function Ir(t,e){t=ui.lab(t),e=ui.lab(e);var n=t.l,r=t.a,a=t.b,o=e.l-n,i=e.a-r,l=e.b-a;return function(t){return pt(n+o*t,r+i*t,a+l*t)+""}}function Fr(t,e){return e-=t,function(n){return Math.round(t+e*n)}}function Br(t){var e=[t.a,t.b],n=[t.c,t.d],r=Hr(e),a=qr(e,n),o=Hr(Vr(n,e,-a))||0;e[0]*n[1]180?e+=360:e-t>180&&(t+=360),r.push({i:n.push(Gr(n)+"rotate(",null,")")-2,x:xr(t,e)})):e&&n.push(Gr(n)+"rotate("+e+")")}function Yr(t,e,n,r){t!==e?r.push({i:n.push(Gr(n)+"skewX(",null,")")-2,x:xr(t,e)}):e&&n.push(Gr(n)+"skewX("+e+")")}function Zr(t,e,n,r){if(t[0]!==e[0]||t[1]!==e[1]){var a=n.push(Gr(n)+"scale(",null,",",null,")");r.push({i:a-4,x:xr(t[0],e[0])},{i:a-2,x:xr(t[1],e[1])})}else 1===e[0]&&1===e[1]||n.push(Gr(n)+"scale("+e+")")}function Wr(t,e){var n=[],r=[];return t=ui.transform(t),e=ui.transform(e),Ur(t.translate,e.translate,n,r),Xr(t.rotate,e.rotate,n,r),Yr(t.skew,e.skew,n,r),Zr(t.scale,e.scale,n,r),t=e=null,function(t){for(var e,a=-1,o=r.length;++a=0;)n.push(a[r])}function sa(t,e){for(var n=[t],r=[];null!=(t=n.pop());)if(r.push(t),(o=t.children)&&(a=o.length))for(var a,o,i=-1;++ia&&(r=n,a=e);return r}function xa(t){return t.reduce(ba,0)}function ba(t,e){return t+e[1]}function _a(t,e){return wa(t,Math.ceil(Math.log(e.length)/Math.LN2+1))}function wa(t,e){for(var n=-1,r=+t[0],a=(t[1]-r)/e,o=[];++n<=e;)o[n]=a*n+r;return o}function Ma(t){return[ui.min(t),ui.max(t)]}function ka(t,e){return t.value-e.value}function Aa(t,e){var n=t._pack_next;t._pack_next=e,e._pack_prev=t,e._pack_next=n,n._pack_prev=e}function Ta(t,e){t._pack_next=e,e._pack_prev=t}function La(t,e){var n=e.x-t.x,r=e.y-t.y,a=t.r+e.r;return.999*a*a>n*n+r*r}function Ca(t){function e(t){u=Math.min(t.x-t.r,u),f=Math.max(t.x+t.r,f),d=Math.min(t.y-t.r,d),h=Math.max(t.y+t.r,h)}if((n=t.children)&&(c=n.length)){var n,r,a,o,i,l,s,c,u=1/0,f=-(1/0),d=1/0,h=-(1/0);if(n.forEach(za),r=n[0],r.x=-r.r,r.y=0,e(r),c>1&&(a=n[1],a.x=a.r,a.y=0,e(a),c>2))for(o=n[2],Pa(r,a,o),e(o),Aa(r,o),r._pack_prev=o,Aa(o,a),a=r._pack_next,i=3;i=0;)e=a[o],e.z+=n,e.m+=n,n+=e.s+(r+=e.c)}function Ia(t,e,n){return t.a.parent===e.parent?t.a:n}function Fa(t){return 1+ui.max(t,function(t){return t.y})}function Ba(t){return t.reduce(function(t,e){return t+e.x},0)/t.length}function qa(t){var e=t.children;return e&&e.length?qa(e[0]):t}function Ha(t){var e,n=t.children;return n&&(e=n.length)?Ha(n[e-1]):t}function Va(t){return{x:t.x,y:t.y,dx:t.dx,dy:t.dy}}function Ga(t,e){var n=t.x+e[3],r=t.y+e[0],a=t.dx-e[1]-e[3],o=t.dy-e[0]-e[2];return a<0&&(n+=a/2,a=0),o<0&&(r+=o/2,o=0),{x:n,y:r,dx:a,dy:o}}function Ua(t){var e=t[0],n=t[t.length-1];return e2?Qa:Ya,s=r?$r:Qr;return i=a(t,e,s,n),l=a(e,t,s,_r),o}function o(t){return i(t)}var i,l;return o.invert=function(t){return l(t)},o.domain=function(e){return arguments.length?(t=e.map(Number),a()):t},o.range=function(t){return arguments.length?(e=t,a()):e},o.rangeRound=function(t){return o.range(t).interpolate(Fr)},o.clamp=function(t){return arguments.length?(r=t,a()):r},o.interpolate=function(t){return arguments.length?(n=t,a()):n},o.ticks=function(e){return eo(t,e)},o.tickFormat=function(e,n){return no(t,e,n)},o.nice=function(e){return Ka(t,e),a()},o.copy=function(){return $a(t,e,n,r)},a()}function Ja(t,e){return ui.rebind(t,e,"range","rangeRound","interpolate","clamp")}function Ka(t,e){return Za(t,Wa(to(t,e)[2])),Za(t,Wa(to(t,e)[2])),t}function to(t,e){null==e&&(e=10);var n=Ua(t),r=n[1]-n[0],a=Math.pow(10,Math.floor(Math.log(r/e)/Math.LN10)),o=e/r*a;return o<=.15?a*=10:o<=.35?a*=5:o<=.75&&(a*=2),n[0]=Math.ceil(n[0]/a)*a,n[1]=Math.floor(n[1]/a)*a+.5*a,n[2]=a,n}function eo(t,e){return ui.range.apply(ui,to(t,e))}function no(t,e,n){var r=to(t,e);if(n){var a=dl.exec(n);if(a.shift(),"s"===a[8]){var o=ui.formatPrefix(Math.max(bi(r[0]),bi(r[1])));return a[7]||(a[7]="."+ro(o.scale(r[2]))),a[8]="f",n=ui.format(a.join("")),function(t){return n(o.scale(t))+o.symbol}}a[7]||(a[7]="."+ao(a[8],r)),n=a.join("")}else n=",."+ro(r[2])+"f";return ui.format(n)}function ro(t){return-Math.floor(Math.log(t)/Math.LN10+.01)}function ao(t,e){var n=ro(e[2]);return t in As?Math.abs(n-ro(Math.max(bi(e[0]),bi(e[1]))))+ +("e"!==t):n-2*("%"===t)}function oo(t,e,n,r){function a(t){return(n?Math.log(t<0?0:t):-Math.log(t>0?0:-t))/Math.log(e)}function o(t){return n?Math.pow(e,t):-Math.pow(e,-t)}function i(e){return t(a(e))}return i.invert=function(e){return o(t.invert(e))},i.domain=function(e){return arguments.length?(n=e[0]>=0,t.domain((r=e.map(Number)).map(a)),i):r},i.base=function(n){return arguments.length?(e=+n,t.domain(r.map(a)),i):e},i.nice=function(){var e=Za(r.map(a),n?Math:Ls);return t.domain(e),r=e.map(o),i},i.ticks=function(){var t=Ua(r),i=[],l=t[0],s=t[1],c=Math.floor(a(l)),u=Math.ceil(a(s)),f=e%1?2:e;if(isFinite(u-c)){if(n){for(;c0;d--)i.push(o(c)*d);for(c=0;i[c]s;u--);i=i.slice(c,u)}return i},i.tickFormat=function(t,n){if(!arguments.length)return Ts;arguments.length<2?n=Ts:"function"!=typeof n&&(n=ui.format(n));var r=Math.max(1,e*t/i.ticks().length);return function(t){var i=t/o(Math.round(a(t)));return i*e0?l[n-1]:t[0],n0?0:1}function _o(t,e,n,r,a){var o=t[0]-e[0],i=t[1]-e[1],l=(a?r:-r)/Math.sqrt(o*o+i*i),s=l*i,c=-l*o,u=t[0]+s,f=t[1]+c,d=e[0]+s,h=e[1]+c,p=(u+d)/2,g=(f+h)/2,m=d-u,v=h-f,y=m*m+v*v,x=n-r,b=u*h-d*f,_=(v<0?-1:1)*Math.sqrt(Math.max(0,x*x*y-b*b)),w=(b*v-m*_)/y,M=(-b*m-v*_)/y,k=(b*v+m*_)/y,A=(-b*m+v*_)/y,T=w-p,L=M-g,C=k-p,z=A-g;return T*T+L*L>C*C+z*z&&(w=k,M=A),[[w-s,M-c],[w*n/x,M*n/x]]}function wo(t){function e(e){function i(){c.push("M",o(t(u),l))}for(var s,c=[],u=[],f=-1,d=e.length,h=Ct(n),p=Ct(r);++f1?t.join("L"):t+"Z"}function ko(t){return t.join("L")+"Z"}function Ao(t){for(var e=0,n=t.length,r=t[0],a=[r[0],",",r[1]];++e1&&a.push("H",r[0]),a.join("")}function To(t){for(var e=0,n=t.length,r=t[0],a=[r[0],",",r[1]];++e1){l=e[1],o=t[s],s++,r+="C"+(a[0]+i[0])+","+(a[1]+i[1])+","+(o[0]-l[0])+","+(o[1]-l[1])+","+o[0]+","+o[1];for(var c=2;c9&&(a=3*e/Math.sqrt(a),i[l]=a*n,i[l+1]=a*r));for(l=-1;++l<=s;)a=(t[Math.min(s,l+1)][0]-t[Math.max(0,l-1)][0])/(6*(1+i[l]*i[l])),o.push([a||0,i[l]*a||0]);return o}function Ho(t){return t.length<3?Mo(t):t[0]+Oo(t,qo(t))}function Vo(t){for(var e,n,r,a=-1,o=t.length;++a0;)h[--l].call(t,i);if(o>=1)return g.event&&g.event.end.call(t,t.__data__,e),--p.count?delete p[r]:delete t[n],1}var s,c,u,d,h,p=t[n]||(t[n]={active:0,count:0}),g=p[r];g||(s=a.time,c=Et(o,0,s),g=p[r]={tween:new f,time:s,timer:c,delay:a.delay,duration:a.duration,ease:a.ease,index:e},a=null,++p.count)}function ri(t,e,n){t.attr("transform",function(t){var r=e(t);return"translate("+(isFinite(r)?r:n(t))+",0)"})}function ai(t,e,n){t.attr("transform",function(t){var r=e(t);return"translate(0,"+(isFinite(r)?r:n(t))+")"})}function oi(t){return t.toISOString()}function ii(t,e,n){function r(e){return t(e)}function a(t,n){var r=t[1]-t[0],a=r/n,o=ui.bisect(Js,a);return o==Js.length?[e.year,to(t.map(function(t){return t/31536e6}),n)[2]]:o?e[a/Js[o-1]1?{floor:function(e){for(;n(e=t.floor(e));)e=li(e-1);return e},ceil:function(e){for(;n(e=t.ceil(e));)e=li(+e+1);return e}}:t))},r.ticks=function(t,e){var n=Ua(r.domain()),o=null==t?a(n,10):"number"==typeof t?a(n,t):!t.range&&[{range:t},e];return o&&(t=o[0],e=o[1]),t.range(n[0],li(+n[1]+1),e<1?1:e)},r.tickFormat=function(){return n},r.copy=function(){return ii(t.copy(),e,n)},Ja(r,t)}function li(t){return new Date(t)}function si(t){return JSON.parse(t.responseText)}function ci(t){var e=hi.createRange();return e.selectNode(hi.body),e.createContextualFragment(t.responseText)}var ui={version:"3.5.17"},fi=[].slice,di=function(t){return fi.call(t)},hi=this.document;if(hi)try{di(hi.documentElement.childNodes)[0].nodeType}catch(t){di=function(t){for(var e=t.length,n=new Array(e);e--;)n[e]=t[e];return n}}if(Date.now||(Date.now=function(){return+new Date}),hi)try{hi.createElement("DIV").style.setProperty("opacity",0,"")}catch(t){var pi=this.Element.prototype,gi=pi.setAttribute,mi=pi.setAttributeNS,vi=this.CSSStyleDeclaration.prototype,yi=vi.setProperty;pi.setAttribute=function(t,e){gi.call(this,t,e+"")},pi.setAttributeNS=function(t,e,n){mi.call(this,t,e,n+"")},vi.setProperty=function(t,e,n){yi.call(this,t,e+"",n)}}ui.ascending=a,ui.descending=function(t,e){return et?1:e>=t?0:NaN},ui.min=function(t,e){var n,r,a=-1,o=t.length;if(1===arguments.length){for(;++a=r){n=r;break}for(;++ar&&(n=r)}else{for(;++a=r){n=r;break}for(;++ar&&(n=r)}return n},ui.max=function(t,e){var n,r,a=-1,o=t.length;if(1===arguments.length){for(;++a=r){n=r;break}for(;++an&&(n=r)}else{for(;++a=r){n=r;break}for(;++an&&(n=r)}return n},ui.extent=function(t,e){var n,r,a,o=-1,i=t.length;if(1===arguments.length){for(;++o=r){n=a=r;break}for(;++or&&(n=r),a=r){n=a=r;break}for(;++or&&(n=r),a1)return s/(u-1)},ui.deviation=function(){var t=ui.variance.apply(this,arguments);return t?Math.sqrt(t):t};var xi=l(a);ui.bisectLeft=xi.left,ui.bisect=ui.bisectRight=xi.right,ui.bisector=function(t){return l(1===t.length?function(e,n){return a(t(e),n)}:t)},ui.shuffle=function(t,e,n){(o=arguments.length)<3&&(n=t.length,o<2&&(e=0));for(var r,a,o=n-e;o;)a=Math.random()*o--|0,r=t[o+e],t[o+e]=t[a+e],t[a+e]=r;return t},ui.permute=function(t,e){for(var n=e.length,r=new Array(n);n--;)r[n]=t[e[n]];return r},ui.pairs=function(t){for(var e,n=0,r=t.length-1,a=t[0],o=new Array(r<0?0:r);n=0;)for(r=t[a],e=r.length;--e>=0;)n[--i]=r[e];return n};var bi=Math.abs;ui.range=function(t,e,n){if(arguments.length<3&&(n=1,arguments.length<2&&(e=t,t=0)),(e-t)/n===1/0)throw new Error("infinite range");var r,a=[],o=c(bi(n)),i=-1;if(t*=o,e*=o,n*=o,n<0)for(;(r=t+n*++i)>e;)a.push(r/o);else for(;(r=t+n*++i)=o.length)return r?r.call(a,i):n?i.sort(n):i;for(var s,c,u,d,h=-1,p=i.length,g=o[l++],m=new f;++h=o.length)return t;var r=[],a=i[n++];return t.forEach(function(t,a){r.push({key:t,values:e(a,n)})}),a?r.sort(function(t,e){return a(t.key,e.key)}):r}var n,r,a={},o=[],i=[];return a.map=function(e,n){return t(n,e,0)},a.entries=function(n){return e(t(ui.map,n,0),0)},a.key=function(t){return o.push(t),a},a.sortKeys=function(t){return i[o.length-1]=t,a},a.sortValues=function(t){return n=t,a},a.rollup=function(t){return r=t,a},a},ui.set=function(t){var e=new x;if(t)for(var n=0,r=t.length;n=0&&(r=t.slice(n+1),t=t.slice(0,n)),t)return arguments.length<2?this[t].on(r):this[t].on(r,e);if(2===arguments.length){if(null==e)for(t in this)this.hasOwnProperty(t)&&this[t].on(r,null);return this}},ui.event=null,ui.requote=function(t){return t.replace(ki,"\\$&")};var ki=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,Ai={}.__proto__?function(t,e){t.__proto__=e}:function(t,e){for(var n in e)t[n]=e[n]},Ti=function(t,e){return e.querySelector(t)},Li=function(t,e){return e.querySelectorAll(t)},Ci=function(t,e){var n=t.matches||t[w(t,"matchesSelector")];return(Ci=function(t,e){return n.call(t,e)})(t,e)};"function"==typeof Sizzle&&(Ti=function(t,e){return Sizzle(t,e)[0]||null},Li=Sizzle,Ci=Sizzle.matchesSelector),ui.selection=function(){return ui.select(hi.documentElement)};var zi=ui.selection.prototype=[];zi.select=function(t){var e,n,r,a,o=[];t=S(t);for(var i=-1,l=this.length;++i=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Oi.hasOwnProperty(n)?{space:Oi[n],local:t}:t}},zi.attr=function(t,e){if(arguments.length<2){if("string"==typeof t){var n=this.node();return t=ui.ns.qualify(t),t.local?n.getAttributeNS(t.space,t.local):n.getAttribute(t)}for(e in t)this.each(P(e,t[e]));return this}return this.each(P(t,e))},zi.classed=function(t,e){if(arguments.length<2){if("string"==typeof t){var n=this.node(),r=(t=D(t)).length,a=-1;if(e=n.classList){for(;++a=0;)(n=r[a])&&(o&&o!==n.nextSibling&&o.parentNode.insertBefore(n,o),o=n);return this},zi.sort=function(t){t=G.apply(this,arguments);for(var e=-1,n=this.length;++e0&&(e=e.transition().duration(z)),e.call(t.event)}function l(){_&&_.domain(b.range().map(function(t){return(t-k.x)/k.k}).map(b.invert)),M&&M.domain(w.range().map(function(t){return(t-k.y)/k.k}).map(w.invert))}function s(t){S++||t({type:"zoomstart"})}function c(t){l(),t({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function u(t){--S||(t({type:"zoomend"}),m=null)}function f(){function t(){l=1,o(ui.mouse(a),d),c(i)}function n(){f.on(P,null).on(E,null),h(l),u(i)}var a=this,i=D.of(a,arguments),l=0,f=ui.select(r(a)).on(P,t).on(E,n),d=e(ui.mouse(a)),h=$(a);Hs.call(a),s(i)}function d(){function t(){var t=ui.touches(p);return h=k.k,t.forEach(function(t){t.identifier in m&&(m[t.identifier]=e(t))}),t}function n(){var e=ui.event.target;ui.select(e).on(b,r).on(_,l),w.push(e);for(var n=ui.event.changedTouches,a=0,o=n.length;a1){var u=s[0],f=s[1],d=u[0]-f[0],h=u[1]-f[1];v=d*d+h*h}}function r(){var t,e,n,r,i=ui.touches(p);Hs.call(p);for(var l=0,s=i.length;l=c)return i;if(a)return a=!1,o;var e=u;if(34===t.charCodeAt(e)){for(var n=e;n++=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,hl=ui.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,e){return t.toPrecision(e)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},r:function(t,e){return(t=ui.round(t,jt(t,e))).toFixed(Math.max(0,Math.min(20,jt(t*(1+1e-15),e))))}}),pl=ui.time={},gl=Date;qt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){ml.setUTCDate.apply(this._,arguments)},setDay:function(){ml.setUTCDay.apply(this._,arguments)},setFullYear:function(){ml.setUTCFullYear.apply(this._,arguments)},setHours:function(){ml.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){ml.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){ml.setUTCMinutes.apply(this._,arguments)},setMonth:function(){ml.setUTCMonth.apply(this._,arguments)},setSeconds:function(){ml.setUTCSeconds.apply(this._,arguments)},setTime:function(){ml.setTime.apply(this._,arguments)}};var ml=Date.prototype;pl.year=Ht(function(t){return t=pl.day(t),t.setMonth(0,1),t},function(t,e){t.setFullYear(t.getFullYear()+e)},function(t){return t.getFullYear()}),pl.years=pl.year.range,pl.years.utc=pl.year.utc.range,pl.day=Ht(function(t){var e=new gl(2e3,0);return e.setFullYear(t.getFullYear(),t.getMonth(),t.getDate()),e},function(t,e){t.setDate(t.getDate()+e)},function(t){return t.getDate()-1}),pl.days=pl.day.range,pl.days.utc=pl.day.utc.range,pl.dayOfYear=function(t){var e=pl.year(t);return Math.floor((t-e-6e4*(t.getTimezoneOffset()-e.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(t,e){e=7-e;var n=pl[t]=Ht(function(t){return(t=pl.day(t)).setDate(t.getDate()-(t.getDay()+e)%7),t},function(t,e){t.setDate(t.getDate()+7*Math.floor(e))},function(t){var n=pl.year(t).getDay();return Math.floor((pl.dayOfYear(t)+(n+e)%7)/7)-(n!==e)});pl[t+"s"]=n.range,pl[t+"s"].utc=n.utc.range,pl[t+"OfYear"]=function(t){var n=pl.year(t).getDay();return Math.floor((pl.dayOfYear(t)+(n+e)%7)/7)}}),pl.week=pl.sunday,pl.weeks=pl.sunday.range,pl.weeks.utc=pl.sunday.utc.range,pl.weekOfYear=pl.sundayOfYear;var vl={"-":"",_:" ",0:"0"},yl=/^\s*\d+/,xl=/^%/;ui.locale=function(t){return{numberFormat:Ft(t),timeFormat:Gt(t)}};var bl=ui.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ui.format=bl.numberFormat,ui.geo={},fe.prototype={s:0,t:0,add:function(t){de(t,this.t,_l),de(_l.s,this.s,this),this.s?this.t+=_l.t:this.s=_l.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var _l=new fe;ui.geo.stream=function(t,e){t&&wl.hasOwnProperty(t.type)?wl[t.type](t,e):he(t,e)};var wl={Feature:function(t,e){he(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,a=n.length;++rh&&(h=e)}function e(e,n){var r=ve([e*Vi,n*Vi]);if(v){var a=xe(v,r),o=[a[1],-a[0],0],i=xe(o,a);we(i),i=Me(i);var s=e-p,c=s>0?1:-1,g=i[0]*Gi*c,m=bi(s)>180;if(m^(c*ph&&(h=y)}else if(g=(g+360)%360-180,m^(c*ph&&(h=n);m?el(u,d)&&(d=e):l(e,d)>l(u,d)&&(u=e):d>=u?(ed&&(d=e)):e>p?l(u,e)>l(u,d)&&(d=e):l(e,d)>l(u,d)&&(u=e)}else t(e,n);v=r,p=e}function n(){_.point=e}function r(){b[0]=u,b[1]=d,_.point=t,v=null}function a(t,n){if(v){var r=t-p;y+=bi(r)>180?r+(r>0?360:-360):r}else g=t,m=n;Tl.point(t,n),e(t,n)}function o(){Tl.lineStart()}function i(){a(g,m),Tl.lineEnd(),bi(y)>ji&&(u=-(d=180)),b[0]=u,b[1]=d,v=null}function l(t,e){return(e-=t)<0?e+360:e}function s(t,e){return t[0]-e[0]}function c(t,e){return e[0]<=e[1]?e[0]<=t&&t<=e[1]:tji?h=90:y<-ji&&(f=-90),b[0]=u,b[1]=d}};return function(t){h=d=-(u=f=1/0),x=[],ui.geo.stream(t,_);var e=x.length;if(e){x.sort(s);for(var n,r=1,a=x[0],o=[a];rl(a[0],a[1])&&(a[1]=n[1]),l(n[0],a[1])>l(a[0],a[1])&&(a[0]=n[0])):o.push(a=n);for(var i,n,p=-(1/0),e=o.length-1,r=0,a=o[e];r<=e;a=n,++r)n=o[r],(i=l(a[1],n[0]))>p&&(p=i,u=n[0],d=a[1])}return x=b=null,u===1/0||f===1/0?[[NaN,NaN],[NaN,NaN]]:[[u,f],[d,h]]}}(),ui.geo.centroid=function(t){Ll=Cl=zl=Sl=Ol=Pl=El=Nl=Dl=Rl=jl=0,ui.geo.stream(t,Il);var e=Dl,n=Rl,r=jl,a=e*e+n*n+r*r;return a=.12&&a<.234&&r>=-.425&&r<-.214?i:a>=.166&&a<.234&&r>=-.214&&r<-.115?l:o).invert(t)},t.stream=function(t){var e=o.stream(t),n=i.stream(t),r=l.stream(t);return{point:function(t,a){e.point(t,a),n.point(t,a),r.point(t,a)},sphere:function(){e.sphere(),n.sphere(),r.sphere()},lineStart:function(){e.lineStart(),n.lineStart(),r.lineStart()},lineEnd:function(){e.lineEnd(),n.lineEnd(),r.lineEnd()},polygonStart:function(){e.polygonStart(),n.polygonStart(),r.polygonStart()},polygonEnd:function(){e.polygonEnd(),n.polygonEnd(),r.polygonEnd()}}},t.precision=function(e){return arguments.length?(o.precision(e),i.precision(e),l.precision(e),t):o.precision()},t.scale=function(e){return arguments.length?(o.scale(e),i.scale(.35*e),l.scale(e),t.translate(o.translate())):o.scale()},t.translate=function(e){if(!arguments.length)return o.translate();var c=o.scale(),u=+e[0],f=+e[1];return n=o.translate(e).clipExtent([[u-.455*c,f-.238*c],[u+.455*c,f+.238*c]]).stream(s).point,r=i.translate([u-.307*c,f+.201*c]).clipExtent([[u-.425*c+ji,f+.12*c+ji],[u-.214*c-ji,f+.234*c-ji]]).stream(s).point,a=l.translate([u-.205*c,f+.212*c]).clipExtent([[u-.214*c+ji,f+.166*c+ji],[u-.115*c-ji,f+.234*c-ji]]).stream(s).point,t},t.scale(1070)};var ql,Hl,Vl,Gl,Ul,Xl,Yl={point:M,lineStart:M,lineEnd:M,polygonStart:function(){Hl=0,Yl.lineStart=Ze},polygonEnd:function(){Yl.lineStart=Yl.lineEnd=Yl.point=M,ql+=bi(Hl/2)}},Zl={point:We,lineStart:M,lineEnd:M,polygonStart:M,polygonEnd:M},Wl={point:Je,lineStart:Ke,lineEnd:tn,polygonStart:function(){Wl.lineStart=en},polygonEnd:function(){Wl.point=Je,Wl.lineStart=Ke,Wl.lineEnd=tn}};ui.geo.path=function(){function t(t){return t&&("function"==typeof l&&o.pointRadius(+l.apply(this,arguments)),i&&i.valid||(i=a(o)),ui.geo.stream(t,i)),o.result()}function e(){return i=null,t}var n,r,a,o,i,l=4.5;return t.area=function(t){return ql=0,ui.geo.stream(t,a(Yl)),ql},t.centroid=function(t){return zl=Sl=Ol=Pl=El=Nl=Dl=Rl=jl=0,ui.geo.stream(t,a(Wl)),jl?[Dl/jl,Rl/jl]:Nl?[Pl/Nl,El/Nl]:Ol?[zl/Ol,Sl/Ol]:[NaN,NaN]},t.bounds=function(t){return Ul=Xl=-(Vl=Gl=1/0),ui.geo.stream(t,a(Zl)),[[Vl,Gl],[Ul,Xl]]},t.projection=function(t){return arguments.length?(a=(n=t)?t.stream||an(t):b,e()):n},t.context=function(t){return arguments.length?(o=null==(r=t)?new Qe:new nn(t),"function"!=typeof l&&o.pointRadius(l),e()):r},t.pointRadius=function(e){return arguments.length?(l="function"==typeof e?e:(o.pointRadius(+e),+e),t):l},t.projection(ui.geo.albersUsa()).context(null)},ui.geo.transform=function(t){return{stream:function(e){var n=new on(e);for(var r in t)n[r]=t[r];return n}}},on.prototype={point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ui.geo.projection=sn,ui.geo.projectionMutator=cn,(ui.geo.equirectangular=function(){return sn(fn)}).raw=fn.invert=fn,ui.geo.rotation=function(t){function e(e){return e=t(e[0]*Vi,e[1]*Vi),e[0]*=Gi,e[1]*=Gi,e}return t=hn(t[0]%360*Vi,t[1]*Vi,t.length>2?t[2]*Vi:0),e.invert=function(e){return e=t.invert(e[0]*Vi,e[1]*Vi),e[0]*=Gi,e[1]*=Gi,e},e},dn.invert=fn,ui.geo.circle=function(){function t(){var t="function"==typeof r?r.apply(this,arguments):r,e=hn(-t[0]*Vi,-t[1]*Vi,0).invert,a=[];return n(null,null,1,{point:function(t,n){a.push(t=e(t,n)),t[0]*=Gi,t[1]*=Gi}}),{type:"Polygon",coordinates:[a]}}var e,n,r=[0,0],a=6;return t.origin=function(e){return arguments.length?(r=e,t):r},t.angle=function(r){return arguments.length?(n=vn((e=+r)*Vi,a*Vi),t):e},t.precision=function(r){return arguments.length?(n=vn(e*Vi,(a=+r)*Vi),t):a},t.angle(90)},ui.geo.distance=function(t,e){var n,r=(e[0]-t[0])*Vi,a=t[1]*Vi,o=e[1]*Vi,i=Math.sin(r),l=Math.cos(r),s=Math.sin(a),c=Math.cos(a),u=Math.sin(o),f=Math.cos(o);return Math.atan2(Math.sqrt((n=f*i)*n+(n=c*u-s*f*l)*n),s*u+c*f*l)},ui.geo.graticule=function(){function t(){return{type:"MultiLineString",coordinates:e()}}function e(){return ui.range(Math.ceil(o/m)*m,a,m).map(d).concat(ui.range(Math.ceil(c/v)*v,s,v).map(h)).concat(ui.range(Math.ceil(r/p)*p,n,p).filter(function(t){return bi(t%m)>ji}).map(u)).concat(ui.range(Math.ceil(l/g)*g,i,g).filter(function(t){return bi(t%v)>ji}).map(f))}var n,r,a,o,i,l,s,c,u,f,d,h,p=10,g=p,m=90,v=360,y=2.5;return t.lines=function(){return e().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[d(o).concat(h(s).slice(1),d(a).reverse().slice(1),h(c).reverse().slice(1))]}},t.extent=function(e){return arguments.length?t.majorExtent(e).minorExtent(e):t.minorExtent()},t.majorExtent=function(e){return arguments.length?(o=+e[0][0],a=+e[1][0],c=+e[0][1],s=+e[1][1],o>a&&(e=o,o=a,a=e),c>s&&(e=c,c=s,s=e),t.precision(y)):[[o,c],[a,s]]},t.minorExtent=function(e){return arguments.length?(r=+e[0][0],n=+e[1][0],l=+e[0][1],i=+e[1][1],r>n&&(e=r,r=n,n=e),l>i&&(e=l,l=i,i=e),t.precision(y)):[[r,l],[n,i]]},t.step=function(e){return arguments.length?t.majorStep(e).minorStep(e):t.minorStep()},t.majorStep=function(e){return arguments.length?(m=+e[0],v=+e[1],t):[m,v]},t.minorStep=function(e){return arguments.length?(p=+e[0],g=+e[1],t):[p,g]},t.precision=function(e){return arguments.length?(y=+e,u=xn(l,i,90),f=bn(r,n,y),d=xn(c,s,90),h=bn(o,a,y),t):y},t.majorExtent([[-180,-90+ji],[180,90-ji]]).minorExtent([[-180,-80-ji],[180,80+ji]])},ui.geo.greatArc=function(){function t(){return{type:"LineString",coordinates:[e||r.apply(this,arguments),n||a.apply(this,arguments)]}}var e,n,r=_n,a=wn;return t.distance=function(){return ui.geo.distance(e||r.apply(this,arguments),n||a.apply(this,arguments))},t.source=function(n){return arguments.length?(r=n,e="function"==typeof n?null:n,t):r},t.target=function(e){return arguments.length?(a=e,n="function"==typeof e?null:e,t):a},t.precision=function(){return arguments.length?t:0},t},ui.geo.interpolate=function(t,e){return Mn(t[0]*Vi,t[1]*Vi,e[0]*Vi,e[1]*Vi)},ui.geo.length=function(t){return Ql=0,ui.geo.stream(t,$l),Ql};var Ql,$l={sphere:M,point:M,lineStart:kn,lineEnd:M,polygonStart:M,polygonEnd:M},Jl=An(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(ui.geo.azimuthalEqualArea=function(){return sn(Jl)}).raw=Jl;var Kl=An(function(t){var e=Math.acos(t);return e&&e/Math.sin(e)},b);(ui.geo.azimuthalEquidistant=function(){return sn(Kl)}).raw=Kl,(ui.geo.conicConformal=function(){return Xe(Tn)}).raw=Tn,(ui.geo.conicEquidistant=function(){return Xe(Ln)}).raw=Ln;var ts=An(function(t){return 1/t},Math.atan);(ui.geo.gnomonic=function(){return sn(ts)}).raw=ts,Cn.invert=function(t,e){return[t,2*Math.atan(Math.exp(e))-Hi]},(ui.geo.mercator=function(){return zn(Cn)}).raw=Cn;var es=An(function(){return 1},Math.asin);(ui.geo.orthographic=function(){return sn(es)}).raw=es;var ns=An(function(t){return 1/(1+t)},function(t){return 2*Math.atan(t)});(ui.geo.stereographic=function(){return sn(ns)}).raw=ns,Sn.invert=function(t,e){return[-e,2*Math.atan(Math.exp(t))-Hi]},(ui.geo.transverseMercator=function(){var t=zn(Sn),e=t.center,n=t.rotate;return t.center=function(t){return t?e([-t[1],t[0]]):(t=e(),[t[1],-t[0]])},t.rotate=function(t){return t?n([t[0],t[1],t.length>2?t[2]+90:90]):(t=n(),[t[0],t[1],t[2]-90])},n([0,0,90])}).raw=Sn,ui.geom={},ui.geom.hull=function(t){function e(t){if(t.length<3)return[];var e,a=Ct(n),o=Ct(r),i=t.length,l=[],s=[];for(e=0;e=0;--e)h.push(t[l[c[e]][2]]);for(e=+f;e=r&&c.x<=o&&c.y>=a&&c.y<=i?[[r,i],[o,i],[o,a],[r,a]]:[];u.point=t[l]}),e}function n(t){return t.map(function(t,e){return{x:Math.round(o(t,e)/ji)*ji,y:Math.round(i(t,e)/ji)*ji,i:e}})}var r=On,a=Pn,o=r,i=a,l=fs;return t?e(t):(e.links=function(t){return cr(n(t)).edges.filter(function(t){return t.l&&t.r}).map(function(e){return{source:t[e.l.i],target:t[e.r.i]}})},e.triangles=function(t){var e=[];return cr(n(t)).cells.forEach(function(n,r){for(var a,o,i=n.site,l=n.edges.sort(Yn),s=-1,c=l.length,u=l[c-1].edge,f=u.l===i?u.r:u.l;++s=c,d=r>=u,h=d<<1|f;t.leaf=!1,t=t.nodes[h]||(t.nodes[h]=pr()),f?a=c:l=c,d?i=u:s=u,o(t,e,n,r,a,i,l,s)}var u,f,d,h,p,g,m,v,y,x=Ct(l),b=Ct(s);if(null!=e)g=e,m=n,v=r,y=a;else if(v=y=-(g=m=1/0),f=[],d=[],p=t.length,i)for(h=0;hv&&(v=u.x),u.y>y&&(y=u.y),f.push(u.x),d.push(u.y);else for(h=0;hv&&(v=_),w>y&&(y=w),f.push(_),d.push(w)}var M=v-g,k=y-m;M>k?y=m+M:v=g+k;var A=pr();if(A.add=function(t){o(A,t,+x(t,++h),+b(t,h),g,m,v,y)},A.visit=function(t){gr(t,A,g,m,v,y)},A.find=function(t){return mr(A,t[0],t[1],g,m,v,y)},h=-1,null==e){for(;++h=0?t.slice(0,e):t,r=e>=0?t.slice(e+1):"in";return n=gs.get(n)||ps,r=ms.get(r)||b,Mr(r(n.apply(null,fi.call(arguments,1))))},ui.interpolateHcl=Rr,ui.interpolateHsl=jr,ui.interpolateLab=Ir,ui.interpolateRound=Fr,ui.transform=function(t){var e=hi.createElementNS(ui.ns.prefix.svg,"g");return(ui.transform=function(t){if(null!=t){e.setAttribute("transform",t);var n=e.transform.baseVal.consolidate()}return new Br(n?n.matrix:vs)})(t)},Br.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var vs={a:1,b:0,c:0,d:1,e:0,f:0};ui.interpolateTransform=Wr,ui.layout={},ui.layout.bundle=function(){return function(t){for(var e=[],n=-1,r=t.length;++n0?a=t:(n.c=null,n.t=NaN,n=null,c.end({type:"end",alpha:a=0})):t>0&&(c.start({type:"start",alpha:a=t}),n=Et(s.tick)),s):a},s.start=function(){function t(t,r){if(!n){for(n=new Array(a),s=0;s=0;)i.push(u=c[s]),u.parent=o,u.depth=o.depth+1;r&&(o.value=0),o.children=c}else r&&(o.value=+r.call(t,o,o.depth)||0),delete o.children;return sa(a,function(t){var n,a;e&&(n=t.children)&&n.sort(e),r&&(a=t.parent)&&(a.value+=t.value)}),l}var e=fa,n=ca,r=ua;return t.sort=function(n){return arguments.length?(e=n,t):e},t.children=function(e){return arguments.length?(n=e,t):n},t.value=function(e){return arguments.length?(r=e,t):r},t.revalue=function(e){return r&&(la(e,function(t){t.children&&(t.value=0)}),sa(e,function(e){var n;e.children||(e.value=+r.call(t,e,e.depth)||0),(n=e.parent)&&(n.value+=e.value)})),e},t},ui.layout.partition=function(){function t(e,n,r,a){var o=e.children;if(e.x=n,e.y=e.depth*a,e.dx=r,e.dy=a,o&&(i=o.length)){var i,l,s,c=-1;for(r=e.value?r/e.value:0;++cl&&(l=r),i.push(r)}for(n=0;n0)for(o=-1;++o=u[0]&&l<=u[1]&&(i=s[ui.bisect(f,l,1,h)-1],i.y+=p,i.push(t[o]));return s}var e=!0,n=Number,r=Ma,a=_a;return t.value=function(e){return arguments.length?(n=e,t):n},t.range=function(e){return arguments.length?(r=Ct(e),t):r},t.bins=function(e){return arguments.length?(a="number"==typeof e?function(t){return wa(t,e)}:Ct(e),t):a},t.frequency=function(n){return arguments.length?(e=!!n,t):e},t},ui.layout.pack=function(){function t(t,o){var i=n.call(this,t,o),l=i[0],s=a[0],c=a[1],u=null==e?Math.sqrt:"function"==typeof e?e:function(){return e};if(l.x=l.y=0,sa(l,function(t){t.r=+u(t.value)}),sa(l,Ca),r){var f=r*(e?1:Math.max(2*l.r/s,2*l.r/c))/2;sa(l,function(t){t.r+=f}),sa(l,Ca),sa(l,function(t){t.r-=f})}return Oa(l,s/2,c/2,e?1:1/Math.max(2*l.r/s,2*l.r/c)),i}var e,n=ui.layout.hierarchy().sort(ka),r=0,a=[1,1];return t.size=function(e){return arguments.length?(a=e,t):a},t.radius=function(n){return arguments.length?(e=null==n||"function"==typeof n?n:+n,t):e},t.padding=function(e){return arguments.length?(r=+e,t):r},ia(t,n)},ui.layout.tree=function(){function t(t,a){var u=i.call(this,t,a),f=u[0],d=e(f);if(sa(d,n),d.parent.m=-d.z,la(d,r),c)la(f,o);else{var h=f,p=f,g=f;la(f,function(t){t.xp.x&&(p=t),t.depth>g.depth&&(g=t)});var m=l(h,p)/2-h.x,v=s[0]/(p.x+l(p,h)/2+m),y=s[1]/(g.depth||1);la(f,function(t){t.x=(t.x+m)*v,t.y=t.depth*y})}return u}function e(t){for(var e,n={A:null,children:[t]},r=[n];null!=(e=r.pop());)for(var a,o=e.children,i=0,l=o.length;i0&&(Ra(Ia(i,t,n),t,r),c+=r,u+=r),f+=i.m,c+=a.m,d+=s.m,u+=o.m;i&&!Da(o)&&(o.t=i,o.m+=f-u),a&&!Na(s)&&(s.t=a,s.m+=c-d,n=t)}return n}function o(t){t.x*=s[0],t.y=t.depth*s[1]}var i=ui.layout.hierarchy().sort(null).value(null),l=Ea,s=[1,1],c=null;return t.separation=function(e){return arguments.length?(l=e,t):l},t.size=function(e){return arguments.length?(c=null==(s=e)?o:null,t):c?null:s},t.nodeSize=function(e){return arguments.length?(c=null==(s=e)?null:o,t):c?s:null},ia(t,i)},ui.layout.cluster=function(){function t(t,o){var i,l=e.call(this,t,o),s=l[0],c=0;sa(s,function(t){var e=t.children;e&&e.length?(t.x=Ba(e),t.y=Fa(e)):(t.x=i?c+=n(t,i):0,t.y=0,i=t)});var u=qa(s),f=Ha(s),d=u.x-n(u,f)/2,h=f.x+n(f,u)/2;return sa(s,a?function(t){t.x=(t.x-s.x)*r[0],t.y=(s.y-t.y)*r[1]}:function(t){t.x=(t.x-d)/(h-d)*r[0],t.y=(1-(s.y?t.y/s.y:1))*r[1]}),l}var e=ui.layout.hierarchy().sort(null).value(null),n=Ea,r=[1,1],a=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(e){return arguments.length?(a=null==(r=e),t):a?null:r},t.nodeSize=function(e){return arguments.length?(a=null!=(r=e),t):a?r:null},ia(t,e)},ui.layout.treemap=function(){function t(t,e){for(var n,r,a=-1,o=t.length;++a0;)u.push(i=d[s-1]),u.area+=i.area,"squarify"!==h||(l=r(u,g))<=p?(d.pop(),p=l):(u.area-=u.pop().area,a(u,g,c,!1),g=Math.min(c.dx,c.dy),u.length=u.area=0,p=1/0);u.length&&(a(u,g,c,!0),u.length=u.area=0),o.forEach(e)}}function n(e){var r=e.children;if(r&&r.length){var o,i=f(e),l=r.slice(),s=[];for(t(l,i.dx*i.dy/e.value),s.area=0;o=l.pop();)s.push(o),s.area+=o.area,null!=o.z&&(a(s,o.z?i.dx:i.dy,i,!l.length),s.length=s.area=0);r.forEach(n)}}function r(t,e){for(var n,r=t.area,a=0,o=1/0,i=-1,l=t.length;++ia&&(a=n));return r*=r,e*=e,r?Math.max(e*a*p/r,r/(e*o*p)):1/0}function a(t,e,n,r){var a,o=-1,i=t.length,l=n.x,c=n.y,u=e?s(t.area/e):0;if(e==n.dx){for((r||u>n.dy)&&(u=n.dy);++on.dx)&&(u=n.dx);++o1);return t+e*n*Math.sqrt(-2*Math.log(a)/a)}},logNormal:function(){var t=ui.random.normal.apply(ui,arguments);return function(){return Math.exp(t())}},bates:function(t){var e=ui.random.irwinHall(t);return function(){return e()/t}},irwinHall:function(t){return function(){for(var e=0,n=0;nf?0:1;if(c=qi)return e(c,h)+(t?e(t,1-h):"")+"Z";var p,g,m,v,y,x,b,_,w,M,k,A,T=0,L=0,C=[];if((v=(+s.apply(this,arguments)||0)/2)&&(m=o===Ps?Math.sqrt(t*t+c*c):+o.apply(this,arguments),h||(L*=-1),c&&(L=rt(m/c*Math.sin(v))),t&&(T=rt(m/t*Math.sin(v)))),c){y=c*Math.cos(u+L),x=c*Math.sin(u+L),b=c*Math.cos(f-L),_=c*Math.sin(f-L);var z=Math.abs(f-u-2*L)<=Fi?0:1;if(L&&bo(y,x,b,_)===h^z){var S=(u+f)/2;y=c*Math.cos(S),x=c*Math.sin(S),b=_=null}}else y=x=0;if(t){w=t*Math.cos(f-T),M=t*Math.sin(f-T),k=t*Math.cos(u+T),A=t*Math.sin(u+T);var O=Math.abs(u-f+2*T)<=Fi?0:1;if(T&&bo(w,M,k,A)===1-h^O){var P=(u+f)/2;w=t*Math.cos(P),M=t*Math.sin(P),k=A=null}}else w=M=0;if(d>ji&&(p=Math.min(Math.abs(c-t)/2,+a.apply(this,arguments)))>.001){g=tFi)+",1 "+e}function a(t,e,n,r){return"Q 0,0 "+r}var o=_n,i=wn,l=Uo,s=vo,c=yo;return t.radius=function(e){return arguments.length?(l=Ct(e),t):l},t.source=function(e){return arguments.length?(o=Ct(e),t):o},t.target=function(e){return arguments.length?(i=Ct(e),t):i},t.startAngle=function(e){return arguments.length?(s=Ct(e),t):s},t.endAngle=function(e){return arguments.length?(c=Ct(e),t):c},t},ui.svg.diagonal=function(){function t(t,a){var o=e.call(this,t,a),i=n.call(this,t,a),l=(o.y+i.y)/2,s=[o,{x:o.x,y:l},{x:i.x,y:l},i];return s=s.map(r),"M"+s[0]+"C"+s[1]+" "+s[2]+" "+s[3]}var e=_n,n=wn,r=Xo;return t.source=function(n){return arguments.length?(e=Ct(n),t):e},t.target=function(e){return arguments.length?(n=Ct(e),t):n},t.projection=function(e){return arguments.length?(r=e,t):r},t},ui.svg.diagonal.radial=function(){var t=ui.svg.diagonal(),e=Xo,n=t.projection;return t.projection=function(t){return arguments.length?n(Yo(e=t)):e},t},ui.svg.symbol=function(){function t(t,r){return(js.get(e.call(this,t,r))||Qo)(n.call(this,t,r))}var e=Wo,n=Zo;return t.type=function(n){return arguments.length?(e=Ct(n),t):e},t.size=function(e){return arguments.length?(n=Ct(e),t):n},t};var js=ui.map({circle:Qo,cross:function(t){var e=Math.sqrt(t/5)/2;return"M"+-3*e+","+-e+"H"+-e+"V"+-3*e+"H"+e+"V"+-e+"H"+3*e+"V"+e+"H"+e+"V"+3*e+"H"+-e+"V"+e+"H"+-3*e+"Z"},diamond:function(t){var e=Math.sqrt(t/(2*Fs)),n=e*Fs;return"M0,"+-e+"L"+n+",0 0,"+e+" "+-n+",0Z"},square:function(t){var e=Math.sqrt(t)/2;return"M"+-e+","+-e+"L"+e+","+-e+" "+e+","+e+" "+-e+","+e+"Z"},"triangle-down":function(t){var e=Math.sqrt(t/Is),n=e*Is/2;return"M0,"+n+"L"+e+","+-n+" "+-e+","+-n+"Z"},"triangle-up":function(t){var e=Math.sqrt(t/Is),n=e*Is/2;return"M0,"+-n+"L"+e+","+n+" "+-e+","+n+"Z"}});ui.svg.symbolTypes=js.keys();var Is=Math.sqrt(3),Fs=Math.tan(30*Vi);zi.transition=function(t){for(var e,n,r=Bs||++Gs,a=ei(t),o=[],i=qs||{time:Date.now(),ease:Cr,delay:0,duration:250},l=-1,s=this.length;++lrect,.s>rect").attr("width",f[1]-f[0])}function a(t){t.select(".extent").attr("y",d[0]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",d[1]-d[0])}function o(){function o(){32==ui.event.keyCode&&(z||(x=null,O[0]-=f[1],O[1]-=d[1],z=2),T())}function g(){32==ui.event.keyCode&&2==z&&(O[0]+=f[1],O[1]+=d[1],z=0,T())}function m(){var t=ui.mouse(_),r=!1;b&&(t[0]+=b[0],t[1]+=b[1]),z||(ui.event.altKey?(x||(x=[(f[0]+f[1])/2,(d[0]+d[1])/2]),O[0]=f[+(t[0]0&&this._events[t].length>n&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace())),this},r.prototype.on=r.prototype.addListener,r.prototype.once=function(t,e){function n(){this.removeListener(t,n),r||(r=!0,e.apply(this,arguments))}if(!a(e))throw TypeError("listener must be a function");var r=!1;return n.listener=e,this.on(t,n),this},r.prototype.removeListener=function(t,e){var n,r,o,l;if(!a(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(n=this._events[t],o=n.length,r=-1,n===e||a(n.listener)&&n.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(i(n)){for(l=o;l-- >0;)if(n[l]===e||n[l].listener&&n[l].listener===e){r=l;break}if(r<0)return this;1===n.length?(n.length=0,delete this._events[t]):n.splice(r,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},r.prototype.removeAllListeners=function(t){var e,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(n=this._events[t],a(n))this.removeListener(t,n);else if(n)for(;n.length;)this.removeListener(t,n[n.length-1]);return delete this._events[t],this},r.prototype.listeners=function(t){var e;return e=this._events&&this._events[t]?a(this._events[t])?[this._events[t]]:this._events[t].slice():[]},r.prototype.listenerCount=function(t){if(this._events){var e=this._events[t];if(a(e))return 1;if(e)return e.length}return 0},r.listenerCount=function(t,e){return t.listenerCount(e)}},{}],13:[function(t,e,n){"use strict";function r(t){for(var e,n=t.length,r=0;r13)&&32!==e&&133!==e&&160!==e&&5760!==e&&6158!==e&&(e<8192||e>8205)&&8232!==e&&8233!==e&&8239!==e&&8287!==e&&8288!==e&&12288!==e&&65279!==e)return!1;return!0}e.exports=function(t){var e=typeof t;if("string"===e){var n=t;if(t=+t,0===t&&r(n))return!1}else if("number"!==e)return!1;return t-t<1}},{}],14:[function(t,e,n){function r(t,e){var n=e[0],r=e[1],a=e[2],o=e[3],i=n+n,l=r+r,s=a+a,c=n*i,u=r*i,f=r*l,d=a*i,h=a*l,p=a*s,g=o*i,m=o*l,v=o*s;return t[0]=1-f-p,t[1]=u+v,t[2]=d-m,t[3]=0,t[4]=u-v,t[5]=1-c-p,t[6]=h+g,t[7]=0,t[8]=d+m,t[9]=h-g,t[10]=1-c-f,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}e.exports=r},{}],15:[function(t,e,n){function r(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function o(t){if(f===setTimeout)return setTimeout(t,0);if((f===r||!f)&&setTimeout)return f=setTimeout,setTimeout(t,0);try{return f(t,0)}catch(e){try{return f.call(null,t,0)}catch(e){return f.call(this,t,0)}}}function i(t){if(d===clearTimeout)return clearTimeout(t);if((d===a||!d)&&clearTimeout)return d=clearTimeout,clearTimeout(t);try{return d(t)}catch(e){try{return d.call(null,t)}catch(e){return d.call(this,t)}}}function l(){m&&p&&(m=!1,p.length?g=p.concat(g):v=-1,g.length&&s())}function s(){if(!m){var t=o(l);m=!0;for(var e=g.length;e;){for(p=g,g=[];++v1)for(var n=1;n.5?s/(2-o-i):s/(o+i),o){case t:r=(e-n)/s+(e1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+(e-t)*(2/3-n)*6:t}var a,o,i;if(t=C(t,360),e=C(e,100),n=C(n,100),0===e)a=o=i=n;else{var l=n<.5?n*(1+e):n+e-n*e,s=2*n-l;a=r(s,l,t+1/3),o=r(s,l,t),i=r(s,l,t-1/3)}return{r:255*a,g:255*o,b:255*i}}function s(t,e,n){t=C(t,255),e=C(e,255),n=C(n,255);var r,a,o=U(t,e,n),i=G(t,e,n),l=o,s=o-i;if(a=0===o?0:s/o,o==i)r=0;else{switch(o){case t:r=(e-n)/s+(e>1)+720)%360;--e;)a.h=(a.h+o)%360,i.push(r(a));return i}function A(t,e){e=e||6;for(var n=r(t).toHsv(),a=n.h,o=n.s,i=n.v,l=[],s=1/e;e--;)l.push(r({h:a,s:o,v:i})),i=(i+s)%1;return l}function T(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[t[n]]=n);return e}function L(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function C(t,n){O(t)&&(t="100%");var r=P(t);return t=G(n,U(0,parseFloat(t))),r&&(t=parseInt(t*n,10)/100),e.abs(t-n)<1e-6?1:t%n/parseFloat(n)}function z(t){return G(1,U(0,t))}function S(t){return parseInt(t,16)}function O(t){return"string"==typeof t&&t.indexOf(".")!=-1&&1===parseFloat(t)}function P(t){return"string"==typeof t&&t.indexOf("%")!=-1}function E(t){return 1==t.length?"0"+t:""+t}function N(t){return t<=1&&(t=100*t+"%"),t}function D(t){return e.round(255*parseFloat(t)).toString(16)}function R(t){return S(t)/255}function j(t){return!!W.CSS_UNIT.exec(t)}function I(t){t=t.replace(B,"").replace(q,"").toLowerCase();var e=!1;if(Y[t])t=Y[t],e=!0;else if("transparent"==t)return{r:0,g:0,b:0,a:0,format:"name"};var n;return(n=W.rgb.exec(t))?{r:n[1],g:n[2],b:n[3]}:(n=W.rgba.exec(t))?{r:n[1],g:n[2],b:n[3],a:n[4]}:(n=W.hsl.exec(t))?{h:n[1],s:n[2],l:n[3]}:(n=W.hsla.exec(t))?{h:n[1],s:n[2],l:n[3],a:n[4]}:(n=W.hsv.exec(t))?{h:n[1],s:n[2],v:n[3]}:(n=W.hsva.exec(t))?{h:n[1],s:n[2],v:n[3],a:n[4]}:(n=W.hex8.exec(t))?{r:S(n[1]),g:S(n[2]),b:S(n[3]),a:R(n[4]),format:e?"name":"hex8"}:(n=W.hex6.exec(t))?{r:S(n[1]),g:S(n[2]),b:S(n[3]),format:e?"name":"hex"}:(n=W.hex4.exec(t))?{r:S(n[1]+""+n[1]),g:S(n[2]+""+n[2]),b:S(n[3]+""+n[3]),a:R(n[4]+""+n[4]),format:e?"name":"hex8"}:!!(n=W.hex3.exec(t))&&{r:S(n[1]+""+n[1]),g:S(n[2]+""+n[2]),b:S(n[3]+""+n[3]),format:e?"name":"hex"}}function F(t){var e,n;return t=t||{level:"AA",size:"small"},e=(t.level||"AA").toUpperCase(),n=(t.size||"small").toLowerCase(),"AA"!==e&&"AAA"!==e&&(e="AA"),"small"!==n&&"large"!==n&&(n="small"),{level:e,size:n}}var B=/^\s+/,q=/\s+$/,H=0,V=e.round,G=e.min,U=e.max,X=e.random;r.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var t,n,r,a,o,i,l=this.toRgb();return t=l.r/255,n=l.g/255,r=l.b/255,a=t<=.03928?t/12.92:e.pow((t+.055)/1.055,2.4),o=n<=.03928?n/12.92:e.pow((n+.055)/1.055,2.4),i=r<=.03928?r/12.92:e.pow((r+.055)/1.055,2.4),.2126*a+.7152*o+.0722*i},setAlpha:function(t){return this._a=L(t),this._roundA=V(100*this._a)/100,this},toHsv:function(){var t=s(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=s(this._r,this._g,this._b),e=V(360*t.h),n=V(100*t.s),r=V(100*t.v);return 1==this._a?"hsv("+e+", "+n+"%, "+r+"%)":"hsva("+e+", "+n+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var t=i(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=i(this._r,this._g,this._b),e=V(360*t.h),n=V(100*t.s),r=V(100*t.l);return 1==this._a?"hsl("+e+", "+n+"%, "+r+"%)":"hsla("+e+", "+n+"%, "+r+"%, "+this._roundA+")"},toHex:function(t){return u(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return f(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:V(this._r),g:V(this._g),b:V(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+V(this._r)+", "+V(this._g)+", "+V(this._b)+")":"rgba("+V(this._r)+", "+V(this._g)+", "+V(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:V(100*C(this._r,255))+"%",g:V(100*C(this._g,255))+"%",b:V(100*C(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+V(100*C(this._r,255))+"%, "+V(100*C(this._g,255))+"%, "+V(100*C(this._b,255))+"%)":"rgba("+V(100*C(this._r,255))+"%, "+V(100*C(this._g,255))+"%, "+V(100*C(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(Z[u(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var e="#"+d(this._r,this._g,this._b,this._a),n=e,a=this._gradientType?"GradientType = 1, ":"";if(t){var o=r(t);n="#"+d(o._r,o._g,o._b,o._a)}return"progid:DXImageTransform.Microsoft.gradient("+a+"startColorstr="+e+",endColorstr="+n+")"},toString:function(t){var e=!!t;t=t||this._format;var n=!1,r=this._a<1&&this._a>=0,a=!e&&r&&("hex"===t||"hex6"===t||"hex3"===t||"hex4"===t||"hex8"===t||"name"===t);return a?"name"===t&&0===this._a?this.toName():this.toRgbString():("rgb"===t&&(n=this.toRgbString()),"prgb"===t&&(n=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(n=this.toHexString()),"hex3"===t&&(n=this.toHexString(!0)),"hex4"===t&&(n=this.toHex8String(!0)),"hex8"===t&&(n=this.toHex8String()),"name"===t&&(n=this.toName()),"hsl"===t&&(n=this.toHslString()),"hsv"===t&&(n=this.toHsvString()),n||this.toHexString())},clone:function(){return r(this.toString())},_applyModification:function(t,e){var n=t.apply(null,[this].concat([].slice.call(e)));return this._r=n._r,this._g=n._g,this._b=n._b,this.setAlpha(n._a),this},lighten:function(){return this._applyModification(m,arguments)},brighten:function(){return this._applyModification(v,arguments)},darken:function(){return this._applyModification(y,arguments)},desaturate:function(){return this._applyModification(h,arguments)},saturate:function(){return this._applyModification(p,arguments); +},greyscale:function(){return this._applyModification(g,arguments)},spin:function(){return this._applyModification(x,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(k,arguments)},complement:function(){return this._applyCombination(b,arguments)},monochromatic:function(){return this._applyCombination(A,arguments)},splitcomplement:function(){return this._applyCombination(M,arguments)},triad:function(){return this._applyCombination(_,arguments)},tetrad:function(){return this._applyCombination(w,arguments)}},r.fromRatio=function(t,e){if("object"==typeof t){var n={};for(var a in t)t.hasOwnProperty(a)&&("a"===a?n[a]=t[a]:n[a]=N(t[a]));t=n}return r(t,e)},r.equals=function(t,e){return!(!t||!e)&&r(t).toRgbString()==r(e).toRgbString()},r.random=function(){return r.fromRatio({r:X(),g:X(),b:X()})},r.mix=function(t,e,n){n=0===n?0:n||50;var a=r(t).toRgb(),o=r(e).toRgb(),i=n/100,l={r:(o.r-a.r)*i+a.r,g:(o.g-a.g)*i+a.g,b:(o.b-a.b)*i+a.b,a:(o.a-a.a)*i+a.a};return r(l)},r.readability=function(t,n){var a=r(t),o=r(n);return(e.max(a.getLuminance(),o.getLuminance())+.05)/(e.min(a.getLuminance(),o.getLuminance())+.05)},r.isReadable=function(t,e,n){var a,o,i=r.readability(t,e);switch(o=!1,a=F(n),a.level+a.size){case"AAsmall":case"AAAlarge":o=i>=4.5;break;case"AAlarge":o=i>=3;break;case"AAAsmall":o=i>=7}return o},r.mostReadable=function(t,e,n){var a,o,i,l,s=null,c=0;n=n||{},o=n.includeFallbackColors,i=n.level,l=n.size;for(var u=0;uc&&(c=a,s=r(e[u]));return r.isReadable(t,s,{level:i,size:l})||!o?s:(n.includeFallbackColors=!1,r.mostReadable(t,["#fff","#000"],n))};var Y=r.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},Z=r.hexNames=T(Y),W=function(){var t="[-\\+]?\\d+%?",e="[-\\+]?\\d*\\.\\d+%?",n="(?:"+e+")|(?:"+t+")",r="[\\s|\\(]+("+n+")[,|\\s]+("+n+")[,|\\s]+("+n+")\\s*\\)?",a="[\\s|\\(]+("+n+")[,|\\s]+("+n+")[,|\\s]+("+n+")[,|\\s]+("+n+")\\s*\\)?";return{CSS_UNIT:new RegExp(n),rgb:new RegExp("rgb"+r),rgba:new RegExp("rgba"+a),hsl:new RegExp("hsl"+r),hsla:new RegExp("hsla"+a),hsv:new RegExp("hsv"+r),hsva:new RegExp("hsva"+a),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof n&&n.exports?n.exports=r:"function"==typeof t&&t.amd?t(function(){return r}):window.tinycolor=r}(Math)},{}],17:[function(e,n,r){!function(e,a){"object"==typeof r&&"undefined"!=typeof n?a(r):"function"==typeof t&&t.amd?t(["exports"],a):a(e.topojson=e.topojson||{})}(this,function(t){"use strict";function e(t,e){var r=e.id,a=e.bbox,o=null==e.properties?{}:e.properties,i=n(t,e);return null==r&&null==a?{type:"Feature",properties:o,geometry:i}:null==a?{type:"Feature",id:r,properties:o,geometry:i}:{type:"Feature",id:r,bbox:a,properties:o,geometry:i}}function n(t,e){function n(t,e){e.length&&e.pop();for(var n=f[t<0?~t:t],r=0,a=n.length;r1)r=a(t,e,n);else for(o=0,r=new Array(i=t.arcs.length);o1)for(var a,o,s=1,c=i(r[0]);sc&&(o=r[0],r[0]=r[s],r[s]=o,c=a);return r})}}var l=function(t){return t},s=function(t){if(null==(e=t.transform))return l;var e,n,r,a=e.scale[0],o=e.scale[1],i=e.translate[0],s=e.translate[1];return function(t,e){return e||(n=r=0),t[0]=(n+=t[0])*a+i,t[1]=(r+=t[1])*o+s,t}},c=function(t){function e(t){l[0]=t[0],l[1]=t[1],i(l),l[0]f&&(f=l[0]),l[1]d&&(d=l[1])}function n(t){switch(t.type){case"GeometryCollection":t.geometries.forEach(n);break;case"Point":e(t.coordinates);break;case"MultiPoint":t.coordinates.forEach(e)}}var r=t.bbox;if(!r){var a,o,i=s(t),l=new Array(2),c=1/0,u=c,f=-c,d=-c;t.arcs.forEach(function(t){for(var e=-1,n=t.length;++ef&&(f=l[0]),l[1]d&&(d=l[1])});for(o in t.objects)n(t.objects[o]);r=t.bbox=[c,u,f,d]}return r},u=function(t,e){for(var n,r=t.length,a=r-e;a<--r;)n=t[a],t[a++]=t[r],t[r]=n},f=function(t,n){return"GeometryCollection"===n.type?{type:"FeatureCollection",features:n.geometries.map(function(n){return e(t,n)})}:e(t,n)},d=function(t,e){function n(e){var n,r=t.arcs[e<0?~e:e],a=r[0];return t.transform?(n=[0,0],r.forEach(function(t){n[0]+=t[0],n[1]+=t[1]})):n=r[r.length-1],e<0?[n,a]:[a,n]}function r(t,e){for(var n in t){var r=t[n];delete e[r.start],delete r.start,delete r.end,r.forEach(function(t){a[t<0?~t:t]=1}),l.push(r)}}var a={},o={},i={},l=[],s=-1;return e.forEach(function(n,r){var a,o=t.arcs[n<0?~n:n];o.length<3&&!o[1][0]&&!o[1][1]&&(a=e[++s],e[s]=n,e[r]=a)}),e.forEach(function(t){var e,r,a=n(t),l=a[0],s=a[1];if(e=i[l])if(delete i[e.end],e.push(t),e.end=s,r=o[s]){delete o[r.start];var c=r===e?e:e.concat(r);o[c.start=e.start]=i[c.end=r.end]=c}else o[e.start]=i[e.end]=e;else if(e=o[s])if(delete o[e.start],e.unshift(t),e.start=l,r=i[l]){delete i[r.end];var u=r===e?e:r.concat(e);o[u.start=r.start]=i[u.end=e.end]=u}else o[e.start]=i[e.end]=e;else e=[t],o[e.start=l]=i[e.end=s]=e}),r(i,o),r(o,i),e.forEach(function(t){a[t<0?~t:t]||l.push([t])}),l},h=function(t){return n(t,r.apply(this,arguments))},p=function(t){return n(t,i.apply(this,arguments))},g=function(t,e){for(var n=0,r=t.length;n>>1;t[a]=2))throw new Error("n must be \u22652");if(t.transform)throw new Error("already quantized");var a,o=c(t),i=o[0],l=(o[2]-i)/(e-1)||1,s=o[1],u=(o[3]-s)/(e-1)||1;t.arcs.forEach(function(t){for(var e,n,r,a=1,o=1,c=t.length,f=t[0],d=f[0]=Math.round((f[0]-i)/l),h=f[1]=Math.round((f[1]-s)/u);a2/3?"right":"center"),{center:0,middle:0,left:.5,bottom:-.5,right:-.5,top:.5}[e]}rt.selectAll("tspan.line").attr({y:0,x:0});var r=$.select(".annotation-math-group"),a=!r.empty(),l=h.bBox((a?r:rt).node()),c=l.width,p=l.height,v=Math.round(c+2*tt),y=Math.round(p+2*tt);G._w=c,G._h=p;var b=!1;if(["x","y"].forEach(function(e){var r,a=G[e+"ref"]||e,o=f.getFromId(t,a),i=(Z+("x"===e?0:90))*Math.PI/180,l=v*Math.abs(Math.cos(i))+y*Math.abs(Math.sin(i)),s=G[e+"anchor"];if(o){var c=o.r2fraction(G[e]);if(!o.autorange&&(c<0||c>1)&&(G["a"+e+"ref"]===a?(c=o.r2fraction(G["a"+e]),(c<0||c>1)&&(b=!0)):b=!0,b))return;Y[e]=o._offset+o.r2p(G[e]),r=.5}else r=G[e],"y"===e&&(r=1-r),Y[e]="x"===e?O.l+O.w*r:O.t+O.h*r;var u=0;G["a"+e+"ref"]===a?Y["aa"+e]=o._offset+o.r2p(G["a"+e]):(u=G.showarrow?G["a"+e]:l*n(r,s),Y[e]+=u),G["_"+e+"type"]=o&&o.type,G["_"+e+"size"]=l,G["_"+e+"shift"]=u}),b)return void $.remove();var _,w;G.showarrow&&(_=G.axref===G.xref?Y.x:u.constrain(Y.x-G.ax,1,k.width-1),w=G.ayref===G.yref?Y.y:u.constrain(Y.y-G.ay,1,k.height-1)),Y.x=u.constrain(Y.x,1,k.width-1),Y.y=u.constrain(Y.y,1,k.height-1);var M=tt-l.top,A=tt-l.left;a?r.select("svg").attr({x:tt-1,y:tt}):(rt.attr({x:A,y:M}),rt.selectAll("tspan.line").attr({y:M,x:A})),et.call(h.setRect,J/2,J/2,v-J,y-J);var T=0,L=0;T=G.axref===G.xref?Math.round(Y.aax-v/2):Math.round(Y.x-v/2),L=G.ayref===G.yref?Math.round(Y.aay-y/2):Math.round(Y.y-y/2),$.call(u.setTranslate,T,L);var C="annotations["+e+"]",z=function(n,r){i.select(t).selectAll('.annotation-arrow-g[data-index="'+e+'"]').remove();var a,l;a=G.axref===G.xref?Y.aax+n:Y.x+n,l=G.ayref===G.yref?Y.aay+r:Y.y+r;var c=u.rotationXYMatrix(Z,a,l),f=u.apply2DTransform(c),h=u.apply2DTransform2(c),p=et.attr("width")/2,g=et.attr("height")/2,v=[[a-p,l-g,a-p,l+g],[a-p,l+g,a+p,l+g],[a+p,l+g,a+p,l-g],[a+p,l-g,a-p,l-g]].map(h);if(!v.reduce(function(t,e){return t^!!o(_,w,_+1e6,w+1e6,e[0],e[1],e[2],e[3])},!1)){v.forEach(function(t){var e=o(a,l,_,w,t[0],t[1],t[2],t[3]);e&&(a=e.x,l=e.y)});var y=G.arrowwidth,b=G.arrowcolor,M=W.append("g").style({opacity:d.opacity(b)}).classed("annotation-arrow-g",!0).attr("data-index",String(e)),k=M.append("path").attr("d","M"+a+","+l+"L"+_+","+w).style("stroke-width",y+"px").call(d.stroke,d.rgb(b));x(k,G.arrowhead,"end",G.arrowsize);var A=M.append("path").classed("annotation",!0).classed("anndrag",!0).attr({"data-index":String(e),d:"M3,3H-3V-3H3ZM0,0L"+(a-_)+","+(l-w),transform:"translate("+_+","+w+")"}).style("stroke-width",y+6+"px").call(d.stroke,"rgba(0,0,0,0)").call(d.fill,"rgba(0,0,0,0)");if(t._context.editable){var T,L,z;m.init({element:A.node(),prepFn:function(){var t=u.getTranslate($);L=t.x,z=t.y,T={},U&&U.autorange&&(T[U._name+".autorange"]=!0),X&&X.autorange&&(T[X._name+".autorange"]=!0)},moveFn:function(t,e){M.attr("transform","translate("+t+","+e+")");var n=f(L,z),r=n[0]+t,a=n[1]+e;$.call(u.setTranslate,r,a),T[C+".x"]=U?U.p2r(U.r2p(G.x)+t):(_+t-O.l)/O.w,T[C+".y"]=X?X.p2r(X.r2p(G.y)+e):1-(w+e-O.t)/O.h,G.axref===G.xref&&(T[C+".ax"]=U?U.p2r(U.r2p(G.ax)+t):(_+t-O.l)/O.w),G.ayref===G.yref&&(T[C+".ay"]=X?X.p2r(X.r2p(G.ay)+e):1-(w+e-O.t)/O.h),Q.attr({transform:"rotate("+Z+","+r+","+a+")"})},doneFn:function(e){if(e){s.relayout(t,T);var n=document.querySelector(".js-notes-box-panel");n&&n.redraw(n.selectedObj)}}})}}};G.showarrow&&z(0,0);var S=u.rotationXYMatrix(Z,Y.x,Y.y),P=u.apply2DTransform(S);if(t._context.editable){var E,N,D;m.init({element:$.node(),prepFn:function(){var t=u.getTranslate($);E=t.x,N=t.y,D={}},moveFn:function(t,e){$.call(u.setTranslate,E+t,N+e);var n="pointer";if(G.showarrow)G.axref===G.xref?D[C+".ax"]=U.p2r(U.r2p(G.ax)+t):D[C+".ax"]=G.ax+t,G.ayref===G.yref?D[C+".ay"]=X.p2r(X.r2p(G.ay)+e):D[C+".ay"]=G.ay+e,z(t,e);else{if(U)D[C+".x"]=G.x+t/U._m;else{var r=G._xsize/O.w,a=G.x+G._xshift/O.w-r/2;D[C+".x"]=m.align(a+t/O.w,r,0,1,G.xanchor)}if(X)D[C+".y"]=G.y+e/X._m;else{var o=G._ysize/O.h,i=G.y-G._yshift/O.h-o/2;D[C+".y"]=m.align(i-e/O.h,o,0,1,G.yanchor)}U&&X||(n=m.getCursor(U?.5:D[C+".x"],X?.5:D[C+".y"],G.xanchor,G.yanchor))}var l=P(E,N),s=l[0]+t,c=l[1]+e;$.call(u.setTranslate,E+t,N+e),Q.attr({transform:"rotate("+Z+","+s+","+c+")"}),g($,n)},doneFn:function(e){if(g($),e){s.relayout(t,D);var n=document.querySelector(".js-notes-box-panel");n&&n.redraw(n.selectedObj)}}})}}var w,M=t.layout,k=t._fullLayout;if(!l(e)||e===-1){if(!e&&Array.isArray(c))return M.annotations=c,y(M,k),void r(t);if("remove"===c)return delete M.annotations,k.annotations=[],void r(t);if(n&&"add"!==c){for(w=0;we;w--)k._infolayer.selectAll('.annotation[data-index="'+(w-1)+'"]').attr("data-index",String(w)),a(t,w)}}k._infolayer.selectAll('.annotation[data-index="'+e+'"]').remove();var T=M.annotations[e],L=k.annotations[e];if(T){var C={};"string"==typeof n&&n?C[n]=c:u.isPlainObject(n)&&(C=n);var z=Object.keys(C);for(w=0;w4/3&&(j=H)}}else R&&(F&&(j<1/3?j+=q:j>2/3&&(j-=q)),j=(j-R.domain[0])/(R.domain[1]-R.domain[0]),j=R.fraction2r(j))}R&&R===D&&I&&("log"===I&&"log"!==R.type?j=Math.pow(10,j):"log"!==I&&"log"===R.type&&(j=j>0?Math.log(j)/Math.LN10:void 0)),T[N]=j}}var G={};v(T,G,k),k.annotations[e]=G;var U=f.getFromId(t,G.xref),X=f.getFromId(t,G.yref),Y={x:0,y:0},Z=+G.textangle||0,W=k._infolayer.append("g").classed("annotation",!0).attr("data-index",String(e)).style("opacity",G.opacity).on("click",function(){t._dragging=!1,t.emit("plotly_clickannotation",{index:e,annotation:T,fullAnnotation:G})});G.classes&&W.classed(G.classes,!0);var Q=W.append("g").classed("annotation-text-g",!0).attr("data-index",String(e)),$=Q.append("g"),J=G.borderwidth,K=G.borderpad,tt=J+K,et=$.append("rect").attr("class","bg").style("stroke-width",J+"px").call(d.stroke,G.bordercolor).call(d.fill,G.bgcolor),nt=G.font,rt=$.append("text").classed("annotation",!0).attr("data-unformatted",G.text).text(G.text);t._context.editable?rt.call(p.makeEditable,$).call(b).on("edit",function(n){G.text=n,this.attr({"data-unformatted":G.text}),this.call(b);var r={};r["annotations["+e+"].text"]=G.text,U&&U.autorange&&(r[U._name+".autorange"]=!0),X&&X.autorange&&(r[X._name+".autorange"]=!0),s.relayout(t,r)}):rt.call(b),Q.attr({transform:"rotate("+Z+","+Y.x+","+Y.y+")"}).call(h.setPosition,Y.x,Y.y)}}}function o(t,e,n,r,a,o,i,l){var s=n-t,c=a-t,u=i-a,f=r-e,d=o-e,h=l-o,p=s*h-u*f;if(0===p)return null;var g=(c*h-u*d)/p,m=(c*f-s*d)/p;return m<0||m>1||g<0||g>1?null:{x:t+s*g,y:e+f*g}}var i=t("d3"),l=t("fast-isnumeric"),s=t("../../plotly"),c=t("../../plots/plots"),u=t("../../lib"),f=t("../../plots/cartesian/axes"),d=t("../color"),h=t("../drawing"),p=t("../../lib/svg_text_utils"),g=t("../../lib/setcursor"),m=t("../dragelement"),v=t("./annotation_defaults"),y=t("./defaults"),x=t("./draw_arrow_head");e.exports={draw:r,drawOne:a}},{"../../lib":122,"../../lib/setcursor":132,"../../lib/svg_text_utils":134,"../../plotly":145,"../../plots/cartesian/axes":150,"../../plots/plots":186,"../color":27,"../dragelement":48,"../drawing":50,"./annotation_defaults":18,"./defaults":22,"./draw_arrow_head":24,d3:10,"fast-isnumeric":13}],24:[function(t,e,n){"use strict";var r=t("d3"),a=t("fast-isnumeric"),o=t("../color"),i=t("../drawing"),l=t("./arrow_paths");e.exports=function(t,e,n,s){a(s)||(s=1);var c=t.node(),u=l[e||0];if(u){"string"==typeof n&&n||(n="end");var f,d,h,p,g=(i.getPx(t,"stroke-width")||1)*s,m=t.style("stroke")||o.defaultLine,v=t.style("stroke-opacity")||1,y=n.indexOf("start")>=0,x=n.indexOf("end")>=0,b=u.backoff*g;if("line"===c.nodeName){if(f={x:+t.attr("x1"),y:+t.attr("y1")},d={x:+t.attr("x2"),y:+t.attr("y2")},h=Math.atan2(f.y-d.y,f.x-d.x),p=h+Math.PI,b){var _=b*Math.cos(h),w=b*Math.sin(h);y&&(f.x-=_,f.y-=w,t.attr({x1:f.x,y1:f.y})),x&&(d.x+=_,d.y+=w,t.attr({x2:d.x,y2:d.y}))}}else if("path"===c.nodeName){var M=c.getTotalLength(),k="";if(y){var A=c.getPointAtLength(0),T=c.getPointAtLength(.1);h=Math.atan2(A.y-T.y,A.x-T.x),f=c.getPointAtLength(Math.min(b,M)),b&&(k="0px,"+b+"px,")}if(x){var L=c.getPointAtLength(M),C=c.getPointAtLength(M-.1);if(p=Math.atan2(L.y-C.y,L.x-C.x),d=c.getPointAtLength(Math.max(0,M-b)),b){var z=k?2*b:b;k+=M-z+"px,"+M+"px"}}else k&&(k+=M+"px");k&&t.style("stroke-dasharray",k)}var S=function(n,a){e>5&&(a=0),r.select(c.parentElement).append("path").attr({class:t.attr("class"),d:u.path,transform:"translate("+n.x+","+n.y+")rotate("+180*a/Math.PI+")scale("+g+")"}).style({fill:m,opacity:v,"stroke-width":0})};y&&S(f,h),x&&S(d,p)}}},{"../color":27,"../drawing":50,"./arrow_paths":19,d3:10,"fast-isnumeric":13}],25:[function(t,e,n){"use strict";var r=t("./draw");e.exports={moduleType:"component",name:"annotations",layoutAttributes:t("./attributes"),supplyLayoutDefaults:t("./defaults"),calcAutorange:t("./calc_autorange"),draw:r.draw,drawOne:r.drawOne}},{"./attributes":20,"./calc_autorange":21,"./defaults":22,"./draw":23}],26:[function(t,e,n){"use strict";n.defaults=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],n.defaultLine="#444",n.lightLine="#eee",n.background="#fff",n.borderLine="#BEC8D9",n.lightFraction=1e3/11},{}],27:[function(t,e,n){"use strict";function r(t){if(o(t)||"string"!=typeof t)return t;var e=t.trim();if("rgb"!==e.substr(0,3))return t;var n=e.match(/^rgba?\s*\(([^()]*)\)$/);if(!n)return t;var r=n[1].trim().split(/\s*[\s,]\s*/),a="a"===e.charAt(3)&&4===r.length;if(!a&&3!==r.length)return t;for(var i=0;i=0))return t;if(3===i)r[i]>1&&(r[i]=1);else if(r[i]>=1)return t}var l=Math.round(255*r[0])+", "+Math.round(255*r[1])+", "+Math.round(255*r[2]);return a?"rgba("+l+", "+r[3]+")":"rgb("+l+")"}var a=t("tinycolor2"),o=t("fast-isnumeric"),i=e.exports={},l=t("./attributes");i.defaults=l.defaults,i.defaultLine=l.defaultLine,i.lightLine=l.lightLine,i.background=l.background,i.overrideColorDefaults=function(t){return"undefined"==typeof t?i.defaults:void(i.defaults=t)},i.tinyRGB=function(t){var e=t.toRgb();return"rgb("+Math.round(e.r)+", "+Math.round(e.g)+", "+Math.round(e.b)+")"},i.rgb=function(t){return i.tinyRGB(a(t))},i.opacity=function(t){return t?a(t).getAlpha():0},i.addOpacity=function(t,e){var n=a(t).toRgb();return"rgba("+Math.round(n.r)+", "+Math.round(n.g)+", "+Math.round(n.b)+", "+e+")"},i.combine=function(t,e){var n=a(t).toRgb();if(1===n.a)return a(t).toRgbString();var r=a(e||i.background).toRgb(),o=1===r.a?r:{r:255*(1-r.a)+r.r*r.a,g:255*(1-r.a)+r.g*r.a,b:255*(1-r.a)+r.b*r.a},l={r:o.r*(1-n.a)+n.r*n.a,g:o.g*(1-n.a)+n.g*n.a,b:o.b*(1-n.a)+n.b*n.a};return a(l).toRgbString()},i.contrast=function(t,e,n){var r=a(t),o=r.isLight()?r.darken(n):r.lighten(e);return o.toString()},i.stroke=function(t,e){var n=a(e);t.style({stroke:i.tinyRGB(n),"stroke-opacity":n.getAlpha()})},i.fill=function(t,e){var n=a(e);t.style({fill:i.tinyRGB(n),"fill-opacity":n.getAlpha()})},i.clean=function(t){if(t&&"object"==typeof t){var e,n,a,o,l=Object.keys(t);for(e=0;el&&(o[1]-=(lt-l)/2)):n.node()&&!n.classed("js-placeholder")&&(lt=h.bBox(e.node()).height),lt){if(lt+=5,"top"===_.titleside)K.domain[1]-=lt/T.h,o[1]*=-1;else{K.domain[0]+=lt/T.h;var c=Math.max(1,n.selectAll("tspan.line").size());o[1]+=(1-c)*l}e.attr("transform","translate("+o+")"),K.setScale()}}ot.selectAll(".cbfills,.cblines,.cbaxis").attr("transform","translate(0,"+Math.round(T.h*(1-K.domain[1]))+")");var f=ot.select(".cbfills").selectAll("rect.cbfill").data(S);f.enter().append("rect").classed("cbfill",!0).style("stroke","none"),f.exit().remove(),f.each(function(t,e){var n=[0===e?C[0]:(S[e]+S[e-1])/2,e===S.length-1?C[1]:(S[e]+S[e+1])/2].map(K.c2p).map(Math.round);e!==S.length-1&&(n[1]+=n[1]>n[0]?1:-1);var o=P(t).replace("e-",""),i=a(o).toHexString();r.select(this).attr({x:Y,width:Math.max(B,2),y:r.min(n),height:Math.max(r.max(n)-r.min(n),2),fill:i})});var d=ot.select(".cblines").selectAll("path.cbline").data(_.line.color&&_.line.width?z:[]);return d.enter().append("path").classed("cbline",!0),d.exit().remove(),d.each(function(t){r.select(this).attr("d","M"+Y+","+(Math.round(K.c2p(t))+_.line.width/2%1)+"h"+B).call(h.lineGroupStyle,_.line.width,O(t),_.line.dash)}),K._axislayer.selectAll("g."+K._id+"tick,path").remove(),K._pos=Y+B+(_.outlinewidth||0)/2-("outside"===_.ticks?1:0),K.side="right",u.syncOrAsync([function(){return s.doTicks(t,K,!0)},function(){if(["top","bottom"].indexOf(_.titleside)===-1){var e=K.titlefont.size,n=K._offset+K._length/2,a=T.l+(K.position||0)*T.w+("right"===K.side?10+e*(K.showticklabels?1:.5):-10-e*(K.showticklabels?.5:0));M("h"+K._id+"title",{avoid:{selection:r.select(t).selectAll("g."+K._id+"tick"),side:_.titleside,offsetLeft:T.l,offsetTop:T.t,maxShift:A.width},attributes:{x:a,y:n,"text-anchor":"middle"},transform:{rotate:"-90",offset:0}})}}])}function M(e,n){var r,a=b();r=l.traceIs(a,"markerColorscale")?"marker.colorbar.title":"colorbar.title";var o={propContainer:K,propName:r,traceIndex:a.index,dfltName:"colorscale",containerGroup:ot.select(".cbtitle")},i="h"===e.charAt(0)?e.substr(1):"h"+e;ot.selectAll("."+i+",."+i+"-math-group").remove(),g.draw(t,e,f(o,n||{}))}function k(){var n=B+_.outlinewidth/2+h.bBox(K._axislayer.node()).width;if(j=it.select("text"),j.node()&&!j.classed("js-placeholder")){var r,a=it.select(".h"+K._id+"title-math-group").node();r=a&&["top","bottom"].indexOf(_.titleside)!==-1?h.bBox(a).width:h.bBox(it.node()).right-Y-T.l,n=Math.max(n,r)}var o=2*_.xpad+n+_.borderwidth+_.outlinewidth/2,l=Q-$;ot.select(".cbbg").attr({x:Y-_.xpad-(_.borderwidth+_.outlinewidth)/2,y:$-U,width:Math.max(o,2),height:Math.max(l+2*U,2)}).call(p.fill,_.bgcolor).call(p.stroke,_.bordercolor).style({"stroke-width":_.borderwidth}),ot.selectAll(".cboutline").attr({x:Y,y:$+_.ypad+("top"===_.titleside?lt:0),width:Math.max(B,2),height:Math.max(l-2*_.ypad-lt,2)}).call(p.stroke,_.outlinecolor).style({fill:"None","stroke-width":_.outlinewidth});var s=({center:.5,right:1}[_.xanchor]||0)*o;ot.attr("transform","translate("+(T.l-s)+","+T.t+")"),i.autoMargin(t,e,{x:_.x,y:_.y,l:o*({right:1,center:.5}[_.xanchor]||0),r:o*({left:1,center:.5}[_.xanchor]||0),t:l*({bottom:1,middle:.5}[_.yanchor]||0),b:l*({top:1,middle:.5}[_.yanchor]||0)})}var A=t._fullLayout,T=A._size;if("function"!=typeof _.fillcolor&&"function"!=typeof _.line.color)return void A._infolayer.selectAll("g."+e).remove();var L,C=r.extent(("function"==typeof _.fillcolor?_.fillcolor:_.line.color).domain()),z=[],S=[],O="function"==typeof _.line.color?_.line.color:function(){return _.line.color},P="function"==typeof _.fillcolor?_.fillcolor:function(){return _.fillcolor},E=_.levels.end+_.levels.size/100,N=_.levels.size,D=1.001*C[0]-.001*C[1],R=1.001*C[1]-.001*C[0];for(L=_.levels.start;(L-E)*N<0;L+=N)L>D&&LC[0]&&L1){var at=Math.pow(10,Math.floor(Math.log(rt)/Math.LN10));et*=at*u.roundUp(rt/at,[2,5,10]),(Math.abs(_.levels.start)/_.levels.size+1e-6)%1<2e-6&&(K.tick0=0)}K.dtick=et}K.domain=[W+X,W+V-X],K.setScale();var ot=A._infolayer.selectAll("g."+e).data([0]);ot.enter().append("g").classed(e,!0).each(function(){var t=r.select(this);t.append("rect").classed("cbbg",!0),t.append("g").classed("cbfills",!0),t.append("g").classed("cblines",!0),t.append("g").classed("cbaxis",!0).classed("crisp",!0),t.append("g").classed("cbtitleunshift",!0).append("g").classed("cbtitle",!0),t.append("rect").classed("cboutline",!0),t.select(".cbtitle").datum(0)}),ot.attr("transform","translate("+Math.round(T.l)+","+Math.round(T.t)+")");var it=ot.select(".cbtitleunshift").attr("transform","translate(-"+Math.round(T.l)+",-"+Math.round(T.t)+")");K._axislayer=ot.select(".cbaxis");var lt=0;if(["top","bottom"].indexOf(_.titleside)!==-1){var st,ct=T.l+(_.x+G)*T.w,ut=K.titlefont.size;st="top"===_.titleside?(1-(W+V-X))*T.h+T.t+3+.75*ut:(1-(W+X))*T.h+T.t-3-.25*ut,M(K._id+"title",{attributes:{x:ct,y:st,"text-anchor":"start"}})}var ft=u.syncOrAsync([i.previousPromises,w,i.previousPromises,k],t);if(ft&&ft.then&&(t._promises||[]).push(ft),t._context.editable){var dt,ht,pt;c.init({element:ot.node(),prepFn:function(){dt=ot.attr("transform"),d(ot)},moveFn:function(t,e){ot.attr("transform",dt+" translate("+t+","+e+")"),ht=c.align(Z+t/T.w,q,0,1,_.xanchor),pt=c.align(W-e/T.h,V,0,1,_.yanchor);var n=c.getCursor(ht,pt,_.xanchor,_.yanchor);d(ot,n)},doneFn:function(e){d(ot),e&&void 0!==ht&&void 0!==pt&&o.restyle(t,{"colorbar.x":ht,"colorbar.y":pt},b().index)}})}return ft}function b(){var n,r,a=e.substr(2);for(n=0;n=0?a.Reds:a.Blues,s.colorscale=d,l.reversescale&&(d=o(d)),l.colorscale=d)}},{"../../lib":122,"./flip_scale":38,"./scales":45}],34:[function(t,e,n){"use strict";var r=t("./attributes"),a=t("../../lib/extend").extendDeep;t("./scales.js");e.exports=function(t){return{color:{valType:"color",arrayOk:!0},colorscale:a({},r.colorscale,{}),cauto:a({},r.zauto,{}),cmax:a({},r.zmax,{}),cmin:a({},r.zmin,{}),autocolorscale:a({},r.autocolorscale,{}),reversescale:a({},r.reversescale,{})}}},{"../../lib/extend":117,"./attributes":32,"./scales.js":45}],35:[function(t,e,n){"use strict";var r=t("./scales");e.exports=r.RdBu},{"./scales":45}],36:[function(t,e,n){"use strict";var r=t("fast-isnumeric"),a=t("../../lib"),o=t("../colorbar/has_colorbar"),i=t("../colorbar/defaults"),l=t("./is_valid_scale"),s=t("./flip_scale");e.exports=function(t,e,n,c,u){var f=u.prefix,d=u.cLetter,h=f.slice(0,f.length-1),p=f?a.nestedProperty(t,h).get()||{}:t,g=f?a.nestedProperty(e,h).get()||{}:e,m=p[d+"min"],v=p[d+"max"],y=p.colorscale,x=r(m)&&r(v)&&m=0;a--,o++)e=t[a],r[o]=[1-e[0],e[1]];return r}},{}],39:[function(t,e,n){"use strict";var r=t("./scales"),a=t("./default_scale"),o=t("./is_valid_scale_array");e.exports=function(t,e){function n(){try{t=r[t]||JSON.parse(t)}catch(n){t=e}}return e||(e=a),t?("string"==typeof t&&(n(),"string"==typeof t&&n()),o(t)?t:e):e}},{"./default_scale":35,"./is_valid_scale_array":43,"./scales":45}],40:[function(t,e,n){"use strict";var r=t("fast-isnumeric"),a=t("../../lib"),o=t("./is_valid_scale");e.exports=function(t,e){var n=e?a.nestedProperty(t,e).get()||{}:t,i=n.color,l=!1;if(Array.isArray(i))for(var s=0;s4/3-l?i:l}},{}],47:[function(t,e,n){"use strict";var r=t("../../lib"),a=[["sw-resize","s-resize","se-resize"],["w-resize","move","e-resize"],["nw-resize","n-resize","ne-resize"]];e.exports=function(t,e,n,o){return t="left"===n?0:"center"===n?1:"right"===n?2:r.constrain(Math.floor(3*t),0,2),e="bottom"===o?0:"middle"===o?1:"top"===o?2:r.constrain(Math.floor(3*e),0,2),a[e][t]}},{"../../lib":122}],48:[function(t,e,n){"use strict";function r(){var t=document.createElement("div");t.className="dragcover";var e=t.style;return e.position="fixed",e.left=0,e.right=0,e.top=0,e.bottom=0,e.zIndex=999999999,e.background="none",document.body.appendChild(t),t}function a(t){t._dragging=!1,t._replotPending&&o.plot(t)}var o=t("../../plotly"),i=t("../../lib"),l=t("../../plots/cartesian/constants"),s=e.exports={};s.align=t("./align"),s.getCursor=t("./cursor");var c=t("./unhover");s.unhover=c.wrapped,s.unhoverRaw=c.raw,s.init=function(t){function e(e){return t.element.onmousemove=p,g._dragged=!1,g._dragging=!0,c=e.clientX,u=e.clientY,h=e.target,f=(new Date).getTime(),f-g._mouseDownTimev&&(m=Math.max(m-1,1)),t.doneFn&&t.doneFn(g._dragged,m),!g._dragged){var n=document.createEvent("MouseEvents");n.initMouseEvent("click",e.bubbles,e.cancelable,e.view,0,0,0,0,0,!1,!1,!1,!1,e.button,null),h.dispatchEvent(n)}return a(g),g._dragged=!1,i.pauseEvent(e)}var c,u,f,d,h,p,g=i.getPlotDiv(t.element)||{},m=1,v=l.DBLCLICKDELAY;g._mouseDownTime||(g._mouseDownTime=0),p=t.element.onmousemove,t.setCursor&&(t.element.onmousemove=t.setCursor),t.element.onmousedown=e,t.element.style.pointerEvents="all"},s.coverSlip=r},{"../../lib":122,"../../plotly":145,"../../plots/cartesian/constants":155,"./align":46,"./cursor":47,"./unhover":49}],49:[function(t,e,n){"use strict";var r=t("../../lib/events"),a=e.exports={};a.wrapped=function(t,e,n){"string"==typeof t&&(t=document.getElementById(t)),t._hoverTimer&&(clearTimeout(t._hoverTimer),t._hoverTimer=void 0),a.raw(t,e,n)},a.raw=function(t,e){var n=t._fullLayout;e||(e={}),e.target&&r.triggerHandler(t,"plotly_beforehover",e)===!1||(n._hoverlayer.selectAll("g").remove(),e.target&&t._hoverdata&&t.emit("plotly_unhover",{points:t._hoverdata}),t._hoverdata=void 0)}},{"../../lib/events":116}],50:[function(t,e,n){"use strict";function r(t,e,n,r,a,o,i){if(l.traceIs(n,"symbols")){var c=p(n);e.attr("d",function(t){var e;e="various"===t.ms||"various"===o.size?3:h.isBubble(n)?c(t.ms):(o.size||6)/2,t.mrc=e;var r=g.symbolNumber(t.mx||o.symbol)||0,a=r%100;return t.om=r%200>=100,g.symbolFuncs[a](e)+(r>=200?y:"")}).style("opacity",function(t){return(t.mo+1||o.opacity+1)-1})}var u,f,d;t.so?(d=i.outlierwidth,f=i.outliercolor,u=o.outliercolor):(d=(t.mlw+1||i.width+1||(t.trace?t.trace.marker.line.width:0)+1)-1,f="mlc"in t?t.mlcc=a(t.mlc):Array.isArray(i.color)?s.defaultLine:i.color,u="mc"in t?t.mcc=r(t.mc):Array.isArray(o.color)?s.defaultLine:o.color||"rgba(0,0,0,0)"),t.om?e.call(s.stroke,u).style({"stroke-width":(d||1)+"px",fill:"none"}):(e.style("stroke-width",d+"px").call(s.fill,u),d&&e.call(s.stroke,f))}function a(t,e,n,r){var a=t[0]-e[0],i=t[1]-e[1],l=n[0]-e[0],s=n[1]-e[1],c=Math.pow(a*a+i*i,_/2),u=Math.pow(l*l+s*s,_/2),f=(u*u*a-c*c*l)*r,d=(u*u*i-c*c*s)*r,h=3*u*(c+u),p=3*c*(c+u);return[[o.round(e[0]+(h&&f/h),2),o.round(e[1]+(h&&d/h),2)],[o.round(e[0]-(p&&f/p),2),o.round(e[1]-(p&&d/p),2)]]}var o=t("d3"),i=t("fast-isnumeric"),l=t("../../registry"),s=t("../color"),c=t("../colorscale"),u=t("../../lib"),f=t("../../lib/svg_text_utils"),d=t("../../constants/xmlns_namespaces"),h=t("../../traces/scatter/subtypes"),p=t("../../traces/scatter/make_bubble_size_func"),g=e.exports={};g.font=function(t,e,n,r){e&&e.family&&(r=e.color,n=e.size,e=e.family),e&&t.style("font-family",e),n+1&&t.style("font-size",n+"px"),r&&t.call(s.fill,r)},g.setPosition=function(t,e,n){t.attr("x",e).attr("y",n)},g.setSize=function(t,e,n){t.attr("width",e).attr("height",n)},g.setRect=function(t,e,n,r,a){t.call(g.setPosition,e,n).call(g.setSize,r,a)},g.translatePoint=function(t,e,n,r){var a=t.xp||n.c2p(t.x),o=t.yp||r.c2p(t.y);i(a)&&i(o)?"text"===e.node().nodeName?e.attr("x",a).attr("y",o):e.attr("transform","translate("+a+","+o+")"):e.remove()},g.translatePoints=function(t,e,n,r){t.each(function(t){var a=o.select(this);g.translatePoint(t,a,e,n,r)})},g.getPx=function(t,e){return Number(t.style(e).replace(/px$/,""))},g.crispRound=function(t,e,n){return e&&i(e)?t._context.staticPlot?e:e<1?1:Math.round(e):n||0},g.singleLineStyle=function(t,e,n,r,a){e.style("fill","none");var o=(((t||[])[0]||{}).trace||{}).line||{},i=n||o.width||0,l=a||o.dash||"";s.stroke(e,r||o.color),g.dashLine(e,l,i)},g.lineGroupStyle=function(t,e,n,r){t.style("fill","none").each(function(t){var a=(((t||[])[0]||{}).trace||{}).line||{},i=e||a.width||0,l=r||a.dash||"";o.select(this).call(s.stroke,n||a.color).call(g.dashLine,l,i)})},g.dashLine=function(t,e,n){var r=Math.max(n,3);"solid"===e?e="":"dot"===e?e=r+"px,"+r+"px":"dash"===e?e=3*r+"px,"+3*r+"px":"longdash"===e?e=5*r+"px,"+5*r+"px":"dashdot"===e?e=3*r+"px,"+r+"px,"+r+"px,"+r+"px":"longdashdot"===e&&(e=5*r+"px,"+2*r+"px,"+r+"px,"+2*r+"px"),t.style({"stroke-dasharray":e,"stroke-width":n+"px"})},g.fillGroupStyle=function(t){t.style("stroke-width",0).each(function(e){var n=o.select(this);try{n.call(s.fill,e[0].trace.fillcolor)}catch(e){u.error(e,t),n.remove()}})};var m=t("./symbol_defs");g.symbolNames=[],g.symbolFuncs=[],g.symbolNeedLines={},g.symbolNoDot={},g.symbolList=[],Object.keys(m).forEach(function(t){var e=m[t];g.symbolList=g.symbolList.concat([e.n,t,e.n+100,t+"-open"]),g.symbolNames[e.n]=t,g.symbolFuncs[e.n]=e.f,e.needLine&&(g.symbolNeedLines[e.n]=!0),e.noDot?g.symbolNoDot[e.n]=!0:g.symbolList=g.symbolList.concat([e.n+200,t+"-dot",e.n+300,t+"-open-dot"])});var v=g.symbolNames.length,y="M0,0.5L0.5,0L0,-0.5L-0.5,0Z";g.symbolNumber=function(t){if("string"==typeof t){var e=0;t.indexOf("-open")>0&&(e=100,t=t.replace("-open","")),t.indexOf("-dot")>0&&(e+=200,t=t.replace("-dot","")),t=g.symbolNames.indexOf(t),t>=0&&(t+=e)}return t%100>=v||t>=400?0:Math.floor(Math.max(t,0))},g.singlePointStyle=function(t,e,n){var a=n.marker,o=a.line,i=g.tryColorscale(a,""),l=g.tryColorscale(a,"line");r(t,e,n,i,l,a,o)},g.pointStyle=function(t,e){if(t.size()){var n=e.marker,r=g.tryColorscale(n,""),a=g.tryColorscale(n,"line");t.each(function(t){g.singlePointStyle(t,o.select(this),e,r,a)})}},g.tryColorscale=function(t,e){var n=e?u.nestedProperty(t,e).get():t,r=n.colorscale,a=n.color;return r&&Array.isArray(a)?c.makeColorScaleFunc(c.extractScale(r,n.cmin,n.cmax)):u.identity};var x={start:1,end:-1,middle:0,bottom:1,top:-1},b=1.3;g.textPointStyle=function(t,e){t.each(function(t){var n=o.select(this),r=t.tx||e.text;if(!r||Array.isArray(r))return void n.remove();var a=t.tp||e.textposition,l=a.indexOf("top")!==-1?"top":a.indexOf("bottom")!==-1?"bottom":"middle",s=a.indexOf("left")!==-1?"end":a.indexOf("right")!==-1?"start":"middle",c=t.ts||e.textfont.size,u=t.mrc?t.mrc/.8+1:0;c=i(c)&&c>0?c:0,n.call(g.font,t.tf||e.textfont.family,c,t.tc||e.textfont.color).attr("text-anchor",s).text(r).call(f.convertToTspans);var d=o.select(this.parentNode),h=n.selectAll("tspan.line"),p=((h[0].length||1)-1)*b+1,m=x[s]*u,v=.75*c+x[l]*u+(x[l]-1)*p*c/2;d.attr("transform","translate("+m+","+v+")"),p>1&&h.attr({x:n.attr("x"),y:n.attr("y")})})};var _=.5;g.smoothopen=function(t,e){if(t.length<3)return"M"+t.join("L");var n,r="M"+t[0],o=[];for(n=1;n=A&&(o.selectAll("[data-bb]").attr("data-bb",null),k=[]),t.setAttribute("data-bb",k.length),k.push(s),u.extendFlat({},s)},g.setClipUrl=function(t,e){if(!e)return void t.attr("clip-path",null);var n="#"+e,r=o.select("base");r.size()&&r.attr("href")&&(n=window.location.href+n),t.attr("clip-path","url("+n+")")}},{"../../constants/xmlns_namespaces":109,"../../lib":122,"../../lib/svg_text_utils":134,"../../registry":194,"../../traces/scatter/make_bubble_size_func":249,"../../traces/scatter/subtypes":254,"../color":27,"../colorscale":41,"./symbol_defs":51,d3:10,"fast-isnumeric":13}],51:[function(t,e,n){"use strict";var r=t("d3");e.exports={circle:{n:0,f:function(t){var e=r.round(t,2);return"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"}},square:{n:1,f:function(t){var e=r.round(t,2);return"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"}},diamond:{n:2,f:function(t){var e=r.round(1.3*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"Z"}},cross:{n:3,f:function(t){var e=r.round(.4*t,2),n=r.round(1.2*t,2);return"M"+n+","+e+"H"+e+"V"+n+"H-"+e+"V"+e+"H-"+n+"V-"+e+"H-"+e+"V-"+n+"H"+e+"V-"+e+"H"+n+"Z"}},x:{n:4,f:function(t){var e=r.round(.8*t/Math.sqrt(2),2),n="l"+e+","+e,a="l"+e+",-"+e,o="l-"+e+",-"+e,i="l-"+e+","+e;return"M0,"+e+n+a+o+a+o+i+o+i+n+i+n+"Z"}},"triangle-up":{n:5,f:function(t){var e=r.round(2*t/Math.sqrt(3),2),n=r.round(t/2,2),a=r.round(t,2);return"M-"+e+","+n+"H"+e+"L0,-"+a+"Z"}},"triangle-down":{n:6,f:function(t){var e=r.round(2*t/Math.sqrt(3),2),n=r.round(t/2,2),a=r.round(t,2);return"M-"+e+",-"+n+"H"+e+"L0,"+a+"Z"}},"triangle-left":{n:7,f:function(t){var e=r.round(2*t/Math.sqrt(3),2),n=r.round(t/2,2),a=r.round(t,2);return"M"+n+",-"+e+"V"+e+"L-"+a+",0Z"}},"triangle-right":{n:8,f:function(t){var e=r.round(2*t/Math.sqrt(3),2),n=r.round(t/2,2),a=r.round(t,2);return"M-"+n+",-"+e+"V"+e+"L"+a+",0Z"}},"triangle-ne":{n:9,f:function(t){var e=r.round(.6*t,2),n=r.round(1.2*t,2);return"M-"+n+",-"+e+"H"+e+"V"+n+"Z"}},"triangle-se":{n:10,f:function(t){var e=r.round(.6*t,2),n=r.round(1.2*t,2);return"M"+e+",-"+n+"V"+e+"H-"+n+"Z"}},"triangle-sw":{n:11,f:function(t){var e=r.round(.6*t,2),n=r.round(1.2*t,2);return"M"+n+","+e+"H-"+e+"V-"+n+"Z"}},"triangle-nw":{n:12,f:function(t){var e=r.round(.6*t,2),n=r.round(1.2*t,2);return"M-"+e+","+n+"V-"+e+"H"+n+"Z"}},pentagon:{n:13,f:function(t){var e=r.round(.951*t,2),n=r.round(.588*t,2),a=r.round(-t,2),o=r.round(t*-.309,2),i=r.round(.809*t,2);return"M"+e+","+o+"L"+n+","+i+"H-"+n+"L-"+e+","+o+"L0,"+a+"Z"}},hexagon:{n:14,f:function(t){var e=r.round(t,2),n=r.round(t/2,2),a=r.round(t*Math.sqrt(3)/2,2);return"M"+a+",-"+n+"V"+n+"L0,"+e+"L-"+a+","+n+"V-"+n+"L0,-"+e+"Z"}},hexagon2:{n:15,f:function(t){var e=r.round(t,2),n=r.round(t/2,2),a=r.round(t*Math.sqrt(3)/2,2);return"M-"+n+","+a+"H"+n+"L"+e+",0L"+n+",-"+a+"H-"+n+"L-"+e+",0Z"}},octagon:{n:16,f:function(t){var e=r.round(.924*t,2),n=r.round(.383*t,2);return"M-"+n+",-"+e+"H"+n+"L"+e+",-"+n+"V"+n+"L"+n+","+e+"H-"+n+"L-"+e+","+n+"V-"+n+"Z"}},star:{n:17,f:function(t){var e=1.4*t,n=r.round(.225*e,2),a=r.round(.951*e,2),o=r.round(.363*e,2),i=r.round(.588*e,2),l=r.round(-e,2),s=r.round(e*-.309,2),c=r.round(.118*e,2),u=r.round(.809*e,2),f=r.round(.382*e,2);return"M"+n+","+s+"H"+a+"L"+o+","+c+"L"+i+","+u+"L0,"+f+"L-"+i+","+u+"L-"+o+","+c+"L-"+a+","+s+"H-"+n+"L0,"+l+"Z"}},hexagram:{n:18,f:function(t){var e=r.round(.66*t,2),n=r.round(.38*t,2),a=r.round(.76*t,2);return"M-"+a+",0l-"+n+",-"+e+"h"+a+"l"+n+",-"+e+"l"+n+","+e+"h"+a+"l-"+n+","+e+"l"+n+","+e+"h-"+a+"l-"+n+","+e+"l-"+n+",-"+e+"h-"+a+"Z"}},"star-triangle-up":{n:19,f:function(t){var e=r.round(t*Math.sqrt(3)*.8,2),n=r.round(.8*t,2),a=r.round(1.6*t,2),o=r.round(4*t,2),i="A "+o+","+o+" 0 0 1 ";return"M-"+e+","+n+i+e+","+n+i+"0,-"+a+i+"-"+e+","+n+"Z"}},"star-triangle-down":{n:20,f:function(t){var e=r.round(t*Math.sqrt(3)*.8,2),n=r.round(.8*t,2),a=r.round(1.6*t,2),o=r.round(4*t,2),i="A "+o+","+o+" 0 0 1 ";return"M"+e+",-"+n+i+"-"+e+",-"+n+i+"0,"+a+i+e+",-"+n+"Z"}},"star-square":{n:21,f:function(t){var e=r.round(1.1*t,2),n=r.round(2*t,2),a="A "+n+","+n+" 0 0 1 ";return"M-"+e+",-"+e+a+"-"+e+","+e+a+e+","+e+a+e+",-"+e+a+"-"+e+",-"+e+"Z"}},"star-diamond":{n:22,f:function(t){var e=r.round(1.4*t,2),n=r.round(1.9*t,2),a="A "+n+","+n+" 0 0 1 ";return"M-"+e+",0"+a+"0,"+e+a+e+",0"+a+"0,-"+e+a+"-"+e+",0Z"}},"diamond-tall":{n:23,f:function(t){var e=r.round(.7*t,2),n=r.round(1.4*t,2);return"M0,"+n+"L"+e+",0L0,-"+n+"L-"+e+",0Z"}},"diamond-wide":{n:24,f:function(t){var e=r.round(1.4*t,2),n=r.round(.7*t,2);return"M0,"+n+"L"+e+",0L0,-"+n+"L-"+e+",0Z"}},hourglass:{n:25,f:function(t){var e=r.round(t,2);return"M"+e+","+e+"H-"+e+"L"+e+",-"+e+"H-"+e+"Z"},noDot:!0},bowtie:{n:26,f:function(t){var e=r.round(t,2);return"M"+e+","+e+"V-"+e+"L-"+e+","+e+"V-"+e+"Z"; +},noDot:!0},"circle-cross":{n:27,f:function(t){var e=r.round(t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"},needLine:!0,noDot:!0},"circle-x":{n:28,f:function(t){var e=r.round(t,2),n=r.round(t/Math.sqrt(2),2);return"M"+n+","+n+"L-"+n+",-"+n+"M"+n+",-"+n+"L-"+n+","+n+"M"+e+",0A"+e+","+e+" 0 1,1 0,-"+e+"A"+e+","+e+" 0 0,1 "+e+",0Z"},needLine:!0,noDot:!0},"square-cross":{n:29,f:function(t){var e=r.round(t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"},needLine:!0,noDot:!0},"square-x":{n:30,f:function(t){var e=r.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e+"M"+e+",-"+e+"L-"+e+","+e+"M"+e+","+e+"H-"+e+"V-"+e+"H"+e+"Z"},needLine:!0,noDot:!0},"diamond-cross":{n:31,f:function(t){var e=r.round(1.3*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"ZM0,-"+e+"V"+e+"M-"+e+",0H"+e},needLine:!0,noDot:!0},"diamond-x":{n:32,f:function(t){var e=r.round(1.3*t,2),n=r.round(.65*t,2);return"M"+e+",0L0,"+e+"L-"+e+",0L0,-"+e+"ZM-"+n+",-"+n+"L"+n+","+n+"M-"+n+","+n+"L"+n+",-"+n},needLine:!0,noDot:!0},"cross-thin":{n:33,f:function(t){var e=r.round(1.4*t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e},needLine:!0,noDot:!0},"x-thin":{n:34,f:function(t){var e=r.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e+"M"+e+",-"+e+"L-"+e+","+e},needLine:!0,noDot:!0},asterisk:{n:35,f:function(t){var e=r.round(1.2*t,2),n=r.round(.85*t,2);return"M0,"+e+"V-"+e+"M"+e+",0H-"+e+"M"+n+","+n+"L-"+n+",-"+n+"M"+n+",-"+n+"L-"+n+","+n},needLine:!0,noDot:!0},hash:{n:36,f:function(t){var e=r.round(t/2,2),n=r.round(t,2);return"M"+e+","+n+"V-"+n+"m-"+n+",0V"+n+"M"+n+","+e+"H-"+n+"m0,-"+n+"H"+n},needLine:!0},"y-up":{n:37,f:function(t){var e=r.round(1.2*t,2),n=r.round(1.6*t,2),a=r.round(.8*t,2);return"M-"+e+","+a+"L0,0M"+e+","+a+"L0,0M0,-"+n+"L0,0"},needLine:!0,noDot:!0},"y-down":{n:38,f:function(t){var e=r.round(1.2*t,2),n=r.round(1.6*t,2),a=r.round(.8*t,2);return"M-"+e+",-"+a+"L0,0M"+e+",-"+a+"L0,0M0,"+n+"L0,0"},needLine:!0,noDot:!0},"y-left":{n:39,f:function(t){var e=r.round(1.2*t,2),n=r.round(1.6*t,2),a=r.round(.8*t,2);return"M"+a+","+e+"L0,0M"+a+",-"+e+"L0,0M-"+n+",0L0,0"},needLine:!0,noDot:!0},"y-right":{n:40,f:function(t){var e=r.round(1.2*t,2),n=r.round(1.6*t,2),a=r.round(.8*t,2);return"M-"+a+","+e+"L0,0M-"+a+",-"+e+"L0,0M"+n+",0L0,0"},needLine:!0,noDot:!0},"line-ew":{n:41,f:function(t){var e=r.round(1.4*t,2);return"M"+e+",0H-"+e},needLine:!0,noDot:!0},"line-ns":{n:42,f:function(t){var e=r.round(1.4*t,2);return"M0,"+e+"V-"+e},needLine:!0,noDot:!0},"line-ne":{n:43,f:function(t){var e=r.round(t,2);return"M"+e+",-"+e+"L-"+e+","+e},needLine:!0,noDot:!0},"line-nw":{n:44,f:function(t){var e=r.round(t,2);return"M"+e+","+e+"L-"+e+",-"+e},needLine:!0,noDot:!0}}},{d3:10}],52:[function(t,e,n){"use strict";e.exports={visible:{valType:"boolean"},type:{valType:"enumerated",values:["percent","constant","sqrt","data"]},symmetric:{valType:"boolean"},array:{valType:"data_array"},arrayminus:{valType:"data_array"},value:{valType:"number",min:0,dflt:10},valueminus:{valType:"number",min:0,dflt:10},traceref:{valType:"integer",min:0,dflt:0},tracerefminus:{valType:"integer",min:0,dflt:0},copy_ystyle:{valType:"boolean"},copy_zstyle:{valType:"boolean"},color:{valType:"color"},thickness:{valType:"number",min:0,dflt:2},width:{valType:"number",min:0},_deprecated:{opacity:{valType:"number"}}}},{}],53:[function(t,e,n){"use strict";function r(t,e,n,r){var o=e["error_"+r]||{},s=o.visible&&["linear","log"].indexOf(n.type)!==-1,c=[];if(s){for(var u=l(o),f=0;f0;t.each(function(t){var e,f=t[0].trace,d=f.error_x||{},h=f.error_y||{};f.ids&&(e=function(t){return t.id});var p=i.hasMarkers(f)&&f.marker.maxdisplayed>0;if(h.visible||d.visible){var g=a.select(this).selectAll("g.errorbar").data(t,e);g.exit().remove(),g.style("opacity",1);var m=g.enter().append("g").classed("errorbar",!0);u&&m.style("opacity",0).transition().duration(n.duration).style("opacity",1),g.each(function(t){var e=a.select(this),i=r(t,s,c);if(!p||t.vis){var f;if(h.visible&&o(i.x)&&o(i.yh)&&o(i.ys)){var g=h.width;f="M"+(i.x-g)+","+i.yh+"h"+2*g+"m-"+g+",0V"+i.ys,i.noYS||(f+="m-"+g+",0h"+2*g);var m=e.select("path.yerror");l=!m.size(),l?m=e.append("path").classed("yerror",!0):u&&(m=m.transition().duration(n.duration).ease(n.easing)),m.attr("d",f)}if(d.visible&&o(i.y)&&o(i.xh)&&o(i.xs)){var v=(d.copy_ystyle?h:d).width;f="M"+i.xh+","+(i.y-v)+"v"+2*v+"m0,-"+v+"H"+i.xs,i.noXS||(f+="m0,-"+v+"v"+2*v);var y=e.select("path.xerror");l=!y.size(),l?y=e.append("path").classed("xerror",!0):u&&(y=y.transition().duration(n.duration).ease(n.easing)),y.attr("d",f)}}})}})}},{"../../traces/scatter/subtypes":254,d3:10,"fast-isnumeric":13}],58:[function(t,e,n){"use strict";var r=t("d3"),a=t("../color");e.exports=function(t){t.each(function(t){var e=t[0].trace,n=e.error_y||{},o=e.error_x||{},i=r.select(this);i.selectAll("path.yerror").style("stroke-width",n.thickness+"px").call(a.stroke,n.color),o.copy_ystyle&&(o=n),i.selectAll("path.xerror").style("stroke-width",o.thickness+"px").call(a.stroke,o.color)})}},{"../color":27,d3:10}],59:[function(t,e,n){"use strict";var r=t("../../plots/cartesian/constants");e.exports={_isLinkedToArray:"image",visible:{valType:"boolean",dflt:!0},source:{valType:"string"},layer:{valType:"enumerated",values:["below","above"],dflt:"above"},sizex:{valType:"number",dflt:0},sizey:{valType:"number",dflt:0},sizing:{valType:"enumerated",values:["fill","contain","stretch"],dflt:"contain"},opacity:{valType:"number",min:0,max:1,dflt:1},x:{valType:"any",dflt:0},y:{valType:"any",dflt:0},xanchor:{valType:"enumerated",values:["left","center","right"],dflt:"left"},yanchor:{valType:"enumerated",values:["top","middle","bottom"],dflt:"top"},xref:{valType:"enumerated",values:["paper",r.idRegex.x.toString()],dflt:"paper"},yref:{valType:"enumerated",values:["paper",r.idRegex.y.toString()],dflt:"paper"}}},{"../../plots/cartesian/constants":155}],60:[function(t,e,n){"use strict";function r(t,e,n){function r(n,r){return a.coerce(t,e,l,n,r)}var i=r("source"),s=r("visible",!!i);if(!s)return e;r("layer"),r("x"),r("y"),r("xanchor"),r("yanchor"),r("sizex"),r("sizey"),r("sizing"),r("opacity");for(var c={_fullLayout:n},u=["x","y"],f=0;f<2;f++)o.coerceRef(t,e,c,u[f],"paper");return e}var a=t("../../lib"),o=t("../../plots/cartesian/axes"),i=t("../../plots/array_container_defaults"),l=t("./attributes"),s="images";e.exports=function(t,e){var n={name:s,handleItemDefaults:r};i(t,e,n)}},{"../../lib":122,"../../plots/array_container_defaults":147,"../../plots/cartesian/axes":150,"./attributes":59}],61:[function(t,e,n){"use strict";var r=t("d3"),a=t("../drawing"),o=t("../../plots/cartesian/axes"),i=t("../../constants/xmlns_namespaces");e.exports=function(t){function e(e){var n=r.select(this);if(!this.img||this.img.src!==e.source){n.attr("xmlns",i.svg);var a=new Promise(function(t){function r(){n.remove(),t()}var a=new Image;this.img=a,a.setAttribute("crossOrigin","anonymous"),a.onerror=r,a.onload=function(){var t=document.createElement("canvas");t.width=this.width,t.height=this.height;var e=t.getContext("2d");e.drawImage(this,0,0);var r=t.toDataURL("image/png");n.attr("xlink:href",r)},n.on("error",r),n.on("load",t),a.src=e.source}.bind(this));t._promises.push(a)}}function n(e){var n=r.select(this),i=o.getFromId(t,e.xref),s=o.getFromId(t,e.yref),c=l._size,u=i?Math.abs(i.l2p(e.sizex)-i.l2p(0)):e.sizex*c.w,f=s?Math.abs(s.l2p(e.sizey)-s.l2p(0)):e.sizey*c.h,d=u*h.x[e.xanchor].offset,p=f*h.y[e.yanchor].offset,g=h.x[e.xanchor].sizing+h.y[e.yanchor].sizing,m=(i?i.r2p(e.x)+i._offset:e.x*c.w+c.l)+d,v=(s?s.r2p(e.y)+s._offset:c.h-e.y*c.h+c.t)+p;switch(e.sizing){case"fill":g+=" slice";break;case"stretch":g="none"}n.attr({x:m,y:v,width:u,height:f,preserveAspectRatio:g,opacity:e.opacity});var y=i?i._id:"",x=s?s._id:"",b=y+x;b&&n.call(a.setClipUrl,"clip"+l._uid+b)}for(var l=t._fullLayout,s=[],c=[],u=[],f=0;f=2/3},n.isCenterAnchor=function(t){return"center"===t.xanchor||"auto"===t.xanchor&&t.x>1/3&&t.x<2/3},n.isBottomAnchor=function(t){return"bottom"===t.yanchor||"auto"===t.yanchor&&t.y<=1/3},n.isMiddleAnchor=function(t){return"middle"===t.yanchor||"auto"===t.yanchor&&t.y>1/3&&t.y<2/3}},{}],64:[function(t,e,n){"use strict";var r=t("../../plots/font_attributes"),a=t("../color/attributes"),o=t("../../lib/extend").extendFlat;e.exports={bgcolor:{valType:"color"},bordercolor:{valType:"color",dflt:a.defaultLine},borderwidth:{valType:"number",min:0,dflt:0},font:o({},r,{}),orientation:{valType:"enumerated",values:["v","h"],dflt:"v"},traceorder:{valType:"flaglist",flags:["reversed","grouped"],extras:["normal"]},tracegroupgap:{valType:"number",min:0,dflt:10},x:{valType:"number",min:-2,max:3,dflt:1.02},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left"},y:{valType:"number",min:-2,max:3,dflt:1},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"auto"}}},{"../../lib/extend":117,"../../plots/font_attributes":170,"../color/attributes":26}],65:[function(t,e,n){"use strict";e.exports={scrollBarWidth:4,scrollBarHeight:20,scrollBarColor:"#808BA4",scrollBarMargin:4}},{}],66:[function(t,e,n){"use strict";var r=t("../../registry"),a=t("../../lib"),o=t("./attributes"),i=t("../../plots/layout_attributes"),l=t("./helpers");e.exports=function(t,e,n){function s(t,e){return a.coerce(h,p,o,t,e)}for(var c,u,f,d,h=t.legend||{},p=e.legend={},g=0,m="normal",v=0;v1);if(x!==!1){if(s("bgcolor",e.paper_bgcolor),s("bordercolor"),s("borderwidth"),a.coerceFont(s,"font",e.font),s("orientation"),"h"===p.orientation){var b=t.xaxis;b&&b.rangeslider&&b.rangeslider.visible?(c=0,f="left",u=1.1,d="bottom"):(c=0,f="left",u=-.1,d="top")}s("traceorder",m),l.isGrouped(e.legend)&&s("tracegroupgap"),s("x",c),s("xanchor",f),s("y",u),s("yanchor",d),a.noneOrAll(h,p,["x","y"])}}},{"../../lib":122,"../../plots/layout_attributes":184,"../../registry":194,"./attributes":64,"./helpers":69}],67:[function(t,e,n){"use strict";function r(t,e){function n(n){v.convertToTspans(n,function(){n.selectAll("tspan.line").attr({x:n.attr("x")}),t.call(o,e)})}var r=t.data()[0][0],a=e._fullLayout,i=r.trace,l=h.traceIs(i,"pie"),s=i.index,c=l?r.label:i.name,f=t.selectAll("text.legendtext").data([0]);f.enter().append("text").classed("legendtext",!0),f.attr({x:40,y:0,"data-unformatted":c}).style("text-anchor","start").classed("user-select-none",!0).call(g.font,a.legend.font).text(c),e._context.editable&&!l?f.call(v.makeEditable).call(n).on("edit",function(t){this.attr({"data-unformatted":t}),this.text(t).call(n),this.text()||(t=" ");var a,o=r.trace._fullInput||{};if(["ohlc","candlestick"].indexOf(o.type)!==-1){var i=r.trace.transforms,l=i[i.length-1].direction;a=l+".legenditem.name"}else a="name";u.restyle(e,a,t,s)}):f.call(n)}function a(t,e){var n=e._fullLayout.hiddenlabels?e._fullLayout.hiddenlabels.slice():[],r=t.selectAll("rect").data([0]);r.enter().append("rect").classed("legendtoggle",!0).style("cursor","pointer").attr("pointer-events","all").call(m.fill,"rgba(0,0,0,0)"),r.on("click",function(){if(!e._dragged){var r,a,o=t.data()[0][0],i=e._fullData,l=o.trace,s=l.legendgroup,c=[];if(h.traceIs(l,"pie")){var f=o.label,d=n.indexOf(f);d===-1?n.push(f):n.splice(d,1),u.relayout(e,"hiddenlabels",n)}else{if(""===s)c=[l.index];else for(var p=0;ptspan"),d=u[0].length||1;n=l*d,r=c.node()&&g.bBox(c.node()).width;var h=l*(.3+(1-d)/2);c.attr("y",h),u.attr("y",h)}n=Math.max(n,16)+3,a.height=n,a.width=r}function i(t,e,n){var r=t._fullLayout,a=r.legend,o=a.borderwidth,i=_.isGrouped(a);if(_.isVertical(a))i&&e.each(function(t,e){f.setTranslate(this,0,e*a.tracegroupgap)}),a.width=0,a.height=0,n.each(function(t){var e=t[0],n=e.height,r=e.width;f.setTranslate(this,o,5+o+a.height+n/2),a.height+=n,a.width=Math.max(a.width,r)}),a.width+=45+2*o,a.height+=10+2*o,i&&(a.height+=(a._lgroupsLength-1)*a.tracegroupgap),a.width=Math.ceil(a.width),a.height=Math.ceil(a.height),n.each(function(e){var n=e[0],r=c.select(this).select(".legendtoggle");r.call(g.setRect,0,-n.height/2,(t._context.editable?0:a.width)+40,n.height)});else if(i){a.width=0,a.height=0;for(var l=[a.width],s=e.data(),u=0,d=s.length;ur.width-(r.margin.r+r.margin.l)&&(x=0,m+=v,a.height=a.height+v,v=0),f.setTranslate(this,o+x,5+o+e.height/2+m),a.width+=i+n,a.height=Math.max(a.height,e.height),x+=i+n,v=Math.max(e.height,v)}),a.width+=2*o,a.height+=10+2*o,a.width=Math.ceil(a.width),a.height=Math.ceil(a.height),n.each(function(e){var n=e[0],r=c.select(this).select(".legendtoggle");r.call(g.setRect,0,-n.height/2,t._context.editable?0:a.width,n.height)})}}function l(t){var e=t._fullLayout,n=e.legend,r="left";w.isRightAnchor(n)?r="right":w.isCenterAnchor(n)&&(r="center");var a="top";w.isBottomAnchor(n)?a="bottom":w.isMiddleAnchor(n)&&(a="middle"),d.autoMargin(t,"legend",{x:n.x,y:n.y,l:n.width*({right:1,center:.5}[r]||0),r:n.width*({left:1,center:.5}[r]||0),b:n.height*({top:1,middle:.5}[a]||0),t:n.height*({bottom:1,middle:.5}[a]||0)})}function s(t){var e=t._fullLayout,n=e.legend,r="left";w.isRightAnchor(n)?r="right":w.isCenterAnchor(n)&&(r="center"),d.autoMargin(t,"legend",{x:n.x,y:.5,l:n.width*({right:1,center:.5}[r]||0),r:n.width*({left:1,center:.5}[r]||0),b:0,t:0})}var c=t("d3"),u=t("../../plotly"),f=t("../../lib"),d=t("../../plots/plots"),h=t("../../registry"),p=t("../dragelement"),g=t("../drawing"),m=t("../color"),v=t("../../lib/svg_text_utils"),y=t("./constants"),x=t("./get_legend_data"),b=t("./style"),_=t("./helpers"),w=t("./anchor_utils");e.exports=function(t){function e(t,e){L.attr("data-scroll",e).call(f.setTranslate,0,e),C.call(g.setRect,F,t,y.scrollBarWidth,y.scrollBarHeight),A.select("rect").attr({y:v.borderwidth-e})}var n=t._fullLayout,o="legend"+n._uid;if(n._infolayer&&t.calcdata){var v=n.legend,_=n.showlegend&&x(t.calcdata,v),M=n.hiddenlabels||[];if(!n.showlegend||!_.length)return n._infolayer.selectAll(".legend").remove(),n._topdefs.select("#"+o).remove(),void d.autoMargin(t,"legend");var k=n._infolayer.selectAll("g.legend").data([0]);k.enter().append("g").attr({class:"legend","pointer-events":"all"});var A=n._topdefs.selectAll("#"+o).data([0]);A.enter().append("clipPath").attr("id",o).append("rect");var T=k.selectAll("rect.bg").data([0]);T.enter().append("rect").attr({class:"bg","shape-rendering":"crispEdges"}),T.call(m.stroke,v.bordercolor),T.call(m.fill,v.bgcolor),T.style("stroke-width",v.borderwidth+"px");var L=k.selectAll("g.scrollbox").data([0]);L.enter().append("g").attr("class","scrollbox");var C=k.selectAll("rect.scrollbar").data([0]);C.enter().append("rect").attr({class:"scrollbar",rx:20,ry:2,width:0,height:0}).call(m.fill,"#808BA4");var z=L.selectAll("g.groups").data(_);z.enter().append("g").attr("class","groups"),z.exit().remove();var S=z.selectAll("g.traces").data(f.identity);S.enter().append("g").attr("class","traces"),S.exit().remove(),S.call(b).style("opacity",function(t){var e=t[0].trace;return h.traceIs(e,"pie")?M.indexOf(t[0].label)!==-1?.5:1:"legendonly"===e.visible?.5:1}).each(function(){c.select(this).call(r,t).call(a,t)});var O=0!==k.enter().size();O&&(i(t,z,S),l(t));var P=0,E=n.width,N=0,D=n.height;i(t,z,S),v.height>D?s(t):l(t);var R=n._size,j=R.l+R.w*v.x,I=R.t+R.h*(1-v.y);w.isRightAnchor(v)?j-=v.width:w.isCenterAnchor(v)&&(j-=v.width/2),w.isBottomAnchor(v)?I-=v.height:w.isMiddleAnchor(v)&&(I-=v.height/2);var F=v.width;R.w;j+F>E&&(j=E-F),jq?(I=R.t,B=q):(I+B>D&&(I=D-B),In[1])return n[1]}return a}function n(t){return t[0]}var r,a,o=t[0],i=o.trace,l=h.hasMarkers(i),c=h.hasText(i),d=h.hasLines(i);if(l||c||d){var p={},g={};l&&(p.mc=e("marker.color",n),p.mo=e("marker.opacity",u.mean,[.2,1]),p.ms=e("marker.size",u.mean,[2,16]),p.mlc=e("marker.line.color",n),p.mlw=e("marker.line.width",u.mean,[0,5]),g.marker={sizeref:1,sizemin:1,sizemode:"diameter"}),d&&(g.line={width:e("line.width",n,[0,10])}),c&&(p.tx="Aa",p.tp=e("textposition",n),p.ts=10,p.tc=e("textfont.color",n),p.tf=e("textfont.family",n)),r=[u.minExtend(o,p)],a=u.minExtend(i,g)}var m=s.select(this).select("g.legendpoints"),v=m.selectAll("path.scatterpts").data(l?r:[]);v.enter().append("path").classed("scatterpts",!0).attr("transform","translate(20,0)"),v.exit().remove(),v.call(f.pointStyle,a),l&&(r[0].mrc=3);var y=m.selectAll("g.pointtext").data(c?r:[]);y.enter().append("g").classed("pointtext",!0).append("text").attr("transform","translate(20,0)"),y.exit().remove(),y.selectAll("text").call(f.textPointStyle,a)}function o(t){var e=t[0].trace,n=e.marker||{},r=n.line||{},a=s.select(this).select("g.legendpoints").selectAll("path.legendbar").data(c.traceIs(e,"bar")?[t]:[]);a.enter().append("path").classed("legendbar",!0).attr("d","M6,6H-6V-6H6Z").attr("transform","translate(20,0)"),a.exit().remove(),a.each(function(t){var e=(t.mlw+1||r.width+1)-1,a=s.select(this);a.style("stroke-width",e+"px").call(d.fill,t.mc||n.color),e&&a.call(d.stroke,t.mlc||r.color)})}function i(t){var e=t[0].trace,n=s.select(this).select("g.legendpoints").selectAll("path.legendbox").data(c.traceIs(e,"box")&&e.visible?[t]:[]);n.enter().append("path").classed("legendbox",!0).attr("d","M6,6H-6V-6H6Z").attr("transform","translate(20,0)"),n.exit().remove(),n.each(function(t){var n=(t.lw+1||e.line.width+1)-1,r=s.select(this);r.style("stroke-width",n+"px").call(d.fill,t.fc||e.fillcolor),n&&r.call(d.stroke,t.lc||e.line.color)})}function l(t){var e=t[0].trace,n=s.select(this).select("g.legendpoints").selectAll("path.legendpie").data(c.traceIs(e,"pie")&&e.visible?[t]:[]);n.enter().append("path").classed("legendpie",!0).attr("d","M6,6H-6V-6H6Z").attr("transform","translate(20,0)"),n.exit().remove(),n.size()&&n.call(p,t[0],e)}var s=t("d3"),c=t("../../registry"),u=t("../../lib"),f=t("../drawing"),d=t("../color"),h=t("../../traces/scatter/subtypes"),p=t("../../traces/pie/style_one");e.exports=function(t){t.each(function(t){var e=s.select(this),n=e.selectAll("g.legendfill").data([t]);n.enter().append("g").classed("legendfill",!0);var r=e.selectAll("g.legendlines").data([t]);r.enter().append("g").classed("legendlines",!0);var a=e.selectAll("g.legendsymbols").data([t]);a.enter().append("g").classed("legendsymbols",!0),a.style("opacity",t[0].trace.opacity),a.selectAll("g.legendpoints").data([t]).enter().append("g").classed("legendpoints",!0)}).each(o).each(i).each(l).each(r).each(a)}},{"../../lib":122,"../../registry":194,"../../traces/pie/style_one":232,"../../traces/scatter/subtypes":254,"../color":27,"../drawing":50,d3:10}],72:[function(t,e,n){"use strict";function r(t,e){var n=e.currentTarget,r=n.getAttribute("data-attr"),a=n.getAttribute("data-val")||!0,o=t._fullLayout,i={};if("zoom"===r){for(var l,s,u="in"===a?.5:2,d=(1+u)/2,h=(1-u)/2,p=f.list(t,null,!0),g=0;g1)return r(["resetViews","toggleHover"]),i(m,n);u&&(r(["zoom3d","pan3d","orbitRotation","tableRotation"]),r(["resetCameraDefault3d","resetCameraLastSave3d"]),r(["hoverClosest3d"])),d&&(r(["zoomInGeo","zoomOutGeo","resetGeo"]),r(["hoverClosestGeo"]));var v=a(l),y=[];return((c||p)&&!v||g)&&(y=["zoom2d","pan2d"]),(c||g)&&o(s)&&(y.push("select2d"),y.push("lasso2d")),y.length&&r(y),!c&&!p||v||g||r(["zoomIn2d","zoomOut2d","autoScale2d","resetScale2d"]),c&&h?r(["toggleHover"]):p?r(["hoverClosestGl2d"]):c?r(["hoverClosestCartesian","hoverCompareCartesian"]):h&&r(["hoverClosestPie"]),i(m,n)}function a(t){for(var e=s.list({_fullLayout:t},null,!0),n=!0,r=0;r0);if(p){var g=a(e,n,s);u("x",g[0]),u("y",g[1]),o.noneOrAll(t,e,["x","y"]),u("xanchor"),u("yanchor"),o.coerceFont(u,"font",n.font);var m=u("bgcolor");u("activecolor",i.contrast(m,c.lightAmount,c.darkAmount)),u("bordercolor"),u("borderwidth")}}},{"../../lib":122,"../color":27,"./attributes":76,"./button_attributes":77,"./constants":78}],80:[function(t,e,n){"use strict";function r(t){for(var e=v.list(t,"x",!0),n=[],r=0;rp&&(p=d)));return p>=h?[h,p]:void 0}}var a=t("../../lib"),o=t("../../plots/cartesian/axes"),i=t("./constants"),l=t("./helpers");e.exports=function(t){var e=t._fullLayout,n=a.filterVisible(e.shapes);if(n.length&&t._fullData.length)for(var l=0;le;o--)f(t,o).selectAll('[data-index="'+(o-1)+'"]').attr("data-index",o),a(t,o)}function u(t,e,n,r){function a(n){var r={"data-index":e,"fill-rule":"evenodd",d:h(t,C)},a=C.line.width?C.line.color:"rgba(0,0,0,0)",o=n.append("path").attr(r).style("opacity",C.opacity).call(y.stroke,a).call(y.fill,C.fillcolor).call(x.dashLine,C.line.dash,C.line.width);C.classes&&o.classed(C.classes,!0),z&&o.call(x.setClipUrl,"clip"+t._fullLayout._uid+z)}var o,i;f(t,e).selectAll('[data-index="'+e+'"]').remove();var l=t.layout.shapes[e];if(l){var s={};"string"==typeof n&&n?s[n]=r:m.isPlainObject(n)&&(s=n);var c=Object.keys(s);for(o=0;ol&&(t="X"),t});return r>l&&(s=s.replace(/[\s,]*X.*/,""),m.log("Ignoring extra params in segment "+t)),a+s})}var g=t("fast-isnumeric"),m=(t("../../plotly"),t("../../lib")),v=t("../../plots/cartesian/axes"),y=t("../color"),x=t("../drawing"),b=(t("../dragelement"),t("../../lib/setcursor"),t("./constants")),_=t("./helpers"),w=t("./shape_defaults"),M=t("./defaults");e.exports={draw:r,drawOne:a}},{"../../lib":122,"../../lib/setcursor":132,"../../plotly":145,"../../plots/cartesian/axes":150,"../color":27,"../dragelement":48,"../drawing":50,"./constants":90,"./defaults":91,"./helpers":93,"./shape_defaults":95,"fast-isnumeric":13}],93:[function(t,e,n){"use strict";n.rangeToShapePosition=function(t){return"log"===t.type?t.r2d:function(t){return t}},n.shapePositionToRange=function(t){return"log"===t.type?t.d2r:function(t){return t}},n.decodeDate=function(t){return function(e){return e.replace&&(e=e.replace("_"," ")),t(e)}},n.encodeDate=function(t){return function(e){return t(e).replace(" ","_")}},n.getDataToPixel=function(t,e,r){var a,o=t._fullLayout._size;if(e){var i=n.shapePositionToRange(e);a=function(t){return e._offset+e.r2p(i(t,!0))},"date"===e.type&&(a=n.decodeDate(a))}else a=r?function(t){return o.t+o.h*(1-t)}:function(t){return o.l+o.w*t};return a},n.getPixelToData=function(t,e,r){var a,o=t._fullLayout._size;if(e){var i=n.rangeToShapePosition(e);a=function(t){return i(e.p2r(t-e._offset))}}else a=r?function(t){return 1-(t-o.t)/o.h}:function(t){return(t-o.l)/o.w};return a}},{}],94:[function(t,e,n){"use strict";var r=t("./draw");e.exports={moduleType:"component",name:"shapes",layoutAttributes:t("./attributes"),supplyLayoutDefaults:t("./defaults"),calcAutorange:t("./calc_autorange"), +draw:r.draw,drawOne:r.drawOne}},{"./attributes":88,"./calc_autorange":89,"./defaults":91,"./draw":92}],95:[function(t,e,n){"use strict";var r=t("../../lib"),a=t("../../plots/cartesian/axes"),o=t("./attributes"),i=t("./helpers");e.exports=function(t,e,n,l,s){function c(n,a){return r.coerce(t,e,o,n,a)}l=l||{},s=s||{};var u=c("visible",!s.itemIsNotPlainObject);if(!u)return e;c("layer"),c("opacity"),c("fillcolor"),c("line.color"),c("line.width"),c("line.dash");for(var f=t.path?"path":"rect",d=c("type",f),h=["x","y"],p=0;p<2;p++){var g=h[p],m={_fullLayout:n},v=a.coerceRef(t,e,m,g,"","paper");if("path"!==d){var y,x,b,_=.25,w=.75;"paper"!==v?(y=a.getFromId(m,v),b=i.rangeToShapePosition(y),x=i.shapePositionToRange(y)):x=b=r.identity;var M=g+"0",k=g+"1",A=t[M],T=t[k];t[M]=x(t[M],!0),t[k]=x(t[k],!0),a.coercePosition(e,m,c,v,M,_),a.coercePosition(e,m,c,v,k,w),e[M]=b(e[M]),e[k]=b(e[k]),t[M]=A,t[k]=T}}return"path"===d?c("path"):r.noneOrAll(t,e,["x0","x1","y0","y1"]),t.classes&&(e.classes=t.classes),e}},{"../../lib":122,"../../plots/cartesian/axes":150,"./attributes":88,"./helpers":93}],96:[function(t,e,n){"use strict";var r=t("../../plots/font_attributes"),a=t("../../plots/pad_attributes"),o=t("../../lib/extend").extendFlat,i=t("../../lib/extend").extendDeep,l=t("../../plots/animation_attributes"),s=t("./constants"),c={_isLinkedToArray:"step",method:{valType:"enumerated",values:["restyle","relayout","animate","update"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string"},value:{valType:"string"}};e.exports={_isLinkedToArray:"slider",visible:{valType:"boolean",dflt:!0},active:{valType:"number",min:0,dflt:0},steps:c,lenmode:{valType:"enumerated",values:["fraction","pixels"],dflt:"fraction"},len:{valType:"number",min:0,dflt:1},x:{valType:"number",min:-2,max:3,dflt:0},pad:i({},a,{},{t:{dflt:20}}),xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left"},y:{valType:"number",min:-2,max:3,dflt:0},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},transition:{duration:{valType:"number",min:0,dflt:150},easing:{valType:"enumerated",values:l.transition.easing.values,dflt:"cubic-in-out"}},currentvalue:{visible:{valType:"boolean",dflt:!0},xanchor:{valType:"enumerated",values:["left","center","right"],dflt:"left"},offset:{valType:"number",dflt:10},prefix:{valType:"string"},suffix:{valType:"string"},font:o({},r,{})},font:o({},r,{}),activebgcolor:{valType:"color",dflt:s.gripBgActiveColor},bgcolor:{valType:"color",dflt:s.railBgColor},bordercolor:{valType:"color",dflt:s.railBorderColor},borderwidth:{valType:"number",min:0,dflt:s.railBorderWidth},ticklen:{valType:"number",min:0,dflt:s.tickLength},tickcolor:{valType:"color",dflt:s.tickColor},tickwidth:{valType:"number",min:0,dflt:1},minorticklen:{valType:"number",min:0,dflt:s.minorTickLength}}},{"../../lib/extend":117,"../../plots/animation_attributes":146,"../../plots/font_attributes":170,"../../plots/pad_attributes":185,"./constants":97}],97:[function(t,e,n){"use strict";e.exports={name:"sliders",containerClassName:"slider-container",groupClassName:"slider-group",inputAreaClass:"slider-input-area",railRectClass:"slider-rail-rect",railTouchRectClass:"slider-rail-touch-rect",gripRectClass:"slider-grip-rect",tickRectClass:"slider-tick-rect",inputProxyClass:"slider-input-proxy",labelsClass:"slider-labels",labelGroupClass:"slider-label-group",labelClass:"slider-label",currentValueClass:"slider-current-value",railHeight:5,menuIndexAttrName:"slider-active-index",autoMarginIdRoot:"slider-",minWidth:30,minHeight:30,textPadX:40,fontSizeToHeight:1.3,arrowOffsetX:4,railRadius:2,railWidth:5,railBorder:4,railBorderWidth:1,railBorderColor:"#bec8d9",railBgColor:"#f8fafc",railInset:8,stepInset:10,gripRadius:10,gripWidth:20,gripHeight:20,gripBorder:20,gripBorderWidth:1,gripBorderColor:"#bec8d9",gripBgColor:"#f6f8fa",gripBgActiveColor:"#dbdde0",labelPadding:8,labelOffset:0,tickWidth:1,tickColor:"#333",tickOffset:25,tickLength:7,minorTickOffset:25,minorTickColor:"#333",minorTickLength:4,currentValuePadding:8,currentValueInset:0}},{}],98:[function(t,e,n){"use strict";function r(t,e,n){function r(n,r){return o.coerce(t,e,l,n,r)}var i=a(t,e),s=r("visible",i.length>0);if(s){r("active"),r("x"),r("y"),o.noneOrAll(t,e,["x","y"]),r("xanchor"),r("yanchor"),r("len"),r("lenmode"),r("pad.t"),r("pad.r"),r("pad.b"),r("pad.l"),o.coerceFont(r,"font",n.font);var c=r("currentvalue.visible");c&&(r("currentvalue.xanchor"),r("currentvalue.prefix"),r("currentvalue.suffix"),r("currentvalue.offset"),o.coerceFont(r,"currentvalue.font",e.font)),r("transition.duration"),r("transition.easing"),r("bgcolor"),r("activebgcolor"),r("bordercolor"),r("borderwidth"),r("ticklen"),r("tickwidth"),r("tickcolor"),r("minorticklen")}}function a(t,e){function n(t,e){return o.coerce(r,a,u,t,e)}for(var r,a,i=t.steps||[],l=e.steps=[],s=0;s0&&(i=i.transition().duration(e.transition.duration).ease(e.transition.easing)),i.attr("transform","translate("+(o-.5*z.gripWidth)+","+e.currentValueTotalHeight+")")}}function v(t,e){return t.inputAreaStart+z.stepInset+(t.inputAreaLength-2*z.stepInset)*Math.min(1,Math.max(0,e))}function y(t,e){return Math.min(1,Math.max(0,(e-z.stepInset-t.inputAreaStart)/(t.inputAreaLength-2*z.stepInset-2*t.inputAreaStart)))}function x(t,e,n){var r=t.selectAll("rect."+z.railTouchRectClass).data([0]);r.enter().append("rect").classed(z.railTouchRectClass,!0).call(h,e,t,n).style("pointer-events","all"),r.attr({width:n.inputAreaLength,height:Math.max(n.inputAreaWidth,z.tickOffset+n.ticklen+n.labelHeight)}).call(A.fill,n.bgcolor).attr("opacity",0),k.setTranslate(r,0,n.currentValueTotalHeight)}function b(t,e){var n=t.selectAll("rect."+z.railRectClass).data([0]);n.enter().append("rect").classed(z.railRectClass,!0);var r=e.inputAreaLength-2*z.railInset;n.attr({width:r,height:z.railWidth,rx:z.railRadius,ry:z.railRadius,"shape-rendering":"crispEdges"}).call(A.stroke,e.bordercolor).call(A.fill,e.bgcolor).style("stroke-width",e.borderwidth+"px"),k.setTranslate(n,z.railInset,.5*(e.inputAreaWidth-z.railWidth)+e.currentValueTotalHeight)}function _(t){for(var e=t._fullLayout._pushmargin||{},n=Object.keys(e),r=0;r0?[0]:[]);if(l.enter().append("g").classed(z.containerClassName,!0).style("cursor","ew-resize"),l.exit().remove(),l.exit().size()&&_(t),0!==n.length){var s=l.selectAll("g."+z.groupClassName).data(n,a);s.enter().append("g").classed(z.groupClassName,!0),s.exit().each(function(e){w.select(this).remove(),e._commandObserver.remove(),delete e._commandObserver,M.autoMargin(t,z.autoMarginIdRoot+e._index)});for(var c=0;c0||d<0){var h={left:[-n,0],right:[n,0],top:[0,-n],bottom:[0,n]}[x.side];e.attr("transform","translate("+h+")")}}}function p(){L=0,C=!0,z=O,M._infolayer.select("."+e).attr({"data-unformatted":z}).text(z).on("mouseover.opacity",function(){r.select(this).transition().duration(100).style("opacity",1)}).on("mouseout.opacity",function(){r.select(this).transition().duration(1e3).style("opacity",0)})}var g=n.propContainer,m=n.propName,v=n.traceIndex,y=n.dfltName,x=n.avoid||{},b=n.attributes,_=n.transform,w=n.containerGroup,M=t._fullLayout,k=g.titlefont.family,A=g.titlefont.size,T=g.titlefont.color,L=1,C=!1,z=g.title.trim();""===z&&(L=0),z.match(/Click to enter .+ title/)&&(L=.2,C=!0),w||(w=M._infolayer.selectAll(".g-"+e).data([0]),w.enter().append("g").classed("g-"+e,!0));var S=w.selectAll("text").data([0]);S.enter().append("text"),S.text(z).attr("class",e),S.attr({"data-unformatted":z}).call(f);var O="Click to enter "+y+" title",P=t._context.editable;P&&(g===M?P=t._context.editableMainTitle:g===M.xaxis?P=t._context.editableAxisXTitle:g===M.yaxis?P=t._context.editableAxisYTitle:g===M.yaxis2?P=t._context.editableAxisY2Title:g===M.xaxis2&&(P=t._context.editableAxisX2Title)),P?(z||p(),S.call(u.makeEditable).on("edit",function(e){void 0!==v?o.restyle(t,m,e,v):o.relayout(t,m,e)}).on("cancel",function(){this.text(this.attr("data-unformatted")).call(f)}).on("input",function(t){this.text(t||" ").attr(b).selectAll("tspan.line").attr(b)})):z&&!z.match(/Click to enter .+ title/)||S.remove(),S.classed("js-placeholder",C),g._titleElement=S}},{"../../lib":122,"../../lib/svg_text_utils":134,"../../plotly":145,"../../plots/plots":186,"../color":27,"../drawing":50,d3:10,"fast-isnumeric":13}],102:[function(t,e,n){"use strict";var r=t("../../plots/font_attributes"),a=t("../color/attributes"),o=t("../../lib/extend").extendFlat,i=t("../../plots/pad_attributes"),l={_isLinkedToArray:"button",method:{valType:"enumerated",values:["restyle","relayout","animate","update"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string",dflt:""}};e.exports={_isLinkedToArray:"updatemenu",visible:{valType:"boolean"},type:{valType:"enumerated",values:["dropdown","buttons"],dflt:"dropdown"},direction:{valType:"enumerated",values:["left","right","up","down"],dflt:"down"},active:{valType:"integer",min:-1,dflt:0},showactive:{valType:"boolean",dflt:!0},buttons:l,x:{valType:"number",min:-2,max:3,dflt:-.05},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"right"},y:{valType:"number",min:-2,max:3,dflt:1},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},pad:o({},i,{}),font:o({},r,{}),bgcolor:{valType:"color"},bordercolor:{valType:"color",dflt:a.borderLine},borderwidth:{valType:"number",min:0,dflt:1}}},{"../../lib/extend":117,"../../plots/font_attributes":170,"../../plots/pad_attributes":185,"../color/attributes":26}],103:[function(t,e,n){"use strict";e.exports={name:"updatemenus",containerClassName:"updatemenu-container",headerGroupClassName:"updatemenu-header-group",headerClassName:"updatemenu-header",headerArrowClassName:"updatemenu-header-arrow",dropdownButtonGroupClassName:"updatemenu-dropdown-button-group",dropdownButtonClassName:"updatemenu-dropdown-button",buttonClassName:"updatemenu-button",itemRectClassName:"updatemenu-item-rect",itemTextClassName:"updatemenu-item-text",menuIndexAttrName:"updatemenu-active-index",autoMarginIdRoot:"updatemenu-",blankHeaderOpts:{label:" "},minWidth:30,minHeight:30,textPadX:24,arrowPadX:16,fontSizeToHeight:1.3,rx:2,ry:2,textOffsetX:12,textOffsetY:3,arrowOffsetX:4,gapButtonHeader:5,gapButton:2,activeColor:"#F4FAFF",hoverColor:"#F4FAFF"}},{}],104:[function(t,e,n){"use strict";function r(t,e,n){function r(n,r){return o.coerce(t,e,l,n,r)}var i=a(t,e),s=r("visible",i.length>0);s&&(r("active"),r("direction"),r("type"),r("showactive"),r("x"),r("y"),o.noneOrAll(t,e,["x","y"]),r("xanchor"),r("yanchor"),r("pad.t"),r("pad.r"),r("pad.b"),r("pad.l"),o.coerceFont(r,"font",n.font),r("bgcolor",n.paper_bgcolor),r("bordercolor"),r("borderwidth"))}function a(t,e){function n(t,e){return o.coerce(r,a,u,t,e)}for(var r,a,i=t.buttons||[],l=e.buttons=[],s=0;s0?[0]:[]);if(c.enter().append("g").classed(T.containerClassName,!0).style("cursor","pointer"),c.exit().remove(),c.exit().size()&&y(t),0!==n.length){var u=c.selectAll("g."+T.headerGroupClassName).data(n,a);u.enter().append("g").classed(T.headerGroupClassName,!0);var f=c.selectAll("g."+T.dropdownButtonGroupClassName).data([0]);f.enter().append("g").classed(T.dropdownButtonGroupClassName,!0).style("pointer-events","all"),u.enter().size()&&f.call(v).attr(T.menuIndexAttrName,"-1"),u.exit().each(function(e){x.select(this).remove(),f.call(v).attr(T.menuIndexAttrName,"-1"),b.autoMargin(t,T.autoMarginIdRoot+e._index)});for(var d=0;d",nbsp:"\xa0",times:"\xd7",plusmn:"\xb1",deg:"\xb0"},unicodeToEntity:{"&":"amp","<":"lt",">":"gt",'"':"quot","'":"#x27","/":"#x2F"}}},{}],109:[function(t,e,n){"use strict";n.xmlns="http://www.w3.org/2000/xmlns/",n.svg="http://www.w3.org/2000/svg",n.xlink="http://www.w3.org/1999/xlink",n.svgAttrs={xmlns:n.svg,"xmlns:xlink":n.xlink}},{}],110:[function(t,e,n){"use strict";var r=t("./plotly");n.version="1.20.2-d27",t("es6-promise").polyfill(),t("../build/plotcss"),t("./fonts/mathjax_config"),n.plot=r.plot,n.newPlot=r.newPlot,n.restyle=r.restyle,n.relayout=r.relayout,n.redraw=r.redraw,n.update=r.update,n.extendTraces=r.extendTraces,n.prependTraces=r.prependTraces,n.addTraces=r.addTraces,n.deleteTraces=r.deleteTraces,n.moveTraces=r.moveTraces,n.purge=r.purge,n.setPlotConfig=t("./plot_api/set_plot_config"),n.register=t("./plot_api/register"),n.toImage=t("./plot_api/to_image"),n.downloadImage=t("./snapshot/download"),n.validate=t("./plot_api/validate"),n.addFrames=r.addFrames,n.deleteFrames=r.deleteFrames,n.animate=r.animate,n.register(t("./traces/scatter")),n.register([t("./components/legend"),t("./components/annotations"),t("./components/shapes"),t("./components/images"),t("./components/updatemenus"),t("./components/sliders"),t("./components/rangeslider"),t("./components/rangeselector")]),n.Icons=t("../build/ploticon"),n.Plots=r.Plots,n.Fx=r.Fx,n.Snapshot=t("./snapshot"),n.PlotSchema=t("./plot_api/plot_schema"),n.Queue=t("./lib/queue");var a=t("./components/color");n.colorDefaults=a.overrideColorDefaults,n.d3=t("d3")},{"../build/plotcss":1,"../build/ploticon":2,"./components/annotations":25,"./components/color":27,"./components/images":62,"./components/legend":70,"./components/rangeselector":82,"./components/rangeslider":87,"./components/shapes":94,"./components/sliders":100,"./components/updatemenus":106,"./fonts/mathjax_config":111,"./lib/queue":130,"./plot_api/plot_schema":139,"./plot_api/register":140,"./plot_api/set_plot_config":141,"./plot_api/to_image":143,"./plot_api/validate":144,"./plotly":145,"./snapshot":199,"./snapshot/download":196,"./traces/scatter":244,d3:10,"es6-promise":11}],111:[function(t,e,n){"use strict";"undefined"!=typeof MathJax?(n.MathJax=!0,MathJax.Hub.Config({messageStyle:"none",skipStartupTypeset:!0,displayAlign:"left",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]]}}),MathJax.Hub.Configured()):n.MathJax=!1},{}],112:[function(t,e,n){"use strict";e.exports=function(t,e,n,r){Array.isArray(t)&&(e[n]=t[r])}},{}],113:[function(t,e,n){"use strict";var r=t("fast-isnumeric"),a=t("../constants/numerical").BADNUM,o=/^['"%,$#\s']+/,i=/['"%,$#\s']+$/;e.exports=function(t){return"string"==typeof t&&(t=t.replace(o,"").replace(i,"")),r(t)?Number(t):a}},{"../constants/numerical":107,"fast-isnumeric":13}],114:[function(t,e,n){"use strict";var r=t("fast-isnumeric"),a=t("tinycolor2"),o=t("../components/colorscale/get_scale"),i=(Object.keys(t("../components/colorscale/scales")),t("./nested_property")),l=/^([2-9]|[1-9][0-9]+)$/;n.valObjects={data_array:{coerceFunction:function(t,e,n){Array.isArray(t)?e.set(t):void 0!==n&&e.set(n)}},enumerated:{coerceFunction:function(t,e,n,r){r.coerceNumber&&(t=+t),r.values.indexOf(t)===-1?e.set(n):e.set(t)}},boolean:{coerceFunction:function(t,e,n){t===!0||t===!1?e.set(t):e.set(n)}},number:{coerceFunction:function(t,e,n,a){!r(t)||void 0!==a.min&&ta.max?e.set(n):e.set(+t)}},integer:{coerceFunction:function(t,e,n,a){t%1||!r(t)||void 0!==a.min&&ta.max?e.set(n):e.set(+t)}},string:{coerceFunction:function(t,e,n,r){if("string"!=typeof t){var a="number"==typeof t;r.strict!==!0&&a?e.set(String(t)):e.set(n)}else r.noBlank&&!t?e.set(n):e.set(t)}},color:{coerceFunction:function(t,e,n){a(t).isValid()?e.set(t):e.set(n)}},colorscale:{coerceFunction:function(t,e,n){e.set(o(t,n))}},angle:{coerceFunction:function(t,e,n){"auto"===t?e.set("auto"):r(t)?(Math.abs(t)>180&&(t-=360*Math.round(t/360)),e.set(+t)):e.set(n)}},subplotid:{coerceFunction:function(t,e,n){var r=n.length;return"string"==typeof t&&t.substr(0,r)===n&&l.test(t.substr(r))?void e.set(t):void e.set(n)},validateFunction:function(t,e){var n=e.dflt,r=n.length;return t===n||"string"==typeof t&&!(t.substr(0,r)!==n||!l.test(t.substr(r)))}},flaglist:{coerceFunction:function(t,e,n,r){if("string"!=typeof t)return void e.set(n);if((r.extras||[]).indexOf(t)!==-1)return void e.set(t);for(var a=t.split("+"),o=0;o=h&&t<=p?t:s;if("string"!=typeof t&&"number"!=typeof t)return s;var e,r,a,i,l=String(t).trim().split(" ");if(l.length>2)return s;var c=l[0].split("-"),u=!0;""===c[0]&&(u=!1,c.splice(0,1));var g=c.length;if(g>3||3!==g&&l[1]||!g)return s;if(4===c[0].length)e=Number(c[0]);else{if(2!==c[0].length)return s;if(!u)return s;var m=(new Date).getFullYear();e=((Number(c[0])-m+70)%100+200)%100+m-70}if(!o(e))return s;var v=new Date(0,0,1);if(v.setFullYear(u?e:-e),c.length>1){if(r=Number(c[1])-1,c[1].length>2||!(r>=0&&r<=11))return s;if(v.setMonth(r),c.length>2){if(a=Number(c[2]),c[2].length>2||!(a>=1&&a<=31))return s;if(v.setDate(a),v.getDate()!==a)return s;if(l[1]){if(c=l[1].split(":"),c.length>3)return s;if(i=Number(c[0]),c[0].length>2||!c[0].length||!(i>=0&&i<=23))return s;if(v.setHours(i),v.getHours()!==i)return s;if(c.length>1)return a=v.getTime(),r=Number(c[1]),2===c[1].length&&r>=0&&r<=59?(a+=f*r,2===c.length?a:2!==c[2].split(".")[0].length?s:(t=Number(c[2]),t>=0&&t<60?a+t*d:s)):s}}}return v.getTime()},h=n.MIN_MS=n.dateTime2ms("-9999"),p=n.MAX_MS=n.dateTime2ms("9999-12-31 23:59:59.9999"),n.isDateTime=function(t){return n.dateTime2ms(t)!==s};var g=90*c,m=3*u,v=5*f;n.ms2DateTime=function(t,e){if("number"!=typeof t||!(t>=h&&t<=p))return s;e||(e=0);var n=new Date(Math.floor(t)),o=a.time.format("%Y-%m-%d")(n),i=e0&&(r.push(a),a=[])}return r.push(a),r},n.makeLine=function(t,e){var n={};return n=1===t.length?{type:"LineString",coordinates:t[0]}:{type:"MultiLineString",coordinates:t},e&&(n.trace=e),n},n.makePolygon=function(t,e){var n={};if(1===t.length)n={type:"Polygon",coordinates:t};else{for(var r=new Array(t.length),a=0;an?Math.max(n,Math.min(e,t)):Math.max(e,Math.min(n,t))},a.bBoxIntersect=function(t,e,n){return n=n||0,t.left<=e.right+n&&e.left<=t.right+n&&t.top<=e.bottom+n&&e.top<=t.bottom+n},a.identity=function(t){return t},a.noop=function(){},a.randstr=function t(e,n,r){if(r||(r=16),void 0===n&&(n=24),n<=0)return"0";var a,o,i,l=Math.log(Math.pow(2,n))/Math.log(r),s="";for(a=2;l===1/0;a*=2)l=Math.log(Math.pow(2,n/a))/Math.log(r)*a;var c=l-Math.floor(l);for(a=0;a-1||u!==1/0&&u>=Math.pow(2,n)?t(e,n,r):s},a.OptionControl=function(t,e){t||(t={}),e||(e="opt");var n={};return n.optionList=[],n._newoption=function(r){r[e]=t,n[r.name]=r,n.optionList.push(r)},n["_"+e]=t,n},a.smooth=function(t,e){if(e=Math.round(e)||0,e<2)return t;var n,r,a,o,i=t.length,l=2*i,s=2*e-1,c=new Array(s),u=new Array(i);for(n=0;n=l&&(a-=l*Math.floor(a/l)),a<0?a=-1-a:a>=i&&(a=l-1-a),o+=t[a]*c[r];u[n]=o}return u},a.syncOrAsync=function(t,e,n){function r(){return a.syncOrAsync(t,e,n)}for(var o,i;t.length;)if(i=t.splice(0,1)[0],o=i(e),o&&o.then)return o.then(r).then(void 0,a.promiseError);return n&&n(e)},a.stripTrailingSlash=function(t){return"/"===t.substr(-1)?t.substr(0,t.length-1):t},a.noneOrAll=function(t,e,n){if(t){var r,a,o=!1,i=!0;for(r=0;r1?a+i[1]:"";if(o&&(i.length>1||l.length>4||n))for(;r.test(l);)l=l.replace(r,"$1"+o+"$2");return l+s}},{"./clean_number":113,"./coerce":114,"./dates":115,"./extend":117,"./filter_unique":118,"./filter_visible":119,"./is_array":123,"./is_plain_object":124,"./loggers":125,"./matrix":126,"./nested_property":127,"./notifier":128,"./search":131,"./stats":133,d3:10}],123:[function(t,e,n){"use strict";e.exports=function(t){return Array.isArray(t)||ArrayBuffer.isView(t)}},{}],124:[function(t,e,n){"use strict";e.exports=function(t){return window&&window.process&&window.process.versions?"[object Object]"===Object.prototype.toString.call(t):"[object Object]"===Object.prototype.toString.call(t)&&Object.getPrototypeOf(t)===Object.prototype}},{}],125:[function(t,e,n){"use strict";var r=t("../plot_api/plot_config"),a=e.exports={};a.log=function(){if(r.logging>1){for(var t=["LOG:"],e=0;e0){for(var t=["WARN:"],e=0;e0){for(var t=["ERROR:"],e=0;e=0;e--){if(r=t[e],i=!1,d(r))for(n=r.length-1;n>=0;n--)c(r[n])?i?r[n]=void 0:r.pop():i=!0;else if("object"==typeof r&&null!==r)for(o=Object.keys(r),i=!1,n=o.length-1;n>=0;n--)c(r[o[n]])&&!a(r[o[n]],o[n])?delete r[o[n]]:i=!0;if(i)return}}function c(t){return void 0===t||null===t||"object"==typeof t&&(d(t)?!t.length:!Object.keys(t).length)}function u(t,e,n){return{set:function(){throw"bad container"},get:function(){},astr:e,parts:n,obj:t}}var f=t("fast-isnumeric"),d=t("./is_array");e.exports=function(t,e){if(f(e))e=String(e);else if("string"!=typeof e||"[-1]"===e.substr(e.length-4))throw"bad property string";for(var n,a,i,l=0,s=e.split(".");lo||rl)&&(!e||!c(t))}function n(t,e){var n=t[0],s=t[1];if(no||sl)return!1;var c,u,f,d,h,p=r.length,g=r[0][0],m=r[0][1],v=0;for(c=1;cMath.max(u,g)||s>Math.max(f,m)))if(su||Math.abs(r(i,d))>a)return!0;return!1};a.filter=function(t,e){function n(n){t.push(n);var l=r.length,s=a;r.splice(i+1);for(var c=s+1;c1){var l=t.pop();n(l)}return{addPt:n,raw:t,filtered:r}}},{"./matrix":126}],130:[function(t,e,n){"use strict";function r(t,e){for(var n,r=[],o=0;oo.queueLength&&(t.undoQueue.queue.shift(),t.undoQueue.index--)))},i.startSequence=function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!0,t.undoQueue.beginSequence=!0},i.stopSequence=function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!1,t.undoQueue.beginSequence=!1},i.undo=function(t){var e,n;if(t.framework&&t.framework.isPolar)return void t.framework.undo();if(!(void 0===t.undoQueue||isNaN(t.undoQueue.index)||t.undoQueue.index<=0)){for(t.undoQueue.index--,e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,n=0;n=t.undoQueue.queue.length)){for(e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,n=0;ne}function i(t,e){return t>=e}var l=t("fast-isnumeric"),s=t("./loggers");n.findBin=function(t,e,n){if(l(e.start))return n?Math.ceil((t-e.start)/e.size)-1:Math.floor((t-e.start)/e.size);var c,u,f=0,d=e.length,h=0;for(u=e[e.length-1]>=e[0]?n?r:a:n?i:o;f90&&s.log("Long binary search..."),f-1},n.sorterAsc=function(t,e){return t-e},n.sorterDes=function(t,e){return e-t},n.distinctVals=function(t){var e=t.slice();e.sort(n.sorterAsc);for(var r=e.length-1,a=e[r]-e[0]||1,o=a/(r||1)/1e4,i=[e[0]],l=0;le[l]+o&&(a=Math.min(a,e[l+1]-e[l]),i.push(e[l+1]));return{vals:i,minDiff:a}},n.roundUp=function(t,e,n){for(var r,a=0,o=e.length-1,i=0,l=n?0:1,s=n?1:0,c=n?Math.ceil:Math.floor;at.length-1)return t[t.length-1];var n=e%1;return n*t[Math.ceil(e)]+(1-n)*t[Math.floor(e)]}},{"fast-isnumeric":13}],134:[function(t,e,n){"use strict";function r(t,e){return t.node().getBoundingClientRect()[e]}function a(t){return t.replace(/(<|<|<)/g,"\\lt ").replace(/(>|>|>)/g,"\\gt ")}function o(t,e,n){var r="math-output-"+d.randstr([],64),o=f.select("body").append("div").attr({id:r}).style({visibility:"hidden",position:"absolute"}).style({"font-size":e.fontSize+"px"}).text(a(t));MathJax.Hub.Queue(["Typeset",MathJax.Hub,o.node()],function(){var e=f.select("body").select("#MathJax_SVG_glyphs");if(o.select(".MathJax_SVG").empty()||!o.select("svg").node())d.log("There was an error in the tex syntax.",t),n();else{var r=o.select("svg").node().getBoundingClientRect();n(o.select(".MathJax_SVG"),e,r)}o.remove()})}function i(t,e){for(var n=t||"",r=0;r]*>)/).map(function(t){var e=t.match(/<(\/?)([^ >]*)\s*(.*)>/i),r=e&&e[2].toLowerCase(),a=g[r];if(void 0!==a){var o=e[1],i=e[3],l=i.match(/^style\s*=\s*"([^"]+)"\s*/i);if("a"===r){if(o)return"
";if("href"!==i.substr(0,4).toLowerCase())return"";var c=i.substr(4).replace(/["']/g,"").replace(/=/,""),u=document.createElement("a");return u.href=c,m.indexOf(u.protocol)===-1?"":''}if("br"===r)return"
";if(o)return"sup"===r?'':"sub"===r?'':"";var f=""}return n.xml_entity_encode(t).replace(/");a>0;a=e.indexOf("
",a+1))r.push(a);var o=0;r.forEach(function(t){for(var n=t+o,r=e.slice(0,n),a="",i=r.length-1;i>=0;i--){var l=r[i].match(/<(\/?).*>/i);if(l&&"
"!==r[i]){l[1]||(a=r[i]);break}}a&&(e.splice(n+1,0,a),e.splice(n,0,""),o+=2)});var i=e.join(""),c=i.split(/
/gi);return c.length>1&&(e=c.map(function(t,e){return''+t+""})),e.join("")}function u(t,e,n){var r,a,o,i=n.horizontalAlign,l=n.verticalAlign||"top",s=t.node().getBoundingClientRect(),c=e.node().getBoundingClientRect();return a="bottom"===l?function(){return s.bottom-r.height}:"middle"===l?function(){return s.top+(s.height-r.height)/2}:function(){return s.top},o="right"===i?function(){return s.right-r.width}:"center"===i?function(){return s.left+(s.width-r.width)/2}:function(){return s.left},function(){return r=this.node().getBoundingClientRect(),this.style({top:a()-c.top+"px",left:o()-c.left+"px","z-index":1e3}),this}}var f=t("d3"),d=t("../lib"),h=t("../constants/xmlns_namespaces"),p=t("../constants/string_mappings");f.selection.prototype.appendSVG=function(t){for(var e=['',t,""].join(""),n=(new DOMParser).parseFromString(e,"application/xml"),r=n.documentElement.firstChild;r;)this.node().appendChild(this.node().ownerDocument.importNode(r,!0)),r=r.nextSibling;return n.querySelector("parsererror")?(d.log(n.querySelector("parsererror div").textContent),null):f.select(this.node().lastChild)},n.html_entity_decode=function(t){var e=f.select("body").append("div").style({display:"none"}).html(""),n=t.replace(/(&[^;]*;)/gi,function(t){return"<"===t?"<":"&rt;"===t?">":e.html(t).text()});return e.remove(),n},n.xml_entity_encode=function(t){return t.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g,"&")},n.convertToTspans=function(t,e){function n(){h.empty()||(p=l.attr("class")+"-math",h.select("svg."+p).remove()),t.text("").style({visibility:"inherit","white-space":"pre"}),u=t.appendSVG(i),u||t.text(a),t.select("a").size()&&t.style("pointer-events","all"),e&&e.call(l)}var a=t.text(),i=c(a),l=t,s=!l.attr("data-notex")&&i.match(/([^$]*)([$]+[^$]*[$]+)([^$]*)/),u=a,h=f.select(l.node().parentNode);if(!h.empty()){var p=l.attr("class")?l.attr("class").split(" ")[0]:"text";p+="-math",h.selectAll("svg."+p).remove(),h.selectAll("g."+p+"-group").remove(),t.style({visibility:null});for(var g=t.node();g&&g.removeAttribute;g=g.parentNode)g.removeAttribute("data-bb");if(s){var m=d.getPlotDiv(l.node());(m&&m._promises||[]).push(new Promise(function(t){l.style({visibility:"hidden"});var a={fontSize:parseInt(l.style("font-size"),10)};o(s[2],a,function(a,o,i){h.selectAll("svg."+p).remove(),h.selectAll("g."+p+"-group").remove();var s=a&&a.select("svg");if(!s||!s.node())return n(),void t();var c=h.append("g").classed(p+"-group",!0).attr({"pointer-events":"none"});c.node().appendChild(s.node()),o&&o.node()&&s.node().insertBefore(o.node().cloneNode(!0),s.node().firstChild),s.attr({class:p,height:i.height,preserveAspectRatio:"xMinYMin meet"}).style({overflow:"visible","pointer-events":"none"});var u=l.style("fill")||"black";s.select("g").attr({fill:u,stroke:u});var f=r(s,"width"),d=r(s,"height"),g=+l.attr("x")-f*{start:0,middle:.5,end:1}[l.attr("text-anchor")||"start"],m=parseInt(l.style("font-size"),10)||r(l,"height"),v=-m/4;"y"===p[0]?(c.attr({transform:"rotate("+[-90,+l.attr("x"),+l.attr("y")]+") translate("+[-f/2,v-d/2]+")"}),s.attr({x:+l.attr("x"),y:+l.attr("y")})):"l"===p[0]?s.attr({x:l.attr("x"),y:v-d/2}):"a"===p[0]?s.attr({x:0,y:v}):s.attr({x:g,y:+l.attr("y")+v-d/2}),e&&e.call(l,c),t(c)})}))}else n();return t}};var g={sup:'font-size:70%" dy="-0.6em',sub:'font-size:70%" dy="0.3em',b:"font-weight:bold",i:"font-style:italic",a:"",span:"",br:"",em:"font-style:italic;font-weight:bold"},m=["http:","https:","mailto:"],v=new RegExp("]*)?/?>","g"),y=Object.keys(p.entityToUnicode).map(function(t){return{regExp:new RegExp("&"+t+";","g"),sub:p.entityToUnicode[t]}}),x=Object.keys(p.unicodeToEntity).map(function(t){return{regExp:new RegExp(t,"g"),sub:"&"+p.unicodeToEntity[t]+";"}});n.plainText=function(t){return(t||"").replace(v," ")},n.makeEditable=function(t,e,n){function r(){o(),i.style({opacity:0});var t,e=c.attr("class");t=e?"."+e.split(" ")[0]+"-math-group":"[class*=-math-group]",t&&f.select(i.node().parentNode).select(t).style({opacity:0})}function a(t){var e=t.node(),n=document.createRange();n.selectNodeContents(e);var r=window.getSelection();r.removeAllRanges(),r.addRange(n),e.focus()}function o(){var t=f.select(d.getPlotDiv(i.node())),e=t.select(".svg-container"),r=e.append("div");r.classed("plugin-editable editable",!0).style({position:"absolute","font-family":i.style("font-family")||"Arial","font-size":i.style("font-size")||12,color:n.fill||i.style("fill")||"black",opacity:1,"background-color":n.background||"transparent",outline:"#ffffff33 1px solid",margin:[-parseFloat(i.style("font-size"))/8+1,0,0,-1].join("px ")+"px",padding:"0", +"box-sizing":"border-box"}).attr({contenteditable:!0}).text(n.text||i.attr("data-unformatted")).call(u(i,e,n)).on("blur",function(){i.text(this.textContent).style({opacity:1});var t,e=f.select(this).attr("class");t=e?"."+e.split(" ")[0]+"-math-group":"[class*=-math-group]",t&&f.select(i.node().parentNode).select(t).style({opacity:0});var n=this.textContent;f.select(this).transition().duration(0).remove(),f.select(document).on("mouseup",null),l.edit.call(i,n)}).on("focus",function(){var t=this;f.select(document).on("mouseup",function(){return f.event.target!==t&&void(document.activeElement===r.node()&&r.node().blur())})}).on("keyup",function(){27===f.event.which?(i.style({opacity:1}),f.select(this).style({opacity:0}).on("blur",function(){return!1}).transition().remove(),l.cancel.call(i,this.textContent)):(l.input.call(i,this.textContent),f.select(this).call(u(i,e,n)))}).on("keydown",function(){13===f.event.which&&this.blur()}).call(a)}n||(n={});var i=this,l=f.dispatch("edit","input","cancel"),s=f.select(this.node()).style({"pointer-events":"all"}),c=e||s;return e&&s.style({"pointer-events":"none"}),n.immediate?r():c.on("click",r),f.rebind(this,l,"on")}},{"../constants/string_mappings":108,"../constants/xmlns_namespaces":109,"../lib":122,d3:10}],135:[function(t,e,n){"use strict";var r=e.exports={},a=t("../plots/geo/constants").locationmodeToLayer,o=t("topojson-client").feature;r.getTopojsonName=function(t){return[t.scope.replace(/ /g,"-"),"_",t.resolution.toString(),"m"].join("")},r.getTopojsonPath=function(t,e){return t+e+".json"},r.getTopojsonFeatures=function(t,e){var n=a[t.locationmode],r=e.objects[n];return o(e,r).features}},{"../plots/geo/constants":172,"topojson-client":17}],136:[function(t,e,n){"use strict";function r(t,e){var n=t[e],r=e.charAt(0);n&&"paper"!==n&&(t[e]=f.cleanId(n,r))}function a(t){var e="middle",n="center";return t.indexOf("top")!==-1?e="top":t.indexOf("bottom")!==-1&&(e="bottom"),t.indexOf("left")!==-1?n="left":t.indexOf("right")!==-1&&(n="right"),e+" "+n}function o(t,e){return e in t&&"object"==typeof t[e]&&0===Object.keys(t[e]).length}var i=t("fast-isnumeric"),l=t("gl-mat4/fromQuat"),s=t("../registry"),c=t("../lib"),u=t("../plots/plots"),f=t("../plots/cartesian/axes"),d=t("../components/color");n.getGraphDiv=function(t){var e;if("string"==typeof t){if(e=document.getElementById(t),null===e)throw new Error("No DOM element with id '"+t+"' exists on the page.");return e}if(null===t||void 0===t)throw new Error("DOM element provided is null or undefined");return t},n.clearPromiseQueue=function(t){Array.isArray(t._promises)&&t._promises.length>0&&c.log("Clearing previous rejected promises from queue."),t._promises=[]},n.cleanLayout=function(t){var e,n;t||(t={}),t.xaxis1&&(t.xaxis||(t.xaxis=t.xaxis1),delete t.xaxis1),t.yaxis1&&(t.yaxis||(t.yaxis=t.yaxis1),delete t.yaxis1);var a=f.list({_fullLayout:t});for(e=0;e3?(m.x=1.02,m.xanchor="left"):m.x<-2&&(m.x=-.02,m.xanchor="right"),m.y>3?(m.y=1.02,m.yanchor="bottom"):m.y<-2&&(m.y=-.02,m.yanchor="top")),"rotate"===t.dragmode&&(t.dragmode="orbit"),t.scene1&&(t.scene||(t.scene=t.scene1),delete t.scene1);var v=u.getSubplotIds(t,"gl3d");for(e=0;e=t.data.length||a<-t.data.length)throw new Error(n+" must be valid indices for gd.data.");if(e.indexOf(a,r+1)>-1||a>=0&&e.indexOf(-t.data.length+a)>-1||a<0&&e.indexOf(t.data.length+a)>-1)throw new Error("each index in "+n+" must be unique.")}}function s(t,e,n){if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if("undefined"==typeof e)throw new Error("currentIndices is a required argument.");if(Array.isArray(e)||(e=[e]),l(t,e,"currentIndices"),"undefined"==typeof n||Array.isArray(n)||(n=[n]),"undefined"!=typeof n&&l(t,n,"newIndices"),"undefined"!=typeof n&&e.length!==n.length)throw new Error("current and new indices must be of equal length.")}function c(t,e,n){var r,a;if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if("undefined"==typeof e)throw new Error("traces must be defined.");for(Array.isArray(e)||(e=[e]),r=0;r=0&&sO.range[0]?[1,2]:[2,1]);else{var P=O.range[0],E=O.range[1];"log"===b?(P<=0&&E<=0&&n(L+".autorange",!0),P<=0?P=E/1e6:E<=0&&(E=P/1e6),n(L+".range[0]",Math.log(P)/Math.LN10),n(L+".range[1]",Math.log(E)/Math.LN10)):(n(L+".range[0]",Math.pow(10,P)),n(L+".range[1]",Math.pow(10,E)))}else n(L+".autorange",!0)}if("reverse"===A)C.range?C.range.reverse():(n(L+".autorange",!0),C.range=[1,0]),z.autorange?h.docalc=!0:h.doplot=!0;else if("annotations"===v.parts[0]||"shapes"===v.parts[0]){var N=v.parts[1],D=v.parts[0],R=o[D]||[],j=R[N]||{};2===v.parts.length&&(null===b&&(e[m]="remove"),"add"===e[m]||x.isPlainObject(e[m])?g[m]="remove":"remove"===e[m]?N===-1?(g[D]=R,delete g[m]):g[m]=j:x.log("???",e)),!r(j,"x")&&!r(j,"y")||x.containsAny(m,["color","opacity","align","dash"])||(h.docalc=!0);var I=w.getComponentMethod(D,"drawOne");I(t,N,v.parts.slice(2).join("."),e[m]),delete e[m]}else if(M.layoutArrayContainers.indexOf(v.parts[0])!==-1||"mapbox"===v.parts[0]&&"layers"===v.parts[1])S.manageArrayContainers(v,b,g),h.doplot=!0;else{var F=String(v.parts[1]||"");0===v.parts[0].indexOf("scene")?h.doplot=!0:0===v.parts[0].indexOf("geo")?h.doplot=!0:0===v.parts[0].indexOf("ternary")?h.doplot=!0:"paper_bgcolor"===m?h.doplot=!0:!i._has("gl2d")||m.indexOf("axis")===-1&&"plot_bgcolor"!==v.parts[0]?"hiddenlabels"===m?h.docalc=!0:v.parts[0].indexOf("legend")!==-1?h.dolegend=!0:m.indexOf("title")!==-1?h.doticks=!0:v.parts[0].indexOf("bgcolor")!==-1?h.dolayoutstyle=!0:v.parts.length>1&&x.containsAny(F,["tick","exponent","grid","zeroline"])?h.doticks=!0:m.indexOf(".linewidth")!==-1&&m.indexOf("axis")!==-1?h.doticks=h.dolayoutstyle=!0:v.parts.length>1&&F.indexOf("line")!==-1?h.dolayoutstyle=!0:v.parts.length>1&&"mirror"===F?h.doticks=h.dolayoutstyle=!0:"margin.pad"===m?h.doticks=h.dolayoutstyle=!0:"margin"===v.parts[0]||"autorange"===v.parts[1]||"rangemode"===v.parts[1]||"type"===v.parts[1]||"domain"===v.parts[1]||m.match(/^(bar|box|font)/)?h.docalc=!0:["hovermode","dragmode"].indexOf(m)!==-1?h.domodebar=!0:["hovermode","dragmode","height","width","autosize"].indexOf(m)===-1&&(h.doplot=!0):h.doplot=!0,v.set(b)}}}var B=t._fullLayout.width,q=t._fullLayout.height;M.supplyDefaults(t),t.layout.autosize&&M.plotAutoSize(t,t.layout,t._fullLayout);var H=e.height||e.width||t._fullLayout.width!==B||t._fullLayout.height!==q;return H&&(h.docalc=!0),(h.doplot||h.docalc)&&(h.layoutReplot=!0),{flags:h,undoit:g,redoit:p,eventData:x.extendDeep({},p)}}function g(t){var e=m.select(t),n=t._fullLayout;if(n._container=e.selectAll(".plot-container").data([0]),n._container.enter().insert("div",":first-child").classed("plot-container",!0).classed("plotly",!0),n._paperdiv=n._container.selectAll(".svg-container").data([0]),n._paperdiv.enter().append("div").classed("svg-container",!0).style("position","relative"),n._glcontainer=n._paperdiv.selectAll(".gl-container").data([0]),n._glcontainer.enter().append("div").classed("gl-container",!0),n._geocontainer=n._paperdiv.selectAll(".geo-container").data([0]),n._geocontainer.enter().append("div").classed("geo-container",!0),n._paperdiv.selectAll(".main-svg").remove(),n._paper=n._paperdiv.insert("svg",":first-child").classed("main-svg",!0),n._toppaper=n._paperdiv.append("svg").classed("main-svg",!0),!n._uid){var r=[];m.selectAll("defs").each(function(){this.id&&r.push(this.id.split("-")[1])}),n._uid=x.randstr(r)}n._paperdiv.selectAll(".main-svg").attr(C.svgAttrs),n._defs=n._paper.append("defs").attr("id","defs-"+n._uid),n._topdefs=n._toppaper.append("defs").attr("id","topdefs-"+n._uid),n._draggers=n._paper.append("g").classed("draglayer",!0);var a=n._paper.append("g").classed("layer-below",!0);n._imageLowerLayer=a.append("g").classed("imagelayer",!0),n._shapeLowerLayer=a.append("g").classed("shapelayer",!0),n._cartesianlayer=n._paper.append("g").classed("cartesianlayer",!0),n._ternarylayer=n._paper.append("g").classed("ternarylayer",!0);var o=n._paper.append("g").classed("layer-above",!0);n._imageUpperLayer=o.append("g").classed("imagelayer",!0),n._shapeUpperLayer=o.append("g").classed("shapelayer",!0),n._pielayer=n._paper.append("g").classed("pielayer",!0),n._glimages=n._paper.append("g").classed("glimages",!0),n._geoimages=n._paper.append("g").classed("geoimages",!0),n._infolayer=n._toppaper.append("g").classed("infolayer",!0),n._zoomlayer=n._toppaper.append("g").classed("zoomlayer",!0),n._hoverlayer=n._toppaper.append("g").classed("hoverlayer",!0),t.emit("plotly_framework")}var m=t("d3"),v=t("fast-isnumeric"),y=t("../plotly"),x=t("../lib"),b=t("../lib/events"),_=t("../lib/queue"),w=t("../registry"),M=t("../plots/plots"),k=t("../plots/cartesian/graph_interact"),A=t("../plots/polar"),T=t("../components/drawing"),L=t("../components/errorbars"),C=t("../constants/xmlns_namespaces"),z=t("../lib/svg_text_utils"),S=t("./helpers"),O=t("./subroutines");y.plot=function(t,e,n,r){function i(){if(_)return y.addFrames(t,_)}function l(){for(var e=P._basePlotModules,n=0;n=l.length?l[0]:l[t]:l}function a(t){return Array.isArray(s)?t>=s.length?s[0]:s[t]:s}function o(t,e){var n=0;return function(){if(t&&++n===e)return t()}}if(t=S.getGraphDiv(t),!x.isPlotDiv(t))throw new Error("This element is not a Plotly plot: "+t+". It's likely that you've failed to create a plot before animating it. For more details, see https://plot.ly/javascript/animations/");var i=t._transitionData;i._frameQueue||(i._frameQueue=[]),n=M.supplyAnimationDefaults(n);var l=n.transition,s=n.frame;return void 0===i._frameWaitingCnt&&(i._frameWaitingCnt=0),new Promise(function(s,c){function u(){if(0!==i._frameQueue.length){for(;i._frameQueue.length;){var e=i._frameQueue.pop();e.onInterrupt&&e.onInterrupt()}t.emit("plotly_animationinterrupted",[])}}function f(e){if(0!==e.length){for(var l=0;li._timeToNext&&h()};e()}function g(t){return Array.isArray(l)?y>=l.length?t.transitionOpts=l[y]:t.transitionOpts=l[0]:t.transitionOpts=l,y++,t}var m,v,y=0,b=[],_=void 0===e||null===e,w=Array.isArray(e),k=!_&&!w&&x.isPlainObject(e);if(k)b.push({type:"object",data:g(x.extendFlat({},e))});else if(_||"string"==typeof e)for(m=0;m0&&LL)&&C.push(v);b=C}}b.length>0?f(b):(t.emit("plotly_animated"),s())})},y.addFrames=function(t,e,n){if(t=S.getGraphDiv(t),null===e||void 0===e)return Promise.resolve();if(!x.isPlotDiv(t))throw new Error("This element is not a Plotly plot: "+t+". It's likely that you've failed to create a plot before adding frames. For more details, see https://plot.ly/javascript/animations/");var r,a,o,i,l=t._transitionData._frames,s=t._transitionData._frameHash;if(!Array.isArray(e))throw new Error("addFrames failure: frameList must be an Array of frame definitions"+e);var c=l.length+2*e.length,u=[];for(r=e.length-1;r>=0;r--)u.push({frame:M.supplyFrameDefaults(e[r]),index:n&&void 0!==n[r]&&null!==n[r]?n[r]:c+r});u.sort(function(t,e){return t.index>e.index?-1:t.index=0;r--){if(a=u[r].frame,!a.name)for(;s[a.name="frame "+t._transitionData._counter++];);if(s[a.name]){for(o=0;o=0;n--)r=e[n],o.push({type:"delete",index:r}),i.unshift({type:"insert",index:r,value:a[r]});var l=M.modifyFrames,s=M.modifyFrames,c=[t,i],u=[t,o];return _&&_.add(t,l,c,s,u),M.modifyFrames(t,o)},y.purge=function(t){t=S.getGraphDiv(t);var e=t._fullLayout||{},n=t._fullData||[];return M.cleanPlot([],{},n,e),M.purge(t),b.purge(t),e._container&&e._container.remove(),delete t._context,delete t._replotPending,delete t._mouseDownTime,delete t._hmpixcount,delete t._hmlumcount,t}},{"../components/drawing":50,"../components/errorbars":56,"../constants/xmlns_namespaces":109,"../lib":122,"../lib/events":116,"../lib/queue":130,"../lib/svg_text_utils":134,"../plotly":145,"../plots/cartesian/graph_interact":157,"../plots/plots":186,"../plots/polar":189,"../registry":194,"./helpers":136,"./subroutines":142,d3:10,"fast-isnumeric":13}],138:[function(t,e,n){"use strict";function r(t,n){try{t._fullLayout._paper.style("background",n)}catch(t){e.exports.logging>0&&console.error(t)}}e.exports={staticPlot:!1,editable:!1,editableMainTitle:!0,editableAxisXTitle:!0,editableAxisX2Title:!0,editableAxisYTitle:!0,editableAxisY2Title:!0,autosizable:!1,queueLength:0,fillFrame:!1,frameMargins:0,scrollZoom:!1,doubleClick:"reset+autosize",showTips:!0,showLink:!1,sendData:!0,linkText:"Edit chart",showSources:!1,displayModeBar:"hover",modeBarButtonsToRemove:[],modeBarButtonsToAdd:[],modeBarButtons:!1,displaylogo:!0,plotGlPixelRatio:2,setBackground:r,topojsonURL:"https://cdn.plot.ly/",mapboxAccessToken:null,logging:!1,globalTransforms:[]}},{}],139:[function(t,e,n){"use strict";function r(t){var e,n;"area"===t?(e={attributes:y},n={}):(e=d.modules[t]._module,n=e.basePlotModule);var r={};r.type=null,_(r,p),_(r,e.attributes),n.attributes&&_(r,n.attributes),r.type=t;var a={meta:e.meta||{},attributes:i(r)};if(e.layoutAttributes){var o={};_(o,e.layoutAttributes),a.layoutAttributes=i(o)}return a}function a(){var t={};return _(t,g),Object.keys(d.subplotsRegistry).forEach(function(e){var n=d.subplotsRegistry[e];if(n.layoutAttributes)if("cartesian"===n.name)u(t,n,"xaxis"),u(t,n,"yaxis");else{var r="subplot"===n.attr?n.name:n.attr;u(t,n,r)}}),t=c(t),Object.keys(d.componentsRegistry).forEach(function(e){var n=d.componentsRegistry[e];n.layoutAttributes&&(Array.isArray(n.layoutNodes)?n.layoutNodes.forEach(function(e){f(t,n,e+n.name)}):f(t,n,n.name))}),{layoutAttributes:i(t)}}function o(t){var e=d.transformsRegistry[t];return{attributes:i(e.attributes)}}function i(t){return l(t),s(t),t}function l(t){function e(t){return{valType:"string"}}function r(t,r,a){n.isValObject(t)?"data_array"===t.valType?(t.role="data",a[r+"src"]=e(r)):t.arrayOk===!0&&(a[r+"src"]=e(r)):h.isPlainObject(t)&&(t.role="object")}n.crawl(t,r)}function s(t){function e(t,e,n){if(t){var r=t[M];r&&(delete t[M],n[e]={items:{}},n[e].items[r]=t,n[e].role="object")}}n.crawl(t,e)}function c(t){return b(t,{radialaxis:x.radialaxis,angularaxis:x.angularaxis}),b(t,x.layout),t}function u(t,e,n){var r=h.nestedProperty(t,n),a=_({},e.layoutAttributes);a[w]=!0,r.set(a)}function f(t,e,n){var r=h.nestedProperty(t,n),a=_(r.get()||{},e.layoutAttributes);r.set(a)}var d=t("../registry"),h=t("../lib"),p=t("../plots/attributes"),g=t("../plots/layout_attributes"),m=t("../plots/frame_attributes"),v=t("../plots/animation_attributes"),y=t("../plots/polar/area_attributes"),x=t("../plots/polar/axis_attributes"),b=h.extendFlat,_=h.extendDeep,w="_isSubplotObj",M="_isLinkedToArray",k="_deprecated",A=[w,M,k];n.IS_SUBPLOT_OBJ=w,n.IS_LINKED_TO_ARRAY=M,n.DEPRECATED=k,n.UNDERSCORE_ATTRS=A,n.get=function(){var t={};d.allTypes.concat("area").forEach(function(e){t[e]=r(e)});var e={};return Object.keys(d.transformsRegistry).forEach(function(t){e[t]=o(t)}),{defs:{valObjects:h.valObjects,metaKeys:A.concat.role},traces:t,layout:a(),transforms:e,frames:i(m),animation:i(v)}},n.crawl=function(t,e,r){var a=r||0;Object.keys(t).forEach(function(r){var o=t[r];A.indexOf(r)===-1&&(e(o,r,t,a),n.isValObject(o)||h.isPlainObject(o)&&n.crawl(o,e,a+1))})},n.isValObject=function(t){return t&&void 0!==t.valType},n.findArrayAttributes=function(t){function e(e,n,i,l){o=o.slice(0,l).concat([n]);var s="data_array"===e.valType||e.arrayOk===!0;if(s){var c=r(o),u=h.nestedProperty(t,c).get();Array.isArray(u)&&a.push(c)}}function r(t){return t.join(".")}var a=[],o=[];if(n.crawl(t._module.attributes,e),t.transforms)for(var i=t.transforms,l=0;l1)};d(e.width)&&d(e.height)||r(new Error("Height and width should be pixel values."));var h=s(t,{format:"png",height:e.height,width:e.width}),p=h.gd;p.style.position="absolute",p.style.left="-5000px",document.body.appendChild(p);var g=l.getRedrawFunc(p);o.plot(p,h.data,h.layout,h.config).then(g).then(f).then(function(t){n(t)}).catch(function(t){r(t)})});return n}var a=t("fast-isnumeric"),o=t("../plotly"),i=t("../lib"),l=t("../snapshot/helpers"),s=t("../snapshot/cloneplot"),c=t("../snapshot/tosvg"),u=t("../snapshot/svgtoimg");e.exports=r},{"../lib":122,"../plotly":145,"../snapshot/cloneplot":195,"../snapshot/helpers":198,"../snapshot/svgtoimg":200,"../snapshot/tosvg":202,"fast-isnumeric":13}],144:[function(t,e,n){"use strict";function r(t,e,n,a,o,c){c=c||[];for(var u=Object.keys(t),d=0;d1&&s.push(i("object","layout"))),d.supplyDefaults(c);for(var u=c._fullData,m=n.length,v=0;vu&&e10||"01-01"!==r.substr(5)?t._tickround="d":t._tickround=+e.substr(1)%12===0?"y":"m";else if(e>=O&&a<=10||e>=15*O)t._tickround="d";else if(e>=E&&a<=16||e>=P)t._tickround="M";else if(e>=N&&a<=19||e>=E)t._tickround="S";else{var o=w.ms2DateTime(n+e).replace(/^-/,"").length;t._tickround=Math.max(a,o)-20}}else if(x(e)||"L"===e.charAt(0)){var i=t.range.map(t.r2d||Number);x(e)||(e=Number(e.substr(1))),t._tickround=2-Math.floor(Math.log(e)/Math.LN10+.01);var l=Math.max(Math.abs(i[0]),Math.abs(i[1])),s=Math.floor(Math.log(l)/Math.LN10+.01);Math.abs(s)>3&&("SI"===t.exponentformat||"B"===t.exponentformat?t._tickexponent=3*Math.round((s-1)/3):t._tickexponent=s)}else t._tickround=null}function i(t,e){var n=t.match(W),r=new Date(e);if(n){var a=Math.min(+n[1]||6,6),o=String(e/1e3%1+2.0000005).substr(2,a).replace(/0+$/,"")||"0";return y.time.format(t.replace(W,o))(r)}return y.time.format(t)(r)}function l(t,e,n){var r=t.tickfont||t._gd._fullLayout.font;return{x:e,dx:0,dy:0,text:n||"",fontSize:r.size,font:r.family,fontColor:r.color}}function s(t,e,n,r){var a,o,l=e.x,s=t._tickround,c=s,u=new Date(l);n&&t.hoverformat?o=i(t.hoverformat,l):t.tickformat?o=i(t.tickformat,l):(r&&(x(s)?s+=2:s={y:"m",m:"d",d:"M",M:"S",S:2}[s]),"y"===s?o=V(u):"m"===s?o=G(u):"d"===s?(n||(a="
"+V(u)),o=U(u)):(n||(a="
"+X(u)),o=Y(u),"M"!==s?(o+=Z(u),"S"!==s&&(o+=d(y.round(v(l/1e3,1),4),t,"none",n).substr(1))):"d"===c&&(o=U(u)+" "+o))),!a||t._inCalcTicks&&a===t._prevSuffix||(o+=a,t._prevSuffix=a),e.text=o}function c(t,e,n,r,a){var o=t.dtick,i=e.x;if(!r||"string"==typeof o&&"L"===o.charAt(0)||(o="L3"),t.tickformat||"string"==typeof o&&"L"===o.charAt(0))e.text=d(Math.pow(10,i),t,a,r);else if(x(o)||"D"===o.charAt(0)&&v(i+.01,1)<.1)if(["e","E","power"].indexOf(t.exponentformat)!==-1){var l=Math.round(i);0===l?e.text=1:1===l?e.text="10":l>1?e.text="10"+l+"":e.text="10\u2212"+-l+"",e.fontSize*=1.25}else e.text=d(Math.pow(10,i),t,"","fakehover"),"D1"===o&&"y"===t._id.charAt(0)&&(e.dy-=e.fontSize/6);else{if("D"!==o.charAt(0))throw"unrecognized dtick "+String(o);e.text=String(Math.round(Math.pow(10,v(i,1)))),e.fontSize*=.75}if("D1"===t.dtick){var s=String(e.text).charAt(0);"0"!==s&&"1"!==s||("y"===t._id.charAt(0)?e.dx-=e.fontSize/4:(e.dy+=e.fontSize/2,e.dx+=(t.range[1]>t.range[0]?1:-1)*e.fontSize*(i<0?.5:.25)))}}function u(t,e){var n=t._categories[Math.round(e.x)];void 0===n&&(n=""),e.text=String(n)}function f(t,e,n,r,a){"all"===t.showexponent&&Math.abs(e.x/t.dtick)<1e-6&&(a="hide"),e.text=d(e.x,t,a,r)}function d(t,e,n,r){var a=t<0,i=e._tickround,l=n||e.exponentformat||"B",s=e._tickexponent,c=e.tickformat,u=e.separatethousands;if(r){var f={exponentformat:e.exponentformat,dtick:"none"===e.showexponent?e.dtick:x(t)?Math.abs(t)||1:1,range:"none"===e.showexponent?e.range.map(e.r2d):[0,t||1]};o(f),i=(Number(f._tickround)||0)+4,s=f._tickexponent,e.hoverformat&&(c=e.hoverformat)}if(c)return y.format(c)(t).replace(/-/g,"\u2212");var d=Math.pow(10,-i)/2;if("none"===l&&(s=0),t=Math.abs(t),t12||s<-15)?t+="e"+g:"E"===l?t+="E"+g:"power"===l?t+="\xd710"+g+"":"B"===l&&9===s?t+="B":"SI"!==l&&"B"!==l||(t+=Q[s/3+5])}return a?"\u2212"+t:t}function h(t,e){var n,r,a=[];for(n=0;n1)for(r=1;r2e-6||((n-t._forceTick0)/t._minDtick%1+1.000001)%1>2e-6)&&(t._minDtick=0)):t._minDtick=0},D.getAutoRange=function(t){var e,n=[],r=t._min[0].val,a=t._max[0].val;for(e=1;e0&&u>0&&f/u>d&&(s=i,c=l,d=f/u);if(r===a){var g=r-1,m=r+1;n="tozero"===t.rangemode?r<0?[g,0]:[0,m]:"nonnegative"===t.rangemode?[Math.max(0,g),Math.max(0,m)]:[g,m]}else d&&("linear"!==t.type&&"-"!==t.type||("tozero"===t.rangemode?(s.val>=0&&(s={val:0,pad:0}),c.val<=0&&(c={val:0,pad:0})):"nonnegative"===t.rangemode&&(s.val-d*s.pad<0&&(s={val:0,pad:0}),c.val<0&&(c={val:1,pad:0})),d=(c.val-s.val)/(t._length-s.pad-c.pad)),n=[s.val-d*s.pad,c.val+d*c.pad]);return n[0]===n[1]&&("tozero"===t.rangemode?n=n[0]<0?[n[0],0]:n[0]>0?[0,n[0]]:[0,1]:(n=[n[0]-1,n[0]+1],"nonnegative"===t.rangemode&&(n[0]=Math.max(0,n[0])))),h&&n.reverse(),n.map(t.l2r||Number)},D.doAutoRange=function(t){t._length||t.setScale();var e=t._min&&t._max&&t._min.length&&t._max.length;if(t.autorange&&e){t.range=D.getAutoRange(t);var n=t._gd.layout[t._name];n||(t._gd.layout[t._name]=n={}),n!==t&&(n.range=t.range.slice(),n.autorange=t.autorange)}},D.saveRangeInitial=function(t,e){for(var n=D.list(t,"",!0),r=!1,a=0;a=d?h=!1:l.val>=c&&l.pad<=d&&(t._min.splice(i,1),i--);h&&t._min.push({val:c,pad:y&&0===c?0:d})}if(r(u)){for(h=!0,i=0;i=u&&l.pad>=f?h=!1:l.val<=u&&l.pad<=f&&(t._max.splice(i,1),i--);h&&t._max.push({val:u,pad:y&&0===u?0:f})}}}if((t.autorange||t._needsExpand)&&e){t._min||(t._min=[]),t._max||(t._max=[]),n||(n={}),t._m||t.setScale();var o,i,l,s,c,u,f,d,h,p,g,m=e.length,v=n.padded?.05*t._length:0,y=n.tozero&&("linear"===t.type||"-"===t.type),b=r((t._m>0?n.ppadplus:n.ppadminus)||n.ppad||0),_=r((t._m>0?n.ppadminus:n.ppadplus)||n.ppad||0),w=r(n.vpadplus||n.vpad),M=r(n.vpadminus||n.vpad);for(o=0;o<6;o++)a(o);for(o=m-1;o>5;o--)a(o)}},D.autoBin=function(t,e,n,r){function a(t){return(1+100*(t-h)/f.dtick)%100<2}var o=w.aggNums(Math.min,null,t),i=w.aggNums(Math.max,null,t);if("category"===e.type)return{start:o-.5,end:i+.5,size:1};var l;if(n)l=(i-o)/n;else{var s=w.distinctVals(t),c=Math.pow(10,Math.floor(Math.log(s.minDiff)/Math.LN10)),u=c*w.roundUp(s.minDiff/c,[.9,1.9,4.9,9.9],!0);l=Math.max(u,2*w.stdev(t)/Math.pow(t.length,r?.25:.4))}var f;f="log"===e.type?{type:"linear",range:[o,i],r2l:Number}:{type:e.type,range:[o,i].map(e.l2r),r2l:e.r2l},D.autoTicks(f,l);var d,h=D.tickIncrement(D.tickFirst(f),f.dtick,"reverse");if("number"==typeof f.dtick){for(var p=0,g=0,m=0,v=0,y=0;y.3*b||a(o)||a(i))){var _=f.dtick/2;h+=h+_0&&t.dtick<2*t._minDtick&&(t.dtick=t._minDtick,t.tick0=t.l2r(t._forceTick0))}t.tick0||(t.tick0="date"===t.type?"2000-01-01":0),o(t),t._tmin=D.tickFirst(t);var i=e[1]=s:c<=s)&&(l.push(c),!(l.length>1e3));c=D.tickIncrement(c,t.dtick,i));t._tmax=l[l.length-1],t._prevSuffix="",t._inCalcTicks=!0;for(var u=new Array(l.length),f=0;fz?(e/=z,n=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick="M"+12*a(e,n,j)):r>S?(e/=S,t.dtick="M"+a(e,1,I)):r>O?(t.dtick=a(e,O,B),t.tick0="2000-01-02"):r>P?t.dtick=a(e,P,I):r>E?t.dtick=a(e,E,F):r>N?t.dtick=a(e,N,F):(n=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick=a(e,n,j))}else if("log"===t.type){t.tick0=0;var o=t.range.map(t.r2l);if(e>.7)t.dtick=Math.ceil(e);else if(Math.abs(o[1]-o[0])<1){var i=1.5*Math.abs((o[1]-o[0])/e);e=Math.abs(Math.pow(10,o[1])-Math.pow(10,o[0]))/i,n=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick="L"+a(e,n,j)}else t.dtick=e>.3?"D2":"D1"}else"category"===t.type?(t.tick0=0,t.dtick=Math.ceil(Math.max(e,1))):(t.tick0=0,n=Math.pow(10,Math.floor(Math.log(e)/Math.LN10)),t.dtick=a(e,n,j));if(0===t.dtick&&(t.dtick=1),!x(t.dtick)&&"string"!=typeof t.dtick){var l=t.dtick;throw t.dtick=1,"ax.dtick error: "+String(l)}},D.tickIncrement=function(t,e,n){var r=n?-1:1;if(x(e))return t+r*e;var a=e.charAt(0),o=r*Number(e.substr(1));if("M"===a){var i=new Date(t);return i.setMonth(i.getMonth()+o)}if("L"===a)return Math.log(Math.pow(10,t)+o)/Math.LN10;if("D"===a){var l="D2"===e?H:q,s=t+.01*r,c=w.roundUp(v(s,1),l,n);return Math.floor(s)+Math.log(y.round(Math.pow(10,c),1))/Math.LN10}throw"unrecognized dtick "+String(e)},D.tickFirst=function(t){var e=t.r2l||Number,n=t.range.map(e),r=n[1]o:f1&&er){var o=t.text,i=Math.round(r/(a/o.length)),l=Math.floor(i/2),s=i-l-1;o=o.substr(0,l)+"\u2026"+o.substr(-s);var c=e.select("text");c.text(o),e.insert("title","text").text(t.text)}})}function u(){var e,n,r=c._boundingBox,a=0,o=0;if("x"===c._id.charAt(0)?(e="height","2"===c._id.charAt(1)?(o=1,n="t"):n="b"):"y"===c._id.charAt(0)&&(e="width","2"===c._id.charAt(1)?(a=1,n="r"):n="l"),e&&n){var i=r[e];if(c._titleElement){var l=c._titleElement.node().getBoundingClientRect();i+=l[e]+2}var s=.5*t._fullLayout[e];i=Math.min(i,s);var u={x:a,y:o,l:0,r:0,b:0,t:0};u[n]=i,_.autoMargin(t,c._name,u)}}function f(){c._boundingBox=n.node().getBoundingClientRect()}n.style("pointer-events","all");var d=n.selectAll("g."+z).data(L,C);if(!c.showticklabels||!x(r))return d.remove(),void i(e);var p,v,b,k,A;"x"===m?(A="bottom"===q?1:-1,p=function(t){return t.dx+N*A},k=r+(E+P)*A,v=function(t){return t.dy+k+t.fontSize*("bottom"===q?1:-.5)},b=function(t){return x(t)&&0!==t&&180!==t?t*A<0?"end":"start":"middle"}):(A="right"===q?1:-1,v=function(t){return t.dy+t.fontSize/2-N*A},p=function(t){return t.dx+r+(E+P+(90===Math.abs(c.tickangle)?t.fontSize/2:0))*A},b=function(t){return x(t)&&90===Math.abs(t)?"middle":"right"===q?"start":"end"});var S=0,O=0,D=[],R=d.enter().append("g").classed(z,1);R.append("text").attr("text-anchor","middle").each(function(e){var n=y.select(this),r=t._promises.length;n.call(T.setPosition,p(e),v(e)).call(T.font,e.font,e.fontSize,e.fontColor).text(e.text).call(M.convertToTspans),r=t._promises[r],r?D.push(t._promises.pop().then(function(){a(n,c.tickangle)})):a(n,c.tickangle)}),d.exit().remove(),d.each(function(t){S=Math.max(S,t.fontSize)}),a(d,c._lastangle||c.tickangle);var j=w.syncOrAsync([o,l,f,u]);return j&&j.then&&t._promises.push(j),j}function i(e){if(!n){var r,a,o,i,l=R.getFromId(t,e),s=y.select(t).selectAll("g."+e+"tick"),c={selection:s,side:l.side},f=e.charAt(0),d=t._fullLayout._size,h=1.5,p=l.titlefont.size;if(s.size()){var g=y.select(s.node().parentNode).attr("transform").match(/translate\(([-\.\d]+),([-\.\d]+)\)/);g&&(c.offsetLeft=+g[1],c.offsetTop=+g[2])}"x"===f?(a="free"===l.anchor?{_offset:d.t+(1-(l.position||0))*d.h,_length:0}:R.getFromId(t,l.anchor),o=l._offset+l._length/2,i=a._offset+("top"===l.side?-10-p*(h+(l.showticklabels?1:0)):a._length+10+p*(h+(l.showticklabels?1.5:.5))),l.rangeslider&&l.rangeslider.visible&&l._boundingBox&&(i+=(u.height-u.margin.b-u.margin.t)*l.rangeslider.thickness+l._boundingBox.height),c.side||(c.side="bottom")):(a="free"===l.anchor?{_offset:d.l+(l.position||0)*d.w,_length:0}:R.getFromId(t,l.anchor),i=l._offset+l._length/2,o=a._offset+("right"===l.side?a._length+10+p*(h+(l.showticklabels?1:.5)):-10-p*(h+(l.showticklabels?.5:0))),r={rotate:"-90",offset:0},c.side||(c.side="left")),k.draw(t,e+"title",{propContainer:l,propName:l._name+".title",dfltName:f.toUpperCase()+" axis",avoid:c,transform:r,attributes:{x:o,y:i,"text-anchor":"middle"}})}}function l(t,e){return t.visible===!0&&t.xaxis+t.yaxis===e&&(!(!b.traceIs(t,"bar")||t.orientation!=={x:"h",y:"v"}[m])||t.fill&&t.fill.charAt(t.fill.length-1)===m)}function s(e,n,a){var o=e.gridlayer,i=e.zerolinelayer,s=e["hidegrid"+m]?[]:V,u=c._gridpath||"M0,0"+("x"===m?"v":"h")+n._length,f=o.selectAll("path."+S).data(c.showgrid===!1?[]:s,C);if(f.enter().append("path").classed(S,1).classed("crisp",1).attr("d",u).each(function(t){c.zeroline&&("linear"===c.type||"-"===c.type)&&Math.abs(t.x)2*r}function o(t){for(var e,n=Math.max(1,(t.length-1)/1e3),r=0,a=0,o=0;o2*r}var i=t("fast-isnumeric"),l=t("../../lib"),s=t("../../constants/numerical").BADNUM;e.exports=function(t){return a(t)?"date":o(t)?"category":r(t)?"linear":"-"}},{"../../constants/numerical":107,"../../lib":122,"fast-isnumeric":13}],152:[function(t,e,n){"use strict";function r(t,e){if("-"===t.type){var n=t._id,r=n.charAt(0);n.indexOf("scene")!==-1&&(n=r);var l=i(e,n,r);if(l){if("histogram"===l.type&&r==={v:"y",h:"x"}[l.orientation||"v"])return void(t.type="linear");if(o(l,r)){for(var s,u=a(l),f=[],d=0;d0;o&&(r="array");var i=n("categoryorder",r);"array"===i&&n("categoryarray"),o||"array"!==i||(e.categoryorder="trace")}}},{}],155:[function(t,e,n){"use strict";e.exports={idRegex:{x:/^x([2-9]|[1-9][0-9]+)?$/,y:/^y([2-9]|[1-9][0-9]+)?$/},attrRegex:{x:/^xaxis([2-9]|[1-9][0-9]+)?$/,y:/^yaxis([2-9]|[1-9][0-9]+)?$/},xAxisMatch:/^xaxis[0-9]*$/,yAxisMatch:/^yaxis[0-9]*$/,AX_ID_PATTERN:/^[xyz][0-9]*$/,AX_NAME_PATTERN:/^[xyz]axis[0-9]*$/,DBLCLICKDELAY:300,MINDRAG:8,MINSELECT:12,MINZOOM:20,DRAGGERSIZE:20,MAXDIST:20,YANGLE:60,HOVERARROWSIZE:6,HOVERTEXTPAD:3,HOVERFONTSIZE:13,HOVERFONT:"Arial, sans-serif",HOVERMINTIME:50,BENDPX:1.5,REDRAWDELAY:50,DFLTRANGEX:[-1,6],DFLTRANGEY:[-1,4],DFLTRANGEDATE:["2000-01-01","2001-01-01"]}},{}],156:[function(t,e,n){"use strict";function r(t,e){var n,r=t.range[e],a=Math.abs(r-t.range[1-e]);return"date"===t.type?r:"log"===t.type?(n=Math.ceil(Math.max(0,-Math.log(a)/Math.LN10))+3,l.format("."+n+"g")(Math.pow(10,r))):(n=Math.floor(Math.log(Math.abs(r))/Math.LN10)-Math.floor(Math.log(a)/Math.LN10)+4,l.format("."+String(n)+"g")(r))}function a(t,e){return t?"nsew"===t?"pan"===e?"move":"crosshair":t.toLowerCase()+"-resize":"pointer"}function o(t){l.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}function i(t){var e=["lasso","select"];return e.indexOf(t)!==-1}var l=t("d3"),s=t("tinycolor2"),c=t("../../plotly"),u=t("../../registry"),f=t("../../lib"),d=t("../../lib/svg_text_utils"),h=t("../../components/color"),p=t("../../components/drawing"),g=t("../../lib/setcursor"),m=t("../../components/dragelement"),v=t("./axes"),y=t("./select"),x=t("./constants"),b=!0;e.exports=function(t,e,n,l,_,w,M,k){function A(t,e){for(var n=0;n.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("transform","translate("+gt+", "+mt+")").attr("d",ct+"Z"),ht=pt.append("path").attr("class","zoombox-corners").style({fill:h.background,stroke:h.defaultLine,"stroke-width":1,opacity:0}).attr("transform","translate("+gt+", "+mt+")").attr("d","M0,0Z"),C()}function C(){pt.selectAll(".select-outline").remove()}function z(e,n){if(t._transitioningWithDuration)return!1;var r=Math.max(0,Math.min(V,e+ot)),a=Math.max(0,Math.min(G,n+it)),o=Math.abs(r-ot),i=Math.abs(a-it),l=Math.floor(Math.min(i,o,X)/2);lt.l=Math.min(ot,r),lt.r=Math.max(ot,r),lt.t=Math.min(it,a),lt.b=Math.max(it,a),!K||i.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),ht.transition().style("opacity",1).duration(200),ut=!0)}function S(t,e,n){var r,a,o,i=[];for(r=0;rzoom back out","long"),b=!1),l.pre=!1,t.emit("plotly_zoom",l))}function P(e,n){var a=1===(M+k).length;if(e)j();else if(2!==n||a){if(1===n&&a){var o=M?H[0]:q[0],i="s"===M||"w"===k?0:1,l=o._name+".range["+i+"]",s=r(o,i),u="left",f="middle";if(o.fixedrange)return;M?(f="n"===M?"top":"bottom","right"===o.side&&(u="right")):"e"===k&&(u="right"),nt.call(d.makeEditable,null,{immediate:!0,background:F.paper_bgcolor,text:String(s),fill:o.tickfont?o.tickfont.color:"#444",horizontalAlign:u,verticalAlign:f}).on("edit",function(e){var n=o.d2r(e);void 0!==n&&c.relayout(t,l,n)})}}else R()}function E(e){function n(t,e,n){function r(e){return t.l2r(o+(e-o)*n)}if(!t.fixedrange){var a=t.range.map(t.r2l),o=a[0]+(a[1]-a[0])*e;t.range=a.map(r)}}if(t._context.scrollZoom||F._enablescrollzoom){if(t._transitioningWithDuration)return f.pauseEvent(e);var r=t.querySelector(".plotly");if(T(),!(r.scrollHeight-r.clientHeight>10||r.scrollWidth-r.clientWidth>10)){clearTimeout(yt);var a=-e.deltaY;if(isFinite(a)||(a=e.wheelDelta/10),!isFinite(a))return void f.log("Did not find wheel motion attributes: ",e);var o,i=Math.exp(-Math.min(Math.max(a,-20),20)/100),l=bt.draglayer.select(".nsewdrag").node().getBoundingClientRect(),s=(e.clientX-l.left)/l.width,c=vt[0]+vt[2]*s,u=(l.bottom-e.clientY)/l.height,d=vt[1]+vt[3]*(1-u);if(k){for(o=0;o=0?Math.min(t,.9):1/(1/Math.max(t,-.3)+3.222))}function o(t,e,n){for(var r,o,i=1-e,l=0;l0;r--)n.push(e);return n}function a(t,e){for(var n=[],r=0;rZ.width||Y<0||Y>Z.height)return _.unhoverRaw(t,e)}else X="xpx"in e?e.xpx:k[0]._length/2,Y="ypx"in e?e.ypx:A[0]._length/2;if(O="xval"in e?r(o,e.xval):a(k,X),P="yval"in e?r(o,e.yval):a(A,Y),!g(O[0])||!g(P[0]))return m.warn("Fx.hover failed",e,t),_.unhoverRaw(t,e)}var W=1/0;for(N=0;N1||R.hoverinfo.indexOf("name")!==-1?R.name:void 0,index:!1,distance:Math.min(W,M.MAXDIST),color:x.defaultLine,x0:void 0,x1:void 0,y0:void 0,y1:void 0,xLabelVal:void 0,yLabelVal:void 0,zLabelVal:void 0,text:void 0},i[j]&&(H.subplot=i[j]._subplot),V=G.length,"array"===F){var Q=e[N];"pointNumber"in Q?(H.index=Q.pointNumber,F="closest"):(F="","xval"in Q&&(B=Q.xval,F="x"),"yval"in Q&&(q=Q.yval,F=F?"closest":"y"))}else B=O[I],q=P[I];if(R._module&&R._module.hoverPoints){var $=R._module.hoverPoints(H,B,q,F);if($)for(var J,K=0;K<$.length;K++)J=$[K],g(J.x0)&&g(J.y0)&&G.push(s(J,S))}else m.log("Unrecognized trace type in hover:",R);"closest"===S&&G.length>V&&(G.splice(0,V),W=G[0].distance)}if(0===G.length)return _.unhoverRaw(t,e);var tt="y"===S&&U.length>1;G.sort(function(t,e){return t.distance-e.distance});var et=x.combine(i.plot_bgcolor||x.background,i.paper_bgcolor),nt={hovermode:S,rotateLabels:tt,bgColor:et,container:i._hoverlayer,outerContainer:i._paperdiv},rt=c(G,nt,e,t.layout.hoverFollowsMouse);u(G,tt?"xa":"ya"),f(rt,tt);var at=t._hoverdata,ot=[];for(E=0;E128?"#000":x.background;if(t.name&&void 0===t.zLabelVal){var d=document.createElement("p");d.innerHTML=t.name,a=d.textContent||"",a.length>15&&(a=a.substr(0,12)+"...")}void 0!==t.extraText&&(o+=t.extraText),void 0!==t.zLabel?(void 0!==t.xLabel&&(o+="x: "+t.xLabel+"
"),void 0!==t.yLabel&&(o+="y: "+t.yLabel+"
"),o+=(o?"z: ":"")+t.zLabel):C&&t[i+"Label"]===v?o=t[("x"===i?"y":"x")+"Label"]||"":void 0===t.xLabel?void 0!==t.yLabel&&(o=t.yLabel):o=void 0===t.yLabel?t.xLabel:"("+t.xLabel+", "+t.yLabel+")",t.text&&!Array.isArray(t.text)&&(o+=(o?"
":"")+t.text),""===o&&(""===a&&e.remove(),o=a);var g=e.select("text.nums").style("fill",f).call(b.setPosition,0,0).text(o).attr("data-notex",1).call(y.convertToTspans);g.selectAll("tspan.line").call(b.setPosition,0,0);var m=e.select("text.name"),_=0;a&&a!==o?(m.style("fill",u).text(a).call(b.setPosition,0,0).attr("data-notex",1).call(y.convertToTspans),m.selectAll("tspan.line").call(b.setPosition,0,0),_=m.node().getBoundingClientRect().width+2*E):(m.remove(),e.select("rect").remove()),e.select("path").style({fill:u,stroke:f});var w,M,z=g.node().getBoundingClientRect(),S=t.xa._offset+(t.x0+t.x1)/2,O=t.ya._offset+(t.y0+t.y1)/2,N=Math.abs(t.x1-t.x0),D=Math.abs(t.y1-t.y0),R=z.width+P+E+_;t.ty0=k-z.top,t.bx=z.width+2*E,t.by=z.height+2*E,t.anchor="start",t.txwidth=z.width,t.tx2width=_,t.offset=0,r&&"closest"===i&&n&&n.layerX&&n.layerY&&(S=n.layerX,O=n.layerY),l?(t.pos=S,w=O+D/2+R<=T,M=O-D/2-R>=0,"top"!==t.idealAlign&&w||!M?w?(O+=D/2,t.anchor="start"):t.anchor="middle":(O-=D/2,t.anchor="end")):(t.pos=O,w=S+N/2+R<=A,M=S-N/2-R>=0,"left"!==t.idealAlign&&w||!M?w?(S+=N/2,t.anchor="start"):t.anchor="middle":(S-=N/2,t.anchor="end")),g.attr("text-anchor",t.anchor),_&&m.attr("text-anchor",t.anchor),e.attr("transform","translate("+S+","+O+")"+(l?"rotate("+L+")":""))}),O}function u(t,e){function n(t){var e=t[0],n=t[t.length-1];if(a=e.pmin-e.pos-e.dp+e.size,o=n.pos+n.dp+n.size-e.pmax,a>.01){for(l=t.length-1;l>=0;l--)t[l].dp+=a;r=!1}if(!(o<.01)){if(a<-.01){for(l=t.length-1;l>=0;l--)t[l].dp-=o;r=!1}if(r){var c=0;for(i=0;ie.pmax&&c++;for(i=t.length-1;i>=0&&!(c<=0);i--)s=t[i],s.pos>e.pmax-1&&(s.del=!0,c--);for(i=0;i=0;l--)t[l].dp-=o;for(i=t.length-1;i>=0&&!(c<=0);i--)s=t[i],s.pos+s.dp+s.size>e.pmax&&(s.del=!0,c--)}}}for(var r,a,o,i,l,s,c,u=0,f=t.map(function(t,n){var r=t[e];return[{i:n,dp:0,pos:t.pos,posref:t.posref,size:t.by*("x"===r._id.charAt(0)?z:1)/2,pmin:r._offset,pmax:r._offset+r._length}]}).sort(function(t,e){return t[0].posref-e[0].posref});!r&&u<=t.length;){for(u++,r=!0,i=0;i.01&&p.pmin===g.pmin&&p.pmax===g.pmax){for(l=h.length-1;l>=0;l--)h[l].dp+=a;for(d.push.apply(d,h),f.splice(i+1,1),c=0,l=d.length-1;l>=0;l--)c+=d[l].dp;for(o=c/d.length,l=d.length-1;l>=0;l--)d[l].dp-=o;r=!1}else i++}f.forEach(n)}for(i=f.length-1;i>=0;i--){var m=f[i];for(l=m.length-1;l>=0;l--){var v=m[l],y=t[v.i];y.offset=v.dp,y.del=v.del}}}function f(t,e){t.each(function(t){var n=h.select(this);if(t.del)return void n.remove();var r="end"===t.anchor?-1:1,a=n.select("text.nums"),o={start:1,end:-1,middle:0}[t.anchor],i=o*(P+E),l=i+o*(t.txwidth+E),s=0,c=t.offset;"middle"===t.anchor&&(i-=t.tx2width/2,l-=t.tx2width/2),e&&(c*=-O,s=t.offset*S),n.select("path").attr("d","middle"===t.anchor?"M-"+t.bx/2+",-"+t.by/2+"h"+t.bx+"v"+t.by+"h-"+t.bx+"Z":"M0,0L"+(r*P+s)+","+(P+c)+"v"+(t.by/2-P)+"h"+r*t.bx+"v-"+t.by+"H"+(r*P+s)+"V"+(c-P)+"Z"),a.call(b.setPosition,i+s,c+t.ty0-t.by/2+E).selectAll("tspan.line").attr({x:a.attr("x"),y:a.attr("y")}),t.tx2width&&(n.select("text.name, text.name tspan.line").call(b.setPosition,l+o*E+s,c+t.ty0-t.by/2+E),n.select("rect").call(b.setRect,l+(o-1)*t.tx2width/2+s,c-t.by/2-1,t.tx2width,t.by+2))})}function d(t,e,n){if(!e.target)return!1;if(!n||n.length!==t._hoverdata.length)return!0;for(var r=n.length-1;r>=0;r--){var a=n[r],o=t._hoverdata[r];if(a.curveNumber!==o.curveNumber||String(a.pointNumber)!==String(o.pointNumber))return!0}return!1}var h=t("d3"),p=t("tinycolor2"),g=t("fast-isnumeric"),m=t("../../lib"),v=t("../../lib/events"),y=t("../../lib/svg_text_utils"),x=t("../../components/color"),b=t("../../components/drawing"),_=t("../../components/dragelement"),w=t("./axes"),M=t("./constants"),k=t("./dragbox"),A=t("../layout_attributes"),T=e.exports={};T.unhover=_.unhover,T.layoutAttributes={},T.supplyLayoutDefaults=function(t,e,n){function r(n,r){return m.coerce(t,e,A,n,r)}r("dragmode");var a;if(e._has("cartesian")){var o=e._isHoriz=T.isHoriz(n);a=o?"y":"x"}else a="closest";r("hovermode",a)},T.isHoriz=function(t){for(var e=!0,n=0;nt._lastHoverTime+M.HOVERMINTIME?(i(t,e,n),void(t._lastHoverTime=Date.now())):void(t._hoverTimer=setTimeout(function(){i(t,e,n),t._lastHoverTime=Date.now(),t._hoverTimer=void 0},M.HOVERMINTIME))},T.getDistanceFunction=function(t,e,n,r){return"closest"===t?r||o(e,n):"x"===t?e:n},T.getClosest=function(t,e,n){if(n.index!==!1)n.index>=0&&n.indexf[1]-.01&&(e.domain=[0,1]),a.noneOrAll(t.domain,e.domain,[0,1])}return e}},{"../../lib":122,"fast-isnumeric":13}],163:[function(t,e,n){"use strict";function r(t){return t._id}var a=t("../../lib/polygon"),o=t("../../components/color"),i=t("./axes"),l=t("./constants"),s=a.filter,c=a.tester,u=l.MINSELECT;e.exports=function(t,e,n,a,f){function d(t){var e="y"===t._id.charAt(0)?1:0;return function(n){return t.p2d(n[e])}}function h(t,e){return t-e}var p,g=a.gd._fullLayout._zoomlayer,m=a.element.getBoundingClientRect(),v=a.plotinfo.xaxis._offset,y=a.plotinfo.yaxis._offset,x=e-m.left,b=n-m.top,_=x,w=b,M="M"+x+","+b,k=a.xaxes[0]._length,A=a.yaxes[0]._length,T=a.xaxes.map(r),L=a.yaxes.map(r),C=a.xaxes.concat(a.yaxes);"lasso"===f&&(p=s([[x,b]],l.BENDPX));var z=g.selectAll("path.select-outline").data([1,2]);z.enter().append("path").attr("class",function(t){return"select-outline select-outline-"+t}).attr("transform","translate("+v+", "+y+")").attr("d",M+"Z");var S,O,P,E,N,D=g.append("path").attr("class","zoombox-corners").style({fill:o.background,stroke:o.defaultLine,"stroke-width":1}).attr("transform","translate("+v+", "+y+")").attr("d","M0,0Z"),R=[],j=a.gd,I=[];for(S=0;S0)return Math.log(e)/Math.LN10;if(e<=0&&n&&t.range&&2===t.range.length){var r=t.range[0],a=t.range[1];return.5*(r+a-3*f*Math.abs(r-a))}return s}function n(t){return Math.pow(10,t)}function i(t){return a(t)?(t=Number(t),t<-l||t>l?s:a(t)?Number(t):s):s}var f=10;t.c2l="log"===t.type?e:i,t.l2c="log"===t.type?n:i,t.l2d=function(e){return t.c2d(t.l2c(e))},t.p2d=function(e){return t.l2d(t.p2l(e))},t.cleanRange=function(e){e||(e="range");var n,r,i=t[e],s=(t._id||"x").charAt(0);if(r="date"===t.type?c.DFLTRANGEDATE:"y"===s?c.DFLTRANGEY:c.DFLTRANGEX,r=r.slice(),!i||2!==i.length)return void(t[e]=r);for("date"===t.type&&(i[0]=o.cleanDate(i[0]),i[1]=o.cleanDate(i[1])),n=0;n<2;n++)if("date"===t.type){if(!o.isDateTime(i[n])){t[e]=r;break}if(i[n]o.MAX_MS&&(i[n]=o.MAX_MS),t.r2l(i[0])===t.r2l(i[1])){var u=o.constrain(t.r2l(i[0]),o.MIN_MS+1e3,o.MAX_MS-1e3);i[0]=t.l2r(u-1e3),i[1]=t.l2r(u+1e3);break}}else{if(!a(i[n])){if(!a(i[1-n])){t[e]=r;break}i[n]=i[1-n]*(n?10:.1)}if(i[n]<-l?i[n]=-l:i[n]>l&&(i[n]=l),i[0]===i[1]){var f=Math.max(1,Math.abs(1e-6*i[0]));i[0]-=f,i[1]+=f}}},t.fraction2r=function(e){var n=t.r2l(t.range[0]),r=t.r2l(t.range[1]);return t.l2r(n+e*(r-n))},t.r2fraction=function(e){var n=t.r2l(t.range[0]),r=t.r2l(t.range[1]);return(t.r2l(e)-n)/(r-n)},t.setScale=function(e){var n=t._gd._fullLayout._size,r=t._id.charAt(0);if(t._categories||(t._categories=[]),t.overlaying){var a=u.getFromId(t._gd,t.overlaying);t.domain=a.domain}var i=e&&t._r?"_r":"range";t.cleanRange(i);var l=t.r2l(t[i][0]),s=t.r2l(t[i][1]);if("y"===r?(t._offset=n.t+(1-t.domain[1])*n.h,t._length=n.h*(t.domain[1]-t.domain[0]),t._m=t._length/(l-s),t._b=-t._m*s):(t._offset=n.l+t.domain[0]*n.w,t._length=n.w*(t.domain[1]-t.domain[0]),t._m=t._length/(s-l),t._b=-t._m*l),!isFinite(t._m)||!isFinite(t._b))throw o.notifier("Something went wrong with axis scaling","long"),t._gd._replotting=!1,new Error("axis scaling")},t.l2p=function(e){return a(e)?r.round(t._b+t._m*e,2):s},t.p2l=function(e){return(e-t._b)/t._m},t.c2p=function(e,n){return t.l2p(t.c2l(e,n))},t.p2c=function(e){return t.l2c(t.p2l(e))},t.r2p=function(e,n){return t.l2p(t.r2l(e,n))},t.p2r=function(e){return t.l2r(t.p2l(e))},t.r2c=function(e){return t.l2c(t.r2l(e))},t.c2r=function(e){return t.l2r(t.c2l(e))},["linear","log","-"].indexOf(t.type)!==-1?(t.c2d=i,t.d2c=o.cleanNumber,"log"===t.type?(t.d2l=function(e,n){return t.c2l(t.d2c(e),n)},t.d2r=t.d2l,t.r2d=t.l2d):(t.d2l=o.cleanNumber,t.d2r=o.cleanNumber,t.r2d=i),t.r2l=i,t.l2r=i):"date"===t.type?(t.c2d=o.ms2DateTime,t.d2c=function(t){var e=o.dateTime2ms(t);if(e===s){if(!a(t))return s;e=Number(t)}return o.constrain(e,o.MIN_MS,o.MAX_MS)},t.d2l=t.d2c,t.r2l=t.d2c,t.l2r=t.c2d,t.d2r=o.identity,t.r2d=o.identity,t.cleanr=function(e){return t.c2d(t.d2c(e))}):"category"===t.type&&(t.c2d=function(e){return t._categories[Math.round(e)]},t.d2c=function(e){null!==e&&void 0!==e&&t._categories.indexOf(e)===-1&&t._categories.push(e);var n=t._categories.indexOf(e);return n===-1?s:n},t.d2l=t.d2c,t.r2l=i,t.l2r=i,t.d2r=t.d2c,t.r2d=t.c2d),t.makeCalcdata=function(e,n){var r,a,o;if(n in e)for(r=e[n],a=new Array(r.length),o=0;o0?Number(u):c;else if("string"!=typeof u)e.dtick=c;else{var f=u.charAt(0),d=u.substr(1);d=r(d)?Number(d):0,(d<=0||!("date"===i&&"M"===f&&d===Math.round(d)||"log"===i&&"L"===f||"log"===i&&"D"===f&&(1===d||2===d)))&&(e.dtick=c)}var h="date"===i?"2000-01-01":0,p=n("tick0",h);"date"===i?e.tick0=a.cleanDate(p,h):r(p)&&"D1"!==u&&"D2"!==u?e.tick0=Number(p):e.tick0=h}else{var g=n("tickvals");void 0===g?e.tickmode="auto":n("ticktext")}}},{"../../constants/numerical":107,"../../lib":122,"fast-isnumeric":13}],168:[function(t,e,n){"use strict";var r=t("d3"),a=t("../../plotly"),o=t("../../registry"),i=t("../../lib"),l=t("./axes"),s=/((x|y)([2-9]|[1-9][0-9]+)?)axis$/;e.exports=function(t,e,n,c){function u(t){var e,n,r,a,o,i={};for(e in t)if(n=e.split("."),r=n[0].match(s)){var l=r[1],c=l+"axis";if(a=y[c],o={},Array.isArray(t[e])?o.to=t[e].slice(0):Array.isArray(t[e].range)&&(o.to=t[e].range.slice(0)),!o.to)continue;o.axisName=c,o.length=a._length,x.push(l),i[l]=o}return i}function f(t,e,n){var r,a,o,i=t._plots,l=[];for(r in i){var s=i[r];if(l.indexOf(s)===-1){var c=s.xaxis._id,u=s.yaxis._id,f=s.xaxis.range,d=s.yaxis.range;s.xaxis._r=s.xaxis.range.slice(),s.yaxis._r=s.yaxis.range.slice(),a=n[c]?n[c].to:f,o=n[u]?n[u].to:d,f[0]===a[0]&&f[1]===a[1]&&d[0]===o[0]&&d[1]===o[1]||e.indexOf(c)===-1&&e.indexOf(u)===-1||l.push(s)}}return l}function d(e,n){function r(e,n){for(a=0;an.duration?(g(),T=window.cancelAnimationFrame(v)):T=window.requestAnimationFrame(v)}var y=t._fullLayout,x=[],b=u(e),_=Object.keys(b),w=f(y,_,b);if(!w.length)return!1;var M;c&&(M=c());var k,A,T,L=r.ease(n.easing);return t._transitionData._interruptCallbacks.push(function(){return window.cancelAnimationFrame(T),T=null,m()}),k=Date.now(),T=window.requestAnimationFrame(v),Promise.resolve()}},{"../../lib":122,"../../plotly":145,"../../registry":194,"./axes":150,d3:10}],169:[function(t,e,n){"use strict";function r(t,e,n){var r,a,o,i=!1;if("data"===e.type)r=t._fullData[null!==e.traces?e.traces[0]:0];else{if("layout"!==e.type)return!1;r=t._fullLayout}return a=c.nestedProperty(r,e.prop).get(),o=n[e.type]=n[e.type]||{},o.hasOwnProperty(e.prop)&&o[e.prop]!==a&&(i=!0),o[e.prop]=a,{changed:i,value:a}}function a(t,e){return Array.isArray(e[0])&&1===e[0].length&&"string"==typeof e[0][0]?[{type:"layout",prop:"_currentFrame",value:e[0][0]}]:[]}function o(t,e){var n=[],r=e[0],a={};if("string"==typeof r)a[r]=e[1];else{if(!c.isPlainObject(r))return n;a=r}return l(a,function(t,e,r){n.push({type:"layout",prop:t,value:r})},"",0),n}function i(t,e){var n,r,a,o,i=[];if(r=e[0],a=e[1],n=e[2],o={},"string"==typeof r)o[r]=a;else{if(!c.isPlainObject(r))return i;o=r,void 0===n&&(n=a)}return void 0===n&&(n=null),l(o,function(e,r,a){var o;if(Array.isArray(a)){var l=Math.min(a.length,t.data.length);n&&(l=Math.min(l,n.length)),o=[];for(var s=0;s0?".":"")+a;c.isPlainObject(o)?l(o,e,i,r+1):e(i,a,o)}})}var s=t("../plotly"),c=t("../lib");n.manageCommandObserver=function(t,e,a,o){var i={},l=!0;e&&e._commandObserver&&(i=e._commandObserver),i.cache||(i.cache={}),i.lookupTable={};var s=n.hasSimpleAPICommandBindings(t,a,i.lookupTable);if(e&&e._commandObserver){if(s)return i;if(e._commandObserver.remove)return e._commandObserver.remove(),e._commandObserver=null,i}if(s){r(t,s,i.cache),i.check=function(){if(l){var e=r(t,s,i.cache);return e.changed&&o&&void 0!==i.lookupTable[e.value]&&(i.disable(),Promise.resolve(o({value:e.value,type:s.type,prop:s.prop,traces:s.traces,index:i.lookupTable[e.value]})).then(i.enable,i.enable)),e.changed}};for(var u=["plotly_relayout","plotly_redraw","plotly_restyle","plotly_update","plotly_animatingframe","plotly_afterplot"],f=0;fa},M.render=function(){function t(t){var e=n.projection(t.lonlat);return e?"translate("+e[0]+","+e[1]+")":null}function e(t){return n.isLonLatOverEdges(t.lonlat)?"0":"1.0"}var n=this,r=n.framework,a=r.select("g.choroplethlayer"),o=r.select("g.scattergeolayer"),i=n.path;r.selectAll("path.basepath").attr("d",i),r.selectAll("path.graticulepath").attr("d",i),a.selectAll("path.choroplethlocation").attr("d",i),a.selectAll("path.basepath").attr("d",i),o.selectAll("path.js-line").attr("d",i),null!==n.clipAngle?(o.selectAll("path.point").style("opacity",e).attr("transform",t),o.selectAll("text").style("opacity",e).attr("transform",t)):(o.selectAll("path.point").attr("transform",t),o.selectAll("text").attr("transform",t))}},{"../../components/color":27,"../../components/drawing":50,"../../constants/xmlns_namespaces":109,"../../lib/topojson_utils":135,"../../plots/cartesian/axes":150,"../../plots/cartesian/graph_interact":157,"./constants":172,"./projections":180,"./set_scale":181,"./zoom":182,"./zoom_reset":183,d3:10,"topojson-client":17}],174:[function(t,e,n){"use strict";function r(t,e){for(var n=[],r=0;rr^h>r&&n<(d-c)*(r-u)/(h-u)+c&&(a=!a)}return a}function i(t){return t?t/Math.sin(t):1}function l(t){return t>1?P:t<-1?-P:Math.asin(t)}function s(t){return t>1?0:t<-1?O:Math.acos(t)}function c(t,e){var n=(2+P)*Math.sin(e);e/=2;for(var r=0,a=1/0;r<10&&Math.abs(a)>z;r++){var o=Math.cos(e);e-=a=(e+Math.sin(e)*(o+2)-n)/(2*o*(1+o))}return[2/Math.sqrt(O*(4+O))*t*(1+Math.cos(e)),2*Math.sqrt(O/(4+O))*Math.sin(e)]}function u(t,e){function n(n,r){var a=j(n/e,r);return a[0]*=t,a}return arguments.length<2&&(e=t),1===e?j:e===1/0?d:(n.invert=function(n,r){var a=j.invert(n/t,r);return a[0]*=e,a},n)}function f(){var t=2,e=R(u),n=e(t);return n.coefficient=function(n){return arguments.length?e(t=+n):t},n}function d(t,e){return[t*Math.cos(e)/Math.cos(e/=2),2*Math.sin(e)]}function h(t,e){return[3*t/(2*O)*Math.sqrt(O*O/3-e*e),e]}function p(t,e){return[t,1.25*Math.log(Math.tan(O/4+.4*e))]}function g(t){return function(e){var n,r=t*Math.sin(e),a=30;do e-=n=(e+Math.sin(e)-r)/(1+Math.cos(e));while(Math.abs(n)>z&&--a>0);return e/2}}function m(t,e,n){function r(n,r){return[t*n*Math.cos(r=a(r)),e*Math.sin(r)]}var a=g(n);return r.invert=function(r,a){var o=l(a/e);return[r/(t*Math.cos(o)),l((2*o+Math.sin(2*o))/n)]},r}function v(t,e){var n=e*e,r=n*n;return[t*(.8707-.131979*n+r*(-.013791+r*(.003971*n-.001529*r))),e*(1.007226+n*(.015085+r*(-.044475+.028874*n-.005916*r)))]}function y(t,e){var n,r=Math.min(18,36*Math.abs(e)/O),a=Math.floor(r),o=r-a,i=(n=F[a])[0],l=n[1],s=(n=F[++a])[0],c=n[1],u=(n=F[Math.min(19,++a)])[0],f=n[1];return[t*(s+o*(u-i)/2+o*o*(u-2*s+i)/2),(e>0?P:-P)*(c+o*(f-l)/2+o*o*(f-2*c+l)/2)]}function x(t,e){return[t*Math.cos(e),e]}function b(t,e){var n=Math.cos(e),r=i(s(n*Math.cos(t/=2)));return[2*n*Math.sin(t)*r,Math.sin(e)*r]}function _(t,e){var n=b(t,e);return[(n[0]+t/P)/2,(n[1]+e)/2]}t.geo.project=function(t,e){var r=e.stream;if(!r)throw new Error("not yet supported");return(t&&w.hasOwnProperty(t.type)?w[t.type]:n)(t,r)};var w={Feature:e,FeatureCollection:function(t,n){return{type:"FeatureCollection",features:t.features.map(function(t){return e(t,n)})}}},M=[],k=[],A={point:function(t,e){M.push([t,e])},result:function(){var t=M.length?M.length<2?{type:"Point",coordinates:M[0]}:{type:"MultiPoint",coordinates:M}:null;return M=[],t}},T={lineStart:r,point:function(t,e){M.push([t,e])},lineEnd:function(){M.length&&(k.push(M),M=[])},result:function(){var t=k.length?k.length<2?{type:"LineString",coordinates:k[0]}:{type:"MultiLineString",coordinates:k}:null;return k=[],t}},L={polygonStart:r,lineStart:r,point:function(t,e){M.push([t,e])},lineEnd:function(){var t=M.length;if(t){do M.push(M[0].slice());while(++t<4);k.push(M),M=[]}},polygonEnd:r,result:function(){if(!k.length)return null;var t=[],e=[];return k.forEach(function(n){a(n)?t.push([n]):e.push(n)}),e.forEach(function(e){var n=e[0];t.some(function(t){if(o(t[0],n))return t.push(e),!0})||t.push([e])}),k=[],t.length?t.length>1?{type:"MultiPolygon",coordinates:t}:{type:"Polygon",coordinates:t[0]}:null}},C={Point:A,MultiPoint:A,LineString:T,MultiLineString:T,Polygon:L,MultiPolygon:L,Sphere:L},z=1e-6,S=z*z,O=Math.PI,P=O/2,E=(Math.sqrt(O),O/180),N=180/O,D=t.geo.projection,R=t.geo.projectionMutator;t.geo.interrupt=function(e){function n(t,n){for(var r=n<0?-1:1,a=s[+(n<0)],o=0,i=a.length-1;oa[o][2][0];++o);var l=e(t-a[o][1][0],n);return l[0]+=e(a[o][1][0],r*n>r*a[o][0][1]?a[o][0][1]:n)[0],l}function r(){l=s.map(function(t){return t.map(function(t){var n,r=e(t[0][0],t[0][1])[0],a=e(t[2][0],t[2][1])[0],o=e(t[1][0],t[0][1])[1],i=e(t[1][0],t[1][1])[1];return o>i&&(n=o,o=i, +i=n),[[r,o],[a,i]]})})}function a(){for(var e=1e-6,n=[],r=0,a=s[0].length;r=0;--r){var i=s[1][r],l=180*i[0][0]/O,c=180*i[0][1]/O,u=180*i[1][1]/O,f=180*i[2][0]/O,d=180*i[2][1]/O;n.push(o([[f-e,d-e],[f-e,u+e],[l+e,u+e],[l+e,c-e]],30))}return{type:"Polygon",coordinates:[t.merge(n)]}}function o(t,e){for(var n,r,a,o=-1,i=t.length,l=t[0],s=[];++oz&&--a>0);return[t/(.8707+(o=r*r)*(-.131979+o*(-.013791+o*o*o*(.003971-.001529*o)))),r]},(t.geo.naturalEarth=function(){return D(v)}).raw=v;var F=[[.9986,-.062],[1,0],[.9986,.062],[.9954,.124],[.99,.186],[.9822,.248],[.973,.31],[.96,.372],[.9427,.434],[.9216,.4958],[.8962,.5571],[.8679,.6176],[.835,.6769],[.7986,.7346],[.7597,.7903],[.7186,.8435],[.6732,.8936],[.6213,.9394],[.5722,.9761],[.5322,1]];F.forEach(function(t){t[1]*=1.0144}),y.invert=function(t,e){var n=e/P,r=90*n,a=Math.min(18,Math.abs(r/5)),o=Math.max(0,Math.floor(a));do{var i=F[o][1],l=F[o+1][1],s=F[Math.min(19,o+2)][1],c=s-i,u=s-2*l+i,f=2*(Math.abs(n)-l)/c,d=u/c,h=f*(1-d*f*(1-2*d*f));if(h>=0||1===o){r=(e>=0?5:-5)*(h+a);var p,g=50;do a=Math.min(18,Math.abs(r)/5),o=Math.floor(a),h=a-o,i=F[o][1],l=F[o+1][1],s=F[Math.min(19,o+2)][1],r-=(p=(e>=0?P:-P)*(l+h*(s-i)/2+h*h*(s-2*l+i)/2)-e)*N;while(Math.abs(p)>S&&--g>0);break}}while(--o>=0);var m=F[o][0],v=F[o+1][0],y=F[Math.min(19,o+2)][0];return[t/(v+h*(y-m)/2+h*h*(y-2*v+m)/2),r*E]},(t.geo.robinson=function(){return D(y)}).raw=y,x.invert=function(t,e){return[t/Math.cos(e),e]},(t.geo.sinusoidal=function(){return D(x)}).raw=x,b.invert=function(t,e){if(!(t*t+4*e*e>O*O+z)){var n=t,r=e,a=25;do{var o,i=Math.sin(n),l=Math.sin(n/2),c=Math.cos(n/2),u=Math.sin(r),f=Math.cos(r),d=Math.sin(2*r),h=u*u,p=f*f,g=l*l,m=1-p*c*c,v=m?s(f*c)*Math.sqrt(o=1/m):o=0,y=2*v*f*l-t,x=v*u-e,b=o*(p*g+v*f*c*h),_=o*(.5*i*d-2*v*u*l),w=.25*o*(d*l-v*u*p*i),M=o*(h*c+v*g*f),k=_*w-M*b;if(!k)break;var A=(x*_-y*M)/k,T=(y*w-x*b)/k;n-=A,r-=T}while((Math.abs(A)>z||Math.abs(T)>z)&&--a>0);return[n,r]}},(t.geo.aitoff=function(){return D(b)}).raw=b,_.invert=function(t,e){var n=t,r=e,a=25;do{var o,i=Math.cos(r),l=Math.sin(r),c=Math.sin(2*r),u=l*l,f=i*i,d=Math.sin(n),h=Math.cos(n/2),p=Math.sin(n/2),g=p*p,m=1-f*h*h,v=m?s(i*h)*Math.sqrt(o=1/m):o=0,y=.5*(2*v*i*p+n/P)-t,x=.5*(v*l+r)-e,b=.5*o*(f*g+v*i*h*u)+.5/P,_=o*(d*c/4-v*l*p),w=.125*o*(c*p-v*l*f*d),M=.5*o*(u*h+v*g*i)+.5,k=_*w-M*b,A=(x*_-y*M)/k,T=(y*w-x*b)/k;n-=A,r-=T}while((Math.abs(A)>z||Math.abs(T)>z)&&--a>0);return[n,r]},(t.geo.winkel3=function(){return D(_)}).raw=_}e.exports=r},{}],181:[function(t,e,n){"use strict";function r(t,e){var n=t.projection,r=t.lonaxis,i=t.lataxis,s=t.domain,c=t.framewidth||0,u=e.w*(s.x[1]-s.x[0]),f=e.h*(s.y[1]-s.y[0]),d=r.range[0]+l,h=r.range[1]-l,p=i.range[0]+l,g=i.range[1]-l,m=r._fullRange[0]+l,v=r._fullRange[1]-l,y=i._fullRange[0]+l,x=i._fullRange[1]-l;n._translate0=[e.l+u/2,e.t+f/2];var b=h-d,_=g-p,w=[d+b/2,p+_/2],M=n._rotate;n._center=[w[0]+M[0],w[1]+M[1]];var k=function(e){function r(t){return Math.min(_*u/(t[1][0]-t[0][0]),_*f/(t[1][1]-t[0][1]))}var i,l,s,b,_=e.scale(),w=n._translate0,M=a(d,p,h,g),k=a(m,y,v,x);s=o(e,M),i=r(s),b=o(e,k),n._fullScale=r(b),e.scale(i),s=o(e,M),l=[w[0]-s[0][0]+c,w[1]-s[0][1]+c],n._translate=l,e.translate(l),s=o(e,M),t._isAlbersUsa||e.clipExtent(s),i=n.scale*i,n._scale=i,t._width=Math.round(s[1][0])+c,t._height=Math.round(s[1][1])+c,t._marginX=(u-Math.round(s[1][0]))/2,t._marginY=(f-Math.round(s[1][1]))/2};return k}function a(t,e,n,r){var a=(n-t)/4;return{type:"Polygon",coordinates:[[[t,e],[t,r],[t+a,r],[t+2*a,r],[t+3*a,r],[n,r],[n,e],[n-a,e],[n-2*a,e],[n-3*a,e],[t,e]]]}}function o(t,e){return i.geo.path().projection(t).bounds(e)}var i=t("d3"),l=t("./constants").clipPad;e.exports=r},{"./constants":172,d3:10}],182:[function(t,e,n){"use strict";function r(t,e){var n;return(n=e._isScoped?o:e._clipAngle?l:i)(t,e.projection)}function a(t,e){var n=e._fullScale;return _.behavior.zoom().translate(t.translate()).scale(t.scale()).scaleExtent([.5*n,100*n])}function o(t,e){function n(){_.select(this).style(k)}function r(){i.scale(_.event.scale).translate(_.event.translate),t.render()}function o(){_.select(this).style(A)}var i=t.projection,l=a(i,e);return l.on("zoomstart",n).on("zoom",r).on("zoomend",o),l}function i(t,e){function n(t){return m.invert(t)}function r(t){var e=m(n(t));return Math.abs(e[0]-t[0])>y||Math.abs(e[1]-t[1])>y}function o(){_.select(this).style(k),s=_.mouse(this),c=m.rotate(),u=m.translate(),f=c,d=n(s)}function i(){return h=_.mouse(this),r(s)?(v.scale(m.scale()),void v.translate(m.translate())):(m.scale(_.event.scale),m.translate([u[0],_.event.translate[1]]),d?n(h)&&(g=n(h),p=[f[0]+(g[0]-d[0]),c[1],c[2]],m.rotate(p),f=p):(s=h,d=n(s)),void t.render())}function l(){_.select(this).style(A)}var s,c,u,f,d,h,p,g,m=t.projection,v=a(m,e),y=2;return v.on("zoomstart",o).on("zoom",i).on("zoomend",l),v}function l(t,e){function n(t){v++||t({type:"zoomstart"})}function r(t){t({type:"zoom"})}function o(t){--v||t({type:"zoomend"})}var i,l=t.projection,h={r:l.rotate(),k:l.scale()},p=a(l,e),g=b(p,"zoomstart","zoom","zoomend"),v=0,y=p.on;return p.on("zoomstart",function(){_.select(this).style(k);var t=_.mouse(this),e=l.rotate(),a=e,o=l.translate(),v=c(e);i=s(l,t),y.call(p,"zoom",function(){var n=_.mouse(this);if(l.scale(h.k=_.event.scale),i){if(s(l,n)){l.rotate(e).translate(o);var c=s(l,n),p=f(i,c),y=m(u(v,p)),x=h.r=d(y,i,a);isFinite(x[0])&&isFinite(x[1])&&isFinite(x[2])||(x=a),l.rotate(x),a=x}}else t=n,i=s(l,t);r(g.of(this,arguments))}),n(g.of(this,arguments))}).on("zoomend",function(){_.select(this).style(A),y.call(p,"zoom",null),o(g.of(this,arguments))}).on("zoom.redraw",function(){t.render()}),_.rebind(p,g,"on")}function s(t,e){var n=t.invert(e);return n&&isFinite(n[0])&&isFinite(n[1])&&v(n)}function c(t){var e=.5*t[0]*w,n=.5*t[1]*w,r=.5*t[2]*w,a=Math.sin(e),o=Math.cos(e),i=Math.sin(n),l=Math.cos(n),s=Math.sin(r),c=Math.cos(r);return[o*l*c+a*i*s,a*l*c-o*i*s,o*i*c+a*l*s,o*l*s-a*i*c]}function u(t,e){var n=t[0],r=t[1],a=t[2],o=t[3],i=e[0],l=e[1],s=e[2],c=e[3];return[n*i-r*l-a*s-o*c,n*l+r*i+a*c-o*s,n*s-r*c+a*i+o*l,n*c+r*s-a*l+o*i]}function f(t,e){if(t&&e){var n=x(t,e),r=Math.sqrt(y(n,n)),a=.5*Math.acos(Math.max(-1,Math.min(1,y(t,e)))),o=Math.sin(a)/r;return r&&[Math.cos(a),n[2]*o,-n[1]*o,n[0]*o]}}function d(t,e,n){var r=g(e,2,t[0]);r=g(r,1,t[1]),r=g(r,0,t[2]-n[2]);var a,o,i=e[0],l=e[1],s=e[2],c=r[0],u=r[1],f=r[2],d=Math.atan2(l,i)*M,p=Math.sqrt(i*i+l*l);Math.abs(u)>p?(o=(u>0?90:-90)-d,a=0):(o=Math.asin(u/p)*M-d,a=Math.sqrt(p*p-u*u));var m=180-o-2*d,v=(Math.atan2(f,c)-Math.atan2(s,a))*M,y=(Math.atan2(f,c)-Math.atan2(s,-a))*M,x=h(n[0],n[1],o,v),b=h(n[0],n[1],m,y);return x<=b?[o,v,n[2]]:[m,y,n[2]]}function h(t,e,n,r){var a=p(n-t),o=p(r-e);return Math.sqrt(a*a+o*o)}function p(t){return(t%360+540)%360-180}function g(t,e,n){var r=n*w,a=t.slice(),o=0===e?1:0,i=2===e?1:2,l=Math.cos(r),s=Math.sin(r);return a[o]=t[o]*l-t[i]*s,a[i]=t[i]*l+t[o]*s,a}function m(t){return[Math.atan2(2*(t[0]*t[1]+t[2]*t[3]),1-2*(t[1]*t[1]+t[2]*t[2]))*M,Math.asin(Math.max(-1,Math.min(1,2*(t[0]*t[2]-t[3]*t[1]))))*M,Math.atan2(2*(t[0]*t[3]+t[1]*t[2]),1-2*(t[2]*t[2]+t[3]*t[3]))*M]}function v(t){var e=t[0]*w,n=t[1]*w,r=Math.cos(n);return[r*Math.cos(e),r*Math.sin(e),Math.sin(n)]}function y(t,e){for(var n=0,r=0,a=t.length;r=e.width-20?(o["text-anchor"]="start",o.x=5):(o["text-anchor"]="end",o.x=e._paper.attr("width")-7),n.attr(o);var i=n.select(".js-link-to-tool"),l=n.select(".js-link-spacer"),c=n.select(".js-sourcelinks");t._context.showSources&&t._context.showSources(t),t._context.showLink&&r(t,i),l.text(i.text()&&c.text()?" - ":"")},p.sendDataToCloud=function(t){t.emit("plotly_beforeexport");var e=window.PLOTLYENV&&window.PLOTLYENV.BASE_URL||"https://plot.ly",n=s.select(t).append("div").attr("id","hiddenform").style("display","none"),r=n.append("form").attr({action:e+"/external",method:"post",target:"_blank"}),a=r.append("input").attr({type:"text",name:"data"});return a.node().value=p.graphJson(t,!1,"keepdata"),r.node().submit(),n.remove(),t.emit("plotly_afterexport"),!1},p.supplyDefaults=function(t){var e,n=t._fullLayout||{},r=t._fullLayout={},o=t.layout||{},i=t._fullData||[],l=t._fullData=[],s=t.data||[];if(t._transitionData||p.createTransitionData(t),n._initialAutoSizeIsDone){var c=n.width,f=n.height;p.supplyLayoutGlobalDefaults(o,r),o.width||(r.width=c),o.height||(r.height=f)}else{p.supplyLayoutGlobalDefaults(o,r);var d=!o.width||!o.height,h=r.autosize,g=t._context&&t._context.autosizable,m=d&&(h||g);m?p.plotAutoSize(t,o,r):d&&p.sanitizeMargins(t),!h&&d&&(o.width=r.width,o.height=r.height)}r._initialAutoSizeIsDone=!0,r._dataLength=s.length,r._globalTransforms=(t._context||{}).globalTransforms,p.supplyDataDefaults(s,l,o,r),r._has=p._hasPlotType.bind(r);var v=r._modules;for(e=0;e0){var u=l(t._boundingBoxMargins),f=u.left+u.right,h=u.bottom+u.top,g=1-2*i,m=n._container&&n._container.node?n._container.node().getBoundingClientRect():{width:n.width,height:n.height};r=Math.round(g*(m.width-f)),a=Math.round(g*(m.height-h))}else{var v=s?window.getComputedStyle(t):{};r=parseFloat(v.width)||n.width,a=parseFloat(v.height)||n.height}var y=p.layoutAttributes.width.min,x=p.layoutAttributes.height.min;r1,_=!e.height&&Math.abs(n.height-a)>1;(_||b)&&(b&&(n.width=r),_&&(n.height=a)),t._initialAutoSize||(t._initialAutoSize={width:r,height:a}),p.sanitizeMargins(n)},p.supplyLayoutModuleDefaults=function(t,e,n,r){var a,o;u.Axes.supplyLayoutDefaults(t,e,n);var i=e._basePlotModules;for(a=0;a.5*r.width&&(n.l=n.r=0),n.b+n.t>.5*r.height&&(n.b=n.t=0),r._pushmargin[e]={l:{val:n.x,size:n.l+a},r:{val:n.x,size:n.r+a},b:{val:n.y,size:n.b+a},t:{val:n.y,size:n.t+a}}}else delete r._pushmargin[e];t._replotting||p.doAutoMargin(t)}},p.doAutoMargin=function(t){var e=t._fullLayout;e._size||(e._size={}),e._pushmargin||(e._pushmargin={});var n=e._size,r=JSON.stringify(n),a=Math.max(e.margin.l||0,0),o=Math.max(e.margin.r||0,0),i=Math.max(e.margin.t||0,0),l=Math.max(e.margin.b||0,0),s=e._pushmargin;if(e.margin.autoexpand!==!1&&(s.base={l:{val:0,size:a},r:{val:1,size:o},t:{val:1,size:i},b:{val:0,size:l}},Object.keys(s).forEach(function(t){var n=s[t].l||{},r=s[t].b||{},u=n.val,f=n.size,d=r.val,h=r.size;Object.keys(s).forEach(function(t){if(c(f)&&s[t].r){var n=s[t].r.val,r=s[t].r.size;if(n>u){var p=(f*n+(r-e.width)*u)/(n-u),g=(r*(1-u)+(f-e.width)*(1-n))/(n-u);p>=0&&g>=0&&p+g>a+o&&(a=p,o=g)}}if(c(h)&&s[t].t){var m=s[t].t.val,v=s[t].t.size;if(m>d){var y=(h*m+(v-e.height)*d)/(m-d),x=(v*(1-d)+(h-e.height)*(1-m))/(m-d);y>=0&&x>=0&&y+x>l+i&&(l=y,i=x)}}})})),n.l=Math.round(a),n.r=Math.round(o),n.t=Math.round(i),n.b=Math.round(l),n.p=Math.round(e.margin.pad),n.w=Math.round(e.width)-n.l-n.r,n.h=Math.round(e.height)-n.t-n.b,!t._replotting&&"{}"!==r&&r!==JSON.stringify(e._size))return u.plot(t)},p.graphJson=function(t,e,n,r,a){function o(t){if("function"==typeof t)return null;if(d.isPlainObject(t)){var e,r,a={};for(e in t)if("function"!=typeof t[e]&&["_","["].indexOf(e.charAt(0))===-1){if("keepdata"===n){if("src"===e.substr(e.length-3))continue}else if("keepstream"===n){if(r=t[e+"src"],"string"==typeof r&&r.indexOf(":")>0&&!d.isPlainObject(t.stream))continue}else if("keepall"!==n&&(r=t[e+"src"],"string"==typeof r&&r.indexOf(":")>0))continue;a[e]=o(t[e])}return a}return Array.isArray(t)?t.map(o):d.isJSDate(t)?d.ms2DateTime(+t):t}(a&&e&&!t._fullData||a&&!e&&!t._fullLayout)&&p.supplyDefaults(t);var i=a?t._fullData:t.data,l=a?t._fullLayout:t.layout,s={data:(i||[]).map(function(t){var n=o(t);return e&&delete n.fit,n})};return e||(s.layout=o(l)),t.framework&&t.framework.isPolar&&(s=t.framework.getConfig()),"object"===r?s:JSON.stringify(s)},p.modifyFrames=function(t,e){var n,r,a,o=t._transitionData._frames,i=t._transitionData._frameHash;for(n=0;n0&&(t._transitioningWithDuration=!0),t._transitionData._interruptCallbacks.push(function(){_=!0}),a.redraw&&t._transitionData._interruptCallbacks.push(function(){return u.redraw(t)}),t._transitionData._interruptCallbacks.push(function(){t.emit("plotly_transitioninterrupted",[])});var i,l,s=0,c=0,h=t._fullLayout._basePlotModules,p=!1;if(n)for(l=0;l=0,z=C?f.angularAxis.domain:r.extent(k),S=Math.abs(k[1]-k[0]);T&&!A&&(S=0);var O=z.slice();L&&A&&(O[1]+=S);var P=f.angularAxis.ticksCount||4;P>8&&(P=P/(P/8)+P%8),f.angularAxis.ticksStep&&(P=(O[1]-O[0])/P);var E=f.angularAxis.ticksStep||(O[1]-O[0])/(P*(f.minorTicks+1));M&&(E=Math.max(Math.round(E),1)),O[2]||(O[2]=E);var N=r.range.apply(this,O);if(N=N.map(function(t,e){return parseFloat(t.toPrecision(12))}),l=r.scale.linear().domain(O.slice(0,2)).range("clockwise"===f.direction?[0,360]:[360,0]),u.layout.angularAxis.domain=l.domain(),u.layout.angularAxis.endPadding=L?S:0,e=r.select(this).select("svg.chart-root"),"undefined"==typeof e||e.empty()){var D="' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '",R=(new DOMParser).parseFromString(D,"application/xml"),j=this.appendChild(this.ownerDocument.importNode(R.documentElement,!0));e=r.select(j)}e.select(".guides-group").style({"pointer-events":"none"}),e.select(".angular.axis-group").style({"pointer-events":"none"}),e.select(".radial.axis-group").style({"pointer-events":"none"});var I,F=e.select(".chart-group"),B={fill:"none",stroke:f.tickColor},q={"font-size":f.font.size,"font-family":f.font.family,fill:f.font.color,"text-shadow":["-1px 0px","1px -1px","-1px 1px","1px 1px"].map(function(t,e){return" "+t+" 0 "+f.font.outlineColor}).join(",")};if(f.showLegend){I=e.select(".legend-group").attr({transform:"translate("+[x,f.margin.top]+")"}).style({display:"block"});var H=h.map(function(t,e){var n=i.util.cloneJson(t);return n.symbol="DotPlot"===t.geometry?t.dotType||"circle":"LinePlot"!=t.geometry?"square":"line",n.visibleInLegend="undefined"==typeof t.visibleInLegend||t.visibleInLegend,n.color="LinePlot"===t.geometry?t.strokeColor:t.color,n});i.Legend().config({data:h.map(function(t,e){return t.name||"Element"+e}),legendConfig:o({},i.Legend.defaultConfig().legendConfig,{container:I,elements:H,reverseOrder:f.legend.reverseOrder})})();var V=I.node().getBBox();x=Math.min(f.width-V.width-f.margin.left-f.margin.right,f.height-f.margin.top-f.margin.bottom)/2,x=Math.max(10,x),_=[f.margin.left+x,f.margin.top+x],a.range([0,x]),u.layout.radialAxis.domain=a.domain(),I.attr("transform","translate("+[_[0]+x,_[1]-x]+")")}else I=e.select(".legend-group").style({display:"none"});e.attr({width:f.width,height:f.height}).style({opacity:f.opacity}),F.attr("transform","translate("+_+")").style({cursor:"crosshair"});var G=[(f.width-(f.margin.left+f.margin.right+2*x+(V?V.width:0)))/2,(f.height-(f.margin.top+f.margin.bottom+2*x))/2];if(G[0]=Math.max(0,G[0]),G[1]=Math.max(0,G[1]),e.select(".outer-group").attr("transform","translate("+G+")"),f.title){var U=e.select("g.title-group text").style(q).text(f.title),X=U.node().getBBox();U.attr({x:_[0]-X.width/2,y:_[1]-x-20})}var Y=e.select(".radial.axis-group");if(f.radialAxis.gridLinesVisible){var Z=Y.selectAll("circle.grid-circle").data(a.ticks(5));Z.enter().append("circle").attr({class:"grid-circle"}).style(B),Z.attr("r",a),Z.exit().remove()}Y.select("circle.outside-circle").attr({r:x}).style(B);var W=e.select("circle.background-circle").attr({r:x}).style({fill:f.backgroundColor,stroke:f.stroke});if(f.radialAxis.visible){var Q=r.svg.axis().scale(a).ticks(5).tickSize(5);Y.call(Q).attr({transform:"rotate("+f.radialAxis.orientation+")"}),Y.selectAll(".domain").style(B),Y.selectAll("g>text").text(function(t,e){return this.textContent+f.radialAxis.ticksSuffix}).style(q).style({"text-anchor":"start"}).attr({x:0,y:0,dx:0,dy:0,transform:function(t,e){return"horizontal"===f.radialAxis.tickOrientation?"rotate("+-f.radialAxis.orientation+") translate("+[0,q["font-size"]]+")":"translate("+[0,q["font-size"]]+")"}}),Y.selectAll("g>line").style({stroke:"black"})}var $=e.select(".angular.axis-group").selectAll("g.angular-tick").data(N),J=$.enter().append("g").classed("angular-tick",!0);$.attr({transform:function(t,e){return"rotate("+s(t,e)+")"}}).style({display:f.angularAxis.visible?"block":"none"}),$.exit().remove(),J.append("line").classed("grid-line",!0).classed("major",function(t,e){return e%(f.minorTicks+1)==0}).classed("minor",function(t,e){return!(e%(f.minorTicks+1)==0)}).style(B),J.selectAll(".minor").style({stroke:f.minorTickColor}),$.select("line.grid-line").attr({x1:f.tickLength?x-f.tickLength:0,x2:x}).style({display:f.angularAxis.gridLinesVisible?"block":"none"}),J.append("text").classed("axis-text",!0).style(q);var K=$.select("text.axis-text").attr({x:x+f.labelOffset,dy:".35em",transform:function(t,e){var n=s(t,e),r=x+f.labelOffset,a=f.angularAxis.tickOrientation;return"horizontal"==a?"rotate("+-n+" "+r+" 0)":"radial"==a?n<270&&n>90?"rotate(180 "+r+" 0)":null:"rotate("+(n<=180&&n>0?-90:90)+" "+r+" 0)"}}).style({"text-anchor":"middle",display:f.angularAxis.labelsVisible?"block":"none"}).text(function(t,e){return e%(f.minorTicks+1)!=0?"":M?M[t]+f.angularAxis.ticksSuffix:t+f.angularAxis.ticksSuffix}).style(q);f.angularAxis.rewriteTicks&&K.text(function(t,e){return e%(f.minorTicks+1)!=0?"":f.angularAxis.rewriteTicks(this.textContent,e)});var tt=r.max(F.selectAll(".angular-tick text")[0].map(function(t,e){return t.getCTM().e+t.getBBox().width}));I.attr({transform:"translate("+[x+tt,f.margin.top]+")"});var et=e.select("g.geometry-group").selectAll("g").size()>0,nt=e.select("g.geometry-group").selectAll("g.geometry").data(h);if(nt.enter().append("g").attr({class:function(t,e){return"geometry geometry"+e}}),nt.exit().remove(),h[0]||et){var rt=[];h.forEach(function(t,e){var n={};n.radialScale=a,n.angularScale=l,n.container=nt.filter(function(t,n){return n==e}),n.geometry=t.geometry,n.orientation=f.orientation,n.direction=f.direction,n.index=e,rt.push({data:t,geometryConfig:n})});var at=r.nest().key(function(t,e){return"undefined"!=typeof t.data.groupId||"unstacked"}).entries(rt),ot=[];at.forEach(function(t,e){"unstacked"===t.key?ot=ot.concat(t.values.map(function(t,e){return[t]})):ot.push(t.values)}),ot.forEach(function(t,e){var n;n=Array.isArray(t)?t[0].geometryConfig.geometry:t.geometryConfig.geometry;var r=t.map(function(t,e){return o(i[n].defaultConfig(),t)});i[n]().config(r)()})}var it,lt,st=e.select(".guides-group"),ct=e.select(".tooltips-group"),ut=i.tooltipPanel().config({container:ct,fontSize:8})(),ft=i.tooltipPanel().config({container:ct,fontSize:8})(),dt=i.tooltipPanel().config({container:ct,hasTick:!0})();if(!A){var ht=st.select("line").attr({x1:0,y1:0,y2:0}).style({stroke:"grey","pointer-events":"none"});F.on("mousemove.angular-guide",function(t,e){var n=i.util.getMousePos(W).angle;ht.attr({x2:-x,transform:"rotate("+n+")"}).style({opacity:.5});var r=(n+180+360-f.orientation)%360;it=l.invert(r);var a=i.util.convertToCartesian(x+12,n+180);ut.text(i.util.round(it)).move([a[0]+_[0],a[1]+_[1]])}).on("mouseout.angular-guide",function(t,e){st.select("line").style({opacity:0})})}var pt=st.select("circle").style({stroke:"grey",fill:"none"});F.on("mousemove.radial-guide",function(t,e){var n=i.util.getMousePos(W).radius;pt.attr({r:n}).style({opacity:.5}),lt=a.invert(i.util.getMousePos(W).radius);var r=i.util.convertToCartesian(n,f.radialAxis.orientation);ft.text(i.util.round(lt)).move([r[0]+_[0],r[1]+_[1]])}).on("mouseout.radial-guide",function(t,e){pt.style({opacity:0}),dt.hide(),ut.hide(),ft.hide()}),e.selectAll(".geometry-group .mark").on("mouseover.tooltip",function(t,n){var a=r.select(this),o=a.style("fill"),l="black",s=a.style("opacity")||1;if(a.attr({"data-opacity":s}),"none"!=o){a.attr({"data-fill":o}),l=r.hsl(o).darker().toString(),a.style({fill:l,opacity:1});var c={t:i.util.round(t[0]),r:i.util.round(t[1])};A&&(c.t=M[t[0]]);var u="t: "+c.t+", r: "+c.r,f=this.getBoundingClientRect(),d=e.node().getBoundingClientRect(),h=[f.left+f.width/2-G[0]-d.left,f.top+f.height/2-G[1]-d.top];dt.config({color:l}).text(u),dt.move(h)}else o=a.style("stroke"),a.attr({"data-stroke":o}),l=r.hsl(o).darker().toString(),a.style({stroke:l,opacity:1})}).on("mousemove.tooltip",function(t,e){return 0==r.event.which&&void(r.select(this).attr("data-fill")&&dt.show())}).on("mouseout.tooltip",function(t,e){dt.hide();var n=r.select(this),a=n.attr("data-fill");a?n.style({fill:a,opacity:n.attr("data-opacity")}):n.style({stroke:n.attr("data-stroke"),opacity:n.attr("data-opacity")})})}),d}var e,n,a,l,s={data:[],layout:{}},c={},u={},f=r.dispatch("hover"),d={};return d.render=function(e){return t(e),this},d.config=function(t){if(!arguments.length)return s;var e=i.util.cloneJson(t);return e.data.forEach(function(t,e){s.data[e]||(s.data[e]={}),o(s.data[e],i.Axis.defaultConfig().data[0]),o(s.data[e],t)}),o(s.layout,i.Axis.defaultConfig().layout),o(s.layout,e.layout),this},d.getLiveConfig=function(){return u},d.getinputConfig=function(){return c},d.radialScale=function(t){return a},d.angularScale=function(t){return l},d.svg=function(){return e},r.rebind(d,f,"on"),d},i.Axis.defaultConfig=function(t,e){var n={data:[{t:[1,2,3,4],r:[10,11,12,13],name:"Line1",geometry:"LinePlot",color:null,strokeDash:"solid",strokeColor:null,strokeSize:"1",visibleInLegend:!0,opacity:1}],layout:{defaultColorRange:r.scale.category10().range(),title:null,height:450,width:500,margin:{top:40,right:40,bottom:40,left:40},font:{size:12,color:"gray",outlineColor:"white",family:"Tahoma, sans-serif"},direction:"clockwise",orientation:0,labelOffset:10,radialAxis:{domain:null,orientation:-45,ticksSuffix:"",visible:!0,gridLinesVisible:!0,tickOrientation:"horizontal",rewriteTicks:null},angularAxis:{domain:[0,360],ticksSuffix:"",visible:!0,gridLinesVisible:!0,labelsVisible:!0,tickOrientation:"horizontal",rewriteTicks:null,ticksCount:null,ticksStep:null},minorTicks:0,tickLength:null,tickColor:"silver",minorTickColor:"#eee",backgroundColor:"none",needsEndSpacing:null,showLegend:!0,legend:{reverseOrder:!1},opacity:1}};return n},i.util={},i.DATAEXTENT="dataExtent",i.AREA="AreaChart",i.LINE="LinePlot",i.DOT="DotPlot",i.BAR="BarChart",i.util._override=function(t,e){for(var n in t)n in e&&(e[n]=t[n])},i.util._extend=function(t,e){for(var n in t)e[n]=t[n]},i.util._rndSnd=function(){return 2*Math.random()-1+(2*Math.random()-1)+(2*Math.random()-1)},i.util.dataFromEquation2=function(t,e){var n=e||6,a=r.range(0,360+n,n).map(function(e,n){var r=e*Math.PI/180,a=t(r);return[e,a]});return a},i.util.dataFromEquation=function(t,e,n){var a=e||6,o=[],i=[];r.range(0,360+a,a).forEach(function(e,n){var r=e*Math.PI/180,a=t(r);o.push(e),i.push(a)});var l={t:o,r:i};return n&&(l.name=n),l},i.util.ensureArray=function(t,e){if("undefined"==typeof t)return null;var n=[].concat(t);return r.range(e).map(function(t,e){return n[e]||n[0]})},i.util.fillArrays=function(t,e,n){return e.forEach(function(e,r){t[e]=i.util.ensureArray(t[e],n)}),t},i.util.cloneJson=function(t){return JSON.parse(JSON.stringify(t))},i.util.validateKeys=function(t,e){"string"==typeof e&&(e=e.split("."));var n=e.shift();return t[n]&&(!e.length||objHasKeys(t[n],e))},i.util.sumArrays=function(t,e){return r.zip(t,e).map(function(t,e){return r.sum(t)})},i.util.arrayLast=function(t){return t[t.length-1]},i.util.arrayEqual=function(t,e){for(var n=Math.max(t.length,e.length,1);n-- >=0&&t[n]===e[n];);return n===-2},i.util.flattenArray=function(t){for(var e=[];!i.util.arrayEqual(e,t);)e=t,t=[].concat.apply([],t);return t},i.util.deduplicate=function(t){return t.filter(function(t,e,n){return n.indexOf(t)==e})},i.util.convertToCartesian=function(t,e){var n=e*Math.PI/180,r=t*Math.cos(n),a=t*Math.sin(n);return[r,a]},i.util.round=function(t,e){var n=e||2,r=Math.pow(10,n);return Math.round(t*r)/r},i.util.getMousePos=function(t){var e=r.mouse(t.node()),n=e[0],a=e[1],o={};return o.x=n,o.y=a,o.pos=e,o.angle=180*(Math.atan2(a,n)+Math.PI)/Math.PI,o.radius=Math.sqrt(n*n+a*a),o},i.util.duplicatesCount=function(t){for(var e,n={},r={},a=0,o=t.length;a0)){var l=r.select(this.parentNode).selectAll("path.line").data([0]);l.enter().insert("path"),l.attr({class:"line",d:d(i),transform:function(e,n){return"rotate("+(t.orientation+90)+")"},"pointer-events":"none"}).style({fill:function(t,e){return m.fill(n,a,o)},"fill-opacity":0,stroke:function(t,e){return m.stroke(n,a,o)},"stroke-width":function(t,e){return m["stroke-width"](n,a,o)},"stroke-dasharray":function(t,e){return m["stroke-dasharray"](n,a,o)},opacity:function(t,e){return m.opacity(n,a,o)},display:function(t,e){return m.display(n,a,o)}})}};var h=t.angularScale.range(),p=Math.abs(h[1]-h[0])/s[0].length*Math.PI/180,g=r.svg.arc().startAngle(function(t){return-p/2}).endAngle(function(t){return p/2}).innerRadius(function(e){return t.radialScale(u+(e[2]||0))}).outerRadius(function(e){return t.radialScale(u+(e[2]||0))+t.radialScale(e[1])});f.arc=function(e,n,a){r.select(this).attr({class:"mark arc",d:g,transform:function(e,n){return"rotate("+(t.orientation+c(e[0])+90)+")"}})};var m={fill:function(t,n,r){return e[r].data.color},stroke:function(t,n,r){return e[r].data.strokeColor},"stroke-width":function(t,n,r){return e[r].data.strokeSize+"px"},"stroke-dasharray":function(t,n,r){return l[e[r].data.strokeDash]},opacity:function(t,n,r){return e[r].data.opacity},display:function(t,n,r){return"undefined"==typeof e[r].data.visible||e[r].data.visible?"block":"none"}},v=r.select(this).selectAll("g.layer").data(s);v.enter().append("g").attr({class:"layer"});var y=v.selectAll("path.mark").data(function(t,e){return t});y.enter().append("path").attr({class:"mark"}),y.style(m).each(f[t.geometryType]),y.exit().remove(),v.exit().remove()})}var e,n=[i.PolyChart.defaultConfig()],a=r.dispatch("hover"),l={solid:"none",dash:[5,2],dot:[2,5]};return t.config=function(t){return arguments.length?(t.forEach(function(t,e){n[e]||(n[e]={}),o(n[e],i.PolyChart.defaultConfig()),o(n[e],t)}),this):n},t.getColorScale=function(){return e},r.rebind(t,a,"on"),t},i.PolyChart.defaultConfig=function(){var t={data:{name:"geom1",t:[[1,2,3,4]],r:[[1,2,3,4]],dotType:"circle",dotSize:64,dotVisible:!1,barWidth:20,color:"#ffa500",strokeSize:1,strokeColor:"silver",strokeDash:"solid",opacity:1,index:0,visible:!0,visibleInLegend:!0},geometryConfig:{geometry:"LinePlot",geometryType:"arc",direction:"clockwise",orientation:0,container:"body",radialScale:null,angularScale:null,colorScale:r.scale.category20()}};return t},i.BarChart=function(){return i.PolyChart()},i.BarChart.defaultConfig=function(){var t={geometryConfig:{geometryType:"bar"}};return t},i.AreaChart=function(){return i.PolyChart()},i.AreaChart.defaultConfig=function(){var t={geometryConfig:{geometryType:"arc"}};return t},i.DotPlot=function(){return i.PolyChart()},i.DotPlot.defaultConfig=function(){var t={geometryConfig:{geometryType:"dot",dotType:"circle"}};return t},i.LinePlot=function(){return i.PolyChart()},i.LinePlot.defaultConfig=function(){var t={geometryConfig:{geometryType:"line"}};return t},i.Legend=function(){function t(){var n=e.legendConfig,a=e.data.map(function(t,e){return[].concat(t).map(function(t,r){var a=o({},n.elements[e]);return a.name=t,a.color=[].concat(n.elements[e].color)[r],a})}),i=r.merge(a);i=i.filter(function(t,e){return n.elements[e]&&(n.elements[e].visibleInLegend||"undefined"==typeof n.elements[e].visibleInLegend)}),n.reverseOrder&&(i=i.reverse());var l=n.container;("string"==typeof l||l.nodeName)&&(l=r.select(l));var s=i.map(function(t,e){return t.color}),c=n.fontSize,u=null==n.isContinuous?"number"==typeof i[0]:n.isContinuous,f=u?n.height:c*i.length,d=l.classed("legend-group",!0),h=d.selectAll("svg").data([0]),p=h.enter().append("svg").attr({width:300,height:f+c,xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",version:"1.1"});p.append("g").classed("legend-axis",!0),p.append("g").classed("legend-marks",!0);var g=r.range(i.length),m=r.scale[u?"linear":"ordinal"]().domain(g).range(s),v=r.scale[u?"linear":"ordinal"]().domain(g)[u?"range":"rangePoints"]([0,f]),y=function(t,e){var n=3*e;return"line"===t?"M"+[[-e/2,-e/12],[e/2,-e/12],[e/2,e/12],[-e/2,e/12]]+"Z":r.svg.symbolTypes.indexOf(t)!=-1?r.svg.symbol().type(t).size(n)():r.svg.symbol().type("square").size(n)()};if(u){var x=h.select(".legend-marks").append("defs").append("linearGradient").attr({id:"grad1",x1:"0%",y1:"0%",x2:"0%",y2:"100%"}).selectAll("stop").data(s);x.enter().append("stop"),x.attr({offset:function(t,e){return e/(s.length-1)*100+"%"}}).style({"stop-color":function(t,e){return t}}),h.append("rect").classed("legend-mark",!0).attr({height:n.height,width:n.colorBandWidth,fill:"url(#grad1)"})}else{var b=h.select(".legend-marks").selectAll("path.legend-mark").data(i);b.enter().append("path").classed("legend-mark",!0),b.attr({transform:function(t,e){return"translate("+[c/2,v(e)+c/2]+")"},d:function(t,e){var n=t.symbol;return y(n,c)},fill:function(t,e){return m(e)}}),b.exit().remove()}var _=r.svg.axis().scale(v).orient("right"),w=h.select("g.legend-axis").attr({transform:"translate("+[u?n.colorBandWidth:c,c/2]+")"}).call(_);return w.selectAll(".domain").style({fill:"none",stroke:"none"}),w.selectAll("line").style({fill:"none",stroke:u?n.textColor:"none"}),w.selectAll("text").style({fill:n.textColor,"font-size":n.fontSize}).text(function(t,e){return i[e].name}),t}var e=i.Legend.defaultConfig(),n=r.dispatch("hover");return t.config=function(t){return arguments.length?(o(e,t),this):e},r.rebind(t,n,"on"),t},i.Legend.defaultConfig=function(t,e){var n={data:["a","b","c"],legendConfig:{elements:[{symbol:"line",color:"red"},{symbol:"square",color:"yellow"},{symbol:"diamond",color:"limegreen"}],height:150,colorBandWidth:30,fontSize:12,container:"body",isContinuous:null,textColor:"grey",reverseOrder:!1}};return n},i.tooltipPanel=function(){var t,e,n,a={container:null,hasTick:!1,fontSize:12,color:"white",padding:5},l="tooltip-"+i.tooltipPanel.uid++,s=10,c=function(){t=a.container.selectAll("g."+l).data([0]);var r=t.enter().append("g").classed(l,!0).style({"pointer-events":"none",display:"none"});return n=r.append("path").style({fill:"white","fill-opacity":.9}).attr({d:"M0 0"}),e=r.append("text").attr({dx:a.padding+s,dy:.3*+a.fontSize}),c};return c.text=function(o){var i=r.hsl(a.color).l,l=i>=.5?"#aaa":"white",u=i>=.5?"black":"white",f=o||"";e.style({fill:u,"font-size":a.fontSize+"px"}).text(f);var d=a.padding,h=e.node().getBBox(),p={fill:a.color,stroke:l,"stroke-width":"2px"},g=h.width+2*d+s,m=h.height+2*d;return n.attr({d:"M"+[[s,-m/2],[s,-m/4],[a.hasTick?0:s,0],[s,m/4],[s,m/2],[g,m/2],[g,-m/2]].join("L")+"Z"}).style(p),t.attr({transform:"translate("+[s,-m/2+2*d]+")"}),t.style({display:"block"}),c},c.move=function(e){if(t)return t.attr({transform:"translate("+[e[0],e[1]]+")"}).style({display:"block"}),c},c.hide=function(){if(t)return t.style({display:"none"}),c},c.show=function(){if(t)return t.style({display:"block"}),c},c.config=function(t){return o(a,t),c},c},i.tooltipPanel.uid=1,i.adapter={},i.adapter.plotly=function(){var t={};return t.convert=function(t,e){var n={};if(t.data&&(n.data=t.data.map(function(t,n){var r=o({},t),a=[[r,["marker","color"],["color"]],[r,["marker","opacity"],["opacity"]],[r,["marker","line","color"],["strokeColor"]],[r,["marker","line","dash"],["strokeDash"]],[r,["marker","line","width"],["strokeSize"]],[r,["marker","symbol"],["dotType"]],[r,["marker","size"],["dotSize"]],[r,["marker","barWidth"],["barWidth"]],[r,["line","interpolation"],["lineInterpolation"]],[r,["showlegend"],["visibleInLegend"]]];return a.forEach(function(t,n){i.util.translator.apply(null,t.concat(e))}),e||delete r.marker,e&&delete r.groupId,e?("LinePlot"===r.geometry?(r.type="scatter",r.dotVisible===!0?(delete r.dotVisible,r.mode="lines+markers"):r.mode="lines"):"DotPlot"===r.geometry?(r.type="scatter",r.mode="markers"):"AreaChart"===r.geometry?r.type="area":"BarChart"===r.geometry&&(r.type="bar"),delete r.geometry):("scatter"===r.type?"lines"===r.mode?r.geometry="LinePlot":"markers"===r.mode?r.geometry="DotPlot":"lines+markers"===r.mode&&(r.geometry="LinePlot",r.dotVisible=!0):"area"===r.type?r.geometry="AreaChart":"bar"===r.type&&(r.geometry="BarChart"),delete r.mode,delete r.type),r}),!e&&t.layout&&"stack"===t.layout.barmode)){var a=i.util.duplicates(n.data.map(function(t,e){return t.geometry}));n.data.forEach(function(t,e){var r=a.indexOf(t.geometry);r!=-1&&(n.data[e].groupId=r)})}if(t.layout){var l=o({},t.layout),s=[[l,["plot_bgcolor"],["backgroundColor"]],[l,["showlegend"],["showLegend"]],[l,["radialaxis"],["radialAxis"]],[l,["angularaxis"],["angularAxis"]],[l.angularaxis,["showline"],["gridLinesVisible"]],[l.angularaxis,["showticklabels"],["labelsVisible"]],[l.angularaxis,["nticks"],["ticksCount"]],[l.angularaxis,["tickorientation"],["tickOrientation"]],[l.angularaxis,["ticksuffix"],["ticksSuffix"]],[l.angularaxis,["range"],["domain"]],[l.angularaxis,["endpadding"],["endPadding"]],[l.radialaxis,["showline"],["gridLinesVisible"]],[l.radialaxis,["tickorientation"],["tickOrientation"]],[l.radialaxis,["ticksuffix"],["ticksSuffix"]],[l.radialaxis,["range"],["domain"]],[l.angularAxis,["showline"],["gridLinesVisible"]],[l.angularAxis,["showticklabels"],["labelsVisible"]],[l.angularAxis,["nticks"],["ticksCount"]],[l.angularAxis,["tickorientation"],["tickOrientation"]],[l.angularAxis,["ticksuffix"],["ticksSuffix"]],[l.angularAxis,["range"],["domain"]],[l.angularAxis,["endpadding"],["endPadding"]],[l.radialAxis,["showline"],["gridLinesVisible"]],[l.radialAxis,["tickorientation"],["tickOrientation"]],[l.radialAxis,["ticksuffix"],["ticksSuffix"]],[l.radialAxis,["range"],["domain"]],[l.font,["outlinecolor"],["outlineColor"]],[l.legend,["traceorder"],["reverseOrder"]],[l,["labeloffset"],["labelOffset"]],[l,["defaultcolorrange"],["defaultColorRange"]]];if(s.forEach(function(t,n){i.util.translator.apply(null,t.concat(e))}),e?("undefined"!=typeof l.tickLength&&(l.angularaxis.ticklen=l.tickLength,delete l.tickLength),l.tickColor&&(l.angularaxis.tickcolor=l.tickColor,delete l.tickColor)):(l.angularAxis&&"undefined"!=typeof l.angularAxis.ticklen&&(l.tickLength=l.angularAxis.ticklen),l.angularAxis&&"undefined"!=typeof l.angularAxis.tickcolor&&(l.tickColor=l.angularAxis.tickcolor)),l.legend&&"boolean"!=typeof l.legend.reverseOrder&&(l.legend.reverseOrder="normal"!=l.legend.reverseOrder),l.legend&&"boolean"==typeof l.legend.traceorder&&(l.legend.traceorder=l.legend.traceorder?"reversed":"normal",delete l.legend.reverseOrder),l.margin&&"undefined"!=typeof l.margin.t){var c=["t","r","b","l","pad"],u=["top","right","bottom","left","pad"],f={};r.entries(l.margin).forEach(function(t,e){f[u[c.indexOf(t.key)]]=t.value}),l.margin=f}e&&(delete l.needsEndSpacing,delete l.minorTickColor,delete l.minorTicks,delete l.angularaxis.ticksCount,delete l.angularaxis.ticksCount,delete l.angularaxis.ticksStep,delete l.angularaxis.rewriteTicks,delete l.angularaxis.nticks,delete l.radialaxis.ticksCount,delete l.radialaxis.ticksCount,delete l.radialaxis.ticksStep,delete l.radialaxis.rewriteTicks,delete l.radialaxis.nticks),n.layout=l}return n},t}},{"../../lib":122,d3:10}],191:[function(t,e,n){"use strict";var r=t("d3"),a=t("../../lib"),o=t("../../components/color"),i=t("./micropolar"),l=t("./undo_manager"),s=a.extendDeepAll,c=e.exports={};c.framework=function(t){function e(e,a){return a&&(f=a),r.select(r.select(f).node().parentNode).selectAll(".svg-container>*:not(.chart-root)").remove(),n=n?s(n,e):e,o||(o=i.Axis()),u=i.adapter.plotly().convert(n),o.config(u).render(f),t.data=n.data,t.layout=n.layout,c.fillLayout(t),n}var n,a,o,u,f,d=new l;return e.isPolar=!0,e.svg=function(){return o.svg()},e.getConfig=function(){return n},e.getLiveConfig=function(){return i.adapter.plotly().convert(o.getLiveConfig(),!0)},e.getLiveScales=function(){return{t:o.angularScale(),r:o.radialScale()}},e.setUndoPoint=function(){var t=this,e=i.util.cloneJson(n);!function(e,n){d.add({undo:function(){n&&t(n)},redo:function(){t(e)}})}(e,a),a=i.util.cloneJson(e)},e.undo=function(){d.undo()},e.redo=function(){d.redo()},e},c.fillLayout=function(t){var e=r.select(t).selectAll(".plot-container"),n=e.selectAll(".svg-container"),a=t.framework&&t.framework.svg&&t.framework.svg(),i={width:800,height:600,paper_bgcolor:o.background,_container:e,_paperdiv:n,_paper:a};t._fullLayout=s(i,t.layout)}},{"../../components/color":27,"../../lib":122,"./micropolar":190,"./undo_manager":192,d3:10}],192:[function(t,e,n){"use strict";e.exports=function(){function t(t,e){return t?(a=!0,t[e](),a=!1,this):this}var e,n=[],r=-1,a=!1;return{add:function(t){return a?this:(n.splice(r+1,n.length-r),n.push(t),r=n.length-1,this)},setCallback:function(t){e=t},undo:function(){var a=n[r];return a?(t(a,"undo"),r-=1,e&&e(a.undo),this):this},redo:function(){var a=n[r+1];return a?(t(a,"redo"),r+=1,e&&e(a.redo),this):this},clear:function(){n=[],r=-1},hasUndo:function(){return r!==-1},hasRedo:function(){return r-1}var o=t("../lib"),i=t("../plots/plots"),l=o.extendFlat,s=o.extendDeep;e.exports=function(t,e){t.framework&&t.framework.isPolar&&(t=t.framework.getConfig());var n,o=t.data,c=t.layout,u=s([],o),f=s({},c,r(e.tileClass));if(e.width&&(f.width=e.width),e.height&&(f.height=e.height),"thumbnail"===e.tileClass||"themes__thumb"===e.tileClass){f.annotations=[];var d=Object.keys(f);for(n=0;n=2?o(t):t>e?Math.ceil(t):Math.floor(t)}var m,v,y,x,b=e.p+(h?d[n]:d),_=b+(g?p[n]:p),w=e.b,M=w+e.s;if("h"===l.orientation?(y=u.c2p(b,!0),x=u.c2p(_,!0),m=c.c2p(w,!0),v=c.c2p(M,!0)):(m=c.c2p(b,!0),v=c.c2p(_,!0),y=u.c2p(w,!0),x=u.c2p(M,!0)),!(a(m)&&a(v)&&a(y)&&a(x)&&m!==v&&y!==x))return void r.select(this).remove();var k=(e.mlw+1||l.marker.line.width+1||(e.trace?e.trace.marker.line.width:0)+1)-1,A=r.round(k/2%1,2);if(!t._context.staticPlot){var T=i.opacity(e.mc||l.marker.color),L=T<1||k>.01?o:s;m=L(m,v),v=L(v,m),y=L(y,x),x=L(x,y)}r.select(this).attr("d","M"+m+","+y+"V"+x+"H"+v+"V"+y+"Z")})}),d.call(l.plot,e)}},{"../../components/color":27,"../../components/errorbars":56,"../../lib":122,"./arrays_to_calcdata":203,d3:10,"fast-isnumeric":13}],212:[function(t,e,n){"use strict";function r(t,e,n,r){if(r.length){var l,s,c,u,f,d=t._fullLayout.barmode,h="overlay"===d,p="group"===d;if(h)a(t,e,n,r);else if(p){for(l=[],s=[],c=0;cs+i&&(c=!0,s=y)),v(e.c2l(g))&&(gs+i&&(c=!0,s=g))}}x.expand(e,[l,s],{tozero:!0,padded:c})}function m(t){return t._id.charAt(0)}var v=t("fast-isnumeric"),y=t("../../registry"),x=t("../../plots/cartesian/axes"),b=t("./sieve.js");e.exports=function(t,e){var n,a=e.xaxis,o=e.yaxis,i=t._fullData,l=t.calcdata,s=[],c=[];for(n=0;n1||0===l.bargap&&0===l.bargroupgap&&!t[0].trace.marker.line.width)&&r.select(this).attr("shape-rendering","crispEdges")}),e.selectAll("g.points").each(function(t){var e=t[0].trace,n=e.marker,i=n.line,l=o.tryColorscale(n,""),s=o.tryColorscale(n,"line");r.select(this).selectAll("path").each(function(t){var e,o,c=(t.mlw+1||i.width+1)-1,u=r.select(this);e="mc"in t?t.mcc=l(t.mc):Array.isArray(n.color)?a.defaultLine:n.color,u.style("stroke-width",c+"px").call(a.fill,e),c&&(o="mlc"in t?t.mlcc=s(t.mlc):Array.isArray(i.color)?a.defaultLine:i.color,u.call(a.stroke,o))})}),e.call(i.style)}},{"../../components/color":27,"../../components/drawing":50,"../../components/errorbars":56,d3:10}],215:[function(t,e,n){"use strict";var r=t("../../components/color"),a=t("../../components/colorscale/has_colorscale"),o=t("../../components/colorscale/defaults");e.exports=function(t,e,n,i,l){n("marker.color",i),a(t,"marker")&&o(t,e,l,n,{prefix:"marker.",cLetter:"c"}),n("marker.line.color",r.defaultLine),a(t,"marker.line")&&o(t,e,l,n,{prefix:"marker.line.",cLetter:"c"}),n("marker.line.width")}},{"../../components/color":27,"../../components/colorscale/defaults":36,"../../components/colorscale/has_colorscale":40}],216:[function(t,e,n){"use strict";var r=t("../scattergeo/attributes"),a=t("../../components/colorscale/attributes"),o=t("../../components/colorbar/attributes"),i=t("../../plots/attributes"),l=t("../../lib/extend").extendFlat,s=r.marker.line;e.exports=l({},{locations:{valType:"data_array"},locationmode:r.locationmode,z:{valType:"data_array"},text:{valType:"data_array"},marker:{line:{color:s.color,width:s.width}},hoverinfo:l({},i.hoverinfo,{flags:["location","z","text","name"]})},a,{colorbar:o})},{"../../components/colorbar/attributes":28,"../../components/colorscale/attributes":32,"../../lib/extend":117,"../../plots/attributes":148,"../scattergeo/attributes":257}],217:[function(t,e,n){"use strict";var r=t("../../components/colorscale/calc");e.exports=function(t,e){r(e,e.z,"","z")}},{"../../components/colorscale/calc":33}],218:[function(t,e,n){"use strict";var r=t("../../lib"),a=t("../../components/colorscale/defaults"),o=t("./attributes");e.exports=function(t,e,n,i){function l(n,a){return r.coerce(t,e,o,n,a)}var s,c=l("locations");if(c&&(s=c.length),!c||!s)return void(e.visible=!1);var u=l("z");return Array.isArray(u)?(u.length>s&&(e.z=u.slice(0,s)),l("locationmode"),l("text"),l("marker.line.color"),l("marker.line.width"),a(t,e,i,l,{prefix:"",cLetter:"z"}),void l("hoverinfo",1===i._dataLength?"location+z+text":void 0)):void(e.visible=!1)}},{"../../components/colorscale/defaults":36,"../../lib":122,"./attributes":216}],219:[function(t,e,n){"use strict";var r={};r.attributes=t("./attributes"),r.supplyDefaults=t("./defaults"),r.colorbar=t("../heatmap/colorbar"),r.calc=t("./calc"),r.plot=t("./plot").plot,r.hoverPoints=function(){},r.moduleType="trace",r.name="choropleth",r.basePlotModule=t("../../plots/geo"),r.categories=["geo","noOpacity"],r.meta={},e.exports=r},{"../../plots/geo":174,"../heatmap/colorbar":221,"./attributes":216,"./calc":217,"./defaults":218,"./plot":220}],220:[function(t,e,n){"use strict";function r(t,e){function n(e){var n=t.mockAxis;return i.tickText(n,n.c2l(e),"hover").text}var r=e.hoverinfo;if("none"===r||"skip"===r)return function(t){delete t.nameLabel,delete t.textLabel};var a="all"===r?g.hoverinfo.flags:r.split("+"),o=a.indexOf("name")!==-1,l=a.indexOf("location")!==-1,s=a.indexOf("z")!==-1,c=a.indexOf("text")!==-1,u=!o&&l;return function(t){var r=[];u?t.nameLabel=t.id:(o&&(t.nameLabel=e.name),l&&r.push(t.id)),s&&r.push(n(t.z)),c&&r.push(t.tx),t.textLabel=r.join("
")}}function a(t){return function(e,n){return{points:[{data:t._input,fullData:t,curveNumber:t.index,pointNumber:n,location:e.id,z:e.z}]}}}var o=t("d3"),i=t("../../plots/cartesian/axes"),l=t("../../plots/cartesian/graph_interact"),s=t("../../components/color"),c=t("../../components/drawing"),u=t("../../components/colorscale"),f=t("../../lib/topojson_utils").getTopojsonFeatures,d=t("../../lib/geo_location_utils").locationToFeature,h=t("../../lib/array_to_calc_item"),p=t("../../plots/geo/constants"),g=t("./attributes"),m=e.exports={};m.calcGeoJSON=function(t,e){for(var n,r=[],a=t.locations,o=a.length,i=f(t,e),l=(t.marker||{}).line||{},s=0;s0&&(r[0].trace=t),r},m.plot=function(t,e,n){function i(t){return t[0].trace.uid}var s,c=t.framework,u=c.select("g.choroplethlayer"),f=c.select("g.baselayer"),d=c.select("g.baselayeroverchoropleth"),h=p.baseLayersOverChoropleth,g=u.selectAll("g.trace.choropleth").data(e,i);g.enter().append("g").attr("class","trace choropleth"),g.exit().remove(),g.each(function(e){function n(e,n){if(t.showHover){var r=t.projection(e.properties.ct);u(e),l.loneHover({x:r[0],y:r[1],name:e.nameLabel,text:e.textLabel},{container:t.hoverContainer.node()}),d=f(e,n),t.graphDiv.emit("plotly_hover",d)}}function i(e,n){t.graphDiv.emit("plotly_click",f(e,n))}var s=e[0].trace,c=m.calcGeoJSON(s,t.topojson),u=r(t,s),f=a(s),d=null,h=o.select(this).selectAll("path.choroplethlocation").data(c);h.enter().append("path").classed("choroplethlocation",!0).on("mouseover",n).on("click",i).on("mouseout",function(){l.loneUnhover(t.hoverContainer),t.graphDiv.emit("plotly_unhover",d)}).on("mousedown",function(){l.loneUnhover(t.hoverContainer)}).on("mouseup",n),h.exit().remove()}),d.selectAll("*").remove();for(var v=0;v")}return g};var s},{"../../components/color":27,"./helpers":226,"fast-isnumeric":13,tinycolor2:16}],225:[function(t,e,n){"use strict";var r=t("../../lib"),a=t("./attributes");e.exports=function(t,e,n,o){function i(n,o){return r.coerce(t,e,a,n,o)}var l=r.coerceFont,s=i("values");if(!Array.isArray(s)||!s.length)return void(e.visible=!1);var c=i("labels");Array.isArray(c)||(i("label0"),i("dlabel"));var u=i("marker.line.width");u&&i("marker.line.color");var f=i("marker.colors");Array.isArray(f)||(e.marker.colors=[]),i("scalegroup");var d=i("text"),h=i("textinfo",Array.isArray(d)?"text+percent":"percent");if(i("hoverinfo",1===o._dataLength?"label+text+value+percent":void 0),h&&"none"!==h){var p=i("textposition"),g=Array.isArray(p)||"auto"===p,m=g||"inside"===p,v=g||"outside"===p;if(m||v){var y=l(i,"textfont",o.font);m&&l(i,"insidetextfont",y),v&&l(i,"outsidetextfont",y)}}i("domain.x"),i("domain.y"),i("hole"),i("sort"),i("direction"),i("rotation"),i("pull")}},{"../../lib":122,"./attributes":222}],226:[function(t,e,n){"use strict";var r=t("../../lib"); +n.formatPiePercent=function(t,e){var n=(100*t).toPrecision(3);return n.lastIndexOf(".")!==-1&&(n=n.replace(/[.]?0+$/,"")),r.numSeparate(n,e)+"%"},n.formatPieValue=function(t,e){var n=t.toPrecision(10);return n.lastIndexOf(".")!==-1&&(n=n.replace(/[.]?0+$/,"")),r.numSeparate(n,e)}},{"../../lib":122}],227:[function(t,e,n){"use strict";var r={};r.attributes=t("./attributes"),r.supplyDefaults=t("./defaults"),r.supplyLayoutDefaults=t("./layout_defaults"),r.layoutAttributes=t("./layout_attributes"),r.calc=t("./calc"),r.plot=t("./plot"),r.style=t("./style"),r.styleOne=t("./style_one"),r.moduleType="trace",r.name="pie",r.basePlotModule=t("./base_plot"),r.categories=["pie","showLegend"],r.meta={},e.exports=r},{"./attributes":222,"./base_plot":223,"./calc":224,"./defaults":225,"./layout_attributes":228,"./layout_defaults":229,"./plot":230,"./style":231,"./style_one":232}],228:[function(t,e,n){"use strict";e.exports={hiddenlabels:{valType:"data_array"}}},{}],229:[function(t,e,n){"use strict";var r=t("../../lib"),a=t("./layout_attributes");e.exports=function(t,e){function n(n,o){return r.coerce(t,e,a,n,o)}n("hiddenlabels")}},{"../../lib":122,"./layout_attributes":228}],230:[function(t,e,n){"use strict";function r(t,e,n){var r=Math.sqrt(t.width*t.width+t.height*t.height),o=t.width/t.height,i=Math.PI*Math.min(e.v/n.vTotal,.5),l=1-n.trace.hole,s=a(e,n),c={scale:s*n.r*2/r,rCenter:1-s,rotate:0};if(c.scale>=1)return c;var u=o+1/(2*Math.tan(i)),f=n.r*Math.min(1/(Math.sqrt(u*u+.5)+u),l/(Math.sqrt(o*o+l/2)+o)),d={scale:2*f/t.height,rCenter:Math.cos(f/n.r)-f*o/n.r,rotate:(180/Math.PI*e.midangle+720)%180-90},h=1/o,p=h+1/(2*Math.tan(i)),g=n.r*Math.min(1/(Math.sqrt(p*p+.5)+p),l/(Math.sqrt(h*h+l/2)+h)),m={scale:2*g/t.width,rCenter:Math.cos(g/n.r)-g/o/n.r,rotate:(180/Math.PI*e.midangle+810)%180-90},v=m.scale>d.scale?m:d;return c.scale<1&&v.scale>c.scale?v:c}function a(t,e){if(t.v===e.vTotal&&!e.trace.hole)return 1;var n=Math.PI*Math.min(t.v/e.vTotal,.5);return Math.min(1/(1+1/Math.sin(n)),(1-e.trace.hole)/2)}function o(t,e){var n=e.pxmid[0],r=e.pxmid[1],a=t.width/2,o=t.height/2;return n<0&&(a*=-1),r<0&&(o*=-1),{scale:1,rCenter:1,rotate:0,x:a+Math.abs(o)*(a>0?1:-1)/2,y:o/(1+n*n/(r*r)),outside:!0}}function i(t,e){function n(t,e){return t.pxmid[1]-e.pxmid[1]}function r(t,e){return e.pxmid[1]-t.pxmid[1]}function a(t,n){n||(n={});var r,a,o,l,d,h,g=n.labelExtraY+(i?n.yLabelMax:n.yLabelMin),m=i?t.yLabelMin:t.yLabelMax,v=i?t.yLabelMax:t.yLabelMin,y=t.cyFinal+c(t.px0[1],t.px1[1]),x=g-m;if(x*f>0&&(t.labelExtraY=x),Array.isArray(e.pull))for(a=0;a=e.pull[o.i]||((t.pxmid[1]-o.pxmid[1])*f>0?(l=o.cyFinal+c(o.px0[1],o.px1[1]),x=l-m-t.labelExtraY,x*f>0&&(t.labelExtraY+=x)):(v+t.labelExtraY-y)*f>0&&(r=3*u*Math.abs(a-p.indexOf(t)),d=o.cxFinal+s(o.px0[0],o.px1[0]),h=d+r-(t.cxFinal+t.pxmid[0])-t.labelExtraX,h*u>0&&(t.labelExtraX+=h)))}var o,i,l,s,c,u,f,d,h,p,g,m,v;for(i=0;i<2;i++)for(l=i?n:r,c=i?Math.max:Math.min,f=i?1:-1,o=0;o<2;o++){for(s=o?Math.max:Math.min,u=o?1:-1,d=t[i][o],d.sort(l),h=t[1-i][o],p=h.concat(d),m=[],g=0;gu&&(u=l.pull[o]);i.r=Math.min(n/c(l.tilt,Math.sin(s),l.depth),r/c(l.tilt,Math.cos(s),l.depth))/(2+2*u),i.cx=e.l+e.w*(l.domain.x[1]+l.domain.x[0])/2,i.cy=e.t+e.h*(2-l.domain.y[1]-l.domain.y[0])/2,l.scalegroup&&h.indexOf(l.scalegroup)===-1&&h.push(l.scalegroup)}for(o=0;of.vTotal/2?1:0)}function c(t,e,n){if(!t)return 1;var r=Math.sin(t*Math.PI/180);return Math.max(.01,n*r*Math.abs(e)+2*Math.sqrt(1-r*r*e*e))}var u=t("d3"),f=t("../../plots/cartesian/graph_interact"),d=t("../../components/color"),h=t("../../components/drawing"),p=t("../../lib/svg_text_utils"),g=t("./helpers");e.exports=function(t,e){var n=t._fullLayout;l(e,n._size);var c=n._pielayer.selectAll("g.trace").data(e);c.enter().append("g").attr({"stroke-linejoin":"round",class:"trace"}),c.exit().remove(),c.order(),c.each(function(e){var l=u.select(this),c=e[0],m=c.trace,v=0,y=(m.depth||0)*c.r*Math.sin(v)/2,x=m.tiltaxis||0,b=x*Math.PI/180,_=[y*Math.sin(b),y*Math.cos(b)],w=c.r*Math.cos(v),M=l.selectAll("g.part").data(m.tilt?["top","sides"]:["top"]);M.enter().append("g").attr("class",function(t){return t+" part"}),M.exit().remove(),M.order(),s(e),l.selectAll(".top").each(function(){var l=u.select(this).selectAll("g.slice").data(e);l.enter().append("g").classed("slice",!0),l.exit().remove();var s=[[[],[]],[[],[]]],v=!1;l.each(function(i){function l(e){var r=t._fullLayout,o=t._fullData[m.index],l=o.hoverinfo;if("all"===l&&(l="label+text+value+percent+name"),!t._dragging&&r.hovermode!==!1&&"none"!==l&&"skip"!==l&&l){var s=a(i,c),u=M+i.pxmid[0]*(1-s),d=k+i.pxmid[1]*(1-s),h=n.separators,p=[];l.indexOf("label")!==-1&&p.push(i.label),o.text&&o.text[i.i]&&l.indexOf("text")!==-1&&p.push(o.text[i.i]),l.indexOf("value")!==-1&&p.push(g.formatPieValue(i.v,h)),l.indexOf("percent")!==-1&&p.push(g.formatPiePercent(i.v/c.vTotal,h)),f.loneHover({x0:u-s*c.r,x1:u+s*c.r,y:d,text:p.join("
"),name:l.indexOf("name")!==-1?o.name:void 0,color:i.color,idealAlign:i.pxmid[0]<0?"left":"right"},{container:r._hoverlayer.node(),outerContainer:r._paper.node()}),f.hover(t,e,"pie"),L=!0}}function d(e){t.emit("plotly_unhover",{points:[e]}),L&&(f.loneUnhover(n._hoverlayer.node()),L=!1)}function y(){t._hoverdata=[i],i.curveNumber=e[0].trace.index,t._hoverdata.trace=e[0].trace,f.click(t,window.event||{target:!0})}function b(t,e,n,r){return"a"+r*c.r+","+r*w+" "+x+" "+i.largeArc+(n?" 1 ":" 0 ")+r*(e[0]-t[0])+","+r*(e[1]-t[1])}if(i.hidden)return void u.select(this).selectAll("path,g").remove();s[i.pxmid[1]<0?0:1][i.pxmid[0]<0?0:1].push(i);var M=c.cx+_[0],k=c.cy+_[1],A=u.select(this),T=A.selectAll("path.surface").data([i]),L=!1;if(T.enter().append("path").classed("surface",!0).style({"pointer-events":"all"}),A.select("path.textline").remove(),A.on("mouseover",l).on("mouseout",d).on("click",y).on("contextmenu",y),m.pull){var C=+(Array.isArray(m.pull)?m.pull[i.i]:m.pull)||0;C>0&&(M+=C*i.pxmid[0],k+=C*i.pxmid[1])}i.cxFinal=M,i.cyFinal=k;var z=m.hole;if(i.v===c.vTotal){var S="M"+(M+i.px0[0])+","+(k+i.px0[1])+b(i.px0,i.pxmid,!0,1)+b(i.pxmid,i.px0,!0,1)+"Z";z?T.attr("d","M"+(M+z*i.px0[0])+","+(k+z*i.px0[1])+b(i.px0,i.pxmid,!1,z)+b(i.pxmid,i.px0,!1,z)+"Z"+S):T.attr("d",S)}else{var O=b(i.px0,i.px1,!0,1);if(z){var P=1-z;T.attr("d","M"+(M+z*i.px1[0])+","+(k+z*i.px1[1])+b(i.px1,i.px0,!1,z)+"l"+P*i.px0[0]+","+P*i.px0[1]+O+"Z")}else T.attr("d","M"+M+","+k+"l"+i.px0[0]+","+i.px0[1]+O+"Z")}var E=Array.isArray(m.textposition)?m.textposition[i.i]:m.textposition,N=A.selectAll("g.slicetext").data(i.text&&"none"!==E?[0]:[]);N.enter().append("g").classed("slicetext",!0),N.exit().remove(),N.each(function(){var t=u.select(this).selectAll("text").data([0]);t.enter().append("text").attr("data-notex",1),t.exit().remove(),t.text(i.text).attr({class:"slicetext",transform:"","data-bb":"","text-anchor":"middle",x:0,y:0}).call(h.font,"outside"===E?m.outsidetextfont:m.insidetextfont).call(p.convertToTspans),t.selectAll("tspan.line").attr({x:0,y:0});var e,n=h.bBox(t.node());"outside"===E?e=o(n,i):(e=r(n,i,c),"auto"===E&&e.scale<1&&(t.call(h.font,m.outsidetextfont),m.outsidetextfont.family===m.insidetextfont.family&&m.outsidetextfont.size===m.insidetextfont.size||(t.attr({"data-bb":""}),n=h.bBox(t.node())),e=o(n,i)));var a=M+i.pxmid[0]*e.rCenter+(e.x||0),l=k+i.pxmid[1]*e.rCenter+(e.y||0);e.outside&&(i.yLabelMin=l-n.height/2,i.yLabelMid=l,i.yLabelMax=l+n.height/2,i.labelExtraX=0,i.labelExtraY=0,v=!0),t.attr("transform","translate("+a+","+l+")"+(e.scale<1?"scale("+e.scale+")":"")+(e.rotate?"rotate("+e.rotate+")":"")+"translate("+-(n.left+n.right)/2+","+-(n.top+n.bottom)/2+")")})}),v&&i(s,m),l.each(function(t){if(t.labelExtraX||t.labelExtraY){var e=u.select(this),n=e.select("g.slicetext text");n.attr("transform","translate("+t.labelExtraX+","+t.labelExtraY+")"+n.attr("transform"));var r=t.cxFinal+t.pxmid[0],a=t.cyFinal+t.pxmid[1],o="M"+r+","+a,i=(t.yLabelMax-t.yLabelMin)*(t.pxmid[0]<0?-1:1)/4;if(t.labelExtraX){var l=t.labelExtraX*t.pxmid[1]/t.pxmid[0],s=t.yLabelMid+t.labelExtraY-(t.cyFinal+t.pxmid[1]);o+=Math.abs(l)>Math.abs(s)?"l"+s*t.pxmid[0]/t.pxmid[1]+","+s+"H"+(r+t.labelExtraX+i):"l"+t.labelExtraX+","+l+"v"+(s-l)+"h"+i}else o+="V"+(t.yLabelMid+t.labelExtraY)+"h"+i;e.append("path").classed("textline",!0).call(d.stroke,m.outsidetextfont.color).attr({"stroke-width":Math.min(2,m.outsidetextfont.size/8),d:o,fill:"none"})}})})}),setTimeout(function(){c.selectAll("tspan").each(function(){var t=u.select(this);t.attr("dy")&&t.attr("dy",t.attr("dy"))})},0)}},{"../../components/color":27,"../../components/drawing":50,"../../lib/svg_text_utils":134,"../../plots/cartesian/graph_interact":157,"./helpers":226,d3:10}],231:[function(t,e,n){"use strict";var r=t("d3"),a=t("./style_one");e.exports=function(t){t._fullLayout._pielayer.selectAll(".trace").each(function(t){var e=t[0],n=e.trace,o=r.select(this);o.style({opacity:n.opacity}),o.selectAll(".top path.surface").each(function(t){r.select(this).call(a,t,n)})})}},{"./style_one":232,d3:10}],232:[function(t,e,n){"use strict";var r=t("../../components/color");e.exports=function(t,e,n){var a=n.marker.line.color;Array.isArray(a)&&(a=a[e.i]||r.defaultLine);var o=n.marker.line.width||0;Array.isArray(o)&&(o=o[e.i]||0),t.style({"stroke-width":o,fill:e.color}).call(r.stroke,a)}},{"../../components/color":27}],233:[function(t,e,n){"use strict";var r=t("../../lib");e.exports=function(t){var e=t[0].trace,n=e.marker;if(r.mergeArray(e.text,t,"tx"),r.mergeArray(e.textposition,t,"tp"),e.textfont&&(r.mergeArray(e.textfont.size,t,"ts"),r.mergeArray(e.textfont.color,t,"tc"),r.mergeArray(e.textfont.family,t,"tf")),n&&n.line){var a=n.line;r.mergeArray(n.opacity,t,"mo"),r.mergeArray(n.symbol,t,"mx"),r.mergeArray(n.color,t,"mc"),r.mergeArray(a.color,t,"mlc"),r.mergeArray(a.width,t,"mlw")}}},{"../../lib":122}],234:[function(t,e,n){"use strict";var r=t("../../components/colorscale/color_attributes"),a=t("../../components/errorbars/attributes"),o=t("../../components/colorbar/attributes"),i=t("../../components/drawing"),l=(t("./constants"),t("../../lib/extend").extendFlat);e.exports={x:{valType:"data_array"},x0:{valType:"any",dflt:0},dx:{valType:"number",dflt:1},y:{valType:"data_array"},y0:{valType:"any",dflt:0},dy:{valType:"number",dflt:1},ids:{valType:"data_array"},text:{valType:"string",dflt:"",arrayOk:!0},mode:{valType:"flaglist",flags:["lines","markers","text"],extras:["none"]},hoveron:{valType:"flaglist",flags:["points","fills"]},line:{color:{valType:"color"},width:{valType:"number",min:0,dflt:2},shape:{valType:"enumerated",values:["linear","spline","hv","vh","hvh","vhv"],dflt:"linear"},smoothing:{valType:"number",min:0,max:1.3,dflt:1},dash:{valType:"string",values:["solid","dot","dash","longdash","dashdot","longdashdot"],dflt:"solid"},simplify:{valType:"boolean",dflt:!0}},connectgaps:{valType:"boolean",dflt:!1},fill:{valType:"enumerated",values:["none","tozeroy","tozerox","tonexty","tonextx","toself","tonext"],dflt:"none"},fillcolor:{valType:"color"},marker:l({},{symbol:{valType:"enumerated",values:i.symbolList,dflt:"circle",arrayOk:!0},opacity:{valType:"number",min:0,max:1,arrayOk:!0},size:{valType:"number",min:0,dflt:6,arrayOk:!0},maxdisplayed:{valType:"number",min:0,dflt:0},sizeref:{valType:"number",dflt:1},sizemin:{valType:"number",min:0,dflt:0},sizemode:{valType:"enumerated",values:["diameter","area"],dflt:"diameter"},showscale:{valType:"boolean",dflt:!1},colorbar:o,line:l({},{width:{valType:"number",min:0,arrayOk:!0}},r("marker.line"))},r("marker")),textposition:{valType:"enumerated",values:["top left","top center","top right","middle left","middle center","middle right","bottom left","bottom center","bottom right"],dflt:"middle center",arrayOk:!0},textfont:{family:{valType:"string",noBlank:!0,strict:!0,arrayOk:!0},size:{valType:"number",min:1,arrayOk:!0},color:{valType:"color",arrayOk:!0}},r:{valType:"data_array"},t:{valType:"data_array"},error_y:a,error_x:a}},{"../../components/colorbar/attributes":28,"../../components/colorscale/color_attributes":34,"../../components/drawing":50,"../../components/errorbars/attributes":52,"../../lib/extend":117,"./constants":239}],235:[function(t,e,n){"use strict";var r=t("fast-isnumeric"),a=t("../../plots/cartesian/axes"),o=t("../../lib"),i=t("./subtypes"),l=t("./colorscale_calc");e.exports=function(t,e){var n,s,c,u=a.getFromId(t,e.xaxis||"x"),f=a.getFromId(t,e.yaxis||"y"),d=u.makeCalcdata(e,"x"),h=f.makeCalcdata(e,"y"),p=Math.min(d.length,h.length);u._minDtick=0,f._minDtick=0,d.length>p&&d.splice(p,d.length-p),h.length>p&&h.splice(p,h.length-p);var g={padded:!0},m={padded:!0};if(i.hasMarkers(e)){if(n=e.marker,s=n.size,Array.isArray(s)){var v={type:"linear"};a.setConvert(v),s=v.makeCalcdata(e.marker,"size"),s.length>p&&s.splice(p,s.length-p)}var y,x=1.6*(e.marker.sizeref||1);y="area"===e.marker.sizemode?function(t){return Math.max(Math.sqrt((t||0)/x),3)}:function(t){return Math.max((t||0)/x,3)},g.ppad=m.ppad=Array.isArray(s)?s.map(y):y(s)}l(e),!("tozerox"===e.fill||"tonextx"===e.fill&&t.firstscatter)||d[0]===d[p-1]&&h[0]===h[p-1]?e.error_y.visible||["tonexty","tozeroy"].indexOf(e.fill)===-1&&(i.hasMarkers(e)||i.hasText(e))||(g.padded=!1,g.ppad=0):g.tozero=!0,!("tozeroy"===e.fill||"tonexty"===e.fill&&t.firstscatter)||d[0]===d[p-1]&&h[0]===h[p-1]?["tonextx","tozerox"].indexOf(e.fill)!==-1&&(m.padded=!1):m.tozero=!0,a.expand(u,d,g),a.expand(f,h,m);var b=new Array(p);for(c=0;c=0;a--){var o=t[a];if("scatter"===o.type&&o.xaxis===n.xaxis&&o.yaxis===n.yaxis){o.opacity=void 0;break}}}}}},{}],237:[function(t,e,n){"use strict";var r=t("fast-isnumeric"),a=t("../../lib"),o=t("../../plots/plots"),i=t("../../components/colorscale"),l=t("../../components/colorbar/draw");e.exports=function(t,e){var n=e[0].trace,s=n.marker,c="cb"+n.uid;if(t._fullLayout._infolayer.selectAll("."+c).remove(),void 0===s||!s.showscale)return void o.autoMargin(t,c);var u=s.color,f=s.cmin,d=s.cmax;r(f)||(f=a.aggNums(Math.min,null,u)),r(d)||(d=a.aggNums(Math.max,null,u));var h=e[0].t.cb=l(t,c),p=i.makeColorScaleFunc(i.extractScale(s.colorscale,f,d),{noNumericCheck:!0});h.fillcolor(p).filllevels({start:f,end:d,size:(d-f)/254}).options(s.colorbar)()}},{"../../components/colorbar/draw":30,"../../components/colorscale":41,"../../lib":122,"../../plots/plots":186,"fast-isnumeric":13}],238:[function(t,e,n){"use strict";var r=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/calc"),o=t("./subtypes");e.exports=function(t){o.hasLines(t)&&r(t,"line")&&a(t,t.line.color,"line","c"),o.hasMarkers(t)&&(r(t,"marker")&&a(t,t.marker.color,"marker","c"),r(t,"marker.line")&&a(t,t.marker.line.color,"marker.line","c"))}},{"../../components/colorscale/calc":33,"../../components/colorscale/has_colorscale":40,"./subtypes":254}],239:[function(t,e,n){"use strict";e.exports={PTS_LINESONLY:20}},{}],240:[function(t,e,n){"use strict";var r=t("../../lib"),a=t("./attributes"),o=t("./constants"),i=t("./subtypes"),l=t("./xy_defaults"),s=t("./marker_defaults"),c=t("./line_defaults"),u=t("./line_shape_defaults"),f=t("./text_defaults"),d=t("./fillcolor_defaults"),h=t("../../components/errorbars/defaults");e.exports=function(t,e,n,p){function g(n,o){return r.coerce(t,e,a,n,o)}var m=l(t,e,g),v=my[x].x0&&ey[x].y0&&nV!=D>=V&&(P=S[C-1][0],E=S[C][0],O=P+(E-P)*(V-N)/(D-N),F=Math.min(F,O),B=Math.max(B,O));F=Math.max(F,0),B=Math.min(B,d._length);var G=s.defaultLine;return s.opacity(f.fillcolor)?G=f.fillcolor:s.opacity((f.line||{}).color)&&(G=f.line.color),r.extendFlat(t,{distance:o.MAXDIST+10,x0:F,x1:B,y0:V,y1:V,color:G}),delete t.index,f.text&&!Array.isArray(f.text)?t.text=String(f.text):t.text=f.name,[t]}}}},{"../../components/color":27,"../../components/errorbars":56,"../../lib":122,"../../plots/cartesian/constants":155,"../../plots/cartesian/graph_interact":157,"./get_trace_color":242}],244:[function(t,e,n){"use strict";var r={},a=t("./subtypes");r.hasLines=a.hasLines,r.hasMarkers=a.hasMarkers,r.hasText=a.hasText,r.isBubble=a.isBubble,r.attributes=t("./attributes"),r.supplyDefaults=t("./defaults"),r.cleanData=t("./clean_data"),r.calc=t("./calc"),r.arraysToCalcdata=t("./arrays_to_calcdata"),r.plot=t("./plot"),r.colorbar=t("./colorbar"),r.style=t("./style"),r.hoverPoints=t("./hover"),r.selectPoints=t("./select"),r.animatable=!0,r.moduleType="trace",r.name="scatter",r.basePlotModule=t("../../plots/cartesian"),r.categories=["cartesian","symbols","markerColorscale","errorBarsOK","showLegend"],r.meta={},e.exports=r},{"../../plots/cartesian":158,"./arrays_to_calcdata":233,"./attributes":234,"./calc":235,"./clean_data":236,"./colorbar":237,"./defaults":240,"./hover":243,"./plot":251,"./select":252,"./style":253,"./subtypes":254}],245:[function(t,e,n){"use strict";var r=t("../../components/colorscale/has_colorscale"),a=t("../../components/colorscale/defaults");e.exports=function(t,e,n,o,i){var l=(t.marker||{}).color;if(i("line.color",n),r(t,"line"))a(t,e,o,i,{prefix:"line.",cLetter:"c"});else{var s=!Array.isArray(l)&&l||n;i("line.color",s)}i("line.width"),i("line.dash")}},{"../../components/colorscale/defaults":36,"../../components/colorscale/has_colorscale":40}],246:[function(t,e,n){"use strict";var r=t("../../constants/numerical").BADNUM;e.exports=function(t,e){function n(e){var n=w.c2p(t[e].x),a=M.c2p(t[e].y);return n!==r&&a!==r&&[n,a]}function a(t){var e=t[0]/w._length,n=t[1]/M._length;return(1+10*Math.max(0,-e,e-1,-n,n-1))*T}function o(t,e){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)}var i,l,s,c,u,f,d,h,p,g,m,v,y,x,b,_,w=e.xaxis,M=e.yaxis,k=e.simplify,A=e.connectGaps,T=e.baseTolerance,L=e.linear,C=[],z=.2,S=new Array(t.length),O=0;for(k||(T=z=-1),i=0;ia(f))break;s=f,y=g[0]*p[0]+g[1]*p[1],y>m?(m=y,c=f,h=!1):y=t.length||!f)break;S[O++]=f,l=f}}else S[O++]=c}C.push(S.slice(0,O))}return C}},{"../../constants/numerical":107}],247:[function(t,e,n){"use strict";e.exports=function(t,e,n){var r=n("line.shape");"spline"===r&&n("line.smoothing")}},{}],248:[function(t,e,n){"use strict";e.exports=function(t,e,n){for(var r,a,o=null,i=0;i0?Math.max(e,a):0}}},{"fast-isnumeric":13}],250:[function(t,e,n){"use strict";var r=t("../../components/color"),a=t("../../components/colorscale/has_colorscale"),o=t("../../components/colorscale/defaults"),i=t("./subtypes");e.exports=function(t,e,n,l,s){var c,u=i.isBubble(t),f=(t.line||{}).color;f&&(n=f),s("marker.symbol"),s("marker.opacity",u?.7:1),s("marker.size"),s("marker.color",n),a(t,"marker")&&o(t,e,l,s,{prefix:"marker.",cLetter:"c"}),c=f&&!Array.isArray(f)&&e.marker.color!==f?f:u?r.background:r.defaultLine,s("marker.line.color",c),a(t,"marker.line")&&o(t,e,l,s,{prefix:"marker.line.",cLetter:"c"}),s("marker.line.width",u?1:0),u&&(s("marker.sizeref"),s("marker.sizemin"),s("marker.sizemode"))}},{"../../components/color":27,"../../components/colorscale/defaults":36,"../../components/colorscale/has_colorscale":40,"./subtypes":254}],251:[function(t,e,n){"use strict";function r(t,e){var n;e.selectAll("g.trace").each(function(t){var e=i.select(this);if(n=t[0].trace,n._nexttrace){if(n._nextFill=e.select(".js-fill.js-tonext"),!n._nextFill.size()){var r=":first-child";e.select(".js-fill.js-tozero").size()&&(r+=" + *"),n._nextFill=e.insert("path",r).attr("class","js-fill js-tonext")}}else e.selectAll(".js-fill.js-tonext").remove(),n._nextFill=null;n.fill&&("tozero"===n.fill.substr(0,6)||"toself"===n.fill||"to"===n.fill.substr(0,2)&&!n._prevtrace)?(n._ownFill=e.select(".js-fill.js-tozero"),n._ownFill.size()||(n._ownFill=e.insert("path",":first-child").attr("class","js-fill js-tozero"))):(e.selectAll(".js-fill.js-tozero").remove(),n._ownFill=null)})}function a(t,e,n,r,a,h,g){function m(t){return k?t.transition():t}function v(t){return t.filter(function(t){return t.vis})}function y(t){return t.id}function x(t){if(t.ids)return y}function b(){return!1}function _(t){var e,n,r=t[0].trace,a=i.select(this),o=u.hasMarkers(r),c=u.hasText(r),f=x(r),d=b,h=b;o&&(d=r.marker.maxdisplayed?v:l.identity),c&&(h=r.marker.maxdisplayed?v:l.identity),n=a.selectAll("path.point"),e=n.data(d,f);var p=e.enter().append("path").classed("point",!0);p.call(s.pointStyle,r).call(s.translatePoints,A,T,r),k&&p.style("opacity",0).transition().style("opacity",1),e.each(function(t){var e=m(i.select(this));s.translatePoint(t,e,A,T),s.singlePointStyle(t,e,r)}),k?e.exit().transition().style("opacity",0).remove():e.exit().remove(),n=a.selectAll("g"),e=n.data(h,f),e.enter().append("g").append("text"),e.each(function(t){var e=m(i.select(this).select("text"));s.translatePoint(t,e,A,T)}),e.selectAll("text").call(s.textPointStyle,r).each(function(t){var e=t.xp||A.c2p(t.x),n=t.yp||T.c2p(t.y);i.select(this).selectAll("tspan").each(function(){m(i.select(this)).attr({x:e,y:n})})}),e.exit().remove()}var w,M;o(t,e,n,r,a);var k=!!g&&g.duration>0,A=n.xaxis,T=n.yaxis,L=r[0].trace,C=L.line,z=i.select(h);if(z.call(c.plot,n,g),L.visible===!0){m(z).style("opacity",L.opacity);var S,O,P=L.fill.charAt(L.fill.length-1);"x"!==P&&"y"!==P&&(P=""),r[0].node3=z,f(r);var E="",N=[],D=L._prevtrace;D&&(E=D._prevRevpath||"",O=D._nextFill,N=D._polygons);var R,j,I,F,B,q,H,V,G,U="",X="",Y=[],Z=[],W=l.noop;if(S=L._ownFill,u.hasLines(L)||"none"!==L.fill){for(O&&O.datum(r),["hv","vh","hvh","vhv"].indexOf(C.shape)!==-1?(I=s.steps(C.shape),F=s.steps(C.shape.split("").reverse().join(""))):I=F="spline"===C.shape?function(t){var e=t[t.length-1];return t[0][0]===e[0]&&t[0][1]===e[1]?s.smoothclosed(t.slice(1),C.smoothing):s.smoothopen(t,C.smoothing)}:function(t){return"M"+t.join("L")},B=function(t){return F(t.reverse())},Y=d(r,{xaxis:A,yaxis:T,connectGaps:L.connectgaps,baseTolerance:Math.max(C.width||1,3)/4,linear:"linear"===C.shape,simplify:C.simplify}),G=L._polygons=new Array(Y.length),M=0;M1}),W=function(t){return function(e){if(R=I(e),j=B(e),U?P?(U+="L"+R.substr(1),X=j+("L"+X.substr(1))):(U+="Z"+R,X=j+"Z"+X):(U=R,X=j),u.hasLines(L)&&e.length>1){var n=i.select(this);if(n.datum(r),t)m(n.style("opacity",0).attr("d",R).call(s.lineGroupStyle)).style("opacity",1);else{var a=m(n);a.attr("d",R),s.singleLineStyle(r,a)}}}}}var Q=z.selectAll(".js-line").data(Z);m(Q.exit()).style("opacity",0).remove(),Q.each(W(!1)),Q.enter().append("path").classed("js-line",!0).style("vector-effect","non-scaling-stroke").call(s.lineGroupStyle).each(W(!0)),Y.length&&(S?q&&V&&(P?("y"===P?q[1]=V[1]=T.c2p(0,!0):"x"===P&&(q[0]=V[0]=A.c2p(0,!0)),m(S).attr("d","M"+V+"L"+q+"L"+U.substr(1))):m(S).attr("d",U+"Z")):"tonext"===L.fill.substr(0,6)&&U&&E&&("tonext"===L.fill?m(O).attr("d",U+"Z"+E+"Z"):m(O).attr("d",U+"L"+E.substr(1)+"Z"),L._polygons=L._polygons.concat(N)),L._prevRevpath=X,L._prevPolygons=G);var $=z.selectAll(".points");w=$.data([r]),$.each(_),w.enter().append("g").classed("points",!0).each(_),w.exit().remove()}}function o(t,e,n,r,a){var o=n.xaxis,l=n.yaxis,s=i.extent(o.range.map(o.r2l).map(o.l2c)),c=i.extent(l.range.map(l.r2l).map(l.l2c)),f=r[0].trace;if(u.hasMarkers(f)){var d=f.marker.maxdisplayed;if(0!==d){var h=r.filter(function(t){return t.x>=s[0]&&t.x<=s[1]&&t.y>=c[0]&&t.y<=c[1]}),p=Math.ceil(h.length/d),g=0;a.forEach(function(t,n){var r=t[0].trace;u.hasMarkers(r)&&r.marker.maxdisplayed>0&&n0;for(u=p.selectAll("g.trace"),f=u.data(n,function(t){return t[0].trace.uid}),f.enter().append("g").attr("class",function(t){return"trace scatter trace"+t[0].trace.uid}).style("stroke-miterlimit",2),h(t,e,n),r(t,p),s=0,c=[];sr?1:-1}),m){l&&(d=l());var v=i.transition().duration(o.duration).ease(o.easing).each("end",function(){d&&d()}).each("interrupt",function(){d&&d()});v.each(function(){p.selectAll("g.trace").each(function(r,i){a(t,i,e,r,n,this,o)})})}else p.selectAll("g.trace").each(function(r,i){a(t,i,e,r,n,this,o)});g&&f.exit().remove(),p.selectAll("path:not([d])").remove()}},{"../../components/drawing":50,"../../components/errorbars":56,"../../lib":122,"../../lib/polygon":129,"./arrays_to_calcdata":233,"./line_points":246,"./link_traces":248,"./subtypes":254,d3:10}],252:[function(t,e,n){"use strict";var r=t("./subtypes"),a=.2;e.exports=function(t,e){var n,o,i,l,s=t.cd,c=t.xaxis,u=t.yaxis,f=[],d=s[0].trace,h=d.index,p=d.marker,g=!r.hasMarkers(d)&&!r.hasText(d);if(d.visible===!0&&!g){var m=Array.isArray(p.opacity)?1:p.opacity;if(e===!1)for(n=0;n0&&(i[l-1].gapAfter=!0):(l++,i.push(u))}return a(e),i}},{"../scatter/colorscale_calc":238,"fast-isnumeric":13}],259:[function(t,e,n){"use strict";function r(t,e,n){var r,a,o=0,i=n("locations");return i?(n("locationmode"),o=i.length):(r=n("lon")||[],a=n("lat")||[],o=Math.min(r.length,a.length),o")}var a=t("../../plots/cartesian/graph_interact"),o=t("../../plots/cartesian/axes"),i=t("../scatter/get_trace_color"),l=t("./attributes");e.exports=function(t){function e(t){return u.projection(t)}function n(t){var n=t.lonlat;if(null===n[0]||null===n[1])return 1/0;if(u.isLonLatOverEdges(n))return 1/0;var r=e(n),a=s.c2p(),o=c.c2p(),i=Math.abs(a-r[0]),l=Math.abs(o-r[1]),f=Math.max(3,t.mrc||0);return Math.max(Math.sqrt(i*i+l*l)-f,1-3/f)}var o=t.cd,l=o[0].trace,s=t.xa,c=t.ya,u=t.subplot;if(!o[0].placeholder&&(a.getClosest(o,n,t),t.index!==!1)){var f=o[t.index],d=f.lonlat,h=e(d),p=f.mrc||1;return t.x0=h[0]-p,t.x1=h[0]+p,t.y0=h[1]-p,t.y1=h[1]+p,t.loc=f.loc,t.lat=d[0],t.lon=d[1],t.color=i(l,f),t.extraText=r(l,f,u.mockAxis),[t]}}},{"../../plots/cartesian/axes":150,"../../plots/cartesian/graph_interact":157,"../scatter/get_trace_color":242,"./attributes":257}],262:[function(t,e,n){"use strict";var r={};r.attributes=t("./attributes"),r.supplyDefaults=t("./defaults"),r.colorbar=t("../scatter/colorbar"),r.calc=t("./calc"),r.plot=t("./plot"),r.hoverPoints=t("./hover"),r.eventData=t("./event_data"),r.moduleType="trace",r.name="scattergeo",r.basePlotModule=t("../../plots/geo"),r.categories=["geo","symbols","markerColorscale","showLegend"],r.meta={},e.exports=r},{"../../plots/geo":174,"../scatter/colorbar":237,"./attributes":257,"./calc":258,"./defaults":259,"./event_data":260,"./hover":261,"./plot":263}],263:[function(t,e,n){"use strict";function r(t,e){if(!Array.isArray(t.locations))return c.identity;var n=u(t,e),r=t.locationmode;return function(t){var e=f(r,t.loc,n);return e?(t.lonlat=e.properties.ct,t):(t.lonlat=[null,null],!1)}}function a(t,e,n){function r(t,r){h(t,e,r,n)}var a=t.marker;if(r(t.text,"tx"),r(t.textposition,"tp"),t.textfont&&(r(t.textfont.size,"ts"),r(t.textfont.color,"tc"),r(t.textfont.family,"tf")),a&&a.line){var o=a.line;r(a.opacity,"mo"),r(a.symbol,"mx"),r(a.color,"mc"),r(a.size,"ms"),r(o.color,"mlc"),r(o.width,"mlw")}}function o(t){var e=t.framework.selectAll("g.trace.scattergeo");e.style("opacity",function(t){return t[0].trace.opacity}),e.each(function(t){var e=t[0].trace,n=i.select(this);n.selectAll("path.point").call(l.pointStyle,e),n.selectAll("text").call(l.textPointStyle,e)}),e.selectAll("path.js-line").style("fill","none").each(function(t){var e=i.select(this),n=t.trace,r=n.line||{};e.call(s.stroke,r.color).call(l.dashLine,r.dash||"",r.width||0),"none"!==n.fill&&e.call(s.fill,n.fillcolor)})}var i=t("d3"),l=t("../../components/drawing"),s=t("../../components/color"),c=t("../../lib"),u=t("../../lib/topojson_utils").getTopojsonFeatures,f=t("../../lib/geo_location_utils").locationToFeature,d=t("../../lib/geojson_utils"),h=t("../../lib/array_to_calc_item"),p=t("../scatter/subtypes");e.exports=function(t,e){function n(t){return t[0].trace.uid}var l=t.framework.select(".scattergeolayer").selectAll("g.trace.scattergeo").data(e,n);l.enter().append("g").attr("class","trace scattergeo"),l.exit().remove(),l.selectAll("*").remove(),l.each(function(e){var n=i.select(this),o=e[0].trace,l=r(o,t.topojson);e[0].placeholder&&n.remove();for(var s=[],c=0;c