Skip to content

Commit

Permalink
imp: project
Browse files Browse the repository at this point in the history
  • Loading branch information
Tardo committed Jan 7, 2024
1 parent 24aa3e2 commit 0b24e91
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 95 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ import {Component} from 'mirlo';
export default class Demo01 extends Component {
useServices = ['requests']; // Mandatory due to fetchData usage

onWillStart() {
async onWillStart() {
this.fetchData.chart = {
endpoint: '/get_demo01_data',
data: {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mirlo",
"version": "0.1.4",
"version": "0.1.5",
"type": "module",
"keywords": [
"initiator",
Expand Down
84 changes: 28 additions & 56 deletions src/js/base/app.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import domAddEventListener from '../utils/dom_add_event_listener.mjs';
import domRemoveEventListener from '../utils/dom_remove_event_listener.mjs';
import domGetComponentObj from '../utils/dom_get_component_object';
import Component from './component.mjs';

Expand Down Expand Up @@ -27,8 +25,6 @@ class App extends Component {
Object.values(this.#services).forEach(service => service.destroy());
this.#services = [];
this.#observer.disconnect();
domRemoveEventListener('click', "[class~='dropdown']");
domRemoveEventListener('click', '[data-dismiss]');
}

registerComponent(name, component) {
Expand Down Expand Up @@ -85,18 +81,6 @@ class App extends Component {
childList: true,
subtree: true,
});

// Assign core event
domAddEventListener(
'click',
"[class~='dropdown']",
this.#onCoreClickDropdown.bind(this),
);
domAddEventListener(
'click',
'[data-dismiss]',
this.#onCoreClickDismiss.bind(this),
);
}

#initializeServices() {
Expand All @@ -109,19 +93,31 @@ class App extends Component {
const service_names = Object.keys(this.#services);
for (const service_name of service_names) {
const service = this.#services[service_name];
tasks.push(service.onWillStart());
tasks.push(service.onInit());
}
return Promise.all(tasks);
}

#instantiateComponent(name, ...args) {
const component_cls = this.getComponentClass(name);
async mountComponent(component_name, node) {
const component_cls = this.getComponentClass(component_name);
if (component_cls) {
const component = new component_cls(...args);
const parent_component = node.closest('[data-component]');
const parent_component_obj = domGetComponentObj(parent_component);
const component = new component_cls(
parent_component_obj || this,
node,
this.#getNodeComponentOptions(node),
);
this.#assignServices(component);
return component.onWillStart().then(() => component.onStart());
await component.onWillStart();
component.onStart();
} else {
throw Error(`Can't found the '${component_name}' component!`);
}
return Promise.reject(`Can't found the '${name}' component!`);
}

unmountComponent(node) {
domGetComponentObj(node)?.destroy();
}

#getNodeComponentOptions(dom_el) {
Expand All @@ -139,22 +135,11 @@ class App extends Component {

#initializeComponents(nodes) {
const tasks = [];
for (const dom_el of nodes) {
if (domGetComponentObj(dom_el)) {
continue;
nodes.forEach(dom_el => {
if (!domGetComponentObj(dom_el)) {
tasks.push(this.mountComponent(dom_el.dataset.component, dom_el));
}
const component_name = dom_el.dataset.component;
const parent_component = dom_el.closest('[data-component]');
const parent_component_obj = domGetComponentObj(parent_component);
tasks.push(
this.#instantiateComponent(
component_name,
parent_component_obj || this,
dom_el,
this.#getNodeComponentOptions(dom_el),
),
);
}
});
return Promise.all(tasks);
}

Expand All @@ -165,22 +150,18 @@ class App extends Component {
}

#traverseNodeListRemoved(node) {
if (node.children) {
for (const cnode of node.children) {
this.#traverseNodeListRemoved(cnode);
}
for (const cnode of node.children) {
this.#traverseNodeListRemoved(cnode);
}
domGetComponentObj(node)?.onDestroy();
domGetComponentObj(node)?.onRemove();
}

#traverseNodeListAdded(node, node_list) {
if (Object.hasOwn(node.dataset, 'component')) {
if (node.dataset.component) {
node_list.push(node);
}
if (node.children) {
for (const cnode of node.children) {
this.#traverseNodeListAdded(cnode, node_list);
}
for (const cnode of node.children) {
this.#traverseNodeListAdded(cnode, node_list);
}
}

Expand Down Expand Up @@ -213,15 +194,6 @@ class App extends Component {
);
}
}

#onCoreClickDropdown(ev) {
this.query(ev.currentTarget.dataset.target).classList.toggle('hidden');
}

#onCoreClickDismiss(ev) {
const classname = `.${ev.currentTarget.datatset.dismiss}`;
ev.currentTarget.closest(classname).remove();
}
}

export const app = new App(null, document.body);
39 changes: 19 additions & 20 deletions src/js/base/component.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@ export default class {
this.state = new Proxy(this.#root_state, state_handler);
}

onWillStart() {
if (
Object.keys(this.fetchData).length &&
this.useServices.indexOf('requests') === -1
) {
async onWillStart() {
const fetch_entries = Object.entries(this.fetchData);
if (fetch_entries.length && !this.requests) {
throw Error("Need 'requests' service to use 'fetchData'");
}
return Promise.all(
Object.entries(this.fetchData).map(([key, value]) =>
return await Promise.all(
fetch_entries.map(([key, value]) =>
this.requests.postJSON(value.endpoint, value.data).then(result => {
this.data[key] = result;
return result;
Expand All @@ -48,18 +46,8 @@ export default class {
});
}

onDestroy() {
this.#childrens = [];
for (const cevent in this.events) {
const [event_name, ...event_rest] = cevent.split(' ');
const event_target = (event_rest && event_rest.join(' ')) || null;
const dom_target =
(event_target && this.query(event_target)) || this.dom_el;
dom_target.removeEventListener(
event_name,
this.events[cevent].bind(this),
);
}
onRemove() {
// Override me
}

onStateChanged(prop, new_value) {
Expand Down Expand Up @@ -89,7 +77,18 @@ export default class {
}

destroy() {
this.dom_el.remove();
this.#childrens.forEach(component => component.destroy());
this.#childrens = [];
for (const cevent in this.events) {
const [event_name, ...event_rest] = cevent.split(' ');
const event_target = (event_rest && event_rest.join(' ')) || null;
const dom_target =
(event_target && this.query(event_target)) || this.dom_el;
dom_target.removeEventListener(
event_name,
this.events[cevent].bind(this),
);
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/js/base/service.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export default class {
onWillStart() {
return Promise.resolve();
async onInit() {
return true;
}

destroy() {
throw Error('Not Implemented!');
// Override me
}
}
5 changes: 0 additions & 5 deletions src/js/utils/dom_add_event_listener.mjs

This file was deleted.

5 changes: 0 additions & 5 deletions src/js/utils/dom_remove_event_listener.mjs

This file was deleted.

4 changes: 2 additions & 2 deletions tests/components/test01.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ export default class Test01 extends Component {
click: this.#onClick,
};

onDestroy() {
super.onDestroy();
onRemove() {
super.onRemove();
++window.comp_rmv_count;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/components/test02.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class ServiceTest02 extends Service {
export class Test02 extends Component {
useServices = ['requests', 'servTest02'];

onWillStart() {
async onWillStart() {
this.fetchData.ipify = {endpoint: 'https://api.ipify.org/?format=json'};
return super.onWillStart(...arguments);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/mirlo.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ test('on-fly component initialization', async () => {
new_div_comp.dataset.component = 'test01';
new_div.appendChild(new_div_comp);
document.getElementById('containerC').appendChild(new_div);
await new Promise(process.nextTick); // flush promises
await waitRAF();
await new Promise(process.nextTick); // flush promises
expect(screen.getByText('Hello World!')).toBeVisible();
expect(screen.getByText('Clicked!')).toBeVisible();
});
Expand Down

0 comments on commit 0b24e91

Please sign in to comment.