entlib
Version:
Entry API Wrapper
254 lines (204 loc) • 7.8 kB
text/typescript
const sel = <K extends keyof HTMLElementTagNameMap = 'div'>(selector: string) => {
return document.querySelector(selector) as HTMLElementTagNameMap[K] | null
}
let id: string = 'null'
if (Entry.getMainWS()) {
sel('.popup')!.style.display = 'none'
Entry.Command[1103].do()
const nid = sel('.popup')!.children[0].className.replace('popup_wrap__', '')
id = nid
sel(`.btn_back__${id}`)!.click()
sel('.popup')!.style.display = ''
}
export type ModalEventListener = (modal: Modal, selectedItems: ModalItem[]) => void
export interface ModalButton {
text: string,
type: 'confirm' | 'normal',
onClick: ModalEventListener
}
export interface ModalParams1 {
title: string
alertMessage?: string
confirmText: string
onConfirm: ModalEventListener
onCancel?: ModalEventListener
items?: ModalItem[]
}
export interface ModalParams2 {
title: string
alertMessage?: string
buttons: ModalButton[]
onCancel?: ModalEventListener
items?: ModalItem[]
}
export interface ModalParams3 {
title: string
alertMessage?: string
confirmText: string
cancelText: string
onConfirm: ModalEventListener
onCancel: ModalEventListener
items?: ModalItem[]
}
const defaultDOM = `
<div class="popup_wrap__${id}">
<header class="pop_header__${id}">
<h1>{TITLE}</h1>
<button class="btn_back__${id} imbtn_pop_back__${id}"><span class="blind__${id}">Menus.history_back</span></button>
</header>
<section class="extend_content__${id} pop_content__${id}">
<div class="section_cont__${id}">
<h2 class="blind__${id}">BIG ICON LIST</h2>
<div class="cont_box__${id}">
<div class="desc__${id}">
<div class="imico_exclamation_mark__${id}"></div>
<div class="content__${id}">{ALERT_MESSAGE}</div>
</div>
<div class="extend_block__${id}">
<ul class="list__${id}"></ul>
</div>
</div>
</div>
</section>
<div class="pop_btn_box__${id}"></div>
</div>`.trim()
const defaultItemDOM = `
<li>
<div class="link__${id}">
<div class="thmb__${id}" style="background-image: url({BACKGROUND_IMAGE}); background-repeat: no-repeat; position: relative;">
<div class="sponser_text__${id}"><span class="sponser_text_span__${id}">{SPONSER_MESSAGE}</span></div>
</div>
<div class="inner_box__${id}">
<strong class="sjt__${id}">{TITLE}</strong>
<div class="dsc__${id}">{DESCRIPTION}</div>
</div>
</div>
</li>`.trim()
const parseDOM = <K extends keyof HTMLElementTagNameMap>(h: string) => {
return new DOMParser().parseFromString(h, 'text/html').body.childNodes[0] as HTMLElementTagNameMap[K]
}
export interface ItemParams {
title: string
description: string
image: string
sponserMessage?: string
}
export class ModalItem {
protected pSelected: boolean = false
protected domElement: HTMLLIElement
public readonly title: string
public readonly description: string
public readonly image: string
public readonly sponserMessage: string | null
constructor({ title, description, image, sponserMessage }: ItemParams) {
if (!Entry.getMainWS()) throw new Error('Modal is only available in ws-mode')
this.title = title
this.image = image
this.description = description
this.sponserMessage = sponserMessage ?? null
this.domElement = parseDOM<'li'>(defaultItemDOM
.replace('{TITLE}', title)
.replace('{DESCRIPTION}', description)
.replace('{BACKGROUND_IMAGE}', image)
.replace('{SPONSER_MESSAGE}', sponserMessage ?? '')
)
this.domElement.addEventListener('click', () => {
this.selected = !this.selected
})
if (!this.sponserMessage) this.domElement.querySelector<HTMLDivElement>(`.sponser_text__${id}`)!.style.display = 'none'
}
public getDOMElement() {
return this.domElement
}
set selected(v: boolean) {
if (v) this.domElement.classList.add(`on__${id}`)
else this.domElement.classList.remove(`on__${id}`)
this.pSelected = v
}
get selected() {
return this.pSelected
}
}
export class Modal {
protected pIsDestroyed: boolean = false
protected domElement: HTMLDivElement
public readonly title: string = ''
public readonly buttons: ModalButton[] = []
public readonly alertMessage: string | null = null
public readonly items: ModalItem[] = []
public readonly onCancel: ModalEventListener | null = null
constructor(p: ModalParams1)
constructor(p: ModalParams2)
constructor(p: ModalParams3)
constructor({ title, alertMessage, confirmText, cancelText, onConfirm, onCancel, buttons, items }: any) {
if (!Entry.getMainWS()) throw new Error('Modal is only available in ws-mode')
this.onCancel = onCancel ?? null
if (buttons) {
this.buttons = buttons
} else {
const arr: ModalButton[] = [{
text: confirmText,
type: 'confirm',
onClick: onConfirm
}]
if (cancelText) arr.push({
text: cancelText,
type: 'normal',
onClick: onCancel
})
this.buttons = arr
}
this.title = title
this.alertMessage = alertMessage ?? null
this.items = items ?? []
this.domElement = parseDOM<'div'>(defaultDOM
.replace('{TITLE}', title)
.replace('{ALERT_MESSAGE}', this.alertMessage ?? '')
)
if (!this.alertMessage) this.domElement.querySelector<HTMLDivElement>(`.desc__${id}`)!.style.display = 'none'
const buttonContainer = this.domElement.querySelector<HTMLDivElement>(`.pop_btn_box__${id}`)!
this.domElement.querySelector<HTMLDivElement>(`btn_back__${id}`)!.addEventListener('click', () => {
if (this.onCancel) {
this.onCancel(this, this.items.filter(item => item.selected))
} else {
this.destroy()
}
})
this.buttons.forEach(btn => {
const elem = document.createElement('a')
elem.addEventListener('click', () => {
btn.onClick(this, this.items.filter(item => item.selected))
})
if (btn.type == 'confirm') elem.classList.add(`active__${id}`)
elem.innerText = btn.text
buttonContainer.appendChild(elem)
})
}
public addItems(...items: ModalItem[]) {
if (this.isDestroyed) throw new Error('Modal destroyed')
this.items.push(...items)
}
public show() {
if (this.isDestroyed) throw new Error('Modal destroyed')
const itemContainer = this.domElement.querySelector<HTMLUListElement>(`.list__${id}`)!
itemContainer.innerHTML = ''
this.items.forEach(item => {
itemContainer.appendChild(item.getDOMElement())
})
sel('.popup')!.appendChild(this.domElement)
sel('.modal')!.style.display = 'block'
this.domElement.style.display = ''
}
public hide() {
if (this.isDestroyed) throw new Error('Modal destroyed')
sel('.modal')!.style.display = 'none'
this.domElement.style.display = 'none'
}
public destroy() {
this.pIsDestroyed = true
this.domElement.remove()
}
public get isDestroyed() {
return this.pIsDestroyed
}
}