PageSourceSearch

https://www.paperstreet.com/wp-content/themes/paperstreet/assets/js/main.js?ver=4.988121

js paperstreet.com collected 2026-10-02 15:11:14 UTC 10,149 bytes, 302 lines download raw bytes

1/** @format */
2
3document.addEventListener("DOMContentLoaded", () => {
4	console.log("main.js DOMContentLoaded - Lazy image fade-in script initialized");
5	// Start script here
6	setupYouTube();
7
8	function addAiIcons() {
9		document.querySelectorAll(".header-menu li.ai > a").forEach((link) => {
10			// skip if already added
11			if (link.querySelector("img.ai-img")) return;
12
13			const img = new Image();
14			img.src = "/wp-content/themes/paperstreet/assets/images/ps-ai-new.svg";
15			img.width = 15;
16			img.height = 15;
17			img.alt = "AI";
18			img.className = "ai-img";
19			// optional: improve rendering hints
20			img.decoding = "async";
21			img.loading = "lazy";
22			link.appendChild(img);
23		});
24	}
25
26	// run when DOM is ready
27	if (document.readyState === "loading") {
28		document.addEventListener("DOMContentLoaded", addAiIcons);
29	} else {
30		addAiIcons();
31	}
32
33	// Remove empty <p> tags inside elements with class 'tlct-shortdes' on page load
34	// See "Our Story" timeline page
35	var shortdesElements = document.querySelectorAll(".tlct-shortdes");
36	if (shortdesElements.length > 0) {
37		shortdesElements.forEach(function (parent) {
38			parent.querySelectorAll("p").forEach(function (p) {
39				if (p.textContent.trim() === "" && p.innerHTML.trim() === "") {
40					p.remove();
41				}
42			});
43		});
44	}
45
46	console.log("main.js loaded. Referrer = " + document.referrer);
47
48	// Function to get query parameters as an object
49	function getQueryParams() {
50		var params = {};
51		var queryString = window.location.search.substring(1);
52		if (queryString) {
53			var pairs = queryString.split("&");
54			for (var i = 0; i < pairs.length; i++) {
55				var pair = pairs[i].split("=");
56				params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
57			}
58		}
59		return params;
60	}
61
62	// Function to store referrer and current URL on first visit
63	function storeOnFirstVisit() {
64		// Check if it's the user's first visit
65		if (!localStorage.getItem("firstVisit")) {
66			// Store the referrer
67			var referrer = document.referrer || "Direct Visit";
68			localStorage.setItem("referrer", referrer);
69
70			// Store the full current URL (including parameters)
71			var currentUrl = window.location.href;
72			localStorage.setItem("currentUrl", currentUrl);
73
74			// Store query parameters (optional, you can skip this if storing full URL)
75			var queryParams = getQueryParams();
76			if (Object.keys(queryParams).length > 0) {
77				localStorage.setItem("storedParams", JSON.stringify(queryParams));
78			}
79
80			// Mark that the first visit has occurred
81			localStorage.setItem("firstVisit", "true");
82		}
83	}
84
85	// Call function to store data on first visit
86	storeOnFirstVisit();
87
88	// Retrieve the referrer, current URL, and stored query parameters
89	var referrerInput = document.getElementById("referrerInput");
90	var storedReferrer = localStorage.getItem("referrer") || "Direct Visit";
91	var storedCurrentUrl = localStorage.getItem("currentUrl") || window.location.href;
92	var storedParams = JSON.parse(localStorage.getItem("storedParams")) || {};
93
94	// Combine referrer, current URL, and query parameters if needed
95	if (referrerInput) {
96		var combinedInfo = "Referrer: " + storedReferrer + " | Full URL: " + storedCurrentUrl;
97
98		// Optionally, append stored query parameters (if separate handling of params is needed)
99		if (Object.keys(storedParams).length > 0) {
100			combinedInfo += " | Query Params: " + JSON.stringify(storedParams);
101		}
102
103		// Set the combined info to the input value
104		referrerInput.value = combinedInfo;
105	}
106
107	// Check header scroll on load
108	scrollHeaderClass();
109
110	// GLightbox options and settings here (https://biati-digital.github.io/glightbox/)
111	if (typeof GLightbox !== "undefined") {
112		const lightbox = GLightbox();
113	}
114
115	// add class to header when scrolling
116	window.addEventListener("scroll", scrollHeaderClass);
117
118	function scrollHeaderClass() {
119		const header = document.querySelector(".header");
120		if (window.pageYOffset >= 100) {
121			header.classList.add("is-fixed");
122		} else {
123			header.classList.remove("is-fixed");
124		}
125	}
126
127	// Set header top and main margin-top based on AI banner height (only on home page)
128	function adjustLayoutForAiBanner() {
129		if (document.body.classList.contains("home") && window.innerWidth >= 1025) {
130			const aiBanner = document.getElementById("ai-banner");
131			const header = document.querySelector(".header");
132			const main = document.querySelector("main");
133
134			if (aiBanner && header && main) {
135				const bannerHeight = aiBanner.offsetHeight;
136				if (bannerHeight > 0) {
137					header.style.top = bannerHeight + "px";
138					main.style.marginTop = bannerHeight + "px";
139				}
140			}
141		} else {
142			//remove header style attribute
143			document.querySelector(".header").removeAttribute("style");
144			document.querySelector("main").removeAttribute("style");
145		}
146	}
147
148	// Run on page load
149	// adjustLayoutForAiBanner();
150
151	// Re-check on window resize in case banner height changes
152	// window.addEventListener("resize", adjustLayoutForAiBanner);
153
154	// End script here
155
156	// Lazy load images
157	let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
158	console.log("Lazy images found:", lazyImages.length, lazyImages);
159
160	if ("IntersectionObserver" in window) {
161		let lazyImageObserver = new IntersectionObserver(function (entries, observer) {
162			entries.forEach(function (entry) {
163				if (entry.isIntersecting) {
164					let lazyImage = entry.target;
165					console.log(
166						"LazyImage entering viewport:",
167						lazyImage.dataset.src || lazyImage.src,
168						lazyImage
169					);
170
171					// Check if image is inside a picture element
172					let pictureElement = lazyImage.closest("picture");
173
174					if (pictureElement) {
175						// Find all source tags within the picture element
176						let sourceTags = pictureElement.querySelectorAll("source[data-srcset]");
177						sourceTags.forEach(function (sourceTag) {
178							if (sourceTag.dataset.srcset) {
179								sourceTag.srcset = sourceTag.dataset.srcset;
180								console.log("LazyImage picture source applied:", sourceTag.srcset);
181							}
182						});
183					}
184
185					// Trigger fade-in after image loads
186					lazyImage.addEventListener("load", function () {
187						console.log("LazyImage loaded (event), triggering fade-in:", lazyImage.src);
188						// Use requestAnimationFrame to ensure browser has processed the load
189						requestAnimationFrame(function () {
190							lazyImage.classList.add("lazy-loaded");
191						});
192					});
193
194					// Apply the src to the image
195					console.log("LazyImage setting src:", lazyImage.dataset.src);
196					lazyImage.src = lazyImage.dataset.src;
197
198					// Fallback for cached images (already loaded)
199					if (lazyImage.complete && lazyImage.naturalHeight !== 0) {
200						console.log("LazyImage already cached, triggering fade-in immediately:", lazyImage.src);
201						// Use requestAnimationFrame for cached images too
202						requestAnimationFrame(function () {
203							lazyImage.classList.add("lazy-loaded");
204						});
205					}
206
207					lazyImageObserver.unobserve(lazyImage);
208				}
209			});
210		});
211
212		lazyImages.forEach(function (lazyImage) {
213			lazyImageObserver.observe(lazyImage);
214		});
215	}
216
217	// Lazy load background images
218	let lazyBgImages = [].slice.call(document.querySelectorAll(".lazy-bg"));
219	console.log("Lazy background images found:", lazyBgImages.length, lazyBgImages);
220
221	if ("IntersectionObserver" in window) {
222		let lazyBgImageObserver = new IntersectionObserver(function (entries, observer) {
223			entries.forEach(function (entry) {
224				if (entry.isIntersecting) {
225					let lazyBgImage = entry.target;
226					console.log("LazyBgImage entering viewport:", lazyBgImage.dataset.bg, lazyBgImage);
227
228					// Create a temporary image to detect when background loads
229					let tempImg = new Image();
230					tempImg.onload = function () {
231						console.log("LazyBgImage loaded, triggering fade-in:", lazyBgImage.dataset.bg);
232						// Use requestAnimationFrame to ensure browser has processed the load
233						requestAnimationFrame(function () {
234							lazyBgImage.classList.add("lazy-loaded");
235						});
236					};
237					tempImg.src = lazyBgImage.dataset.bg;
238
239					lazyBgImage.style.backgroundImage = "url(" + lazyBgImage.dataset.bg + ")";
240					lazyBgImageObserver.unobserve(lazyBgImage);
241				}
242			});
243		});
244
245		lazyBgImages.forEach(function (lazyBgImage) {
246			lazyBgImageObserver.observe(lazyBgImage);
247		});
248	}
249
250	// Video inline play
251	const videoContainers = document.querySelectorAll("[data-video]");
252
253	videoContainers.forEach((container) => {
254		container.addEventListener("click", function () {
255			const videoUrl = this.getAttribute("data-video");
256			const videoId = videoUrl.split("v=")[1];
257			const embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1&rel=0`;
258
259			this.innerHTML = `<iframe width="560" height="315" src="${embedUrl}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
260			this.classList.add("is-active");
261		});
262	});
263});
264
265function setupYouTube() {
266	// Prepare YouTube video placeholders that turn into iframe on click
267	var players = document.getElementsByClassName("youtube-player");
268	if (players.length === 0) {
269		return;
270	}
271
272	for (var n = 0; n < players.length; n++) {
273		var player = players[n];
274		var div = document.createElement("div");
275		div.setAttribute("data-id", player.dataset.id);
276		div.setAttribute("data-list", player.dataset.list);
277		div.innerHTML =
278			'<img src="https://img.youtube.com/vi/' + player.dataset.id + '/hqdefault.jpg" alt="">';
279
280		// Add attributes and classes to the div to make it interactive
281		div.classList.add("youtube-player-inner");
282		div.setAttribute("tabindex", "0");
283		div.setAttribute("aria-label", "Play video");
284		div.addEventListener("click", getYouTubeFrame);
285		div.addEventListener("keypress", getYouTubeFrame);
286
287		// Add the div to this player
288		player.appendChild(div);
289	}
290}
291
292function getYouTubeFrame() {
293	var iframe = document.createElement("iframe");
294	var embed = "https://www.youtube.com/embed/ID?autoplay=1&rel=0";
295
296	iframe.setAttribute("src", embed.replace("ID", this.dataset.id));
297	iframe.setAttribute("frameborder", "0");
298	iframe.setAttribute("allow", "autoplay;");
299	iframe.setAttribute("allowfullscreen", "1");
300
301	this.parentNode.replaceChild(iframe, this);
302}

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.