From 1a56c3527670520e79538cb0e1fe27f9ad27582e Mon Sep 17 00:00:00 2001 From: Michael Winter Date: Sat, 4 Apr 2026 13:56:42 +0200 Subject: [PATCH] Add cents/frequency toggle for node labels - Add toggle button and 'f' keyboard shortcut - Calculate frequencies on-demand using fundamental * fraction - Use direct style updates for reliable label refresh --- webapp/path_navigator.html | 55 +++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/webapp/path_navigator.html b/webapp/path_navigator.html index d069dfd..373bd16 100644 --- a/webapp/path_navigator.html +++ b/webapp/path_navigator.html @@ -283,6 +283,7 @@ Octave: +
@@ -317,6 +318,53 @@ let hasPrev = false; let hasNext = false; let allGraphsData = null; + let displayMode = 'cents'; + + // Parse fraction string like "3/2" or "1" into a number + function parseFraction(fracStr) { + if (!fracStr || fracStr === "1") return 1; + const parts = fracStr.split('/'); + if (parts.length === 2) { + return parseInt(parts[0]) / parseInt(parts[1]); + } + return parseFloat(fracStr); + } + + // Toggle between cents and frequency display + function toggleDisplayUnit() { + displayMode = displayMode === 'cents' ? 'frequency' : 'cents'; + const btn = document.getElementById('toggleUnitBtn'); + if (btn) { + btn.textContent = displayMode === 'cents' ? 'Show: Cents' : 'Show: Frequency'; + } + + if (!cy) return; + + const fundamental = parseFloat(document.getElementById("fundamentalInput").value) || 110; + + cy.nodes().forEach(node => { + const cents = node.data('cents'); + const fraction = node.data('fraction'); + + if (displayMode === 'frequency' && fraction) { + const frac = parseFraction(fraction); + const freq = fundamental * frac; + node.data('displayLabel', Math.round(freq * 10) / 10); + } else { + node.data('displayLabel', cents); + } + + node.style('label', node.data('displayLabel')); + }); + } + + // Set up toggle button listener after DOM loads + document.addEventListener('DOMContentLoaded', () => { + const toggleBtn = document.getElementById('toggleUnitBtn'); + if (toggleBtn) { + toggleBtn.addEventListener('click', toggleDisplayUnit); + } + }); // Cytoscape instance let cy = null; @@ -343,7 +391,7 @@ 'background-color': 'data(color)', 'width': 32, 'height': 32, - 'label': 'data(cents)', + 'label': function(ele) { return ele.data('displayLabel'); }, 'text-valign': 'center', 'text-halign': 'center', 'color': '#000000', @@ -572,6 +620,8 @@ id: nodeId, localId: n.id, cents: n.cents, + displayLabel: n.cents, + fraction: n.fraction || "1", chordIndex: chordIdx, chordLabel: `c${chordIdx}`, color: voiceColors[n.id % voiceColors.length], @@ -724,6 +774,7 @@ nodes.push({ id: i, cents: Math.round(cents), + displayLabel: Math.round(cents), fraction: pitch.fraction || "1", hs_array: pitch.hs_array || [] }); @@ -1020,6 +1071,8 @@ }).catch(err => { console.log('Error sending kill:', err); }); + } else if (e.key === "f" || e.key === "F") { + toggleDisplayUnit(); } });