1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
const panel = document.querySelector('aside.pattern');
const preset = panel.querySelector('.control--preset select');
const patternLength = document.getElementById('pattern-len');
const steps = panel.querySelector('.steps');
let length = 12;
let pattern = [0, 2, 4, 5, 7, 9, 11];
const PRESETS = {
'major-7': [0, 2, 4, 5, 7, 9, 11],
'minor-7': [0, 2, 3, 5, 7, 8, 10],
'minor-harm-7': [0, 2, 3, 5, 7, 8, 11],
'minor-mel-7': [0, 2, 3, 5, 7, 9, 11],
'minor-hung-7': [0, 2, 3, 6, 7, 8, 11],
'penta': [0, 2, 4, 7, 9],
'major-3': [0, 4, 7],
'major-3+': [0, 4, 8],
'minor-3': [0, 3, 7],
'minor-3-': [0, 3, 6],
};
const update = () => {
while (steps.childElementCount > length) {
steps.lastElementChild.remove();
}
while (steps.childElementCount < length) {
const input = document.createElement('input');
input.type = 'checkbox';
steps.append(input);
}
Array.from(steps.children).forEach((toggle, i) => {
toggle.checked = pattern.includes(i);
});
updatePreset();
};
const updatePreset = () => {
const presetName = Object.keys(PRESETS).find(k => PRESETS[k].join(',') === pattern.join(','));
preset.value = presetName ?? 'custom';
};
patternLength.onchange = () => {
length = +patternLength.value;
pattern = pattern.filter(n => n < length);
update();
};
steps.onchange = () => {
pattern = [];
Array.from(steps.children).forEach((toggle, i) => {
if (toggle.checked) pattern.push(i);
});
updatePreset();
};
preset.onchange = (e) => {
const nextPattern = PRESETS[preset.value];
if (nextPattern) {
pattern = nextPattern.slice();
update();
}
};
preset.value = 'major-7';
preset.onchange();
export const getLength = () => length;
export const getSteps = () => pattern;
|