1let stickyHeader = () =>{ 2 var header = document.querySelector(".mainHeader"); 3 4 if (!header) return; 5 let lastScrollTop = 0; 6 7 var sticky = header.offsetTop; 8 var headerHeight = header.offsetHeight; 9 10 document.documentElement.style.setProperty('--headerHeight', headerHeight + "px"); 11 12 function checkSticky() { 13 const currentScroll = window.pageYOffset || document.documentElement.scrollTop; 14 if (currentScroll > 100) { 15 header.classList.add("sticky"); 16 if (currentScroll > lastScrollTop) { 17 header.classList.add("header-up"); 18 } 19 // scrolling up 20 else { 21 header.classList.remove("header-up"); 22 } 23 } else { 24 header.classList.remove("sticky"); 25 header.classList.remove("header-up"); 26 } 27 lastScrollTop = currentScroll <= 0 ? 0 : currentScroll; 28 } 29 30 window.onscroll = function() { 31 checkSticky(); 32 }; 33 34} 35 36 37// let stickyHeader = () => { 38// const header = document.querySelector(".mainHeader"); 39 40 41// if (!header) return; 42 43// let lastScrollTop = 0; 44 45// function handleScroll() { 46// const currentScroll = 47// window.pageYOffset || document.documentElement.scrollTop; 48 49// var headerHeight = header.offsetHeight; 50// document.documentElement.style.setProperty('--headerHeight', headerHeight + "px"); 51 52// if (currentScroll > 100) { 53// header.classList.add("sticky"); 54 55// // scrolling down 56// if (currentScroll > lastScrollTop) { 57// header.classList.add("header-up"); 58// } 59// // scrolling up 60// else { 61// header.classList.remove("header-up"); 62// } 63// } else { 64// header.classList.remove("sticky"); 65// header.classList.remove("header-up"); 66// } 67 68// lastScrollTop = currentScroll <= 0 ? 0 : currentScroll; 69// } 70 71// window.addEventListener("scroll", handleScroll); 72// }; 73 74 75let itemHeightFix = (item, parent = false)=> { 76 const elements = document.querySelectorAll(item); 77 78 elements.forEach((element) => { 79 const itemHeight = element.offsetHeight; 80 element.style.setProperty("--itemHeight", `${itemHeight}px`); 81 if (parent) { 82 document.querySelector(parent).style.setProperty("--itemHeight", `${itemHeight}px`); 83 } 84 }); 85} 86 87 88window.addEventListener('load', () => { 89 stickyHeader(); 90 //itemHeightFix('.homeHero .heroOverlay', '.homeHero'); 91 92 93 94}); 95window.addEventListener('resize', () => { 96 stickyHeader(); 97 // itemHeightFix('.homeHero .heroOverlay', '.homeHero'); 98}); 99 100 101document.addEventListener("DOMContentLoaded", function() { 102 103//itemHeightFix('.homeHero .heroOverlay', '.homeHero'); 104 105}); 106 107// jQuery(document).ready(function ($) { 108 109// function updateAccordionImage(detailsEl) { 110// const sourceImg = $(detailsEl).find('.accordionImg img'); 111 112// if (!sourceImg.length) return; 113 114// const src = 115// sourceImg.attr('data-src') || 116// sourceImg.attr('data-lazy-src') || 117// sourceImg.attr('src'); 118 119// const srcset = 120// sourceImg.attr('data-srcset') || 121// sourceImg.attr('srcset') || 122// ''; 123 124// const alt = sourceImg.attr('alt') || ''; 125 126// const target = $('.accordionRightImage'); 127 128// if (!target.find('img').length) { 129// target.html('<img src="" alt="">'); 130// } 131 132// target.find('img') 133// .attr('src', src) 134// .attr('srcset', srcset) 135// .attr('alt', alt); 136 137// // console.log('RIGHT image updated:', src); 138// } 139 140// /* â On page load */ 141// const firstOpen = $('details.e-n-accordion-item[open]').first(); 142// if (firstOpen.length) updateAccordionImage(firstOpen); 143 144// /* â Elementor-friendly accordion click */ 145// $(document).on('click', '.e-n-accordion-item summary', function () { 146 147// // Wait for Elementor to update "open" state 148// setTimeout(() => { 149// const openItem = $(this).closest('.e-n-accordion-item'); 150 151// if (openItem.attr('open')) {
152// updateAccordionImage(openItem[0]); 153// // console.log('Accordion clicked & open:', openItem[0]); 154// } 155// }, 10); 156 157// }); 158 159// }); 160 161jQuery(document).ready(function ($) { 162 163 const rightContainer = $('.accordionRightImage'); 164 const accordionItems = $('.e-n-accordion-item'); 165 let imagesLoaded = 0; 166 let maxHeight = 0; 167 168 /* ---------------------------- 169 1ï¸â£ Append images (hidden) 170 ----------------------------- */ 171 accordionItems.each(function (index) { 172 173 const img = $(this).find('.accordionImg img'); 174 if (!img.length) return; 175 176 const src = 177 img.attr('data-src') || 178 img.attr('data-lazy-src') || 179 img.attr('src'); 180 181 const srcset = 182 img.attr('data-srcset') || 183 img.attr('srcset') || 184 ''; 185 186 const alt = img.attr('alt') || ''; 187 188 const clonedImg = $('<img>', { 189 src, 190 srcset, 191 alt, 192 'data-accordion-index': index, 193 class: 'accordion-right-img' 194 }).css({ 195 position: 'relative', 196 visibility: 'hidden', 197 opacity: 0, 198 width: '100%', 199 height: 'auto' 200 }); 201 202 clonedImg.on('load', function () { 203 const h = $(this).outerHeight(); 204 maxHeight = Math.max(maxHeight, h); 205 206 imagesLoaded++; 207 208 // Once ALL images are measured 209 if (imagesLoaded === accordionItems.length) { 210 rightContainer.css('height', maxHeight + 'px'); 211 212 // Switch all images to stacked absolute mode 213 rightContainer.find('.accordion-right-img').css({ 214 position: 'absolute', 215 inset: 0, 216 visibility: 'visible' 217 }); 218 } 219 }); 220 221 rightContainer.append(clonedImg); 222 }); 223 224 /* ---------------------------- 225 2ï¸â£ Show first open accordion 226 ----------------------------- */ 227 const firstOpen = accordionItems.filter('[open]').first(); 228 if (firstOpen.length) { 229 showImage(accordionItems.index(firstOpen)); 230 } 231 232 /* ---------------------------- 233 3ï¸â£ Accordion click handler 234 ----------------------------- */ 235 $(document).on('click', '.e-n-accordion-item summary', function () { 236 setTimeout(() => { 237 const item = $(this).closest('.e-n-accordion-item'); 238 if (!item.attr('open')) return; 239 240 showImage(accordionItems.index(item)); 241 }, 10); 242 }); 243 244 /* ---------------------------- 245 4ï¸â£ Image switcher 246 ----------------------------- */ 247 function showImage(index) { 248 $('.accordion-right-img') 249 .removeClass('is-active') 250 .filter(`[data-accordion-index="${index}"]`) 251 .addClass('is-active'); 252 } 253 254}); 255 256 257document.addEventListener('DOMContentLoaded', function() { 258 const formSelector = '.galleryphotos-fileform'; 259 const form = document.querySelector(formSelector); 260 const fileInput = document.querySelector(`${formSelector} .elementor-upload-field`); 261 const uploadFieldContainer = document.querySelector(`${formSelector} .elementor-field-type-upload`); 262 263 if (!form || !fileInput || !uploadFieldContainer) { 264 console.warn('Required form elements not found.'); 265 return; 266 } 267 268 // Set multiple attribute if needed 269 fileInput.setAttribute('multiple', 'multiple'); 270 271 // 1. Handle file display on selection 272 fileInput.addEventListener('change', function(event) { 273 const files = event.target.files; 274 let fileListDisplay = document.querySelector(`${formSelector} #file-list-display`); 275 276 if (!fileListDisplay) { 277 fileListDisplay = document.createElement('div'); 278 fileListDisplay.id = 'file-list-display'; 279 uploadFieldContainer.appendChild(fileListDisplay); 280 } 281 282 if (files.length > 0) { 283 fileListDisplay.innerHTML = ''; // Clear previous list 284 for (let i = 0; i < files.length; i++) { 285 const listItem = document.createElement('p'); 286 listItem.textContent = files[i].name; 287 fileListDisplay.appendChild(listItem); 288 } 289 } else { 290 fileListDisplay.innerHTML = '<p>No files selected.</p>'; 291 } 292 }); 293 294 // 2. Clear files on form submission (Elementor Pro event) 295 jQuery(document).on('elementorPro/forms/submit_success', function(event, formId, response) { 296 // Match the specific form using formId (Elementor forms have id="elementor-form-{formId}" or similar) 297 const targetForm = jQuery(`#elementor-form-${formId}, form[data-id="${formId}"]`); 298 if (targetForm.hasClass('galleryphotos-fileform')) { 299 // Clear the file input value 300 jQuery(fileInput).val(''); 301 302 // Clear the custom file list display 303 const fileListDisplay = document.querySelector(`${formSelector} #file-list-display`); 304 if (fileListDisplay) { 305 fileListDisplay.innerHTML = '<p>No files selected.</p>'; 306 } 307 308 // Force UI refresh for styled upload field (small delay) 309 setTimeout(function() { 310 // Trigger a change event to reset Elementor's label/display if needed 311 fileInput.dispatchEvent(new Event('change', { bubbles: true })); 312 // Optionally, hide/show the container to force repaint (if still stuck) 313 uploadFieldContainer.style.display = 'none'; 314 uploadFieldContainer.offsetHeight; // Trigger reflow 315 uploadFieldContainer.style.display = ''; 316 }, 100); 317 } 318 }); 319 320 // Fallback for non-Pro Elementor or standard submit_success (uncomment if Pro event doesn't work) 321 /* 322 jQuery(document).on('submit_success', function(event, formId, response) { 323 // Same logic as above... 324 const targetForm = jQuery(`#elementor-form-${formId}, form[data-id="${formId}"]`); 325 if (targetForm.hasClass('galleryphotos-fileform')) { 326 // Clear logic here (copy from above) 327 } 328 }); 329 */ 330 331 // Optional: Handle non-AJAX submission (if form isn't AJAX-enabled) 332 form.addEventListener('submit', function() { 333 // Clear on submit (before send), but this won't catch AJAX success 334 jQuery(fileInput).val(''); 335 const fileListDisplay = document.querySelector(`${formSelector} #file-list-display`); 336 if (fileListDisplay) { 337 fileListDisplay.innerHTML = '<p>No files selected.</p>'; 338 } 339 }); 340}); 341 342document.addEventListener('DOMContentLoaded', function() { 343 const parentContainer = document.querySelector('.blogFilter-taxonomy'); 344 if (!parentContainer) return; 345 346 const filterContainer = parentContainer.querySelector('.e-filter'); 347 if (filterContainer) { 348 // Define the SVG arrow to reuse 349 const arrowSvg = '<span class="droparrow"><svg aria-hidden="true" class="fa-svg-chevron-down e-font-icon-svg e-fas-chevron-down" viewB
349ox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"></path></svg></span>'; 350 351 // 1. Add extra DIV before the filter (Heading/Label) 352 const titleDiv = document.createElement('div'); 353 titleDiv.className = 'filter-header-label'; 354 titleDiv.innerHTML = 'Filter By:'; // You can change this text 355 filterContainer.parentNode.insertBefore(titleDiv, filterContainer); 356 357 // 2. Create the Trigger Button 358 const trigger = document.createElement('div'); 359 trigger.className = 'filter-dropdown-trigger'; 360 361 // 3. Logic to set default text (Select 'All' or current active) 362 const updateTriggerText = () => { 363 const activeItem = filterContainer.querySelector('.e-filter-item[aria-pressed="true"]'); 364 const allItem = filterContainer.querySelector('.e-filter-item'); // Grab the first one (All) 365 366 let currentText = "Select Filter"; 367 if (activeItem) { 368 currentText = activeItem.innerText; 369 } else if (allItem) { 370 currentText = allItem.innerText; 371 } 372 373 trigger.innerHTML = currentText + ' ' + arrowSvg; 374 }; 375 376 // Initial Set 377 updateTriggerText(); 378 379 // Insert trigger after the titleDiv but before filter items 380 filterContainer.parentNode.insertBefore(trigger, filterContainer); 381 382 // 4. Toggle visibility on click 383 trigger.addEventListener('click', function() { 384 filterContainer.classList.toggle('is-open'); 385 }); 386 387 // 5. Update text when a button is clicked 388 const filterButtons = filterContainer.querySelectorAll('.e-filter-item'); 389 filterButtons.forEach(button => { 390 button.addEventListener('click', function() { 391 // Short delay to let Elementor process the click/active state 392 setTimeout(() => { 393 updateTriggerText(); 394 filterContainer.classList.remove('is-open'); 395 }, 50); 396 }); 397 }); 398 399 // Close dropdown if user clicks outside 400 window.addEventListener('click', function(e) { 401 if (!parentContainer.contains(e.target)) { 402 filterContainer.classList.remove('is-open'); 403 } 404 }); 405 } 406}); 407 408// document.addEventListener('DOMContentLoaded', function() { 409// // Select the parent container first 410// const parentContainer = document.querySelector('.blogFilter-taxonomy'); 411 412// // If the parent doesn't exist on this page, exit the script 413// if (!parentContainer) return; 414 415// // Select the filter element within that specific parent 416// const filterContainer = parentContainer.querySelector('.e-filter'); 417 418// if (filterContainer) { 419// // Create the Trigger Button 420// const trigger = document.createElement('div'); 421// trigger.className = 'filter-dropdown-trigger'; 422// trigger.innerHTML = 'Select Filter <span class="droparrow"><svg aria-hidden="true" class="fa-svg-chevron-down e-font-icon-svg e-fas-chevron-down" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"></path></svg></span>'; 423 424// // Insert trigger inside the parent, but before the filter items 425// filterContainer.parentNode.insertBefore(trigger, filterContainer); 426 427// // Toggle visibility on click 428// trigger.addEventListener('click', function() { 429// filterContainer.classList.toggle('is-open'); 430// }); 431 432// // Close dropdown and update text when an item is selected 433// const filterButtons = filterContainer.querySelectorAll('.e-filter-item'); 434// filterButtons.forEach(button => { 435// button.addEventListener('click', function() { 436// // Update the trigger label to show the active filter 437// trigger.innerHTML = this.innerText + ' <span class="droparrow"><svg aria-hidden="true" class="fa-svg-chevron-down e-font-icon-svg e-fas-chevron-down" viewB
437ox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"></path></svg></span>'; 438// filterContainer.classList.remove('is-open'); 439// }); 440// }); 441 442// // Optional: Close dropdown if user clicks outside of the widget 443// window.addEventListener('click', function(e) { 444// if (!parentContainer.contains(e.target)) { 445// filterContainer.classList.remove('is-open'); 446// } 447// }); 448// } 449// }); 450 451 452document.addEventListener('DOMContentLoaded', function() { 453 // Target the specific video section 454 const videoWrapper = document.querySelector('.video-section'); 455 if (!videoWrapper) return; 456 457 const video = videoWrapper.querySelector('video'); 458 459 // The HTML structure you want to re-append 460 const overlayHTML = ` 461 <div class="elementor-custom-embed-image-overlay" style="background-image: url(https://blackhillsballoons1.devtest.center/wp-content/uploads/2026/02/experience-video.webp);"> 462 <div class="elementor-custom-embed-play" role="button" aria-label="Play Video" tabindex="0"> 463 <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" width="200" height="200" viewBox="0 0 200 200"> 464 <circle cx="100" cy="100" r="95.71" style="opacity: .5;"></circle> 465 <path d="M100,199.71C45.02,199.71.29,154.98.29,100S45.02.29,100,.29s99.71,44.73,99.71,99.71-44.73,99.71-99.71,99.71ZM100,8.29C49.43,8.29,8.29,49.43,8.29,100s41.14,91.71,91.71,91.71,91.71-41.14,91.71-91.71S150.57,8.29,100,8.29ZM67.81,56.9v85.92c0,3.39,3.67,5.5,6.6,3.81l74.41-42.96c2.93-1.69,2.93-5.93,0-7.62l-74.41-42.96c-2.93-1.69-6.6.42-6.6,3.81Z" style="fill: #fff;"></path> 466 </svg> 467 </div> 468 </div>`; 469 470 // Function to append the overlay 471 const showOverlay = () => { 472 // Check if it already exists to prevent duplicates 473 if (!videoWrapper.querySelector('.elementor-custom-embed-image-overlay')) { 474 video.insertAdjacentHTML('afterend', overlayHTML); 475 476 // Re-attach click event to the new overlay so clicking it plays the video again 477 const newOverlay = videoWrapper.querySelector('.elementor-custom-embed-image-overlay'); 478 newOverlay.addEventListener('click', function() { 479 video.play(); 480 newOverlay.remove(); // Remove it immediately when play is clicked 481 }); 482 } 483 }; 484 485 if (video) { 486 // When video is paused 487 video.addEventListener('pause', function() { 488 showOverlay(); 489 }); 490 491 // When video ends 492 video.addEventListener('ended', function() { 493 showOverlay(); 494 }); 495 496 // Remove overlay if video starts playing via other controls 497 video.addEventListener('play', function() { 498 const overlay = videoWrapper.querySelector('.elementor-custom-embed-image-overlay'); 499 if (overlay) overlay.remove(); 500 }); 501 } 502}); 503 504document.addEventListener("DOMContentLoaded", function() { 505 const targetNode = document.querySelector('.filter-dropdown-trigger'); 506 507 if (targetNode) { 508 // We use a flag to prevent an infinite loop (Observer detects our own changes) 509 let isScriptChanging = false; 510 511 function updateText() { 512 // 1. Get the text node (specifically the first child to avoid the arrow span) 513 let textNode = targetNode.childNodes[0]; 514 515 // Safety check if textNode is missing 516 if (!textNode) return; 517 518 const currentText = textNode.nodeValue; 519 const savedFullText = targetNode.getAttribute('data-full-text'); 520 521 if (!savedFullText || (currentText !== savedFullText && !currentText.endsWith('... '))) { 522 targetNode.setAttribute('data-full-text', currentText.trim()); 523 } 524 525 // 3. Perform Truncation Logic 526 const fullText = targetNode.getAttribute('data-full-text'); 527 528 if (window.innerWidth <= 767 && fullText) { 529 const words = fullText.split(/\s+/); 530 if (words.length > 3) { 531 const truncated = words.slice(0, 3).join(' ') + '... '; 532 533 // Only update if it's not already truncated to avoid loop 534 if (textNode.nodeValue !== truncated) { 535 isScriptChanging = true; // Signal that WE are making this change 536 textNode.nodeValue = truncated; 537 isScriptChanging = false; // Reset signal 538 } 539 } 540 } else if (fullText) { 541 // Desktop view: Restore full text 542 if (textNode.nodeValue.trim() !== fullText) { 543 isScriptChanging = true; 544 textNode.nodeValue = fullText + ' '; 545 isScriptChanging = false;
546 } 547 } 548 } 549 550 const observer = new MutationObserver(function(mutations) { 551 if (isScriptChanging) return; // Ignore changes made by this script 552 updateText(); 553 }); 554 555 // Start watching the element for text changes or child list changes 556 observer.observe(targetNode, { childList: true, characterData: true, subtree: true }); 557 updateText(); 558 // Run on resize 559 window.addEventListener('resize', updateText); 560 } 561});
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.