forked from wezm/wezm.net
Switch to a dygraph temperature graph and add extremes
This commit is contained in:
parent
71f2d3d65c
commit
503380c8f5
4 changed files with 243 additions and 148 deletions
|
@ -442,9 +442,22 @@ body.weather
|
|||
width: 100%
|
||||
height: 320px
|
||||
|
||||
section.rain
|
||||
section, section > .temperature
|
||||
clear: both
|
||||
margin-top: 2em
|
||||
|
||||
.extreme
|
||||
float: left
|
||||
margin: 0 2em 2em 0
|
||||
|
||||
time.day
|
||||
display: block
|
||||
text-align: center
|
||||
|
||||
div, time
|
||||
margin: 0.5em 0
|
||||
font-family: $ans-serif
|
||||
|
||||
small
|
||||
display: block
|
||||
font-size: smaller
|
||||
|
|
|
@ -5,7 +5,13 @@
|
|||
|
||||
<div class="loading"><img src="/images/spinner.gif" width="64" height="64" alt="Loading" /> Loading</div>
|
||||
|
||||
<div class="temperature chart"></div>
|
||||
<section class="extremes"></section>
|
||||
|
||||
<div class="temperature">
|
||||
<h3>History</h3>
|
||||
<button id="today">Today</button>
|
||||
<div class="chart"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="rain">
|
||||
|
@ -22,4 +28,34 @@
|
|||
<div class="rainfall week chart"></div>
|
||||
</section>
|
||||
|
||||
<small>Forecast icons by <a href="http://lavana.deviantart.com/art/Flat-Weather-Icons-32021664">LavAna</a></small>
|
||||
<small>Forecast icons by <a href="http://lavana.deviantart.com/art/Flat-Weather-Icons-32021664">LavAna</a></small>
|
||||
<script id="current-template" type="text/x-handlebars-template">
|
||||
<div id="current">
|
||||
<figure class="forecast">
|
||||
<img src="/images/weather/{{forecast}}.png" width="48" height="48" alt="{{forecast}}" />
|
||||
<figcaption>Forecast</figcaption>
|
||||
</figure>
|
||||
|
||||
<div class="temperature">
|
||||
<div class="current temperature">{{temperature}}°C</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script id="extremes-template" type="text/x-handlebars-template">
|
||||
<section class="extremes">
|
||||
<h3>Extremes</h3>
|
||||
{{#extremes}}
|
||||
<div class="extreme">
|
||||
<time datetime="{{isoDate date}}" class="day">{{day date}}</time>
|
||||
<div class="min">
|
||||
Min <span class="temperature">{{min/temperature}}°C</span> at
|
||||
<time datetime="{{isoDate min/time}}">{{time min/time}}</time>
|
||||
</div>
|
||||
<div class="max">
|
||||
Max <span class="temperature">{{max/temperature}}°C</span> at
|
||||
<time datetime="{{isoDate max/time}}">{{time max/time}}</time>
|
||||
</div>
|
||||
</div>
|
||||
{{/extremes}}
|
||||
</section>
|
||||
</script>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<%= render '_head' %>
|
||||
<script src="/js/jquery.flot.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="/js/dygraph-combined.js" type="text/javascript" charset="utf-8"></script>
|
||||
<!--[if IE lt 9]><script language="javascript" type="text/javascript" src="/js/excanvas.min.js"></script><![endif]-->
|
||||
<script src="/js/handlebars.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="/js/weather.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
|
|
@ -1,158 +1,203 @@
|
|||
function render_current(o) {
|
||||
return '<div id="current">\n\
|
||||
<figure class="forecast">\n\
|
||||
<img src="/images/weather/' + (Mojo.escape(Mojo.normalize(o, "forecast"))) + '.png" width="48" height="48" alt="' + (Mojo.escape(Mojo.normalize(o, "forecast"))) + '" />\n\
|
||||
<figcaption>Forecast</figcaption>\n\
|
||||
</figure>\n\
|
||||
\n\
|
||||
<div class="temperature">\n\
|
||||
<div class="current temperature">' + (Mojo.escape(Mojo.normalize(o, "temperature"))) + '°C</div>\n\
|
||||
<div class="minmax">\n\
|
||||
Minimum <span class="min temperature">' + (Mojo.escape(Mojo.normalize(o, "min_temp"))) + '°C</span> at\n\
|
||||
<time datetime="' + (Mojo.escape(Mojo.normalize(o, "min_datetime"))) + '">' + (Mojo.escape(Mojo.normalize(o, "minDateString"))) + '</time>\n\
|
||||
Maximum <span class="max temperature">' + (Mojo.escape(Mojo.normalize(o, "max_temp"))) + '°C</span> at\n\
|
||||
<time datetime="' + (Mojo.escape(Mojo.normalize(o, "max_datetime"))) + '">' + (Mojo.escape(Mojo.normalize(o, "maxDateString"))) + '</time>\n\
|
||||
</div>\n\
|
||||
</div>\n\
|
||||
</div>';
|
||||
};
|
||||
(function() {
|
||||
// {"wind_angle":270,"rel_humidity_in":51,"rain_1h":0,"temperature_out":9.9,"forecast":"Sunny","rain_24h":0,"dewpoint":7.11,"wind_chill":9.9,"temperature_in":20.8,"rel_humidity_out":83,"tendency":"Rising","wind_speed":0,"rel_pressure":970.7,"rain_total":1.55,"datetime":"2010-09-20 11:30:13","wind_direction":"W"}
|
||||
|
||||
// {"wind_angle":270,"rel_humidity_in":51,"rain_1h":0,"temperature_out":9.9,"forecast":"Sunny","rain_24h":0,"dewpoint":7.11,"wind_chill":9.9,"temperature_in":20.8,"rel_humidity_out":83,"tendency":"Rising","wind_speed":0,"rel_pressure":970.7,"rain_total":1.55,"datetime":"2010-09-20 11:30:13","wind_direction":"W"}
|
||||
// forecaset is Rainy, Cloudy or Sunny
|
||||
|
||||
// forecaset is Rainy, Cloudy or Sunny
|
||||
// Return a string of a number padded with leading zeros
|
||||
function padNumber(n, count) {
|
||||
if(count === undefined) count = 2;
|
||||
|
||||
// Return a string of a number padded with leading zeros
|
||||
function padNumber(n, count) {
|
||||
if(count === undefined) count = 2;
|
||||
|
||||
var string = n.toString();
|
||||
var padding = [];
|
||||
for(var i = count - string.length; i > 0; i--) {
|
||||
padding.push('0');
|
||||
}
|
||||
return padding.join('') + string;
|
||||
}
|
||||
|
||||
function isoString(date) {
|
||||
// YYYY-MM-DDTHH:MM:SS
|
||||
if(!date) return '';
|
||||
|
||||
return [
|
||||
[
|
||||
date.getUTCFullYear(),
|
||||
padNumber(date.getUTCMonth() + 1),
|
||||
padNumber(date.getUTCDate())
|
||||
].join('-'),
|
||||
'T',
|
||||
[
|
||||
padNumber(date.getUTCHours()),
|
||||
padNumber(date.getUTCMinutes()),
|
||||
padNumber(date.getUTCSeconds())
|
||||
].join(':')
|
||||
].join('')
|
||||
}
|
||||
|
||||
function datetimeString(date) {
|
||||
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||
return [
|
||||
date.getUTCDate(),
|
||||
months[date.getUTCMonth()],
|
||||
timeString(date)
|
||||
].join(' ')
|
||||
}
|
||||
|
||||
function timeString(date) {
|
||||
return [
|
||||
padNumber(date.getUTCHours()),
|
||||
padNumber(date.getUTCMinutes())
|
||||
].join(':')
|
||||
}
|
||||
|
||||
//function newUTCDate()
|
||||
|
||||
jQuery(function() {
|
||||
var now = new Date();
|
||||
jQuery.getJSON("/weather.json", function(data, status) {
|
||||
// Populate the current conditions
|
||||
var current = {
|
||||
temperature: data.current.temperature_out,
|
||||
timestamp: function() {
|
||||
var d = new Date(data.current.timestamp);
|
||||
return datetimeString(d);
|
||||
},
|
||||
min_temp: data.current.min.temperature,
|
||||
min_date: new Date(data.current.min.timestamp),
|
||||
min_datetime: function() {
|
||||
return isoString(this.min_date)
|
||||
},
|
||||
minDateString: function() {
|
||||
return timeString(current.min_date)
|
||||
},
|
||||
max_temp: data.current.max.temperature,
|
||||
max_date: new Date(data.current.max.timestamp),
|
||||
max_datetime: function() {
|
||||
return isoString(this.max_date)
|
||||
},
|
||||
maxDateString: function() {
|
||||
return timeString(current.max_date)
|
||||
},
|
||||
forecast: data.current.forecast
|
||||
};
|
||||
|
||||
var current_div = render_current(current);
|
||||
$('.loading').replaceWith(current_div)
|
||||
|
||||
// Populate the charts
|
||||
var count = data.history.length;
|
||||
for(var i = 0; i < count; i++) {
|
||||
data.history[i][0] = new Date(data.history[i][0] - (now.getTimezoneOffset() * 60 * 1000));
|
||||
var string = n.toString();
|
||||
var padding = [];
|
||||
for(var i = count - string.length; i > 0; i--) {
|
||||
padding.push('0');
|
||||
}
|
||||
jQuery.plot('.temperature.chart', data.history, {
|
||||
xaxis: {
|
||||
mode: "time"
|
||||
return padding.join('') + string;
|
||||
}
|
||||
|
||||
function isoString(date) {
|
||||
// YYYY-MM-DDTHH:MM:SS
|
||||
if(!date) return '';
|
||||
|
||||
if (typeof date.toISOString == 'function') {
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
return [
|
||||
[
|
||||
date.getUTCFullYear(),
|
||||
padNumber(date.getUTCMonth() + 1),
|
||||
padNumber(date.getUTCDate())
|
||||
].join('-'),
|
||||
'T',
|
||||
[
|
||||
padNumber(date.getUTCHours()),
|
||||
padNumber(date.getUTCMinutes()),
|
||||
padNumber(date.getUTCSeconds())
|
||||
].join(':'),
|
||||
'Z'
|
||||
].join('')
|
||||
}
|
||||
|
||||
function datetimeString(date) {
|
||||
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||
return [
|
||||
date.getUTCDate(),
|
||||
months[date.getUTCMonth()],
|
||||
timeString(date)
|
||||
].join(' ')
|
||||
}
|
||||
|
||||
function timeString(date) {
|
||||
return [
|
||||
padNumber(date.getHours()),
|
||||
padNumber(date.getMinutes())
|
||||
].join(':')
|
||||
}
|
||||
|
||||
function dateWindowToday() {
|
||||
var now = new Date();
|
||||
var start = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
var end = new Date(start.getTime() + (1000 * 60 * 60 * 24) - 1) // 1 day minus a millisecond
|
||||
|
||||
return [start, end];
|
||||
}
|
||||
|
||||
// Register Handlebars date helpers
|
||||
var days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
|
||||
Handlebars.registerHelper('day', function(date) {
|
||||
return days[date.getDay()];
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('time', function(date) {
|
||||
return timeString(date);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('isoDate', function(date) {
|
||||
return isoString(date);
|
||||
});
|
||||
|
||||
jQuery(function() {
|
||||
// Compile templates
|
||||
var currentTemplate = Handlebars.compile($('#current-template').html());
|
||||
var extremesTemplate = Handlebars.compile($('#extremes-template').html());
|
||||
|
||||
var now = new Date();
|
||||
jQuery.getJSON("/weather.json", function(data, status) {
|
||||
// Populate the current conditions
|
||||
var current = {
|
||||
temperature: data.current.temperature_out,
|
||||
timestamp: function() {
|
||||
var d = new Date(data.current.timestamp);
|
||||
return datetimeString(d);
|
||||
},
|
||||
// min_temp: data.current.min.temperature,
|
||||
// min_date: new Date(data.current.min.timestamp),
|
||||
// min_datetime: function() {
|
||||
// return isoString(this.min_date)
|
||||
// },
|
||||
// minDateString: function() {
|
||||
// return timeString(current.min_date)
|
||||
// },
|
||||
// max_temp: data.current.max.temperature,
|
||||
// max_date: new Date(data.current.max.timestamp),
|
||||
// max_datetime: function() {
|
||||
// return isoString(this.max_date)
|
||||
// },
|
||||
// maxDateString: function() {
|
||||
// return timeString(current.max_date)
|
||||
// },
|
||||
forecast: data.current.forecast
|
||||
};
|
||||
|
||||
var current_div = currentTemplate(current);
|
||||
$('.loading').replaceWith(current_div)
|
||||
|
||||
// Populate the extremes
|
||||
var extremes = [];
|
||||
var len = data.extremes.length;
|
||||
for(var i = 0; i < len; i++) {
|
||||
var e = data.extremes[i];
|
||||
var extreme = {
|
||||
date: new Date(e.date),
|
||||
min: {
|
||||
temperature: e.min.temperature,
|
||||
time: new Date(e.min.timestamp)
|
||||
},
|
||||
max: {
|
||||
temperature: e.max.temperature,
|
||||
time: new Date(e.max.timestamp)
|
||||
}
|
||||
};
|
||||
extremes.push(extreme);
|
||||
}
|
||||
});
|
||||
|
||||
// Rain
|
||||
var total_rain_today = 0;
|
||||
jQuery.each(data.rain.today, function(idx, reading) {
|
||||
total_rain_today += reading[1];
|
||||
reading[0] = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), reading[0]));
|
||||
});
|
||||
$("section.rain .total").html(Math.round(total_rain_today * 10) / 10)
|
||||
var extremes_div = extremesTemplate({extremes: extremes});
|
||||
$('section.extremes').replaceWith(extremes_div);
|
||||
|
||||
jQuery.each(data.rain.history, function(idx, reading) {
|
||||
var date = reading[0].split("-")
|
||||
reading[0] = new Date(Date.UTC(date[0], date[1] - 1, date[2]));
|
||||
});
|
||||
// Populate the charts
|
||||
// Temperature history
|
||||
var count = data.history.length;
|
||||
for(var i = 0; i < count; i++) {
|
||||
// Convert timestamps to Date objects
|
||||
data.history[i][0] = new Date(data.history[i][0]);
|
||||
}
|
||||
var chart = $('.temperature .chart');
|
||||
chart.css('width', chart.width()); // TODO: bind to resize event and redraw
|
||||
var temperatureGraph = new Dygraph(chart[0], data.history, {
|
||||
rollPeriod: 5,
|
||||
showRoller: true,
|
||||
labels: ['Date', 'Inside Temperature', 'Outside Temperature']
|
||||
});
|
||||
$('#today').click(function() {
|
||||
temperatureGraph.updateOptions({
|
||||
dateWindow: dateWindowToday()
|
||||
});
|
||||
});
|
||||
|
||||
jQuery.plot(".rainfall.today.chart", [data.rain.today], {
|
||||
series: {
|
||||
bars: {
|
||||
show: true,
|
||||
barWidth: 1000 * 60 * 60 // 1 hour
|
||||
// Rain
|
||||
var total_rain_today = 0;
|
||||
jQuery.each(data.rain.today, function(idx, reading) {
|
||||
total_rain_today += reading[1];
|
||||
|
||||
// Convert the hour value into a date
|
||||
reading[0] = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), reading[0]));
|
||||
});
|
||||
$("section.rain .total").html(Math.round(total_rain_today * 10) / 10)
|
||||
|
||||
jQuery.each(data.rain.history, function(idx, reading) {
|
||||
var date = reading[0].split("-")
|
||||
reading[0] = new Date(Date.UTC(date[0], date[1] - 1, date[2]));
|
||||
});
|
||||
|
||||
jQuery.plot(".rainfall.today.chart", [data.rain.today], {
|
||||
series: {
|
||||
bars: {
|
||||
show: true,
|
||||
barWidth: 1000 * 60 * 60 // 1 hour
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
mode: "time",
|
||||
min: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())),
|
||||
max: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 23, 59, 59)),
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
mode: "time",
|
||||
min: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())),
|
||||
max: new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 23, 59, 59)),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
jQuery.plot(".rainfall.week.chart", [data.rain.history], {
|
||||
series: {
|
||||
bars: {
|
||||
show: true,
|
||||
barWidth: 1000 * 60 * 60 * 24 // 1 day
|
||||
jQuery.plot(".rainfall.week.chart", [data.rain.history], {
|
||||
series: {
|
||||
bars: {
|
||||
show: true,
|
||||
barWidth: 1000 * 60 * 60 * 24 // 1 day
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
// min: 0,
|
||||
// max: 24
|
||||
mode: "time",
|
||||
minTickSize: [1, "day"]
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
// min: 0,
|
||||
// max: 24
|
||||
mode: "time",
|
||||
minTickSize: [1, "day"]
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
|
Loading…
Reference in a new issue