When I type the music note do in the textarea and click the up button, it goes to do# and the "notes_Sharps" scale works perfectly, whether it is in uppercase or lowercase (Do or do).
What I want is:
If I write reb and click the up button, to follow the "notes_Flats" scale. ['do','reb','re','mib','mi','fa','solb','sol','lab','la','sib','si']
Now, it reads the "notes_Sharps" scale.
In the same way, I want exactly the same thing if I write ρε# or ρεb, to follow the corresponding scales, "notes_Sharps_Gr" and "notes_Flats_Gr"
How do I program it? It's been a week and I'm still at this result.. Thanks in advance
const
textareaId = document.querySelector('#textarea'),
notes_Sharps = ['do', 'do#', 're', 're#', 'mi', 'fa', 'fa#', 'sol', 'sol#', 'la', 'la#', 'si'],
notes_Flats = ['do', 'reb', 're', 'mib', 'mi', 'fa', 'solb', 'sol', 'lab', 'la', 'sib', 'si'],
notes_Sharps_Gr = ['ντο', 'ντο#', 'ρε', 'ρε#', 'μι', 'φα', 'φα#', 'σολ', 'σολ#', 'λα', 'λα#', 'σι'],
notes_Flats_Gr = ['ντο', 'ρεb', 'ρε', 'μιb', 'μι', 'φα', 'σολb', 'σολ', 'λαb', 'λα', 'σιb', 'σι'],
notesExchg = {
reb: 'do#',
mib: 're#',
solb: 'fa#',
lab: 'sol#',
sib: 'la#'
},
changeNotes = val => notesExchg[val.toLowerCase()] || val;
function stepOn(stepNotes = +1) {
let textarea_regex = textareaId.value.split(/([A-Za-zÉé]+\#?)/);
textareaId.value = textarea_regex.reduce((acc, Nx) => {
if (!Boolean(Nx))
return acc;
let flatToSharp = changeNotes(Nx),
isUpC = Nx[0].toUpperCase() === Nx[0],
noteSearch = notes_Sharps.findIndex(x => flatToSharp.toLowerCase() === x);
if (noteSearch === -1)
acc += Nx;
else {
let NotesStep = notes_Sharps[(noteSearch + stepNotes + notes_Sharps.length) % notes_Sharps.length];
acc += isUpC ? NotesStep.toUpperCase() : NotesStep;
}
return acc;
}, '')
}
<button onclick="stepOn(+1 )" class="stepUp_Button">Up</button>
<button onclick="stepOn(-1 )" class="stepDown_Button">Down</button>
<textarea id="textarea" rows="5" cols="30">
</textarea>
</div>
Try this solution based on your solution. It saves the cache and remembers the each individual notes. Comments are in the code (shared notations like do
will be treated as sharp notation).
const
textareaId = document.querySelector('#textarea'),
notes_Sharps = ['do', 'do#', 're', 're#', 'mi', 'fa', 'fa#', 'sol', 'sol#', 'la', 'la#', 'si'],
notes_Flats = ['do', 'reb', 're', 'mib', 'mi', 'fa', 'solb', 'sol', 'lab', 'la', 'sib', 'si'],
notes_Sharps_Gr = ['ντο', 'ντο#', 'ρε', 'ρε#', 'μι', 'φα', 'φα#', 'σολ', 'σολ#', 'λα', 'λα#', 'σι'],
notes_Flats_Gr = ['ντο', 'ρεb', 'ρε', 'μιb', 'μι', 'φα', 'σολb', 'σολ', 'λαb', 'λα', 'σιb', 'σι'];
const cachedScales = [];
function stepOn(stepNotes = +1) {
let textarea_regex = textareaId.value.split(/([A-Za-zÉéΑ-Ωα-ω]+#?)/);
textareaId.value = textarea_regex.reduce((acc, Nx, i) => {
if (!Nx) return acc;
// find the target scale for each notes from the cache, if not found, search through all the notes list
const targetScale = cachedScales[i] ?? [notes_Sharps, notes_Flats, notes_Sharps_Gr, notes_Flats_Gr].find(scales => scales.includes(Nx.toLowerCase()));
const noteSearch = targetScale?.indexOf(Nx.toLowerCase()) ?? -1;
if (noteSearch === -1) {
acc += Nx;
} else {
cachedScales[i] = targetScale; // save the notes to cache
const isUpC = Nx[0].toUpperCase() === Nx[0];
const isCap = isUpC && Nx[1] && Nx[1].toUpperCase() !== Nx[1];
const NotesStep = targetScale[(noteSearch + stepNotes + targetScale.length) % targetScale.length];
acc += (isCap ? NotesStep.charAt(0).toUpperCase() + NotesStep.substring(1) : isUpC ? NotesStep.toUpperCase() : NotesStep).replace(/(?<=.)B$/, 'b');
}
return acc;
}, '')
}
// upon editing, clear the cache
textareaId.addEventListener('input', () => cachedScales.length = 0);
<button onclick="stepOn(+1 )" class="stepUp_Button">Up</button>
<button onclick="stepOn(-1 )" class="stepDown_Button">Down</button>
<textarea id="textarea" rows="5" cols="30">
</textarea>