diff --git a/cubism.v1.js b/cubism.v1.js index 19970ca..9e69c0d 100644 --- a/cubism.v1.js +++ b/cubism.v1.js @@ -681,6 +681,10 @@ cubism_contextPrototype.metric = function(request, name) { return values[i]; }; + metric.values = function() { + return values; + }; + // metric.shift = function(offset) { return context.metric(cubism_metricShift(request, +offset)); @@ -814,6 +818,7 @@ cubism_contextPrototype.horizon = function() { function horizon(selection) { selection + //here focus is being set to mouse x, but other places it corresponds to the data array index. .on("mousemove.horizon", function() { context.focus(Math.round(d3.mouse(this)[0])); }) .on("mouseout.horizon", function() { context.focus(null); }); @@ -900,8 +905,8 @@ cubism_contextPrototype.horizon = function() { for (var i = i0, n = dataSize, y1; i < n; ++i) { y1 = metric_.valueAt(i); - rLeft = i*xScale; - rWidth = xScale; + rLeft = Math.round(i*xScale); + rWidth = Math.round(xScale); if (y1 <= 0) { negative = true; continue; } if (y1 === undefined) continue; canvas.fillRect(rLeft, y1 = scale(y1), rWidth, y0 - y1); @@ -927,7 +932,8 @@ cubism_contextPrototype.horizon = function() { for (var i = i0, n = dataSize, y1; i < n; ++i) { y1 = metric_.valueAt(i); if (y1 >= 0) continue; - canvas.fillRect(i*xScale, scale(-y1), xScale, y0 - scale(-y1)); + canvas.fillRect(Math.round(i*xScale), scale(-y1), + Math.round(xScale), y0 - scale(-y1)); } } } @@ -935,10 +941,14 @@ cubism_contextPrototype.horizon = function() { canvas.restore(); } - function focus(i) { - if (i == null) i = dataSize - 1; - var value = metric_.valueAt(i); + function focus(mouse_x) { + if (mouse_x == null) mouse_x = dataSize - 1; + // since we are getting mouse_x and it's a scaled value, + // need to convert this back to an index to look up + var index = Math.round(mouse_x/xScale); + var value = metric_.valueAt(index); span.datum(value).text(isNaN(value) ? null : format); + span.style("left", mouse_x+"px"); } // Update the chart when the context changes. @@ -1368,10 +1378,10 @@ cubism_contextPrototype.rule = function() { 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); + context.on("focus.rule-" + id, function(mouse_x) { + line.datum(mouse_x) + .style("display", mouse_x == null ? "none" : null) + .style("left", mouse_x == null ? null : cubism_ruleLeft); }); } diff --git a/cubism.v1.min.js b/cubism.v1.min.js index e69de29..9f6b4a0 100644 --- a/cubism.v1.min.js +++ b/cubism.v1.min.js @@ -0,0 +1 @@ +(function(a){function d(a){return a}function e(){}function j(a){return Math.floor(a/1e3)}function k(a){var b=a.indexOf("|"),c=a.substring(0,b),d=c.lastIndexOf(","),e=c.lastIndexOf(",",d-1),f=c.lastIndexOf(",",e-1),g=c.substring(f+1,e)*1e3,h=c.substring(d+1)*1e3;return a.substring(b+1).split(",").slice(1).map(function(a){return+a})}function l(a){return a.getTime()/1e3+"s"}function m(a,b){var c=b,d=JSON.parse(a.response),e=d[0].columns.indexOf(c);return e<0&&(e=d[0].columns.length-1),d[0].points.map(function(a){return a[e]})}function n(a){if(!(a instanceof e))throw new Error("invalid context");this.context=a}function q(a,b){return function(c,d,e,f){a(new Date(+c+b),new Date(+d+b),e,f)}}function r(a,b){n.call(this,a),b=+b;var c=b+"";this.valueOf=function(){return b},this.toString=function(){return c}}function t(a,b){function c(b,c){if(c instanceof n){if(b.context!==c.context)throw new Error("mismatch context")}else c=new r(b.context,c);n.call(this,b.context),this.left=b,this.right=c,this.toString=function(){return b+" "+a+" "+c}}var d=c.prototype=Object.create(n.prototype);return d.valueAt=function(a){return b(this.left.valueAt(a),this.right.valueAt(a))},d.shift=function(a){return new c(this.left.shift(a),this.right.shift(a))},d.on=function(a,b){return arguments.length<2?this.left.on(a):(this.left.on(a,b),this.right.on(a,b),this)},function(a){return new c(this,a)}}function w(a){return a&16777214}function x(a){return(a+1&16777214)-1}function B(a){a.style("position","absolute").style("top",0).style("bottom",0).style("width","1px").style("pointer-events","none")}function C(a){return a+"px"}var b=a.cubism={version:"1.6.0"},c=0;b.option=function(a,c){var d=b.options(a);return d.length?d[0]:c},b.options=function(a,b){var c=location.search.substring(1).split("&"),d=[],e=-1,f=c.length,g;while(++e=1?f/d:1,n.range([0,d*p]);var c=Date.now();return h=new Date(Math.floor((c-k-l)/b)*b),g=new Date(h-d*b),j=new Date(Math.floor((c-k)/b)*b),i=new Date(j-d*b),n.domain([g,h]),a}var a=new e,b=1e4,d=1440,f=1440,g,h,i,j,k=5e3,l=5e3,m=d3.dispatch("prepare","beforechange","change","focus"),n=a.scale=d3.time.scale().range([0,d]),o,p,q;return a.xScale=function(){return p},a.start=function(){o&&clearTimeout(o);var c=+j+k-Date.now();return c0&&a.focus(--q);break;case 39:q==null&&(q=d-2),q=c)return c;if(a<=b)return b;var d,e,f;for(f=a;f<=c;f++){d=avail_rsts.indexOf(f);if(d>-1){e=avail_rsts[d];break}}var g;for(f=a;f>=b;f--){d=avail_rsts.indexOf(f);if(d>-1){g=avail_rsts[d];break}}return e-ae?3600:(i=f(c),d>g&&i<900?900:d>h&&i<60?60:i)}var d={},e=this;auth_string="Basic "+btoa(a+":"+c),avail_rsts=[1,60,900,3600];var j=function(a){function d(b,d,e){var f="compose="+a+"&start_time="+b+"&end_time="+d+"&resolution="+g(b,d,e);return c+"?"+f}function e(a,b,c,d){var e=[];for(i=a;i<=b;i+=c){var f=[];while(d.length&&d[0].measure_time<=i)f.push(d.shift().value);var g;f.length?g=f.reduce(function(a,b){return a+b})/f.length:g=e.length?e[e.length-1]:0,e.push(g)}return e}var c="https://metrics-api.librato.com/v1/metrics";return request={},request.fire=function(a,c,f,g){function i(j){d3.json(j).header("X-Requested-With","XMLHttpRequest").header("Authorization",auth_string).header("Librato-User-Agent","cubism/"+b.version).get(function(b,j){if(!b){if(j.measurements.length===0)return;j.measurements[0].series.forEach(function(a){h.push(a)});var k="query"in j&&"next_time"in j.query;if(k)i(d(j.query.next_time,c,f));else{var l=e(a,c,f,h);g(l)}}})}var h=[];i(d(a,c,f))},request};return d.metric=function(a){return e.metric(function(b,c,d,e){j(a).fire(h(b),h(c),h(d),function(a){e(null,a)})},a+="")},d.toString=function(){return"librato"},d};var h=function(a){return Math.floor(a/1e3)};f.graphite=function(a){arguments.length||(a="");var b={},c=this;return b.metric=function(b){var d="sum",e=c.metric(function(c,e,f,g){var h=b;f!==1e4&&(h="summarize("+h+",'"+(f%36e5?f%6e4?f/1e3+"sec":f/6e4+"min":f/36e5+"hour")+"','"+d+"')"),d3.text(a+"/render?format=raw"+"&target="+encodeURIComponent("alias("+h+",'')")+"&from="+j(c-2*f)+"&until="+j(e-1e3),function(a){if(!a)return g(new Error("unable to load data"));g(null,k(a))})},b+="");return e.summarize=function(a){return d=a,e},e},b.find=function(b,c){d3.json(a+"/metrics/find?format=completer"+"&query="+encodeURIComponent(b),function(a){if(!a)return c(new Error("unable to find metrics"));c(null,a.metrics.map(function(a){return a.path}))})},b.toString=function(){return a},b},f.influxdb=function(a){arguments.length||(a="");var b={},c=this;return b.metric=function(b){return c.metric(function(c,d,e,f){var g="&q=select+sum("+b.column+")+from+"+b.series+"+group+by+time("+e*1e3+"u)+fill(0)"+"+where"+"+time+<+"+l(d)+"+and+time+>+"+l(c),h=a+g;d3.xhr(h,"application/json",function(a,b){if(!b)return f(new Error("unable to load data"));f(null,m(b))})},b)},b.toString=function(){return a},b},f.gangliaWeb=function(a){var b="",c="/ganglia2/";arguments.length&&(a.host&&(b=a.host),a.uriPathPrefix&&(c=a.uriPathPrefix,c[0]!="/"&&(c="/"+c),c[c.length-1]!="/"&&(c+="/")));var d={},e=this;return d.metric=function(a){var d=a.clusterName,f=a.metricName,g=a.hostName,h=a.isReport||!1,i=a.titleGenerator||function(a){return"clusterName:"+d+" metricName:"+f+(g?" hostName:"+g:"")},j=a.onChangeCallback,k=h?"g":"m",l=e.metric(function(a,e,h,i){function j(){return"c="+d+"&"+k+"="+f+(g?"&h="+g:"")+"&cs="+a/1e3+"&ce="+e/1e3+"&step="+h/1e3+"&graphlot=1"}d3.json(b+c+"graph.php?"+j(),function(a){if(!a)return i(new Error("Unable to fetch GangliaWeb data"));i(null,a[0].data)})},i(a));return l.toString=function(){return i(a)},j&&l.on("change",j),l},d.toString=function(){return b+c},d};var o=n.prototype;b.metric=n,o.valueAt=function(){return NaN},o.alias=function(a){return this.toString=function(){return a},this},o.extent=function(){var a=0,b=this.context.size(),c,d=Infinity,e=-Infinity;while(++ae&&(e=c);return[d,e]},o.on=function(a,b){return arguments.length<2?null:this},o.shift=function(){return this},o.on=function(){return arguments.length<2?null:this},f.metric=function(a,b){function r(b,c){var d=Math.min(j,Math.round((b-g)/i));if(!d||o)return;o=!0,d=Math.min(j,d+p);var f=new Date(c-d*i);a(f,c,i,function(a,b){o=!1;if(a)return console.warn(a);var d=isFinite(g)?Math.round((f-g)/i):0;for(var h=0,j=b.length;h1&&(e.toString=function(){return b}),e};var p=6,s=r.prototype=Object.create(n.prototype);s.valueAt=function(){return+this},s.extent=function(){return[+this,+this]},o.add=t("+",function(a,b){return a+b}),o.subtract=t("-",function(a,b){return a-b}),o.multiply=t("*",function(a,b){return a*b}),o.divide=t("/",function(a,b){return a/b}),f.horizon=function(){function r(r){r.on("mousemove.horizon",function(){a.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.horizon",function(){a.focus(null)}),r.append("canvas").attr("width",g*b).attr("height",h),r.append("span").attr("class","title").text(l),r.append("span").attr("class","value"),r.each(function(l,r){function E(c,d){z.save();var j=u.extent();D=j.every(isFinite),w!=null&&(j=w);var k=0,l=Math.max(-j[0],j[1]);if(this===a){if(l==B){k=g-p;var m=(c-x)/y;if(m=0)continue;z.fillRect(Math.round(E*b),i(-G),Math.round(b),A-i(-G))}}}z.restore()}function F(a){a==null&&(a=g-1);var c=Math.round(a/b),d=u.valueAt(c);A.datum(d).text(isNaN(d)?null:m),A.style("left",a+"px")}var s=this,t=++c,u=typeof j=="function"?j.call(s,l,r):j,v=typeof n=="function"?n.call(s,l,r):n,w=typeof k=="function"?k.call(s,l,r):k,x=-Infinity,y=a.step(),z=d3.select(s).select("canvas"),A=d3.select(s).select(".value"),B,C=v.length>>1,D;z.datum({id:t,metric:u}),z=z.node().getContext("2d"),a.on("change.horizon-"+t,E),a.on("focus.horizon-"+t,F),u.on("change.horizon-"+t,function(a,b){E(a,b),F(),D&&u.on("change.horizon-"+t,d)})})}var a=this,b=a.xScale(),e="offset",f=document.createElement("canvas"),g=a.size(),h=f.height=30,i=d3.scale.linear().interpolate(d3.interpolateRound),j=d,k=null,l=d,m=d3.format(".2s"),n=["#08519c","#3182bd","#6baed6","#bdd7e7","#bae4b3","#74c476","#31a354","#006d2c"],o,q;return f.width=g*b,r.remove=function(b){function c(b){b.metric.on("change.horizon-"+b.id,null),a.on("change.horizon-"+b.id,null),a.on("focus.horizon-"+b.id,null)}b.on("mousemove.horizon",null).on("mouseout.horizon",null),b.selectAll("canvas").each(c).remove(),b.selectAll(".title,.value").remove()},r.mode=function(a){return arguments.length?(e=a+"",r):e},r.height=function(a){return arguments.length?(f.height=h=+a,r):h},r.metric=function(a){return arguments.length?(j=a,r):j},r.scale=function(a){return arguments.length?(i=a,r):i},r.extent=function(a){return arguments.length?(k=a,r):k},r.title=function(a){return arguments.length?(l=a,r):l},r.format=function(a){return arguments.length?(m=a,r):m},r.colors=function(a){return arguments.length?(n=a,r):n},r},f.comparison=function(){function o(o){o.on("mousemove.comparison",function(){a.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.comparison",function(){a.focus(null)}),o.append("canvas").attr("width",b).attr("height",e),o.append("span").attr("class","title").text(j),o.append("span").attr("class","value primary"),o.append("span").attr("class","value change"),o.each(function(j,o){function B(c,d){v.save(),v.clearRect(0,0,b,e);var g=r.extent(),h=s.extent(),i=t==null?g:t;f.domain(i).range([e,0]),A=g.concat(h).every(isFinite);var j=c/a.step()&1?x:w;v.fillStyle=m[2];for(var k=0,l=b;kp&&v.fillRect(j(k),p,1,o-p)}v.fillStyle=m[3];for(k=0;kp&&v.fillRect(j(k),o-n,1,n)}v.restore()}function C(a){a==null&&(a=b-1);var c=r.valueAt(a),d=s.valueAt(a),e=(c-d)/d;y.datum(c).text(isNaN(c)?null:k),z.datum(e).text(isNaN(e)?null:l).attr("class","value change "+(e>0?"positive":e<0?"negative":""))}function D(a,b){B(a,b),C(),A&&(r.on("change.comparison-"+q,d),s.on("change.comparison-"+q,d))}var p=this,q=++c,r=typeof g=="function"?g.call(p,j,o):g,s=typeof h=="function"?h.call(p,j,o):h,t=typeof i=="function"?i.call(p,j,o):i,u=d3.select(p),v=u.select("canvas"),y=u.select(".value.primary"),z=u.select(".value.change"),A;v.datum({id:q,primary:r,secondary:s}),v=v.node().getContext("2d"),r.on("change.comparison-"+q,D),s.on("change.comparison-"+q,D),a.on("change.comparison-"+q,B),a.on("focus.comparison-"+q,C)})}var a=this,b=a.size(),e=120,f=d3.scale.linear().interpolate(d3.interpolateRound),g=function(a){return a[0]},h=function(a){return a[1]},i=null,j=d,k=u,l=v,m=["#9ecae1","#225b84","#a1d99b","#22723a"],n=1.5;return o.remove=function(b){function c(b){b.primary.on("change.comparison-"+b.id,null),b.secondary.on("change.comparison-"+b.id,null),a.on("change.comparison-"+b.id,null),a.on("focus.comparison-"+b.id,null)}b.on("mousemove.comparison",null).on("mouseout.comparison",null),b.selectAll("canvas").each(c).remove(),b.selectAll(".title,.value").remove()},o.height=function(a){return arguments.length?(e=+a,o):e},o.primary=function(a){return arguments.length?(g=a,o):g},o.secondary=function(a){return arguments.length?(h=a,o):h},o.scale=function(a){return arguments.length?(f=a,o):f},o.extent=function(a){return arguments.length?(i=a,o):i},o.title=function(a){return arguments.length?(j=a,o):j},o.formatPrimary=function(a){return arguments.length?(k=a,o):k},o.formatChange=function(a){return arguments.length?(l=a,o):l},o.colors=function(a){return arguments.length?(m=a,o):m},o.strokeWidth=function(a){return arguments.length?(n=a,o):n},o};var u=d3.format(".2s"),v=d3.format("+.0%");f.axis=function(){function h(f){var i=++c,j,k=Math.floor(a.size()*e),l=f.append("svg").datum({id:i}).attr("width",k).attr("height",Math.max(28,-h.tickSize())).append("g").attr("transform","translate(0,"+(d.orient()==="top"?27:4)+")").call(d);a.on("change.axis-"+i,function(){l.call(d),j||(j=d3.select(l.node().appendChild(l.selectAll("text").node().cloneNode(!0))).style("display","none").text(null))}),a.on("focus.axis-"+i,function(a){if(j)if(a==null)j.style("display","none"),l.selectAll("text").style("fill-opacity",null);else{j.style("display",null).attr("x",a).text(g(b.invert(a)));var c=j.node().getComputedTextLength()+6;l.selectAll("text").style("fill-opacity",function(d){return Math.abs(b(d)-a)= 0) continue; - canvas.fillRect(i*xScale, scale(-y1), xScale, y0 - scale(-y1)); + canvas.fillRect(Math.round(i*xScale), scale(-y1), + Math.round(xScale), y0 - scale(-y1)); } } } @@ -138,10 +140,14 @@ cubism_contextPrototype.horizon = function() { canvas.restore(); } - function focus(i) { - if (i == null) i = dataSize - 1; - var value = metric_.valueAt(i); + function focus(mouse_x) { + if (mouse_x == null) mouse_x = dataSize - 1; + // since we are getting mouse_x and it's a scaled value, + // need to convert this back to an index to look up + var index = Math.round(mouse_x/xScale); + var value = metric_.valueAt(index); span.datum(value).text(isNaN(value) ? null : format); + span.style("left", mouse_x+"px"); } // Update the chart when the context changes. diff --git a/src/metric.js b/src/metric.js index ff3e75f..93fac5f 100644 --- a/src/metric.js +++ b/src/metric.js @@ -84,6 +84,10 @@ cubism_contextPrototype.metric = function(request, name) { return values[i]; }; + metric.values = function() { + return values; + }; + // metric.shift = function(offset) { return context.metric(cubism_metricShift(request, +offset)); diff --git a/src/rule.js b/src/rule.js index 603a677..7abc775 100644 --- a/src/rule.js +++ b/src/rule.js @@ -36,10 +36,10 @@ cubism_contextPrototype.rule = function() { 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); + context.on("focus.rule-" + id, function(mouse_x) { + line.datum(mouse_x) + .style("display", mouse_x == null ? "none" : null) + .style("left", mouse_x == null ? null : cubism_ruleLeft); }); }