mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-02-04 01:04:33 +00:00
Extract common JS into a new project #88
This commit is contained in:
@@ -63,10 +63,6 @@
|
|||||||
<p>This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.</p>
|
<p>This software is dedicated to the memory of Tom G1PJB, SK, a friend and colleague who sadly passed away around the time I started writing it in Autumn 2025. I was looking forward to showing it to you when it was done.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-about").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-about").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|
||||||
|
|||||||
@@ -69,10 +69,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script src="/js/add-spot.js?v=5"></script>
|
<script src="/js/add-spot.js?v=5"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-add-spot").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -168,10 +168,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script src="/js/alerts.js?v=5"></script>
|
<script src="/js/alerts.js?v=5"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-alerts").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -134,10 +134,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=5"></script>
|
<script src="/js/spotsbandsandmap.js?v=5"></script>
|
||||||
<script src="/js/bands.js?v=5"></script>
|
<script src="/js/bands.js?v=5"></script>
|
||||||
|
|||||||
@@ -46,6 +46,11 @@
|
|||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/cjs/tinycolor.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/tinycolor2@1.6.0/cjs/tinycolor.min.js"></script>
|
||||||
|
|
||||||
|
<script src="https://misc.ianrenton.com/jsutils/utils.js?v=5"></script>
|
||||||
|
<script src="https://misc.ianrenton.com/jsutils/storage.js?v=5"></script>
|
||||||
|
<script src="https://misc.ianrenton.com/jsutils/ui-ham.js?v=5"></script>
|
||||||
|
<script src="https://misc.ianrenton.com/jsutils/geo.js?v=5"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
@@ -152,10 +152,6 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/leaflet.geodesic"></script>
|
<script src="https://cdn.jsdelivr.net/npm/leaflet.geodesic"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@joergdietrich/leaflet.terminator@1.1.0/L.Terminator.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@joergdietrich/leaflet.terminator@1.1.0/L.Terminator.min.js"></script>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=5"></script>
|
<script src="/js/spotsbandsandmap.js?v=5"></script>
|
||||||
<script src="/js/map.js?v=5"></script>
|
<script src="/js/map.js?v=5"></script>
|
||||||
|
|||||||
@@ -223,10 +223,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script src="/js/spotsbandsandmap.js?v=5"></script>
|
<script src="/js/spotsbandsandmap.js?v=5"></script>
|
||||||
<script src="/js/spots.js?v=5"></script>
|
<script src="/js/spots.js?v=5"></script>
|
||||||
|
|||||||
@@ -3,10 +3,6 @@
|
|||||||
|
|
||||||
<div id="status-container" class="row row-cols-1 row-cols-md-4 g-4 mt-4"></div>
|
<div id="status-container" class="row row-cols-1 row-cols-md-4 g-4 mt-4"></div>
|
||||||
|
|
||||||
<script src="/js/tools/utils.js?v=5"></script>
|
|
||||||
<script src="/js/tools/storage.js?v=5"></script>
|
|
||||||
<script src="/js/tools/ui-ham.js?v=5"></script>
|
|
||||||
<script src="/js/tools/geo.js?v=5"></script>
|
|
||||||
<script src="/js/common.js?v=5"></script>
|
<script src="/js/common.js?v=5"></script>
|
||||||
<script src="/js/status.js?v=5"></script>
|
<script src="/js/status.js?v=5"></script>
|
||||||
<script>$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav --></script>
|
<script>$(document).ready(function() { $("#nav-link-status").addClass("active"); }); <!-- highlight active page in nav --></script>
|
||||||
|
|||||||
@@ -9,12 +9,18 @@ info:
|
|||||||
The API calls described below allow third-party software to access data from Spothole, and receive data on spots and alerts in a consistent format regardless of the data sources used by Spothole itself. Utility calls are also provided for general data lookups.
|
The API calls described below allow third-party software to access data from Spothole, and receive data on spots and alerts in a consistent format regardless of the data sources used by Spothole itself. Utility calls are also provided for general data lookups.
|
||||||
|
|
||||||
Please note that the data coming out of Spothole is only as good as the data going in. People mis-hear and make typos when spotting callsigns all the time, and there are plenty of areas where Spothole's location data may be inaccurate. If you are doing something where accuracy is important, such as contesting, you should not rely on Spothole's data to fill in any gaps in your log.
|
Please note that the data coming out of Spothole is only as good as the data going in. People mis-hear and make typos when spotting callsigns all the time, and there are plenty of areas where Spothole's location data may be inaccurate. If you are doing something where accuracy is important, such as contesting, you should not rely on Spothole's data to fill in any gaps in your log.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### 1.1
|
||||||
|
|
||||||
|
Added Server-Sent Event API endpoint. Removed band colour and icon information from spots.
|
||||||
contact:
|
contact:
|
||||||
email: ian@ianrenton.com
|
email: ian@ianrenton.com
|
||||||
license:
|
license:
|
||||||
name: The Unlicense
|
name: The Unlicense
|
||||||
url: https://unlicense.org/#the-unlicense
|
url: https://unlicense.org/#the-unlicense
|
||||||
version: v1
|
version: v1.1
|
||||||
servers:
|
servers:
|
||||||
- url: https://spothole.app/api/v1
|
- url: https://spothole.app/api/v1
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
//
|
|
||||||
// GEOGRAPHIC UTILITY FUNCTIONS
|
|
||||||
// Great Circle calculation, Maidenhead grid calcs, etc.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Calculate great circle bearing between two lat/lon points.
|
|
||||||
function calcBearing(lat1, lon1, lat2, lon2) {
|
|
||||||
lat1 *= Math.PI / 180;
|
|
||||||
lon1 *= Math.PI / 180;
|
|
||||||
lat2 *= Math.PI / 180;
|
|
||||||
lon2 *= Math.PI / 180;
|
|
||||||
var lonDelta = lon2 - lon1;
|
|
||||||
var y = Math.sin(lonDelta) * Math.cos(lat2);
|
|
||||||
var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lonDelta);
|
|
||||||
var bearing = Math.atan2(y, x);
|
|
||||||
bearing = bearing * (180 / Math.PI);
|
|
||||||
if ( bearing < 0 ) { bearing += 360; }
|
|
||||||
return bearing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a Maidenhead grid reference of arbitrary precision to the lat/long of the centre point of the square.
|
|
||||||
// Returns null if the grid format is invalid.
|
|
||||||
function latLonForGridCentre(grid) {
|
|
||||||
let [lat, lon, latCellSize, lonCellSize] = latLonForGridSWCornerPlusSize(grid);
|
|
||||||
if (lat != null && lon != null && latCellSize != null && lonCellSize != null) {
|
|
||||||
return [lat + latCellSize / 2.0, lon + lonCellSize / 2.0];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a Maidenhead grid reference of arbitrary precision to lat/long, including in the result the size of the
|
|
||||||
// lowest grid square. This is a utility method used by the main methods that return the centre, southwest, and
|
|
||||||
// northeast coordinates of a grid square.
|
|
||||||
// The return type is always an array of size 4. The elements in it are null if the grid format is invalid.
|
|
||||||
function latLonForGridSWCornerPlusSize(grid) {
|
|
||||||
// Make sure we are in upper case so our maths works. Case is arbitrary for Maidenhead references
|
|
||||||
grid = grid.toUpperCase();
|
|
||||||
|
|
||||||
// Return null if our Maidenhead string is invalid or too short
|
|
||||||
let len = grid.length;
|
|
||||||
if (len <= 0 || (len % 2) !== 0) {
|
|
||||||
return [null, null, null, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
let lat = 0.0; // aggregated latitude
|
|
||||||
let lon = 0.0; // aggregated longitude
|
|
||||||
let latCellSize = 10; // Size in degrees latitude of the current cell. Starts at 20 and gets smaller as the calculation progresses
|
|
||||||
let lonCellSize = 20; // Size in degrees longitude of the current cell. Starts at 20 and gets smaller as the calculation progresses
|
|
||||||
let latCellNo; // grid latitude cell number this time
|
|
||||||
let lonCellNo; // grid longitude cell number this time
|
|
||||||
|
|
||||||
// Iterate through blocks (two-character sections)
|
|
||||||
for (let block = 0; block * 2 < len; block += 1) {
|
|
||||||
if (block % 2 === 0) {
|
|
||||||
// Letters in this block
|
|
||||||
lonCellNo = grid.charCodeAt(block * 2) - 'A'.charCodeAt(0);
|
|
||||||
latCellNo = grid.charCodeAt(block * 2 + 1) - 'A'.charCodeAt(0);
|
|
||||||
// Bail if the values aren't in range. Allowed values are A-R (0-17) for the first letter block, or
|
|
||||||
// A-X (0-23) thereafter.
|
|
||||||
let maxCellNo = (block === 0) ? 17 : 23;
|
|
||||||
if (latCellNo < 0 || latCellNo > maxCellNo || lonCellNo < 0 || lonCellNo > maxCellNo) {
|
|
||||||
return [null, null, null, null];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Numbers in this block
|
|
||||||
lonCellNo = parseInt(grid.charAt(block * 2));
|
|
||||||
latCellNo = parseInt(grid.charAt(block * 2 + 1));
|
|
||||||
// Bail if the values aren't in range 0-9..
|
|
||||||
if (latCellNo < 0 || latCellNo > 9 || lonCellNo < 0 || lonCellNo > 9) {
|
|
||||||
return [null, null, null, null];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aggregate the angles
|
|
||||||
lat += latCellNo * latCellSize;
|
|
||||||
lon += lonCellNo * lonCellSize;
|
|
||||||
|
|
||||||
// Reduce the cell size for the next block, unless we are on the last cell.
|
|
||||||
if (block * 2 < len - 2) {
|
|
||||||
// Still have more work to do, so reduce the cell size
|
|
||||||
if (block % 2 === 0) {
|
|
||||||
// Just dealt with letters, next block will be numbers so cells will be 1/10 the current size
|
|
||||||
latCellSize = latCellSize / 10.0;
|
|
||||||
lonCellSize = lonCellSize / 10.0;
|
|
||||||
} else {
|
|
||||||
// Just dealt with numbers, next block will be letters so cells will be 1/24 the current size
|
|
||||||
latCellSize = latCellSize / 24.0;
|
|
||||||
lonCellSize = lonCellSize / 24.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset back to (-180, -90) where the grid starts
|
|
||||||
lon -= 180.0;
|
|
||||||
lat -= 90.0;
|
|
||||||
|
|
||||||
// Return nulls on maths errors
|
|
||||||
if (isNaN(lat) || isNaN(lon) || isNaN(latCellSize) || isNaN(lonCellSize)) {
|
|
||||||
return [null, null, null, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [lat, lon, latCellSize, lonCellSize];
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
//
|
|
||||||
// LOCAL STORAGE FUNCTIONS
|
|
||||||
// Generic functions for saving the state of HTML inputs to local storage, and restoring them
|
|
||||||
//
|
|
||||||
|
|
||||||
let useLocalStorage = true;
|
|
||||||
|
|
||||||
// Save settings to local storage. Suppressed if "use local storage" is false.
|
|
||||||
function saveSettings() {
|
|
||||||
if (useLocalStorage) {
|
|
||||||
// Find all storeable UI elements, store a key of "element id:property name" mapped to the value of that
|
|
||||||
// property. For a checkbox, that's the "checked" property.
|
|
||||||
$(".storeable-checkbox").each(function() {
|
|
||||||
localStorage.setItem("#" + $(this)[0].id + ":checked", JSON.stringify($(this)[0].checked));
|
|
||||||
});
|
|
||||||
$(".storeable-select").each(function() {
|
|
||||||
localStorage.setItem("#" + $(this)[0].id + ":value", JSON.stringify($(this)[0].value));
|
|
||||||
});
|
|
||||||
$(".storeable-text").each(function() {
|
|
||||||
localStorage.setItem("#" + $(this)[0].id + ":value", JSON.stringify($(this)[0].value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load settings from local storage and set up the filter selectors. Suppressed if "use local storage" is false.
|
|
||||||
function loadSettings() {
|
|
||||||
if (useLocalStorage) {
|
|
||||||
// Find all local storage entries and push their data to the corresponding UI element
|
|
||||||
Object.keys(localStorage).forEach(function(key) {
|
|
||||||
if (key.startsWith("#") && key.includes(":")) {
|
|
||||||
// Split the key back into an element ID and a property
|
|
||||||
var split = key.split(":");
|
|
||||||
$(split[0]).prop(split[1], JSON.parse(localStorage.getItem(key)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,377 +0,0 @@
|
|||||||
//
|
|
||||||
// USER INTERFACE FUNCTIONS (AMATEUR RADIO)
|
|
||||||
// Functions providing colour schemes for ham radio bands, SIG icons etc.
|
|
||||||
//
|
|
||||||
|
|
||||||
const BAND_COLOR_SCHEMES = {
|
|
||||||
"PSK Reporter": {
|
|
||||||
"2200m": "#ff4500",
|
|
||||||
"600m": "#1e90ff",
|
|
||||||
"160m": "#7cfc00",
|
|
||||||
"80m": "#e550e5",
|
|
||||||
"60m": "#00008b",
|
|
||||||
"40m": "#5959ff",
|
|
||||||
"30m": "#62d962",
|
|
||||||
"20m": "#f2c40c",
|
|
||||||
"17m": "#f2f261",
|
|
||||||
"15m": "#cca166",
|
|
||||||
"12m": "#b22222",
|
|
||||||
"11m": "#00ff00",
|
|
||||||
"10m": "#ff69b4",
|
|
||||||
"6m": "#FF0000",
|
|
||||||
"5m": "#e0e0e0",
|
|
||||||
"4m": "#cc0044",
|
|
||||||
"2m": "#FF1493",
|
|
||||||
"1.25m": "#CCFF00",
|
|
||||||
"70cm": "#999900",
|
|
||||||
"23cm": "#5AB8C7",
|
|
||||||
"2.4GHz": "#FF7F50",
|
|
||||||
"5.8GHz": "#cc0099",
|
|
||||||
"10GHz": "#696969",
|
|
||||||
"24GHz": "#f3edc6",
|
|
||||||
"47GHz": "#ffe786",
|
|
||||||
"76GHz": "#baf9d8"
|
|
||||||
},
|
|
||||||
"PSK Reporter (Adjusted)": {
|
|
||||||
"2200m": "#ff4500",
|
|
||||||
"600m": "#1e90ff",
|
|
||||||
"160m": "#7cfc00",
|
|
||||||
"80m": "#b33fb3",
|
|
||||||
"60m": "#00008b",
|
|
||||||
"40m": "#5959ff",
|
|
||||||
"30m": "#62d962",
|
|
||||||
"20m": "#f2c40c",
|
|
||||||
"17m": "#f2f261",
|
|
||||||
"15m": "#cca166",
|
|
||||||
"12m": "#b22222",
|
|
||||||
"11m": "#00ff00",
|
|
||||||
"10m": "#ff7eb4",
|
|
||||||
"6m": "#FF0000",
|
|
||||||
"5m": "#e0e0e0",
|
|
||||||
"4m": "#cc0044",
|
|
||||||
"2m": "#FF1493",
|
|
||||||
"1.25m": "#CCFF00",
|
|
||||||
"70cm": "#999900",
|
|
||||||
"23cm": "#5AB8C7",
|
|
||||||
"2.4GHz": "#FF7F50",
|
|
||||||
"5.8GHz": "#cc0099",
|
|
||||||
"10GHz": "#696969",
|
|
||||||
"24GHz": "#f3edc6",
|
|
||||||
"47GHz": "#ffe786",
|
|
||||||
"76GHz": "#baf9d8"
|
|
||||||
},
|
|
||||||
"RBN": {
|
|
||||||
"2200m": "#000000",
|
|
||||||
"600m": "#aaaaaa",
|
|
||||||
"160m": "#ffe000",
|
|
||||||
"80m": "#093F00",
|
|
||||||
"60m": "#777777",
|
|
||||||
"40m": "#ffa500",
|
|
||||||
"30m": "#ff0000",
|
|
||||||
"20m": "#800080",
|
|
||||||
"17m": "#0000ff",
|
|
||||||
"15m": "#444444",
|
|
||||||
"12m": "#00ffff",
|
|
||||||
"11m": "#000000",
|
|
||||||
"10m": "#ff00ff",
|
|
||||||
"6m": "#ffc0cb",
|
|
||||||
"5m": "#000000",
|
|
||||||
"4m": "#a276ff",
|
|
||||||
"2m": "#92FF7F",
|
|
||||||
"1.25m": "#000000",
|
|
||||||
"70cm": "#000000",
|
|
||||||
"23cm": "#000000",
|
|
||||||
"2.4GHz": "#000000",
|
|
||||||
"5.8GHz": "#000000",
|
|
||||||
"10GHz": "#000000",
|
|
||||||
"24GHz": "#000000",
|
|
||||||
"47GHz": "#000000",
|
|
||||||
"76GHz": "#000000"
|
|
||||||
},
|
|
||||||
"Ham Rainbow": {
|
|
||||||
"2200m": "#8e4f37",
|
|
||||||
"600m": "#8e4f37",
|
|
||||||
"160m": "#8e3737",
|
|
||||||
"80m": "#da2f93",
|
|
||||||
"60m": "#792fda",
|
|
||||||
"40m": "#2f4bda",
|
|
||||||
"30m": "#2fdad2",
|
|
||||||
"20m": "#68da2f",
|
|
||||||
"17m": "#dad52f",
|
|
||||||
"15m": "#da832f",
|
|
||||||
"12m": "#da5c2f",
|
|
||||||
"11m": "#8e8e8e",
|
|
||||||
"10m": "#da2f2f",
|
|
||||||
"6m": "#8e377a",
|
|
||||||
"5m": "#8e8e8e",
|
|
||||||
"4m": "#42378e",
|
|
||||||
"2m": "#37748e",
|
|
||||||
"1.25m": "#8e8e8e",
|
|
||||||
"70cm": "#378e65",
|
|
||||||
"23cm": "#8e8e37",
|
|
||||||
"2.4GHz": "#8e6037",
|
|
||||||
"5.8GHz": "#8e6037",
|
|
||||||
"10GHz": "#8e6037",
|
|
||||||
"24GHz": "#8e6037",
|
|
||||||
"47GHz": "#8e6037",
|
|
||||||
"76GHz": "#8e6037"
|
|
||||||
},
|
|
||||||
"Ham Rainbow (Reverse)": {
|
|
||||||
"2200m": "#42378e",
|
|
||||||
"600m": "#42378e",
|
|
||||||
"160m": "#8e377a",
|
|
||||||
"80m": "#da2f2f",
|
|
||||||
"60m": "#da5c2f",
|
|
||||||
"40m": "#da832f",
|
|
||||||
"30m": "#dad52f",
|
|
||||||
"20m": "#68da2f",
|
|
||||||
"17m": "#2fdad2",
|
|
||||||
"15m": "#2f4bda",
|
|
||||||
"12m": "#792fda",
|
|
||||||
"11m": "#8e8e8e",
|
|
||||||
"10m": "#da2f93",
|
|
||||||
"6m": "#8e3737",
|
|
||||||
"5m": "#8e8e8e",
|
|
||||||
"4m": "#8e4f37",
|
|
||||||
"2m": "#8e6037",
|
|
||||||
"1.25m": "#8e8e8e",
|
|
||||||
"70cm": "#8e8e37",
|
|
||||||
"23cm": "#378e65",
|
|
||||||
"2.4GHz": "#37748e",
|
|
||||||
"5.8GHz": "#37748e",
|
|
||||||
"10GHz": "#37748e",
|
|
||||||
"24GHz": "#37748e",
|
|
||||||
"47GHz": "#37748e",
|
|
||||||
"76GHz": "#37748e",
|
|
||||||
},
|
|
||||||
"Kate Morley": {
|
|
||||||
"2200m": "#817",
|
|
||||||
"600m": "#817",
|
|
||||||
"160m": "#817",
|
|
||||||
"80m": "#a35",
|
|
||||||
"60m": "#c66",
|
|
||||||
"40m": "#e94",
|
|
||||||
"30m": "#ed0",
|
|
||||||
"20m": "#9d5",
|
|
||||||
"17m": "#4d8",
|
|
||||||
"15m": "#2cb",
|
|
||||||
"12m": "#0bc",
|
|
||||||
"11m": "#09c",
|
|
||||||
"10m": "#09c",
|
|
||||||
"6m": "#36b",
|
|
||||||
"5m": "#36b",
|
|
||||||
"4m": "#36b",
|
|
||||||
"2m": "#36b",
|
|
||||||
"1.25m": "#36b",
|
|
||||||
"70cm": "#639",
|
|
||||||
"23cm": "#639",
|
|
||||||
"2.4GHz": "#639",
|
|
||||||
"5.8GHz": "#639",
|
|
||||||
"10GHz": "#639",
|
|
||||||
"24GHz": "#639",
|
|
||||||
"47GHz": "#639",
|
|
||||||
"76GHz": "#639",
|
|
||||||
},
|
|
||||||
"ColorBrewer": {
|
|
||||||
"2200m": "#54278f",
|
|
||||||
"600m": "#756bb1",
|
|
||||||
"160m": "#9e9ac8",
|
|
||||||
"80m": "#cbc9e2",
|
|
||||||
"60m": "#08519c",
|
|
||||||
"40m": "#3182bd",
|
|
||||||
"30m": "#6baed6",
|
|
||||||
"20m": "#bdd7e7",
|
|
||||||
"17m": "#006d2c",
|
|
||||||
"15m": "#31a354",
|
|
||||||
"12m": "#74c476",
|
|
||||||
"11m": "#bae4b3",
|
|
||||||
"10m": "#a63603",
|
|
||||||
"6m": "#e6550d",
|
|
||||||
"5m": "#fd8d3c",
|
|
||||||
"4m": "#fdbe85",
|
|
||||||
"2m": "#a50f15",
|
|
||||||
"1.25m": "#de2d26",
|
|
||||||
"70cm": "#fb6a4a",
|
|
||||||
"23cm": "#fcae91",
|
|
||||||
"2.4GHz": "#636363",
|
|
||||||
"5.8GHz": "#636363",
|
|
||||||
"10GHz": "#969696",
|
|
||||||
"24GHz": "#969696",
|
|
||||||
"47GHz": "#cccccc",
|
|
||||||
"76GHz": "#cccccc",
|
|
||||||
},
|
|
||||||
"IWantHue": {
|
|
||||||
"2200m": "#409271",
|
|
||||||
"600m": "#b03ce1",
|
|
||||||
"160m": "#50c640",
|
|
||||||
"80m": "#d545b7",
|
|
||||||
"60m": "#99b936",
|
|
||||||
"40m": "#7260db",
|
|
||||||
"30m": "#60af57",
|
|
||||||
"20m": "#d54788",
|
|
||||||
"17m": "#58c79f",
|
|
||||||
"15m": "#e2462a",
|
|
||||||
"12m": "#49b1d3",
|
|
||||||
"11m": "#df872f",
|
|
||||||
"10m": "#506bb0",
|
|
||||||
"6m": "#c6a639",
|
|
||||||
"5m": "#9554a3",
|
|
||||||
"4m": "#36783c",
|
|
||||||
"2m": "#da405b",
|
|
||||||
"1.25m": "#657527",
|
|
||||||
"70cm": "#8c97e2",
|
|
||||||
"23cm": "#b44f2f",
|
|
||||||
"2.4GHz": "#d386c8",
|
|
||||||
"5.8GHz": "#aaac66",
|
|
||||||
"10GHz": "#9d4760",
|
|
||||||
"24GHz": "#90672c",
|
|
||||||
"47GHz": "#e08086",
|
|
||||||
"76GHz": "#dc9769",
|
|
||||||
},
|
|
||||||
"IWantHue (Color Blind)": {
|
|
||||||
"2200m": "#bf9e3d",
|
|
||||||
"600m": "#9d2fec",
|
|
||||||
"160m": "#79df39",
|
|
||||||
"80m": "#d445db",
|
|
||||||
"60m": "#5dd175",
|
|
||||||
"40m": "#814dd8",
|
|
||||||
"30m": "#d7ce2f",
|
|
||||||
"20m": "#657af1",
|
|
||||||
"17m": "#8cc34a",
|
|
||||||
"15m": "#d635aa",
|
|
||||||
"12m": "#6cbd80",
|
|
||||||
"11m": "#b860c1",
|
|
||||||
"10m": "#e48721",
|
|
||||||
"6m": "#686ccc",
|
|
||||||
"5m": "#d44e2b",
|
|
||||||
"4m": "#51b3db",
|
|
||||||
"2m": "#d74058",
|
|
||||||
"1.25m": "#56c5ad",
|
|
||||||
"70cm": "#d0478d",
|
|
||||||
"23cm": "#708940",
|
|
||||||
"2.4GHz": "#c380c2",
|
|
||||||
"5.8GHz": "#cab775",
|
|
||||||
"10GHz": "#7a7fc2",
|
|
||||||
"24GHz": "#b87148",
|
|
||||||
"47GHz": "#bd678c",
|
|
||||||
"76GHz": "#c3666b",
|
|
||||||
},
|
|
||||||
"Mokole": {
|
|
||||||
"2200m": "#8b4513",
|
|
||||||
"600m": "#006400",
|
|
||||||
"160m": "#808000",
|
|
||||||
"80m": "#483d8b",
|
|
||||||
"60m": "#5f9ea0",
|
|
||||||
"40m": "#000080",
|
|
||||||
"30m": "#9acd32",
|
|
||||||
"20m": "#8b008b",
|
|
||||||
"17m": "#ff0000",
|
|
||||||
"15m": "#ff8c00",
|
|
||||||
"12m": "#ffd700",
|
|
||||||
"11m": "#7fff00",
|
|
||||||
"10m": "#8a2be2",
|
|
||||||
"6m": "#00ff7f",
|
|
||||||
"5m": "#dc143c",
|
|
||||||
"4m": "#00bfff",
|
|
||||||
"2m": "#0000ff",
|
|
||||||
"1.25m": "#d8bfd8",
|
|
||||||
"70cm": "#ff00ff",
|
|
||||||
"23cm": "#1e90ff",
|
|
||||||
"2.4GHz": "#db7093",
|
|
||||||
"5.8GHz": "#f0e68c",
|
|
||||||
"10GHz": "#ff1493",
|
|
||||||
"24GHz": "#ffa07a",
|
|
||||||
"47GHz": "#ee82ee",
|
|
||||||
"76GHz": "#7fffd4",
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let bandColorScheme = "PSK Reporter (Adjusted)";
|
|
||||||
|
|
||||||
// Set the band colour scheme. Returns true if successful, false if the requested scheme was not known
|
|
||||||
function setBandColorScheme(scheme) {
|
|
||||||
let ret = BAND_COLOR_SCHEMES[scheme]
|
|
||||||
if (ret) {
|
|
||||||
bandColorScheme = scheme;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of known bands
|
|
||||||
function getKnownBands() {
|
|
||||||
return Array.from(Object.keys(BAND_COLOR_SCHEMES[bandColorScheme]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of available band colour schemes
|
|
||||||
function getAvailableBandColorSchemes() {
|
|
||||||
return Array.from(Object.keys(BAND_COLOR_SCHEMES));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Band name to colour (in the current colour scheme). If the band is unknown, black will be returned.
|
|
||||||
function bandToColor(band) {
|
|
||||||
let col = (band != null) ? BAND_COLOR_SCHEMES[bandColorScheme][band] : null;
|
|
||||||
if (col) {
|
|
||||||
return col;
|
|
||||||
} else {
|
|
||||||
return "black";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Band name to contrast colour (in the current colour scheme). This is either black or white, contrasting as well as
|
|
||||||
// possible with the band colour. If the band is unknown, white will be returned.
|
|
||||||
function bandToContrastColor(band) {
|
|
||||||
let tc = tinycolor(bandToColor(band));
|
|
||||||
return tc.isLight() ? "black" : "white";
|
|
||||||
}
|
|
||||||
|
|
||||||
const MODE_TYPE_COLOR_SCHEMES = {
|
|
||||||
"CW": "green",
|
|
||||||
"PHONE": "red",
|
|
||||||
"DATA": "blue"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode type (CW, PHONE, DATA) to colour. If the mode type is unknown, black will be returned.
|
|
||||||
function modeTypeToColor(modeType) {
|
|
||||||
let col = (modeType != null) ? MODE_TYPE_COLOR_SCHEMES[modeType.toUpperCase()] : null;
|
|
||||||
if (col) {
|
|
||||||
return col;
|
|
||||||
} else {
|
|
||||||
return "black";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SIG_ICONS = {
|
|
||||||
"POTA": "fa-tree",
|
|
||||||
"SOTA": "fa-mountain-sun",
|
|
||||||
"WWFF": "fa-seedling",
|
|
||||||
"GMA": "fa-person-hiking",
|
|
||||||
"WWBOTA": "fa-radiation",
|
|
||||||
"HEMA": "fa-mound",
|
|
||||||
"IOTA": "fa-umbrella-beach",
|
|
||||||
"MOTA": "fa-fan",
|
|
||||||
"ARLHS": "fa-tower-observation",
|
|
||||||
"ILLW": "fa-tower-observation",
|
|
||||||
"SIOTA": "fa-wheat-awn",
|
|
||||||
"WCA": "fa-chess-rook",
|
|
||||||
"ZLOTA": "fa-kiwi-bird",
|
|
||||||
"WOTA": "fa-w",
|
|
||||||
"BOTA": "fa-water",
|
|
||||||
"KRMNPA": "fa-earth-oceania",
|
|
||||||
"WAB": "fa-table-cells-large",
|
|
||||||
"WAI": "fa-table-cells-large",
|
|
||||||
"TOTA": "fa-toilet"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Font Awesome icon for a given SIG. If the SIG is unknown, the provided default symbol will be returned
|
|
||||||
function sigToIcon(sig, defaultIcon) {
|
|
||||||
let col = (sig != null) ? SIG_ICONS[sig.toUpperCase()] : null;
|
|
||||||
if (col) {
|
|
||||||
return col;
|
|
||||||
} else {
|
|
||||||
return defaultIcon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of known SIGs
|
|
||||||
function getKnownSIGs() {
|
|
||||||
return Array.from(Object.keys(SIG_ICONS));
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
//
|
|
||||||
// GENERAL UTILITY FUNCTIONS
|
|
||||||
// String manipulation etc.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Utility function to escape HTML characters from a string.
|
|
||||||
function escapeHtml(str) {
|
|
||||||
if (typeof str !== 'string') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const escapeCharacter = (match) => {
|
|
||||||
switch (match) {
|
|
||||||
case '&': return '&';
|
|
||||||
case '<': return '<';
|
|
||||||
case '>': return '>';
|
|
||||||
case '"': return '"';
|
|
||||||
case '\'': return ''';
|
|
||||||
case '`': return '`';
|
|
||||||
default: return match;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return str.replace(/[&<>"'`]/g, escapeCharacter);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user