PageSourceSearch

https://www.walkingbread.com/assets/js/global.js?v=4E9BOq68RK68pygn

js walkingbread.com collected 2026-10-04 08:09:15 UTC 18,159 bytes, 591 lines download raw bytes

1let isTablet = window.matchMedia('(max-width: 991px)').matches;
2
3window.addEventListener('resize', () => {
4  isTablet = window.matchMedia('(max-width: 991px)').matches;
5});
6
7function getParameterByName(name, url) {
8  if (!url) url = window.location.href;
9  name = name.replace(/[\[\]]/g, "\\$&");
10  var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
11      results = regex.exec(url);
12  if (!results) return null;
13  if (!results[2]) return '';
14  return decodeURIComponent(results[2].replace(/\+/g, " "));
15}
16
17function hexToRgba(hex) {
18  hex = hex.replace('#', '');
19
20  const r = parseInt(hex.substring(0, 2), 16);
21  const g = parseInt(hex.substring(2, 4), 16);
22  const b = parseInt(hex.substring(4, 6), 16);
23
24  let opac_60 =  `rgba(${r}, ${g}, ${b}, 0.6)`;
25  let opac_20 =  `rgba(${r}, ${g}, ${b}, 0.15)`;
26
27  document.documentElement.style.setProperty('--text-color-60', opac_60);
28  document.documentElement.style.setProperty('--text-color-20', opac_20);
29}
30
31function loadFonts(fonts, doc = document){
32    const data = fonts;
33    if(!data) return;
34
35    const ghostFonts = document.querySelector('link[href*="fonts.bunny.net/css"]');
36
37    if(ghostFonts) return;
38    
39    const root = document.documentElement;
40   
41    let splitArray = data.toString().replace(/,\s*/g, ',').split(',');
42
43    let googleFontsURL = `https://fonts.googleapis.com/css2?`;
44
45    for(let i = 0; i < splitArray.length; i++){
46       if(i == 2) break;
47
48       root.style.setProperty(`--font${i+1}`, `'${splitArray[i].toString()}'`);
49
50       splitArray[i] = splitArray[i].replace(' ', '+');
51       googleFontsURL += `family=${splitArray[i]}:wght@300;400;500;600&`  
52    }
53
54    googleFontsURL += 'display=swap'
55
56    const linkElement = doc.createElement('link');
57    linkElement.rel = 'stylesheet';
58    linkElement.href = googleFontsURL;
59
60    doc.head.appendChild(linkElement);
61}
62
63let tl;
64let resizeTimeout;
65
66function horizontalScroll() {
67  gsap.registerPlugin(ScrollTrigger);
68
69  let container = document.querySelector(".horizontal-container");
70  container.style.width = container.scrollWidth + "px";
71
72  //This fixes image hover in jittering. After the scrolling is done it moves all of the sections to a whole pixel (not float): example from 2599.43px to 2599px
73  window.addEventListener('scroll', () => {
74    if(isTablet) return;
75
76    isScrolling = true;
77    clearTimeout(scrollTimeout);
78    scrollTimeout = setTimeout(() => {
79      if (isScrolling) {
80        translateSections();
81        isScrolling = false;
82      }
83    }, 600);
84  });
85
86  createScrollTrigger();
87  if(!isTablet){
88    setTimeout(() => {
89      translateSections()
90    }, 600)
91  }
92
93  window.addEventListener('resize', debounce(() => {
94    createScrollTrigger();
95  }, 30));
96}
97
98function createScrollTrigger() {
99  let sections = gsap.utils.toArray(".horizontal-section");
100
101  if(isTablet){
102    if (tl && tl.scrollTrigger) {
103      tl.scrollTrigger.kill();
104    }
105  }
106  if(isTablet) return;
107
108  let position = window.scrollY;
109
110  if (tl && tl.scrollTrigger) {
111    let scrollerWidth = getScrollbarWidth();
112    
113    tl.scrollTrigger.kill();
114    document.querySelectorAll('.horizontal-section').forEach(section => {
115      section.style.transform = `translateX(${-position - scrollerWidth / 2}px)`
116    });   
117  }
118
119  if (resizeTimeout) {
120    clearTimeout(resizeTimeout);
121  }
122
123  // Adding a small delay to ensure DOM is updated
124  resizeTimeout = setTimeout(() => {
125    let size = 0;
126    document.querySelectorAll('.horizontal-section').forEach(section => {
127      size += section.offsetWidth;
128    });
129
130    sections = gsap.utils.toArray(".horizontal-section");
131
132    tl = gsap.to(sections, {
133      x: () => -(size - document.documentElement.clientWidth),
134      ease: "none",
135      scrollTrigger: {
136        trigger: ".horizontal-container",
137        pin: true,
138        scrub: 0.6,
139        end: () => (size - document.documentElement.clientWidth),
140        invalidateOnRefresh: true,
141        onRefresh: () => {
142          window.scrollTo(0, position);
143        }
144      }
145    });
146
147    // Reset the timeout variable
148    resizeTimeout = null;
149  }, 0);   
150}
151
152let scrollTimeout;
153let isScrolling = false;
154
155function translateSections() {
156  document.querySelectorAll('.horizontal-section').forEach(section => {
157    let computedStyle = window.getComputedStyle(section);
158    let transformValue = computedStyle.getPropertyValue('transform');
159    let matrix = transformValue.split('(')[1].split(')')[0].split(',');
160    let xTranslation = Math.round(parseFloat(matrix[4]));
161
162    section.style.transform = `translateX(${xTranslation}px)`
163  });
164}
165
166function debounce(fn, delay) {
167  let timerId;
168  return function(...args) {
169    if (timerId) {
170      clearTimeout(timerId);
171    }
172    timerId = setTimeout(() => {
173      fn(...args);
174      timerId = null;
175    }, delay);
176  };
177}
178 
179let scrollPosition = 0;
180 
181function disableScrolling() {
182  scrollPosition = window.pageYOffset;
183  document.body.style.overflow = 'hidden';
184  document.body.style.position = 'fixed';
185  document.body.style.top = `-${scrollPosition}px`;
186  document.body.style.width = '100%';
187  document.documentElement.style.scrollBehavior = 'auto';
188   
189}
190   
191function enableScrolling() {
192  document.body.style.removeProperty('overflow');
193  document.body.style.removeProperty('position');
194  document.body.style.removeProperty('top');
195  document.body.style.removeProperty('width');
196  window.scrollTo(0, scrollPosition);
197  document.documentElement.style.scrollBehavior = 'smooth';
198}
199
200function scrollToNextSection() {
201  window.scroll({
202    top: document.querySelectorAll('section')[0].getBoundingClientRect().right + window.pageYOffset,
203    behavior: 'smooth'
204  });
205}
206
207function scrollToStart(){
208  window.scroll({
209    top: 0,
210    behavior: 'smooth'
211  });
212}
213
214function pageLoadAnimations(container = document) {
215  const elements = container.querySelectorAll('.card-animation');
216  const opacityElements = container.querySelectorAll('.opacity-animation');
217  let stepDelay = 100;
218
219  function handleIntersection(entries, observer) {
220    let delay = 0;
221
222    entries.forEach(entry => {
223      const overlay = entry.target.querySelector('.card-overlay');
224      const title = entry.target.querySelector('.card-title');
225      const top = entry.target.querySelector('.card-top');
226      const bottom = entry.target.querySelector('.card-bottom');
227      const excerpt = entry.target.querySelector('.card-excerpt');
228      const tagStepDelay = entry.target.getAttribute('data-step-delay');
229
230      tagStepDelay ? stepDelay = parseInt(tagStepDelay) : stepDelay = 100;
231         
232      if (entry.isIntersecting ) {
233        if(entry.target.classList.contains('card-animation-handler')) return;
234        
235        overlay.animate(
236          {
237            height: ['100%', '0%']
238          },
239          {
240            duration: 1000,
241            delay: delay,
242            easing: "cubic-bezier(.19,1,.22,1)",
243            fill: "forwards"
244          }
245        );
246
247        easeIn({element: title, delay: delay});
248        easeIn({element: top, delay: delay});
249        easeIn({element: bottom, value: '15px', delay: delay});
250        easeIn({element: excerpt, value: '15px', delay: delay, opacity: 0.6});
251
252        delay = delay + stepDelay;
253
254        entry.target.classList.add('card-animation-handler');  
255      }    
256
257      entry.target.style.visibility = 'visible';
258      entry.target.classList.remove('card-animation')
259      observer.unobserve(entry.target);  
260    });
261  }
262
263  const options = {
264    root: null,
265    threshold: 0,
266  };
267
268  const observer = new IntersectionObserver(handleIntersection, options);
269
270  setTimeout(() => {
271    elements.forEach(element => {
272      observer.observe(element);
273    });
274  }, 200);
275  
276
277  //Opacity
278  opacityElements.forEach(el => {
279    el.animate(
280      {
281        opacity: [0, 1]
282      },
283      {
284        duration: 800,
285        delay: 300,
286        easing: "ease",
287        fill: "forwards"
288      }
289    );
290  })
291
292  //Adding a class here instead of animation because there was a problem with Lightense & this animation
293  let postContent = document.querySelector('.post-content');
294  if(postContent){
295      postContent.classList.add('visible-content')
296  }   
297}
298
299function easeIn({element: element, value: value = '-15px', delay: delay, opacity: opacity = 1}){
300  if(!element) return;
301
302  element.style.opacity = 0;
303  element.animate(
304    {
305      opacity: [0, opacity],
306      transform: [`translateY(${value})`, "translateY(0)"]
307    },
308    {
309      duration: 1000,
310      delay: delay + 300,
311      easing: "cubic-bezier(.19,1,.22,1)",
312      fill: "forwards"
313    }
314  );
315}
316
317function noHeroHeadingText(){
318  let hero = document.querySelector('.hidden-hero');
319  if(!hero) return;
320
321  hero.querySelector('.subtitle-name').innerHTML = hero.getAttribute('data-hidden-title');
322  hero.querySelector('.subtitle-name-desktop').innerHTML = hero.getAttribute('data-hidden-title-desktop');
323}
324
325let stickyObserver;
326
327function stickyHeading(){
328  let section = document.querySelector('.sticky-hero-section');
329
330  if(!section) return;
331
332  let stopSection = document.querySelectorAll('section')[2];
333  let main = document.querySelector('main');
334  let posts = document.querySelector('.sticky-posts-section');
335
336  if(!isTablet){
337    section.querySelector('.title-and-subtitle').style.width = document.documentElement.clientWidth - parseFloat(window.getComputedStyle(posts).paddingLeft) * 2 + 'px';
338    posts.prepend(section)
339    section.classList.remove('horizontal-section');
340
341    if (stickyObserver) {
342      stickyObserver.disconnect();
343    }
344
345    stickyObserver = new IntersectionObserver((entries) => {
346        entries.forEach(entry => {
347            if (entry.isIntersecting) {
348              posts.prepend(section)
349              section.style.position = 'absolute';
350              section.style.transform = `translateY(-${window.getComputedStyle(posts).marginTop})`;
351              section.style.left = 'unset';
352              section.style.right = parseFloat(window.getComputedStyle(posts).paddingRight) - parseFloat(window.getComputedStyle(posts).paddingLeft) - getScrollbarWidth() + 'px';
353            } else {
354              main.prepend(section)
355              section.style.position = 'fixed';
356              section.style.transform = 'translateY(0px)'
357              section.style.left = '0'
358              section.style.right = '0'
359            }
360        });
361    }, {
362        root: null,
363        rootMargin: parseFloat(window.getComputedStyle(posts).paddingRight) - parseFloat(window.getComputedStyle(posts).paddingLeft) + 'px',
364        threshold: 0
365    });
366
367    stickyObserver.observe(stopSection);
368  }else{
369    section.classList.add('horizontal-section');
370    main.prepend(section);
371  }
372}
373
374function getScrollbarWidth() {
375  return window.innerWidth - document.documentElement.clientWidth;
376}
377
378function featuredTagsOnHomepage(tagSlugs) {
379  if (!tagSlugs) return;
380
381  let tags = tagSlugs.split(',').map(item => item.trim());
382  let fetchPromises = [];
383
384  tags.forEach(tag => {
385    let url = window.location.origin + `/tag/${tag}/page/1/`;
386
387    let fetchPromise = fetch(url)
388      .then(response => response.text())
389      .then(data => {
390        let parser = new DOMParser();
391        let html = parser.parseFromString(data, "text/html");
392        let newPosts = html.querySelector("#posts-section");
393
394        // Store the newPosts element and its tag for later reordering
395        return { tag, newPosts };
396      })
397      .catch(error => {
398        console.error("Error loading more posts for tag:", tag, error);
399        return null; // Return null in case of error to handle it gracefully
400      });
401
402    fetchPromises.push(fetchPromise);
403  });
404
405  Promise.all(fetchPromises)
406    .then(results => {
407      let imageLoadPromises = [];
408
409      results
410        .filter(result => result !== null) // Filter out any null results due to errors
411        .forEach(({ tag, newPosts }) => {
412          let latest = document.querySelector('.latest-posts');
413          let parent = latest.parentNode;
414
415          parent.insertBefore(newPosts, latest);
416
417          newPosts.querySelector('.subtitle-name').innerHTML = newPosts.getAttribute('data-hidden-title');
418          newPosts.setAttribute('data-section-name', newPosts.getAttribute('data-hidden-title'));
419          newPosts.classList.remove('padding-top-on-mobile', 'hidden-hero', 'sticky-posts-section');
420          newPosts.querySelector('.grid').removeAttribute('id');
421          newPosts.querySelector('#custom-pagination')?.removeAttribute('id');
422
423          let button = newPosts.querySelector('#load-more-btn');
424          if (button) {
425            button.removeAttribute('id');
426
427            const anchor = document.createElement('a');
428            anchor.classList.add('pagination-button', 'button');
429            anchor.innerHTML = `&nbsp;${button.getAttribute('data-featured-tag-text')}&nbsp;`;
430            button.parentNode.replaceChild(anchor, button);
431            anchor.href = `/tag/${tag}`;
432          }
433
434          pageLoadAnimations(newPosts);
435
436          // Create promises for each image to ensure they are fully loaded
437          newPosts.querySelectorAll('img').forEach(img => {
438            let imgLoadPromise = new Promise(resolve => {
439              img.onload = img.onerror = resolve;
440            });
441            imageLoadPromises.push(imgLoadPromise);
442          });
443        });
444
445      // Wait for all images to be loaded before running afterAllLoaded
446      Promise.all(imageLoadPromises).then(() => {
447        afterAllLoaded();
448      });
449    })
450    .catch(error => {
451      console.error("Error processing fetch promises:", error);
452      afterAllLoaded();
453    });
454
455  function afterAllLoaded() {
456    horizontalScroll();
457    const customIndicator = document.querySelector('custom-indicator');
458    if (customIndicator && typeof customIndicator.init === 'function') {
459      customIndicator.init();
460    } else {
461      console.error("Custom indicator element or init function not found.");
462    }
463
464    
465    pageLoadAnimations();
466  }
467}
468
469function setLightense(){
470  window.addEventListener('DOMContentLoaded', function () {
471      const imagesInAnchors = document.querySelectorAll('.post-content a img, .post-content .kg-product-card img, .kg-signup-card img, .kg-header-card img');
472  
473      imagesInAnchors.forEach((img) => {
474          img.classList.add('no-lightense');  
475      });
476  
477      Lightense('.post-content img:not(.no-lightense)', {
478          background: 'var(--background-color)'
479      });
480  }, false);
481}
482
483function copyUrlToClipboard(parentElement){
484  let parent = document.querySelector(`.${parentElement}`)
485  let alert = parent.querySelector('.clipboard-alert');
486
487  parent.querySelector('.clipboard-link').addEventListener('click', () => {
488      navigator.clipboard.writeText(window.location.href);
489      alert.style.display = "block";
490
491      setTimeout(function () {
492          alert.style.display = "none";
493      }, 3000);
494  })
495}
496
497function deleteBorder() {
498  window.addEventListener('DOMContentLoaded', function () {
499    let relatedPosts = document.querySelector('.related-posts-inner');
500    if(!relatedPosts) return;
501
502    if(isTablet){
503      const prevPost = document.querySelector('.older-post .related-post-wrapper-inner');
504      const nextPost = document.querySelector('.newer-post .related-post-wrapper-inner');
505
506      prevPost && nextPost ? null : document.querySelector('.related-posts-separator').style.display = 'none';
507    }
508  })
509}
510
511function contentResizeHandler(){ 
512  let item = document.querySelector('main') 
513  if (item) {
514    const resizeObserver = new ResizeObserver(entries => {
515      for (let entry of entries) {
516        document.querySelector('custom-indicator').onResizeHandler();
517      }
518    });
519
520    resizeObserver.observe(item);
521  }
522}
523
524function setToggle() {
525  const toggleHeadingElements = document.getElementsByClassName("kg-toggle-heading");
526
527  const dropdownIcon = document.createElement('div');
528  dropdownIcon.classList.add('dropdown-icon');
529  const verticalLine = document.createElement('div');
530  verticalLine.classList.add('dropdown-line', 'dropdown-vertical-line');
531  const horizontalLine = document.createElement('div');
532  horizontalLine.classList.add('dropdown-line', 'dropdown-horizontal-line');
533
534  dropdownIcon.appendChild(verticalLine);
535  dropdownIcon.appendChild(horizontalLine);
536
537  document.querySelectorAll('.kg-toggle-card').forEach(card => {
538      card.querySelector('.kg-toggle-heading svg').remove();
539
540      const container = card.querySelector(".kg-toggle-card-icon");
541      const clonedIcon = dropdownIcon.cloneNode(true);
542
543      container.appendChild(clonedIcon);
544  })
545  
546  const toggleFn = function(event) {
547      
548      const targetElement = event.target;
549      const parentElement = targetElement.closest('.kg-toggle-card');
550      var toggleState = parentElement.getAttribute("data-kg-toggle-state");
551      if (toggleState === 'close') {
552          parentElement.setAttribute('data-kg-toggle-state', 'open');
553      } else {
554          parentElement.setAttribute('data-kg-toggle-state', 'close');
555      }
556  };
557
558  for (let i = 0; i < toggleHeadingElements.length; i++) {
559      toggleHeadingElements[i].addEventListener('click', toggleFn, false);
560  }
561}
562
563let lenis;
564
565function setSmoothScroll() {
566  if(window.safari !== undefined) return;
567
568  if (lenis) {
569    lenis.destroy();
570  }
571
572  let speed = 0.6;
573
574  lenis = new Lenis({
575    duration: speed,
576    easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
577    direction: 'vertical',
578    gestureDirection: 'vertical',
579    smooth: true,
580    smoothTouch: false,
581    touchMultiplier: 2,
582    infinite: false
583  })
584
585  function raf(time) {
586      lenis.raf(time)
587      requestAnimationFrame(raf)
588  }
589
590  requestAnimationFrame(raf);
591}

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.