<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
<![endif]-->

<script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet-src.js"></script>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.0.0-rc.3/lodash.underscore.min.js"></script>

<script type="text/javascript" src="colorbrewer.js"></script>
<script type="text/javascript" src="leaflet.points-layer.js"></script>

<style type="text/css">
html, body { margin: 0; padding: 0; height: 100%; }
.mapHere { height: 100%; width: 100%; margin:0;padding:0;position:absolute;top:0;left:0; }
.leaflet-popup-content ul { padding-left: 1.5em; }
.circle { visibility: hidden; }
.circle.selected { visibility: visible; }
.quake-timeseries { font: 10px sans-serif; position:absolute;bottom:0;left:0;background-color:rgba(255,255,255,0.8);}
.axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; }
.death{stroke:black;opacity:0.3;fill:red;}
</style>
</head>
<body>
<div class='mapHere' data-source="data-deaths.csv"></div>
<script type="text/javascript">
(function () {
		var extent, scale,
				classes = 9,
				reverse = false;
				scheme = colorbrewer['YlGn'][classes],
				container = document.querySelector('.mapHere');
				map = L.map(container).setView([45, 0], 3);

		L.tileLayer(
			'http://{s}.tile.osm.org/{z}/{x}/{y}.png'
			,{
				attribution: '<a href="http://content.stamen.com/dotspotting_toner_cartography_available_for_download">Stamen Toner</a>, <a href="http://www.openstreetmap.org/">OpenStreetMap</a>, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
				,maxZoom: 17
			}
		).addTo(map);
		map._initPathRoot();
		var svg = d3.select(container.querySelector('svg'))
		,markers = svg.append('g')
		;
		
		d3.csv(container.dataset.source, function(collection) {
/*
{
	"Event_id": "",
	"cause_of_death": "asphyxiated",
	"CartoDB_Cause_of_death": "drowning or exhaustion related death",
	"dataset": "",
	"date": "2015-08-27T00:00:00Z",
	"quarter": "3Q2015",
	"Date-month": "2015 -- 8",
	"Year": "2015",
	"dead": "70",
	"missing": "0",
	"dead_and_missing": "70",
	"description": "Up to 70 people, presumed to be asylum-seekers, have been found dead in the back of a lorry in Austria.",
	"location": "Parndorf",
	"latitude": "48",
	"longitude": "16.8",
	"latlong": "48, 16.8",
	"Somme Dedoublement": "",
	"name": "",
	"route": "Western Balkan route       ",
	"source": "Austrian Police",
	"source_url": "http://www.ft.com/cms/s/0/83323a26-4cc0-11e5-9b5d-89a026fda5c9.html#axzz3k5quE1Mi"
}
*/
			collection.forEach(function(d, i, a){
				d.LatLng = new L.LatLng( d.latitude || 0, d.longitude || 0);
			});
			// setup data binding
			var markerLayer = markers.selectAll('circle')
			.data(collection)

			// create, setting up un-changing properties+attributes
			markerLayer
			.enter()
			.append('circle')
			.attr('class','death')
			;
			
			// update per models (chaning values)
			markerLayer
			.attr("r", function(d){
				return Math.pow((d.dead_and_missing * 1), 0.5);
			})
			;  

			// cleanup as they're removed
			markerLayer.exit().remove();

			map.on("viewreset", update);
			update();

			function update() {
				markerLayer.attr("transform", 
				function(d) { 
					return "translate("+ 
						map.latLngToLayerPoint(d.LatLng).x +","+ 
						map.latLngToLayerPoint(d.LatLng).y +")";
					}
				)
			}
			;

				L.pointsLayer(collection, {
						radius: get_radius,
						applyStyle: circle_style
				}).addTo(map);

				var chart = timeseries_chart(scheme)
								.x(get_time).xLabel("Earthquake origin time")
								.y(get_magnitude).yLabel("Magnitude")
								.brushmove(on_brush);

				d3.select("body").datum(collection.features).call(chart);
		});

		function get_time(d) {
				return d3.time.format.iso.parse(d.properties.origintime);
		}

		function get_magnitude(d) {
				return +d.properties.magnitude;
		}

		function on_brush(brush) {
				var s = brush.extent();
				d3.selectAll(".circle").classed("selected", function (d) {
						var time = get_time(d);
						return s[0] <= time && time <= s[1];
				});
		}

		function get_radius(d) {
				return d.properties.magnitude * d.properties.magnitude;
		}

		function circle_style(circles) {
				if (!(extent && scale)) {
						extent = d3.extent(circles.data(), function (d) { return d.properties.depth; });
						scale = d3.scale.log()
										.domain(reverse ? extent.reverse() : extent)
										.range(d3.range(classes));
				}
				circles.attr('opacity', 0.4)
						.attr('stroke', scheme[classes - 1])
						.attr('stroke-width', 1)
						.attr('fill', function (d) {
								return scheme[(scale(d.properties.depth) * 10).toFixed()];
						});

				circles.on('click', function (d, i) {
						L.DomEvent.stopPropagation(d3.event);

						var t = '<h3><%- id %></h3>' +
										'<ul>' +
										'<li>Magnitude: <%- mag %></li>' +
										'<li>Depth: <%- depth %>km</li>' +
										'</ul>';

						var data = {
										id: d.id,
										mag: d.properties.magnitude,
										depth: d.properties.depth
								};

						L.popup()
								.setLatLng([d.geometry.coordinates[1], d.geometry.coordinates[0]])
								.setContent(_.template(t, data))
								.openOn(map);

				});
		}

		function timeseries_chart(color) {
				var margin = { top: 5, right: 5, bottom: 40, left: 45 },
						width = 960 - margin.left - margin.right,
						height = 80;

				var x = d3.time.scale(),
						y = d3.scale.linear(),
						x_label = "X", y_label = "Y",
						brush = d3.svg.brush().x(x).on("brush", _brushmove);

				var get_x = no_op,
						get_y = no_op;

				function timeseries(selection) {
						selection.each(function (d) {
								x.range([0, width]);
								y.range([height, 0]);

								var series = d3.select(this).append("svg").attr("class", "quake-timeseries")
												.attr("width", width + margin.left + margin.right)
												.attr("height", height + margin.top + margin.bottom)
												.append("g").attr("id", "date-brush")
												.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

								var x_axis = series.append("g")
												.attr("class", "x axis")
												.attr("transform", "translate(0," + height + ")");

								var y_axis = series.append("g")
												.attr("class", "y axis");

								x_axis.append("text")
										.attr("class", "label")
										.attr("x", width)
										.attr("y", 30)
										.style("text-anchor", "end")
										.text(x_label);

								y_axis.append("text")
										.attr("class", "label")
										.attr("transform", "rotate(-90)")
										.attr("y", -40)
										.attr("dy", ".71em")
										.style("text-anchor", "end")
										.text(y_label);

								series.append("clipPath")
										.attr("id", "clip")
										.append("rect")
										.attr("width", width - 1)
										.attr("height", height - .25)
										.attr("transform", "translate(1,0)");

								series.append("g")
												.attr("class", "brush")
												.call(brush)
												.selectAll("rect")
												.attr("height", height)
												.style("stroke-width", 1)
												.style("stroke", color[color.length - 1])
												.style("fill", color[2])
												.attr("opacity", 0.4);

								x.domain(d3.extent(d, get_x));
								x_axis.call(d3.svg.axis().scale(x).orient("bottom"));

								y.domain(d3.extent(d, get_y));
								y_axis.call(d3.svg.axis().scale(y).orient("left"));

								series.append("g").attr("class", "timeseries")
										.attr("clip-path", "url(#clip)")
										.selectAll("circle")
										.data(d).enter()
										.append("circle")
										.style("stroke", color[color.length - 2])
										.style("stroke-width", .5)
										.style("fill", color[color.length - 1])
										.attr("opacity", .4)
										.attr("r", 2)
										.attr("transform", function (d) {
												return "translate(" + x(get_x(d)) + "," + y(get_y(d)) + ")";
										});
						});
				}

				timeseries.x = function (accessor) {
						if (!arguments.length) return get_x;
						get_x = accessor;
						return timeseries;
				};

				timeseries.y = function (accessor) {
						if (!arguments.length) return get_y;
						get_y = accessor;
						return timeseries;
				};

				timeseries.xLabel = function (label) {
						if (!arguments.length) return x_label;
						x_label = label;
						return timeseries;
				}

				timeseries.yLabel = function (label) {
						if (!arguments.length) return y_label;
						y_label = label;
						return timeseries;
				}

				timeseries.brushmove = function (cb) {
						if (!arguments.length) return brushmove;
						brushmove = cb;
						return timeseries;
				};

				function _brushmove() {
						brushmove.call(null, brush);
				}

				function no_op() {}

				return timeseries;
		}
}());
</script>
</body>
</html>