Skip to content

Commit c3c6716

Browse files
Refactor heatmap UI: replace select elements with custom interactive components and improve event handling
1 parent 34a648e commit c3c6716

4 files changed

Lines changed: 160 additions & 53 deletions

File tree

_includes/heatmap.html

Lines changed: 112 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
{% assign e = site.data[page.lang]['heatmap-ui'] %}
22

3-
<div style="flex-basis: 100%; display: flex; justify-content: center; align-items: center; pointer-events: auto; gap: 30px">
4-
<!--<div role="select" style="border: 1px solid #e8e8e8; border-radius: .5em; padding: .5em;">
5-
<input type="checkbox" style="display: none">
6-
<div class="hand-select">
7-
<span id="hand-selected"></span>
8-
<img src="/assets/img/arrow_down.png" alt="arrow_down" style="aspect-ratio: 1 / 1; height: 1.6em;">
3+
<div id="interface">
4+
<div class="select active" role="select" style="width: 14em">
5+
<input class="select-checkbox" id="hand-select-checkbox" type="checkbox">
6+
<label for="hand-select-checkbox" style="display: flex; justify-content: space-between">
7+
<span id="hand-selected">{{ e.total }}</span>
8+
<img alt="arrow_down" src="/assets/img/arrow_down.png" style="aspect-ratio: 1 / 1; height: 1.6em;">
9+
</label>
10+
<div id="hand-select-options" class="select-options">
11+
<span class="select-option">{{ e.total }}</span>
12+
<span class="select-option">{{ e.preferred }}</span>
13+
<span class="select-option">{{ e.hf_format | replace: '%h%', e.left | replace: '%f%', e.hand }}</span>
14+
<span class="select-option">{{ e.hf_format | replace: '%h%', e.right | replace: '%f%', e.hand }}</span>
915
</div>
10-
<div class="hand-select-options" style="display: flex; flex-direction: column; color: #383838">
11-
<span class="hand-select-option">{{ e.total }}</span>
12-
<span class="hand-select-option">{{ e.preferred }}</span>
13-
<span class="hand-select-option">{{ e.hf_format | replace: '%h%', e.left | replace: '%f%', e.hand }}</span>
14-
<span class="hand-select-option">{{ e.hf_format | replace: '%h%', e.right | replace: '%f%', e.hand }}</span>
16+
</div>
17+
<div class="select" id="finger-select" role="select" style="width: 8em">
18+
<input class="select-checkbox" id="finger-select-checkbox" type="checkbox">
19+
<label for="finger-select-checkbox" style="display: flex; justify-content: space-between">
20+
<span id="finger-selected">{{ e.all_button }}</span>
21+
<img alt="arrow_down" src="/assets/img/arrow_down.png" style="aspect-ratio: 1 / 1; height: 1.6em;">
22+
</label>
23+
<div id="finger-select-options" class="select-options">
24+
<span class="select-option">{{ e.all_button }}</span>
25+
<span class="select-option">{{ e.thumb }}</span>
26+
<span class="select-option">{{ e.index }}</span>
27+
<span class="select-option">{{ e.middle }}</span>
28+
<span class="select-option">{{ e.ring }}</span>
29+
<span class="select-option">{{ e.little }}</span>
1530
</div>
16-
</div>-->
17-
18-
<select class="finger-select active" id="all-fingers">
19-
<option value="total">{{ e.total }}</option>
20-
<option value="preferred">{{ e.preferred }}</option>
21-
<option value="L">{{ e.hf_format | replace: '%h%', e.left | replace: '%f%', e.hand }}</option>
22-
<option value="R">{{ e.hf_format | replace: '%h%', e.right | replace: '%f%', e.hand }}</option>
23-
</select>
24-
<select class="finger-select" id="finger-select">
25-
<option value="H">{{ e.all_button }}</option>
26-
<option value="T">{{ e.thumb }}</option>
27-
<option value="I">{{ e.index }}</option>
28-
<option value="M">{{ e.middle }}</option>
29-
<option value="R">{{ e.ring }}</option>
30-
<option value="L">{{ e.little }}</option>
31-
</select>
31+
</div>
3232
</div>
3333

3434
<div id="model-container"></div>
@@ -69,11 +69,15 @@
6969
import langFinger from '/assets/js/ui-lang.json' with {type: 'json'};
7070

7171
document.addEventListener('DOMContentLoaded', function () {
72+
const handLabel = document.getElementById('hand-selected')
73+
const fingerLabel = document.getElementById('finger-selected')
74+
const fingerSelect = document.getElementById('finger-select')
75+
const handCheckbox = document.getElementById('hand-select-checkbox')
76+
const fingerCheckbox = document.getElementById('finger-select-checkbox')
77+
7278
const selectionText = document.getElementById('selection-text');
7379
const selectionIcon = document.querySelector('#selection-badge .selection-icon');
7480
const fingerContext = document.getElementById('finger-context');
75-
const fingerSelect = document.getElementById('finger-select');
76-
const allFingers = document.getElementById('all-fingers');
7781

7882
const FACES = ['R', 'B', 'G', 'W', 'Y'];
7983
const ALL_FINGERS = ['LT', 'LI', 'LM', 'LR', 'LL', 'RT', 'RI', 'RM', 'RR', 'RL'];
@@ -168,39 +172,104 @@
168172
updateUI('best', ALL_FINGERS);
169173
}
170174

171-
function handleSelect() {
172-
let selectValue = allFingers.value;
175+
function handleCustomSelect(value) {
176+
switch (value) {
177+
case "{{ e.total }}":
178+
return "total";
179+
case "{{ e.preferred }}":
180+
return "preferred";
181+
case "{{ e.hf_format | replace: '%h%', e.left | replace: '%f%', e.hand }}":
182+
return "L";
183+
case "{{ e.hf_format | replace: '%h%', e.right | replace: '%f%', e.hand }}":
184+
return "R";
185+
case "{{ e.all_button }}":
186+
return "H";
187+
case "{{ e.thumb }}":
188+
return "T";
189+
case "{{ e.index }}":
190+
return "I";
191+
case "{{ e.middle }}":
192+
return "M";
193+
case "{{ e.ring }}":
194+
return "R";
195+
case "{{ e.little }}":
196+
return "L";
197+
}
198+
}
199+
200+
function handleFirstSelect(value) {
201+
let selectValue = handleCustomSelect(value);
173202
if (selectValue === "total") {
174203
if (fingerSelect.classList.contains('active')) {
175204
fingerSelect.classList.remove('active');
176-
fingerSelect.value = "H"
205+
fingerCheckbox.checked = false;
206+
fingerLabel.textContent = '{{ e.all_button }}'
177207
}
178208
updateSelection("total");
209+
handLabel.textContent = value;
179210
} else if (selectValue === "preferred") {
180211
if (fingerSelect.classList.contains('active')) {
181212
fingerSelect.classList.remove('active');
182-
fingerSelect.value = "H"
213+
fingerCheckbox.checked = false;
214+
fingerLabel.textContent = '{{ e.all_button }}'
183215
}
184216
handleBestFinger();
217+
handLabel.textContent = value;
185218
} else {
186219
fingerSelect.classList.add('active')
187-
let selectFinger = fingerSelect.value;
188-
if (selectFinger === 'H') {
189-
if (selectValue === 'L') {
220+
if (selectValue === 'L') {
221+
handleHandAll('left')
222+
handLabel.textContent = value;
223+
} else {
224+
handleHandAll('right')
225+
handLabel.textContent = value;
226+
}
227+
}
228+
}
229+
230+
function handleSecondSelect(value) {
231+
let selectValue = handleCustomSelect(value);
232+
switch (selectValue) {
233+
case "H":
234+
if (handleCustomSelect(handLabel.textContent) === 'L') {
190235
handleHandAll('left')
236+
fingerLabel.textContent = value;
191237
} else {
192238
handleHandAll('right')
193-
}
194-
} else {
195-
updateSelection(selectValue + selectFinger)
196-
}
239+
fingerLabel.textContent = value;
240+
} break;
241+
case "T":
242+
case "I":
243+
case "M":
244+
case "R":
245+
case "L":
246+
updateSelection(handleCustomSelect(handLabel.textContent) + selectValue);
247+
fingerLabel.textContent = value;
248+
break;
197249
}
198250
}
199251

200-
allFingers.addEventListener('change', handleSelect)
201-
fingerSelect.addEventListener('change', handleSelect)
252+
fingerCheckbox.addEventListener('change', () => {
253+
handCheckbox.checked = false;
254+
})
255+
256+
handCheckbox.addEventListener('change', () => {
257+
fingerCheckbox.checked = false;
258+
})
259+
260+
document.querySelectorAll('#hand-select-options .select-option').forEach(elem => {
261+
elem.addEventListener('click', () => {
262+
handleFirstSelect(elem.textContent);
263+
});
264+
})
265+
266+
document.querySelectorAll('#finger-select-options .select-option').forEach(elem => {
267+
elem.addEventListener('click', () => {
268+
handleSecondSelect(elem.textContent);
269+
});
270+
})
202271

203-
handleSelect();
272+
handleFirstSelect('{{ e.total }}');
204273
document.getElementById('model-container').classList.add('active');
205274
});
206275
</script>

assets/css/heatmap.css

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
justify-content: center;
88
align-items: center;
99
box-sizing: border-box;
10-
margin: 0 auto;
10+
margin: 4rem auto 0;
1111
overflow: visible;
1212
object-fit: cover;
1313

@@ -97,6 +97,53 @@
9797
pointer-events: auto;
9898
}
9999

100+
#interface {
101+
position: absolute;
102+
left: 50%;
103+
transform: translateX(-50%);
104+
display: flex;
105+
align-items: flex-start;
106+
pointer-events: auto;
107+
gap: 30px;
108+
user-select: none;
109+
}
110+
111+
.select-checkbox {
112+
display: none;
113+
}
114+
115+
.select {
116+
border: 1px solid #e8e8e8;
117+
border-radius: .5em;
118+
padding: .5em;
119+
background-color: white;
120+
flex-direction: row;
121+
122+
opacity: 50%;
123+
pointer-events: none;
124+
}
125+
126+
.select.active {
127+
opacity: 100%;
128+
pointer-events: auto;
129+
}
130+
131+
.select-options {
132+
display: flex;
133+
flex-direction: column;
134+
color: #383838;
135+
background-color: white;
136+
}
137+
138+
.select-checkbox ~ .select-options {
139+
display: none;
140+
}
141+
142+
.select-checkbox:checked ~ .select-options {
143+
display: flex;
144+
padding-top: 0.2em;
145+
}
146+
100147
/* Finger context */
101148
.finger-context {
102149
display: flex;

assets/img/arrow_down.png

1.36 KB
Loading

assets/js/dataviz.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ document.addEventListener('DOMContentLoaded', function () {
55
const perFingerReachability = window.perFingerReachability;
66

77
const defaultModeMeta = document.querySelector('meta[name="default-mode"]');
8-
const currentMode = defaultModeMeta ? defaultModeMeta.getAttribute('content') : 'reachability';
98

109
const FACES = ['R', 'B', 'G', 'W', 'Y'];
1110

@@ -64,14 +63,6 @@ document.addEventListener('DOMContentLoaded', function () {
6463
});
6564
}
6665

67-
// Finger filter for reachability
68-
const fingerSelect = document.getElementById('finger-select');
69-
if (fingerSelect) {
70-
fingerSelect.addEventListener('change', function () {
71-
if (currentMode === 'reachability') applyReachabilityView();
72-
});
73-
}
74-
7566
// ═══════════════════════════════════════════════════════
7667
// SHARED CONTROLS
7768
// ═══════════════════════════════════════════════════════

0 commit comments

Comments
 (0)