rytm-webflow 2.2.3 → 2.2.5
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/CLAUDE.md +363 -0
- package/package.json +1 -1
- package/scripts/aswap/View.js +13 -1
- package/scripts/aswap/WebflowListView.js +40 -2
- package/scripts/aswap/WebflowView.js +10 -9
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# rytm-webflow
|
|
2
|
+
|
|
3
|
+
AJAX view-swapping engine and scroll-triggered animation framework for tuki CMS projects.
|
|
4
|
+
Built on GSAP + ScrollMagic. Transforms server-rendered pages into pseudo-SPAs.
|
|
5
|
+
|
|
6
|
+
**Version**: 2.2.4 | **Entry**: `scripts/index.js` | **Deps**: gsap, imagesloaded, scrollmagic
|
|
7
|
+
|
|
8
|
+
## Exports
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
import RytmWebflow from 'rytm-webflow'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Export | Type | Purpose |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `aswap` | Singleton | AJAX page swap engine |
|
|
17
|
+
| `Controller` | Class | Base controller — view lifecycle & event management |
|
|
18
|
+
| `ControllerImgLoad` | Class | Controller that waits for images before showing view |
|
|
19
|
+
| `View` | Class | Base view — animation hooks |
|
|
20
|
+
| `WebflowView` | Class | View with declarative animations via data attributes |
|
|
21
|
+
| `WebflowListView` | Class | Staggered list animations with scroll triggers |
|
|
22
|
+
| `bootsrap5` | Object | Bootstrap 5 modal/offcanvas close helpers |
|
|
23
|
+
| `scrollController` | Singleton | ScrollMagic controller manager |
|
|
24
|
+
| `showUp` | Singleton | Standalone scroll-triggered animations (no ASwap needed) |
|
|
25
|
+
| `getWebflowProps(str)` | Function | Parse webflow show/hide syntax |
|
|
26
|
+
| `getWebflowAnimationProps(str)` | Function | Parse single animation string |
|
|
27
|
+
| `getParallaxProps(str)` | Function | Parse parallax syntax |
|
|
28
|
+
| `parseProps(str)` | Function | Parse `key:value` comma-separated pairs |
|
|
29
|
+
| `getScrollMagicSceneProps(el, setup)` | Function | Generate ScrollMagic scene config |
|
|
30
|
+
| `elementIsVisibleInViewport(el, partial)` | Function | Viewport visibility check |
|
|
31
|
+
| `CLASS_NAME_WEBSCROLL_FIRED` | Constant | `'webflow-scroll-fired'` |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## ASwap — AJAX page swap engine
|
|
36
|
+
|
|
37
|
+
### Init
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
RytmWebflow.aswap.init(params, events)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**params** (all optional, shown with defaults):
|
|
44
|
+
|
|
45
|
+
| Param | Default | Description |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `animationTimeHide` | `800` | Hide transition duration (ms) |
|
|
48
|
+
| `animationTimeShow` | `800` | Show transition duration (ms) |
|
|
49
|
+
| `routes` | `{}` | Route definitions — `{ viewName: { controller, view } }` |
|
|
50
|
+
| `swapSelector` | `'#stage'` | Container selector for swapped content |
|
|
51
|
+
| `cacheOn` | `true` | Cache AJAX responses |
|
|
52
|
+
| `noCacheClassName` | `'no-as-cache'` | Link class to skip cache |
|
|
53
|
+
| `noSwapClassName` | `'no-as'` | Link class to skip ASwap entirely |
|
|
54
|
+
| `noScrollClassName` | `'no-as-scroll'` | Link class to keep scroll position |
|
|
55
|
+
| `resetScrollOn` | `true` | Reset scroll on navigation |
|
|
56
|
+
| `preloadOnHover` | `false` | Preload pages on link hover |
|
|
57
|
+
| `formsEnabled` | `true` | AJAX form submission |
|
|
58
|
+
| `formsSelector` | `'form'` | Form selector |
|
|
59
|
+
| `swipeEnabled` | `true` | Swipe navigation on mobile |
|
|
60
|
+
| `historyEnabled` | `true` | Use History API |
|
|
61
|
+
| `refreshOnSameUrl` | `true` | Reload on same-URL click |
|
|
62
|
+
| `defaultDocumentScrollBehavior` | `'smooth'` | Scroll animation |
|
|
63
|
+
| `trace` | `() => {}` | Debug logging function |
|
|
64
|
+
|
|
65
|
+
**events** (all optional):
|
|
66
|
+
|
|
67
|
+
| Event | When |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `onInited` | ASwap initialized |
|
|
70
|
+
| `onRequestUrl` | URL navigation started |
|
|
71
|
+
| `onRequestLoad` | AJAX loading started |
|
|
72
|
+
| `onRequestLoaded` | Response received |
|
|
73
|
+
| `onRequestSameUrl` | Same URL re-requested |
|
|
74
|
+
| `onViewHide` | Hide animation starting |
|
|
75
|
+
| `onViewHidden` | Hide animation complete |
|
|
76
|
+
| `onViewSwapStart` | Before DOM swap |
|
|
77
|
+
| `onViewSwapComplete` | After DOM swap |
|
|
78
|
+
| `onViewShow` | Show animation starting |
|
|
79
|
+
| `onViewShown` | Show animation complete |
|
|
80
|
+
|
|
81
|
+
### Methods
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
RytmWebflow.aswap.openURL(url, noHistory?, useCache?) // Navigate programmatically
|
|
85
|
+
RytmWebflow.aswap.clearCache(url?) // Clear all or specific cache
|
|
86
|
+
RytmWebflow.aswap.formSubmit(formElement) // Submit form via AJAX
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### HTML requirements
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<body data-html-classes="optional-classes">
|
|
93
|
+
<div id="stage">
|
|
94
|
+
<div data-as-view="viewname" data-as-id="unique-id">
|
|
95
|
+
<!-- swapped content -->
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</body>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Link classes
|
|
102
|
+
|
|
103
|
+
| Class | Effect |
|
|
104
|
+
|---|---|
|
|
105
|
+
| `no-as` | Skip ASwap — regular navigation |
|
|
106
|
+
| `no-as-cache` | Skip response cache |
|
|
107
|
+
| `no-as-scroll` | Don't reset scroll position |
|
|
108
|
+
|
|
109
|
+
### Swipe navigation
|
|
110
|
+
|
|
111
|
+
```html
|
|
112
|
+
<div data-as-swipe-left="/next" data-as-swipe-right="/prev">
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Controller
|
|
118
|
+
|
|
119
|
+
Base class for view lifecycle management. One instance per `data-as-id`.
|
|
120
|
+
|
|
121
|
+
### Key properties
|
|
122
|
+
|
|
123
|
+
| Property | Type | Description |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `id` | string | Unique identifier from `data-as-id` |
|
|
126
|
+
| `name` | string | Route name from `data-as-view` |
|
|
127
|
+
| `active` | boolean | Whether view is currently visible |
|
|
128
|
+
| `view` | View\|false | Associated View instance |
|
|
129
|
+
|
|
130
|
+
### Lifecycle (override in subclass)
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
class MyController extends RytmWebflow.Controller {
|
|
134
|
+
addEventListeners() {
|
|
135
|
+
super.addEventListeners()
|
|
136
|
+
// Add DOM listeners — called when view becomes visible
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
removeEventListeners() {
|
|
140
|
+
super.removeEventListeners()
|
|
141
|
+
// Remove DOM listeners — called when view hides
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Event handler sequence
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
Click link → onRequestUrl → onRequestLoad → onRequestLoaded
|
|
150
|
+
→ onViewHide (removeEventListeners + view.hide)
|
|
151
|
+
→ onViewHidden
|
|
152
|
+
→ DOM swap (onViewSwapStart → onViewSwapComplete)
|
|
153
|
+
→ onViewShow (view.show)
|
|
154
|
+
→ onViewShown (addEventListeners + view.shown)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Utility methods
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
controller.getViewContainer(wrapper) // Find this controller's DOM container
|
|
161
|
+
controller.getContainerSelector() // Returns '[data-as-id="..."]'
|
|
162
|
+
controller.isActive() // Check if visible
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## ControllerImgLoad
|
|
168
|
+
|
|
169
|
+
Extends `Controller`. Delays show animation until all images in container are loaded.
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
class GalleryCtrl extends RytmWebflow.ControllerImgLoad {
|
|
173
|
+
loadImagesComplete() {
|
|
174
|
+
super.loadImagesComplete()
|
|
175
|
+
// All images loaded — safe for layout-dependent operations
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
CSS class `as-images-loading` is on container while images load.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## View
|
|
185
|
+
|
|
186
|
+
Base class for show/hide animations.
|
|
187
|
+
|
|
188
|
+
### Lifecycle methods (override in subclass)
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
class MyView extends RytmWebflow.View {
|
|
192
|
+
prepare(container) { super.prepare(container) } // Before show, set initial state
|
|
193
|
+
show(container) { super.show(container) } // Animate in
|
|
194
|
+
shown(container) { } // Show complete
|
|
195
|
+
hide(container) { super.hide(container) } // Animate out
|
|
196
|
+
hidden(container) { } // Hide complete
|
|
197
|
+
|
|
198
|
+
// Only with ControllerImgLoad:
|
|
199
|
+
loadImagesStart(container) { }
|
|
200
|
+
loadImagesComplete(container) { }
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Utility
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
// Filter elements to exclude nested views
|
|
208
|
+
const items = [...container.querySelectorAll('.item')].filter(this.elementBelongsToView)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## WebflowView — declarative animations
|
|
214
|
+
|
|
215
|
+
Extends `View`. Reads animation config from data attributes — no manual animation code needed.
|
|
216
|
+
|
|
217
|
+
### ASwap view animations (show/hide on page transition)
|
|
218
|
+
|
|
219
|
+
```html
|
|
220
|
+
<div data-webview-initial="o:0"
|
|
221
|
+
data-webview-show="o:1,t:.5,e:power3.out"
|
|
222
|
+
data-webview-hide="o:0,t:.3">
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Scroll-triggered animations
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<div data-webscroll-initial="o:0,y:100"
|
|
229
|
+
data-webscroll-show="o:1,y:0,t:.5,e:power3.out"
|
|
230
|
+
data-webscroll-hide="o:0,t:.3">
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Stagger animations (lists)
|
|
234
|
+
|
|
235
|
+
```html
|
|
236
|
+
<ul data-stagger-initial="o:0,y:20"
|
|
237
|
+
data-stagger-show="o:1,y:0,t:.5,stagger:.08"
|
|
238
|
+
data-stagger-hide="o:0,t:.3,stagger:.04"
|
|
239
|
+
data-webset="selector:li">
|
|
240
|
+
<li>Item 1</li>
|
|
241
|
+
<li>Item 2</li>
|
|
242
|
+
</ul>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Webflow syntax reference
|
|
246
|
+
|
|
247
|
+
| Code | CSS Property | Example |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| `o` | opacity | `o:0` → `o:1` |
|
|
250
|
+
| `x` | translateX | `x:100` (px, supports `vw`/`vh`) |
|
|
251
|
+
| `y` | translateY | `y:-50` |
|
|
252
|
+
| `s` | scale | `s:1.2` |
|
|
253
|
+
| `r` | rotation | `r:90` (degrees) |
|
|
254
|
+
| `w` | width | `w:500` (px) |
|
|
255
|
+
| `h` | height | `h:300` (px) |
|
|
256
|
+
| `t` | duration | `t:.5` (seconds) |
|
|
257
|
+
| `d` | delay | `d:.2` (seconds) |
|
|
258
|
+
| `e` | ease | `e:power3.out` (GSAP v3 syntax) |
|
|
259
|
+
| `stagger` | item delay | `stagger:.1` (seconds, for lists) |
|
|
260
|
+
|
|
261
|
+
### data-webset options
|
|
262
|
+
|
|
263
|
+
```html
|
|
264
|
+
<div data-webset="trigger:parent,offset:center,fireOnce:false,duration:100%">
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
| Option | Values | Default | Description |
|
|
268
|
+
|---|---|---|---|
|
|
269
|
+
| `trigger` | `parent`, CSS selector | element itself | What triggers the animation |
|
|
270
|
+
| `offset` | `top`, `center`, px value | bottom of viewport | Viewport trigger position |
|
|
271
|
+
| `fireOnce` | `true`, `false` | `true` | Animate only once |
|
|
272
|
+
| `duration` | `%`, `vh` | — | Parallax-style animation over scroll distance |
|
|
273
|
+
| `selector` | CSS selector | — | Required for stagger: selects list items |
|
|
274
|
+
| `stagger` | seconds | `0.05` | Delay between stagger items |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## WebflowListView
|
|
279
|
+
|
|
280
|
+
Extends `View`. Applies scroll-triggered stagger animations to list items.
|
|
281
|
+
|
|
282
|
+
```html
|
|
283
|
+
<div data-as-view="list" data-as-id="products" data-webset="selector:.item,stagger:.15">
|
|
284
|
+
<div class="item">
|
|
285
|
+
<div data-webscroll-initial="o:0" data-webscroll-show="o:1,t:.5">Content</div>
|
|
286
|
+
</div>
|
|
287
|
+
<!-- more items... -->
|
|
288
|
+
</div>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Each item's delay = `index × stagger + original delay`.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## ShowUp — standalone scroll animations
|
|
296
|
+
|
|
297
|
+
Works without ASwap. For elements that animate on scroll across all pages.
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
RytmWebflow.showUp.init() // Build all scroll scenes from DOM
|
|
301
|
+
RytmWebflow.showUp.rebuild() // Destroy and reinit (call after DOM changes)
|
|
302
|
+
RytmWebflow.showUp.hide() // Trigger all hide animations
|
|
303
|
+
RytmWebflow.showUp.destroy() // Clean up all scenes
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### HTML syntax
|
|
307
|
+
|
|
308
|
+
```html
|
|
309
|
+
<!-- Show;Hide separated by semicolon -->
|
|
310
|
+
<div data-webflow="o:0,t:.5,e:power3.out;o:0,y:-50,t:.3">
|
|
311
|
+
Animate on scroll
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
<!-- Parallax -->
|
|
315
|
+
<div data-webpara="y:-100" data-webset="duration:100%,trigger:parent">
|
|
316
|
+
Parallax effect
|
|
317
|
+
</div>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### ASwap integration (required)
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
const aswapEvents = {
|
|
324
|
+
onViewSwapComplete: () => RytmWebflow.showUp.rebuild(),
|
|
325
|
+
onViewHide: () => RytmWebflow.showUp.hide()
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Bootstrap 5 helpers
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
RytmWebflow.bootsrap5.hideFlyovers() // Close all modals + offcanvases
|
|
335
|
+
RytmWebflow.bootsrap5.hideModals() // Close modals only
|
|
336
|
+
RytmWebflow.bootsrap5.hideOffcanvases() // Close offcanvases only
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Note: the export name has a typo (`bootsrap5`, not `bootstrap5`).
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## scrollController
|
|
344
|
+
|
|
345
|
+
```javascript
|
|
346
|
+
RytmWebflow.scrollController.get() // Get/create ScrollMagic.Controller
|
|
347
|
+
RytmWebflow.scrollController.refresh() // Update all scenes
|
|
348
|
+
RytmWebflow.scrollController.destroy() // Clean up
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Common pitfalls
|
|
354
|
+
|
|
355
|
+
1. **ShowUp not updating after page swap** — call `showUp.rebuild()` in `onViewSwapComplete`
|
|
356
|
+
2. **Layout shifts from images** — use `ControllerImgLoad` for image-heavy pages
|
|
357
|
+
3. **Nested view element leaks** — filter with `elementBelongsToView()` when querying elements
|
|
358
|
+
4. **ScrollMagic memory leaks** — WebflowView handles cleanup automatically; manual scenes need explicit `destroy()`
|
|
359
|
+
5. **Bootstrap modals persist on navigation** — call `bootsrap5.hideFlyovers()` in `onViewHide`
|
|
360
|
+
6. **Event listener accumulation** — always clean up in `removeEventListeners()`
|
|
361
|
+
7. **Stagger not working** — requires `data-webset="selector:..."` attribute
|
|
362
|
+
8. **Easing not applied** — use GSAP v3 syntax: `e:power3.out` (not `e:Power3.easeOut`)
|
|
363
|
+
9. **Cache causes stale content** — add `no-as-cache` class to forms or dynamic links
|
package/package.json
CHANGED
package/scripts/aswap/View.js
CHANGED
|
@@ -50,7 +50,19 @@ class View {
|
|
|
50
50
|
* fired only if ControllerImgLoad is used
|
|
51
51
|
*/
|
|
52
52
|
loadImagesComplete(container) {
|
|
53
|
-
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* check if DOM element belongs to view
|
|
56
|
+
* exclude elements belonging to nested views
|
|
57
|
+
*/
|
|
58
|
+
elementBelongsToView = (el) => {
|
|
59
|
+
let result = false;
|
|
60
|
+
const elContainer = el.closest('[data-as-view]');
|
|
61
|
+
if (elContainer && elContainer.dataset.asId === this.id) {
|
|
62
|
+
result = true;
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
54
66
|
}
|
|
55
67
|
|
|
56
68
|
export default View;
|
|
@@ -6,6 +6,7 @@ import { CLASS_NAME_WEBSCROLL_FIRED } from './WebflowView';
|
|
|
6
6
|
// data-webscroll-... (scroll magic)
|
|
7
7
|
const DATA_ATTR_WEBSCROLL_INIT = "webscroll-initial";
|
|
8
8
|
const DATA_ATTR_WEBSCROLL_SHOW = "webscroll-show";
|
|
9
|
+
const DATA_ATTR_WEBSCROLL_HIDE = "webscroll-hide";
|
|
9
10
|
const DATA_ATTR_SETUP = "webset";
|
|
10
11
|
const DEFAULT_STAGGER = .05;
|
|
11
12
|
|
|
@@ -24,7 +25,7 @@ class WebflowListView extends View {
|
|
|
24
25
|
console.warn("Unknown selector for WebflowListView", this);
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
|
-
const list = [...container.querySelectorAll(this.webset.selector)];
|
|
28
|
+
const list = [...container.querySelectorAll(this.webset.selector)].filter(this.elementBelongsToView);
|
|
28
29
|
list.forEach(this.listElementShow.bind(this));
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
@@ -32,6 +33,13 @@ class WebflowListView extends View {
|
|
|
32
33
|
**/
|
|
33
34
|
hide(container) {
|
|
34
35
|
super.hide(container);
|
|
36
|
+
this.webset = parseProps(container.dataset[DATA_ATTR_SETUP]);
|
|
37
|
+
if (!this.webset.selector) {
|
|
38
|
+
console.warn("Unknown selector for WebflowListView", this);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const list = [...container.querySelectorAll(this.webset.selector)].filter(this.elementBelongsToView);
|
|
42
|
+
list.forEach(this.listElementHide.bind(this));
|
|
35
43
|
}
|
|
36
44
|
/**
|
|
37
45
|
* ############
|
|
@@ -45,7 +53,7 @@ class WebflowListView extends View {
|
|
|
45
53
|
const stagger = this.webset.stagger ? parseFloat(this.webset.stagger) : DEFAULT_STAGGER;
|
|
46
54
|
const delay = index * stagger;
|
|
47
55
|
// search for all webscroll elements
|
|
48
|
-
const list = [...el.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')];
|
|
56
|
+
const list = [...el.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')].filter(this.elementBelongsToView);
|
|
49
57
|
list.forEach((el) => {
|
|
50
58
|
this.webScrollElementShow(el, delay);
|
|
51
59
|
})
|
|
@@ -68,6 +76,36 @@ class WebflowListView extends View {
|
|
|
68
76
|
});
|
|
69
77
|
}
|
|
70
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* ############
|
|
81
|
+
* ### HIDE ###
|
|
82
|
+
* ############
|
|
83
|
+
*/
|
|
84
|
+
// show list element
|
|
85
|
+
listElementHide(el, index) {
|
|
86
|
+
// check if element is in viewport
|
|
87
|
+
if (!this.isElementInViewport(el)) return;
|
|
88
|
+
const stagger = this.webset.stagger ? parseFloat(this.webset.stagger) : DEFAULT_STAGGER;
|
|
89
|
+
const delay = index * stagger;
|
|
90
|
+
// search for all webscroll elements
|
|
91
|
+
const list = [...el.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')].filter(this.elementBelongsToView);
|
|
92
|
+
list.forEach((el) => {
|
|
93
|
+
this.webScrollElementHide(el, delay);
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
// show web scroll element
|
|
97
|
+
webScrollElementHide(el, delay) {
|
|
98
|
+
const propsHide = this.getTweenProps(el, DATA_ATTR_WEBSCROLL_HIDE);
|
|
99
|
+
if (propsHide) {
|
|
100
|
+
delay = delay + (propsHide.tween.delay || 0);
|
|
101
|
+
gsap.killTweensOf(el);
|
|
102
|
+
gsap.to(el, {
|
|
103
|
+
duration: propsHide.time,
|
|
104
|
+
...propsHide.tween,
|
|
105
|
+
delay,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
71
109
|
/**
|
|
72
110
|
* ###############
|
|
73
111
|
* ### HELPERS ###
|
|
@@ -55,6 +55,7 @@ class WebflowView extends View {
|
|
|
55
55
|
* animate out (hide)
|
|
56
56
|
**/
|
|
57
57
|
hide(container) {
|
|
58
|
+
this.container = container;
|
|
58
59
|
super.hide(container);
|
|
59
60
|
// hide Aswap webviews
|
|
60
61
|
this.webViewsHide();
|
|
@@ -120,7 +121,7 @@ class WebflowView extends View {
|
|
|
120
121
|
console.warn("Unknown container", this);
|
|
121
122
|
return;
|
|
122
123
|
}
|
|
123
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBVIEW_SHOW + ']')];
|
|
124
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBVIEW_SHOW + ']')].filter(this.elementBelongsToView);
|
|
124
125
|
list.forEach(this.webViewElementShow.bind(this));
|
|
125
126
|
}
|
|
126
127
|
// showe webview element
|
|
@@ -140,7 +141,7 @@ class WebflowView extends View {
|
|
|
140
141
|
console.warn("Unknown container", this);
|
|
141
142
|
return;
|
|
142
143
|
}
|
|
143
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_STAGGER_SHOW + ']')];
|
|
144
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_STAGGER_SHOW + ']')].filter(this.elementBelongsToView);
|
|
144
145
|
list.forEach(this.staggerListShow.bind(this));
|
|
145
146
|
}
|
|
146
147
|
staggerListShow(el, index) {
|
|
@@ -149,7 +150,7 @@ class WebflowView extends View {
|
|
|
149
150
|
console.warn("Unknown selector for webflow stagger", el);
|
|
150
151
|
return;
|
|
151
152
|
}
|
|
152
|
-
const items = [...el.querySelectorAll(selector)];
|
|
153
|
+
const items = [...el.querySelectorAll(selector)].filter(this.elementBelongsToView);
|
|
153
154
|
const propsInit = this.getTweenProps(el, DATA_ATTR_STAGGER_INIT);
|
|
154
155
|
const propsShow = this.getTweenProps(el, DATA_ATTR_STAGGER_SHOW);
|
|
155
156
|
if (items.length && propsInit && propsShow) {
|
|
@@ -165,7 +166,7 @@ class WebflowView extends View {
|
|
|
165
166
|
console.warn("Unknown container", this);
|
|
166
167
|
return;
|
|
167
168
|
}
|
|
168
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')];
|
|
169
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')].filter(this.elementBelongsToView);
|
|
169
170
|
list.forEach(this.hideScrollElement.bind(this));
|
|
170
171
|
}
|
|
171
172
|
hideScrollElement(el, index) {
|
|
@@ -183,7 +184,7 @@ class WebflowView extends View {
|
|
|
183
184
|
console.warn("Unknown container", this);
|
|
184
185
|
return;
|
|
185
186
|
}
|
|
186
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')];
|
|
187
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')].filter(this.elementBelongsToView);
|
|
187
188
|
list.forEach(this.buildScrollmagicScene.bind(this));
|
|
188
189
|
}
|
|
189
190
|
/**
|
|
@@ -248,7 +249,7 @@ class WebflowView extends View {
|
|
|
248
249
|
console.warn("Unknown container", this);
|
|
249
250
|
return;
|
|
250
251
|
}
|
|
251
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBVIEW_HIDE + ']')];
|
|
252
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBVIEW_HIDE + ']')].filter(this.elementBelongsToView);
|
|
252
253
|
list.forEach(this.webViewsElementHide.bind(this));
|
|
253
254
|
}
|
|
254
255
|
// showe webview element
|
|
@@ -266,7 +267,7 @@ class WebflowView extends View {
|
|
|
266
267
|
console.warn("Unknown container", this);
|
|
267
268
|
return;
|
|
268
269
|
}
|
|
269
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_STAGGER_HIDE + ']')];
|
|
270
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_STAGGER_HIDE + ']')].filter(this.elementBelongsToView);
|
|
270
271
|
list.forEach(this.staggerListHide.bind(this));
|
|
271
272
|
}
|
|
272
273
|
// Hide stagger element
|
|
@@ -276,7 +277,7 @@ class WebflowView extends View {
|
|
|
276
277
|
console.warn("Unknown selector for webflow stagger", el);
|
|
277
278
|
return;
|
|
278
279
|
}
|
|
279
|
-
const items = [...el.querySelectorAll(selector)];
|
|
280
|
+
const items = [...el.querySelectorAll(selector)].filter(this.elementBelongsToView);
|
|
280
281
|
const propsHide = this.getTweenProps(el, DATA_ATTR_STAGGER_HIDE);
|
|
281
282
|
if (items.length && propsHide) {
|
|
282
283
|
gsap.killTweensOf(items);
|
|
@@ -292,7 +293,7 @@ class WebflowView extends View {
|
|
|
292
293
|
console.warn("Unknown container", this);
|
|
293
294
|
return;
|
|
294
295
|
}
|
|
295
|
-
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_HIDE + ']')];
|
|
296
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_HIDE + ']')].filter(this.elementBelongsToView);
|
|
296
297
|
list.forEach(this.hideScrollmagicElement.bind(this));
|
|
297
298
|
}
|
|
298
299
|
/**
|