PageSourceSearch

https://camping.se/themes/custom/citybreakweb/cb_camping/js/adsWatcherListAndProductPage.js?tlwz01

js camping.se collected 2026-09-25 19:51:56 UTC 4,494 bytes, 131 lines download raw bytes

1/**
2 * Efficiently watches for elements and triggers ad displays using Intersection Observer
3 */
4(function() {
5  // Early exit if no relevant page type
6  const isProductLandingPage = document.querySelector('.page-node-type-cbis-product-landing-page') !== null;
7  const isProductListPage = document.querySelector('.node--type-cbis-product-list.display-with-ads') !== null;
8
9  if (!isProductLandingPage && !isProductListPage) {
10    console.log('No relevant ad containers on this page, exiting ad watcher');
11    return;
12  }
13
14  console.log(`Ads watcher initialized for ${isProductLandingPage ? 'product landing page' : 'product list'}`);
15
16  // Configuration mapping selectors to watch for - only include relevant ones
17  const adSelectors = isProductLandingPage ? [
18    '.page-node-type-cbis-product-landing-page .ads-wrapper-plp-1',
19    '.page-node-type-cbis-product-landing-page .ads-wrapper-plp-2',
20    '.page-node-type-cbis-product-landing-page .ads-wrapper-plp-3'
21  ] : [
22    '.node--type-cbis-product-list.display-with-ads .ads-wrapper-list-swipe1',
23    '.node--type-cbis-product-list.display-with-ads .ads-wrapper-list-swipe2',
24    '.node--type-cbis-product-list.display-with-ads .ads-wrapper-list-swipe3'
25  ];
26
27  // Set timeout based on page type
28  const timeoutDuration = isProductLandingPage ? 90000 : 40000;
29
30  // Helper function to display the ad
31  function displayAdForElement(element) {
32    const id = element.firstElementChild?.id;
33    if (id && typeof googletag !== 'undefined') {
34      googletag.cmd.push(function() {
35        googletag.display(id);
36      });
37    }
38  }
39
40  // Create a single DOM mutation observer to look for ad containers
41  const mutationObserver = new MutationObserver((mutations) => {
42    checkForAdContainers();
43  });
44
45  // Start the mutation observer
46  mutationObserver.observe(document.body, {
47    childList: true,
48    subtree: true
49  });
50
51  // Set timeout for observers
52  setTimeout(() => {
53    if (mutationObserver) {
54      mutationObserver.disconnect();
55      console.log(`Ads watcher timed out after ${timeoutDuration/1000} seconds, disconnecting observer.`);
56
57      // Force check one last time when timing out to catch any missed ads
58      checkForAdContainers(true);
59    }
60  }, timeoutDuration);
61
62  // Function to check for ad containers and set up Intersection Observers
63  function checkForAdContainers(isFinalCheck = false) {
64    adSelectors.forEach(selector => {
65      const containers = document.querySelectorAll(selector);
66
67      containers.forEach(container => {
68        // Skip if this container already has an observer
69        if (container.dataset.adObserved) {
70          return;
71        }
72
73        // Mark as observed
74        container.dataset.adObserved = 'true';
75
76        // On final check, display ads regardless of visibility
77        if (isFinalCheck) {
78          displayAdForElement(container);
79          return;
80        }
81
82        // Create an Intersection Observer for this container
83        const intersectionObserver = new IntersectionObserver((entries) => {
84          entries.forEach(entry => {
85            if (entry.isIntersecting) {
86              displayAdForElement(entry.target);
87              intersectionObserver.unobserve(entry.target);
88            }
89          });
90        }, {
91          rootMargin: '200px', // Load ads when they're within 200px of viewport
92          threshold: 0.01
93        });
94
95        // Start observing this container
96        intersectionObserver.observe(container);
97      });
98    });
99  }
100
101  // Check for containers immediately
102  checkForAdContainers();
103
104  // Setup scroll and resize handlers
105  let scrollTimeout;
106  window.addEventListener('scroll', () => {
107    clearTimeout(scrollTimeout);
108    scrollTimeout = setTimeout(() => {
109      checkForAdContainers();
110    }, 100); // Debounce scroll events
111  });
112
113  // Also check on window resize
114  let resizeTimeout;
115  window.addEventListener('resize', () => {
116    clearTimeout(resizeTimeout);
117    resizeTimeout = setTimeout(() => {
118      checkForAdContainers();
119    }, 200); // Debounce resize events
120  });
121
122  // Additional checks at specific intervals to catch lazy-loaded content
123  setTimeout(checkForAdContainers, 2500);  // Quick initial check
124  setTimeout(checkForAdContainers, 10000); // Check after 10 seconds
125
126  // For product landing pages, do even more delayed checks
127  if (isProductLandingPage) {
128    setTimeout(checkForAdContainers, 30000); // Check after 30 seconds
129    setTimeout(checkForAdContainers, 60000); // Check after 60 seconds
130  }
131})();

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.