diff options
author | Brian Cully <bjc@spork.org> | 2025-03-09 16:50:07 -0400 |
---|---|---|
committer | Brian Cully <bjc@spork.org> | 2025-03-09 16:50:07 -0400 |
commit | 53631ad1ef5497017f00f56608649e9bee90b264 (patch) | |
tree | 5099a928f2cbecc2c708bedc929042c60a4ad563 | |
parent | 45c8b61f2c55a4534e7069c1febc36bf5709fccd (diff) | |
download | chords-53631ad1ef5497017f00f56608649e9bee90b264.tar.gz chords-53631ad1ef5497017f00f56608649e9bee90b264.zip |
add display for available chords in the key
-rw-r--r-- | index.html | 18 | ||||
-rw-r--r-- | key-picker.mjs | 25 | ||||
-rw-r--r-- | main.css | 11 | ||||
-rw-r--r-- | scale.mjs | 1 |
4 files changed, 52 insertions, 3 deletions
@@ -101,12 +101,17 @@ <label for='tonic'>tonic:</label> <select id='tonic' name='tonic'> <option value='A'>A</option> + <option value='A#'>A#</option> <option value='B'>B</option> <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> </select> <label for='diatonic'>diatonic:</label> <select id='diatonic' name='diatonic'> @@ -117,7 +122,7 @@ <hr> <ol class='notes'> - <li class='first'>C</li> + <li class='tonic'>C</li> <li class='second'>D</li> <li class='third'>E</li> <li class='fourth'>F</li> @@ -125,6 +130,17 @@ <li class='sixth'>A</li> <li class='seventh'>B</li> </ol> + <hr> + + <p>Available chords:</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> diff --git a/key-picker.mjs b/key-picker.mjs index bd6482a..fc6b4ed 100644 --- a/key-picker.mjs +++ b/key-picker.mjs @@ -14,9 +14,32 @@ function scaleFrom(tonic, diatonic) { function formChanged(form) { const formData = new FormData(form); const scale = scaleFrom(formData.get('tonic'), formData.get('diatonic')); - ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh'].forEach((c, i) => { + ['tonic', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh'].forEach((c, i) => { Array.from(form.getElementsByClassName(c)).forEach(elt => elt.innerText = scale[i]); }); + + // todo: memoize this or put it in the scales module. + const allScales = chromaticScale.flatMap(tonic => { + return [MajorScale(tonic), MinorScale(tonic)]; + }) + + const availableScales = + allScales.reduce((acc, s, i) => { + const suffix = i % 2 == 0 ? '' : 'min'; + if (scale.includes(s.tonic) && scale.includes(s.third) && scale.includes(s.fifth)) { + return acc.concat(`${s.tonic}${suffix}`); + } + return acc; + }, []); + Array.from(form.getElementsByClassName('chords')).forEach(list => { + const items = availableScales.map(s => { + const elt = document.createElement('li'); + elt.innerText = s; + return elt; + }); + list.replaceChildren(); + items.forEach(item => list.appendChild(item)); + }); } function handleFormChanged(e) { @@ -67,3 +67,14 @@ body { counter-increment: notes; text-align: center; } + +#key-picker .chords { + display: grid; + grid-template-rows: 1; + grid-template-columns: 4em 4em 4em 4em 4em 4em; + padding-left: 0; +} + +#key-picker .chords li { + display: grid; +} @@ -61,7 +61,6 @@ class Scale { } get length() { - console.debug(`get length`, this.scale.length); return this.scale.length; } |