PageSourceSearch

https://www.houstonlanding.org/srv/htdocs/wp-content/plugins/houst…//js/components/intersect.js?ver=2531

js houstonlanding.org collected 2026-09-24 09:04:11 UTC 7,818 bytes, 310 lines download raw bytes

1/** 
2	
3	PURPOSE FOR intersections: MODULES FOR INTERACTIONS TO OCCUR ON PAGE SCROLL
4
5**/
6
7
8const Intersect = (function() {
9
10	const setClass = 'intersected'
11
12	const handleFixedPositioning = (container) => {
13
14		if(elementIsVisibleInViewport(container, 0.05)) {
15			container.classList.add(setClass)
16		} else {
17			container.classList.remove(setClass)
18		}
19
20	}
21
22	/*
23	----------------
24	FADE UP REVEAL
25	----------------
26	*/
27	const fadeUpCollection = document.querySelectorAll('.intersect-fadeup:not(.' + setClass + ')')
28	let isFadeUpRef
29
30	const handleFadeUp = () => {
31		clearTimeout(isFadeUpRef)
32
33		isFadeUpRef = setTimeout(() => {
34
35			fadeUpCollection.forEach((ele, ind) => {
36				if(elementIsVisibleInViewport(ele)) {
37					const parent = ele.parentNode
38					const children = parent.querySelectorAll('.intersect-fadeup:not(.' + setClass + ')')
39					const nthChild = Array.prototype.indexOf.call(children, ele) + 1
40
41					setTimeout(() => { ele.classList.add(setClass) }, (50*(nthChild+(nthChild*2))))
42				}
43			})
44
45		}, 30)
46
47	}
48
49	/*
50	----------------------
51	MULTIPLE COVER REVEAL
52	----------------------
53	*/
54	let isCoverOpacityRefs = []
55
56	const getGalleryImages = (container) => {
57
58		const mobileVersions = container.querySelectorAll(':scope > .wp-block-gallery.mobile .wp-block-image')
59
60		if(mobileVersions.length < 1) {
61			return container.querySelectorAll(':scope > .wp-block-gallery .wp-block-image')
62		}
63
64		if(window.innerWidth <= 780) {
65			return mobileVersions
66		} else {
67			return container.querySelectorAll(':scope > .wp-block-gallery.desktop .wp-block-image')
68		}
69	}
70
71	const handleCoverOpacity = (container, containerID) => {
72		clearTimeout(isCoverOpacityRefs[containerID])
73
74		const coverCollection = container.querySelectorAll(':scope > .wp-block-group > .wp-block-group')
75		const coverBackgrounds = getGalleryImages(container)
76
77		handleFixedPositioning(container)
78
79		isCoverOpacityRefs[containerID] = setTimeout(() => {
80
81			coverCollection.forEach((ele, eleID) => {
82
83				const thisImage = coverBackgrounds[eleID]
84
85				thisImage.style.transition = 'opacity 0.15s ease-in-out'
86
87				if(elementIsVisibleInViewport(ele, 0.5)) {
88					coverBackgrounds.forEach((bg, bgID) => {
89						bg.style.opacity = 0
90					})
91					thisImage.style.opacity = 1
92
93				}
94			})
95
96		}, 10)
97	}
98
99	const setCoverMarginLeft = (items, newCount) => {
100		items.forEach((item) => item.style.setProperty('margin-left', 'calc(100vw * -' + newCount + ')', 'important'))
101	}
102
103	const handleCoverMobileScroll = (container, containerID) => {
104		const scrollImages = container.querySelector(':scope .wp-block-gallery')
105		const scrollTexts = container.querySelector(':scope .wp-block-group')
106		const scrollCountTotal = scrollImages.querySelectorAll('.wp-block-image').length
107
108		const scrollButtons = container.querySelector(':scope .wp-block-buttons')
109		const scrollButtonPrev = scrollButtons.querySelector(':scope .wp-block-button:first-child a')
110		const scrollButtonNext = scrollButtons.querySelector(':scope .wp-block-button:last-child a')
111
112		scrollImages.style.transition = 'margin-left 0.25s ease-in-out'
113		scrollTexts.style.transition = 'margin-left 0.25s ease-in-out'
114
115		let scrollCount = 0
116
117		scrollButtonPrev.addEventListener('click', function( e ) {
118			e.preventDefault()
119			if(scrollCount != 0) {
120				scrollCount--
121			}
122			setCoverMarginLeft([scrollImages, scrollTexts], scrollCount)
123		})
124		scrollButtonNext.addEventListener('click', function( e ) {
125			e.preventDefault()
126			if(scrollCount < (scrollCountTotal - 1)) {
127				scrollCount++
128			}
129			setCoverMarginLeft([scrollImages, scrollTexts], scrollCount)
130		})
131		
132		// scrollItems.forEach((ele) => {
133			Gesture.swipe(
134				container, 
135				function() { 
136					scrollButtonNext.click() 
137				}, 
138				function() { 
139					scrollButtonPrev.click() 
140				} 
141			)
142		// })
143	}
144
145
146	/*
147	--------------------------------
148	Horizontal Scrolling on Scroll
149	--------------------------------
150	*/
151	let isHorizontalScrollRefs = []
152
153	const handleHorizontalScroll = (container, containerID) => {
154		clearTimeout(isHorizontalScrollRefs[containerID])
155
156		const timeline = container.querySelector(':scope .houston-custom-timeline')
157		const visibility = getElementPercentVisibility(container)
158
159		handleFixedPositioning(container)
160
161		timeline.style.transform = 'translateX(-' + (100-visibility) + '%)'
162
163	}
164
165
166	/*
167	--------------------------
168	Sticky Sections on Scroll
169	--------------------------
170	*/
171	const handleStickySections = (stickyContainers, set = true) => {
172
173		if(set) {
174			stickyContainers.forEach((container, containerID) => {
175				const containerHeight = container.getBoundingClientRect().height
176				const stopPoint = (containerHeight - (window.innerHeight / 2)) * -1
177	
178				container.style.top = stopPoint + 'px'
179			})
180		} else {
181			stickyContainers.forEach((container) => container.style.position = 'static')
182			
183			setTimeout(() => {
184				stickyContainers.forEach((container) => container.style.removeProperty('position'))
185			}, 80);
186		}
187	}
188
189	const handleStickySectionsNav = (container) => {
190		if(!elementIsVisibleInViewport(container)) return
191
192		const navLinks = document.querySelectorAll('.series-navigation-links a')
193		const navLink = document.querySelector('.series-navigation-links a[href="#' + container.id +'"]')
194
195		if(navLink) {
196			navLinks.forEach((item) => item.classList.remove('selected'))
197			navLink.classList.add('selected')
198		} 
199	}
200
201	return {
202		fadeUp: function() {
203			window.addEventListener('scroll', handleFadeUp)
204		},
205		coverOpacity: function() {
206			const coverContainers = document.querySelectorAll('.houston-custom-multi-cover')
207
208			coverContainers.forEach((container, containerID) => {
209				if(container.querySelector(':scope .wp-block-buttons')) {
210					handleCoverMobileScroll(container, containerID)
211				}
212
213				window.addEventListener('scroll', function() {
214					handleCoverOpacity(container, containerID)
215				})
216				window.addEventListener('load', function() {
217					handleFixedPositioning(container)
218				})
219			})
220			
221		},
222		horizontalScroll: function() {
223			const timelineContainers = document.querySelectorAll('.wp-block-group:has(.houston-custom-timeline)')
224
225			timelineContainers.forEach((container, containerID) => {
226				container.classList.add('js-' + setClass)
227
228				window.addEventListener('scroll', function() {
229					handleHorizontalScroll(container, containerID)
230				})
231				window.addEventListener('load', function() {
232					handleFixedPositioning(container)
233				})
234			})
235		},
236		stickySections: function() {
237			const stickyContainers = document.querySelectorAll('.houston-custom-sticky-sections')
238			const stickyContainersExcludeFirst = Array.from(stickyContainers).slice(1)
239
240			if(stickyContainers.length == 0) return;
241
242			document.querySelectorAll('.series-navigation a').forEach((navItem) => {
243				navItem.addEventListener('click', function( e ) {
244					handleStickySections(stickyContainers, false)
245				})
246			})
247
248			handleStickySections(stickyContainersExcludeFirst)
249
250			stickyContainers.forEach((container) => {
251				window.addEventListener('scroll', function() {
252					handleStickySectionsNav(container)
253				})
254			})
255		},
256		stickyZoom: function() {
257			const scrollers = document.querySelectorAll('.houston-custom-sticky-zoom')
258
259			if(scrollers.length == 0) return;
260
261			scrollers.forEach((scroller) => {
262				
263				const visual = scroller.querySelector(':scope img')
264				const visualVH = parseFloat(window.getComputedStyle(visual).height) / window.innerHeight * 100
265
266				window.addEventListener('scroll', function() {
267					const visibility = getElementPercentVisibility(scroller)
268
269					if(visibility > 0) {
270						zoom = visualVH + (100-visibility)
271					}
272
273					visual.style.height = zoom + 'vh'
274				})
275			})
276		}
277	}
278
279})();
280
281(function() {
282	Intersect.fadeUp();
283	Intersect.coverOpacity();
284	Intersect.horizontalScroll();
285	Intersect.stickySections();
286	Intersect.stickyZoom();
287})();
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.