Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg { width:100%; height: 100% }
.table th{
text-align:center;
}
.table td{
text-align:center;
}
.table td:first-child{
text-align:left
}
.bar {fill: steelblue;}
.bar:hover {fill: red}
</style>
</head>
<body>
<div class="col-md-12">
<h3 id="market-name">market</h3>
</div>
<div class="col-md-4">
<div id="page-title">
</div>
<div id="roster"></div>
</div>
<div class="col-md-8">
<div id="area1"> </div>
</div>
<script>
var dateparser = d3.time.format("%m/%d/%Y");
var pctformat = d3.format("%");
var r2precision = d3.format(".2f")
var mformat = d3.format(",");
var months = {0:"Jan", 1:"Feb", 2:"Mar", 3:"Apr", 4:"May", 5:"Jun", 6:"Jul", 7:"Aug", 8:"Sep", 9:"Oct", 10:"Nov", 11:"Dec" };
var data = [];
var columns = ["Period", "Visits", "Bounce Rate", "Avg. Visit Duration" ];
var markets =[];
var marketSelector = d3.select("#page-title")
.append("select")
.attr("id", "market-selector")
.on("change", function() { selectMarket(this.value); });
var margin = {top: 40, right: 50, bottom: 50, left:75
},
width = 700 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var svg = d3.select("#area1").append("svg")
.attr("width",width+ margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class","viewport")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var y = d3.scale.linear()
.range([height,0]);
var table = d3.select("#roster")
.append("table")
.classed("table", true);
var thead = table.append("thead");
var tbody = table.append("tbody");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
//start reload
//console.log("start reload")
var reload = function () {
d3.csv("data.csv", function(records){
data = records;
data.forEach(function (d) {
d.Date = dateparser.parse(d.Date);
d.Month = d.Date.getMonth();
d.Year = d.Date.getFullYear();
d.Period = d.Year + "-" + (d.Month+1)
d.Visits = +d.Visits;
d.Bounces = +d.Bounces;
d.Pageviews = +d.Pageviews;
d.SPV = +d.SPV;
d.TotalSeconds = +d.TotalSeconds;
if (markets.indexOf(d.Market)<0) {
markets.push(d.Market);
};
});
//console.log(data);
//establish x and y axes
x.domain(data.map(function(d) { return d.Period; }));
y.domain([0, d3.max(data, function(d) { return d.Visits; })]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("Left")
.ticks(5)
.tickFormat(d3.format("s"));
svg.append("g")
.attr("class", "x-axis")
.style("font-size","11px")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y-axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".30em")
.style("text-anchor", "end")
.style("font-size","12px")
.text("visits");
markets.sort();
selectMarket(markets[0]);
});
};
//start of redraw function
var redraw = function(roster) {
var nested_data = [];
current_sel = svg.selectAll(".bar").data(nested_data),function(d){return d;};
current_sel.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.chartPeriod); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.chartVisits); })
.attr("height", function(d) { return height - y(d.chartVisits);});
current_sel.exit().remove();
var nested_data = d3.nest()
.key(function(d) {return d.Period; }).sortKeys(d3.ascending)
.rollup(function(v) {return{
visits:d3.sum(v, function(d) {return d.Visits; }),
BounceRate : d3.sum(v, function(d) {return d.Bounces; })/d3.sum(v, function(d) {return d.Visits; }),
AVD:d3.sum(v, function (d) {return d.TotalSeconds;}) / (d3.sum(v, function(d) {return d.Visits; })-d3.sum(v, function(d) {return d.Bounces; }))/60
};})
.entries(roster);
nested_data.forEach(function (d) {
d.Period = months[d.key.split("-").pop() - 1] + "-" + d.key.slice(0,4) ;
d.Visits = mformat(d.values.visits);
d["Bounce Rate"] = pctformat(d.values.BounceRate);
d["Avg. Visit Duration"] = r2precision(d.values.AVD)
d.chartVisits = +d.values.visits
d.chartPeriod = d.Period
});
console.log(nested_data);
//update axes domains and establish rescaled axes
x.domain(nested_data.map(function(d) { return d.chartPeriod; }));
y.domain([0, d3.max(nested_data, function(d) { return d.chartVisits; })]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickFormat(d3.format("s"));
d3.select(".x-axis")
.transition()
.call(xAxis);
d3.select(".y-axis")
.transition()
.call(yAxis);
//update drop-down selector
marketSelector.selectAll("option")
.data(markets)
.enter()
.append("option")
.attr("value", function(d) { return d; })
.text(function(d) { return d; })
.sort(function(a,b) { return d3.ascending(a,b); });
//update table header and rows
thead.selectAll("tr")
.data([columns])
.enter()
.append("tr")
.selectAll("th")
.data(function(d) { return d; })
.enter()
.append("th")
.on("click", function(d) {
tbody.selectAll("tr")
.sort(function(a,b) {
return (d === 'No')
? d3.ascending(+a[d], +b[d])
: d3.ascending(a[d], b[d])
})
.style("background-color", function(d,i) { return (i%2)? "white":"lightgray"; });
}).text(function(d) { return d; })
;
var rows = tbody.selectAll("tr")
.data(nested_data);
rows.enter()
.append("tr")
.style("background-color", function(d,i) { return (i%2)? "white":"lightgray"; });
rows.exit().remove();
var cells = rows.selectAll("td")
.data(function(row) { return columns.map(function(col) {
return row[col];
});});
cells.enter().append("td");
cells.text(function(d) { return d; });
cells.exit().remove();
//redraw chart
current_sel = svg.selectAll(".bar").data(nested_data),function(d){return d;};
current_sel.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.chartPeriod); })
.attr("width", x.rangeBand())
.attr("y",y(0))
.attr("height",0)
.transition()
.delay(function (d, i) { return i*50; })
.duration(800)
.attr("y", function(d) { return y(d.chartVisits); })
.attr("height", function(d) { return height - y(d.chartVisits);});
current_sel.exit().remove();
//tooltip
var div = d3.select("#area1").append("div")
.style("position", "absolute")
.style("text-align","center")
.style("width","120px")
.style("height", "3.0 em")
.style("font", "1em Open Sans")
.style("color", "black")
.style("background","white")
.style("border-radius", "4px")
.style("border", "solid 2px red")
.style("opacity", 0);
function mouseover(d) {
div.html ("Period: " + d.chartPeriod + "<br />"
+ "Visits: " + d.chartVisits)
.style("left", (x(d.chartPeriod)) + 90 + "px")
.style ("top", (y(d.chartVisits)) - 10 + "px")
.style("opacity",1);
}
function mouseout() {
div.style("opacity", 1e-6)
.style("left","1px")
.style("top", height+100);
}
d3.selectAll(".bar")
.on("mouseover", mouseover)
.on("mouseout", mouseout);
};
//end of redraw function
var selectMarket = function(marketId) {
var roster = data.filter(function(d) { return d.Market === marketId; });
redraw(roster);
d3.select("#market-name").text(marketId + ": Summary Metrics");
document.getElementById("market-selector").value = marketId;
};
reload();
</script>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js