summaryrefslogtreecommitdiffstats
path: root/fretboard.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'fretboard.mjs')
-rw-r--r--fretboard.mjs172
1 files changed, 82 insertions, 90 deletions
diff --git a/fretboard.mjs b/fretboard.mjs
index ef9e0b5..7ba0dab 100644
--- a/fretboard.mjs
+++ b/fretboard.mjs
@@ -1,22 +1,14 @@
-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'
-};
+const openStrings = ['E', 'A', 'D', 'G', 'B', 'E'];
// convert ‘string1’ ‘fret2’ in ‘form’ to F#
export function fretToNote(form, stringName, fretName) {
- const string = strings[stringName];
- if (!string) {
- return null;
+ if (!form) {
+ console.error('fretToNote with no form!');
+ return 'C';
}
+ console.log('lookingforfret', stringName, form, form.querySelector(`.${stringName} .open`));
if (form.querySelector(`.${stringName}.muted`)) {
return 'x';
} else if (!fretName?.startsWith('fret')) {
@@ -26,64 +18,9 @@ export function fretToNote(form, stringName, fretName) {
}
}
-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 class extends HTMLElement {
+ static observedAttributes = ['strings', 'frets'];
+
static name = 'x-fretboard';
static register() {
console.debug('Registering Element', this.name, this);
@@ -98,22 +35,15 @@ export default class extends HTMLElement {
console.debug('Fretboard#constructor', this);
}
+ attributeChangedCallback(name, old, v) {
+ console.debug('Fretboard#attributeChangedCallback',
+ this, name, old, v);
+ this.formChanged();
+ }
+
connectedCallback() {
console.debug('Fretboard#connectedCallback', this);
-
- // TODO: don't trawl the dom, custom element means we know
- // what's inside.
- this.form = this.querySelector('form');
- this.form.onchange = handleFormChanged;
- this.form.querySelectorAll('.open').forEach(elt => {
- elt.onclick = openClick;
- });
- this.form.querySelectorAll('input[type="radio"]').forEach(elt => {
- elt.onmousedown = fretMousedown;
- elt.onclick = fretClick;
- });
-
- this.form.querySelectorAll('.save').forEach(elt => {
+ this.querySelectorAll('.save').forEach(elt => {
elt.onclick = (e) => {
console.log('Fretboard#onSave');
e.preventDefault();
@@ -125,16 +55,78 @@ export default class extends HTMLElement {
this.dispatchEvent(event);
};
})
- formChanged(this.form);
+ this.formChanged();
}
get notes() {
console.debug('Fretboard#notes', this);
- const formData = new FormData(this.form);
- return Array.from(this.form.querySelectorAll('tbody .selected')).map(elt => {
- const string = Array.from(elt.parentNode.classList).filter(x => x.startsWith('string'))[0];
- const val = formData.get(string);
- return fretToNote(this.form, string, val);
+ return [];
+ // const formData = new FormData(this.form);
+ // return Array.from(this.form.querySelectorAll('tbody .selected')).map(elt => {
+ // const string = Array.from(elt.parentNode.classList).filter(x => x.startsWith('string'))[0];
+ // const val = formData.get(string);
+ // return fretToNote(this.form, string, val);
+ // })
+ }
+
+ updateSelected(formData) {
+ // this.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(this, string, val));
+ // if (note.isSharp) {
+ // elt.innerText = `${note} / ${note.toAlternateString()}`;
+ // } else {
+ // elt.innerText = note;
+ // }
+ // });
+ }
+
+ zotStrings() {
+ console.debug('Fretboard#zotStrings', this);
+ const tmpl = this.querySelector('template.string');
+ console.log(' -- tmpl', tmpl);
+ const parent = tmpl.parentNode;
+ parent.querySelectorAll('[slot="string"]').forEach(elt => {
+ console.debug(' -- del', elt);
+ parent.removeChild(elt);
})
}
+
+ zotForm() {
+ console.debug('Fretboard#zotForm', this);
+ this.zotStrings();
+ }
+
+ #strings; #frets;
+ formChanged() {
+ console.debug('Fretboard#formChanged', this);
+ // TODO: this is inelegant. ideally, none of this stuff is
+ // triggered until the form is set, and doing it here is not
+ // robust.
+ const [strings, frets] =
+ [this.getAttribute('strings'), this.getAttribute('frets')].map(s => Number(s));
+ console.debug(' -- strings', strings, 'frets', frets);
+ if (strings && frets && strings !== this.#strings && frets != this.#frets) {
+ console.debug(' -- rerender table');
+ this.zotForm();
+
+ const tmpl = this.querySelector('template.string');
+ for (let i = 0; i < strings; i++) {
+ console.debug(' -- appending string', i, tmpl);
+ const item = tmpl.content.cloneNode(true);
+ console.debug(' -- item', item);
+ const tonic = openStrings[i];
+ item.querySelectorAll('[slot="string"]').forEach(s => {
+ console.debug(' -- setting tonic', tonic, 'on', s);
+ s.setAttribute('tonic', tonic);
+ s.setAttribute('selected', tonic);
+ s.setAttribute('frets', frets.toString());
+ })
+ tmpl.parentNode.insertBefore(item, tmpl);
+ }
+ this.#frets = frets;
+ this.#strings = strings;
+ }
+ }
}