Scenario generator for vore roleplay and story ideas. https://scenario-generator.deliciousreya.net/responses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
vore-scenario-generator/src/client/responses-entrypoint.ts

82 lines
2.8 KiB

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<RollTableResultFull<RollTableDetailsAndResults>>) => 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<RollTableResultFull<RollTableDetailsAndResults>>("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<RollTableDetailsAndResults>) {
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<HTMLElement>(`#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<ResponseLists> = DOMLoaded.then(() => initResponseList())
export const db: Promise<RollTableDatabase> = responseLists.then(r => r.db)