diff options
| -rw-r--r-- | fretboard.mjs | 49 | ||||
| -rw-r--r-- | index.html | 275 | ||||
| -rw-r--r-- | key-picker.mjs | 38 | ||||
| -rw-r--r-- | main.mjs | 29 | ||||
| -rw-r--r-- | notes.org | 6 |
5 files changed, 230 insertions, 167 deletions
diff --git a/fretboard.mjs b/fretboard.mjs index 8b330cc..38fdc0f 100644 --- a/fretboard.mjs +++ b/fretboard.mjs @@ -83,15 +83,42 @@ function openClick(e) { 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); +// export default function (form, { onSave }) { +// } + +export default class extends HTMLElement { + static name = 'x-fretboard' + static register() { + console.debug('Registering Element', this.name, this); + customElements.define(this.name, this); + } + + constructor() { + super(); + + console.debug('Fretboard#constructor', this); + } + + connectedCallback() { + console.debug('Fretboard#connectedCallback', this); + + // TODO: don't trawl the dom, custom element means we know + // what's inside. + const form = this.querySelector('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; + }); + form.querySelectorAll('.save').forEach(elt => { + elt.onclick = (e) => { + e.preventDefault(); + console.log('Fretboard#onSave'); + }; + }) + formChanged(form); + } } @@ -8,149 +8,154 @@ </head> <body> - <form id='fretboard'> - <table> - <thead> - <tr> - <td class='open'>open</td> - <td class='fret1'></td> - <td class='fret2'></td> - <td class='fret3'>•</td> - <td class='fret4'></td> - <td class='fret5'>••</td> - <td class='fret6'></td> - <td class='fret7'>•</td> - <td class='selected'>selected</td> - </tr> - </thead> + <x-fretboard> + <form id='fretboard'> + <table> + <thead> + <tr> + <td class='open'>open</td> + <td class='fret1'></td> + <td class='fret2'></td> + <td class='fret3'>•</td> + <td class='fret4'></td> + <td class='fret5'>••</td> + <td class='fret6'></td> + <td class='fret7'>•</td> + <td class='selected'>selected</td> + </tr> + </thead> - <tbody> - <tr class='string1'> - <td class='open' x-data-note='E'>E</td> - <td x-data-note='F'><input type='radio' name='string1' value='fret1'></td> - <td x-data-note='F♯'><input type='radio' name='string1' value='fret2'></td> - <td x-data-note='G'><input type='radio' name='string1' value='fret3'></td> - <td x-data-note='G♯'><input type='radio' name='string1' value='fret4'></td> - <td x-data-note='A'><input type='radio' name='string1' value='fret5'></td> - <td x-data-note='A♯'><input type='radio' name='string1' value='fret6'></td> - <td x-data-note='B'><input type='radio' name='string1' value='fret7'></td> - <td class='selected'></td> - </tr> - <tr class='string2'> - <td class='open' x-data-note='A'>A</td> - <td x-data-note='A♯'><input type='radio' name='string2' value='fret1'></td> - <td x-data-note='B'><input type='radio' name='string2' value='fret2'></td> - <td x-data-note='C'><input type='radio' name='string2' value='fret3'></td> - <td x-data-note='C♯'><input type='radio' name='string2' value='fret4'></td> - <td x-data-note='D'><input type='radio' name='string2' value='fret5'></td> - <td x-data-note='D♯'><input type='radio' name='string2' value='fret6'></td> - <td x-data-note='E'><input type='radio' name='string2' value='fret7'></td> - <td class='selected'></td> - </tr> - <tr class='string3'> - <td class='open' x-data-note='D'>D</td> - <td x-data-note='D♯'><input type='radio' name='string3' value='fret1'></td> - <td x-data-note='E'><input type='radio' name='string3' value='fret2'></td> - <td x-data-note='F'><input type='radio' name='string3' value='fret3'></td> - <td x-data-note='F♯'><input type='radio' name='string3' value='fret4'></td> - <td x-data-note='G'><input type='radio' name='string3' value='fret5'></td> - <td x-data-note='G♯'><input type='radio' name='string3' value='fret6'></td> - <td x-data-note='A'><input type='radio' name='string3' value='fret7'></td> - <td class='selected'></td> - </tr> - <tr class='string4'> - <td class='open' x-data-note='G'>G</td> - <td x-data-note='G♯'><input type='radio' name='string4' value='fret1'></td> - <td x-data-note='A'><input type='radio' name='string4' value='fret2'></td> - <td x-data-note='A♯'><input type='radio' name='string4' value='fret3'></td> - <td x-data-note='B'><input type='radio' name='string4' value='fret4'></td> - <td x-data-note='C'><input type='radio' name='string4' value='fret5'></td> - <td x-data-note='C♯'><input type='radio' name='string4' value='fret6'></td> - <td x-data-note='D'><input type='radio' name='string4' value='fret7'></td> - <td class='selected'></td> - </tr> - <tr class='string5'> - <td class='open' x-data-note='B'>B</td> - <td x-data-note='C'><input type='radio' name='string5' value='fret1'></td> - <td x-data-note='C♯'><input type='radio' name='string5' value='fret2'></td> - <td x-data-note='D'><input type='radio' name='string5' value='fret3'></td> - <td x-data-note='D♯'><input type='radio' name='string5' value='fret4'></td> - <td x-data-note='E'><input type='radio' name='string5' value='fret5'></td> - <td x-data-note='F'><input type='radio' name='string5' value='fret6'></td> - <td x-data-note='F♯'><input type='radio' name='string5' value='fret7'></td> - <td class='selected'></td> - </tr> - <tr class='string6'> - <td class='open' x-data-note='E'>E</td> - <td x-data-note='F'><input type='radio' name='string6' value='fret1'></td> - <td x-data-note='F♯'><input type='radio' name='string6' value='fret2'></td> - <td x-data-note='G'><input type='radio' name='string6' value='fret3'></td> - <td x-data-note='G♯'><input type='radio' name='string6' value='fret4'></td> - <td x-data-note='A'><input type='radio' name='string6' value='fret5'></td> - <td x-data-note='A♯'><input type='radio' name='string6' value='fret6'></td> - <td x-data-note='B'><input type='radio' name='string6' value='fret7'></td> - <td class='selected'></td> - </tr> - </tbody> - </table> + <tbody> + <tr class='string1'> + <td class='open' x-data-note='E'>E</td> + <td x-data-note='F'><input type='radio' name='string1' value='fret1'></td> + <td x-data-note='F♯'><input type='radio' name='string1' value='fret2'></td> + <td x-data-note='G'><input type='radio' name='string1' value='fret3'></td> + <td x-data-note='G♯'><input type='radio' name='string1' value='fret4'></td> + <td x-data-note='A'><input type='radio' name='string1' value='fret5'></td> + <td x-data-note='A♯'><input type='radio' name='string1' value='fret6'></td> + <td x-data-note='B'><input type='radio' name='string1' value='fret7'></td> + <td class='selected'></td> + </tr> + <tr class='string2'> + <td class='open' x-data-note='A'>A</td> + <td x-data-note='A♯'><input type='radio' name='string2' value='fret1'></td> + <td x-data-note='B'><input type='radio' name='string2' value='fret2'></td> + <td x-data-note='C'><input type='radio' name='string2' value='fret3'></td> + <td x-data-note='C♯'><input type='radio' name='string2' value='fret4'></td> + <td x-data-note='D'><input type='radio' name='string2' value='fret5'></td> + <td x-data-note='D♯'><input type='radio' name='string2' value='fret6'></td> + <td x-data-note='E'><input type='radio' name='string2' value='fret7'></td> + <td class='selected'></td> + </tr> + <tr class='string3'> + <td class='open' x-data-note='D'>D</td> + <td x-data-note='D♯'><input type='radio' name='string3' value='fret1'></td> + <td x-data-note='E'><input type='radio' name='string3' value='fret2'></td> + <td x-data-note='F'><input type='radio' name='string3' value='fret3'></td> + <td x-data-note='F♯'><input type='radio' name='string3' value='fret4'></td> + <td x-data-note='G'><input type='radio' name='string3' value='fret5'></td> + <td x-data-note='G♯'><input type='radio' name='string3' value='fret6'></td> + <td x-data-note='A'><input type='radio' name='string3' value='fret7'></td> + <td class='selected'></td> + </tr> + <tr class='string4'> + <td class='open' x-data-note='G'>G</td> + <td x-data-note='G♯'><input type='radio' name='string4' value='fret1'></td> + <td x-data-note='A'><input type='radio' name='string4' value='fret2'></td> + <td x-data-note='A♯'><input type='radio' name='string4' value='fret3'></td> + <td x-data-note='B'><input type='radio' name='string4' value='fret4'></td> + <td x-data-note='C'><input type='radio' name='string4' value='fret5'></td> + <td x-data-note='C♯'><input type='radio' name='string4' value='fret6'></td> + <td x-data-note='D'><input type='radio' name='string4' value='fret7'></td> + <td class='selected'></td> + </tr> + <tr class='string5'> + <td class='open' x-data-note='B'>B</td> + <td x-data-note='C'><input type='radio' name='string5' value='fret1'></td> + <td x-data-note='C♯'><input type='radio' name='string5' value='fret2'></td> + <td x-data-note='D'><input type='radio' name='string5' value='fret3'></td> + <td x-data-note='D♯'><input type='radio' name='string5' value='fret4'></td> + <td x-data-note='E'><input type='radio' name='string5' value='fret5'></td> + <td x-data-note='F'><input type='radio' name='string5' value='fret6'></td> + <td x-data-note='F♯'><input type='radio' name='string5' value='fret7'></td> + <td class='selected'></td> + </tr> + <tr class='string6'> + <td class='open' x-data-note='E'>E</td> + <td x-data-note='F'><input type='radio' name='string6' value='fret1'></td> + <td x-data-note='F♯'><input type='radio' name='string6' value='fret2'></td> + <td x-data-note='G'><input type='radio' name='string6' value='fret3'></td> + <td x-data-note='G♯'><input type='radio' name='string6' value='fret4'></td> + <td x-data-note='A'><input type='radio' name='string6' value='fret5'></td> + <td x-data-note='A♯'><input type='radio' name='string6' value='fret6'></td> + <td x-data-note='B'><input type='radio' name='string6' value='fret7'></td> + <td class='selected'></td> + </tr> + </tbody> + </table> - <button class='save-chord'>+</button> - </form> + <button class='save'>+</button> + </form> + </x-fretboard> - <form id='key-picker'> - <fieldset> - <legend>key</legend> - <label for='tonic'>tonic:</label> - <select id='tonic' name='tonic'> - <option value='C' selected>C</option> - <option value='C♯'>C♯</option> - <option value='D'>D</option> - <option value='D♯'>D♯</option> - <option value='E'>E</option> - <option value='F'>F</option> - <option value='F♯'>F♯</option> - <option value='G'>G</option> - <option value='G♯'>G♯</option> - <option value='A'>A</option> - <option value='A♯'>A♯</option> - <option value='B'>B</option> - </select> - <label for='scale'>scale:</label> - <select id='scale' name='scale'> - <option value='major' selected>major</option> - <option value='minor'>minor</option> - <option value='aug'>augmented</option> - <option value='dim'>diminished</option> - </select> + <x-key-picker> + <form id='key-picker'> + <fieldset> + <legend>key</legend> + <label for='tonic'>tonic:</label> + <select id='tonic' name='tonic'> + <option value='C' selected>C</option> + <option value='C♯'>C♯</option> + <option value='D'>D</option> + <option value='D♯'>D♯</option> + <option value='E'>E</option> + <option value='F'>F</option> + <option value='F♯'>F♯</option> + <option value='G'>G</option> + <option value='G♯'>G♯</option> + <option value='A'>A</option> + <option value='A♯'>A♯</option> + <option value='B'>B</option> + </select> + <label for='scale'>scale:</label> + <select id='scale' name='scale'> + <option value='major' selected>major</option> + <option value='minor'>minor</option> + <option value='aug'>augmented</option> + <option value='dim'>diminished</option> + </select> - <hr> + <hr> - <ol class='notes'> - <li class='tonic'>C</li> - <li class='second'>D</li> - <li class='third'>E</li> - <li class='fourth'>F</li> - <li class='fifth'>G</li> - <li class='sixth'>A</li> - <li class='seventh'>B</li> - </ol> - <hr> + <ol class='notes'> + <li class='tonic'>C</li> + <li class='second'>D</li> + <li class='third'>E</li> + <li class='fourth'>F</li> + <li class='fifth'>G</li> + <li class='sixth'>A</li> + <li class='seventh'>B</li> + </ol> + <hr> - <p>Available triads:</p> - <ul class='chords'> - <li>Amin</li> - <li>C</li> - <li>Dmin</li> - <li>Emin</li> - <li>F</li> - <li>G</li> - </ul> - </fieldset> - </form> + <p>Available triads:</p> + <ul class='chords'> + <li>Amin</li> + <li>C</li> + <li>Dmin</li> + <li>Emin</li> + <li>F</li> + <li>G</li> + </ul> + </fieldset> + </form> + </x-key-picker> - <form id='saved-chords'> + <x-chords-history></x-chords-history> + <form id='history'> <fieldset> - <legend>saved</legend> + <legend>history</legend> <ol> <li>GCEGCE</li> <li>EBEGBE</li> diff --git a/key-picker.mjs b/key-picker.mjs index 3aa8340..b24422d 100644 --- a/key-picker.mjs +++ b/key-picker.mjs @@ -106,15 +106,33 @@ function handleFormChanged(e) { formChanged(e.target.form); } -export default function (form) { - console.debug('KeyPicker()', form); - form.onchange = handleFormChanged; - form.querySelectorAll('.notes li').forEach(elt => { - elt.onmouseenter = handleNoteEnter; - elt.onmouseleave = handleNoteLeave; - elt.onclick = handleNoteClick; - }); - formChanged(form); +export default class extends HTMLElement { + static name = 'x-key-picker' + static register() { + console.debug('Registering Element', this.name, this); + customElements.define(this.name, this); + } + + constructor() { + super(); + + console.debug('KeyPicker#constructor', this); + } + + connectedCallback() { + console.debug('KeyPicker#connectedCallback', this); - console.log('bjc', 'Cdim', DiminishedScale('C').toString()); + // TODO: don't trawl the dom, custom element means we know + // what's inside. + const form = this.querySelector('form'); + form.onchange = handleFormChanged; + form.querySelectorAll('.notes li').forEach(elt => { + elt.onmouseenter = handleNoteEnter; + elt.onmouseleave = handleNoteLeave; + elt.onclick = handleNoteClick; + }); + formChanged(form); + + console.log('bjc', 'Cdim', DiminishedScale('C').toString()); + } } @@ -2,25 +2,32 @@ import Fretboard, { fretToNote } from './fretboard.mjs'; import KeyPicker from './key-picker.mjs'; import History from './history.mjs'; +function memoize(fn) { + let val = undefined; + return function () { + if (val === undefined) { + val = fn(); + } + return val; + } +} + function notes(form) { const strings = ['string1', 'string2', 'string3', 'string4', 'string5', 'string6']; const formData = new FormData(form); - console.log('notes', form, formData); + console.debug('notes', form, formData); return strings.map((klass) => fretToNote(form, klass, formData.get(klass))); } function onSave(form) { - console.log('we done saved', form, notes(form)); + console.debug('we done saved', form, notes(form)); } +function init() { + console.debug('App#init', this); -function main() { - const fretboard = document.getElementById('fretboard'); - const keyPicker = document.getElementById('key-picker'); - const history = document.getElementById('history'); - - Fretboard(fretboard, { onSave }); - KeyPicker(keyPicker); - History(history, keyPicker); + Fretboard.register(); + KeyPicker.register(); + History.register(); } -document.addEventListener('DOMContentLoaded', main); +document.addEventListener('DOMContentLoaded', init); @@ -1,3 +1,9 @@ +* convert to web components +https://developer.mozilla.org/en-US/docs/Web/API/Web_components +** don't trawl dom when setting up behavior +since it's a custom element, we should know its exact layout at all +times, so ~querySelector~ shouldn't be necessary. + * well-tempered scale | semi-tones | freq | just | interval | |------------+-----------+------+----------| |
