146 lines
5.5 KiB
JavaScript
146 lines
5.5 KiB
JavaScript
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
|
});
|
||
|
};
|
||
|
import * as EventEmitter from 'eventemitter3';
|
||
|
import { SoundManager } from './sound-manager';
|
||
|
import { KeyboardManager } from './keyboard-manager';
|
||
|
export class Menu extends EventEmitter {
|
||
|
constructor(title = 'Menu', menuItems = [], soundSet = null, defaultAction = null, cancelAction = null) {
|
||
|
super();
|
||
|
this.title = title;
|
||
|
this.menuItems = menuItems;
|
||
|
this.soundSet = soundSet;
|
||
|
this.defaultAction = defaultAction;
|
||
|
this.cancelAction = cancelAction;
|
||
|
this.currentIndex = 0;
|
||
|
this.DOMNodes = [];
|
||
|
this.currentIndex = 0;
|
||
|
this.currentItem = null;
|
||
|
this.soundManager = new SoundManager(soundSet);
|
||
|
this.keyboardManager = new KeyboardManager(this);
|
||
|
this.init();
|
||
|
}
|
||
|
init() {
|
||
|
this.menuItems[this.currentIndex] &&
|
||
|
this.menuItems[this.currentIndex].focus();
|
||
|
this.emit('init');
|
||
|
}
|
||
|
addItem(item) {
|
||
|
this.menuItems.push(item);
|
||
|
this.emit('item.add', item);
|
||
|
return this;
|
||
|
}
|
||
|
setTitle(title) {
|
||
|
this.title = title;
|
||
|
return this;
|
||
|
}
|
||
|
setSoundSet(soundSet) {
|
||
|
this.soundSet = soundSet;
|
||
|
this.soundManager.setSoundSet(this.soundSet);
|
||
|
return this;
|
||
|
}
|
||
|
setDefaultAction(id) {
|
||
|
this.defaultAction = id;
|
||
|
return this;
|
||
|
}
|
||
|
setCancelAction(id) {
|
||
|
this.cancelAction = id;
|
||
|
return this;
|
||
|
}
|
||
|
run(element) {
|
||
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
this.element = element;
|
||
|
this.container = document.createElement('div');
|
||
|
this.titleContainer = document.createElement('h1');
|
||
|
this.titleContainer.textContent = this.title;
|
||
|
this.container.appendChild(this.titleContainer);
|
||
|
this.menuItems.forEach((item) => {
|
||
|
this.appendToContainer(item.getDOMNode());
|
||
|
item.on('update', this.handleItemUpdate.bind(this));
|
||
|
item.on('focus', this.onItemFocus.bind(this));
|
||
|
item.on('choose', (event) => {
|
||
|
const menuMap = this.compile();
|
||
|
this.soundManager.handleSound('choose');
|
||
|
this.emit('choose', menuMap);
|
||
|
resolve(menuMap);
|
||
|
});
|
||
|
});
|
||
|
element.appendChild(this.container);
|
||
|
this.soundManager.handleSound('open');
|
||
|
this.keyboardManager.init();
|
||
|
// push some data onto the history stack so that we can use the browser's back button to exit out of the menu.
|
||
|
history.pushState({ menu: true }, null, null);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
close() {
|
||
|
this.container.remove();
|
||
|
this.soundManager.handleSound('close');
|
||
|
this.keyboardManager.release();
|
||
|
this.DOMNodes.forEach((item) => {
|
||
|
this.container.removeChild(item);
|
||
|
});
|
||
|
this.emit('close');
|
||
|
}
|
||
|
appendToContainer(node) {
|
||
|
this.container.appendChild(node);
|
||
|
this.DOMNodes.push(node);
|
||
|
}
|
||
|
handleItemUpdate(value) {
|
||
|
this.soundManager.handleSound(value.type, value.value);
|
||
|
this.emit('update', this.compile());
|
||
|
}
|
||
|
onItemFocus(id) {
|
||
|
this.soundManager.handleSound('focus');
|
||
|
this.currentIndex = this.menuItems.indexOf(this.menuItems.find((item) => item.getID() == id));
|
||
|
this.emit('focus', this.menuItems[this.currentIndex]);
|
||
|
}
|
||
|
focusNext() {
|
||
|
if (this.currentIndex < this.menuItems.length - 1) {
|
||
|
this.currentIndex++;
|
||
|
}
|
||
|
this.focusCurrentIndex();
|
||
|
}
|
||
|
focusPrevious() {
|
||
|
if (this.currentIndex > 0) {
|
||
|
this.currentIndex--;
|
||
|
}
|
||
|
this.focusCurrentIndex();
|
||
|
}
|
||
|
focusCurrentIndex() {
|
||
|
this.menuItems[this.currentIndex].focus();
|
||
|
}
|
||
|
getCurrentFocus() {
|
||
|
return this.menuItems[this.currentIndex];
|
||
|
}
|
||
|
getContainer() {
|
||
|
return this.container;
|
||
|
}
|
||
|
clickDefaultAction() {
|
||
|
if (!this.defaultAction)
|
||
|
return;
|
||
|
const item = this.menuItems.find((item) => item.getID() === this.defaultAction);
|
||
|
item.click();
|
||
|
}
|
||
|
clickCancelAction() {
|
||
|
if (!this.cancelAction)
|
||
|
return;
|
||
|
const node = this.menuItems.find((item) => item.getID() === this.cancelAction);
|
||
|
node.click();
|
||
|
}
|
||
|
compile() {
|
||
|
const menuMap = new Map();
|
||
|
this.menuItems.forEach((item) => menuMap.set(item.getID(), item.getContents()));
|
||
|
menuMap.set('selected', this.menuItems[this.currentIndex].getID());
|
||
|
return menuMap;
|
||
|
}
|
||
|
}
|
||
|
export * from './items';
|