360 lines
15 KiB
HTML
360 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>RLX Ver Helper</title>
|
|
|
|
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.1/themes/smoothness/jquery-ui.css">
|
|
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
|
|
<!-- Make sure CSS is loaded before JS that might interact with the DOM -->
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
|
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js" integrity="sha256-6XMVI0zB8cRzfZjqKcD01PBsAy3FlDASrlC8SxCpInY=" crossorigin="anonymous"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.4.2/chroma.min.js" integrity="sha512-zInFF17qBFVvvvFpIfeBzo7Tj7+rQxLeTJDmbxjBz5/zIr89YVbTNelNhdTT+/DCrxoVzBeUPVFJsczKbB7sew==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
|
|
<script src="https://unpkg.com/file-saver@2.0.5/dist/FileSaver.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.js" integrity="sha512-wUa0ktp10dgVVhWdRVfcUO4vHS0ryT42WOEcXjVVF2+2rcYBKTY7Yx7JCEzjWgPV+rj2EDUr8TwsoWF6IoIOPg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
|
<script src="https://cdn.rawgit.com/hayeswise/Leaflet.PointInPolygon/v1.0.0/wise-leaflet-pip.js"></script>
|
|
|
|
<style type="text/css">
|
|
body {
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
html, body {
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
|
|
#mapid {
|
|
height: 95%;
|
|
/* background: none !important; */ /* Consider if !important is truly needed */
|
|
}
|
|
|
|
#bottombar {
|
|
/* height: 98%; */
|
|
}
|
|
|
|
.box {
|
|
position: absolute;
|
|
top: 225px;
|
|
z-index: 9999;
|
|
text-align: center;
|
|
width: 250px;
|
|
left: 10%;
|
|
margin-left: -75px; /* half of the width */
|
|
}
|
|
|
|
.box2 {
|
|
position: absolute;
|
|
top: 500px;
|
|
z-index: 9999;
|
|
text-align: center;
|
|
width: 250px;
|
|
left: 10%;
|
|
margin-left: -75px; /* half of the width */
|
|
}
|
|
|
|
input[type=number] {
|
|
width: 50px;
|
|
}
|
|
|
|
input[type=text] {
|
|
width: 150px;
|
|
}
|
|
|
|
.legend {
|
|
line-height: 18px;
|
|
color: #555;
|
|
}
|
|
|
|
.legend i {
|
|
width: 15px;
|
|
height: 15px;
|
|
float: left;
|
|
margin-right: 8px;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.info {
|
|
padding: 6px 8px;
|
|
font: 14px/16px Arial, Helvetica, sans-serif;
|
|
background: white;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.info h4 {
|
|
margin: 0 0 5px;
|
|
color: #777;
|
|
}
|
|
|
|
#slider-2 {
|
|
position: absolute;
|
|
left: 20px;
|
|
top: 200px;
|
|
width: 300px;
|
|
}
|
|
|
|
#timeforsaveimages {
|
|
position: absolute;
|
|
left: 20px;
|
|
bottom: 20px;
|
|
color: black;
|
|
font-size: 30px;
|
|
}
|
|
|
|
#stats {
|
|
/* Style for stats if needed */
|
|
}
|
|
|
|
.my-label {
|
|
font-size: 10px; /* Note: 6px is very small */
|
|
/* font-weight: bold; */
|
|
/* background-color: transparent; */
|
|
border: 0px solid #ccc;
|
|
border-radius: 1px;
|
|
padding: 1px 2px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="box">
|
|
<div id="toggle">
|
|
<button id="archive" onclick="resetmap()">Reset Map</button><br>
|
|
Left click on zone to increment up, right click on zone to reset zone
|
|
</div>
|
|
</div>
|
|
<div id="slider-2"></div>
|
|
<div class="box2">
|
|
<div id="changelog">
|
|
</div>
|
|
</div>
|
|
|
|
<div id="mapid"></div>
|
|
|
|
<script>
|
|
var update_position_timeout = null;
|
|
|
|
function resetmap() {
|
|
$.get({
|
|
url: 'main.php?service=ver&reset=potato',
|
|
success: function () {
|
|
geoJSONcounties.setStyle({ fillColor: 'red' }); // Reset visually immediately
|
|
loadlsr(); // Reload data from server
|
|
},
|
|
error: function (xhr, error) {
|
|
console.error("Error resetting map:", error); // Log error
|
|
alert('Unable to reset map state, please refresh page');
|
|
}
|
|
});
|
|
}
|
|
|
|
// --- Leaflet Map Initialization ---
|
|
var mymap = L.map('mapid', {
|
|
zoomDelta: 0.25,
|
|
zoomSnap: 0.25, // Using 0.25 to match zoomDelta often makes sense
|
|
doubleClickZoom: false // *** THIS DISABLES DOUBLE CLICK ZOOM ***
|
|
}).setView([38.508, -81.652480], 8.0);
|
|
|
|
var geoJSONcounties = L.geoJSON(false, {
|
|
onEachFeature: function (feature, layer) {
|
|
// Use feature.properties.name or similar if available and more descriptive than shortname
|
|
layer.bindTooltip(feature.properties.shortname || 'Unnamed Zone', { permanent: true, direction: 'center', className: 'my-label' });
|
|
|
|
layer.on({
|
|
contextmenu: function (e) {
|
|
L.DomEvent.stopPropagation(e); // Prevent map context menu if any
|
|
L.DomEvent.preventDefault(e); // Prevent browser context menu
|
|
clickdown(feature, layer, e);
|
|
},
|
|
click: function (e) {
|
|
clickup(feature, layer, e);
|
|
},
|
|
});
|
|
},
|
|
style: function (feature) {
|
|
return {
|
|
fillColor: 'red', // Default color
|
|
color: 'navy',
|
|
weight: 3,
|
|
opacity: 1,
|
|
fillOpacity: 0.50
|
|
};
|
|
}
|
|
}).addTo(mymap);
|
|
|
|
|
|
function getColorValue(color) {
|
|
switch (String(color).toLowerCase()) { // Add String() for safety
|
|
case 'red': return 0;
|
|
case 'yellow': return 1;
|
|
case 'green': return 2;
|
|
default: return 0; // Default to red if color is unexpected
|
|
}
|
|
}
|
|
|
|
function vercolor(d) {
|
|
if (d == 0) return 'red';
|
|
if (d == 1) return 'yellow';
|
|
if (d >= 2) return 'green'; // Use >= 2 to catch any higher values
|
|
return 'red'; // Default color if d is unexpected (e.g., null, undefined, < 0)
|
|
}
|
|
|
|
|
|
function clickup(feature, layer, e) {
|
|
var zone = feature.properties.state_zone;
|
|
var currentLsrValue = getColorValue(layer.options.fillColor);
|
|
var newLsr = currentLsrValue + 1;
|
|
// Optional: Add logic to cap the max value if needed (e.g., if (newLsr > 2) newLsr = 2;)
|
|
|
|
$.get({
|
|
url: `main.php?service=ver&lsrs=potato&zone=${zone}&lsr=${newLsr}&dir=1`, // dir=1 seems specific to 'up'
|
|
success: function () {
|
|
layer.setStyle({ fillColor: vercolor(newLsr) });
|
|
// No need to call loadlsr() here, the server state is updated,
|
|
// and the visual state is updated directly. loadlsr() will refresh periodically anyway.
|
|
},
|
|
error: function (xhr, error) {
|
|
console.error("Error updating zone (up):", error);
|
|
alert('Unable to update zone, please try again or refresh.');
|
|
// Optional: Revert style if update fails?
|
|
// layer.setStyle({ fillColor: vercolor(currentLsrValue) });
|
|
}
|
|
});
|
|
}
|
|
|
|
function clickdown(feature, layer, e) {
|
|
var zone = feature.properties.state_zone;
|
|
// On right-click (contextmenu), reset the zone to 0 (red)
|
|
var newLsr = 0; // Reset to red
|
|
|
|
$.get({
|
|
url: `main.php?service=ver&lsrs=potato&zone=${zone}&lsr=${newLsr}`, // No dir needed? Or specific dir for reset?
|
|
success: function () {
|
|
layer.setStyle({ fillColor: vercolor(newLsr) });
|
|
// No need to call loadlsr() here
|
|
},
|
|
error: function (xhr, error) {
|
|
console.error("Error updating zone (down/reset):", error);
|
|
alert('Unable to reset zone, please try again or refresh.');
|
|
// Optional: Revert style if update fails?
|
|
// layer.setStyle({ fillColor: vercolor(getColorValue(layer.options.fillColor)) }); // Revert to original before click
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
function loadlsr() {
|
|
// Clear existing timeout *before* making the new request
|
|
if (update_position_timeout) {
|
|
clearTimeout(update_position_timeout); // Use clearTimeout for setTimeout
|
|
update_position_timeout = null; // Best practice to nullify after clearing
|
|
}
|
|
|
|
$.getJSON('https://wx.stoat.org/main.php?service=ver&lsrslist=potato')
|
|
.done(function (data) {
|
|
if (data && data.length > 0) {
|
|
var zoneData = {};
|
|
// Create a lookup map for efficiency
|
|
for (var i in data) {
|
|
if (data[i] && data[i].zone !== undefined && data[i].lsr !== undefined) {
|
|
zoneData[data[i].zone] = data[i].lsr;
|
|
}
|
|
}
|
|
|
|
geoJSONcounties.eachLayer(function (layer) {
|
|
var zone = layer.feature.properties.state_zone;
|
|
if (zoneData.hasOwnProperty(zone)) {
|
|
layer.setStyle({ fillColor: vercolor(zoneData[zone]) });
|
|
} else {
|
|
// Optional: Set a default color if zone not in data?
|
|
// layer.setStyle({ fillColor: 'grey' }); // Example default
|
|
}
|
|
});
|
|
} else {
|
|
// No data or empty data, maybe reset all to default?
|
|
console.log("No LSR data received or data is empty. Setting zones to default red.");
|
|
geoJSONcounties.setStyle({ fillColor: 'red' });
|
|
}
|
|
|
|
// Schedule the next update *after* the current one succeeded
|
|
update_position_timeout = setTimeout(loadlsr, 3000); // Re-schedule
|
|
})
|
|
.fail(function (jqXHR, textStatus, errorThrown) {
|
|
console.error("Failed to load LSR data:", textStatus, errorThrown);
|
|
// Optionally, you might want to retry after a longer delay or stop polling
|
|
// For now, let's schedule the next attempt as usual, but log the error
|
|
update_position_timeout = setTimeout(loadlsr, 5000); // Maybe wait longer after failure
|
|
});
|
|
}
|
|
|
|
|
|
// var countiesjson = 'rlxtest.json'; // Local testing
|
|
var countiesjson = 'https://wx.stoat.org/main.php?service=ver'; // Production endpoint
|
|
|
|
function initial_county_load() {
|
|
geoJSONcounties.clearLayers();
|
|
|
|
$.getJSON(countiesjson)
|
|
.done(function (data) {
|
|
if(data && data.features) { // Basic check if data looks like GeoJSON
|
|
geoJSONcounties.addData(data);
|
|
geoJSONcounties.bringToBack();
|
|
loadlsr(); // Load the initial LSR states after counties are drawn
|
|
} else {
|
|
console.error("Received invalid GeoJSON data for counties.");
|
|
alert("Error: Could not load county boundaries.");
|
|
}
|
|
})
|
|
.fail(function (jqXHR, textStatus, errorThrown) {
|
|
console.error("Failed to load initial county GeoJSON:", textStatus, errorThrown);
|
|
alert("Fatal Error: Could not load county boundaries. Please refresh the page.");
|
|
});
|
|
}
|
|
|
|
|
|
// --- Base Layers ---
|
|
var Esri_WorldStreetMap = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {
|
|
attribution: 'Tiles © Esri'
|
|
});
|
|
|
|
var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
|
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
|
});
|
|
|
|
var Esri_WorldTopoMap = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', {
|
|
attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community'
|
|
});
|
|
|
|
var CartoDB_Positron = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
|
subdomains: 'abcd',
|
|
maxZoom: 20
|
|
});
|
|
|
|
var USGS_USImageryTopo = L.tileLayer('https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryTopo/MapServer/tile/{z}/{y}/{x}', {
|
|
maxZoom: 20,
|
|
attribution: 'Tiles courtesy of the <a href="https://usgs.gov/">U.S. Geological Survey</a>'
|
|
});
|
|
|
|
var baselayers = {
|
|
"Black and White": CartoDB_Positron,
|
|
"Esri Street Map": Esri_WorldStreetMap,
|
|
"Esri Satellite": Esri_WorldImagery,
|
|
"Esri Topo": Esri_WorldTopoMap,
|
|
"USGS Sat/Topo": USGS_USImageryTopo,
|
|
};
|
|
|
|
L.control.layers(baselayers, null, { collapsed: false }).addTo(mymap);
|
|
|
|
CartoDB_Positron.addTo(mymap); // Set default base layer
|
|
|
|
// --- Initial Load ---
|
|
initial_county_load(); // Load counties first, then load LSR data
|
|
|
|
</script>
|
|
</body>
|
|
</html> |