PageSourceSearch

https://saracenshead-hotel.co.uk/wp-content/plugins/corporate-even…e-promotions-carousel/carousel.js?ver=1.1.0

js saracenshead-hotel.co.uk collected 2026-10-06 20:16:23 UTC 8,189 bytes, 279 lines download raw bytes

1/**
2 * Corporate Promotions Carousel Block JavaScript
3 *
4 * @package Corporate_Events_Display
5 * @since 1.0.0
6 */
7
8(function () {
9  "use strict";
10
11  /**
12   * Initialize a single carousel
13   */
14  function initializeCarousel(carouselElement) {
15    console.log("Initializing corporate promotions carousel:", carouselElement);
16
17    // Check if already initialized
18    if (carouselElement.classList.contains("splide-initialized")) {
19      console.log("Carousel already initialized, skipping");
20      return;
21    }
22
23    // Get configuration from data attribute
24    let config = {};
25    try {
26      const configData = carouselElement.getAttribute("data-splide");
27      if (configData) {
28        config = JSON.parse(configData);
29        console.log("Loaded configuration from data attribute:", config);
30      }
31    } catch (error) {
32      console.warn("Error parsing carousel configuration:", error);
33    }
34
35    // Default configuration (fallback)
36    const defaultConfig = {
37      type: config.enableLoop !== false ? "loop" : "slide",
38      perPage: 3,
39      perMove: 1,
40      pagination: true,
41      arrows: true,
42      autoplay: false,
43      pauseOnHover: true,
44      breakpoints: {
45        768: { perPage: 2 },
46        480: { perPage: 1 },
47      },
48    };
49
50    // Merge configurations (config from data attribute takes priority)
51    const finalConfig = { ...defaultConfig, ...config };
52
53    // Calculate responsive padding/peek values if padding is set
54    if (finalConfig.padding && finalConfig.padding !== "0") {
55      const originalPadding = finalConfig.padding;
56
57      // Try to extract numeric value for responsive calculations
58      let paddingValue = 0;
59      if (typeof originalPadding === "string") {
60        paddingValue = parseInt(originalPadding) || 0;
61      } else {
62        paddingValue = originalPadding || 0;
63      }
64
65      // Calculate responsive padding
66      const tabletPadding =
67        paddingValue > 0 ? Math.max(paddingValue * 0.6, 10) + "px" : 0;
68      const mobilePadding =
69        paddingValue > 0 ? Math.max(paddingValue * 0.3, 5) + "px" : 0;
70
71      // Update breakpoints with responsive padding
72      finalConfig.breakpoints = {
73        ...finalConfig.breakpoints,
74        768: {
75          ...finalConfig.breakpoints[768],
76          padding: tabletPadding,
77        },
78        480: {
79          ...finalConfig.breakpoints[480],
80          padding: mobilePadding,
81        },
82      };
83    }
84
85    console.log("Final carousel configuration:", finalConfig);
86
87    // Wait for Splide.js to be available
88    function waitForSplide() {
89      if (typeof window.Splide !== "undefined") {
90        console.log("Splide.js is available, creating carousel instance");
91        try {
92          // Create and mount the Splide instance
93          const splide = new window.Splide(carouselElement, finalConfig);
94          splide.mount();
95
96          // Mark as initialized
97          carouselElement.classList.add("splide-initialized");
98          console.log("Corporate promotions carousel initialized successfully");
99        } catch (error) {
100          console.error("Error initializing Splide carousel:", error);
101        }
102      } else {
103        console.log("Splide.js not yet available, retrying...");
104        setTimeout(waitForSplide, 100);
105      }
106    }
107
108    waitForSplide();
109  }
110
111  /**
112   * Initialize all corporate promotions carousels on the page
113   */
114  function initCarousels() {
115    const carousels = document.querySelectorAll(
116      ".corporate-promotions-carousel__splide"
117    );
118    console.log(
119      `Found ${carousels.length} corporate promotions carousel(s) to initialize`
120    );
121
122    carousels.forEach(function (carousel, index) {
123      console.log(`Initializing carousel ${index + 1}/${carousels.length}`);
124      initializeCarousel(carousel);
125    });
126  }
127
128  /**
129   * Initialize when DOM is ready
130   */
131  if (document.readyState === "loading") {
132    document.addEventListener("DOMContentLoaded", initCarousels);
133  } else {
134    initCarousels();
135  }
136
137  /**
138   * Reinitialize carousels when new content is loaded (e.g., via AJAX)
139   */
140  window.corporatePromotionsInitCarousels = initCarousels;
141
142  // Handle ACF block preview updates
143  if (typeof window.acf !== "undefined") {
144    window.acf.addAction("render_block_preview", function () {
145      setTimeout(function () {
146        const carousels = document.querySelectorAll(
147          ".corporate-promotions-carousel__splide"
148        );
149        carousels.forEach(function (carousel) {
150          if (!carousel.classList.contains("splide-initialized")) {
151            initializeCarousel(carousel);
152          }
153        });
154      }, 100);
155    });
156  }
157
158  // MutationObserver to handle dynamically added content
159  const observer = new MutationObserver(function (mutations) {
160    mutations.forEach(function (mutation) {
161      if (mutation.type === "childList") {
162        mutation.addedNodes.forEach(function (node) {
163          if (node.nodeType === Node.ELEMENT_NODE) {
164            // Check if the added node is a carousel or contains carousels
165            const carousels = node.classList?.contains(
166              "corporate-promotions-carousel__splide"
167            )
168              ? [node]
169              : node.querySelectorAll?.(
170                  ".corporate-promotions-carousel__splide"
171                ) || [];
172
173            if (carousels.length > 0) {
174              console.log(
175                `Found ${carousels.length} new corporate promotions carousel(s), initializing...`
176              );
177              carousels.forEach(initializeCarousel);
178            }
179          }
180        });
181      }
182    });
183  });
184
185  // Start observing
186  observer.observe(document.body, {
187    childList: true,
188    subtree: true,
189  });
190
191  console.log("Corporate Promotions Carousel: Initialization complete");
192})();
193
194// ============================================
195// Read More / Read Less functionality for event descriptions
196// ============================================
197document.addEventListener("DOMContentLoaded", () => {
198  const cards = Array.from(
199    document.querySelectorAll(".corporate-promotions-carousel__description")
200  );
201
202  // debounce helper
203  function debounce(fn, wait = 120) {
204    let t;
205    return function (...args) {
206      clearTimeout(t);
207      t = setTimeout(() => fn.apply(this, args), wait);
208    };
209  }
210
211  // find the related button for a given card
212  function getButtonForCard(card) {
213    const cardBody = card.closest(".corporate-promotions-carousel__body");
214    if (!cardBody) return null;
215    return cardBody.querySelector(".btn-read-more");
216  }
217
218  // check if card content is truncated
219  function cardNeedsButton(card) {
220    const btn = getButtonForCard(card);
221    if (!btn) return false;
222
223    card.classList.remove("read-more"); // ensure clamped for measuring
224    const full = card.scrollHeight;
225    const visible = card.clientHeight;
226
227    return full > visible + 2; // truncated if full > visible
228  }
229
230  // update a single card
231  function updateCard(card) {
232    const btn = getButtonForCard(card);
233    if (!btn) return;
234
235    if (card.classList.contains("read-more")) {
236      btn.style.display = "block";
237      btn.textContent = "Read less";
238    } else if (cardNeedsButton(card)) {
239      btn.style.display = "block";
240      btn.textContent = "Read more";
241    } else {
242      btn.style.display = "none";
243    }
244  }
245
246  // update all cards
247  const updateAll = () => cards.forEach(updateCard);
248  const debouncedUpdateAll = debounce(updateAll, 120);
249
250  // attach click handlers
251  cards.forEach((card) => {
252    const btn = getButtonForCard(card);
253    if (!btn) return;
254
255    btn.addEventListener("click", () => {
256      card.classList.toggle("read-more");
257
258      if (card.classList.contains("read-more")) {
259        btn.textContent = "Read less";
260      } else {
261        if (cardNeedsButton(card)) btn.textContent = "Read more";
262        else btn.style.display = "none";
263      }
264    });
265  });
266
267  // handle resize + load
268  window.addEventListener("resize", debouncedUpdateAll);
269  window.addEventListener("load", updateAll);
270
271  // observe card size changes
272  if (window.ResizeObserver) {
273    const ro = new ResizeObserver(debouncedUpdateAll);
274    cards.forEach((card) => ro.observe(card));
275  }
276
277  // initial check
278  updateAll();
279});

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.