commit:9ba078f713b5a834ae1baa5e7c44691121ec30c0
author:Chip Black
committer:Chip Black
date:Sat Oct 27 21:56:33 2018 -0500
parents:5c8fe730e106cdf6ebf166efac9b6592dad73db3
Make editor slightly cleaner with FragmentManager
diff --git a/src/editor.ts b/src/editor.ts
line changes: +25/-22
index b2b367f..a53152a
--- a/src/editor.ts
+++ b/src/editor.ts
@@ -1,5 +1,6 @@
 import { Cell } from './cell';
 import { GameEvent, GameEventType } from './event';
+import FragmentManager from './fragmentmanager';
 
 export type EditorCallback = (cell: Cell) => void;
 
@@ -7,7 +8,7 @@ export default class Editor {
     container: HTMLDivElement
     titleRef: HTMLInputElement
     descriptionRef: HTMLTextAreaElement
-    eventListRef: HTMLDivElement
+    events: FragmentManager[]
     cell: Cell
 
     onClose: (cell: Cell) => void
@@ -23,7 +24,7 @@ export default class Editor {
 
         const addEventButton = document.getElementById('add-event');
         addEventButton.addEventListener('click', this.addEventHandler.bind(this));
-        this.eventListRef = <HTMLDivElement>document.getElementById('event-list');
+        this.events = []
 
         const closeButton = document.getElementById('editor-close');
         closeButton.addEventListener('click', this.closeHandler.bind(this));
@@ -34,9 +35,6 @@ export default class Editor {
         this.titleRef.value = cell.title;
         this.descriptionRef.value = cell.description;
 
-        while (this.eventListRef.firstChild)
-            this.eventListRef.removeChild(this.eventListRef.firstChild);
-
         for (let [k, e] of cell.events) {
             this.addEvent(e);
         }
@@ -49,9 +47,7 @@ export default class Editor {
     }
 
     addEvent(event?: GameEvent) {
-        const eventForm = document.createElement('div');
-        eventForm.className = 'vflex';
-        eventForm.innerHTML = `
+        const eventForm = new FragmentManager(`
             <h3>ID</h3>
             <input name="id">
             <h3>Type</h3>
@@ -68,24 +64,27 @@ export default class Editor {
             <div>
                 <button name="delete">Delete Event</button>
             </div>
-        `;
-        this.eventListRef.appendChild(eventForm);
+        `, 'div', { className: 'vflex' });
+        eventForm.mount('event-list');
+        this.events.push(eventForm);
 
-        const deleteButton = eventForm.querySelector('[name=delete]');
+        const deleteButton = eventForm.q('[name=delete]');
         deleteButton.addEventListener('click', () => {
-            this.eventListRef.removeChild(eventForm);
+            eventForm.unmount();
+            const i = this.events.indexOf(eventForm);
+            this.events.splice(i, 1);
         });
 
         if (!event) {
             event = new GameEvent();
         }
-        (<HTMLInputElement>eventForm.querySelector('[name=id]'))
+        (<HTMLInputElement>eventForm.q('[name=id]'))
             .value = event.id;
-        (<HTMLSelectElement>eventForm.querySelector('[name=type]'))
+        (<HTMLSelectElement>eventForm.q('[name=type]'))
             .value = event.type.toString();
-        (<HTMLInputElement>eventForm.querySelector('[name=title]'))
+        (<HTMLInputElement>eventForm.q('[name=title]'))
             .value = event.title;
-        (<HTMLTextAreaElement>eventForm.querySelector('[name=script]'))
+        (<HTMLTextAreaElement>eventForm.q('[name=script]'))
             .value = event.script;
     }
 
@@ -99,12 +98,11 @@ export default class Editor {
 
         // We recreate all of the cell's events to make sure we remove any deleted ones
         this.cell.events.clear();
-        for (let i = 0; i < this.eventListRef.children.length; i++) {
-            const eventForm = this.eventListRef.children[i];
-            const id = (<HTMLInputElement>eventForm.querySelector('[name=id]')).value;
-            const type = <GameEventType>parseInt((<HTMLInputElement>eventForm.querySelector('[name=type]')).value);
-            const title = (<HTMLInputElement>eventForm.querySelector('[name=title]')).value;
-            const script = (<HTMLInputElement>eventForm.querySelector('[name=script]')).value;
+        for (let eventForm of this.events) {
+            const id = (<HTMLInputElement>eventForm.q('[name=id]')).value;
+            const type = <GameEventType>parseInt((<HTMLInputElement>eventForm.q('[name=type]')).value);
+            const title = (<HTMLInputElement>eventForm.q('[name=title]')).value;
+            const script = (<HTMLInputElement>eventForm.q('[name=script]')).value;
 
             const e = new GameEvent();
 
@@ -115,6 +113,11 @@ export default class Editor {
 
             this.cell.events.set(id, e);
         }
+
+        for (let ev of this.events)
+            ev.unmount();
+        this.events = [];
+
         if (this.onClose) {
             this.onClose(this.cell);
             this.onClose = null;

diff --git a/src/fragmentmanager.ts b/src/fragmentmanager.ts
line changes: +35/-0
index 0000000..73bb779
--- /dev/null
+++ b/src/fragmentmanager.ts
@@ -0,0 +1,35 @@
+interface TagProperties {
+    [key: string]: string
+}
+
+export default class FragmentManager {
+    elem: HTMLElement
+
+    constructor(html: string, tagName: string = 'div', tagProperties: TagProperties = {}) {
+        this.elem = document.createElement(tagName);
+        for (let k of Object.keys(tagProperties)) {
+            this.elem.setAttribute(k, tagProperties[k]);
+        }
+        this.elem.innerHTML = html;
+    }
+
+    mount(destNode: string | HTMLElement) {
+        if (typeof destNode == 'string') {
+            destNode = document.getElementById(destNode);
+            if (!destNode) {
+                throw new Error('Could not find destination node ' + destNode);
+            }
+        }
+
+        destNode.appendChild(this.elem);
+    }
+
+    unmount() {
+        if (this.elem.parentNode)
+            this.elem.parentNode.removeChild(this.elem);
+    }
+
+    q(query: string) {
+        return this.elem.querySelector(query);
+    }
+}