templates/visualization.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SWEatshop.tech</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400" rel="stylesheet">
<link rel="stylesheet" href="/static/css/styles.processed.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.js"></script>
<link rel="shortcut icon" href="/static/img/favicon.ico">
<script src="http://phuonghuynh.github.io/js/bower_components/d3/d3.min.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/d3-transform/src/d3-transform.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/cafej/src/extarray.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/cafej/src/misc.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/cafej/src/micro-observer.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/microplugin/src/microplugin.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/bubble-chart/src/bubble-chart.js"></script>
<script src="/static/js/central-click.js"></script>
<script src="http://phuonghuynh.github.io/js/bower_components/bubble-chart/src/plugins/lines/lines.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
$(document).ready(function () {
var bubbleChart = new d3.svg.BubbleChart({
supportResponsive: true,
//container: => use @default
size: 600,
//viewBoxSize: => use @default
innerRadius: 600 / 3.5,
//outerRadius: => use @default
radiusMin: 50,
//radiusMax: use @default
//intersectDelta: use @default
//intersectInc: use @default
//circleColor: use @default
data: {
items: {{type_count|tojson}},
eval: function (item) {return item.count;},
classed: function (item) {return item.text.split(" ").join("");}
},
plugins: [
{
name: "central-click",
options: {
style: {
"font-size": "12px",
"font-style": "italic",
"font-family": "Source Sans Pro, sans-serif",
"text-anchor": "middle",
"fill": "white"
},
attr: {dy: "65px"}
}
},
{
name: "lines",
options: {
format: [
{// Line #0
textField: "count",
classed: {count: true},
style: {
"font-size": "28px",
"font-family": "Source Sans Pro, sans-serif",
"text-anchor": "middle",
fill: "white"
},
attr: {
dy: "0px",
x: function (d) {return d.cx;},
y: function (d) {return d.cy;}
}
},
{// Line #1
textField: "text",
classed: {text: true},
style: {
"font-size": "14px",
"font-family": "Source Sans Pro, sans-serif",
"text-anchor": "middle",
fill: "white"
},
attr: {
dy: "20px",
x: function (d) {return d.cx;},
y: function (d) {return d.cy;}
}
}
],
centralFormat: [
{// Line #0
style: {"font-size": "50px"},
attr: {}
},
{// Line #1
style: {"font-size": "30px"},
attr: {dy: "40px"}
}
]
}
}]
});
});
</script>
</head>
<body class="gradient-bg">
<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse-opacity">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="/index.html"><img alt="Brand" src="/static/img/sweatshop-logo.png" style="width: 200px;"></a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="/index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about.html">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/companies.html">Companies</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">People</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/investors.html">Investors</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/schools.html">Schools</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="/visualization.html">Visualization<span class="sr-only">(current)</span></a>
</li>
<li><a href="#search"><img src="http://www.freeiconspng.com/uploads/search-icon-png-4.png" style="height: 35px;"></a></li>
</ul>
</div>
</nav>
<div style="min-height:89vh">
<h1 class="cover-heading">Visualization</h1>
<div class="container" style="color: white;">
<h3>Average Restaurant Rating by Zipcode</h3>
<h4>data provided by <a href="http://foodcloseto.me" target="_blank">foodcloseto.me</a></h4>
<label><input type="checkbox"> Sort by Rating/Zipcode</label>
<div id="d32"></div>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Zipcode:</strong> <span style='color:dodgerblue'>" +d.letter + "</span></br><strong>Average Rating:</strong> <span style='color:dodgerblue'>" + d.frequency + "</span>" ;
})
var svg = d3.select("#d32").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.call(tip);
d3.tsv("{{ url_for('static', filename='data.tsv') }}", function(error, data) {
data.forEach(function(d) {
d.frequency = +d.frequency;
});
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Zipcode");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Average Rating");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
d3.select("input").on("change", change);
var sortTimeout = setTimeout(function() {
d3.select("input").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(sortTimeout);
// Copy-on-write since tweens are evaluated after a delay.
var x0 = x.domain(data.sort(this.checked
? function(a, b) { return b.frequency - a.frequency; }
: function(a, b) { return d3.ascending(a.letter, b.letter); })
.map(function(d) { return d.letter; }))
.copy();
svg.selectAll(".bar")
.sort(function(a, b) { return x0(a.letter) - x0(b.letter); });
var transition = svg.transition().duration(750),
delay = function(d, i) { return i * 50; };
transition.selectAll(".bar")
.delay(delay)
.attr("x", function(d) { return x0(d.letter); });
transition.select(".x.axis")
.call(xAxis)
.selectAll("g")
.delay(delay);
}
});
</script>
<br/><br/>
<h3>Top 10 Food Types</h3>
<h4>data provided by <a href="http://foodcloseto.me" target="_blank">foodcloseto.me</a></h4>
<div class="bubbleChart"></div>
<br/><br/>
</div>
</div>
<div class="outro">
© SWEatshop 2017
</div>
</body>
<div id="search">
<button type="button" class="close">×</button>
<form action="/search" method="get">
<input type="search" name="query" value="" placeholder="type keyword(s) here" />
<button type="submit" class="btn btn-primary">Search</button>
</form>
</div>
<script>
$(function () {
$('a[href="#search"]').on('click', function(event) {
event.preventDefault();
$('#search').addClass('open');
$('#search > form > input[type="search"]').focus();
});
$('#search, #search button.close').on('click keyup', function(event) {
if (event.target == this || event.target.className == 'close' || event.keyCode == 27) {
$(this).removeClass('open');
}
});
});
</script>
</html>