You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PackageHelper/www/assets/js/toolbox_weather.js

296 lines
12 KiB
JavaScript

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
function ftoc(f) {
return (f - 32) * 5 / 9;
}
function loadWeather(reload) {
if (typeof reload == "undefined") {
reload = false;
} else {
reload = reload == true;
}
if (userPosition.coords.accuracy > 99999) {
app.dialog.alert("Couldn't find your location. Wait for a GPS signal and try again.", "Error");
return;
}
var requestfinished = false;
var weatherdialogopen = false;
$.ajax({
url: SETTINGS.weatherapi,
dataType: 'json',
data: {
// Round the numbers off to increase user privacy
// Accuracy with two decimal places is ~1.1km/0.6mi
latitude: userPosition.coords.latitude.toFixed(2),
longitude: userPosition.coords.longitude.toFixed(2)
},
timeout: 15 * 1000,
success: function (resp) {
if (weatherdialogopen) {
app.dialog.close();
weatherdialogopen = false;
}
requestfinished = true;
if (resp.status == "OK") {
//
// Summary tab
//
var mintemp = (getStorage("units") == "metric" ? Math.round(ftoc(resp.summary.temp.min)) + " °C" : Math.round(resp.summary.temp.min) + " °F");
var maxtemp = (getStorage("units") == "metric" ? Math.round(ftoc(resp.summary.temp.max)) + " °C" : Math.round(resp.summary.temp.max) + " °F");
$("#summarylowtemp").html(mintemp);
$("#summaryhightemp").html(maxtemp);
$("#summaryprecipchance").text(Math.round(resp.summary.precipitation.chance * 100.0) + "% chance");
if (getStorage("units") == "metric") {
$("#summarywindspeed").text(Math.round(resp.summary.windspeed * 1.609344) + " km/h");
} else {
$("#summarywindspeed").text(Math.round(resp.summary.windspeed) + " mph");
}
if (SETTINGS.weathericons.includes(resp.summary.icon)) {
$("#summaryweathericon").attr("src", "assets/images/weather-" + resp.summary.icon + ".svg");
} else {
$("#summaryweathericon").attr("src", "assets/images/weather-none.svg");
}
$("#summary-forecast-location").text(resp.location_name);
$("#summary-forecast-info").text("Forecast covers the next " + resp.summary.forecast_hours + " hours (until " + timestampToTimeString(resp.summary.forecast_until) + ").");
$("#summary-forecast-creditlink").text(resp.source.text);
$("#summary-forecast-creditlink").attr("onclick", "openExternalBrowser('" + resp.source.url + "')");
//
// Now tab
//
var temp = (getStorage("units") == "metric" ? Math.round(ftoc(resp.now.temp)) + " °C" : Math.round(resp.now.temp) + " °F");
var feelslike = (getStorage("units") == "metric" ? Math.round(ftoc(resp.now.feelslike)) + " °C" : Math.round(resp.now.feelslike) + " °F");
$("#nowtemp").html(temp);
$("#nowfeelslike").html(feelslike);
if (SETTINGS.weathericons.includes(resp.now.icon)) {
$("#nowweathericon").attr("src", "assets/images/weather-" + resp.now.icon + ".svg");
} else {
$("#nowweathericon").attr("src", "assets/images/weather-none.svg");
}
app.gauge.get('#nowuvindexgauge').update({
value: Math.min(resp.now.uv_index, 10) / 10,
valueText: resp.now.uv_index,
borderColor: colorThemeNameToHex(uvIndexToColor(resp.now.uv_index))
});
if (getStorage("units") == "metric") {
$("#nowwindspeed").text(Math.round(resp.now.windspeed * 1.609344) + " km/h");
} else {
$("#nowwindspeed").text(Math.round(resp.now.windspeed) + " mph");
}
$("#nowwinddirection").text(degreesToCardinal(resp.now.winddirection));
var minutelydata = [];
var maxprecip = 0;
for (var i = 0; i < resp.today.minutely.length; i++) {
precip = resp.today.minutely[i].precip;
if (getStorage("units") == "metric") {
precip = precip * 25.4;
}
minutelydata[i] = {
x: new Date(resp.today.minutely[i].time * 1000),
y: precip
};
if (precip > maxprecip) {
maxprecip = precip;
}
}
if (maxprecip > 0) {
// only make rain chart if there's rain
var precipChart = new Chart(document.getElementById('precipchart'), {
type: "line",
data: {
datasets: [
{
fill: true,
data: minutelydata,
borderWidth: 0,
spanGaps: true,
backgroundColor: "#03A9F4",
borderColor: "#03A9F4"
}
]
},
options: {
responsive: true,
elements: {
point: {
radius: 0
}
},
scales: {
xAxes: [{
type: 'time',
display: true,
scaleLabel: {
display: false
},
gridLines: {
display: true,
drawBorder: false
},
time: {
unit: 'minute',
stepSize: 5,
displayFormats: {
minute: 'h:mm',
hour: 'hA'
}
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true
},
gridLines: {
display: false,
drawBorder: false
},
ticks: {
min: 0,
max: Math.round(maxprecip),
stepSize: (Math.round(maxprecip) / 2),
callback: function (value, index, values) {
if (getStorage("units") == "metric") {
return value + ' mm';
} else {
return value + ' in';
}
}
}
}]
},
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
}
//
// Forecast tab
//
forecastItems = [];
for (var i = 0; i < resp.forecast.length; i++) {
var low = (getStorage("units") == "metric" ? Math.round(ftoc(resp.forecast[i].temp.min)) : Math.round(resp.forecast[i].temp.min));
var high = (getStorage("units") == "metric" ? Math.round(ftoc(resp.forecast[i].temp.max)) + " &deg;C" : Math.round(resp.forecast[i].temp.max) + " &deg;F");
var precipcolor = precipChanceToColor(resp.forecast[i].precipitation.chance);
forecastItems.push({
day: (i == 0 ? "Today" : formatTimestamp('l', resp.forecast[i].date)),
temps: low + " to " + high,
uv_index: resp.forecast[i].uv_index,
uv_color: uvIndexToColor(resp.forecast[i].uv_index),
precip_chance: Math.round(resp.forecast[i].precipitation.chance * 100),
precip_color: precipcolor
});
}
forecastItemTemplate = '<li>'
+ '<div class="item-content">'
+ ' <div class="item-inner">'
+ ' <div class="item-title">'
+ ' <div class="item-header">{{day}}</div>'
+ ' {{temps}}'
+ ' <br /><span class="padding-half forecast-uv-badge badge color-{{uv_color}}"><i class="fas fa-sun fa-fw"></i> {{uv_index}}</span>'
+ ' &nbsp; <span class="padding-half forecast-precip-badge badge color-{{precip_color}}"><i class="fas fa-tint fa-fw"></i> {{precip_chance}}%</span>'
+ ' </div>'
+ ' </div>'
+ '</div>'
+ '</li>';
forecastVirtualList = app.virtualList.create({
el: "#forecast-list",
items: forecastItems,
itemTemplate: forecastItemTemplate
});
} else {
app.dialog.alert(resp.message, "Error");
}
},
error: function (jqXHR, status, errorThrown) {
if (weatherdialogopen) {
app.dialog.close();
weatherdialogopen = false;
}
requestfinished = true;
app.dialog.alert("There was a network issue while checking the weather. Please try again.", "Error");
}
});
// Open a loading message if there's a delay or we're reloading
if (reload) {
app.dialog.preloader("Checking Weather...");
weatherdialogopen = true;
} else {
setTimeout(function () {
if (!requestfinished) {
app.dialog.preloader("Checking Weather...");
weatherdialogopen = true;
}
}, 1000);
}
}
$("#app").on("click", "#weather-forecast .forecast-uv-badge", function () {
app.toast.show({
text: "<i class='fas fa-info-circle'></i> UV index",
position: "bottom",
destroyOnClose: true,
closeTimeout: 1000 * 3
});
});
$("#app").on("click", "#weather-forecast .forecast-precip-badge", function () {
app.toast.show({
text: "<i class='fas fa-info-circle'></i> Chance of precipitation",
position: "bottom",
destroyOnClose: true,
closeTimeout: 1000 * 3
});
});
function uvIndexToColor(index) {
var uvcolor = "green";
if (index >= 11) {
uvcolor = "purple";
} else if (index >= 8) {
uvcolor = "red";
} else if (index >= 6) {
uvcolor = "orange";
} else if (index >= 3) {
uvcolor = "yellow";
}
return uvcolor;
}
function precipChanceToColor(chance) {
var color = "lightblue";
if (chance > 0.8) {
color = "gray";
} else if (chance > 0.2) {
color = "blue";
} else {
color = "lightblue";
}
return color;
}