import { Note } from "./scale.mjs"; // open string notes, starting from the deepest string. const strings = { string1: 'E', string2: 'A', string3: 'D', string4: 'G', string5: 'B', string6: 'E' }; // convert ‘string1’ ‘fret2’ in ‘form’ to F# export function fretToNote(form, stringName, fretName) { const string = strings[stringName]; if (!string) { return null; } if (form.querySelector(`.${stringName}.muted`)) { return 'x'; } else if (!fretName?.startsWith('fret')) { return form.querySelector(`.${stringName} .open`).getAttribute("x-data-note"); } else { return form.querySelector(`.${stringName} [value="${fretName}"]`).parentNode.getAttribute("x-data-note"); } } function formChanged(form) { const formData = new FormData(form); form.querySelectorAll('tbody .selected').forEach(elt => { const string = Array.from(elt.parentNode.classList).filter(x => x.startsWith('string'))[0]; const val = formData.get(string); const note = Note.fromString(fretToNote(form, string, val)); if (note.isSharp) { elt.innerText = `${note} / ${note.toAlternateString()}`; } else { elt.innerText = note; } }); } function handleFormChanged(e) { formChanged(e.target.form); } let mousedownVal = undefined; function fretMousedown(e) { // at mousedown time, the form hasn't yet been changed. to support // deselecting elements, we need to know what the previous // selection was, so store it here. // // it'd be nice to be able to do this just in the click handler. mousedownVal = e.target.checked; } function fretClick(e) { const elt = e.target; // if this element was selected at mousedown time, deselect it // now. if (mousedownVal) { elt.checked = false; // doesn't get called automatically. formChanged(elt.form); } } function openClick(e) { const elt = e.target.parentNode; if (elt.classList.contains('muted')) { elt.classList.remove('muted'); elt.querySelectorAll('input[type="radio"]').forEach(input => { input.disabled = false; }) } else { elt.classList.add('muted'); elt.querySelectorAll('input[type="radio"]').forEach(input => { input.checked = false; input.disabled = true; }) } formChanged(elt.closest('form')); } export default function (form) { console.debug('Fretboard()', form); form.onchange = handleFormChanged; form.querySelectorAll('.open').forEach(elt => { elt.onclick = openClick; }); form.querySelectorAll('input[type="radio"]').forEach(elt => { elt.onmousedown = fretMousedown; elt.onclick = fretClick; }); formChanged(form); }