diff --git a/src/app/Mounter.ts b/src/app/Mounter.ts deleted file mode 100644 index 8e6c273d..00000000 --- a/src/app/Mounter.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ModelPath } from '@mcschema/core' -import { hexId } from './Utils' - -type Registry = { - [id: string]: (el: Element) => void -} - -export interface Mounter { - register(callback: (el: Element) => void): string - registerEvent(type: string, callback: (el: Element) => void): string - registerChange(callback: (el: Element) => void): string - registerClick(callback: (el: Element) => void): string - mount(el: Element): void -} - -export class Mounter implements Mounter { - registry: Registry = {} - - /** - * Registers a callback and gives an ID - * @param callback function that is called when the element is mounted - * @returns the ID that should be applied to the data-id attribute - */ - register(callback: (el: Element) => void): string { - const id = hexId() - this.registry[id] = callback - return id - } - - /** - * Registers an event and gives an ID - * @param type event type - * @param callback function that is called when the event is fired - * @returns the ID that should be applied to the data-id attribute - */ - registerEvent(type: string, callback: (el: Element) => void): string { - return this.register(el => { - el.addEventListener(type, evt => { - callback(el) - evt.stopPropagation() - }) - }) - } - - /** - * Registers a change event and gives an ID - * @param callback function that is called when the event is fired - * @returns the ID that should be applied to the data-id attribute - */ - registerChange(callback: (el: Element) => void): string { - return this.registerEvent('change', callback) - } - - /** - * Registers a click event and gives an ID - * @param callback function that is called when the event is fired - * @returns the ID that should be applied to the data-id attribute - */ - registerClick(callback: (el: Element) => void): string { - return this.registerEvent('click', callback) - } - - mount(el: Element): void { - for (const id in this.registry) { - const element = el.querySelector(`[data-id="${id}"]`) - if (element !== null) this.registry[id](element) - } - this.registry = {} - } -} diff --git a/src/app/components/panels/TreePanel.ts b/src/app/components/panels/TreePanel.ts index 12e95f30..ffc9bcfd 100644 --- a/src/app/components/panels/TreePanel.ts +++ b/src/app/components/panels/TreePanel.ts @@ -3,7 +3,6 @@ import { App, checkVersion, Previews } from '../../App'; import { Tracker } from '../../Tracker' import { toggleMenu, View } from '../../views/View'; import { Octicon } from '../Octicon'; -import { Mounter } from '../../Mounter'; import { renderHtml } from '../../hooks/renderHtml'; import config from '../../../config.json' import { BiomeNoisePreview } from '../../preview/BiomeNoisePreview'; @@ -39,11 +38,10 @@ const treeViewObserver = (el: Element) => { } export const TreePanel = (view: View, model: DataModel) => { - const mounter = new Mounter() const getContent = () => { if (App.loaded.get()) { const path = new ModelPath(model) - const rendered = model.schema.hook(renderHtml, path, model.data, mounter) + const rendered = model.schema.hook(renderHtml, path, model.data, view) const category = model.schema.category(path) if (rendered[1]) { return `
@@ -56,9 +54,8 @@ export const TreePanel = (view: View, model: DataModel) => { return '
' } const mountContent = (el: Element) => { - el.innerHTML = getContent() + view.mount(el, getContent(), false) treeViewObserver(el) - mounter.mount(el) } const tree = view.register(el => { App.loaded.watchRun((value) => { diff --git a/src/app/hooks/renderHtml.ts b/src/app/hooks/renderHtml.ts index 33cc61b1..50a56db9 100644 --- a/src/app/hooks/renderHtml.ts +++ b/src/app/hooks/renderHtml.ts @@ -1,6 +1,6 @@ import { Hook, ModelPath, Path, StringHookParams, ValidationOption, EnumOption, INode, DataModel, MapNode, StringNode } from '@mcschema/core' import { locale, segmentedLocale } from '../Locales' -import { Mounter } from '../Mounter' +import { Mounter } from '../views/View' import { hexId, htmlEncode } from '../Utils' import { suffixInjector } from './suffixInjector' @@ -22,10 +22,10 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { }, boolean({ node }, path, value, mounter) { - const onFalse = mounter.registerClick(el => { + const onFalse = mounter.onClick(el => { path.model.set(path, node.optional() && value === false ? undefined : false) }) - const onTrue = mounter.registerClick(el => { + const onTrue = mounter.onClick(el => { path.model.set(path, node.optional() && value === true ? undefined : true) }) return ['', ` = { }, list({ children }, path, value, mounter) { - const onAdd = mounter.registerClick(el => { + const onAdd = mounter.onClick(el => { if (!Array.isArray(value)) value = [] path.model.set(path, [children.default(), ...value]) }) - const onAddBottom = mounter.registerClick(el => { + const onAddBottom = mounter.onClick(el => { if (!Array.isArray(value)) value = [] path.model.set(path, [...value, children.default()]) }) @@ -74,7 +74,7 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { let body = '' if (Array.isArray(value)) { body = value.map((childValue, index) => { - const removeId = mounter.registerClick(el => path.model.set(path.push(index), undefined)) + const removeId = mounter.onClick(el => path.model.set(path.push(index), undefined)) const childPath = path.push(index).contextPush('entry') const category = children.category(childPath) const [cPrefix, cSuffix, cBody] = children.hook(this, childPath, childValue, mounter) @@ -101,7 +101,7 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { map({ keys, children }, path, value, mounter) { const keyPath = new ModelPath(keysModel, new Path([hashString(path.toString())])) - const onAdd = mounter.registerClick(el => { + const onAdd = mounter.onClick(el => { const key = keyPath.get() path.model.set(path.push(key), children.default()) }) @@ -111,7 +111,7 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { if (typeof value === 'object' && value !== undefined) { body = Object.keys(value) .map(key => { - const removeId = mounter.registerClick(el => path.model.set(path.push(key), undefined)) + const removeId = mounter.onClick(el => path.model.set(path.push(key), undefined)) const childPath = path.modelPush(key) const category = children.category(childPath) const [cPrefix, cSuffix, cBody] = children.hook(this, childPath, value[key], mounter) @@ -131,7 +131,7 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { }, number({ integer, config }, path, value, mounter) { - const onChange = mounter.registerChange(el => { + const onChange = mounter.onChange(el => { const value = (el as HTMLInputElement).value let parsed = config?.color ? parseInt(value.slice(1), 16) @@ -149,9 +149,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = { let prefix = '' if (node.optional()) { if (value === undefined) { - prefix = `` + prefix = `` } else { - prefix = `` + prefix = `` } } let suffix = node.hook(suffixInjector, path, mounter) || '' diff --git a/src/app/hooks/suffixInjector.ts b/src/app/hooks/suffixInjector.ts index c85cfb49..781454d5 100644 --- a/src/app/hooks/suffixInjector.ts +++ b/src/app/hooks/suffixInjector.ts @@ -2,7 +2,7 @@ import { Hook, ModelPath, Path } from '@mcschema/core' import { App, Previews } from '../App' import { Octicon } from '../components/Octicon' import { locale } from '../Locales' -import { Mounter } from '../Mounter' +import { Mounter } from '../views/View' import { BiomeNoisePreview } from '../preview/BiomeNoisePreview' import { Preview } from '../preview/Preview' import { Tracker } from '../Tracker' @@ -32,7 +32,7 @@ export const suffixInjector: Hook<[Mounter], string | void> = { && path.pop().pop().endsWith(new Path(['generator', 'biome_source', 'biomes']))) { const biomePreview = Previews.biome_noise as BiomeNoisePreview const biome = path.get() - const id = mounter.registerChange(el => { + const id = mounter.onChange(el => { biomePreview.setBiomeColor(biome, (el as HTMLInputElement).value) }) return `` @@ -41,7 +41,7 @@ export const suffixInjector: Hook<[Mounter], string | void> = { } function setPreview(preview: Preview, path: ModelPath, mounter: Mounter) { - const id = mounter.registerClick(() => { + const id = mounter.onClick(() => { Tracker.setPreview(preview.getName()) preview.path = path App.preview.set(preview) diff --git a/src/app/views/View.ts b/src/app/views/View.ts index bfb1ea55..690110fc 100644 --- a/src/app/views/View.ts +++ b/src/app/views/View.ts @@ -1,7 +1,15 @@ import { locale } from "../Locales" import { hexId } from "../Utils" -export class View { + +export interface Mounter { + register(callback: (el: Element) => void): string + onChange(callback: (el: Element) => void): string + onClick(callback: (el: Element) => void): string + mounted(el: Element, clear?: boolean): void +} + +export class View implements Mounter{ private registry: { [id: string]: (el: Element) => void } = {} render(): string { @@ -42,7 +50,7 @@ export class View { if (clear) { this.registry = {} } - document.querySelectorAll('[data-i18n]').forEach(el => { + el.querySelectorAll('[data-i18n]').forEach(el => { el.textContent = locale(el.attributes.getNamedItem('data-i18n')!.value) }) }