import type { RollTableDatabase, RollTableDetailsAndResults, RollTableResultFull } from '../common/rolltable'; import { DOMLoaded } from './onload'; import { scrapeResponseLists } from './scraper'; import { htmlTableIdentifier } from '../common/template'; import escapeHTML from 'escape-html'; class ResponseLists { readonly db: RollTableDatabase readonly listsElement: HTMLElement constructor(db: RollTableDatabase, listsElement: HTMLElement) { this.db = db this.listsElement = listsElement } addSelectionListener(listener: (e: CustomEvent>) => void, options?: boolean|EventListenerOptions): void { this.listsElement.addEventListener("resultselected", listener, options) } configureHandlers(): this { this.listsElement.addEventListener("click", (e) => { if (e.target instanceof HTMLElement && e.target.classList.contains("makeResponseActive")) { const response = e.target.closest(`.response`) if (!response) { console.log("no response") return } const mappingId = response.id && response.id.startsWith("response-") ? parseInt(response.id.substring("response-".length), 10) : NaN if (isNaN(mappingId)) { console.log("no mapping ID") return } const result = this.db.mappings.get(mappingId) if (!result) { console.log("no result") return } const ev = new CustomEvent>("resultselected", { bubbles: true, cancelable: true, detail: result }) if (e.target.dispatchEvent(ev)) { this.setActiveElementForTable(result) const button = response.querySelector(`.resultText`) as HTMLElement if (button) { button.focus() } } } }) return this } setActiveElementForTable(result: RollTableResultFull) { const oldActive = this.listsElement.querySelector(`#responses-${escapeHTML(htmlTableIdentifier(result.table))} .response.active`) const newActive = this.listsElement.querySelector(`#response-${escapeHTML(`${result.mappingId}`)}`) if (!newActive || oldActive === newActive) { return } newActive.classList.add("active") if (!oldActive) { return } oldActive.classList.remove("active") } } function initResponseList(): ResponseLists { const listsElement = document.querySelector(`#responseLists`) if (!listsElement) { throw Error(`can't find #responseLists`) } const lists = scrapeResponseLists(listsElement) if (!lists) { throw Error(`can't parse #responseLists`) } const {db, active} = lists return new ResponseLists(db, listsElement).configureHandlers() } export const responseLists: Promise = DOMLoaded.then(() => initResponseList()) export const db: Promise = responseLists.then(r => r.db)