From 636c18b9640733ffab9d9bb35fa7753a7d1903a3 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Mon, 28 Jul 2025 09:48:56 -0400 Subject: put key picker note hover back --- key-picker.mjs | 54 +++++++++++++++++++++++++++++++----------------------- main.mjs | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/key-picker.mjs b/key-picker.mjs index b3f871c..53c089f 100644 --- a/key-picker.mjs +++ b/key-picker.mjs @@ -15,27 +15,6 @@ function scaleFrom(tonic, scale) { } } -function handleNoteEnter(e) { - const elt = e.target; - const n = Note.fromString(elt.textContent).toString(); - // todo: this should be delegated. the key selector shouldn't know - // about the fretboard at all. - elt.classList.add('hover'); - document.querySelectorAll(`#fretboard [x-data-note="${n}"]`).forEach(elt => { - elt.classList.add('hover'); - }) -} - -function handleNoteLeave(e) { - const elt = e.target; - const n = Note.fromString(elt.textContent).toString(); - // ibid. - elt.classList.remove('hover'); - document.querySelectorAll(`#fretboard [x-data-note="${n}"]`).forEach(elt => { - elt.classList.remove('hover'); - }) -} - function noteClicked(elt, justClear=false) { const n = Note.fromString(elt.textContent).toString(); const count = Number(elt.getAttribute('x-data-clicked')) || 0; @@ -114,6 +93,9 @@ export default class extends HTMLElement { customElements.define(this.name, this); } + noteEnterEvent = 'x-key-picker-note-enter' + noteLeaveEvent = 'x-key-picker-note-leave' + constructor() { super(); @@ -128,12 +110,38 @@ export default class extends HTMLElement { const form = this.querySelector('form'); form.onchange = handleFormChanged; form.querySelectorAll('.notes li').forEach(elt => { - elt.onmouseenter = handleNoteEnter; - elt.onmouseleave = handleNoteLeave; + elt.onmouseenter = this.handleNoteEnter.bind(this); + elt.onmouseleave = this.handleNoteLeave.bind(this); elt.onclick = handleNoteClick; }); formChanged(form); console.log('bjc', 'Cdim', DiminishedScale('C').toString()); } + + handleNoteEnter(e) { + const elt = e.target; + const note = Note.fromString(elt.textContent) + elt.classList.add('hover'); + + const event = new CustomEvent(this.noteEnterEvent, { + bubbles: true, + cancelable: true, + detail: note + }); + this.dispatchEvent(event); + } + + handleNoteLeave(e) { + const elt = e.target; + const note = Note.fromString(elt.textContent) + elt.classList.remove('hover'); + + const event = new CustomEvent(this.noteLeaveEvent, { + bubbles: true, + cancelable: true, + detail: note + }); + this.dispatchEvent(event); + } } diff --git a/main.mjs b/main.mjs index 6c71e9c..9aa4dd2 100644 --- a/main.mjs +++ b/main.mjs @@ -5,30 +5,31 @@ import String from './string.mjs'; import Player from './player.mjs'; import { Note, toCents } from './scale.mjs'; +// assume A440 tuning +const noteA = Note.fromString('A'); let player = undefined; -function save(e) { +function save({ detail }) { document.querySelectorAll(History.name).forEach(h => { - console.debug('h is', h, 'e is', e.detail); - h.add(e.detail); + console.debug('h is', h, 'e is', detail); + h.add(detail); }); } -function play(e) { - console.debug('got playEvent', e, e.detail.notes); +function play({ detail }) { + console.debug('got playEvent', detail.notes); if (player) { player.stop(); } - const played = e.detail.notes.map((n, i) => { + const played = detail.notes.map((n, i) => { if (n !== 'x') { - return [Note.fromString(n), e.detail.octaves[i]]; + return [Note.fromString(n), detail.octaves[i]]; } }).filter(n => n); - const a = Note.fromString('A'); player = new Player(played.map(([n, o]) => { - return toCents([a, 4], [n, o]); + return toCents([noteA, 4], [n, o]); })); player.start(); } @@ -40,6 +41,20 @@ function stop(e) { } } +function noteEnter({ detail }) { + console.debug('got noteEnter', detail); + Array.from(document.querySelectorAll(`.fret [value='${detail.toString()}']`)) + .map(f => f.parentNode) + .forEach(f => f.classList.add('hover')); +} + +function noteLeave({ detail }) { + console.debug('got noteLeave', detail); + Array.from(document.querySelectorAll(`.fret [value='${detail.toString()}']`)) + .map(f => f.parentNode) + .forEach(f => f.classList.remove('hover')); +} + function init() { console.debug('init()', this); @@ -54,5 +69,10 @@ function init() { f.addEventListener(f.playEvent, play); f.addEventListener(f.stopEvent, stop); }); + + document.querySelectorAll(KeyPicker.name).forEach(kp => { + kp.addEventListener(kp.noteEnterEvent, noteEnter); + kp.addEventListener(kp.noteLeaveEvent, noteLeave); + }) } document.addEventListener('DOMContentLoaded', init); -- cgit v1.3