forked from square/cubism
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cubism.v1.min.js
1 lines (1 loc) · 26.4 KB
/
cubism.v1.min.js
1
!function(exports){var cubism=exports.cubism={version:"1.4.0"};var cubism_id=0;function cubism_identity(d){return d}cubism.option=function(name,defaultValue){var values=cubism.options(name);return values.length?values[0]:defaultValue};cubism.options=function(name,defaultValues){var options=location.search.substring(1).split("&"),values=[],i=-1,n=options.length,o;while(++i<n){if((o=options[i].split("="))[0]==name){values.push(decodeURIComponent(o[1]))}}return values.length||arguments.length<2?values:defaultValues};cubism.context=function(){var context=new cubism_context,step=1e4,size=1440,start0,stop0,start1,stop1,serverDelay=5e3,clientDelay=5e3,seek=0,event=d3.dispatch("prepare","beforechange","change","focus"),scale=context.scale=d3.time.scale().range([0,size]),timeout,focus;function update(){if(seek!=0){stop0=new Date(Math.floor(seek/step)*step);start0=new Date(stop0-size*step);stop1=stop0;start1=start0;scale.domain([start0,stop0])}else{var now=Date.now();stop0=new Date(Math.floor((now-serverDelay-clientDelay)/step)*step);start0=new Date(stop0-size*step);stop1=new Date(Math.floor((now-serverDelay)/step)*step);start1=new Date(stop1-size*step);scale.domain([start0,stop0])}return context}context.start=function(){if(seek!=0){event.prepare.call(context,start1,stop1,function(){event.beforechange.call(context,start1,stop1);event.change.call(context,start1,stop1);event.focus.call(context,focus)})}else{if(timeout)clearTimeout(timeout);var delay=+stop1+serverDelay-Date.now();if(delay<clientDelay)delay+=step;timeout=setTimeout(function prepare(){stop1=new Date(Math.floor((Date.now()-serverDelay)/step)*step);start1=new Date(stop1-size*step);event.prepare.call(context,start1,stop1);setTimeout(function(){scale.domain([start0=start1,stop0=stop1]);event.beforechange.call(context,start1,stop1);event.change.call(context,start1,stop1);event.focus.call(context,focus)},clientDelay);timeout=setTimeout(prepare,step)},delay)}return context};context.stop=function(){timeout=clearTimeout(timeout);return context};timeout=setTimeout(context.start,10);context.seek=function(_){if(!arguments.length)return seek;seek=+_;return update().stop().start()};context.step=function(_){if(!arguments.length)return step;step=+_;return update()};context.size=function(_){if(!arguments.length)return size;scale.range([0,size=+_]);return update()};context.serverDelay=function(_){if(!arguments.length)return serverDelay;serverDelay=+_;return update()};context.clientDelay=function(_){if(!arguments.length)return clientDelay;clientDelay=+_;return update()};context.focus=function(i){event.focus.call(context,focus=i);return context};context.on=function(type,listener){if(arguments.length<2)return event.on(type);event.on(type,listener);if(listener!=null){if(/^prepare(\.|$)/.test(type))listener.call(context,start1,stop1);if(/^beforechange(\.|$)/.test(type))listener.call(context,start0,stop0);if(/^change(\.|$)/.test(type))listener.call(context,start0,stop0);if(/^focus(\.|$)/.test(type))listener.call(context,focus)}return context};d3.select(window).on("keydown.context-"+ ++cubism_id,function(){switch(!d3.event.metaKey&&d3.event.keyCode){case 37:if(focus==null)focus=size-1;if(focus>0)context.focus(--focus);break;case 39:if(focus==null)focus=size-2;if(focus<size-1)context.focus(++focus);break;default:return}d3.event.preventDefault()});return update()};function cubism_context(){}var cubism_contextPrototype=cubism.context.prototype=cubism_context.prototype;cubism_contextPrototype.constant=function(value){return new cubism_metricConstant(this,+value)};cubism_contextPrototype.cube=function(host){if(!arguments.length)host="";var source={},context=this;source.metric=function(expression){return context.metric(function(start,stop,step,callback){d3.json(host+"/1.0/metric"+"?expression="+encodeURIComponent(expression)+"&start="+cubism_cubeFormatDate(start)+"&stop="+cubism_cubeFormatDate(stop)+"&step="+step,function(data){if(!data)return callback(new Error("unable to load data"));callback(null,data.map(function(d){return d.value}))})},expression+="")};source.toString=function(){return host};return source};var cubism_cubeFormatDate=d3.time.format.iso;cubism_contextPrototype.librato=function(user,token){var source={},context=this;auth_string="Basic "+btoa(user+":"+token);enable_log=true,avail_rsts=[1,60,900,3600];function log(msg){if(enable_log)console.log(msg)}function log_interval(start,stop,step){log("---------------------- Starting request");log("START: "+new Date(start*1e3));log("STOP : "+new Date(stop*1e3));log("STEP : "+step);var nes_num_mes=(stop-start)/step;log("# of measurements necessary: "+nes_num_mes)}function find_ideal_librato_resolution(step){var highest_res=avail_rsts[0],lowest_res=avail_rsts[avail_rsts.length];if(step>=lowest_res)return lowest_res;if(step<=highest_res)return highest_res;var iof,top_res,i;for(i=step;i<=lowest_res;i++){iof=avail_rsts.indexOf(i);if(iof>-1){top_res=avail_rsts[iof];break}}var low_res;for(i=step;i>=highest_res;i--){iof=avail_rsts.indexOf(i);if(iof>-1){low_res=avail_rsts[iof];break}}return top_res-step<step-low_res?top_res:low_res}function find_librato_resolution(sdate,edate,step){var i_size=edate-sdate,month=2419200,week=604800,two_days=172800,ideal_res;if(i_size>month)return 3600;ideal_res=find_ideal_librato_resolution(step);if(i_size>week&&ideal_res<900)return 900;else if(i_size>two_days&&ideal_res<60)return 60;else return ideal_res}var librato_request=function(metric,source){var url_prefix="https://metrics-api.librato.com/v1/metrics";function make_url(sdate,edate,step){var params="start_time="+sdate+"&end_time="+edate+"&resolution="+find_librato_resolution(sdate,edate,step);full_url=url_prefix+"/"+metric+"?"+params;log("full_url = "+full_url);log_interval(sdate,edate,step);return full_url}function down_up_sampling(isdate,iedate,step,librato_mm){var av=[];for(i=isdate;i<=iedate;i+=step){var int_mes=[];while(librato_mm.length&&librato_mm[0].measure_time<=i){int_mes.push(librato_mm.shift().value)}var v;if(int_mes.length){v=int_mes.reduce(function(a,b){return a+b})/int_mes.length}else{v=av.length?av[av.length-1]:0}av.push(v)}return av}request={};request.fire=function(isdate,iedate,step,callback_done){var a_values=[];function actual_request(full_url){d3.json(full_url).header("X-Requested-With","XMLHttpRequest").header("Authorization",auth_string).header("Librato-User-Agent","cubism/"+cubism.version).get(function(error,data){if(!error){log("# of partial measurements: "+data.measurements[source].length);data.measurements[source].forEach(function(o){a_values.push(o)});var still_more_values="query"in data&&"next_time"in data.query;if(still_more_values){log("Requesting more values");actual_request(make_url(data.query.next_time,iedate,step))}else{log("total number of measurements from librato: "+a_values.length);var a_adjusted=down_up_sampling(isdate,iedate,step,a_values);log("number of measurements after adjusting time values: "+a_adjusted.length);callback_done(a_adjusted)}}else{log("There was an error when performing the librato request:");log(error)}})}actual_request(make_url(isdate,iedate,step))};return request};source.metric=function(m_name,m_source){return context.metric(function(start,stop,step,callback){librato_request(m_name,m_source).fire(cubism_libratoFormatDate(start),cubism_libratoFormatDate(stop),cubism_libratoFormatDate(step),function(a_values){callback(null,a_values)})},m_name+="")};source.toString=function(){return"librato"};return source};var cubism_libratoFormatDate=function(time){return Math.floor(time/1e3)};cubism_contextPrototype.graphite=function(host){if(!arguments.length)host="";var source={},context=this;source.metric=function(expression){var sum="sum";var metric=context.metric(function(start,stop,step,callback){var target=expression;if(step!==1e4)target="summarize("+target+",'"+(!(step%36e5)?step/36e5+"hour":!(step%6e4)?step/6e4+"min":step/1e3+"sec")+"','"+sum+"')";d3.text(host+"/render?format=raw"+"&target="+encodeURIComponent("alias("+target+",'')")+"&from="+cubism_graphiteFormatDate(start-2*step)+"&until="+cubism_graphiteFormatDate(stop-1e3),function(text){if(!text)return callback(new Error("unable to load data"));callback(null,cubism_graphiteParse(text))})},expression+="");metric.summarize=function(_){sum=_;return metric};return metric};source.find=function(pattern,callback){d3.json(host+"/metrics/find?format=completer"+"&query="+encodeURIComponent(pattern),function(result){if(!result)return callback(new Error("unable to find metrics"));callback(null,result.metrics.map(function(d){return d.path}))})};source.toString=function(){return host};return source};function cubism_graphiteFormatDate(time){return Math.floor(time/1e3)}function cubism_graphiteParse(text){var i=text.indexOf("|"),meta=text.substring(0,i),c=meta.lastIndexOf(","),b=meta.lastIndexOf(",",c-1),a=meta.lastIndexOf(",",b-1),start=meta.substring(a+1,b)*1e3,step=meta.substring(c+1)*1e3;return text.substring(i+1).split(",").slice(1).map(function(d){return+d})}cubism_contextPrototype.gangliaWeb=function(config){var host="",uriPathPrefix="/ganglia2/";if(arguments.length){if(config.host){host=config.host}if(config.uriPathPrefix){uriPathPrefix=config.uriPathPrefix;if(uriPathPrefix[0]!="/"){uriPathPrefix="/"+uriPathPrefix}if(uriPathPrefix[uriPathPrefix.length-1]!="/"){uriPathPrefix+="/"}}}var source={},context=this;source.metric=function(metricInfo){var clusterName=metricInfo.clusterName,metricName=metricInfo.metricName,hostName=metricInfo.hostName,isReport=metricInfo.isReport||false,titleGenerator=metricInfo.titleGenerator||function(unusedMetricInfo){return"clusterName:"+clusterName+" metricName:"+metricName+(hostName?" hostName:"+hostName:"")},onChangeCallback=metricInfo.onChangeCallback;var metricKeyName=isReport?"g":"m";var gangliaWebMetric=context.metric(function(start,stop,step,callback){function constructGangliaWebRequestQueryParams(){return"c="+clusterName+"&"+metricKeyName+"="+metricName+(hostName?"&h="+hostName:"")+"&cs="+start/1e3+"&ce="+stop/1e3+"&step="+step/1e3+"&graphlot=1"}d3.json(host+uriPathPrefix+"graph.php?"+constructGangliaWebRequestQueryParams(),function(result){if(!result){return callback(new Error("Unable to fetch GangliaWeb data"))}callback(null,result[0].data)})},titleGenerator(metricInfo));gangliaWebMetric.toString=function(){return titleGenerator(metricInfo)};if(onChangeCallback){gangliaWebMetric.on("change",onChangeCallback)}return gangliaWebMetric};source.toString=function(){return host+uriPathPrefix};return source};function cubism_metric(context){if(!(context instanceof cubism_context))throw new Error("invalid context");this.context=context}var cubism_metricPrototype=cubism_metric.prototype;cubism.metric=cubism_metric;cubism_metricPrototype.valueAt=function(){return NaN};cubism_metricPrototype.alias=function(name){this.toString=function(){return name};return this};cubism_metricPrototype.extent=function(){var i=0,n=this.context.size(),value,min=Infinity,max=-Infinity;while(++i<n){value=this.valueAt(i);if(value<min)min=value;if(value>max)max=value}return[min,max]};cubism_metricPrototype.on=function(type,listener){return arguments.length<2?null:this};cubism_metricPrototype.shift=function(){return this};cubism_metricPrototype.on=function(){return arguments.length<2?null:this};cubism_contextPrototype.metric=function(request,name){var context=this,metric=new cubism_metric(context),id=".metric-"+ ++cubism_id,start=-Infinity,stop,step=context.step(),size=context.size(),values=[],event=d3.dispatch("change"),listening=0,fetching;function prepare(start1,stop,callback){if(start1>start){var steps=Math.min(size,Math.round((start1-start)/step));if(!steps||fetching)return;fetching=true;steps=Math.min(size,steps+cubism_metricOverlap);var start0=new Date(stop-steps*step);request(start0,stop,step,function(error,data){fetching=false;if(error)return console.warn(error);var i=isFinite(start)?Math.round((start0-start)/step):0;for(var j=0,m=data.length;j<m;++j)values[j+i]=data[j];event.change.call(metric,start,stop);if(callback!=null)callback()})}else{var steps=Math.min(size,Math.round((start-start1)/step));if(!steps||fetching)return;fetching=true;var stop0=new Date(+start1+steps*step);request(start1,stop0,step,function(error,data){fetching=false;if(error)return console.warn(error);prevalues=[];for(var j=0,m=data.length;j<m;++j)prevalues[j]=data[j];values=prevalues.concat(values);event.change.call(metric,start,stop);if(callback!=null)callback()})}}function beforechange(start1,stop1){if(!isFinite(start))start=start1;if(start1>start)values.splice(0,Math.max(0,Math.min(size,Math.round((start1-start)/step))));else values.splice(stop1,Math.max(0,Math.min(size,Math.round((start-start1)/step))));start=start1;stop=stop1}metric.valueAt=function(i){return values[i]};metric.shift=function(offset){return context.metric(cubism_metricShift(request,+offset))};metric.on=function(type,listener){if(!arguments.length)return event.on(type);if(listener==null){if(event.on(type)!=null&&--listening==0){context.on("prepare"+id,null).on("beforechange"+id,null)}}else{if(event.on(type)==null&&++listening==1){context.on("prepare"+id,prepare).on("beforechange"+id,beforechange)}}event.on(type,listener);if(listener!=null){if(/^change(\.|$)/.test(type))listener.call(context,start,stop)}return metric};if(arguments.length>1)metric.toString=function(){return name};return metric};var cubism_metricOverlap=6;function cubism_metricShift(request,offset){return function(start,stop,step,callback){request(new Date(+start+offset),new Date(+stop+offset),step,callback)}}function cubism_metricConstant(context,value){cubism_metric.call(this,context);value=+value;var name=value+"";this.valueOf=function(){return value};this.toString=function(){return name}}var cubism_metricConstantPrototype=cubism_metricConstant.prototype=Object.create(cubism_metric.prototype);cubism_metricConstantPrototype.valueAt=function(){return+this};cubism_metricConstantPrototype.extent=function(){return[+this,+this]};function cubism_metricOperator(name,operate){function cubism_metricOperator(left,right){if(!(right instanceof cubism_metric))right=new cubism_metricConstant(left.context,right);else if(left.context!==right.context)throw new Error("mismatch context");cubism_metric.call(this,left.context);this.left=left;this.right=right;this.toString=function(){return left+" "+name+" "+right}}var cubism_metricOperatorPrototype=cubism_metricOperator.prototype=Object.create(cubism_metric.prototype);cubism_metricOperatorPrototype.valueAt=function(i){return operate(this.left.valueAt(i),this.right.valueAt(i))};cubism_metricOperatorPrototype.shift=function(offset){return new cubism_metricOperator(this.left.shift(offset),this.right.shift(offset))};cubism_metricOperatorPrototype.on=function(type,listener){if(arguments.length<2)return this.left.on(type);this.left.on(type,listener);this.right.on(type,listener);return this};return function(right){return new cubism_metricOperator(this,right)}}cubism_metricPrototype.add=cubism_metricOperator("+",function(left,right){return left+right});cubism_metricPrototype.subtract=cubism_metricOperator("-",function(left,right){return left-right});cubism_metricPrototype.multiply=cubism_metricOperator("*",function(left,right){return left*right});cubism_metricPrototype.divide=cubism_metricOperator("/",function(left,right){return left/right});cubism_contextPrototype.horizon=function(){var context=this,mode="offset",buffer=document.createElement("canvas"),width=buffer.width=context.size(),height=buffer.height=30,scale=d3.scale.linear().interpolate(d3.interpolateRound),metric=cubism_identity,extent=null,title=cubism_identity,format=d3.format(".2s"),colors=["#08519c","#3182bd","#6baed6","#bdd7e7","#bae4b3","#74c476","#31a354","#006d2c"];function horizon(selection){selection.on("mousemove.horizon",function(){context.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.horizon",function(){context.focus(null)});selection.append("canvas").attr("width",width).attr("height",height);selection.append("span").attr("class","title").text(title);selection.append("span").attr("class","value");selection.each(function(d,i){var that=this,id=++cubism_id,metric_=typeof metric==="function"?metric.call(that,d,i):metric,colors_=typeof colors==="function"?colors.call(that,d,i):colors,extent_=typeof extent==="function"?extent.call(that,d,i):extent,start=-Infinity,step=context.step(),canvas=d3.select(that).select("canvas"),span=d3.select(that).select(".value"),max_,m=colors_.length>>1,ready;canvas.datum({id:id,metric:metric_});canvas=canvas.node().getContext("2d");function change(start1,stop){canvas.save();var extent=metric_.extent();ready=extent.every(isFinite);if(extent_!=null)extent=extent_;var i0=0,max=Math.max(-extent[0],extent[1]);var iEnd=width;if(this===context){if(max==max_){if(start1<start){var dx=(start-start1)/step;iEnd=dx;if(dx<width){var canvas0=buffer.getContext("2d");canvas0.clearRect(0,0,width,height);canvas0.drawImage(canvas.canvas,0,0,width-dx,height,dx,0,width-dx,height);canvas.clearRect(0,0,width,height);canvas.drawImage(canvas0.canvas,0,0)}}else{var dx=(start1-start)/step;i0=width-dx-cubism_metricOverlap;if(dx<width){var canvas0=buffer.getContext("2d");canvas0.clearRect(0,0,width,height);canvas0.drawImage(canvas.canvas,dx,0,width-dx,height,0,0,width-dx,height);canvas.clearRect(0,0,width,height);canvas.drawImage(canvas0.canvas,0,0)}}}else{canvas.clearRect(0,0,width,height)}start=start1}scale.domain([0,max_=max]);canvas.clearRect(i0,0,iEnd,height);var negative;for(var j=0;j<m;++j){canvas.fillStyle=colors_[m+j];var y0=(j-m+1)*height;scale.range([m*height+y0,y0]);y0=scale(0);for(var i=i0,n=iEnd,y1;i<n;++i){y1=metric_.valueAt(i);if(y1<=0){negative=true;continue}if(y1===undefined)continue;canvas.fillRect(i,y1=scale(y1),1,y0-y1)}}if(negative){if(mode==="offset"){canvas.translate(0,height);canvas.scale(1,-1)}for(var j=0;j<m;++j){canvas.fillStyle=colors_[m-1-j];var y0=(j-m+1)*height;scale.range([m*height+y0,y0]);y0=scale(0);for(var i=i0,n=iEnd,y1;i<n;++i){y1=metric_.valueAt(i);if(y1>=0)continue;canvas.fillRect(i,scale(-y1),1,y0-scale(-y1))}}}canvas.restore()}function focus(i){if(i==null)i=width-1;var value=metric_.valueAt(i);span.datum(value).text(isNaN(value)?null:format)}context.on("change.horizon-"+id,change);context.on("focus.horizon-"+id,focus);metric_.on("change.horizon-"+id,function(start,stop){change(start,stop),focus();if(ready)metric_.on("change.horizon-"+id,cubism_identity)})})}horizon.remove=function(selection){selection.on("mousemove.horizon",null).on("mouseout.horizon",null);selection.selectAll("canvas").each(remove).remove();selection.selectAll(".title,.value").remove();function remove(d){d.metric.on("change.horizon-"+d.id,null);context.on("change.horizon-"+d.id,null);context.on("focus.horizon-"+d.id,null)}};horizon.mode=function(_){if(!arguments.length)return mode;mode=_+"";return horizon};horizon.height=function(_){if(!arguments.length)return height;buffer.height=height=+_;return horizon};horizon.metric=function(_){if(!arguments.length)return metric;metric=_;return horizon};horizon.scale=function(_){if(!arguments.length)return scale;scale=_;return horizon};horizon.extent=function(_){if(!arguments.length)return extent;extent=_;return horizon};horizon.title=function(_){if(!arguments.length)return title;title=_;return horizon};horizon.format=function(_){if(!arguments.length)return format;format=_;return horizon};horizon.colors=function(_){if(!arguments.length)return colors;colors=_;return horizon};return horizon};cubism_contextPrototype.comparison=function(){var context=this,width=context.size(),height=120,scale=d3.scale.linear().interpolate(d3.interpolateRound),primary=function(d){return d[0]},secondary=function(d){return d[1]},extent=null,title=cubism_identity,formatPrimary=cubism_comparisonPrimaryFormat,formatChange=cubism_comparisonChangeFormat,colors=["#9ecae1","#225b84","#a1d99b","#22723a"],strokeWidth=1.5;function comparison(selection){selection.on("mousemove.comparison",function(){context.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.comparison",function(){context.focus(null)});selection.append("canvas").attr("width",width).attr("height",height);selection.append("span").attr("class","title").text(title);selection.append("span").attr("class","value primary");selection.append("span").attr("class","value change");selection.each(function(d,i){var that=this,id=++cubism_id,primary_=typeof primary==="function"?primary.call(that,d,i):primary,secondary_=typeof secondary==="function"?secondary.call(that,d,i):secondary,extent_=typeof extent==="function"?extent.call(that,d,i):extent,div=d3.select(that),canvas=div.select("canvas"),spanPrimary=div.select(".value.primary"),spanChange=div.select(".value.change"),ready;canvas.datum({id:id,primary:primary_,secondary:secondary_});canvas=canvas.node().getContext("2d");function change(start,stop){canvas.save();canvas.clearRect(0,0,width,height);var primaryExtent=primary_.extent(),secondaryExtent=secondary_.extent(),extent=extent_==null?primaryExtent:extent_;scale.domain(extent).range([height,0]);ready=primaryExtent.concat(secondaryExtent).every(isFinite);var round=start/context.step()&1?cubism_comparisonRoundOdd:cubism_comparisonRoundEven;canvas.fillStyle=colors[2];for(var i=0,n=width;i<n;++i){var y0=scale(primary_.valueAt(i)),y1=scale(secondary_.valueAt(i));if(y0<y1)canvas.fillRect(round(i),y0,1,y1-y0)}canvas.fillStyle=colors[0];for(i=0;i<n;++i){var y0=scale(primary_.valueAt(i)),y1=scale(secondary_.valueAt(i));if(y0>y1)canvas.fillRect(round(i),y1,1,y0-y1)}canvas.fillStyle=colors[3];for(i=0;i<n;++i){var y0=scale(primary_.valueAt(i)),y1=scale(secondary_.valueAt(i));if(y0<=y1)canvas.fillRect(round(i),y0,1,strokeWidth)}canvas.fillStyle=colors[1];for(i=0;i<n;++i){var y0=scale(primary_.valueAt(i)),y1=scale(secondary_.valueAt(i));if(y0>y1)canvas.fillRect(round(i),y0-strokeWidth,1,strokeWidth)}canvas.restore()}function focus(i){if(i==null)i=width-1;var valuePrimary=primary_.valueAt(i),valueSecondary=secondary_.valueAt(i),valueChange=(valuePrimary-valueSecondary)/valueSecondary;spanPrimary.datum(valuePrimary).text(isNaN(valuePrimary)?null:formatPrimary);spanChange.datum(valueChange).text(isNaN(valueChange)?null:formatChange).attr("class","value change "+(valueChange>0?"positive":valueChange<0?"negative":""))}primary_.on("change.comparison-"+id,firstChange);secondary_.on("change.comparison-"+id,firstChange);function firstChange(start,stop){change(start,stop),focus();if(ready){primary_.on("change.comparison-"+id,cubism_identity);secondary_.on("change.comparison-"+id,cubism_identity)}}context.on("change.comparison-"+id,change);context.on("focus.comparison-"+id,focus)})}comparison.remove=function(selection){selection.on("mousemove.comparison",null).on("mouseout.comparison",null);selection.selectAll("canvas").each(remove).remove();selection.selectAll(".title,.value").remove();function remove(d){d.primary.on("change.comparison-"+d.id,null);d.secondary.on("change.comparison-"+d.id,null);context.on("change.comparison-"+d.id,null);context.on("focus.comparison-"+d.id,null)}};comparison.height=function(_){if(!arguments.length)return height;height=+_;return comparison};comparison.primary=function(_){if(!arguments.length)return primary;primary=_;return comparison};comparison.secondary=function(_){if(!arguments.length)return secondary;secondary=_;return comparison};comparison.scale=function(_){if(!arguments.length)return scale;scale=_;return comparison};comparison.extent=function(_){if(!arguments.length)return extent;extent=_;return comparison};comparison.title=function(_){if(!arguments.length)return title;title=_;return comparison};comparison.formatPrimary=function(_){if(!arguments.length)return formatPrimary;formatPrimary=_;return comparison};comparison.formatChange=function(_){if(!arguments.length)return formatChange;formatChange=_;return comparison};comparison.colors=function(_){if(!arguments.length)return colors;colors=_;return comparison};comparison.strokeWidth=function(_){if(!arguments.length)return strokeWidth;strokeWidth=_;return comparison};return comparison};var cubism_comparisonPrimaryFormat=d3.format(".2s"),cubism_comparisonChangeFormat=d3.format("+.0%");function cubism_comparisonRoundEven(i){return i&16777214}function cubism_comparisonRoundOdd(i){return(i+1&16777214)-1}cubism_contextPrototype.axis=function(){var context=this,scale=context.scale,axis_=d3.svg.axis().scale(scale);var format=context.step()<6e4?cubism_axisFormatSeconds:context.step()<864e5?cubism_axisFormatMinutes:cubism_axisFormatDays;function axis(selection){var id=++cubism_id,tick;var g=selection.append("svg").datum({id:id}).attr("width",context.size()).attr("height",Math.max(28,-axis.tickSize())).append("g").attr("transform","translate(0,"+(axis_.orient()==="top"?27:4)+")").call(axis_);context.on("change.axis-"+id,function(){g.call(axis_);if(!tick)tick=d3.select(g.node().appendChild(g.selectAll("text").node().cloneNode(true))).style("display","none").text(null)});context.on("focus.axis-"+id,function(i){if(tick){if(i==null){tick.style("display","none");g.selectAll("text").style("fill-opacity",null)}else{tick.style("display",null).attr("x",i).text(format(scale.invert(i)));var dx=tick.node().getComputedTextLength()+6;g.selectAll("text").style("fill-opacity",function(d){return Math.abs(scale(d)-i)<dx?0:1})}}})}axis.remove=function(selection){selection.selectAll("svg").each(remove).remove();function remove(d){context.on("change.axis-"+d.id,null);context.on("focus.axis-"+d.id,null)}};return d3.rebind(axis,axis_,"orient","ticks","tickSubdivide","tickSize","tickPadding","tickFormat")};var cubism_axisFormatSeconds=d3.time.format("%I:%M:%S %p"),cubism_axisFormatMinutes=d3.time.format("%I:%M %p"),cubism_axisFormatDays=d3.time.format("%B %d");cubism_contextPrototype.rule=function(){var context=this,metric=cubism_identity;function rule(selection){var id=++cubism_id;var line=selection.append("div").datum({id:id}).attr("class","line").call(cubism_ruleStyle);selection.each(function(d,i){var that=this,id=++cubism_id,metric_=typeof metric==="function"?metric.call(that,d,i):metric;if(!metric_)return;function change(start,stop){var values=[];for(var i=0,n=context.size();i<n;++i){if(metric_.valueAt(i)){values.push(i)}}var lines=selection.selectAll(".metric").data(values);lines.exit().remove();lines.enter().append("div").attr("class","metric line").call(cubism_ruleStyle);lines.style("left",cubism_ruleLeft)}context.on("change.rule-"+id,change);metric_.on("change.rule-"+id,change)});context.on("focus.rule-"+id,function(i){line.datum(i).style("display",i==null?"none":null).style("left",i==null?null:cubism_ruleLeft)})}rule.remove=function(selection){selection.selectAll(".line").each(remove).remove();function remove(d){context.on("focus.rule-"+d.id,null)}};rule.metric=function(_){if(!arguments.length)return metric;metric=_;return rule};return rule};function cubism_ruleStyle(line){line.style("position","absolute").style("top",0).style("bottom",0).style("width","1px").style("pointer-events","none")}function cubism_ruleLeft(i){return i+"px"}}(this);