turbo-web 4.3.0 → 4.5.0
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/README.md +9 -0
- package/dist/turbo.js +33 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,7 +84,10 @@ JavaScript object tree that represents the UI.
|
|
|
84
84
|
### [CORE] Feature 4: Components
|
|
85
85
|
**Encapsulation & Reusability** principles: making UI building blocks with better combined hierarchical tree structure.
|
|
86
86
|
|
|
87
|
+
// Events accept additional modificator ```.stop .prevent``` to stop event bubbling and prevent default browser behaviour.
|
|
88
|
+
|
|
87
89
|
```component.js // building scheme: h(tagOrComponent, { attributes, class, style, on: events }, [children])```
|
|
90
|
+
|
|
88
91
|
### Feature 5: Client-Side Router (#hash-based)
|
|
89
92
|
Allows for the **SPA design** (Single Page Application) with route guards (fn: checkNavigation) and a common "catch-all route" (cases: route not found). Based on a hash part of the URL, implemented with regex pattern matching by simulating URL path, parameters and query as part of the hash fragment itself.
|
|
90
93
|
|
|
@@ -190,4 +193,10 @@ onMounted() {
|
|
|
190
193
|
onUnmounted() {
|
|
191
194
|
if (this.unsubscribe) this.unsubscribe();
|
|
192
195
|
},
|
|
196
|
+
```
|
|
197
|
+
### [6] Event bubbling & default browser behaviour override
|
|
198
|
+
It is possible to prevent both by passing additional modificators with functions.
|
|
199
|
+
```
|
|
200
|
+
on: { 'click.stop': () => this.addLog('Button with .stop Clicked') }
|
|
201
|
+
on: { 'click.prevent': () => this.addLog('Link with .prevent Clicked') }
|
|
193
202
|
```
|
package/dist/turbo.js
CHANGED
|
@@ -194,25 +194,42 @@ function hSlot(name = 'default', children = []) {
|
|
|
194
194
|
return { type: DOM_TYPES.SLOT, name: name, children: children }
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
function addEventListener(
|
|
198
|
-
|
|
197
|
+
function addEventListener(eventNameWithModifiers, handlerConfig, el, hostComponent = null) {
|
|
198
|
+
const [eventName, ...modifiers] = eventNameWithModifiers.split('.');
|
|
199
|
+
const isDelegated = typeof handlerConfig === 'object' && handlerConfig.delegate;
|
|
200
|
+
const handler = isDelegated ? handlerConfig.handler : handlerConfig;
|
|
201
|
+
const selector = isDelegated ? handlerConfig.delegate : null;
|
|
202
|
+
function boundHandler(event) {
|
|
203
|
+
let target = event.target;
|
|
204
|
+
if (isDelegated) {
|
|
205
|
+
target = event.target.closest(selector);
|
|
206
|
+
if (!target || !el.contains(target)) return;
|
|
207
|
+
}
|
|
208
|
+
if (modifiers.includes('stop')) {
|
|
209
|
+
event.stopPropagation();
|
|
210
|
+
}
|
|
211
|
+
if (modifiers.includes('prevent')) {
|
|
212
|
+
event.preventDefault();
|
|
213
|
+
}
|
|
214
|
+
const args = isDelegated ? [event, target] : [event];
|
|
199
215
|
hostComponent
|
|
200
|
-
? handler.apply(hostComponent,
|
|
201
|
-
: handler(...
|
|
216
|
+
? handler.apply(hostComponent, args)
|
|
217
|
+
: handler(...args);
|
|
202
218
|
}
|
|
203
219
|
el.addEventListener(eventName, boundHandler);
|
|
204
220
|
return boundHandler
|
|
205
221
|
}
|
|
206
222
|
function addEventListeners(listeners = {}, el, hostComponent = null ) {
|
|
207
223
|
const addedListeners = {};
|
|
208
|
-
Object.entries(listeners).forEach(([eventName,
|
|
209
|
-
const listener = addEventListener(eventName,
|
|
224
|
+
Object.entries(listeners).forEach(([eventName, handlerConfig]) => {
|
|
225
|
+
const listener = addEventListener(eventName, handlerConfig, el, hostComponent);
|
|
210
226
|
addedListeners[eventName] = listener;
|
|
211
227
|
});
|
|
212
228
|
return addedListeners
|
|
213
229
|
}
|
|
214
230
|
function removeEventListeners(listeners = {}, el) {
|
|
215
|
-
Object.entries(listeners).forEach(([
|
|
231
|
+
Object.entries(listeners).forEach(([eventNameWithModifiers, handler]) => {
|
|
232
|
+
const eventName = eventNameWithModifiers.split('.')[0];
|
|
216
233
|
el.removeEventListener(eventName, handler);
|
|
217
234
|
});
|
|
218
235
|
}
|
|
@@ -893,14 +910,15 @@ function patchStyles(el, oldStyle = {}, newStyle = {}) {
|
|
|
893
910
|
}
|
|
894
911
|
function patchEvents(el, oldListeners = {}, oldEvents = {}, newEvents = {}, hostComponent) {
|
|
895
912
|
const { removed, added, updated } = objectsDiff(oldEvents, newEvents);
|
|
896
|
-
for (const
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
913
|
+
for (const eventNameWithModifiers of removed.concat(updated)) {
|
|
914
|
+
const eventName = eventNameWithModifiers.split('.')[0];
|
|
915
|
+
el.removeEventListener(eventName, oldListeners[eventNameWithModifiers]);
|
|
916
|
+
}
|
|
917
|
+
const addedListeners = { ...oldListeners };
|
|
918
|
+
removed.forEach(key => delete addedListeners[key]);
|
|
919
|
+
for (const eventNameWithModifiers of added.concat(updated)) {
|
|
920
|
+
const listener = addEventListener(eventNameWithModifiers, newEvents[eventNameWithModifiers], el, hostComponent);
|
|
921
|
+
addedListeners[eventNameWithModifiers] = listener;
|
|
904
922
|
}
|
|
905
923
|
return addedListeners
|
|
906
924
|
}
|