Files
byuiars-reop-net/mesh/eimeshcore.htm
T

379 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Radio Mobile Coverage – BYU-Idaho Amateur Radio Society</title>
<link rel="stylesheet" href="/style.css" />
<script src="/script.js" defer></script>
<style>
/* OpenLayers & Map Overrides */
.ol-map-container {
position: relative;
width: 100%;
height: 650px;
border-radius: var(--border-radius);
overflow: hidden;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
margin-top: 1rem;
}
.ol-popup {
display: none;
position: absolute;
background-color: var(--bg-color);
color: var(--text-color);
padding: 15px;
border: 1px solid #cccccc;
bottom: 12px;
left: -50px;
border-radius: var(--border-radius);
}
.ol-popup:after, .ol-popup:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after {
border-top-color: var(--bg-color);
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-content {
min-width: 170px;
max-height: 200px;
overflow-x: auto;
}
.ol-popup-closer {
position: absolute;
top: 2px;
right: 2px;
font-size: 120%;
padding: 0 4px;
color: gray;
text-decoration: none;
}
.ol-popup-closer:after {
content: "✕";
}
.ol-mouse-position { top: 8px; right: 8px; position: absolute; }
.ol-scale-line { background: rgba(0,60,136,.3); border-radius: 4px; bottom: 8px; left: 8px; padding: 2px; position: absolute; }
.ol-scale-line-inner { border: 1px solid #eee; border-top: none; color: #eee; font-size: 10px; text-align: center; margin: 1px; padding: 0 2px; }
.ol-control { position: absolute; background-color: rgba(255,255,255,.4); border-radius: 4px; padding: 2px; }
.ol-control:hover { background-color: rgba(255,255,255,.6); }
.ol-zoom { top: .5em; left: .5em; }
.ol-control button { display: block; margin: 1px; padding: 0; color: #fff; font-size: 1.14em; font-weight: 700; text-align: center; height: 1.375em; width: 1.375em; background-color: rgba(0,60,136,.5); border: none; border-radius: 2px; cursor: pointer; }
.ol-zoomslider { position: absolute; top: 4.5em; left: .5em; background: rgba(255,255,255,.4); width: 24px; height: 200px; }
.ol-zoomslider-thumb { position: absolute; background: rgba(0,60,136,.5); border-radius: 2px; cursor: pointer; height: 10px; width: 22px; margin: 3px; }
</style>
<script type="text/javascript">
var map, layers = [], mapkey, mapgrey;
var infowindow, ie, marker, rmap1, rmap2, rmap3, rmap4, mlat, mlon, job;
var ti, link, cover, txt, txtm, icon = 0;
var no = 'N', so = 'S', es = 'E', ws = 'W';
function initialize(lat, lon, zoom, j, mode) {
job = j;
createmapstyles();
switch (job) {
case 0:
map = initmap('map_canvas', 'test', 'ladeg', 'lodeg', 'ladms', 'lodms', mode);
setlltags(lat, lon, 'ladeg', 'lodeg', 'ladms', 'lodms');
icon = 3;
marker = addmarker(map, icon, lat, lon);
break;
case 1:
icon = 4;
map = initmap('map_canvas', 'test', null, null, null, null, mode);
mlat = lat; mlon = lon;
do_overlays();
break;
case 2:
icon = 4;
marker = new Array(); link = new Array(); link2 = new Array(); cover = new Array(); txt = new Array(); txtm = new Array();
map = initmap('map_canvas', 'test', null, null, null, null, mode);
init(true);
multi();
break;
}
setmap(map, lat, lon, zoom);
}
function multi() {
var i;
var s = document.getElementById('sc');
if (s) {
for (i = 1; i < s.length; ++i) cover[i - 1].setVisible(s.options[i].selected);
}
s = document.getElementById('sl');
if (s) {
for (i = 1; i < s.length; ++i) link[i - 1].setVisible(s.options[i].selected);
}
s = document.getElementById('sm');
if (s) {
for (i = 1; i < s.length; ++i) marker[i - 1].setVisible(s.options[i].selected);
}
}
function switchtiles(ind) {
selectmaptiles(map, ind);
}
function findZoom() {
if (document.form1) {
document.form1.m_lat.value = getmarkerlat(marker);
document.form1.m_lon.value = getmarkerlon(marker);
document.form1.m_zoom.value = getmapzoom(map);
}
}
function centerit() {
setmap(map, getmarkerlat(marker), getmarkerlon(marker), getmapzoom(map));
}
function centercursor() {
var lat = getmaplat(map);
var lon = getmaplon(map);
setlltags(lat, lon, 'ladeg', 'lodeg', 'ladms', 'lodms');
setmarker(marker, lat, lon);
}
function initmap(mapdiv, session, latag, lotag, ladms, lodms, src) {
var inter;
if (latag && lotag && ladms && lodms) {
initdrag(latag, lotag, ladms, lodms);
inter = ol.interaction.defaults().extend([new app.Drag()]);
}
if (!src) src = 0;
var map = new ol.Map({
interactions: inter,
layers: layers,
target: mapdiv
});
selectmaptiles(map, src);
map.addControl(new ol.control.ZoomSlider());
return map;
}
function createmapstyles() {
layers[0] = new ol.layer.Tile({
visible: false,
source: new ol.source.OSM({ url: 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png', maxZoom: 19 })
});
layers[1] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({
tileUrlFunction: function (tileCoord) {
var z = tileCoord[0], x = tileCoord[1], y = tileCoord[2];
return 'https://r0.ortho.tiles.virtualearth.net/tiles/r' + quadkey(x, y, z) + '.png?g=1';
}, maxZoom: 19
})
});
layers[2] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({
tileUrlFunction: function (tileCoord) {
var z = tileCoord[0], x = tileCoord[1], y = tileCoord[2];
return 'https://a0.ortho.tiles.virtualearth.net/tiles/a' + quadkey(x, y, z) + '.jpeg?g=1';
}, maxZoom: 19
})
});
layers[3] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({ url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}', maxZoom: 16 })
});
layers[4] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({ url: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}', maxZoom: 16 })
});
layers[5] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({ url: 'https://tile.opentopomap.org/{z}/{x}/{y}.png', maxZoom: 17 })
});
layers[6] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({ url: 'https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', maxZoom: 19 })
});
layers[7] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({ url: 'https://mt.google.com/vt/lyrs=r&x={x}&y={y}&z={z}', maxZoom: 19 })
});
layers[8] = new ol.layer.Tile({
visible: false,
source: new ol.source.XYZ({ url: 'https://mt.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', maxZoom: 19 })
});
}
var quadkey = function (x, y, z) {
var quadKey = [];
for (var i = z; i > 0; i--) {
var digit = '0';
var mask = 1 << (i - 1);
if ((x & mask) != 0) digit++;
if ((y & mask) != 0) { digit++; digit++; }
quadKey.push(digit);
}
return quadKey.join('');
};
function selectmaptiles(map, src) {
for (var i = 0, ii = layers.length; i < ii; ++i) layers[i].setVisible(i == src);
}
function getmaplat(map) {
var c = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
return c[1];
}
function getmaplon(map) {
var c = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
return c[0];
}
function getmapzoom(map) {
return map.getView().getZoom();
}
function setmap(map, lat, lon, z) {
map.setView(new ol.View({
center: ol.proj.transform([lon, lat], 'EPSG:4326', 'EPSG:3857'),
zoom: z, minZoom: 2, maxZoom: 19
}));
}
function addimage(map, src, lamin, lomin, lamax, lomax) {
var c1 = ol.proj.transform([lomin, lamin], 'EPSG:4326', 'EPSG:3857');
var c2 = ol.proj.transform([lomax, lamax], 'EPSG:4326', 'EPSG:3857');
var cx = ol.proj.transform([(lomin + lomax) / 2, (lamin + lamax) / 2], 'EPSG:4326', 'EPSG:3857');
var dx = (c2[0] - c1[0]) / 2;
var dy = (c2[1] - c1[1]) / 2;
c1[0] = cx[0] - dx;
c2[0] = cx[0] + dx;
c1[1] = cx[1] - dy;
c2[1] = cx[1] + dy;
var ov = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: src,
imageExtent: [c1[0], c1[1], c2[0], c2[1]]
})
});
map.addLayer(ov);
return ov;
}
function addmarker(map, iconindex, lat, lon, label, html) {
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326', 'EPSG:3857'))
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1.0],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
opacity: 0.9,
src: ico[iconindex]
}),
text: new ol.style.Text({
font: '12px helvetica,sans-serif',
text: label,
fill: new ol.style.Fill({ color: '#000' }),
stroke: new ol.style.Stroke({ color: '#fff', width: 2 })
})
});
iconFeature.setStyle(iconStyle);
iconFeature.setId(html);
var vectorSource = new ol.source.Vector({ features: [iconFeature] });
var vectorLayer = new ol.layer.Vector({ source: vectorSource });
map.addLayer(vectorLayer);
return vectorLayer;
}
function setlltags(lat, lon, latag, lotag, ladms, lodms) {
var a;
var t = ol.coordinate.toStringHDMS([lon, lat]).split(" ");
if (latag && document.getElementById(latag)) document.getElementById(latag).innerHTML = lat.toFixed(8);
while (lon < -180) lon += 360; while (lon > 180) lon -= 360;
if (lotag && document.getElementById(lotag)) document.getElementById(lotag).innerHTML = lon.toFixed(8);
a = (lat < 0) ? so : no;
if (ladms && document.getElementById(ladms)) document.getElementById(ladms).innerHTML = t[0] + " " + t[1] + " " + t[2] + " " + a;
a = (lon < 0) ? ws : es;
if (lodms && document.getElementById(lodms)) document.getElementById(lodms).innerHTML = t[4] + " " + t[5] + " " + t[6] + " " + a;
}
var ico = [
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAuCAMAAAB6WzuLAAADAFBMVEUAbv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0AbPoAZvAAYOYAWtsAVNMAUc0ATsgATcYATMUATMQAS8QAS8MAS8MAS8MAS8MAS8MAS8MATMMBUcEBVb8BV70BWLoBVa0BT6ABR5IBQooCQIcCPoUDO38GNnIING0NLmsRK2wYMnIjPnsoQn0tRoEySYM1TIU7UYhBW5BIZZhUbp1ZdKBhfKZpha1uirBzjrB2kK9+lLCImLOMmrSPm7WQnLaTn7eYpLmdq7yiscGquMSxv8m4xM69yNPDzdfH0dzK09/N1uHP1+TU2ujY3enb3urg4evj4uzm5O3o5u3q6O7t6+7w7vDy8PH08/P29vX4+Pb6+vj7+/j8/Pn+/vn+/vn///n///j///j///f///j///v///z///7////////////////9///8///+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+9nfC1AAABAHRSTlP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfaoGpAAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAUBJREFUOI2NlD2OwyAQhbmFj0OZZoqIwtooQkuxoXASaWlIE1nu3WyTE83FYsB2MAx4X4f0aebNHwx3xeJHf9PfSqrOFpChOwngTgCtsgSiBefNKi7UI0GMhGYrLvQG6QRvMoGKkJvIgQ/jECsOJNKAXhBFZAkSfUDuqdPIswrIuRgkhGFoy0FCGDaWnTi1LsqpUM6cySJ70T1ZBFdkz5qVyYxGZnYQ9S/ksY8MO3bvU9FtHeknpN66L9e6qhm4+DHWMoEfI3aVZZBhGSo1gZm37qdk2AfxSHGS8LtegC64UdEdnUlC2PjUqDA8PjX6To5DjIzPY+71mvwMl+zs5Zggf2kqYbL/JTlsN78USaqSSCCogEqz/Q4/dkAjjZhlVkvTcmStPE6TIPM8Qb/KiLezTZMhKPlB9nWk19JgHSH0BsTENRFLsv6lAAAAAElFTkSuQmCC",
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAuCAMAAAB6WzuLAAADAFBMVEUReP4ReP4ReP4QeP4Pd/4Ndv4LdP4Jc/4Gcf4DcP4CcP4Bb/4Ab/4Ab/4Ab/4Abv4Abv4Abv4Abv4Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0Abv0AavYAY+sAXOAAWNgAVNEAUcwAT8kATscATcUATMQATMQAS8MAS8MAS8MAS8MAS8MAS8MAS8MAS8MAS8MATMMATMMATMIATcIAUMABVb4BWLwBW7oBXrcCXrICWqsBU6ABSpQBQ4sBQokBQYgCQIcCP4UEPIIFOH0JMnMLLW0NL28PMnIUNnUZOnghQHwnRYAqSIIuS4QyToc2U4o+W5BEYpZKaZpPbp5WdKJceqZng6xvi7BwjbByjrB3kbGBl7KGmbKKmrOMm7ONm7OOm7SPnLWQnbWRnraVormZp7ydrL+hssOnuciqvcuwwc+3x9S/zdrF09/J1uLL1+PN2eTR2+bV3ejZ3+nd4evg4+vj5Ozl5u3l5+3m6e/k6/Dh7vLZ8PTP9Pe7+fu2+vy1+/21+/21+/21+/21+/21+/21+/23+/26+/2//P3H/P3b/f32/v3+//3///z///z///z///v///z///3///7///7////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////1DM8mAAABAHRSTlP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAA//////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApx8BhgAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAVxJREFUOI2F1L2KwzAMAGA/wC2d825+gI5atIUrNORM4Qqe0rvFlGRyZo/lIA/iV7n8R5adVFvgQ7YsKcK/DUE/7EN/qVJV9Q5pqwuCHAIgV3WCaJQyW0OiahgxBWRhSNQBqVBmUYAi5IEx2MxAajwnSQZ6ISpxyhRoJ/LLb0rurCZypUmEc46lEb6mST5cSIY0oqM3OTlGsnzIctnKGXOEBBsvXtubOBcTeHhhgYuASO2FeUMUI+IUkZsXDSFzSTxLG7QwIvDTF50fE9uToIkR+RyeroEDAvectjfkRaUdSwS6R5TQMtCZG4DlP3bfcIWOSkZBOhgTMugEa0kSRPbomCdZ01VITLumqpfcEW0o6G+9jP2/hn+EerX3RMfLHj0IT/V/YYg/944RVVfgE8YoYfCYJqRy0TxOzVL48WkzWyrdqIjL3E/Rrn/ib5MdExJfyXNpjYnVh/DFJxD+xZNmYMqLlMgAAAABJRU5ErkJggg=="
];
</script>
</head>
<body onload="if(typeof initialize === 'function') initialize(43.8231, -111.7924, 11, 1, 0);">
<!-- Announcement Banner -->
<div id="banner" class="banner-bg hidden">
<strong id="banner-title"></strong>: <span id="banner-content"></span>
</div>
<!-- Navigation Bar -->
<nav class="navbar accent-bg">
<div class="nav-container">
<a href="/" class="nav-brand">BYU-I Amateur Radio Society</a>
<!-- Mobile Hamburger Toggle -->
<button id="menu-toggle" class="icon-button mobile-only" aria-label="Toggle Navigation Menu">
<svg id="icon-hamburger" class="icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<svg id="icon-close" class="icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<!-- Desktop Links -->
<div id="desktop-links" class="nav-links desktop-only"></div>
<!-- Desktop Dark Mode Toggle -->
<button class="theme-toggle icon-button desktop-only" aria-label="Toggle Dark Mode">
<svg class="icon icon-sun hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m8.66-8.66h-1M4.34 12H3m15.36 6.36l-.71-.71M6.34 6.34l-.71-.71m12.02 0l-.71.71M6.34 17.66l-.71.71M12 5a7 7 0 100 14 7 7 0 000-14z" />
</svg>
<svg class="icon icon-moon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 009.79 9.79z" />
</svg>
</button>
</div>
<!-- Mobile Dropdown Menu -->
<div id="mobile-menu" class="mobile-menu mobile-only hidden">
<div id="mobile-links"></div>
<button class="theme-toggle mobile-theme-btn" aria-label="Toggle Dark Mode">
<span class="theme-text">🌙 Dark Mode</span>
</button>
</div>
</nav>
<!-- Main Content -->
<main class="main-