-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKeyboardMenu.js
More file actions
83 lines (74 loc) · 3.48 KB
/
KeyboardMenu.js
File metadata and controls
83 lines (74 loc) · 3.48 KB
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
72
73
74
75
76
77
78
79
80
81
82
83
class KeyboardMenu {
constructor() {
this.options = []; // set by updater method showMenu() in submissionMenu
this.up = null;
this.down = null;
this.prevFocus = null;
}
setOptions(options) {
this.options = options;
this.element.innerHTML = this.options.map((option, index) => { // kind of like enumerate?
const disabledAttr = option.disabled ? "disabled" : "";
//const autoFocusAttr = index === 0 ? "autofocus" : "";
return (`
<div class="option">
<button ${disabledAttr} data-button="${index}" data-description="${option.description}">
${option.label}
</button>
<span class="right">${option.right ? option.right() : ""}</span>
</div>
`)
}).join("");
this.element.querySelectorAll("button").forEach(button => {
button.addEventListener("click", () => {
// goal: get a reference to the callback (handler()) that we are trying to fire
const chosenOption = this.options[ Number(button.dataset.button) ]; // getting the # button in the array using the data-button attribute lookup
chosenOption.handler();
})
button.addEventListener("mouseover", () => {
button.focus();
})
button.addEventListener("focus", () => {
this.prevFocus = button;
this.descriptionElementText.innerText = button.dataset.description; // descriptionElementText is a <p>
})
})
}
createElement() {
this.element = document.createElement("div");
this.element.classList.add("KeyboardMenu");
// description box element
this.descriptionElement = document.createElement("div");
this.descriptionElement.classList.add("DescriptionBox");
this.descriptionElement.innerHTML = (`<p></p>`);
this.descriptionElementText = this.descriptionElement.querySelector("p"); // saving a reference to the paragraph / description because it will be updated a lot (on focus)
}
end() {
this.element.remove();
this.descriptionElement.remove()
// cleaning up bindings
this.up.unbind();
this.down.unbind();
}
init(container) {
this.createElement();
container.appendChild(this.descriptionElement);
container.appendChild(this.element);
this.up = new KeyPressListener("KeyW", () => {
const current = Number(this.prevFocus.getAttribute("data-button"));
const prevButton = Array.from(this.element.querySelectorAll("button[data-button]")).reverse().find( el => {
// find a button whose data-button attr is greater than the current
return el.dataset.button < current && !el.disabled;
})
prevButton?.focus();
})
this.down = new KeyPressListener("KeyS", () => {
const current = Number(this.prevFocus.getAttribute("data-button"));
const nextButton = Array.from(this.element.querySelectorAll("button[data-button]")).find( el => {
// find a button whose data-button attr is greater than the current
return el.dataset.button > current && !el.disabled;
})
nextButton?.focus(); // then the focus listener takes over - highlighting it in the DOM and updating the focus text
})
}
}