From 0b3b35db35e344e9aaf3453fc1277d7af1dee214 Mon Sep 17 00:00:00 2001 From: Ian Renton Date: Tue, 21 Oct 2025 16:04:10 +0100 Subject: [PATCH] First pass of the new style of band panel #48 --- webassets/css/style.css | 94 ++++++++++++++----------------- webassets/js/bands.js | 121 ++++++++++++++++++++++------------------ 2 files changed, 108 insertions(+), 107 deletions(-) diff --git a/webassets/css/style.css b/webassets/css/style.css index 7ec31b7..76b6e7a 100644 --- a/webassets/css/style.css +++ b/webassets/css/style.css @@ -162,76 +162,64 @@ div#bands-container { overscroll-behavior-x: none; } -div.bandCol { - min-width: 8em; - display: flex; - flex-flow: column; - overflow-y: clip; +#bands-table { + min-width: 100%; } -div.bandColHeader { - flex: 0 1 auto; +#bands-table th { + width: 20%; + min-width: 12em; + padding: 0.5em; text-align: center; font-weight: bold; - padding: 0.5em; } -div.bandColMiddle { - flex: 1 1 auto; - margin-left: 3px; - border-left: 2px dotted var(--text); +#bands-table td { + width: 20%; + min-width: 12em; } -div.bandColMiddle ul { - display: table; - table-layout: fixed; +div.band-container { + height: 62em; + width: 20%; + min-width: 12em; + position: relative; +} + +div.band-markers { width: 100%; height: 100%; - margin: 0; - padding: 0; - -moz-box-sizing: border-box; - box-sizing: border-box; - border-left: 2px dotted; + position: absolute; + top: 0; + left: 0; + z-index: 13; } -div.bandColMiddle ul li { - display: table-row; - line-height: 0.5em; +div.band-spots { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 15; } -/*noinspection CssUnusedSymbol*/ -div.bandColMiddle ul li.withSpots { - line-height: 1em; +canvas.band-lines-canvas { + width: 5em; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 11; } -div.bandColMiddle ul li span { - display: table-cell; - vertical-align: middle; -} - -div.bandColSpot { - display: block; +div.band-spot { + position: absolute; + left: 5em; + padding: 0 0.25em; + background-color: white; border-radius: 3px; - padding: 3px; - 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; + cursor: default; } diff --git a/webassets/js/bands.js b/webassets/js/bands.js index ffcda9a..3c1e3af 100644 --- a/webassets/js/bands.js +++ b/webassets/js/bands.js @@ -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. function loadSpots() { $.getJSON('/api/v1/spots' + buildQueryString(), function(jsonData) { @@ -28,9 +36,9 @@ function buildQueryString() { // Update the bands display function updateBands() { // Stop here if nothing to display - var bandsPanel = $("#bands-container"); + var bandsContainer = $("#bands-container"); if (spots.length === 0) { - bandsPanel.html(""); + bandsContainer.html(""); return; } @@ -51,73 +59,78 @@ function updateBands() { } }); - // Build up HTML content for each band - let html = ""; - const columnWidthPercent = Math.max(30, 100 / bandToSpots.size); - let columnIndex = 0; + // Build up table content for each band + var table = $('').append(''); bandToSpots.forEach(function (spotList, bandName) { // Get the colours for the band from the first spot, and prepare the header - html += "
"; - html += "
" + spotList[0].band + "
"; - html += "
"; + table.find('thead tr').append(`
`); // Get the band data to fetch start and end frequencies let band = options["bands"].filter(function (b) { return b.name === bandName; })[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 = $('
'); const freqStep = (band.end_freq - band.start_freq) / 40.0; - html += ""; - html += "
"; - columnIndex++; + // Print the spots on the band. Each one is a div with the details, shifted down if necessary to prevent + // overlap, and a horizontal or diagonal line on the canvas linking it to where it properly appears on the + // band. + bandSpotsDiv = $("
"); + bandLinesCanvas = $(``); + // 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(`
${s.dx_call}
`); + + // 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 = $("
${spotList[0].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 - // noinspection JSDeprecatedSymbols - $(".bandColHeader").on("wheel", () => bandsPanel.scrollLeft(bandsPanel.scrollLeft() + event.deltaY / 10.0)); + // Update the DOM with the band HTML + bandsContainer.html(table); } // Iterate through a temporary list of spots, merging duplicates in a way suitable for the band panel. If two or more