Skip to content

Commit b90836e

Browse files
committed
fixed methods and events reconciliation
1 parent 29904fd commit b90836e

5 files changed

Lines changed: 56 additions & 41 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "modular-openscriptjs",
3-
"version": "2.0.8",
3+
"version": "2.0.9",
44
"description": "OpenScriptJs Framework - A lightweight, reactive JavaScript framework for building modern web applications",
55
"type": "module",
66
"main": "./dist/modular-openscriptjs.umd.js",

src/component/Component.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ export default class Component {
219219

220220
this.releaseMemory();
221221
this.unmounted = true;
222+
this.emit(this.EVENTS.unmounted);
222223

223224
return true;
224225
}
@@ -510,7 +511,7 @@ export default class Component {
510511

511512
this.emit(this.EVENTS.rendered, this.id);
512513

513-
if (parent && parent.isConnected) {
514+
if (parent && parent.isConnected && this.mounted == false) {
514515
this.emit(this.EVENTS.mounted, this.id);
515516
}
516517

src/component/DOMReconciler.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { container } from "../core/Container";
2-
import { destroyNodeDeep, removeDomMethod } from "../utils/helpers";
2+
import {
3+
destroyNodeDeep,
4+
indirectEventHandler,
5+
registerDomListeners,
6+
removeDomMethod,
7+
} from "../utils/helpers";
38

49
/**
510
* DOMReconciler Class
@@ -92,20 +97,20 @@ export default class DOMReconciler {
9297
}
9398

9499
replaceEventListeners(targetNode, sourceNode) {
95-
const events = this.getEventListeners(targetNode);
96-
97-
for (const [eventName, listeners] of events) {
98-
listeners.forEach((listener) => {
99-
targetNode.removeListener(eventName, listener);
100-
});
100+
if (targetNode.removeAllListeners) {
101+
targetNode.removeAllListeners();
101102
}
102103

103104
const sourceEvents = this.getEventListeners(sourceNode);
104105

105106
for (const [eventName, listeners] of sourceEvents) {
106107
listeners.forEach((listener) => {
107-
targetNode.addListener(eventName, listener);
108+
registerDomListeners(targetNode, eventName, listener);
108109
});
110+
111+
if (targetNode.addListener) {
112+
targetNode.addListener(eventName, indirectEventHandler);
113+
}
109114
}
110115
}
111116

@@ -122,6 +127,9 @@ export default class DOMReconciler {
122127
container.resolve("repository").domMethods.set(targetNode, targetMethods);
123128
}
124129

130+
// remove all previous methods
131+
container.resolve("repository").domMethods.get(targetNode)?.clear();
132+
125133
for (const [name, fn] of methodsMap) {
126134
removeDomMethod(targetNode, name);
127135
targetMethods.set(name, fn);

src/component/MarkupEngine.js

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import Utils from "../utils/Utils.js";
33
import Component from "./Component.js";
44
import State from "../core/State.js";
55
import { container } from "../core/Container.js";
6-
import { defineDomMethod, indirectEventHandler, isClass } from "../utils/helpers.js";
6+
import {
7+
defineDomMethod,
8+
indirectEventHandler,
9+
isClass,
10+
registerDomListeners,
11+
} from "../utils/helpers.js";
712

813
/**
914
* Base Markup Engine Class
@@ -37,13 +42,13 @@ export default class MarkupEngine {
3742
registerComponent = (name, componentClass) => {
3843
if (!(typeof name === "string")) {
3944
throw Error(
40-
`MarkupEngine.Exception: A Component's name must be a string: type '${typeof name}' given`
45+
`MarkupEngine.Exception: A Component's name must be a string: type '${typeof name}' given`,
4146
);
4247
}
4348

4449
if (!(componentClass.prototype instanceof Component)) {
4550
throw new Error(
46-
`MarkupEngine.Exception: The component for ${name} must be an Component component. ${componentClass.name} given`
51+
`MarkupEngine.Exception: The component for ${name} must be an Component component. ${componentClass.name} given`,
4752
);
4853
}
4954

@@ -83,7 +88,7 @@ export default class MarkupEngine {
8388
if (this.hasComponent(name)) return true;
8489

8590
console.warn(
86-
`MarkupEngine.Warn: Trying to ${method} an unregistered component {${name}}. Please ensure that the component is registered by using h.has(componentName)`
91+
`MarkupEngine.Warn: Trying to ${method} an unregistered component {${name}}. Please ensure that the component is registered by using h.has(componentName)`,
8792
);
8893

8994
return false;
@@ -105,7 +110,8 @@ export default class MarkupEngine {
105110
// remove the listener from the event map in the repository
106111
// since for each event, there is only the indirect event handler
107112
// listening to that event.
108-
let eventMap = container.resolve("repository").domListeners.get(this) ?? new Map();
113+
let eventMap =
114+
container.resolve("repository").domListeners.get(this) ?? new Map();
109115

110116
let listeners = eventMap.get(event) ?? new Set();
111117

@@ -124,7 +130,9 @@ export default class MarkupEngine {
124130
};
125131

126132
element.getEventListeners = function () {
127-
return container.resolve("repository").domListeners.get(this) ?? new Map();
133+
return (
134+
container.resolve("repository").domListeners.get(this) ?? new Map()
135+
);
128136
};
129137

130138
element.toString = function () {
@@ -135,7 +143,8 @@ export default class MarkupEngine {
135143
let methods = {};
136144

137145
// get the methods from the repository
138-
let methodsMap = container.resolve("repository").domMethods.get(this) ?? new Map();
146+
let methodsMap =
147+
container.resolve("repository").domMethods.get(this) ?? new Map();
139148

140149
for (let [k, v] of methodsMap) {
141150
methods[k] = v;
@@ -149,6 +158,7 @@ export default class MarkupEngine {
149158
this.removeEventListener(event, indirectEventHandler);
150159
});
151160
this.__eventListeners?.clear();
161+
container.resolve("repository").domListeners.get(this)?.clear();
152162
};
153163

154164
element.__openscript_cleanup__ = () => {
@@ -180,7 +190,7 @@ export default class MarkupEngine {
180190
handle = (name, ...args) => {
181191
if (!(typeof name === "string")) {
182192
throw Error(
183-
`MarkupEngine.Exception: A Component's name must be a string: type '${typeof name}' given`
193+
`MarkupEngine.Exception: A Component's name must be a string: type '${typeof name}' given`,
184194
);
185195
}
186196

@@ -213,7 +223,6 @@ export default class MarkupEngine {
213223
return cmp.wrap(...args);
214224
}
215225

216-
217226
/**
218227
* @type {DocumentFragment|HTMLElement}
219228
*/
@@ -285,7 +294,7 @@ export default class MarkupEngine {
285294
if (k === "listeners") {
286295
if (typeof v !== "object") {
287296
throw TypeError(
288-
`The value of 'listeners' should be an object. but found ${typeof v}`
297+
`The value of 'listeners' should be an object. but found ${typeof v}`,
289298
);
290299
}
291300

@@ -294,12 +303,12 @@ export default class MarkupEngine {
294303

295304
if (Array.isArray(listener)) {
296305
listener.forEach((l) => {
297-
this.registerDomListeners(root, evt, l);
306+
registerDomListeners(root, evt, l);
298307
});
299308

300309
root.addListener(evt, indirectEventHandler);
301310
} else {
302-
this.registerDomListeners(root, evt, listener);
311+
registerDomListeners(root, evt, listener);
303312
root.addListener(evt, indirectEventHandler);
304313
}
305314
}
@@ -310,10 +319,10 @@ export default class MarkupEngine {
310319
if (k === "methods") {
311320
if (typeof v !== "object") {
312321
throw TypeError(
313-
`The value of 'methods' attribute should be an object. but found ${typeof v}`
322+
`The value of 'methods' attribute should be an object. but found ${typeof v}`,
314323
);
315324
}
316-
325+
317326
let methodMap = container.resolve("repository").domMethods.get(root);
318327
if (!methodMap) {
319328
methodMap = new Map();
@@ -346,7 +355,7 @@ export default class MarkupEngine {
346355
`MarkupEngine.ParseAttribute.Exception: `,
347356
e,
348357
`. Attributes resulting in the error: `,
349-
obj
358+
obj,
350359
);
351360
throw Error(e);
352361
}
@@ -444,7 +453,7 @@ export default class MarkupEngine {
444453
f = () => {
445454
const h = container.resolve("h");
446455
return h["ojs-group"]();
447-
}
456+
},
448457
) => {
449458
return f();
450459
};
@@ -522,17 +531,4 @@ export default class MarkupEngine {
522531
toElement = (value) => {
523532
return value;
524533
};
525-
526-
registerDomListeners = (node, event, listener) => {
527-
let eventMap = container.resolve("repository").domListeners.get(node);
528-
529-
if (!eventMap) {
530-
eventMap = new Map();
531-
container.resolve("repository").domListeners.set(node, eventMap);
532-
}
533-
534-
let listeners = eventMap.get(event) ?? new Set();
535-
listeners.add(listener);
536-
eventMap.set(event, listeners);
537-
};
538534
}

src/utils/helpers.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ export function cleanupDisconnectedComponents() {
7878
const repo = container.resolve("repository");
7979

8080
for (const [id, component] of repo.components) {
81-
82-
if(!component?.mounted === true) continue;
81+
if (!component?.mounted === true) continue;
8382

8483
let markups = component.markup();
8584

@@ -94,4 +93,15 @@ export function getOjsChildren(parent) {
9493
return parent?.querySelectorAll(".__ojs-c-class__") ?? [];
9594
}
9695

96+
export function registerDomListeners(node, event, listener) {
97+
let eventMap = container.resolve("repository").domListeners.get(node);
98+
99+
if (!eventMap) {
100+
eventMap = new Map();
101+
container.resolve("repository").domListeners.set(node, eventMap);
102+
}
97103

104+
let listeners = eventMap.get(event) ?? new Set();
105+
listeners.add(listener);
106+
eventMap.set(event, listeners);
107+
}

0 commit comments

Comments
 (0)