mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
First pass of the new style of band panel #48
This commit is contained in:
@@ -162,76 +162,64 @@ div#bands-container {
|
|||||||
overscroll-behavior-x: none;
|
overscroll-behavior-x: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bandCol {
|
#bands-table {
|
||||||
min-width: 8em;
|
min-width: 100%;
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
overflow-y: clip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bandColHeader {
|
#bands-table th {
|
||||||
flex: 0 1 auto;
|
width: 20%;
|
||||||
|
min-width: 12em;
|
||||||
|
padding: 0.5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 0.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bandColMiddle {
|
#bands-table td {
|
||||||
flex: 1 1 auto;
|
width: 20%;
|
||||||
margin-left: 3px;
|
min-width: 12em;
|
||||||
border-left: 2px dotted var(--text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bandColMiddle ul {
|
div.band-container {
|
||||||
display: table;
|
height: 62em;
|
||||||
table-layout: fixed;
|
width: 20%;
|
||||||
|
min-width: 12em;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.band-markers {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
position: absolute;
|
||||||
padding: 0;
|
top: 0;
|
||||||
-moz-box-sizing: border-box;
|
left: 0;
|
||||||
box-sizing: border-box;
|
z-index: 13;
|
||||||
border-left: 2px dotted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bandColMiddle ul li {
|
div.band-spots {
|
||||||
display: table-row;
|
width: 100%;
|
||||||
line-height: 0.5em;
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*noinspection CssUnusedSymbol*/
|
canvas.band-lines-canvas {
|
||||||
div.bandColMiddle ul li.withSpots {
|
width: 5em;
|
||||||
line-height: 1em;
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bandColMiddle ul li span {
|
div.band-spot {
|
||||||
display: table-cell;
|
position: absolute;
|
||||||
vertical-align: middle;
|
left: 5em;
|
||||||
}
|
padding: 0 0.25em;
|
||||||
|
background-color: white;
|
||||||
div.bandColSpot {
|
|
||||||
display: block;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 3px;
|
cursor: default;
|
||||||
background: lightyellow;
|
|
||||||
margin: 0.1em 2em 0.1em 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.bandColSpot {
|
|
||||||
vertical-align: bottom;
|
|
||||||
display: inline !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't wrap frequencies */
|
|
||||||
span.bandColSpotFreq {
|
|
||||||
white-space: nowrap;
|
|
||||||
display: inline !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.bandColSpotMode {
|
|
||||||
padding-left: 0.5em;
|
|
||||||
font-size: 0.8em;
|
|
||||||
line-height: 0.4em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
// A couple of constants that must match what's in CSS. We need to know them before the content actually renders, so we
|
||||||
|
// can't just ask the elements themselves for their dimensions.
|
||||||
|
BAND_COLUMN_HEIGHT_EM = 62;
|
||||||
|
BAND_COLUMN_CANVAS_WIDTH_EM = 4;
|
||||||
|
BAND_COLUMN_FONT_SIZE = 16;
|
||||||
|
BAND_COLUMN_HEIGHT_PX = BAND_COLUMN_HEIGHT_EM * BAND_COLUMN_FONT_SIZE;
|
||||||
|
BAND_COLUMN_CANVAS_WIDTH_PX = BAND_COLUMN_CANVAS_WIDTH_EM * BAND_COLUMN_FONT_SIZE;
|
||||||
|
|
||||||
// Load spots and populate the bands display.
|
// Load spots and populate the bands display.
|
||||||
function loadSpots() {
|
function loadSpots() {
|
||||||
$.getJSON('/api/v1/spots' + buildQueryString(), function(jsonData) {
|
$.getJSON('/api/v1/spots' + buildQueryString(), function(jsonData) {
|
||||||
@@ -28,9 +36,9 @@ function buildQueryString() {
|
|||||||
// Update the bands display
|
// Update the bands display
|
||||||
function updateBands() {
|
function updateBands() {
|
||||||
// Stop here if nothing to display
|
// Stop here if nothing to display
|
||||||
var bandsPanel = $("#bands-container");
|
var bandsContainer = $("#bands-container");
|
||||||
if (spots.length === 0) {
|
if (spots.length === 0) {
|
||||||
bandsPanel.html("<div class='alert alert-danger' role='alert'>No spots match your filters.</div>");
|
bandsContainer.html("<div class='alert alert-danger' role='alert'>No spots match your filters.</div>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,73 +59,78 @@ function updateBands() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Build up HTML content for each band
|
// Build up table content for each band
|
||||||
let html = "";
|
var table = $('<table id="bands-table">').append('<thead><tr></tr></thead><tbody><tr></tr></tbody>');
|
||||||
const columnWidthPercent = Math.max(30, 100 / bandToSpots.size);
|
|
||||||
let columnIndex = 0;
|
|
||||||
bandToSpots.forEach(function (spotList, bandName) {
|
bandToSpots.forEach(function (spotList, bandName) {
|
||||||
// Get the colours for the band from the first spot, and prepare the header
|
// Get the colours for the band from the first spot, and prepare the header
|
||||||
html += "<div class='bandCol' style='width:" + columnWidthPercent + "%'>";
|
table.find('thead tr').append(`<th style='background-color:${spotList[0].band_color}; color:${spotList[0].band_contrast_color}'>${spotList[0].band}</th>`);
|
||||||
html += "<div class='bandColHeader' style='background-color:" + spotList[0].band_color + "; color:" + spotList[0].band_contrast_color + "'>" + spotList[0].band + "</div>";
|
|
||||||
html += "<div class='bandColMiddle'>";
|
|
||||||
|
|
||||||
// Get the band data to fetch start and end frequencies
|
// Get the band data to fetch start and end frequencies
|
||||||
let band = options["bands"].filter(function (b) {
|
let band = options["bands"].filter(function (b) {
|
||||||
return b.name === bandName;
|
return b.name === bandName;
|
||||||
})[0];
|
})[0];
|
||||||
// Start printing the band
|
|
||||||
|
// Print the frequency band markers. This is 41 steps to divide the band evenly into 40 markers. One in every
|
||||||
|
// four will show the actual frequency, the others will just be dashes.
|
||||||
|
bandMarkersDiv = $('<div class="band-markers">');
|
||||||
const freqStep = (band.end_freq - band.start_freq) / 40.0;
|
const freqStep = (band.end_freq - band.start_freq) / 40.0;
|
||||||
html += "<ul>";
|
|
||||||
html += "<li><span>-</span></li>";
|
|
||||||
|
|
||||||
// Do 40 steps down the band
|
|
||||||
for (let i = 0; i <= 40; i++) {
|
for (let i = 0; i <= 40; i++) {
|
||||||
|
if (i % 4 === 0) {
|
||||||
// Work out if there are any spots in this step
|
bandMarkersDiv.append("—" + ((band.start_freq + i * freqStep)/1000000).toFixed(3) + "<br/>");
|
||||||
const freqStepStart = band.start_freq + i * freqStep;
|
} else if (i % 4 === 2) {
|
||||||
const freqStepEnd = freqStepStart + freqStep;
|
bandMarkersDiv.append("–<br/>");
|
||||||
const spotsInStep = spotList.filter(function (s) {
|
|
||||||
// Normally we do >= start and < end, but in the special case where this is the last step and there is a spot
|
|
||||||
// right at the end of the band, we include this too
|
|
||||||
return s.freq >= freqStepStart && (s.freq < freqStepEnd || (s.freq === freqStepEnd && freqStepEnd === band.end_freq));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (spotsInStep.length > 0) {
|
|
||||||
// If this step has spots in it, print them
|
|
||||||
html += "<li class='withSpots'><span>";
|
|
||||||
spotsInStep.sort((a, b) => (a.freq > b.freq) ? 1 : ((b.freq > a.freq) ? -1 : 0));
|
|
||||||
spotsInStep.forEach(function (s) {
|
|
||||||
html += "<div class='bandColSpot'><span class='bandColSpot'>" + s.dx_call + "<br/><span class='bandColSpotFreq'>" + (s.freq/1000000) + "</span>";
|
|
||||||
if (s.mode != null && s.mode.length > 0 && s.mode !== "Unknown") {
|
|
||||||
html += "<span class='bandColSpotMode'>" + s.mode + "</span>";
|
|
||||||
}
|
|
||||||
html += "</span></div>";
|
|
||||||
});
|
|
||||||
html += "</li></span>";
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Step had no spots in it, so just print a marker. This is a frequency on multiples of 4, or a dash otherwise.
|
bandMarkersDiv.append("-<br/>");
|
||||||
if (i % 4 === 0) {
|
|
||||||
html += "<li><span>—" + ((band.start_freq + i * freqStep)/1000000).toFixed(3) + "</span></li>";
|
|
||||||
} else if (i % 4 === 2) {
|
|
||||||
html += "<li><span>–</span></li>";
|
|
||||||
} else {
|
|
||||||
html += "<li><span>-</span></li>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html += "<li><span>-</span></li>";
|
|
||||||
html += "</ul>";
|
|
||||||
|
|
||||||
html += "</div></div>";
|
// Print the spots on the band. Each one is a div with the details, shifted down if necessary to prevent
|
||||||
columnIndex++;
|
// overlap, and a horizontal or diagonal line on the canvas linking it to where it properly appears on the
|
||||||
|
// band.
|
||||||
|
bandSpotsDiv = $("<div class='band-spots'>");
|
||||||
|
bandLinesCanvas = $(`<canvas class='band-lines-canvas' width='${BAND_COLUMN_CANVAS_WIDTH_PX}' height='${BAND_COLUMN_HEIGHT_PX}'>`);
|
||||||
|
// Sort by frequency so we print higher frequencies later, and can bump them further down the track to prevent
|
||||||
|
// overlaps
|
||||||
|
spotList.sort(function(a, b) { return a.freq - b.freq; });
|
||||||
|
var lastSpotEmDownBand = -999;
|
||||||
|
// Iterate through the spots list
|
||||||
|
spotList.forEach(s => {
|
||||||
|
// Work out how far down the div to draw it
|
||||||
|
var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text
|
||||||
|
var emDownBand = percentDownBand * BAND_COLUMN_HEIGHT_EM;
|
||||||
|
var pxDownBandFreq = (percentDownBand + 0.015) * BAND_COLUMN_HEIGHT_PX; // same fudge but add half to put the left end of the line in the right place
|
||||||
|
if (emDownBand < lastSpotEmDownBand + 1.6) {
|
||||||
|
emDownBand = lastSpotEmDownBand + 1.6; // Prevent overlap
|
||||||
|
}
|
||||||
|
lastSpotEmDownBand = emDownBand;
|
||||||
|
var pxDownBandLabel = (emDownBand * BAND_COLUMN_FONT_SIZE) + (0.015 * BAND_COLUMN_HEIGHT_PX);
|
||||||
|
|
||||||
|
// Add spot div to DOM
|
||||||
|
bandSpotsDiv.append(`<div class="band-spot" label="${(s.freq/1000000).toFixed(3)}MHz ${s.mode}" onclick="alert('${s.dx_call} on ${(s.freq/1000000).toFixed(3)}MHz ${s.mode}');" style="top: ${emDownBand}em; border-top: 1px solid ${s.band_color}; border-left: 5px solid ${s.band_color}; border-bottom: 1px solid ${s.band_color}; border-right: 1px solid ${s.band_color};">${s.dx_call}</div>`);
|
||||||
|
|
||||||
|
// Draw the line on the canvas
|
||||||
|
var ctx = bandLinesCanvas[0].getContext('2d');
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.lineCap = "round";
|
||||||
|
ctx.strokeStyle = s.band_color;
|
||||||
|
ctx.moveTo(0, pxDownBandFreq);
|
||||||
|
ctx.lineTo(BAND_COLUMN_CANVAS_WIDTH_PX, pxDownBandLabel);
|
||||||
|
ctx.stroke();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assemble the table cell
|
||||||
|
td = $("<td>");
|
||||||
|
container = $("<div class='band-container'>");
|
||||||
|
container.append(bandLinesCanvas);
|
||||||
|
container.append(bandMarkersDiv);
|
||||||
|
container.append(bandSpotsDiv);
|
||||||
|
td.append(container);
|
||||||
|
table.find('tbody tr').append(td);
|
||||||
});
|
});
|
||||||
// Update the DOM with the band HTML
|
|
||||||
bandsPanel.html(html);
|
|
||||||
|
|
||||||
// Desktop mouse wheel to scroll bands horizontally if used on the headers
|
// Update the DOM with the band HTML
|
||||||
// noinspection JSDeprecatedSymbols
|
bandsContainer.html(table);
|
||||||
$(".bandColHeader").on("wheel", () => bandsPanel.scrollLeft(bandsPanel.scrollLeft() + event.deltaY / 10.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through a temporary list of spots, merging duplicates in a way suitable for the band panel. If two or more
|
// Iterate through a temporary list of spots, merging duplicates in a way suitable for the band panel. If two or more
|
||||||
|
|||||||
Reference in New Issue
Block a user