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.
82 lines
2.8 KiB
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)
|
|
|