var ContextMenu = new class ContextMenu { elements: { menu: HTMLDivElement; items: { copy: HTMLDivElement; paste: HTMLDivElement; cut: HTMLDivElement; ghost: HTMLDivElement; osc: HTMLDivElement; http: HTMLDivElement; }; }; open: boolean; contextHolder: HTMLElement; constructor() { this.elements = { menu: document.querySelector('.contextmenu'), items: { copy: document.querySelector('.contextmenu').querySelector('.copy'), paste: document.querySelector('.contextmenu').querySelector('.paste'), cut: document.querySelector('.contextmenu').querySelector('.cut'), ghost: document.querySelector('.contextmenu').querySelector('.ghost'), osc: document.querySelector('.contextmenu').querySelector('.osc'), http: document.querySelector('.contextmenu').querySelector('.http') } }; this.open = false; this.contextHolder = null; window.addEventListener('contextmenu', (ev: MouseEvent) => this.handle(this.elements.menu, ev)); window.addEventListener('mousedown', (ev: MouseEvent) => { if (this.open == true) if (ev.target) { var target = ev.target as HTMLElement; if ( target.classList.contains('contextmenu') || (target.parentElement != undefined && target.parentElement.classList.contains('contextmenu')) ) { } else { this.close(); } } else this.close(); }); } setItems(items: DropdownItemTypes[]) { for (var type in this.elements.items) { if (items.includes(type)) this.elements.items[type].style.display = 'block'; else this.elements.items[type].style.display = 'none'; } } close() { this.elements.menu.style.display = 'none'; if (this.contextHolder != null) { this.contextHolder.classList.remove('context'); this.contextHolder = null; } this.open = false; } handle(menu: HTMLDivElement, ev: MouseEvent) { if (ev.target != undefined) { var target = ev.target as HTMLElement; var types = { key: (element: HTMLElement) => { if (element.hasAttribute('x') && element.hasAttribute('y')) { var keyX = element.getAttribute('x'); var keyY = element.getAttribute('y'); var items: DropdownItemTypes[] = [ 'osc', 'http' ]; if (PageHandler.currentPage.keys[keyY][keyX].state.type != 'empty') items.push('copy', 'cut'); if (PageHandler.currentPage.keys[keyY][keyX].state.type == 'custom') items.push('ghost'); if (UndeckedClipboard.hasKeyInClipboard()) items.push('paste'); this.setItems(items); this.elements.items.copy.onclick = () => { UndeckedClipboard.copyKey(parseInt(keyX), parseInt(keyY)); this.close(); }; this.elements.items.cut.onclick = () => { UndeckedClipboard.cutKey(parseInt(keyX), parseInt(keyY)); this.close(); }; this.elements.items.paste.onclick = () => { UndeckedClipboard.pasteKey(parseInt(keyX), parseInt(keyY)); this.close(); }; this.elements.items.ghost.onclick = () => { UndeckedClipboard.copyGhostKey(parseInt(keyX), parseInt(keyY)); this.close(); }; return items.length > 0; } } }; for (var type in types) if (target.classList.contains(type)) { ev.preventDefault(); var valid = types[type](target); if (valid) { this.contextHolder = target; target.classList.add('context'); setTimeout(() => { this.open = true; }, 100); menu.style.left = `${ev.pageX}px`; menu.style.top = `${ev.pageY - 50}px`; menu.style.display = 'block'; } return; } } } }(); type DropdownItemTypes = 'copy' | 'paste' | 'cut' | 'ghost' | 'osc' | 'http';