1/* 2function adjustElementHeight() { 3 4 // Query elements inside the function to ensure they exist 5 const $element = document.querySelector(".adjust-height-to-cta-buttons"); 6 const $ctaButtons = document.querySelectorAll(".inquire-visit-apply-cta"); 7 8 if (!$element || $ctaButtons.length === 0) { 9 return; 10 } 11 12 // Unset min-height and max-height with !important 13 $element.style.setProperty("min-height", "unset", "important"); 14 $element.style.setProperty("max-height", "none", "important"); 15 16 // Get screen height 17 const screenHeight = window.innerHeight; 18 const viewportWidth = window.innerWidth; 19 const isDesktop = viewportWidth >= 1024; 20 21 // Get header height for desktop 22 let headerHeight = 0; 23 if (isDesktop) { 24 const $header = document.querySelector("#header-outer"); 25 if ($header) { 26 headerHeight = $header.offsetHeight; 27 } 28 } 29 30 // Get WordPress admin bar height (topbar) if user is logged in 31 let adminBarHeight = 0; 32 const $adminBar = document.querySelector("#wpadminbar"); 33 if ($adminBar) { 34 adminBarHeight = $adminBar.offsetHeight; 35 } 36 37 // Get the actual rendered height of the button group 38 // Use getBoundingClientRect to get the actual height from first to last button 39 let totalButtonsHeight = 0; 40 if ($ctaButtons.length > 0) { 41 const firstButton = $ctaButtons[0]; 42 const lastButton = $ctaButtons[$ctaButtons.length - 1]; 43 const firstRect = firstButton.getBoundingClientRect(); 44 const lastRect = lastButton.getBoundingClientRect(); 45 // Height is from top of first button to bottom of last button 46 totalButtonsHeight = lastRect.bottom - firstRect.top; 47 } 48 49 // Calculate element height: screen height - button group height - header height (desktop only) - admin bar height 50 const elementHeight = 51 screenHeight - totalButtonsHeight - headerHeight - adminBarHeight; 52 53 console.log("Screen height:", screenHeight); 54 console.log("Viewport width:", viewportWidth); 55 console.log("Is desktop:", isDesktop); 56 console.log("Header height:", headerHeight); 57 console.log("Admin bar height:", adminBarHeight); 58 console.log("Button group height:", totalButtonsHeight); 59 console.log("Element height:", elementHeight); 60 61 // Set the height with !important to ensure it overrides any CSS 62 $element.style.setProperty("height", `${elementHeight}px`, "important"); 63} 64 65// Debounce function to prevent excessive calls during resize 66let resizeTimeout; 67function debouncedAdjustHeight() { 68 clearTimeout(resizeTimeout); 69 resizeTimeout = setTimeout(adjustElementHeight, 100); 70} 71 72// Function to handle CTA fixed positioning on scroll 73function handleCTAFixedPosition() { 74 const $ctaButtons = document.querySelectorAll(".inquire-visit-apply-cta"); 75 const $header = document.querySelector("#header-outer"); 76 77 if ($ctaButtons.length === 0) { 78 return; 79 } 80 81 // Get the first CTA button to check its position 82 const firstCTA = $ctaButtons[0]; 83 84 // Temporarily remove fixed class to get accurate viewport position 85 const wasFixed = firstCTA.classList.contains("cta-fixed"); 86 if (wasFixed) { 87 firstCTA.classList.remove("cta-fixed"); 88 firstCTA.style.removeProperty("top"); 89 } 90 91 // Get CTA's current position in viewport 92 const ctaRect = firstCTA.getBoundingClientRect(); 93 const ctaTop = ctaRect.top; 94 95 // Get header height 96 let headerHeight = 0; 97 if ($header) { 98 headerHeight = $header.offsetHeight; 99 } 100 101 // Get WordPress admin bar height if present 102 let adminBarHeight = 0; 103 const $adminBar = document.querySelector("#wpadminbar"); 104 if ($adminBar) { 105 adminBarHeight = $adminBar.offsetHeight; 106 } 107 108 // Calculate the total offset from top (header + admin bar) 109 const totalOffsetFromTop = headerHeight + adminBarHeight; 110 111 // Check if CTA has touched or passed the header 112 // CTA should be fixed when its top edge reaches or passes the header bottom 113 const shouldBeFixed = ctaTop <= totalOffsetFromTop; 114 115 // Restore fixed state temporarily removed for measurement 116 if (wasFixed && shouldBeFixed) { 117 firstCTA.classList.add("cta-fixed"); 118 firstCTA.style.setProperty("top", `${totalOffsetFromTop}px`, "important"); 119 } 120 121 // Add or remove fixed class based on scroll position 122 for (const button of $ctaButtons) { 123 if (shouldBeFixed) { 124 button.classList.add("cta-fixed"); 125 // Set top position to header height (plus admin bar if present) 126 button.style.setProperty("top", `${totalOffsetFromTop}px`, "important"); 127 } else { 128 button.classList.remove("cta-fixed"); 129 button.style.removeProperty("top"); 130 } 131 } 132} 133 134// Debounce function for scroll events 135let scrollTimeout; 136function debouncedHandleCTAFixed() { 137 if (scrollTimeout) { 138 cancelAnimationFrame(scrollTimeout); 139 } 140 scrollTimeout = requestAnimationFrame(handleCTAFixedPosition); 141} 142 143// Ensure code runs only after page is fully loaded 144function initHeightAdjustment() { 145 // Use window.load for production reliability - ensures all resources are loaded 146 if (document.readyState === "complete") { 147 adjustElementHeight(); 148 handleCTAFixedPosition(); 149 } else { 150 window.addEventListener("load", () => {
151 adjustElementHeight(); 152 handleCTAFixedPosition(); 153 }); 154 } 155 156 // Run on window resize with debouncing 157 window.addEventListener("resize", () => { 158 debouncedAdjustHeight(); 159 debouncedHandleCTAFixed(); 160 }); 161 162 // Also run on orientation change (mobile/tablet) 163 window.addEventListener("orientationchange", () => { 164 setTimeout(() => { 165 adjustElementHeight(); 166 handleCTAFixedPosition(); 167 }, 200); 168 }); 169 170 // Handle scroll events for CTA fixed positioning 171 window.addEventListener("scroll", debouncedHandleCTAFixed, { passive: true }); 172} 173 174// Initialize when DOM is ready 175if (document.readyState === "loading") { 176 document.addEventListener("DOMContentLoaded", initHeightAdjustment); 177} else { 178 initHeightAdjustment(); 179} 180*/ 181 182(() => { 183 window.PCS_CTA_DEBUG = window.PCS_CTA_DEBUG || false; 184 185 function getFlipCardTargets() { 186 const targets = []; 187 const ctaTextBlocks = document.querySelectorAll( 188 ".hp-age-and-stage .cta-text", 189 ); 190 191 for (const ctaText of ctaTextBlocks) { 192 const card = ctaText.closest(".vc_column-inner"); 193 if (card && targets.indexOf(card) === -1) { 194 targets.push(card); 195 } 196 } 197 198 return targets; 199 } 200 201 function setOriginalDisplay(element) { 202 if (!element.dataset.originalDisplay) { 203 element.dataset.originalDisplay = 204 window.getComputedStyle(element).display; 205 } 206 } 207 208 function setFlipState(card, shouldFlip) { 209 const hideSelectors = "h2, h3, h4, .divider-wrap"; 210 const elementsToHide = card.querySelectorAll(hideSelectors); 211 const ctaText = card.querySelector(".cta-text"); 212 213 for (const element of elementsToHide) { 214 setOriginalDisplay(element); 215 element.style.display = shouldFlip 216 ? "none" 217 : element.dataset.originalDisplay; 218 } 219 220 if (ctaText) { 221 setOriginalDisplay(ctaText); 222 ctaText.style.display = shouldFlip ? "flex" : "none"; 223 ctaText.classList.toggle("is-visible", shouldFlip); 224 } 225 226 card.classList.toggle("is-flipped", shouldFlip); 227 card.setAttribute("aria-pressed", shouldFlip ? "true" : "false"); 228 } 229 230 function toggleFlipState(card) { 231 const shouldFlip = !card.classList.contains("is-flipped"); 232 setFlipState(card, shouldFlip); 233 } 234 235 function logCtaMetrics(card, context) { 236 if (!window.PCS_CTA_DEBUG) { 237 return; 238 } 239 240 const ctaText = card.querySelector(".cta-text");
241 const wrapper = ctaText ? ctaText.querySelector(".wpb_wrapper") : null; 242 243 console.groupCollapsed(`[PCS CTA] ${context}`, card); 244 console.log("card.clientHeight", card.clientHeight); 245 console.log("card.scrollHeight", card.scrollHeight); 246 if (ctaText) { 247 console.log("ctaText.clientHeight", ctaText.clientHeight); 248 console.log("ctaText.scrollHeight", ctaText.scrollHeight); 249 console.log("ctaText.scrollTop", ctaText.scrollTop); 250 console.log( 251 "ctaText.alignItems", 252 window.getComputedStyle(ctaText).alignItems, 253 ); 254 console.log( 255 "ctaText.justifyContent", 256 window.getComputedStyle(ctaText).justifyContent, 257 ); 258 } 259 if (wrapper) { 260 console.log("wrapper.clientHeight", wrapper.clientHeight); 261 console.log("wrapper.scrollHeight", wrapper.scrollHeight); 262 console.log("wrapper.scrollTop", wrapper.scrollTop); 263 } 264 console.groupEnd(); 265 } 266 267 function bindFlipCardEvents(card) { 268 card.setAttribute("role", "button"); 269 card.setAttribute("tabindex", "0"); 270 card.setAttribute("aria-pressed", "false"); 271 272 card.addEventListener("mouseenter", () => { 273 setFlipState(card, true); 274 logCtaMetrics(card, "hover-in"); 275 }); 276 277 card.addEventListener("mouseleave", () => { 278 setFlipState(card, false); 279 logCtaMetrics(card, "hover-out"); 280 }); 281 282 card.addEventListener("focus", () => { 283 setFlipState(card, true); 284 logCtaMetrics(card, "focus"); 285 }); 286 287 card.addEventListener("blur", () => { 288 setFlipState(card, false); 289 logCtaMetrics(card, "blur"); 290 }); 291 } 292 293 function initCtaFlipCards() { 294 const cards = getFlipCardTargets(); 295 296 for (const card of cards) { 297 setFlipState(card, false); 298 bindFlipCardEvents(card); 299 logCtaMetrics(card, "init"); 300 } 301 302 if (window.PCS_CTA_DEBUG && !cards.length) { 303 console.warn( 304 "[PCS CTA] No cards found. Check selector:", 305 ".hp-age-and-stage .cta-text", 306 ); 307 } 308 309 window.addEventListener("resize", () => { 310 for (const card of cards) { 311 logCtaMetrics(card, "resize"); 312 } 313 }); 314 } 315 316 window.PCS_CTA_LOG = () => { 317 window.PCS_CTA_DEBUG = true; 318 const cards = getFlipCardTargets(); 319 if (!cards.length) { 320 console.warn( 321 "[PCS CTA] No cards found. Check selector:", 322 ".hp-age-and-stage .cta-text", 323 ); 324 } 325 for (const card of cards) { 326 logCtaMetrics(card, "manual"); 327 } 328 }; 329 330 if (document.readyState === "loading") { 331 document.addEventListener("DOMContentLoaded", initCtaFlipCards); 332 } else { 333 initCtaFlipCards(); 334 } 335})();
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.