This repository has been archived by the owner on Feb 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmoduler2.mjs
127 lines (110 loc) · 3.52 KB
/
moduler2.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
let path = {};
export const moduler2 = function (settings) {
path = settings.path;
loadModules(settings.element || document.body);
detectDomChanges();
};
const loadModules = (node) => {
const elements = node.querySelectorAll("[data-module]");
// Iterate all nodes with a data-module attribute
for (let element of elements) {
let names = element.getAttribute("data-module").split(" ");
// Iterate all module names in current data-module attribute
for (let name of names) {
addModuleToElement(name, element);
}
}
};
const addModuleToElement = (name, element) => {
// Abort if module is already initialized on the element
if (element._modules && element._modules[name]) {
return;
}
// Dynamicly import module
import(path + name + ".js")
.then((Module) => {
if (Module) {
// Add empty object to element property with module name as the key
element._modules
? (element._modules[name] = {})
: (element._modules = { [name]: {} });
// Create module
element._modules[name] = new Module[toPascalCase(name)](
parseData(element.getAttribute("data-" + name))
);
element._modules[name].element = element;
element._modules[name].init();
}
})
.catch(console.error);
};
const removeModuleFromElement = (name, element) => {
// Make sure module is loaded on element
if (element._modules[name]) {
// Run destroy method to remove stuff like attached events
if (element._modules[name].destroy) {
element._modules[name].destroy();
}
// Remove module name from element module-attribute
if (element.getAttribute("module")) {
element.setAttribute(
"module",
element.getAttribute("module").replace(name, "")
);
}
// Remove module-named object from element object
delete element._modules[name];
}
};
const detectDomChanges = () => {
// Callback function to execute when mutations are observed
const callback = function (mutationsList) {
for (let mutation of mutationsList) {
// Node is added to DOM
if (mutation.addedNodes.length) {
// Look for new modules
for (let node of mutation.addedNodes) {
loadModules(node);
}
}
// Node is removed from DOM
if (mutation.removedNodes.length) {
for (let node of mutation.removedNodes) {
// If element had modules attached to it
if (node.getAttribute("data-module").length) {
for (let name in node.modules) {
removeModuleFromElement(name, node);
}
}
}
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(document.body, { childList: true });
};
const parseData = (data) => {
if (!data) {
return {};
} else if (data[0] === "{") {
// Is using JSON syntax
// Replace single-quote character with double quotes
return JSON.parse(data.replace(/'/g, '"'));
} else {
// Wrap all property names with quotes and replace single-quote character with double quotes
return JSON.parse(
"{" +
data
.replace(
/([\w\-$]+):(?:|\s|\d|false|true|null|undefined|\{|\[|\"|\')/gi,
'"$1":'
)
.replace(/'/g, '"') +
"}"
);
}
};
const toPascalCase = (value) =>
value.replace(/(?:^|[\s-])(\w)/g, (matches, letter) => letter.toUpperCase());