1/******/ (function() { // webpackBootstrap 2/******/ "use strict"; 3/******/ var __webpack_modules__ = ({ 4 5/***/ 60: 6/***/ (function(module) { 7 8 9;// ./src/js/accordions.js 10const initAccordions = (campFinder = false) => { 11 let toggles; 12 if (campFinder) { 13 toggles = document.querySelectorAll(".camp-finder .accordion-js-toggle"); 14 } else { 15 toggles = document.querySelectorAll(".accordion-js-toggle"); 16 } 17 if (!toggles) { 18 return; 19 } 20 toggles.forEach(togglesItem => { 21 togglesItem.addEventListener("click", () => { 22 const accordion = togglesItem.closest('.accordion-js'); 23 if (togglesItem.dataset.imageSrc && document.querySelector('.tab-scheduler__image').src != togglesItem.dataset.imageSrc) { 24 document.querySelector('.tab-scheduler__image').src = togglesItem.dataset.imageSrc; 25 } 26 if (togglesItem.classList.contains("is-open")) { 27 togglesItem.classList.remove("is-open"); 28 togglesItem.querySelector('.accordion-js-content').classList.remove('is-open'); 29 } else { 30 const togglesOpened = accordion.querySelectorAll(".is-open"); 31 togglesOpened.forEach(toggleOpened => { 32 toggleOpened.classList.remove("is-open"); 33 }); 34 togglesItem.classList.add("is-open"); 35 togglesItem.querySelector('.accordion-js-content').classList.add('is-open'); 36 } 37 }); 38 }); 39}; 40 41;// ./src/js/camp-finder-form-redirect.js 42const initCampFinderFormRedirect = async () => { 43 const campFinderForms = document.querySelectorAll('.camp-finder-form-redirect'); 44 if (campFinderForms.length === 0) { 45 return; 46 } 47 48 // Load the Google Maps JavaScript API 49 (g => { 50 var h, 51 a, 52 k, 53 p = "The Google Maps JavaScript API", 54 c = "google", 55 l = "importLibrary", 56 q = "__ib__", 57 m = document, 58 b = window; 59 b = b[c] || (b[c] = {}); 60 var d = b.maps || (b.maps = {}), 61 r = new Set(), 62 e = new URLSearchParams(), 63 u = () => h || (h = new Promise(async (f, n) => { 64 await (a = m.createElement("script")); 65 e.set("libraries", [...r] + ""); 66 for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); 67 e.set("callback", c + ".maps." + q); 68 a.src = `https://maps.${c}apis.com/maps/api/js?` + e; 69 d[q] = f; 70 a.onerror = () => h = n(Error(p + " could not load.")); 71 a.nonce = m.querySelector("script[nonce]")?.nonce || ""; 72 m.head.append(a); 73 })); 74 d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)); 75 })({ 76 key: googleMapsApi.key, 77 v: "quarterly", 78 libraries: ["places"] 79 }); 80 const { 81 Autocomplete 82 } = await google.maps.importLibrary("places"); 83 campFinderForms.forEach(async form => { 84 var options = { 85 types: ['(cities)'], 86 componentRestrictions: { 87 country: "us" 88 } 89 }; 90 var autocomplete = new Autocomplete(form.querySelector('input[type="text"]'), options); 91 const handleFormSubmit = async e => { 92 e.preventDefault(); 93 const searchInput = form.querySelector('input[type="text"]'); 94 const submitButton = form.querySelector('button[type="submit"]'); 95 const address = searchInput.value; 96 if (address === '') { 97 return; 98 } 99 let formRedirectUrl = ''; 100 let lat = 0; 101 let lng = 0; 102 let city = ''; 103 let state = ''; 104 const geocoder = new google.maps.Geocoder(); 105 geocoder.geocode({ 106 address: address, 107 componentRestrictions: { 108 country: "us" 109 } 110 }, (results, status) => { 111 if (status === 'OK') { 112 const result = results[0]; 113 lat = result.geometry.location.lat(); 114 lng = result.geometry.location.lng(); 115 city = result.address_components.find(component => component.types.includes('locality')).long_name; 116 state = result.address_components.find(component => component.types.includes('administrative_area_level_1')).short_name; 117 formRedirectUrl = `/camp-finder?lat=${lat}&lng=${lng}&city=${city}&state=${state}`; 118 submitButton.textContent = 'Loading...'; 119 submitButton.disabled = true; 120 window.location.href = formRedirectUrl; 121 } else { 122 console.error('Geocode was not successful for the following reason: ' + status); 123 return; 124 } 125 }); 126 }; 127 form.addEventListener('submit', handleFormSubmit); 128 form.addEventListener('keydown', e => { 129 if (e.key === 'Enter') { 130 handleFormSubmit(e); 131 } 132 }); 133 }); 134}; 135 136;// ./src/js/customForms.js
137const initCustomForms = () => { 138 const partnershipsForm = document.querySelector('.wpforms-form'); 139 if (partnershipsForm === null) { 140 return; 141 } 142 const otherSpecifyInput = partnershipsForm.querySelector('input[name="wpforms[fields][14]"]'); 143 const otherSpecifyInputLabel = partnershipsForm.querySelector('input[name="wpforms[fields][14]"]').closest('.wpforms-field'); 144 otherSpecifyInputLabel.style.display = 'none'; 145 partnershipsForm.querySelectorAll('input[type="checkbox"]').forEach(checkbox => { 146 if (checkbox.value === 'Other') { 147 checkbox.addEventListener('change', () => { 148 if (checkbox.checked) { 149 otherSpecifyInputLabel.style.display = 'block'; 150 otherSpecifyInput.required = true; 151 } else { 152 otherSpecifyInputLabel.style.display = 'none'; 153 otherSpecifyInput.required = false; 154 } 155 }); 156 } 157 }); 158}; 159 160;// ./src/js/dropdowns.js 161const initDropdowns = () => { 162 const toggles = document.querySelectorAll('.dropdown-js-toggle'); 163 const dropdowns = document.querySelectorAll('.dropdown-js'); 164 if (!toggles || !dropdowns) { 165 return; 166 } 167 toggles.forEach(toggle => { 168 toggle.addEventListener('click', e => { 169 e.preventDefault(); 170 toggle.classList.toggle('is-open'); 171 const dropdown = toggle.nextElementSibling; 172 dropdowns.forEach(item => { 173 if (item !== dropdown) { 174 item.classList.remove('is-open'); 175 } 176 }); 177 toggle.nextElementSibling.classList.toggle('is-open'); 178 }); 179 }); 180}; 181 182;// ./src/js/gallery.js 183const initGallery = () => { 184 const thumbs = document.querySelectorAll('.gallery-js-thumb'); 185 if (thumbs.length === 0) { 186 return; 187 } 188 thumbs.forEach(thumb => { 189 thumb.addEventListener('click', e => { 190 const url = thumb.getAttribute('src'); 191 const alt = thumb.getAttribute('alt'); 192 thumb.closest('.gallery-js').querySelector('.gallery-js-image').src = url; 193 thumb.closest('.gallery-js').querySelector('.gallery-js-caption').innerHTML = alt; 194 thumbs.forEach(thumb => { 195 if (thumb == e.target) { 196 thumb.classList.add('active'); 197 } else { 198 thumb.classList.remove('active'); 199 } 200 }); 201 }); 202 }); 203}; 204 205;// ./src/js/image-accordion.js 206const initImageAccordion = () => { 207 if (document.querySelector('.image-accordion-images') === null) { 208 return; 209 } 210 const swiperImage = new Swiper(".image-accordion-images", { 211 spaceBetween: 10, 212 effect: "fade", 213 noSwipping: true 214 }); 215 const swiperText = new Swiper(".image-accordion-thumbs", { 216 spaceBetween: 20, 217 slidesPerView: 'auto', 218 watchSlidesProgress: true, 219 scrollbar: { 220 el: ".image-accordion-thumbs__scrollbar" 221 }, 222 thumbs: { 223 swiper: swiperImage 224 }, 225 slideToClickedSlide: true 226 }); 227}; 228const initImageAccordionToggles = () => { 229 const toggles = document.querySelectorAll('.image-accordion__toggle'); 230 if (toggles.length === 0) { 231 return; 232 } 233 toggles.forEach(toggle => { 234 toggle.addEventListener('change', e => { 235 const scrollbar = e.target.closest('.image-accordion__items').querySelector('.scrollbar'); 236 const imageAccordion = e.target.closest('.image-accordion'); 237 const { 238 id 239 } = e.target.dataset; 240 imageAccordion.querySelectorAll('.image-accordion__image').forEach(image => { 241 if (image.dataset.id == id) { 242 image.dataset.show = true; 243 } else { 244 image.dataset.show = false; 245 } 246 }); 247 scrollbar.style.top = id * 66 + 'px'; 248 }); 249 }); 250}; 251 252;// ./src/js/image-accordion-slider.js 253const initImageAccordionSlider = () => { 254 const swiperButtons = new Swiper(".accordion-slider-buttons", { 255 spaceBetween: 10, 256 slidesPerView: 'auto', 257 freeMode: true, 258 watchSlidesProgress: true 259 }); 260 const swiperTabs = new Swiper(".accordion-slider-tabs", { 261 spaceBetween: 10, 262 slidesPerView: 1, 263 autoHeight: true, 264 effect: 'fade', 265 thumbs: { 266 swiper: swiperButtons 267 }, 268 breakpoints: { 269 1024: { 270 pagination: { 271 el: '.accordion-slider-tabs__pagination' 272 }, 273 navigation: { 274 nextEl: '.accordion-slider-tabs__button-next', 275 prevEl: '.accordion-slider-tabs__button-prev' 276 } 277 } 278 } 279 }); 280 const buttons = document.querySelectorAll(".accordion-slider-buttons .swiper-slide"); 281 buttons.forEach((button, index) => { 282 button.addEventListener('click', () => { 283 swiperTabs.slideTo(index, 500); 284 swiperButtons.slideTo(index, 500); 285 }); 286 }); 287}; 288const initImageAccordionSliderToggles = () => { 289 const toggles = document.querySelectorAll('.accordion-slider__toggle'); 290 if (toggles.length === 0) { 291 return; 292 }
293 toggles.forEach(toggle => { 294 toggle.addEventListener('change', e => { 295 const scrollbar = e.target.closest('.accordion-slider__items').querySelector('.scrollbar'); 296 const imageAccordion = e.target.closest('.accordion-slider'); 297 const { 298 id 299 } = e.target.dataset; 300 imageAccordion.querySelectorAll('.accordion-slider__image').forEach(image => { 301 if (image.dataset.id == id) { 302 image.dataset.show = true; 303 } else { 304 image.dataset.show = false; 305 } 306 }); 307 scrollbar.style.top = id * 66 + 'px'; 308 }); 309 }); 310}; 311 312;// ./node_modules/events/events.js 313var events_namespaceObject = /*#__PURE__*/__webpack_require__.cjs(function(module, exports) {
vendor: 14,879 bytes, lines 313-811
313 314// Copyright Joyent, Inc. and other Node contributors. 315// 316// Permission is hereby granted, free of charge, to any person obtaining a 317// copy of this software and associated documentation files (the 318// "Software"), to deal in the Software without restriction, including 319// without limitation the rights to use, copy, modify, merge, publish, 320// distribute, sublicense, and/or sell copies of the Software, and to permit 321// persons to whom the Software is furnished to do so, subject to the 322// following conditions: 323// 324// The above copyright notice and this permission notice shall be included 325// in all copies or substantial portions of the Software. 326// 327// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 328// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 329// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 330// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 331// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 332// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 333// USE OR OTHER DEALINGS IN THE SOFTWARE. 334 335 336 337var R = typeof Reflect === 'object' ? Reflect : null 338var ReflectApply = R && typeof R.apply === 'function' 339 ? R.apply 340 : function ReflectApply(target, receiver, args) { 341 return Function.prototype.apply.call(target, receiver, args); 342 } 343 344var ReflectOwnKeys 345if (R && typeof R.ownKeys === 'function') { 346 ReflectOwnKeys = R.ownKeys 347} else if (Object.getOwnPropertySymbols) { 348 ReflectOwnKeys = function ReflectOwnKeys(target) { 349 return Object.getOwnPropertyNames(target) 350 .concat(Object.getOwnPropertySymbols(target)); 351 }; 352} else { 353 ReflectOwnKeys = function ReflectOwnKeys(target) { 354 return Object.getOwnPropertyNames(target); 355 }; 356} 357 358function ProcessEmitWarning(warning) { 359 if (console && console.warn) console.warn(warning); 360} 361 362var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { 363 return value !== value; 364} 365 366function EventEmitter() { 367 EventEmitter.init.call(this); 368} 369module.exports = EventEmitter; 370module.exports.once = once; 371 372// Backwards-compat with node 0.10.x 373EventEmitter.EventEmitter = EventEmitter; 374 375EventEmitter.prototype._events = undefined; 376EventEmitter.prototype._eventsCount = 0; 377EventEmitter.prototype._maxListeners = undefined; 378 379// By default EventEmitters will print a warning if more than 10 listeners are 380// added to it. This is a useful default which helps finding memory leaks. 381var defaultMaxListeners = 10; 382 383function checkListener(listener) { 384 if (typeof listener !== 'function') { 385 throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); 386 } 387} 388 389Object.defineProperty(EventEmitter, 'defaultMaxListeners', { 390 enumerable: true, 391 get: function() { 392 return defaultMaxListeners; 393 }, 394 set: function(arg) { 395 if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { 396 throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); 397 } 398 defaultMaxListeners = arg; 399 } 400}); 401 402EventEmitter.init = function() { 403 404 if (this._events === undefined || 405 this._events === Object.getPrototypeOf(this)._events) { 406 this._events = Object.create(null); 407 this._eventsCount = 0; 408 } 409 410 this._maxListeners = this._maxListeners || undefined; 411}; 412 413// Obviously not all Emitters should be limited to 10. This function allows 414// that to be increased. Set to zero for unlimited. 415EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { 416 if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { 417 throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); 418 } 419 this._maxListeners = n; 420 return this; 421}; 422 423function _getMaxListeners(that) { 424 if (that._maxListeners === undefined) 425 return EventEmitter.defaultMaxListeners; 426 return that._maxListeners; 427} 428 429EventEmitter.prototype.getMaxListeners = function getMaxListeners() { 430 return _getMaxListeners(this); 431}; 432 433EventEmitter.prototype.emit = function emit(type) { 434 var args = []; 435 for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); 436 var doError = (type === 'error'); 437 438 var events = this._events; 439 if (events !== undefined) 440 doError = (doError && events.error === undefined); 441 else if (!doError) 442 return false; 443 444 // If there is no 'error' event listener then throw. 445 if (doError) { 446 var er; 447 if (args.length > 0) 448 er = args[0]; 449 if (er instanceof Error) { 450 // Note: The comments on the `throw` lines are intentional, they show 451 // up in Node's output if this results in an unhandled exception. 452 throw er; // Unhandled 'error' event 453 } 454 // At least give some kind of context to the user 455 var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); 456 err.context = er; 457 throw err; // Unhandled 'error' event 458 } 459 460 var handler = events[type]; 461 462 if (handler === undefined) 463 return false; 464 465 if (typeof handler === 'function') { 466 ReflectApply(handler, this, args); 467 } else { 468 var len = handler.length; 469 var listeners = arrayClone(handler, len); 470 for (var i = 0; i < len; ++i) 471 ReflectApply(listeners[i], this, args); 472 } 473 474 return true; 475}; 476 477function _addListener(target, type, listener, prepend) { 478 var m; 479 var events; 480 var existing; 481 482 checkListener(listener); 483 484 events = target._events; 485 if (events === undefined) { 486 events = target._events = Object.create(null); 487 target._eventsCount = 0; 488 } else { 489 // To avoid recursion in the case that type === "newListener"! Before 490 // adding it to the listeners, first emit "newListener". 491 if (events.newListener !== undefined) { 492 target.emit('newListener', type, 493 listener.listener ? listener.listener : listener); 494 495 // Re-assign `events` because a newListener handler could have caused the 496 // this._events to be assigned to a new object 497 events = target._events; 498 } 499 existing = events[type]; 500 } 501 502 if (existing === undefined) { 503 // Optimize the case of one listener. Don't need the extra array object. 504 existing = events[type] = listener; 505 ++target._eventsCount; 506 } else { 507 if (typeof existing === 'function') { 508 // Adding the second element, need to change to array. 509 existing = events[type] = 510 prepend ? [listener, existing] : [existing, listener]; 511 // If we've already got an array, just append. 512 } else if (prepend) { 513 existing.unshift(listener); 514 } else { 515 existing.push(listener); 516 } 517 518 // Check for listener leak 519 m = _getMaxListeners(target); 520 if (m > 0 && existing.length > m && !existing.warned) { 521 existing.warned = true; 522 // No error code for this since it is a Warning 523 // eslint-disable-next-line no-restricted-syntax 524 var w = new Error('Possible EventEmitter memory leak detected. ' + 525 existing.length + ' ' + String(type) + ' listeners ' + 526 'added. Use emitter.setMaxListeners() to ' + 527 'increase limit'); 528 w.name = 'MaxListenersExceededWarning'; 529 w.emitter = target; 530 w.type = type; 531 w.count = existing.length; 532 ProcessEmitWarning(w); 533 } 534 } 535 536 return target; 537} 538 539EventEmitter.prototype.addListener = function addListener(type, listener) { 540 return _addListener(this, type, listener, false); 541}; 542 543EventEmitter.prototype.on = EventEmitter.prototype.addListener; 544 545EventEmitter.prototype.prependListener = 546 function prependListener(type, listener) { 547 return _addListener(this, type, listener, true); 548 }; 549 550function onceWrapper() { 551 if (!this.fired) { 552 this.target.removeListener(this.type, this.wrapFn); 553 this.fired = true; 554 if (arguments.length === 0) 555 return this.listener.call(this.target); 556 return this.listener.apply(this.target, arguments); 557 } 558} 559 560function _onceWrap(target, type, listener) { 561 var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; 562 var wrapped = onceWrapper.bind(state); 563 wrapped.listener = listener; 564 state.wrapFn = wrapped; 565 return wrapped; 566} 567 568EventEmitter.prototype.once = function once(type, listener) { 569 checkListener(listener); 570 this.on(type, _onceWrap(this, type, listener)); 571 return this; 572}; 573 574EventEmitter.prototype.prependOnceListener = 575 function prependOnceListener(type, listener) { 576 checkListener(listener); 577 this.prependListener(type, _onceWrap(this, type, listener)); 578 return this; 579 }; 580 581// Emits a 'removeListener' event if and only if the listener was removed. 582EventEmitter.prototype.removeListener = 583 function removeListener(type, listener) { 584 var list, events, position, i, originalListener; 585 586 checkListener(listener); 587 588 events = this._events; 589 if (events === undefined) 590 return this; 591 592 list = events[type]; 593 if (list === undefined) 594 return this; 595 596 if (list === listener || list.listener === listener) { 597 if (--this._eventsCount === 0) 598 this._events = Object.create(null); 599 else { 600 delete events[type]; 601 if (events.removeListener) 602 this.emit('removeListener', type, list.listener || listener); 603 } 604 } else if (typeof list !== 'function') { 605 position = -1; 606 607 for (i = list.length - 1; i >= 0; i--) { 608 if (list[i] === listener || list[i].listener === listener) { 609 originalListener = list[i].listener; 610 position = i; 611 break; 612 } 613 } 614 615 if (position < 0) 616 return this; 617 618 if (position === 0) 619 list.shift(); 620 else { 621 spliceOne(list, position); 622 } 623 624 if (list.length === 1) 625 events[type] = list[0]; 626 627 if (events.removeListener !== undefined) 628 this.emit('removeListener', type, originalListener || listener); 629 } 630 631 return this; 632 }; 633 634EventEmitter.prototype.off = EventEmitter.prototype.removeListener; 635 636EventEmitter.prototype.removeAllListeners = 637 function removeAllListeners(type) { 638 var listeners, events, i; 639 640 events = this._events; 641 if (events === undefined) 642 return this; 643 644 // not listening for removeListener, no need to emit 645 if (events.removeListener === undefined) { 646 if (arguments.length === 0) { 647 this._events = Object.create(null); 648 this._eventsCount = 0; 649 } else if (events[type] !== undefined) { 650 if (--this._eventsCount === 0) 651 this._events = Object.create(null); 652 else 653 delete events[type]; 654 } 655 return this; 656 } 657 658 // emit removeListener for all listeners on all events 659 if (arguments.length === 0) { 660 var keys = Object.keys(events); 661 var key; 662 for (i = 0; i < keys.length; ++i) { 663 key = keys[i]; 664 if (key === 'removeListener') continue; 665 this.removeAllListeners(key); 666 } 667 this.removeAllListeners('removeListener'); 668 this._events = Object.create(null); 669 this._eventsCount = 0; 670 return this; 671 } 672 673 listeners = events[type]; 674 675 if (typeof listeners === 'function') { 676 this.removeListener(type, listeners); 677 } else if (listeners !== undefined) { 678 // LIFO order 679 for (i = listeners.length - 1; i >= 0; i--) { 680 this.removeListener(type, listeners[i]); 681 } 682 } 683 684 return this; 685 }; 686 687function _listeners(target, type, unwrap) { 688 var events = target._events; 689 690 if (events === undefined) 691 return []; 692 693 var evlistener = events[type]; 694 if (evlistener === undefined) 695 return []; 696 697 if (typeof evlistener === 'function') 698 return unwrap ? [evlistener.listener || evlistener] : [evlistener]; 699 700 return unwrap ? 701 unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); 702} 703 704EventEmitter.prototype.listeners = function listeners(type) { 705 return _listeners(this, type, true); 706}; 707 708EventEmitter.prototype.rawListeners = function rawListeners(type) { 709 return _listeners(this, type, false); 710}; 711 712EventEmitter.listenerCount = function(emitter, type) { 713 if (typeof emitter.listenerCount === 'function') { 714 return emitter.listenerCount(type); 715 } else { 716 return listenerCount.call(emitter, type); 717 } 718}; 719 720EventEmitter.prototype.listenerCount = listenerCount; 721function listenerCount(type) { 722 var events = this._events; 723 724 if (events !== undefined) { 725 var evlistener = events[type]; 726 727 if (typeof evlistener === 'function') { 728 return 1; 729 } else if (evlistener !== undefined) { 730 return evlistener.length; 731 } 732 } 733 734 return 0; 735} 736 737EventEmitter.prototype.eventNames = function eventNames() { 738 return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; 739}; 740 741function arrayClone(arr, n) { 742 var copy = new Array(n); 743 for (var i = 0; i < n; ++i) 744 copy[i] = arr[i]; 745 return copy; 746} 747 748function spliceOne(list, index) { 749 for (; index + 1 < list.length; index++) 750 list[index] = list[index + 1]; 751 list.pop(); 752} 753 754function unwrapListeners(arr) { 755 var ret = new Array(arr.length); 756 for (var i = 0; i < ret.length; ++i) { 757 ret[i] = arr[i].listener || arr[i]; 758 } 759 return ret; 760} 761 762function once(emitter, name) { 763 return new Promise(function (resolve, reject) { 764 function errorListener(err) { 765 emitter.removeListener(name, resolver); 766 reject(err); 767 } 768 769 function resolver() { 770 if (typeof emitter.removeListener === 'function') { 771 emitter.removeListener('error', errorListener); 772 } 773 resolve([].slice.call(arguments)); 774 }; 775 776 eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); 777 if (name !== 'error') { 778 addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); 779 } 780 }); 781} 782 783function addErrorHandlerIfEventEmitter(emitter, handler, flags) { 784 if (typeof emitter.on === 'function') { 785 eventTargetAgnosticAddListener(emitter, 'error', handler, flags); 786 } 787} 788 789function eventTargetAgnosticAddListener(emitter, name, listener, flags) { 790 if (typeof emitter.on === 'function') { 791 if (flags.once) { 792 emitter.once(name, listener); 793 } else { 794 emitter.on(name, listener); 795 } 796 } else if (typeof emitter.addEventListener === 'function') { 797 // EventTarget does not have `error` event semantics like Node 798 // EventEmitters, we do not listen for `error` events here. 799 emitter.addEventListener(name, function wrapListener(arg) { 800 // IE does not have builtin `{ once: true }` support so we 801 // have to do it manually. 802 if (flags.once) { 803 emitter.removeEventListener(name, wrapListener); 804 } 805 listener(arg); 806 }); 807 } else { 808 throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); 809 } 810} 811
812}); 813 814;// ./src/js/worldSvg.js 815const worldSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="25px" height="25px" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="M8 4V6C8 7.10457 8.89543 8 10 8H11C12.1046 8 13 8.89543 13 10V10C13 11.1046 13.8954 12 15 12V12C16.1046 12 17 11.1046 17 10V10C17 8.89543 17.8954 8 19 8H20M20 16H17C15.8954 16 15 16.8954 15 18V20M11 20V18C11 16.8954 10.1046 16 9 16V16C7.89543 16 7 15.1046 7 14V14C7 12.8954 6.10457 12 5 12H3" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg>`; 816/* harmony default export */ var worldSvg = (worldSVG); 817;// ./src/js/camp-finder.js 818let allMarkers = []; 819 820 821 822const eventEmitter = new events_namespaceObject.EventEmitter(); 823const slugify = str => { 824 return str.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, ""); 825}; 826const getNearestCamps = async (position, campFinderForm) => { 827 let isRegionalPage = document.querySelector('.camp-finder--regional'); 828 var formData = new FormData(); 829 formData.append('action', 'camp_finder'); // Action name camp_finder AJAX handler 830 831 if (campFinderForm) { 832 let requestedRadius = campFinderForm.querySelector('#radius').value; 833 formData.append('requested_radius', requestedRadius); 834 } 835 if (position === 'getAllLocations' && !isRegionalPage) { 836 formData.append('requested_location', 'getAllLocations'); 837 } else if (isRegionalPage) { 838 formData.append('regional_page_id', isRegionalPage.dataset.regionalPageId); 839 formData.append('is_regional', true); 840 } else { 841 const cityComponent = position.address_components.find(component => component.types.includes('administrative_area_level_2')); 842 const stateComponent = position.address_components.find(component => component.types.includes('administrative_area_level_1')); 843 let lat; 844 let lng; 845 lat = typeof position.geometry.location.lat === 'function' ? position.geometry.location.lat() : position.geometry.location.lat; 846 lng = typeof position.geometry.location.lng === 'function' ? position.geometry.location.lng() : position.geometry.location.lng; 847 formData.append('requested_location', JSON.stringify({ 848 lat: lat, 849 lng: lng, 850 city: cityComponent ? cityComponent.long_name : '', 851 state: stateComponent ? stateComponent.short_name : '' 852 })); 853 } 854 try { 855 const response = await fetch('/wp-admin/admin-ajax.php', { 856 method: 'POST', 857 body: formData 858 }); 859 if (!response.ok) { 860 throw new Error('Network response was not ok ' + response.statusText); 861 } 862 const data = await response.json(); 863 return data; 864 } catch (error) { 865 console.error('There has been a problem with your fetch operation:', error); 866 throw error; 867 } 868}; 869const geoCoderLocate = (loc, withoutCountry = false) => { 870 return new Promise((resolve, reject) => { 871 const geocoder = new google.maps.Geocoder(); 872 geocoder.geocode({ 873 'address': loc, 874 'componentRestrictions': withoutCountry ? {} : { 875 country: "us" 876 } 877 }, function (res, status) { 878 if (status === 'OK') { 879 resolve(res[0]); 880 } else if (status === 'ZERO_RESULTS') { 881 reject('Location not found'); 882 } else { 883 reject('Geocoding failed due to: ' + status); 884 } 885 }); 886 }); 887};
888const initCampFinder = async map => { 889 const campFinderForm = document.getElementById('camp-finder-js-form'); 890 if (!campFinderForm) { 891 return; 892 } 893 894 // Show the submit button on mobile and update order 895 if (window.innerWidth < 768) { 896 const submitButton = campFinderForm.querySelector('button[type="submit"]'); 897 submitButton.parentElement.appendChild(submitButton); 898 submitButton.style.display = 'block'; 899 } 900 campFinderForm.addEventListener('submit', async e => { 901 e.preventDefault(); 902 const searchInput = campFinderForm.querySelector('#search-map'); 903 if (searchInput.value === '') { 904 return; 905 } 906 907 // Disable the submit button and change the text to loading 908 const submitButton = campFinderForm.querySelector('button[type="submit"]'); 909 const originalButtonText = submitButton.textContent; 910 submitButton.textContent = 'Loading...'; 911 submitButton.disabled = true; 912 allMarkers.forEach(marker => marker.setMap(null)); 913 allMarkers = []; 914 var location = document.getElementById('search-map'); 915 var loc = location.value; 916 var geocoderRequestedLocation = await geoCoderLocate(loc); 917 let notFound = false; 918 let position = false; 919 let data = await getNearestCamps(geocoderRequestedLocation, campFinderForm); 920 if (data.length === 0) { 921 data = await getNearestCamps('getAllLocations'); 922 notFound = true; 923 position = geocoderRequestedLocation; 924 } 925 926 //const sortedData = data.sort((a, b) => a.Location.localeCompare(b.Location)); 927 928 populateMap(map, data); 929 populateCards(data, map, notFound, position); 930 931 // Restore the button after the operation is complete 932 submitButton.textContent = originalButtonText; 933 submitButton.disabled = false; 934 935 //console.log('Camp Finder Data:', data); 936 }); 937}; 938const getRegionCards = async (data, map, cardContainer) => { 939 let regionCardsArray = []; 940 941 // Create an array of promises for all the async operations 942 const promises = data.map(async location => { 943 let regionCard; 944 945 //let region = await geoCoderLocate(location.Address.City); 946 //let region = location.Address.State; 947 948 //const stateComponent = region.address_components.find(component => 949 // component.types.includes('administrative_area_level_1') 950 //); 951 952 const regionName = location.Region; 953 const regionIdName = regionName.toLowerCase().replace(/\s+/g, '-'); 954 ; 955 let idExists = regionCardsArray.some(card => card.id === `region-card-${regionIdName}`); 956 if (regionName && !idExists) { 957 regionCard = document.createElement('div'); 958 regionCard.id = `region-card-${regionIdName}`; 959 regionCard.className = 'camp-finder__state accordion-js-toggle'; 960 regionCard.innerHTML = ` 961 <h4 class="camp-finder__state-title"> 962 ${regionName} 963 <img src="/wp-content/themes/galileo-wp-theme/img/icon-chevron-down.svg"> 964 </h4> 965 `; 966 regionCardsArray.push(regionCard); 967 } 968 //else { 969 // regionCard = document.getElementById(`region-card-${regionShortName}`); 970 //} 971 }); 972 973 // Wait for all async operations to complete 974 await Promise.all(promises); 975 const sortedRegionCards = regionCardsArray.sort((a, b) => a.textContent.localeCompare(b.textContent)); 976 sortedRegionCards.forEach(regionCard => { 977 let listRegion = document.createElement('ul'); 978 listRegion.className = 'camp-finder__state-list accordion-js-content'; 979 cardContainer.appendChild(regionCard); 980 regionCard.appendChild(listRegion); 981 }); 982}; 983const locationCardHTML = location => { 984 return ` 985 <li class="location-card"> 986 <div class="location-card__top"> 987 <div class="location-card__info"> 988 <h2 class="location-card__title">${location.Location}</h2> 989 <p class="location-card__school"> 990 ${location.CampSite} 991 <span class="location-card__place"> 992 ${location.Address.Street ? `${location.Address.Street}, ` : ''} ${location.Address.City ? `${location.Address.City}, ` : ''} ${location.Address.State ? `${location.Address.State}, ` : ''} ${location.Address.Zip ? `${location.Address.Zip}` : ''} 993 </span>
994 ${location.Miles ? `<span class="location-card__miles">${location.Miles} miles away</span>` : ''} 995 </p> 996 </div> 997 </div> 998 <div class="location-card__bottom"> 999 <a href="${location.link}" class="location-card__link"> 1000 <div> 1001 ${worldSvg} 1002 </div> 1003 Camp Information 1004 </a> 1005 </div> 1006 </li> 1007 `; 1008}; 1009const getLocationCards = (data, map, cardContainer) => { 1010 const sortedData = data.sort((a, b) => parseFloat(a.Miles) - parseFloat(b.Miles)); 1011 sortedData.forEach(location => { 1012 const card = document.createElement('div'); 1013 card.className = "view-on-map"; 1014 card.innerHTML = locationCardHTML(location); 1015 1016 // Add click event listener to the "View on Map" button 1017 card.addEventListener('click', e => { 1018 if (e.target.classList.contains('location-card__link')) return; 1019 window.location.href = `${location.link}`; 1020 1021 // This functionality opens the location withing the map and add a more visible card | commented by clients request to instantly redirect to the location page 1022 //card.classList.add('active'); 1023 //viewOnMap(new google.maps.LatLng(location.Address.Latitude, location.Address.Longitude), map, e, location); 1024 //document.querySelectorAll('.view-on-map.active').forEach((card) => { 1025 // if(card !== e.currentTarget){ 1026 // card.classList.remove('active'); 1027 // } 1028 //}); 1029 }); 1030 cardContainer.appendChild(card); 1031 }); 1032}; 1033const populateCards = async (data, map, notFound = false, position = false, onlyRegion = false) => { 1034 const noResults = document.querySelector('#camp-finder-js-noresults'); 1035 const cardContainer = document.querySelector('.camp-finder-js-cards'); 1036 // Clear existing cards 1037 cardContainer.innerHTML = ''; 1038 let requestedLocation; 1039 if (position && position.city) { 1040 requestedLocation = `â${position.city}â`; 1041 } else if (position && position.address_components) { 1042 const cityComponent = position.address_components.find(component => component.types.includes('locality')); 1043 if (cityComponent) { 1044 requestedLocation = `${cityComponent.long_name}`; 1045 } else { 1046 requestedLocation = `${position.address_components[0].long_name}`; 1047 } 1048 } else { 1049 requestedLocation = 'your location'; 1050 } 1051 if (notFound) {
1052 let card; 1053 const noResultsContainer = document.querySelector('#camp-finder-js-noresults'); 1054 const noResultsCard = document.querySelector('.camp-finder__noresults'); 1055 const servingArea = document.createElement('div'); 1056 const noResultsLocationCard = document.querySelector('#camp-finder-js-noresults > .view-on-map') ?? false; 1057 noResults.classList.remove('hidden'); 1058 if (noResultsCard) { 1059 card = noResultsCard; 1060 if (onlyRegion === true && !card.classList.contains('hidden')) { 1061 card.classList.add('hidden'); 1062 } else { 1063 card.classList.remove('hidden'); 1064 } 1065 } else { 1066 if (noResultsLocationCard) { 1067 noResultsContainer.innerHTML = ''; 1068 } 1069 card = document.createElement('div'); 1070 card.className = 'camp-finder__noresults'; 1071 if (onlyRegion === true && !card.classList.contains('hidden')) { 1072 card.classList.add('hidden'); 1073 } 1074 noResults.appendChild(card); 1075 servingArea.innerHTML = ` 1076 <h3 class="camp-finder__communities-title">We currently serve the following communities</h3> 1077 `; 1078 servingArea.className = 'camp-finder__communities accordion-js'; 1079 noResults.appendChild(servingArea); 1080 await getRegionCards(data, map, servingArea); 1081 const sortedData = data.sort((a, b) => a.Location.localeCompare(b.Location)); 1082 data.forEach(location => { 1083 let locationCard = document.createElement('a'); 1084 let regionCard = document.querySelector(`#region-card-${location.Region.toLowerCase().replace(/\s+/g, '-')} .accordion-js-content`); 1085 if (regionCard) { 1086 locationCard.innerHTML = ` 1087 <li class="view-on-map"> 1088 ${location.Location} <span>Map camp location</span> 1089 </li> 1090 `; 1091 locationCard.querySelector('.view-on-map').addEventListener('click', e => { 1092 e.preventDefault(); 1093 window.scrollTo({ 1094 top: 50, 1095 behavior: 'smooth' 1096 }); 1097 }); 1098 regionCard.appendChild(locationCard); 1099 } 1100 locationCard.querySelector('.view-on-map').addEventListener('click', e => { 1101 window.location.href = `${location.link}`; 1102 //viewOnMap(new google.maps.LatLng(location.Address.Latitude, location.Address.Longitude), map, e, location); 1103 }); 1104 }); 1105 1106 // Now initialize accordions after all cards are added 1107 initAccordions(true); 1108 } 1109 card.innerHTML = ` 1110 <p>We are not yet bringing the magic of Galileo to ${requestedLocation}.</p> 1111 <a class="side-js-button" href="#contact-form">Bring us to your neighboorhood</a> 1112 `; 1113 eventEmitter.emit('campFinderRenderComplete'); 1114 } else { 1115 noResults.classList.add('hidden'); 1116 getLocationCards(data, map, cardContainer); 1117 } 1118}; 1119const viewOnMap = (position, map, e, location) => { 1120 e.preventDefault(); 1121 map.setCenter(position); 1122 map.setZoom(15); 1123 const regionCards = document.querySelectorAll('.camp-finder__state'); 1124 const targetText = e.target.textContent.replace('Map camp location', ''); 1125 const currentActiveLocation = document.querySelector('.camp-finder__state-list .active'); 1126 const noResultsContainer = document.querySelector('#camp-finder-js-noresults'); 1127 const currentActiveLocationCard = document.querySelector('#camp-finder-js-noresults > .view-on-map'); 1128 const noResultsCard = document.querySelector('#camp-finder-js-noresults > .camp-finder__noresults'); 1129 const inputValue = document.querySelector('.camp-finder #search-map'); 1130 const card = document.createElement('div'); 1131 let regionCard, regionCardTitle; 1132 if (e.target.closest('.camp-finder__state')) { 1133 regionCard = e.target.closest('.camp-finder__state'); 1134 regionCardTitle = regionCard.querySelector('.camp-finder__state-title'); 1135 } 1136 card.className = "view-on-map"; 1137 card.innerHTML = locationCardHTML(location); 1138 if (currentActiveLocationCard) { 1139 currentActiveLocationCard.remove(); 1140 } 1141 if (noResultsCard) { 1142 noResultsCard.remove(); 1143 } 1144 if (inputValue) { 1145 inputValue.value = ''; 1146 } 1147 noResultsContainer.prepend(card); 1148 regionCards.forEach(regionCard => { 1149 const span = regionCard.querySelector('.camp-finder__state-title span'); 1150 if (span) { 1151 span.remove(); 1152 } 1153 }); 1154 if (regionCardTitle !== undefined) { 1155 regionCardTitle.innerHTML = regionCardTitle.innerHTML.replace('<img', `<span class="camp-finder__state-title--text">- ${targetText}</span><img`); 1156 } 1157 if (currentActiveLocation) { 1158 currentActiveLocation.classList.remove('active'); 1159 } 1160 e.target.classList.add('active'); 1161 1162 // Find the corresponding marker and open its info window 1163 const marker = allMarkers.find(m => m.getPosition().equals(position)); 1164 if (marker) { 1165 google.maps.event.trigger(marker, 'click'); 1166 } 1167 window.scrollTo({ 1168 top: 50, 1169 behavior: 'smooth' 1170 }); 1171}; 1172const populateMap = async (map, data) => { 1173 // Add markers for each location in the data array 1174 const promises = data.map(async location => { 1175 var position; 1176 const latitude = location.Address.Latitude; 1177 const longitude = location.Address.Longitude; 1178 if (latitude && longitude) { 1179 position = new google.maps.LatLng(latitude, longitude); 1180 } else { 1181 // Geocode the address if latitude and longitude are not available 1182 //const address = `${location.Address.Street}, ${location.Address.City}, ${location.Address.State}`; 1183 //let geocoderRequestedLocation = await geoCoderLocate(address); 1184 //position = geocoderRequestedLocation.geometry.location; 1185 //position = new google.maps.LatLng(address.Latitude, address.Longitude); 1186 } 1187 let marker = new google.maps.Marker({ 1188 position: position, 1189 map: map, 1190 title: location.Name, 1191 icon: { 1192 url: '/wp-content/themes/galileo-wp-theme/img/mapMarkerGalileo.svg', 1193 scaledSize: new google.maps.Size(50, 50), 1194 origin: new google.maps.Point(0, 0), 1195 anchor: new google.maps.Point(25, 50) 1196 } 1197 }); 1198 allMarkers.push(marker); 1199 1200 // Add info window for each marker 1201 const infoWindow = new google.maps.InfoWindow({ 1202 content: ` 1203 <div style="width: 350px; max-width: 100%; height: fit-content;">
1204 <span style="font-size: 18px; font-weight: 800; line-height: 1.4;">${location.Location}</span> 1205 <h3 style="font-size: 20px; font-weight: 600; text-wrap: balance; line-height: 1.2; margin-bottom: 0.7rem;">${location.CampSite}</h3> 1206 <p style=" font-size: 1rem;">${location.Address.Street ? `${location.Address.Street}, ` : ''} ${location.Address.City ? `${location.Address.City}, ` : ''} ${location.Address.State ? `${location.Address.State}, ` : ''} ${location.Address.Zip ? `${location.Address.Zip}` : ''}</p> 1207 <a class="map-content__url" href="${location.link}"> 1208 ${worldSvg} 1209 Camp Information 1210 </a> 1211 </div> 1212 ` 1213 }); 1214 marker.addListener('click', () => { 1215 infoWindow.open(map, marker); 1216 }); 1217 }); 1218 await Promise.all(promises); 1219 let bounds = new google.maps.LatLngBounds(); 1220 allMarkers.forEach(marker => { 1221 bounds.extend(marker.getPosition()); 1222 }); 1223 if (allMarkers.length === 1) { 1224 map.setCenter(allMarkers[0].getPosition()); 1225 map.setZoom(16); 1226 } else { 1227 map.fitBounds(bounds); 1228 } 1229}; 1230const initMap = async () => { 1231 if (window.innerWidth >= 1024) { 1232 const getMap = document.querySelector('.map-js-mobile'); 1233 const desktopMap = document.querySelector('.map-js-desktop'); 1234 if (getMap) { 1235 desktopMap.innerHTML = getMap.innerHTML; 1236 getMap.innerHTML = ''; 1237 } 1238 } 1239 const mapElement = document.getElementById('map'); 1240 if (!mapElement) { 1241 return; 1242 } 1243 1244 // Load the Google Maps JavaScript API 1245 (g => { 1246 var h, 1247 a, 1248 k, 1249 p = "The Google Maps JavaScript API", 1250 c = "google", 1251 l = "importLibrary", 1252 q = "__ib__", 1253 m = document, 1254 b = window; 1255 b = b[c] || (b[c] = {}); 1256 var d = b.maps || (b.maps = {}), 1257 r = new Set(), 1258 e = new URLSearchParams(), 1259 u = () => h || (h = new Promise(async (f, n) => { 1260 await (a = m.createElement("script")); 1261 e.set("libraries", [...r] + ""); 1262 for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); 1263 e.set("callback", c + ".maps." + q); 1264 a.src = `https://maps.${c}apis.com/maps/api/js?` + e; 1265 d[q] = f; 1266 a.onerror = () => h = n(Error(p + " could not load.")); 1267 a.nonce = m.querySelector("script[nonce]")?.nonce || ""; 1268 m.head.append(a); 1269 })); 1270 d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)); 1271 })({ 1272 key: googleMapsApi.key, 1273 v: "quarterly", 1274 libraries: ["places"] 1275 }); 1276 1277 // Load the necessary libraries 1278 const { 1279 Map 1280 } = await google.maps.importLibrary("maps"); 1281 const { 1282 StyledMapType 1283 } = await google.maps.importLibrary("maps"); 1284 const { 1285 Autocomplete 1286 } = await google.maps.importLibrary("places"); 1287 //const { Marker } = await google.maps.importLibrary("marker"); 1288 1289 var map; 1290 var options = { 1291 types: ['(cities)'], 1292 componentRestrictions: { 1293 country: "us" 1294 } 1295 }; 1296 var input = document.getElementById('search-map'); 1297 var autocomplete = new Autocomplete(input, options); 1298 var styledMapType = new StyledMapType([{ 1299 "featureType": "administrative", 1300 "elementType": "labels.text.fill", 1301 "stylers": [{ 1302 "color": "#444444" 1303 }] 1304 }, { 1305 "featureType": "landscape", 1306 "elementType": "all", 1307 "stylers": [{ 1308 "color": "#f2f2f2" 1309 }] 1310 }, { 1311 "featureType": "landscape", 1312 "elementType": "labels.text", 1313 "stylers": [{ 1314 "visibility": "on" 1315 }, { 1316 "hue": "#ff0000" 1317 }] 1318 }, { 1319 "featureType": "poi", 1320 "elementType": "all", 1321 "stylers": [{ 1322 "visibility": "off" 1323 }] 1324 }, { 1325 "featureType": "road", 1326 "elementType": "all", 1327 "stylers": [{ 1328 "saturation": -100 1329 }, { 1330 "lightness": 45 1331 }] 1332 }, { 1333 "featureType": "road.highway", 1334 "elementType": "all", 1335 "stylers": [{ 1336 "visibility": "simplified" 1337 }] 1338 }, { 1339 "featureType": "road.arterial", 1340 "elementType": "labels.icon", 1341 "stylers": [{ 1342 "visibility": "off" 1343 }] 1344 }, { 1345 "featureType": "transit", 1346 "elementType": "all", 1347 "stylers": [{ 1348 "visibility": "off" 1349 }] 1350 }, { 1351 "featureType": "water", 1352 "elementType": "all", 1353 "stylers": [{ 1354 "color": "#1D96CA" 1355 }, {
1356 "visibility": "on" 1357 }] 1358 }], { 1359 name: 'Styled Map' 1360 }); 1361 map = new Map(mapElement, { 1362 center: { 1363 lat: 40.7128, 1364 lng: -74.0060 1365 }, 1366 zoom: 4, 1367 disableDefaultUI: true, 1368 mapTypeControlOptions: { 1369 mapTypeIds: ['roadmap', 'satellite', 'hybrid', 'terrain', 'styled_map'] 1370 } 1371 }); 1372 map.setOptions({ 1373 zoomControl: true, 1374 zoomControlOptions: { 1375 position: google.maps.ControlPosition.BOTTOM_LEFT 1376 } 1377 }); 1378 map.mapTypes.set('styled_map', styledMapType); 1379 map.setMapTypeId('styled_map'); 1380 if (mapElement.className.includes('single-map')) { 1381 const position = new google.maps.LatLng(mapElement.dataset.latitude, mapElement.dataset.longitude); 1382 let marker = new google.maps.Marker({ 1383 position: position, 1384 map: map, 1385 title: location.Name, 1386 icon: { 1387 url: '/wp-content/themes/galileo-wp-theme/img/mapMarkerGalileo.svg', 1388 scaledSize: new google.maps.Size(50, 50), 1389 origin: new google.maps.Point(0, 0), 1390 anchor: new google.maps.Point(25, 50) 1391 } 1392 }); 1393 allMarkers.push(marker); 1394 map.setCenter(position); 1395 map.setZoom(16); 1396 return; 1397 } 1398 let region = new URLSearchParams(window.location.search).get('region'); 1399 //get params from url 1400 const urlParams = new URLSearchParams(window.location.search); 1401 const lat = parseFloat(urlParams.get('lat')); 1402 const lng = parseFloat(urlParams.get('lng')); 1403 let city = urlParams.get('city'); 1404 let state = urlParams.get('state'); 1405 let isRegionalPage = document.querySelector('.camp-finder--regional'); 1406 if (region) { 1407 region = region.replace(/[^\w\s-]/g, '-'); // Sanitize the region 1408 1409 //let regionPosition = await geoCoderLocate(region); 1410 1411 let regionPositionName = region.toLowerCase().replace(/\s+/g, '-'); 1412 const data = await getNearestCamps('getAllLocations'); 1413 if (data.length > 0) { 1414 let count = 0; 1415 const sortedData = data.sort((a, b) => a.Location.localeCompare(b.Location)); 1416 data.forEach(location => { 1417 if (location.Region.toLowerCase().replace(/\s+/g, '-') === regionPositionName) { 1418 populateMap(map, [location]); 1419 getLocationCards([location], map, document.querySelector('.camp-finder-js-cards')); 1420 count++; 1421 } 1422 }); 1423 if (count === 0) { 1424 populateMap(map, data); 1425 populateCards(data, map, true, regionPositionName); 1426 } 1427 } 1428 1429 //map.setCenter(regionPosition.geometry.location); 1430 //map.setZoom(7); 1431 } else if (lat && lng && city && state && urlParams.size > 0) { 1432 // Validate latitude and longitude 1433 if (isNaN(lat) || lat < -90 || lat > 90) { 1434 //console.error('Invalid latitude value:', lat); 1435 return; // Handle invalid latitude 1436 } 1437 if (isNaN(lng) || lng < -180 || lng > 180) { 1438 //console.error('Invalid longitude value:', lng); 1439 return; // Handle invalid longitude 1440 } 1441 city = city.trim().replace(/[^\w\s]/g, ''); 1442 state = state.trim().replace(/[^\w\s]/g, ''); 1443 let notFound = false; 1444 allMarkers.forEach(marker => marker.setMap(null)); 1445 allMarkers = []; 1446 const geocoderResult = { 1447 geometry: { 1448 location: { 1449 lat: lat, 1450 lng: lng 1451 } 1452 }, 1453 address_components: [{ 1454 long_name: city, 1455 types: ['administrative_area_level_2'] 1456 }, { 1457 short_name: state, 1458 types: ['administrative_area_level_1'] 1459 }] 1460 }; 1461 let data = await getNearestCamps(geocoderResult); 1462 if (data.length === 0) { 1463 data = await getNearestCamps('getAllLocations'); 1464 notFound = true; 1465 } 1466 allMarkers.forEach(marker => marker.setMap(null)); 1467 allMarkers = []; 1468 populateMap(map, data); 1469 populateCards(data, map, notFound, geocoderResult); 1470 } else if (isRegionalPage) { 1471 let data = await getNearestCamps('getAllLocations'); 1472 populateMap(map, data); 1473 populateCards(data, map, false); 1474 } else { 1475 // Get user's location 1476 if (navigator.geolocation) { 1477 console.log('Geolocation consent given'); 1478 if (cmplz_has_consent('marketing')) { 1479 navigator.geolocation.getCurrentPosition(async position => { 1480 const userLocation = { 1481 lat: position.coords.latitude, 1482 lng: position.coords.longitude 1483 }; 1484 1485 // Use geocoder to get address details 1486 try { 1487 let geocoderResult; 1488 geocoderResult = await geoCoderLocate(`${userLocation.lat},${userLocation.lng}`, true); 1489 console.log(geocoderResult, 'geocoderresult'); 1490 let data = await getNearestCamps(geocoderResult); 1491 if (data.length > 0) { 1492 populateMap(map, data); 1493 populateCards(data, map); 1494 } else { 1495 data = await getNearestCamps('getAllLocations'); 1496 populateMap(map, data); 1497 populateCards(data, map, true); 1498 } 1499 1500 // disable zoom and center on user location 1501 //map.setCenter(userLocation); 1502 //map.setZoom(8); 1503 } catch (error) { 1504 console.error('Error getting user location details:', error); 1505 } 1506 }, error => { 1507 // If error getting user location, get all locations 1508 const data = getNearestCamps('getAllLocations'); 1509 data.then(data => { 1510 populateMap(map, data); 1511 populateCards(data, map, true, false, true); 1512 }); 1513 console.error('Error getting user location:', error); 1514 }); 1515 } else { 1516 // Remove geolocation if consent is not given 1517 console.error('No consent given for geolocation'); 1518 const data = getNearestCamps('getAllLocations'); 1519 data.then(data => { 1520 populateMap(map, data); 1521 populateCards(data, map, true, false, true); 1522 }); 1523 } 1524 } 1525 } 1526 const campFinderForm = document.getElementById('camp-finder-js-form'); 1527 if (!campFinderForm) { 1528 return; 1529 } 1530 initCampFinder(map); 1531}; 1532 1533;// ./src/js/menu-mobile.js 1534const initMenuMobile = () => { 1535 const btnToggle = document.querySelector('.menu-mobile-js-toggle'); 1536 const menu = document.querySelector('.menu-mobile-js'); 1537 if (btnToggle === null || menu === null) { 1538 return; 1539 } 1540 btnToggle.addEventListener('click', () => { 1541 btnToggle.classList.toggle('is-open'); 1542 menu.classList.toggle('is-open'); 1543 }); 1544}; 1545 1546;// ./src/js/pointers.js 1547const activePointer = (pointers, id) => {
1548 pointers.forEach(pointer => { 1549 if (pointer.dataset.id === id) { 1550 pointer.classList.add('active'); 1551 } else { 1552 pointer.classList.remove('active'); 1553 } 1554 }); 1555}; 1556const initPointers = () => { 1557 const pointers = document.querySelectorAll('.pointer-js'); 1558 if (!pointers) { 1559 return; 1560 } 1561 pointers.forEach(pointer => { 1562 pointer.addEventListener('click', e => { 1563 const { 1564 id 1565 } = pointer.dataset; 1566 activePointer(pointers, id); 1567 }); 1568 }); 1569}; 1570 1571;// ./src/js/search-form.js 1572const initPostSearchForm = () => { 1573 const categories = document.querySelectorAll('[name="category_name"]'); 1574 if (categories.length < 1) { 1575 return; 1576 } 1577 categories.forEach(category => { 1578 category.addEventListener('change', () => { 1579 category.closest('form').submit(); 1580 }); 1581 }); 1582}; 1583 1584;// ./src/js/read-more.js 1585const initReadMore = () => { 1586 const readMoreBtn = document.querySelector('.read-more-btn'); 1587 const hiddenContent = document.querySelector('.image-content-read-more__hidden-content'); 1588 if (!readMoreBtn || !hiddenContent) { 1589 return; 1590 } 1591 readMoreBtn.addEventListener('click', () => { 1592 if (hiddenContent.classList.contains('is-open')) { 1593 let movedReadMoreBtn = document.querySelector('.image-content-read-more__hidden-content .read-more-btn'); 1594 hiddenContent.classList.remove('is-open'); 1595 readMoreBtn.textContent = 'Read More'; 1596 movedReadMoreBtn.closest('.container').querySelector('.image-content-read-more__body').appendChild(movedReadMoreBtn); 1597 } else { 1598 hiddenContent.classList.add('is-open'); 1599 readMoreBtn.textContent = 'Read Less'; 1600 hiddenContent.appendChild(readMoreBtn); 1601 } 1602 }); 1603}; 1604 1605;// ./src/js/sideSlide.js 1606 1607const initSideSlide = () => { 1608 const times = document.querySelectorAll('.side-js-close'); 1609 const overlay = document.querySelector('.camp-slide__overlay'); 1610 if (!overlay) { 1611 return; 1612 } 1613 const buttonsListener = () => { 1614 const buttons = document.querySelectorAll('.side-js-button'); 1615 buttons.forEach(button => { 1616 button.addEventListener('click', e => { 1617 if (!button.getAttribute("href").includes('#')) { 1618 return; 1619 } 1620 e.preventDefault(); 1621 if (button.getAttribute("href") == "") { 1622 return; 1623 } 1624 document.querySelector(button.getAttribute("href")).classList.add('opened'); 1625 overlay.classList.toggle('opened'); 1626 }); 1627 }); 1628 }; 1629 if (document.querySelector('.camp-finder')) { 1630 eventEmitter.on('campFinderRenderComplete', () => { 1631 buttonsListener(); 1632 }); 1633 } else { 1634 buttonsListener(); 1635 } 1636 times.forEach(time => { 1637 time.addEventListener('click', e => { 1638 e.preventDefault(); 1639 time.closest('.side-js').classList.remove('opened'); 1640 overlay.classList.toggle('opened'); 1641 }); 1642 }); 1643 overlay.addEventListener('click', () => { 1644 document.querySelector('.side-js.opened').classList.remove('opened'); 1645 overlay.classList.toggle('opened'); 1646 }); 1647}; 1648 1649;// ./src/js/sliders.js 1650const initSliders = () => { 1651 if (document.querySelector('.testimonials-swiper')) { 1652 const setMessageVars = swiper => { 1653 const slide = swiper.slides[swiper.activeIndex]; 1654 const message = slide ? slide.querySelector('.testimonial__message') : null; 1655 if (!message) return; 1656 const swiperRect = swiper.el.getBoundingClientRect(); 1657 const messageRect = message.getBoundingClientRect(); 1658 swiper.el.style.setProperty('--message-top', `${messageRect.top - swiperRect.top}px`); 1659 swiper.el.style.setProperty('--message-height', `${messageRect.height}px`); 1660 swiper.el.style.setProperty('--message-left', `${messageRect.left - swiperRect.left}px`); 1661 swiper.el.style.setProperty('--message-width', `${messageRect.width}px`); 1662 const wrapper = swiper.el.closest('.testimonials'); 1663 if (wrapper) { 1664 const wrapperRect = wrapper.getBoundingClientRect(); 1665 wrapper.style.setProperty('--message-bottom', `${messageRect.bottom - wrapperRect.top}px`); 1666 wrapper.style.setProperty('--message-center-x', `${messageRect.left + messageRect.width / 2 - wrapperRect.left}px`); 1667 const btn = wrapper.querySelector('.container__button a.btn'); 1668 if (btn) { 1669 const BTN_GAP = 60; 1670 const slideBottom = swiperRect.top - wrapperRect.top + slide.getBoundingClientRect().height; 1671 const btnBottom = messageRect.bottom - wrapperRect.top + BTN_GAP + btn.getBoundingClientRect().height; 1672 wrapper.style.setProperty('--controls-overhang', `${Math.max(0, btnBottom - slideBottom)}px`); 1673 } 1674 } 1675 }; 1676 const testimonialsSlider = new Swiper(".testimonials-swiper", { 1677 slidesPerView: 1, 1678 watchSlidesProgress: true, 1679 autoHeight: true, 1680 effect: 'fade', 1681 longSwipes: false, 1682 pagination: { 1683 clickable: true, 1684 el: '.testimonials-swiper__pagination' 1685 }, 1686 navigation: { 1687 nextEl: '.testimonials-swiper__button-next', 1688 prevEl: '.testimonials-swiper__button-prev' 1689 }, 1690 on: { 1691 afterInit: setMessageVars, 1692 slideChange: setMessageVars, 1693 resize: setMessageVars 1694 } 1695 }); 1696 window.addEventListener('load', () => setMessageVars(testimonialsSlider)); 1697 } 1698 if (document.querySelector('.locations-swiper')) { 1699 const locationsSlider = new Swiper(".locations-swiper", { 1700 slidesPerView: 2, 1701 spaceBetween: 15, 1702 watchSlidesProgress: true, 1703 autoHeight: false, 1704 pagination: { 1705 clickable: true, 1706 el: '.locations-swiper__pagination' 1707 }, 1708 navigation: { 1709 nextEl: '.locations-swiper__button-next', 1710 prevEl: '.locations-swiper__button-prev' 1711 } 1712 }); 1713 }
1714 if (document.querySelector('.social-proof-slider-swiper')) { 1715 console.log('social-proof-slider-swiper'); 1716 const socialProofSlider = new Swiper(".social-proof-slider-swiper", { 1717 slidesPerView: 1, 1718 watchSlidesProgress: true, 1719 loop: true, 1720 pagination: { 1721 el: '.social-proof-slider-swiper__pagination' 1722 }, 1723 navigation: { 1724 nextEl: '.social-proof-slider-swiper__button-next', 1725 prevEl: '.social-proof-slider-swiper__button-prev' 1726 }, 1727 breakpoints: { 1728 1024: { 1729 slidesPerView: 3, 1730 spaceBetween: 30 1731 } 1732 } 1733 }); 1734 } 1735 if (document.querySelector('.values-swiper')) { 1736 const valuesSlider = new Swiper('.values-swiper', { 1737 spaceBetween: 30, 1738 slidesPerView: 'auto', 1739 centeredSlides: true, 1740 pagination: { 1741 el: '.values-swiper__pagination' 1742 }, 1743 breakpoints: { 1744 1024: { 1745 slidesPerView: 4, 1746 centeredSlides: false 1747 } 1748 } 1749 }); 1750 } 1751 const sliderCardsSwiper = document.querySelector('.slider-cards-swiper'); 1752 if (sliderCardsSwiper) { 1753 const isEarlyEnrollment = sliderCardsSwiper.dataset.earlyEnrollment === 'true'; 1754 let cardsSlider = null; 1755 function initSwiper() { 1756 if (isEarlyEnrollment) { 1757 if (window.innerWidth >= 1024) { 1758 if (!cardsSlider) { 1759 cardsSlider = new Swiper(sliderCardsSwiper, { 1760 spaceBetween: 10, 1761 slidesPerView: 2, 1762 centeredSlides: false, 1763 pagination: { 1764 el: '.slider-cards-swiper__pagination' 1765 }, 1766 breakpoints: { 1767 1024: { 1768 spaceBetween: 30 1769 } 1770 } 1771 }); 1772 } 1773 } else { 1774 if (cardsSlider) { 1775 cardsSlider.destroy(true, true); 1776 cardsSlider = null; 1777 } 1778 } 1779 return; 1780 } 1781 if (!cardsSlider) { 1782 cardsSlider = new Swiper(sliderCardsSwiper, { 1783 spaceBetween: 10, 1784 slidesPerView: 'auto', 1785 centeredSlides: true, 1786 pagination: { 1787 el: '.slider-cards-swiper__pagination' 1788 }, 1789 breakpoints: { 1790 1024: { 1791 slidesPerView: 3, 1792 centeredSlides: false 1793 } 1794 } 1795 }); 1796 } 1797 } 1798 initSwiper(); 1799 if (isEarlyEnrollment) { 1800 window.addEventListener('resize', initSwiper); 1801 } 1802 } 1803 const imageSliderSwiper = document.querySelector('.image-slider-swiper'); 1804 if (imageSliderSwiper) { 1805 const autoplay = imageSliderSwiper.dataset.autoplay === 'true'; 1806 const imageSlider = new Swiper(imageSliderSwiper, { 1807 spaceBetween: 32, 1808 slidesPerView: 'auto', 1809 centeredSlides: true, 1810 loop: true, 1811 autoplay: autoplay, 1812 pagination: { 1813 el: '.image-slider-swiper__pagination' 1814 }, 1815 navigation: { 1816 nextEl: '.image-slider-swiper__button-next', 1817 prevEl: '.image-slider-swiper__button-prev' 1818 }, 1819 breakpoints: { 1820 1024: { 1821 loop: true, 1822 centeredSlides: false, 1823 initialSlide: autoplay ? 0 : 2, 1824 slidesPerView: autoplay ? 3 : 4 1825 } 1826 } 1827 }); 1828 } 1829 1830 //Function to update the position of the title in the slider for mobile 1831 const updateTitlePosition = slider => { 1832 const closestSlider = slider.closest('.image-content-slider--right'); 1833 if (window.innerWidth < 768 && closestSlider) { 1834 const title = closestSlider.querySelector('.image-content-slider__body h2'); 1835 closestSlider.prepend(title); 1836 } 1837 }; 1838 if (document.querySelector('.image-content-swiper-right')) { 1839 const rightSliders = document.querySelectorAll('.image-content-swiper-right');
1840 rightSliders.forEach(slider => { 1841 const closestSlider = slider.closest('.image-content-slider--right'); 1842 updateTitlePosition(slider); 1843 new Swiper(slider, { 1844 spaceBetween: 32, 1845 slidesPerView: 1, 1846 centeredSlides: true, 1847 pagination: { 1848 el: closestSlider.querySelector('.image-content-swiper-right__pagination') 1849 }, 1850 navigation: { 1851 nextEl: closestSlider.querySelector('.image-content-swiper-right__button-next'), 1852 prevEl: closestSlider.querySelector('.image-content-swiper-right__button-prev') 1853 } 1854 }); 1855 }); 1856 } 1857 if (document.querySelector('.image-content-swiper-left')) { 1858 const leftSliders = document.querySelectorAll('.image-content-swiper-left'); 1859 leftSliders.forEach(slider => { 1860 const closestSlider = slider.closest('.image-content-slider--left'); 1861 updateTitlePosition(slider); 1862 new Swiper(slider, { 1863 spaceBetween: 32, 1864 slidesPerView: 1, 1865 centeredSlides: true, 1866 pagination: { 1867 el: closestSlider.querySelector('.image-content-swiper-left__pagination') 1868 }, 1869 navigation: { 1870 nextEl: closestSlider.querySelector('.image-content-swiper-left__button-next'), 1871 prevEl: closestSlider.querySelector('.image-content-swiper-left__button-prev') 1872 } 1873 }); 1874 }); 1875 } 1876 if (document.querySelector('.partners-slider-swiper')) { 1877 new Swiper('.partners-slider-swiper', { 1878 spaceBetween: 40, 1879 slidesPerView: 'auto', 1880 centeredSlides: true, 1881 loop: true, 1882 autoplay: { 1883 delay: 1500 1884 }, 1885 breakpoints: { 1886 768: { 1887 loop: true, 1888 spaceBetween: 80, 1889 centeredSlides: true 1890 }, 1891 1200: { 1892 loop: true, 1893 spaceBetween: 80, 1894 centeredSlides: true, 1895 slidesPerView: 5 1896 } 1897 }, 1898 pagination: { 1899 el: '.partners-slider-swiper__pagination', 1900 clickable: true 1901 } 1902 }); 1903 } 1904 if (document.querySelector('.camp-main__swiper')) { 1905 new Swiper('.camp-main__swiper', { 1906 spaceBetween: 30, 1907 slidesPerView: 1, 1908 effect: 'fade', 1909 loop: true, 1910 autoplay: true, 1911 pagination: { 1912 el: '.camp-main__swiper-pagination' 1913 } 1914 }); 1915 } 1916 if (document.querySelector('.camp-blog-swiper')) { 1917 new Swiper('.camp-blog-swiper', { 1918 slidesPerView: 'auto', 1919 pagination: { 1920 el: '.camp-blog-swiper__pagination' 1921 } 1922 }); 1923 } 1924 const testimonialsAlternativeSlider = document.querySelector('.testimonials-alternative__slider'); 1925 if (testimonialsAlternativeSlider) { 1926 const testimonialsAlternative = new Swiper(testimonialsAlternativeSlider, { 1927 spaceBetween: 14, 1928 slidesPerView: 1.3, 1929 loop: false, 1930 pagination: { 1931 el: '.testimonials-alternative__pagination' 1932 }, 1933 navigation: { 1934 nextEl: '.testimonials-alternative__button-next', 1935 prevEl: '.testimonials-alternative__button-prev' 1936 }, 1937 breakpoints: { 1938 1024: { 1939 slidesPerView: 3.2 1940 } 1941 } 1942 }); 1943 } 1944}; 1945 1946;// ./src/js/stickyHeader.js 1947const stickyHeader = () => { 1948 const header = document.querySelector(".header"); 1949 const headerRect = header.getBoundingClientRect(); 1950 if (header === null) { 1951 return; 1952 } 1953 window.onscroll = function () { 1954 if (window.scrollY > headerRect.height) { 1955 document.body.classList.add("sticky-header"); 1956 header.classList.add("sticky"); 1957 } else { 1958 header.classList.remove("sticky"); 1959 document.body.classList.remove("sticky-header"); 1960 } 1961 }; 1962}; 1963 1964;// ./src/js/stickySearch.js 1965const stickySearch = () => { 1966 const isSticky = document.querySelector('.sticky-search'); 1967 if (!isSticky) return; 1968 // Arrays de rutas 1969 const rutasPrimerGrupo = ['/', '/weekly-schedule/']; 1970 const rutasSegundoGrupo = ['/our-approach/', '/about-us/']; 1971 1972 // Obtener la ruta actual 1973 const pathActual = window.location.pathname; 1974 1975 // Función para mostrar el sticky-search 1976 function mostrarStickySearch() { 1977 isSticky.classList.add('show'); 1978 } 1979 1980 // Función para ocultar el sticky-search 1981 function ocultarStickySearch() { 1982 isSticky.classList.remove('show'); 1983 } 1984 1985 // Comprobar si estamos en las rutas del primer grupo 1986 if (rutasPrimerGrupo.includes(pathActual)) { 1987 const heroMediaSearch = document.querySelector('.hero-media-search'); 1988 if (heroMediaSearch) { 1989 // Crear un observador de intersección para el elemento hero-media-search 1990 const observer = new IntersectionObserver(function (entries) { 1991 if (entries[0].intersectionRatio > 0.40) { 1992 ocultarStickySearch(); 1993 } else { 1994 mostrarStickySearch(); 1995 } 1996 }, { 1997 threshold: [0, 0.4] 1998 } // Observar cuando la visibilidad sea 0% y 40% 1999 ); 2000 2001 // Comenzar a observar el elemento 2002 observer.observe(heroMediaSearch); 2003 } 2004 } 2005 2006 // Comprobar si estamos en las rutas del segundo grupo 2007 else if (rutasSegundoGrupo.includes(pathActual)) { 2008 const header = document.querySelector('header'); 2009 if (header) { 2010 // Configurar un MutationObserver para detectar cambios en las clases del header 2011 const observer = new MutationObserver(function (mutations) { 2012 mutations.forEach(function (mutation) { 2013 if (mutation.attributeName === 'class') { 2014 // Si el header tiene la clase 'sticky', mostrar sticky-search 2015 if (header.classList.contains('sticky')) { 2016 mostrarStickySearch(); 2017 } else { 2018 ocultarStickySearch(); 2019 } 2020 } 2021 }); 2022 }); 2023 2024 // Configuración del observador: observar cambios en los atributos del header 2025 observer.observe(header, { 2026 attributes: true 2027 }); 2028 2029 // Verificar el estado inicial 2030 if (header.classList.contains('sticky')) { 2031 mostrarStickySearch(); 2032 } 2033 } 2034 } 2035}; 2036 2037;// ./src/js/tabs.js 2038const initTabs = () => { 2039 const allTabsButtons = document.querySelectorAll('.tabs-js-button'); 2040 // const tabs = document.querySelectorAll('.tabs-js-content') 2041 2042 if (allTabsButtons.length === 0) { 2043 return; 2044 } 2045 allTabsButtons.forEach(item => { 2046 item.addEventListener('click', e => { 2047 const { 2048 id 2049 } = e.target.dataset; 2050 const tabs = item.closest('.tabs-js').querySelectorAll('.tabs-js-content'); 2051 const tabsButtons = item.closest('.tabs-js').querySelectorAll('.tabs-js-button'); 2052 tabsButtons.forEach(button => { 2053 if (button == e.target) { 2054 button.classList.add('active'); 2055 } else { 2056 button.classList.remove('active'); 2057 } 2058 });
2059 tabs.forEach(tab => { 2060 if (tab.id == id) { 2061 tab.dataset.show = true; 2062 } else { 2063 tab.dataset.show = false; 2064 } 2065 }); 2066 }); 2067 }); 2068}; 2069 2070;// ./src/js/tabs-faq.js 2071const initTabsFAQ = () => { 2072 const tabsButtons = document.querySelectorAll('.tabs-faq__button'); 2073 const tabs = document.querySelectorAll('.tabs-faq__items'); 2074 if (tabsButtons.length === 0 || tabs.length === 0) { 2075 return; 2076 } 2077 tabsButtons.forEach(item => { 2078 item.addEventListener('click', e => { 2079 const { 2080 id 2081 } = e.target.dataset; 2082 tabsButtons.forEach(button => { 2083 if (button == e.target) { 2084 button.classList.add('active'); 2085 } else { 2086 button.classList.remove('active'); 2087 } 2088 }); 2089 tabs.forEach(tab => { 2090 if (tab.id == id) { 2091 tab.dataset.show = true; 2092 } else { 2093 tab.dataset.show = false; 2094 } 2095 }); 2096 }); 2097 }); 2098}; 2099 2100;// ./src/js/tabs-image-accordion.js 2101const initTabsImageAccordion = () => { 2102 if (document.querySelector('.tabs-image-accordion__buttons')) { 2103 var buttons = new Swiper(".tabs-image-accordion__buttons", { 2104 spaceBetween: 10, 2105 slidesPerView: 'auto', 2106 freeMode: true, 2107 watchSlidesProgress: true, 2108 slideToClickedSlide: true, 2109 breakpoints: { 2110 1024: { 2111 slidesPerView: 3 2112 } 2113 } 2114 }); 2115 } 2116 if (document.querySelector('.tabs-image-accordion__tabs')) { 2117 new Swiper(".tabs-image-accordion__tabs", { 2118 spaceBetween: 10, 2119 slidesPerView: 1, 2120 effect: 'fade', 2121 thumbs: { 2122 swiper: buttons 2123 } 2124 }); 2125 } 2126 if (document.querySelector('.tabs-image-accordion__items')) { 2127 new Swiper(".tabs-image-accordion__items", { 2128 spaceBetween: 10, 2129 slidesPerView: 'auto', 2130 nested: true, 2131 autoHeight: true, 2132 scrollbar: { 2133 el: '.tabs-image-accordion__items-scrollbar' 2134 } 2135 }); 2136 } 2137}; 2138const initTabsImageAccordionToggles = () => { 2139 const toggles = document.querySelectorAll('.tab-image-accordion__toggle'); 2140 if (toggles.length === 0) { 2141 return; 2142 } 2143 toggles.forEach(toggle => { 2144 toggle.addEventListener('change', e => { 2145 const scrollbar = e.target.closest('.tab-image-accordion__items').querySelector('.scrollbar'); 2146 const { 2147 id 2148 } = e.target.dataset; 2149 scrollbar.style.top = id * 66 + 'px'; 2150 }); 2151 }); 2152}; 2153 2154;// ./src/js/tabs-scheduler.js 2155const initTabsScheduler = () => { 2156 const tabsButtons = document.querySelectorAll('.tabs-scheduler-js-button'); 2157 const tabs = document.querySelectorAll('.tabs-scheduler-js-tab'); 2158 if (tabsButtons.length === 0 || tabs.length === 0) { 2159 return; 2160 } 2161 tabsButtons.forEach(item => { 2162 item.addEventListener('click', e => { 2163 const { 2164 id 2165 } = e.target.dataset; 2166 tabsButtons.forEach(button => { 2167 if (button == e.target) { 2168 button.classList.add('active'); 2169 } else { 2170 button.classList.remove('active'); 2171 } 2172 });
2173 tabs.forEach(tab => { 2174 if (tab.id == id) { 2175 tab.dataset.show = true; 2176 } else { 2177 tab.dataset.show = false; 2178 } 2179 }); 2180 }); 2181 }); 2182}; 2183 2184;// ./src/js/searchBar.js 2185const initSearchBar = () => { 2186 const searchBarToggle = document.querySelectorAll('.search-js-toggle'); 2187 const searchBar = document.querySelector('.search-js'); 2188 const searchBarClose = document.querySelector('.search-js-close'); 2189 if (searchBarToggle.length === 0) { 2190 return; 2191 } 2192 const closeSearchBar = e => { 2193 searchBar.classList.toggle('opened'); 2194 }; 2195 searchBarToggle.forEach(btn => { 2196 btn.addEventListener('click', e => { 2197 e.preventDefault(); 2198 searchBar.classList.toggle('opened'); 2199 }); 2200 }); 2201 searchBarClose.addEventListener('click', closeSearchBar); 2202}; 2203 2204;// ./src/js/salesforceForms.js 2205const showMessage = (message, form, reset) => { 2206 const messageElm = form.querySelector('.message'); 2207 const btn = form.querySelector('.btn'); 2208 messageElm.classList.remove('hidden'); 2209 messageElm.innerHTML = message; 2210 if (btn.dataset.text != '') { 2211 btn.innerHTML = btn.dataset.text; 2212 } else { 2213 btn.innerHTML = 'Submit'; 2214 } 2215 if (reset) { 2216 form.reset(); 2217 } 2218 setTimeout(() => { 2219 messageElm.classList.add('hidden'); 2220 }, 10000); 2221}; 2222const sendLead = async (form, e) => { 2223 e.target.querySelector('.btn').innerHTML = 'Sending...'; 2224 const confirmationMessage = form.dataset.message; 2225 2226 // Send data to Simon Signal 2227 if (form.id === 'newsletter-form-popup') { 2228 const formSimonData = new FormData(form); 2229 formSimonData.append('action', 'simon_data_event'); 2230 formSimonData.append('form_id', form.id); 2231 formSimonData.append('email', form.querySelector('input[name="Email"]').value); 2232 formSimonData.append('name', form.querySelector('input[name="Name"]') ? form.querySelector('input[name="Name"]').value : null); 2233 try { 2234 const response = await fetch('/wp-admin/admin-ajax.php', { 2235 method: 'POST', 2236 body: formSimonData 2237 }); 2238 if (!response.ok) { 2239 throw new Error('Network response was not ok ' + response.statusText); 2240 } 2241 } catch (error) { 2242 console.error('There has been a problem with your fetch operation:', error); 2243 throw error; 2244 } 2245 } 2246 const formData = new FormData(e.target); 2247 formData.append('action', 'sf_form'); 2248 let reset; 2249 try { 2250 const response = await fetch('/wp-admin/admin-ajax.php', { 2251 method: 'POST', 2252 body: formData 2253 }); 2254 if (!response.ok) { 2255 const response = await fetch('/wp-admin/admin-ajax.php', { 2256 method: 'POST', 2257 body: formData 2258 }); 2259 if (!response.ok) { 2260 throw new Error('Network response was not ok ' + response.statusText); 2261 } 2262 } 2263 const data = await response.json(); 2264 reset = true; 2265 if (data.message === null) { 2266 showMessage('Try again, an error have ocurred.', form); 2267 } else if (data.message.includes('Lead Record with record Id')) { 2268 showMessage(confirmationMessage, form, reset); 2269 } else if (data.message.includes('Case Record with record Id')) { 2270 showMessage('The message has been sent!', form, reset); 2271 } else showMessage(data.message, form); 2272 return data; 2273 } catch (error) { 2274 reset = false; 2275 showMessage(error, form, reset); 2276 console.error('There has been a problem with your fetch operation:', error); 2277 throw error; 2278 } 2279}; 2280const initSalesforceForms = () => { 2281 const newsletterForms = document.querySelectorAll('.newsletter-js-form'); 2282 if (newsletterForms.length === 0) { 2283 return; 2284 } 2285 newsletterForms.forEach(form => { 2286 form.addEventListener('submit', e => { 2287 e.preventDefault(); 2288 grecaptcha.ready(function () { 2289 grecaptcha.execute('6Lc8EIcqAAAAACJL_JHW_vkaPunVrBXi2nAAX61e', { 2290 action: 'submit' 2291 }).then(function (token) { 2292 sendLead(form, e); 2293 }); 2294 }); 2295 }); 2296 }); 2297}; 2298 2299;// ./src/js/weekOverview.js 2300 2301const getWeekOverview = (id, elm) => { 2302 const jsonOverview = JSON.parse(document.querySelector(`[data-overview="${id}"]`).textContent); 2303 if (jsonOverview === null) { 2304 return; 2305 } 2306 2307 // console.log(jsonOverview) 2308 elm.querySelector('#wo-status').innerHTML = jsonOverview.status_name; 2309 elm.querySelector('#wo-status').className = `activity-card__status activity__status ${jsonOverview.status}`; 2310 elm.querySelector('#wo-grade-title').innerHTML = jsonOverview.grade_name; 2311 elm.querySelector('#wo-grade').innerHTML = jsonOverview.grade; 2312 elm.querySelector('#wo-grade').className = `group-${jsonOverview.grade}`; 2313 elm.querySelector('#wo-start-date').innerHTML = jsonOverview.first_date; 2314 elm.querySelector('#wo-price').innerHTML = `$${jsonOverview.price}`; 2315 elm.querySelector('#wo-overview').innerHTML = jsonOverview.overview; 2316 elm.querySelector('#wo-image').src = jsonOverview.images[0].src; 2317 elm.querySelector('#wo-image-alt').innerHTML = jsonOverview.images[0].alt; 2318 elm.querySelector('#wo-grade-overview').innerHTML = jsonOverview.grade_overview; 2319 elm.querySelector('#wo-images').innerHTML = '';
2320 jsonOverview.images.forEach((image, index) => { 2321 const li = document.createElement('li'); 2322 const img = document.createElement('img'); 2323 img.src = image.src; 2324 img.alt = image.alt; 2325 if (index === 0) { 2326 img.className = "activity__thumb gallery-js-thumb active"; 2327 } else { 2328 img.className = "activity__thumb gallery-js-thumb"; 2329 } 2330 li.appendChild(img); 2331 elm.querySelector('#wo-images').appendChild(li); 2332 }); 2333 initGallery(); 2334}; 2335const initWeekOverview = () => { 2336 const buttons = document.querySelectorAll('.woverview-js-button'); 2337 const times = document.querySelectorAll('.woverview-js-close'); 2338 const woverview = document.querySelector('.woverview-js'); 2339 const overlay = document.querySelector('.camp-slide__overlay'); 2340 if (!overlay) { 2341 return; 2342 } 2343 buttons.forEach(button => { 2344 button.addEventListener('click', e => { 2345 if (!button.dataset.id) { 2346 return; 2347 } 2348 e.preventDefault(); 2349 getWeekOverview(button.dataset.id, woverview); 2350 woverview.classList.add('opened'); 2351 overlay.classList.toggle('opened'); 2352 }); 2353 }); 2354 times.forEach(time => { 2355 time.addEventListener('click', e => { 2356 e.preventDefault(); 2357 time.closest('.woverview-js').classList.remove('opened'); 2358 overlay.classList.toggle('opened'); 2359 }); 2360 }); 2361 overlay.addEventListener('click', () => { 2362 document.querySelector('.woverview-js.opened').classList.remove('opened'); 2363 overlay.classList.toggle('opened'); 2364 }); 2365}; 2366 2367;// ./src/js/welcome-pop-up.js 2368const welcomePopUp = () => { 2369 // Seleccionar el elemento overlay del popup 2370 const popupOverlay = document.getElementById('popup-overlay'); 2371 2372 // Adds support for locations targeted popup 2373 const isLocationsTargetedPopup = document.querySelector('.locations-targeted-popup'); 2374 2375 // Validar que el elemento exista, si no existe, terminar la ejecución 2376 if (!popupOverlay) { 2377 return; 2378 } 2379 2380 // Seleccionar el botón de cierre 2381 const closeButton = popupOverlay.querySelector('.popup-container__close-btn'); 2382 const popupForm = document.getElementById('newsletter-form-popup'); 2383 if (popupForm) { 2384 popupForm.addEventListener('submit', () => { 2385 if (isLocationsTargetedPopup) { 2386 createCookie('submited-locations-targeted-popup'); 2387 } else { 2388 createCookie('submited-popup'); 2389 } 2390 }); 2391 } 2392 2393 // Función para mostrar el popup 2394 const showPopup = () => { 2395 popupOverlay.style.visibility = 'visible'; 2396 popupOverlay.style.opacity = '1'; 2397 }; 2398 2399 // Función para ocultar el popup 2400 const hidePopup = () => { 2401 popupOverlay.style.visibility = 'hidden'; 2402 popupOverlay.style.opacity = '0'; 2403 if (isLocationsTargetedPopup) { 2404 createCookie('closed-locations-targeted-popup'); 2405 } else { 2406 createCookie('closed-popup'); 2407 } 2408 }; 2409 const createCookie = name => { 2410 if (name === 'closed-locations-targeted-popup') { 2411 document.cookie = `${name}=true; path=/`; 2412 return; 2413 } 2414 let expirationDate; 2415 if (name === 'submited-popup' || name === 'submited-locations-targeted-popup') { 2416 expirationDate = new Date(Date.now() + 1000 * 60 * 60 * 24 * 365); 2417 } else if (name === 'closed-popup') { 2418 expirationDate = new Date(Date.now() + 1000 * 60 * 60 * 24 * 5); 2419 } 2420 document.cookie = `${name}=true; expires=${expirationDate.toUTCString()}; path=/`; 2421 }; 2422 const checkCookie = () => {
2423 let cookie; 2424 if (isLocationsTargetedPopup) { 2425 cookie = document.cookie.split('; ').find(row => row.startsWith('closed-locations-targeted-popup=') || row.startsWith('submited-locations-targeted-popup=')); 2426 } else { 2427 cookie = document.cookie.split('; ').find(row => row.startsWith('closed-popup=') || row.startsWith('submited-popup=')); 2428 } 2429 return cookie == undefined; 2430 }; 2431 2432 // Solo mostrar el popup si no se ha alcanzado el lÃmite de intentos 2433 if (checkCookie()) { 2434 // Usar setTimeout para mostrar el popup después de 5 segundos 2435 setTimeout(showPopup, 3000); 2436 } 2437 2438 // Evento click para cerrar el popup al hacer clic en el botón de cierre 2439 if (closeButton) { 2440 closeButton.addEventListener('click', hidePopup); 2441 } 2442}; 2443 2444;// ./src/js/weekly-videos.js 2445const initWeeklyVideos = () => { 2446 const weeklyVideos = document.querySelector('.weekly-videos'); 2447 if (!weeklyVideos) { 2448 return; 2449 } 2450 2451 // Selectors for age and week filters 2452 const selectByAge = document.querySelector('.weekly-videos__search-by-age-select'); 2453 const selectByWeek = document.querySelector('.weekly-videos__search-by-week-select'); 2454 2455 // Mobile layout adjustments and Swiper initialization 2456 if (window.innerWidth < 991) { 2457 document.querySelectorAll('.weekly-videos__video-card').forEach(video => { 2458 video.classList.add('swiper-slide'); 2459 }); 2460 document.querySelectorAll('.weekly-videos__embed').forEach(embed => { 2461 embed.classList.add('swiper'); 2462 embed.querySelector('.weekly-videos__embed--container').classList.add('swiper-wrapper'); 2463 2464 // Initialize Swiper for mobile layout 2465 new Swiper(embed, { 2466 slidesPerView: 1.3, 2467 spaceBetween: 15, 2468 loop: true, 2469 pagination: { 2470 el: embed.querySelector('.weekly-videos__embed--pagination'), 2471 clickable: true 2472 }, 2473 navigation: { 2474 nextEl: embed.querySelector('.weekly-videos__embed--button-next'), 2475 prevEl: embed.querySelector('.weekly-videos__embed--button-prev') 2476 } 2477 }); 2478 }); 2479 } 2480 2481 // Desktop layout adjustments if more elements are present 2482 if (window.innerWidth > 991) { 2483 document.querySelectorAll('.weekly-videos__embed').forEach(embed => { 2484 let totalHeight = 0; 2485 let childrenLength = embed.querySelectorAll('.weekly-videos__video-card').length; 2486 const isWeek = embed.closest('.search-by-week'); 2487 const isAge = embed.closest('.search-by-age'); 2488 if (isAge && childrenLength > 5 || isWeek && childrenLength > 4) { 2489 embed.querySelectorAll('.weekly-videos__video-card').forEach(child => { 2490 totalHeight += child.offsetHeight; 2491 }); 2492 } else { 2493 return; 2494 } 2495 embed.style.borderBottom = '2px solid rgba(0, 0, 0, 0.11)'; 2496 embed.style.overflowY = 'scroll'; 2497 embed.style.scrollbarColor = 'rgba(0, 0, 0, 0.11) rgba(0, 0, 0, 0.01)'; 2498 embed.style.scrollbarWidth = 'thin'; 2499 embed.style.paddingRight = '10px'; 2500 if (isWeek) { 2501 totalHeight = totalHeight / childrenLength * 2.2; 2502 } else if (isAge) { 2503 totalHeight = totalHeight / childrenLength * 6.29; 2504 } 2505 embed.style.maxHeight = `${totalHeight}px`; 2506 totalHeight = 0; 2507 }); 2508 } 2509 2510 // Function to update Swiper based on filter selection 2511 const updateSwiper = (selectedValue, videos, swiper) => { 2512 const selectedDataSet = swiper === 'search-by-age' ? 'age' : 'week'; 2513 videos.forEach(video => { 2514 if (selectedValue === 'all') { 2515 video.classList.remove('hidden'); 2516 if (window.innerWidth < 991) { 2517 video.classList.add('swiper-slide'); 2518 } 2519 } else { 2520 if (video.dataset[selectedDataSet] !== selectedValue) { 2521 video.classList.add('hidden'); 2522 } else { 2523 video.classList.remove('hidden'); 2524 if (window.innerWidth < 991) { 2525 video.classList.add('swiper-slide'); 2526 } 2527 } 2528 } 2529 }); 2530 2531 // Update Swiper after filtering (mobile layout) 2532 if (window.innerWidth < 991) { 2533 document.querySelectorAll(`.${swiper} .weekly-videos__video-card.hidden`).forEach(video => { 2534 video.classList.remove('swiper-slide', 'swiper-slide-active', 'swiper-slide-next'); 2535 }); 2536 const activeVideos = document.querySelectorAll(`.${swiper} .swiper-slide`); 2537 if (activeVideos.length === 1) { 2538 document.querySelector(`.${swiper} .swiper-wrapper`).style.justifyContent = 'center'; 2539 document.querySelector(`.${swiper} .swiper`).style.height = 'fit-content'; 2540 } else { 2541 document.querySelector(`.${swiper} .swiper-wrapper`).style.justifyContent = 'flex-start'; 2542 } 2543 activeVideos.forEach((video, index) => { 2544 video.ariaLabel = index + ' / ' + activeVideos.length; 2545 video.dataset.swiperSlideIndex = index; 2546 }); 2547 const swiperInstance = document.querySelector(`.${swiper} .swiper`).swiper;
2548 swiperInstance.update(); 2549 } 2550 }; 2551 2552 // Event listeners for filter selections 2553 [selectByAge, selectByWeek].forEach(select => { 2554 select.addEventListener('change', e => { 2555 let selectedValue = e.target.value; 2556 const searchBy = e.target.closest('.search-by-age') ? 'search-by-age' : 'search-by-week'; 2557 const videos = e.target.closest(`.${searchBy}`).querySelectorAll('.weekly-videos__video-card'); 2558 updateSwiper(selectedValue, videos, searchBy); 2559 }); 2560 }); 2561 2562 // Open lightbox on video card click 2563 document.querySelectorAll('.weekly-videos__video-card').forEach(video => { 2564 video.addEventListener('click', () => { 2565 const lightbox = document.createElement('div'); 2566 lightbox.classList.add('weekly-videos__lightbox'); 2567 lightbox.innerHTML = ` 2568 <div class="weekly-videos__lightbox--content"> 2569 <div class="weekly-videos__lightbox--close">X</div> 2570 <div class="weekly-videos__lightbox--video"> 2571 <iframe 2572 src="https://www.youtube.com/embed/${video.dataset.videoId}?enablejsapi=1&autoplay=1&mute=0" 2573 class="js-youtube" 2574 allow="autoplay; encrypted-media;" 2575 allowfullscreen 2576 title="video" 2577 referrerpolicy="strict-origin-when-cross-origin" 2578 ></iframe> 2579 2580 <div class="weekly-videos__lightbox--video-title">${video.querySelector('.weekly-videos__video-card--heading').textContent}</div> 2581 <div class="weekly-videos__lightbox--video-description">${video.querySelector('.weekly-videos__video-card--description').textContent}</div> 2582 </div> 2583 </div> 2584 `; 2585 lightbox.querySelector('.weekly-videos__lightbox--close').addEventListener('click', () => { 2586 lightbox.remove(); 2587 }); 2588 document.body.appendChild(lightbox); 2589 }); 2590 }); 2591}; 2592 2593;// ./src/js/disable-cookies-consent.js 2594const disableCookiesConsent = () => { 2595 window.addEventListener('DOMContentLoaded', () => { 2596 if (!cmplz_has_consent('marketing')) { 2597 // Remove all cookies except WordPress and functional cookies 2598 const cookies = document.cookie.split(';'); 2599 cookies.forEach(cookie => { 2600 const cookieName = cookie.split('=')[0].trim(); 2601 if (!cookieName.startsWith('wp-') && !cookieName.startsWith('cmplz_') && !cookieName.startsWith('wp_') && !cookieName.startsWith('cmplz_') && cookieName !== 'PHPSESSID' && !cookieName.includes('wordpress')) { 2602 // Delete the cookie by setting expired date 2603 document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`; 2604 2605 // Also try deleting with domain 2606 const domain = window.location.hostname; 2607 document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${domain};`; 2608 document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.google.com;`; 2609 document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.novapower.io;`; 2610 } 2611 }); 2612 } 2613 }); 2614}; 2615 2616;// ./src/js/index.js 2617 2618 2619 2620//import { initCookieBanner } from "./cookieBanner.js"; 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644document.addEventListener("DOMContentLoaded", function () { 2645 let node = document.querySelector('.preload-transitions'); 2646 node.classList.remove('preload-transitions'); 2647 stickyHeader(); 2648 stickySearch(); 2649 initAccordions(); 2650 initCampFinderFormRedirect(); 2651 initCustomForms(); 2652 initMap(); 2653 initMenuMobile(); 2654 initDropdowns(); 2655 initImageAccordion(); 2656 initImageAccordionToggles(); 2657 initSliders(); 2658 initTabsScheduler(); 2659 initImageAccordionSlider(); 2660 initImageAccordionSliderToggles(); 2661 initTabsImageAccordion(); 2662 initTabsImageAccordionToggles(); 2663 initTabsFAQ(); 2664 initTabs(); 2665 initPostSearchForm(); 2666 initPointers(); 2667 initReadMore(); 2668 initSideSlide(); 2669 initGallery(); 2670 initSearchBar(); 2671 initSalesforceForms(); 2672 initWeekOverview(); 2673 welcomePopUp(); 2674 //initCookieBanner() 2675 initWeeklyVideos(); 2676 disableCookiesConsent(); 2677}); 2678 2679/***/ }) 2680 2681/******/ }); 2682/************************************************************************/ 2683/******/ // The module cache 2684/******/ var __webpack_module_cache__ = {}; 2685/******/ 2686/******/ // The require function 2687/******/ function __webpack_require__(moduleId) { 2688/******/ // Check if module is in cache 2689/******/ var cachedModule = __webpack_module_cache__[moduleId]; 2690/******/ if (cachedModule !== undefined) { 2691/******/ return cachedModule.exports; 2692/******/ } 2693/******/ // Create a new module (and put it into the cache) 2694/******/ var module = __webpack_module_cache__[moduleId] = { 2695/******/ // no module.id needed 2696/******/ // no module.loaded needed 2697/******/ exports: {} 2698/******/ }; 2699/******/ 2700/******/ // Execute the module function 2701/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 2702/******/ 2703/******/ // Return the exports of the module 2704/******/ return module.exports; 2705/******/ } 2706/******/ 2707/************************************************************************/ 2708/******/ /* webpack/runtime/wrap commonjs module */ 2709/******/ !function() { 2710/******/ // execute a CommonJS module body with real module/exports objects, returning the final exports 2711/******/ __webpack_require__.cjs = function(body) { 2712/******/ var mod = { exports: {} };
2713/******/ body.call(mod.exports, mod, mod.exports); 2714/******/ return mod.exports; 2715/******/ }; 2716/******/ }(); 2717/******/ 2718/************************************************************************/ 2719/******/ 2720/******/ // startup 2721/******/ // Load entry module and return exports 2722/******/ // This entry module used 'module' so it can't be inlined 2723/******/ var __webpack_exports__ = __webpack_require__(60); 2724/******/ 2725/******/ })() 2726; 2727//# sourceMappingURL=endrock.scripts.js.map
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.