1// Fetch and parse next page 2async function getNextPage(url) { 3 try { 4 const res = await fetch(url); 5 6 if (!res.ok) { 7 throw new Error("Failed to fetch page"); 8 } 9 10 const nextPageHtml = await res.text(); 11 const parser = new DOMParser(); 12 const parsed = parser.parseFromString(nextPageHtml, "text/html"); 13 const posts = parsed.querySelectorAll(".post-card"); 14 const nextLink = parsed 15 .querySelector('link[rel="next"]') 16 ?.getAttribute("href"); 17 18 return { posts, nextLink }; 19 } catch (error) { 20 throw new Error(error); 21 } 22 } 23 24 function infiniteScroll() { 25 let link = document.querySelector('link[rel="next"]')?.getAttribute("href"); 26 27 if (!link) { 28 return; 29 } 30 31 const options = { 32 // When the last card is within a 150px of the viewport, fetch the next page. This provides a smoother transition between pages 33 rootMargin: "150px", 34 }; 35 36 const callback = (entries, observer) => { 37 try { 38 entries.forEach((entry) => { 39 if (entry.isIntersecting) { 40 if (link) { 41 getNextPage(link).then(({ posts, nextLink }) => { 42 posts.forEach((post) => { 43 document.querySelector(".feed").append(post); 44 }); 45 46 if (nextLink) { 47 link = nextLink; 48 observer.observe( 49 document.querySelector(".post-card:last-of-type") 50 ); 51 } else { 52 observer.disconnect(); 53 } 54 }); 55 } 56 } 57 }); 58 } catch (error) { 59 console.log(error); 60 } 61 }; 62 63 let observer = new IntersectionObserver(callback, options); 64 65 observer.observe(document.querySelector(".post-card:last-of-type")); 66 } 67 68 document.addEventListener("DOMContentLoaded", infiniteScroll); 69
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.