586 lines
18 KiB
HTML
586 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>RLX Weather Camera List</title>
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
margin: 0;
|
|
background-color: #f0f0f0;
|
|
color: #333;
|
|
}
|
|
|
|
#menu {
|
|
background-color: #003366;
|
|
color: white;
|
|
width: 180px;
|
|
height: 100%;
|
|
position: fixed;
|
|
padding: 5px;
|
|
box-shadow: 2px 0 5px rgba(0,0,0,0.3);
|
|
transition: width 0.3s;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
#menu.collapsed {
|
|
width: 40px;
|
|
}
|
|
|
|
#menu.collapsed .menu-content {
|
|
display: none;
|
|
}
|
|
|
|
#toggle-menu {
|
|
cursor: pointer;
|
|
padding: 8px;
|
|
margin-bottom: 10px;
|
|
text-align: center;
|
|
background-color: #002244;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
#menu a {
|
|
color: white;
|
|
text-decoration: none;
|
|
display: block;
|
|
margin: 8px 0;
|
|
padding: 8px;
|
|
transition: background 0.3s;
|
|
}
|
|
|
|
#menu a:hover {
|
|
background-color: #005599;
|
|
}
|
|
|
|
#container {
|
|
margin-left: 180px; /* Adds space for the menu */
|
|
padding: 12px;
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(275px, 1fr));
|
|
gap: 5px;
|
|
transition: margin-left 0.3s;
|
|
}
|
|
|
|
#container.expanded {
|
|
margin-left: 180px;
|
|
}
|
|
|
|
#container.collapsed {
|
|
margin-left: 40px;
|
|
}
|
|
|
|
.image {
|
|
position: relative;
|
|
background-color: #fff;
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
|
|
transition: transform 0.3s;
|
|
}
|
|
|
|
.image:hover {
|
|
transform: scale(1.04);
|
|
z-index:9999;
|
|
}
|
|
|
|
.image img {
|
|
width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
}
|
|
|
|
.label {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
background-color: rgba(0, 0, 0, 0.7);
|
|
color: #fff;
|
|
padding: 5px 10px;
|
|
font-size: 12px;
|
|
width: 100%;
|
|
}
|
|
|
|
select, input[type=number] {
|
|
width: calc(100% - 20px);
|
|
padding: 8px 10px;
|
|
margin: 10px 0;
|
|
border: 1px solid #ccc;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
label {
|
|
margin: 10px 0 5px;
|
|
display: block;
|
|
}
|
|
|
|
input[type="checkbox"] {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="menu">
|
|
<div id="toggle-menu" onclick="toggleMenu()">☰</div>
|
|
<div class="menu-content">
|
|
<h2>Menu</h2>
|
|
<a href="map.html">Map</a>
|
|
<a href="db.html">Wunderground obs</a>
|
|
<a href="5min.html">5m ASOS obs</a>
|
|
<a href="outage.html">Power Outages</a>
|
|
<a href="https://docs.google.com/forms/d/1-2rTBkNyyBVe08G1vN1hcSOEOvvLUcS1Vs2SmmaudlU" target="_blank">Questions / Comments</a>
|
|
|
|
<label for="filters">Filters:</label>
|
|
<label for="states">States:</label>
|
|
<select id="filters" name="filters" onchange="filter()" multiple>
|
|
<option selected="selected" value="WV">WV</option>
|
|
<option selected="selected" value="KY">KY</option>
|
|
<option selected="selected" value="VA">VA</option>
|
|
<option selected="selected" value="OH">OH</option>
|
|
</select>
|
|
|
|
<label for="cwa">
|
|
<input type="checkbox" id="cwa" name="cwa" value="RLX" checked onchange="filter()"> RLX only
|
|
</label>
|
|
|
|
<label>Misc Filters:</label>
|
|
<label for="hydro">
|
|
<input type="checkbox" id="hydro" name="hydro" value="true" onchange="filter()"> Hydro
|
|
</label>
|
|
<label for="airport">
|
|
<input type="checkbox" id="airport" name="airport" value="true" onchange="filter()"> Airports
|
|
</label>
|
|
|
|
<label for="sort">Sorting:</label>
|
|
<select id="sort" name="sort" onchange="sortcams()">
|
|
<option selected="selected" value="elevd">Elev Descending</option>
|
|
<option value="eleva">Elev Ascending</option>
|
|
<option value="countyaz">County A-Z</option>
|
|
<option value="countyza">County Z-A</option>
|
|
<option value="westeast">West to East</option>
|
|
<option value="northsouth">North to South</option>
|
|
</select>
|
|
|
|
<label for="numberofimages">Frames for Loops</label>
|
|
<input type="number" id="numberofimages" name="numberofimages" value="20" onchange="setcams()">
|
|
|
|
<p>Archive: 240 hours</p>
|
|
<p id="camcount"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="container">
|
|
<!-- Dynamic content will be populated here -->
|
|
</div>
|
|
|
|
<script>
|
|
// Function to set a cookie
|
|
function setCookie(name, value, days) {
|
|
var expires = "";
|
|
if (days) {
|
|
var date = new Date();
|
|
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
expires = "; expires=" + date.toUTCString();
|
|
}
|
|
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
|
}
|
|
|
|
// Function to get a cookie
|
|
function getCookie(name) {
|
|
var nameEQ = name + "=";
|
|
var ca = document.cookie.split(';');
|
|
for(var i=0;i < ca.length;i++) {
|
|
var c = ca[i];
|
|
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
|
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// Toggle menu function
|
|
function toggleMenu() {
|
|
var menu = document.getElementById('menu');
|
|
var container = document.getElementById('container');
|
|
if (menu.classList.contains('collapsed')) {
|
|
menu.classList.remove('collapsed');
|
|
container.classList.remove('collapsed');
|
|
container.classList.add('expanded');
|
|
setCookie('menuCollapsed', 'false', 365);
|
|
} else {
|
|
menu.classList.add('collapsed');
|
|
container.classList.remove('expanded');
|
|
container.classList.add('collapsed');
|
|
setCookie('menuCollapsed', 'true', 365);
|
|
}
|
|
}
|
|
|
|
// Load settings from cookies
|
|
function loadSettings() {
|
|
// Load menu state
|
|
var menuCollapsed = getCookie('menuCollapsed');
|
|
if (menuCollapsed === 'true') {
|
|
document.getElementById('menu').classList.add('collapsed');
|
|
document.getElementById('container').classList.add('collapsed');
|
|
document.getElementById('container').classList.remove('expanded');
|
|
} else {
|
|
document.getElementById('menu').classList.remove('collapsed');
|
|
document.getElementById('container').classList.add('expanded');
|
|
document.getElementById('container').classList.remove('collapsed');
|
|
}
|
|
|
|
// Load number of images
|
|
var savedImages = getCookie('numberofimages');
|
|
if (savedImages) {
|
|
document.getElementById('numberofimages').value = savedImages;
|
|
camimages = savedImages;
|
|
} else {
|
|
camimages = 20;
|
|
}
|
|
|
|
// Load states filter
|
|
var savedStates = getCookie('statesFilter');
|
|
if (savedStates) {
|
|
var statesArray = JSON.parse(savedStates);
|
|
var statesSelect = document.getElementById('filters');
|
|
for (var i = 0; i < statesSelect.options.length; i++) {
|
|
statesSelect.options[i].selected = statesArray.includes(statesSelect.options[i].value);
|
|
}
|
|
}
|
|
|
|
// Load RLX checkbox
|
|
var savedRLX = getCookie('rLXOnly');
|
|
if (savedRLX !== null) {
|
|
document.getElementById('cwa').checked = (savedRLX === 'true');
|
|
}
|
|
|
|
// Load hydro checkbox
|
|
var savedHydro = getCookie('hydroFilter');
|
|
if (savedHydro !== null) {
|
|
document.getElementById('hydro').checked = (savedHydro === 'true');
|
|
}
|
|
|
|
// Load airport checkbox
|
|
var savedAirport = getCookie('airportFilter');
|
|
if (savedAirport !== null) {
|
|
document.getElementById('airport').checked = (savedAirport === 'true');
|
|
}
|
|
|
|
// Load sort option
|
|
var savedSort = getCookie('sortOption');
|
|
if (savedSort) {
|
|
document.getElementById('sort').value = savedSort;
|
|
}
|
|
}
|
|
|
|
// Save settings to cookies
|
|
function saveSettings() {
|
|
// Save number of images
|
|
setCookie('numberofimages', document.getElementById('numberofimages').value, 365);
|
|
|
|
// Save states filter
|
|
var statesSelect = document.getElementById('filters');
|
|
var selectedStates = [];
|
|
for (var i = 0; i < statesSelect.options.length; i++) {
|
|
if (statesSelect.options[i].selected) {
|
|
selectedStates.push(statesSelect.options[i].value);
|
|
}
|
|
}
|
|
setCookie('statesFilter', JSON.stringify(selectedStates), 365);
|
|
|
|
// Save RLX checkbox
|
|
setCookie('rLXOnly', document.getElementById('cwa').checked, 365);
|
|
|
|
// Save hydro checkbox
|
|
setCookie('hydroFilter', document.getElementById('hydro').checked, 365);
|
|
|
|
// Save airport checkbox
|
|
setCookie('airportFilter', document.getElementById('airport').checked, 365);
|
|
|
|
// Save sort option
|
|
setCookie('sortOption', document.getElementById('sort').value, 365);
|
|
}
|
|
|
|
camimages = 20;
|
|
function setcams() {
|
|
camimages = document.getElementById("numberofimages").value;
|
|
saveSettings(); // Save when changed
|
|
refreshcams();
|
|
}
|
|
|
|
var showcams = [];
|
|
|
|
function filter() {
|
|
saveSettings(); // Save when filter changes
|
|
showcams = [];
|
|
var x = document.getElementById("filters");
|
|
options = x.getElementsByTagName('option');
|
|
var y = document.getElementById("cwa").checked;
|
|
var hydroFilter = document.getElementById("hydro").checked;
|
|
var airportFilter = document.getElementById("airport").checked;
|
|
values = [];
|
|
for (var i=options.length; i--;) {
|
|
if (options[i].selected) values.push(options[i].value)
|
|
}
|
|
|
|
console.log('Hydro filter checked:', hydroFilter); // Debug
|
|
console.log('Airport filter checked:', airportFilter); // Debug
|
|
for(var k in allcams) {
|
|
// Check state filter
|
|
var stateMatch = false;
|
|
for(var l in values) {
|
|
if (allcams[k].state == values[l]) {
|
|
stateMatch = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check RLX filter
|
|
var rlxMatch = true;
|
|
if (y) {
|
|
rlxMatch = ('RLX' == allcams[k].cwa);
|
|
}
|
|
|
|
// Check hydro filter
|
|
var hydroMatch = true;
|
|
if (hydroFilter) {
|
|
// Only show if hydro is true when filter is selected
|
|
console.log('Camera:', allcams[k].camid, 'hydro value:', allcams[k].hydro); // Debug
|
|
// Handle cases where hydro might be undefined or not present
|
|
// If hydro field doesn't exist or is not true, don't show
|
|
hydroMatch = (allcams[k].hasOwnProperty('hydro') && allcams[k].hydro === true);
|
|
} else {
|
|
// When hydro filter is not selected, show all (both true and false)
|
|
hydroMatch = true;
|
|
}
|
|
|
|
// Check airport filter
|
|
var airportMatch = true;
|
|
if (airportFilter) {
|
|
// Only show if airport is true when filter is selected
|
|
console.log('Camera:', allcams[k].camid, 'airport value:', allcams[k].airport); // Debug
|
|
// Handle cases where airport might be undefined or not present
|
|
// If airport field doesn't exist or is not true, don't show
|
|
airportMatch = (allcams[k].hasOwnProperty('airport') && allcams[k].airport === true);
|
|
} else {
|
|
// When airport filter is not selected, show all (both true and false)
|
|
airportMatch = true;
|
|
}
|
|
|
|
if (stateMatch && rlxMatch && hydroMatch && airportMatch) {
|
|
showcams.push(allcams[k].camid);
|
|
}
|
|
|
|
// Hide all first
|
|
document.getElementById(allcams[k].camid).style.display = 'none';
|
|
}
|
|
|
|
// Show matching cams
|
|
for(var o in showcams) {
|
|
document.getElementById(showcams[o]).style.display = '';
|
|
}
|
|
console.log('Number of cams to show:', showcams.length); // Debug
|
|
|
|
// Show a message if no cameras match
|
|
if (showcams.length === 0) {
|
|
console.log('No cameras match the current filters');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function sortcams() {
|
|
saveSettings(); // Save when sort changes
|
|
var sortcams = allcams;
|
|
var x = document.getElementById("sort");
|
|
options = x.getElementsByTagName('option');
|
|
values = [];
|
|
for (var i=options.length; i--;) {
|
|
|
|
if (options[i].selected) {
|
|
switch(options[i].value) {
|
|
case "elevd":
|
|
sortcams.sort(function(a,b) {
|
|
return b.elevation-a.elevation
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
break;
|
|
case "eleva":
|
|
sortcams.sort(function(a,b) {
|
|
return a.elevation-b.elevation
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
// code block
|
|
break;
|
|
case "westeast":
|
|
sortcams.sort(function(a,b) {
|
|
if (a.lon > b.lon) {
|
|
return -1;
|
|
}
|
|
if (b.lon > a.lon) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
|
|
|
|
|
|
})
|
|
break;
|
|
case "northsouth":
|
|
sortcams.sort(function(a,b) {
|
|
if (a.lat> b.lat) {
|
|
return -1;
|
|
}
|
|
if (b.lat > a.lat) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
|
|
|
|
|
|
})
|
|
break;
|
|
case "countyza":
|
|
sortcams.sort(function(a,b) {
|
|
if (a.county > b.county) {
|
|
return -1;
|
|
}
|
|
if (b.county > a.county) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
|
|
|
|
|
|
})
|
|
break;
|
|
case "countyaz":
|
|
sortcams.sort(function(a,b) {
|
|
if (a.county > b.county) {
|
|
return 1;
|
|
}
|
|
if (b.county > a.county) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
|
|
|
|
})
|
|
break;
|
|
default:
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
for (var ii in sortcams) {
|
|
//console.log(sortcams[ii].camid);
|
|
//var xx = document.getElementsByTagName("Figure");
|
|
var x = document.getElementById(sortcams[ii].camid);
|
|
x.style.order=ii
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Load settings when the page loads
|
|
window.onload = function() {
|
|
loadSettings();
|
|
$.getJSON('cam.php', function(data) {
|
|
var wild = Math.random();
|
|
allcams = data;
|
|
console.log('Camera data:', data); // Debug: log camera data
|
|
|
|
// Check if hydro field exists in any camera
|
|
var hasHydroField = false;
|
|
for (var i in data) {
|
|
if (data[i].hasOwnProperty('hydro')) {
|
|
hasHydroField = true;
|
|
break;
|
|
}
|
|
}
|
|
console.log('Does camera data have hydro field?', hasHydroField);
|
|
|
|
for (var i in data) {
|
|
var div = document.createElement('div');
|
|
var a = document.createElement('a');
|
|
div.className = "image";
|
|
div.id = data[i].camid;
|
|
var img = document.createElement('img');
|
|
img.src = 'camdata/' + data[i].camid + "/latest.jpg" //?" + wild;
|
|
a.href = 'one.php?camid=' + data[i].camid + '&camimages=' + camimages;
|
|
a.target = "_blank";
|
|
a.appendChild(img);
|
|
div.appendChild(a);
|
|
var span = document.createElement('span');
|
|
span.className = 'label';
|
|
span.innerHTML = data[i].description + ' / ' + data[i].county + ' ' + data[i].state + ' / ' + data[i].elevation + ' ft';
|
|
div.appendChild(span);
|
|
document.getElementById('container').appendChild(div);
|
|
}
|
|
filter();
|
|
sortcams(); // Apply saved sort
|
|
$.getJSON('camapi.php?camdb', function(data){
|
|
document.getElementById("camcount").textContent = "Total Images: " + data[0].count;
|
|
});
|
|
});
|
|
};
|
|
|
|
function refreshcams() {
|
|
|
|
|
|
$.getJSON('cam.php', function(data){
|
|
var wild = Math.random();
|
|
//console.log(data);
|
|
for(var i in data){
|
|
|
|
var updatefigure = document.getElementById(data[i].camid);
|
|
if (updatefigure != null) {
|
|
if(updatefigure.hasChildNodes()) {
|
|
var children = updatefigure.childNodes;
|
|
for (var m = 0; m < children.length; m++) {
|
|
children[m].href = 'one.php?camid=' + data[i].camid + '&camimages=' + camimages;
|
|
if (children[m].nodeName == 'A') {
|
|
children[m].firstElementChild.src = 'camdata/' + data[i].camid + "/latest.jpg"//?" + wild
|
|
//children[m].firstElementChild.src = 'camdata/' + data[i].lastimage;
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}}
|
|
});
|
|
$.getJSON('camapi.php?camdb', function(data){
|
|
document.getElementById("camcount").textContent = "Total Images: " + data[0].count;
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
window.setInterval(function() {
|
|
refreshcams();
|
|
}, 30000);
|
|
</script>
|
|
</body>
|
|
</html>
|