https://friendsprovidentfoundation.org/wp-content/themes/fpf-main/js/main.js?ver=1.79028479678E%2B12
1/* Init object fit polyfill */ 2/* To make it work, add 'font-family: 'object-fit: cover;';' to image */ 3if (window.objectFitImages) { 4 window.objectFitImages(); 5} 6 7(function () { 8 9 let resizeId; // for resize timer 10 let wWidth = window.innerWidth; // for resize 11 let isObserver = true; //for scroll reveal 12 let observer; //for scroll reveal 13 let root = document.documentElement; //for css variables update 14 let scrollPosition = 0; 15 const $body = document.body; 16 const $html = document.documentElement; 17 let $landingScreenInterval; 18 19 /// /* Setup helper functions */ 20 21 // https://www.afasterweb.com/2017/09/26/performance-basics-throttling/ 22 function throttle(callback, limit) { 23 let tick = false; 24 return function () { 25 if (!tick) { 26 callback.call(); 27 tick = true; 28 setTimeout(function () { 29 tick = false; 30 }, limit); 31 } 32 } 33 } 34 35 // window.addEventListener("scroll", throttle(customFunction, 16)); 36 37 function disableScrolling() { 38 if (document.documentElement.scrollHeight > window.innerHeight) { 39 const scrollTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop; // Works for Chrome, Firefox, IE... 40 document.documentElement.classList.add('disable-scrolling'); 41 document.documentElement.style.top = -scrollTop + 'px'; 42 43 setTimeout(() => { 44 document.documentElement.classList.add('scroll-default'); 45 }, 0) 46 } 47 } 48 49 function enableScrolling() { 50 const scrollTop = parseInt(document.documentElement.style.top); 51 document.documentElement.classList.remove('disable-scrolling'); 52 document.documentElement.scrollTop = -scrollTop; 53 document.body.scrollTop = -scrollTop; 54 setTimeout(() => { 55 document.documentElement.classList.remove('scroll-default'); 56 }, 0) 57 } 58 59 function isMobile() { 60 if (document.querySelector('.is-mobile').style.display === 'block') { 61 return true; 62 } else { 63 return false; 64 } 65 } 66 67 //Scroll revealing animation 68 if ( 69 !('IntersectionObserver' in window) 70 || !('IntersectionObserverEntry' in window) 71 || !('isIntersecting' in window.IntersectionObserverEntry.prototype) 72 ) { 73 isObserver = false; 74 document.documentElement.classList.remove('is-observer'); 75 } 76 77 if (isObserver) { 78 observer = new IntersectionObserver( 79 entries => { 80 entries.forEach(entry => { 81 if (entry.isIntersecting) { 82 entry.target.classList.add('is-visible'); 83 observer.unobserve(entry.target); 84 } 85 }); 86 }, 87 { rootMargin: '0px 0px -15% 0px' } 88 ); 89 } 90 91 if (isObserver) { 92 document.querySelectorAll('.js-visibility').forEach((el, i) => { 93 observer.observe(el); 94 }) 95 } 96 97 document.querySelectorAll('.scroll-link').forEach((el, i) => { 98 el.addEventListener('click', (e) => { 99 const $target = e.currentTarget.getAttribute('href'); 100 const $targetFormatted = document.querySelector($target.substring(1)).offsetTop; 101 // document.documentElement.scrollTop = $targetFormatted.offsetTop; 102 // document.body.scrollTop = $targetFormatted.offsetTop; 103 window.scrollTo( 104 0, 105 $targetFormatted - document.querySelector('.site-header').getBoundingClientRect().height); 106 }) 107 }) 108 109 document.querySelectorAll('.btn-scroll-top--js').forEach((el, i) => { 110 el.addEventListener('click', (e) => { 111 e.preventDefault(); 112 window.scrollTo(0, 0); 113 }) 114 }) 115 116 117 // Mac and IOS devices require different nav styling 118 let isMacLike = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform); 119 let isIOS = /(iPhone|iPod|iPad)/i.test(navigator.platform); 120 121 if (isIOS || isMacLike) { 122 // $('.section-404').addClass('is-ios'); 123 // $('.homepage-hero__item-inner').addClass('is-ios'); 124 } 125 126 // 127 128 let isTouch; 129 130 function isTouchDevice() { 131 const prefixes = ' -webkit- -moz- -o- -ms- '.split(' '); 132 const mq = (query) => { 133 return window.matchMedia(query).matches; 134 }; 135 136 if ( 137 'ontouchstart' in window || 138 // eslint-disable-next-line no-undef 139 (window.DocumentTouch && document instanceof DocumentTouch) 140 ) { 141 return true; 142 } 143 144 // include the 'heartz' as a way to have a non matching MQ to help terminate the join 145 // https://git.io/vznFH 146 const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join( 147 '' 148 );
149 return mq(query); 150 } 151 152 if (isTouchDevice()) { 153 isTouch = true; 154 document.documentElement.classList.add('is-touch'); 155 } 156 157 const getNextSibling = function (elem, selector) { 158 159 // Get the next sibling element 160 let sibling = elem.nextElementSibling; 161 162 // If there's no selector, return the first sibling 163 if (!selector) return sibling; 164 165 // If the sibling matches our selector, use it 166 // If not, jump to the next sibling and continue the loop 167 while (sibling) { 168 if (sibling.matches(selector)) return sibling; 169 sibling = sibling.nextElementSibling 170 } 171 172 }; 173 /// /* End of Setup helper functions */ 174 175 function mobileMenuActionHandler() { 176 const mobileMenu = document.querySelector('.mobile-menu'); 177 const mobileMenuOpen = document.querySelector('.js-menu--open'); 178 const mobileMenuClose = document.querySelector('.js-menu--close'); 179 const menuItems = mobileMenu.querySelectorAll('.menu-item a'); 180 181 mobileMenuOpen.addEventListener('click', function (e) { 182 mobileMenu.classList.add('is--visible'); 183 }); 184 mobileMenuClose.addEventListener('click', function (e) { 185 mobileMenu.classList.remove('is--visible'); 186 }); 187 menuItems.forEach(menuItem => { 188 menuItem.addEventListener('click', function () { 189 mobileMenu.classList.remove('is--visible'); 190 }); 191 }) 192 } 193 function carouselsHandler() { 194 const libraryCarousel = new Swiper(".js-cards-carousel", { 195 slidesPerView: 1.3, 196 spaceBetween: 25, 197 scrollbar: { 198 el: ".swiper-scrollbar", 199 hide: false, 200 draggable: true, 201 }, 202 breakpoints: { 203 767: { 204 slidesPerView: 2.3, 205 spaceBetween: 30, 206 }, 207 1280: { 208 slidesPerView: 3.7, 209 }, 210 } 211 }); 212 const libraryPickCarousel = new Swiper(".library-pick-carousel", { 213 slidesPerView: 1, 214 effect: 'fade', 215 autoplay: { 216 delay: 5000, 217 }, 218 fadeEffect: { // added 219 crossFade: true // added(resolve the overlapping of the slides) 220 }, 221 pagination: { 222 el: ".swiper-pagination", 223 clickable: true 224 }, 225 }); 226 227 const homeHeroCarousel = new Swiper(".js-hero-carousel", { 228 slidesPerView: 1, 229 spaceBetween: 17, 230 slidesPerView: 1.3, 231 autoplay: { 232 delay: 5000, 233 }, 234 pagination: { 235 el: ".swiper-pagination", 236 clickable: true 237 }, 238 breakpoints: { 239 767: { 240 spaceBetween: 40, 241 }, 242 1280: { 243 slidesPerView: 1.4, 244 spaceBetween: 50, 245 }, 246 } 247 }); 248 249 const singleImagesCarousel = new Swiper(".js-images-carousel", { 250 slidesPerView: 1, 251 spaceBetween: 25, 252 slidesPerView: 1.3, 253 scrollbar: { 254 el: ".swiper-scrollbar", 255 hide: false, 256 draggable: true, 257 }, 258 breakpoints: { 259 767: { 260 spaceBetween: 40, 261 }, 262 1280: { 263 slidesPerView: 2, 264 }, 265 } 266 }); 267 268 269 const genCarousels = document.querySelectorAll('.gen-carousel'); 270 genCarousels.forEach(carousel => { 271 let genCarousel = new Swiper(carousel, { 272 slidesPerView: 1.2, 273 spaceBetween: 21, 274 scrollbar: { 275 el: ".swiper-scrollbar", 276 hide: false, 277 draggable: true, 278 }, 279 breakpoints: { 280 767: { 281 slidesPerView: 1.3, 282 spaceBetween: 38, 283 }, 284 1280: { 285 slidesPerView: 1.7, 286 spaceBetween: 40, 287 }, 288 } 289 }); 290 }); 291 292 293 } 294 295 function headerSearchHandler() { 296 const searchOpen = document.querySelector('.search--open'); 297 const searchClose = document.querySelector('.search--close'); 298 const search = document.querySelector('.header__search .search-form'); 299 const menu = document.querySelector('.header__nav'); 300 searchOpen.addEventListener('click', function () { 301 menu.classList.add('is--hidden'); 302 searchOpen.classList.remove('is--visible'); 303 setTimeout(() => { 304 search.classList.add('is--visible'); 305 searchClose.classList.add('is--visible'); 306 }, 500) 307 }); 308 searchClose.addEventListener('click', function () { 309 search.classList.remove('is--visible'); 310 searchClose.classList.remove('is--visible'); 311 setTimeout(() => { 312 menu.classList.remove('is--hidden'); 313 searchOpen.classList.add('is--visible'); 314 }, 500) 315 }); 316 document.addEventListener('click', function (e) { 317 let closestSearch = e.target.closest('.header__search .search-form'); 318 let closestBtn = e.target.closest('.search--open');
319 if (!closestSearch && !closestBtn && search.classList.contains('is--visible')) { 320 search.classList.remove('is--visible'); 321 searchClose.classList.remove('is--visible'); 322 setTimeout(() => { 323 menu.classList.remove('is--hidden'); 324 searchOpen.classList.add('is--visible'); 325 }, 500) 326 } 327 }); 328 329 } 330 function anchorDropdownHandler() { 331 const dropdown = document.querySelector('.anchor-nav__dropdown'); 332 if (dropdown) { 333 dropdown.addEventListener('click', function () { 334 dropdown.classList.toggle('is--expanded'); 335 if (dropdown.classList.contains('is--expanded')) { 336 dropdown.style.height = `${dropdown.scrollHeight}px`; 337 } else { 338 dropdown.style.height = '46px'; 339 } 340 }); 341 } 342 343 } 344 function lazyLoadHandler() { 345 // Get a reference to the animated element 346 const animatedEls = document.querySelectorAll('.js-animated-el'); 347 animatedEls.forEach(el => { 348 // Create a GSAP animation for the element 349 const animation = gsap.fromTo(el, { 350 duration: 0.7, 351 yPercent: 50, 352 opacity: 0, 353 }, { 354 opacity: 1, 355 duration: 0.7, 356 yPercent: 0, 357 paused: true, // Initially, the animation is paused 358 // Additional animation properties if needed 359 }); 360 ScrollTrigger.create({ 361 trigger: el, 362 start: 'top 80%', // When to start the animation (80% from the top of the viewport) 363 end: 'bottom 20%', // When to end the animation (20% from the bottom of the viewport) 364 animation: animation, 365 toggleActions: 'play none none', // Play animation on enter and reverse it on leave 366 }); 367 }); 368 }; 369 function popupHandler() { 370 const people = document.querySelectorAll('.js-popup--open'); 371 const popupBody = document.querySelector('.person-popup'); 372 const popupClose = document.querySelector('.js-popup--close'); 373 if (popupBody && people) { 374 const popup = { 375 img: popupBody.querySelector('.js-popup-image'), 376 pronouns: popupBody.querySelector('.js-popup-pronouns'), 377 name: popupBody.querySelector('.js-popup-name'), 378 role: popupBody.querySelector('.js-popup-role'), 379 copy: popupBody.querySelector('.js-popup-copy'), 380 twitter: popupBody.querySelector('.js-popup-twitter'), 381 facebook: popupBody.querySelector('.js-popup-facebook'), 382 linkedin: popupBody.querySelector('.js-popup-linkedin'), 383 email: popupBody.querySelector('.js-popup-email'), 384 } 385 people.forEach(popupTrigger => { 386 popupTrigger.addEventListener('click', function () { 387 console.log('click'); 388 let img = this.getAttribute('data-image'); 389 let pronouns = this.getAttribute('data-pronouns'); 390 let name = this.getAttribute('data-name'); 391 let role = this.getAttribute('data-role'); 392 let copy = this.getAttribute('data-copy'); 393 let twitter = this.getAttribute('data-twitter'); 394 let facebook = this.getAttribute('data-facebook'); 395 let linkedin = this.getAttribute('data-linkedin'); 396 let email = this.getAttribute('data-email'); 397 398 popup.img.setAttribute('src', img); 399 popup.pronouns.textContent = pronouns; 400 popup.name.textContent = name; 401 popup.role.textContent = role; 402 popup.copy.textContent = copy; 403 404 if (twitter) { 405 popup.twitter.setAttribute('href', twitter); 406 } else { 407 popup.twitter.parentElement.style = "display:none"; 408 } 409 if (facebook) { 410 popup.facebook.setAttribute('href', facebook); 411 } else { 412 popup.facebook.parentElement.style = "display:none"; 413 } 414 if (linkedin) { 415 popup.linkedin.setAttribute('href', linkedin); 416 } else { 417 popup.linkedin.parentElement.style = "display:none"; 418 } 419 if (email) { 420 popup.email.setAttribute('href', 'mailto:' + email); 421 } else { 422 popup.email.parentElement.style = "display:none"; 423 } 424 425 popupBody.classList.add('is--visible'); 426 }); 427 428 popupClose.addEventListener('click', function () { 429 popupBody.classList.remove('is--visible'); 430 }); 431 432 document.addEventListener('click', function (e) { 433 let closestPopup = e.target.closest('.person-popup'); 434 let closestPerson = e.target.closest('.js-popup--open');
435 if (!closestPopup && !closestPerson && popupBody.classList.contains('is--visible')) { 436 popupBody.classList.remove('is--visible'); 437 } 438 }); 439 }); 440 } 441 } 442 function accordionHandler() { 443 const accordionBtns = document.querySelectorAll('.js-accordion-heading'); 444 if (accordionBtns) { 445 446 accordionBtns.forEach(el => { 447 const accordionTrigger = el.querySelector('.accordion-item__btn'); 448 accordionInteraction(accordionTrigger); 449 accordionInteraction(el); 450 }); 451 452 function accordionInteraction(trigger){ 453 trigger.addEventListener('click', function () { 454 const accordionContent = this.parentElement.querySelector('.accordion-item__copy'); 455 const accordionBtn = this.querySelector('.accordion-item__btn-name'); 456 this.parentElement.classList.toggle('is--active'); 457 458 if (this.parentElement.getAttribute('aria-label') === 'expanded') { 459 this.parentElement.setAttribute( 460 'aria-label', 461 'collapsed' 462 ); 463 } else { 464 this.parentElement.setAttribute('aria-label', 'expanded'); 465 } 466 467 accordionContent.classList.toggle('is--visible'); 468 469 accordionBtns.forEach(sibling => { 470 if (sibling !== trigger) { 471 sibling.parentElement.classList.remove('is--active'); 472 let accordionContent = sibling.nextElementSibling; 473 sibling.parentElement.setAttribute( 474 'aria-label', 475 'collapsed' 476 ); 477 accordionContent.classList.remove('is--visible'); 478 accordionContent.style.height = '0'; 479 sibling.querySelector('.accordion-item__btn-name').textContent = "Open"; 480 } 481 }); 482 483 if (accordionContent.classList.contains('is--visible')) { 484 accordionContent.style.height = `${accordionContent.scrollHeight}px`; 485 accordionBtn.textContent = "Close"; 486 } else { 487 accordionContent.style.height = '0'; 488 accordionBtn.textContent = "Open"; 489 } 490 }); 491 } 492 } 493 } 494 function customSelectHandler() { 495 const select = document.querySelector('.js-custom-select'); 496 if (select) { 497 const options = select.querySelectorAll('.js-select-option'); 498 const pickedVal = select.querySelectorAll('.js-select-picked'); 499 select.addEventListener('click', function () { 500 select.classList.toggle('is--expanded'); 501 if (select.classList.contains('is--expanded')) { 502 select.style.height = `${select.scrollHeight}px`; 503 } else { 504 select.style.height = '46px'; 505 } 506 }); 507 options.forEach(option => { 508 option.addEventListener('change', function () { 509 pickedVal.innerText = this.value; 510 select.classList.remove('is--expanded'); 511 select.style.height = '46px'; 512 }); 513 }); 514 } 515 } 516 517 function customSelectCF7() { 518 const select = document.querySelector('.form-select'); 519 const picked = document.querySelector('.form-select__picked'); 520 if (select) { 521 select.addEventListener('click', function () { 522 this.classList.toggle('is--active'); 523 524 if (this.getAttribute('aria-label') === 'expanded') { 525 this.setAttribute('aria-label', 'collapsed'); 526 } else { 527 this.setAttribute('aria-label', 'expanded'); 528 } 529 if (this.classList.contains('is--active')) { 530 this.style.height = `${this.scrollHeight}px`; 531 } else { 532 if (window.innerWidth < 767){ 533 this.style.height = '82px'; 534 } else { 535 this.style.height = '68px'; 536 } 537 } 538 }); 539 const inputs = select.querySelectorAll('input');
540 inputs.forEach(input => { 541 input.addEventListener('change', function () { 542 console.log(true); 543 select.classList.remove('is--active'); 544 select.setAttribute('aria-label', 'collapsed'); 545 if (window.innerWidth < 767){ 546 select.style.height = '82px'; 547 } else { 548 select.style.height = '68px'; 549 } 550 picked.innerText = this.nextElementSibling.innerText; 551 }); 552 }); 553 } 554 } 555 556 557 558 function copyArticleLinkInit() { 559 const link = document.querySelector('.share-list-link--copy'); 560 if (link) { 561 const copy = link.nextElementSibling; 562 const tooltip = link.querySelector('.tooltip'); 563 link.addEventListener('click', function(e) { 564 e.preventDefault(); 565 let url = this.getAttribute('href'); 566 navigator.clipboard.writeText(url); 567 tooltip.classList.add('is--visible'); 568 setTimeout(() => { 569 tooltip.classList.remove('is--visible'); 570 }, 500); 571 }); 572 } 573 } 574 575 function anchorLinksInteraction(){ 576 const items = document.querySelectorAll('.legal__nav-item a'); 577 items.forEach(item => { 578 item.addEventListener('click', function(e){ 579 this.classList.add('is--active'); 580 items.forEach(sibling => { 581 if (sibling !== item) { 582 sibling.classList.remove('is--active'); 583 } 584 }); 585 }); 586 587 588 }); 589 } 590 591 mobileMenuActionHandler(); 592 carouselsHandler(); 593 headerSearchHandler(); 594 anchorDropdownHandler(); 595 // lazyLoadHandler(); 596 accordionHandler(); 597 customSelectHandler(); 598 popupHandler(); 599 copyArticleLinkInit(); 600 customSelectCF7(); 601 anchorLinksInteraction(); 602} 603 604 605)();
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.