|
window.onload = (function () { |
|
"use strict"; |
|
var base_url = 'https://ecoengine.berkeley.edu/api/sensors/', |
|
d3canvas; |
|
|
|
function create_url(interval, sensor, start, end) { |
|
return base_url + sensor + '/aggregate/?format=json&page_size=10000&min_date=' + start + "&max_date=" + end + "&interval=" + interval; |
|
} |
|
|
|
function D3Obj() { |
|
var data, timestring, tooltime, |
|
margin = {top: 20, right: 20, bottom: 30, left: 50}, |
|
width = 900 - margin.left - margin.right, |
|
height = 400 - margin.top - margin.bottom, |
|
x = d3.time.scale().range([0, width]), |
|
y = d3.scale.linear().range([height, 0]), |
|
xAxis = d3.svg.axis().scale(x).orient("bottom"), |
|
yAxis = d3.svg.axis().scale(y).orient("left"), |
|
format = d3.time.format("%Y-%m-%dT%H:%M:%S"), |
|
svg = d3.select("#canvas").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 + ")"), |
|
rect = svg.append("svg:rect") |
|
.attr("class", "pane") |
|
.attr("width", width) |
|
.attr("height", height), |
|
div = d3.select("#canvas").append("div") |
|
.attr("class", "tooltip_box") |
|
.style("opacity", 1), |
|
path2 = svg.append("path") |
|
.attr("class", "line"), |
|
circle = svg.append("circle") |
|
.attr("r", 4) |
|
.attr("cx", 0) |
|
.attr("cy", 0) |
|
.attr("class", "circle") |
|
.attr("opacity", 0); |
|
svg.append("g") |
|
.attr("class", "x_axis") |
|
.attr("transform", "translate(0," + height + ")"); |
|
svg.append("g") |
|
.attr("class", "y_axis") |
|
.attr("y", 6) |
|
.attr("dy", ".71em"); |
|
// define value cursor |
|
rect.on("mousemove", function (event) { |
|
// http://jsfiddle.net/D4MRP/15/ |
|
var pathData = path2.data(), |
|
X_px = d3.mouse(this)[0], |
|
Y_px, |
|
X_date = format(x.invert(X_px)), |
|
Y_val, |
|
X_val; |
|
if (pathData[0]) { |
|
pathData[0].forEach(function (element, index, array) { |
|
if (index + 1 < array.length && |
|
array[index].begin_date <= X_date && |
|
array[index + 1].begin_date >= X_date |
|
) { |
|
Y_val = array[index + 1].mean; |
|
X_val = array[index + 1].begin_date; |
|
} |
|
}); |
|
} |
|
Y_px = y(Y_val); |
|
X_px = x(format.parse(X_val)); |
|
timestring = d3.time.format("%Y %b %e %I:%M%p"); |
|
tooltime = timestring(format.parse(X_val)); |
|
circle |
|
.attr("opacity", 1) |
|
.attr("cx", X_px) |
|
.attr("cy", Y_px); |
|
if (Y_val !== null) { |
|
d3.select(".tooltip_box") |
|
.html("<b>Date:</b> " + tooltime + "<br><span style='color:#E04E39'><b>Value:</b></span> " + Number(Y_val.toFixed(3))); |
|
} else { |
|
d3.select(".tooltip_box") |
|
.html("<b>Date:</b> " + tooltime + "<br><span style='color:#E04E39'><b>Value:</b></span> null"); |
|
} |
|
}); |
|
this.update = function (json) { |
|
data = json.results; |
|
var line = d3.svg.line() |
|
.x(function (d) { return x(format.parse(d.begin_date));}) |
|
.y(function (d) { return y(d.mean); }); |
|
x.domain(d3.extent(data, function (d) { return format.parse(d.begin_date); })); |
|
y.domain(d3.extent(data, function (d) { return d.mean; })); |
|
svg.selectAll(".x_axis") |
|
.transition().duration(750).delay(500) |
|
.call(xAxis); |
|
svg.selectAll(".y_axis") |
|
.transition().duration(750).delay(500) |
|
.call(yAxis); |
|
var path = svg.selectAll(".line") |
|
.datum(data) |
|
.transition().duration(750).delay(500) |
|
.attr("d", line); |
|
}; |
|
} |
|
|
|
function Chart() { |
|
this.update = function(args) { |
|
var item; |
|
// looping through argument literal and updating property when in literal |
|
for(item in args) { |
|
this[item] = args[item]; |
|
} |
|
var url = create_url(this.interval, this.sensor, this.start, this.end); |
|
d3.json(url, function(error, json) { |
|
if (error) return console.warn(error); |
|
d3canvas.update(json); |
|
}); |
|
}; |
|
} |
|
|
|
(function init() { |
|
d3canvas = new D3Obj(); |
|
var chart = new Chart(); |
|
// populate menu |
|
d3.json(base_url, function(error, json) { |
|
if (error) return alert("Cannot access Ecoengine data"); |
|
// first introspect count than adjust page-size to make request |
|
if (json.count) { |
|
d3.json(base_url + '?page_size=' + json.count, function(error, json) { |
|
var options = d3.select("#sensor_select").selectAll('option').data(json.results); |
|
options.enter() |
|
.append('option') |
|
.attr('class', 'sensor_selector') |
|
.attr('value', function (d) {return d.record;}) |
|
.html(function (d) {return d.station_name + ', ' + d.variable;}); |
|
// update on initial load |
|
chart.update({ |
|
'sensor': json.results[0].record, |
|
'interval': 'weeks', |
|
'start': '1998-01-01', |
|
'end': '2013-12-31'}); |
|
}); |
|
} |
|
}); |
|
d3.select('#interval_select').on('change', function () { |
|
chart.update({interval: d3.event.target.value}); |
|
}); |
|
d3.select('#sensor_select').on('change', function () { |
|
chart.update({sensor: d3.event.target.value}); |
|
}); |
|
}()); |
|
|
|
}()); |