From 454c5e4605047fbe64bb8bf44856b8617f218eb1 Mon Sep 17 00:00:00 2001 From: Bob Monteverde Date: Sun, 8 Apr 2012 02:59:44 -0400 Subject: [PATCH] Drastic speed increase with line.js, needed for stackedAre chart --- Makefile | 1 + examples/stackedAreaWithLegend.html | 4 +- nv.d3.js | 308 ++++++++++++++++++++++------ nv.d3.min.js | 4 +- src/models/line.js | 35 ++-- src/models/stackedArea.js | 1 + 6 files changed, 273 insertions(+), 80 deletions(-) diff --git a/Makefile b/Makefile index 1432be5..13dfff4 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ JS_FILES = \ src/models/sparkline.js \ src/models/stackedArea.js \ src/models/stackedAreaWithLegend.js \ + src/charts/lineChart.js \ src/outro.js JS_COMPILER = \ diff --git a/examples/stackedAreaWithLegend.html b/examples/stackedAreaWithLegend.html index 1a7b842..06fc3a4 100644 --- a/examples/stackedAreaWithLegend.html +++ b/examples/stackedAreaWithLegend.html @@ -36,8 +36,8 @@ text { //Format A nv.addGraph({ generate: function() { - var n = 6, // number of layers - m = 200; // number of samples per layer + var n = 4, // number of layers + m = 120; // number of samples per layer... 10 years of monthly //color = d3.interpolateRgb("#aad", "#556"); //format data to our liking, add keys diff --git a/nv.d3.js b/nv.d3.js index 6b9d5af..cbfdc5f 100644 --- a/nv.d3.js +++ b/nv.d3.js @@ -619,6 +619,7 @@ nv.models.line = function() { getX = function(d) { return d.x }, getY = function(d) { return d.y }, interactive = true, + clipVoronoi = true, xDomain, yDomain; var x = d3.scale.linear(), @@ -629,17 +630,19 @@ nv.models.line = function() { function chart(selection) { selection.each(function(data) { - var seriesData = data.map(function(d) { return d.values }); + var seriesData = data.map(function(d) { return d.values }), + availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; x0 = x0 || x; y0 = y0 || y; - //TODO: consider reusing the parent's scales (almost always making duplicates of the same scale) + x .domain(xDomain || d3.extent(d3.merge(seriesData), getX )) - .range([0, width - margin.left - margin.right]); + .range([0, availableWidth]); y .domain(yDomain || d3.extent(d3.merge(seriesData), getY )) - .range([height - margin.top - margin.bottom, 0]); + .range([availableHeight, 0]); var wrap = d3.select(this).selectAll('g.d3line').data([data]); @@ -657,8 +660,8 @@ nv.models.line = function() { .attr('id', 'chart-clip-path-' + id) .append('rect'); wrap.select('#chart-clip-path-' + id + ' rect') - .attr('width', width - margin.left - margin.right) - .attr('height', height - margin.top - margin.bottom); + .attr('width', availableWidth) + .attr('height', availableHeight); gEnter .attr('clip-path', 'url(#chart-clip-path-' + id + ')'); @@ -666,12 +669,18 @@ nv.models.line = function() { var shiftWrap = gEnter.append('g').attr('class', 'shiftWrap'); - //TODO: currently doesnt remove if user renders, then turns off interactions... currently must turn off before the first render (will need to fix) - if (interactive) { + + // destroy interactive layer during transition, + // VERY needed because of performance issues + g.selectAll('.point-clips *, .point-paths *').remove(); + + + function interactiveLayer() { + if (!interactive) return false; + shiftWrap.append('g').attr('class', 'point-clips'); shiftWrap.append('g').attr('class', 'point-paths'); - var vertices = d3.merge(data.map(function(line, lineIndex) { return line.values.map(function(point, pointIndex) { //return [x(getX(point)), y(getY(point)), lineIndex, pointIndex]; //inject series and point index for reference into voronoi @@ -680,8 +689,7 @@ nv.models.line = function() { }) ); - - + // ***These clips are more than half the cause for the slowdown*** //var pointClips = wrap.select('.point-clips').selectAll('clipPath') // **BROWSER BUG** can't reselect camel cased elements var pointClips = wrap.select('.point-clips').selectAll('.clip-path') .data(vertices); @@ -695,23 +703,19 @@ nv.models.line = function() { //inject series and point index for reference into voronoi + // considering adding a removeZeros option, may be useful for the stacked chart and maybe others var voronoi = d3.geom.voronoi(vertices).map(function(d, i) { return { 'data': d, 'series': vertices[i][2], 'point': vertices[i][3] } }); //TODO: Add small amount noise to prevent duplicates var pointPaths = wrap.select('.point-paths').selectAll('path') .data(voronoi); - pointPaths.enter().append('path') .attr('class', function(d,i) { return 'path-'+i; }) - //.style('fill', d3.rgb(230, 230, 230)) - //.style('stroke', d3.rgb(200, 200, 200)) .style('fill-opacity', 0); - pointPaths.exit().remove(); - pointPaths - .attr('clip-path', function(d,i) { return 'url(#clip-' + id + '-' + d.series + '-' + d.point +')' }) + .attr('clip-path', function(d,i) { return clipVoronoi ? 'url(#clip-' + id + '-' + d.series + '-' + d.point +')' : '' }) .attr('d', function(d) { return 'M' + d.data.join(',') + 'Z'; }) .on('mouseover', function(d) { var series = data[d.series], @@ -759,12 +763,15 @@ nv.models.line = function() { lines .attr('class', function(d,i) { return 'line series-' + i }) .classed('hover', function(d) { return d.hover }) - .style('fill', function(d,i){ return color[i % 20] }) - .style('stroke', function(d,i){ return color[i % 20] }) + .style('fill', function(d,i){ return color[i % 10] }) + .style('stroke', function(d,i){ return color[i % 10] }) d3.transition(lines) .style('stroke-opacity', 1) - .style('fill-opacity', .5); + .style('fill-opacity', .5) + //.each('end', function(d,i) { if (!i) setTimeout(interactiveLayer, 0) }); //trying to call this after transitions are over, doesn't work on resize! + //.each('end', function(d,i) { if (!i) interactiveLayer() }); //trying to call this after transitions are over, not sure if the timeout gains anything + setTimeout(interactiveLayer, 1000); //seems not to work as well as above... BUT fixes broken resize var paths = lines.selectAll('path') .data(function(d, i) { return [d.values] }); @@ -866,6 +873,12 @@ nv.models.line = function() { return chart; }; + chart.clipVoronoi= function(_) { + if (!arguments.length) return clipVoronoi; + clipVoronoi = _; + return chart; + }; + chart.dotRadius = function(_) { if (!arguments.length) return dotRadius; dotRadius = d3.functor(_); @@ -1091,6 +1104,7 @@ nv.models.lineWithFocus = function() { selection.transition().call(chart); }); +/* legend.dispatch.on('legendMouseover', function(d, i) { d.hover = true; selection.transition().call(chart) @@ -1099,7 +1113,7 @@ nv.models.lineWithFocus = function() { d.hover = false; selection.transition().call(chart) }); - +*/ focus.dispatch.on('pointMouseover.tooltip', function(e) { dispatch.tooltipShow({ @@ -1268,20 +1282,22 @@ nv.models.lineWithLegend = function() { function chart(selection) { selection.each(function(data) { var width = getWidth(), - height = getHeight(); + height = getHeight(), + availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; var series = data.filter(function(d) { return !d.disabled }) .map(function(d) { return d.values }); x .domain(d3.extent(d3.merge(series), getX )) - .range([0, width - margin.left - margin.right]); + .range([0, availableWidth]); y .domain(d3.extent(d3.merge(series), getY )) - .range([height - margin.top - margin.bottom, 0]); + .range([availableHeight, 0]); lines - .width(width - margin.left - margin.right) - .height(height - margin.top - margin.bottom) + .width(availableWidth) + .height(availableHeight) .color(data.map(function(d,i) { return d.color || color[i % 10]; }).filter(function(d,i) { return !data[i].disabled })) @@ -1310,6 +1326,8 @@ nv.models.lineWithLegend = function() { selection.transition().call(chart); }); +/* + // legend.dispatch.on('legendMouseover', function(d, i) { d.hover = true; selection.transition().call(chart) @@ -1319,6 +1337,7 @@ nv.models.lineWithLegend = function() { d.hover = false; selection.transition().call(chart) }); +*/ lines.dispatch.on('pointMouseover.tooltip', function(e) { dispatch.tooltipShow({ @@ -1339,14 +1358,14 @@ nv.models.lineWithLegend = function() { margin.top = legend.height(); var g = wrap.select('g') - .attr('transform', 'translate(' + margin.left + ',' + legend.height() + ')'); + .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); legend.width(width/2 - margin.right); g.select('.legendWrap') .datum(data) - .attr('transform', 'translate(' + (width/2 - margin.left) + ',' + (-legend.height()) +')') + .attr('transform', 'translate(' + (width/2 - margin.left) + ',' + (-margin.top) +')') .call(legend); @@ -1361,7 +1380,7 @@ nv.models.lineWithLegend = function() { .domain(x.domain()) .range(x.range()) .ticks( width / 100 ) - .tickSize(-(height - margin.top - margin.bottom), 0); + .tickSize(-availableHeight, 0); g.select('.x.axis') .attr('transform', 'translate(0,' + y.range()[0] + ')'); @@ -1372,7 +1391,7 @@ nv.models.lineWithLegend = function() { .domain(y.domain()) .range(y.range()) .ticks( height / 36 ) - .tickSize(-(width - margin.right - margin.left), 0); + .tickSize(-availableWidth, 0); d3.transition(g.select('.y.axis')) .call(yAxis); @@ -1450,7 +1469,9 @@ nv.models.scatter = function() { function chart(selection) { selection.each(function(data) { - var seriesData = data.map(function(d) { return d.values }); + var seriesData = data.map(function(d) { return d.values }), + availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; x0 = x0 || x; y0 = y0 || y; @@ -1471,10 +1492,10 @@ nv.models.scatter = function() { //TODO: figure out the best way to deal with scales with equal MIN and MAX x .domain(d3.extent(d3.merge(seriesData).map( getX ).concat(forceX) )) - .range([0, width - margin.left - margin.right]); + .range([0, availableWidth]); y .domain(d3.extent(d3.merge(seriesData).map( getY ).concat(forceY) )) - .range([height - margin.top - margin.bottom, 0]); + .range([availableHeight, 0]); z .domain(d3.extent(d3.merge(seriesData), getSize )) .range([2, 10]); @@ -1482,7 +1503,8 @@ nv.models.scatter = function() { var vertices = d3.merge(data.map(function(group, groupIndex) { return group.values.map(function(point, pointIndex) { - return [x(getX(point)), y(getY(point)), groupIndex, pointIndex]; //inject series and point index for reference into voronoi + //return [x(getX(point)), y(getY(point)), groupIndex, pointIndex]; //inject series and point index for reference into voronoi + return [x(getX(point)) * (Math.random() / 1e12 + 1) , y(getY(point)) * (Math.random() / 1e12 + 1), groupIndex, pointIndex]; //temp hack to add noise untill I think of a better way so there are no duplicates }) }) ); @@ -1507,8 +1529,8 @@ nv.models.scatter = function() { wrap.select('.voronoi-clip rect') .attr('x', -10) .attr('y', -10) - .attr('width', width - margin.left - margin.right + 20) - .attr('height', height - margin.top - margin.bottom + 20); + .attr('width', availableWidth + 20) + .attr('height', availableHeight + 20); wrap.select('.point-paths') .attr('clip-path', 'url(#voronoi-clip-path-' + id + ')'); @@ -1529,7 +1551,6 @@ nv.models.scatter = function() { var voronoi = d3.geom.voronoi(vertices).map(function(d, i) { return { 'data': d, 'series': vertices[i][2], 'point': vertices[i][3] } }); - //TODO: Need to deal with duplicates, maybe add small amount of noise to all var pointPaths = wrap.select('.point-paths').selectAll('path') .data(voronoi); pointPaths.enter().append('path') @@ -2028,9 +2049,12 @@ nv.models.stackedArea = function() { width = 960, height = 500, color = d3.scale.category10().range(), + getX = function(d) { return d.x }, + getY = function(d) { return d.y }, style = 'stack', offset = 'zero', - order = 'default'; + order = 'default', + xDomain, yDomain; /************************************ * offset: @@ -2044,29 +2068,35 @@ nv.models.stackedArea = function() { * 'default' (input order) ************************************/ - var lines = nv.models.line(); + var lines = nv.models.line(), + x = d3.scale.linear(), + y = d3.scale.linear(); function chart(selection) { selection.each(function(data) { - // Need to leave data alone to switch between stacked, stream, and expanded - var dataCopy = JSON.parse(JSON.stringify(data)); + var dataCopy = JSON.parse(JSON.stringify(data)), + seriesData = dataCopy.map(function(d) { return d.values }), + availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; //compute the data based on offset and order (calc's y0 for every point) - dataCopy = d3.layout.stack().offset(offset).order(order).values(function(d){ return d.values })(dataCopy); + dataCopy = d3.layout.stack().offset(offset).order(order).values(function(d){ return d.values })(dataCopy); - var mx = dataCopy[0].values.length - 1, // assumes that all layers have same # of samples & that there is at least one layer - my = d3.max(dataCopy, function(d) { - return d3.max(d.values, function(d) { - return d.y0 + d.y; - }); - }); + x .domain(xDomain || d3.extent(d3.merge(seriesData), getX)) + .range([0, availableWidth]); + + y .domain(yDomain || [0, d3.max(dataCopy, function(d) { return d3.max(d.values, function(d) { return d.y0 + d.y }) }) ]) + .range([availableHeight, 0]); lines - .width(width - margin.left - margin.right) - .height(height - margin.top - margin.bottom) + //.interactive(false) + .width(availableWidth) + .height(availableHeight) + .xDomain(x.domain()) + .yDomain(y.domain()) .y(function(d) { return d.y + d.y0 }) .color(data.map(function(d,i) { return d.color || color[i % 10]; @@ -2090,23 +2120,19 @@ nv.models.stackedArea = function() { d3.transition(linesWrap).call(lines); - - // Update the stacked graph - var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom; - var area = d3.svg.area() - .x(function(d) { return d.x * availableWidth / mx; }) - .y0(function(d) { return availableHeight - d.y0 * availableHeight / my; }) - .y1(function(d) { return availableHeight - (d.y + d.y0) * availableHeight / my; }); + .x(function(d) { return x(getX(d)) }) + .y0(function(d) { return y(d.y0) }) + .y1(function(d) { return y(d.y + d.y0) }); var zeroArea = d3.svg.area() - .x(function(d) { return d.x * availableWidth / mx; }) - .y0(function(d) { return availableHeight - d.y0 * availableHeight / my; }) - .y1(function(d) { return availableHeight - d.y0 * availableHeight / my; }) + .x(function(d) { return x(getX(d)) }) + .y0(function(d) { return y(d.y0) }) + .y1(function(d) { return y(d.y0) }); + var path = g.select('.areaWrap').selectAll('path.area') - .data(function(d) { return d }); + .data(function(d) { return d }); path.enter().append('path').attr('class', 'area'); d3.transition(path.exit()) .attr('d', function(d,i) { return zeroArea(d.values,i) }) @@ -2438,4 +2464,162 @@ nv.models.stackedAreaWithLegend = function() { return chart; } + +// This is an attempt to make an extremely easy to use chart that is ready to go, +// basically the chart models with the extra glue... Queuing, tooltips, automatic resize, etc. +// I may make these more specific, like 'time series line with month end data points', etc. +// or may make yet another layer of abstraction... common settings. +nv.charts.line = function() { + var selector = null, + data = [], + duration = 500, + tooltip = function(key, x, y, e, graph) { + return '

' + key + '

' + + '

' + y + ' at ' + x + '

' + }; + + + var graph = nv.models.lineWithLegend(), + showTooltip = function(e) { + var offset = $(selector).offset(), + left = e.pos[0] + offset.left, + top = e.pos[1] + offset.top, + formatX = graph.xAxis.tickFormat(), + formatY = graph.yAxis.tickFormat(), + x = formatX(graph.x()(e.point)), + y = formatY(graph.y()(e.point)), + content = tooltip(e.series.key, x, y, e, graph); + + nvtooltip.show([left, top], content); + }; + + //setting component defaults + graph.xAxis.tickFormat(d3.format(',r')); + graph.yAxis.tickFormat(d3.format(',.2f')); + + + //TODO: consider a method more similar to how the models are built + function chart() { + if (!selector || !data.length) return chart; //do nothing if you have nothing to work with + + d3.select(selector).select('svg') + .datum(data) + .transition().duration(duration).call(graph); //consider using transition chaining like in the models + + return chart; + } + + + // This should always only be called once, then update should be used after, + // in which case should consider the 'd3 way' and merge this with update, + // but simply do this on enter... should try anoter example that way + chart.build = function() { + if (!selector || !data.length) return chart; //do nothing if you have nothing to work with + + nv.addGraph({ + generate: function() { + var container = d3.select(selector), + width = function() { return parseInt(container.style('width')) }, + height = function() { return parseInt(container.style('height')) }, + svg = container.append('svg'); + + graph + .width(width) + .height(height); + + svg + .attr('width', width()) + .attr('height', height()) + .datum(data) + .transition().duration(duration).call(graph); + + return graph; + }, + callback: function(graph) { + graph.dispatch.on('tooltipShow', showTooltip); + graph.dispatch.on('tooltipHide', nvtooltip.cleanup); + + //TODO: create resize queue and have nv core handle resize instead of binding all to window resize + $(window).resize(function() { + // now that width and height are functions, should be automatic..of course you can always override them + d3.select(selector + ' svg') + .attr('width', graph.width()()) //need to set SVG dimensions, chart is not aware of the SVG component + .attr('height', graph.height()()) + .call(graph); + }); + } + }); + + return chart; + }; + + + /* + // moved to chart() + chart.update = function() { + if (!selector || !data.length) return chart; //do nothing if you have nothing to work with + + d3.select(selector).select('svg') + .datum(data) + .transition().duration(duration).call(graph); + + return chart; + }; + */ + + chart.data = function(_) { + if (!arguments.length) return data; + data = _; + return chart; + }; + + chart.selector = function(_) { + if (!arguments.length) return selector; + selector = _; + return chart; + }; + + chart.duration = function(_) { + if (!arguments.length) return duration; + duration = _; + return chart; + }; + + chart.tooltip = function(_) { + if (!arguments.length) return tooltip; + tooltip = _; + return chart; + }; + + chart.xTickFormat = function(_) { + if (!arguments.length) return graph.xAxis.tickFormat(); + graph.xAxis.tickFormat(typeof _ === 'function' ? _ : d3.format(_)); + return chart; + }; + + chart.yTickFormat = function(_) { + if (!arguments.length) return graph.yAxis.tickFormat(); + graph.yAxis.tickFormat(typeof _ === 'function' ? _ : d3.format(_)); + return chart; + }; + + chart.xAxisLabel = function(_) { + if (!arguments.length) return graph.xAxis.axisLabel(); + graph.xAxis.axisLabel(_); + return chart; + }; + + chart.yAxisLabel = function(_) { + if (!arguments.length) return graph.yAxis.axisLabel(); + graph.yAxis.axisLabel(_); + return chart; + }; + + d3.rebind(chart, graph, 'x', 'y'); + + chart.graph = graph; // Give direct access for getter/setters, and dispatchers + + return chart; +}; + })(); diff --git a/nv.d3.min.js b/nv.d3.min.js index 79c2ef8..0988688 100644 --- a/nv.d3.min.js +++ b/nv.d3.min.js @@ -1,4 +1,4 @@ /***** * A no frills tooltip implementation. - *****/(function(a){var b=window.nvtooltip={};b.show=function(b,c,d,e){var f=a('
');d=d||"s",e=e||20,f.html(c).css({left:-1e3,top:-1e3,opacity:0}).appendTo("body");var g=f.height()+parseInt(f.css("padding-top"))+parseInt(f.css("padding-bottom")),h=f.width()+parseInt(f.css("padding-left"))+parseInt(f.css("padding-right")),i=a(window).width(),j=a(window).height(),k=a("body").scrollTop(),l=a("body").scrollLeft(),m,n;switch(d){case"e":m=b[0]-h-e,n=b[1]-g/2,mk+j&&(n=k-g-5);break;case"w":m=b[0]+e,n=b[1]-g/2,m+h>i&&(m=b[0]-h-e),nk+j&&(n=k-g-5);break;case"n":m=b[0]-h/2,n=b[1]+e,mi&&(m=i-h-5),n+g>k+j&&(n=b[1]-g-e);break;case"s":m=b[0]-h/2,n=b[1]-g-e,mi&&(m=i-h-5),k>n&&(n=b[1]+20)}f.css({left:m,top:n,opacity:1});return f},b.cleanup=function(){var b=a(".nvtooltip");b.css({"transition-delay":"0 !important","-moz-transition-delay":"0 !important","-webkit-transition-delay":"0 !important"}),b.css("opacity",0),setTimeout(function(){b.remove()},500)}})(jQuery),function(){function c(a,b,c){return function(d,e,f){var g=a(d),h=[];g1)while(gn&&(n=m);return"translate("+o+","+l+")"}),i.attr("transform","translate("+(b-a.right-n)+","+a.top+")"),c=a.top+a.bottom+l+15});return f}var a={top:5,right:0,bottom:5,left:10},b=400,c=20,d=d3.scale.category10().range(),e=d3.dispatch("legendClick","legendMouseover","legendMouseout");f.dispatch=e,f.margin=function(b){if(!arguments.length)return a;a=b;return f},f.width=function(a){if(!arguments.length)return b;b=a;return f},f.height=function(a){if(!arguments.length)return c;c=a;return f},f.color=function(a){if(!arguments.length)return d;d=a;return f};return f},a.models.xaxis=function(){function f(g){g.each(function(f){d.domain(a).range(b);var g=d3.select(this).selectAll("text.axislabel").data([c||null]);g.enter().append("text").attr("class","axislabel").attr("text-anchor","middle").attr("x",b[1]/2).attr("y",25),g.exit().remove(),g.text(function(a){return a}),d3.transition(d3.select(this)).call(e),d3.select(this).selectAll("line.tick").filter(function(a){return!parseFloat(Math.round(a*1e5)/1e6)}).classed("zero",!0)});return f}var a=[0,1],b=[0,1],c=!1,d=d3.scale.linear(),e=d3.svg.axis().scale(d).orient("bottom");f.domain=function(b){if(!arguments.length)return a;a=b;return f},f.range=function(a){if(!arguments.length)return b;b=a;return f},f.scale=function(a){if(!arguments.length)return d;d=a,e.scale(d);return f},f.axisLabel=function(a){if(!arguments.length)return c;c=a;return f},d3.rebind(f,e,"orient","ticks","tickSubdivide","tickSize","tickPadding","tickFormat");return f},a.models.yaxis=function(){function f(g){g.each(function(f){d.domain(a).range(b);var g=d3.select(this).selectAll("text.axislabel").data([c||null]);g.enter().append("text").attr("class","axislabel").attr("transform","rotate(-90)").attr("text-anchor","middle").attr("y",-40),g.exit().remove(),g.attr("x",-b[0]/2).text(function(a){return a}),d3.transition(d3.select(this)).call(e),d3.select(this).selectAll("line.tick").filter(function(a){return!parseFloat(Math.round(a*1e5)/1e6)}).classed("zero",!0)});return f}var a=[0,1],b=[0,1],c=!1,d=d3.scale.linear(),e=d3.svg.axis().scale(d).orient("left");f.domain=function(b){if(!arguments.length)return a;a=b;return f},f.range=function(a){if(!arguments.length)return b;b=a;return f},f.axisLabel=function(a){if(!arguments.length)return c;c=a;return f},d3.rebind(f,e,"scale","orient","ticks","tickSubdivide","tickSize","tickPadding","tickFormat");return f},a.models.bar=function(){function i(j){j.each(function(i){e.domain(["One","Two","Three","Four","Five"]).rangeRoundBands([0,b-a.left-a.right],.1),f.domain([0,d3.max(i,function(a){return a.y})]).range([c-a.top-a.bottom,0]),g.ticks(b/100),h.ticks(c/36).tickSize(-(b-a.right-a.left),0),h.tickSize(-(b-a.right-a.left),0);var j=d3.select(this).selectAll("g.wrap").data([i]),k=j.enter().append("g").attr("class","wrap").append("g");k.append("g").attr("class","x axis"),k.append("g").attr("class","y axis"),k.append("g").attr("class","bars"),j.attr("width",b).attr("height",c);var l=j.select("g").attr("transform","translate("+a.left+","+a.top+")"),m=j.select(".bars").selectAll(".bar").data(function(a){return a});m.exit().remove();var n=m.enter().append("g").attr("class","bar").on("mouseover",function(a,b){d3.select(this).classed("hover",!0)}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1)});n.append("rect").attr("y",function(a){return f(0)}),n.append("text").attr("text-anchor","middle").attr("dy","-4px"),m.attr("transform",function(a,b){return"translate("+e(a.label)+",0)"}),m.selectAll("rect").order().attr("width",e.rangeBand).transition().duration(d).attr("x",0).attr("y",function(a){return f(a.y)}).attr("height",function(a){return f.range()[0]-f(a.y)}),m.selectAll("text").attr("x",0).attr("y",function(a){return f(a.y)}).attr("dx",e.rangeBand()/2).text(function(a){return a.y}),l.select(".x.axis").attr("transform","translate(0,"+f.range()[0]+")").call(g),l.select(".y.axis").call(h)});return i}var a={top:20,right:10,bottom:20,left:60},b=960,c=500,d=500,e=d3.scale.ordinal(),f=d3.scale.linear(),g=d3.svg.axis().scale(e).orient("bottom").ticks(5),h=d3.svg.axis().scale(f).orient("left");i.margin=function(b){if(!arguments.length)return a;a=b;return i},i.width=function(c){if(!arguments.length)return b;a.left+a.right+20>c?b=a.left+a.right+20:b=c;return i},i.height=function(b){if(!arguments.length)return c;a.top+a.bottom+20>b?c=a.top+a.bottom+20:c=b;return i},i.animate=function(a){if(!arguments.length)return d;d=a;return i},i.xaxis={},d3.rebind(i.xaxis,g,"tickFormat"),i.yaxis={},d3.rebind(i.yaxis,h,"tickFormat");return i},a.models.line=function(){function q(r){r.each(function(q){var r=q.map(function(a){return a.values});o=o||l,p=p||m,l.domain(j||d3.extent(d3.merge(r),g)).range([0,b-a.left-a.right]),m.domain(k||d3.extent(d3.merge(r),h)).range([c-a.top-a.bottom,0]);var s=d3.select(this).selectAll("g.d3line").data([q]),t=s.enter().append("g").attr("class","d3line"),u=t.append("g");u.append("g").attr("class","lines");var v=s.select("g").attr("transform","translate("+a.left+","+a.top+")");t.append("defs").append("clipPath").attr("id","chart-clip-path-"+f).append("rect"),s.select("#chart-clip-path-"+f+" rect").attr("width",b-a.left-a.right).attr("height",c-a.top-a.bottom),u.attr("clip-path","url(#chart-clip-path-"+f+")");var w=u.append("g").attr("class","shiftWrap");if(i){w.append("g").attr("class","point-clips"),w.append("g").attr("class","point-paths");var z=d3.merge(q.map(function(a,b){return a.values.map(function(a,c){return[l(g(a))*(Math.random()/1e12+1),m(h(a))*(Math.random()/1e12+1),b,c]})})),A=s.select(".point-clips").selectAll(".clip-path").data(z);A.enter().append("clipPath").attr("class","clip-path").append("circle").attr("r",25),A.exit().remove(),A.attr("id",function(a,b){return"clip-"+f+"-"+a[2]+"-"+a[3]}).attr("transform",function(a){return"translate("+a[0]+","+a[1]+")"});var B=d3.geom.voronoi(z).map(function(a,b){return{data:a,series:z[b][2],point:z[b][3]}}),C=s.select(".point-paths").selectAll("path").data(B);C.enter().append("path").attr("class",function(a,b){return"path-"+b}).style("fill-opacity",0),C.exit().remove(),C.attr("clip-path",function(a,b){return"url(#clip-"+f+"-"+a.series+"-"+a.point+")"}).attr("d",function(a){return"M"+a.data.join(",")+"Z"}).on("mouseover",function(b){var c=q[b.series],d=c.values[b.point];n.pointMouseover({point:d,series:c,pos:[l(g(d))+a.left,m(h(d))+a.top],seriesIndex:b.series,pointIndex:b.point})}).on("mouseout",function(a,b){n.pointMouseout({point:q[a.series].values[a.point],series:q[a.series],seriesIndex:a.series,pointIndex:a.point})}),n.on("pointMouseover.point",function(a){s.select(".series-"+a.seriesIndex+" .point-"+a.pointIndex).classed("hover",!0)}),n.on("pointMouseout.point",function(a){s.select(".series-"+a.seriesIndex+" circle.point-"+a.pointIndex).classed("hover",!1)})}var D=s.select(".lines").selectAll(".line").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(D.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"line series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return e[b%20]}).style("stroke",function(a,b){return e[b%20]}),d3.transition(D).style("stroke-opacity",1).style("fill-opacity",.5);var E=D.selectAll("path").data(function(a,b){return[a.values]});E.enter().append("path").attr("d",d3.svg.line().x(function(a){return o(g(a))}).y(function(a){return p(h(a))})),d3.transition(D.exit().selectAll("path")).attr("d",d3.svg.line().x(function(a){return l(g(a))}).y(function(a){return m(h(a))})).remove(),d3.transition(E).attr("d",d3.svg.line().x(function(a){return l(g(a))}).y(function(a){return m(h(a))}));var F=D.selectAll("circle.point").data(function(a){return a.values});F.enter().append("circle").attr("cx",function(a){return o(g(a))}).attr("cy",function(a){return p(h(a))}),d3.transition(F.exit()).attr("cx",function(a){return l(g(a))}).attr("cy",function(a){return m(h(a))}).remove(),d3.transition(D.exit().selectAll("circle.point")).attr("cx",function(a){return l(g(a))}).attr("cy",function(a){return m(h(a))}).remove(),F.attr("class",function(a,b){return"point point-"+b}),d3.transition(F).attr("cx",function(a){return l(g(a))}).attr("cy",function(a){return m(h(a))}).attr("r",d),o=l.copy(),p=m.copy()});return q}var a={top:0,right:0,bottom:0,left:0},b=960,c=500,d=function(){return 2.5},e=d3.scale.category10().range(),f=Math.floor(Math.random()*1e4),g=function(a){return a.x},h=function(a){return a.y},i=!0,j,k,l=d3.scale.linear(),m=d3.scale.linear(),n=d3.dispatch("pointMouseover","pointMouseout"),o,p;q.dispatch=n,q.x=function(a){if(!arguments.length)return g;g=a;return q},q.y=function(a){if(!arguments.length)return h;h=a;return q},q.margin=function(b){if(!arguments.length)return a;a=b;return q},q.width=function(a){if(!arguments.length)return b;b=a;return q},q.height=function(a){if(!arguments.length)return c;c=a;return q},q.xDomain=function(a){if(!arguments.length)return j;j=a;return q},q.yDomain=function(a){if(!arguments.length)return k;k=a;return q},q.interactive=function(a){if(!arguments.length)return i;i=a;return q},q.dotRadius=function(a){if(!arguments.length)return d;d=d3.functor(a);return q},q.color=function(a){if(!arguments.length)return e;e=a;return q},q.id=function(a){if(!arguments.length)return f;f=a;return q};return q},a.models.lineWithFocus=function(){function z(a){a.each(function(h){function H(){var a=y.empty()?p.domain():d3.extent(d3.merge(seriesData).filter(function(a){return j(a)>=y.extent()[0]&&j(a)<=y.extent()[1]}),k);typeof a[0]=="undefined"&&(a=p.domain()),m.domain(y.empty()?o.domain():y.extent()),n.domain(a),v.xDomain(m.domain()),v.yDomain(n.domain())}function G(){H(),D.call(v),l.select(".x.axis").call(q),l.select(".y.axis").call(r)}seriesData=h.filter(function(a){return!a.disabled}).map(function(a){return a.values}),o.domain(d3.extent(d3.merge(seriesData),j)).range([0,d-b.left-b.right]),p.domain(d3.extent(d3.merge(seriesData),k)).range([g-c.top-c.bottom,0]),m.domain(y.empty()?o.domain():y.extent()).range([0,d-b.left-b.right]),n.domain(p.domain()).range([f-b.top-b.bottom,0]),y.on("brush",G),v.width(d-b.left-b.right).height(f-b.top-b.bottom).color(h.map(function(a,b){return a.color||i[b%10]}).filter(function(a,b){return!h[b].disabled})),w.width(d-b.left-b.right).height(g-c.top-c.bottom).color(h.map(function(a,b){return a.color||i[b%10]}).filter(function(a,b){return!h[b].disabled})),H();var l=d3.select(this).selectAll("g.wrap").data([h]),A=l.enter().append("g").attr("class","wrap d3lineWithFocus").append("g");A.append("g").attr("class","focus"),A.append("g").attr("class","context"),A.append("g").attr("class","legendWrap");var B=l.select("g");u.width(d/2-b.right),B.select(".legendWrap").datum(h).attr("transform","translate("+(d/2-b.left)+",0)").call(u),b.top=u.height();var C=B.select(".focus").attr("transform","translate("+b.left+","+b.top+")");A.select(".focus").append("g").attr("class","x axis"),A.select(".focus").append("g").attr("class","y axis"),A.select(".focus").append("g").attr("class","focusLines");var D=C.select(".focusLines").datum(h.filter(function(a){return!a.disabled}));d3.transition(D).call(v),q.domain(m.domain()).range(m.range()).ticks(d/100).tickSize(-(f-b.top-b.bottom),0),C.select(".x.axis").attr("transform","translate(0,"+n.range()[0]+")"),d3.transition(B.select(".x.axis")).call(q),r.domain(n.domain()).range(n.range()).ticks(e/36).tickSize(-(d-b.right-b.left),0),d3.transition(B.select(".y.axis")).call(r);var E=B.select(".context").attr("transform","translate("+c.left+","+f+")");A.select(".context").append("g").attr("class","x2 axis"),A.select(".context").append("g").attr("class","y2 axis"),A.select(".context").append("g").attr("class","contextLines"),A.select(".context").append("g").attr("class","x brush").attr("class","x brush").call(y).selectAll("rect").attr("y",-5).attr("height",g+4);var F=E.select(".contextLines").datum(h.filter(function(a){return!a.disabled}));d3.transition(F).call(w),s.domain(o.domain()).range(o.range()).ticks(d/100).tickSize(-(g-c.top-c.bottom),0),E.select(".x2.axis").attr("transform","translate(0,"+p.range()[0]+")"),d3.transition(E.select(".x2.axis")).call(s),t.domain(p.domain()).range(p.range()).ticks((g-c.top-c.bottom)/24).tickSize(-(d-c.right-c.left),0),E.select(".y2.axis"),d3.transition(E.select(".y2.axis")).call(t),u.dispatch.on("legendClick",function(b,c){b.disabled=!b.disabled,h.filter(function(a){return!a.disabled}).length||h.map(function(a){a.disabled=!1,l.selectAll(".series").classed("disabled",!1);return a}),a.transition().call(z)}),u.dispatch.on("legendMouseover",function(b,c){b.hover=!0,a.transition().call(z)}),u.dispatch.on("legendMouseout",function(b,c){b.hover=!1,a.transition().call(z)}),v.dispatch.on("pointMouseover.tooltip",function(a){x.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),v.dispatch.on("pointMouseout.tooltip",function(a){x.tooltipHide(a)})});return z}var b={top:30,right:20,bottom:30,left:60},c={top:0,right:20,bottom:20,left:60},d=960,e=500,f=400,g=100,h=function(){return 2.5},i=d3.scale.category10().range(),j=function(a){return a.x},k=function(a){return a.y},l=Math.floor(Math.random()*1e4),m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=d3.scale.linear(),q=a.models.xaxis().scale(m),r=a.models.yaxis().scale(n),s=a.models.xaxis().scale(o),t=a.models.yaxis().scale(p),u=a.models.legend().height(30),v=a.models.line(),w=a.models.line().dotRadius(.1).interactive(!1),x=d3.dispatch("tooltipShow","tooltipHide"),y=d3.svg.brush().x(o);z.dispatch=x,z.x=function(a){if(!arguments.length)return j;j=a,v.x(a),w.x(a);return z},z.y=function(a){if(!arguments.length)return k;k=a,v.y(a),w.y(a);return z},z.margin=function(a){if(!arguments.length)return b;b=a;return z},z.width=function(a){if(!arguments.length)return d;d=a;return z},z.height=function(a){if(!arguments.length)return e;e=a,f=a-g;return z},z.contextHeight=function(a){if(!arguments.length)return g;g=a,f=e-a;return z},z.dotRadius=function(a){if(!arguments.length)return h;h=d3.functor(a),v.dotRadius=a;return z},z.id=function(a){if(!arguments.length)return l;l=a;return z},z.xTickFormat=function(a){if(!arguments.length)return m.tickFormat();q.tickFormat(a),s.tickFormat(a);return z},z.yTickFormat=function(a){if(!arguments.length)return n.tickFormat();r.tickFormat(a),t.tickFormat(a);return z},z.xAxis=q,z.yAxis=r;return z},a.models.lineWithLegend=function(){function p(a){a.each(function(e){var q=c(),r=d(),s=e.filter(function(a){return!a.disabled}).map(function(a){return a.values});h.domain(d3.extent(d3.merge(s),j)).range([0,q-b.left-b.right]),i.domain(d3.extent(d3.merge(s),k)).range([r-b.top-b.bottom,0]),o.width(q-b.left-b.right).height(r-b.top-b.bottom).color(e.map(function(a,b){return a.color||f[b%10]}).filter(function(a,b){return!e[b].disabled}));var t=d3.select(this).selectAll("g.wrap").data([e]),u=t.enter().append("g").attr("class","wrap d3lineWithLegend").append("g");u.append("g").attr("class","x axis"),u.append("g").attr("class","y axis"),u.append("g").attr("class","linesWrap"),u.append("g").attr("class","legendWrap"),n.dispatch.on("legendClick",function(b,c){b.disabled=!b.disabled,e.filter(function(a){return!a.disabled}).length||e.map(function(a){a.disabled=!1,t.selectAll(".series").classed("disabled",!1);return a}),a.transition().call(p)}),n.dispatch.on("legendMouseover",function(b,c){b.hover=!0,a.transition().call(p)}),n.dispatch.on("legendMouseout",function(b,c){b.hover=!1,a.transition().call(p)}),o.dispatch.on("pointMouseover.tooltip",function(a){g.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),o.dispatch.on("pointMouseout.tooltip",function(a){g.tooltipHide(a)}),b.top=n.height();var v=t.select("g").attr("transform","translate("+b.left+","+n.height()+")");n.width(q/2-b.right),v.select(".legendWrap").datum(e).attr("transform","translate("+(q/2-b.left)+","+ -n.height()+")").call(n);var w=v.select(".linesWrap").datum(e.filter(function(a){return!a.disabled}));d3.transition(w).call(o),l.domain(h.domain()).range(h.range()).ticks(q/100).tickSize(-(r-b.top-b.bottom),0),v.select(".x.axis").attr("transform","translate(0,"+i.range()[0]+")"),d3.transition(v.select(".x.axis")).call(l),m.domain(i.domain()).range(i.range()).ticks(r/36).tickSize(-(q-b.right-b.left),0),d3.transition(v.select(".y.axis")).call(m)});return p}var b={top:30,right:20,bottom:50,left:60},c=function(){return 960},d=function(){return 500},e=function(){return 2.5},f=d3.scale.category10().range(),g=d3.dispatch("tooltipShow","tooltipHide"),h=d3.scale.linear(),i=d3.scale.linear(),j=function(a){return a.x},k=function(a){return a.y},l=a.models.xaxis().scale(h),m=a.models.yaxis().scale(i),n=a.models.legend().height(30),o=a.models.line();p.dispatch=g,p.legend=n,p.xAxis=l,p.yAxis=m,p.x=function(a){if(!arguments.length)return j;j=a,o.x(a);return p},p.y=function(a){if(!arguments.length)return k;k=a,o.y(a);return p},p.margin=function(a){if(!arguments.length)return b;b=a;return p},p.width=function(a){if(!arguments.length)return c;c=d3.functor(a);return p},p.height=function(a){if(!arguments.length)return d;d=d3.functor(a);return p},p.dotRadius=function(a){if(!arguments.length)return e;e=d3.functor(a),o.dotRadius=a;return p};return p},a.models.scatter=function(){function r(s){s.each(function(r){var s=r.map(function(a){return a.values});n=n||f,o=o||g,p=p||h,r=r.map(function(a,b){a.values=a.values.map(function(a){a.series=b;return a});return a}),f.domain(d3.extent(d3.merge(s).map(i).concat(l))).range([0,b-a.left-a.right]),g.domain(d3.extent(d3.merge(s).map(j).concat(m))).range([c-a.top-a.bottom,0]),h.domain(d3.extent(d3.merge(s),k)).range([2,10]);var t=d3.merge(r.map(function(a,b){return a.values.map(function(a,c){return[f(i(a)),g(j(a)),b,c]})})),u=d3.select(this).selectAll("g.d3scatter").data([r]),v=u.enter().append("g").attr("class","d3scatter").append("g");v.append("g").attr("class","groups"),v.append("g").attr("class","point-clips"),v.append("g").attr("class","point-paths"),v.append("g").attr("class","distribution");var w=u.select("g").attr("transform","translate("+a.left+","+a.top+")"),A=v.append("g").attr("class","voronoi-clip").append("clipPath").attr("id","voronoi-clip-path-"+e).append("rect");u.select(".voronoi-clip rect").attr("x",-10).attr("y",-10).attr("width",b-a.left-a.right+20).attr("height",c-a.top-a.bottom+20),u.select(".point-paths").attr("clip-path","url(#voronoi-clip-path-"+e+")");var B=u.select(".point-clips").selectAll(".clip-path").data(t);B.enter().append("clipPath").attr("class","clip-path").append("circle").attr("r",25),B.exit().remove(),B.attr("id",function(a,b){return"clip-"+e+"-"+a[2]+"-"+a[3]}).attr("transform",function(a){return"translate("+a[0]+","+a[1]+")"});var C=d3.geom.voronoi(t).map(function(a,b){return{data:a,series:t[b][2],point:t[b][3]}}),D=u.select(".point-paths").selectAll("path").data(C);D.enter().append("path").attr("class",function(a,b){return"path-"+b}),D.exit().remove(),D.attr("clip-path",function(a,b){return"url(#clip-"+e+"-"+a.series+"-"+a.point+")"}).attr("d",function(a){return"M"+a.data.join(",")+"Z"}).on("mouseover",function(b){q.pointMouseover({point:r[b.series].values[b.point],series:r[b.series],pos:[f(i(r[b.series].values[b.point]))+a.left,g(j(r[b.series].values[b.point]))+a.top],seriesIndex:b.series,pointIndex:b.point})}).on("mouseout",function(a,b){q.pointMouseout({point:r[a.series].values[a.point],series:r[a.series],seriesIndex:a.series,pointIndex:a.point})});var E=u.select(".groups").selectAll(".group").data(function(a){return a},function(a){return a.key});E.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(E.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),E.attr("class",function(a,b){return"group series-"+b}).classed("hover",function(a){return a.hover&&!a.disabled}),d3.transition(E).style("fill",function(a,b){return d[b%10]}).style("stroke",function(a,b){return d[b%10]}).style("stroke-opacity",1).style("fill-opacity",.5);var F=E.selectAll("circle.point").data(function(a){return a.values});F.enter().append("circle").attr("cx",function(a){return n(i(a))}).attr("cy",function(a){return o(j(a))}).attr("r",function(a){return p(k(a))}),d3.transition(E.exit().selectAll("circle.point")).attr("cx",function(a){return f(i(a))}).attr("cy",function(a){return g(j(a))}).attr("r",function(a){return h(k(a))}).remove(),F.attr("class",function(a,b){return"point point-"+b}),d3.transition(F).attr("cx",function(a){return f(i(a))}).attr("cy",function(a){return g(j(a))}).attr("r",function(a){return h(k(a))});var G=E.selectAll("line.distX").data(function(a){return a.values});G.enter().append("line").attr("x1",function(a){return n(i(a))}).attr("x2",function(a){return n(i(a))}),d3.transition(E.exit().selectAll("line.distX")).attr("x1",function(a){return f(i(a))}).attr("x2",function(a){return f(i(a))}).remove(),G.attr("class",function(a,b){return"distX distX-"+b}).attr("y1",g.range()[0]).attr("y2",g.range()[0]+8),d3.transition(G).attr("x1",function(a){return f(i(a))}).attr("x2",function(a){return f(i(a))});var H=E.selectAll("line.distY").data(function(a){return a.values});H.enter().append("line").attr("y1",function(a){return o(j(a))}).attr("y2",function(a){return o(j(a))}),d3.transition(E.exit().selectAll("line.distY")).attr("y1",function(a){return g(j(a))}).attr("y2",function(a){return g(j(a))}).remove(),H.attr("class",function(a,b){return"distY distY-"+b}).attr("x1",f.range()[0]).attr("x2",f.range()[0]-8),d3.transition(H).attr("y1",function(a){return g(j(a))}).attr("y2",function(a){return g(j(a))}),q.on("pointMouseover.point",function(b){u.select(".series-"+b.seriesIndex+" .point-"+b.pointIndex).classed("hover",!0),u.select(".series-"+b.seriesIndex+" .distX-"+b.pointIndex).attr("y1",b.pos[1]-a.top),u.select(".series-"+b.seriesIndex+" .distY-"+b.pointIndex).attr("x1",b.pos[0]-a.left)}),q.on("pointMouseout.point",function(a){u.select(".series-"+a.seriesIndex+" circle.point-"+a.pointIndex).classed("hover",!1),u.select(".series-"+a.seriesIndex+" .distX-"+a.pointIndex).attr("y1",g.range()[0]),u.select(".series-"+a.seriesIndex+" .distY-"+a.pointIndex).attr("x1",f.range()[0])}),n=f.copy(),o=g.copy(),p=h.copy()});return r}var a={top:0,right:0,bottom:0,left:0},b=960,c=500,d=d3.scale.category10().range(),e=Math.floor(Math.random()*1e5),f=d3.scale.linear(),g=d3.scale.linear(),h=d3.scale.sqrt(),i=function(a){return a.x},j=function(a){return a.y},k=function(a){return a.size},l=[],m=[],n,o,p,q=d3.dispatch("pointMouseover","pointMouseout");r.dispatch=q,r.margin=function(b){if(!arguments.length)return a;a=b;return r},r.width=function(a){if(!arguments.length)return b;b=a;return r},r.height=function(a){if(!arguments.length)return c;c=a;return r},r.x=function(a){if(!arguments.length)return i;i=d3.functor(a);return r},r.y=function(a){if(!arguments.length)return j;j=d3.functor(a);return r},r.size=function(a){if(!arguments.length)return k;k=d3.functor(a);return r},r.forceX=function(a){if(!arguments.length)return l;l=a;return r},r.forceY=function(a){if(!arguments.length)return m;m=a;return r},r.color=function(a){if(!arguments.length)return d;d=a;return r},r.id=function(a){if(!arguments.length)return e;e=a;return r};return r},a.models.scatterWithLegend=function(){function w(a){a.each(function(f){var g=f.filter(function(a){return!a.disabled}).map(function(a){return a.values});q.domain(d3.extent(d3.merge(g).map(k).concat(n))).range([0,c-b.left-b.right]),r.domain(d3.extent(d3.merge(g).map(l).concat(o))).range([d-b.top-b.bottom,0]),v.width(c-b.left-b.right).height(d-b.top-b.bottom).color(f.map(function(a,b){return a.color||j[b%20]}).filter(function(a,b){return!f[b].disabled})),s.ticks(c/100).tickSize(-(d-b.top-b.bottom),0),t.ticks(d/36).tickSize(-(c-b.right-b.left),0);var h=d3.select(this).selectAll("g.wrap").data([f]),i=h.enter().append("g").attr("class","wrap d3lineWithLegend").append("g");i.append("g").attr("class","legendWrap"),i.append("g").attr("class","x axis"),i.append("g").attr("class","y axis"),i.append("g").attr("class","scatterWrap"),u.dispatch.on("legendClick",function(b,c,d){b.disabled=!b.disabled,f.filter(function(a){return!a.disabled}).length||f.map(function(a){a.disabled=!1,h.selectAll(".series").classed("disabled",!1);return a}),a.transition(e).call(w)}),v.dispatch.on("pointMouseover.tooltip",function(a){p.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),v.dispatch.on("pointMouseout.tooltip",function(a){p.tooltipHide(a)}),u.width(c/2-b.right),h.select(".legendWrap").datum(f).attr("transform","translate("+(c/2-b.left)+","+ -u.height()+")").call(u),b.top=u.height();var m=h.select("g").attr("transform","translate("+b.left+","+b.top+")"),z=h.select(".scatterWrap").datum(f.filter(function(a){return!a.disabled}));d3.transition(z).call(v),s.domain(q.domain()).range(q.range()).ticks(c/100).tickSize(-(d-b.top-b.bottom),0),m.select(".x.axis").attr("transform","translate(0,"+r.range()[0]+")"),d3.transition(m.select(".x.axis")).call(s),t.domain(r.domain()).range(r.range()).ticks(d/36).tickSize(-(c-b.right-b.left),0),d3.transition(m.select(".y.axis")).call(t)});return w}var b={top:30,right:20,bottom:50,left:60},c=960,d=500,e=500,f=!0,g=!0,h=!1,i=!1,j=d3.scale.category10().range(),k=function(a){return a.x},l=function(a){return a.y},m=function(a){return a.size},n=[],o=[],p=d3.dispatch("tooltipShow","tooltipHide"),q=d3.scale.linear(),r=d3.scale.linear(),s=a.models.xaxis().scale(q).tickPadding(10),t=a.models.yaxis().scale(r).tickPadding(10),u=a.models.legend().height(30),v=a.models.scatter();w.dispatch=p,w.margin=function(a){if(!arguments.length)return b;b=a;return w},w.width=function(a){if(!arguments.length)return c;c=a;return w},w.height=function(a){if(!arguments.length)return d;d=a;return w},w.forceX=function(a){if(!arguments.length)return n;n=a,v.forceX(a);return w},w.forceY=function(a){if(!arguments.length)return o;o=a,v.forceY(a);return w},w.animate=function(a){if(!arguments.length)return e;e=a;return w},w.xAxis=s,w.yAxis=t;return w},a.models.sparkline=function(){function h(d){d.each(function(d){f.domain(d3.extent(d,function(a){return a.x})).range([0,b-a.left-a.right]),g.domain(d3.extent(d,function(a){return a.y})).range([c-a.top-a.bottom,0]);var h=d3.select(this).selectAll("svg").data([d]),i=h.enter().append("svg").append("g");i.append("g").attr("class","sparkline").attr("transform","translate("+a.left+","+a.top+")").style("stroke",function(a,b){return a.color||e[b*2%20]}),h.attr("width",b).attr("height",c);var j=i.select(".sparkline").selectAll("path").data(function(a){return[a]});j.enter().append("path"),j.exit().remove(),j.attr("d",d3.svg.line().x(function(a){return f(a.x)}).y(function(a){return g(a.y)}));var k=i.select(".sparkline").selectAll("circle.point").data(function(a){return a.filter(function(a){return g.domain().indexOf(a.y)!=-1})});k.enter().append("circle").attr("class","point"),k.exit().remove(),k.attr("cx",function(a){return f(a.x)}).attr("cy",function(a){return g(a.y)}).attr("r",2).style("stroke",function(a,b){return a.y==g.domain()[0]?"#d62728":"#2ca02c"}).style("fill",function(a,b){return a.y==g.domain()[0]?"#d62728":"#2ca02c"})});return h}var a={top:3,right:3,bottom:3,left:3},b=200,c=20,d=!0,e=d3.scale.category20().range(),f=d3.scale.linear(),g=d3.scale.linear();h.margin=function(b){if(!arguments.length)return a;a=b;return h},h.width=function(a){if(!arguments.length)return b;b=a;return h},h.height=function(a){if(!arguments.length)return c;c=a;return h},h.animate=function(a){if(!arguments.length)return d;d=a;return h};return h},a.models.stackedArea=function(){function j(a){a.each(function(a){var f=JSON.parse(JSON.stringify(a));f=d3.layout.stack().offset(g).order(h).values(function(a){return a.values})(f);var j=f[0].values.length-1,k=d3.max(f,function(a){return d3.max(a.values,function(a){return a.y0+a.y})});i.width(c-b.left-b.right).height(d-b.top-b.bottom).y(function(a){return a.y+a.y0}).color(a.map(function(a,b){return a.color||e[b%10]}).filter(function(b,c){return!a[c].disabled}));var l=d3.select(this).selectAll("g.d3stackedarea").data([f]),m=l.enter().append("g").attr("class","d3stackedarea").append("g");m.append("g").attr("class","areaWrap"),m.append("g").attr("class","linesWrap");var n=l.select("g").attr("transform","translate("+b.left+","+b.top+")"),o=n.select(".linesWrap").datum(f.filter(function(a){return!a.disabled}));d3.transition(o).call(i);var p=c-b.left-b.right,q=d-b.top-b.bottom,r=d3.svg.area().x(function(a){return a.x*p/j}).y0(function(a){return q-a.y0*q/k}).y1(function(a){return q-(a.y+a.y0)*q/k}),s=d3.svg.area().x(function(a){return a.x*p/j}).y0(function(a){return q-a.y0*q/k}).y1(function(a){return q-a.y0*q/k}),t=n.select(".areaWrap").selectAll("path.area").data(function(a){return a});t.enter().append -("path").attr("class","area"),d3.transition(t.exit()).attr("d",function(a,b){return s(a.values,b)}).remove(),t.style("fill",function(a,b){return e[b%10]}).style("stroke",function(a,b){return e[b%10]}),d3.transition(t).attr("d",function(a,b){return r(a.values,b)})});return j}var b={top:0,right:0,bottom:0,left:0},c=960,d=500,e=d3.scale.category10().range(),f="stack",g="zero",h="default",i=a.models.line();j.margin=function(a){if(!arguments.length)return b;b=a;return j},j.width=function(a){if(!arguments.length)return c;c=a;return j},j.height=function(a){if(!arguments.length)return d;d=a;return j},j.color=function(a){if(!arguments.length)return e;e=a;return j},j.offset=function(a){if(!arguments.length)return g;g=a;return j},j.order=function(a){if(!arguments.length)return h;h=a;return j},j.style=function(a){if(!arguments.length)return f;f=a;switch(f){case"stack":g="zero",h="default";break;case"stream":g="wiggle",h="inside-out";break;case"expand":g="expand",h="default"}return j},j.dispatch=i.dispatch;return j},a.models.stackedAreaWithLegend=function(){function r(a){a.each(function(e){var f=e.filter(function(a){return!a.disabled}).reduce(function(a,b,c){b.values.forEach(function(b,d){c||(a[d]={x:b.x,y:0}),a[d].y+=k(b)});return a},[]);h.domain(d3.extent(d3.merge(f),j)).range([0,c-b.left-b.right]),i.domain(p.offset()=="zero"?[0,d3.max(d3.merge(f),k)]:[0,1]).range([d-b.top-b.bottom,0]),p.width(c-b.left-b.right).height(d-b.top-b.bottom);var s=d3.select(this).selectAll("g.wrap").data([e]),t=s.enter().append("g").attr("class","wrap d3stackedWithLegend").append("g");t.append("g").attr("class","x axis"),t.append("g").attr("class","y axis"),t.append("g").attr("class","stackedWrap"),t.append("g").attr("class","legendWrap"),t.append("g").attr("class","controlsWrap"),n.dispatch.on("legendClick",function(b,c){b.disabled=!b.disabled,b.disabled?b.values.map(function(a){a._y=a.y,a.y=0;return a}):b.values.map(function(a){a.y=a._y;return a}),e.filter(function(a){return!a.disabled}).length||e.map(function(a){a.disabled=!1,a.values.map(function(a){a.y=a._y;return a});return a}),a.transition().call(r)}),o.dispatch.on("legendClick",function(b,c){if(!!b.disabled){q=q.map(function(a){a.disabled=!0;return a}),b.disabled=!1;switch(b.key){case"Stacked":p.style("stack");break;case"Stream":p.style("stream");break;case"Expanded":p.style("expand")}a.transition().call(r)}}),p.dispatch.on("pointMouseover.tooltip",function(a){g.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),p.dispatch.on("pointMouseout.tooltip",function(a){g.tooltipHide(a)}),b.top=n.height();var u=s.select("g").attr("transform","translate("+b.left+","+b.top+")");n.width(c/2-b.right),o.width(280).color(["#666","#666","#666"]),u.select(".legendWrap").datum(e).attr("transform","translate("+(c/2-b.left)+","+ -b.top+")").call(n),u.select(".controlsWrap").datum(q).attr("transform","translate(0,"+ -b.top+")").call(o);var v=u.select(".stackedWrap").datum(e);d3.transition(v).call(p),l.domain(h.domain()).range(h.range()).ticks(c/100).tickSize(-(d-b.top-b.bottom),0),u.select(".x.axis").attr("transform","translate(0,"+i.range()[0]+")"),d3.transition(u.select(".x.axis")).call(l),m.domain(i.domain()).range(i.range()).ticks(p.offset()=="wiggle"?0:d/36).tickSize(-(c-b.right-b.left),0).tickFormat(p.offset()=="zero"?d3.format(",.2f"):d3.format("%")),d3.transition(u.select(".y.axis")).call(m)});return r}var b={top:30,right:20,bottom:50,left:60},c=960,d=500,e=function(){return 2.5},f=d3.scale.category10().range(),g=d3.dispatch("tooltipShow","tooltipHide"),h=d3.scale.linear(),i=d3.scale.linear(),j=function(a){return a.x},k=function(a){return a.y},l=a.models.xaxis().scale(h),m=a.models.yaxis().scale(i),n=a.models.legend().height(30),o=a.models.legend().height(30),p=a.models.stackedArea(),q=[{key:"Stacked"},{key:"Stream",disabled:!0},{key:"Expanded",disabled:!0}];r.dispatch=g,r.x=function(a){if(!arguments.length)return j;j=a,p.x(a);return r},r.y=function(a){if(!arguments.length)return k;k=a,p.y(a);return r},r.margin=function(a){if(!arguments.length)return b;b=a;return r},r.width=function(a){if(!arguments.length)return c;c=a;return r},r.height=function(a){if(!arguments.length)return d;d=a;return r},r.dotRadius=function(a){if(!arguments.length)return e;e=d3.functor(a),p.dotRadius=a;return r},r.stacked=p,r.xAxis=l,r.yAxis=m;return r}}() \ No newline at end of file + *****/(function(a){var b=window.nvtooltip={};b.show=function(b,c,d,e){var f=a('
');d=d||"s",e=e||20,f.html(c).css({left:-1e3,top:-1e3,opacity:0}).appendTo("body");var g=f.height()+parseInt(f.css("padding-top"))+parseInt(f.css("padding-bottom")),h=f.width()+parseInt(f.css("padding-left"))+parseInt(f.css("padding-right")),i=a(window).width(),j=a(window).height(),k=a("body").scrollTop(),l=a("body").scrollLeft(),m,n;switch(d){case"e":m=b[0]-h-e,n=b[1]-g/2,mk+j&&(n=k-g-5);break;case"w":m=b[0]+e,n=b[1]-g/2,m+h>i&&(m=b[0]-h-e),nk+j&&(n=k-g-5);break;case"n":m=b[0]-h/2,n=b[1]+e,mi&&(m=i-h-5),n+g>k+j&&(n=b[1]-g-e);break;case"s":m=b[0]-h/2,n=b[1]-g-e,mi&&(m=i-h-5),k>n&&(n=b[1]+20)}f.css({left:m,top:n,opacity:1});return f},b.cleanup=function(){var b=a(".nvtooltip");b.css({"transition-delay":"0 !important","-moz-transition-delay":"0 !important","-webkit-transition-delay":"0 !important"}),b.css("opacity",0),setTimeout(function(){b.remove()},500)}})(jQuery),function(){function c(a,b,c){return function(d,e,f){var g=a(d),h=[];g1)while(gn&&(n=m);return"translate("+o+","+l+")"}),i.attr("transform","translate("+(b-a.right-n)+","+a.top+")"),c=a.top+a.bottom+l+15});return f}var a={top:5,right:0,bottom:5,left:10},b=400,c=20,d=d3.scale.category10().range(),e=d3.dispatch("legendClick","legendMouseover","legendMouseout");f.dispatch=e,f.margin=function(b){if(!arguments.length)return a;a=b;return f},f.width=function(a){if(!arguments.length)return b;b=a;return f},f.height=function(a){if(!arguments.length)return c;c=a;return f},f.color=function(a){if(!arguments.length)return d;d=a;return f};return f},a.models.xaxis=function(){function f(g){g.each(function(f){d.domain(a).range(b);var g=d3.select(this).selectAll("text.axislabel").data([c||null]);g.enter().append("text").attr("class","axislabel").attr("text-anchor","middle").attr("x",b[1]/2).attr("y",25),g.exit().remove(),g.text(function(a){return a}),d3.transition(d3.select(this)).call(e),d3.select(this).selectAll("line.tick").filter(function(a){return!parseFloat(Math.round(a*1e5)/1e6)}).classed("zero",!0)});return f}var a=[0,1],b=[0,1],c=!1,d=d3.scale.linear(),e=d3.svg.axis().scale(d).orient("bottom");f.domain=function(b){if(!arguments.length)return a;a=b;return f},f.range=function(a){if(!arguments.length)return b;b=a;return f},f.scale=function(a){if(!arguments.length)return d;d=a,e.scale(d);return f},f.axisLabel=function(a){if(!arguments.length)return c;c=a;return f},d3.rebind(f,e,"orient","ticks","tickSubdivide","tickSize","tickPadding","tickFormat");return f},a.models.yaxis=function(){function f(g){g.each(function(f){d.domain(a).range(b);var g=d3.select(this).selectAll("text.axislabel").data([c||null]);g.enter().append("text").attr("class","axislabel").attr("transform","rotate(-90)").attr("text-anchor","middle").attr("y",-40),g.exit().remove(),g.attr("x",-b[0]/2).text(function(a){return a}),d3.transition(d3.select(this)).call(e),d3.select(this).selectAll("line.tick").filter(function(a){return!parseFloat(Math.round(a*1e5)/1e6)}).classed("zero",!0)});return f}var a=[0,1],b=[0,1],c=!1,d=d3.scale.linear(),e=d3.svg.axis().scale(d).orient("left");f.domain=function(b){if(!arguments.length)return a;a=b;return f},f.range=function(a){if(!arguments.length)return b;b=a;return f},f.axisLabel=function(a){if(!arguments.length)return c;c=a;return f},d3.rebind(f,e,"scale","orient","ticks","tickSubdivide","tickSize","tickPadding","tickFormat");return f},a.models.bar=function(){function i(j){j.each(function(i){e.domain(["One","Two","Three","Four","Five"]).rangeRoundBands([0,b-a.left-a.right],.1),f.domain([0,d3.max(i,function(a){return a.y})]).range([c-a.top-a.bottom,0]),g.ticks(b/100),h.ticks(c/36).tickSize(-(b-a.right-a.left),0),h.tickSize(-(b-a.right-a.left),0);var j=d3.select(this).selectAll("g.wrap").data([i]),k=j.enter().append("g").attr("class","wrap").append("g");k.append("g").attr("class","x axis"),k.append("g").attr("class","y axis"),k.append("g").attr("class","bars"),j.attr("width",b).attr("height",c);var l=j.select("g").attr("transform","translate("+a.left+","+a.top+")"),m=j.select(".bars").selectAll(".bar").data(function(a){return a});m.exit().remove();var n=m.enter().append("g").attr("class","bar").on("mouseover",function(a,b){d3.select(this).classed("hover",!0)}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1)});n.append("rect").attr("y",function(a){return f(0)}),n.append("text").attr("text-anchor","middle").attr("dy","-4px"),m.attr("transform",function(a,b){return"translate("+e(a.label)+",0)"}),m.selectAll("rect").order().attr("width",e.rangeBand).transition().duration(d).attr("x",0).attr("y",function(a){return f(a.y)}).attr("height",function(a){return f.range()[0]-f(a.y)}),m.selectAll("text").attr("x",0).attr("y",function(a){return f(a.y)}).attr("dx",e.rangeBand()/2).text(function(a){return a.y}),l.select(".x.axis").attr("transform","translate(0,"+f.range()[0]+")").call(g),l.select(".y.axis").call(h)});return i}var a={top:20,right:10,bottom:20,left:60},b=960,c=500,d=500,e=d3.scale.ordinal(),f=d3.scale.linear(),g=d3.svg.axis().scale(e).orient("bottom").ticks(5),h=d3.svg.axis().scale(f).orient("left");i.margin=function(b){if(!arguments.length)return a;a=b;return i},i.width=function(c){if(!arguments.length)return b;a.left+a.right+20>c?b=a.left+a.right+20:b=c;return i},i.height=function(b){if(!arguments.length)return c;a.top+a.bottom+20>b?c=a.top+a.bottom+20:c=b;return i},i.animate=function(a){if(!arguments.length)return d;d=a;return i},i.xaxis={},d3.rebind(i.xaxis,g,"tickFormat"),i.yaxis={},d3.rebind(i.yaxis,h,"tickFormat");return i},a.models.line=function(){function r(s){s.each(function(r){function C(){if(!i)return!1;B.append("g").attr("class","point-clips"),B.append("g").attr("class","point-paths");var b=d3.merge(r.map(function(a,b){return a.values.map(function(a,c){return[m(g(a))*(Math.random()/1e12+1),n(h(a))*(Math.random()/1e12+1),b,c]})})),c=v.select(".point-clips").selectAll(".clip-path").data(b);c.enter().append("clipPath").attr("class","clip-path").append("circle").attr("r",25),c.exit().remove(),c.attr("id",function(a,b){return"clip-"+f+"-"+a[2]+"-"+a[3]}).attr("transform",function(a){return"translate("+a[0]+","+a[1]+")"});var d=d3.geom.voronoi(b).map(function(a,c){return{data:a,series:b[c][2],point:b[c][3]}}),e=v.select(".point-paths").selectAll("path").data(d);e.enter().append("path").attr("class",function(a,b){return"path-"+b}).style("fill-opacity",0),e.exit().remove(),e.attr("clip-path",function(a,b){return j?"url(#clip-"+f+"-"+a.series+"-"+a.point+")":""}).attr("d",function(a){return"M"+a.data.join(",")+"Z"}).on("mouseover",function(b){var c=r[b.series],d=c.values[b.point];o.pointMouseover({point:d,series:c,pos:[m(g(d))+a.left,n(h(d))+a.top],seriesIndex:b.series,pointIndex:b.point})}).on("mouseout",function(a,b){o.pointMouseout({point:r[a.series].values[a.point],series:r[a.series],seriesIndex:a.series,pointIndex:a.point})}),o.on("pointMouseover.point",function(a){v.select(".series-"+a.seriesIndex+" .point-"+a.pointIndex).classed("hover",!0)}),o.on("pointMouseout.point",function(a){v.select(".series-"+a.seriesIndex+" circle.point-"+a.pointIndex).classed("hover",!1)})}var s=r.map(function(a){return a.values}),t=b-a.left-a.right,u=c-a.top-a.bottom;p=p||m,q=q||n,m.domain(k||d3.extent(d3.merge(s),g)).range([0,t]),n.domain(l||d3.extent(d3.merge(s),h)).range([u,0]);var v=d3.select(this).selectAll("g.d3line").data([r]),w=v.enter().append("g").attr("class","d3line"),z=w.append("g");z.append("g").attr("class","lines");var A=v.select("g").attr("transform","translate("+a.left+","+a.top+")");w.append("defs").append("clipPath").attr("id","chart-clip-path-"+f).append("rect"),v.select("#chart-clip-path-"+f+" rect").attr("width",t).attr("height",u),z.attr("clip-path","url(#chart-clip-path-"+f+")");var B=z.append("g").attr("class","shiftWrap");A.selectAll(".point-clips *, .point-paths *").remove();var D=v.select(".lines").selectAll(".line").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(D.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"line series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return e[b%10]}).style("stroke",function(a,b){return e[b%10]}),d3.transition(D).style("stroke-opacity",1).style("fill-opacity",.5),setTimeout(C,1e3);var E=D.selectAll("path").data(function(a,b){return[a.values]});E.enter().append("path").attr("d",d3.svg.line().x(function(a){return p(g(a))}).y(function(a){return q(h(a))})),d3.transition(D.exit().selectAll("path")).attr("d",d3.svg.line().x(function(a){return m(g(a))}).y(function(a){return n(h(a))})).remove(),d3.transition(E).attr("d",d3.svg.line().x(function(a){return m(g(a))}).y(function(a){return n(h(a))}));var F=D.selectAll("circle.point").data(function(a){return a.values});F.enter().append("circle").attr("cx",function(a){return p(g(a))}).attr("cy",function(a){return q(h(a))}),d3.transition(F.exit()).attr("cx",function(a){return m(g(a))}).attr("cy",function(a){return n(h(a))}).remove(),d3.transition(D.exit().selectAll("circle.point")).attr("cx",function(a){return m(g(a))}).attr("cy",function(a){return n(h(a))}).remove(),F.attr("class",function(a,b){return"point point-"+b}),d3.transition(F).attr("cx",function(a){return m(g(a))}).attr("cy",function(a){return n(h(a))}).attr("r",d),p=m.copy(),q=n.copy()});return r}var a={top:0,right:0,bottom:0,left:0},b=960,c=500,d=function(){return 2.5},e=d3.scale.category10().range(),f=Math.floor(Math.random()*1e4),g=function(a){return a.x},h=function(a){return a.y},i=!0,j=!0,k,l,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.dispatch("pointMouseover","pointMouseout"),p,q;r.dispatch=o,r.x=function(a){if(!arguments.length)return g;g=a;return r},r.y=function(a){if(!arguments.length)return h;h=a;return r},r.margin=function(b){if(!arguments.length)return a;a=b;return r},r.width=function(a){if(!arguments.length)return b;b=a;return r},r.height=function(a){if(!arguments.length)return c;c=a;return r},r.xDomain=function(a){if(!arguments.length)return k;k=a;return r},r.yDomain=function(a){if(!arguments.length)return l;l=a;return r},r.interactive=function(a){if(!arguments.length)return i;i=a;return r},r.clipVoronoi=function(a){if(!arguments.length)return j;j=a;return r},r.dotRadius=function(a){if(!arguments.length)return d;d=d3.functor(a);return r},r.color=function(a){if(!arguments.length)return e;e=a;return r},r.id=function(a){if(!arguments.length)return f;f=a;return r};return r},a.models.lineWithFocus=function(){function z(a){a.each(function(h){function H(){var a=y.empty()?p.domain():d3.extent(d3.merge(seriesData).filter(function(a){return j(a)>=y.extent()[0]&&j(a)<=y.extent()[1]}),k);typeof a[0]=="undefined"&&(a=p.domain()),m.domain(y.empty()?o.domain():y.extent()),n.domain(a),v.xDomain(m.domain()),v.yDomain(n.domain())}function G(){H(),D.call(v),l.select(".x.axis").call(q),l.select(".y.axis").call(r)}seriesData=h.filter(function(a){return!a.disabled}).map(function(a){return a.values}),o.domain(d3.extent(d3.merge(seriesData),j)).range([0,d-b.left-b.right]),p.domain(d3.extent(d3.merge(seriesData),k)).range([g-c.top-c.bottom,0]),m.domain(y.empty()?o.domain():y.extent()).range([0,d-b.left-b.right]),n.domain(p.domain()).range([f-b.top-b.bottom,0]),y.on("brush",G),v.width(d-b.left-b.right).height(f-b.top-b.bottom).color(h.map(function(a,b){return a.color||i[b%10]}).filter(function(a,b){return!h[b].disabled})),w.width(d-b.left-b.right).height(g-c.top-c.bottom).color(h.map(function(a,b){return a.color||i[b%10]}).filter(function(a,b){return!h[b].disabled})),H();var l=d3.select(this).selectAll("g.wrap").data([h]),A=l.enter().append("g").attr("class","wrap d3lineWithFocus").append("g");A.append("g").attr("class","focus"),A.append("g").attr("class","context"),A.append("g").attr("class","legendWrap");var B=l.select("g");u.width(d/2-b.right),B.select(".legendWrap").datum(h).attr("transform","translate("+(d/2-b.left)+",0)").call(u),b.top=u.height();var C=B.select(".focus").attr("transform","translate("+b.left+","+b.top+")");A.select(".focus").append("g").attr("class","x axis"),A.select(".focus").append("g").attr("class","y axis"),A.select(".focus").append("g").attr("class","focusLines");var D=C.select(".focusLines").datum(h.filter(function(a){return!a.disabled}));d3.transition(D).call(v),q.domain(m.domain()).range(m.range()).ticks(d/100).tickSize(-(f-b.top-b.bottom),0),C.select(".x.axis").attr("transform","translate(0,"+n.range()[0]+")"),d3.transition(B.select(".x.axis")).call(q),r.domain(n.domain()).range(n.range()).ticks(e/36).tickSize(-(d-b.right-b.left),0),d3.transition(B.select(".y.axis")).call(r);var E=B.select(".context").attr("transform","translate("+c.left+","+f+")");A.select(".context").append("g").attr("class","x2 axis"),A.select(".context").append("g").attr("class","y2 axis"),A.select(".context").append("g").attr("class","contextLines"),A.select(".context").append("g").attr("class","x brush").attr("class","x brush").call(y).selectAll("rect").attr("y",-5).attr("height",g+4);var F=E.select(".contextLines").datum(h.filter(function(a){return!a.disabled}));d3.transition(F).call(w),s.domain(o.domain()).range(o.range()).ticks(d/100).tickSize(-(g-c.top-c.bottom),0),E.select(".x2.axis").attr("transform","translate(0,"+p.range()[0]+")"),d3.transition(E.select(".x2.axis")).call(s),t.domain(p.domain()).range(p.range()).ticks((g-c.top-c.bottom)/24).tickSize(-(d-c.right-c.left),0),E.select(".y2.axis"),d3.transition(E.select(".y2.axis")).call(t),u.dispatch.on("legendClick",function(b,c){b.disabled=!b.disabled,h.filter(function(a){return!a.disabled}).length||h.map(function(a){a.disabled=!1,l.selectAll(".series").classed("disabled",!1);return a}),a.transition().call(z)}),v.dispatch.on("pointMouseover.tooltip",function(a){x.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),v.dispatch.on("pointMouseout.tooltip",function(a){x.tooltipHide(a)})});return z}var b={top:30,right:20,bottom:30,left:60},c={top:0,right:20,bottom:20,left:60},d=960,e=500,f=400,g=100,h=function(){return 2.5},i=d3.scale.category10().range(),j=function(a){return a.x},k=function(a){return a.y},l=Math.floor(Math.random()*1e4),m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=d3.scale.linear(),q=a.models.xaxis().scale(m),r=a.models.yaxis().scale(n),s=a.models.xaxis().scale(o),t=a.models.yaxis().scale(p),u=a.models.legend().height(30),v=a.models.line(),w=a.models.line().dotRadius(.1).interactive(!1),x=d3.dispatch("tooltipShow","tooltipHide"),y=d3.svg.brush().x(o);z.dispatch=x,z.x=function(a){if(!arguments.length)return j;j=a,v.x(a),w.x(a);return z},z.y=function(a){if(!arguments.length)return k;k=a,v.y(a),w.y(a);return z},z.margin=function(a){if(!arguments.length)return b;b=a;return z},z.width=function(a){if(!arguments.length)return d;d=a;return z},z.height=function(a){if(!arguments.length)return e;e=a,f=a-g;return z},z.contextHeight=function(a){if(!arguments.length)return g;g=a,f=e-a;return z},z.dotRadius=function(a){if(!arguments.length)return h;h=d3.functor(a),v.dotRadius=a;return z},z.id=function(a){if(!arguments.length)return l;l=a;return z},z.xTickFormat=function(a){if(!arguments.length)return m.tickFormat();q.tickFormat(a),s.tickFormat(a);return z},z.yTickFormat=function(a){if(!arguments.length)return n.tickFormat();r.tickFormat(a),t.tickFormat(a);return z},z.xAxis=q,z.yAxis=r;return z},a.models.lineWithLegend=function(){function p(a){a.each(function(e){var q=c(),r=d(),s=q-b.left-b.right,t=r-b.top-b.bottom,u=e.filter(function(a){return!a.disabled}).map(function(a){return a.values});h.domain(d3.extent(d3.merge(u),j)).range([0,s]),i.domain(d3.extent(d3.merge(u),k)).range([t,0]),o.width(s).height(t).color(e.map(function(a,b){return a.color||f[b%10]}).filter(function(a,b){return!e[b].disabled}));var v=d3.select(this).selectAll("g.wrap").data([e]),w=v.enter().append("g").attr("class","wrap d3lineWithLegend").append("g");w.append("g").attr("class","x axis"),w.append("g").attr("class","y axis"),w.append("g").attr("class","linesWrap"),w.append("g").attr("class","legendWrap"),n.dispatch.on("legendClick",function(b,c){b.disabled=!b.disabled,e.filter(function(a){return!a.disabled}).length||e.map(function(a){a.disabled=!1,v.selectAll(".series").classed("disabled",!1);return a}),a.transition().call(p)}),o.dispatch.on("pointMouseover.tooltip",function(a){g.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),o.dispatch.on("pointMouseout.tooltip",function(a){g.tooltipHide(a)}),b.top=n.height();var z=v.select("g").attr("transform","translate("+b.left+","+b.top+")");n.width(q/2-b.right),z.select(".legendWrap").datum(e).attr("transform","translate("+(q/2-b.left)+","+ -b.top+")").call(n);var A=z.select(".linesWrap").datum(e.filter(function(a){return!a.disabled}));d3.transition(A).call(o),l.domain(h.domain()).range(h.range()).ticks(q/100).tickSize(-t,0),z.select(".x.axis").attr("transform","translate(0,"+i.range()[0]+")"),d3.transition(z.select(".x.axis")).call(l),m.domain(i.domain()).range(i.range()).ticks(r/36).tickSize(-s,0),d3.transition(z.select(".y.axis")).call(m)});return p}var b={top:30,right:20,bottom:50,left:60},c=function(){return 960},d=function(){return 500},e=function(){return 2.5},f=d3.scale.category10().range(),g=d3.dispatch("tooltipShow","tooltipHide"),h=d3.scale.linear(),i=d3.scale.linear(),j=function(a){return a.x},k=function(a){return a.y},l=a.models.xaxis().scale(h),m=a.models.yaxis().scale(i),n=a.models.legend().height(30),o=a.models.line();p.dispatch=g,p.legend=n,p.xAxis=l,p.yAxis=m,p.x=function(a){if(!arguments.length)return j;j=a,o.x(a);return p},p.y=function(a){if(!arguments.length)return k;k=a,o.y(a);return p},p.margin=function(a){if(!arguments.length)return b;b=a;return p},p.width=function(a){if(!arguments.length)return c;c=d3.functor(a);return p},p.height=function(a){if(!arguments.length)return d;d=d3.functor(a);return p},p.dotRadius=function(a){if(!arguments.length)return e;e=d3.functor(a),o.dotRadius=a;return p};return p},a.models.scatter=function(){function r(s){s.each(function(r){var s=r.map(function(a){return a.values}),t=b-a.left-a.right,u=c-a.top-a.bottom;n=n||f,o=o||g,p=p||h,r=r.map(function(a,b){a.values=a.values.map(function(a){a.series=b;return a});return a}),f.domain(d3.extent(d3.merge(s).map(i).concat(l))).range([0,t]),g.domain(d3.extent(d3.merge(s).map(j).concat(m))).range([u,0]),h.domain(d3.extent(d3.merge(s),k)).range([2,10]);var v=d3.merge(r.map(function(a,b){return a.values.map(function(a,c){return[f(i(a))*(Math.random()/1e12+1),g(j(a))*(Math.random()/1e12+1),b,c]})})),w=d3.select(this).selectAll("g.d3scatter").data([r]),A=w.enter().append("g").attr("class","d3scatter").append("g");A.append("g").attr("class","groups"),A.append("g").attr("class","point-clips"),A.append("g").attr("class","point-paths"),A.append("g").attr("class","distribution");var B=w.select("g").attr("transform","translate("+a.left+","+a.top+")"),C=A.append("g").attr("class","voronoi-clip").append("clipPath").attr("id","voronoi-clip-path-"+e).append("rect");w.select(".voronoi-clip rect").attr("x",-10).attr("y",-10).attr("width",t+20).attr("height",u+20),w.select(".point-paths").attr("clip-path","url(#voronoi-clip-path-"+e+")");var D=w.select(".point-clips").selectAll(".clip-path").data(v);D.enter().append("clipPath").attr("class","clip-path").append("circle").attr("r",25),D.exit().remove(),D.attr("id",function(a,b){return"clip-"+e+"-"+a[2]+"-"+a[3]}).attr("transform",function(a){return"translate("+a[0]+","+a[1]+")"});var E=d3.geom.voronoi(v).map(function(a,b){return{data:a,series:v[b][2],point:v[b][3]}}),F=w.select(".point-paths").selectAll("path").data(E);F.enter().append("path").attr("class",function(a,b){return"path-"+b}),F.exit().remove(),F.attr("clip-path",function(a,b){return"url(#clip-"+e+"-"+a.series+"-"+a.point+")"}).attr("d",function(a){return"M"+a.data.join(",")+"Z"}).on("mouseover",function(b){q.pointMouseover({point:r[b.series].values[b.point],series:r[b.series],pos:[f(i(r[b.series].values[b.point]))+a.left,g(j(r[b.series].values[b.point]))+a.top],seriesIndex:b.series,pointIndex:b.point})}).on("mouseout",function(a,b){q.pointMouseout({point:r[a.series].values[a.point],series:r[a.series],seriesIndex:a.series,pointIndex:a.point})});var G=w.select(".groups").selectAll(".group").data(function(a){return a},function(a){return a.key});G.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(G.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),G.attr("class",function(a,b){return"group series-"+b}).classed("hover",function(a){return a.hover&&!a.disabled}),d3.transition(G).style("fill",function(a,b){return d[b%10]}).style("stroke",function(a,b){return d[b%10]}).style("stroke-opacity",1).style("fill-opacity",.5);var H=G.selectAll("circle.point").data(function(a){return a.values});H.enter().append("circle").attr("cx",function(a){return n(i(a))}).attr("cy",function(a){return o(j(a))}).attr("r",function(a){return p(k(a))}),d3.transition(G.exit().selectAll("circle.point")).attr("cx",function(a){return f(i(a))}).attr("cy",function(a){return g(j(a))}).attr("r",function(a){return h(k(a))}).remove(),H.attr("class",function(a,b){return"point point-"+b}),d3.transition(H).attr("cx",function(a){return f(i(a))}).attr("cy",function(a){return g(j(a))}).attr("r",function(a){return h(k(a))});var I=G.selectAll("line.distX").data(function(a){return a.values});I.enter().append("line").attr("x1",function(a){return n(i(a))}).attr("x2",function(a){return n(i(a))}),d3.transition(G.exit().selectAll("line.distX")).attr("x1",function(a){return f(i(a))}).attr("x2",function(a){return f(i(a))}).remove(),I.attr("class",function(a,b){return"distX distX-"+b}).attr("y1",g.range()[0]).attr("y2",g.range()[0]+8),d3.transition(I).attr("x1",function(a){return f(i(a))}).attr("x2",function(a){return f(i(a))});var J=G.selectAll("line.distY").data(function(a){return a.values});J.enter().append("line").attr("y1",function(a){return o(j(a))}).attr("y2",function(a){return o(j(a))}),d3.transition(G.exit().selectAll("line.distY")).attr("y1",function(a){return g(j(a))}).attr("y2",function(a){return g(j(a))}).remove(),J.attr("class",function(a,b){return"distY distY-"+b}).attr("x1",f.range()[0]).attr("x2",f.range()[0]-8),d3.transition(J).attr("y1",function(a){return g(j(a))}).attr("y2",function(a){return g(j(a))}),q.on("pointMouseover.point",function(b){w.select(".series-"+b.seriesIndex+" .point-"+b.pointIndex).classed("hover",!0),w.select(".series-"+b.seriesIndex+" .distX-"+b.pointIndex).attr("y1",b.pos[1]-a.top),w.select(".series-"+b.seriesIndex+" .distY-"+b.pointIndex).attr("x1",b.pos[0]-a.left)}),q.on("pointMouseout.point",function(a){w.select(".series-"+a.seriesIndex+" circle.point-"+a.pointIndex).classed("hover",!1),w.select(".series-"+a.seriesIndex+" .distX-"+a.pointIndex).attr("y1",g.range()[0]),w.select(".series-"+a.seriesIndex+" .distY-"+a.pointIndex).attr("x1",f.range()[0])}),n=f.copy(),o=g.copy(),p=h.copy()});return r}var a={top:0,right:0,bottom:0,left:0},b=960,c=500,d=d3.scale.category10().range(),e=Math.floor(Math.random()*1e5),f=d3.scale.linear(),g=d3.scale.linear(),h=d3.scale.sqrt(),i=function(a){return a.x},j=function(a){return a.y},k=function(a){return a.size},l=[],m=[],n,o,p,q=d3.dispatch("pointMouseover","pointMouseout");r.dispatch=q,r.margin=function(b){if(!arguments.length)return a;a=b;return r},r.width=function(a){if(!arguments.length)return b;b=a;return r},r.height=function(a){if(!arguments.length)return c;c=a;return r},r.x=function(a){if(!arguments.length)return i;i=d3.functor(a);return r},r.y=function(a){if(!arguments.length)return j;j=d3.functor(a);return r},r.size=function(a){if(!arguments.length)return k;k=d3.functor(a);return r},r.forceX=function(a){if(!arguments.length)return l;l=a;return r},r.forceY=function(a){if(!arguments.length)return m;m=a;return r},r.color=function(a){if(!arguments.length)return d;d=a;return r},r.id=function(a){if(!arguments.length)return e;e=a;return r};return r},a.models.scatterWithLegend=function(){function w(a){a.each(function(f){var g=f.filter(function(a){return!a.disabled}).map(function(a){return a.values});q.domain(d3.extent(d3.merge(g).map(k).concat(n))).range([0,c-b.left-b.right]),r.domain(d3.extent(d3.merge(g).map(l).concat(o))).range([d-b.top-b.bottom,0]),v.width(c-b.left-b.right).height(d-b.top-b.bottom).color(f.map(function(a,b){return a.color||j[b%20]}).filter(function(a,b){return!f[b].disabled})),s.ticks(c/100).tickSize(-(d-b.top-b.bottom),0),t.ticks(d/36).tickSize(-(c-b.right-b.left),0);var h=d3.select(this).selectAll("g.wrap").data([f]),i=h.enter().append("g").attr("class","wrap d3lineWithLegend").append("g");i.append("g").attr("class","legendWrap"),i.append("g").attr("class","x axis"),i.append("g").attr("class","y axis"),i.append("g").attr("class","scatterWrap"),u.dispatch.on("legendClick",function(b,c,d){b.disabled=!b.disabled,f.filter(function(a){return!a.disabled}).length||f.map(function(a){a.disabled=!1,h.selectAll(".series").classed("disabled",!1);return a}),a.transition(e).call(w)}),v.dispatch.on("pointMouseover.tooltip",function(a){p.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),v.dispatch.on("pointMouseout.tooltip",function(a){p.tooltipHide(a)}),u.width(c/2-b.right),h.select(".legendWrap").datum(f).attr("transform","translate("+(c/2-b.left)+","+ -u.height()+")").call(u),b.top=u.height();var m=h.select("g").attr("transform","translate("+b.left+","+b.top+")"),z=h.select(".scatterWrap").datum(f.filter(function(a){return!a.disabled}));d3.transition(z).call(v),s.domain(q.domain()).range(q.range()).ticks(c/100).tickSize(-(d-b.top-b.bottom),0),m.select(".x.axis").attr("transform","translate(0,"+r.range()[0]+")"),d3.transition(m.select(".x.axis")).call(s),t.domain(r.domain()).range(r.range()).ticks(d/36).tickSize(-(c-b.right-b.left),0),d3.transition(m.select(".y.axis")).call(t)});return w}var b={top:30,right:20,bottom:50,left:60},c=960,d=500,e=500,f=!0,g=!0,h=!1,i=!1,j=d3.scale.category10().range(),k=function(a){return a.x},l=function(a){return a.y},m=function(a){return a.size},n=[],o=[],p=d3.dispatch("tooltipShow","tooltipHide"),q=d3.scale.linear(),r=d3.scale.linear(),s=a.models.xaxis().scale(q).tickPadding(10),t=a.models.yaxis().scale(r).tickPadding(10),u=a.models.legend().height(30),v=a.models.scatter();w.dispatch=p,w.margin=function(a){if(!arguments.length)return b;b=a;return w},w.width=function(a){if(!arguments.length)return c;c=a;return w},w.height=function(a){if(!arguments.length)return d;d=a;return w},w.forceX=function(a){if(!arguments.length)return n;n=a,v.forceX(a);return w},w.forceY=function(a){if(!arguments.length)return o;o=a,v.forceY(a);return w},w.animate=function(a){if(!arguments.length)return e;e=a;return w},w.xAxis=s,w.yAxis=t;return w},a.models.sparkline=function(){function h(d){d.each(function(d){f.domain(d3.extent(d,function(a){return a.x})).range([0,b-a.left-a.right]),g.domain(d3.extent(d,function(a){return a.y})).range([c-a.top-a.bottom,0]);var h=d3.select(this).selectAll("svg").data([d]),i=h.enter().append("svg").append("g");i.append("g").attr("class","sparkline").attr("transform","translate("+a.left+","+a.top+")").style("stroke",function(a,b){return a.color||e[b*2%20]}),h.attr("width",b).attr("height",c);var j=i.select(".sparkline").selectAll("path").data(function(a){return[a]});j.enter().append("path"),j.exit().remove(),j.attr("d",d3.svg.line().x(function(a){return f(a.x)}).y(function(a){return g(a.y)}));var k=i.select(".sparkline").selectAll("circle.point").data(function(a){return a.filter(function(a){return g.domain().indexOf(a.y)!=-1})});k.enter().append("circle").attr("class","point"),k.exit().remove(),k.attr("cx",function(a){return f(a.x)}).attr("cy",function(a){return g(a.y)}).attr("r",2).style("stroke",function(a,b){return a.y==g.domain()[0]?"#d62728":"#2ca02c"}).style("fill",function(a,b){return a.y==g.domain()[0]?"#d62728":"#2ca02c"})});return h}var a={top:3,right:3,bottom:3,left:3},b=200,c=20,d=!0,e=d3.scale.category20().range(),f=d3.scale.linear(),g=d3.scale.linear();h.margin=function(b){if(!arguments.length)return a;a=b;return h},h.width=function(a){if(!arguments.length)return b;b=a;return h},h.height=function(a){if(!arguments.length)return c;c=a;return h},h.animate=function(a){if(!arguments.length)return d;d=a;return h};return h},a.models.stackedArea=function(){function p(a){a.each(function(a){var g=JSON.parse(JSON.stringify(a)),h=g.map(function(a){return a.values}),p=c-b.left-b.right,q=d-b.top-b.bottom;g=d3.layout.stack().offset(i).order(j).values(function(a){return a.values})(g),n.domain(k||d3.extent(d3.merge(h),f)).range([0,p]),o.domain(l||[0,d3.max(g,function(a){return d3.max(a.values,function(a){return a.y0+a.y})})]).range([q,0]),m.width(p).height(q).xDomain(n.domain()).yDomain(o.domain()).y(function(a){return a.y+a.y0}).color(a.map(function(a,b){return a.color||e[b%10]}).filter(function(b,c){return!a[c].disabled}));var r=d3.select(this).selectAll("g.d3stackedarea").data([g]),s=r.enter().append("g").attr("class","d3stackedarea").append("g");s.append("g").attr("class","areaWrap"),s.append("g").attr("class","linesWrap");var t=r.select("g").attr("transform","translate("+b.left+","+b.top+")"),u=t.select(".linesWrap").datum(g.filter(function(a){return!a.disabled}));d3.transition(u).call(m);var v=d3.svg.area().x(function(a){return n(f(a))}).y0(function(a){return o(a.y0)}).y1(function(a){return o(a.y+a.y0)}),w=d3.svg.area().x(function(a){return n(f(a))}).y0(function(a){return o(a.y0)}).y1(function(a){return o(a.y0)}),z=t.select(".areaWrap").selectAll("path.area").data(function(a){return a});z.enter().append("path").attr("class","area"),d3.transition(z.exit()).attr("d",function(a,b){return w(a.values,b)}).remove(),z.style("fill",function( +a,b){return e[b%10]}).style("stroke",function(a,b){return e[b%10]}),d3.transition(z).attr("d",function(a,b){return v(a.values,b)})});return p}var b={top:0,right:0,bottom:0,left:0},c=960,d=500,e=d3.scale.category10().range(),f=function(a){return a.x},g=function(a){return a.y},h="stack",i="zero",j="default",k,l,m=a.models.line(),n=d3.scale.linear(),o=d3.scale.linear();p.margin=function(a){if(!arguments.length)return b;b=a;return p},p.width=function(a){if(!arguments.length)return c;c=a;return p},p.height=function(a){if(!arguments.length)return d;d=a;return p},p.color=function(a){if(!arguments.length)return e;e=a;return p},p.offset=function(a){if(!arguments.length)return i;i=a;return p},p.order=function(a){if(!arguments.length)return j;j=a;return p},p.style=function(a){if(!arguments.length)return h;h=a;switch(h){case"stack":i="zero",j="default";break;case"stream":i="wiggle",j="inside-out";break;case"expand":i="expand",j="default"}return p},p.dispatch=m.dispatch;return p},a.models.stackedAreaWithLegend=function(){function r(a){a.each(function(e){var f=e.filter(function(a){return!a.disabled}).reduce(function(a,b,c){b.values.forEach(function(b,d){c||(a[d]={x:b.x,y:0}),a[d].y+=k(b)});return a},[]);h.domain(d3.extent(d3.merge(f),j)).range([0,c-b.left-b.right]),i.domain(p.offset()=="zero"?[0,d3.max(d3.merge(f),k)]:[0,1]).range([d-b.top-b.bottom,0]),p.width(c-b.left-b.right).height(d-b.top-b.bottom);var s=d3.select(this).selectAll("g.wrap").data([e]),t=s.enter().append("g").attr("class","wrap d3stackedWithLegend").append("g");t.append("g").attr("class","x axis"),t.append("g").attr("class","y axis"),t.append("g").attr("class","stackedWrap"),t.append("g").attr("class","legendWrap"),t.append("g").attr("class","controlsWrap"),n.dispatch.on("legendClick",function(b,c){b.disabled=!b.disabled,b.disabled?b.values.map(function(a){a._y=a.y,a.y=0;return a}):b.values.map(function(a){a.y=a._y;return a}),e.filter(function(a){return!a.disabled}).length||e.map(function(a){a.disabled=!1,a.values.map(function(a){a.y=a._y;return a});return a}),a.transition().call(r)}),o.dispatch.on("legendClick",function(b,c){if(!!b.disabled){q=q.map(function(a){a.disabled=!0;return a}),b.disabled=!1;switch(b.key){case"Stacked":p.style("stack");break;case"Stream":p.style("stream");break;case"Expanded":p.style("expand")}a.transition().call(r)}}),p.dispatch.on("pointMouseover.tooltip",function(a){g.tooltipShow({point:a.point,series:a.series,pos:[a.pos[0]+b.left,a.pos[1]+b.top],seriesIndex:a.seriesIndex,pointIndex:a.pointIndex})}),p.dispatch.on("pointMouseout.tooltip",function(a){g.tooltipHide(a)}),b.top=n.height();var u=s.select("g").attr("transform","translate("+b.left+","+b.top+")");n.width(c/2-b.right),o.width(280).color(["#666","#666","#666"]),u.select(".legendWrap").datum(e).attr("transform","translate("+(c/2-b.left)+","+ -b.top+")").call(n),u.select(".controlsWrap").datum(q).attr("transform","translate(0,"+ -b.top+")").call(o);var v=u.select(".stackedWrap").datum(e);d3.transition(v).call(p),l.domain(h.domain()).range(h.range()).ticks(c/100).tickSize(-(d-b.top-b.bottom),0),u.select(".x.axis").attr("transform","translate(0,"+i.range()[0]+")"),d3.transition(u.select(".x.axis")).call(l),m.domain(i.domain()).range(i.range()).ticks(p.offset()=="wiggle"?0:d/36).tickSize(-(c-b.right-b.left),0).tickFormat(p.offset()=="zero"?d3.format(",.2f"):d3.format("%")),d3.transition(u.select(".y.axis")).call(m)});return r}var b={top:30,right:20,bottom:50,left:60},c=960,d=500,e=function(){return 2.5},f=d3.scale.category10().range(),g=d3.dispatch("tooltipShow","tooltipHide"),h=d3.scale.linear(),i=d3.scale.linear(),j=function(a){return a.x},k=function(a){return a.y},l=a.models.xaxis().scale(h),m=a.models.yaxis().scale(i),n=a.models.legend().height(30),o=a.models.legend().height(30),p=a.models.stackedArea(),q=[{key:"Stacked"},{key:"Stream",disabled:!0},{key:"Expanded",disabled:!0}];r.dispatch=g,r.x=function(a){if(!arguments.length)return j;j=a,p.x(a);return r},r.y=function(a){if(!arguments.length)return k;k=a,p.y(a);return r},r.margin=function(a){if(!arguments.length)return b;b=a;return r},r.width=function(a){if(!arguments.length)return c;c=a;return r},r.height=function(a){if(!arguments.length)return d;d=a;return r},r.dotRadius=function(a){if(!arguments.length)return e;e=d3.functor(a),p.dotRadius=a;return r},r.stacked=p,r.xAxis=l,r.yAxis=m;return r},a.charts.line=function(){function h(){if(!b||!c.length)return h;d3.select(b).select("svg").datum(c).transition().duration(d).call(f);return h}var b=null,c=[],d=500,e=function(a,b,c,d,e){return"

"+a+"

"+"

"+c+" at "+b+"

"},f=a.models.lineWithLegend(),g=function(a){var c=$(b).offset(),d=a.pos[0]+c.left,g=a.pos[1]+c.top,h=f.xAxis.tickFormat(),i=f.yAxis.tickFormat(),j=h(f.x()(a.point)),k=i(f.y()(a.point)),l=e(a.series.key,j,k,a,f);nvtooltip.show([d,g],l)};f.xAxis.tickFormat(d3.format(",r")),f.yAxis.tickFormat(d3.format(",.2f")),h.build=function(){if(!b||!c.length)return h;a.addGraph({generate:function(){var a=d3.select(b),e=function(){return parseInt(a.style("width"))},g=function(){return parseInt(a.style("height"))},h=a.append("svg");f.width(e).height(g),h.attr("width",e()).attr("height",g()).datum(c).transition().duration(d).call(f);return f},callback:function(a){a.dispatch.on("tooltipShow",g),a.dispatch.on("tooltipHide",nvtooltip.cleanup),$(window).resize(function(){d3.select(b+" svg").attr("width",a.width()()).attr("height",a.height()()).call(a)})}});return h},h.data=function(a){if(!arguments.length)return c;c=a;return h},h.selector=function(a){if(!arguments.length)return b;b=a;return h},h.duration=function(a){if(!arguments.length)return d;d=a;return h},h.tooltip=function(a){if(!arguments.length)return e;e=a;return h},h.xTickFormat=function(a){if(!arguments.length)return f.xAxis.tickFormat();f.xAxis.tickFormat(typeof a=="function"?a:d3.format(a));return h},h.yTickFormat=function(a){if(!arguments.length)return f.yAxis.tickFormat();f.yAxis.tickFormat(typeof a=="function"?a:d3.format(a));return h},h.xAxisLabel=function(a){if(!arguments.length)return f.xAxis.axisLabel();f.xAxis.axisLabel(a);return h},h.yAxisLabel=function(a){if(!arguments.length)return f.yAxis.axisLabel();f.yAxis.axisLabel(a);return h},d3.rebind(h,f,"x","y"),h.graph=f;return h}}() \ No newline at end of file diff --git a/src/models/line.js b/src/models/line.js index d71a8f6..1702b1e 100644 --- a/src/models/line.js +++ b/src/models/line.js @@ -12,6 +12,7 @@ nv.models.line = function() { getX = function(d) { return d.x }, getY = function(d) { return d.y }, interactive = true, + clipVoronoi = true, xDomain, yDomain; var x = d3.scale.linear(), @@ -30,7 +31,6 @@ nv.models.line = function() { y0 = y0 || y; - //TODO: consider reusing the parent's scales (almost always making duplicates of the same scale) x .domain(xDomain || d3.extent(d3.merge(seriesData), getX )) .range([0, availableWidth]); @@ -62,15 +62,18 @@ nv.models.line = function() { var shiftWrap = gEnter.append('g').attr('class', 'shiftWrap'); - //TODO: currently doesnt remove if user renders, then turns off interactions... currently must turn off before the first render (will need to fix) - //TODO: have the interactive component update AFTER transitions are complete + + // destroy interactive layer during transition, + // VERY needed because of performance issues + g.selectAll('.point-clips *, .point-paths *').remove(); + + function interactiveLayer() { if (!interactive) return false; shiftWrap.append('g').attr('class', 'point-clips'); shiftWrap.append('g').attr('class', 'point-paths'); - var vertices = d3.merge(data.map(function(line, lineIndex) { return line.values.map(function(point, pointIndex) { //return [x(getX(point)), y(getY(point)), lineIndex, pointIndex]; //inject series and point index for reference into voronoi @@ -79,8 +82,7 @@ nv.models.line = function() { }) ); - - + // ***These clips are more than half the cause for the slowdown*** //var pointClips = wrap.select('.point-clips').selectAll('clipPath') // **BROWSER BUG** can't reselect camel cased elements var pointClips = wrap.select('.point-clips').selectAll('.clip-path') .data(vertices); @@ -94,21 +96,19 @@ nv.models.line = function() { //inject series and point index for reference into voronoi + // considering adding a removeZeros option, may be useful for the stacked chart and maybe others var voronoi = d3.geom.voronoi(vertices).map(function(d, i) { return { 'data': d, 'series': vertices[i][2], 'point': vertices[i][3] } }); //TODO: Add small amount noise to prevent duplicates var pointPaths = wrap.select('.point-paths').selectAll('path') .data(voronoi); - pointPaths.enter().append('path') .attr('class', function(d,i) { return 'path-'+i; }) .style('fill-opacity', 0); - pointPaths.exit().remove(); - pointPaths - .attr('clip-path', function(d,i) { return 'url(#clip-' + id + '-' + d.series + '-' + d.point +')' }) + .attr('clip-path', function(d,i) { return clipVoronoi ? 'url(#clip-' + id + '-' + d.series + '-' + d.point +')' : '' }) .attr('d', function(d) { return 'M' + d.data.join(',') + 'Z'; }) .on('mouseover', function(d) { var series = data[d.series], @@ -156,14 +156,15 @@ nv.models.line = function() { lines .attr('class', function(d,i) { return 'line series-' + i }) .classed('hover', function(d) { return d.hover }) - .style('fill', function(d,i){ return color[i % 20] }) - .style('stroke', function(d,i){ return color[i % 20] }) + .style('fill', function(d,i){ return color[i % 10] }) + .style('stroke', function(d,i){ return color[i % 10] }) d3.transition(lines) .style('stroke-opacity', 1) .style('fill-opacity', .5) - .each('end', function(d,i) { if (!i) interactiveLayer() }); //trying to call this after transitions are over.. not sure if the setTimeout is helpful, or dangerous - //.each('end', function(d,i) { if (!i) setTimeout(interactiveLayer,0) }); //trying to call this after transitions are over.. not sure if the setTimeout is helpful, or dangerous + //.each('end', function(d,i) { if (!i) setTimeout(interactiveLayer, 0) }); //trying to call this after transitions are over, doesn't work on resize! + //.each('end', function(d,i) { if (!i) interactiveLayer() }); //trying to call this after transitions are over, not sure if the timeout gains anything + setTimeout(interactiveLayer, 1000); //seems not to work as well as above... BUT fixes broken resize var paths = lines.selectAll('path') .data(function(d, i) { return [d.values] }); @@ -265,6 +266,12 @@ nv.models.line = function() { return chart; }; + chart.clipVoronoi= function(_) { + if (!arguments.length) return clipVoronoi; + clipVoronoi = _; + return chart; + }; + chart.dotRadius = function(_) { if (!arguments.length) return dotRadius; dotRadius = d3.functor(_); diff --git a/src/models/stackedArea.js b/src/models/stackedArea.js index c4e69a6..d379063 100644 --- a/src/models/stackedArea.js +++ b/src/models/stackedArea.js @@ -47,6 +47,7 @@ nv.models.stackedArea = function() { lines + //.interactive(false) .width(availableWidth) .height(availableHeight) .xDomain(x.domain())