PageSourceSearch

https://www.facom.com/modules/custom/sbd_site_studio/js/gsap-content.js?tl1qv4

js facom.com collected 2026-09-24 22:42:34 UTC 9,042 bytes, 228 lines download raw bytes

1(function ($) {
2  // Initialize the flag to control animations
3  let runAnimations = true;
4
5  Drupal.behaviors.gsapContent = {
6    attach: function (context, settings) {
7      // Register Plugin
8      if (gsap && gsap.registerPlugin && ScrollTrigger) {
9        gsap.registerPlugin(ScrollTrigger);
10      } else {
11        console.error('GSAP or ScrollTrigger not available.');
12      }
13
14      // Removes gsap animation from carousels inside tab/accordion components
15      const tabbedComponent = document.querySelectorAll('.coh-accordion-tabs-content');
16
17      tabbedComponent.forEach((element) => {
18        const tabCarouselItems = element.querySelectorAll('.gsap-carousel-item');
19        tabCarouselItems.forEach((element) => {
20          element.classList.remove("gsap-carousel-item");
21        });
22      });
23
24      // Defines elements to be animated
25      const elements = {
26        featureBlockTextFirst: gsap.utils.toArray('.feature-block-component[data-content-order="text-first"]'),
27        featureBlockImageFirst: gsap.utils.toArray('.feature-block-component[data-content-order="image-first"]'),
28        pageHeaderComponent: gsap.utils.toArray('.page-header-component'),
29        fiftyFiftyComponent: gsap.utils.toArray('.fifty-fifty-component'),
30        listingComponent: gsap.utils.toArray('.listing-component:not([gsap-animation="disabled"]'),
31        pageHeroComponent: gsap.utils.toArray('.page-hero-component'),
32        pdpFadeInSection: gsap.utils.toArray('.gsap-fadein-section'),
33        pdpGalleryFadeInContainer: gsap.utils.toArray('.gsap-fadein-sku-gallery-container'),
34        carouselContainer: gsap.utils.toArray('.sbd-carousel'),
35        carouselItem: gsap.utils.toArray('.gsap-carousel-item'),
36        richTextFadeIn: gsap.utils.toArray('div:not(.coh-modal-inner):not(.coh-accordion-tabs-content) > .gsap-fadein-richtext:not([gsap-animation="disabled"])'),
37        toolboxItem: gsap.utils.toArray('#block-mytoolbox .items-list-wrapper .items-list')
38      };
39
40      // Elements to reset on mobile or when reduced motion is enabled
41      const elementsToSetOpacity = Object.values(elements).flat();
42
43      // Running animations only if the viewport is below 1024px
44      let isMobile = window.innerWidth <= 1024;
45      let reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
46
47      // Initial check for media query and reduced motion
48      handleMediaQueryChange();
49
50      // Add listener for future changes
51      window.addEventListener('resize', () => {
52        // Update isMobile on window resize
53        isMobile = window.innerWidth <= 1024;
54        handleMediaQueryChange();
55      });
56
57      // Add listener for reduce motion preference change
58      window.matchMedia("(prefers-reduced-motion: reduce)").addEventListener('change', (event) => {
59        // Update reduceMotion on preference change
60        reduceMotion = event.matches;
61        handleMediaQueryChange();
62      });
63
64      // Handle page show event for browser back button
65      window.addEventListener('pageshow', (event) => {
66        if (event.persisted) {
67          // Page was loaded from the back/forward cache
68          resetCarouselAnimations();
69          handleMediaQueryChange();
70        }
71      });
72
73      function handleMediaQueryChange() {
74        if (!isMobile && !reduceMotion && runAnimations) {
75          // Animations when text is displayed first
76          elements.featureBlockTextFirst.forEach((element) => {
77            animateFeatureBlock(element, 50, 0);
78          });
79
80          // Animations when image is displayed first
81          elements.featureBlockImageFirst.forEach((element) => {
82            animateFeatureBlock(element, -50, 0);
83          });
84
85          // Fades In Page Headers
86          fadeInElements(elements.pageHeaderComponent);
87
88          // Fades In 50/50 Component
89          fadeInElements(elements.fiftyFiftyComponent);
90
91          // Fades In Listing Component
92          fadeInElements(elements.listingComponent);
93
94          // Fades In Hero Component
95          fadeInElements(elements.pageHeroComponent);
96
97          // Fade in PDP template sections
98          fadeInElements(elements.pdpFadeInSection);
99
100          // Fade in PDP product gallery
101          fadeInElements(elements.pdpGalleryFadeInContainer);
102
103          // Fade in Rich Text component
104          fadeInElements(elements.richTextFadeIn);
105
106          // Carousel item fade in
107          ScrollTrigger.batch(":not(.pdp-ajax-carousel-container) .gsap-carousel-item", {
108            batchMax: 3,
109            invalidateOnRefresh: true,
110            onEnter: batch => gsap.to(batch, { opacity: 1, duration: 1, stagger: { each: 0.2 }
110, overwrite: true })
111          });
112
113          // Toolbox item fade in
114          fadeInElements(elements.toolboxItem, 75);
115
116          // Find a retailer item fade in
117          //fadeInElements(elements.retailerLocations, 75, '.lsp__location-result-set-wrapper');
118
119        } else {
120          // Set runAnimations to false to prevent animations
121          runAnimations = false;
122
123          // Clear any existing animations or triggers
124          gsap.globalTimeline.clear();
125          ScrollTrigger.getAll().forEach(trigger => trigger.kill());
126
127          // Reset opacity and visibility for elements
128          elementsToSetOpacity.forEach((element) => {
129            if (element) {
130              gsap.set(element, { opacity: 1, visibility: 'visible' });
131            }
132          });
133
134          // Reset initial styles for featureBlockTextFirst
135          resetFeatureBlockStyles(elements.featureBlockTextFirst);
136
137          // Reset initial styles for featureBlockImageFirst
138          resetFeatureBlockStyles(elements.featureBlockImageFirst);
139        }
140      }
141
142      function fadeInElements(elements, start = "20% 75%", scroller = null) {
143        elements.forEach((element) => {
144          if (element) {
145            const tl = gsap.timeline({
146              onComplete: function () {
147                // Removes class to prevent rich text from animating after opening/closing tab component
148                element.classList.remove("gsap-fadein-richtext");
149                element.classList.remove("gsap-fadein-sku-gallery-container");
150              },
151            });
152            tl.fromTo(element, { autoAlpha: 0 }, { duration: 1, autoAlpha: 1 });
153
154            ScrollTrigger.create({
155              trigger: element,
156              animation: tl,
157              toggleActions: 'play none none none',
158              start: start,
159              scroller: scroller
160            });
161          }
162        });
163      }
164
165      function animateFeatureBlock(element, xValue, yValue) {
166        const
167          contentBox = element.querySelector('.content-box'),
168          mediaContainer = element.querySelector('.media-container'),
169          buttons = element.querySelectorAll('.reusable-button-set .coh-buttons a'),
170          textButton = element.querySelector('.reusable-button-set .coh-text-button'),
171          tl = gsap.timeline();
172
173          if (mediaContainer) {
174            tl.fromTo(mediaContainer, { autoAlpha: 0, x: xValue }, { duration: 1, autoAlpha: 1, x: 0 });
175          }
176          
177          if (contentBox) {
178            tl.fromTo(contentBox, { autoAlpha: 0, x: -xValue }, { duration: 1, autoAlpha: 1, x: 0 }, '<.25');
179          }
180          
181          if (buttons) {
182            tl.fromTo(buttons, { autoAlpha: 0, y: 30 }, { duration: 1, autoAlpha: 1, y: 0, stagger: { amount: .25, grid: 'auto' } }, '<.25');
183          }
184          
185          if (textButton) {
186              tl.fromTo(textButton, { autoAlpha: 0, y: 20 }, { duration: 1, autoAlpha: 1, y: 0 }, '<.25');
187          }
188          
189          ScrollTrigger.create({
190              trigger: element,
191              animation: tl,
192              toggleActions: 'play none none none',
193              start: "20% 75%"
194          });
195      }
196
197      function resetFeatureBlockStyles(elements) {
198        elements.forEach((element) => {
199          const
200            contentBox = element.querySelector('.content-box'),
201            mediaContainer = element.querySelector('.media-container'),
202            buttons = element.querySelectorAll('.reusable-button-set .coh-buttons a'),
203            textButton = element.querySelector('.reusable-button-set .coh-text-button');
204
205          if (contentBox && mediaContainer && buttons && textButton) {
206            gsap.set(mediaContainer, { autoAlpha: 1, x: 0 });
207            gsap.set(contentBox, { autoAlpha: 1, x: 0 });
208            gsap.set(buttons, { autoAlpha: 1, y: 0 });
209            gsap.set(textButton, { autoAlpha: 1, y: 0 });
210          }
211        });
212      }
213
214      // Function to reset carousel animations
215      function resetCarouselAnimations() {
216        // Clear existing ScrollTriggers for carousel items
217        ScrollTrigger.getAll().forEach(trigger => {
218          if (trigger.trigger.classList.contains('gsap-carousel-item')) {
219            trigger.kill();
220          }
221        });
222
223        // Reset GSAP animations for carousel items
224        gsap.set('.gsap-carousel-item', { opacity: 0 });
225      }
226    }
227  };
228})(jQuery);

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.