@brandocms/jupiter 3.54.1 → 3.54.2
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/package.json
CHANGED
|
@@ -12,10 +12,10 @@ import Dom from '../Dom'
|
|
|
12
12
|
|
|
13
13
|
gsap.registerPlugin(ScrollToPlugin)
|
|
14
14
|
gsap.defaults({
|
|
15
|
-
ease: 'sine.out'
|
|
15
|
+
ease: 'sine.out',
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
-
window.onpageshow = event => {
|
|
18
|
+
window.onpageshow = (event) => {
|
|
19
19
|
if (event.persisted) {
|
|
20
20
|
const f = document.querySelector('#fader')
|
|
21
21
|
if (f) {
|
|
@@ -46,7 +46,7 @@ window.onpageshow = event => {
|
|
|
46
46
|
const DEFAULT_OPTIONS = {
|
|
47
47
|
respectReducedMotion: true,
|
|
48
48
|
featureTests: {
|
|
49
|
-
touch: true
|
|
49
|
+
touch: true,
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
focusableSelectors: [
|
|
@@ -55,7 +55,7 @@ const DEFAULT_OPTIONS = {
|
|
|
55
55
|
'select',
|
|
56
56
|
'button',
|
|
57
57
|
'textarea',
|
|
58
|
-
'iframe' // , 'video'?
|
|
58
|
+
'iframe', // , 'video'?
|
|
59
59
|
],
|
|
60
60
|
|
|
61
61
|
bindScroll: true,
|
|
@@ -79,10 +79,10 @@ const DEFAULT_OPTIONS = {
|
|
|
79
79
|
gsap.set(fader, { display: 'none' })
|
|
80
80
|
document.body.classList.remove('unloaded')
|
|
81
81
|
callback()
|
|
82
|
-
}
|
|
82
|
+
},
|
|
83
83
|
})
|
|
84
|
-
}
|
|
85
|
-
}
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
export default class Application {
|
|
@@ -101,16 +101,17 @@ export default class Application {
|
|
|
101
101
|
initialOuterHeight: 0,
|
|
102
102
|
initialInnerWidth: 0,
|
|
103
103
|
initialOuterWidth: 0,
|
|
104
|
-
zoom: 1
|
|
104
|
+
zoom: 1,
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
this.position = {
|
|
108
108
|
top: 0,
|
|
109
|
-
left: 0
|
|
109
|
+
left: 0,
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
this.state = {
|
|
113
|
-
revealed: false
|
|
113
|
+
revealed: false,
|
|
114
|
+
forcedScroll: false,
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
this.opts = _defaultsDeep(opts, DEFAULT_OPTIONS)
|
|
@@ -144,33 +145,48 @@ export default class Application {
|
|
|
144
145
|
gsap.globalTimeline.timeScale(200)
|
|
145
146
|
document.documentElement.classList.add('prefers-reduced-motion')
|
|
146
147
|
}
|
|
147
|
-
window.addEventListener(
|
|
148
|
+
window.addEventListener(
|
|
149
|
+
Events.BREAKPOINT_CHANGE,
|
|
150
|
+
this.onBreakpointChanged.bind(this)
|
|
151
|
+
)
|
|
148
152
|
|
|
149
|
-
this.beforeInitializedEvent = new window.CustomEvent(
|
|
150
|
-
|
|
153
|
+
this.beforeInitializedEvent = new window.CustomEvent(
|
|
154
|
+
Events.APPLICATION_PRELUDIUM,
|
|
155
|
+
this
|
|
156
|
+
)
|
|
157
|
+
this.initializedEvent = new window.CustomEvent(
|
|
158
|
+
Events.APPLICATION_INITIALIZED,
|
|
159
|
+
this
|
|
160
|
+
)
|
|
151
161
|
this.readyEvent = new window.CustomEvent(Events.APPLICATION_READY, this)
|
|
152
|
-
this.revealedEvent = new window.CustomEvent(
|
|
162
|
+
this.revealedEvent = new window.CustomEvent(
|
|
163
|
+
Events.APPLICATION_REVEALED,
|
|
164
|
+
this
|
|
165
|
+
)
|
|
153
166
|
|
|
154
167
|
/**
|
|
155
168
|
* Grab common events and defer
|
|
156
169
|
*/
|
|
157
|
-
document.addEventListener(
|
|
170
|
+
document.addEventListener(
|
|
171
|
+
'visibilitychange',
|
|
172
|
+
this.onVisibilityChange.bind(this)
|
|
173
|
+
)
|
|
158
174
|
window.addEventListener('orientationchange', this.onResize.bind(this), {
|
|
159
175
|
capture: false,
|
|
160
|
-
passive: true
|
|
176
|
+
passive: true,
|
|
161
177
|
})
|
|
162
178
|
|
|
163
179
|
if (opts.bindScroll) {
|
|
164
180
|
window.addEventListener('scroll', rafCallback(this.onScroll.bind(this)), {
|
|
165
181
|
capture: false,
|
|
166
|
-
passive: true
|
|
182
|
+
passive: true,
|
|
167
183
|
})
|
|
168
184
|
}
|
|
169
185
|
|
|
170
186
|
if (opts.bindResize) {
|
|
171
187
|
window.addEventListener('resize', rafCallback(this.onResize.bind(this)), {
|
|
172
188
|
capture: false,
|
|
173
|
-
passive: true
|
|
189
|
+
passive: true,
|
|
174
190
|
})
|
|
175
191
|
}
|
|
176
192
|
}
|
|
@@ -208,7 +224,10 @@ export default class Application {
|
|
|
208
224
|
break
|
|
209
225
|
|
|
210
226
|
case 'safari':
|
|
211
|
-
this._zoomSVG = document.createElementNS(
|
|
227
|
+
this._zoomSVG = document.createElementNS(
|
|
228
|
+
'http://www.w3.org/2000/svg',
|
|
229
|
+
'svg'
|
|
230
|
+
)
|
|
212
231
|
this._zoomSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
|
|
213
232
|
this._zoomSVG.setAttribute('version', '1.1')
|
|
214
233
|
gsap.set(this._zoomSVG, { display: 'none' })
|
|
@@ -252,13 +271,17 @@ export default class Application {
|
|
|
252
271
|
default:
|
|
253
272
|
if ([1, -1].indexOf(dprDelta) === -1) {
|
|
254
273
|
if (dimsChanged) {
|
|
255
|
-
this.size.zoom =
|
|
274
|
+
this.size.zoom =
|
|
275
|
+
1 + (zoom.calculate(this.browser) - this._initialZoom)
|
|
256
276
|
if (this.size.zoom === 0) {
|
|
257
277
|
this.size.zoom = 1
|
|
258
278
|
}
|
|
259
279
|
}
|
|
260
280
|
} else {
|
|
261
|
-
this._initialZoom = Math.min(
|
|
281
|
+
this._initialZoom = Math.min(
|
|
282
|
+
Math.max(this._initialZoom - dprDelta, 1),
|
|
283
|
+
2
|
|
284
|
+
)
|
|
262
285
|
}
|
|
263
286
|
}
|
|
264
287
|
|
|
@@ -289,7 +312,7 @@ export default class Application {
|
|
|
289
312
|
if (!Object.prototype.hasOwnProperty.call(this.callbacks, type)) {
|
|
290
313
|
return
|
|
291
314
|
}
|
|
292
|
-
this.callbacks[type].forEach(cb => cb(this))
|
|
315
|
+
this.callbacks[type].forEach((cb) => cb(this))
|
|
293
316
|
}
|
|
294
317
|
|
|
295
318
|
/**
|
|
@@ -325,7 +348,9 @@ export default class Application {
|
|
|
325
348
|
window.dispatchEvent(ev)
|
|
326
349
|
this.SCROLL_LOCKED = true
|
|
327
350
|
gsap.set(document.body, { overflow: 'hidden' })
|
|
328
|
-
gsap.set(this._scrollPaddedElements, {
|
|
351
|
+
gsap.set(this._scrollPaddedElements, {
|
|
352
|
+
paddingRight: currentScrollbarWidth,
|
|
353
|
+
})
|
|
329
354
|
document.addEventListener('touchmove', this.scrollVoid, false)
|
|
330
355
|
}
|
|
331
356
|
|
|
@@ -350,7 +375,10 @@ export default class Application {
|
|
|
350
375
|
*/
|
|
351
376
|
scrollTo(target, time = 0.8, emitEvents = true, ease = 'sine.inOut') {
|
|
352
377
|
let scrollToData
|
|
353
|
-
const forcedScrollEventStart = new window.CustomEvent(
|
|
378
|
+
const forcedScrollEventStart = new window.CustomEvent(
|
|
379
|
+
Events.APPLICATION_FORCED_SCROLL_START
|
|
380
|
+
)
|
|
381
|
+
this.state.forcedScroll = true
|
|
354
382
|
if (emitEvents) {
|
|
355
383
|
window.dispatchEvent(forcedScrollEventStart)
|
|
356
384
|
}
|
|
@@ -365,12 +393,15 @@ export default class Application {
|
|
|
365
393
|
duration: time,
|
|
366
394
|
scrollTo: scrollToData,
|
|
367
395
|
onComplete: () => {
|
|
368
|
-
const forcedScrollEventEnd = new window.CustomEvent(
|
|
396
|
+
const forcedScrollEventEnd = new window.CustomEvent(
|
|
397
|
+
Events.APPLICATION_FORCED_SCROLL_END
|
|
398
|
+
)
|
|
369
399
|
if (emitEvents) {
|
|
370
400
|
window.dispatchEvent(forcedScrollEventEnd)
|
|
401
|
+
requestAnimationFrame(() => (this.state.forcedScroll = false))
|
|
371
402
|
}
|
|
372
403
|
},
|
|
373
|
-
ease
|
|
404
|
+
ease,
|
|
374
405
|
})
|
|
375
406
|
}
|
|
376
407
|
|
|
@@ -516,10 +547,22 @@ export default class Application {
|
|
|
516
547
|
this.size.initialOuterWidth = window.outerWidth
|
|
517
548
|
this.size.scrollHeight = document.body.scrollHeight
|
|
518
549
|
|
|
519
|
-
root.style.setProperty(
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
550
|
+
root.style.setProperty(
|
|
551
|
+
'--vp-initial-inner-h',
|
|
552
|
+
`${this.size.initialInnerHeight}px`
|
|
553
|
+
)
|
|
554
|
+
root.style.setProperty(
|
|
555
|
+
'--vp-initial-outer-h',
|
|
556
|
+
`${this.size.initialOuterHeight}px`
|
|
557
|
+
)
|
|
558
|
+
root.style.setProperty(
|
|
559
|
+
'--vp-initial-inner-w',
|
|
560
|
+
`${this.size.initialInnerWidth}px`
|
|
561
|
+
)
|
|
562
|
+
root.style.setProperty(
|
|
563
|
+
'--vp-initial-outer-w',
|
|
564
|
+
`${this.size.initialOuterWidth}px`
|
|
565
|
+
)
|
|
523
566
|
root.style.setProperty('--ec-zoom', `${this.size.zoom}`)
|
|
524
567
|
root.style.setProperty('--scroll-h', `${this.size.scrollHeight}px`)
|
|
525
568
|
|
|
@@ -551,7 +594,9 @@ export default class Application {
|
|
|
551
594
|
*/
|
|
552
595
|
setvh100() {
|
|
553
596
|
const root = document.querySelector(':root')
|
|
554
|
-
const height = this.featureTests.results.ios
|
|
597
|
+
const height = this.featureTests.results.ios
|
|
598
|
+
? screen.height
|
|
599
|
+
: window.innerHeight
|
|
555
600
|
root.style.setProperty('--vp-100vh', `${height}px`)
|
|
556
601
|
root.style.setProperty('--vp-1vh', `${height * 0.01}px`)
|
|
557
602
|
}
|
|
@@ -603,7 +648,7 @@ export default class Application {
|
|
|
603
648
|
this.setFontBaseVw()
|
|
604
649
|
|
|
605
650
|
const evt = new CustomEvent(Events.APPLICATION_RESIZE, {
|
|
606
|
-
detail: { widthChanged, heightChanged }
|
|
651
|
+
detail: { widthChanged, heightChanged },
|
|
607
652
|
})
|
|
608
653
|
window.dispatchEvent(evt)
|
|
609
654
|
}
|
|
@@ -672,9 +717,13 @@ export default class Application {
|
|
|
672
717
|
|
|
673
718
|
const span = userAgent.querySelector('span')
|
|
674
719
|
const windowWidth =
|
|
675
|
-
window.innerWidth ||
|
|
720
|
+
window.innerWidth ||
|
|
721
|
+
document.documentElement.clientWidth ||
|
|
722
|
+
document.body.clientWidth
|
|
676
723
|
const windowHeight =
|
|
677
|
-
window.innerHeight ||
|
|
724
|
+
window.innerHeight ||
|
|
725
|
+
document.documentElement.clientHeight ||
|
|
726
|
+
document.body.clientHeight
|
|
678
727
|
|
|
679
728
|
span.addEventListener('click', () => {
|
|
680
729
|
const copyText = userAgent.querySelector('b')
|
|
@@ -724,7 +773,7 @@ ${JSON.stringify(this.featureTests.results, undefined, 2)}
|
|
|
724
773
|
gsap.set(breakpoint, { width: 'auto', display: 'block' })
|
|
725
774
|
tl.from(breakpoint, { duration: 0.7, width: 0 }).to(breakpoint, {
|
|
726
775
|
duration: 0.3,
|
|
727
|
-
autoAlpha: 1
|
|
776
|
+
autoAlpha: 1,
|
|
728
777
|
})
|
|
729
778
|
break
|
|
730
779
|
|
|
@@ -733,7 +782,7 @@ ${JSON.stringify(this.featureTests.results, undefined, 2)}
|
|
|
733
782
|
gsap.set(userAgent, { width: 'auto', display: 'block' })
|
|
734
783
|
tl.from(userAgent, { duration: 0.7, width: 0 }).to(userAgent, {
|
|
735
784
|
duration: 0.3,
|
|
736
|
-
autoAlpha: 1
|
|
785
|
+
autoAlpha: 1,
|
|
737
786
|
})
|
|
738
787
|
break
|
|
739
788
|
|
|
@@ -746,7 +795,7 @@ ${JSON.stringify(this.featureTests.results, undefined, 2)}
|
|
|
746
795
|
* CTRL-G to show grid overlay
|
|
747
796
|
*/
|
|
748
797
|
setupGridoverlay() {
|
|
749
|
-
const gridKeyPressed = e => {
|
|
798
|
+
const gridKeyPressed = (e) => {
|
|
750
799
|
if (e.keyCode === 71 && e.ctrlKey) {
|
|
751
800
|
const guides = Dom.find('.dbg-grid')
|
|
752
801
|
const cols = Dom.all(guides, 'b')
|
|
@@ -764,7 +813,7 @@ ${JSON.stringify(this.featureTests.results, undefined, 2)}
|
|
|
764
813
|
ease: 'sine.inOut',
|
|
765
814
|
onComplete: () => {
|
|
766
815
|
guides.classList.toggle('visible')
|
|
767
|
-
}
|
|
816
|
+
},
|
|
768
817
|
})
|
|
769
818
|
} else {
|
|
770
819
|
gsap.set(cols, { width: 0 })
|
|
@@ -773,7 +822,7 @@ ${JSON.stringify(this.featureTests.results, undefined, 2)}
|
|
|
773
822
|
duration: 0.35,
|
|
774
823
|
width: '100%',
|
|
775
824
|
stagger: 0.02,
|
|
776
|
-
ease: 'sine.inOut'
|
|
825
|
+
ease: 'sine.inOut',
|
|
777
826
|
})
|
|
778
827
|
}
|
|
779
828
|
}
|
|
@@ -42,7 +42,7 @@ const DEFAULT_OPTIONS = {
|
|
|
42
42
|
page: 0,
|
|
43
43
|
loaderParam: {},
|
|
44
44
|
filter: '',
|
|
45
|
-
onFetch: dataloader => {
|
|
45
|
+
onFetch: (dataloader) => {
|
|
46
46
|
/**
|
|
47
47
|
* Called after fetch complete. Do your DOM manipulation here
|
|
48
48
|
*
|
|
@@ -53,7 +53,7 @@ const DEFAULT_OPTIONS = {
|
|
|
53
53
|
* new EqualHeightImages(dataloader.app, {}, dataloader.$canvasEl)
|
|
54
54
|
* mw.ready()
|
|
55
55
|
*/
|
|
56
|
-
}
|
|
56
|
+
},
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export default class Dataloader {
|
|
@@ -71,12 +71,12 @@ export default class Dataloader {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
static replaceInnerHTML(el, url) {
|
|
74
|
-
return new Promise(resolve => {
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
75
|
fetch(url)
|
|
76
|
-
.then(res => {
|
|
76
|
+
.then((res) => {
|
|
77
77
|
return res.text()
|
|
78
78
|
})
|
|
79
|
-
.then(html => {
|
|
79
|
+
.then((html) => {
|
|
80
80
|
el.innerHTML = html
|
|
81
81
|
return resolve(el)
|
|
82
82
|
})
|
|
@@ -101,7 +101,7 @@ export default class Dataloader {
|
|
|
101
101
|
this.baseURL = this.$el.dataset.loader
|
|
102
102
|
this.$paramEls = Dom.all(this.$el, '[data-loader-param]')
|
|
103
103
|
|
|
104
|
-
this.$paramEls.forEach($paramEl => {
|
|
104
|
+
this.$paramEls.forEach(($paramEl) => {
|
|
105
105
|
$paramEl.addEventListener('click', this.onParam.bind(this))
|
|
106
106
|
})
|
|
107
107
|
|
|
@@ -119,7 +119,10 @@ export default class Dataloader {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
if (this.$filterInput) {
|
|
122
|
-
this.$filterInput.addEventListener(
|
|
122
|
+
this.$filterInput.addEventListener(
|
|
123
|
+
'input',
|
|
124
|
+
this.debounce(this.onFilterInput.bind(this))
|
|
125
|
+
)
|
|
123
126
|
}
|
|
124
127
|
}
|
|
125
128
|
|
|
@@ -156,14 +159,15 @@ export default class Dataloader {
|
|
|
156
159
|
// if already selected, clear it
|
|
157
160
|
const key = e.currentTarget.dataset.loaderParamKey || 'defaultParam'
|
|
158
161
|
if (multiVals) {
|
|
159
|
-
this.opts.loaderParam[key] = this.opts.loaderParam[key].filter(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
this.opts.loaderParam[key] = this.opts.loaderParam[key].filter(
|
|
163
|
+
(val) => {
|
|
164
|
+
return val !== e.currentTarget.dataset.loaderParam
|
|
165
|
+
}
|
|
166
|
+
)
|
|
162
167
|
} else {
|
|
163
168
|
delete this.opts.loaderParam[key]
|
|
164
169
|
}
|
|
165
170
|
e.currentTarget.removeAttribute('data-loader-param-selected')
|
|
166
|
-
console.log(this.opts.loaderParam[key])
|
|
167
171
|
} else {
|
|
168
172
|
if (multiVals) {
|
|
169
173
|
const key = e.currentTarget.dataset.loaderParamKey || 'defaultParam'
|
|
@@ -174,7 +178,7 @@ export default class Dataloader {
|
|
|
174
178
|
e.currentTarget.setAttribute('data-loader-param-selected', '')
|
|
175
179
|
} else {
|
|
176
180
|
const paramKey = e.currentTarget.dataset.loaderParamKey
|
|
177
|
-
this.$paramEls.forEach($paramEl => {
|
|
181
|
+
this.$paramEls.forEach(($paramEl) => {
|
|
178
182
|
if (paramKey) {
|
|
179
183
|
if ($paramEl.dataset.loaderParamKey === paramKey) {
|
|
180
184
|
$paramEl.removeAttribute('data-loader-param-selected')
|
|
@@ -201,12 +205,12 @@ export default class Dataloader {
|
|
|
201
205
|
`${this.baseURL}/${defaultParam ? defaultParam + '/' : ''}${this.opts.page}?` +
|
|
202
206
|
new URLSearchParams({ filter, ...otherParams })
|
|
203
207
|
)
|
|
204
|
-
.then(res => {
|
|
208
|
+
.then((res) => {
|
|
205
209
|
this.status = res.headers.get('jpt-dataloader') || 'available'
|
|
206
210
|
this.updateButton()
|
|
207
211
|
return res.text()
|
|
208
212
|
})
|
|
209
|
-
.then(html => {
|
|
213
|
+
.then((html) => {
|
|
210
214
|
if (addEntries) {
|
|
211
215
|
this.$canvasEl.innerHTML += html
|
|
212
216
|
} else {
|
|
@@ -29,16 +29,16 @@ import * as Events from '../../events'
|
|
|
29
29
|
import Dom from '../Dom'
|
|
30
30
|
|
|
31
31
|
const DEFAULT_EVENTS = {
|
|
32
|
-
onPin: h => {
|
|
32
|
+
onPin: (h) => {
|
|
33
33
|
gsap.to(h.el, {
|
|
34
34
|
duration: 0.35,
|
|
35
35
|
yPercent: '0',
|
|
36
36
|
ease: 'sine.out',
|
|
37
|
-
autoRound: true
|
|
37
|
+
autoRound: true,
|
|
38
38
|
})
|
|
39
39
|
},
|
|
40
40
|
|
|
41
|
-
onUnpin: h => {
|
|
41
|
+
onUnpin: (h) => {
|
|
42
42
|
h._hiding = true
|
|
43
43
|
gsap.to(h.el, {
|
|
44
44
|
duration: 0.25,
|
|
@@ -47,50 +47,50 @@ const DEFAULT_EVENTS = {
|
|
|
47
47
|
autoRound: true,
|
|
48
48
|
onComplete: () => {
|
|
49
49
|
h._hiding = false
|
|
50
|
-
}
|
|
50
|
+
},
|
|
51
51
|
})
|
|
52
52
|
},
|
|
53
53
|
|
|
54
|
-
onAltBg: h => {
|
|
54
|
+
onAltBg: (h) => {
|
|
55
55
|
if (h.opts.altBgColor) {
|
|
56
56
|
gsap.to(h.el, {
|
|
57
57
|
duration: 0.2,
|
|
58
|
-
backgroundColor: h.opts.altBgColor
|
|
58
|
+
backgroundColor: h.opts.altBgColor,
|
|
59
59
|
})
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
|
|
63
|
-
onNotAltBg: h => {
|
|
63
|
+
onNotAltBg: (h) => {
|
|
64
64
|
if (h.opts.regBgColor) {
|
|
65
65
|
gsap.to(h.el, {
|
|
66
66
|
duration: 0.4,
|
|
67
|
-
backgroundColor: h.opts.regBgColor
|
|
67
|
+
backgroundColor: h.opts.regBgColor,
|
|
68
68
|
})
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
71
|
|
|
72
72
|
// eslint-disable-next-line no-unused-vars
|
|
73
|
-
onSmall: h => {},
|
|
73
|
+
onSmall: (h) => {},
|
|
74
74
|
// eslint-disable-next-line no-unused-vars
|
|
75
|
-
onNotSmall: h => {},
|
|
75
|
+
onNotSmall: (h) => {},
|
|
76
76
|
// eslint-disable-next-line no-unused-vars
|
|
77
|
-
onTop: h => {},
|
|
77
|
+
onTop: (h) => {},
|
|
78
78
|
// eslint-disable-next-line no-unused-vars
|
|
79
|
-
onNotTop: h => {},
|
|
79
|
+
onNotTop: (h) => {},
|
|
80
80
|
// eslint-disable-next-line no-unused-vars
|
|
81
|
-
onBottom: h => {},
|
|
81
|
+
onBottom: (h) => {},
|
|
82
82
|
// eslint-disable-next-line no-unused-vars
|
|
83
|
-
onNotBottom: h => {},
|
|
83
|
+
onNotBottom: (h) => {},
|
|
84
84
|
// eslint-disable-next-line no-unused-vars
|
|
85
|
-
onMobileMenuOpen: h => {},
|
|
85
|
+
onMobileMenuOpen: (h) => {},
|
|
86
86
|
// eslint-disable-next-line no-unused-vars
|
|
87
|
-
onMobileMenuClose: h => {},
|
|
87
|
+
onMobileMenuClose: (h) => {},
|
|
88
88
|
// eslint-disable-next-line no-unused-vars
|
|
89
|
-
onIntersect: h => {},
|
|
90
|
-
onOutline: h => {
|
|
89
|
+
onIntersect: (h) => {},
|
|
90
|
+
onOutline: (h) => {
|
|
91
91
|
h.preventUnpin = true
|
|
92
92
|
h.pin()
|
|
93
|
-
}
|
|
93
|
+
},
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
const DEFAULT_OPTIONS = {
|
|
@@ -98,18 +98,19 @@ const DEFAULT_OPTIONS = {
|
|
|
98
98
|
on: Events.APPLICATION_REVEALED,
|
|
99
99
|
unpinOnForcedScrollStart: true,
|
|
100
100
|
pinOnForcedScrollEnd: true,
|
|
101
|
+
ignoreForcedScroll: false,
|
|
101
102
|
rafScroll: true,
|
|
102
103
|
|
|
103
104
|
default: {
|
|
104
105
|
unPinOnResize: true,
|
|
105
106
|
canvas: window,
|
|
106
107
|
intersects: null,
|
|
107
|
-
beforeEnter: h => {
|
|
108
|
+
beforeEnter: (h) => {
|
|
108
109
|
const timeline = gsap.timeline()
|
|
109
110
|
timeline.set(h.el, { yPercent: -100 }).set(h.lis, { opacity: 0 })
|
|
110
111
|
},
|
|
111
112
|
|
|
112
|
-
enter: h => {
|
|
113
|
+
enter: (h) => {
|
|
113
114
|
const timeline = gsap.timeline()
|
|
114
115
|
timeline
|
|
115
116
|
.to(h.el, {
|
|
@@ -117,7 +118,7 @@ const DEFAULT_OPTIONS = {
|
|
|
117
118
|
yPercent: 0,
|
|
118
119
|
delay: h.opts.enterDelay,
|
|
119
120
|
ease: 'power3.out',
|
|
120
|
-
autoRound: true
|
|
121
|
+
autoRound: true,
|
|
121
122
|
})
|
|
122
123
|
.staggerTo(h.lis, 0.8, { opacity: 1, ease: 'sine.in' }, 0.1, '-=1')
|
|
123
124
|
},
|
|
@@ -129,8 +130,8 @@ const DEFAULT_OPTIONS = {
|
|
|
129
130
|
offsetBg: 200, // how far down before changing backgroundcolor
|
|
130
131
|
regBgColor: null,
|
|
131
132
|
altBgColor: null,
|
|
132
|
-
...DEFAULT_EVENTS
|
|
133
|
-
}
|
|
133
|
+
...DEFAULT_EVENTS,
|
|
134
|
+
},
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
export default class FixedHeader {
|
|
@@ -223,7 +224,11 @@ export default class FixedHeader {
|
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
if (this.mainOpts.pinOnForcedScrollEnd) {
|
|
226
|
-
window.addEventListener(
|
|
227
|
+
window.addEventListener(
|
|
228
|
+
Events.APPLICATION_FORCED_SCROLL_END,
|
|
229
|
+
this.pin.bind(this),
|
|
230
|
+
false
|
|
231
|
+
)
|
|
227
232
|
}
|
|
228
233
|
|
|
229
234
|
this.app.registerCallback(Events.APPLICATION_REVEALED, () => {
|
|
@@ -234,11 +239,14 @@ export default class FixedHeader {
|
|
|
234
239
|
|
|
235
240
|
window.addEventListener(SCROLL_EVENT, this.redraw.bind(this), {
|
|
236
241
|
capture: false,
|
|
237
|
-
passive: true
|
|
242
|
+
passive: true,
|
|
238
243
|
})
|
|
239
244
|
})
|
|
240
245
|
|
|
241
|
-
this.app.registerCallback(
|
|
246
|
+
this.app.registerCallback(
|
|
247
|
+
Events.APPLICATION_READY,
|
|
248
|
+
this.unpinIfScrolled.bind(this)
|
|
249
|
+
)
|
|
242
250
|
|
|
243
251
|
this.preflight()
|
|
244
252
|
|
|
@@ -248,7 +256,11 @@ export default class FixedHeader {
|
|
|
248
256
|
|
|
249
257
|
// DON'T unpin on iOS since this will unpin when bottom menu bar appears on scrolling upwards!
|
|
250
258
|
if (this.opts.unPinOnResize && !this.app.featureTests.results.ios) {
|
|
251
|
-
window.addEventListener(
|
|
259
|
+
window.addEventListener(
|
|
260
|
+
Events.APPLICATION_RESIZE,
|
|
261
|
+
this.setResizeTimer.bind(this),
|
|
262
|
+
false
|
|
263
|
+
)
|
|
252
264
|
}
|
|
253
265
|
|
|
254
266
|
this.opts.beforeEnter(this)
|
|
@@ -367,7 +379,10 @@ export default class FixedHeader {
|
|
|
367
379
|
}
|
|
368
380
|
|
|
369
381
|
checkBot(force) {
|
|
370
|
-
if (
|
|
382
|
+
if (
|
|
383
|
+
this.currentScrollY + this.getViewportHeight() >=
|
|
384
|
+
this.getScrollerHeight()
|
|
385
|
+
) {
|
|
371
386
|
if (force) {
|
|
372
387
|
this.bottom()
|
|
373
388
|
} else if (!this._bottom) {
|
|
@@ -411,7 +426,10 @@ export default class FixedHeader {
|
|
|
411
426
|
|
|
412
427
|
/* content-visibility: auto may CHANGE the scrollheight of the document
|
|
413
428
|
as we roll down/up. Try to avoid false positives here */
|
|
414
|
-
if (
|
|
429
|
+
if (
|
|
430
|
+
this.currentScrollHeight !== this.lastKnownScrollHeight &&
|
|
431
|
+
!this._firstLoad
|
|
432
|
+
) {
|
|
415
433
|
this.lastKnownScrollY = this.currentScrollY
|
|
416
434
|
this.lastKnownScrollHeight = this.currentScrollHeight
|
|
417
435
|
return
|
|
@@ -421,7 +439,12 @@ export default class FixedHeader {
|
|
|
421
439
|
this.checkBg(false)
|
|
422
440
|
this.checkTop(false)
|
|
423
441
|
this.checkBot(false)
|
|
424
|
-
|
|
442
|
+
|
|
443
|
+
if (this.mainOpts.ignoreForcedScroll && this.app.state.forcedScroll) {
|
|
444
|
+
// ignore forced scroll
|
|
445
|
+
} else {
|
|
446
|
+
this.checkPin(false, toleranceExceeded)
|
|
447
|
+
}
|
|
425
448
|
|
|
426
449
|
this.lastKnownScrollY = this.currentScrollY
|
|
427
450
|
this.lastKnownScrollHeight = this.currentScrollHeight
|
|
@@ -526,7 +549,8 @@ export default class FixedHeader {
|
|
|
526
549
|
isOutOfBounds() {
|
|
527
550
|
const pastTop = this.currentScrollY < 0
|
|
528
551
|
const pastBottom =
|
|
529
|
-
this.currentScrollY + this.getScrollerPhysicalHeight() >
|
|
552
|
+
this.currentScrollY + this.getScrollerPhysicalHeight() >
|
|
553
|
+
this.getScrollerHeight()
|
|
530
554
|
|
|
531
555
|
return pastTop || pastBottom
|
|
532
556
|
}
|
|
@@ -559,7 +583,9 @@ export default class FixedHeader {
|
|
|
559
583
|
|
|
560
584
|
getViewportHeight() {
|
|
561
585
|
return (
|
|
562
|
-
window.innerHeight ||
|
|
586
|
+
window.innerHeight ||
|
|
587
|
+
document.documentElement.clientHeight ||
|
|
588
|
+
document.body.clientHeight
|
|
563
589
|
)
|
|
564
590
|
}
|
|
565
591
|
|
|
@@ -578,11 +604,18 @@ export default class FixedHeader {
|
|
|
578
604
|
if (this.opts.canvas.scrollTop !== undefined) {
|
|
579
605
|
return this.opts.canvas.scrollTop
|
|
580
606
|
}
|
|
581
|
-
return (
|
|
607
|
+
return (
|
|
608
|
+
document.documentElement ||
|
|
609
|
+
document.body.parentNode ||
|
|
610
|
+
document.body
|
|
611
|
+
).scrollTop
|
|
582
612
|
}
|
|
583
613
|
|
|
584
614
|
toleranceExceeded() {
|
|
585
|
-
return
|
|
615
|
+
return (
|
|
616
|
+
Math.abs(this.currentScrollY - this.lastKnownScrollY) >=
|
|
617
|
+
this.opts.tolerance
|
|
618
|
+
)
|
|
586
619
|
}
|
|
587
620
|
|
|
588
621
|
_getOptionsForSection(section, opts) {
|
|
@@ -601,8 +634,14 @@ export default class FixedHeader {
|
|
|
601
634
|
}
|
|
602
635
|
|
|
603
636
|
_bindMobileMenuListeners() {
|
|
604
|
-
window.addEventListener(
|
|
605
|
-
|
|
637
|
+
window.addEventListener(
|
|
638
|
+
'APPLICATION:MOBILE_MENU:OPEN',
|
|
639
|
+
this._onMobileMenuOpen.bind(this)
|
|
640
|
+
)
|
|
641
|
+
window.addEventListener(
|
|
642
|
+
'APPLICATION:MOBILE_MENU:CLOSED',
|
|
643
|
+
this._onMobileMenuClose.bind(this)
|
|
644
|
+
)
|
|
606
645
|
}
|
|
607
646
|
|
|
608
647
|
_onMobileMenuOpen() {
|
|
@@ -7,17 +7,17 @@ import * as Events from '../../events'
|
|
|
7
7
|
const DEFAULT_OPTIONS = {
|
|
8
8
|
revealIntersectionObserverConfig: {
|
|
9
9
|
rootMargin: '0px 100px 0px 100px',
|
|
10
|
-
threshold: 0.0
|
|
10
|
+
threshold: 0.0,
|
|
11
11
|
},
|
|
12
12
|
loadIntersectionObserverConfig: {
|
|
13
13
|
rootMargin: '850px 500px 850px 500px',
|
|
14
|
-
threshold: 0.0
|
|
14
|
+
threshold: 0.0,
|
|
15
15
|
},
|
|
16
16
|
useNativeLazyloadIfAvailable: true,
|
|
17
17
|
mode: 'default',
|
|
18
18
|
minSize: 40,
|
|
19
19
|
updateSizes: true,
|
|
20
|
-
registerCallback: true
|
|
20
|
+
registerCallback: true,
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export default class Lazyload {
|
|
@@ -49,16 +49,21 @@ export default class Lazyload {
|
|
|
49
49
|
this.initializeSections()
|
|
50
50
|
|
|
51
51
|
// if we have native lazyload, use it.
|
|
52
|
-
if (
|
|
52
|
+
if (
|
|
53
|
+
'loading' in HTMLImageElement.prototype &&
|
|
54
|
+
this.opts.useNativeLazyloadIfAvailable
|
|
55
|
+
) {
|
|
53
56
|
const lazyImages = document.querySelectorAll('[data-ll-image]')
|
|
54
|
-
lazyImages.forEach(img => {
|
|
57
|
+
lazyImages.forEach((img) => {
|
|
55
58
|
img.setAttribute('loading', 'lazy')
|
|
56
59
|
this.swapImage(img)
|
|
57
60
|
})
|
|
58
61
|
|
|
59
62
|
const lazyPictures = document.querySelectorAll('[data-ll-srcset]')
|
|
60
|
-
lazyPictures.forEach(picture => {
|
|
61
|
-
picture
|
|
63
|
+
lazyPictures.forEach((picture) => {
|
|
64
|
+
picture
|
|
65
|
+
.querySelectorAll('img')
|
|
66
|
+
.forEach((img) => img.setAttribute('loading', 'lazy'))
|
|
62
67
|
this.swapPicture(picture)
|
|
63
68
|
})
|
|
64
69
|
|
|
@@ -98,7 +103,7 @@ export default class Lazyload {
|
|
|
98
103
|
this.lazyPictures.forEach((picture, idx) => {
|
|
99
104
|
if (setAttrs) {
|
|
100
105
|
picture.setAttribute('data-ll-srcset-initialized', '')
|
|
101
|
-
picture.querySelectorAll('img:not([data-ll-loaded])').forEach(img => {
|
|
106
|
+
picture.querySelectorAll('img:not([data-ll-loaded])').forEach((img) => {
|
|
102
107
|
img.setAttribute('data-ll-blurred', '')
|
|
103
108
|
img.setAttribute('data-ll-idx', idx)
|
|
104
109
|
img.style.setProperty('--ll-idx', idx)
|
|
@@ -108,6 +113,14 @@ export default class Lazyload {
|
|
|
108
113
|
})
|
|
109
114
|
}
|
|
110
115
|
|
|
116
|
+
forceLoad($container = document.body) {
|
|
117
|
+
const images = Dom.all($container, '[data-ll-image]')
|
|
118
|
+
images.forEach((img) => this.swapImage(img))
|
|
119
|
+
|
|
120
|
+
const pictures = Dom.all($container, '[data-ll-srcset]')
|
|
121
|
+
pictures.forEach((picture) => this.revealPicture(picture))
|
|
122
|
+
}
|
|
123
|
+
|
|
111
124
|
initializeAutoSizes() {
|
|
112
125
|
if (this.opts.updateSizes) {
|
|
113
126
|
this.$autoSizesImages = Dom.all('[data-sizes="auto"]')
|
|
@@ -120,11 +133,11 @@ export default class Lazyload {
|
|
|
120
133
|
* Set sizes attribute for all imgs with `data-sizes="auto"` and source within the <picture>
|
|
121
134
|
*/
|
|
122
135
|
autoSizes() {
|
|
123
|
-
Array.from(this.$autoSizesImages).forEach(img => {
|
|
136
|
+
Array.from(this.$autoSizesImages).forEach((img) => {
|
|
124
137
|
const width = this.getWidth(img)
|
|
125
138
|
img.setAttribute('sizes', `${width}px`)
|
|
126
139
|
if (img.parentNode) {
|
|
127
|
-
Array.from(Dom.all(img.parentNode, 'source')).forEach(source =>
|
|
140
|
+
Array.from(Dom.all(img.parentNode, 'source')).forEach((source) =>
|
|
128
141
|
source.setAttribute('sizes', `${width}px`)
|
|
129
142
|
)
|
|
130
143
|
}
|
|
@@ -149,12 +162,12 @@ export default class Lazyload {
|
|
|
149
162
|
const sectionObserver = (section, children) => {
|
|
150
163
|
const imagesInSection = Dom.all(section, 'img')
|
|
151
164
|
return new IntersectionObserver((entries, self) => {
|
|
152
|
-
entries.forEach(entry => {
|
|
165
|
+
entries.forEach((entry) => {
|
|
153
166
|
if (entry.isIntersecting || entry.intersectionRatio > 0) {
|
|
154
167
|
imagesAreLoaded(imagesInSection, true).then(() => {
|
|
155
168
|
dispatchElementEvent(section, Events.SECTION_LAZYLOADED)
|
|
156
169
|
})
|
|
157
|
-
children.forEach(picture => {
|
|
170
|
+
children.forEach((picture) => {
|
|
158
171
|
this.loadPicture(picture)
|
|
159
172
|
this.loadObserver.unobserve(picture)
|
|
160
173
|
})
|
|
@@ -164,7 +177,7 @@ export default class Lazyload {
|
|
|
164
177
|
}, this.opts.intersectionObserverConfig)
|
|
165
178
|
}
|
|
166
179
|
|
|
167
|
-
sections.forEach(section => {
|
|
180
|
+
sections.forEach((section) => {
|
|
168
181
|
const children = section.querySelectorAll('picture')
|
|
169
182
|
const obs = sectionObserver(section, children)
|
|
170
183
|
obs.observe(section)
|
|
@@ -174,7 +187,7 @@ export default class Lazyload {
|
|
|
174
187
|
|
|
175
188
|
// we load the picture a ways before it enters the viewport
|
|
176
189
|
handleLoadEntries(elements) {
|
|
177
|
-
elements.forEach(item => {
|
|
190
|
+
elements.forEach((item) => {
|
|
178
191
|
if (item.isIntersecting || item.intersectionRatio > 0) {
|
|
179
192
|
const picture = item.target
|
|
180
193
|
this.loadPicture(picture)
|
|
@@ -185,16 +198,19 @@ export default class Lazyload {
|
|
|
185
198
|
|
|
186
199
|
// we reveal the picture when it enters the viewport
|
|
187
200
|
handleRevealEntries(elements) {
|
|
188
|
-
const srcsetReadyObserver = new MutationObserver(mutations => {
|
|
189
|
-
mutations.forEach(record => {
|
|
190
|
-
if (
|
|
201
|
+
const srcsetReadyObserver = new MutationObserver((mutations) => {
|
|
202
|
+
mutations.forEach((record) => {
|
|
203
|
+
if (
|
|
204
|
+
record.type === 'attributes' &&
|
|
205
|
+
record.attributeName === 'data-ll-srcset-ready'
|
|
206
|
+
) {
|
|
191
207
|
this.revealPicture(record.target)
|
|
192
208
|
this.revealObserver.unobserve(record.target)
|
|
193
209
|
}
|
|
194
210
|
})
|
|
195
211
|
})
|
|
196
212
|
|
|
197
|
-
elements.forEach(item => {
|
|
213
|
+
elements.forEach((item) => {
|
|
198
214
|
if (item.isIntersecting || item.intersectionRatio > 0) {
|
|
199
215
|
const picture = item.target
|
|
200
216
|
const ready = item.target.hasAttribute('data-ll-srcset-ready')
|
|
@@ -233,7 +249,10 @@ export default class Lazyload {
|
|
|
233
249
|
const img = picture.querySelector('img')
|
|
234
250
|
|
|
235
251
|
const onload = () => {
|
|
236
|
-
if (
|
|
252
|
+
if (
|
|
253
|
+
!img.getAttribute('data-ll-ready') &&
|
|
254
|
+
this.app.browser === 'firefox'
|
|
255
|
+
) {
|
|
237
256
|
// set sizes attribute on load again,
|
|
238
257
|
// since firefox sometimes is a bit slow to
|
|
239
258
|
// get the actual image width
|
|
@@ -241,7 +260,7 @@ export default class Lazyload {
|
|
|
241
260
|
|
|
242
261
|
img.setAttribute('sizes', `${width}px`)
|
|
243
262
|
if (img.parentNode) {
|
|
244
|
-
Array.from(Dom.all(img.parentNode, 'source')).forEach(source =>
|
|
263
|
+
Array.from(Dom.all(img.parentNode, 'source')).forEach((source) =>
|
|
245
264
|
source.setAttribute('sizes', `${width}px`)
|
|
246
265
|
)
|
|
247
266
|
}
|
|
@@ -290,7 +309,7 @@ export default class Lazyload {
|
|
|
290
309
|
}
|
|
291
310
|
|
|
292
311
|
lazyloadImages(elements) {
|
|
293
|
-
elements.forEach(item => {
|
|
312
|
+
elements.forEach((item) => {
|
|
294
313
|
if (item.isIntersecting || item.intersectionRatio > 0) {
|
|
295
314
|
const image = item.target
|
|
296
315
|
this.swapImage(image)
|
|
@@ -7,13 +7,24 @@ gsap.registerPlugin(ScrollToPlugin)
|
|
|
7
7
|
const DEFAULT_OPTIONS = {
|
|
8
8
|
triggerEvents: true,
|
|
9
9
|
scrollDuration: 0.8,
|
|
10
|
+
scrollOffsetNav: false,
|
|
10
11
|
mobileMenuDelay: 800,
|
|
11
12
|
openExternalInWindow: true,
|
|
12
|
-
linkQuery:
|
|
13
|
+
linkQuery:
|
|
14
|
+
'a:not([href^="#"]):not([target="_blank"]):not([data-lightbox]):not(.noanim)',
|
|
13
15
|
anchorQuery: 'a[href^="#"]:not(.noanim)',
|
|
14
16
|
|
|
15
17
|
onAnchor: (target, links) => {
|
|
16
|
-
|
|
18
|
+
if (links.opts.scrollOffsetNav) {
|
|
19
|
+
const header = document.querySelector('header[data-nav]')
|
|
20
|
+
const headerHeight = header ? header.clientHeight : 0
|
|
21
|
+
target = { y: target, offsetY: headerHeight }
|
|
22
|
+
}
|
|
23
|
+
links.app.scrollTo(
|
|
24
|
+
target,
|
|
25
|
+
links.opts.scrollDuration,
|
|
26
|
+
links.opts.triggerEvents
|
|
27
|
+
)
|
|
17
28
|
},
|
|
18
29
|
|
|
19
30
|
onTransition: (href, app) => {
|
|
@@ -27,7 +38,7 @@ const DEFAULT_OPTIONS = {
|
|
|
27
38
|
gsap.to(main, {
|
|
28
39
|
duration: 0.8,
|
|
29
40
|
y: 25,
|
|
30
|
-
ease: 'power3.out'
|
|
41
|
+
ease: 'power3.out',
|
|
31
42
|
})
|
|
32
43
|
|
|
33
44
|
if (header) {
|
|
@@ -43,13 +54,13 @@ const DEFAULT_OPTIONS = {
|
|
|
43
54
|
opacity: 1,
|
|
44
55
|
onComplete: () => {
|
|
45
56
|
window.location = href
|
|
46
|
-
}
|
|
57
|
+
},
|
|
47
58
|
})
|
|
48
59
|
} else {
|
|
49
60
|
gsap.to(main, {
|
|
50
61
|
duration: 0.8,
|
|
51
62
|
y: 25,
|
|
52
|
-
ease: 'power3.out'
|
|
63
|
+
ease: 'power3.out',
|
|
53
64
|
})
|
|
54
65
|
|
|
55
66
|
if (header) {
|
|
@@ -65,10 +76,10 @@ const DEFAULT_OPTIONS = {
|
|
|
65
76
|
opacity: 0,
|
|
66
77
|
onComplete: () => {
|
|
67
78
|
window.location = href
|
|
68
|
-
}
|
|
79
|
+
},
|
|
69
80
|
})
|
|
70
81
|
}
|
|
71
|
-
}
|
|
82
|
+
},
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
export default class Links {
|
|
@@ -87,7 +98,7 @@ export default class Links {
|
|
|
87
98
|
bindHeroLink() {
|
|
88
99
|
const el = document.querySelector('[data-link-to-content]')
|
|
89
100
|
if (el) {
|
|
90
|
-
el.addEventListener('click', e => {
|
|
101
|
+
el.addEventListener('click', (e) => {
|
|
91
102
|
const dataTarget = document.querySelector('main')
|
|
92
103
|
e.preventDefault()
|
|
93
104
|
if (dataTarget) {
|
|
@@ -99,8 +110,8 @@ export default class Links {
|
|
|
99
110
|
|
|
100
111
|
bindAnchors(anchors) {
|
|
101
112
|
let wait = false
|
|
102
|
-
Array.from(anchors).forEach(anchor => {
|
|
103
|
-
anchor.addEventListener('click', e => {
|
|
113
|
+
Array.from(anchors).forEach((anchor) => {
|
|
114
|
+
anchor.addEventListener('click', (e) => {
|
|
104
115
|
e.preventDefault()
|
|
105
116
|
const href = anchor.getAttribute('href')
|
|
106
117
|
if (href === '#') {
|
|
@@ -124,11 +135,22 @@ export default class Links {
|
|
|
124
135
|
history.pushState({}, '', href)
|
|
125
136
|
}
|
|
126
137
|
|
|
127
|
-
if (this.app.header
|
|
128
|
-
|
|
129
|
-
this.app.header.unpin()
|
|
130
|
-
}, 800)
|
|
138
|
+
if (!this.app.header) {
|
|
139
|
+
return
|
|
131
140
|
}
|
|
141
|
+
if (dataTarget.id === 'top') {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
if (this.app.header.mainOpts.ignoreForcedScroll) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
if (this.app.header.mainOpts.pinOnForcedScrollEnd) {
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
this.app.header.unpin()
|
|
153
|
+
}, 800)
|
|
132
154
|
}
|
|
133
155
|
}
|
|
134
156
|
|
|
@@ -142,19 +164,38 @@ export default class Links {
|
|
|
142
164
|
}
|
|
143
165
|
|
|
144
166
|
bindLinks(links) {
|
|
145
|
-
|
|
167
|
+
const loadingContainer = document.querySelector('.loading-container')
|
|
168
|
+
|
|
169
|
+
Array.from(links).forEach((link) => {
|
|
146
170
|
const href = link.getAttribute('href')
|
|
147
|
-
if (!href) {
|
|
148
|
-
return
|
|
171
|
+
if (!href || href === '#' || href.startsWith('javascript:')) {
|
|
172
|
+
return // Skip empty, anchor, or JS-based links
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Determine the normalized hostname of the current document.
|
|
176
|
+
const normalizedCurrentHost = this.normalizeHostname(
|
|
177
|
+
document.location.hostname
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
// For absolute URLs, use the URL constructor.
|
|
181
|
+
let linkHostname
|
|
182
|
+
try {
|
|
183
|
+
linkHostname = new URL(href, document.location.href).hostname
|
|
184
|
+
} catch (error) {
|
|
185
|
+
// If URL construction fails, assume it's not internal.
|
|
186
|
+
console.warn(`Failed to parse URL for href "${href}":`, error) // Log errors for debugging
|
|
187
|
+
linkHostname = ''
|
|
149
188
|
}
|
|
150
|
-
const
|
|
189
|
+
const normalizedLinkHost = this.normalizeHostname(linkHostname)
|
|
190
|
+
|
|
191
|
+
// Check if the link is internal by comparing the normalized hostnames.
|
|
192
|
+
const internalLink = normalizedLinkHost === normalizedCurrentHost
|
|
193
|
+
|
|
151
194
|
if (this.opts.openExternalInWindow && !internalLink) {
|
|
152
195
|
link.setAttribute('target', '_blank')
|
|
153
196
|
}
|
|
154
197
|
|
|
155
|
-
link.addEventListener('click', e => {
|
|
156
|
-
const loadingContainer = document.querySelector('.loading-container')
|
|
157
|
-
|
|
198
|
+
link.addEventListener('click', (e) => {
|
|
158
199
|
if (e.shiftKey || e.metaKey || e.ctrlKey) {
|
|
159
200
|
return
|
|
160
201
|
}
|
|
@@ -170,4 +211,8 @@ export default class Links {
|
|
|
170
211
|
})
|
|
171
212
|
})
|
|
172
213
|
}
|
|
214
|
+
|
|
215
|
+
normalizeHostname(hostname) {
|
|
216
|
+
return hostname.replace(/^www\./, '')
|
|
217
|
+
}
|
|
173
218
|
}
|