saloe 0.0.90 → 0.0.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/listener.cjs.js +285 -202
- package/dist/listener.es.js +285 -202
- package/package.json +1 -1
- package/src/constants.js +18 -18
package/dist/listener.cjs.js
CHANGED
|
@@ -1,209 +1,292 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
const LISTENER_SCRIPT = `({
|
|
4
|
+
SRC_ELEMEMENTS_QUERY = [],
|
|
5
|
+
listenAfterMs = 2_500,
|
|
6
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
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
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
|
-
|
|
7
|
+
const EVENTS_PREVENT_DEFAULT_MANDATORY = [
|
|
8
|
+
'submit'
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const EVENTS = [
|
|
12
|
+
'mouseover',
|
|
13
|
+
'click',
|
|
14
|
+
'submit',
|
|
15
|
+
'input',
|
|
16
|
+
'blur',
|
|
17
|
+
'change',
|
|
18
|
+
'focus',
|
|
19
|
+
'invalid',
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
const addListener = ({ srcElement, eventName, listeners, afterExecuteListeners }) => {
|
|
23
|
+
srcElement?.addEventListener(eventName, (e) => {
|
|
24
|
+
executeListeners({ e, srcElement, listeners, afterExecuteListeners })
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const executeListeners = async ({ e, srcElement, listeners, afterExecuteListeners }) => {
|
|
29
|
+
await Promise.all(
|
|
30
|
+
(listeners ?? []).map((listener) => {
|
|
31
|
+
if (listener) return listener({ e, srcElement })
|
|
32
|
+
})
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
if (afterExecuteListeners) await afterExecuteListeners()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const getListenerFromScript = ({ script, eventName }) => {
|
|
39
|
+
if (!script) return null
|
|
40
|
+
if (script[eventName]) return script[eventName]
|
|
41
|
+
const prev = Object.keys(script)?.find((key) => script[key][eventName])
|
|
42
|
+
if (!prev) return null
|
|
43
|
+
return script[prev][eventName]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const fetchListeners = async ({ srcElement, eventName, e }) => {
|
|
47
|
+
if (!srcElement?.getAttribute) return
|
|
48
|
+
|
|
49
|
+
const scriptNames = srcElement?.getAttribute(\`on-\${eventName}\`)
|
|
50
|
+
if (!scriptNames) return
|
|
51
|
+
|
|
52
|
+
if (e && scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(eventName)) e.preventDefault()
|
|
53
|
+
|
|
54
|
+
const scripts = await Promise.all(
|
|
55
|
+
scriptNames?.split(',')?.map((scriptName) => {
|
|
56
|
+
const scriptToImport = \`/\${scriptName?.trim()}.js\`
|
|
57
|
+
return importScriptDynamically({ path: scriptToImport })
|
|
58
|
+
})
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const listeners = scripts?.map((script) => getListenerFromScript({ script, eventName }))
|
|
62
|
+
|
|
63
|
+
return listeners
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const addScripts = () => {
|
|
67
|
+
const scriptsToLoad = [...document.querySelectorAll('script[data-script-to-load]')]
|
|
68
|
+
return Promise.all(
|
|
69
|
+
scriptsToLoad?.map((scriptToLoad) => {
|
|
70
|
+
const id = scriptToLoad?.getAttribute('data-script-to-load')
|
|
71
|
+
scriptToLoad.removeAttribute('data-script-to-load')
|
|
72
|
+
|
|
73
|
+
const attrs = scriptToLoad?.getAttributeNames()?.reduce((acc, attrName) => {
|
|
74
|
+
const attrValue = scriptToLoad.getAttribute(attrName)
|
|
75
|
+
if (attrValue !== 'text/script-to-load') acc[attrName] = attrValue
|
|
76
|
+
return acc
|
|
77
|
+
}, {})
|
|
78
|
+
|
|
79
|
+
const content = scriptToLoad?.textContent
|
|
80
|
+
|
|
81
|
+
scriptToLoad?.remove()
|
|
82
|
+
|
|
83
|
+
return loadScript({ id, attrs, content }).catch((err) => {
|
|
84
|
+
console.error(err)
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const loadScript = ({ id, attrs, content }) => {
|
|
91
|
+
const script = document?.createElement('script')
|
|
92
|
+
|
|
93
|
+
Object.keys(attrs)?.forEach((attrKey) => script?.setAttribute(attrKey, attrs[attrKey]))
|
|
94
|
+
script.id = id
|
|
95
|
+
script.type = 'module'
|
|
96
|
+
|
|
97
|
+
if (content) script?.insertAdjacentHTML('beforeend', content)
|
|
98
|
+
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
if (!attrs.src) {
|
|
101
|
+
resolve()
|
|
102
|
+
document?.body?.insertAdjacentElement('beforeend', script)
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
script.onload = script.onreadystatechange = function () {
|
|
107
|
+
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
|
|
108
|
+
resolve()
|
|
109
|
+
script.onload = script.onreadystatechange = null
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
script.onerror = () => {
|
|
114
|
+
console.error('script failed to load')
|
|
115
|
+
reject(new Error(\`Failed to load script with src \${script.src}\`))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
document?.body?.insertAdjacentElement('beforeend', script)
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// FIX: return import() to prevent __vitePreload to take action
|
|
123
|
+
const importScriptDynamically = ({ path }) => {
|
|
124
|
+
return import(path)?.catch((err) => { })
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// load
|
|
128
|
+
const fireLoadListener = () => {
|
|
129
|
+
const eventName = 'load'
|
|
130
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
131
|
+
|
|
132
|
+
srcElements?.forEach(async (srcElement) => {
|
|
133
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
134
|
+
executeListeners({ e: null, srcElement, listeners })
|
|
135
|
+
|
|
136
|
+
srcElement?.removeAttribute(\`on-\${eventName}\`)
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// invalid
|
|
141
|
+
const fireInvalidListener = () => {
|
|
142
|
+
const eventName = 'invalid'
|
|
143
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
144
|
+
|
|
145
|
+
srcElements?.forEach(async (srcElement) => {
|
|
146
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
147
|
+
addListener({ srcElement, eventName, listeners })
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// blur
|
|
152
|
+
const fireBlurListener = () => {
|
|
153
|
+
const eventName = 'blur'
|
|
154
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
155
|
+
|
|
156
|
+
srcElements?.forEach(async (srcElement) => {
|
|
157
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
158
|
+
addListener({ srcElement, eventName, listeners })
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// focus
|
|
163
|
+
const fireFocusListener = () => {
|
|
164
|
+
const eventName = 'focus'
|
|
165
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
166
|
+
|
|
167
|
+
srcElements?.forEach(async (srcElement) => {
|
|
168
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
169
|
+
addListener({ srcElement, eventName, listeners })
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// observers
|
|
174
|
+
const fireObserverListeners = () => {
|
|
175
|
+
const srcElements = [...document.querySelectorAll('[on-observe]')]
|
|
176
|
+
|
|
177
|
+
const uniqueScriptNames = [...srcElements?.reduce((acc, srcElement) => {
|
|
178
|
+
const attribute = srcElement?.getAttribute('on-observe')
|
|
179
|
+
if (attribute === 'undefined') return acc
|
|
180
|
+
|
|
181
|
+
const scriptNames = attribute?.split(',')
|
|
182
|
+
scriptNames?.forEach((scriptName) => acc?.set(scriptName, 1))
|
|
183
|
+
|
|
184
|
+
return acc
|
|
185
|
+
}, new Map())?.keys()]
|
|
186
|
+
|
|
187
|
+
uniqueScriptNames?.forEach(async (scriptName) => {
|
|
188
|
+
const observedSrcElements = document.querySelectorAll(\`[on-observe*="\${scriptName}"]\`)
|
|
189
|
+
|
|
190
|
+
const script = await importScriptDynamically({ path: \`/\${scriptName?.trim()}.js\` })
|
|
191
|
+
const listener = getListenerFromScript({ script, eventName: 'observe' })
|
|
192
|
+
if (!listener) return
|
|
193
|
+
|
|
194
|
+
const observer = new IntersectionObserver((entries) => {
|
|
195
|
+
entries.forEach((entry) => listener({ entry, observer }))
|
|
196
|
+
}, {
|
|
197
|
+
threshold: .5,
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
observedSrcElements?.forEach((observerSrcElement) => {
|
|
201
|
+
observer.observe(observerSrcElement)
|
|
202
|
+
|
|
203
|
+
const observerAttr = observerSrcElement?.getAttribute('on-observe')
|
|
204
|
+
const updatedObserverAttr = observerAttr?.replaceAll(scriptName + ', ', '')?.replaceAll(', ' + scriptName, '')?.replaceAll(scriptName, '')
|
|
205
|
+
|
|
206
|
+
if (!updatedObserverAttr) observerSrcElement.removeAttribute('on-observe')
|
|
207
|
+
else observerSrcElement.setAttribute('on-observe', updatedObserverAttr)
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const getSrcElement = ({ srcElement, eventName }) => {
|
|
213
|
+
if (!srcElement?.hasAttribute) return srcElement
|
|
214
|
+
const attribute = \`on-\${eventName}\`
|
|
215
|
+
const hasScriptName = srcElement?.hasAttribute(attribute)
|
|
216
|
+
if (hasScriptName) return srcElement
|
|
217
|
+
|
|
218
|
+
const query = \`:is(\${['a', 'button', ...SRC_ELEMEMENTS_QUERY].join(',')})[\${attribute}]\`
|
|
219
|
+
const closestButton = srcElement?.closest(query)
|
|
220
|
+
if (closestButton) return closestButton
|
|
221
|
+
|
|
222
|
+
return srcElement
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const cloneSrcElement = ({ srcElement }) => {
|
|
226
|
+
const newSrcElement = document.createElement(srcElement?.tagName)
|
|
227
|
+
|
|
228
|
+
Array.from(srcElement?.attributes).forEach((attr) => {
|
|
229
|
+
if (attr.name.startsWith('on-')) return
|
|
230
|
+
newSrcElement.setAttribute(attr.name, attr.value)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
return newSrcElement
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const isAnchorBeingClicked = ({ srcElement, eventName }) => {
|
|
237
|
+
return srcElement?.tagName === 'A' && eventName === 'click'
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const clickDefaultAnchor = ({ srcElement }) => {
|
|
241
|
+
const newAnchor = cloneSrcElement({ srcElement })
|
|
242
|
+
newAnchor.click()
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const fireListeners = () => {
|
|
246
|
+
EVENTS.forEach((eventName) => {
|
|
247
|
+
document.body[\`on\${eventName}\`] = async (e) => {
|
|
248
|
+
const srcElement = getSrcElement({ srcElement: e?.srcElement, eventName })
|
|
249
|
+
const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName })
|
|
250
|
+
|
|
251
|
+
if (isAnchorClicked) e.preventDefault()
|
|
252
|
+
|
|
253
|
+
const listeners = await fetchListeners({ srcElement, eventName, e })
|
|
254
|
+
const afterExecuteListeners = isAnchorClicked
|
|
255
|
+
? () => { clickDefaultAnchor({ srcElement }) }
|
|
256
|
+
: null
|
|
257
|
+
|
|
258
|
+
executeListeners({ e, srcElement, listeners, afterExecuteListeners })
|
|
259
|
+
addListener({ srcElement, eventName, listeners, afterExecuteListeners })
|
|
260
|
+
|
|
261
|
+
if (srcElement?.removeAttribute) srcElement.removeAttribute(\`on-\${eventName}\`)
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
const saloeListenEvent = new CustomEvent('saloeListen', {
|
|
266
|
+
detail: { message: 'This is a custom eventName!' }
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
document.body.addEventListener('saloeListen', async (e) => {
|
|
270
|
+
await addScripts()
|
|
271
|
+
fireLoadListener()
|
|
272
|
+
fireObserverListeners()
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
document.body.saloeListen = function () {
|
|
276
|
+
document.body.dispatchEvent(saloeListenEvent)
|
|
94
277
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
};
|
|
108
|
-
const fireLoadListener = () => {
|
|
109
|
-
const eventName = "load";
|
|
110
|
-
const srcElements = document == null ? void 0 : document.querySelectorAll(`[on-${eventName}]`);
|
|
111
|
-
srcElements == null ? void 0 : srcElements.forEach(async (srcElement) => {
|
|
112
|
-
const listeners = await fetchListeners({ srcElement, eventName, e: null });
|
|
113
|
-
executeListeners({ e: null, srcElement, listeners });
|
|
114
|
-
srcElement == null ? void 0 : srcElement.removeAttribute(`on-${eventName}`);
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
const fireObserverListeners = () => {
|
|
118
|
-
var _a;
|
|
119
|
-
const srcElements = [...document.querySelectorAll("[on-observe]")];
|
|
120
|
-
const uniqueScriptNames = [...(_a = srcElements == null ? void 0 : srcElements.reduce((acc, srcElement) => {
|
|
121
|
-
const attribute = srcElement == null ? void 0 : srcElement.getAttribute("on-observe");
|
|
122
|
-
if (attribute === "undefined") return acc;
|
|
123
|
-
const scriptNames = attribute == null ? void 0 : attribute.split(",");
|
|
124
|
-
scriptNames == null ? void 0 : scriptNames.forEach((scriptName) => acc == null ? void 0 : acc.set(scriptName, 1));
|
|
125
|
-
return acc;
|
|
126
|
-
}, /* @__PURE__ */ new Map())) == null ? void 0 : _a.keys()];
|
|
127
|
-
uniqueScriptNames == null ? void 0 : uniqueScriptNames.forEach(async (scriptName) => {
|
|
128
|
-
const observedSrcElements = document.querySelectorAll(`[on-observe*="${scriptName}"]`);
|
|
129
|
-
const script = await importScriptDynamically({ path: `/${scriptName == null ? void 0 : scriptName.trim()}.js` });
|
|
130
|
-
const listener2 = getListenerFromScript({ script, eventName: "observe" });
|
|
131
|
-
if (!listener2) return;
|
|
132
|
-
const observer = new IntersectionObserver((entries) => {
|
|
133
|
-
entries.forEach((entry) => listener2({ entry, observer }));
|
|
134
|
-
}, {
|
|
135
|
-
threshold: 0.5
|
|
136
|
-
});
|
|
137
|
-
observedSrcElements == null ? void 0 : observedSrcElements.forEach((observerSrcElement) => {
|
|
138
|
-
var _a2, _b;
|
|
139
|
-
observer.observe(observerSrcElement);
|
|
140
|
-
const observerAttr = observerSrcElement == null ? void 0 : observerSrcElement.getAttribute("on-observe");
|
|
141
|
-
const updatedObserverAttr = (_b = (_a2 = observerAttr == null ? void 0 : observerAttr.replaceAll(scriptName + ", ", "")) == null ? void 0 : _a2.replaceAll(", " + scriptName, "")) == null ? void 0 : _b.replaceAll(scriptName, "");
|
|
142
|
-
if (!updatedObserverAttr) observerSrcElement.removeAttribute("on-observe");
|
|
143
|
-
else observerSrcElement.setAttribute("on-observe", updatedObserverAttr);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
};
|
|
147
|
-
const getSrcElement = ({ srcElement, eventName }) => {
|
|
148
|
-
if (!(srcElement == null ? void 0 : srcElement.hasAttribute)) return srcElement;
|
|
149
|
-
const attribute = `on-${eventName}`;
|
|
150
|
-
const hasScriptName = srcElement == null ? void 0 : srcElement.hasAttribute(attribute);
|
|
151
|
-
if (hasScriptName) return srcElement;
|
|
152
|
-
const query = `:is(${["a", "button", ...SRC_ELEMEMENTS_QUERY].join(",")})[${attribute}]`;
|
|
153
|
-
const closestButton = srcElement == null ? void 0 : srcElement.closest(query);
|
|
154
|
-
if (closestButton) return closestButton;
|
|
155
|
-
return srcElement;
|
|
156
|
-
};
|
|
157
|
-
const cloneSrcElement = ({ srcElement }) => {
|
|
158
|
-
const newSrcElement = document.createElement(srcElement == null ? void 0 : srcElement.tagName);
|
|
159
|
-
Array.from(srcElement == null ? void 0 : srcElement.attributes).forEach((attr) => {
|
|
160
|
-
if (attr.name.startsWith("on-")) return;
|
|
161
|
-
newSrcElement.setAttribute(attr.name, attr.value);
|
|
162
|
-
});
|
|
163
|
-
return newSrcElement;
|
|
164
|
-
};
|
|
165
|
-
const isAnchorBeingClicked = ({ srcElement, eventName }) => {
|
|
166
|
-
return (srcElement == null ? void 0 : srcElement.tagName) === "A" && eventName === "click";
|
|
167
|
-
};
|
|
168
|
-
const clickDefaultAnchor = ({ srcElement }) => {
|
|
169
|
-
const newAnchor = cloneSrcElement({ srcElement });
|
|
170
|
-
newAnchor.click();
|
|
171
|
-
};
|
|
172
|
-
const fireListeners = () => {
|
|
173
|
-
EVENTS.forEach((eventName) => {
|
|
174
|
-
document.body[`on${eventName}`] = async (e) => {
|
|
175
|
-
const srcElement = getSrcElement({ srcElement: e == null ? void 0 : e.srcElement, eventName });
|
|
176
|
-
const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName });
|
|
177
|
-
if (isAnchorClicked) e.preventDefault();
|
|
178
|
-
const listeners = await fetchListeners({ srcElement, eventName, e });
|
|
179
|
-
const afterExecuteListeners = isAnchorClicked ? () => {
|
|
180
|
-
clickDefaultAnchor({ srcElement });
|
|
181
|
-
} : null;
|
|
182
|
-
executeListeners({ e, srcElement, listeners, afterExecuteListeners });
|
|
183
|
-
addListener({ srcElement, eventName, listeners, afterExecuteListeners });
|
|
184
|
-
if (srcElement == null ? void 0 : srcElement.removeAttribute) srcElement.removeAttribute(`on-${eventName}`);
|
|
185
|
-
};
|
|
186
|
-
});
|
|
187
|
-
const saloeListenEvent = new CustomEvent("saloeListen", {
|
|
188
|
-
detail: { message: "This is a custom eventName!" }
|
|
189
|
-
});
|
|
190
|
-
document.body.addEventListener("saloeListen", async (e) => {
|
|
191
|
-
await addScripts();
|
|
192
|
-
fireLoadListener();
|
|
193
|
-
fireObserverListeners();
|
|
194
|
-
});
|
|
195
|
-
document.body.saloeListen = function() {
|
|
196
|
-
document.body.dispatchEvent(saloeListenEvent);
|
|
197
|
-
};
|
|
198
|
-
};
|
|
199
|
-
fireListeners();
|
|
200
|
-
window.onload = () => {
|
|
201
|
-
setTimeout(() => {
|
|
202
|
-
document.body.saloeListen();
|
|
203
|
-
}, listenAfterMs);
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
const LISTENER_SCRIPT = listener.toString();
|
|
278
|
+
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
fireListeners()
|
|
282
|
+
|
|
283
|
+
window.onload = () => {
|
|
284
|
+
setTimeout(() => {
|
|
285
|
+
document.body.saloeListen()
|
|
286
|
+
}, listenAfterMs)
|
|
287
|
+
}
|
|
288
|
+
}`;
|
|
289
|
+
const listener = new Function("return (" + LISTENER_SCRIPT + ")")();
|
|
207
290
|
const getScriptListener = ({
|
|
208
291
|
SRC_ELEMEMENTS_QUERY = [],
|
|
209
292
|
listenAfterMs = 2500
|
package/dist/listener.es.js
CHANGED
|
@@ -1,207 +1,290 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const LISTENER_SCRIPT = `({
|
|
2
|
+
SRC_ELEMEMENTS_QUERY = [],
|
|
3
|
+
listenAfterMs = 2_500,
|
|
4
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
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
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
|
-
|
|
5
|
+
const EVENTS_PREVENT_DEFAULT_MANDATORY = [
|
|
6
|
+
'submit'
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
const EVENTS = [
|
|
10
|
+
'mouseover',
|
|
11
|
+
'click',
|
|
12
|
+
'submit',
|
|
13
|
+
'input',
|
|
14
|
+
'blur',
|
|
15
|
+
'change',
|
|
16
|
+
'focus',
|
|
17
|
+
'invalid',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
const addListener = ({ srcElement, eventName, listeners, afterExecuteListeners }) => {
|
|
21
|
+
srcElement?.addEventListener(eventName, (e) => {
|
|
22
|
+
executeListeners({ e, srcElement, listeners, afterExecuteListeners })
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const executeListeners = async ({ e, srcElement, listeners, afterExecuteListeners }) => {
|
|
27
|
+
await Promise.all(
|
|
28
|
+
(listeners ?? []).map((listener) => {
|
|
29
|
+
if (listener) return listener({ e, srcElement })
|
|
30
|
+
})
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
if (afterExecuteListeners) await afterExecuteListeners()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const getListenerFromScript = ({ script, eventName }) => {
|
|
37
|
+
if (!script) return null
|
|
38
|
+
if (script[eventName]) return script[eventName]
|
|
39
|
+
const prev = Object.keys(script)?.find((key) => script[key][eventName])
|
|
40
|
+
if (!prev) return null
|
|
41
|
+
return script[prev][eventName]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const fetchListeners = async ({ srcElement, eventName, e }) => {
|
|
45
|
+
if (!srcElement?.getAttribute) return
|
|
46
|
+
|
|
47
|
+
const scriptNames = srcElement?.getAttribute(\`on-\${eventName}\`)
|
|
48
|
+
if (!scriptNames) return
|
|
49
|
+
|
|
50
|
+
if (e && scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(eventName)) e.preventDefault()
|
|
51
|
+
|
|
52
|
+
const scripts = await Promise.all(
|
|
53
|
+
scriptNames?.split(',')?.map((scriptName) => {
|
|
54
|
+
const scriptToImport = \`/\${scriptName?.trim()}.js\`
|
|
55
|
+
return importScriptDynamically({ path: scriptToImport })
|
|
56
|
+
})
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
const listeners = scripts?.map((script) => getListenerFromScript({ script, eventName }))
|
|
60
|
+
|
|
61
|
+
return listeners
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const addScripts = () => {
|
|
65
|
+
const scriptsToLoad = [...document.querySelectorAll('script[data-script-to-load]')]
|
|
66
|
+
return Promise.all(
|
|
67
|
+
scriptsToLoad?.map((scriptToLoad) => {
|
|
68
|
+
const id = scriptToLoad?.getAttribute('data-script-to-load')
|
|
69
|
+
scriptToLoad.removeAttribute('data-script-to-load')
|
|
70
|
+
|
|
71
|
+
const attrs = scriptToLoad?.getAttributeNames()?.reduce((acc, attrName) => {
|
|
72
|
+
const attrValue = scriptToLoad.getAttribute(attrName)
|
|
73
|
+
if (attrValue !== 'text/script-to-load') acc[attrName] = attrValue
|
|
74
|
+
return acc
|
|
75
|
+
}, {})
|
|
76
|
+
|
|
77
|
+
const content = scriptToLoad?.textContent
|
|
78
|
+
|
|
79
|
+
scriptToLoad?.remove()
|
|
80
|
+
|
|
81
|
+
return loadScript({ id, attrs, content }).catch((err) => {
|
|
82
|
+
console.error(err)
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const loadScript = ({ id, attrs, content }) => {
|
|
89
|
+
const script = document?.createElement('script')
|
|
90
|
+
|
|
91
|
+
Object.keys(attrs)?.forEach((attrKey) => script?.setAttribute(attrKey, attrs[attrKey]))
|
|
92
|
+
script.id = id
|
|
93
|
+
script.type = 'module'
|
|
94
|
+
|
|
95
|
+
if (content) script?.insertAdjacentHTML('beforeend', content)
|
|
96
|
+
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
if (!attrs.src) {
|
|
99
|
+
resolve()
|
|
100
|
+
document?.body?.insertAdjacentElement('beforeend', script)
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
script.onload = script.onreadystatechange = function () {
|
|
105
|
+
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
|
|
106
|
+
resolve()
|
|
107
|
+
script.onload = script.onreadystatechange = null
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
script.onerror = () => {
|
|
112
|
+
console.error('script failed to load')
|
|
113
|
+
reject(new Error(\`Failed to load script with src \${script.src}\`))
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
document?.body?.insertAdjacentElement('beforeend', script)
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// FIX: return import() to prevent __vitePreload to take action
|
|
121
|
+
const importScriptDynamically = ({ path }) => {
|
|
122
|
+
return import(path)?.catch((err) => { })
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// load
|
|
126
|
+
const fireLoadListener = () => {
|
|
127
|
+
const eventName = 'load'
|
|
128
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
129
|
+
|
|
130
|
+
srcElements?.forEach(async (srcElement) => {
|
|
131
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
132
|
+
executeListeners({ e: null, srcElement, listeners })
|
|
133
|
+
|
|
134
|
+
srcElement?.removeAttribute(\`on-\${eventName}\`)
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// invalid
|
|
139
|
+
const fireInvalidListener = () => {
|
|
140
|
+
const eventName = 'invalid'
|
|
141
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
142
|
+
|
|
143
|
+
srcElements?.forEach(async (srcElement) => {
|
|
144
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
145
|
+
addListener({ srcElement, eventName, listeners })
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// blur
|
|
150
|
+
const fireBlurListener = () => {
|
|
151
|
+
const eventName = 'blur'
|
|
152
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
153
|
+
|
|
154
|
+
srcElements?.forEach(async (srcElement) => {
|
|
155
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
156
|
+
addListener({ srcElement, eventName, listeners })
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// focus
|
|
161
|
+
const fireFocusListener = () => {
|
|
162
|
+
const eventName = 'focus'
|
|
163
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
164
|
+
|
|
165
|
+
srcElements?.forEach(async (srcElement) => {
|
|
166
|
+
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
167
|
+
addListener({ srcElement, eventName, listeners })
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// observers
|
|
172
|
+
const fireObserverListeners = () => {
|
|
173
|
+
const srcElements = [...document.querySelectorAll('[on-observe]')]
|
|
174
|
+
|
|
175
|
+
const uniqueScriptNames = [...srcElements?.reduce((acc, srcElement) => {
|
|
176
|
+
const attribute = srcElement?.getAttribute('on-observe')
|
|
177
|
+
if (attribute === 'undefined') return acc
|
|
178
|
+
|
|
179
|
+
const scriptNames = attribute?.split(',')
|
|
180
|
+
scriptNames?.forEach((scriptName) => acc?.set(scriptName, 1))
|
|
181
|
+
|
|
182
|
+
return acc
|
|
183
|
+
}, new Map())?.keys()]
|
|
184
|
+
|
|
185
|
+
uniqueScriptNames?.forEach(async (scriptName) => {
|
|
186
|
+
const observedSrcElements = document.querySelectorAll(\`[on-observe*="\${scriptName}"]\`)
|
|
187
|
+
|
|
188
|
+
const script = await importScriptDynamically({ path: \`/\${scriptName?.trim()}.js\` })
|
|
189
|
+
const listener = getListenerFromScript({ script, eventName: 'observe' })
|
|
190
|
+
if (!listener) return
|
|
191
|
+
|
|
192
|
+
const observer = new IntersectionObserver((entries) => {
|
|
193
|
+
entries.forEach((entry) => listener({ entry, observer }))
|
|
194
|
+
}, {
|
|
195
|
+
threshold: .5,
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
observedSrcElements?.forEach((observerSrcElement) => {
|
|
199
|
+
observer.observe(observerSrcElement)
|
|
200
|
+
|
|
201
|
+
const observerAttr = observerSrcElement?.getAttribute('on-observe')
|
|
202
|
+
const updatedObserverAttr = observerAttr?.replaceAll(scriptName + ', ', '')?.replaceAll(', ' + scriptName, '')?.replaceAll(scriptName, '')
|
|
203
|
+
|
|
204
|
+
if (!updatedObserverAttr) observerSrcElement.removeAttribute('on-observe')
|
|
205
|
+
else observerSrcElement.setAttribute('on-observe', updatedObserverAttr)
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const getSrcElement = ({ srcElement, eventName }) => {
|
|
211
|
+
if (!srcElement?.hasAttribute) return srcElement
|
|
212
|
+
const attribute = \`on-\${eventName}\`
|
|
213
|
+
const hasScriptName = srcElement?.hasAttribute(attribute)
|
|
214
|
+
if (hasScriptName) return srcElement
|
|
215
|
+
|
|
216
|
+
const query = \`:is(\${['a', 'button', ...SRC_ELEMEMENTS_QUERY].join(',')})[\${attribute}]\`
|
|
217
|
+
const closestButton = srcElement?.closest(query)
|
|
218
|
+
if (closestButton) return closestButton
|
|
219
|
+
|
|
220
|
+
return srcElement
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const cloneSrcElement = ({ srcElement }) => {
|
|
224
|
+
const newSrcElement = document.createElement(srcElement?.tagName)
|
|
225
|
+
|
|
226
|
+
Array.from(srcElement?.attributes).forEach((attr) => {
|
|
227
|
+
if (attr.name.startsWith('on-')) return
|
|
228
|
+
newSrcElement.setAttribute(attr.name, attr.value)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
return newSrcElement
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const isAnchorBeingClicked = ({ srcElement, eventName }) => {
|
|
235
|
+
return srcElement?.tagName === 'A' && eventName === 'click'
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const clickDefaultAnchor = ({ srcElement }) => {
|
|
239
|
+
const newAnchor = cloneSrcElement({ srcElement })
|
|
240
|
+
newAnchor.click()
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const fireListeners = () => {
|
|
244
|
+
EVENTS.forEach((eventName) => {
|
|
245
|
+
document.body[\`on\${eventName}\`] = async (e) => {
|
|
246
|
+
const srcElement = getSrcElement({ srcElement: e?.srcElement, eventName })
|
|
247
|
+
const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName })
|
|
248
|
+
|
|
249
|
+
if (isAnchorClicked) e.preventDefault()
|
|
250
|
+
|
|
251
|
+
const listeners = await fetchListeners({ srcElement, eventName, e })
|
|
252
|
+
const afterExecuteListeners = isAnchorClicked
|
|
253
|
+
? () => { clickDefaultAnchor({ srcElement }) }
|
|
254
|
+
: null
|
|
255
|
+
|
|
256
|
+
executeListeners({ e, srcElement, listeners, afterExecuteListeners })
|
|
257
|
+
addListener({ srcElement, eventName, listeners, afterExecuteListeners })
|
|
258
|
+
|
|
259
|
+
if (srcElement?.removeAttribute) srcElement.removeAttribute(\`on-\${eventName}\`)
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
const saloeListenEvent = new CustomEvent('saloeListen', {
|
|
264
|
+
detail: { message: 'This is a custom eventName!' }
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
document.body.addEventListener('saloeListen', async (e) => {
|
|
268
|
+
await addScripts()
|
|
269
|
+
fireLoadListener()
|
|
270
|
+
fireObserverListeners()
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
document.body.saloeListen = function () {
|
|
274
|
+
document.body.dispatchEvent(saloeListenEvent)
|
|
92
275
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
const fireLoadListener = () => {
|
|
107
|
-
const eventName = "load";
|
|
108
|
-
const srcElements = document == null ? void 0 : document.querySelectorAll(`[on-${eventName}]`);
|
|
109
|
-
srcElements == null ? void 0 : srcElements.forEach(async (srcElement) => {
|
|
110
|
-
const listeners = await fetchListeners({ srcElement, eventName, e: null });
|
|
111
|
-
executeListeners({ e: null, srcElement, listeners });
|
|
112
|
-
srcElement == null ? void 0 : srcElement.removeAttribute(`on-${eventName}`);
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
const fireObserverListeners = () => {
|
|
116
|
-
var _a;
|
|
117
|
-
const srcElements = [...document.querySelectorAll("[on-observe]")];
|
|
118
|
-
const uniqueScriptNames = [...(_a = srcElements == null ? void 0 : srcElements.reduce((acc, srcElement) => {
|
|
119
|
-
const attribute = srcElement == null ? void 0 : srcElement.getAttribute("on-observe");
|
|
120
|
-
if (attribute === "undefined") return acc;
|
|
121
|
-
const scriptNames = attribute == null ? void 0 : attribute.split(",");
|
|
122
|
-
scriptNames == null ? void 0 : scriptNames.forEach((scriptName) => acc == null ? void 0 : acc.set(scriptName, 1));
|
|
123
|
-
return acc;
|
|
124
|
-
}, /* @__PURE__ */ new Map())) == null ? void 0 : _a.keys()];
|
|
125
|
-
uniqueScriptNames == null ? void 0 : uniqueScriptNames.forEach(async (scriptName) => {
|
|
126
|
-
const observedSrcElements = document.querySelectorAll(`[on-observe*="${scriptName}"]`);
|
|
127
|
-
const script = await importScriptDynamically({ path: `/${scriptName == null ? void 0 : scriptName.trim()}.js` });
|
|
128
|
-
const listener2 = getListenerFromScript({ script, eventName: "observe" });
|
|
129
|
-
if (!listener2) return;
|
|
130
|
-
const observer = new IntersectionObserver((entries) => {
|
|
131
|
-
entries.forEach((entry) => listener2({ entry, observer }));
|
|
132
|
-
}, {
|
|
133
|
-
threshold: 0.5
|
|
134
|
-
});
|
|
135
|
-
observedSrcElements == null ? void 0 : observedSrcElements.forEach((observerSrcElement) => {
|
|
136
|
-
var _a2, _b;
|
|
137
|
-
observer.observe(observerSrcElement);
|
|
138
|
-
const observerAttr = observerSrcElement == null ? void 0 : observerSrcElement.getAttribute("on-observe");
|
|
139
|
-
const updatedObserverAttr = (_b = (_a2 = observerAttr == null ? void 0 : observerAttr.replaceAll(scriptName + ", ", "")) == null ? void 0 : _a2.replaceAll(", " + scriptName, "")) == null ? void 0 : _b.replaceAll(scriptName, "");
|
|
140
|
-
if (!updatedObserverAttr) observerSrcElement.removeAttribute("on-observe");
|
|
141
|
-
else observerSrcElement.setAttribute("on-observe", updatedObserverAttr);
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
const getSrcElement = ({ srcElement, eventName }) => {
|
|
146
|
-
if (!(srcElement == null ? void 0 : srcElement.hasAttribute)) return srcElement;
|
|
147
|
-
const attribute = `on-${eventName}`;
|
|
148
|
-
const hasScriptName = srcElement == null ? void 0 : srcElement.hasAttribute(attribute);
|
|
149
|
-
if (hasScriptName) return srcElement;
|
|
150
|
-
const query = `:is(${["a", "button", ...SRC_ELEMEMENTS_QUERY].join(",")})[${attribute}]`;
|
|
151
|
-
const closestButton = srcElement == null ? void 0 : srcElement.closest(query);
|
|
152
|
-
if (closestButton) return closestButton;
|
|
153
|
-
return srcElement;
|
|
154
|
-
};
|
|
155
|
-
const cloneSrcElement = ({ srcElement }) => {
|
|
156
|
-
const newSrcElement = document.createElement(srcElement == null ? void 0 : srcElement.tagName);
|
|
157
|
-
Array.from(srcElement == null ? void 0 : srcElement.attributes).forEach((attr) => {
|
|
158
|
-
if (attr.name.startsWith("on-")) return;
|
|
159
|
-
newSrcElement.setAttribute(attr.name, attr.value);
|
|
160
|
-
});
|
|
161
|
-
return newSrcElement;
|
|
162
|
-
};
|
|
163
|
-
const isAnchorBeingClicked = ({ srcElement, eventName }) => {
|
|
164
|
-
return (srcElement == null ? void 0 : srcElement.tagName) === "A" && eventName === "click";
|
|
165
|
-
};
|
|
166
|
-
const clickDefaultAnchor = ({ srcElement }) => {
|
|
167
|
-
const newAnchor = cloneSrcElement({ srcElement });
|
|
168
|
-
newAnchor.click();
|
|
169
|
-
};
|
|
170
|
-
const fireListeners = () => {
|
|
171
|
-
EVENTS.forEach((eventName) => {
|
|
172
|
-
document.body[`on${eventName}`] = async (e) => {
|
|
173
|
-
const srcElement = getSrcElement({ srcElement: e == null ? void 0 : e.srcElement, eventName });
|
|
174
|
-
const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName });
|
|
175
|
-
if (isAnchorClicked) e.preventDefault();
|
|
176
|
-
const listeners = await fetchListeners({ srcElement, eventName, e });
|
|
177
|
-
const afterExecuteListeners = isAnchorClicked ? () => {
|
|
178
|
-
clickDefaultAnchor({ srcElement });
|
|
179
|
-
} : null;
|
|
180
|
-
executeListeners({ e, srcElement, listeners, afterExecuteListeners });
|
|
181
|
-
addListener({ srcElement, eventName, listeners, afterExecuteListeners });
|
|
182
|
-
if (srcElement == null ? void 0 : srcElement.removeAttribute) srcElement.removeAttribute(`on-${eventName}`);
|
|
183
|
-
};
|
|
184
|
-
});
|
|
185
|
-
const saloeListenEvent = new CustomEvent("saloeListen", {
|
|
186
|
-
detail: { message: "This is a custom eventName!" }
|
|
187
|
-
});
|
|
188
|
-
document.body.addEventListener("saloeListen", async (e) => {
|
|
189
|
-
await addScripts();
|
|
190
|
-
fireLoadListener();
|
|
191
|
-
fireObserverListeners();
|
|
192
|
-
});
|
|
193
|
-
document.body.saloeListen = function() {
|
|
194
|
-
document.body.dispatchEvent(saloeListenEvent);
|
|
195
|
-
};
|
|
196
|
-
};
|
|
197
|
-
fireListeners();
|
|
198
|
-
window.onload = () => {
|
|
199
|
-
setTimeout(() => {
|
|
200
|
-
document.body.saloeListen();
|
|
201
|
-
}, listenAfterMs);
|
|
202
|
-
};
|
|
203
|
-
};
|
|
204
|
-
const LISTENER_SCRIPT = listener.toString();
|
|
276
|
+
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
fireListeners()
|
|
280
|
+
|
|
281
|
+
window.onload = () => {
|
|
282
|
+
setTimeout(() => {
|
|
283
|
+
document.body.saloeListen()
|
|
284
|
+
}, listenAfterMs)
|
|
285
|
+
}
|
|
286
|
+
}`;
|
|
287
|
+
const listener = new Function("return (" + LISTENER_SCRIPT + ")")();
|
|
205
288
|
const getScriptListener = ({
|
|
206
289
|
SRC_ELEMEMENTS_QUERY = [],
|
|
207
290
|
listenAfterMs = 2500
|
package/package.json
CHANGED
package/src/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const LISTENER_SCRIPT = `({
|
|
2
2
|
SRC_ELEMEMENTS_QUERY = [],
|
|
3
3
|
listenAfterMs = 2_500,
|
|
4
4
|
} = {}) => {
|
|
@@ -44,14 +44,14 @@ const listener = ({
|
|
|
44
44
|
const fetchListeners = async ({ srcElement, eventName, e }) => {
|
|
45
45
|
if (!srcElement?.getAttribute) return
|
|
46
46
|
|
|
47
|
-
const scriptNames = srcElement?.getAttribute(
|
|
47
|
+
const scriptNames = srcElement?.getAttribute(\`on-\${eventName}\`)
|
|
48
48
|
if (!scriptNames) return
|
|
49
49
|
|
|
50
50
|
if (e && scriptNames && EVENTS_PREVENT_DEFAULT_MANDATORY.includes(eventName)) e.preventDefault()
|
|
51
51
|
|
|
52
52
|
const scripts = await Promise.all(
|
|
53
53
|
scriptNames?.split(',')?.map((scriptName) => {
|
|
54
|
-
const scriptToImport =
|
|
54
|
+
const scriptToImport = \`/\${scriptName?.trim()}.js\`
|
|
55
55
|
return importScriptDynamically({ path: scriptToImport })
|
|
56
56
|
})
|
|
57
57
|
)
|
|
@@ -110,7 +110,7 @@ const listener = ({
|
|
|
110
110
|
|
|
111
111
|
script.onerror = () => {
|
|
112
112
|
console.error('script failed to load')
|
|
113
|
-
reject(new Error(
|
|
113
|
+
reject(new Error(\`Failed to load script with src \${script.src}\`))
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
document?.body?.insertAdjacentElement('beforeend', script)
|
|
@@ -125,20 +125,20 @@ const listener = ({
|
|
|
125
125
|
// load
|
|
126
126
|
const fireLoadListener = () => {
|
|
127
127
|
const eventName = 'load'
|
|
128
|
-
const srcElements = document?.querySelectorAll(
|
|
128
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
129
129
|
|
|
130
130
|
srcElements?.forEach(async (srcElement) => {
|
|
131
131
|
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
132
132
|
executeListeners({ e: null, srcElement, listeners })
|
|
133
133
|
|
|
134
|
-
srcElement?.removeAttribute(
|
|
134
|
+
srcElement?.removeAttribute(\`on-\${eventName}\`)
|
|
135
135
|
})
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
// invalid
|
|
139
139
|
const fireInvalidListener = () => {
|
|
140
140
|
const eventName = 'invalid'
|
|
141
|
-
const srcElements = document?.querySelectorAll(
|
|
141
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
142
142
|
|
|
143
143
|
srcElements?.forEach(async (srcElement) => {
|
|
144
144
|
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
@@ -149,7 +149,7 @@ const listener = ({
|
|
|
149
149
|
// blur
|
|
150
150
|
const fireBlurListener = () => {
|
|
151
151
|
const eventName = 'blur'
|
|
152
|
-
const srcElements = document?.querySelectorAll(
|
|
152
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
153
153
|
|
|
154
154
|
srcElements?.forEach(async (srcElement) => {
|
|
155
155
|
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
@@ -160,7 +160,7 @@ const listener = ({
|
|
|
160
160
|
// focus
|
|
161
161
|
const fireFocusListener = () => {
|
|
162
162
|
const eventName = 'focus'
|
|
163
|
-
const srcElements = document?.querySelectorAll(
|
|
163
|
+
const srcElements = document?.querySelectorAll(\`[on-\${eventName}]\`)
|
|
164
164
|
|
|
165
165
|
srcElements?.forEach(async (srcElement) => {
|
|
166
166
|
const listeners = await fetchListeners({ srcElement, eventName, e: null })
|
|
@@ -183,9 +183,9 @@ const listener = ({
|
|
|
183
183
|
}, new Map())?.keys()]
|
|
184
184
|
|
|
185
185
|
uniqueScriptNames?.forEach(async (scriptName) => {
|
|
186
|
-
const observedSrcElements = document.querySelectorAll(
|
|
186
|
+
const observedSrcElements = document.querySelectorAll(\`[on-observe*="\${scriptName}"]\`)
|
|
187
187
|
|
|
188
|
-
const script = await importScriptDynamically({ path:
|
|
188
|
+
const script = await importScriptDynamically({ path: \`/\${scriptName?.trim()}.js\` })
|
|
189
189
|
const listener = getListenerFromScript({ script, eventName: 'observe' })
|
|
190
190
|
if (!listener) return
|
|
191
191
|
|
|
@@ -209,11 +209,11 @@ const listener = ({
|
|
|
209
209
|
|
|
210
210
|
const getSrcElement = ({ srcElement, eventName }) => {
|
|
211
211
|
if (!srcElement?.hasAttribute) return srcElement
|
|
212
|
-
const attribute =
|
|
212
|
+
const attribute = \`on-\${eventName}\`
|
|
213
213
|
const hasScriptName = srcElement?.hasAttribute(attribute)
|
|
214
214
|
if (hasScriptName) return srcElement
|
|
215
215
|
|
|
216
|
-
const query =
|
|
216
|
+
const query = \`:is(\${['a', 'button', ...SRC_ELEMEMENTS_QUERY].join(',')})[\${attribute}]\`
|
|
217
217
|
const closestButton = srcElement?.closest(query)
|
|
218
218
|
if (closestButton) return closestButton
|
|
219
219
|
|
|
@@ -242,7 +242,7 @@ const listener = ({
|
|
|
242
242
|
|
|
243
243
|
const fireListeners = () => {
|
|
244
244
|
EVENTS.forEach((eventName) => {
|
|
245
|
-
document.body[
|
|
245
|
+
document.body[\`on\${eventName}\`] = async (e) => {
|
|
246
246
|
const srcElement = getSrcElement({ srcElement: e?.srcElement, eventName })
|
|
247
247
|
const isAnchorClicked = isAnchorBeingClicked({ srcElement, eventName })
|
|
248
248
|
|
|
@@ -256,7 +256,7 @@ const listener = ({
|
|
|
256
256
|
executeListeners({ e, srcElement, listeners, afterExecuteListeners })
|
|
257
257
|
addListener({ srcElement, eventName, listeners, afterExecuteListeners })
|
|
258
258
|
|
|
259
|
-
if (srcElement?.removeAttribute) srcElement.removeAttribute(
|
|
259
|
+
if (srcElement?.removeAttribute) srcElement.removeAttribute(\`on-\${eventName}\`)
|
|
260
260
|
}
|
|
261
261
|
})
|
|
262
262
|
|
|
@@ -283,11 +283,11 @@ const listener = ({
|
|
|
283
283
|
document.body.saloeListen()
|
|
284
284
|
}, listenAfterMs)
|
|
285
285
|
}
|
|
286
|
-
}
|
|
286
|
+
}`
|
|
287
287
|
|
|
288
|
-
const
|
|
288
|
+
const listener = new Function('return (' + LISTENER_SCRIPT + ')')()
|
|
289
289
|
|
|
290
290
|
export {
|
|
291
291
|
listener,
|
|
292
292
|
LISTENER_SCRIPT,
|
|
293
|
-
}
|
|
293
|
+
}
|