1/*! elementor-pro - v4.3.0 - 30-09-2026 */ 2(function(_wordpress_i18n) { 3 //#region \0rolldown/runtime.js 4 var __create = Object.create; 5 var __defProp$7 = Object.defineProperty; 6 var __name = (target, value) => __defProp$7(target, "name", { 7 value, 8 configurable: true 9 }); 10 var __getOwnPropDesc = Object.getOwnPropertyDescriptor; 11 var __getOwnPropNames = Object.getOwnPropertyNames; 12 var __getProtoOf = Object.getPrototypeOf; 13 var __hasOwnProp$3 = Object.prototype.hasOwnProperty; 14 var __esmMin = (fn, res, err) => () => { 15 if (err) throw err[0]; 16 try { 17 return fn && (res = fn(fn = 0)), res; 18 } catch (e) { 19 throw err = [e], e; 20 } 21 }; 22 var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports); 23 var __exportAll = (all, no_symbols) => { 24 let target = {}; 25 for (var name in all) __defProp$7(target, name, { 26 get: all[name], 27 enumerable: true 28 }); 29 if (!no_symbols) __defProp$7(target, Symbol.toStringTag, { value: "Module" }); 30 return target; 31 }; 32 var __copyProps = (to, from, except, desc) => { 33 if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { 34 key = keys[i]; 35 if (!__hasOwnProp$3.call(to, key) && key !== except) __defProp$7(to, key, { 36 get: ((k) => from[k]).bind(null, key), 37 enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable 38 }); 39 } 40 return to; 41 }; 42 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp$7(target, "default", { 43 value: mod, 44 enumerable: true 45 }) : target, mod)); 46 var __vitePreload = function preload(baseModule, deps, importerUrl) { 47 let promise = Promise.resolve(); 48 function handlePreloadError(err) { 49 const e = new Event("vite:preloadError", { cancelable: true }); 50 e.payload = err; 51 window.dispatchEvent(e); 52 if (!e.defaultPrevented) throw err; 53 } 54 return promise.then((res) => { 55 for (const item of res || []) { 56 if (item.status !== "rejected") continue; 57 handlePreloadError(item.reason); 58 } 59 return baseModule().catch(handlePreloadError); 60 }); 61 }; 62 //#endregion 63 //#region modules/animated-headline/assets/js/frontend/handlers/animated-headlines.js 64 var animated_headlines_exports = /* @__PURE__ */ __exportAll({ default: () => animated_headlines_default }); 65 var animated_headlines_default; 66 var init_animated_headlines = __esmMin((() => { 67 animated_headlines_default = elementorModules.frontend.handlers.Base.extend({ 68 svgPaths: { 69 circle: ["M325,18C228.7-8.3,118.5,8.3,78,21C22.4,38.4,4.6,54.6,5.6,77.6c1.4,32.4,52.2,54,142.6,63.7 c66.2,7.1,212.2,7.5,273.5-8.3c64.4-16.6,104.3-57.6,33.8-98.2C386.7-4.9,179.4-1.4,126.3,20.7"], 70 underline_zigzag: ["M9.3,127.3c49.3-3,150.7-7.6,199.7-7.4c121.9,0.4,189.9,0.4,282.3,7.2C380.1,129.6,181.2,130.6,70,139 c82.6-2.9,254.2-1,335.9,1.3c-56,1.4-137.2-0.3-197.1,9"], 71 x: ["M497.4,23.9C301.6,40,155.9,80.6,4,144.4", "M14.1,27.6c204.5,20.3,393.8,74,467.3,111.7"], 72 strikethrough: ["M3,75h493.5"], 73 curly: ["M3,146.1c17.1-8.8,33.5-17.8,51.4-17.8c15.6,0,17.1,18.1,30.2,18.1c22.9,0,36-18.6,53.9-18.6 c17.1,0,21.3,18.5,37.5,18.5c21.3,0,31.8-18.6,49-18.6c22.1,0,18.8,18.8,36.8,18.8c18.8,0,37.5-18.6,49-18.6c20.4,0,17.1,19,36.8,19 c22.9,0,36.8-20.6,54.7-18.6c17.7,1.4,7.1,19.5,33.5,18.8c17.1,0,47.2-6.5,61.1-15.6"], 74 diagonal: ["M13.5,15.5c131,13.7,289.3,55.5,475,125.5"], 75 double: ["M8.4,143.1c14.2-8,97.6-8.8,200.6-9.2c122.3-0.4,287.5,7.2,287.5,7.2", "M8,19.4c72.3-5.3,162-7.8,216-7.8c54,0,136.2,0,267,7.8"], 76 double_underline: ["M5,125.4c30.5-3.8,137.9-7.6,177.3-7.6c117.2,0,252.2,4.7,312.7,7.6", "M26.9,143.8c55.1-6.1,126-6.3,162.2-6.1c46.5,0.2,203.9,3.2,268.9,6.4"], 77 underline: ["M7.7,145.6C109,125,299.9,116.2,401,121.3c42.1,2.2,87.6,11.8,87.3,25.7"] 78 }, 79 getDefaultSettings() { 80 const iterationDelay = this.getElementSettings("rotate_iteration_delay"); 81 const settings = { 82 animationDelay: iterationDelay || 2500, 83 lettersDelay: iterationDelay * .02 || 50, 84 typeLettersDelay: iterationDelay * .06 || 150, 85 selectionDuration: iterationDelay * .2 || 500, 86 revealDuration: iterationDelay * .24 || 600, 87 revealAnimationDelay: iterationDelay * .6 || 1500, 88 highlightAnimationDuration: this.getElementSettings("highlight_animation_duration") || 1200, 89 highlightAnimationDelay: this.getElementSettings("highlight_iteration_delay") || 8e3 90 }; 91 settings.typeAnimationDelay = settings.selectionDuration + 800; 92 settings.selectors = { 93 headline: ".elementor-headline", 94 dynamicWrapper: ".elementor-headline-dynamic-wrapper", 95 dynamicText: ".elementor-headline-dynamic-text" 96 }; 97 settings.classes = { 98 dynamicText: "elementor-headline-dynamic-text", 99 dynamicLetter: "elementor-headline-dynamic-letter", 100 textActive: "elementor-headline-text-active", 101 textInactive: "elementor-headline-text-inactive", 102 letters: "elementor-headline-letters", 103 animationIn: "elementor-headline-animation-in", 104 typeSelected: "elementor-headline-typing-selected", 105 activateHighlight: "e-animated", 106 hideHighlight: "e-hide-highlight" 107 }; 108 return settings; 109 }, 110 getDefaultElements() {
111 var selectors = this.getSettings("selectors"); 112 return { 113 $headline: this.$element.find(selectors.headline), 114 $dynamicWrapper: this.$element.find(selectors.dynamicWrapper), 115 $dynamicText: this.$element.find(selectors.dynamicText) 116 }; 117 }, 118 getNextWord($word) { 119 return $word.is(":last-child") ? $word.parent().children().eq(0) : $word.next(); 120 }, 121 switchWord($oldWord, $newWord) { 122 $oldWord.removeClass("elementor-headline-text-active").addClass("elementor-headline-text-inactive"); 123 $newWord.removeClass("elementor-headline-text-inactive").addClass("elementor-headline-text-active"); 124 this.setDynamicWrapperWidth($newWord); 125 }, 126 singleLetters() { 127 var classes = this.getSettings("classes"); 128 this.elements.$dynamicText.each(function() { 129 var $word = jQuery(this); 130 var letters = $word.text().split(""); 131 var isActive = $word.hasClass(classes.textActive); 132 $word.empty(); 133 letters.forEach(function(letter) { 134 var $letter = jQuery("<span>", { class: classes.dynamicLetter }).text(letter);
135 if (isActive) $letter.addClass(classes.animationIn); 136 $word.append($letter); 137 }); 138 $word.css("opacity", 1); 139 }); 140 }, 141 showLetter($letter, $word, bool, duration) { 142 var self = this; 143 var classes = this.getSettings("classes"); 144 $letter.addClass(classes.animationIn); 145 if (!$letter.is(":last-child")) setTimeout(function() { 146 self.showLetter($letter.next(), $word, bool, duration); 147 }, duration); 148 else if (!bool) setTimeout(function() { 149 self.hideWord($word); 150 }, self.getSettings("animationDelay")); 151 }, 152 hideLetter($letter, $word, bool, duration) { 153 var self = this; 154 var settings = this.getSettings(); 155 $letter.removeClass(settings.classes.animationIn); 156 if (!$letter.is(":last-child")) setTimeout(function() { 157 self.hideLetter($letter.next(), $word, bool, duration); 158 }, duration); 159 else if (bool) setTimeout(function() { 160 self.hideWord(self.getNextWord($word)); 161 }, self.getSettings("animationDelay")); 162 }, 163 showWord($word, $duration) { 164 var self = this; 165 var settings = self.getSettings(); 166 var animationType = self.getElementSettings("animation_type"); 167 if ("typing" === animationType) { 168 self.showLetter($word.find("." + settings.classes.dynamicLetter).eq(0), $word, false, $duration); 169 $word.addClass(settings.classes.textActive).removeClass(settings.classes.textInactive); 170 } else if ("clip" === animationType) self.elements.$dynamicWrapper.animate({ width: $word.width() + 10 }, settings.revealDuration, function() { 171 setTimeout(function() { 172 self.hideWord($word); 173 }, settings.revealAnimationDelay); 174 }); 175 }, 176 hideWord($word) { 177 var self = this; 178 var settings = self.getSettings(); 179 var classes = settings.classes; 180 var letterSelector = "." + classes.dynamicLetter; 181 if (!this.isLoopMode && $word.is(":last-child")) return; 182 var animationType = self.getElementSettings("animation_type"); 183 var nextWord = self.getNextWord($word); 184 if ("typing" === animationType) {
185 self.elements.$dynamicWrapper.addClass(classes.typeSelected); 186 setTimeout(function() { 187 self.elements.$dynamicWrapper.removeClass(classes.typeSelected); 188 $word.addClass(settings.classes.textInactive).removeClass(classes.textActive).children(letterSelector).removeClass(classes.animationIn); 189 }, settings.selectionDuration); 190 setTimeout(function() { 191 self.showWord(nextWord, settings.typeLettersDelay); 192 }, settings.typeAnimationDelay); 193 } else if (self.elements.$headline.hasClass(classes.letters)) { 194 var bool = $word.children(letterSelector).length >= nextWord.children(letterSelector).length; 195 self.hideLetter($word.find(letterSelector).eq(0), $word, bool, settings.lettersDelay); 196 self.showLetter(nextWord.find(letterSelector).eq(0), nextWord, bool, settings.lettersDelay); 197 self.setDynamicWrapperWidth(nextWord); 198 } else if ("clip" === animationType) self.elements.$dynamicWrapper.animate({ width: "2px" }, settings.revealDuration, function() { 199 self.switchWord($word, nextWord); 200 self.showWord(nextWord); 201 }); 202 else { 203 self.switchWord($word, nextWord); 204 setTimeout(function() { 205 self.hideWord(nextWord); 206 }, settings.animationDelay); 207 } 208 }, 209 setDynamicWrapperWidth($word) { 210 const animationType = this.getElementSettings("animation_type"); 211 if ("clip" !== animationType && "typing" !== animationType) this.elements.$dynamicWrapper.css("width", $word.width()); 212 }, 213 animateHeadline() { 214 var self = this; 215 var animationType = self.getElementSettings("animation_type"); 216 var $dynamicWrapper = self.elements.$dynamicWrapper; 217 if ("clip" === animationType) $dynamicWrapper.width($dynamicWrapper.width() + 10); 218 else if ("typing" !== animationType) self.setDynamicWrapperWidth(self.elements.$dynamicText); 219 setTimeout(function() { 220 self.hideWord(self.elements.$dynamicText.eq(0)); 221 }, self.getSettings("animationDelay")); 222 }, 223 getSvgPaths(pathName) { 224 var pathsInfo = this.svgPaths[pathName]; 225 var $paths = jQuery(); 226 pathsInfo.forEach(function(pathInfo) { 227 $paths = $paths.add(jQuery("<path>", { d: pathInfo })); 228 }); 229 return $paths; 230 }, 231 addHighlight() { 232 const elementSettings = this.getElementSettings(); 233 const $svg = jQuery("<svg>", { 234 xmlns: "http://www.w3.org/2000/svg", 235 viewBox: "0 0 500 150", 236 preserveAspectRatio: "none", 237 "aria-hidden": "true" 238 }).html(this.getSvgPaths(elementSettings.marker)); 239 this.elements.$dynamicWrapper.append($svg[0].outerHTML); 240 }, 241 rotateHeadline() { 242 var settings = this.getSettings(); 243 if (this.elements.$headline.hasClass(settings.classes.letters)) this.singleLetters(); 244 this.animateHeadline(); 245 }, 246 initHeadline() { 247 const headlineStyle = this.getElementSettings("headline_style"); 248 if ("rotate" === headlineStyle) this.rotateHeadline(); 249 else if ("highlight" === headlineStyle) { 250 this.addHighlight(); 251 this.activateHighlightAnimation(); 252 } 253 this.deactivateScrollListener(); 254 }, 255 activateHighlightAnimation() { 256 const settings = this.getSettings(); 257 const classes = settings.classes; 258 const $headline = this.elements.$headline; 259 if (!this.prefersReducedMotion) this.prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"); 260 if (this.prefersReducedMotion.matches) {
261 $headline.addClass(classes.activateHighlight); 262 return; 263 } 264 $headline.removeClass(classes.hideHighlight).addClass(classes.activateHighlight); 265 if (!this.isLoopMode) return; 266 setTimeout(() => { 267 $headline.removeClass(classes.activateHighligh).addClass(classes.hideHighlight); 268 }, settings.highlightAnimationDuration + settings.highlightAnimationDelay * .8); 269 setTimeout(() => { 270 this.activateHighlightAnimation(false); 271 }, settings.highlightAnimationDuration + settings.highlightAnimationDelay); 272 }, 273 activateScrollListener() { 274 const scrollBuffer = -100; 275 this.intersectionObservers.startAnimation.observer = elementorModules.utils.Scroll.scrollObserver({ 276 offset: `0px 0px ${scrollBuffer}px`, 277 callback: (event) => { 278 if (event.isInViewport) this.initHeadline(); 279 } 280 }); 281 this.intersectionObservers.startAnimation.element = this.elements.$headline[0]; 282 this.intersectionObservers.startAnimation.observer.observe(this.intersectionObservers.startAnimation.element); 283 }, 284 deactivateScrollListener() { 285 this.intersectionObservers.startAnimation.observer.unobserve(this.intersectionObservers.startAnimation.element); 286 }, 287 onInit() { 288 elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments); 289 this.intersectionObservers = { startAnimation: { 290 observer: null, 291 element: null 292 } }; 293 this.isLoopMode = "yes" === this.getElementSettings("loop"); 294 this.activateScrollListener(); 295 } 296 }); 297 })); 298 //#endregion 299 //#region modules/animated-headline/assets/js/frontend/frontend.js 300 var frontend_default$23 = class extends elementorModules.Module { 301 static { 302 __name(this, "default"); 303 } 304 constructor() { 305 super(); 306 elementorFrontend.elementsHandler.attachHandler("animated-headline", () => __vitePreload(() => Promise.resolve().then(() => (init_animated_headlines(), animated_headlines_exports)), void 0)); 307 } 308 }; 309 //#endregion 310 //#region \0@[email protected]/helpers/esm/asyncToGenerator.js 311 function asyncGeneratorStep(n, t, e, r, o, a, c) { 312 try { 313 var i = n[a](c); 314 var u = i.value; 315 } catch (n) { 316 e(n); 317 return; 318 } 319 i.done ? t(u) : Promise.resolve(u).then(r, o); 320 } 321 function _asyncToGenerator(n) { 322 return function() { 323 var t = this; 324 var e = arguments; 325 return new Promise(function(r, o) { 326 var a = n.apply(t, e); 327 function _next(n) { 328 asyncGeneratorStep(a, r, o, _next, _throw, "next", n); 329 } 330 function _throw(n) { 331 asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); 332 } 333 _next(void 0); 334 }); 335 }; 336 } 337 var init_asyncToGenerator = __esmMin((() => {})); 338 //#endregion 339 //#region modules/carousel/assets/js/frontend/handlers/base.js 340 var CarouselBase; 341 var init_base$1 = __esmMin((() => { 342 init_asyncToGenerator(); 343 CarouselBase = class extends elementorModules.frontend.handlers.SwiperBase { 344 getDefaultSettings() { 345 return { 346 selectors: { 347 swiperContainer: ".elementor-main-swiper", 348 swiperSlide: ".swiper-slide" 349 }, 350 slidesPerView: { 351 widescreen: 3, 352 desktop: 3, 353 laptop: 3, 354 tablet_extra: 3, 355 tablet: 2, 356 mobile_extra: 2, 357 mobile: 1 358 } 359 }; 360 } 361 getDefaultElements() { 362 const selectors = this.getSettings("selectors"); 363 const elements = { $swiperContainer: this.$element.find(selectors.swiperContainer) }; 364 elements.$slides = elements.$swiperContainer.find(selectors.swiperSlide); 365 return elements; 366 } 367 getEffect() { 368 return this.getElementSettings("effect"); 369 } 370 getDeviceSlidesPerView(device) { 371 const slidesPerViewKey = "slides_per_view" + ("desktop" === device ? "" : "_" + device); 372 return Math.min(this.getSlidesCount(), +this.getElementSettings(slidesPerViewKey) || this.get
372Settings("slidesPerView")[device]); 373 } 374 getSlidesPerView(device) { 375 if ("slide" === this.getEffect()) return this.getDeviceSlidesPerView(device); 376 return 1; 377 } 378 getDeviceSlidesToScroll(device) { 379 const slidesToScrollKey = "slides_to_scroll" + ("desktop" === device ? "" : "_" + device); 380 return Math.min(this.getSlidesCount(), +this.getElementSettings(slidesToScrollKey) || 1); 381 } 382 getSlidesToScroll(device) { 383 if ("slide" === this.getEffect()) return this.getDeviceSlidesToScroll(device); 384 return 1; 385 } 386 getSpaceBetween(device) { 387 let propertyName = "space_between"; 388 if (device && "desktop" !== device) propertyName += "_" + device; 389 return this.getElementSettings(propertyName).size || 0; 390 } 391 getSwiperOptions() { 392 const elementSettings = this.getElementSettings(); 393 const swiperOptions = { 394 grabCursor: true, 395 initialSlide: this.getInitialSlide(), 396 slidesPerView: this.getSlidesPerView("desktop"), 397 slidesPerGroup: this.getSlidesToScroll("desktop"), 398 spaceBetween: this.getSpaceBetween(), 399 loop: "yes" === elementSettings.loop, 400 speed: elementSettings.speed, 401 effect: this.getEffect(), 402 preventClicksPropagation: false, 403 slideToClickedSlide: true, 404 handleElementorBreakpoints: true 405 }; 406 if ("yes" === elementSettings.lazyload) swiperOptions.lazy = { 407 loadPrevNext: true, 408 loadPrevNextAmount: 1 409 }; 410 if (elementSettings.show_arrows) swiperOptions.navigation = { 411 prevEl: ".elementor-swiper-button-prev", 412 nextEl: ".elementor-swiper-button-next" 413 }; 414 if (elementSettings.pagination) swiperOptions.pagination = { 415 el: ".swiper-pagination", 416 type: elementSettings.pagination, 417 clickable: true 418 }; 419 if ("cube" !== this.getEffect()) { 420 const breakpointsSettings = {}; 421 const breakpoints = elementorFrontend.config.responsive.activeBreakpoints; 422 Object.keys(breakpoints).forEach((breakpointName) => { 423 breakpointsSettings[breakpoints[breakpointName].value] = { 424 slidesPerView: this.getSlidesPerView(breakpointName), 425 slidesPerGroup: this.getSlidesToScroll(breakpointName), 426 spaceBetween: this.getSpaceBetween(breakpointName) 427 }; 428 }); 429 swiperOptions.breakpoints = breakpointsSettings; 430 } 431 if (!this.isEdit && elementSettings.autoplay) swiperOptions.autoplay = { 432 delay: elementSettings.autoplay_speed, 433 disableOnInteraction: !!elementSettings.pause_on_interaction 434 }; 435 return swiperOptions; 436 } 437 getDeviceBreakpointValue(device) { 438 if (!this.breakpointsDictionary) { 439 const breakpoints = elementorFrontend.config.responsive.activeBreakpoints; 440 this.breakpointsDictionary = {}; 441 Object.keys(breakpoints).forEach((breakpointName) => { 442 this.breakpointsDictionary[breakpointName] = breakpoints[breakpointName].value; 443 }); 444 } 445 return this.breakpointsDictionary[device]; 446 } 447 updateSpaceBetween(propertyName) { 448 const deviceMatch = propertyName.match("space_between_(.*)"); 449 const device = deviceMatch ? deviceMatch[1] : "desktop"; 450 const newSpaceBetween = this.getSpaceBetween(device); 451 if ("desktop" !== device) this.swiper.params.breakpoints[this.getDeviceBreakpointValue(device)].spaceBetween = newSpaceBetween; 452 else this.swiper.params.spaceBetween = newSpaceBetween; 453 this.swiper.params.spaceBetween = newSpaceBetween; 454 this.swiper.update(); 455 } 456 onInit() { 457 var _arguments = arguments; 458 var _this = this; 459 return _asyncToGenerator(function* () { 460 elementorModules.frontend.handlers.Base.prototype.onInit.apply(_this, _arguments); 461 if (1 >= _this.getSlidesCount()) return; 462 const Swiper = elementorFrontend.utils.swiper; 463 _this.swiper = yield new Swiper(_this.elements.$swiperContainer, _this.getSwiperOptions()); 464 if ("yes" === _this.getElementSettings().pause_on_hover) _this.togglePauseOnHover(true); 465 _this.elements.$swiperContainer.data("swiper", _this.swiper); 466 })(); 467 } 468 getChangeableProperties() { 469 return { 470 autoplay: "autoplay", 471 pause_on_hover: "pauseOnHover", 472 pause_on_interaction: "disableOnInteraction", 473 autoplay_speed: "delay", 474 speed: "speed", 475 width: "width" 476 }; 477 } 478 updateSwiperOption(propertyName) { 479 if (0 === propertyName.indexOf("width")) {
480 this.swiper.update(); 481 return; 482 } 483 const elementSettings = this.getElementSettings(); 484 const newSettingValue = elementSettings[propertyName]; 485 let propertyToUpdate = this.getChangeableProperties()[propertyName]; 486 let valueToUpdate = newSettingValue; 487 switch (propertyName) { 488 case "autoplay": 489 if (newSettingValue) valueToUpdate = { 490 delay: elementSettings.autoplay_speed, 491 disableOnInteraction: "yes" === elementSettings.pause_on_interaction 492 }; 493 else valueToUpdate = false; 494 break; 495 case "autoplay_speed": 496 propertyToUpdate = "autoplay"; 497 valueToUpdate = { 498 delay: newSettingValue, 499 disableOnInteraction: "yes" === elementSettings.pause_on_interaction 500 }; 501 break; 502 case "pause_on_hover": 503 this.togglePauseOnHover("yes" === newSettingValue); 504 break; 505 case "pause_on_interaction": 506 valueToUpdate = "yes" === newSettingValue; 507 break; 508 } 509 if ("pause_on_hover" !== propertyName) this.swiper.params[propertyToUpdate] = valueToUpdate; 510 this.swiper.update(); 511 } 512 onElementChange(propertyName) { 513 if (1 >= this.getSlidesCount()) return; 514 if (0 === propertyName.indexOf("width")) { 515 this.swiper.update(); 516 if (this.thumbsSwiper) this.thumbsSwiper.update(); 517 return; 518 } 519 if (0 === propertyName.indexOf("space_between")) { 520 this.updateSpaceBetween(propertyName); 521 return; 522 } 523 const changeableProperties = this.getChangeableProperties(); 524 if (Object.prototype.hasOwnProperty.call(changeableProperties, propertyName)) this.updateSwiperOption(propertyName); 525 } 526 onEditSettingsChange(propertyName) { 527 if (1 >= this.getSlidesCount()) return; 528 if ("activeItemIndex" === propertyName) this.swiper.slideToLoop(this.getEditSettings("activeItemIndex") - 1); 529 } 530 }; 531 })); 532 //#endregion 533 //#region modules/carousel/assets/js/frontend/handlers/media-carousel.js 534 var media_carousel_exports = /* @__PURE__ */ __exportAll({ default: () => MediaCarousel }); 535 var MediaCarousel; 536 var init_media_carousel = __esmMin((() => { 537 init_base$1(); 538 init_asyncToGenerator(); 539 MediaCarousel = class extends CarouselBase { 540 isSlideshow() { 541 return "slideshow" === this.getElementSettings("skin"); 542 } 543 getDefaultSettings(...args) { 544 const defaultSettings = super.getDefaultSettings(...args); 545 if (this.isSlideshow()) { 546 defaultSettings.selectors.thumbsSwiper = ".elementor-thumbnails-swiper"; 547 defaultSettings.slidesPerView = { 548 widescreen: 5, 549 desktop: 5, 550 laptop: 5, 551 tablet_extra: 5, 552 tablet: 4, 553 mobile_extra: 4, 554 mobile: 3 555 }; 556 } 557 return defaultSettings; 558 } 559 getSlidesPerViewSettingNames() { 560 if (!this.slideshowElementSettings) { 561 this.slideshowElementSettings = ["slides_per_view"]; 562 const activeBreakpoints = elementorFrontend.config.responsive.activeBreakpoints; 563 Object.keys(activeBreakpoints).forEach((breakpointName) => { 564 this.slideshowElementSettings.push("slides_per_view_" + breakpointName); 565 }); 566 } 567 return this.slideshowElementSettings; 568 } 569 getElementSettings(setting) { 570 if (-1 !== this.getSlidesPerViewSettingNames().indexOf(setting) && this.isSlideshow()) setting = "slideshow_" + setting; 571 return super.getElementSettings(setting); 572 } 573 getDefaultElements(...args) { 574 const selectors = this.getSettings("selectors"); 575 const defaultElements = super.getDefaultElements(...args); 576 if (this.isSlideshow()) defaultElements.$thumbsSwiper = this.$element.find(selectors.thumbsSwiper); 577 return defaultElements; 578 } 579 getEffect() { 580 if ("coverflow" === this.getElementSettings("skin")) return "coverflow"; 581 return super.getEffect(); 582 } 583 getSlidesPerView(device) { 584 if (this.isSlideshow()) return 1; 585 if ("coverflow" === this.getElementSettings("skin")) return this.getDeviceSlidesPerView(device); 586 return super.getSlidesPerView(device); 587 } 588 getSwiperOptions() { 589 const options = super.getSwiperOptions(); 590 if (this.isSlideshow()) {
591 options.loopedSlides = this.getSlidesCount(); 592 delete options.pagination; 593 delete options.breakpoints; 594 } 595 return options; 596 } 597 onInit() { 598 var _superprop_getOnInit = () => super.onInit; 599 var _this = this; 600 return _asyncToGenerator(function* () { 601 yield _superprop_getOnInit().call(_this); 602 const slidesCount = _this.getSlidesCount(); 603 if (!_this.isSlideshow() || 1 >= slidesCount) return; 604 const elementSettings = _this.getElementSettings(); 605 const loop = "yes" === elementSettings.loop; 606 const breakpointsSettings = {}; 607 const breakpoints = elementorFrontend.config.responsive.activeBreakpoints; 608 const desktopSlidesPerView = _this.getDeviceSlidesPerView("desktop"); 609 Object.keys(breakpoints).forEach((breakpointName) => { 610 breakpointsSettings[breakpoints[breakpointName].value] = { 611 slidesPerView: _this.getDeviceSlidesPerView(breakpointName), 612 spaceBetween: _this.getSpaceBetween(breakpointName) 613 }; 614 }); 615 const thumbsSliderOptions = { 616 slidesPerView: desktopSlidesPerView, 617 initialSlide: _this.getInitialSlide(), 618 centeredSlides: elementSettings.centered_slides, 619 slideToClickedSlide: true, 620 spaceBetween: _this.getSpaceBetween(), 621 loopedSlides: slidesCount, 622 loop, 623 breakpoints: breakpointsSettings, 624 handleElementorBreakpoints: true 625 }; 626 if ("yes" === elementSettings.lazyload) thumbsSliderOptions.lazy = { 627 loadPrevNext: true, 628 loadPrevNextAmount: 1 629 }; 630 const Swiper = elementorFrontend.utils.swiper; 631 _this.swiper.controller.control = _this.thumbsSwiper = yield new Swiper(_this.elements.$thumbsSwiper, thumbsSliderOptions); 632 _this.elements.$thumbsSwiper.data("swiper", _this.thumbsSwiper); 633 _this.thumbsSwiper.controller.control = _this.swiper; 634 })(); 635 } 636 }; 637 })); 638 //#endregion 639 //#region modules/carousel/assets/js/frontend/handlers/testimonial-carousel.js 640 var testimonial_carousel_exports = /* @__PURE__ */ __exportAll({ default: () => TestimonialCarousel }); 641 var TestimonialCarousel; 642 var init_testimonial_carousel = __esmMin((() => { 643 init_base$1(); 644 TestimonialCarousel = class extends CarouselBase { 645 getDefaultSettings() { 646 const defaultSettings = super.getDefaultSettings(); 647 defaultSettings.slidesPerView = { desktop: 1 }; 648 Object.keys(elementorFrontend.config.responsive.activeBreakpoints).forEach((breakpointName) => { 649 defaultSettings.slidesPerView[breakpointName] = 1; 650 }); 651 if (defaultSettings.loop) defaultSettings.loopedSlides = this.getSlidesCount(); 652 return defaultSettings; 653 } 654 getEffect() { 655 return "slide"; 656 } 657 }; 658 })); 659 //#endregion 660 //#region modules/carousel/assets/js/frontend/frontend.js 661 var frontend_default$22 = class extends elementorModules.Module { 662 static { 663 __name(this, "default"); 664 } 665 constructor() { 666 super(); 667 elementorFrontend.elementsHandler.attachHandler("media-carousel", () => __vitePreload(() => Promise.resolve().then(() => (init_media_carousel(), media_carousel_exports)), void 0)); 668 elementorFrontend.elementsHandler.attachHandler("testimonial-carousel", () => __vitePreload(() => Promise.resolve().then(() => (init_testimonial_carousel(), testimonial_carousel_exports)), void 0)); 669 elementorFrontend.elementsHandler.attachHandler("reviews", () => __vitePreload(() => Promise.resolve().then(() => (init_testimonial_carousel(), testimonial_carousel_exports)), void 0)); 670 } 671 }; 672 //#endregion 673 //#region modules/countdown/assets/js/frontend/handlers/countdown.js 674 var countdown_exports = /* @__PURE__ */ __exportAll({ default: () => countdown_default }); 675 var countdown_default; 676 var init_countdown = __esmMin((() => { 677 countdown_default = elementorModules.frontend.handlers.Base.extend({ 678 cache: null, 679 cacheElements() { 680 const $countDown = this.$element.find(".elementor-countdown-wrapper"); 681 this.cache = { 682 $countDown, 683 timeInterval: null, 684 elements: { 685 $countdown: $countDown.find(".elementor-countdown-wrapper"), 686 $daysSpan: $countDown.find(".elementor-countdown-days"), 687 $hoursSpan: $countDown.find(".elementor-countdown-hours"), 688 $minutesSpan: $countDown.find(".elementor-countdown-minutes"), 689 $secondsSpan: $countDown.find(".elementor-countdown-seconds"), 690 $expireMessage: $countDown.parent().find(".elementor-countdown-expire--message") 691 }, 692 data: { 693 id: this.$element.data("id"), 694 endTime: /* @__PURE__ */ new Date($countDown.data("date") * 1e3), 695 actions: $countDown.data("expire-actions"), 696 evergreenInterval: $countDown.data("evergreen-interval") 697 } 698 }; 699 }, 700 onInit() { 701 elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments); 702 this.cacheElements(); 703 if (0 < this.cache.data.evergreenInterval) this.cache.data.endTime = this.getEvergreenDate(); 704 this.initializeClock(); 705 }, 706 updateClock() { 707 const self = this; 708 const timeRemaining = this.getTimeRemaining(this.cache.data.endTime); 709 jQuery.each(timeRemaining.parts, function(timePart) { 710 const $element = self.cache.elements["$" + timePart + "Span"]; 711 let partValue = this.toString(); 712 if (1 === partValue.length) partValue = 0 + partValue; 713 if ($element.length) $element.text(partValue); 714 }); 715 if (timeRemaining.total <= 0) { 716 clearInterval(this.cache.timeInterval); 717 this.runActions(); 718 } 719 }, 720 initializeClock() { 721 const self = this; 722 this.updateClock(); 723 this.cache.timeInterval = setInterval(function() { 724 self.updateClock(); 725 }, 1e3); 726 }, 727 runActions() { 728 const self = this; 729 self.$element.trigger("countdown_expire", self.$element); 730 if (!this.cache.data.actions) return; 731 this.cache.data.actions.forEach(function(action) { 732 switch (action.type) { 733 case "hide": 734 self.cache.$countDown.hide(); 735 break; 736 case "redirect": 737 if (action.redirect_url && action.redirect_url.startsWith("http")) window.location.href = action.redirect_url; 738 break; 739 case "message": 740 self.cache.elements.$expireMessage.show(); 741 break; 742 } 743 }); 744 }, 745 getTimeRemaining(endTime) { 746 const timeRemaining = endTime - /* @__PURE__ */ new Date(); 747 let seconds = Math.floor(timeRemaining / 1e3 % 60); 748 let minutes = Math.floor(timeRemaining / 1e3 / 60 % 60); 749 let hours = Math.floor(timeRemaining / (1e3 * 60 * 60) % 24); 750 let days = Math.floor(timeRemaining / (1e3 * 60 * 60 * 24)); 751 if (days < 0 || hours < 0 || minutes < 0) seconds = minutes = hours = days = 0; 752 return { 753 total: timeRemaining, 754 parts: { 755 days, 756 hours, 757 minutes, 758 seconds 759 } 760 }; 761 }, 762 getEvergreenDate() { 763 const self = this; 764 const id = this.cache.data.id; 765 const interval = this.cache.data.evergreenInterval; 766 const dueDateKey = id + "-evergreen_due_date"; 767 const intervalKey = id + "-evergreen_interval"; 768 const localData = { 769 dueDate: localStorage.getItem(dueDateKey), 770 interval: localStorage.getItem(intervalKey) 771 }; 772 const initEvergreen = function() { 773 var evergreenDueDate = /* @__PURE__ */ new Date(); 774 self.cache.data.endTime = evergreenDueDate.setSeconds(evergreenDueDate.getSeconds() + interval); 775 localStorage.setItem(dueDateKey, self.cache.data.endTime); 776 localStorage.setItem(intervalKey, interval); 777 return self.cache.data.endTime; 778 }; 779 if (null === localData.dueDate && null === localData.interval) return initEvergreen(); 780 if (null !== localData.dueDate && interval !== parseInt(localData.interval, 10)) return initEvergreen(); 781 if (localData.dueDate > 0 && parseInt(localData.interval, 10) === interval) return localData.dueDate; 782 } 783 }); 784 })); 785 //#endregion 786 //#region modules/countdown/assets/js/frontend/frontend.js 787 var frontend_default$21 = class extends elementorModules.Module { 788 static { 789 __name(this, "default"); 790 } 791 constructor() { 792 super(); 793 elementorFrontend.elementsHandler.attachHandler("countdown",
793() => __vitePreload(() => Promise.resolve().then(() => (init_countdown(), countdown_exports)), void 0)); 794 } 795 }; 796 //#endregion 797 //#region modules/dynamic-tags/assets/js/frontend/frontend.js 798 var frontend_default$20 = class extends elementorModules.Module { 799 static { 800 __name(this, "default"); 801 } 802 constructor() { 803 super(); 804 elementorFrontend.on("components:init", () => this.onFrontendComponentsInit()); 805 } 806 onFrontendComponentsInit() { 807 elementorFrontend.utils.urlActions.addAction("reload-page", () => document.location.reload()); 808 } 809 }; 810 //#endregion 811 //#region modules/hotspot/assets/js/frontend/handlers/hotspot.js 812 var hotspot_exports = /* @__PURE__ */ __exportAll({ default: () => Hotspot }); 813 var Hotspot; 814 var init_hotspot = __esmMin((() => { 815 Hotspot = class extends elementorModules.frontend.handlers.Base { 816 getDefaultSettings() { 817 return { selectors: { 818 hotspot: ".e-hotspot", 819 tooltip: ".e-hotspot__tooltip" 820 } }; 821 } 822 getDefaultElements() { 823 const selectors = this.getSettings("selectors"); 824 return { 825 $hotspot: this.$element.find(selectors.hotspot), 826 $hotspotsExcludesLinks: this.$element.find(selectors.hotspot).filter(":not(.e-hotspot--no-tooltip)"), 827 $tooltip: this.$element.find(selectors.tooltip) 828 }; 829 } 830 bindEvents() { 831 const tooltipTrigger = this.getCurrentDeviceSetting("tooltip_trigger"); 832 const tooltipTriggerEvent = "mouseenter" === tooltipTrigger ? "mouseleave mouseenter" : tooltipTrigger; 833 if (tooltipTriggerEvent !== "none") this.elements.$hotspotsExcludesLinks.on(tooltipTriggerEvent, (event) => this.onHotspotTriggerEvent(event)); 834 } 835 onDeviceModeChange() { 836 this.elements.$hotspotsExcludesLinks.off(); 837 this.bindEvents(); 838 } 839 onHotspotTriggerEvent(event) { 840 const elementTarget = jQuery(event.target); 841 const isHotspotButtonEvent = elementTarget.closest(".e-hotspot__button").length; 842 const isTooltipMouseLeave = "mouseleave" === event.type && (elementTarget.is(".e-hotspot--tooltip-position") || elementTarget.parents(".e-hotspot--tooltip-position").length); 843 const isMobile = "mobile" === elementorFrontend.getCurrentDeviceMode(); 844 if (!(elementTarget.closest(".e-hotspot--link").length && isMobile && ("mouseleave" === event.type || "mouseenter" === event.type)) && (isHotspotButtonEvent || isTooltipMouseLeave)) { 845 const currentHotspot = jQuery(event.currentTarget); 846 this.elements.$hotspot.not(currentHotspot).removeClass("e-hotspot--active"); 847 currentHotspot.toggleClass("e-hotspot--active"); 848 } 849 } 850 editorAddSequencedAnimation() { 851 this.elements.$hotspot.toggleClass("e-hotspot--sequenced", "yes" === this.getElementSettings("hotspot_sequenced_animation")); 852 } 853 hotspotSequencedAnimation() { 854 const elementSettings = this.getElementSettings(); 855 if ("no" === elementSettings.hotspot_sequenced_animation) return; 856 const hotspotObserver = elementorModules.utils.Scroll.scrollObserver({ callback: (event) => { 857 if (event.isInViewport) { 858 hotspotObserver.unobserve(this.$element[0]); 859 this.elements.$hotspot.each((index, element) => { 860 if (0 === index) return; 861 const sequencedAnimation = elementSettings.hotspot_sequenced_animation_duration; 862 const animationDelay = index * ((sequencedAnimation ? sequencedAnimation.size : 1e3) / this.elements.$hotspot.length); 863 element.style.animationDelay = animationDelay + "ms"; 864 }); 865 } 866 } }); 867 hotspotObserver.observe(this.$element[0]); 868 } 869 setTooltipPositionControl() { 870 const elementSettings = this.getElementSettings(); 871 if ("undefined" !== typeof elementSettings.tooltip_animation && elementSettings.tooltip_animation.match(/^e-hotspot--(slide|fade)-direction/)) { 872 this.elements.$tooltip.removeClass("e-hotspot--tooltip-animation-from-left e-hotspot--tooltip-animation-from-top e-hotspot--tooltip-animation-from-right e-hotspot--tooltip-animation-from-bottom"); 873 this.elements.$tooltip.addClass("e-hotspot--tooltip-animation-from-" + elementSettings.tooltip_position); 874 } 875 } 876 onInit(...args) { 877 super.onInit(...args); 878 this.hotspotSequencedAnimation(); 879 this.setTooltipPositionControl(); 880 if (window.elementor) elementor.listenTo(elementor.channels.deviceMode, "change", () => this.onDeviceModeChange()); 881 } 882 onElementChange(propertyName) { 883 if (propertyName.startsWith("tooltip_position")) this.setTooltipPositionControl(); 884 if (propertyName.startsWith("hotspot_sequenced_animation")) this.editorAddSequencedAnimation(); 885 } 886 }; 887 })); 888 //#endregion 889 //#region modules/hotspot/assets/js/frontend/frontend.js 890 var frontend_default$19 = class extends elementorModules.Module { 891 static { 892 __name(this, "default"); 893 } 894 constructor() { 895 super(); 896 elementorFrontend.elementsHandler.attachHandler("hotspot", () => __vitePreload(() => Promise.resolve().then(() =>
896 (init_hotspot(), hotspot_exports)), void 0)); 897 } 898 }; 899 //#endregion 900 //#region modules/forms/assets/js/frontend/handlers/form-steps.js 901 var form_steps_exports = /* @__PURE__ */ __exportAll({ default: () => FormSteps }); 902 var __defProp$6, __getOwnPropSymbols$2, __hasOwnProp$2, __propIsEnum$2, __defNormalProp$6, __spreadValues$2, FormSteps; 903 var init_form_steps = __esmMin((() => { 904 __defProp$6 = Object.defineProperty; 905 __getOwnPropSymbols$2 = Object.getOwnPropertySymbols; 906 __hasOwnProp$2 = Object.prototype.hasOwnProperty; 907 __propIsEnum$2 = Object.prototype.propertyIsEnumerable; 908 __defNormalProp$6 = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp$6(obj, key, { 909 enumerable: true, 910 configurable: true, 911 writable: true, 912 value 913 }) : obj[key] = value, "__defNormalProp"); 914 __spreadValues$2 = /* @__PURE__ */ __name((a, b) => { 915 for (var prop in b || (b = {})) if (__hasOwnProp$2.call(b, prop)) __defNormalProp$6(a, prop, b[prop]); 916 if (__getOwnPropSymbols$2) { 917 for (var prop of __getOwnPropSymbols$2(b)) if (__propIsEnum$2.call(b, prop)) __defNormalProp$6(a, prop, b[prop]); 918 } 919 return a; 920 }, "__spreadValues"); 921 FormSteps = class extends elementorModules.frontend.handlers.Base { 922 getDefaultSettings() { 923 return { 924 selectors: { 925 form: ".elementor-form", 926 fieldsWrapper: ".elementor-form-fields-wrapper", 927 fieldGroup: ".elementor-field-group", 928 stepWrapper: ".elementor-field-type-step", 929 stepField: ".e-field-step", 930 submitWrapper: ".elementor-field-type-submit", 931 submitButton: "[type=\"submit\"]", 932 buttons: ".e-form__buttons", 933 buttonWrapper: ".e-form__buttons__wrapper", 934 button: ".e-form__buttons__wrapper__button", 935 indicator: ".e-form__indicators__indicator", 936 indicatorProgress: ".e-form__indicators__indicator__progress", 937 indicatorProgressMeter: ".e-form__indicators__indicator__progress__meter", 938 formHelpInline: ".elementor-form-help-inline" 939 }, 940 classes: { 941 hidden: "elementor-hidden", 942 column: "elementor-column", 943 fieldGroup: "elementor-field-group", 944 elementorButton: "elementor-button", 945 step: "e-form__step", 946 buttons: "e-form__buttons", 947 buttonWrapper: "e-form__buttons__wrapper", 948 button: "e-form__buttons__wrapper__button", 949 indicators: "e-form__indicators", 950 indicator: "e-form__indicators__indicator", 951 indicatorIcon: "e-form__indicators__indicator__icon", 952 indicatorNumber: "e-form__indicators__indicator__number", 953 indicatorLabel: "e-form__indicators__indicator__label", 954 indicatorProgress: "e-form__indicators__indicator__progress", 955 indicatorProgressMeter: "e-form__indicators__indicator__progress__meter", 956 indicatorSeparator: "e-form__indicators__indicator__separator", 957 indicatorInactive: "e-form__indicators__indicator--state-inactive", 958 indicatorActive: "e-form__indicators__indicator--state-active", 959 indicatorCompleted: "e-form__indicators__indicator--state-completed", 960 indicatorShapeCircle: "e-form__indicators__indicator--shape-circle", 961 indicatorShapeSquare: "e-form__indicators__indicator--shape-square", 962 indicatorShapeRounded: "e-form__indicators__indicator--shape-rounded", 963 indicatorShapeNone: "e-form__indicators__indicator--shape-none" 964 } 965 }; 966 } 967 getDefaultElements() { 968 const { selectors } = this.getSettings(), elements = { $form: this.$element.find(selectors.form) }; 969 elements.$fieldsWrapper = elements.$form.children(selectors.fieldsWrapper); 970 elements.$stepWrapper = elements.$fieldsWrapper.children(selectors.stepWrapper); 971 elements.$stepField = elements.$stepWrapper.children(selectors.stepField); 972 elements.$fieldGroup = elements.$fieldsWrapper.children(selectors.fieldGroup); 973 elements.$submitWrapper = elements.$fieldsWrapper.children(selectors.submitWrapper); 974 elements.$submitButton = elements.$submitWrapper.children(selectors.submitButton); 975 return elements; 976 } 977 onInit(...args) { 978 super.onInit(...args); 979 if (!this.isStepsExist()) return; 980 this.data = { 981 steps: [], 982 indicatorsWithObjectTags: [] 983 }; 984 this.state = { 985 currentStep: 0, 986 stepsType: "", 987 stepsShape: "" 988 }; 989 this.buildSteps(); 990 this.elements = __spreadValues$2(__spreadValues$2(__spreadValues$2({}, this.elements), this.createStepsIndicators()), this.createStepsButtons()); 991 this.initProgressBar(); 992 this.extractResponsiveSizeFromSubmitWrapper(); 993 } 994 bindEvents() { 995 if (!this.isStepsExist()) return; 996 const { selectors }
996 = this.getSettings(); 997 this.elements.$form.on({ 998 submit: () => this.resetForm(), 999 keydown: (e) => { 1000 var _a; 1001 var _b; 1002 if (13 === e.keyCode && !this.isLastStep() && "textarea" !== e.target.localName) { 1003 e.preventDefault(); 1004 const direction = ((_b = (_a = e.target.closest(selectors.button)) == null ? void 0 : _a.dataset) == null ? void 0 : _b.direction) || "next"; 1005 this.applyStep(direction); 1006 } 1007 }, 1008 error: () => this.onFormError() 1009 }); 1010 } 1011 isStepsExist() { 1012 return this.elements.$stepWrapper.length; 1013 } 1014 initProgressBar() { 1015 if ("progress_bar" === this.getElementSettings().step_type) this.setProgressBar(); 1016 } 1017 buildSteps() { 1018 this.elements.$stepWrapper.each((index, el) => { 1019 const { selectors, classes } = this.getSettings(), $currentStep = jQuery(el); 1020 $currentStep.addClass(classes.step).removeClass(classes.fieldGroup, classes.column); 1021 if (index) $currentStep.addClass(classes.hidden); 1022 this.setStepData($currentStep.children(selectors.stepField)); 1023 $currentStep.append($currentStep.nextUntil(this.elements.$stepWrapper).not(this.elements.$submitWrapper)); 1024 }); 1025 } 1026 setStepData($stepElement) { 1027 const dataAttributes = [ 1028 "label", 1029 "previousButton", 1030 "nextButton", 1031 "iconUrl", 1032 "iconLibrary", 1033 "icon" 1034 ]; 1035 const stepData = {}; 1036 dataAttributes.forEach((attr) => { 1037 const attrValue = $stepElement.attr("data-" + attr); 1038 if (attrValue) stepData[attr] = attrValue; 1039 }); 1040 this.data.steps.push(stepData); 1041 } 1042 createStepsIndicators() { 1043 const stepsSettings = this.getElementSettings(); 1044 const stepsElements = {}; 1045 if ("none" !== stepsSettings.step_type) { 1046 const { selectors, classes } = this.getSettings(), indicatorsTypeClass = classes.indicators + "--type-" + stepsSettings.step_type, indicatorsClasses = [classes.indicators, indicatorsTypeClass]; 1047 stepsElements.$indicatorsWrapper = jQuery("<div>", { class: indicatorsClasses.join(" ") }); 1048 stepsElements.$indicatorsWrapper.append(this.buildIndicators()); 1049 this.elements.$fieldsWrapper.before(stepsElements.$indicatorsWrapper); 1050 if ("progress_bar" === stepsSettings.step_type) { 1051 stepsElements.$progressBar = stepsElements.$indicatorsWrapper.find(selectors.indicatorProgress); 1052 stepsElements.$progressBarMeter = stepsElements.$indicatorsWrapper.find(selectors.indicatorProgressMeter); 1053 } else { 1054 stepsElements.$indicators = stepsElements.$indicatorsWrapper.find(selectors.indicator); 1055 stepsElements.$currentIndicator = stepsElements.$indicators.eq(this.state.currentStep); 1056 } 1057 } 1058 this.saveIndicatorsState(); 1059 return stepsElements; 1060 } 1061 buildIndicators() { 1062 return "progress_bar" === this.getElementSettings().step_type ? this.buildProgressBar() : this.buildIndicatorsFromStepsData(); 1063 } 1064 buildProgressBar() { 1065 const { classes } = this.getSettings(), $progressBar = jQuery("<div>", { class: classes.indicatorProgress }), $progressBarMeter = jQuery("<div>", { class: classes.indicatorProgressMeter }); 1066 $progressBar.append($progressBarMeter); 1067 return $progressBar; 1068 } 1069 getProgressBarValue() { 1070 const totalSteps = this.data.steps.length; 1071 const currentStep = this.state.currentStep; 1072 const percentage = currentStep ? (currentStep + 1) / totalSteps * 100 : 100 / totalSteps; 1073 return Math.floor(percentage) + "%"; 1074 } 1075 setProgressBar() { 1076 const progressBarValue = this.getProgressBarValue(); 1077 this.updateProgressMeterCSSVariable(progressBarValue); 1078 this.elements.$progressBarMeter.text(progressBarValue); 1079 } 1080 updateProgressMeterCSSVariable(value) { 1081 this.$element[0].style.setProperty("--e-form-steps-indicator-progress-meter-width", value); 1082 } 1083 saveIndicatorsState() { 1084 const stepsSettings = this.getElementSettings(); 1085 this.state.stepsType = stepsSettings.step_type; 1086 if (![ 1087 "none", 1088 "text", 1089 "progress_bar" 1090 ].includes(stepsSettings.step_type)) this.state.stepsShape = stepsSettings.step_icon_shape; 1091 } 1092 buildIndicatorsFromStepsData() { 1093 const indicators = []; 1094 this.data.steps.forEach((stepObj, index) => { 1095 if (index) indicators.push(this.getStepSeparator()); 1096 indicators.push(this.getStepIndicatorElement(stepObj, index)); 1097 }); 1098 return indicators; 1099 } 1100 getStepIndicatorElement(stepObj, index) { 1101 const { classes }
1101 = this.getSettings(), stepsSettings = this.getElementSettings(), indicatorStateClass = this.getIndicatorStateClass(index), indicatorClasses = [classes.indicator, indicatorStateClass], $stepIndicator = jQuery("<div>", { class: indicatorClasses.join(" ") }); 1102 if (stepsSettings.step_type.includes("icon")) $stepIndicator.append(this.getStepIconElement(stepObj)); 1103 if (stepsSettings.step_type.includes("number")) $stepIndicator.append(this.getStepNumberElement(index)); 1104 if (stepsSettings.step_type.includes("text")) $stepIndicator.append(this.getStepLabelElement(stepObj.label)); 1105 return $stepIndicator; 1106 } 1107 getIndicatorStateClass(index) { 1108 const { classes } = this.getSettings(); 1109 if (index < this.state.currentStep) return classes.indicatorCompleted; 1110 else if (index > this.state.currentStep) return classes.indicatorInactive; 1111 return classes.indicatorActive; 1112 } 1113 getIndicatorShapeClass() { 1114 const stepsSettings = this.getElementSettings(), { classes } = this.getSettings(); 1115 return classes["indicatorShape" + this.firstLetterToUppercase(stepsSettings.step_icon_shape)]; 1116 } 1117 firstLetterToUppercase(str) { 1118 return str.charAt(0).toUpperCase() + str.slice(1); 1119 } 1120 getStepNumberElement(index) { 1121 const { classes } = this.getSettings(), numberClasses = [classes.indicatorNumber, this.getIndicatorShapeClass()]; 1122 return jQuery("<div>", { 1123 class: numberClasses.join(" "), 1124 text: index + 1 1125 }); 1126 } 1127 getStepIconElement(stepObj) { 1128 const { classes } = this.getSettings(), iconClasses = [classes.indicatorIcon, this.getIndicatorShapeClass()], $icon = jQuery("<div>", { class: iconClasses.join(" ") }); 1129 if (stepObj.icon) $icon.html(stepObj.icon); 1130 else { 1131 let $iconElement; 1132 if (stepObj.iconLibrary) $iconElement = jQuery("<i>", { class: stepObj.iconLibrary }); 1133 else { 1134 $iconElement = jQuery(`<object type="image/svg+xml" data="${stepObj.iconUrl}"></object>`); 1135 $iconElement.on("load", (event) => { 1136 event.target.contentDocument.querySelector("svg").style.fill = $iconElement.css("fill"); 1137 }); 1138 this.data.indicatorsWithObjectTags.push($iconElement); 1139 } 1140 $icon.append($iconElement); 1141 } 1142 return $icon; 1143 } 1144 getStepLabelElement(label) { 1145 const { classes } = this.getSettings(); 1146 return jQuery("<label>", { 1147 class: classes.indicatorLabel, 1148 text: label 1149 }); 1150 } 1151 getStepSeparator() { 1152 const { classes } = this.getSettings(); 1153 return jQuery("<div>", { class: classes.indicatorSeparator }); 1154 } 1155 createStepsButtons() { 1156 const { selectors } = this.getSettings(), stepsElements = {}; 1157 this.injectButtonsToSteps(stepsElements); 1158 stepsElements.$buttonsContainer = this.elements.$stepWrapper.find(selectors.buttons); 1159 stepsElements.$buttonsWrappers = stepsElements.$buttonsContainer.children(selectors.buttonWrapper); 1160 return stepsElements; 1161 } 1162 injectButtonsToSteps() { 1163 const totalSteps = this.elements.$stepWrapper.length; 1164 this.elements.$stepWrapper.each((index, el) => { 1165 const $el = jQuery(el); 1166 const $container = this.getButtonsContainer(); 1167 let $nextButton; 1168 if (index) { 1169 $container.append(this.getStepButton("previous", index)); 1170 $nextButton = index === totalSteps - 1 ? this.getSubmitButton() : this.getStepButton("next", index); 1171 } else $nextButton = this.getStepButton("next", index); 1172 $container.append($nextButton); 1173 $el.append($container); 1174 }); 1175 } 1176 getButtonsContainer() { 1177 const { classes } = this.getSettings(), stepsSettings = this.getElementSettings(), buttonColumnWidthClasses = [ 1178 classes.buttons, 1179 classes.column, 1180 "elementor-col-" + stepsSettings.button_width 1181 ]; 1182 return jQuery("<div>", { class: buttonColumnWidthClasses.join(" ") }); 1183 } 1184 extractResponsiveSizeFromSubmitWrapper() { 1185 let sizeClasses = []; 1186 this.elements.$submitWrapper.removeClass((index, className) => { 1187 var _a; 1188 sizeClasses = (_a = className.match(/elementor-(sm|md)-[0-9]+/g)) == null ? void 0 : _a.join(" "); 1189 return sizeClasses; 1190 }); 1191 this.elements.$buttonsContainer.addClass(sizeClasses); 1192 } 1193 getStepButton(buttonType, index) { 1194 const { classes }
1194 = this.getSettings(), $button = this.getButton(buttonType, index).on("click", () => this.applyStep(buttonType)), buttonWrapperClasses = [ 1195 classes.fieldGroup, 1196 classes.buttonWrapper, 1197 "elementor-field-type-" + buttonType 1198 ]; 1199 return jQuery("<div>", { class: buttonWrapperClasses.join(" ") }).append($button); 1200 } 1201 getSubmitButton() { 1202 const { classes } = this.getSettings(); 1203 this.elements.$submitButton.addClass(classes.button); 1204 return this.elements.$submitWrapper.attr("class", (index, className) => { 1205 return this.replaceClassNameColSize(className, ""); 1206 }).removeClass(classes.column).removeClass(classes.buttons).addClass(classes.buttonWrapper); 1207 } 1208 replaceClassNameColSize(className, value) { 1209 return className.replace(/elementor-col-([0-9]+)/g, value); 1210 } 1211 getButton(buttonType, index) { 1212 const { classes } = this.getSettings(), submitSizeClass = this.elements.$submitButton.attr("class").match(/elementor-size-([^\W\d]+)/g), buttonClasses = [ 1213 classes.elementorButton, 1214 submitSizeClass, 1215 classes.button, 1216 classes.button + "-" + buttonType 1217 ]; 1218 return jQuery("<button>", { 1219 type: "button", 1220 text: this.getButtonLabel(buttonType, index), 1221 class: buttonClasses.join(" "), 1222 "data-direction": buttonType 1223 }); 1224 } 1225 getButtonLabel(buttonType, index) { 1226 const stepsSettings = this.getElementSettings(); 1227 const stepData = this.data.steps[index]; 1228 const buttonName = buttonType + "Button"; 1229 const buttonSettingsProp = `step_${buttonType}_label`; 1230 return stepData[buttonName] || stepsSettings[buttonSettingsProp]; 1231 } 1232 applyStep(direction) { 1233 const nextIndex = "next" === direction ? this.state.currentStep + 1 : this.state.currentStep - 1; 1234 if ("next" === direction && !this.isFieldsValid(this.elements.$stepWrapper)) return false; 1235 this.goToStep(nextIndex); 1236 this.state.currentStep = nextIndex; 1237 if ("progress_bar" === this.state.stepsType) this.setProgressBar(); 1238 else if ("none" !== this.state.stepsType) this.updateIndicatorsState(direction); 1239 } 1240 goToStep(index) { 1241 const { classes } = this.getSettings(); 1242 this.elements.$stepWrapper.eq(this.state.currentStep).addClass(classe
1242s.hidden); 1243 this.elements.$stepWrapper.eq(index).removeClass(classes.hidden); 1244 const $firstFocusableField = this.getFirstFocusableField(index); 1245 if (!$firstFocusableField) return; 1246 $firstFocusableField.attr("tabindex", "0"); 1247 $firstFocusableField.trigger("focus"); 1248 } 1249 getFirstFocusableField(index) { 1250 const $fieldGroups = this.elements.$stepWrapper.eq(index).children(this.getSettings("selectors.fieldGroup")); 1251 let $firstFocusableField = null; 1252 $fieldGroups.each((fieldGroupIndex, element) => { 1253 const $fieldGroup = jQuery(element); 1254 const $focusableElement = this.getFocusableElement($fieldGroup); 1255 if (!!$focusableElement) { 1256 $firstFocusableField = $focusableElement; 1257 return false; 1258 } 1259 }); 1260 return $firstFocusableField; 1261 } 1262 getFocusableElement($fieldGroup) { 1263 if (!$fieldGroup.is(":visible")) return; 1264 const $inputFieldInFieldGroup = $fieldGroup.find(":input").first(); 1265 if (!!$inputFieldInFieldGroup.length) return $inputFieldInFieldGroup; 1266 return $fieldGroup; 1267 } 1268 isFieldsValid($stepWrapper) { 1269 let isValid = true; 1270 $stepWrapper.eq(this.state.currentStep).find(".elementor-field-group :input").each((index, el) => { 1271 if (!el.checkValidity()) { 1272 el.reportValidity(); 1273 return isValid = false; 1274 } 1275 }); 1276 return isValid; 1277 } 1278 isLastStep() { 1279 return this.state.currentStep === this.data.steps.length - 1; 1280 } 1281 resetForm() { 1282 this.state.currentStep = 0; 1283 this.resetSteps(); 1284 if ("progress_bar" === this.state.stepsType) this.setProgressBar(); 1285 else if ("none" !== this.state.stepsType) { 1286 this.elements.$currentIndicator = this.elements.$indicators.eq(this.state.currentStep); 1287 this.resetIndicators(); 1288 } 1289 } 1290 resetSteps() { 1291 const { classes } = this.getSettings();
1292 this.elements.$stepWrapper.addClass(classes.hidden).eq(0).removeClass(classes.hidden); 1293 } 1294 resetIndicators() { 1295 const { classes } = this.getSettings(), stateClasses = [ 1296 "inactive", 1297 "active", 1298 "completed" 1299 ].map((state) => classes.indicator + "--state-" + state); 1300 this.elements.$indicators.removeClass(stateClasses.join(" ")).not(this.elements.$indicators.eq(0)).addClass(classes.indicatorInactive); 1301 this.elements.$indicators.eq(0).addClass(classes.indicatorActive); 1302 } 1303 updateIndicatorsState(direction) { 1304 const { classes } = this.getSettings(), indicatorsClasses = { 1305 current: { 1306 remove: classes.indicatorActive, 1307 add: "next" === direction ? classes.indicatorCompleted : classes.indicatorInactive 1308 }, 1309 next: { 1310 remove: "next" === direction ? classes.indicatorInactive : classes.indicatorCompleted, 1311 add: classes.indicatorActive 1312 } 1313 }; 1314 this.elements.$currentIndicator.removeClass(indicatorsClasses.current.remove).addClass(indicatorsClasses.current.add); 1315 this.elements.$currentIndicator = this.elements.$indicators.eq(this.state.currentStep); 1316 this.elements.$currentIndicator.removeClass(indicatorsClasses.next.remove).addClass(indicatorsClasses.next.add); 1317 this.data.indicatorsWithObjectTags.forEach(($element) => { 1318 $element.contents().children("svg").css("fill", $element.css("fill")); 1319 }); 1320 } 1321 updateValue(updatedValue) { 1322 const actionsMap = { 1323 step_type: () => this.updateStepsType(), 1324 step_icon_shape: () => this.updateStepsShape(), 1325 step_next_label: () => this.updateStepButtonsLabel("next"), 1326 step_previous_label: () => this.updateStepButtonsLabel("previous") 1327 }; 1328 if (actionsMap[updatedValue]) actionsMap[updatedValue](); 1329 } 1330 updateStepsType() { 1331 const stepsSettings = this.getElementSettings(); 1332 if (this.elements.$indicatorsWrapper) this.elements.$indicatorsWrapper.remove(); 1333 if ("none" !== stepsSettings.step_type) this.rebuildIndicators(); 1334 this.state.stepsType = stepsSettings.step_type; 1335 } 1336 rebuildIndicators() { 1337 this.elements = __spreadValues$2(__spreadValues$2({}, this.elements), this.createStepsIndicators()); 1338 this.initProgressBar(); 1339 } 1340 updateStepsShape() { 1341 const stepsSettings = this.getElementSettings(), { selectors, classes } = this.getSettings(), shapeClassStart = classes.indicator + "--shape-", currentShapeClass = shapeClassStart + this.state.stepsShape, newShapeClass = shapeClassStart + stepsSettings.step_icon_shape; 1342 let elementsTargetType = ""; 1343 if (stepsSettings.step_type.includes("icon")) elementsTargetType = "icon"; 1344 else if (stepsSettings.step_type.includes("number")) elementsTargetType = "number"; 1345 this.elements.$indicators.children(selectors.indicator + "__" + elementsTargetType).removeClass(currentShapeClass).addClass(newShapeClass); 1346 this.state.stepsShape = stepsSettings.step_icon_shape; 1347 } 1348 updateStepButtonsLabel(buttonType) { 1349 const { selectors } = this.getSettings(), buttonSelector = { 1350 previous: selectors.button + "-previous", 1351 next: selectors.button + "-next" 1352 }; 1353 this.elements.$stepWrapper.each((index, el) => { 1354 jQuery(el).find(buttonSelector[buttonType]).text(this.getButtonLabel(buttonType, index)); 1355 }); 1356 } 1357 onFormError() { 1358 const { selectors } = this.getSettings(), $errorStepElement = this.elements.$form.find(selectors.formHelpInline).closest(selectors.stepWrapper); 1359 if ($errorStepElement.length) this.goToStep($errorStepElement.index()); 1360 } 1361 onElementChange(updatedValue) { 1362 if (!this.isStepsExist()) return; 1363 this.updateValue(updatedValue); 1364 } 1365 }; 1366 })); 1367 //#endregion 1368 //#region modules/forms/assets/js/frontend/handlers/form-sender.js 1369 var form_sender_exports = /* @__PURE__ */ __exportAll({ default: () => form_sender_default }); 1370 var form_sender_default; 1371 var init_form_sender = __esmMin((() => { 1372 form_sender_default = elementorModules.frontend.handlers.Base.extend({ 1373 getDefaultSettings() { 1374 return { 1375 selectors: { 1376 form: ".elementor-form", 1377 submitButton: "[type=\"submit\"]" 1378 }, 1379 action: "elementor_pro_forms_send_form", 1380 ajaxUrl: elementorProFrontend.config.ajaxurl 1381 }; 1382 }, 1383 getDefaultElements() {
1384 const selectors = this.getSettings("selectors"); 1385 const elements = {}; 1386 elements.$form = this.$element.find(selectors.form); 1387 elements.$submitButton = elements.$form.find(selectors.submitButton); 1388 return elements; 1389 }, 1390 bindEvents() { 1391 this.elements.$form.on("submit", this.handleSubmit); 1392 const $fileInput = this.elements.$form.find("input[type=file]"); 1393 if ($fileInput.length) $fileInput.on("change", this.validateFileSize); 1394 }, 1395 validateFileSize(event) { 1396 const $field = jQuery(event.currentTarget); 1397 const files = $field[0].files; 1398 if (!files.length) return; 1399 const maxSize = parseInt($field.attr("data-maxsize")) * 1024 * 1024; 1400 const maxSizeMessage = $field.attr("data-maxsize-message"); 1401 Array.prototype.slice.call(files).forEach((file) => { 1402 if (maxSize < file.size) { 1403 $field.parent().addClass("elementor-error").append("<span class=\"elementor-message elementor-message-danger elementor-help-inline elementor-form-help-inline\" role=\"alert\">" + maxSizeMessage + "</span>").find(":input").attr("aria-invalid", "true"); 1404 this.elements.$form.trigger("error"); 1405 } 1406 }); 1407 }, 1408 beforeSend() { 1409 const $form = this.elements.$form; 1410 $form.animate({ opacity: "0.45" }, 500).addClass("elementor-form-waiting"); 1411 $form.find(".elementor-message").remove(); 1412 $form.find(".elementor-error").removeClass("elementor-error"); 1413 $form.find("div.elementor-field-group").removeClass("error").find("span.elementor-form-help-inline").remove().end().find(":input").attr("aria-invalid", "false"); 1414 this.elements.$submitButton.attr("disabled", "disabled").find("> span").prepend("<span class=\"elementor-button-text elementor-form-spinner\"><i class=\"fa fa-spinner fa-spin\"></i> </span>"); 1415 }, 1416 getFormData() { 1417 const formData = new FormData(this.elements.$form[0]); 1418 formData.append("action", this.getSettings("action")); 1419 formData.append("referrer", location.toString()); 1420 return formData; 1421 }, 1422 onSuccess(response) { 1423 const $form = this.elements.$form; 1424 this.elements.$submitButton.removeAttr("disabled").find(".elementor-form-spinner").remove(); 1425 $form.animate({ opacity: "1" }, 100).removeClass("elementor-form-waiting"); 1426 if (!response.success) { 1427 if (response.data.errors) { 1428 jQuery.each(response.data.errors, function(key, title) { 1429 $form.find("#form-field-" + key).parent().addClass("elementor-error").append("<span class=\"elementor-message elementor-message-danger elementor-help-inline elementor-form-help-inline\" role=\"alert\">" + title + "</span>").find(":input").attr("aria-invalid", "true"); 1430 }); 1431 $form.trigger("error"); 1432 } 1433 $form.append("<div class=\"elementor-message elementor-message-danger\" role=\"alert\">" + response.data.message + "</div>"); 1434 } else { 1435 $form.trigger("submit_success", response.data); 1436 $form.trigger("form_destruct", response.data); 1437 $form.trigger("reset"); 1438 let successClass = "elementor-message elementor-message-success"; 1439 if (elementorFrontendConfig.experimentalFeatures.e_font_icon_svg) successClass += " elementor-message-svg"; 1440 if ("undefined" !== typeof response.data.message && "" !== response.data.message) $form.append("<div class=\"" + successClass + "\" role=\"alert\">" + response.data.message + "</div>"); 1441 } 1442 }, 1443 onError(xhr, desc) { 1444 const $form = this.elements.$form; 1445 $form.append("<div class=\"elementor-message elementor-message-danger\" role=\"alert\">" + desc + "</div>"); 1446 this.elements.$submitButton.html(this.elements.$submitButton.text()).removeAttr("disabled"); 1447 $form.animate({ opacity: "1" }, 100).removeClass("elementor-form-waiting"); 1448 $form.trigger("error"); 1449 }, 1450 handleSubmit(event) { 1451 const self = this; 1452 const $form = this.elements.$form; 1453 event.preventDefault(); 1454 if ($form.hasClass("elementor-form-waiting")) return false; 1455 this.beforeSend(); 1456 jQuery.ajax({ 1457 url: self.getSettings("ajaxUrl"), 1458 type: "POST", 1459 dataType: "json", 1460 data: self.getFormData(), 1461 processData: false, 1462 contentType: false, 1463 success: self.onSuccess, 1464 error: self.onError 1465 }); 1466 } 1467 }); 1468 })); 1469 //#endregion 1470 //#region modules/forms/assets/js/frontend/handlers/form-redirect.js 1471 var form_redirect_exports = /* @__PURE__ */ __exportAll({ default: () => form_redirect_default }); 1472 var form_redirect_default; 1473 var init_form_redirect = __esmMin((() => { 1474 form_redirect_default = elementorModules.frontend.handlers.Base.extend({ 1475 getDefaultSettings() { 1476 return { selectors: { form: ".elementor-form" } }; 1477 }, 1478 getDefaultElements() {
1479 var selectors = this.getSettings("selectors"); 1480 var elements = {}; 1481 elements.$form = this.$element.find(selectors.form); 1482 return elements; 1483 }, 1484 bindEvents() { 1485 this.elements.$form.on("form_destruct", this.handleSubmit); 1486 }, 1487 handleSubmit(event, response) { 1488 if ("undefined" !== typeof response.data.redirect_url) location.href = response.data.redirect_url; 1489 } 1490 }); 1491 })); 1492 //#endregion 1493 //#region modules/forms/assets/js/frontend/handlers/fields/data-time-field-base.js 1494 var DataTimeFieldBase; 1495 var init_data_time_field_base = __esmMin((() => { 1496 DataTimeFieldBase = class extends elementorModules.frontend.handlers.Base { 1497 getDefaultSettings() { 1498 return { 1499 selectors: { fields: this.getFieldsSelector() }, 1500 classes: { useNative: "elementor-use-native" } 1501 }; 1502 } 1503 getDefaultElements() { 1504 const { selectors } = this.getDefaultSettings(); 1505 return { $fields: this.$element.find(selectors.fields) }; 1506 } 1507 addPicker(element) { 1508 const { classes } = this.getDefaultSettings();
1509 if (jQuery(element).hasClass(classes.useNative)) return; 1510 element.flatpickr(this.getPickerOptions(element)); 1511 } 1512 onInit(...args) { 1513 super.onInit(...args); 1514 this.elements.$fields.each((index, element) => this.addPicker(element)); 1515 } 1516 }; 1517 })); 1518 //#endregion 1519 //#region modules/forms/assets/js/frontend/handlers/fields/date.js 1520 var date_exports = /* @__PURE__ */ __exportAll({ default: () => DateField }); 1521 var DateField; 1522 var init_date = __esmMin((() => { 1523 init_data_time_field_base(); 1524 DateField = class extends DataTimeFieldBase { 1525 getFieldsSelector() { 1526 return ".elementor-date-field"; 1527 } 1528 getPickerOptions(element) { 1529 const $element = jQuery(element); 1530 return { 1531 minDate: $element.attr("min") || null, 1532 maxDate: $element.attr("max") || null, 1533 allowInput: true 1534 }; 1535 } 1536 }; 1537 })); 1538 //#endregion 1539 //#region modules/forms/assets/js/frontend/handlers/recaptcha.js 1540 var recaptcha_exports = /* @__PURE__ */ __exportAll({ default: () => Recaptcha }); 1541 var Recaptcha; 1542 var init_recaptcha = __esmMin((() => { 1543 Recaptcha = class extends elementorModules.frontend.handlers.Base { 1544 getDefaultSettings() { 1545 return { selectors: { 1546 recaptcha: ".elementor-g-recaptcha:last", 1547 submit: "button[type=\"submit\"]", 1548 recaptchaResponse: "[name=\"g-recaptcha-response\"]" 1549 } }; 1550 } 1551 getDefaultElements() { 1552 const { selectors } = this.getDefaultSettings(), elements = { $recaptcha: this.$element.find(selectors.recaptcha) }; 1553 elements.$form = elements.$recaptcha.parents("form"); 1554 elements.$submit = elements.$form.find(selectors.submit); 1555 return elements; 1556 } 1557 bindEvents() { 1558 this.onRecaptchaApiReady(); 1559 } 1560 isActive(settings) { 1561 const { selectors } = this.getDefaultSettings(); 1562 return settings.$element.find(selectors.recaptcha).length; 1563 } 1564 addRecaptcha() { 1565 const settings = this.elements.$recaptcha.data(); 1566 const isV2 = "v3" !== settings.type; 1567 const captchaIds = []; 1568 captchaIds.forEach((id) => window.grecaptcha.reset(id)); 1569 const widgetId = window.grecaptcha.render(this.elements.$recaptcha[0], settings); 1570 this.elements.$form.on("reset error", () => { 1571 window.grecaptcha.reset(widgetId); 1572 }); 1573 if (isV2) this.elements.$recaptcha.data("widgetId", widgetId); 1574 else { 1575 captchaIds.push(widgetId); 1576 this.elements.$submit.on("click", (e) => this.onV3FormSubmit(e, widgetId)); 1577 } 1578 } 1579 onV3FormSubmit(e, widgetId) { 1580 e.preventDefault(); 1581 window.grecaptcha.ready(() => { 1582 const $form = this.elements.$form; 1583 grecaptcha.execute(widgetId, { action: this.elements.$recaptcha.data("action") }).then((token) => { 1584 if (this.elements.$recaptchaResponse) this.elements.$recaptchaResponse.val(token); 1585 else { 1586 this.elements.$recaptchaResponse = jQuery("<input>", { 1587 type: "hidden", 1588 value: token, 1589 name: "g-recaptcha-response" 1590 }); 1591 $form.append(this.elements.$recaptchaResponse); 1592 } 1593 if (!$form[0].reportValidity || "function" !== typeof $form[0].reportValidity || $form[0].reportValidity()) $form.trigger("submit"); 1594 }); 1595 }); 1596 } 1597 onRecaptchaApiReady() { 1598 if (window.grecaptcha && window.grecaptcha.render) this.addRecaptcha(); 1599 else setTimeout(() => this.onRecaptchaApiReady(), 350); 1600 } 1601 }; 1602 })); 1603 //#endregion 1604 //#region modules/forms/assets/js/frontend/handlers/fields/time.js 1605 var time_exports = /* @__PURE__ */ __exportAll({ default: () => TimeField }); 1606 var TimeField; 1607 var init_time = __esmMin((() => { 1608 init_data_time_field_base(); 1609 TimeField = class extends DataTimeFieldBase { 1610 getFieldsSelector() { 1611 return ".elementor-time-field"; 1612 } 1613 getPickerOptions() { 1614 return { 1615 noCalendar: true, 1616 enableTime: true, 1617 allowInput: true 1618 }; 1619 } 1620 }; 1621 })); 1622 //#endregion 1623 //#region modules/forms/assets/js/frontend/frontend.js 1624 var frontend_default$18 = class extends elementorModules.Module { 1625 static { 1626 __name(this, "default"); 1627 } 1628 constructor() { 1629 super(); 1630 elementorFrontend.elementsHandler.attachHandler("form", [ 1631 () => __vitePreload(() => Promise.resolve().then(() => (init_form_steps(), form_steps_exports)), void 0), 1632 () => __vitePreload(() => Promise.resolve().then(() =>
1632 (init_form_sender(), form_sender_exports)), void 0), 1633 () => __vitePreload(() => Promise.resolve().then(() => (init_form_redirect(), form_redirect_exports)), void 0), 1634 () => __vitePreload(() => Promise.resolve().then(() => (init_date(), date_exports)), void 0), 1635 () => __vitePreload(() => Promise.resolve().then(() => (init_recaptcha(), recaptcha_exports)), void 0), 1636 () => __vitePreload(() => Promise.resolve().then(() => (init_time(), time_exports)), void 0) 1637 ]); 1638 elementorFrontend.elementsHandler.attachHandler("subscribe", [ 1639 () => __vitePreload(() => Promise.resolve().then(() => (init_form_steps(), form_steps_exports)), void 0), 1640 () => __vitePreload(() => Promise.resolve().then(() => (init_form_sender(), form_sender_exports)), void 0), 1641 () => __vitePreload(() => Promise.resolve().then(() => (init_form_redirect(), form_redirect_exports)), void 0) 1642 ]); 1643 } 1644 }; 1645 //#endregion 1646 //#region modules/gallery/assets/js/frontend/handler.js 1647 var handler_exports$1 = /* @__PURE__ */ __exportAll({ default: () => galleryHandler }); 1648 var galleryHandler; 1649 var init_handler$1 = __esmMin((() => { 1650 galleryHandler = class extends elementorModules.frontend.handlers.Base { 1651 getDefaultSettings() { 1652 return { 1653 selectors: { 1654 container: ".elementor-gallery__container", 1655 galleryTitles: ".elementor-gallery-title", 1656 galleryImages: ".e-gallery-image", 1657 galleryItemOverlay: ".elementor-gallery-item__overlay", 1658 galleryItemContent: ".elementor-gallery-item__content" 1659 }, 1660 classes: { activeTitle: "elementor-item-active" } 1661 }; 1662 } 1663 getDefaultElements() { 1664 const { selectors } = this.getSettings(), elements = { 1665 $container: this.$element.find(selectors.container), 1666 $titles: this.$element.find(selectors.galleryTitles) 1667 }; 1668 elements.$items = elements.$container.children(); 1669 elements.$images = elements.$items.children(selectors.galleryImages); 1670 elements.$itemsOverlay = elements.$items.children(selectors.galleryItemOverlay); 1671 elements.$itemsContent = elements.$items.children(selectors.galleryItemContent); 1672 elements.$itemsContentElements = elements.$itemsContent.children(); 1673 return elements; 1674 } 1675 getGallerySettings() { 1676 const settings = this.getElementSettings(); 1677 const activeBreakpoints = elementorFrontend.config.responsive.activeBreakpoints; 1678 const activeBreakpointsKeys = Object.keys(activeBreakpoints); 1679 const breakPointSettings = {}; 1680 const desktopIdealRowHeight = elementorFrontend.getDeviceSetting("desktop", settings, "ideal_row_height"); 1681 activeBreakpointsKeys.forEach((breakpoint) => { 1682 if ("widescreen" !== breakpoint) { 1683 const idealRowHeight = elementorFrontend.getDeviceSetting(breakpoint, settings, "ideal_row_height"); 1684 breakPointSettings[activeBreakpoints[breakpoint].value] = { 1685 horizontalGap: elementorFrontend.getDeviceSetting(breakpoint, settings, "gap").size, 1686 verticalGap: elementorFrontend.getDeviceSetting(breakpoint, settings, "gap").size, 1687 columns: elementorFrontend.getDeviceSetting(breakpoint, settings, "columns"), 1688 idealRowHeight: idealRowHeight == null ? void 0 : idealRowHeight.size 1689 }; 1690 } 1691 }); 1692 return { 1693 type: settings.gallery_layout, 1694 idealRowHeight: desktopIdealRowHeight == null ? void 0 : desktopIdealRowHeight.size, 1695 container: this.elements.$container, 1696 columns: settings.columns, 1697 aspectRatio: settings.aspect_ratio, 1698 lastRow: "normal", 1699 horizontalGap: elementorFrontend.getDeviceSetting("desktop", settings, "gap").size, 1700 verticalGap: elementorFrontend.getDeviceSetting("desktop", settings, "gap").size, 1701 animationDuration: settings.content_animation_duration, 1702 breakpoints: breakPointSettings, 1703 rtl: elementorFrontend.config.is_rtl, 1704 lazyLoad: "yes" === settings.lazyload 1705 }; 1706 } 1707 initGallery() { 1708 this.gallery = new EGallery(this.getGallerySettings()); 1709 this.toggleAllAnimationsClasses(); 1710 } 1711 removeAnimationClasses($element) { 1712 $element.removeClass((index, className) => (className.match(/elementor-animated-item-\S+/g) || []).join(" ")); 1713 } 1714 toggleOverlayHoverAnimation() { 1715 this.removeAnimationClasses(this.elements.$itemsOverlay); 1716 const hoverAnimation = this.getElementSettings("background_overlay_hover_animation"); 1717 if (hoverAnimation) this.elements.$itemsOverlay.addClass("elementor-animated-item--" + hoverAnimation); 1718 } 1719 toggleOverlayContentAnimation() { 1720 this.removeAnimationClasses(this.elements.$itemsContentElements); 1721 const contentHoverAnimation = this.getElementSettings("content_hover_animation"); 1722 if (contentHoverAnimation) this.elements.$itemsContentElements.addClass("elementor-animated-item--" + contentHoverAnimation); 1723 } 1724 toggleOverlayContentSequencedAnimation() { 1725 this.elements.$itemsContent.toggleClass("elementor-gallery--sequenced-animation", "yes" === this.getElementSettings("content_sequenced_animation")); 1726 } 1727 toggleImageHoverAnimation() { 1728 const imageHoverAnimation = this.getElementSettings("image_hover_animation"); 1729 this.removeAnimationClasses(this.elements.$images); 1730 if (imageHoverAnimation) this.elements.$images.addClass("elementor-animated-item--" + imageHoverAnimation); 1731 }
1732 toggleAllAnimationsClasses() { 1733 const elementSettings = this.getElementSettings(); 1734 const animation = elementSettings.background_overlay_hover_animation || elementSettings.content_hover_animation || elementSettings.image_hover_animation; 1735 this.elements.$items.toggleClass("elementor-animated-content", !!animation); 1736 this.toggleImageHoverAnimation(); 1737 this.toggleOverlayHoverAnimation(); 1738 this.toggleOverlayContentAnimation(); 1739 this.toggleOverlayContentSequencedAnimation(); 1740 } 1741 toggleAnimationClasses(settingKey) { 1742 if ("content_sequenced_animation" === settingKey) this.toggleOverlayContentSequencedAnimation(); 1743 if ("background_overlay_hover_animation" === settingKey) this.toggleOverlayHoverAnimation(); 1744 if ("content_hover_animation" === settingKey) this.toggleOverlayContentAnimation(); 1745 if ("image_hover_animation" === settingKey) this.toggleImageHoverAnimation(); 1746 } 1747 setGalleryTags(id) { 1748 this.gallery.setSettings("tags", "all" === id ? [] : ["" + id]); 1749 } 1750 bindEvents() { 1751 this.elements.$titles.on("click", this.galleriesNavigationListener.bind(this)).on("keyup", (event) => { 1752 if (13 === event.keyCode || 32 === event.keyCode) event.currentTarget.click(); 1753 }); 1754 elementorFrontend.elements.$window.on("elementor/nested-tabs/activate", this.initGallery.bind(this)); 1755 } 1756 galleriesNavigationListener(event) { 1757 const classes = this.getSettings("classes"); 1758 const clickedElement = jQuery(event.target); 1759 this.elements.$titles.removeClass(classes.activeTitle);
1760 clickedElement.addClass(classes.activeTitle); 1761 this.setGalleryTags(clickedElement.data("gallery-index")); 1762 const updateLightboxGroup = () => this.setLightboxGalleryIndex(clickedElement.data("gallery-index")); 1763 setTimeout(updateLightboxGroup, 1e3); 1764 } 1765 setLightboxGalleryIndex(index = "all") { 1766 if ("all" === index) return this.elements.$items.attr("data-elementor-lightbox-slideshow", "all_" + this.getID()); 1767 this.elements.$items.not(".e-gallery-item--hidden").attr("data-elementor-lightbox-slideshow", index + "_" + this.getID()); 1768 } 1769 onInit(...args) { 1770 super.onInit(...args); 1771 if (elementorFrontend.isEditMode() && 1 <= this.$element.find(".elementor-widget-empty-icon").length) this.$element.addClass("elementor-widget-empty"); 1772 if (!this.elements.$container.length) return; 1773 this.initGallery(); 1774 this.elements.$titles.first().trigger("click"); 1775 } 1776 getSettingsDictionary() { 1777 if (this.settingsDictionary) return this.settingsDictionary; 1778 const activeBreakpoints = elementorFrontend.config.responsive.activeBreakpoints; 1779 const activeBreakpointsKeys = Object.keys(activeBreakpoints); 1780 const settingsDictionary = { 1781 columns: ["columns"], 1782 gap: ["horizontalGap", "verticalGap"], 1783 ideal_row_height: ["idealRowHeight"] 1784 }; 1785 activeBreakpointsKeys.forEach((breakpoint) => { 1786 if ("widescreen" === breakpoint) return; 1787 settingsDictionary["columns_" + breakpoint] = ["breakpoints." + activeBreakpoints[breakpoint].value + ".columns"]; 1788 settingsDictionary["gap_" + breakpoint] = ["breakpoints." + activeBreakpoints[breakpoint].value + ".horizontalGap", "breakpoints." + activeBreakpoints[breakpoint].value + ".verticalGap"]; 1789 settingsDictionary["ideal_row_height_" + breakpoint] = ["breakpoints." + activeBreakpoints[breakpoint].value + ".idealRowHeight"]; 1790 }); 1791 settingsDictionary.aspect_ratio = ["aspectRatio"]; 1792 this.settingsDictionary = settingsDictionary; 1793 return this.settingsDictionary; 1794 } 1795 onElementChange(settingKey) { 1796 this.getGallerySettings(); 1797 if (-1 !== [ 1798 "background_overlay_hover_animation", 1799 "content_hover_animation", 1800 "image_hover_animation", 1801 "content_sequenced_animation" 1802 ].indexOf(settingKey)) { 1803 this.toggleAnimationClasses(settingKey); 1804 return; 1805 } 1806 const settingsToUpdate = this.getSettingsDictionary()[settingKey]; 1807 if (settingsToUpdate) { 1808 const gallerySettings = this.getGallerySettings(); 1809 settingsToUpdate.forEach((settingToUpdate) => { 1810 this.gallery.setSettings(settingToUpdate, this.getItems(gallerySettings, settingToUpdate)); 1811 }); 1812 } 1813 } 1814 onDestroy() { 1815 super.onDestroy(); 1816 if (this.gallery) this.gallery.destroy(); 1817 } 1818 }; 1819 })); 1820 //#endregion 1821 //#region modules/gallery/assets/js/frontend/frontend.js 1822 var frontend_default$17 = class extends elementorModules.Module { 1823 static { 1824 __name(this, "default"); 1825 } 1826 constructor() { 1827 super(); 1828 elementorFrontend.elementsHandler.attachHandler("gallery", () => __vitePreload(() => Promise.resolve().then(() => (init_handler$1(), handler_exports$1)), void 0)); 1829 } 1830 }; 1831 //#endregion 1832 //#region modules/lottie/assets/js/frontend/handler.js 1833 var handler_exports = /* @__PURE__ */ __exportAll({ default: () => lottieHandler }); 1834 var __defProp$5, __defProps$1, __getOwnPropDescs$1, __getOwnPropSymbols$1, __hasOwnProp$1, __propIsEnum$1, __defNormalProp$5, __spreadValues$1, __spreadProps$1, lottieHandler; 1835 var init_handler = __esmMin((() => { 1836 __defProp$5 = Object.defineProperty; 1837 __defProps$1 = Object.defineProperties; 1838 __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors; 1839 __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; 1840 __hasOwnProp$1 = Object.prototype.hasOwnProperty; 1841 __propIsEnum$1 = Object.prototype.propertyIsEnumerable; 1842 __defNormalProp$5 = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp$5(obj, key, { 1843 enumerable: true, 1844 configurable: true, 1845 writable: true, 1846 value 1847 }) : obj[key] = value, "__defNormalProp"); 1848 __spreadValues$1 = /* @__PURE__ */ __name((a, b) => { 1849 for (var prop in b || (b = {})) if (__hasOwnProp$1.call(b, prop)) __defNormalProp$5(a, prop, b[prop]); 1850 if (__getOwnPropSymbols$1) { 1851 for (var prop of __getOwnPropSymbols$1(b)) if (__propIsEnum$1.call(b, prop)) __defNormalProp$5(a, prop, b[prop]); 1852 } 1853 return a; 1854 }, "__spreadValues"); 1855 __spreadProps$1 = /* @__PURE__ */ __name((a, b) => __defProps$1(a, __getOwnPropDescs$1(b)), "__spreadProps"); 1856 lottieHandler = class extends elementorModules.frontend.handlers.Base { 1857 getDefaultSettings() { 1858 return { 1859 selectors: { 1860 container: ".e-lottie__container", 1861 containerLink: ".e-lottie__container__link", 1862 animation: ".e-lottie__animation", 1863 caption: ".e-lottie__caption" 1864 }, 1865 classes: { caption: "e-lottie__caption" } 1866 }; 1867 } 1868 getDefaultElements() { 1869 const { selectors }
1869 = this.getSettings(); 1870 return { 1871 $widgetWrapper: this.$element, 1872 $container: this.$element.find(selectors.container), 1873 $containerLink: this.$element.find(selectors.containerLink), 1874 $animation: this.$element.find(selectors.animation), 1875 $caption: this.$element.find(selectors.caption), 1876 $sectionParent: this.$element.closest(".elementor-section"), 1877 $columnParent: this.$element.closest(".elementor-column"), 1878 $containerParent: this.$element.closest(".e-con") 1879 }; 1880 } 1881 onInit(...args) { 1882 super.onInit(...args); 1883 this.lottie = null; 1884 this.state = { 1885 isAnimationScrollUpdateNeededOnFirstLoad: true, 1886 isNewLoopCycle: false, 1887 isInViewport: false, 1888 loop: false, 1889 animationDirection: "forward", 1890 currentAnimationTrigger: "", 1891 effectsRelativeTo: "", 1892 hoverOutMode: "", 1893 hoverArea: "", 1894 caption: "", 1895 playAnimationCount: 0, 1896 animationSpeed: 0, 1897 linkTimeout: 0, 1898 viewportOffset: { 1899 start: 0, 1900 end: 100 1901 } 1902 }; 1903 this.intersectionObservers = { 1904 animation: { 1905 observer: null, 1906 element: null 1907 }, 1908 lazyload: { 1909 observer: null, 1910 element: null 1911 } 1912 }; 1913 this.animationFrameRequest = { 1914 timer: null, 1915 lastScrollY: 0 1916 }; 1917 this.listeners = { 1918 collection: [], 1919 elements: { 1920 $widgetArea: { 1921 triggerAnimationHoverIn: null, 1922 triggerAnimationHoverOut: null 1923 }, 1924 $container: { triggerAnimationClick: null } 1925 } 1926 }; 1927 this.initLottie(); 1928 } 1929 initLottie() { 1930 if (this.getLottieSettings().lazyload) this.lazyloadLottie(); 1931 else this.generateLottie(); 1932 } 1933 lazyloadLottie() { 1934 const bufferHeightBeforeTriggerLottie = 200; 1935 this.intersectionObservers.lazyload.observer = elementorModules.utils.Scroll.scrollObserver({ 1936 offset: `0px 0px ${bufferHeightBeforeTriggerLottie}px`, 1937 callback: (event) => { 1938 if (event.isInViewport) { 1939 this.generateLottie(); 1940 this.intersectionObservers.lazyload.observer.unobserve(this.intersectionObservers.lazyload.element); 1941 } 1942 } 1943 }); 1944 this.intersectionObservers.lazyload.element = this.elements.$container[0]; 1945 this.intersectionObservers.lazyload.observer.observe(this.intersectionObservers.lazyload.element); 1946 } 1947 generateLottie() { 1948 this.createLottieInstance(); 1949 this.setLottieEvents(); 1950 } 1951 createLottieInstance() { 1952 const lottieSettings = this.getLottieSettings(); 1953 this.lottie = bodymovin.loadAnimation({ 1954 container: this.elements.$animation[0], 1955 path: this.getAnimationPath(), 1956 renderer: lottieSettings.renderer, 1957 autoplay: false, 1958 name: "lottie-widget" 1959 }); 1960 this.elements.$animation.data("lottie", this.lottie); 1961 } 1962 getAnimationPath() { 1963 var _a; 1964 var _b; 1965 const lottieSettings = this.getLottieSettings(); 1966 if (((_a = lottieSettings.source_json) == null ? void 0 : _a.url) && "json" === lottieSettings.source_json.url.toLowerCase().substr(-4)) return lottieSettings.source_json.url; 1967 else if ((_b = lottieSettings.source_external_url) == null ? void 0 : _b.url) return lottieSettings.source_external_url.url; 1968 return elementorProFrontend.config.lottie.defaultAnimationUrl; 1969 } 1970 setCaption() { 1971 const lottieSettings = this.getLottieSettings(); 1972 if ("external_url" === lottieSettings.source || "media_file" === lottieSettings.source && "custom" === lottieSettings.caption_source) this.getCaptionElement().text(lottieSettings.caption); 1973 } 1974 getCaptionElement() { 1975 if (!this.elements.$caption.length) { 1976 const { classes } = this.getSettings(); 1977 this.elements.$caption = jQuery("<p>", { class: classes.caption }); 1978 this.elements.$container.append(this.elements.$caption); 1979 return this.elements.$caption; 1980 } 1981 return this.elements.$caption; 1982 } 1983 setLottieEvents() { 1984 this.lottie.addEventListener("DOMLoaded", () => this.onLottieDomLoaded()); 1985 this.lottie.addEventListener("complete", () => this.onComplete()); 1986 } 1987 saveInitialValues() { 1988 var _a; 1989 const lottieSettings = this.getLottieSettings(); 1990 this.lottie.__initialTotalFrames = this.lottie.totalFrames; 1991 this.lottie.__initialFirstFrame = this.lottie.firstFrame; 1992 this.state.currentAnimationTrigger = lottieSettings.trigger; 1993 this.state.effectsRelativeTo = lottieSettings.effects_relative_to; 1994 this.state.viewportOffset.start = lottieSettings.viewport ? lottieSettings.viewport.sizes.start : 0; 1995 this.state.viewportOffset.end = lottieSettings.viewport ? lottieSettings.viewport.sizes.end : 100; 1996 this.state.animationSpeed = (_a = lottieSettings.play_speed) == null ? void 0 : _a.size; 1997 this.state.linkTimeout = lottieSettings.link_timeout; 1998 this.state.caption = lottieSettings.caption; 1999 this.state.loop = lottieSettings.loop; 2000 } 2001 setAnimationFirstFrame() { 2002 const frame = this.getAnimationFrames(); 2003 frame.first = frame.first - this.lottie.__initialFirstFrame; 2004 this.lottie.goToAndStop(frame.first, true); 2005 } 2006 initAnimationTrigger() { 2007 switch (this.getLottieSettings().trigger) { 2008 case "none": 2009 this.playLottie(); 2010 break; 2011 case "arriving_to_viewport": 2012 this.playAnimationWhenArrivingToViewport(); 2013 break; 2014 case "bind_to_scroll": 2015 this.playAnimationWhenBindToScroll(); 2016 break; 2017 case "on_click": 2018 this.bindAnimationClickEvents(); 2019 break; 2020 case "on_hover": 2021 this.bindAnimationHoverEvents(); 2022 break; 2023 } 2024 } 2025 playAnimationWhenArrivingToViewport() { 2026 const offset = this.getOffset(); 2027 this.intersectionObservers.animation.observer = elementorModules.utils.Scroll.
2027scrollObserver({ 2028 offset: `${offset.end}% 0% ${offset.start}%`, 2029 callback: (event) => { 2030 if (event.isInViewport) { 2031 this.state.isInViewport = true; 2032 this.playLottie(); 2033 } else { 2034 this.state.isInViewport = false; 2035 this.lottie.pause(); 2036 } 2037 } 2038 }); 2039 this.intersectionObservers.animation.element = this.elements.$widgetWrapper[0]; 2040 this.intersectionObservers.animation.observer.observe(this.intersectionObservers.animation.element); 2041 } 2042 getOffset() { 2043 const lottieSettings = this.getLottieSettings(); 2044 return { 2045 start: -lottieSettings.viewport.sizes.start || 0, 2046 end: -(100 - lottieSettings.viewport.sizes.end) || 0 2047 }; 2048 } 2049 playAnimationWhenBindToScroll() { 2050 const lottieSettings = this.getLottieSettings(); 2051 const offset = this.getOffset(); 2052 this.intersectionObservers.animation.observer = elementorModules.utils.Scroll.scrollObserver({ 2053 offset: `${offset.end}% 0% ${offset.start}%`, 2054 callback: (event) => this.onLottieIntersection(event) 2055 }); 2056 this.intersectionObservers.animation.element = "viewport" === lottieSettings.effects_relative_to ? this.elements.$widgetWrapper[0] : document.documentElement; 2057 this.intersectionObservers.animation.observer.observe(this.intersectionObservers.animation.element); 2058 } 2059 updateAnimationByScrollPosition() { 2060 const lottieSettings = this.getLottieSettings(); 2061 let percentage; 2062 if ("page" === lottieSettings.effects_relative_to) percentage = this.getLottiePagePercentage(); 2063 else if ("fixed" === this.getCurrentDeviceSetting("_position")) percentage = this.getLottieViewportHeightPercentage(); 2064 else percentage = this.getLottieViewportPercentage(); 2065 let nextFrameToPlay = this.getFrameNumberByPercent(percentage); 2066 nextFrameToPlay = nextFrameToPlay - this.lottie.__initialFirstFrame; 2067 this.lottie.goToAndStop(nextFrameToPlay, true); 2068 } 2069 getLottieViewportPercentage() { 2070 return elementorModules.utils.Scroll.getElementViewportPercentage(this.elements.$widgetWrapper, this.getOffset()); 2071 } 2072 getLottiePagePercentage() { 2073 return elementorModules.utils.Scroll.getPageScrollPercentage(this.getOffset()); 2074 } 2075 getLottieViewportHeightPercentage() { 2076 return elementorModules.utils.Scroll.getPageScrollPercentage(this.getOffset(), window.innerHeight); 2077 } 2078 /** 2079 * @param {number} percent - Percent value between 0-100 2080 */ 2081 getFrameNumberByPercent(percent) { 2082 const frame = this.getAnimationFrames(); 2083 percent = Math.min(100, Math.max(0, percent)); 2084 return frame.first + (frame.last - frame.first) * percent / 100; 2085 } 2086 getAnimationFrames() { 2087 const lottieSettings = this.getLottieSettings(); 2088 const currentFrame = this.getAnimationCurrentFrame(); 2089 const startPoint = this.getAnimationRange().start; 2090 const endPoint = this.getAnimationRange().end; 2091 let firstFrame = this.lottie.__initialFirstFrame; 2092 let lastFrame = 0 === this.lottie.__initialFirstFrame ? this.lottie.__initialTotalFrames : this.lottie.__initialFirstFrame + this.lottie.__initialTotalFrames; 2093 if (startPoint && startPoint > firstFrame) firstFrame = startPoint; 2094 if (endPoint && endPoint < lastFrame) lastFrame = endPoint; 2095 if (!this.state.isNewLoopCycle && "bind_to_scroll" !== lottieSettings.trigger) firstFrame = startPoint && startPoint > currentFrame ? startPoint : currentFrame; 2096 if ("backward" === this.state.animationDirection && this.isReverseMode()) { 2097 firstFrame = currentFrame; 2098 lastFrame = startPoint && startPoint > this.lottie.__initialFirstFrame ? startPoint : this.lottie.__initialFirstFrame; 2099 } 2100 return { 2101 first: firstFrame, 2102 last: lastFrame, 2103 current: currentFrame, 2104 total: this.lottie.__initialTotalFrames 2105 }; 2106 } 2107 getAnimationRange() { 2108 const lottieSettings = this.getLottieSettings(); 2109 return { 2110 start: this.getInitialFrameNumberByPercent(lottieSettings.start_point.size), 2111 end: this.getInitialFrameNumberByPercent(lottieSettings.end_point.size) 2112 }; 2113 } 2114 getInitialFrameNumberByPercent(percent) { 2115 percent = Math.min(100, Math.max(0, percent)); 2116 return this.lottie.__initialFirstFrame + (this.lottie.__initialTotalFrames - this.lottie.__initialFirstFrame) * percent / 100; 2117 } 2118 getAnimationCurrentFrame() { 2119 return 0 === this.lottie.firstFrame ? this.lottie.currentFrame : this.lottie.firstFrame + this.lottie.currentFrame; 2120 } 2121 setLinkTimeout() { 2122 var _a; 2123 const lottieSettings = this.getLottieSettings(); 2124 if ("on_click" === lottieSettings.trigger && ((_a = lottieSettings.custom_link) == null ? void 0 : _a.url) && lottieSettings.link_timeout) this.elements.$containerLink.on("click", (event) => { 2125 event.preventDefault(); 2126 if (!this.isEdit) setTimeout(() => { 2127 const tabTarget = "on" === lottieSettings.custom_link.is_external ? "_blank" : "_self"; 2128 window.open(lottieSettings.custom_link.url, tabTarget); 2129 }, lottieSettings.link_timeout); 2130 }); 2131 } 2132 bindAnimationClickEvents() { 2133 this.listeners.elements.$container.triggerAnimationClick = () => { 2134 this.playLottie(); 2135 }; 2136 this.addSessionEventListener(this.elements.$container, "click", this.listeners.elements.$container.triggerAnimationClick); 2137 } 2138 getLottieSettings() { 2139 var _a; 2140 var _b; 2141 const lottieSettings = this.getElementSettings(); 2142 const settings = __spreadProps$1(__spreadValues$1({}, lottieSettings), { 2143 lazyload: "yes" === lottieSettings.lazyload, 2144 loop: "yes" === lottieSettings.loop 2145 }); 2146 if ("external_url" === lottieSettings.source) settings.source_external_url = __spreadProps$1(__spreadValues$1({}, (_a = lottieSettings.source_external_url) != null ? _a : {}), { url: ((_b = settings.source_external_url) == null ? void 0 : _b.url) || this.getDynamicValue() }); 2147 return settings; 2148 } 2149 playLottie() { 2150 const frame = this.getAnimationFrames(); 2151 this.lottie.stop(); 2152 this.lottie.playSegments([frame.first, frame.last], true); 2153 this.state.isNewLoopCycle = false;
2154 } 2155 bindAnimationHoverEvents() { 2156 this.createAnimationHoverInEvents(); 2157 this.createAnimationHoverOutEvents(); 2158 } 2159 createAnimationHoverInEvents() { 2160 const lottieSettings = this.getLottieSettings(); 2161 const $widgetArea = this.getHoverAreaElement(); 2162 this.state.hoverArea = lottieSettings.hover_area; 2163 this.listeners.elements.$widgetArea.triggerAnimationHoverIn = () => { 2164 this.state.animationDirection = "forward"; 2165 this.playLottie(); 2166 }; 2167 this.addSessionEventListener($widgetArea, "mouseenter", this.listeners.elements.$widgetArea.triggerAnimationHoverIn); 2168 } 2169 /** 2170 * @param {jQuery} $el 2171 * @param {string} event - event type 2172 * @param {Function} callback 2173 */ 2174 addSessionEventListener($el, event, callback) { 2175 $el.on(event, callback); 2176 this.listeners.collection.push({ 2177 $el, 2178 event, 2179 callback 2180 }); 2181 } 2182 createAnimationHoverOutEvents() { 2183 const lottieSettings = this.getLottieSettings(); 2184 const $widgetArea = this.getHoverAreaElement(); 2185 if ("pause" === lottieSettings.on_hover_out || "reverse" === lottieSettings.on_hover_out) { 2186 this.state.hoverOutMode = lottieSettings.on_hover_out; 2187 this.listeners.elements.$widgetArea.triggerAnimationHoverOut = () => { 2188 if ("pause" === lottieSettings.on_hover_out) this.lottie.pause(); 2189 else { 2190 this.state.animationDirection = "backward"; 2191 this.playLottie(); 2192 } 2193 }; 2194 this.addSessionEventListener($widgetArea, "mouseleave", this.listeners.elements.$widgetArea.triggerAnimationHoverOut); 2195 } 2196 } 2197 getHoverAreaElement() { 2198 switch (this.getLottieSettings().hover_area) { 2199 case "section": return this.elements.$sectionParent; 2200 case "column": return this.elements.$columnParent; 2201 case "container": return this.elements.$containerParent; 2202 } 2203 return this.elements.$container; 2204 } 2205 setLoopOnAnimationComplete() { 2206 const lottieSettings = this.getLottieSettings(); 2207 this.state.isNewLoopCycle = true; 2208 if (lottieSettings.loop && !this.isReverseMode()) this.setLoopWhenNotReverse(); 2209 else if (lottieSettings.loop && this.isReverseMode()) this.setReverseAnimationOnLoop(); 2210 else if (!lottieSettings.loop && this.isReverseMode()) this.setReverseAnimationOnSingleTrigger(); 2211 } 2212 isReverseMode() { 2213 const lottieSettings = this.getLottieSettings(); 2214 return "yes" === lottieSettings.reverse_animation || "reverse" === lottieSettings.on_hover_out && "backward" === this.state.animationDirection; 2215 } 2216 setLoopWhenNotReverse() { 2217 const lottieSettings = this.getLottieSettings(); 2218 if (lottieSettings.number_of_times > 0) { 2219 this.state.playAnimationCount++; 2220 if (this.state.playAnimationCount < lottieSettings.number_of_times) this.playLottie(); 2221 else this.state.playAnimationCount = 0; 2222 } else this.playLottie(); 2223 } 2224 setReverseAnimationOnLoop() { 2225 const lottieSettings = this.getLottieSettings(); 2226 if (!lottieSettings.number_of_times || this.state.playAnimationCount < lottieSettings.number_of_times) { 2227 this.state.animationDirection = "forward" === this.state.animationDirection ? "backward" : "forward"; 2228 this.playLottie(); 2229 if ("backward" === this.state.animationDirection) this.state.playAnimationCount++; 2230 } else { 2231 this.state.playAnimationCount = 0; 2232 this.state.animationDirection = "forward"; 2233 } 2234 } 2235 setReverseAnimationOnSingleTrigger() { 2236 if (this.state.playAnimationCount < 1) { 2237 this.state.playAnimationCount++; 2238 this.state.animationDirection = "backward"; 2239 this.playLottie(); 2240 } else if (this.state.playAnimationCount >= 1 && "forward" === this.state.animationDirection) { 2241 this.state.animationDirection = "backward"; 2242 this.playLottie(); 2243 } else { 2244 this.state.playAnimationCount = 0; 2245 this.state.animationDirection = "forward"; 2246 } 2247 } 2248 setAnimationSpeed() { 2249 const lottieSettings = this.getLottieSettings(); 2250 if (lottieSettings.play_speed) this.lottie.setSpeed(lottieSettings.play_speed.size); 2251 } 2252 onElementChange() { 2253 this.updateLottieValues(); 2254 this.resetAnimationTrigger(); 2255 } 2256 updateLottieValues() { 2257 var _a; 2258 const lottieSettings = this.getLottieSettings(); 2259 [ 2260 { 2261 sourceVal: (_a = lottieSettings.play_speed) == null ? void 0 : _a.size, 2262 stateProp: "animationSpeed", 2263 callback: () => this.setAnimationSpeed() 2264 }, 2265 { 2266 sourceVal: lottieSettings.link_timeout, 2267 stateProp: "linkTimeout", 2268 callback: () => this.setLinkTimeout() 2269 }, 2270 { 2271 sourceVal: lottieSettings.caption, 2272 stateProp: "caption", 2273 callback: () => this.setCaption() 2274 }, 2275 { 2276 sourceVal: lottieSettings.effects_relative_to, 2277 stateProp: "effectsRelativeTo", 2278 callback: () => this.updateAnimationByScrollPosition() 2279 }, 2280 { 2281 sourceVal: lottieSettings.loop, 2282 stateProp: "loop", 2283 callback: () => this.onLoopStateChange() 2284 } 2285 ].forEach((item) => { 2286 if ("undefined" !== typeof item.sourceVal && item.sourceVal !== this.state[item.stateProp]) { 2287 this.state[item.stateProp] = item.sourceVal; 2288 item.callback(); 2289 } 2290 }); 2291 } 2292 onLoopStateChange() { 2293 const isInActiveViewportMode = "arriving_to_viewport" === this.state.currentAnimationTrigger && this.state.isInViewport; 2294 if (this.state.loop && (isInActiveViewportMode || "none" === this.state.currentAnimationTrigger)) this.playLottie(); 2295 } 2296 resetAnimationTrigger() { 2297 const lottieSettings = this.getLottieSettings(); 2298 const isTriggerChange = lottieSettings.trigger !== this.state.currentAnimationTrigger; 2299 const isViewportOffsetChange = lottieSettings.viewport ? this.isViewportOffsetChange() : false;
2300 const isHoverOutModeChange = lottieSettings.on_hover_out ? this.isHoverOutModeChange() : false; 2301 const isHoverAreaChange = lottieSettings.hover_area ? this.isHoverAreaChange() : false; 2302 if (isTriggerChange || isViewportOffsetChange || isHoverOutModeChange || isHoverAreaChange) { 2303 this.removeAnimationFrameRequests(); 2304 this.removeObservers(); 2305 this.removeEventListeners(); 2306 this.initAnimationTrigger(); 2307 } 2308 } 2309 isViewportOffsetChange() { 2310 const lottieSettings = this.getLottieSettings(); 2311 const isStartOffsetChange = lottieSettings.viewport.sizes.start !== this.state.viewportOffset.start; 2312 const isEndOffsetChange = lottieSettings.viewport.sizes.end !== this.state.viewportOffset.end; 2313 return isStartOffsetChange || isEndOffsetChange; 2314 } 2315 isHoverOutModeChange() { 2316 return this.getLottieSettings().on_hover_out !== this.state.hoverOutMode; 2317 } 2318 isHoverAreaChange() { 2319 return this.getLottieSettings().hover_area !== this.state.hoverArea; 2320 } 2321 removeEventListeners() { 2322 this.listeners.collection.forEach((listener) => { 2323 listener.$el.off(listener.event, null, listener.callback); 2324 }); 2325 } 2326 removeObservers() { 2327 for (const type in this.intersectionObservers) if (this.intersectionObservers[type].observer && this.intersectionObservers[type].element) this.intersectionObservers[type].observer.unobserve(this.intersectionObservers[type].element); 2328 } 2329 removeAnimationFrameRequests() { 2330 cancelAnimationFrame(this.animationFrameRequest.timer); 2331 } 2332 onDestroy() { 2333 super.onDestroy(); 2334 this.destroyLottie(); 2335 } 2336 destroyLottie() { 2337 this.removeAnimationFrameRequests(); 2338 this.removeObservers(); 2339 this.removeEventListeners(); 2340 this.elements.$animation.removeData("lottie"); 2341 if (this.lottie) this.lottie.destroy(); 2342 } 2343 onLottieDomLoaded() { 2344 this.saveInitialValues(); 2345 this.setAnimationSpeed(); 2346 this.setLinkTimeout(); 2347 this.setCaption(); 2348 this.setAnimationFirstFrame(); 2349 this.initAnimationTrigger(); 2350 } 2351 onComplete() { 2352 this.setLoopOnAnimationComplete(); 2353 } 2354 onLottieIntersection(event) { 2355 if (event.isInViewport) { 2356 if (this.state.isAnimationScrollUpdateNeededOnFirstLoad) { 2357 this.state.isAnimationScrollUpdateNeededOnFirstLoad = false; 2358 this.updateAnimationByScrollPosition(); 2359 } 2360 this.animationFrameRequest.timer = requestAnimationFrame(() => this.onAnimationFrameRequest()); 2361 } else { 2362 const frame = this.getAnimationFrames(); 2363 const finalFrame = "up" === event.intersectionScrollDirection ? frame.first : frame.last; 2364 this.state.isAnimationScrollUpdateNeededOnFirstLoad = false; 2365 cancelAnimationFrame(this.animationFrameRequest.timer); 2366 this.lottie.goToAndStop(finalFrame, true); 2367 } 2368 } 2369 onAnimationFrameRequest() { 2370 if (window.scrollY !== this.animationFrameRequest.lastScrollY) { 2371 this.updateAnimationByScrollPosition(); 2372 this.animationFrameRequest.lastScrollY = window.scrollY; 2373 } 2374 this.animationFrameRequest.timer = requestAnimationFrame(() => this.onAnimationFrameRequest()); 2375 } 2376 getDynamicValue() { 2377 var _a; 2378 var _b; 2379 var _c; 2380 var _d; 2381 var _e; 2382 if (!this.isEdit || !(elementor == null ? void 0 : elementor.dynamicTags)) return ""; 2383 const modelSettings = (_b = (_a = elementor.getContainer(this.getID())) == null ? void 0 : _a.model) == null ? void 0 : _b.get("settings"); 2384 const dynamicValue = (_d = (_c = modelSettings == null ? void 0 : modelSettings.get("__dynamic__")) == null ? void 0 : _c.source_external_url) != null ? _d : null; 2385 if (!dynamicValue) return ""; 2386 const dynamicData = elementor.dynamicTags.tagTextToTagData(dynamicValue); 2387 if (!dynamicData) return ""; 2388 try { 2389 return (_e = elementor.dynamicTags.parseTagsText(dynamicValue, dynamicData, elementor.dynamicTags.getTagDataContent)) != null ? _e : ""; 2390 } catch (e) { 2391 return ""; 2392 } 2393 } 2394 }; 2395 })); 2396 //#endregion 2397 //#region modules/lottie/assets/js/frontend/frontend.js 2398 var frontend_default$16 = class extends elementorModules.Module { 2399 static { 2400 __name(this, "default"); 2401 } 2402 constructor() { 2403 super(); 2404 elementorFrontend.elementsHandler.attachHandler("lottie", () => __vitePreload(() => Promise.resolve().then(() =>
2404 (init_handler(), handler_exports)), void 0)); 2405 } 2406 }; 2407 //#endregion 2408 //#region \0@[email protected]/helpers/esm/typeof.js 2409 function _typeof(o) { 2410 "@babel/helpers - typeof"; 2411 return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) { 2412 return typeof o; 2413 } : function(o) { 2414 return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; 2415 }, _typeof(o); 2416 } 2417 var init_typeof = __esmMin((() => {})); 2418 //#endregion 2419 //#region \0@[email protected]/helpers/esm/toPrimitive.js 2420 function toPrimitive(t, r) { 2421 if ("object" != _typeof(t) || !t) return t; 2422 var e = t[Symbol.toPrimitive]; 2423 if (void 0 !== e) { 2424 var i = e.call(t, r || "default"); 2425 if ("object" != _typeof(i)) return i; 2426 throw new TypeError("@@toPrimitive must return a primitive value."); 2427 } 2428 return ("string" === r ? String : Number)(t); 2429 } 2430 var init_toPrimitive = __esmMin((() => { 2431 init_typeof(); 2432 })); 2433 //#endregion 2434 //#region \0@[email protected]/helpers/esm/toPropertyKey.js 2435 function toPropertyKey(t) { 2436 var i = toPrimitive(t, "string"); 2437 return "symbol" == _typeof(i) ? i : i + ""; 2438 } 2439 var init_toPropertyKey = __esmMin((() => { 2440 init_typeof(); 2441 init_toPrimitive(); 2442 })); 2443 //#endregion 2444 //#region \0@[email protected]/helpers/esm/defineProperty.js 2445 function _defineProperty(e, r, t) { 2446 return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, { 2447 value: t, 2448 enumerable: !0, 2449 configurable: !0, 2450 writable: !0 2451 }) : e[r] = t, e; 2452 } 2453 var init_defineProperty = __esmMin((() => { 2454 init_toPropertyKey(); 2455 })); 2456 //#endregion 2457 //#region assets/dev/js/frontend/utils/anchor-link.js 2458 var AnchorLinks; 2459 var init_anchor_link = __esmMin((() => { 2460 init_defineProperty(); 2461 AnchorLinks = class { 2462 constructor($anchorLinks, classes) { 2463 _defineProperty(this, "observer", null); 2464 this.$anchorLinks = $anchorLinks; 2465 this.activeAnchorClass = classes.activeAnchorItem; 2466 this.anchorClass = classes.anchorItem; 2467 } 2468 getViewportHeight() { 2469 return window.innerHeight; 2470 } 2471 bindEvents() { 2472 this.onResize = this.onResize.bind(this); 2473 window.addEventListener("resize", this.onResize); 2474 } 2475 initialize() { 2476 this.viewPortHeight = this.getViewportHeight(); 2477 this.followMenuAnchors(); 2478 this.bindEvents(); 2479 } 2480 followMenuAnchors() { 2481 this.$anchorLinks.each((index, anchorLink) => { 2482 if (location.pathname === anchorLink.pathname && "" !== anchorLink.hash) this.followMenuAnchor(jQuery(anchorLink)); 2483 }); 2484 } 2485 followMenuAnchor($element) { 2486 const $targetElement = $element.hasClass(this.anchorClass) ? $element : $element.closest(`.${this.anchorClass}`); 2487 const anchorElement = this.getAnchorElement($element); 2488 if (!anchorElement) return; 2489 const options = this.getObserverOptions(anchorElement); 2490 this.observer = this.createObserver($targetElement, $element, options); 2491 this.observer.observe(anchorElement); 2492 } 2493 getAnchorElement($element) { 2494 const anchorSelector = $element[0].hash; 2495 try { 2496 const decodedSelector = decodeURIComponent(anchorSelector); 2497 return document.querySelector(decodedSelector); 2498 } catch (e) { 2499 return null; 2500 } 2501 } 2502 getObserverOptions(element) { 2503 return { 2504 root: null, 2505 rootMargin: this.calculateRootMargin(element) 2506 }; 2507 } 2508 calculateRootMargin(element) { 2509 const isAnchorHeightLargerThanHalfViewport = ((element === null || element === void 0 ? void 0 : element.offsetHeight) || 0) > this.viewPortHeight / 2; 2510 const rootMarginBlockEnd = -1 * this.viewPortHeight / 2; 2511 return `${isAnchorHeightLargerThanHalfViewport ? rootMarginBlockEnd : 0}px 0px ${rootMarginBlockEnd}px 0px`; 2512 } 2513 createObserver($targetElement, $element, options) { 2514 return new IntersectionObserver((entries) => { 2515 entries.forEach((entry) => { 2516 $targetElement.toggleClass(this.activeAnchorClass, entry.isIntersecting); 2517 $element.attr("aria-current", entry.isIntersecting ? "location" : ""); 2518 }); 2519 }, options); 2520 } 2521 onResize() {
2522 this.viewPortHeight = this.getViewportHeight(); 2523 if (this.observer) this.observer.disconnect(); 2524 this.followMenuAnchors(); 2525 } 2526 }; 2527 })); 2528 //#endregion 2529 //#region modules/nav-menu/assets/js/frontend/handlers/nav-menu.js 2530 var nav_menu_exports = /* @__PURE__ */ __exportAll({ default: () => nav_menu_default }); 2531 var nav_menu_default; 2532 var init_nav_menu = __esmMin((() => { 2533 init_anchor_link(); 2534 nav_menu_default = elementorModules.frontend.handlers.Base.extend({ 2535 stretchElement: null, 2536 getDefaultSettings() { 2537 return { 2538 selectors: { 2539 menu: ".elementor-nav-menu", 2540 anchorLink: ".elementor-nav-menu--main .elementor-item-anchor", 2541 dropdownMenu: ".elementor-nav-menu__container.elementor-nav-menu--dropdown", 2542 menuToggle: ".elementor-menu-toggle" 2543 }, 2544 classes: { 2545 anchorItem: "elementor-item-anchor", 2546 activeAnchorItem: "elementor-item-active" 2547 } 2548 }; 2549 }, 2550 getDefaultElements() { 2551 var selectors = this.getSettings("selectors"); 2552 var elements = {}; 2553 elements.$menu = this.$element.find(selectors.menu); 2554 elements.$anchorLink = this.$element.find(selectors.anchorLink); 2555 elements.$dropdownMenu = this.$element.find(selectors.dropdownMenu); 2556 elements.$dropdownMenuFinalItems = elements.$dropdownMenu.find(".menu-item:not(.menu-item-has-children) > a"); 2557 elements.$menuToggle = this.$element.find(selectors.menuToggle); 2558 elements.$links = elements.$dropdownMenu.find("a.elementor-item"); 2559 return elements; 2560 }, 2561 dropdownMenuHeightControllerConfig() { 2562 const selectors = this.getSettings("selectors"); 2563 return { 2564 elements: { 2565 $element: this.$element, 2566 $dropdownMenuContainer: this.$element.find(selectors.dropdownMenu), 2567 $menuToggle: this.$element.find(selectors.menuToggle) 2568 }, 2569 attributes: { menuToggleState: "aria-expanded" }, 2570 settings: { 2571 dropdownMenuContainerMaxHeight: "1000vmax", 2572 menuHeightCssVarName: "--menu-height" 2573 } 2574 }; 2575 }, 2576 bindEvents() { 2577 if (!this.elements.$menu.length) return; 2578 this.elements.$menuToggle.on("click", this.toggleMenu.bind(this)).on("keyup", this.triggerClickOnEnterSpace.bind(this)); 2579 if (this.getElementSettings("full_width")) this.elements.$dropdownMenuFinalItems.on("click", this.toggleMenu.bind(this, false)).on("keyup", this.triggerClickOnEnterSpace.bind(this)); 2580 elementorFrontend.addListenerOnce(this.$element.data("model-cid"), "resize", this.stretchMenu); 2581 elementorFrontend.addListenerOnce(this.$element.data("model-cid"), "scroll", elementorFrontend.debounce(this.menuHeightController.reassignMobileMenuHeight.bind(this.menuHeightController), 250)); 2582 }, 2583 initStretchElement() { 2584 this.stretchElement = new elementorModules.frontend.tools.StretchElement({ element: this.elements.$dropdownMenu }); 2585 }, 2586 toggleNavLinksTabIndex(enabled = true) { 2587 this.elements.$links.attr("tabindex", enabled ? 0 : -1); 2588 }, 2589 toggleMenu(show) { 2590 var isDropdownVisible = this.elements.$menuToggle.hasClass("elementor-active"); 2591 if ("boolean" !== typeof show) show = !isDropdownVisible; 2592 this.elements.$menuToggle.attr("aria-expanded", show); 2593 this.elements.$dropdownMenu.attr("aria-hidden", !show); 2594 this.elements.$menuToggle.toggleClass("elementor-active", show); 2595 this.toggleNavLinksTabIndex(show); 2596 this.menuHeightController.reassignMobileMenuHeight(this); 2597 if (show && this.getElementSettings("full_width")) this.stretchElement.stretch(); 2598 }, 2599 triggerClickOnEnterSpace(event) { 2600 if (13 === event.keyCode || 32 === event.keyCode) { 2601 event.currentTarget.click(); 2602 event.stopPropagation(); 2603 } 2604 }, 2605 stretchMenu() { 2606 if (this.getElementSettings("full_width")) { 2607 this.stretchElement.stretch(); 2608 this.elements.$dropdownMenu.css("top", this.elements.$menuToggle.outerHeight()); 2609 } else this.stretchElement.reset(); 2610 }, 2611 onInit() { 2612 this.menuHeightController = new elementorProFrontend.utils.DropdownMenuHeightController(this.dropdownMenuHeightControllerConfig()); 2613 elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments); 2614 if (!this.elements.$menu.length) return; 2615 this.elements.$menu.smartmenus({ 2616 subIndicators: false, 2617 subMenusMaxWidth: "1000px" 2618 }); 2619 this.initStretchElement();
2620 this.stretchMenu(); 2621 if (!elementorFrontend.isEditMode()) { 2622 const classes = this.getSettings("classes"); 2623 this.anchorLinks = new AnchorLinks(this.elements.$anchorLink, classes); 2624 this.anchorLinks.initialize(); 2625 } 2626 }, 2627 onElementChange(propertyName) { 2628 if ("full_width" === propertyName) this.stretchMenu(); 2629 } 2630 }); 2631 })); 2632 //#endregion 2633 //#region modules/nav-menu/assets/js/frontend/frontend.js 2634 var frontend_default$15 = class extends elementorModules.Module { 2635 static { 2636 __name(this, "default"); 2637 } 2638 constructor() { 2639 super(); 2640 if (jQuery.fn.smartmenus) { 2641 jQuery.SmartMenus.prototype.isCSSOn = function() { 2642 return true; 2643 }; 2644 if (elementorFrontend.config.is_rtl) jQuery.fn.smartmenus.defaults.rightToLeftSubMenus = true; 2645 } 2646 elementorFrontend.elementsHandler.attachHandler("nav-menu", () => __vitePreload(() => Promise.resolve().then(() => (init_nav_menu(), nav_menu_exports)), void 0)); 2647 } 2648 }; 2649 //#endregion 2650 //#region modules/popup/assets/js/frontend/triggers/base.js 2651 var base_default$1 = class extends elementorModules.Module { 2652 static { 2653 __name(this, "default"); 2654 } 2655 constructor(settings, callback) { 2656 super(settings); 2657 this.callback = callback; 2658 } 2659 getTriggerSetting(settingKey) { 2660 return this.getSettings(this.getName() + "_" + settingKey); 2661 } 2662 }; 2663 //#endregion 2664 //#region modules/popup/assets/js/frontend/triggers/page-load.js 2665 var page_load_default = class extends base_default$1 { 2666 static { 2667 __name(this, "default"); 2668 } 2669 getName() { 2670 return "page_load"; 2671 } 2672 run() { 2673 this.timeout = setTimeout(this.callback, this.getTriggerSetting("delay") * 1e3); 2674 } 2675 destroy() { 2676 clearTimeout(this.timeout); 2677 } 2678 }; 2679 //#endregion 2680 //#region modules/popup/assets/js/frontend/triggers/scrolling.js 2681 var scrolling_default = class extends base_default$1 { 2682 static { 2683 __name(this, "default"); 2684 } 2685 constructor(...args) { 2686 super(...args); 2687 this.checkScroll = this.checkScroll.bind(this); 2688 this.lastScrollOffset = 0; 2689 } 2690 getName() { 2691 return "scrolling"; 2692 } 2693 checkScroll() { 2694 const scrollDirection = scrollY > this.lastScrollOffset ? "down" : "up"; 2695 const requestedDirection = this.getTriggerSetting("direction"); 2696 this.lastScrollOffset = scrollY; 2697 if (scrollDirection !== requestedDirection) return; 2698 if ("up" === scrollDirection) { 2699 this.callback(); 2700 return; 2701 } 2702 const fullScroll = elementorFrontend.elements.$document.height() - innerHeight; 2703 if (scrollY / fullScroll * 100 >= this.getTriggerSetting("offset")) this.callback(); 2704 } 2705 run() { 2706 elementorFrontend.elements.$window.on("scroll", this.checkScroll); 2707 } 2708 destroy() { 2709 elementorFrontend.elements.$window.off("scroll", this.checkScroll); 2710 } 2711 }; 2712 //#endregion 2713 //#region modules/popup/assets/js/frontend/triggers/scrolling-to.js 2714 var scrolling_to_default = class extends base_default$1 { 2715 static { 2716 __name(this, "default"); 2717 } 2718 getName() { 2719 return "scrolling_to"; 2720 } 2721 run() { 2722 let $targetElement; 2723 try { 2724 $targetElement = jQuery(this.getTriggerSetting("selector")); 2725 } catch (e) { 2726 return; 2727 } 2728 if ($targetElement.length) { 2729 this.setUpIntersectionObserver(); 2730 this.observer.observe($targetElement[0]); 2731 } 2732 } 2733 setUpIntersectionObserver() { 2734 this.observer = new IntersectionObserver((entries) => { 2735 entries.forEach((entry) => { 2736 if (entry.isIntersecting) this.callback(); 2737 }); 2738 }); 2739 } 2740 destroy() { 2741 if (this.observer) this.observer.disconnect(); 2742 } 2743 }; 2744 //#endregion 2745 //#region modules/popup/assets/js/frontend/triggers/click.js 2746 var click_default = class extends base_default$1 { 2747 static { 2748 __name(this, "default"); 2749 } 2750 constructor(...args) { 2751 super(...args); 2752 this.checkClick = this.checkClick.bind(this); 2753 this.clicksCount = 0; 2754 } 2755 getName() { 2756 return "click"; 2757 } 2758 checkClick() { 2759 this.clicksCount++; 2760 if (this.clicksCount === this.getTriggerSetting("times")) this.callback(); 2761 } 2762 run() { 2763 elementorFrontend.elements.$body.on("click", this.checkClick); 2764 } 2765 destroy() { 2766 elementorFrontend.elements.$body.off("click", this.checkClick); 2767 } 2768 }; 2769 //#endregion 2770 //#region modules/popup/assets/js/frontend/triggers/inactivity.js 2771 var inactivity_default = class extends base_default$1 { 2772 static { 2773 __name(this, "default"); 2774 } 2775 constructor(...args) { 2776 super(...args); 2777 this.restartTimer = this.restartTimer.bind(this); 2778 } 2779 getName() { 2780 return "inactivity"; 2781 } 2782 run() { 2783 this.startTimer(); 2784 elementorFrontend.elements.$document.on("keypress mousemove", this.restartTimer); 2785 } 2786 startTimer() { 2787 this.timeOut = setTimeout(this.callback, this.getTriggerSetting("time") * 1e3); 2788 } 2789 clearTimer() { 2790 clearTimeout(this.timeOut); 2791 } 2792 restartTimer() { 2793 this.clearTimer(); 2794 this.startTimer(); 2795 } 2796 destroy() { 2797 this.clearTimer(); 2798 elementorFrontend.elements.$document.off("keypress mousemove", this.restartTimer); 2799 } 2800 }; 2801 //#endregion 2802 //#region modules/popup/assets/js/frontend/triggers/exit-intent.js 2803 var exit_intent_default = class extends base_default$1 { 2804 static { 2805 __name(this, "default"); 2806 } 2807 constructor(...args) { 2808 super(...args); 2809 this.detectExitIntent = this.detectExitIntent.bind(this); 2810 } 2811 getName() { 2812 return "exit_intent"; 2813 }
2814 detectExitIntent(event) { 2815 if (event.clientY <= 0) this.callback(); 2816 } 2817 run() { 2818 elementorFrontend.elements.$window.on("mouseleave", this.detectExitIntent); 2819 } 2820 destroy() { 2821 elementorFrontend.elements.$window.off("mouseleave", this.detectExitIntent); 2822 } 2823 }; 2824 //#endregion 2825 //#region modules/popup/assets/js/frontend/triggers/adblock-detection.js 2826 var adblock_detection_default = class extends base_default$1 { 2827 static { 2828 __name(this, "default"); 2829 } 2830 getName() { 2831 return "adblock_detection"; 2832 } 2833 generateRandomString() { 2834 const chars = "abcdefghijklmnopqrstuvwxyz0123456789"; 2835 let result = ""; 2836 for (let i = 0; i < 6; i++) { 2837 const randomIndex = Math.floor(Math.random() * 36); 2838 result += chars[randomIndex]; 2839 } 2840 return result; 2841 } 2842 hasAdblock() { 2843 var _a; 2844 const elementId = `elementor-adblock-detection-${this.generateRandomString()}`; 2845 this.createEmptyAdBlockElement(elementId); 2846 const tempAdBlockEle = document.querySelector(`#${elementId}`); 2847 if (!tempAdBlockEle) return true; 2848 const hasAdBlock = "none" === ((_a = window.getComputedStyle(tempAdBlockEle)) == null ? void 0 : _a.display); 2849 this.removeEmptyAdBlockElement(tempAdBlockEle); 2850 return hasAdBlock; 2851 } 2852 createEmptyAdBlockElement(elementId) { 2853 const tempAdDiv = document.createElement("div"); 2854 tempAdDiv.id = elementId; 2855 tempAdDiv.className = "ad-box"; 2856 tempAdDiv.style.position = "fixed"; 2857 tempAdDiv.style.top = "0"; 2858 tempAdDiv.style.left = "0"; 2859 tempAdDiv.setAttribute("aria-hidden", "true"); 2860 tempAdDiv.innerHTML = " "; 2861 document.body.appendChild(tempAdDiv); 2862 } 2863 removeEmptyAdBlockElement(tempAdBlockEle) { 2864 tempAdBlockEle.remove(); 2865 } 2866 run() { 2867 this.timeout = setTimeout(() => { 2868 if (this.hasAdblock()) this.callback(); 2869 }, this.getTriggerSetting("delay") * 1e3); 2870 } 2871 destroy() { 2872 clearTimeout(this.timeout); 2873 } 2874 }; 2875 //#endregion 2876 //#region modules/popup/assets/js/frontend/triggers.js 2877 var triggers_default = class extends elementorModules.Module { 2878 static { 2879 __name(this, "default"); 2880 } 2881 constructor(settings, document) { 2882 super(settings); 2883 this.document = document; 2884 this.triggers = []; 2885 this.triggerClasses = { 2886 page_load: page_load_default, 2887 scrolling: scrolling_default, 2888 scrolling_to: scrolling_to_default, 2889 click: click_default, 2890 inactivity: inactivity_default, 2891 exit_intent: exit_intent_default, 2892 adblock_detection: adblock_detection_default 2893 }; 2894 this.runTriggers(); 2895 } 2896 runTriggers() { 2897 const settings = this.getSettings(); 2898 jQuery.each(this.triggerClasses, (key, TriggerClass) => { 2899 if (!settings[key]) return; 2900 const trigger = new TriggerClass(settings, () => this.onTriggerFired()); 2901 trigger.run(); 2902 this.triggers.push(trigger); 2903 }); 2904 } 2905 destroyTriggers() { 2906 this.triggers.forEach((trigger) => trigger.destroy()); 2907 this.triggers = []; 2908 } 2909 onTriggerFired() { 2910 this.document.showModal(true); 2911 this.destroyTriggers(); 2912 } 2913 }; 2914 //#endregion 2915 //#region modules/popup/assets/js/frontend/timing/base.js 2916 var base_default = class extends elementorModules.Module { 2917 static { 2918 __name(this, "default"); 2919 } 2920 constructor(settings, document) { 2921 super(settings); 2922 this.document = document; 2923 } 2924 getTimingSetting(settingKey) { 2925 return this.getSettings(this.getName() + "_" + settingKey); 2926 } 2927 }; 2928 //#endregion 2929 //#region modules/popup/assets/js/frontend/timing/page-views.js 2930 var page_views_default = class extends base_default { 2931 static { 2932 __name(this, "default"); 2933 } 2934 getName() { 2935 return "page_views"; 2936 } 2937 check() { 2938 const pageViews = elementorFrontend.storage.get("pageViews"); 2939 const name = this.getName(); 2940 let initialPageViews = this.document.getStorage(name + "_initialPageViews"); 2941 if (!initialPageViews) { 2942 this.document.setStorage(name + "_initialPageViews", pageViews); 2943 initialPageViews = pageViews; 2944 } 2945 return pageViews - initialPageViews >= this.getTimingSetting("views"); 2946 } 2947 }; 2948 //#endregion 2949 //#region modules/popup/assets/js/frontend/timing/sessions.js 2950 var sessions_default = class extends base_default { 2951 static { 2952 __name(this, "default"); 2953 } 2954 getName() { 2955 return "sessions"; 2956 } 2957 check() { 2958 const sessions = elementorFrontend.storage.get("sessions"); 2959 const name = this.getName(); 2960 let initialSessions = this.document.getStorage(name + "_initialSessions"); 2961 if (!initialSessions) { 2962 this.document.setStorage(name + "_initialSessions", sessions); 2963 initialSessions = sessions; 2964 } 2965 return sessions - initialSessions >= this.getTimingSetting("sessions"); 2966 } 2967 }; 2968 //#endregion 2969 //#region modules/popup/assets/js/frontend/timing/url.js 2970 var url_default = class extends base_default { 2971 static { 2972 __name(this, "default"); 2973 } 2974 getName() { 2975 return "url"; 2976 } 2977 check() { 2978 const url = this.getTimingSetting("url"); 2979 const action = this.getTimingSetting("action"); 2980 const referrer = document.referrer; 2981 if ("regex" !== action) return "hide" === action ^ -1 !== referrer.indexOf(url); 2982 let regexp; 2983 try { 2984 regexp = new RegExp(url); 2985 } catch (e) { 2986 return false;
2987 } 2988 return regexp.test(referrer); 2989 } 2990 }; 2991 //#endregion 2992 //#region modules/popup/assets/js/frontend/timing/sources.js 2993 var sources_default = class extends base_default { 2994 static { 2995 __name(this, "default"); 2996 } 2997 getName() { 2998 return "sources"; 2999 } 3000 check() { 3001 const sources = this.getTimingSetting("sources"); 3002 if (3 === sources.length) return true; 3003 const referrer = document.referrer.replace(/https?:\/\/(?:www\.)?/, ""); 3004 if (0 === referrer.indexOf(location.host.replace("www.", ""))) return -1 !== sources.indexOf("internal"); 3005 if (-1 !== sources.indexOf("external")) return true; 3006 if (-1 !== sources.indexOf("search")) return /^(google|yahoo|bing|yandex|baidu)\./.test(referrer); 3007 return false; 3008 } 3009 }; 3010 //#endregion 3011 //#region modules/popup/assets/js/frontend/timing/logged-in.js 3012 var logged_in_default = class extends base_default { 3013 static { 3014 __name(this, "default"); 3015 } 3016 getName() { 3017 return "logged_in"; 3018 } 3019 check() { 3020 const userConfig = elementorFrontend.config.user; 3021 if (!userConfig) return true; 3022 if ("all" === this.getTimingSetting("users")) return false; 3023 return !this.getTimingSetting("roles").filter((role) => -1 !== userConfig.roles.indexOf(role)).length; 3024 } 3025 }; 3026 //#endregion 3027 //#region modules/popup/assets/js/frontend/timing/devices.js 3028 var devices_default = class extends base_default { 3029 static { 3030 __name(this, "default"); 3031 } 3032 getName() { 3033 return "devices"; 3034 } 3035 check() { 3036 return -1 !== this.getTimingSetting("devices").indexOf(elementorFrontend.getCurrentDeviceMode()); 3037 } 3038 }; 3039 //#endregion 3040 //#region modules/popup/assets/js/frontend/timing/times-utils.js 3041 var TimesUtils = class { 3042 constructor(args) { 3043 this.uniqueId = args.uniqueId; 3044 this.settings = args.settings; 3045 this.storage = args.storage; 3046 } 3047 getTimeFramesInSecounds(timeFrame) { 3048 return { 3049 day: 86400, 3050 week: 604800, 3051 month: 2628288 3052 }[timeFrame]; 3053 } 3054 setExpiration(name, value, timeFrame) { 3055 if (!this.storage.get(name)) { 3056 const options = { lifetimeInSeconds: this.getTimeFramesInSecounds(timeFrame) }; 3057 this.storage.set(name, value, options); 3058 return; 3059 } 3060 this.storage.set(name, value); 3061 } 3062 getImpressionsCount() { 3063 var _a; 3064 const impressionCount = (_a = this.storage.get(this.uniqueId)) != null ? _a : 0; 3065 return parseInt(impressionCount); 3066 } 3067 incrementImpressionsCount() { 3068 var _a; 3069 var _b; 3070 if (!this.settings.period) this.storage.set("times", ((_a = this.storage.get("times")) != null ? _a : 0) + 1); 3071 else if ("session" !== this.settings.period) { 3072 const impressionCount = this.getImpressionsCount(); 3073 this.setExpiration(this.uniqueId, impressionCount + 1, this.settings.period); 3074 } else sessionStorage.setItem(this.uniqueId, parseInt((_b = sessionStorage.getItem(this.uniqueId)) != null ? _b : 0) + 1); 3075 } 3076 shouldCountOnOpen() { 3077 if (this.settings.countOnOpen) this.incrementImpressionsCount(); 3078 } 3079 shouldDisplayPerTimeFrame() { 3080 if (this.getImpressionsCount() < this.settings.showsLimit) { 3081 this.shouldCountOnOpen(); 3082 return true; 3083 } 3084 return false; 3085 } 3086 shouldDisplayPerSession() { 3087 var _a; 3088 const impressionCount = (_a = sessionStorage.getItem(this.uniqueId)) != null ? _a : 0; 3089 if (parseInt(impressionCount) < this.settings.showsLimit) { 3090 this.shouldCountOnOpen(); 3091 return true; 3092 } 3093 return false; 3094 } 3095 shouldDisplayBackwordCompatible(impressionCount = 0, showsLimit) { 3096 const shouldDisplay = parseInt(impressionCount) < parseInt(showsLimit); 3097 this.shouldCountOnOpen(); 3098 return shouldDisplay; 3099 } 3100 }; 3101 //#endregion 3102 //#region modules/popup/assets/js/frontend/timing/times.js 3103 var times_default = class extends base_default { 3104 static { 3105 __name(this, "default"); 3106 } 3107 constructor(...args) { 3108 super(...args); 3109 this.uniqueId = `popup-${this.document.getSettings("id")}-impressions-count`; 3110 const { times_count: countOnOpen, times_period: period, times_times: showsLimit } = this.getSettings(); 3111 this.settings = { 3112 countOnOpen, 3113 period, 3114 showsLimit: parseInt(showsLimit) 3115 }; 3116 if ("" === this.settings.period) this.settings.period = false;
3117 if (["", "close"].includes(this.settings.countOnOpen)) { 3118 this.settings.countOnOpen = false; 3119 this.onPopupHide(); 3120 } else this.settings.countOnOpen = true; 3121 this.utils = new TimesUtils({ 3122 uniqueId: this.uniqueId, 3123 settings: this.settings, 3124 storage: elementorFrontend.storage 3125 }); 3126 } 3127 getName() { 3128 return "times"; 3129 } 3130 check() { 3131 if (!this.settings.period) { 3132 const impressionCount = this.document.getStorage("times") || 0; 3133 const showsLimit = this.getTimingSetting("times"); 3134 return this.utils.shouldDisplayBackwordCompatible(impressionCount, showsLimit); 3135 } 3136 if ("session" !== this.settings.period) { 3137 if (!this.utils.shouldDisplayPerTimeFrame()) return false; 3138 } else if (!this.utils.shouldDisplayPerSession()) return false; 3139 return true; 3140 } 3141 onPopupHide() { 3142 window.addEventListener("elementor/popup/hide", () => { 3143 this.utils.incrementImpressionsCount(); 3144 }); 3145 } 3146 }; 3147 //#endregion 3148 //#region modules/popup/assets/js/frontend/timing/browsers.js 3149 var browsers_default = class extends base_default { 3150 static { 3151 __name(this, "default"); 3152 } 3153 getName() { 3154 return "browsers"; 3155 } 3156 check() { 3157 if ("all" === this.getTimingSetting("browsers")) return true; 3158 const targetedBrowsers = this.getTimingSetting("browsers_options"); 3159 const browserDetectionFlags = elementorFrontend.utils.environment; 3160 return targetedBrowsers.some((browserName) => browserDetectionFlags[browserName]); 3161 } 3162 }; 3163 //#endregion 3164 //#region modules/popup/assets/js/frontend/timing/schedule-utils.js 3165 var __defProp$4 = Object.defineProperty; 3166 var __defNormalProp$4 = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp$4(obj, key, { 3167 enumerable: true, 3168 configurable: true, 3169 writable: true, 3170 value 3171 }) : obj[key] = value, "__defNormalProp"); 3172 var __publicField$3 = /* @__PURE__ */ __name((obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value), "__publicField"); 3173 var ScheduleUtils = class { 3174 constructor(args) { 3175 __publicField$3(this, "shouldDisplay", () => { 3176 if (!this.settings.startDate && !this.settings.endDate) return true; 3177 const now = this.getCurrentDateTime(); 3178 if ((!this.settings.startDate || now >= this.settings.startDate) && (!this.settings.endDate || now <= this.settings.endDate)) return true; 3179 return false; 3180 }); 3181 this.settings = args.settings; 3182 } 3183 getCurrentDateTime() { 3184 let now = /* @__PURE__ */ new Date(); 3185 if ("site" === this.settings.timezone && this.settings.serverDatetime) now = new Date(this.settings.serverDatetime); 3186 return now; 3187 } 3188 }; 3189 //#endregion 3190 //#region modules/popup/assets/js/frontend/timing/schedule.js 3191 var schedule_default = class extends base_default { 3192 static { 3193 __name(this, "default"); 3194 } 3195 constructor(...args) { 3196 super(...args); 3197 const { schedule_timezone: timezone, schedule_start_date: startDate, schedule_end_date: endDate, schedule_server_datetime: serverDatetime } = this.getSettings(); 3198 this.settings = { 3199 timezone, 3200 startDate: startDate ? new Date(startDate) : false, 3201 endDate: endDate ? new Date(endDate) : false, 3202 serverDatetime: serverDatetime ? new Date(serverDatetime) : false 3203 }; 3204 this.scheduleUtils = new ScheduleUtils({ settings: this.settings }); 3205 } 3206 getName() { 3207 return "schedule"; 3208 } 3209 check() { 3210 return this.scheduleUtils.shouldDisplay(); 3211 } 3212 }; 3213 //#endregion 3214 //#region modules/popup/assets/js/frontend/timing.js 3215 var timing_default = class extends elementorModules.Module { 3216 static { 3217 __name(this, "default"); 3218 } 3219 constructor(settings, document) { 3220 super(settings); 3221 this.document = document; 3222 this.timingClasses = { 3223 page_views: page_views_default, 3224 sessions: sessions_default, 3225 url: url_default, 3226 sources: sources_default, 3227 logged_in: logged_in_default, 3228 devices: devices_default, 3229 times: times_default, 3230 browsers: browsers_default, 3231 schedule: schedule_default 3232 }; 3233 } 3234 check() { 3235 const settings = this.getSettings(); 3236 let checkPassed = true; 3237 jQuery.each(this.timingClasses, (key, TimingClass) => { 3238 if (!settings[key]) return; 3239 if (!new TimingClass(settings, this.document).check()) checkPassed = false;
3240 }); 3241 return checkPassed; 3242 } 3243 }; 3244 //#endregion 3245 //#region assets/dev/js/frontend/utils/icons/manager.js 3246 var __defProp$3 = Object.defineProperty; 3247 var __defNormalProp$3 = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp$3(obj, key, { 3248 enumerable: true, 3249 configurable: true, 3250 writable: true, 3251 value 3252 }) : obj[key] = value, "__defNormalProp"); 3253 var __publicField$2 = /* @__PURE__ */ __name((obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value), "__publicField"); 3254 var _IconsManager = class _IconsManager { 3255 constructor(elementsPrefix) { 3256 this.prefix = `${elementsPrefix}-`; 3257 if (!_IconsManager.symbolsContainer) { 3258 const symbolsContainerId = "e-font-icon-svg-symbols"; 3259 _IconsManager.symbolsContainer = document.getElementById(symbolsContainerId); 3260 if (!_IconsManager.symbolsContainer) { 3261 _IconsManager.symbolsContainer = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 3262 _IconsManager.symbolsContainer.setAttributeNS(null, "style", "display: none;"); 3263 _IconsManager.symbolsContainer.setAttributeNS(null, "class", symbolsContainerId); 3264 document.body.appendChild(_IconsManager.symbolsContainer); 3265 } 3266 } 3267 } 3268 createSvgElement(name, { path, width, height }) { 3269 const elementName = this.prefix + name; 3270 const elementSelector = "#" + this.prefix + name; 3271 if (!_IconsManager.iconsUsageList.includes(elementName)) { 3272 if (!_IconsManager.symbolsContainer.querySelector(elementSelector)) { 3273 const symbol = document.createElementNS("http://www.w3.org/2000/svg", "symbol"); 3274 symbol.id = elementName; 3275 symbol.innerHTML = "<path d=\"" + path + "\"></path>"; 3276 symbol.setAttributeNS(null, "viewBox", "0 0 " + width + " " + height); 3277 _IconsManager.symbolsContainer.appendChild(symbol); 3278 } 3279 _IconsManager.iconsUsageList.push(elementName); 3280 } 3281 const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 3282 svg.innerHTML = "<use xlink:href=\"" + elementSelector + "\" />"; 3283 svg.setAttributeNS(null, "class", "e-font-icon-svg e-" + elementName); 3284 return svg; 3285 } 3286 }; 3287 __publicField$2(_IconsManager, "symbolsContainer"); 3288 __publicField$2(_IconsManager, "iconsUsageList", []); 3289 //#endregion 3290 //#region assets/dev/js/frontend/utils/icons/e-icons.js 3291 var iconsManager = new _IconsManager("eicon"); 3292 var close = { get element() { 3293 return iconsManager.createSvgElement("close", { 3294 path: "M742 167L500 408 258 167C246 154 233 150 217 150 196 150 179 158 167 167 154 179 150 196 150 212 150 229 154 242 171 254L408 500 167 742C138 771 138 800 167 829 196 858 225 858 254 829L496 587 738 829C750 842 767 846 783 846 800 846 817 842 829 829 842 817 846 804 846 783 846 767 842 750 829 737L588 500 833 258C863 229 863 200 833 171 804 137 775 137 742 167Z", 3295 width: 1e3, 3296 height: 1e3 3297 }); 3298 } }; 3299 //#endregion 3300 //#region assets/dev/js/frontend/utils/focusable-element-selectors.js 3301 function focusableElementSelectors() { 3302 return "audio, button, canvas, details, iframe, input, select, summary, textarea, video, [accesskey], a[href], area[href], [tabindex]"; 3303 } 3304 var init_focusable_element_selectors = __esmMin((() => {})); 3305 //#endregion 3306 //#region assets/dev/js/frontend/utils/modal-keyboard-handler.js 3307 var ModalKeyboardHandler; 3308 var init_modal_keyboard_handler = __esmMin((() => { 3309 init_focusable_element_selectors(); 3310 init_defineProperty(); 3311 ModalKeyboardHandler = class { 3312 constructor(elementConfig) { 3313 _defineProperty(this, "lastFocusableElement", null); 3314 _defineProperty(this, "firstFocusableElement", null); 3315 _defineProperty(this, "modalTriggerElement", null); 3316 this.config = elementConfig; 3317 this.changeFocusAfterAnimation = false; 3318 } 3319 onOpenModal() { 3320 this.initializeElements(); 3321 this.setTriggerElement(); 3322 this.changeFocusAfterAnimation = "popup" === this.config.modalType && !!this.config.hasEntranceAnimation; 3323 if (!this.changeFocusAfterAnimation) this.changeFocus(); 3324 this.bindEvents(); 3325 } 3326 onCloseModal() { 3327 elementorFrontend.elements.$window.off("keydown", this.onKeyDownPressed.bind(this)); 3328 if (this.modalTriggerElement) this.setFocusToElement(this.modalTriggerElement); 3329 } 3330 bindEvents() { 3331 elementorFrontend.elements.$window.on("keydown", this.onKeyDownPressed.bind(this)); 3332 if (this.changeFocusAfterAnimation) this.config.$modalElements.on("animationend animationcancel", this.changeFocus.bind(this)); 3333 if ("popup" === this.config.modalType) this.onPopupCloseEvent(); 3334 } 3335 onPopupCloseEvent() { 3336 elementorFrontend.elements.$window.on("elementor/popup/hide", this.onCloseModal.bind(this)); 3337 } 3338 getFocusableElements() { 3339 const selectorFocusedElements = "popup" === this.config.modalType ? ":focusable" : focusableElementSelectors(); 3340 return this.config.$modalElements.find(selectorFocusedElements); 3341 } 3342 initializeElements() { 3343 const $focusableElements = this.getFocusableElements(); 3344 if (!$focusableElements.length) return; 3345 this.lastFocusableElement = $focusableElements[$focusableElements.length - 1]; 3346 this.firstFocusableElement = $focusableElements[0]; 3347 } 3348 setTriggerElement() { 3349 if (!!elementorFrontend.elements.window.document.activeElement) this.modalTriggerElement = elementorFrontend.elements.window.document.activeElement; 3350 else this.modalTriggerElement = null; 3351 } 3352 changeFocus() { 3353 if (!!this.firstFocusableElement) this.setFocusToElement(this.firstFocusableElement); 3354 else { 3355 this.config.$elementWrapper.attr("tabindex", "0"); 3356 this.setFocusToElement(this.config.$elementWrapper[0]); 3357 } 3358 } 3359 onKeyDownPressed(keyDownEvent) { 3360 const TAB_KEY = 9; 3361 const isShiftPressed = keyDownEvent.shiftKey; 3362 const isTabPressed = "Tab" === keyDownEvent.key || TAB_KEY === keyDownEvent.keyCode; 3363 const isContentWrapperFocused = "0" === this.config.$elementWrapper.attr("tabindex");
3364 if (isTabPressed && isContentWrapperFocused) keyDownEvent.preventDefault(); 3365 else if (isTabPressed) this.onTabKeyPressed(isTabPressed, isShiftPressed, keyDownEvent); 3366 } 3367 onTabKeyPressed(isTabPressed, isShiftPressed, keyDownEvent) { 3368 if (elementorFrontend.isEditMode()) this.initializeElements(); 3369 const activeElement = elementorFrontend.elements.window.document.activeElement; 3370 if (isShiftPressed) { 3371 if (activeElement === this.firstFocusableElement) { 3372 this.setFocusToElement(this.lastFocusableElement); 3373 keyDownEvent.preventDefault(); 3374 } 3375 } else if (activeElement === this.lastFocusableElement) { 3376 this.setFocusToElement(this.firstFocusableElement); 3377 keyDownEvent.preventDefault(); 3378 } 3379 } 3380 setFocusToElement(element) { 3381 const focusDelayToEnsureThatAllAnimationsHaveFinished = "popup" === this.config.modalType ? 250 : 100; 3382 setTimeout(() => { 3383 element === null || element === void 0 || element.focus(); 3384 }, focusDelayToEnsureThatAllAnimationsHaveFinished); 3385 } 3386 }; 3387 })); 3388 //#endregion 3389 //#region modules/popup/assets/js/frontend/document.js 3390 init_modal_keyboard_handler(); 3391 init_defineProperty(); 3392 init_asyncToGenerator(); 3393 var document_default = class extends elementorModules.frontend.Document { 3394 static { 3395 __name(this, "default"); 3396 } 3397 constructor(..._args) { 3398 super(..._args); 3399 _defineProperty(this, "keyboardHandler", null); 3400 } 3401 bindEvents() { 3402 const openSelector = this.getDocumentSettings("open_selector"); 3403 if (openSelector) elementorFrontend.elements.$body.on("click", openSelector, this.showModal.bind(this)); 3404 } 3405 startTiming() { 3406 if (new timing_default(this.getDocumentSettings("timing"), this).check()) this.initTriggers(); 3407 } 3408 initTriggers() { 3409 this.triggers = new triggers_default(this.getDocumentSettings("triggers"), this); 3410 } 3411 showModal(avoidMultiple) { 3412 const settings = this.getDocumentSettings(); 3413 if (!this.isEdit) { 3414 if (!elementorFrontend.isWPPreviewMode()) { 3415 if (this.getStorage("disable")) return; 3416 if (avoidMultiple && elementorProFrontend.modules.popup.popupPopped && settings.avoid_multiple_popups) return; 3417 } 3418 this.$element = jQuery(this.elementHTML); 3419 this.elements.$elements = this.$element.find(this.getSettings("selectors.elements")); 3420 } 3421 const modal = this.getModal(); 3422 const $closeButton = modal.getElements("closeButton"); 3423 modal.setMessage(this.$element).show(); 3424 if (!this.isEdit) { 3425 if (settings.close_button_delay) { 3426 $closeButton.hide(); 3427 clearTimeout(this.closeButtonTimeout); 3428 this.closeButtonTimeout = setTimeout(() => $closeButton.show(), settings.close_button_delay * 1e3); 3429 } 3430 super.runElementsHandlers(); 3431 } 3432 this.setEntranceAnimation(); 3433 if (!settings.timing || !settings.timing.times_count) this.countTimes(); 3434 elementorProFrontend.modules.popup.popupPopped = true; 3435 if (!this.isEdit && settings.a11y_navigation) this.handleKeyboardA11y(); 3436 } 3437 setEntranceAnimation() { 3438 const $widgetContent = this.getModal().getElements("widgetContent"); 3439 const settings = this.getDocumentSettings(); 3440 const newAnimation = elementorFrontend.getCurrentDeviceSetting(settings, "entrance_animation"); 3441 if (this.currentAnimation) $widgetContent.removeClass(this.currentAnimation); 3442 this.currentAnimation = newAnimation; 3443 if (!newAnimation) return; 3444 const animationDuration = settings.entrance_animation_duration.size; 3445 $widgetContent.addClass(newAnimation); 3446 setTimeout(() => $widgetContent.removeClass(newAnimation), animationDuration * 1e3); 3447 } 3448 handleKeyboardA11y() { 3449 if (!this.keyboardHandler) this.keyboardHandler = new ModalKeyboardHandler(this.getKeyboardHandlingConfig()); 3450 this.keyboardHandler.onOpenModal(); 3451 } 3452 setExitAnimation() { 3453 const modal = this.getModal(); 3454 const settings = this.getDocumentSettings(); 3455 const $widgetContent = modal.getElements("widgetContent"); 3456 const newAnimation = elementorFrontend.getCurrentDeviceSetting(settings, "exit_animation"); 3457 const animationDuration = newAnimation ? settings.entrance_animation_duration.size : 0; 3458 setTimeout(() => { 3459 if (newAnimation) $widgetContent.removeClass(newAnimation + " reverse"); 3460 if (!this.isEdit) { 3461 this.$element.remove(); 3462 modal.getElements("widget").hide(); 3463 } 3464 }, animationDuration * 1e3); 3465 if (newAnimation) $widgetContent.addClass(newAnimation + " reverse"); 3466 } 3467 initModal() { 3468 let modal; 3469 this.getModal = () => { 3470 if (!modal) { 3471 const settings = this.getDocumentSettings();
3472 const id = this.getSettings("id"); 3473 const triggerPopupEvent = (eventType) => { 3474 const event = "elementor/popup/" + eventType; 3475 elementorFrontend.elements.$document.trigger(event, [id, this]); 3476 window.dispatchEvent(new CustomEvent(event, { detail: { 3477 id, 3478 instance: this 3479 } })); 3480 }; 3481 let classes = "elementor-popup-modal"; 3482 if (settings.classes) classes += " " + settings.classes; 3483 const modalProperties = { 3484 id: "elementor-popup-modal-" + id, 3485 className: classes, 3486 closeButton: true, 3487 preventScroll: settings.prevent_scroll, 3488 onShow: () => triggerPopupEvent("show"), 3489 onHide: () => triggerPopupEvent("hide"), 3490 effects: { 3491 hide: () => { 3492 if (settings.timing && settings.timing.times_count) this.countTimes(); 3493 this.setExitAnimation(); 3494 }, 3495 show: "show" 3496 }, 3497 hide: { 3498 auto: !!settings.close_automatically, 3499 autoDelay: settings.close_automatically * 1e3, 3500 onBackgroundClick: !settings.prevent_close_on_background_click, 3501 onOutsideClick: !settings.prevent_close_on_background_click, 3502 onEscKeyPress: !settings.prevent_close_on_esc_key, 3503 ignore: ".flatpickr-calendar" 3504 }, 3505 position: { enable: false } 3506 }; 3507 if (elementorFrontend.config.experimentalFeatures.e_font_icon_svg) modalProperties.closeButtonOptions = { iconElement: close.element }; 3508 modalProperties.closeButtonClass = "eicon-close"; 3509 modal = elementorFrontend.getDialogsManager().createWidget("lightbox", modalProperties); 3510 modal.getElements("widgetContent").addClass("animated"); 3511 const $closeButton = modal.getElements("closeButton"); 3512 if (this.isEdit) { 3513 $closeButton.off("click"); 3514 modal.hide = () => {}; 3515 } 3516 this.setCloseButtonPosition(); 3517 } 3518 return modal; 3519 }; 3520 } 3521 setCloseButtonPosition() { 3522 const modal = this.getModal(); 3523 const closeButtonPosition = this.getDocumentSettings("close_button_position"); 3524 modal.getElements("closeButton").prependTo(modal.getElements("outside" === closeButtonPosition ? "widget" : "widgetContent")); 3525 } 3526 disable() { 3527 this.setStorage("disable", true); 3528 } 3529 setStorage(key, value, options) { 3530 elementorFrontend.storage.set(`popup_${this.getSettings("id")}_${key}`, value, options); 3531 } 3532 getStorage(key, options) { 3533 return elementorFrontend.storage.get(`popup_${this.getSettings("id")}_${key}`, options); 3534 } 3535 countTimes() { 3536 const displayTimes = this.getStorage("times") || 0; 3537 this.setStorage("times", displayTimes + 1); 3538 } 3539 runElementsHandlers() {} 3540 onInit() { 3541 var _superprop_getOnInit = () => super.onInit; 3542 var _this = this; 3543 return _asyncToGenerator(function* () { 3544 _superprop_getOnInit().call(_this); 3545 if (!window.DialogsManager) yield elementorFrontend.utils.assetsLoader.load("script", "dialog"); 3546 _this.initModal(); 3547 if (_this.isEdit) { 3548 _this.showModal(); 3549 return; 3550 } 3551 _this.$element.show().remove(); 3552 _this.elementHTML = _this.$element[0].outerHTML; 3553 if (elementorFrontend.isEditMode()) return; 3554 if (elementorFrontend.isWPPreviewMode() && elementorFrontend.config.post.id === _this.getSettings("id")) { 3555 _this.showModal(); 3556 return; 3557 } 3558 _this.startTiming(); 3559 })(); 3560 } 3561 onSettingsChange(model) { 3562 const changedKey = Object.keys(model.changed)[0]; 3563 if (-1 !== changedKey.indexOf("entrance_animation")) this.setEntranceAnimation(); 3564 if ("exit_animation" === changedKey) this.setExitAnimation(); 3565 if ("close_button_position" === changedKey) this.setCloseButtonPosition(); 3566 } 3567 getEntranceAnimationDuration() { 3568 var _settings$entrance_an; 3569 const settings = this.getDocumentSettings(); 3570 const entranceAnimation = settings === null || settings === void 0 ? void 0 : settings.entrance_animation; 3571 if (!entranceAnimation || "" === entranceAnimation || "none" === entranceAnimation) return 0; 3572 const entranceAnimationDuration = settings === null || settings === void 0 || (_settings$entrance_an = settings.entrance_animation_duration) === null || _settings$entrance_an === void 0 ? void 0 : _settings$entrance_an.size; 3573 return !!entranceAnimationDuration ? Number(entranceAnimationDuration) : 0; 3574 } 3575 getKeyboardHandlingConfig() { 3576 return { 3577 $modalElements: this.getModal().getElements("widgetContent"), 3578 $elementWrapper: this.$element, 3579 hasEntranceAnimation: 0 !== this.getEntranceAnimationDuration(), 3580 modalType: "popup", 3581 modalId: this.$element.data("elementor-id") 3582 }; 3583 } 3584 }; 3585 //#endregion 3586 //#region modules/popup/assets/js/frontend/handlers/forms-action.js 3587 var forms_action_exports = /* @__PURE__ */ __exportAll({ default: () => forms_action_default }); 3588 var forms_action_default; 3589 var init_forms_action = __esmMin((() => { 3590 forms_action_default = elementorModules.frontend.handlers.Base.extend({ 3591 getDefaultSettings() { 3592 return { selectors: { form: ".elementor-form" } }; 3593 }, 3594 getDefaultElements() {
3595 var selectors = this.getSettings("selectors"); 3596 var elements = {}; 3597 elements.$form = this.$element.find(selectors.form); 3598 return elements; 3599 }, 3600 bindEvents() { 3601 this.elements.$form.on("submit_success", this.handleFormAction); 3602 }, 3603 handleFormAction(event, response) { 3604 if ("undefined" === typeof response.data.popup) return; 3605 const popupSettings = response.data.popup; 3606 if ("open" === popupSettings.action) return elementorProFrontend.modules.popup.showPopup(popupSettings); 3607 setTimeout(() => { 3608 return elementorProFrontend.modules.popup.closePopup(popupSettings, event); 3609 }, 1e3); 3610 } 3611 }); 3612 })); 3613 //#endregion 3614 //#region modules/popup/assets/js/frontend/frontend.js 3615 var frontend_default$14 = class extends elementorModules.Module { 3616 static { 3617 __name(this, "default"); 3618 } 3619 constructor() { 3620 super(); 3621 elementorFrontend.hooks.addAction("elementor/frontend/documents-manager/init-classes", this.addDocumentClass); 3622 elementorFrontend.elementsHandler.attachHandler("form", () => __vitePreload(() => Promise.resolve().then(() => (init_forms_action(), forms_action_exports)), void 0)); 3623 elementorFrontend.on("components:init", () => this.onFrontendComponentsInit()); 3624 if (this.shouldSetViewsAndSessions()) this.setViewsAndSessions(); 3625 } 3626 shouldSetViewsAndSessions() { 3627 return !elementorFrontend.isEditMode() && !elementorFrontend.isWPPreviewMode() && ElementorProFrontendConfig.popup.hasPopUps; 3628 } 3629 addDocumentClass(documentsManager) { 3630 documentsManager.addDocumentClass("popup", document_default); 3631 } 3632 setViewsAndSessions() { 3633 const pageViews = elementorFrontend.storage.get("pageViews") || 0; 3634 elementorFrontend.storage.set("pageViews", pageViews + 1); 3635 if (!elementorFrontend.storage.get("activeSession", { session: true })) { 3636 elementorFrontend.storage.set("activeSession", true, { session: true }); 3637 const sessions = elementorFrontend.storage.get("sessions") || 0; 3638 elementorFrontend.storage.set("sessions", sessions + 1); 3639 } 3640 } 3641 showPopup(settings, event) { 3642 const popup = elementorFrontend.documentsManager.documents[settings.id]; 3643 if (!popup) return; 3644 const modal = popup.getModal(); 3645 if (settings.toggle && modal.isVisible()) modal.hide(); 3646 else popup.showModal(null, event); 3647 } 3648 closePopup(settings, event) { 3649 const popupID = jQuery(event.target).parents("[data-elementor-type=\"popup\"]").data("elementorId"); 3650 if (!popupID) return; 3651 const document = elementorFrontend.documentsManager.documents[popupID]; 3652 document.getModal().hide(); 3653 if (settings.do_not_show_again) document.disable(); 3654 } 3655 onFrontendComponentsInit() { 3656 elementorFrontend.utils.urlActions.addAction("popup:open", (settings, event) => this.showPopup(settings, event)); 3657 elementorFrontend.utils.urlActions.addAction("popup:close", (settings, event) => this.closePopup(settings, event)); 3658 } 3659 }; 3660 //#endregion 3661 //#region modules/posts/assets/js/frontend/handlers/load-more.js 3662 var load_more_exports$1 = /* @__PURE__ */ __exportAll({ default: () => LoadMore }); 3663 var LoadMore; 3664 var init_load_more$1 = __esmMin((() => { 3665 LoadMore = class extends elementorModules.frontend.handlers.Base { 3666 getDefaultSettings() { 3667 return { 3668 selectors: { 3669 postsContainer: ".elementor-posts-container", 3670 postWrapperTag: "article", 3671 loadMoreButton: ".elementor-button", 3672 loadMoreSpinnerWrapper: ".e-load-more-spinner", 3673 loadMoreSpinner: ".e-load-more-spinner i, .e-load-more-spinner svg", 3674 loadMoreAnchor: ".e-load-more-anchor" 3675 }, 3676 classes: { 3677 loadMoreSpin: "eicon-animation-spin", 3678 loadMoreIsLoading: "e-load-more-pagination-loading", 3679 loadMorePaginationEnd: "e-load-more-pagination-end", 3680 loadMoreNoSpinner: "e-load-more-no-spinner" 3681 } 3682 }; 3683 } 3684 getDefaultElements() { 3685 const selectors = this.getSettings("selectors"); 3686 return { 3687 postsWidgetWrapper: this.$element[0], 3688 postsContainer: this.$element[0].querySelector(selectors.postsContainer), 3689 loadMoreButton: this.$element[0].querySelector(selectors.loadMoreButton), 3690 loadMoreSpinnerWrapper: this.$element[0].querySelector(selectors.loadMoreSpinnerWrapper),
3691 loadMoreSpinner: this.$element[0].querySelector(selectors.loadMoreSpinner), 3692 loadMoreAnchor: this.$element[0].querySelector(selectors.loadMoreAnchor) 3693 }; 3694 } 3695 bindEvents() { 3696 super.bindEvents(); 3697 if (!this.elements.loadMoreButton) return; 3698 this.elements.loadMoreButton.addEventListener("click", (event) => { 3699 if (this.isLoading) return; 3700 event.preventDefault(); 3701 this.handlePostsQuery(); 3702 }); 3703 } 3704 onInit() { 3705 super.onInit(); 3706 this.classes = this.getSettings("classes"); 3707 this.isLoading = false; 3708 const paginationType = this.getElementSettings("pagination_type"); 3709 if ("load_more_on_click" !== paginationType && "load_more_infinite_scroll" !== paginationType) return; 3710 this.isInfinteScroll = "load_more_infinite_scroll" === paginationType; 3711 this.isSpinnerAvailable = this.getElementSettings("load_more_spinner").value; 3712 if (!this.isSpinnerAvailable) this.elements.postsWidgetWrapper.classList.add(this.classes.loadMoreNoSpinner); 3713 if (this.isInfinteScroll) this.handleInfiniteScroll(); 3714 else if (this.elements.loadMoreSpinnerWrapper && this.elements.loadMoreButton) this.elements.loadMoreButton.insertAdjacentElement("beforeEnd", this.elements.loadMoreSpinnerWrapper); 3715 this.elementId = this.getID(); 3716 this.postId = elementorFrontendConfig.post.id; 3717 if (this.elements.loadMoreAnchor) { 3718 this.currentPage = parseInt(this.elements.loadMoreAnchor.getAttribute("data-page")); 3719 this.maxPage = parseInt(this.elements.loadMoreAnchor.getAttribute("data-max-page")); 3720 if (this.currentPage === this.maxPage || !this.currentPage) this.handleUiWhenNoPosts(); 3721 } 3722 } 3723 handleInfiniteScroll() { 3724 if (this.isEdit) return; 3725 this.observer = elementorModules.utils.Scroll.scrollObserver({ callback: (event) => { 3726 if (!event.isInViewport || this.isLoading) return; 3727 this.observer.unobserve(this.elements.loadMoreAnchor); 3728 this.handlePostsQuery().then(() => { 3729 if (this.currentPage !== this.maxPage) this.observer.observe(this.elements.loadMoreAnchor); 3730 }); 3731 } }); 3732 this.observer.observe(this.elements.loadMoreAnchor); 3733 } 3734 handleUiBeforeLoading() { 3735 this.isLoading = true; 3736 if (this.elements.loadMoreSpinner) this.elements.loadMoreSpinner.classList.add(this.classes.loadMoreSpin); 3737 this.elements.postsWidgetWrapper.classList.add(this.classes.loadMoreIsLoading); 3738 } 3739 handleUiAfterLoading() { 3740 this.isLoading = false; 3741 if (this.elements.loadMoreSpinner) this.elements.loadMoreSpinner.classList.remove(this.classes.loadMoreSpin); 3742 if (this.isInfinteScroll && this.elements.loadMoreSpinnerWrapper && this.elements.loadMoreAnchor) this.elements.loadMoreAnchor.insertAdjacentElement("afterend", this.elements.loadMoreSpinnerWrapper); 3743 this.elements.postsWidgetWrapper.classList.remove(this.classes.loadMoreIsLoading); 3744 } 3745 handleUiWhenNoPosts() { 3746 this.elements.postsWidgetWrapper.classList.add(this.classes.loadMorePaginationEnd); 3747 } 3748 afterInsertPosts() {} 3749 handleSuccessFetch(result) { 3750 this.handleUiAfterLoading(); 3751 const selectors = this.getSettings("selectors"); 3752 const postsElements = result.querySelectorAll(`[data-id="${this.elementId}"] ${selectors.postsContainer} > ${selectors.postWrapperTag}`); 3753 const nextPageUrl = result.querySelector(`[data-id="${this.elementId}"] .e-load-more-anchor`).getAttribute("data-next-page"); 3754 postsElements.forEach((element) => this.elements.postsContainer.append(element)); 3755 this.elements.loadMoreAnchor.setAttribute("data-page", this.currentPage); 3756 this.elements.loadMoreAnchor.setAttribute("data-next-page", nextPageUrl); 3757 if (this.currentPage === this.maxPage) this.handleUiWhenNoPosts(); 3758 this.afterInsertPosts(postsElements, result); 3759 } 3760 handlePostsQuery() { 3761 this.handleUiBeforeLoading(); 3762 this.currentPage++; 3763 const nextPageUrl = this.elements.loadMoreAnchor.getAttribute("data-next-page"); 3764 return fetch(nextPageUrl).then((response) => response.text()).then((html) => { 3765 const doc = new DOMParser().parseFromString(html, "text/html"); 3766 this.handleSuccessFetch(doc); 3767 }); 3768 } 3769 }; 3770 })); 3771 //#endregion 3772 //#region modules/posts/assets/js/frontend/handlers/posts.js 3773 var posts_exports = /* @__PURE__ */ __exportAll({ default: () => posts_default }); 3774 var posts_default; 3775 var init_posts = __esmMin((() => { 3776 posts_default = elementorModules.frontend.handlers.Base.extend({ 3777 getSkinPrefix() { 3778 return "classic_"; 3779 }, 3780 bindEvents() { 3781 elementorFrontend.addListenerOnce(this.getModelCID(), "resize", this.onWindowResize); 3782 }, 3783 unbindEvents() { 3784 elementorFrontend.removeListeners(this.getModelCID(), "resize", this.onWindowResize); 3785 }, 3786 getClosureMethodsNames() { 3787 return elementorModules.frontend.handlers.Base.prototype.getClosureMethodsNames.apply(this, arguments).concat([ 3788 "fitImages", 3789 "onWindowResize", 3790 "runMasonry" 3791 ]); 3792 }, 3793 getDefaultSettings() { 3794 return { 3795 classes: { 3796 fitHeight: "elementor-fit-height", 3797 hasItemRatio: "elementor-has-item-ratio" 3798 }, 3799 selectors: { 3800 postsContainer: ".elementor-posts-container", 3801 post: ".elementor-post", 3802 postThumbnail: ".elementor-post__thumbnail", 3803 postThumbnailImage: ".elementor-post__thumbnail img" 3804 } 3805 }; 3806 }, 3807 getDefaultElements() {
3808 var selectors = this.getSettings("selectors"); 3809 return { 3810 $postsContainer: this.$element.find(selectors.postsContainer), 3811 $posts: this.$element.find(selectors.post) 3812 }; 3813 }, 3814 fitImage($post) { 3815 var settings = this.getSettings(); 3816 var $imageParent = $post.find(settings.selectors.postThumbnail); 3817 var image = $imageParent.find("img")[0]; 3818 if (!image) return; 3819 var imageParentRatio = $imageParent.outerHeight() / $imageParent.outerWidth(); 3820 var imageRatio = image.naturalHeight / image.naturalWidth; 3821 $imageParent.toggleClass(settings.classes.fitHeight, imageRatio < imageParentRatio); 3822 }, 3823 fitImages() { 3824 var $ = jQuery; 3825 var self = this; 3826 var itemRatio = getComputedStyle(this.$element[0], ":after").content; 3827 var settings = this.getSettings(); 3828 if (self.isMasonryEnabled()) { 3829 this.elements.$postsContainer.removeClass(settings.classes.hasItemRatio); 3830 return; 3831 } 3832 this.elements.$postsContainer.toggleClass(settings.classes.hasItemRatio, !!itemRatio.match(/\d/)); 3833 this.elements.$posts.each(function() { 3834 var $post = $(this); 3835 var $image = $post.find(settings.selectors.postThumbnailImage); 3836 self.fitImage($post); 3837 $image.on("load", function() { 3838 self.fitImage($post); 3839 }); 3840 }); 3841 }, 3842 setColsCountSettings() { 3843 const settings = this.getElementSettings(); 3844 const skinPrefix = this.getSkinPrefix(); 3845 const colsCount = elementorProFrontend.utils.controls.getResponsiveControlValue(settings, `${skinPrefix}columns`); 3846 this.setSettings("colsCount", colsCount); 3847 }, 3848 isMasonryEnabled() { 3849 return !!this.getElementSettings(this.getSkinPrefix() + "masonry"); 3850 }, 3851 initMasonry() { 3852 imagesLoaded(this.elements.$posts, this.runMasonry); 3853 }, 3854 getVerticalSpaceBetween() { 3855 let verticalSpaceBetween = elementorProFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), `${this.getSkinPrefix()}row_gap`, "size"); 3856 if ("" === this.getSkinPrefix() && "" === verticalSpaceBetween) verticalSpaceBetween = this.getElementSettings("item_gap.size"); 3857 return verticalSpaceBetween; 3858 }, 3859 runMasonry() { 3860 var elements = this.elements; 3861 elements.$posts.css({ 3862 marginTop: "", 3863 transitionDuration: "" 3864 }); 3865 this.setColsCountSettings(); 3866 var colsCount = this.getSettings("colsCount"); 3867 var hasMasonry = this.isMasonryEnabled() && colsCount >= 2; 3868 elements.$postsContainer.toggleClass("elementor-posts-masonry", hasMasonry); 3869 if (!hasMasonry) { 3870 elements.$postsContainer.height(""); 3871 return; 3872 } 3873 const verticalSpaceBetween = this.getVerticalSpaceBetween(); 3874 new elementorModules.utils.Masonry({ 3875 container: elements.$postsContainer, 3876 items: elements.$posts.filter(":visible"), 3877 columnsCount: this.getSettings("colsCount"), 3878 verticalSpaceBetween: verticalSpaceBetween || 0 3879 }).run(); 3880 }, 3881 run() { 3882 setTimeout(this.fitImages, 0); 3883 this.initMasonry(); 3884 }, 3885 onInit() { 3886 elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments); 3887 this.bindEvents(); 3888 this.run(); 3889 }, 3890 onWindowResize() { 3891 this.fitImages(); 3892 this.runMasonry(); 3893 }, 3894 onElementChange() { 3895 this.fitImages(); 3896 setTimeout(this.runMasonry); 3897 } 3898 }); 3899 })); 3900 //#endregion 3901 //#region modules/posts/assets/js/frontend/handlers/cards.js 3902 var cards_exports = /* @__PURE__ */ __exportAll({ default: () => cards_default }); 3903 var cards_default; 3904 var init_cards = __esmMin((() => { 3905 init_posts(); 3906 cards_default = posts_default.extend({ getSkinPrefix() { 3907 return "cards_"; 3908 } }); 3909 })); 3910 //#endregion 3911 //#region modules/posts/assets/js/frontend/handlers/portfolio.js 3912 var portfolio_exports = /* @__PURE__ */ __exportAll({ default: () => portfolio_default }); 3913 var portfolio_default; 3914 var init_portfolio = __esmMin((() => { 3915 init_posts(); 3916 portfolio_default = posts_default.extend({ 3917 isActive(settings) { 3918 return settings.$element.find(".elementor-portfolio").length; 3919 }, 3920 getSkinPrefix() { 3921 return ""; 3922 }, 3923 getDefaultSettings() { 3924 var settings = posts_default.prototype.getDefaultSettings.apply(this, arguments); 3925 settings.transitionDuration = 450; 3926 jQuery.extend(settings.classes, { 3927 active: "elementor-active", 3928 item: "elementor-portfolio-item", 3929 ghostItem: "elementor-portfolio-ghost-item" 3930 }); 3931 return settings; 3932 }, 3933 getDefaultElements() { 3934 var elements = posts_default.prototype.getDefaultElements.apply(this, arguments); 3935 elements.$filterButtons = this.$element.find(".elementor-portfolio__filter"); 3936 return elements; 3937 }, 3938 getOffset(itemIndex, itemWidth, itemHeight) {
3939 var settings = this.getSettings(); 3940 var itemGap = this.elements.$postsContainer.width() / settings.colsCount - itemWidth; 3941 itemGap += itemGap / (settings.colsCount - 1); 3942 return { 3943 start: (itemWidth + itemGap) * (itemIndex % settings.colsCount), 3944 top: (itemHeight + itemGap) * Math.floor(itemIndex / settings.colsCount) 3945 }; 3946 }, 3947 getClosureMethodsNames() { 3948 return posts_default.prototype.getClosureMethodsNames.apply(this, arguments).concat(["onFilterButtonClick"]); 3949 }, 3950 filterItems(term) { 3951 var $posts = this.elements.$posts; 3952 var activeClass = this.getSettings("classes.active"); 3953 var termSelector = ".elementor-filter-" + term; 3954 if ("__all" === term) { 3955 $posts.addClass(activeClass); 3956 return; 3957 } 3958 $posts.not(termSelector).removeClass(activeClass); 3959 $posts.filter(termSelector).addClass(activeClass); 3960 }, 3961 removeExtraGhostItems() { 3962 var settings = this.getSettings(); 3963 var $shownItems = this.elements.$posts.filter(":visible"); 3964 var emptyColumns = (settings.colsCount - $shownItems.length % settings.colsCount) % settings.colsCount; 3965 this.elements.$postsContainer.find("." + settings.classes.ghostItem).slice(emptyColumns).remove(); 3966 }, 3967 handleEmptyColumns() { 3968 this.removeExtraGhostItems(); 3969 var settings = this.getSettings(); 3970 var $shownItems = this.elements.$posts.filter(":visible"); 3971 var $ghostItems = this.elements.$postsContainer.find("." + settings.classes.ghostItem); 3972 var emptyColumns = (settings.colsCount - ($shownItems.length + $ghostItems.length) % settings.colsCount) % settings.colsCount; 3973 for (var i = 0; i < emptyColumns; i++) this.elements.$postsContainer.append(jQuery("<div>", { class: settings.classes.item + " " + settings.classes.ghostItem })); 3974 }, 3975 showItems($activeHiddenItems) { 3976 $activeHiddenItems.show(); 3977 setTimeout(function() { 3978 $activeHiddenItems.css({ opacity: 1 }); 3979 }); 3980 }, 3981 hideItems($inactiveShownItems) { 3982 $inactiveShownItems.hide(); 3983 }, 3984 arrangeGrid() { 3985 var $ = jQuery; 3986 var self = this; 3987 var settings = self.getSettings(); 3988 var $activeItems = self.elements.$posts.filter("." + settings.classes.active); 3989 var $inactiveItems = self.elements.$posts.not("." + settings.classes.active); 3990 var $activeHiddenItems = $activeItems.filter(":hidden"); 3991 var $inactiveShownItems = $inactiveItems.filter(":visible"); 3992 self.elements.$posts.css("transition-duration", settings.transitionDuration + "ms"); 3993 self.showItems($activeHiddenItems); 3994 if (self.isEdit) self.fitImages(); 3995 self.handleEmptyColumns(); 3996 if (self.isMasonryEnabled()) { 3997 self.hideItems($inactiveShownItems); 3998 self.showItems($activeHiddenItems); 3999 self.handleEmptyColumns(); 4000 self.runMasonry(); 4001 return; 4002 } 4003 $inactiveShownItems.css({ 4004 opacity: 0, 4005 transform: "scale3d(0.2, 0.2, 1)" 4006 }); 4007 const $shownItems = self.elements.$posts.filter(":visible"); 4008 const $activeOrShownItems = $activeItems.add($shownItems); 4009 const $activeShownItems = $activeItems.filter(":visible"); 4010 const itemWidth = $shownItems.outerWidth(); 4011 const itemHeight = $shownItems.outerHeight(); 4012 $activeShownItems.each(function() { 4013 var $item = $(this); 4014 var currentOffset = self.getOffset($activeOrShownItems.index($item), itemWidth, itemHeight); 4015 var requiredOffset = self.getOffset($shownItems.index($item), itemWidth, itemHeight); 4016 if (currentOffset.start === requiredOffset.start && currentOffset.top === requiredOffset.top) return; 4017 requiredOffset.start -= currentOffset.start; 4018 requiredOffset.top -= currentOffset.top; 4019 if (elementorFrontend.config.is_rtl) requiredOffset.start *= -1; 4020 $item.css({ 4021 transitionDuration: "", 4022 transform: "translate3d(" + requiredOffset.start + "px, " + requiredOffset.top + "px, 0)" 4023 }); 4024 }); 4025 setTimeout(function() { 4026 $activeItems.each(function() { 4027 var $item = $(this); 4028 var currentOffset = self.getOffset($activeOrShownItems.index($item), itemWidth, itemHeight); 4029 var requiredOffset = self.getOffset($activeItems.index($item), itemWidth, itemHeight); 4030 $item.css({ transitionDuration: settings.transitionDuration + "ms" }); 4031 requiredOffset.start -= currentOffset.start; 4032 requiredOffset.top -= currentOffset.top; 4033 if (elementorFrontend.config.is_rtl) requiredOffset.start *= -1; 4034 setTimeout(function() { 4035 $item.css("transform", "translate3d(" + requiredOffset.start + "px, " + requiredOffset.top + "px, 0)"); 4036 }); 4037 }); 4038 }); 4039 setTimeout(function() { 4040 self.hideItems($inactiveShownItems); 4041 $activeItems.css({ 4042 transitionDuration: "", 4043 transform: "translate3d(0px, 0px, 0px)" 4044 }); 4045 self.handleEmptyColumns(); 4046 }, settings.transitionDuration); 4047 }, 4048 activeFilterButton(filter) {
4049 var activeClass = this.getSettings("classes.active"); 4050 var $filterButtons = this.elements.$filterButtons; 4051 var $button = $filterButtons.filter("[data-filter=\"" + filter + "\"]"); 4052 $filterButtons.removeClass(activeClass); 4053 $button.addClass(activeClass); 4054 }, 4055 setFilter(filter) { 4056 this.activeFilterButton(filter); 4057 this.filterItems(filter); 4058 this.arrangeGrid(); 4059 }, 4060 refreshGrid() { 4061 this.setColsCountSettings(); 4062 this.arrangeGrid(); 4063 }, 4064 bindEvents() { 4065 posts_default.prototype.bindEvents.apply(this, arguments); 4066 this.elements.$filterButtons.on("click", this.onFilterButtonClick); 4067 }, 4068 isMasonryEnabled() { 4069 return !!this.getElementSettings("masonry"); 4070 }, 4071 run() { 4072 posts_default.prototype.run.apply(this, arguments); 4073 this.setColsCountSettings(); 4074 this.setFilter("__all"); 4075 this.handleEmptyColumns(); 4076 }, 4077 onFilterButtonClick(event) { 4078 this.setFilter(jQuery(event.currentTarget).data("filter")); 4079 }, 4080 onWindowResize() { 4081 posts_default.prototype.onWindowResize.apply(this, arguments); 4082 this.refreshGrid(); 4083 }, 4084 onElementChange(propertyName) { 4085 posts_default.prototype.onElementChange.apply(this, arguments); 4086 if ("classic_item_ratio" === propertyName) this.refreshGrid(); 4087 } 4088 }); 4089 })); 4090 //#endregion 4091 //#region modules/posts/assets/js/frontend/frontend.js 4092 var frontend_default$13 = class extends elementorModules.Module { 4093 static { 4094 __name(this, "default"); 4095 } 4096 constructor() { 4097 super(); 4098 [ 4099 "classic", 4100 "full_content", 4101 "cards" 4102 ].forEach((skinName) => { 4103 elementorFrontend.elementsHandler.attachHandler("posts", () => __vitePreload(() => Promise.resolve().then(() => (init_load_more$1(), load_more_exports$1)), void 0), skinName); 4104 }); 4105 elementorFrontend.elementsHandler.attachHandler("posts", () => __vitePreload(() => Promise.resolve().then(() => (init_posts(), posts_exports)), void 0), "classic"); 4106 elementorFrontend.elementsHandler.attachHandler("posts", () => __vitePreload(() => Promise.resolve().then(() => (init_posts(), posts_exports)), void 0), "full_content"); 4107 elementorFrontend.elementsHandler.attachHandler("posts", () => __vitePreload(() => Promise.resolve().then(() => (init_cards(), cards_exports)), void 0), "cards"); 4108 elementorFrontend.elementsHandler.attachHandler("portfolio", () => __vitePreload(() => Promise.resolve().then(() => (init_portfolio(), portfolio_exports)), void 0)); 4109 } 4110 }; 4111 //#endregion 4112 //#region assets/dev/js/frontend/utils/handle-parameter-pollution.js 4113 function handleParameterPollution(inputURL) { 4114 const urlObject = new URL(inputURL); 4115 const mainDomain = urlObject.hostname; 4116 const params = new URLSearchParams(urlObject.search); 4117 ["u"].forEach((key) => { 4118 const paramValue = params.get(key); 4119 if (paramValue) try { 4120 if (new URL(paramValue).hostname !== mainDomain) params.delete(key); 4121 } catch (error) { 4122 params.delete(key); 4123 } 4124 }); 4125 urlObject.search = params.toString(); 4126 return urlObject.toString(); 4127 } 4128 var init_handle_parameter_pollution = __esmMin((() => {})); 4129 //#endregion 4130 //#region modules/share-buttons/assets/js/frontend/handlers/share-buttons.js 4131 var share_buttons_exports = /* @__PURE__ */ __exportAll({ default: () => share_buttons_default }); 4132 var share_buttons_default; 4133 var init_share_buttons = __esmMin((() => { 4134 init_handle_parameter_pollution(); 4135 init_asyncToGenerator(); 4136 share_buttons_default = elementorModules.frontend.handlers.Base.extend({ 4137 onInit() { 4138 var _arguments = arguments; 4139 var _this = this; 4140 return _asyncToGenerator(function* () { 4141 if (!_this.isActive()) return; 4142 elementorModules.frontend.handlers.Base.prototype.onInit.apply(_this, _arguments); 4143 const elementSettings = _this.getElementSettings(); 4144 const classes = _this.getSettings("classes"); 4145 const isCustomURL = elementSettings.share_url && elementSettings.share_url.url; 4146 const shareLinkSettings = { classPrefix: classes.shareLinkPrefix }; 4147 if (isCustomURL) shareLinkSettings.url = elementSettings.share_url.url; 4148 else { 4149 shareLinkSettings.url = handleParameterPollution(location.href); 4150 shareLinkSettings.title = elementorFrontend.config.post.title; 4151 shareLinkSettings.text = elementorFrontend.config.post.excerpt; 4152 shareLinkSettings.image = elementorFrontend.config.post.featuredImage; 4153 } 4154 /** 4155 * First check of the ShareLink is for detecting if the optimized mode is disabled and the library should be loaded dynamically. 4156 * Checking if the assetsLoader exist, in case that the library is not loaded due to Ad Blockers and not because the optimized mode is enabled. 4157 */ 4158 if (!window.ShareLink && elementorFrontend.utils.assetsLoader) yield elementorFrontend.utils.assetsLoader.load("script", "share-link"); 4159 /** 4160 * The following condition should remain regardless of the share-link dynamic loading. 4161 * Ad Blockers may block the share script. (/assets/lib/share-link/share-link.js). 4162 */ 4163 if (!_this.elements.$shareButton.shareLink) return; 4164 _this.elements.$shareButton.shareLink(shareLinkSettings); 4165 })(); 4166 }, 4167 getDefaultSettings() { 4168 return { 4169 selectors: { shareButton: ".elementor-share-btn" }, 4170 classes: { shareLinkPrefix: "elementor-share-btn_" } 4171 }; 4172 }, 4173 getDefaultElements() {
4174 var selectors = this.getSettings("selectors"); 4175 return { $shareButton: this.$element.find(selectors.shareButton) }; 4176 }, 4177 isActive() { 4178 return !elementorFrontend.isEditMode(); 4179 } 4180 }); 4181 })); 4182 //#endregion 4183 //#region modules/share-buttons/assets/js/frontend/frontend.js 4184 var frontend_default$12 = class extends elementorModules.Module { 4185 static { 4186 __name(this, "default"); 4187 } 4188 constructor() { 4189 super(); 4190 elementorFrontend.elementsHandler.attachHandler("share-buttons", () => __vitePreload(() => Promise.resolve().then(() => (init_share_buttons(), share_buttons_exports)), void 0)); 4191 } 4192 }; 4193 //#endregion 4194 //#region modules/slides/assets/js/frontend/handlers/slides.js 4195 var slides_exports = /* @__PURE__ */ __exportAll({ default: () => SlidesHandler }); 4196 var SlidesHandler; 4197 var init_slides = __esmMin((() => { 4198 init_asyncToGenerator(); 4199 SlidesHandler = class extends elementorModules.frontend.handlers.SwiperBase { 4200 getDefaultSettings() { 4201 return { 4202 selectors: { 4203 slider: ".elementor-slides-wrapper", 4204 slide: ".swiper-slide", 4205 slideInnerContents: ".swiper-slide-contents", 4206 activeSlide: ".swiper-slide-active", 4207 activeDuplicate: ".swiper-slide-duplicate-active" 4208 }, 4209 classes: { 4210 animated: "animated", 4211 kenBurnsActive: "elementor-ken-burns--active", 4212 slideBackground: "swiper-slide-bg" 4213 }, 4214 attributes: { 4215 dataSliderOptions: "slider_options", 4216 dataAnimation: "animation" 4217 } 4218 }; 4219 } 4220 getDefaultElements() { 4221 const selectors = this.getSettings("selectors"); 4222 const elements = { $swiperContainer: this.$element.find(selectors.slider) }; 4223 elements.$slides = elements.$swiperContainer.find(selectors.slide); 4224 return elements; 4225 } 4226 getSwiperOptions() { 4227 const elementSettings = this.getElementSettings(); 4228 const swiperOptions = { 4229 autoplay: this.getAutoplayConfig(), 4230 grabCursor: true, 4231 initialSlide: this.getInitialSlide(), 4232 slidesPerView: 1, 4233 slidesPerGroup: 1, 4234 loop: "yes" === elementSettings.infinite, 4235 speed: elementSettings.transition_speed, 4236 effect: elementSettings.transition, 4237 observeParents: true, 4238 observer: true, 4239 handleElementorBreakpoints: true, 4240 on: { slideChange: () => { 4241 this.handleKenBurns(); 4242 } } 4243 }; 4244 const showArrows = "arrows" === elementSettings.navigation || "both" === elementSettings.navigation; 4245 const pagination = "dots" === elementSettings.navigation || "both" === elementSettings.navigation; 4246 if (showArrows) swiperOptions.navigation = { 4247 prevEl: ".elementor-swiper-button-prev", 4248 nextEl: ".elementor-swiper-button-next" 4249 }; 4250 if (pagination) swiperOptions.pagination = { 4251 el: ".swiper-pagination", 4252 type: "bullets", 4253 clickable: true 4254 }; 4255 if (true === swiperOptions.loop) swiperOptions.loopedSlides = this.getSlidesCount(); 4256 if ("fade" === swiperOptions.effect) swiperOptions.fadeEffect = { crossFade: true }; 4257 return swiperOptions; 4258 } 4259 getAutoplayConfig() { 4260 const elementSettings = this.getElementSettings(); 4261 if ("yes" !== elementSettings.autoplay) return false; 4262 return { 4263 stopOnLastSlide: true, 4264 delay: elementSettings.autoplay_speed, 4265 disableOnInteraction: "yes" === elementSettings.pause_on_interaction 4266 }; 4267 } 4268 initSingleSlideAnimations() { 4269 const settings = this.getSettings(); 4270 const animation = this.elements.$swiperContainer.data(settings.attributes.dataAnimation); 4271 this.elements.$swiperContainer.find("." + settings.classes.slideBackground).addClass(settings.classes.kenBurnsActive); 4272 if (animation) this.elements.$swiperContainer.find(settings.selectors.slideInnerContents).addClass(settings.classes.animated + " " + animation); 4273 } 4274 initSlider() { 4275 var _this = this; 4276 return _asyncToGenerator(function* () { 4277 const $slider = _this.elements.$swiperContainer; 4278 if (!$slider.length) return; 4279 if (1 >= _this.getSlidesCount()) return; 4280 const Swiper = elementorFrontend.utils.swiper; 4281 _this.swiper = yield new Swiper($slider, _this.getSwiperOptions()); 4282 $slider.data("swiper", _this.swiper); 4283 _this.handleKenBurns(); 4284 if (_this.getElementSettings().pause_on_hover) _this.togglePauseOnHover(true);
4285 const settings = _this.getSettings(); 4286 const animation = $slider.data(settings.attributes.dataAnimation); 4287 if (!animation) return; 4288 _this.swiper.on("slideChangeTransitionStart", function() { 4289 $slider.find(settings.selectors.slideInnerContents).removeClass(settings.classes.animated + " " + animation).hide(); 4290 }); 4291 _this.swiper.on("slideChangeTransitionEnd", function() { 4292 $slider.find(settings.selectors.slideInnerContents).show().addClass(settings.classes.animated + " " + animation); 4293 }); 4294 })(); 4295 } 4296 onInit() { 4297 elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments); 4298 if (2 > this.getSlidesCount()) { 4299 this.initSingleSlideAnimations(); 4300 return; 4301 } 4302 this.initSlider(); 4303 } 4304 getChangeableProperties() { 4305 return { 4306 pause_on_hover: "pauseOnHover", 4307 pause_on_interaction: "disableOnInteraction", 4308 autoplay_speed: "delay", 4309 transition_speed: "speed" 4310 }; 4311 } 4312 updateSwiperOption(propertyName) { 4313 if (0 === propertyName.indexOf("width")) { 4314 this.swiper.update(); 4315 return; 4316 } 4317 const elementSettings = this.getElementSettings(); 4318 const newSettingValue = elementSettings[propertyName]; 4319 let propertyToUpdate = this.getChangeableProperties()[propertyName]; 4320 let valueToUpdate = newSettingValue; 4321 switch (propertyName) { 4322 case "autoplay_speed": 4323 propertyToUpdate = "autoplay"; 4324 valueToUpdate = { 4325 delay: newSettingValue, 4326 disableOnInteraction: "yes" === elementSettings.pause_on_interaction 4327 }; 4328 break; 4329 case "pause_on_hover": 4330 this.togglePauseOnHover("yes" === newSettingValue); 4331 break; 4332 case "pause_on_interaction": 4333 valueToUpdate = "yes" === newSettingValue; 4334 break; 4335 } 4336 if ("pause_on_hover" !== propertyName) this.swiper.params[propertyToUpdate] = valueToUpdate; 4337 this.swiper.update(); 4338 } 4339 onElementChange(propertyName) { 4340 if (1 >= this.getSlidesCount()) return; 4341 const changeableProperties = this.getChangeableProperties(); 4342 if (Object.prototype.hasOwnProperty.call(changeableProperties, propertyName)) { 4343 this.updateSwiperOption(propertyName); 4344 this.swiper.autoplay.start(); 4345 } 4346 } 4347 onEditSettingsChange(propertyName) { 4348 if (1 >= this.getSlidesCount()) return; 4349 if ("activeItemIndex" === propertyName) { 4350 this.swiper.slideToLoop(this.getEditSettings("activeItemIndex") - 1); 4351 this.swiper.autoplay.stop(); 4352 } 4353 } 4354 }; 4355 })); 4356 //#endregion 4357 //#region modules/slides/assets/js/frontend/frontend.js 4358 var frontend_default$11 = class extends elementorModules.Module { 4359 static { 4360 __name(this, "default"); 4361 } 4362 constructor() { 4363 super(); 4364 elementorFrontend.elementsHandler.attachHandler("slides", () => __vitePreload(() => Promise.resolve().then(() => (init_slides(), slides_exports)), void 0)); 4365 } 4366 }; 4367 //#endregion 4368 //#region modules/social/assets/js/frontend/handlers/facebook.js 4369 var facebook_exports = /* @__PURE__ */ __exportAll({ default: () => FacebookHandler }); 4370 var FacebookHandler; 4371 var init_facebook = __esmMin((() => { 4372 FacebookHandler = class extends elementorModules.frontend.handlers.Base { 4373 getConfig() { 4374 return elementorProFrontend.config.facebook_sdk; 4375 } 4376 setConfig(prop, value) { 4377 elementorProFrontend.config.facebook_sdk[prop] = value; 4378 } 4379 parse() { 4380 FB.XFBML.parse(this.$element[0]); 4381 } 4382 loadSDK() { 4383 const config = this.getConfig(); 4384 if (config.isLoading || config.isLoaded) return; 4385 this.setConfig("isLoading", true); 4386 jQuery.ajax({ 4387 url: "https://connect.facebook.net/" + config.lang + "/sdk.js", 4388 dataType: "script", 4389 cache: true, 4390 success: () => { 4391 FB.init({ 4392 appId: config.app_id, 4393 version: "v2.10", 4394 xfbml: false 4395 }); 4396 this.setConfig("isLoaded", true); 4397 this.setConfig("isLoading", false); 4398 elementorFrontend.elements.$document.trigger("fb:sdk:loaded"); 4399 } 4400 }); 4401 } 4402 onInit(...args) { 4403 super.onInit(...args); 4404 this.loadSDK(); 4405 if (this.getConfig().isLoaded) this.parse(); 4406 else elementorFrontend.elements.$document.on("fb:sdk:loaded", () => this.parse()); 4407 } 4408 }; 4409 })); 4410 //#endregion 4411 //#region modules/social/assets/js/frontend/frontend.js 4412 var frontend_default$10 = class extends elementorModules.Module { 4413 static { 4414 __name(this, "default"); 4415 } 4416 constructor() { 4417 super(); 4418 elementorFrontend.elementsHandler.attachHandler("facebook-button", () => __vitePreload(() => Promise.resolve().then(() => (init_facebook(), facebook_exports)), void 0)); 4419 elementorFrontend.elementsHandler.attachHandler("facebook-comments", () => __vitePreload(() => Promise.resolve().then(() => (init_facebook(), facebook_exports)), void 0)); 4420 elementorFrontend.elementsHandler.attachHandler("facebook-embed", () => __vitePreload(() => Promise.resolve().then(() => (init_facebook(), facebook_exports)), void 0)); 4421 elementorFrontend.elementsHandler.attachHandler("facebook-page", () => __vitePreload(() => Promise.resolve().then(() => (init_facebook(), facebook_exports)), void 0)); 4422 } 4423 }; 4424 //#endregion 4425 //#region node_modules/dompurify/dist/purify.es.mjs 4426 /*! @license DOMPurify 3.4.11 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.11/LICENSE */ 4427 function _arrayLikeToArray(r, a) { 4428 (null == a || a > r.length) && (a = r.length); 4429 for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; 4430 return n; 4431 } 4432 function _arrayWithHoles(r) { 4433 if (Array.isArray(r)) return r; 4434 } 4435 function _iterableToArrayLimit(r, l) { 4436 var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; 4437 if (null != t) { 4438 var e; 4439 var n; 4440 var i; 4441 var u; 4442 var a = []; 4443 var f = true; 4444 var o = false;
vendor: 9,644 bytes, lines 4445-4686
4445 try { 4446 if (i = (t = t.call(r)).next, 0 === l); 4447 else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); 4448 } catch (r) { 4449 o = true, n = r; 4450 } finally { 4451 try { 4452 if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; 4453 } finally { 4454 if (o) throw n; 4455 } 4456 } 4457 return a; 4458 } 4459 } 4460 function _nonIterableRest() { 4461 throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); 4462 } 4463 function _slicedToArray(r, e) { 4464 return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); 4465 } 4466 function _unsupportedIterableToArray(r, a) { 4467 if (r) { 4468 if ("string" == typeof r) return _arrayLikeToArray(r, a); 4469 var t = {}.toString.call(r).slice(8, -1); 4470 return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; 4471 } 4472 } 4473 /** 4474 * Creates a new function that calls the given function with a specified thisArg and arguments. 4475 * 4476 * @param func - The function to be wrapped and called. 4477 * @returns A new function that calls the given function with a specified thisArg and arguments. 4478 */ 4479 function unapply(func) { 4480 return function(thisArg) { 4481 if (thisArg instanceof RegExp) thisArg.lastIndex = 0; 4482 for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) args[_key3 - 1] = arguments[_key3]; 4483 return apply(func, thisArg, args); 4484 }; 4485 } 4486 /** 4487 * Creates a new function that constructs an instance of the given constructor function with the provided arguments. 4488 * 4489 * @param func - The constructor function to be wrapped and called. 4490 * @returns A new function that constructs an instance of the given constructor function with the provided arguments. 4491 */ 4492 function unconstruct(Func) { 4493 return function() { 4494 for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) args[_key4] = arguments[_key4]; 4495 return construct(Func, args); 4496 }; 4497 } 4498 /** 4499 * Add properties to a lookup table 4500 * 4501 * @param set - The set to which elements will be added. 4502 * @param array - The array containing elements to be added to the set. 4503 * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set. 4504 * @returns The modified set with added elements. 4505 */ 4506 function addToSet(set, array) { 4507 let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase; 4508 if (setPrototypeOf) setPrototypeOf(set, null); 4509 if (!arrayIsArray(array)) return set; 4510 let l = array.length; 4511 while (l--) { 4512 let element = array[l]; 4513 if (typeof element === "string") { 4514 const lcElement = transformCaseFunc(element); 4515 if (lcElement !== element) { 4516 if (!isFrozen(array)) array[l] = lcElement; 4517 element = lcElement; 4518 } 4519 } 4520 set[element] = true; 4521 } 4522 return set; 4523 } 4524 /** 4525 * Clean up an array to harden against CSPP 4526 * 4527 * @param array - The array to be cleaned. 4528 * @returns The cleaned version of the array 4529 */ 4530 function cleanArray(array) { 4531 for (let index = 0; index < array.length; index++) if (!objectHasOwnProperty(array, index)) array[index] = null; 4532 return array; 4533 } 4534 /** 4535 * Shallow clone an object 4536 * 4537 * @param object - The object to be cloned. 4538 * @returns A new object that copies the original. 4539 */ 4540 function clone(object) { 4541 const newObject = create(null); 4542 for (const _ref2 of entries(object)) { 4543 var _ref3 = _slicedToArray(_ref2, 2); 4544 const property = _ref3[0]; 4545 const value = _ref3[1]; 4546 if (objectHasOwnProperty(object, property)) if (arrayIsArray(value)) newObject[property] = cleanArray(value); 4547 else if (value && typeof value === "object" && value.constructor === Object) newObject[property] = clone(value); 4548 else newObject[property] = value; 4549 } 4550 return newObject; 4551 } 4552 /** 4553 * Convert non-node values into strings without depending on direct property access. 4554 * 4555 * @param value - The value to stringify. 4556 * @returns A string representation of the provided value. 4557 */ 4558 function stringifyValue(value) { 4559 switch (typeof value) { 4560 case "string": return value; 4561 case "number": return numberToString(value); 4562 case "boolean": return booleanToString(value); 4563 case "bigint": return bigintToString ? bigintToString(value) : "0"; 4564 case "symbol": return symbolToString ? symbolToString(value) : "Symbol()"; 4565 case "undefined": return objectToString(value); 4566 case "function": 4567 case "object": { 4568 if (value === null) return objectToString(value); 4569 const valueAsRecord = value; 4570 const valueToString = lookupGetter(valueAsRecord, "toString"); 4571 if (typeof valueToString === "function") { 4572 const stringified = valueToString(valueAsRecord); 4573 return typeof stringified === "string" ? stringified : objectToString(stringified); 4574 } 4575 return objectToString(value); 4576 } 4577 default: return objectToString(value); 4578 } 4579 } 4580 /** 4581 * This method automatically checks if the prop is function or getter and behaves accordingly. 4582 * 4583 * @param object - The object to look up the getter function in its prototype chain. 4584 * @param prop - The property name for which to find the getter function. 4585 * @returns The getter function found in the prototype chain or a fallback function. 4586 */ 4587 function lookupGetter(object, prop) { 4588 while (object !== null) { 4589 const desc = getOwnPropertyDescriptor(object, prop); 4590 if (desc) { 4591 if (desc.get) return unapply(desc.get); 4592 if (typeof desc.value === "function") return unapply(desc.value); 4593 } 4594 object = getPrototypeOf(object); 4595 } 4596 function fallbackValue() { 4597 return null; 4598 } 4599 return fallbackValue; 4600 } 4601 function isRegex(value) { 4602 try { 4603 regExpTest(value, ""); 4604 return true; 4605 } catch (_unused) { 4606 return false; 4607 } 4608 } 4609 function createDOMPurify() { 4610 let window = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal(); 4611 const DOMPurify = (root) => createDOMPurify(root); 4612 DOMPurify.version = "3.4.11"; 4613 DOMPurify.removed = []; 4614 if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) { 4615 DOMPurify.isSupported = false; 4616 return DOMPurify; 4617 } 4618 let document = window.document; 4619 const originalDocument = document; 4620 const currentScript = originalDocument.currentScript; 4621 window.DocumentFragment; 4622 const HTMLTemplateElement = window.HTMLTemplateElement; 4623 const Node = window.Node; 4624 const Element = window.Element; 4625 const NodeFilter = window.NodeFilter; 4626 window.NamedNodeMap === void 0 && (window.NamedNodeMap || window.MozNamedAttrMap); 4627 window.HTMLFormElement; 4628 const DOMParser = window.DOMParser; 4629 const trustedTypes = window.trustedTypes; 4630 const ElementPrototype = Element.prototype; 4631 const cloneNode = lookupGetter(ElementPrototype, "cloneNode"); 4632 const remove = lookupGetter(ElementPrototype, "remove"); 4633 const getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); 4634 const getChildNodes = lookupGetter(ElementPrototype, "childNodes"); 4635 const getParentNode = lookupGetter(ElementPrototype, "parentNode"); 4636 const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot"); 4637 const getAttributes = lookupGetter(ElementPrototype, "attributes"); 4638 const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null; 4639 const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null; 4640 if (typeof HTMLTemplateElement === "function") { 4641 const template = document.createElement("template"); 4642 if (template.content && template.content.ownerDocument) document = template.content.ownerDocument; 4643 } 4644 let trustedTypesPolicy; 4645 let emptyHTML = ""; 4646 let defaultTrustedTypesPolicy; 4647 let defaultTrustedTypesPolicyResolved = false; 4648 let IN_TRUSTED_TYPES_POLICY = 0; 4649 const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy() { 4650 if (IN_TRUSTED_TYPES_POLICY > 0) throw typeErrorCreate("A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the \"DOMPurify and Trusted Types\" section of the README."); 4651 }; 4652 const _createTrustedHTML = function _createTrustedHTML(html) { 4653 _assertNotInTrustedTypesPolicy(); 4654 IN_TRUSTED_TYPES_POLICY++; 4655 try { 4656 return trustedTypesPolicy.createHTML(html); 4657 } finally { 4658 IN_TRUSTED_TYPES_POLICY--; 4659 } 4660 }; 4661 const _createTrustedScriptURL = function _createTrustedScriptURL(scriptUrl) { 4662 _assertNotInTrustedTypesPolicy(); 4663 IN_TRUSTED_TYPES_POLICY++; 4664 try { 4665 return trustedTypesPolicy.createScriptURL(scriptUrl); 4666 } finally { 4667 IN_TRUSTED_TYPES_POLICY--; 4668 } 4669 }; 4670 const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy() { 4671 if (!defaultTrustedTypesPolicyResolved) { 4672 defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); 4673 defaultTrustedTypesPolicyResolved = true; 4674 } 4675 return defaultTrustedTypesPolicy; 4676 }; 4677 const _document = document; 4678 const implementation = _document.implementation; 4679 const createNodeIterator = _document.createNodeIterator; 4680 const createDocumentFragment = _document.createDocumentFragment; 4681 const getElementsByTagName = _document.getElementsByTagName; 4682 const importNode = originalDocument.importNode; 4683 let hooks = _createHooksMap(); 4684 /** 4685 * Expose whether this browser supports running the full DOMPurify. 4686 */
4687 DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0; 4688 const MUSTACHE_EXPR$1 = MUSTACHE_EXPR; 4689 const ERB_EXPR$1 = ERB_EXPR; 4690 const TMPLIT_EXPR$1 = TMPLIT_EXPR; 4691 const DATA_ATTR$1 = DATA_ATTR; 4692 const ARIA_ATTR$1 = ARIA_ATTR; 4693 const IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA; 4694 const ATTR_WHITESPACE$1 = ATTR_WHITESPACE; 4695 const
vendor: 6,772 bytes, lines 4695-4908
4695 CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT; 4696 let IS_ALLOWED_URI$1 = IS_ALLOWED_URI; 4697 /** 4698 * We consider the elements and attributes below to be safe. Ideally 4699 * don't add any new ones but feel free to remove unwanted ones. 4700 */ 4701 let ALLOWED_TAGS = null; 4702 const DEFAULT_ALLOWED_TAGS = addToSet({}, [ 4703 ...html$1, 4704 ...svg$1, 4705 ...svgFilters, 4706 ...mathMl$1, 4707 ...text 4708 ]); 4709 let ALLOWED_ATTR = null; 4710 const DEFAULT_ALLOWED_ATTR = addToSet({}, [ 4711 ...html, 4712 ...svg, 4713 ...mathMl, 4714 ...xml 4715 ]); 4716 let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { 4717 tagNameCheck: { 4718 writable: true, 4719 configurable: false, 4720 enumerable: true, 4721 value: null 4722 }, 4723 attributeNameCheck: { 4724 writable: true, 4725 configurable: false, 4726 enumerable: true, 4727 value: null 4728 }, 4729 allowCustomizedBuiltInElements: { 4730 writable: true, 4731 configurable: false, 4732 enumerable: true, 4733 value: false 4734 } 4735 })); 4736 let FORBID_TAGS = null; 4737 let FORBID_ATTR = null; 4738 const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, { 4739 tagCheck: { 4740 writable: true, 4741 configurable: false, 4742 enumerable: true, 4743 value: null 4744 }, 4745 attributeCheck: { 4746 writable: true, 4747 configurable: false, 4748 enumerable: true, 4749 value: null 4750 } 4751 })); 4752 let ALLOW_ARIA_ATTR = true; 4753 let ALLOW_DATA_ATTR = true; 4754 let ALLOW_UNKNOWN_PROTOCOLS = false; 4755 let ALLOW_SELF_CLOSE_IN_ATTR = true; 4756 let SAFE_FOR_TEMPLATES = false; 4757 let SAFE_FOR_XML = true; 4758 let WHOLE_DOCUMENT = false; 4759 let SET_CONFIG = false; 4760 let SET_CONFIG_ALLOWED_TAGS = null; 4761 let SET_CONFIG_ALLOWED_ATTR = null; 4762 let FORCE_BODY = false; 4763 let RETURN_DOM = false; 4764 let RETURN_DOM_FRAGMENT = false; 4765 let RETURN_TRUSTED_TYPE = false; 4766 let SANITIZE_DOM = true; 4767 let SANITIZE_NAMED_PROPS = false; 4768 const SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; 4769 let KEEP_CONTENT = true; 4770 let IN_PLACE = false; 4771 let USE_PROFILES = {}; 4772 let FORBID_CONTENTS = null; 4773 const DEFAULT_FORBID_CONTENTS = addToSet({}, [ 4774 "annotation-xml", 4775 "audio", 4776 "colgroup", 4777 "desc", 4778 "foreignobject", 4779 "head", 4780 "iframe", 4781 "math", 4782 "mi", 4783 "mn", 4784 "mo", 4785 "ms", 4786 "mtext", 4787 "noembed", 4788 "noframes", 4789 "noscript", 4790 "plaintext", 4791 "script", 4792 "selectedcontent", 4793 "style", 4794 "svg", 4795 "template", 4796 "thead", 4797 "title", 4798 "video", 4799 "xmp" 4800 ]); 4801 let DATA_URI_TAGS = null; 4802 const DEFAULT_DATA_URI_TAGS = addToSet({}, [ 4803 "audio", 4804 "video", 4805 "img", 4806 "source", 4807 "image", 4808 "track" 4809 ]); 4810 let URI_SAFE_ATTRIBUTES = null; 4811 const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [ 4812 "alt", 4813 "class", 4814 "for", 4815 "id", 4816 "label", 4817 "name", 4818 "pattern", 4819 "placeholder", 4820 "role", 4821 "summary", 4822 "title", 4823 "value", 4824 "style", 4825 "xmlns" 4826 ]); 4827 const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML"; 4828 const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; 4829 const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; 4830 let NAMESPACE = HTML_NAMESPACE; 4831 let IS_EMPTY_INPUT = false; 4832 let ALLOWED_NAMESPACES = null; 4833 const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [ 4834 MATHML_NAMESPACE, 4835 SVG_NAMESPACE, 4836 HTML_NAMESPACE 4837 ], stringToString); 4838 const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze([ 4839 "mi", 4840 "mo", 4841 "mn", 4842 "ms", 4843 "mtext" 4844 ]); 4845 let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS); 4846 const DEFAULT_HTML_INTEGRATION_POINTS = freeze(["annotation-xml"]); 4847 let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS); 4848 const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [ 4849 "title", 4850 "style", 4851 "font", 4852 "a", 4853 "script" 4854 ]); 4855 let PARSER_MEDIA_TYPE = null; 4856 const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"]; 4857 const DEFAULT_PARSER_MEDIA_TYPE = "text/html"; 4858 let transformCaseFunc = null; 4859 let CONFIG = null; 4860 const formElement = document.createElement("form"); 4861 const isRegexOrFunction = function isRegexOrFunction(testValue) { 4862 return testValue instanceof RegExp || testValue instanceof Function; 4863 }; 4864 /** 4865 * _parseConfig 4866 * 4867 * @param cfg optional config literal 4868 */ 4869 const _parseConfig = function _parseConfig() { 4870 let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 4871 if (CONFIG && CONFIG === cfg) return; 4872 if (!cfg || typeof cfg !== "object") cfg = {}; 4873 cfg = clone(cfg); 4874 PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; 4875 transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase; 4876 ALLOWED_TAGS = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, { transform: transformCaseFunc }); 4877 ALLOWED_ATTR = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, { transform: transformCaseFunc }); 4878 ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, { transform: stringToString }); 4879 URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, "ADD_URI_SAFE_ATTR", DEFAULT_URI_SAFE_ATTRIBUTES, { 4880 transform: transformCaseFunc, 4881 base: DEFAULT_URI_SAFE_ATTRIBUTES 4882 }); 4883 DATA_URI_TAGS = _resolveSetOption(cfg, "ADD_DATA_URI_TAGS", DEFAULT_DATA_URI_TAGS, { 4884 transform: transformCaseFunc, 4885 base: DEFAULT_DATA_URI_TAGS 4886 }); 4887 FORBID_CONTENTS = _resolveSetOption(cfg, "FORBID_CONTENTS", DEFAULT_FORBID_CONTENTS, { transform: transformCaseFunc }); 4888 FORBID_TAGS = _resolveSetOption(cfg, "FORBID_TAGS", clone({}), { transform: transformCaseFunc }); 4889 FORBID_ATTR = _resolveSetOption(cfg, "FORBID_ATTR", clone({}), { transform: transformCaseFunc }); 4890 USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false; 4891 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; 4892 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; 4893 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; 4894 ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; 4895 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; 4896 SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; 4897 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; 4898 RETURN_DOM = cfg.RETURN_DOM || false; 4899 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; 4900 RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; 4901 FORCE_BODY = cfg.FORCE_BODY || false; 4902 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; 4903 SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; 4904 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; 4905 IN_PLACE = cfg.IN_PLACE || false; 4906 IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; 4907 NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE; 4908 MATHML_TEXT_INTEGRATION_POINTS =
vendor: 7,021 bytes, lines 4908-5038
4908objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS); 4909 HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS); 4910 const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null); 4911 CUSTOM_ELEMENT_HANDLING = create(null); 4912 if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; 4913 if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; 4914 if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; 4915 seal(CUSTOM_ELEMENT_HANDLING); 4916 if (SAFE_FOR_TEMPLATES) ALLOW_DATA_ATTR = false; 4917 if (RETURN_DOM_FRAGMENT) RETURN_DOM = true; 4918 if (USE_PROFILES) { 4919 ALLOWED_TAGS = addToSet({}, text); 4920 ALLOWED_ATTR = create(null); 4921 if (USE_PROFILES.html === true) { 4922 addToSet(ALLOWED_TAGS, html$1); 4923 addToSet(ALLOWED_ATTR, html); 4924 } 4925 if (USE_PROFILES.svg === true) { 4926 addToSet(ALLOWED_TAGS, svg$1); 4927 addToSet(ALLOWED_ATTR, svg); 4928 addToSet(ALLOWED_ATTR, xml); 4929 } 4930 if (USE_PROFILES.svgFilters === true) { 4931 addToSet(ALLOWED_TAGS, svgFilters); 4932 addToSet(ALLOWED_ATTR, svg); 4933 addToSet(ALLOWED_ATTR, xml); 4934 } 4935 if (USE_PROFILES.mathMl === true) { 4936 addToSet(ALLOWED_TAGS, mathMl$1); 4937 addToSet(ALLOWED_ATTR, mathMl); 4938 addToSet(ALLOWED_ATTR, xml); 4939 } 4940 } 4941 EXTRA_ELEMENT_HANDLING.tagCheck = null; 4942 EXTRA_ELEMENT_HANDLING.attributeCheck = null; 4943 if (objectHasOwnProperty(cfg, "ADD_TAGS")) { 4944 if (typeof cfg.ADD_TAGS === "function") EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS; 4945 else if (arrayIsArray(cfg.ADD_TAGS)) { 4946 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) ALLOWED_TAGS = clone(ALLOWED_TAGS); 4947 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); 4948 } 4949 } 4950 if (objectHasOwnProperty(cfg, "ADD_ATTR")) { 4951 if (typeof cfg.ADD_ATTR === "function") EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR; 4952 else if (arrayIsArray(cfg.ADD_ATTR)) { 4953 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) ALLOWED_ATTR = clone(ALLOWED_ATTR); 4954 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); 4955 } 4956 } 4957 if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc); 4958 if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) { 4959 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS); 4960 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc); 4961 } 4962 if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) { 4963 if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS); 4964 addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc); 4965 } 4966 if (KEEP_CONTENT) ALLOWED_TAGS["#text"] = true; 4967 if (WHOLE_DOCUMENT) addToSet(ALLOWED_TAGS, [ 4968 "html", 4969 "head", 4970 "body" 4971 ]); 4972 if (ALLOWED_TAGS.table) { 4973 addToSet(ALLOWED_TAGS, ["tbody"]); 4974 delete FORBID_TAGS.tbody; 4975 } 4976 if (cfg.TRUSTED_TYPES_POLICY) { 4977 if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") throw typeErrorCreate("TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook."); 4978 if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") throw typeErrorCreate("TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook."); 4979 const previousTrustedTypesPolicy = trustedTypesPolicy; 4980 trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY; 4981 try { 4982 emptyHTML = _createTrustedHTML(""); 4983 } catch (error) { 4984 trustedTypesPolicy = previousTrustedTypesPolicy; 4985 throw error; 4986 } 4987 } else if (cfg.TRUSTED_TYPES_POLICY === null) { 4988 trustedTypesPolicy = void 0; 4989 emptyHTML = ""; 4990 } else { 4991 if (trustedTypesPolicy === void 0) trustedTypesPolicy = _getDefaultTrustedTypesPolicy(); 4992 if (trustedTypesPolicy && typeof emptyHTML === "string") emptyHTML = _createTrustedHTML(""); 4993 } 4994 if (freeze) freeze(cfg); 4995 CONFIG = cfg; 4996 }; 4997 const ALL_SVG_TAGS = addToSet({}, [ 4998 ...svg$1, 4999 ...svgFilters, 5000 ...svgDisallowed 5001 ]); 5002 const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]); 5003 /** 5004 * Namespace rules for an element in the SVG namespace. 5005 * 5006 * @param tagName the element's lowercase tag name 5007 * @param parent the (possibly simulated) parent node 5008 * @param parentTagName the parent's lowercase tag name 5009 * @returns true if a spec-compliant parser could produce this element 5010 */ 5011 const _checkSvgNamespace = function _checkSvgNamespace(tagName, parent, parentTagName) { 5012 if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "svg"; 5013 if (parent.namespaceURI === MATHML_NAMESPACE) return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); 5014 return Boolean(ALL_SVG_TAGS[tagName]); 5015 }; 5016 /** 5017 * Namespace rules for an element in the MathML namespace. 5018 * 5019 * @param tagName the element's lowercase tag name 5020 * @param parent the (possibly simulated) parent node 5021 * @param parentTagName the parent's lowercase tag name 5022 * @returns true if a spec-compliant parser could produce this element 5023 */ 5024 const _checkMathMlNamespace = function _checkMathMlNamespace(tagName, parent, parentTagName) { 5025 if (parent.namespaceURI === HTML_NAMESPACE) return tagName === "math"; 5026 if (parent.namespaceURI === SVG_NAMESPACE) return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName]; 5027 return Boolean(ALL_MATHML_TAGS[tagName]); 5028 }; 5029 /** 5030 * Namespace rules for an element in the HTML namespace. 5031 * 5032 * @param tagName the element's lowercase tag name 5033 * @param parent the (possibly simulated) parent node 5034 * @param parentTagName the parent's lowercase tag name 5035 * @returns true if a spec-compliant parser could produce this element 5036 */ 5037 const _checkHtmlNamespace = function _checkHtmlNamespace(tagName, parent, parentTagName) { 5038 if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) return false;
vendor: 4,228 bytes, lines 5039-5150
5039 if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) return false; 5040 return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); 5041 }; 5042 /** 5043 * @param element a DOM element whose namespace is being checked 5044 * @returns Return false if the element has a 5045 * namespace that a spec-compliant parser would never 5046 * return. Return true otherwise. 5047 */ 5048 const _checkValidNamespace = function _checkValidNamespace(element) { 5049 let parent = getParentNode(element); 5050 if (!parent || !parent.tagName) parent = { 5051 namespaceURI: NAMESPACE, 5052 tagName: "template" 5053 }; 5054 const tagName = stringToLowerCase(element.tagName); 5055 const parentTagName = stringToLowerCase(parent.tagName); 5056 if (!ALLOWED_NAMESPACES[element.namespaceURI]) return false; 5057 if (element.namespaceURI === SVG_NAMESPACE) return _checkSvgNamespace(tagName, parent, parentTagName); 5058 if (element.namespaceURI === MATHML_NAMESPACE) return _checkMathMlNamespace(tagName, parent, parentTagName); 5059 if (element.namespaceURI === HTML_NAMESPACE) return _checkHtmlNamespace(tagName, parent, parentTagName); 5060 if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) return true; 5061 return false; 5062 }; 5063 /** 5064 * _forceRemove 5065 * 5066 * @param node a DOM node 5067 */ 5068 const _forceRemove = function _forceRemove(node) { 5069 arrayPush(DOMPurify.removed, { element: node }); 5070 try { 5071 getParentNode(node).removeChild(node); 5072 } catch (_) { 5073 remove(node); 5074 if (!getParentNode(node)) throw typeErrorCreate("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place"); 5075 } 5076 }; 5077 /** 5078 * _neutralizeRoot 5079 * 5080 * Fail-closed teardown of an in-place root after the sanitize walk aborts 5081 * (campaign-3 F2). An internal throw mid-walk — e.g. a page-registered 5082 * custom element's reaction detaches a node so `_forceRemove`'s deliberate 5083 * parentless guard throws, or any other re-entrant engine mutation — would 5084 * otherwise leave the caller's *live* tree half-sanitized, with everything 5085 * after the abort point still carrying its handlers. There is no safe way 5086 * to resume the walk (the tree mutated under us), so we strip the root bare: 5087 * remove every child and every attribute, then let the caller's catch see 5088 * the original error. Clobber-safe (cached `remove`/`childNodes`/`attributes` 5089 * getters; the root was already clobber-pre-flighted at the IN_PLACE entry). 5090 * 5091 * @param root the in-place root to empty 5092 */ 5093 const _neutralizeRoot = function _neutralizeRoot(root) { 5094 const childNodes = getChildNodes(root); 5095 if (childNodes) { 5096 const snapshot = []; 5097 arrayForEach(childNodes, (child) => { 5098 arrayPush(snapshot, child); 5099 }); 5100 arrayForEach(snapshot, (child) => { 5101 try { 5102 remove(child); 5103 } catch (_) {} 5104 }); 5105 } 5106 const attributes = getAttributes(root); 5107 if (attributes) for (let i = attributes.length - 1; i >= 0; --i) { 5108 const attribute = attributes[i]; 5109 const name = attribute && attribute.name; 5110 if (typeof name === "string") try { 5111 root.removeAttribute(name); 5112 } catch (_) {} 5113 } 5114 }; 5115 /** 5116 * _removeAttribute 5117 * 5118 * @param name an Attribute name 5119 * @param element a DOM node 5120 */ 5121 const _removeAttribute = function _removeAttribute(name, element) { 5122 try { 5123 arrayPush(DOMPurify.removed, { 5124 attribute: element.getAttributeNode(name), 5125 from: element 5126 }); 5127 } catch (_) { 5128 arrayPush(DOMPurify.removed, { 5129 attribute: null, 5130 from: element 5131 }); 5132 } 5133 element.removeAttribute(name); 5134 if (name === "is") if (RETURN_DOM || RETURN_DOM_FRAGMENT) try { 5135 _forceRemove(element); 5136 } catch (_) {} 5137 else try { 5138 element.setAttribute(name, ""); 5139 } catch (_) {} 5140 }; 5141 /** 5142 * _stripDisallowedAttributes 5143 * 5144 * Removes every attribute the active configuration does not allow from a 5145 * single element, using the same allowlist as the main attribute pass (so 5146 * `on*` handlers go, but no `/^on/` blocklist is introduced). Used only to 5147 * neutralise nodes that are being discarded from an in-place tree. 5148 * 5149 * @param element the element to strip 5150 */
vendor: 8,537 bytes, lines 5151-5314
5151 const _stripDisallowedAttributes = function _stripDisallowedAttributes(element) { 5152 const attributes = getAttributes(element); 5153 if (!attributes) return; 5154 for (let i = attributes.length - 1; i >= 0; --i) { 5155 const attribute = attributes[i]; 5156 const name = attribute && attribute.name; 5157 if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) continue; 5158 try { 5159 element.removeAttribute(name); 5160 } catch (_) {} 5161 } 5162 }; 5163 /** 5164 * _neutralizeSubtree 5165 * 5166 * Completes the audit-5 F1 fix across every removal path. The KEEP_CONTENT 5167 * move-hoist neutralises only disallowed-tag removals; clobber, mXSS-canary, 5168 * namespace, comment, processing-instruction and KEEP_CONTENT:false removals 5169 * all drop their subtree wholesale via `_forceRemove`. On the IN_PLACE path 5170 * those dropped nodes are detached from the caller's LIVE tree but a 5171 * handler-bearing original among them (an `<img onerror>`/`<video>` that was 5172 * loading) keeps its queued resource event, which fires in page scope after 5173 * sanitize returns. This walks a removed subtree and strips every attribute 5174 * the active configuration does not allow — so `on*` handlers are cancelled 5175 * through the SAME allowlist that governs kept nodes, not a separate `/^on/` 5176 * blocklist. Run synchronously before sanitize returns, i.e. before any 5177 * queued event can fire. Hook-free by design: these nodes leave the output, 5178 * so firing attribute hooks for them would be surprising. Clobber-safe reads; 5179 * a doomed clobbered node may shadow `removeAttribute` (its own attributes are 5180 * irrelevant — it is discarded — while its non-clobbered descendants, e.g. 5181 * the `<img>`, are reached and scrubbed). 5182 * 5183 * @param root the root of a removed subtree to neutralise 5184 */ 5185 const _neutralizeSubtree = function _neutralizeSubtree(root) { 5186 const stack = [root]; 5187 while (stack.length > 0) { 5188 const node = stack.pop(); 5189 if ((getNodeType ? getNodeType(node) : node.nodeType) === NODE_TYPE.element) _stripDisallowedAttributes(node); 5190 const childNodes = getChildNodes(node); 5191 if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]); 5192 } 5193 }; 5194 /** 5195 * _initDocument 5196 * 5197 * @param dirty - a string of dirty markup 5198 * @return a DOM, filled with the dirty markup 5199 */ 5200 const _initDocument = function _initDocument(dirty) { 5201 let doc = null; 5202 let leadingWhitespace = null; 5203 if (FORCE_BODY) dirty = "<remove></remove>" + dirty; 5204 else { 5205 const matches = stringMatch(dirty, /^[\r\n\t ]+/); 5206 leadingWhitespace = matches && matches[0]; 5207 } 5208 if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) dirty = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>" + dirty + "</body></html>"; 5209 const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty; 5210 if (NAMESPACE === HTML_NAMESPACE) try { 5211 doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE); 5212 } catch (_) {} 5213 if (!doc || !doc.documentElement) { 5214 doc = implementation.createDocument(NAMESPACE, "template", null); 5215 try { 5216 doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload; 5217 } catch (_) {} 5218 } 5219 const body = doc.body || doc.documentElement; 5220 if (dirty && leadingWhitespace) body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null); 5221 if (NAMESPACE === HTML_NAMESPACE) return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0]; 5222 return WHOLE_DOCUMENT ? doc.documentElement : body; 5223 }; 5224 /** 5225 * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. 5226 * 5227 * @param root The root element or node to start traversing on. 5228 * @return The created NodeIterator 5229 */ 5230 const _createNodeIterator = function _createNodeIterator(root) { 5231 return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null); 5232 }; 5233 /** 5234 * Replace template expression syntax (mustache, ERB, template 5235 * literal) with a space; shared by all SAFE_FOR_TEMPLATES scrub 5236 * sites. Order matters: mustache, then ERB, then template literal. 5237 * 5238 * @param value the string to scrub 5239 * @returns the scrubbed string 5240 */ 5241 const _stripTemplateExpressions = function _stripTemplateExpressions(value) { 5242 value = stringReplace(value, MUSTACHE_EXPR$1, " "); 5243 value = stringReplace(value, ERB_EXPR$1, " "); 5244 value = stringReplace(value, TMPLIT_EXPR$1, " "); 5245 return value; 5246 }; 5247 /** 5248 * Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the 5249 * character data of an element subtree. Used as the final safety net for 5250 * SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions 5251 * which only form after text-node normalization (e.g. fragments split across 5252 * stripped elements) cannot survive into a template-evaluating framework. 5253 * 5254 * Walks text/comment/CDATA/processing-instruction nodes and mutates `.data` 5255 * in place rather than round-tripping through innerHTML. This preserves 5256 * descendant node references (important for IN_PLACE callers), avoids a 5257 * serialize/reparse cycle, and reads literal character data — which means 5258 * `<%...%>` in text content matches the ERB regex against its real bytes 5259 * instead of the HTML-entity-escaped form innerHTML would produce. 5260 * 5261 * Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for 5262 * attributes is performed during the per-node `_sanitizeAttributes` pass. 5263 * 5264 * @param node The root element whose character data should be scrubbed. 5265 */ 5266 const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) { 5267 var _node$querySelectorAl; 5268 node.normalize(); 5269 const walker = createNodeIterator.call(node.ownerDocument || node, node, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null); 5270 let currentNode = walker.nextNode(); 5271 while (currentNode) { 5272 currentNode.data = _stripTemplateExpressions(currentNode.data); 5273 currentNode = walker.nextNode(); 5274 } 5275 const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, "template"); 5276 if (templates) arrayForEach(templates, (tmpl) => { 5277 if (_isDocumentFragment(tmpl.content)) _scrubTemplateExpressions2(tmpl.content); 5278 }); 5279 }; 5280 /** 5281 * _isClobbered 5282 * 5283 * Detect DOM-clobbering on HTMLFormElement nodes. Form is the only HTML 5284 * interface with [LegacyOverrideBuiltIns]; a descendant element with a 5285 * `name` attribute matching a prototype property shadows that property 5286 * on direct reads. We use this check at the IN_PLACE entry-point and 5287 * during attribute sanitization to refuse clobbered forms. 5288 * 5289 * @param element element to check for clobbering attacks 5290 * @return true if clobbered, false if safe 5291 */ 5292 const _isClobbered = function _isClobbered(element) { 5293 const realTagName = getNodeName ? getNodeName(element) : null; 5294 if (typeof realTagName !== "string") return false; 5295 if (transformCaseFunc(realTagName) !== "form") return false; 5296 return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || element.nodeType !== getNodeType(element) || element.childNodes !== getChildNodes(element); 5297 }; 5298 /** 5299 * Checks whether the given value is a DocumentFragment from any realm. 5300 * 5301 * The realm-independent replacement reads `nodeType` through the cached 5302 * Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE 5303 * constant (11). nodeType is a numeric value resolved from the node's 5304 * internal slot, identical across realms for the same kind of node. 5305 * 5306 * @param value object to check 5307 * @return true if value is a DocumentFragment-shaped node from any realm 5308 */ 5309 const _isDocumentFragment = function _isDocumentFragment(value) { 5310 if (!getNodeType || typeof value !== "object" || value === null) return false; 5311 try { 5312 return getNodeType(value) === NODE_TYPE.documentFragment; 5313 } catch (_) { 5314 return false;
vendor: 5,233 bytes, lines 5315-5430
5315 } 5316 }; 5317 /** 5318 * Checks whether the given object is a DOM node, including nodes that 5319 * originate from a different window/realm (e.g. an iframe's 5320 * contentDocument). The previous `value instanceof Node` check was 5321 * realm-bound: nodes from a different window failed it, causing 5322 * sanitize() to silently stringify them and reset IN_PLACE to false, 5323 * returning the original node unsanitized. See GHSA-4w3q-35jp-p934. 5324 * 5325 * @param value object to check whether it's a DOM node 5326 * @return true if value is a DOM node from any realm 5327 */ 5328 const _isNode = function _isNode(value) { 5329 if (!getNodeType || typeof value !== "object" || value === null) return false; 5330 try { 5331 return typeof getNodeType(value) === "number"; 5332 } catch (_) { 5333 return false; 5334 } 5335 }; 5336 function _executeHooks(hooks, currentNode, data) { 5337 if (hooks.length === 0) return; 5338 arrayForEach(hooks, (hook) => { 5339 hook.call(DOMPurify, currentNode, data, CONFIG); 5340 }); 5341 } 5342 /** 5343 * Structural-threat checks that condemn a node regardless of the 5344 * allowlists: mXSS via namespace confusion, risky CSS construction, 5345 * processing instructions, markup-bearing comments. Pure predicate; 5346 * the caller removes. Check order is load-bearing. 5347 * 5348 * @param currentNode the node to inspect 5349 * @param tagName the node's transformCaseFunc'd tag name 5350 * @return true if the node must be removed 5351 */ 5352 const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) { 5353 if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) return true; 5354 if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) return true; 5355 if (currentNode.nodeType === NODE_TYPE.processingInstruction) return true; 5356 if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) return true; 5357 return false; 5358 }; 5359 /** 5360 * Handle a node whose tag is forbidden or not allowlisted: keep 5361 * allowed custom elements (false return exits _sanitizeElements 5362 * early - namespace/fallback checks and the afterSanitizeElements 5363 * hook are intentionally skipped for kept custom elements), else 5364 * hoist content per KEEP_CONTENT and remove. 5365 * 5366 * @param currentNode the disallowed node 5367 * @param tagName the node's transformCaseFunc'd tag name 5368 * @return true if the node was removed, false if kept 5369 */ 5370 const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName) { 5371 if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) { 5372 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false; 5373 if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false; 5374 } 5375 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) { 5376 const parentNode = getParentNode(currentNode); 5377 const childNodes = getChildNodes(currentNode); 5378 if (childNodes && parentNode) { 5379 const childCount = childNodes.length; 5380 for (let i = childCount - 1; i >= 0; --i) { 5381 const hoisted = IN_PLACE ? childNodes[i] : cloneNode(childNodes[i], true); 5382 parentNode.insertBefore(hoisted, getNextSibling(currentNode)); 5383 } 5384 } 5385 } 5386 _forceRemove(currentNode); 5387 return true; 5388 }; 5389 /** 5390 * _sanitizeElements 5391 * 5392 * @protect nodeName 5393 * @protect textContent 5394 * @protect removeChild 5395 * @param currentNode to check for permission to exist 5396 * @return true if node was killed, false if left alive 5397 */ 5398 const _sanitizeElements = function _sanitizeElements(currentNode) { 5399 _executeHooks(hooks.beforeSanitizeElements, currentNode, null); 5400 if (_isClobbered(currentNode)) { 5401 _forceRemove(currentNode); 5402 return true; 5403 } 5404 const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName); 5405 _executeHooks(hooks.uponSanitizeElement, currentNode, { 5406 tagName, 5407 allowedTags: ALLOWED_TAGS 5408 }); 5409 if (_isUnsafeNode(currentNode, tagName)) { 5410 _forceRemove(currentNode); 5411 return true; 5412 } 5413 if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) return _sanitizeDisallowedNode(currentNode, tagName); 5414 if ((getNodeType ? getNodeType(currentNode) : currentNode.nodeType) === NODE_TYPE.element && !_checkValidNamespace(currentNode)) { 5415 _forceRemove(currentNode); 5416 return true; 5417 } 5418 if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) { 5419 _forceRemove(currentNode); 5420 return true; 5421 } 5422 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) { 5423 const content = _stripTemplateExpressions(currentNode.textContent); 5424 if (currentNode.textContent !== content) { 5425 arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() }); 5426 currentNode.textContent = content; 5427 } 5428 } 5429 _executeHooks(hooks.afterSanitizeElements, currentNode, null); 5430 return false;
5431 }; 5432 /** 5433 * _isValidAttribute 5434 * 5435 * @param lcTag Lowercase tag name of containing element. 5436 * @param lcName Lowercase attribute name. 5437 * @param value Attribute value. 5438 * @return Returns true if `value` is valid, otherwise false. 5439 */ 5440 const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { 5441 if (FORBID_ATTR[lcName]) return false; 5442 if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) return false; 5443 const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag); 5444 if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)); 5445 else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)); 5446 else if (!nameIsPermitted) if (_isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) || lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))); 5447 else return false; 5448 else if (URI_SAFE_ATTRIBUTES[lcName]); 5449 else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))); 5450 else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]); 5451 else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))); 5452 else if (value) return false; 5453 return true; 5454 }; 5455 const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, [ 5456 "annotation-xml", 5457 "color-profile", 5458 "font-face", 5459 "font-face-format", 5460 "font-face-name", 5461 "font-face-src", 5462 "font-face-uri", 5463 "missing-glyph" 5464 ]); 5465 /** 5466 * _isBasicCustomElement 5467 * checks if at least one dash is included in tagName, and it's not the first char 5468 * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name 5469 * 5470 * @param tagName name of the tag of the node to sanitize 5471 * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false. 5472 */ 5473 const _isBasicCustomElement = function _isBasicCustomElement(tagName) { 5474 return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName); 5475 }; 5476 /** 5477 * Wrap an attribute value in the matching Trusted Types object when 5478 * the active policy requires it. Namespaced attributes pass through 5479 * unchanged (no TT support yet, see 5480 * https://bugs.chromium.org/p/chromium/issues/detail?id=1305293). 5481 * 5482 * @param lcTag lowercase tag name of the containing element 5483 * @param lcName lowercase attribute name 5484 * @param namespaceURI the attribute's namespace, if any 5485 * @param value the attribute value to wrap 5486 * @return the value, wrapped when Trusted Types demand it 5487 */ 5488 const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value) { 5489 if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function" && !namespaceURI) switch (trustedTypes.getAttributeType(lcTag, lcName)) { 5490 case "TrustedHTML": return _createTrustedHTML(value); 5491 case "TrustedScriptURL": return _createTrustedScriptURL(value); 5492 } 5493 return value; 5494 }; 5495 /** 5496 * Write a modified attribute value back onto the element. On 5497 * success, re-probe for clobbering introduced by the new value and 5498 * remove the element when found; otherwise pop the removal entry 5499 * recorded by the earlier _removeAttribute (long-standing pairing 5500 * with the SANITIZE_NAMED_PROPS path - do not "fix" casually). On 5501 * failure, remove the attribute instead. 5502 * 5503 * @param currentNode the element carrying the attribute 5504 * @param name the attribute name as present on the element 5505 * @param namespaceURI the attribute's namespace, if any 5506 * @param value the new attribute value 5507 */ 5508 const _setAttributeValue = function _setAttributeValue(currentNode, name, namespaceURI, value) { 5509 try { 5510 if (namespaceURI) currentNode.setAttributeNS(namespaceURI, name, value); 5511 else currentNode.setAttribute(name, value); 5512 if (_isClobbered(currentNode)) _forceRemove(currentNode); 5513 else arrayPop(DOMPurify.removed); 5514 } catch (_) { 5515 _removeAttribute(name, currentNode); 5516 } 5517 }; 5518 /** 5519 * _sanitizeAttributes 5520 * 5521 * @protect attributes 5522 * @protect nodeName 5523 * @protect removeAttribute 5524 * @protect setAttribute 5525 * 5526 * @param currentNode to sanitize 5527 */ 5528 const _sanitizeAttributes = function _sanitizeAttributes(currentNode) { 5529 _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null); 5530 const attributes = currentNode.attributes; 5531 if (!attributes || _isClobbered(currentNode)) return; 5532 const hookEvent = { 5533 attrName: "", 5534 attrValue: "", 5535 keepAttr: true, 5536 allowedAttributes: ALLOWED_ATTR, 5537 forceKeepAttr: void 0 5538 }; 5539 let l = attributes.length; 5540 const lcTag = transformCaseFunc(currentNode.nodeName); 5541 while (l--) { 5542 const attr = attributes[l]; 5543 const name = attr.name; 5544 const namespaceURI = attr.namespaceURI; 5545 const attrValue = attr.value; 5546 const lcName = transformCaseFunc(name); 5547 const initValue = attrValue; 5548 let value = name === "value" ? initValue : stringTrim(initValue); 5549 hookEvent.attrName = lcName; 5550 hookEvent.attrValue = value; 5551 hookEvent.keepAttr = true; 5552 hookEvent.forceKeepAttr = void 0; 5553 _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent); 5554 value = hookEvent.attrValue;
vendor: 4,122 bytes, lines 5555-5662
5555 if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) { 5556 _removeAttribute(name, currentNode); 5557 value = SANITIZE_NAMED_PROPS_PREFIX + value; 5558 } 5559 if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) { 5560 _removeAttribute(name, currentNode); 5561 continue; 5562 } 5563 if (lcName === "attributename" && stringMatch(value, "href")) { 5564 _removeAttribute(name, currentNode); 5565 continue; 5566 } 5567 if (hookEvent.forceKeepAttr) continue; 5568 if (!hookEvent.keepAttr) { 5569 _removeAttribute(name, currentNode); 5570 continue; 5571 } 5572 if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) { 5573 _removeAttribute(name, currentNode); 5574 continue; 5575 } 5576 if (SAFE_FOR_TEMPLATES) value = _stripTemplateExpressions(value); 5577 if (!_isValidAttribute(lcTag, lcName, value)) { 5578 _removeAttribute(name, currentNode); 5579 continue; 5580 } 5581 value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value); 5582 if (value !== initValue) _setAttributeValue(currentNode, name, namespaceURI, value); 5583 } 5584 _executeHooks(hooks.afterSanitizeAttributes, currentNode, null); 5585 }; 5586 /** 5587 * _sanitizeShadowDOM 5588 * 5589 * @param fragment to iterate over recursively 5590 */ 5591 const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) { 5592 let shadowNode = null; 5593 const shadowIterator = _createNodeIterator(fragment); 5594 _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null); 5595 while (shadowNode = shadowIterator.nextNode()) { 5596 _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null); 5597 _sanitizeElements(shadowNode); 5598 _sanitizeAttributes(shadowNode); 5599 if (_isDocumentFragment(shadowNode.content)) _sanitizeShadowDOM2(shadowNode.content); 5600 if ((getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType) === NODE_TYPE.element) { 5601 const innerSr = getShadowRoot(shadowNode); 5602 if (_isDocumentFragment(innerSr)) { 5603 _sanitizeAttachedShadowRoots(innerSr); 5604 _sanitizeShadowDOM2(innerSr); 5605 } 5606 } 5607 } 5608 _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null); 5609 }; 5610 /** 5611 * _sanitizeAttachedShadowRoots 5612 * 5613 * Walks `root` and feeds every attached shadow root we encounter into 5614 * the existing _sanitizeShadowDOM pipeline. The default node iterator 5615 * does not descend into shadow trees, so nodes inside an attached 5616 * shadow root would otherwise be skipped entirely. 5617 * 5618 * Two real input paths put attached shadow roots in front of us: 5619 * 1. IN_PLACE on a DOM node that already has shadow roots attached. 5620 * 2. DOM-node input where importNode(dirty, true) deep-clones the 5621 * shadow root because it was created with `clonable: true`. 5622 * 5623 * This pass runs once, up front, so the main iteration loop (and the 5624 * existing _sanitizeShadowDOM template-content recursion) stay 5625 * untouched — string-input paths are not affected. 5626 * 5627 * @param root the subtree root to walk for attached shadow roots 5628 */ 5629 const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots(root) { 5630 const stack = [{ 5631 node: root, 5632 shadow: null 5633 }]; 5634 while (stack.length > 0) { 5635 const item = stack.pop(); 5636 if (item.shadow) { 5637 _sanitizeShadowDOM2(item.shadow); 5638 continue; 5639 } 5640 const node = item.node; 5641 const isElement = (getNodeType ? getNodeType(node) : node.nodeType) === NODE_TYPE.element; 5642 const childNodes = getChildNodes(node); 5643 if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push({ 5644 node: childNodes[i], 5645 shadow: null 5646 }); 5647 if (isElement) { 5648 const rootName = getNodeName ? getNodeName(node) : null; 5649 if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") { 5650 const content = node.content; 5651 if (_isDocumentFragment(content)) stack.push({ 5652 node: content, 5653 shadow: null 5654 }); 5655 } 5656 } 5657 if (isElement) { 5658 const sr = getShadowRoot(node); 5659 if (_isDocumentFragment(sr)) stack.push({ 5660 node: null, 5661 shadow: sr 5662 }, {
vendor: 4,286 bytes, lines 5663-5757
5663 node: sr, 5664 shadow: null 5665 }); 5666 } 5667 } 5668 }; 5669 DOMPurify.sanitize = function(dirty) { 5670 let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}; 5671 let body = null; 5672 let importedNode = null; 5673 let currentNode = null; 5674 let returnNode = null; 5675 IS_EMPTY_INPUT = !dirty; 5676 if (IS_EMPTY_INPUT) dirty = "<!-->"; 5677 if (typeof dirty !== "string" && !_isNode(dirty)) { 5678 dirty = stringifyValue(dirty); 5679 if (typeof dirty !== "string") throw typeErrorCreate("dirty is not a string, aborting"); 5680 } 5681 if (!DOMPurify.isSupported) return dirty; 5682 if (SET_CONFIG) { 5683 ALLOWED_TAGS = SET_CONFIG_ALLOWED_TAGS; 5684 ALLOWED_ATTR = SET_CONFIG_ALLOWED_ATTR; 5685 } else _parseConfig(cfg); 5686 if (hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) ALLOWED_TAGS = clone(ALLOWED_TAGS); 5687 if (hooks.uponSanitizeAttribute.length > 0) ALLOWED_ATTR = clone(ALLOWED_ATTR); 5688 DOMPurify.removed = []; 5689 const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty); 5690 if (inPlace) { 5691 const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName; 5692 if (typeof nn === "string") { 5693 const tagName = transformCaseFunc(nn); 5694 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place"); 5695 } 5696 if (_isClobbered(dirty)) throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place"); 5697 try { 5698 _sanitizeAttachedShadowRoots(dirty); 5699 } catch (error) { 5700 _neutralizeRoot(dirty); 5701 throw error; 5702 } 5703 } else if (_isNode(dirty)) { 5704 body = _initDocument("<!---->"); 5705 importedNode = body.ownerDocument.importNode(dirty, true); 5706 if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") body = importedNode; 5707 else if (importedNode.nodeName === "HTML") body = importedNode; 5708 else body.appendChild(importedNode); 5709 _sanitizeAttachedShadowRoots(importedNode); 5710 } else { 5711 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf("<") === -1) return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty; 5712 body = _initDocument(dirty); 5713 if (!body) return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : ""; 5714 } 5715 if (body && FORCE_BODY) _forceRemove(body.firstChild); 5716 const nodeIterator = _createNodeIterator(inPlace ? dirty : body); 5717 try { 5718 while (currentNode = nodeIterator.nextNode()) { 5719 _sanitizeElements(currentNode); 5720 _sanitizeAttributes(currentNode); 5721 if (_isDocumentFragment(currentNode.content)) _sanitizeShadowDOM2(currentNode.content); 5722 } 5723 } catch (error) { 5724 if (inPlace) _neutralizeRoot(dirty); 5725 throw error; 5726 } 5727 if (inPlace) { 5728 arrayForEach(DOMPurify.removed, (entry) => { 5729 if (entry.element) _neutralizeSubtree(entry.element); 5730 }); 5731 if (SAFE_FOR_TEMPLATES) _scrubTemplateExpressions2(dirty); 5732 return dirty; 5733 } 5734 if (RETURN_DOM) { 5735 if (SAFE_FOR_TEMPLATES) _scrubTemplateExpressions2(body); 5736 if (RETURN_DOM_FRAGMENT) { 5737 returnNode = createDocumentFragment.call(body.ownerDocument); 5738 while (body.firstChild) returnNode.appendChild(body.firstChild); 5739 } else returnNode = body; 5740 if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) returnNode = importNode.call(originalDocument, returnNode, true); 5741 return returnNode; 5742 } 5743 let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; 5744 if (WHOLE_DOCUMENT && ALLOWED_TAGS["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML; 5745 if (SAFE_FOR_TEMPLATES) serializedHTML = _stripTemplateExpressions(serializedHTML); 5746 return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML; 5747 }; 5748 DOMPurify.setConfig = function() { 5749 let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 5750 _parseConfig(cfg); 5751 SET_CONFIG = true; 5752 SET_CONFIG_ALLOWED_TAGS = ALLOWED_TAGS; 5753 SET_CONFIG_ALLOWED_ATTR = ALLOWED_ATTR; 5754 }; 5755 DOMPurify.clearConfig = function() { 5756 CONFIG = null; 5757 SET_CONFIG = false;
5758 SET_CONFIG_ALLOWED_TAGS = null; 5759 SET_CONFIG_ALLOWED_ATTR = null; 5760 trustedTypesPolicy = defaultTrustedTypesPolicy; 5761 emptyHTML = ""; 5762 }; 5763 DOMPurify.isValidAttribute = function(tag, attr, value) { 5764 if (!CONFIG) _parseConfig({}); 5765 const lcTag = transformCaseFunc(tag); 5766 const lcName = transformCaseFunc(attr); 5767 return _isValidAttribute(lcTag, lcName, value); 5768 }; 5769 DOMPurify.addHook = function(entryPoint, hookFunction) { 5770 if (typeof hookFunction !== "function") return; 5771 if (!objectHasOwnProperty(hooks, entryPoint)) return; 5772 arrayPush(hooks[entryPoint], hookFunction); 5773 }; 5774 DOMPurify.removeHook = function(entryPoint, hookFunction) { 5775 if (!objectHasOwnProperty(hooks, entryPoint)) return; 5776 if (hookFunction !== void 0) { 5777 const index = arrayLastIndexOf(hooks[entryPoint], hookFunction); 5778 return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0]; 5779 } 5780 return arrayPop(hooks[entryPoint]); 5781 }; 5782 DOMPurify.removeHooks = function(entryPoint) { 5783 if (!objectHasOwnProperty(hooks, entryPoint)) return; 5784 hooks[entryPoint] = []; 5785 }; 5786 DOMPurify.removeAllHooks = function() { 5787 hooks = _createHooksMap(); 5788 }; 5789 return DOMPurify; 5790 } 5791 var entries, setPrototypeOf, isFrozen, getPrototypeOf, getOwnPropertyDescriptor, freeze, seal, create, _ref, apply, construct, arrayForEach, arrayLastIndexOf, arrayPop, arrayPush, arraySplice, arrayIsArray, stringToLowerCase, stringToString, stringMatch, stringReplace, stringIndexOf, stringTrim, numberToString, booleanToString, bigintToString, symbolToString, objectHasOwnProperty, objectToString, regExpTest, typeErrorCreate, html$1, svg$1, svgFilters, svgDisallowed, mathMl$1, mathMlDisallowed, text, html, svg, mathMl, xml, MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR, DATA_ATTR, ARIA_ATTR, IS_ALLOWED_URI, IS_SCRIPT_OR_DATA, ATTR_WHITESPACE, DOCTYPE_NAME, CUSTOM_ELEMENT, ELEMENT_MARKUP_PROBE, COMMENT_MARKUP_PROBE, FALLBACK_TAG_CLOSE, SELF_CLOSING_TAG, NODE_TYPE, getGlobal, _createTrustedTypesPolicy, _createHooksMap, _resolveSetOption, purify; 5792 var init_purify_es = __esmMin((() => { 5793 entries = Object.entries; 5794 setPrototypeOf = Object.setPrototypeOf; 5795 isFrozen = Object.isFrozen; 5796 getPrototypeOf = Object.getPrototypeOf; 5797 getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; 5798 freeze = Object.freeze; 5799 seal = Object.seal; 5800 create = Object.create; 5801 _ref = typeof Reflect !== "undefined" && Reflect; 5802 apply = _ref.apply; 5803 construct = _ref.construct; 5804 if (!freeze) freeze = function freeze(x) { 5805 return x; 5806 }; 5807 if (!seal) seal = function seal(x) { 5808 return x; 5809 }; 5810 if (!apply) apply = function apply(func, thisArg) { 5811 for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key]; 5812 return func.apply(thisArg, args); 5813 }; 5814 if (!construct) construct = function construct(Func) { 5815 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) args[_key2 - 1] = arguments[_key2]; 5816 return new Func(...args); 5817 }; 5818 arrayForEach = unapply(Array.prototype.forEach); 5819 arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); 5820 arrayPop = unapply(Array.prototype.pop); 5821 arrayPush = unapply(Array.prototype.push); 5822 arraySplice = unapply(Array.prototype.splice); 5823 arrayIsArray = Array.isArray; 5824 stringToLowerCase = unapply(String.prototype.toLowerCase); 5825 stringToString = unapply(String.prototype.toString); 5826 stringMatch = unapply(String.prototype.match); 5827 stringReplace = unapply(String.prototype.replace); 5828 stringIndexOf = unapply(String.prototype.indexOf); 5829 stringTrim = unapply(String.prototype.trim); 5830 numberToString = unapply(Number.prototype.toString); 5831 booleanToString = unapply(Boolean.prototype.toString); 5832 bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString); 5833 symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString); 5834 objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); 5835 objectToString = unapply(Object.prototype.toString); 5836 regExpTest = unapply(RegExp.prototype.test); 5837 typeErrorCreate = unconstruct(TypeError); 5838 html$1 = freeze([ 5839 "a", 5840 "abbr", 5841 "acronym", 5842 "address", 5843 "area", 5844 "article", 5845 "aside", 5846 "audio", 5847 "b", 5848 "bdi", 5849 "bdo", 5850 "big", 5851 "blink", 5852 "blockquote", 5853 "body", 5854 "br", 5855 "button", 5856 "canvas", 5857 "caption", 5858 "center", 5859 "cite", 5860 "code", 5861 "col", 5862 "colgroup", 5863 "content", 5864 "data", 5865 "datalist", 5866 "dd", 5867 "decorator", 5868 "del", 5869 "details", 5870 "dfn", 5871 "dialog", 5872 "dir", 5873 "div", 5874 "dl", 5875 "dt", 5876 "element", 5877 "em", 5878 "fieldset", 5879 "figcaption", 5880 "figure", 5881 "font", 5882 "footer", 5883 "form", 5884 "h1", 5885 "h2", 5886 "h3", 5887 "h4", 5888 "h5", 5889 "h6", 5890 "head", 5891 "header", 5892 "hgroup", 5893 "hr", 5894 "html", 5895 "i", 5896 "img", 5897 "input", 5898 "ins", 5899 "kbd", 5900 "label", 5901 "legend", 5902 "li", 5903 "main", 5904 "map", 5905 "mark", 5906 "marquee", 5907 "menu", 5908 "menuitem", 5909 "meter", 5910 "nav", 5911 "nobr", 5912 "ol", 5913 "optgroup", 5914 "option", 5915 "output", 5916 "p", 5917 "picture", 5918 "pre", 5919 "progress", 5920 "q", 5921 "rp", 5922 "rt", 5923 "ruby", 5924 "s", 5925 "samp", 5926 "search", 5927 "section", 5928 "select", 5929 "shadow", 5930 "slot", 5931 "small", 5932 "source", 5933 "spacer", 5934 "span", 5935 "strike", 5936 "strong", 5937 "style", 5938 "sub", 5939 "summary", 5940 "sup", 5941 "table", 5942 "tbody", 5943 "td", 5944 "template", 5945 "textarea", 5946 "tfoot", 5947 "th", 5948 "thead", 5949 "time", 5950 "tr", 5951 "track", 5952 "tt", 5953 "u", 5954 "ul", 5955 "var", 5956 "video", 5957 "wbr" 5958 ]); 5959 svg$1 = freeze([ 5960 "svg", 5961 "a", 5962 "altglyph", 5963 "altglyphdef", 5964 "altglyphitem", 5965 "animatecolor", 5966 "animatemotion", 5967 "animatetransform", 5968 "circle", 5969 "clippath", 5970 "defs", 5971 "desc", 5972 "ellipse", 5973 "enterkeyhint", 5974 "exportparts", 5975 "filter", 5976 "font", 5977 "g", 5978 "glyph", 5979 "glyphref", 5980 "hkern", 5981 "image", 5982 "inputmode", 5983 "line", 5984 "lineargradient", 5985 "marker", 5986 "mask", 5987 "metadata", 5988 "mpath", 5989 "part", 5990 "path", 5991 "pattern", 5992 "polygon", 5993 "polyline", 5994 "radialgradient", 5995 "rect", 5996 "stop", 5997 "style", 5998 "switch", 5999 "symbol", 6000 "text", 6001 "textpath", 6002 "title", 6003 "tref", 6004 "tspan", 6005 "view", 6006 "vkern" 6007 ]); 6008 svgFilters = freeze([ 6009 "feBlend", 6010 "feColorMatrix", 6011 "feComponentTransfer", 6012 "feComposite", 6013 "feConvolveMatrix", 6014 "feDiffuseLighting", 6015 "feDisplacementMap", 6016 "feDistantLight", 6017 "feDropShadow", 6018 "feFlood", 6019 "feFuncA", 6020 "feFuncB", 6021 "feFuncG", 6022 "feFuncR", 6023 "feGaussianBlur", 6024 "feImage", 6025 "feMerge", 6026 "feMergeNode", 6027 "feMorphology", 6028 "feOffset", 6029 "fePointLight", 6030 "feSpecularLighting", 6031 "feSpotLight", 6032 "feTile", 6033 "feTurbulence" 6034 ]); 6035 svgDisallowed = freeze([ 6036 "animate", 6037 "color-profile", 6038 "cursor", 6039 "discard", 6040 "font-face", 6041 "font-face-format", 6042 "font-face-name", 6043 "font-face-src", 6044 "font-face-uri", 6045 "foreignobject", 6046 "hatch", 6047 "hatchpath", 6048 "mesh", 6049 "meshgradient", 6050 "meshpatch", 6051 "meshrow", 6052 "missing-glyph", 6053 "script", 6054 "set", 6055 "solidcolor", 6056 "unknown", 6057 "use" 6058 ]); 6059 mathMl$1 = freeze([ 6060 "math", 6061 "menclose", 6062 "merror", 6063 "mfenced", 6064 "mfrac", 6065 "mglyph", 6066 "mi", 6067 "mlabeledtr", 6068 "mmultiscripts", 6069 "mn", 6070 "mo", 6071 "mover", 6072 "mpadded", 6073 "mphantom", 6074 "mroot", 6075 "mrow", 6076 "ms", 6077 "mspace", 6078 "msqrt", 6079 "mstyle", 6080 "msub", 6081 "msup", 6082 "msubsup", 6083 "mtable", 6084 "mtd", 6085 "mtext", 6086 "mtr", 6087 "munder", 6088 "munderover", 6089 "mprescripts" 6090 ]); 6091 mathMlDisallowed = freeze([ 6092 "maction", 6093 "maligngroup", 6094 "malignmark", 6095 "mlongdiv", 6096 "mscarries", 6097 "mscarry", 6098 "msgroup", 6099 "mstack", 6100 "msline", 6101 "msrow", 6102 "semantics", 6103 "annotation", 6104 "annotation-xml", 6105 "mprescripts", 6106 "none" 6107 ]); 6108 text = freeze(["#text"]); 6109 html = freeze([ 6110 "accept", 6111 "action", 6112 "align", 6113 "alt", 6114 "autocapitalize", 6115 "autocomplete", 6116 "autopictureinpicture", 6117 "autoplay", 6118 "background", 6119 "bgcolor", 6120 "border", 6121 "capture", 6122 "cellpadding", 6123 "cellspacing", 6124 "checked", 6125 "cite", 6126 "class", 6127 "clear", 6128 "color", 6129 "cols", 6130 "colspan", 6131 "command", 6132 "commandfor", 6133 "controls", 6134 "controlslist", 6135 "coords", 6136 "crossorigin", 6137 "datetime", 6138 "decoding", 6139 "default", 6140 "dir", 6141 "disabled", 6142 "disablepictureinpicture", 6143 "disableremoteplayback", 6144 "download", 6145 "draggable", 6146 "enctype", 6147 "enterkeyhint", 6148 "exportparts", 6149 "face", 6150 "for", 6151 "headers",
6152 "height", 6153 "hidden", 6154 "high", 6155 "href", 6156 "hreflang", 6157 "id", 6158 "inert", 6159 "inputmode", 6160 "integrity", 6161 "ismap", 6162 "kind", 6163 "label", 6164 "lang", 6165 "list", 6166 "loading", 6167 "loop", 6168 "low", 6169 "max", 6170 "maxlength", 6171 "media", 6172 "method", 6173 "min", 6174 "minlength", 6175 "multiple", 6176 "muted", 6177 "name", 6178 "nonce", 6179 "noshade", 6180 "novalidate", 6181 "nowrap", 6182 "open", 6183 "optimum", 6184 "part", 6185 "pattern", 6186 "placeholder", 6187 "playsinline", 6188 "popover", 6189 "popovertarget", 6190 "popovertargetaction", 6191 "poster", 6192 "preload", 6193 "pubdate", 6194 "radiogroup", 6195 "readonly", 6196 "rel", 6197 "required", 6198 "rev", 6199 "reversed", 6200 "role", 6201 "rows", 6202 "rowspan", 6203 "spellcheck", 6204 "scope", 6205 "selected", 6206 "shape", 6207 "size", 6208 "sizes", 6209 "slot", 6210 "span", 6211 "srclang", 6212 "start", 6213 "src", 6214 "srcset", 6215 "step", 6216 "style", 6217 "summary", 6218 "tabindex", 6219 "title", 6220 "translate", 6221 "type", 6222 "usemap", 6223 "valign", 6224 "value", 6225 "width", 6226 "wrap", 6227 "xmlns" 6228 ]); 6229 svg = freeze([ 6230 "accent-height", 6231 "accumulate", 6232 "additive", 6233 "alignment-baseline", 6234 "amplitude", 6235 "ascent", 6236 "attributename", 6237 "attributetype", 6238 "azimuth", 6239 "basefrequency", 6240 "baseline-shift", 6241 "begin", 6242 "bias", 6243 "by", 6244 "class", 6245 "clip", 6246 "clippathunits", 6247 "clip-path", 6248 "clip-rule", 6249 "color", 6250 "color-interpolation", 6251 "color-interpolation-filters", 6252 "color-profile", 6253 "color-rendering", 6254 "cx", 6255 "cy", 6256 "d", 6257 "dx", 6258 "dy", 6259 "diffuseconstant", 6260 "direction", 6261 "display", 6262 "divisor", 6263 "dur", 6264 "edgemode", 6265 "elevation", 6266 "end", 6267 "exponent", 6268 "fill", 6269 "fill-opacity", 6270 "fill-rule", 6271 "filter", 6272 "filterunits", 6273 "flood-color", 6274 "flood-opacity", 6275 "font-family", 6276 "font-size", 6277 "font-size-adjust", 6278 "font-stretch", 6279 "font-style", 6280 "font-variant", 6281 "font-weight", 6282 "fx", 6283 "fy", 6284 "g1", 6285 "g2", 6286 "glyph-name", 6287 "glyphref", 6288 "gradientunits", 6289 "gradienttransform", 6290 "height", 6291 "href", 6292 "id", 6293 "image-rendering", 6294 "in", 6295 "in2", 6296 "intercept", 6297 "k", 6298 "k1", 6299 "k2", 6300 "k3", 6301 "k4", 6302 "kerning", 6303 "keypoints", 6304 "keysplines", 6305 "keytimes", 6306 "lang", 6307 "lengthadjust", 6308 "letter-spacing", 6309 "kernelmatrix", 6310 "kernelunitlength", 6311 "lighting-color", 6312 "local", 6313 "marker-end", 6314 "marker-mid", 6315 "marker-start", 6316 "markerheight", 6317 "markerunits", 6318 "markerwidth", 6319 "maskcontentunits", 6320 "maskunits", 6321 "max", 6322 "mask", 6323 "mask-type", 6324 "media", 6325 "method", 6326 "mode", 6327 "min", 6328 "name", 6329 "numoctaves", 6330 "offset", 6331 "operator", 6332 "opacity", 6333 "order", 6334 "orient", 6335 "orientation", 6336 "origin", 6337 "overflow", 6338 "paint-order", 6339 "path", 6340 "pathlength", 6341 "patterncontentunits", 6342 "patterntransform", 6343 "patternunits", 6344 "points", 6345 "preservealpha", 6346 "preserveaspectratio", 6347 "primitiveunits", 6348 "r", 6349 "rx", 6350 "ry", 6351 "radius", 6352 "refx", 6353 "refy", 6354 "repeatcount", 6355 "repeatdur", 6356 "restart", 6357 "result", 6358 "rotate", 6359 "scale", 6360 "seed", 6361 "shape-rendering", 6362 "slope", 6363 "specularconstant", 6364 "specularexponent", 6365 "spreadmethod", 6366 "startoffset", 6367 "stddeviation", 6368 "stitchtiles", 6369 "stop-color", 6370 "stop-opacity", 6371 "stroke-dasharray", 6372 "stroke-dashoffset", 6373 "stroke-linecap", 6374 "stroke-linejoin", 6375 "stroke-miterlimit", 6376 "stroke-opacity", 6377 "stroke", 6378 "stroke-width", 6379 "style", 6380 "surfacescale", 6381 "systemlanguage", 6382 "tabindex", 6383 "tablevalues", 6384 "targetx", 6385 "targety", 6386 "transform", 6387 "transform-origin", 6388 "text-anchor", 6389 "text-decoration", 6390 "text-rendering", 6391 "textlength", 6392 "type", 6393 "u1", 6394 "u2", 6395 "unicode", 6396 "values", 6397 "viewbox", 6398 "visibility", 6399 "version", 6400 "vert-adv-y", 6401 "vert-origin-x", 6402 "vert-origin-y", 6403 "width", 6404 "word-spacing", 6405 "wrap", 6406 "writing-mode", 6407 "xchannelselector", 6408 "ychannelselector", 6409 "x", 6410 "x1", 6411 "x2", 6412 "xmlns", 6413 "y", 6414 "y1", 6415 "y2", 6416 "z", 6417 "zoomandpan" 6418 ]); 6419 mathMl = freeze([ 6420 "accent", 6421 "accentunder", 6422 "align", 6423 "bevelled", 6424 "close", 6425 "columnalign", 6426 "columnlines", 6427 "columnspacing", 6428 "columnspan", 6429 "denomalign", 6430 "depth", 6431 "dir", 6432 "display", 6433 "displaystyle", 6434 "encoding", 6435 "fence", 6436 "frame",
6437 "height", 6438 "href", 6439 "id", 6440 "largeop", 6441 "length", 6442 "linethickness", 6443 "lquote", 6444 "lspace", 6445 "mathbackground", 6446 "mathcolor", 6447 "mathsize", 6448 "mathvariant", 6449 "maxsize", 6450 "minsize", 6451 "movablelimits", 6452 "notation", 6453 "numalign", 6454 "open", 6455 "rowalign", 6456 "rowlines", 6457 "rowspacing", 6458 "rowspan", 6459 "rspace", 6460 "rquote", 6461 "scriptlevel", 6462 "scriptminsize", 6463 "scriptsizemultiplier", 6464 "selection", 6465 "separator", 6466 "separators", 6467 "stretchy", 6468 "subscriptshift", 6469 "supscriptshift", 6470 "symmetric", 6471 "voffset", 6472 "width", 6473 "xmlns" 6474 ]); 6475 xml = freeze([ 6476 "xlink:href", 6477 "xml:id", 6478 "xlink:title", 6479 "xml:space", 6480 "xmlns:xlink" 6481 ]); 6482 MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g); 6483 ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g); 6484 TMPLIT_EXPR = seal(/\${[\w\W]*/g); 6485 DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); 6486 ARIA_ATTR = seal(/^aria-[\-\w]+$/); 6487 IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i); 6488 IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); 6489 ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g); 6490 DOCTYPE_NAME = seal(/^html$/i); 6491 CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); 6492 ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g); 6493 COMMENT_MARKUP_PROBE = seal(/<[/\w]/g); 6494 FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i); 6495 SELF_CLOSING_TAG = seal(/\/>/i); 6496 NODE_TYPE = { 6497 element: 1, 6498 attribute: 2, 6499 text: 3, 6500 cdataSection: 4, 6501 entityReference: 5, 6502 entityNode: 6, 6503 processingInstruction: 7, 6504 comment: 8, 6505 document: 9, 6506 documentType: 10, 6507 documentFragment: 11, 6508 notation: 12 6509 }; 6510 getGlobal = function getGlobal() { 6511 return typeof window === "undefined" ? null : window; 6512 }; 6513 _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) { 6514 if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") return null; 6515 let suffix = null; 6516 const ATTR_NAME = "data-tt-policy-suffix"; 6517 if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) suffix = purifyHostElement.getAttribute(ATTR_NAME); 6518 const policyName = "dompurify" + (suffix ? "#" + suffix : ""); 6519 try { 6520 return trustedTypes.createPolicy(policyName, { 6521 createHTML(html) { 6522 return html; 6523 }, 6524 createScriptURL(scriptUrl) { 6525 return scriptUrl; 6526 } 6527 }); 6528 } catch (_) { 6529 console.warn("TrustedTypes policy " + policyName + " could not be created."); 6530 return null; 6531 } 6532 }; 6533 _createHooksMap = function _createHooksMap() { 6534 return { 6535 afterSanitizeAttributes: [], 6536 afterSanitizeElements: [], 6537 afterSanitizeShadowDOM: [], 6538 beforeSanitizeAttributes: [], 6539 beforeSanitizeElements: [], 6540 beforeSanitizeShadowDOM: [], 6541 uponSanitizeAttribute: [], 6542 uponSanitizeElement: [], 6543 uponSanitizeShadowNode: [] 6544 }; 6545 }; 6546 _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) { 6547 return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback; 6548 }; 6549 purify = createDOMPurify(); 6550 })); 6551 //#endregion 6552 //#region modules/table-of-contents/assets/js/frontend/handlers/table-of-contents.js 6553 var table_of_contents_exports = /* @__PURE__ */ __exportAll({ default: () => TOCHandler }); 6554 var TOCHandler; 6555 var init_table_of_contents = __esmMin((() => { 6556 init_purify_es(); 6557 TOCHandler = class extends elementorModules.frontend.handlers.Base { 6558 getDefaultSettings() { 6559 return { 6560 selectors: { 6561 widgetContainer: ".elementor-widget-container", 6562 postContentContainer: ".elementor:not([data-elementor-type=\"header\"]):not([data-elementor-type=\"footer\"]):not([data-elementor-type=\"popup\"])", 6563 expandButton: ".elementor-toc__toggle-button--expand", 6564 collapseButton: ".elementor-toc__toggle-button--collapse", 6565 body: ".elementor-toc__body", 6566 headerTitle: ".elementor-toc__header-title" 6567 }, 6568 classes: { 6569 anchor: "elementor-menu-anchor", 6570 listWrapper: "elementor-toc__list-wrapper", 6571 listItem: "elementor-toc__list-item", 6572 listTextWrapper: "elementor-toc__list-item-text-wrapper", 6573 firstLevelListItem: "elementor-toc__top-level", 6574 listItemText: "elementor-toc__list-item-text", 6575 activeItem: "elementor-item-active", 6576 headingAnchor: "elementor-toc__heading-anchor", 6577 collapsed: "elementor-toc--collapsed" 6578 }, 6579 listWrapperTag: "numbers" === this.getElementSettings().marker_view ? "ol" : "ul" 6580 }; 6581 } 6582 getDefaultElements() {
6583 const settings = this.getSettings(); 6584 let widgetContainer = this.$element.find(settings.selectors.widgetContainer); 6585 if (0 === widgetContainer.length) widgetContainer = this.$element; 6586 return { 6587 $pageContainer: this.getContainer(), 6588 $widgetContainer: widgetContainer, 6589 $expandButton: this.$element.find(settings.selectors.expandButton), 6590 $collapseButton: this.$element.find(settings.selectors.collapseButton), 6591 $tocBody: this.$element.find(settings.selectors.body), 6592 $listItems: this.$element.find("." + settings.classes.listItem) 6593 }; 6594 } 6595 getContainer() { 6596 const elementSettings = this.getElementSettings(); 6597 if (elementSettings.container) return jQuery(purify.sanitize(elementSettings.container)); 6598 const $documentWrapper = this.$element.parents(".elementor"); 6599 if ("popup" === $documentWrapper.attr("data-elementor-type")) return $documentWrapper; 6600 const settings = this.getSettings(); 6601 return jQuery(settings.selectors.postContentContainer); 6602 } 6603 bindEvents() { 6604 const elementSettings = this.getElementSettings(); 6605 if (elementSettings.minimize_box) { 6606 this.elements.$expandButton.on("click", () => this.expandBox()).on("keyup", (event) => this.triggerClickOnEnterSpace(event)); 6607 this.elements.$collapseButton.on("click", () => this.collapseBox()).on("keyup", (event) => this.triggerClickOnEnterSpace(event)); 6608 } 6609 if (elementSettings.collapse_subitems) this.elements.$listItems.on("hover", (event) => jQuery(event.target).slideToggle()); 6610 } 6611 getHeadings() { 6612 const elementSettings = this.getElementSettings(); 6613 const tags = elementSettings.headings_by_tags.join(","); 6614 const selectors = this.getSettings("selectors"); 6615 const excludedSelectors = elementSettings.exclude_headings_by_selector; 6616 return this.elements.$pageContainer.find(tags).not(selectors.headerTitle).filter((index, heading) => { 6617 return !jQuery(heading).closest(excludedSelectors).length; 6618 }); 6619 } 6620 addAnchorsBeforeHeadings() { 6621 const classes = this.getSettings("classes"); 6622 this.elements.$headings.before((index) => { 6623 if (jQuery(this.elements.$headings[index]).data("hasOwnID")) return; 6624 return `<span id="${classes.headingAnchor}-${index}" class="${classes.anchor} "></span>`; 6625 }); 6626 } 6627 activateItems($listItems) { 6628 const classes = this.getSettings("classes"); 6629 this.deactivateItems($listItems); 6630 const $activeListsToExpand = []; 6631 $listItems.forEach(($item) => {
6632 $item.addClass(classes.activeItem); 6633 if (!this.getElementSettings("collapse_subitems")) return; 6634 let $activeList; 6635 if ($item.hasClass(classes.firstLevelListItem)) $activeList = $item.parent().next(); 6636 else $activeList = $item.parents("." + classes.listWrapper).eq(-2); 6637 if ($activeList.length && !$activeListsToExpand.some(($list) => $list[0].contains($activeList[0]))) $activeListsToExpand.push($activeList); 6638 }); 6639 this.deactivateLists($activeListsToExpand); 6640 this.$activeItems = $listItems; 6641 this.$activeLists = $activeListsToExpand; 6642 this.$activeLists.forEach(($list) => $list.stop().slideDown()); 6643 } 6644 deactivateItems($activeToBe) { 6645 if (!this.$activeItems || 0 === this.$activeItems.length) return; 6646 const { classes } = this.getSettings(); 6647 this.$activeItems.forEach(($item) => { 6648 if (!$activeToBe.some(($toBe) => $item.is($toBe))) $item.removeClass(classes.activeItem); 6649 }); 6650 } 6651 deactivateLists($activeListsToBe) { 6652 if (this.$activeLists) this.$activeLists.forEach(($list) => { 6653 if (!$activeListsToBe.some(($listToBe) => $list[0].contains($listToBe[0]))) $list.slideUp(); 6654 }); 6655 } 6656 updateActiveItemFromViewport(scrollDirection) { 6657 const $visibleItems = []; 6658 this.$listItemTexts.each((_, element) => { 6659 const anchorSelector = element.hash; 6660 if (!anchorSelector) return; 6661 let $anchor; 6662 try { 6663 $anchor = jQuery(decodeURIComponent(anchorSelector)); 6664 } catch (e) { 6665 return; 6666 } 6667 const id = $anchor.attr("id"); 6668 if (this.viewportItems[id]) $visibleItems.push(jQuery(element)); 6669 }); 6670 if ($visibleItems.length > 0) this.activateItems($visibleItems); 6671 else if ("up" === scrollDirection) { 6672 const currentIndex = this.$listItemTexts.index(this.$activeItems[0]); 6673 if (0 === currentIndex) { 6674 this.activateItems([]); 6675 return; 6676 } 6677 const itemToActivate = this.$listItemTexts.eq(currentIndex - 1); 6678 if (itemToActivate.length) this.activateItems([itemToActivate]); 6679 } 6680 } 6681 followAnchor($element) { 6682 const anchorSelector = $element[0].hash; 6683 let $anchor; 6684 try { 6685 $anchor = jQuery(decodeURIComponent(anchorSelector)); 6686 } catch (e) { 6687 return; 6688 } 6689 this.createObserver($anchor, { 6690 rootMargin: "0px", 6691 threshold: 0 6692 }).observe($anchor[0]); 6693 } 6694 createObserver($anchor, options) { 6695 let lastScrollTop = 0; 6696 return new IntersectionObserver((entries) => { 6697 entries.forEach((entry) => { 6698 const scrollTop = document.documentElement.scrollTop; 6699 const isScrollingDown = scrollTop > lastScrollTop; 6700 const id = $anchor.attr("id"); 6701 if (entry.isIntersecting) this.viewportItems[id] = true; 6702 else delete this.viewportItems[id]; 6703 lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; 6704 if (this.itemClicked) return; 6705 this.updateActiveItemFromViewport(isScrollingDown ? "down" : "up"); 6706 }); 6707 }, options); 6708 } 6709 followAnchors() { 6710 this.$listItemTexts.each((_index, element) => this.followAnchor(jQuery(element))); 6711 } 6712 populateTOC() { 6713 this.listItemPointer = 0; 6714 if (this.getElementSettings().hierarchical_view) this.createNestedList(); 6715 else this.createFlatList(); 6716 this.$listItemTexts = this.$element.find(".elementor-toc__list-item-text"); 6717 this.$listItemTexts.on("click", this.onListItemClick.bind(this)); 6718 if (!elementorFrontend.isEditMode()) { 6719 this.followAnchors(); 6720 requestAnimationFrame(() => this.updateActiveItemFromViewport()); 6721 } 6722 } 6723 createNestedList() { 6724 this.headingsData.forEach((heading, index) => { 6725 heading.level = 0; 6726 for (let i = index - 1; i >= 0; i--) { 6727 const currentOrderedItem = this.headingsData[i]; 6728 if (currentOrderedItem.tag <= heading.tag) { 6729 heading.level = currentOrderedItem.level; 6730 if (currentOrderedItem.tag < heading.tag) heading.level++; 6731 break; 6732 } 6733 } 6734 }); 6735 this.elements.$tocBody.html(this.getNestedLevel(0)); 6736 } 6737 createFlatList() { 6738 this.elements.$tocBody.html(this.getNestedLevel()); 6739 } 6740 getNestedLevel(level) {
6741 const settings = this.getSettings(); 6742 const elementSettings = this.getElementSettings(); 6743 const icon = this.getElementSettings("icon"); 6744 let renderedIcon; 6745 if (icon) if (elementorFrontend.config.experimentalFeatures.e_font_icon_svg && !elementorFrontend.isEditMode()) renderedIcon = typeof icon.rendered_tag !== "undefined" ? icon.rendered_tag : ""; 6746 else renderedIcon = icon.value ? `<i class="${icon.value}"></i>` : ""; 6747 let html = `<${settings.listWrapperTag} class="${settings.classes.listWrapper}">`; 6748 while (this.listItemPointer < this.headingsData.length) { 6749 const currentItem = this.headingsData[this.listItemPointer]; 6750 let listItemTextClasses = settings.classes.listItemText; 6751 if (0 === currentItem.level) listItemTextClasses += " " + settings.classes.firstLevelListItem; 6752 if (level > currentItem.level) break; 6753 if (level === currentItem.level) { 6754 html += `<li class="${settings.classes.listItem}">`; 6755 html += `<div class="${settings.classes.listTextWrapper}">`; 6756 let liContent = `<a href="#${currentItem.anchorLink}" class="${listItemTextClasses}">${currentItem.text}</a>`; 6757 if ("bullets" === elementSettings.marker_view && icon) liContent = `${renderedIcon}${liContent}`; 6758 liContent = purify.sanitize(liContent); 6759 html += liContent; 6760 html += "</div>"; 6761 this.listItemPointer++; 6762 const nextItem = this.headingsData[this.listItemPointer]; 6763 if (nextItem && level < nextItem.level) html += this.getNestedLevel(nextItem.level); 6764 html += "</li>"; 6765 } 6766 } 6767 html += `</${settings.listWrapperTag}>`; 6768 return html; 6769 } 6770 handleNoHeadingsFound() { 6771 const noHeadingsText = this.getElementSettings("no_headings_message"); 6772 return this.elements.$tocBody.html(noHeadingsText); 6773 } 6774 collapseBodyListener() { 6775 const activeBreakpoints = elementorFrontend.breakpoints.getActiveBreakpointsList({ withDesktop: true }); 6776 const minimizedOn = this.getElementSettings("minimized_on"); 6777 const currentDeviceMode = elementorFrontend.getCurrentDeviceMode(); 6778 const isCollapsed = this.$element.hasClass(this.getSettings("classes.collapsed")); 6779 if ("desktop" === minimizedOn || activeBreakpoints.indexOf(minimizedOn) >= activeBreakpoints.indexOf(currentDeviceMode)) { 6780 if (!isCollapsed) this.collapseBox(false); 6781 } else if (isCollapsed) this.expandBox(false); 6782 } 6783 onElementChange(settings) { 6784 if ("minimized_on" === settings) this.collapseBodyListener(); 6785 } 6786 getHeadingAnchorLink(index, classes) { 6787 var _a; 6788 const headingID = this.elements.$headings[index].id; 6789 const wrapperID = (_a = this.elements.$headings[index].closest(".elementor-widget")) == null ? void 0 : _a.id; 6790 const anchorLink = headingID || wrapperID; 6791 if (anchorLink) { 6792 jQuery(this.elements.$headings[index]).data("hasOwnID", true); 6793 return anchorLink; 6794 } 6795 return `${classes.headingAnchor}-${index}`; 6796 } 6797 setHeadingsData() { 6798 this.headingsData = []; 6799 const classes = this.getSettings("classes"); 6800 this.elements.$headings.each((index, element) => { 6801 const anchorLink = this.getHeadingAnchorLink(index, classes); 6802 this.headingsData.push({ 6803 tag: +element.nodeName.slice(1), 6804 text: element.textContent, 6805 anchorLink 6806 }); 6807 }); 6808 } 6809 run() { 6810 this.elements.$headings = this.getHeadings(); 6811 if (!this.elements.$headings.length) return this.handleNoHeadingsFound(); 6812 this.setHeadingsData(); 6813 if (!elementorFrontend.isEditMode()) this.addAnchorsBeforeHeadings(); 6814 this.populateTOC(); 6815 if (this.getElementSettings("minimize_box")) this.collapseBodyListener(); 6816 } 6817 expandBox(changeFocus = true) { 6818 const boxHeight = this.getCurrentDeviceSetting("min_height"); 6819 this.$element.removeClass(this.getSettings("classes.collapsed")); 6820 this.elements.$tocBody.slideDown(); 6821 this.elements.$expandButton.attr("aria-expanded", "true"); 6822 this.elements.$collapseButton.attr("aria-expanded", "true"); 6823 this.elements.$widgetContainer.css("min-height", boxHeight.size + boxHeight.unit); 6824 if (changeFocus) this.elements.$collapseButton.trigger("focus"); 6825 }
6826 collapseBox(changeFocus = true) { 6827 this.$element.addClass(this.getSettings("classes.collapsed")); 6828 this.elements.$tocBody.slideUp(); 6829 this.elements.$expandButton.attr("aria-expanded", "false"); 6830 this.elements.$collapseButton.attr("aria-expanded", "false"); 6831 this.elements.$widgetContainer.css("min-height", "0px"); 6832 if (changeFocus) this.elements.$expandButton.trigger("focus"); 6833 } 6834 triggerClickOnEnterSpace(event) { 6835 if (13 === event.keyCode || 32 === event.keyCode) { 6836 event.currentTarget.click(); 6837 event.stopPropagation(); 6838 } 6839 } 6840 onInit(...args) { 6841 super.onInit(...args); 6842 this.viewportItems = {}; 6843 this.$activeItems = []; 6844 this.$activeLists = []; 6845 jQuery(() => this.run()); 6846 } 6847 onListItemClick(event) { 6848 this.itemClicked = true; 6849 const scrollEndFallbackTimer = setTimeout(() => { 6850 this.itemClicked = false; 6851 this.updateActiveItemFromViewport(); 6852 }, 2e3); 6853 window.addEventListener("scrollend", () => { 6854 this.itemClicked = false; 6855 clearTimeout(scrollEndFallbackTimer); 6856 this.updateActiveItemFromViewport(); 6857 }, { once: true }); 6858 const $clickedItem = jQuery(event.target); 6859 const $list = $clickedItem.parent().next(); 6860 const collapseNestedList = this.getElementSettings("collapse_subitems"); 6861 let listIsActive; 6862 if (collapseNestedList && $clickedItem.hasClass(this.getSettings("classes.firstLevelListItem"))) { 6863 if ($list.is(":visible")) listIsActive = true; 6864 } 6865 this.activateItems([$clickedItem]); 6866 if (collapseNestedList && listIsActive) $list.slideUp(); 6867 } 6868 }; 6869 })); 6870 //#endregion 6871 //#region modules/table-of-contents/assets/js/frontend/frontend.js 6872 var frontend_default$9 = class extends elementorModules.Module { 6873 static { 6874 __name(this, "default"); 6875 } 6876 constructor() { 6877 super(); 6878 elementorFrontend.elementsHandler.attachHandler("table-of-contents", () => __vitePreload(() => Promise.resolve().then(() => (init_table_of_contents(), table_of_contents_exports)), void 0)); 6879 } 6880 }; 6881 //#endregion 6882 //#region modules/theme-builder/assets/js/frontend/handlers/archive-posts-load-more.js 6883 var archive_posts_load_more_exports = /* @__PURE__ */ __exportAll({ default: () => ArchivePostsLoadMore }); 6884 var ArchivePostsLoadMore; 6885 var init_archive_posts_load_more = __esmMin((() => { 6886 init_load_more$1(); 6887 ArchivePostsLoadMore = class extends LoadMore {}; 6888 })); 6889 //#endregion 6890 //#region modules/theme-builder/assets/js/frontend/handlers/archive-posts-skin-classic.js 6891 var archive_posts_skin_classic_exports = /* @__PURE__ */ __exportAll({ default: () => archive_posts_skin_classic_default }); 6892 var archive_posts_skin_classic_default; 6893 var init_archive_posts_skin_classic = __esmMin((() => { 6894 init_posts(); 6895 archive_posts_skin_classic_default = posts_default.extend({ getSkinPrefix() { 6896 return "archive_classic_"; 6897 } }); 6898 })); 6899 //#endregion 6900 //#region modules/theme-builder/assets/js/frontend/handlers/archive-posts-skin-cards.js 6901 var archive_posts_skin_cards_exports = /* @__PURE__ */ __exportAll({ default: () => archive_posts_skin_cards_default }); 6902 var archive_posts_skin_cards_default; 6903 var init_archive_posts_skin_cards = __esmMin((() => { 6904 init_cards(); 6905 archive_posts_skin_cards_default = cards_default.extend({ getSkinPrefix() { 6906 return "archive_cards_"; 6907 } }); 6908 })); 6909 //#endregion 6910 //#region modules/theme-builder/assets/js/frontend/frontend.js 6911 var frontend_default$8 = class extends elementorModules.Module { 6912 static { 6913 __name(this, "default"); 6914 } 6915 constructor() { 6916 super(); 6917 [ 6918 "archive_classic", 6919 "archive_full_content", 6920 "archive_cards" 6921 ].forEach((skinName) => { 6922 elementorFrontend.elementsHandler.attachHandler("archive-posts", () => __vitePreload(() => Promise.resolve().then(() => (init_archive_posts_load_more(), archive_posts_load_more_exports)), void 0), skinName); 6923 }); 6924 elementorFrontend.elementsHandler.attachHandler("archive-posts", () => __vitePreload(() => Promise.resolve().then(() => (init_archive_posts_skin_classic(), archive_posts_skin_classic_exports)), void 0), "archive_classic"); 6925 elementorFrontend.elementsHandler.attachHandler("archive-posts", () => __vitePreload(() => Promise.resolve().then(() => (init_archive_posts_skin_classic(), archive_posts_skin_classic_exports)), void 0), "archive_full_content"); 6926 elementorFrontend.elementsHandler.attachHandler("archive-posts", () => __vitePreload(() => Promise.resolve().then(() => (init_archive_posts_skin_cards(), archive_posts_skin_cards_exports)), void 0), "archive_cards"); 6927 jQuery(function() { 6928 var match = location.search.match(/theme_template_id=(\d*)/); 6929 var $element = match ? jQuery(".elementor-" + match[1]) : []; 6930 if ($element.length) jQuery("html, body").animate({ scrollTop: $element.offset().top - window.innerHeight / 2 }); 6931 }); 6932 } 6933 }; 6934 //#endregion 6935 //#region modules/theme-elements/assets/js/frontend/handlers/search-form.js 6936 var search_form_exports = /* @__PURE__ */ __exportAll({ default: () => search_form_default }); 6937 var search_form_default; 6938 var init_search_form = __esmMin((() => { 6939 search_form_default = elementorModules.frontend.handlers.Base.extend({ 6940 getDefaultSettings() { 6941 return { 6942 selectors: { 6943 wrapper: ".elementor-search-form", 6944 container: ".elementor-search-form__container", 6945 icon: ".elementor-search-form__icon", 6946 input: ".elementor-search-form__input", 6947 toggle: ".elementor-search-form__toggle", 6948 submit: ".elementor-search-form__submit", 6949 closeButton: ".dialog-close-button" 6950 }, 6951 classes: { 6952 isFocus: "elementor-search-form--focus", 6953 isFullScreen: "elementor-search-form--full-screen", 6954 lightbox: "elementor-lightbox" 6955 } 6956 }; 6957 }, 6958 getDefaultElements() {
6959 var selectors = this.getSettings("selectors"); 6960 var elements = {}; 6961 elements.$wrapper = this.$element.find(selectors.wrapper); 6962 elements.$container = this.$element.find(selectors.container); 6963 elements.$input = this.$element.find(selectors.input); 6964 elements.$icon = this.$element.find(selectors.icon); 6965 elements.$toggle = this.$element.find(selectors.toggle); 6966 elements.$submit = this.$element.find(selectors.submit); 6967 elements.$closeButton = this.$element.find(selectors.closeButton); 6968 return elements; 6969 }, 6970 bindEvents() { 6971 var self = this; 6972 var $container = self.elements.$container; 6973 var $closeButton = self.elements.$closeButton; 6974 var $input = self.elements.$input; 6975 var $wrapper = self.elements.$wrapper; 6976 var $icon = self.elements.$icon; 6977 var $toggle = self.elements.$toggle; 6978 var skin = this.getElementSettings("skin"); 6979 var classes = this.getSettings("classes"); 6980 const openFullScreenSearch = () => { 6981 $container.addClass(classes.isFullScreen).addClass(classes.lightbox); 6982 $input.trigger("focus"); 6983 }; 6984 const closeFullScreenSearch = () => { 6985 $container.removeClass(classes.isFullScreen).removeClass(classes.lightbox); 6986 $toggle.trigger("focus"); 6987 }; 6988 const triggerClickOnEnterSpace = (event) => { 6989 if (13 === event.keyCode || 32 === event.keyCode) { 6990 event.currentTarget.click(); 6991 event.stopPropagation(); 6992 } 6993 }; 6994 if ("full_screen" === skin) { 6995 $toggle.on("click", () => openFullScreenSearch()).on("keyup", (event) => triggerClickOnEnterSpace(event)); 6996 $container.on("click", function(event) {
6997 if ($container.hasClass(classes.isFullScreen) && $container[0] === event.target) $container.removeClass(classes.isFullScreen).removeClass(classes.lightbox); 6998 }); 6999 $closeButton.on("click", () => closeFullScreenSearch()).on("keyup", (event) => triggerClickOnEnterSpace(event)); 7000 elementorFrontend.elements.$document.on("keyup", function(event) { 7001 if (27 === event.keyCode) { 7002 if ($container.hasClass(classes.isFullScreen)) $container.trigger("click"); 7003 } 7004 }); 7005 } else $input.on({ 7006 focus() { 7007 $wrapper.addClass(classes.isFocus); 7008 }, 7009 blur() { 7010 $wrapper.removeClass(classes.isFocus); 7011 } 7012 }); 7013 if ("minimal" === skin) $icon.on("click", function() { 7014 $wrapper.addClass(classes.isFocus); 7015 $input.trigger("focus"); 7016 }); 7017 } 7018 }); 7019 })); 7020 //#endregion 7021 //#region modules/theme-elements/assets/js/frontend/frontend.js 7022 var frontend_default$7 = class extends elementorModules.Module { 7023 static { 7024 __name(this, "default"); 7025 } 7026 constructor() { 7027 super(); 7028 elementorFrontend.elementsHandler.attachHandler("search-form", () => __vitePreload(() => Promise.resolve().then(() => (init_search_form(), search_form_exports)), void 0)); 7029 } 7030 }; 7031 //#endregion 7032 //#region modules/woocommerce/assets/js/frontend/handlers/menu-cart.js 7033 var menu_cart_exports = /* @__PURE__ */ __exportAll({ default: () => menu_cart_default }); 7034 var menu_cart_default; 7035 var init_menu_cart = __esmMin((() => { 7036 menu_cart_default = class extends elementorModules.frontend.handlers.Base { 7037 static { 7038 __name(this, "default"); 7039 } 7040 getDefaultSettings() { 7041 return { 7042 selectors: { 7043 container: ".elementor-menu-cart__container", 7044 main: ".elementor-menu-cart__main", 7045 toggle: ".elementor-menu-cart__toggle", 7046 toggleButton: "#elementor-menu-cart__toggle_button", 7047 toggleWrapper: ".elementor-menu-cart__toggle_wrapper", 7048 closeButton: ".elementor-menu-cart__close-button, .elementor-menu-cart__close-button-custom", 7049 productList: ".elementor-menu-cart__products" 7050 }, 7051 classes: { isShown: "elementor-menu-cart--shown" } 7052 }; 7053 } 7054 getDefaultElements() { 7055 const selectors = this.getSettings("selectors"); 7056 return { 7057 $container: this.$element.find(selectors.container), 7058 $main: this.$element.find(selectors.main), 7059 $toggleWrapper: this.$element.find(selectors.toggleWrapper), 7060 $closeButton: this.$element.find(selectors.closeButton) 7061 }; 7062 } 7063 toggleCart() { 7064 if (!this.isCartOpen) this.showCart(); 7065 else this.hideCart(); 7066 } 7067 showCart() { 7068 if (this.isCartOpen) return; 7069 const classes = this.getSettings("classes"); 7070 const selectors = this.getSettings("selectors"); 7071 this.isCartOpen = true;
7072 this.$element.addClass(classes.isShown); 7073 this.$element.find(selectors.toggleButton).attr("aria-expanded", true); 7074 this.elements.$main.attr("aria-hidden", false); 7075 this.elements.$container.attr("aria-hidden", false); 7076 } 7077 hideCart() { 7078 if (!this.isCartOpen) return; 7079 const classes = this.getSettings("classes"); 7080 const selectors = this.getSettings("selectors"); 7081 this.isCartOpen = false; 7082 this.$element.removeClass(classes.isShown); 7083 this.$element.find(selectors.toggleButton).attr("aria-expanded", false); 7084 this.elements.$main.attr("aria-hidden", true); 7085 this.elements.$container.attr("aria-hidden", true); 7086 } 7087 automaticallyOpenCart() { 7088 if ("yes" === this.getElementSettings().automatically_open_cart) this.showCart(); 7089 } 7090 refreshFragments(eventType, data = null) { 7091 if (elementorFrontend.isEditMode() && elementorPro.modules.woocommerce.didManuallyTriggerAddToCartEvent(data)) return false; 7092 const templatesInPage = []; 7093 jQuery.each(elementorFrontend.documentsManager.documents, (index) => { 7094 templatesInPage.push(index); 7095 }); 7096 jQuery.ajax({ 7097 type: "POST", 7098 url: elementorProFrontend.config.ajaxurl, 7099 context: this, 7100 data: { 7101 action: "elementor_menu_cart_fragments", 7102 templates: templatesInPage, 7103 _nonce: ElementorProFrontendConfig.woocommerce.menu_cart.fragments_nonce, 7104 is_editor: elementorFrontend.isEditMode() 7105 }, 7106 success(successData) { 7107 if (successData === null || successData === void 0 ? void 0 : successData.fragments) jQuery.each(successData.fragments, (key, value) => { 7108 jQuery(key).replaceWith(value); 7109 }); 7110 }, 7111 complete() { 7112 if ("added_to_cart" === eventType) this.automaticallyOpenCart(); 7113 } 7114 }); 7115 } 7116 bindEvents() { 7117 const menuCart = elementorProFrontend.config.woocommerce.menu_cart; 7118 const currentUrl = -1 === menuCart.cart_page_url.indexOf("?") ? window.location.origin + window.location.pathname : window.location.href; 7119 const cartUrl = menuCart.cart_page_url; 7120 const isCart = menuCart.cart_page_url === currentUrl; 7121 const isCheckout = menuCart.checkout_page_url === currentUrl; 7122 const selectors = this.getSettings("selectors"); 7123 if (isCart && isCheckout) { 7124 this.$element.find(selectors.toggleButton).attr("href", cartUrl); 7125 return; 7126 } 7127 const classes = this.getSettings("classes");
7128 this.isCartOpen = this.$element.hasClass(classes.isShown); 7129 if ("mouseover" === this.getElementSettings().open_cart) { 7130 this.elements.$toggleWrapper.on("mouseover click", selectors.toggleButton, (event) => { 7131 event.preventDefault(); 7132 this.showCart(); 7133 }); 7134 this.elements.$toggleWrapper.on("mouseleave", () => this.hideCart()); 7135 } else this.elements.$toggleWrapper.on("click", selectors.toggleButton, (event) => { 7136 event.preventDefault(); 7137 this.toggleCart(); 7138 }); 7139 elementorFrontend.elements.$document.on("click", (event) => { 7140 if (!this.isCartOpen) return; 7141 const $target = jQuery(event.target); 7142 if ($target.closest(this.elements.$main).length || $target.closest(selectors.toggle).length) return; 7143 this.hideCart(); 7144 }); 7145 this.elements.$closeButton.on("click", (event) => { 7146 event.preventDefault(); 7147 this.hideCart(); 7148 }); 7149 elementorFrontend.elements.$document.on("keyup", (event) => { 7150 if (27 === event.keyCode) this.hideCart(); 7151 }); 7152 elementorFrontend.elements.$body.on("wc_fragments_refreshed removed_from_cart added_to_cart", (event, data) => this.refreshFragments(event.type, data)); 7153 elementorFrontend.addListenerOnce(this.getUniqueHandlerID() + "_window_resize_dropdown", "resize", () => this.governDropdownHeight()); 7154 elementorFrontend.elements.$body.on("wc_fragments_loaded wc_fragments_refreshed", () => this.governDropdownHeight()); 7155 } 7156 unbindEvents() { 7157 elementorFrontend.removeListeners(this.getUniqueHandlerID() + "_window_resize_dropdown", "resize"); 7158 } 7159 onInit() { 7160 super.onInit(); 7161 /** 7162 * When the page is reloaded after an item is added to cart, and the user activated the 7163 * "Automatically Open Cart" option, the cart should open to show the updated contents. 7164 */ 7165 if (elementorProFrontend.config.woocommerce.productAddedToCart) this.automaticallyOpenCart(); 7166 this.governDropdownHeight(); 7167 } 7168 governDropdownHeight() { 7169 if ("mini-cart" !== this.getElementSettings().cart_type) return; 7170 const selectors = this.getSettings("selectors"); 7171 const $productList = this.$element.find(selectors.productList); 7172 const $toggle = this.$element.find(selectors.toggle); 7173 if (!$productList.length || !$toggle.length) return; 7174 this.$element.find(selectors.productList).css("max-height", ""); 7175 const windowHeight = document.documentElement.clientHeight; 7176 const toggleHeight = $toggle.height() + parseInt(this.elements.$main.css("margin-top")); 7177 const toggleTopPosition = $toggle[0].getBoundingClientRect().top; 7178 const productListHeight = $productList.height(); 7179 const dropdownWithoutViewportHeight = this.elements.$main.prop("scrollHeight") - productListHeight; 7180 const maxViewportHeight = windowHeight - toggleTopPosition - toggleHeight - dropdownWithoutViewportHeight - 30; 7181 const optimalViewportHeight = Math.max(120, maxViewportHeight); 7182 $productList.css("max-height", optimalViewportHeight); 7183 } 7184 }; 7185 })); 7186 //#endregion 7187 //#region modules/woocommerce/assets/js/frontend/handlers/base.js 7188 var Base$5; 7189 var init_base = __esmMin((() => { 7190 Base$5 = class extends elementorModules.frontend.handlers.Base { 7191 static { 7192 __name(this, "Base"); 7193 } 7194 getDefaultSettings() { 7195 return { 7196 selectors: { stickyRightColumn: ".e-sticky-right-column" }, 7197 classes: { stickyRightColumnActive: "e-sticky-right-column--active" } 7198 }; 7199 } 7200 getDefaultElements() { 7201 const selectors = this.getSettings("selectors"); 7202 return { $stickyRightColumn: this.$element.find(selectors.stickyRightColumn) }; 7203 } 7204 bindEvents() { 7205 elementorFrontend.elements.$document.on("select2:open", (event) => { 7206 this.addSelect2Wrapper(event); 7207 }); 7208 } 7209 addSelect2Wrapper(event) { 7210 const selectElement = jQuery(event.target).data("select2"); 7211 if (selectElement.$dropdown) selectElement.$dropdown.addClass("e-woo-select2-wrapper"); 7212 } 7213 isStickyRightColumnActive() { 7214 const classes = this.getSettings("classes");
7215 return this.elements.$stickyRightColumn.hasClass(classes.stickyRightColumnActive); 7216 } 7217 activateStickyRightColumn() { 7218 const elementSettings = this.getElementSettings(); 7219 const $wpAdminBar = elementorFrontend.elements.$wpAdminBar; 7220 const classes = this.getSettings("classes"); 7221 let stickyOptionsOffset = elementSettings.sticky_right_column_offset || 0; 7222 if ($wpAdminBar.length && "fixed" === $wpAdminBar.css("position")) stickyOptionsOffset += $wpAdminBar.height(); 7223 if ("yes" === this.getElementSettings("sticky_right_column")) { 7224 this.elements.$stickyRightColumn.addClass(classes.stickyRightColumnActive); 7225 this.elements.$stickyRightColumn.css("top", stickyOptionsOffset + "px"); 7226 } 7227 } 7228 deactivateStickyRightColumn() { 7229 if (!this.isStickyRightColumnActive()) return; 7230 const classes = this.getSettings("classes"); 7231 this.elements.$stickyRightColumn.removeClass(classes.stickyRightColumnActive); 7232 } 7233 /** 7234 * Activates the sticky column 7235 * 7236 * @return {void} 7237 */ 7238 toggleStickyRightColumn() { 7239 if (!this.getElementSettings("sticky_right_column")) { 7240 this.deactivateStickyRightColumn(); 7241 return; 7242 } 7243 if (!this.isStickyRightColumnActive()) this.activateStickyRightColumn(); 7244 } 7245 equalizeElementHeight($element) { 7246 if ($element.length) { 7247 $element.removeAttr("style"); 7248 let maxHeight = 0; 7249 $element.each((index, element) => { 7250 maxHeight = Math.max(maxHeight, element.offsetHeight); 7251 }); 7252 if (0 < maxHeight) $element.css({ height: maxHeight + "px" }); 7253 } 7254 } 7255 /** 7256 * WooCommerce prints the Purchase Note separated from the product name by a border and padding. 7257 * In Elementor's Order Summary design, the product name and purchase note are displayed un-separated. 7258 * To achieve this design, it is necessary to access the Product Name line before the Purchase Note line to adjust 7259 * its padding. Since this cannot be achieved in CSS, it is done in this method. 7260 * 7261 * @param {Object} $element 7262 * 7263 * @return {void} 7264 */ 7265 removePaddingBetweenPurchaseNote($element) { 7266 if ($element) $element.each((index, element) => { 7267 jQuery(element).prev().children("td").addClass("product-purchase-note-is-below"); 7268 }); 7269 } 7270 /** 7271 * `elementorPageId` and `elementorWidgetId` are added to the url in the `_wp_http_referer` input which is then 7272 * received when WooCommerce does its cart and checkout ajax requests e.g `update_order_review` and `update_cart`. 7273 * These query strings are extracted from the url and used in our `load_widget_before_wc_ajax` method. 7274 */ 7275 updateWpReferers() { 7276 const selectors = this.getSettings("selectors"); 7277 const wpHttpRefererInputs = this.$element.find(selectors.wpHttpRefererInputs); 7278 const url = new URL(document.location); 7279 url.searchParams.set("elementorPageId", elementorFrontend.config.post.id); 7280 url.searchParams.set("elementorWidgetId", this.getID()); 7281 wpHttpRefererInputs.attr("value", url); 7282 } 7283 }; 7284 })); 7285 //#endregion 7286 //#region modules/woocommerce/assets/js/frontend/handlers/purchase-summary.js 7287 var purchase_summary_exports = /* @__PURE__ */ __exportAll({ default: () => PurchaseSummaryHandler }); 7288 var PurchaseSummaryHandler; 7289 var init_purchase_summary = __esmMin((() => { 7290 init_base(); 7291 PurchaseSummaryHandler = class extends Base$5 { 7292 getDefaultSettings() { 7293 return { selectors: { 7294 container: ".elementor-widget-woocommerce-purchase-summary", 7295 address: "address", 7296 purchasenote: ".product-purchase-note" 7297 } }; 7298 } 7299 getDefaultElements() { 7300 const selectors = this.getSettings("selectors"); 7301 return { 7302 $container: this.$element.find(selectors.container), 7303 $address: this.$element.find(selectors.address), 7304 $purchasenote: this.$element.find(selectors.purchasenote) 7305 }; 7306 } 7307 onElementChange(propertyName) { 7308 for (const property of [ 7309 "general_text_typography", 7310 "sections_padding", 7311 "sections_border_width" 7312 ]) if (propertyName.startsWith(property)) this.equalizeElementHeight(this.elements.$address); 7313 if (propertyName.startsWith("order_details_rows_gap")) this.removePaddingBetweenPurchaseNote(this.elements.$purchasenote); 7314 } 7315 applyButtonsHoverAnimation() { 7316 const elementSettings = this.getElementSettings(); 7317 if (elementSettings.order_details_button_hover_animation) this.$element.find(".order-again .button, td .button").addClass("elementor-animation-" + elementSettings.order_details_button_hover_animation); 7318 } 7319 onInit(...args) { 7320 super.onInit(...args); 7321 this.equalizeElementHeight(this.elements.$address); 7322 this.removePaddingBetweenPurchaseNote(this.elements.$purchasenote); 7323 this.applyButtonsHoverAnimation(); 7324 } 7325 }; 7326 })); 7327 //#endregion 7328 //#region modules/woocommerce/assets/js/frontend/handlers/checkout-page.js 7329 var checkout_page_exports = /* @__PURE__ */ __exportAll({ default: () => Checkout }); 7330 var __defProp$2, __defProps, __getOwnPropDescs, __getOwnPropSymbols, __hasOwnProp, __propIsEnum, __defNormalProp$2, __spreadValues, __spreadProps,
7330Checkout; 7331 var init_checkout_page = __esmMin((() => { 7332 init_base(); 7333 __defProp$2 = Object.defineProperty; 7334 __defProps = Object.defineProperties; 7335 __getOwnPropDescs = Object.getOwnPropertyDescriptors; 7336 __getOwnPropSymbols = Object.getOwnPropertySymbols; 7337 __hasOwnProp = Object.prototype.hasOwnProperty; 7338 __propIsEnum = Object.prototype.propertyIsEnumerable; 7339 __defNormalProp$2 = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp$2(obj, key, { 7340 enumerable: true, 7341 configurable: true, 7342 writable: true, 7343 value 7344 }) : obj[key] = value, "__defNormalProp"); 7345 __spreadValues = (a, b) => { 7346 for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp$2(a, prop, b[prop]); 7347 if (__getOwnPropSymbols) { 7348 for (var prop of __getOwnPropSymbols(b)) if (__propIsEnum.call(b, prop)) __defNormalProp$2(a, prop, b[prop]); 7349 } 7350 return a; 7351 }; 7352 __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); 7353 Checkout = class extends Base$5 { 7354 getDefaultSettings(...args) { 7355 const defaultSettings = super.getDefaultSettings(...args); 7356 return { 7357 selectors: __spreadProps(__spreadValues({}, defaultSettings.selectors), { 7358 container: ".elementor-widget-woocommerce-checkout-page", 7359 loginForm: ".e-woocommerce-login-anchor", 7360 loginSubmit: ".e-woocommerce-form-login-submit", 7361 loginSection: ".e-woocommerce-login-section", 7362 showCouponForm: ".e-show-coupon-form", 7363 couponSection: ".e-coupon-anchor", 7364 showLoginForm: ".e-show-login", 7365 applyCoupon: ".e-apply-coupon", 7366 checkoutForm: "form.woocommerce-checkout", 7367 couponBox: ".e-coupon-box", 7368 address: "address", 7369 wpHttpRefererInputs: "[name=\"_wp_http_referer\"]" 7370 }), 7371 classes: defaultSettings.classes, 7372 ajaxUrl: elementorProFrontend.config.ajaxurl 7373 }; 7374 } 7375 getDefaultElements(...args) { 7376 const selectors = this.getSettings("selectors"); 7377 return __spreadProps(__spreadValues({}, super.getDefaultElements(...args)), { 7378 $container: this.$element.find(selectors.container), 7379 $loginForm: this.$element.find(selectors.loginForm), 7380 $showCouponForm: this.$element.find(selectors.showCouponForm), 7381 $couponSection: this.$element.find(selectors.couponSection), 7382 $showLoginForm: this.$element.find(selectors.showLoginForm), 7383 $applyCoupon: this.$element.find(selectors.applyCoupon), 7384 $loginSubmit: this.$element.find(selectors.loginSubmit), 7385 $couponBox: this.$element.find(selectors.couponBox), 7386 $checkoutForm: this.$element.find(selectors.checkoutForm), 7387 $loginSection: this.$element.find(selectors.loginSection), 7388 $address: this.$element.find(selectors.address) 7389 }); 7390 } 7391 bindEvents(...args) { 7392 super.bindEvents(...args); 7393 this.elements.$showCouponForm.on("click", (event) => { 7394 event.preventDefault(); 7395 this.elements.$couponSection.slideToggle(); 7396 }); 7397 this.elements.$showLoginForm.on("click", (event) => { 7398 event.preventDefault(); 7399 this.elements.$loginForm.slideToggle(); 7400 }); 7401 this.elements.$applyCoupon.on("click", (event) => { 7402 event.preventDefault(); 7403 this.applyCoupon(); 7404 }); 7405 this.elements.$loginSubmit.on("click", (event) => { 7406 event.preventDefault(); 7407 this.loginUser(); 7408 }); 7409 elementorFrontend.elements.$body.on("updated_checkout", () => { 7410 this.applyPurchaseButtonHoverAnimation(); 7411 this.updateWpReferers(); 7412 }); 7413 } 7414 onInit(...args) { 7415 super.onInit(...args); 7416 this.toggleStickyRightColumn(); 7417 this.updateWpReferers(); 7418 this.equalizeElementHeight(this.elements.$address); 7419 if (elementorFrontend.isEditMode()) { 7420 this.elements.$loginForm.show(); 7421 this.elements.$couponSection.show(); 7422 this.applyPurchaseButtonHoverAnimation(); 7423 } 7424 } 7425 onElementChange(propertyName) { 7426 if ("sticky_right_column" === propertyName) this.toggleStickyRightColumn(); 7427 } 7428 onDestroy(...args) { 7429 super.onDestroy(...args); 7430 this.deactivateStickyRightColumn(); 7431 } 7432 applyPurchaseButtonHoverAnimation() { 7433 const purchaseButtonHoverAnimation = this.getElementSettings("purchase_button_hover_animation"); 7434 if (purchaseButtonHoverAnimation) jQuery("#place_order").addClass("elementor-animation-" + purchaseButtonHoverAnimation); 7435 } 7436 applyCoupon() { 7437 if (!wc_checkout_params) return; 7438 this.startProcessing(this.elements.$couponBox); 7439 const data = { 7440 security: wc_checkout_params.apply_coupon_nonce, 7441 coupon_code: this.elements.$couponBox.find("input[name=\"coupon_code\"]").val() 7442 }; 7443 jQuery.ajax({ 7444 type: "POST", 7445 url: wc_checkout_params.wc_ajax_url.toString().replace("%%endpoint%%", "apply_coupon"), 7446 context: this, 7447 data, 7448 success(code) { 7449 jQuery(".woocommerce-error, .woocommerce-message").remove(); 7450 this.elements.$couponBox.removeClass("processing").unblock(); 7451 if (code.includes("woocommerce-error") || code.includes("does not exist")) jQuery("html, body").animate({ scrollTop: 0 }, "fast"); 7452 if (code) { 7453 this.elements.$checkoutForm.before(code);
7454 this.elements.$couponSection.slideUp(); 7455 elementorFrontend.elements.$body.trigger("applied_coupon_in_checkout", [data.coupon_code]); 7456 elementorFrontend.elements.$body.trigger("update_checkout", { update_shipping_method: false }); 7457 } 7458 }, 7459 dataType: "html" 7460 }); 7461 } 7462 loginUser() { 7463 this.startProcessing(this.elements.$loginSection); 7464 const data = { 7465 action: "elementor_woocommerce_checkout_login_user", 7466 username: this.elements.$loginSection.find("input[name=\"username\"]").val(), 7467 password: this.elements.$loginSection.find("input[name=\"password\"]").val(), 7468 nonce: this.elements.$loginSection.find("input[name=\"woocommerce-login-nonce\"]").val(), 7469 remember: this.elements.$loginSection.find("input#rememberme").prop("checked") 7470 }; 7471 jQuery.ajax({ 7472 type: "POST", 7473 url: this.getSettings("ajaxUrl"), 7474 context: this, 7475 data, 7476 success(code) { 7477 code = JSON.parse(code); 7478 this.elements.$loginSection.removeClass("processing").unblock(); 7479 jQuery(".woocommerce-error, .woocommerce-message").remove(); 7480 if (code.logged_in) location.reload(); 7481 else { 7482 this.elements.$checkoutForm.before(code.message); 7483 elementorFrontend.elements.$body.trigger("checkout_error", [code.message]); 7484 } 7485 } 7486 }); 7487 } 7488 startProcessing($form) { 7489 if ($form.is(".processing")) return; 7490 $form.addClass("processing").block({ 7491 message: null, 7492 overlayCSS: { 7493 background: "#fff", 7494 opacity: .6 7495 } 7496 }); 7497 } 7498 }; 7499 })); 7500 //#endregion 7501 //#region \0@[email protected]/helpers/esm/objectSpread2.js 7502 function ownKeys(e, r) { 7503 var t = Object.keys(e); 7504 if (Object.getOwnPropertySymbols) { 7505 var o = Object.getOwnPropertySymbols(e); 7506 r && (o = o.filter(function(r2) { 7507 return Object.getOwnPropertyDescriptor(e, r2).enumerable; 7508 })), t.push.apply(t, o); 7509 } 7510 return t; 7511 } 7512 function _objectSpread2(e) { 7513 for (var r = 1; r < arguments.length; r++) { 7514 var t = null != arguments[r] ? arguments[r] : {}; 7515 r % 2 ? ownKeys(Object(t), true).forEach(function(r2) { 7516 _defineProperty(e, r2, t[r2]); 7517 }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) { 7518 Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2)); 7519 }); 7520 } 7521 return e; 7522 } 7523 var init_objectSpread2 = __esmMin((() => { 7524 init_defineProperty(); 7525 })); 7526 //#endregion 7527 //#region modules/woocommerce/assets/js/frontend/handlers/cart.js 7528 var cart_exports = /* @__PURE__ */ __exportAll({ default: () => Cart }); 7529 var Cart; 7530 var init_cart = __esmMin((() => { 7531 init_base(); 7532 init_objectSpread2(); 7533 Cart = class extends Base$5 { 7534 getDefaultSettings(...args) { 7535 const defaultSettings = super.getDefaultSettings(...args); 7536 return { 7537 selectors: _objectSpread2(_objectSpread2({}, defaultSettings.selectors), {}, { 7538 shippingForm: ".shipping-calculator-form", 7539 quantityInput: ".qty", 7540 updateCartButton: "button[name=update_cart]", 7541 wpHttpRefererInputs: "[name=_wp_http_referer]", 7542 hiddenInput: "input[type=hidden]", 7543 productRemove: ".product-remove a" 7544 }), 7545 classes: defaultSettings.classes, 7546 ajaxUrl: elementorProFrontend.config.ajaxurl 7547 }; 7548 } 7549 getDefaultElements(...args) { 7550 const selectors = this.getSettings("selectors"); 7551 return _objectSpread2(_objectSpread2({}, super.getDefaultElements(...args)), {}, { 7552 $shippingForm: this.$element.find(selectors.shippingForm), 7553 $stickyColumn: this.$element.find(selectors.stickyColumn), 7554 $hiddenInput: this.$element.find(selectors.hiddenInput) 7555 }); 7556 } 7557 bindEvents() { 7558 super.bindEvents(); 7559 const selectors = this.getSettings("selectors"); 7560 elementorFrontend.elements.$body.on("wc_fragments_refreshed", () => this.applyButtonsHoverAnimation()); 7561 if ("yes" === this.getElementSettings("update_cart_automatically")) this.$element.on("input", selectors.quantityInput, () => this.updateCart()); 7562 elementorFrontend.elements.$body.on("wc_fragments_loaded wc_fragments_refreshed", () => { 7563 this.updateWpReferers(); 7564 if (elementorFrontend.isEditMode() || elementorFrontend.isWPPreviewMode()) this.disableActions(); 7565 }); 7566 elementorFrontend.elements.$body.on("added_to_cart", function(e, data) { 7567 if (data.e_manually_triggered) return false;
7568 }); 7569 } 7570 onInit(...args) { 7571 super.onInit(...args); 7572 this.toggleStickyRightColumn(); 7573 this.hideHiddenInputsParentElements(); 7574 if (elementorFrontend.isEditMode()) this.elements.$shippingForm.show(); 7575 this.applyButtonsHoverAnimation(); 7576 this.updateWpReferers(); 7577 if (elementorFrontend.isEditMode() || elementorFrontend.isWPPreviewMode()) this.disableActions(); 7578 } 7579 /** 7580 * Using the WooCommerce Cart controls (quantity, remove product) in the editor will cause the cart to disappear. 7581 * This is because WooCommerce does an ajax round trip where it modifies the cart, then loads that cart into the 7582 * current page and attempts to grab the elements from that page via ajax. In the Editor, if the page is not 7583 * published yet, it fetches an empty page that does not contain the required elements. As a result, the cart 7584 * is rendered empty. 7585 * 7586 * Due to this issue, the cart controls (quantity, remove product) need to be disabled in the Editor. 7587 */ 7588 disableActions() { 7589 const selectors = this.getSettings("selectors"); 7590 this.$element.find(selectors.updateCartButton).attr({ 7591 disabled: "disabled", 7592 "aria-disabled": "true" 7593 }); 7594 if (elementorFrontend.isEditMode()) { 7595 this.$element.find(selectors.quantityInput).attr("disabled", "disabled"); 7596 this.$element.find(selectors.productRemove).css("pointer-events", "none"); 7597 } 7598 } 7599 onElementChange(propertyName) { 7600 if ("sticky_right_column" === propertyName) this.toggleStickyRightColumn(); 7601 if ("additional_template_select" === propertyName) elementorPro.modules.woocommerce.onTemplateIdChange("additional_template_select"); 7602 } 7603 onDestroy(...args) { 7604 super.onDestroy(...args); 7605 this.deactivateStickyRightColumn(); 7606 } 7607 updateCart() { 7608 const selectors = this.getSettings("selectors"); 7609 clearTimeout(this._debounce); 7610 this._debounce = setTimeout(() => { 7611 this.$element.find(selectors.updateCartButton).trigger("click"); 7612 }, 1500); 7613 } 7614 applyButtonsHoverAnimation() { 7615 const elementSettings = this.getElementSettings(); 7616 if (elementSettings.checkout_button_hover_animation) jQuery(".checkout-button").addClass("elementor-animation-" + elementSettings.checkout_button_hover_animation); 7617 if (elementSettings.forms_buttons_hover_animation) jQuery(".shop_table .button").addClass("elementor-animation-" + elementSettings.forms_buttons_hover_animation); 7618 } 7619 /** 7620 * In the editor, WC Frontend JS does not fire (not registered). 7621 * This causes that hidden inputs parent paragraph elements do not get display:none 7622 * as they would have on the front end. 7623 * So this function manually display:none the parent elements of these hidden inputs to avoid having 7624 * gaps/spaces in the layout caused by these parent elements' margins/paddings. 7625 */ 7626 hideHiddenInputsParentElements() { 7627 if (this.isEdit) { 7628 if (this.elements.$hiddenInput) this.elements.$hiddenInput.parent(".form-row").addClass("elementor-hidden"); 7629 } 7630 } 7631 }; 7632 })); 7633 //#endregion 7634 //#region modules/woocommerce/assets/js/frontend/handlers/my-account.js 7635 var my_account_exports = /* @__PURE__ */ __exportAll({ default: () => MyAccountHandler }); 7636 var MyAccountHandler; 7637 var init_my_account = __esmMin((() => { 7638 init_base(); 7639 MyAccountHandler = class extends Base$5 { 7640 getDefaultSettings() { 7641 return { selectors: { 7642 address: "address", 7643 tabLinks: ".woocommerce-MyAccount-navigation-link a", 7644 viewOrderButtons: ".my_account_orders .woocommerce-button.view", 7645 viewOrderLinks: ".woocommerce-orders-table__cell-order-number a", 7646 authForms: "form.login, form.register", 7647 tabWrapper: ".e-my-account-tab", 7648 tabItem: ".woocommerce-MyAccount-navigation li", 7649 allPageElements: "[e-my-account-page]", 7650 purchasenote: "tr.product-purchase-note", 7651 contentWrapper: ".woocommerce-MyAccount-content-wrapper" 7652 } }; 7653 } 7654 getDefaultElements() { 7655 const selectors = this.getSettings("selectors"); 7656 return { 7657 $address: this.$element.find(selectors.address), 7658 $tabLinks: this.$element.find(selectors.tabLinks), 7659 $viewOrderButtons: this.$element.find(selectors.viewOrderButtons), 7660 $viewOrderLinks: this.$element.find(selectors.viewOrderLinks), 7661 $authForms: this.$element.find(selectors.authForms), 7662 $tabWrapper: this.$element.find(selectors.tabWrapper), 7663 $tabItem: this.$element.find(selectors.tabItem),
7664 $allPageElements: this.$element.find(selectors.allPageElements), 7665 $purchasenote: this.$element.find(selectors.purchasenote), 7666 $contentWrapper: this.$element.find(selectors.contentWrapper) 7667 }; 7668 } 7669 editorInitTabs() { 7670 this.elements.$allPageElements.each((index, element) => { 7671 const currentPage = element.getAttribute("e-my-account-page"); 7672 let $linksToThisPage; 7673 switch (currentPage) { 7674 case "view-order": 7675 $linksToThisPage = this.elements.$viewOrderLinks.add(this.elements.$viewOrderButtons); 7676 break; 7677 default: $linksToThisPage = this.$element.find(".woocommerce-MyAccount-navigation-link--" + currentPage); 7678 } 7679 $linksToThisPage.on("click", () => { 7680 this.currentPage = currentPage; 7681 this.editorShowTab(); 7682 }); 7683 }); 7684 } 7685 editorShowTab() { 7686 const $currentPage = this.$element.find("[e-my-account-page=\"" + this.currentPage + "\"]"); 7687 this.$element.attr("e-my-account-page", this.currentPage); 7688 this.elements.$allPageElements.hide(); 7689 $currentPage.show(); 7690 this.toggleEndpointClasses(); 7691 if ("view-order" !== this.currentPage) { 7692 this.elements.$tabItem.removeClass("is-active"); 7693 this.$element.find(".woocommerce-MyAccount-navigation-link--" + this.currentPage).addClass("is-active"); 7694 } 7695 if ("edit-address" === this.currentPage || "view-order" === this.currentPage) this.equalizeElementHeights(); 7696 } 7697 toggleEndpointClasses() { 7698 const wcPages = [ 7699 "dashboard", 7700 "orders", 7701 "view-order", 7702 "downloads", 7703 "edit-account", 7704 "edit-address", 7705 "payment-methods" 7706 ]; 7707 let wrapperClass = ""; 7708 this.elements.$tabWrapper.removeClass("e-my-account-tab__" + wcPages.join(" e-my-account-tab__") + " e-my-account-tab__dashboard--custom"); 7709 if ("dashboard" === this.currentPage && this.elements.$contentWrapper.find(".elementor").length) wrapperClass = " e-my-account-tab__dashboard--custom"; 7710 if (wcPages.includes(this.currentPage)) this.elements.$tabWrapper.addClass("e-my-account-tab__" + this.currentPage + wrapperClass); 7711 } 7712 applyButtonsHoverAnimation() { 7713 const elementSettings = this.getElementSettings(); 7714 if (elementSettings.forms_buttons_hover_animation) this.$element.find(".woocommerce button.button, #add_payment_method #payment #place_order").addClass("elementor-animation-" + elementSettings.forms_buttons_hover_animation); 7715 if (elementSettings.tables_button_hover_animation) this.$element.find(".order-again .button, td .button, .woocommerce-pagination .button").addClass("elementor-animation-" + elementSettings.tables_button_hover_animation); 7716 } 7717 equalizeElementHeights() { 7718 this.equalizeElementHeight(this.elements.$address); 7719 if (!this.isEdit) this.equalizeElementHeight(this.elements.$authForms); 7720 } 7721 onElementChange(propertyName) { 7722 if (0 === propertyName.indexOf("general_text_typography") || 0 === propertyName.indexOf("sections_padding")) this.equalizeElementHeights(); 7723 if (0 === propertyName.indexOf("forms_rows_gap")) this.removePaddingBetweenPurchaseNote(this.elements.$purchasenote); 7724 if ("customize_dashboard_select" === propertyName) elementorPro.modules.woocommerce.onTemplateIdChange("customize_dashboard_select"); 7725 } 7726 bindEvents() { 7727 super.bindEvents(); 7728 elementorFrontend.elements.$body.on("keyup change", ".register #reg_password", () => { 7729 this.equalizeElementHeights(); 7730 }); 7731 } 7732 onInit(...args) { 7733 super.onInit(...args); 7734 if (this.isEdit) { 7735 this.editorInitTabs(); 7736 if (!this.$element.attr("e-my-account-page")) this.currentPage = "dashboard"; 7737 else this.currentPage = this.$element.attr("e-my-account-page"); 7738 this.editorShowTab(); 7739 } 7740 this.applyButtonsHoverAnimation(); 7741 this.equalizeElementHeights(); 7742 this.removePaddingBetweenPurchaseNote(this.elements.$purchasenote); 7743 } 7744 }; 7745 })); 7746 //#endregion 7747 //#region modules/woocommerce/assets/js/frontend/handlers/notices.js 7748 var notices_exports = /* @__PURE__ */ __exportAll({ default: () => notices_default }); 7749 var notices_default; 7750 var init_notices = __esmMin((() => { 7751 notices_default = class extends elementorModules.frontend.handlers.Base { 7752 static { 7753 __name(this, "default"); 7754 } 7755 getDefaultSettings() { 7756 return { selectors: { 7757 woocommerceNotices: ":not(.woocommerce-NoticeGroup) .wc-block-components-notice-banner, .woocommerce-NoticeGroup, :not(.woocommerce-NoticeGroup) .woocommerce-error, :not(.woocommerce-NoticeGroup) .woocommerce-message, :not(.woocommerce-NoticeGroup) .woocommerce-info", 7758 noticesWrapper: ".e-woocommerce-notices-wrapper" 7759 } }; 7760 } 7761 getDefaultElements() {
7762 const selectors = this.getSettings("selectors"); 7763 return { 7764 $documentScrollToElements: elementorFrontend.elements.$document.find("html, body"), 7765 $woocommerceCheckoutForm: elementorFrontend.elements.$body.find(".form.checkout"), 7766 $noticesWrapper: this.$element.find(selectors.noticesWrapper) 7767 }; 7768 } 7769 moveNotices(scrollToNotices = false) { 7770 const selectors = this.getSettings("selectors"); 7771 let $notices = elementorFrontend.elements.$body.find(selectors.woocommerceNotices); 7772 if (elementorFrontend.isEditMode() || elementorFrontend.isWPPreviewMode()) $notices = $notices.filter(":not(.e-notices-demo-notice)"); 7773 if (scrollToNotices) this.elements.$documentScrollToElements.stop(); 7774 this.elements.$noticesWrapper.prepend($notices); 7775 if (!this.is_ready) { 7776 this.elements.$noticesWrapper.removeClass("e-woocommerce-notices-wrapper-loading"); 7777 this.is_ready = true; 7778 } 7779 if (scrollToNotices) { 7780 let $scrollToElement = $notices; 7781 if (!$scrollToElement.length) $scrollToElement = this.elements.$woocommerceCheckoutForm; 7782 if ($scrollToElement.length) this.elements.$documentScrollToElements.animate({ scrollTop: $scrollToElement.offset().top - document.documentElement.clientHeight / 2 }, 1e3); 7783 } 7784 } 7785 onInit() { 7786 super.onInit(); 7787 this.is_ready = false; 7788 this.moveNotices(true); 7789 } 7790 bindEvents() { 7791 elementorFrontend.elements.$body.on("updated_wc_div updated_checkout updated_cart_totals applied_coupon removed_coupon applied_coupon_in_checkout removed_coupon_in_checkout checkout_error", () => this.moveNotices(true)); 7792 } 7793 }; 7794 })); 7795 //#endregion 7796 //#region modules/woocommerce/assets/js/frontend/handlers/product-add-to-cart.js 7797 var product_add_to_cart_exports = /* @__PURE__ */ __exportAll({ default: () => ProductAddToCart }); 7798 var ProductAddToCart; 7799 var init_product_add_to_cart = __esmMin((() => { 7800 init_base(); 7801 ProductAddToCart = class extends Base$5 { 7802 getDefaultSettings() { 7803 return { selectors: { 7804 quantityInput: ".e-loop-add-to-cart-form input.qty", 7805 addToCartButton: ".e-loop-add-to-cart-form .ajax_add_to_cart", 7806 addedToCartButton: ".added_to_cart", 7807 loopFormContainer: ".e-loop-add-to-cart-form-container" 7808 } }; 7809 } 7810 getDefaultElements() { 7811 const selectors = this.getSettings("selectors"); 7812 return { 7813 $quantityInput: this.$element.find(selectors.quantityInput), 7814 $addToCartButton: this.$element.find(selectors.addToCartButton) 7815 }; 7816 } 7817 updateAddToCartButtonQuantity() { 7818 this.elements.$addToCartButton.attr("data-quantity", this.elements.$quantityInput.val()); 7819 } 7820 handleAddedToCart($button) { 7821 const selectors = this.getSettings("selectors"); 7822 const $addToCartButton = $button.siblings(selectors.addedToCartButton); 7823 const $loopFormContainer = $addToCartButton.parents(selectors.loopFormContainer); 7824 $loopFormContainer.children(selectors.addedToCartButton).remove(); 7825 $loopFormContainer.append($addToCartButton); 7826 } 7827 bindEvents(...args) { 7828 super.bindEvents(...args); 7829 this.elements.$quantityInput.on("change", () => { 7830 this.updateAddToCartButtonQuantity(); 7831 }); 7832 elementorFrontend.elements.$body.off("added_to_cart.elementor-woocommerce-product-add-to-cart"); 7833 elementorFrontend.elements.$body.on("added_to_cart.elementor-woocommerce-product-add-to-cart", (e, fragments, cartHash, $button) => { 7834 this.handleAddedToCart($button); 7835 }); 7836 } 7837 }; 7838 })); 7839 //#endregion 7840 //#region modules/woocommerce/assets/js/frontend/frontend.js 7841 var frontend_default$6 = class extends elementorModules.Module { 7842 static { 7843 __name(this, "default"); 7844 } 7845 constructor() { 7846 super(); 7847 elementorFrontend.elementsHandler.attachHandler("woocommerce-menu-cart", () => __vitePreload(() => Promise.resolve().then(() => (init_menu_cart(), menu_cart_exports)), void 0)); 7848 elementorFrontend.elementsHandler.attachHandler("woocommerce-purchase-summary", () => __vitePreload(() => Promise.resolve().then(() => (init_purchase_summary(), purchase_summary_exports)), void 0)); 7849 elementorFrontend.elementsHandler.attachHandler("woocommerce-checkout-page", () => __vitePreload(() => Promise.resolve().then(() =>
7849 (init_checkout_page(), checkout_page_exports)), void 0)); 7850 elementorFrontend.elementsHandler.attachHandler("woocommerce-cart", () => __vitePreload(() => Promise.resolve().then(() => (init_cart(), cart_exports)), void 0)); 7851 elementorFrontend.elementsHandler.attachHandler("woocommerce-my-account", () => __vitePreload(() => Promise.resolve().then(() => (init_my_account(), my_account_exports)), void 0)); 7852 elementorFrontend.elementsHandler.attachHandler("woocommerce-notices", () => __vitePreload(() => Promise.resolve().then(() => (init_notices(), notices_exports)), void 0)); 7853 elementorFrontend.elementsHandler.attachHandler("woocommerce-product-add-to-cart", () => __vitePreload(() => Promise.resolve().then(() => (init_product_add_to_cart(), product_add_to_cart_exports)), void 0)); 7854 if (elementorFrontend.isEditMode()) elementorFrontend.on("components:init", () => { 7855 if (!elementorFrontend.elements.$body.find(".elementor-widget-woocommerce-cart").length) elementorFrontend.elements.$body.append("<div class=\"woocommerce-cart-form\">"); 7856 }); 7857 } 7858 }; 7859 //#endregion 7860 //#region assets/dev/js/frontend/utils/run-element-handlers.js 7861 function runElementHandlers(elements) { 7862 [...elements].flatMap((el) => [...el.querySelectorAll(".elementor-element")]).forEach((el) => elementorFrontend.elementsHandler.runReadyTrigger(el)); 7863 } 7864 var init_run_element_handlers = __esmMin((() => {})); 7865 //#endregion 7866 //#region modules/loop-builder/assets/js/frontend/handlers/load-more.js 7867 var load_more_exports = /* @__PURE__ */ __exportAll({ default: () => LoopLoadMore }); 7868 var LoopLoadMore; 7869 var init_load_more = __esmMin((() => { 7870 init_load_more$1(); 7871 init_run_element_handlers(); 7872 LoopLoadMore = class extends LoadMore { 7873 getDefaultSettings() { 7874 const defaultSettings = super.getDefaultSettings(); 7875 defaultSettings.selectors.postsContainer = ".elementor-loop-container"; 7876 defaultSettings.selectors.postWrapperTag = ".e-loop-item"; 7877 defaultSettings.selectors.loadMoreButton = ".e-loop__load-more .elementor-button"; 7878 defaultSettings.selectors.dynamicStyleElement = "style[id^=\"loop-dynamic\"]"; 7879 return defaultSettings; 7880 } 7881 afterInsertPosts(postsElements, result) { 7882 super.afterInsertPosts(postsElements); 7883 if (ElementorProFrontendConfig.settings.lazy_load_background_images) document.dispatchEvent(new Event("elementor/lazyload/observe")); 7884 this.handleDynamicStyleElements(result); 7885 runElementHandlers(postsElements); 7886 elementorFrontend.elements.$window.trigger("elementor-pro/loop-builder/after-insert-posts"); 7887 } 7888 /** 7889 * Handle Dynamic Style Elements. 7890 * 7891 * Adds the dynamic `<style>` block responsible for any styling that effects each individual loop-item 7892 * e.g. dynamic-tag background images 7893 * 7894 * @param {Object} result - Dom element after the remaining content `afterInsertPosts()` has run. 7895 */ 7896 handleDynamicStyleElements(result) { 7897 const selectors = this.getSettings("selectors"); 7898 const dynamicStyleElements = result.querySelectorAll(`[data-id="${this.elementId}"] ${selectors.dynamicStyleElement}`); 7899 this.$element.append(dynamicStyleElements); 7900 } 7901 }; 7902 })); 7903 //#endregion 7904 //#region assets/dev/js/preview/utils/document-handle.js 7905 function addDocumentHandle({ element, id, title = (0, _wordpress_i18n.__)("Template", "elementor-pro") }, context = EDIT_CONTEXT, onCloseDocument = null, selector = null) { 7906 if ("edit" === context) { 7907 if (!id || !element) throw Error("`id` and `element` are required."); 7908 if (isCurrentlyEditing(element) || hasHandle(element)) return; 7909 } 7910 const handleElement = createHandleElement({ 7911 title, 7912 onClick: () => onDocumentClick(id, context, onCloseDocument, selector) 7913 }, context, element); 7914 element.prepend(handleElement); 7915 if ("edit" === context) element.dataset.editableElementorDocument = id; 7916 } 7917 function isCurrentlyEditing(element) { 7918 return element.classList.contains(EDIT_MODE_CLASS_NAME); 7919 } 7920 function hasHandle(element) { 7921 return !!element.querySelector(`:scope > .${EDIT_HANDLE_CLASS_NAME}`); 7922 } 7923 function createHandleElement({ title, onClick }, context, element = null) { 7924 const handleTitle = ["header", "footer"].includes(element == null ? void 0 : element.dataset.elementorType) ? "%s" : (0, _wordpress_i18n.__)("Edit
7924%s", "elementor-pro"); 7925 const innerElement = createElement({ 7926 tag: "div", 7927 classNames: [`${EDIT_HANDLE_CLASS_NAME}__inner`], 7928 children: [createElement({ 7929 tag: "i", 7930 classNames: [getHandleIcon(context)] 7931 }), createElement({ 7932 tag: "div", 7933 classNames: [`${"edit" === context ? EDIT_HANDLE_CLASS_NAME : SAVE_HANDLE_CLASS_NAME}__title`], 7934 children: [document.createTextNode("edit" === context ? handleTitle.replace("%s", title) : (0, _wordpress_i18n.__)("Save %s", "elementor-pro").replace("%s", title))] 7935 })] 7936 }); 7937 const classNames = [EDIT_HANDLE_CLASS_NAME]; 7938 if ("edit" !== context) classNames.push(SAVE_HANDLE_CLASS_NAME); 7939 const containerElement = createElement({ 7940 tag: "div", 7941 classNames, 7942 children: [innerElement] 7943 }); 7944 containerElement.addEventListener("click", onClick); 7945 return containerElement; 7946 } 7947 function getHandleIcon(context) { 7948 let icon = "eicon-edit"; 7949 if ("save" === context) icon = elementorFrontend.config.is_rtl ? "eicon-arrow-right" : "eicon-arrow-left"; 7950 return icon; 7951 } 7952 function createElement({ tag, classNames = [], children = [] }) { 7953 const element = document.createElement(tag); 7954 element.classList.add(...classNames); 7955 children.forEach((child) => element.appendChild(child)); 7956 return element; 7957 } 7958 function onDocumentClick(id, context, onCloseDocument = null, selector = null) { 7959 return __async(this, null, function* () { 7960 if ("edit" === context) { 7961 window.top.$e.internal("panel/state-loading"); 7962 yield window.top.$e.run("editor/documents/switch", { 7963 id: parseInt(id), 7964 onClose: onCloseDocument, 7965 selector 7966 }); 7967 window.top.$e.internal("panel/state-ready"); 7968 } else { 7969 elementorCommon.api.internal("panel/state-loading"); 7970 elementorCommon.api.run("editor/documents/switch", { 7971 id: elementor.config.initial_document.id, 7972 mode: "save", 7973 shouldScroll: false, 7974 selector 7975 }).finally(() => elementorCommon.api.internal("panel/state-ready")); 7976 } 7977 }); 7978 } 7979 var __async, EDIT_HANDLE_CLASS_NAME, EDIT_MODE_CLASS_NAME, EDIT_CONTEXT, SAVE_HANDLE_CLASS_NAME; 7980 var init_document_handle = __esmMin((() => { 7981 __async = (__this, __arguments, generator) => { 7982 return new Promise((resolve, reject) => { 7983 var fulfilled = (value) => { 7984 try { 7985 step(generator.next(value)); 7986 } catch (e) { 7987 reject(e); 7988 } 7989 }; 7990 var rejected = (value) => { 7991 try { 7992 step(generator.throw(value)); 7993 } catch (e) { 7994 reject(e); 7995 } 7996 }; 7997 var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); 7998 step((generator = generator.apply(__this, __arguments)).next()); 7999 }); 8000 }; 8001 EDIT_HANDLE_CLASS_NAME = "elementor-document-handle"; 8002 EDIT_MODE_CLASS_NAME = "elementor-edit-mode"; 8003 EDIT_CONTEXT = "edit"; 8004 SAVE_HANDLE_CLASS_NAME = "elementor-document-save-back-handle"; 8005 })); 8006 //#endregion 8007 //#region modules/loop-builder/assets/js/frontend/handlers/loop.js 8008 var loop_exports = /* @__PURE__ */ __exportAll({ default: () => Loop }); 8009 var Loop; 8010 var init_loop = __esmMin((() => { 8011 init_posts(); 8012 init_document_handle(); 8013 Loop = class extends posts_default { 8014 getSkinPrefix() { 8015 return ""; 8016 } 8017 getDefaultSettings() { 8018 const defaultSettings = super.getDefaultSettings(); 8019 defaultSettings.selectors.post = ".elementor-loop-container .elementor"; 8020 defaultSettings.selectors.postsContainer = ".elementor-loop-container"; 8021 defaultSettings.classes.inPlaceTemplateEditable = "elementor-in-place-template-editable"; 8022 return defaultSettings; 8023 } 8024 /** 8025 * Fit Images is used in the extended Posts widget handler to apply the "Image Size", "Image Ratio" and 8026 * "Image Width" controls. These controls don't exist in the Loop Grid widget, so we override `fitImages()` 8027 * to disable it's functionality. 8028 */ 8029 fitImages() {} 8030 getVerticalSpaceBetween() { 8031 return elementorProFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), "row_gap", "size"); 8032 } 8033 /** 8034 * This is a callback that runs when the "Edit Template" document handle is clicked in the Editor. 8035 */
8036 onInPlaceEditTemplate() { 8037 this.$element.addClass(this.getDefaultSettings().classes.inPlaceTemplateEditable); 8038 this.elementsToRemove = []; 8039 this.handleSwiper(); 8040 const templateID = this.getElementSettings("template_id"); 8041 this.elementsToRemove = [ 8042 ...this.elementsToRemove, 8043 "style#loop-" + templateID, 8044 "link#font-loop-" + templateID, 8045 "style#loop-dynamic-" + templateID 8046 ]; 8047 this.elementsToRemove.forEach((elementToRemove) => { 8048 this.$element.find(elementToRemove).remove(); 8049 }); 8050 } 8051 handleSwiper() { 8052 const swiper = this.elements.$postsContainer.data("swiper"); 8053 if (!swiper) return; 8054 swiper.slideTo(0); 8055 swiper.autoplay.pause(); 8056 swiper.allowTouchMove = false; 8057 swiper.params.autoplay.delay = 1e6; 8058 swiper.update(); 8059 this.elementsToRemove = [ 8060 ...this.elementsToRemove, 8061 ".swiper-pagination", 8062 ".elementor-swiper-button", 8063 ".elementor-document-handle" 8064 ]; 8065 } 8066 attachEditDocumentHandle() { 8067 const templateId = this.getElementSettings("template_id"); 8068 if (!templateId) return; 8069 const elementSettings = this.getElementSettings(); 8070 const widgetSelector = `.elementor-element-${this.getID()}`; 8071 const editHandleSelector = (elementSettings === null || elementSettings === void 0 ? void 0 : elementSettings.edit_handle_selector) + ("[data-elementor-type=\"loop-item\"]" === (elementSettings === null || elementSettings === void 0 ? void 0 : elementSettings.edit_handle_selector) ? `.elementor-${templateId}` : ""); 8072 const editHandleElement = this.$element.find(editHandleSelector).first()[0]; 8073 if (!editHandleElement) return; 8074 if (this.isFirstEdit()) { 8075 this.$element.find(".elementor-swiper-button").remove(); 8076 return; 8077 } 8078 addDocumentHandle({ 8079 element: editHandleElement, 8080 title: (0, _wordpress_i18n.__)("Template", "elementor-pro"), 8081 id: templateId 8082 }, EDIT_CONTEXT, () => this.onInPlaceEditTemplate(), `${widgetSelector} .elementor-${templateId}`); 8083 } 8084 isFirstEdit() { 8085 return this.$element.has(".e-loop-first-edit").length; 8086 } 8087 handleCTA() { 8088 const emptyViewContainer = document.querySelector(`[data-id="${this.getID()}"] .e-loop-empty-view__wrapper`); 8089 if (!emptyViewContainer) return; 8090 const shadowRoot = emptyViewContainer.attachShadow({ mode: "open" }); 8091 shadowRoot.appendChild(elementorPro.modules.loopBuilder.getCtaStyles()); 8092 shadowRoot.appendChild(elementorPro.modules.loopBuilder.getCtaContent(this.getWidgetType())); 8093 shadowRoot.querySelector(".e-loop-empty-view__box-cta").addEventListener("click", () => { 8094 elementorPro.modules.loopBuilder.createTemplate(); 8095 }); 8096 } 8097 /** 8098 * Allows 3rd party add-ons to run code on the Loop Grid handler when the handler is initialized in the Editor. 8099 */ 8100 doEditorInitAction() { 8101 elementor.hooks.doAction("editor/widgets/loop-grid/on-init", this); 8102 } 8103 onElementChange(control) { 8104 if ("_skin" === control) elementorPro.modules.loopBuilder.onApplySkinChange(); 8105 posts_default.prototype.onElementChange.apply(this); 8106 } 8107 bindEvents() { 8108 super.bindEvents(); 8109 elementorFrontend.elements.$window.on("elementor-pro/loop-builder/after-insert-posts", this.reInitMasonry.bind(this)); 8110 } 8111 reInitMasonry() { 8112 const selectors = this.getSettings("selectors"); 8113 this.elements.$posts = jQuery(`.elementor-element-${this.getID()} ${selectors.post}`); 8114 super.runMasonry(); 8115 } 8116 unbindEvents() { 8117 super.unbindEvents(); 8118 elementorFrontend.elements.$window.off("elementor-pro/loop-builder/after-insert-posts", this.reInitMasonry.bind(this)); 8119 } 8120 onInit(...args) { 8121 super.onInit(...args); 8122 if (elementorFrontend.isEditMode()) { 8123 this.doEditorInitAction(); 8124 this.attachEditDocumentHandle(); 8125 this.handleCTA(); 8126 } 8127 } 8128 }; 8129 })); 8130 //#endregion 8131 //#region modules/loop-builder/assets/js/frontend/handlers/loop-carousel.js 8132 var loop_carousel_exports = /* @__PURE__ */ __exportAll({ default: () => LoopCarousel }); 8133 var LoopCarousel; 8134 var init_loop_carousel = __esmMin((() => { 8135 init_run_element_handlers(); 8136 init_asyncToGenerator(); 8137 LoopCarousel = class extends elementorModules.frontend.handlers.CarouselBase { 8138 getDefaultSettings() { 8139 const defaultSettings = super.getDefaultSettings(); 8140 defaultSettings.selectors.carousel = ".elementor-loop-container"; 8141 return defaultSettings; 8142 } 8143 getSwiperSettings() { 8144 const swiperOptions = super.getSwiperSettings(); 8145 const elementSettings = this.getElementSettings(); 8146 const isRtl = elementorFrontend.config.is_rtl; 8147 const widgetSelector = `.elementor-element-${this.getID()}`; 8148 if ("yes" === elementSettings.arrows) swiperOptions.navigation = { 8149 prevEl: isRtl ? `${widgetSelector} .elementor-swiper-button-next` : `${widgetSelector} .elementor-swiper-button-prev`, 8150 nextEl: isRtl ? `${widgetSelector} .elementor-swiper-button-prev` : `${widgetSelector} .elementor-swiper-button-next` 8151 }; 8152 swiperOptions.on.beforeInit = () => { 8153 this.a11ySetSlidesAriaLabels(); 8154 }; 8155 return swiperOptions; 8156 } 8157 onInit(...args) { 8158 var _superprop_getOnInit = () => super.onInit; 8159 var _this = this; 8160 return _asyncToGenerator(function* () { 8161 _superprop_getOnInit().call(_this, ...args); 8162 _this.ranElementHandlers = false;
8163 })(); 8164 } 8165 handleElementHandlers() { 8166 if (this.ranElementHandlers || !this.swiper) return; 8167 runElementHandlers(Array.from(this.swiper.slides).slice(this.swiper.activeIndex - 1, this.swiper.slides.length)); 8168 this.ranElementHandlers = true; 8169 } 8170 a11ySetSlidesAriaLabels() { 8171 const slides = Array.from(this.elements.$slides); 8172 slides.forEach((slide, index) => { 8173 slide.setAttribute("aria-label", `${parseInt(index + 1)} ${(0, _wordpress_i18n.__)("of", "elementor-pro")} ${slides.length}`); 8174 }); 8175 } 8176 }; 8177 })); 8178 //#endregion 8179 //#region assets/dev/js/frontend/utils/ajax-helper.js 8180 var AjaxHelper; 8181 var init_ajax_helper = __esmMin((() => { 8182 AjaxHelper = class { 8183 addLoadingAnimationOverlay(elementId) { 8184 const widget = document.querySelector(`.elementor-element-${elementId}`); 8185 if (!widget) return; 8186 widget.classList.add("e-loading-overlay"); 8187 } 8188 removeLoadingAnimationOverlay(elementId) { 8189 const widget = document.querySelector(`.elementor-element-${elementId}`); 8190 if (!widget) return; 8191 widget.classList.remove("e-loading-overlay"); 8192 } 8193 }; 8194 })); 8195 //#endregion 8196 //#region modules/loop-builder/assets/js/frontend/handlers/ajax-pagination.js 8197 var ajax_pagination_exports = /* @__PURE__ */ __exportAll({ default: () => AjaxPagination }); 8198 var AjaxPagination; 8199 var init_ajax_pagination = __esmMin((() => { 8200 init_ajax_helper(); 8201 init_run_element_handlers(); 8202 AjaxPagination = class extends elementorModules.frontend.handlers.Base { 8203 getDefaultSettings() { 8204 return { selectors: { 8205 links: "a.page-numbers:not(.current)", 8206 widgetContainer: ".elementor-widget-container", 8207 postWrapperTag: ".e-loop-item" 8208 } }; 8209 } 8210 getDefaultElements() { 8211 const selectors = this.getSettings("selectors"); 8212 return { 8213 links: this.$element[0].querySelectorAll(selectors.links), 8214 widgetContainer: this.$element[0].querySelector(selectors.widgetContainer) 8215 }; 8216 } 8217 bindEvents() { 8218 super.bindEvents(); 8219 this.linksEventListeners(); 8220 } 8221 linksEventListeners() { 8222 if (!this.elements.links.length) return; 8223 if ("ajax" !== this.getElementSettings("pagination_load_type")) return; 8224 this.elements.links.forEach((link) => { 8225 link.addEventListener("click", (event) => { 8226 this.handleLinkClick(event); 8227 }); 8228 }); 8229 } 8230 handleLinkClick(event) { 8231 event.preventDefault(); 8232 if (this.isLoading) return; 8233 this.removeLinksListeners(); 8234 this.handleUiBeforeLoading(); 8235 const nextPageUrl = event === null || event === void 0 ? void 0 : event.target.getAttribute("href"); 8236 this.updateURLQueryString(nextPageUrl); 8237 return fetch(nextPageUrl).then((response) => response.text()).then((html) => { 8238 const doc = new DOMParser().parseFromString(html, "text/html"); 8239 this.handleSuccessFetch(doc); 8240 }); 8241 } 8242 removeLinksListeners() { 8243 if (!this.elements.links.length) return; 8244 this.elements.links.forEach((link) => { 8245 link.removeEventListener("click", this.handleLinkClick); 8246 }); 8247 } 8248 updateURLQueryString(nextPageUrl) { 8249 const currentUrl = new URL(window.location.href); 8250 const currentParams = currentUrl.searchParams; 8251 const targetParams = new URL(nextPageUrl).searchParams; 8252 targetParams.forEach((value, key) => { 8253 currentParams.set(key, value); 8254 }); 8255 if (!targetParams.has("e-page-" + this.elementId)) currentParams.delete("e-page-" + this.elementId); 8256 history.pushState(null, "", currentUrl.href); 8257 } 8258 handleUiBeforeLoading() { 8259 this.setLoading(true); 8260 this.ajaxHelper.addLoadingAnimationOverlay(this.elementId); 8261 this.maybeScrollToTop(); 8262 } 8263 setLoading(loadng) { 8264 this.isLoading = loadng; 8265 } 8266 maybeScrollToTop() { 8267 if ("yes" !== this.getElementSettings("auto_scroll")) return; 8268 const widget = document.querySelector(`.elementor-element-${this.elementId}`); 8269 if (!widget) return; 8270 widget.scrollIntoView({ behavior: "smooth" }); 8271 } 8272 handleUiAfterLoading() { 8273 this.setLoading(false); 8274 this.ajaxHelper.removeLoadingAnimationOverlay(this.elementId); 8275 } 8276 handleSuccessFetch(result) { 8277 this.handleUiAfterLoading();
8278 const selectors = this.getSettings("selectors"); 8279 const newWidgetContainer = result.querySelector(`[data-id="${this.elementId}"] ${selectors.widgetContainer}`); 8280 const existingWidgetContainer = this.elements.widgetContainer; 8281 this.$element[0].replaceChild(newWidgetContainer, existingWidgetContainer); 8282 this.afterInsertPosts(); 8283 } 8284 afterInsertPosts() { 8285 const selectors = this.getSettings("selectors"); 8286 const postsElements = document.querySelectorAll(`[data-id="${this.elementId}"] ${selectors.postWrapperTag}`); 8287 elementorFrontend.elementsHandler.runReadyTrigger(this.$element[0]); 8288 runElementHandlers(postsElements); 8289 if (ElementorProFrontendConfig.settings.lazy_load_background_images) document.dispatchEvent(new Event("elementor/lazyload/observe")); 8290 } 8291 onInit() { 8292 super.onInit(); 8293 this.setLoading(false); 8294 this.elementId = this.getID(); 8295 this.ajaxHelper = new AjaxHelper(); 8296 } 8297 }; 8298 })); 8299 //#endregion 8300 //#region modules/loop-builder/assets/js/frontend/frontend.js 8301 var frontend_default$5 = class extends elementorModules.Module { 8302 static { 8303 __name(this, "default"); 8304 } 8305 constructor() { 8306 super(); 8307 [ 8308 "post", 8309 "product", 8310 "post_taxonomy", 8311 "product_taxonomy" 8312 ].forEach((skinName) => { 8313 elementorFrontend.elementsHandler.attachHandler("loop-grid", () => __vitePreload(() => Promise.resolve().then(() => (init_load_more(), load_more_exports)), void 0), skinName); 8314 elementorFrontend.elementsHandler.attachHandler("loop-grid", () => __vitePreload(() => Promise.resolve().then(() => (init_loop(), loop_exports)), void 0), skinName); 8315 elementorFrontend.elementsHandler.attachHandler("loop-carousel", () => __vitePreload(() => Promise.resolve().then(() => (init_loop(), loop_exports)), void 0), skinName); 8316 elementorFrontend.elementsHandler.attachHandler("loop-carousel", () => __vitePreload(() => Promise.resolve().then(() => (init_loop_carousel(), loop_carousel_exports)), void 0), skinName); 8317 elementorFrontend.elementsHandler.attachHandler("loop-grid", () => __vitePreload(() => Promise.resolve().then(() => (init_ajax_pagination(), ajax_pagination_exports)), void 0), skinName); 8318 }); 8319 } 8320 }; 8321 //#endregion 8322 //#region modules/mega-menu/assets/js/frontend/utils.js 8323 function isMenuInDropdownMode(elementSettings) { 8324 if ("dropdown" === elementSettings.item_layout) return true; 8325 const activeBreakpointsList = elementorFrontend.breakpoints.getActiveBreakpointsList({ withDesktop: true }); 8326 const breakpointIndex = activeBreakpointsList.indexOf(elementSettings.breakpoint_selector); 8327 return activeBreakpointsList.indexOf(elementorFrontend.getCurrentDeviceMode()) <= breakpointIndex; 8328 } 8329 var init_utils = __esmMin((() => {})); 8330 //#endregion 8331 //#region assets/dev/js/frontend/utils/flex-horizontal-scroll.js 8332 function changeScrollStatus(element, event) { 8333 if ("mousedown" === event.type) { 8334 element.classList.add("e-scroll"); 8335 element.dataset.pageX = event.pageX; 8336 } else { 8337 element.classList.remove("e-scroll", "e-scroll-active"); 8338 element.dataset.pageX = ""; 8339 } 8340 } 8341 function setHorizontalTitleScrollValues(element, horizontalScrollStatus, event) { 8342 const isActiveScroll = element.classList.contains("e-scroll"); 8343 const isHorizontalScrollActive = "enable" === horizontalScrollStatus; 8344 const headingContentIsWiderThanWrapper = element.scrollWidth > element.clientWidth; 8345 if (!isActiveScroll || !isHorizontalScrollActive || !headingContentIsWiderThanWrapper) return; 8346 event.preventDefault(); 8347 const previousPositionX = parseFloat(element.dataset.pageX); 8348 const mouseMoveX = event.pageX - previousPositionX; 8349 const maximumScrollValue = 5; 8350 const stepLimit = 20; 8351 let toScrollDistanceX = 0; 8352 if (stepLimit < mouseMoveX) toScrollDistanceX = maximumScrollValue; 8353 else if (stepLimit * -1 > mouseMoveX) toScrollDistanceX = -1 * maximumScrollValue; 8354 else toScrollDistanceX = mouseMoveX; 8355 element.scrollLeft = element.scrollLeft - toScrollDistanceX; 8356 element.classList.add("e-scroll-active"); 8357 } 8358 function setHorizontalScrollAlignment({ element, direction, justifyCSSVariable, horizontalScrollStatus }) { 8359 if (!element) return; 8360 if (isHorizontalScroll(element, horizontalScrollStatus)) initialScrollPosition(element, direction, justifyCSSVariable); 8361 else element.style.setProperty(justifyCSSVariable, ""); 8362 } 8363 function isHorizontalScroll(element, horizontalScrollStatus) { 8364 return element.clientWidth < getChildrenWidth(element.children) && "enable" === horizontalScrollStatus; 8365 } 8366 function getChildrenWidth(children) { 8367 let totalWidth = 0; 8368 const parentContainer = children[0].parentNode; 8369 const computedStyles = getComputedStyle(parentContainer); 8370 const gap = parseFloat(computedStyles.gap) || 0; 8371 for (let i = 0; i < children.length; i++) totalWidth += children[i].offsetWidth + gap; 8372 return totalWidth; 8373 } 8374 function initialScrollPosition(element, direction, justifyCSSVariable) { 8375 const isRTL = elementorFrontend.config.is_rtl; 8376 switch (direction) { 8377 case "end": 8378 element.style.setProperty(justifyCSSVariable, "start"); 8379 element.scrollLeft = isRTL ? -1 * getChildrenWidth(element.children) : getChildrenWidth(element.children); 8380 break; 8381 default: 8382 element.style.setProperty(justifyCSSVariable, "start"); 8383 element.scrollLeft = 0; 8384 } 8385 } 8386 var init_flex_horizontal_scroll = __esmMin((() => {})); 8387 //#endregion 8388 //#region modules/mega-menu/assets/js/frontend/handlers/mega-menu.js 8389 var mega_menu_exports = /* @__PURE__ */ __exportAll({ default: () => MegaMenu }); 8390 var MegaMenu; 8391 var init_mega_menu = __esmMin((() => { 8392 init_utils(); 8393 init_anchor_link(); 8394 init_flex_horizontal_scroll(); 8395 MegaMenu = class extends elementorModules.frontend.handlers.Base {
8396 constructor(...args) { 8397 super(...args); 8398 if (elementorFrontend.isEditMode()) this.lifecycleChangeListener = null; 8399 this.resizeListener = null; 8400 this.prevMouseY = null; 8401 this.isKeyboardNavigation = false; 8402 } 8403 getDefaultSettings() { 8404 return { 8405 selectors: { 8406 elementorWidgetWrapper: ".elementor-widget-n-menu", 8407 widgetContainer: ".e-n-menu", 8408 dropdownMenuToggle: ".e-n-menu-toggle", 8409 menuWrapper: ".e-n-menu-wrapper", 8410 headingContainer: ".e-n-menu-heading", 8411 menuItem: ".e-n-menu-item", 8412 tabTitle: ".e-n-menu-title", 8413 tabTitleText: ".e-n-menu-title-text", 8414 directTabTitle: ":scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-title, :scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-title", 8415 tabClickableTitle: ".e-n-menu-title.e-click", 8416 tabDropdown: ".e-n-menu-dropdown-icon", 8417 menuContent: ".e-n-menu-content", 8418 tabContent: ".e-n-menu-content > .e-con, .e-n-menu-heading > .e-con", 8419 directTabContent: ":scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con, :scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, :scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con, :scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con", 8420 tabContentBeforeInterlacing: "> .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con", 8421 newContainerAfterRepeaterAction: "> .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con:nth-child(2), > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-con, > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-content > .e-con:nth-child(2)", 8422 anchorLink: ".e-anchor a" 8423 }, 8424 classes: { 8425 active: "e-active", 8426 anchorItem: "e-anchor", 8427 activeAnchorItem: "e-current" 8428 }, 8429 dataAttributes: { tabIndex: "data-tab-index" }, 8430 ariaAttributes: { 8431 titleStateAttribute: "aria-expanded", 8432 activeTitleSelector: "[aria-expanded=\"true\"]" 8433 }, 8434 autoExpand: false, 8435 autoFocus: false, 8436 showTabFn: "show", 8437 hideTabFn: "hide", 8438 toggleSelf: false, 8439 hidePrevious: true, 8440 postUrl: "post-url", 8441 internalUrl: "internal-url" 8442 }; 8443 } 8444 getDefaultElements() { 8445 const selectors = this.getSettings("selectors"); 8446 return { 8447 $tabContents: this.findElement(selectors.tabContent), 8448 $widgetContainer: this.findElement(selectors.widgetContainer), 8449 $dropdownMenuToggle: this.findElement(selectors.dropdownMenuToggle), 8450 $menuWrapper: this.findElement(selectors.menuWrapper), 8451 $menuContent: this.findElement(selectors.menuContent), 8452 $headingContainer: this.findElement(selectors.headingContainer), 8453 $menuItems: this.findElement(selectors.menuItem), 8454 $tabTitles: this.findElement(selectors.tabTitle), 8455 $tabDropdowns: this.findElement(selectors.tabDropdown), 8456 $anchorLink: this.findElement(selectors.anchorLink), 8457 $tabContentsBeforeInterlacing: this.findElement(selectors.tabContentBeforeInterlacing) 8458 }; 8459 } 8460 getTabTitleFilterSelector(tabIndex) {
8461 return `[${this.getSettings("dataAttributes").tabIndex}="${tabIndex}"]`; 8462 } 8463 getTabIndex(tabTitleElement) { 8464 return tabTitleElement.getAttribute(this.getSettings("dataAttributes").tabIndex); 8465 } 8466 setKeyboardNavigation(event2) { 8467 if ("Tab" === event2.key) this.isKeyboardNavigation = true; 8468 } 8469 dropdownMenuHeightControllerConfig() { 8470 const selectors = this.getSettings("selectors"); 8471 return { 8472 elements: { 8473 $element: this.$element, 8474 $dropdownMenuContainer: this.$element.find(selectors.menuWrapper), 8475 $menuToggle: this.$element.find(selectors.dropdownMenuToggle) 8476 }, 8477 attributes: { menuToggleState: "aria-expanded" }, 8478 settings: { 8479 dropdownMenuContainerMaxHeight: "auto", 8480 menuHeightCssVarName: "--n-menu-dropdown-content-box-height" 8481 } 8482 }; 8483 } 8484 handleContentContainerPosition($contentContainer = null) { 8485 this.resetContentContainersPosition(); 8486 const activeTitleSelector = this.getSettings("ariaAttributes").activeTitleSelector; 8487 const tabIndex = this.elements.$tabDropdowns.filter(activeTitleSelector).attr("data-tab-index"); 8488 $contentContainer = $contentContainer || this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)); 8489 if (!$contentContainer.length) return; 8490 this.setContentContainerAbsolutePosition($contentContainer); 8491 } 8492 setContentContainerAbsolutePosition($contentContainer) { 8493 const elementSettings = this.getElementSettings(); 8494 const isFitToContent = "fit_to_content" === elementSettings.content_width; 8495 if (isMenuInDropdownMode(elementSettings)) return; 8496 if (isFitToContent) { 8497 const direction = elementorFrontend.config.is_rtl ? "right" : "left"; 8498 const menuItemContainerOffset = 0 < this.getMenuItemContainerAbsolutePosition($contentContainer) ? this.getMenuItemContainerAbsolutePosition($contentContainer) : 0; 8499 $contentContainer.css(direction, menuItemContainerOffset); 8500 } 8501 const headingsHeight = this.elements.$headingContainer[0].getBoundingClientRect().height; 8502 if (this.shouldPositionContentAbove($contentContainer, headingsHeight)) { 8503 const contentContainerBoundingBox = $contentContainer[0].getBoundingClientRect(); 8504 $contentContainer.css({ 8505 width: isFitToContent ? "max-content" : "", 8506 "max-width": contentContainerBoundingBox.width 8507 }); 8508 this.elements.$widgetContainer.addClass("content-above"); 8509 } 8510 } 8511 getMenuItemContainerAbsolutePosition($contentContainer) { 8512 const tabIndex = $contentContainer.data("tab-index"); 8513 const titleBoundingBox = this.elements.$tabDropdowns.filter(this.getTabTitleFilterSelector(tabIndex))[0].closest(this.getSettings("selectors").tabTitle).getBoundingClientRect(); 8514 const contentContainerWidth = $contentContainer[0].clientWidth; 8515 let menuItemContainerOffset = null; 8516 switch (this.getElementSettings("content_horizontal_position")) { 8517 case "left": 8518 menuItemContainerOffset = this.getLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox); 8519 break; 8520 case "right": 8521 menuItemContainerOffset = this.getRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox); 8522 break; 8523 default: menuItemContainerOffset = this.getCenteredContainerOffset(contentContainerWidth, titleBoundingBox); 8524 } 8525 return menuItemContainerOffset; 8526 } 8527 getCenteredContainerOffset(contentContainerWidth, titleBoundingBox) { 8528 const menuItemContentContainerHalfWidth = contentContainerWidth / 2; 8529 const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; 8530 let titleMiddleOffset = this.adjustForScrollbarIfNeeded(titleBoundingBox.left + titleBoundingBox.width / 2); 8531 if (elementorFrontend.config.is_rtl) titleMiddleOffset = bodyWidth - titleMiddleOffset; 8532 let offset = titleMiddleOffset - menuItemContentContainerHalfWidth; 8533 if (titleMiddleOffset + menuItemContentContainerHalfWidth > bodyWidth) offset = bodyWidth - contentContainerWidth; 8534 else if (menuItemContentContainerHalfWidth > titleMiddleOffset) offset = 0; 8535 return offset; 8536 } 8537 getLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { 8538 return elementorFrontend.config.is_rtl ? this.getRtlLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) : this.getLtrLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox); 8539 } 8540 getRtlLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { 8541 const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; 8542 let offset = bodyWidth - this.adjustForScrollbarIfNeeded(titleBoundingBox.left) - contentContainerWidth; 8543 if (-offset + contentContainerWidth > bodyWidth) offset = 0; 8544 return offset; 8545 } 8546 getLtrLeftDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { 8547 let offset = this.adjustForScrollbarIfNeeded(titleBoundingBox.left); 8548 offset = this.adjustStartOffsetToViewport(offset, contentContainerWidth); 8549 return offset; 8550 } 8551 getRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { 8552 return elementorFrontend.config.is_rtl ? this.getRtlRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) : this.getLtrRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox); 8553 } 8554 getRtlRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { 8555 let offset = elementorFrontend.elements.$body[0].clientWidth - this.adjustForScrollbarIfNeeded(titleBoundingBox.right); 8556 offset = this.adjustStartOffsetToViewport(offset, contentContainerWidth); 8557 return offset; 8558 } 8559 /** 8560 * If the content container doesn't fit in the viewport, align its right edge with the viewport'
8560s right edge. 8561 * 8562 * @param {number} offset 8563 * @param {number} contentContainerWidth 8564 */ 8565 adjustStartOffsetToViewport(offset, contentContainerWidth) { 8566 const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; 8567 if (offset + contentContainerWidth > bodyWidth) offset = bodyWidth - contentContainerWidth; 8568 return offset; 8569 } 8570 getLtrRightDirectionContainerOffset(contentContainerWidth, titleBoundingBox) { 8571 return contentContainerWidth > titleBoundingBox.right ? 0 : titleBoundingBox.right - contentContainerWidth; 8572 } 8573 adjustForScrollbarIfNeeded(offset) { 8574 if (elementorFrontend.config.is_rtl && elementorFrontend.isEditMode()) { 8575 const scrollbarWidth = window.innerWidth - elementorFrontend.elements.$body[0].clientWidth; 8576 offset -= scrollbarWidth; 8577 } 8578 return offset; 8579 } 8580 getMenuContainerOffset() { 8581 const menuContainerBoundingBox = this.elements.$widgetContainer[0].getBoundingClientRect(); 8582 return elementorFrontend.config.is_rtl ? this.getMenuContainerOffsetRtl(menuContainerBoundingBox) : menuContainerBoundingBox.left; 8583 } 8584 getMenuContainerOffsetRtl(menuContainerBoundingBox) { 8585 const bodyWidth = elementorFrontend.elements.$body[0].clientWidth; 8586 let menuContainerOffset = bodyWidth - menuContainerBoundingBox.right; 8587 if (elementorFrontend.isEditMode()) { 8588 const scrollbarWidth = window.innerWidth - bodyWidth; 8589 menuContainerOffset += scrollbarWidth; 8590 } 8591 return menuContainerOffset; 8592 } 8593 resetContentContainersPosition() { 8594 this.elements.$tabContents.css({ 8595 left: "", 8596 right: "", 8597 bottom: "", 8598 position: "var(--position)", 8599 "max-width": "", 8600 width: "var(--width)" 8601 }); 8602 this.elements.$widgetContainer.removeClass("content-above"); 8603 } 8604 getTabContentFilterSelector(tabIndex) { 8605 return `[data-tab-index="${tabIndex}"]`; 8606 } 8607 isActiveTab(tabIndex) { 8608 return "true" === this.elements.$tabDropdowns.filter("[data-tab-index=\"" + tabIndex + "\"]").attr(this.getSettings("ariaAttributes").titleStateAttribute); 8609 } 8610 activateDefaultTab() { 8611 const settings = this.getSettings(); 8612 const defaultActiveTab = this.getEditSettings("activeItemIndex") || 1; 8613 const originalToggleMethods = { 8614 showTabFn: settings.showTabFn, 8615 hideTabFn: settings.hideTabFn 8616 }; 8617 this.setSettings({ 8618 showTabFn: "show", 8619 hideTabFn: "hide" 8620 }); 8621 this.changeActiveTab(defaultActiveTab); 8622 this.setSettings(originalToggleMethods); 8623 this.elements.$widgetContainer.addClass("e-activated"); 8624 } 8625 activateTab(tabIndex) { 8626 const settings = this.getSettings(); 8627 const activeClass = settings.classes.active; 8628 const childMenuDropdownSelector = `.elementor-element-${this.getID()} .e-n-menu .e-n-menu .e-n-menu-dropdown-icon`; 8629 const childMenuContentSelector = `.elementor-element-${this.getID()} .e-n-menu .e-n-menu .e-n-menu-content > .e-con`; 8630 const $requestedTitle = this.elements.$tabDropdowns.filter(this.getTabTitleFilterSelector(tabIndex)).not(childMenuDropdownSelector); 8631 const animationDuration = "show" === settings.showTabFn ? 0 : 400; 8632 const $requestedContent = this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)).not(childMenuContentSelector); 8633 this.addAnimationToContentIfNeeded(tabIndex); 8634 $requestedContent[settings.showTabFn](animationDuration, () => this.onShowTabContent($requestedContent)); 8635 $requestedTitle.attr(this.getTitleActivationAttributes()); 8636 $requestedTitle.prev(".e-n-menu-title-container").find("a").attr(this.getTitleActivationAttributes("link")); 8637 $requestedContent.addClass(activeClass).parent().addClass(activeClass); 8638 $requestedContent.css({ display: "var(--display)" }); 8639 $requestedContent.removeAttr("display"); 8640 if (elementorFrontend.isEditMode() && !!$requestedContent.length) this.activeContainerWidthListener($requestedContent); 8641 this.menuHeightController.reassignMenuHeight($requestedContent); 8642 } 8643 deactivateActiveTab() { 8644 var _a; 8645 const settings = this.getSettings(); 8646 const activeClass = settings.classes.active; 8647 const activeTitleFilter = settings.ariaAttributes.activeTitleSelector; 8648 const activeContentFilter = "." + activeClass; 8649 const $activeTitle = this.elements.$tabDropdowns.filter(activeTitleFilter); 8650 const $activeContent = this.elements.$tabContents.filter(activeContentFilter); 8651 this.setTabDeactivationAttributes($activeTitle); 8652 this.elements.$menuContent.removeClass(activeClass); 8653 $activeContent.removeClass(activeClass); 8654 $activeContent[settings.hideTabFn](0, () => this.onHideTabContent($activeContent)); 8655 this.removeAnimationFromContentIfNeeded(); 8656 if (elementorFrontend.isEditMode() && !!$activeContent.length) (_a = this.observedContainer) == null || _a.unobserve($activeContent[0]);
8657 this.menuHeightController.resetMenuHeight($activeContent); 8658 this.clickInProgress = true; 8659 } 8660 getTitleActivationAttributes(elementType = "tab") { 8661 const titleAttributes = {}; 8662 if ("tab" === elementType) titleAttributes["aria-expanded"] = "true"; 8663 return titleAttributes; 8664 } 8665 setTabDeactivationAttributes($activeTitle) { 8666 const titleStateAttribute = this.getSettings("ariaAttributes").titleStateAttribute; 8667 $activeTitle.attr(`${titleStateAttribute}`, "false"); 8668 } 8669 shouldPositionContentAbove($contentContainer, offset = 0) { 8670 const contentDimensions = $contentContainer[0].getBoundingClientRect(); 8671 return this.isContentShorterThanItsTopOffset(contentDimensions, offset) && this.isContentTallerThanItsBottomOffset(contentDimensions); 8672 } 8673 isContentShorterThanItsTopOffset(contentDimensions, offset) { 8674 return contentDimensions.height < contentDimensions.top - offset; 8675 } 8676 isContentTallerThanItsBottomOffset(contentDimensions) { 8677 return window.innerHeight - contentDimensions.top < contentDimensions.height; 8678 } 8679 onShowTabContent($requestedContent) { 8680 this.handleContentContainerPosition($requestedContent); 8681 elementorFrontend.elements.$window.trigger("elementor-pro/motion-fx/recalc"); 8682 elementorFrontend.elements.$window.trigger("elementor/nested-tabs/activate", $requestedContent); 8683 elementorFrontend.elements.$window.trigger("elementor/bg-video/recalc"); 8684 } 8685 onHideTabContent() { 8686 if (this.elements.$widgetContainer.hasClass("content-above")) this.resetContentContainersPosition(); 8687 } 8688 changeActiveTab(tabIndex, fromUser = true, byKeyboard = false) { 8689 if (this.clickInProgress && elementorFrontend.isEditMode() && !byKeyboard) return; 8690 const isActiveTab = this.isActiveTab(tabIndex); 8691 this.deactivateActiveTab(); 8692 if (!isActiveTab || isActiveTab && !fromUser) { 8693 this.clickInProgress = true; 8694 this.activateTab(tabIndex); 8695 } 8696 setTimeout(() => { 8697 this.clickInProgress = false; 8698 }); 8699 } 8700 changeActiveTabByKeyboard(event2, settings) { 8701 if (settings.widgetId.toString() !== this.getID().toString()) return; 8702 if (!settings.titleIndex) { 8703 this.changeActiveTab("", true, true); 8704 return; 8705 } 8706 const $focusableElement = this.$element.find(`[data-focus-index="${settings.titleIndex}"]`); 8707 const isLinkElement = "a" === $focusableElement[0].tagName.toLowerCase(); 8708 const dropdownSelector = this.getSettings("selectors.tabDropdown"); 8709 const $tabDropdown = isLinkElement ? $focusableElement.next(dropdownSelector) : $focusableElement; 8710 const tabIndex = this.getTabIndex($tabDropdown[0]); 8711 this.changeActiveTab(tabIndex, true, true); 8712 event2.stopPropagation(); 8713 } 8714 onTabClick(event2) { 8715 var _a; 8716 var _b; 8717 var _c; 8718 var _d; 8719 if (elementorFrontend.isEditMode()) event2.preventDefault(); 8720 const hasNoDropdown = (_b = (_a = event2 == null ? void 0 : event2.currentTarget) == null ? void 0 : _a.classList) == null ? void 0 : _b.contains("link-only"); 8721 const blockMouseClickEvents = !this.isNeedToOpenOnClick() && !this.isKeyboardNavigation; 8722 if (hasNoDropdown || blockMouseClickEvents) return; 8723 const selectors = this.getSettings("selectors"); 8724 if (((_d = (_c = event2 == null ? void 0 : event2.target) == null ? void 0 : _c.closest(selectors.elementorWidgetWrapper)) == null ? void 0 : _d.getAttribute("data-id")) !== this.getID().toString()) return; 8725 const clickedElement = event2 == null ? void 0 : event2.currentTarget; 8726 const dropdownElement = clickedElement == null ? void 0 : clickedElement.querySelector(selectors.tabDropdown); 8727 const tabIndex = this.getTabIndex(dropdownElement); 8728 this.changeActiveTab(tabIndex, true); 8729 } 8730 bindEvents() { 8731 this.elements.$tabTitles.on(this.getTabEvents()); 8732 this.elements.$dropdownMenuToggle.on("click", this.onClickToggleDropdownMenu.bind(this)); 8733 this.elements.$tabContents.on(this.getContentEvents()); 8734 this.elements.$menuContent.on(this.getContentEvents()); 8735 this.elements.$headingContainer.on(this.getHeadingEvents()); 8736 elementorFrontend.addListenerOnce(this.getModelCID(), "scroll", elementorFrontend.debounce(this.menuHeight
8736Controller.reassignMobileMenuHeight.bind(this.menuHeightController), 250)); 8737 elementorFrontend.elements.$window.on("elementor/nested-tabs/activate", this.reInitSwipers); 8738 elementorFrontend.elements.$window.on("elementor/nested-elements/activate-by-keyboard", this.changeActiveTabByKeyboard.bind(this)); 8739 elementorFrontend.elements.$window.on("elementor/mega-menu/dropdown-toggle-by-keyboard", this.onClickToggleDropdownMenuByKeyboard.bind(this)); 8740 elementorFrontend.elements.$window.on("resize", this.resizeEventHandler.bind(this)); 8741 if (elementorFrontend.isEditMode()) { 8742 this.addChildLifeCycleEventListeners(); 8743 elementorFrontend.elements.$window.on("elementor/dynamic/url_change", this.changeMegaMenuTitleContainerTag.bind(this)); 8744 } 8745 elementorFrontend.elements.$window.on("elementor/nested-container/atomic-repeater", this.linkContainer.bind(this)); 8746 } 8747 unbindEvents() { 8748 this.elements.$tabTitles.off(); 8749 this.elements.$menuContent.off(); 8750 this.elements.$tabContents.off(); 8751 this.elements.$headingContainer.off(); 8752 elementorFrontend.elements.$window.off("resize"); 8753 if (elementorFrontend.isEditMode()) { 8754 this.removeChildLifeCycleEventListeners(); 8755 elementorFrontend.elements.$window.on("elementor/dynamic/url_change", this.changeMegaMenuTitleContainerTag.bind(this)); 8756 } 8757 elementorFrontend.elements.$window.off("elementor/nested-tabs/activate", this.reInitSwipers); 8758 elementorFrontend.elements.$window.off("elementor/nested-elements/activate-by-keyboard", this.changeActiveTabByKeyboard.bind(this)); 8759 elementorFrontend.elements.$window.off("elementor/mega-menu/dropdown-toggle-by-keyboard", this.onClickToggleDropdownMenuByKeyboard.bind(this)); 8760 elementorFrontend.elements.$window.off("resize", this.resizeEventHandler.bind(this)); 8761 elementorFrontend.elements.$window.off("elementor/nested-container/atomic-repeater", this.linkContainer.bind(this)); 8762 } 8763 /** 8764 * Fixes issues where Swipers that have been initialized while a tab is not visible are not properly rendered 8765 * and when switching to the tab the swiper will not respect any of the chosen `autoplay` related settings. 8766 * 8767 * This is triggered when switching to a nested tab, looks for Swipers in the tab content and reinitializes them. 8768 * 8769 * @param {Object} event - Incoming event. 8770 * @param {Object} content - Active nested tab dom element. 8771 */ 8772 reInitSwipers(event2, content) { 8773 const swiperElements = content.querySelectorAll(".swiper"); 8774 for (const element of swiperElements) { 8775 if (!element.swiper) return; 8776 element.swiper.initialized = false; 8777 element.swiper.init(); 8778 } 8779 } 8780 resizeEventHandler() { 8781 this.resizeListener = this.handleContentContainerPosition(); 8782 this.setLayoutType(); 8783 this.setTouchMode(); 8784 this.menuHeightController.reassignMobileMenuHeight(); 8785 this.setScrollPosition(); 8786 const activeTitleSelector = this.getSettings("ariaAttributes").activeTitleSelector; 8787 const tabIndex = this.elements.$tabDropdowns.filter(activeTitleSelector).attr("data-tab-index"); 8788 const childMenuContentSelector = `.elementor-element-${this.getID()} .e-n-menu .e-n-menu .e-n-menu-content > .e-con`; 8789 const $requestedContent = this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)).not(childMenuContentSelector); 8790 this.menuHeightController.resetMenuHeight($requestedContent); 8791 this.menuHeightController.reassignMenuHeight($requestedContent); 8792 } 8793 /** 8794 * Add Child Lifecycle Event Listeners 8795 * 8796 * This method adds event listeners for the elementor/editor/element-rendered and elementor/editor/element-destroyed 8797 * events. These events are fired when an element is rendered or destroyed in the editor. The callback functions 8798 * check if the rendered/destroyed element is nested in this mega-menu instance, and if it is, triggers the 8799 * recalculation of the mega-menu's content containers position. 8800 */ 8801 addChildLifeCycleEventListeners() { 8802 this.lifecycleChangeListener = this.handleContentContainerChildrenChanges.bind(this); 8803 window.addEventListener("elementor/editor/element-rendered", this.lifecycleChangeListener); 8804 window.addEventListener("elementor/editor/element-destroyed", this.lifecycleChangeListener); 8805 } 8806 removeChildLifeCycleEventListeners() { 8807 window.removeEventListener("elementor/editor/element-rendered", this.lifecycleChangeListener); 8808 window.removeEventListener("elementor/editor/element-destroyed", this.lifecycleChangeListener); 8809 } 8810 handleContentContainerChildrenChanges(event2) { 8811 if (!this.isNestedElementRenderedInContentContainer(event2.detail.elementView)) return; 8812 this.handleContentContainerPosition(); 8813 } 8814 isNestedElementRenderedInContentContainer(elementView) { 8815 const elementContainer = elementView == null ? void 0 : elementView.getContainer(); 8816 if (!elementContainer) return false;
8817 return elementContainer.getParentAncestry().some((parent) => this.getID().toString() === parent.model.get("id").toString()); 8818 } 8819 getTabEvents() { 8820 const tabEvents = { click: this.onTabClick.bind(this) }; 8821 return this.isNeedToOpenOnClick() ? tabEvents : this.replaceClickWithHover(tabEvents); 8822 } 8823 getContentEvents() { 8824 return this.isNeedToOpenOnClick() ? {} : { 8825 mouseleave: this.onMouseLeave.bind(this), 8826 mousemove: this.trackMousePosition.bind(this) 8827 }; 8828 } 8829 isNeedToOpenOnClick() { 8830 const elementSettings = this.getElementSettings(); 8831 return this.isEdit || this.isMobileDevice() || "hover" !== elementSettings.open_on || "dropdown" === elementSettings.item_layout; 8832 } 8833 isMobileDevice() { 8834 return [ 8835 "mobile", 8836 "mobile_extra", 8837 "tablet", 8838 "tablet_extra" 8839 ].includes(elementorFrontend.getCurrentDeviceMode()); 8840 } 8841 replaceClickWithHover(tabEvents) { 8842 tabEvents.mouseenter = this.onMouseTitleEnter.bind(this); 8843 tabEvents.mouseleave = this.onMouseLeave.bind(this); 8844 tabEvents.keyup = this.setKeyboardNavigation.bind(this); 8845 return tabEvents; 8846 } 8847 onMouseTitleEnter(event2) { 8848 var _a; 8849 event2.preventDefault(); 8850 const settings = this.getSettings(); 8851 const currentTarget = event2 == null ? void 0 : event2.currentTarget; 8852 const currentTargetWidgetId = (_a = currentTarget == null ? void 0 : currentTarget.closest(settings.selectors.elementorWidgetWrapper)) == null ? void 0 : _a.getAttribute("data-id"); 8853 if (this.$element[0].getAttribute("data-id") !== currentTargetWidgetId) return; 8854 const titleStateAttribute = settings.ariaAttributes.titleStateAttribute; 8855 const dropdownSelector = settings.selectors.tabDropdown; 8856 const activeDropdownElement = currentTarget == null ? void 0 : currentTarget.querySelector(dropdownSelector); 8857 if ("true" === (activeDropdownElement == null ? void 0 : activeDropdownElement.getAttribute(titleStateAttribute))) return; 8858 const tabIndex = activeDropdownElement == null ? void 0 : activeDropdownElement.getAttribute("data-tab-index"); 8859 this.changeActiveTab(tabIndex, true); 8860 } 8861 onClickToggleDropdownMenu(show) { 8862 this.elements.$widgetContainer.attr("data-layout", "dropdown"); 8863 const titleStateAttribute = this.getSettings("ariaAttributes").titleStateAttribute; 8864 const isDropdownVisible = "true" === this.elements.$dropdownMenuToggle.attr(titleStateAttribute); 8865 if ("boolean" !== typeof show) show = !isDropdownVisible; 8866 const activeTabTitleValue = show ? "true" : "false"; 8867 this.elements.$dropdownMenuToggle.attr(titleStateAttribute, activeTabTitleValue); 8868 elementorFrontend.utils.events.dispatch(window, "elementor-pro/mega-menu/dropdown-open"); 8869 this.menuHeightController.reassignMobileMenuHeight(); 8870 } 8871 onClickOutsideDropdownMenu(event2) { 8872 var _a; 8873 var _b; 8874 var _c; 8875 if (!this.isNeedToOpenOnClick()) return; 8876 const settings = this.getSettings(); 8877 const selectors = settings.selectors; 8878 const widgetWrapper = `.elementor-element-${this.getID()}`; 8879 const activeContentFilter = `> .e-con.${settings.classes.active}`; 8880 const isMenuDropdownsClosed = 0 === this.elements.$menuContent.find(activeContentFilter).length; 8881 const isElementRemovedFromDOM = elementorFrontend.isEditMode() && !document.body.contains(event2 == null ? void 0 : event2.target); 8882 const isClickedInsideCurrentMenu = !!((_a = event2 == null ? void 0 : event2.target) == null ? void 0 : _a.closest(`${widgetWrapper} ${selectors.widgetContainer}`)); 8883 if ((_c = (_b = event2 == null ? void 0 : event2.target) == null ? void 0 : _b.classList) == null ? void 0 : _c.contains(selectors.menuContent.replace(".", ""))) { 8884 this.deactivateActiveTab(); 8885 return; 8886 } 8887 if (isMenuDropdownsClosed || isClickedInsideCurrentMenu || isElementRemovedFromDOM) return; 8888 this.deactivateActiveTab(); 8889 } 8890 onClickToggleDropdownMenuByKeyboard(event2, settings) { 8891 if (settings.widgetId.toString() !== this.getID().toString()) return; 8892 this.onClickToggleDropdownMenu(settings.show); 8893 } 8894 addAnimationToContentIfNeeded(tabIndex) { 8895 const openAnimation = this.getElementSettings("open_animation"); 8896 if ("none" === openAnimation || "" === openAnimation) return; 8897 this.elements.$tabContents.filter(this.getTabContentFilterSelector(tabIndex)).addClass(`animated ${openAnimation}`); 8898 } 8899 removeAnimationFromContentIfNeeded() { 8900 const openAnimation = this.getElementSettings("open_animation"); 8901 if ("none" === openAnimation || "" === openAnimation) return; 8902 this.elements.$tabContents.removeClass(`animated ${openAnimation}`); 8903 } 8904 /**
8905 * Store the current Y-coordinate of the mouse cursor. 8906 * 8907 * @param {Event} event - The mouse event object. 8908 */ 8909 trackMousePosition(event2) { 8910 this.prevMouseY = event2 == null ? void 0 : event2.clientY; 8911 } 8912 /** 8913 * Check if the menu content is currently hovered. 8914 * 8915 * @return {boolean} - True if menu content is hovered, otherwise false. 8916 */ 8917 isMenuContentHovered() { 8918 const settings = this.getSettings(); 8919 return this.$element.find(`${settings.selectors.menuContent}:hover`).length > 0; 8920 } 8921 isCursorInBetweenMenuTitleAndContent(event2) { 8922 var _a; 8923 var _b; 8924 var _c; 8925 const settings = this.getSettings(); 8926 const selectors = settings.selectors; 8927 const currentElement = event2 == null ? void 0 : event2.currentTarget; 8928 const activeContent = (_a = currentElement == null ? void 0 : currentElement.closest(selectors.menuItem)) == null ? void 0 : _a.querySelector(selectors.menuContent); 8929 const isMouseLeavingTabTitle = (_b = currentElement.classList) == null ? void 0 : _b.contains(selectors.tabTitle.replace(".", "")); 8930 const hasActiveTabTitle = (_c = activeContent == null ? void 0 : activeContent.classList) == null ? void 0 : _c.contains(settings.classes.active); 8931 if (!isMouseLeavingTabTitle || !hasActiveTabTitle) return false; 8932 const titleBoundingClientRect = currentElement.getBoundingClientRect(); 8933 const contentBoundingClientRect = activeContent.getBoundingClientRect(); 8934 const mouseY = event2.clientY; 8935 return titleBoundingClientRect.bottom <= contentBoundingClientRect.top ? mouseY >= titleBoundingClientRect.bottom && mouseY < contentBoundingClientRect.top : mouseY <= titleBoundingClientRect.top && mouseY > contentBoundingClientRect.bottom; 8936 } 8937 /** 8938 * Determines whether the cursor moved sideways or downwards. 8939 * 8940 * @param {Event} event - The mouse event object. 8941 * @return {boolean} - True if the cursor moved sideways or downwards, otherwise false. 8942 */ 8943 didCursorMoveSidewaysOrDown(event2) { 8944 return this.prevMouseY !== null && (event2 == null ? void 0 : event2.clientY) >= this.prevMouseY; 8945 } 8946 /** 8947 * Check whether the dropdown menu should remain open based on hover and cursor movement. 8948 * 8949 * @param {boolean} isMouseLeavingTabContent - True if the mouse is leaving the tab content. 8950 * @param {Event} event - The mouse event object. 8951 * @return {boolean} - True if dropdown should be considered as hovered, otherwise false. 8952 */ 8953 isHoveredDropdownMenu(isMouseLeavingTabContent, event2) { 8954 if (isMouseLeavingTabContent && this.didCursorMoveSidewaysOrDown(event2)) return false; 8955 return this.isMenuContentHovered(); 8956 } 8957 /** 8958 * Handle the event when the mouse leaves the dropdown. 8959 * 8960 * @param {Event} event - The mouse event object. 8961 */ 8962 onMouseLeave(event2) { 8963 var _a; 8964 var _b; 8965 event2.preventDefault(); 8966 const isMouseLeavingTabContent = (_b = (_a = event2 == null ? void 0 : event2.currentTarget) == null ? void 0 : _a.classList) == null ? void 0 : _b.contains("e-con"); 8967 if (!this.isHoveredDropdownMenu(isMouseLeavingTabContent, event2) && !this.isCursorInBetweenMenuTitleAndContent(event2)) this.deactivateActiveTab(); 8968 } 8969 onInit(...args) { 8970 this.menuHeightController = new elementorProFrontend.utils.DropdownMenuHeightController(this.dropdownMenuHeightControllerConfig()); 8971 super.onInit(...args); 8972 if (this.getSettings("autoExpand")) this.activateDefaultTab(); 8973 setHorizontalScrollAlignment(this.getHorizontalScrollingSettings()); 8974 this.setTouchMode(); 8975 if (!elementorFrontend.isEditMode()) { 8976 const classes = this.getSettings("classes"); 8977 this.anchorLinks = new AnchorLinks(this.elements.$anchorLink, classes); 8978 this.anchorLinks.initialize(); 8979 elementorFrontend.elements.$window.on("elementor/dynamic/url_change", this.changeMegaMenuTitleContainerTag.bind(this)); 8980 } 8981 this.menuToggleVisibilityListener(this.elements.$dropdownMenuToggle); 8982 this.setScrollPosition(); 8983 this.onClickOutsideDropdownMenu = this.onClickOutsideDropdownMenu.bind(this); 8984 document.addEventListener("click", this.onClickOutsideDropdownMenu); 8985 this.clickInProgress = false;
8986 } 8987 onDestroy() { 8988 document.removeEventListener("click", this.onClickOutsideDropdownMenu); 8989 elementorFrontend.elements.$window.off("elementor/dynamic/url_change"); 8990 } 8991 setScrollPosition() { 8992 setHorizontalScrollAlignment({ 8993 element: this.elements.$headingContainer[0], 8994 direction: this.getItemPosition(), 8995 justifyCSSVariable: "--n-menu-heading-justify-content", 8996 horizontalScrollStatus: this.getHorizontalScrollSetting() 8997 }); 8998 } 8999 getPropsThatTriggerContentPositionCalculations() { 9000 return [ 9001 "content_horizontal_position", 9002 "content_position", 9003 "item_position_horizontal", 9004 "content_width", 9005 "item_layout" 9006 ]; 9007 } 9008 activeContainerWidthListener($activeContainer) { 9009 let previousWidth = 0; 9010 this.observedContainer = new ResizeObserver((activeContainer) => { 9011 var _a; 9012 const currentWidth = (_a = activeContainer[0].borderBoxSize) == null ? void 0 : _a[0].inlineSize; 9013 if (!!currentWidth && currentWidth !== previousWidth) { 9014 previousWidth = currentWidth; 9015 if (0 !== previousWidth) this.handleContentContainerPosition(); 9016 } 9017 }); 9018 this.observedContainer.observe($activeContainer[0]); 9019 } 9020 menuToggleVisibilityListener($menuToggle) { 9021 let previousWidth; 9022 this.observedContainer = new ResizeObserver((menuToggle) => { 9023 var _a; 9024 const currentWidth = (_a = menuToggle[0].borderBoxSize) == null ? void 0 : _a[0].inlineSize; 9025 if (currentWidth !== previousWidth) { 9026 previousWidth = currentWidth; 9027 this.setLayoutType(); 9028 } 9029 }); 9030 this.observedContainer.observe($menuToggle[0]); 9031 } 9032 onElementChange(propertyName) { 9033 if (this.getPropsThatTriggerContentPositionCalculations().includes(propertyName)) this.handleContentContainerPosition(); 9034 this.setLayoutType(); 9035 } 9036 onEditSettingsChange(propertyName, value) { 9037 if (this.getSettings().autoFocus && "activeItemIndex" === propertyName) this.changeActiveTab(value, false); 9038 this.setLayoutType(); 9039 } 9040 /** 9041 * Sets the layout type as a data attribute, so that it can be use for the responsive or dropdown menu styling. 9042 * 9043 * Originally this styling was handled by the distinction between the heading and the content styling elements. 9044 * Since we removed the title duplication, we needed another way to distinguish between the horizontal and the dropdown styling. 9045 */ 9046 setLayoutType() { 9047 const layoutType = "none" === this.elements.$dropdownMenuToggle.css("display") ? "horizontal" : "dropdown"; 9048 this.elements.$widgetContainer.attr("data-layout", layoutType); 9049 } 9050 getHeadingEvents() { 9051 const navigationWrapper = this.elements.$headingContainer[0]; 9052 return { 9053 mousedown: this.changeScrollStatusAndDispatch.bind(this, navigationWrapper), 9054 mouseup: this.changeScrollStatusAndDispatch.bind(this, navigationWrapper), 9055 mouseleave: this.changeScrollStatusAndDispatch.bind(this, navigationWrapper), 9056 mousemove: this.setHorizontalTitleScrollValuesAndDispatch.bind(this, navigationWrapper) 9057 }; 9058 } 9059 getHorizontalScrollSetting() { 9060 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 9061 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), "horizontal_scroll", "", currentDevice); 9062 } 9063 getItemPosition() { 9064 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 9065 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), "item_position_horizontal", "", currentDevice); 9066 } 9067 changeScrollStatusAndDispatch(navigationWrapper, event2) { 9068 changeScrollStatus(navigationWrapper, event2); 9069 elementorFrontend.elements.$window.trigger("elementor-pro/mega-menu/heading-mouse-event"); 9070 } 9071 setHorizontalTitleScrollValuesAndDispatch(navigationWrapper, event2) { 9072 setHorizontalTitleScrollValues(navigationWrapper, this.getHorizontalScrollSetting(), event2); 9073 elementorFrontend.elements.$window.trigger("elementor-pro/mega-menu/heading-mouse-event"); 9074 } 9075 linkContainer(event2) { 9076 const { container } = event2.detail, id = container.model.get("id"), currentId = String(this.$element.data("id")), view = container.view.$el; 9077 if (id === currentId) { 9078 this.updateIndexValues(view); 9079 this.updateListeners(view); 9080 } 9081 } 9082 updateIndexValues(view) { 9083 const { selectors: { directTabTitle, directTabContent } } = this.getDefaultSettings(), currentMenu = view[0], tabsContents = currentMenu.querySelectorAll(directTabContent), tabTitles = currentMenu.querySelectorAll(directTabTitle), settings = this.get
9083Settings(), itemIdBase = tabTitles[0].getAttribute("id").slice(0, -1); 9084 tabTitles.forEach((element, index) => { 9085 var _a; 9086 var _b; 9087 var _c; 9088 var _d; 9089 var _e; 9090 var _f; 9091 var _g; 9092 const newIndex = index + 1; 9093 const updatedTabID = itemIdBase + newIndex; 9094 const updatedContainerID = updatedTabID.replace("e-n-menu-title-", "e-n-menu-content-"); 9095 const updatedTabDropdownID = updatedTabID.replace("e-n-menu-title-", "e-n-menu-dropdown-icon-"); 9096 element.setAttribute("id", updatedTabID); 9097 (_a = element.querySelector(settings.selectors.tabDropdown)) == null || _a.setAttribute("data-tab-index", newIndex); 9098 (_b = element.querySelector(settings.selectors.tabDropdown)) == null || _b.setAttribute("id", updatedTabDropdownID); 9099 (_c = element.querySelector(settings.selectors.tabDropdown)) == null || _c.setAttribute("aria-controls", updatedContainerID); 9100 (_d = element.querySelector(settings.selectors.tabTitleText)) == null || _d.setAttribute("data-binding-index", newIndex); 9101 (_e = tabsContents[index]) == null || _e.setAttribute("aria-labelledby", updatedTabDropdownID); 9102 (_f = tabsContents[index]) == null || _f.setAttribute("data-tab-index", newIndex); 9103 (_g = tabsContents[index]) == null || _g.setAttribute("id", updatedContainerID); 9104 }); 9105 } 9106 updateListeners(view) { 9107 const { selectors: { tabClickableTitle, tabDropdown, tabContent, tabTitle } } = this.getSettings(), $tabTitles = view.find(tabTitle), $tabClickableTitle = view.find(tabClickableTitle); 9108 this.elements.$tabTitles = view.find(tabClickableTitle); 9109 this.elements.$tabDropdowns = view.find(tabDropdown); 9110 this.elements.$tabContents = view.find(tabContent); 9111 $tabTitles.off(); 9112 $tabClickableTitle.on(this.getTabEvents()); 9113 this.clickInProgress = false; 9114 } 9115 /** 9116 * Toggle the container tag of the mega menu title. 9117 * Needs to be places in pro Mega Menu frontend handler 9118 * 9119 * @param {Event} event 9120 * @return {undefined} 9121 */ 9122 changeMegaMenuTitleContainerTag(event2) { 9123 var _a; 9124 const { element, actionName, value } = event2.detail, elementParent = element.parentNode, closestMenuItemTitle = elementParent.parentNode, newElement = this.maybeCreateNewElement(elementParent, value), elementToUpdate = this.maybeReplaceMenuItemTitleContent(elementParent, newElement, closestMenuItemTitle), currentUrl = ((_a = element.dataset) == null ? void 0 : _a.currentUrl) || null; 9125 this.maybeUpdateNewElementsHref(value, elementToUpdate); 9126 this.eCurrentClassHandler(actionName, closestMenuItemTitle, currentUrl === value); 9127 } 9128 maybeReplaceMenuItemTitleContent(elementParent, newElement, closestMenuItemTitle) { 9129 if (!newElement) return elementParent; 9130 Array.from(elementParent.attributes).forEach((attr) => { 9131 newElement.setAttribute(attr.name, attr.value); 9132 }); 9133 if ("A" === newElement.tagName) newElement.classList.add("e-link", "e-focus"); 9134 else if ("DIV" === newElement.tagName) newElement.classList.remove("e-link", "e-focus"); 9135 newElement.innerHTML = elementParent.innerHTML; 9136 closestMenuItemTitle.replaceChild(newElement, elementParent); 9137 return newElement; 9138 } 9139 maybeCreateNewElement(elementParent, value) { 9140 if (!value) return document.createElement("div"); 9141 if (value && "DIV" === elementParent.tagName) return document.createElement("a"); 9142 } 9143 maybeUpdateNewElementsHref(value, newElement) { 9144 if (value) newElement.setAttribute("href", value); 9145 else newElement.removeAttribute("href"); 9146 } 9147 eCurrentClassHandler(actionName, closestMenuItemTitle, isCurrentUrl) { 9148 const { classes: { activeAnchorItem: eCurrentClassName }, postUrl, internalUrl } = this.getSettings(); 9149 switch (actionName) { 9150 case postUrl: 9151 closestMenuItemTitle.classList.add(eCurrentClassName); 9152 break; 9153 case internalUrl: 9154 if (isCurrentUrl) closestMenuItemTitle.classList.add(eCurrentClassName); 9155 else closestMenuItemTitle.classList.remove(eCurrentClassName); 9156 break; 9157 default: 9158 if (closestMenuItemTitle.classList.contains(eCurrentClassName) && postUrl !== actionName) closestMenuItemTitle.classList.remove(eCurrentClassName); 9159 break; 9160 } 9161 } 9162 setTouchMode() {
9163 const widgetSelector = this.getSettings("selectors").widgetContainer; 9164 if (elementorFrontend.isEditMode() || "resize" === (event == null ? void 0 : event.type)) { 9165 const responsiveDevices = [ 9166 "mobile", 9167 "mobile_extra", 9168 "tablet", 9169 "tablet_extra" 9170 ]; 9171 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 9172 if (-1 !== responsiveDevices.indexOf(currentDevice)) { 9173 this.$element.find(widgetSelector).attr("data-touch-mode", "true"); 9174 return; 9175 } 9176 } else if ("ontouchstart" in window) { 9177 this.$element.find(widgetSelector).attr("data-touch-mode", "true"); 9178 return; 9179 } 9180 this.$element.find(widgetSelector).attr("data-touch-mode", "false"); 9181 } 9182 getTabsDirection() { 9183 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 9184 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), "tabs_justify_horizontal", "", currentDevice); 9185 } 9186 getHorizontalScrollingSettings() { 9187 return { 9188 element: this.elements.$headingContainer[0], 9189 direction: this.getTabsDirection(), 9190 justifyCSSVariable: "--n-tabs-heading-justify-content", 9191 horizontalScrollStatus: this.getHorizontalScrollSetting() 9192 }; 9193 } 9194 }; 9195 })); 9196 //#endregion 9197 //#region modules/mega-menu/assets/js/frontend/handlers/stretch-menu-item-content.js 9198 var stretch_menu_item_content_exports = /* @__PURE__ */ __exportAll({ default: () => StretchedMenuItemContent }); 9199 var StretchedMenuItemContent; 9200 var init_stretch_menu_item_content = __esmMin((() => { 9201 StretchedMenuItemContent = class extends elementorModules.frontend.handlers.StretchedElement { 9202 getStretchedClass() { 9203 return "elementor-widget-n-menu"; 9204 } 9205 getStretchElementForConfig() { 9206 return this.$element.find(".e-n-menu-wrapper"); 9207 } 9208 getStretchElementConfig() { 9209 const elementConfig = super.getStretchElementConfig(); 9210 elementConfig.cssOutput = "variables"; 9211 return elementConfig; 9212 } 9213 bindEvents() { 9214 super.bindEvents(); 9215 elementorFrontend.addListenerOnce(this.getUniqueHandlerID(), "elementor-pro/mega-menu/dropdown-open", this.stretch); 9216 elementorFrontend.elements.$window.on("elementor-pro/mega-menu/heading-mouse-event", this.stretch); 9217 } 9218 unbindEvents() { 9219 super.unbindEvents(); 9220 elementorFrontend.removeListeners(this.getUniqueHandlerID(), "elementor-pro/mega-menu/dropdown-open", this.stretch); 9221 elementorFrontend.elements.$window.off("elementor-pro/mega-menu/heading-mouse-event", this.stretch); 9222 } 9223 isStretchSettingEnabled() { 9224 return true; 9225 } 9226 isActive() { 9227 return true; 9228 } 9229 }; 9230 })); 9231 //#endregion 9232 //#region modules/mega-menu/assets/js/frontend/handlers/menu-title-keyboard-handler.js 9233 var menu_title_keyboard_handler_exports = /* @__PURE__ */ __exportAll({ default: () => MenuTitleKeyboardHandler }); 9234 var MenuTitleKeyboardHandler; 9235 var init_menu_title_keyboard_handler = __esmMin((() => { 9236 init_focusable_element_selectors(); 9237 init_defineProperty(); 9238 MenuTitleKeyboardHandler = class extends elementorModules.frontend.handlers.Base { 9239 constructor(..._args) { 9240 super(..._args); 9241 _defineProperty(this, "isEditorElementsChanged", false); 9242 } 9243 __construct(...args) { 9244 super.__construct(...args); 9245 this.focusableElementSelector = focusableElementSelectors(); 9246 this.handleMenuToggleKeydown = this.handleMenuToggleKeydown.bind(this); 9247 } 9248 getDefaultSettings() { 9249 return { 9250 selectors: { 9251 widgetInnerWrapper: ".e-n-menu", 9252 menuItem: ".e-n-menu-item", 9253 menuItemWrapper: ".e-n-menu-title", 9254 focusableMenuElement: ".e-focus", 9255 itemContainer: ".e-n-menu-content > .e-con, .e-n-menu-heading > .e-con", 9256 menuToggle: ".e-n-menu-toggle", 9257 directTabTitle: ":scope > .elementor-widget-container > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-title,:scope > .e-n-menu > .e-n-menu-wrapper > .e-n-menu-heading > .e-n-menu-item > .e-n-menu-title", 9258 tabDropdown: ".e-n-menu-dropdown-icon" 9259 }, 9260 ariaAttributes: { 9261 titleStateAttribute: "aria-expanded", 9262 activeTitleSelector: "[aria-expanded=\"true\"]", 9263 titleControlAttribute: "aria-controls" 9264 }, 9265 datasets: { titleIndex: "data-focus-index" } 9266 }; 9267 } 9268 getDefaultElements() {
9269 const selectors = this.getSettings("selectors"); 9270 return { 9271 $menuItemWrappers: this.findElement(selectors.menuItemWrapper), 9272 $focusableMenuElements: this.findElement(selectors.focusableMenuElement), 9273 $itemContainers: this.findElement(selectors.itemContainer), 9274 $focusableContainerElements: this.getFocusableElements(this.findElement(selectors.itemContainer)), 9275 $menuToggle: this.findElement(selectors.menuToggle) 9276 }; 9277 } 9278 getFocusableElements($elements) { 9279 return $elements.find(this.focusableElementSelector).not("[disabled], [inert], [tabindex=\"-1\"]"); 9280 } 9281 getTitleIndex(focusableMenuElement) { 9282 const { titleIndex: indexAttribute } = this.getSettings("datasets"); 9283 return parseInt(focusableMenuElement === null || focusableMenuElement === void 0 ? void 0 : focusableMenuElement.getAttribute(indexAttribute)); 9284 } 9285 getTitleFilterSelector(titleIndex) { 9286 const { titleIndex: indexAttribute } = this.getSettings("datasets"); 9287 return `[${indexAttribute}="${titleIndex}"]`; 9288 } 9289 getActiveTitleElement() { 9290 const activeTitleFilter = this.getSettings("ariaAttributes").activeTitleSelector; 9291 return this.elements.$focusableMenuElements.filter(activeTitleFilter); 9292 } 9293 onInit(...args) { 9294 super.onInit(...args); 9295 let focusTitleCount = 1; 9296 this.elements.$focusableMenuElements.each((index, title) => { 9297 title.setAttribute(this.getSettings("datasets").titleIndex, focusTitleCount++); 9298 }); 9299 } 9300 getTitleEvents() { 9301 return { 9302 keydown: this.handleTitleKeyboardNavigation.bind(this), 9303 keyup: this.handeTitleKeyUp.bind(this) 9304 }; 9305 } 9306 getContentElementEvents() { 9307 return { keydown: this.handleContentElementKeyboardNavigation.bind(this) }; 9308 } 9309 bindEvents() { 9310 this.elements.$focusableMenuElements.on(this.getTitleEvents()); 9311 this.elements.$focusableContainerElements.on(this.getContentElementEvents()); 9312 elementorFrontend.elements.$window.on("keydown", this.handleMenuToggleKeydown); 9313 elementorFrontend.elements.$window.on("elementor/nested-container/atomic-repeater", this.linkContainer.bind(this)); 9314 } 9315 unbindEvents() { 9316 this.elements.$focusableMenuElements.off(this.getTitleEvents()); 9317 this.elements.$focusableContainerElements.off(this.getContentElementEvents()); 9318 elementorFrontend.elements.$window.off("keydown", this.handleMenuToggleKeydown); 9319 elementorFrontend.elements.$window.off("elementor/nested-container/atomic-repeater", this.linkContainer.bind(this)); 9320 } 9321 handleMenuToggleKeydown(event) { 9322 if ("Escape" !== event.key) return; 9323 event.preventDefault(); 9324 event.stopPropagation(); 9325 this.closeMenuDropdown(); 9326 } 9327 handleTitleKeyboardNavigation(event) { 9328 switch (event.key) { 9329 case "Tab": 9330 var _event$currentTarget; 9331 this.maybeRebindFocusableElements(); 9332 const $menuItemElements = this.elements.$focusableMenuElements; 9333 const isForward = !event.shiftKey; 9334 const isLastMenuItemElementForward = isForward && $menuItemElements.last().is(jQuery(event.currentTarget)); 9335 const isFirstMenuItemElementBackwards = !isForward && $menuItemElements.first().is(jQuery(event.currentTarget)); 9336 if (this.isDropdownLayout() && !isLastMenuItemElementForward && !isFirstMenuItemElementBackwards) return; 9337 const isNotOpenDropdown = !event.currentTarget.getAttribute("aria-expanded") || "false" === ((_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 ? void 0 : _event$currentTarget.getAttribute("aria-expanded")); 9338 if (isForward && isNotOpenDropdown || isFirstMenuItemElementBackwards) { 9339 this.closeActiveContentElements(); 9340 this.closeMenuDropdown(); 9341 } 9342 break; 9343 case "Home": 9344 case "End": 9345 this.handleTitleHomeOrEndKey(event); 9346 break; 9347 case "Enter": 9348 case " ": 9349 this.handleTitleActivationKey(event); 9350 break; 9351 case "Escape": 9352 this.handleTitleEscapeKey(event); 9353 break; 9354 } 9355 } 9356 handeTitleKeyUp(event) { 9357 var _event$currentTarget2; 9358 if (this.isDropdownLayout()) return true; 9359 const isTabKey = "Tab" === event.key; 9360 const isNotOpenDropdown = !event.currentTarget.getAttribute("aria-expanded") || "false" === ((_event$currentTarget2 = event.currentTarget) === null || _event$currentTarget2 === void 0 ? void 0 : _event$currentTarget2.getAttribute("aria-expanded")); 9361 if (isTabKey && isNotOpenDropdown) this.closeActiveContentElements(); 9362 } 9363 isDropdownLayout() {
9364 const selectors = this.getSettings("selectors"); 9365 return "dropdown" === this.$element.find(selectors.widgetInnerWrapper).attr("data-layout"); 9366 } 9367 closeMenuDropdown() { 9368 if (!this.isDropdownLayout()) return; 9369 elementorFrontend.elements.$window.trigger("elementor/mega-menu/dropdown-toggle-by-keyboard", { 9370 widgetId: this.getID(), 9371 show: false 9372 }); 9373 } 9374 handleTitleHomeOrEndKey(event) { 9375 event.preventDefault(); 9376 const currentTitleIndex = this.getTitleIndex(event.currentTarget) || 1; 9377 const numberOfTitles = this.elements.$focusableMenuElements.length; 9378 const titleIndexUpdated = this.getTitleIndexFocusUpdated(event, currentTitleIndex, numberOfTitles); 9379 this.setTitleFocus(titleIndexUpdated); 9380 event.stopPropagation(); 9381 } 9382 handleTitleActivationKey(event) { 9383 event.preventDefault(); 9384 if (this.handleTitleLinkEnterOrSpaceEvent(event)) return; 9385 const titleIndex = this.getTitleIndex(event.currentTarget); 9386 elementorFrontend.elements.$window.trigger("elementor/nested-elements/activate-by-keyboard", { 9387 widgetId: this.getID(), 9388 titleIndex 9389 }); 9390 } 9391 setTitleFocus(titleIndexUpdated) { 9392 this.elements.$focusableMenuElements.filter(this.getTitleFilterSelector(titleIndexUpdated)).trigger("focus"); 9393 } 9394 handleTitleLinkEnterOrSpaceEvent(event) { 9395 var _event$currentTarget3; 9396 const isLinkElement = "a" === (event === null || event === void 0 || (_event$currentTarget3 = event.currentTarget) === null || _event$currentTarget3 === void 0 || (_event$currentTarget3 = _event$currentTarget3.tagName) === null || _event$currentTarget3 === void 0 ? void 0 : _event$currentTarget3.toLowerCase()); 9397 if (!elementorFrontend.isEditMode() && isLinkElement) { 9398 var _event$currentTarget4; 9399 event === null || event === void 0 || (_event$currentTarget4 = event.currentTarget) === null || _event$currentTarget4 === void 0 || _event$currentTarget4.click(); 9400 event.stopPropagation(); 9401 } 9402 return isLinkElement; 9403 } 9404 handleTitleEscapeKey(event) { 9405 event.preventDefault(); 9406 event.stopPropagation(); 9407 if (this.isDropdownLayout()) { 9408 elementorFrontend.elements.$window.trigger("elementor/mega-menu/dropdown-toggle-by-keyboard", { widgetId: this.getID() }); 9409 this.setFocusToMenuToggle(); 9410 } 9411 elementorFrontend.elements.$window.trigger("elementor/nested-elements/activate-by-keyboard", { widgetId: this.getID() }); 9412 } 9413 setFocusToMenuToggle() { 9414 const selectors = this.getSettings("selectors"); 9415 this.$element.find(selectors.menuToggle).trigger("focus"); 9416 } 9417 handleContentElementKeyboardNavigation(event) { 9418 switch (event.key) { 9419 case "Tab": 9420 if (!event.shiftKey) this.handleContentElementTabEvents(event); 9421 break; 9422 case "Escape": 9423 event.preventDefault(); 9424 event.stopPropagation(); 9425 this.handleContentElementEscapeEvents(event); 9426 break; 9427 } 9428 } 9429 maybeRebindFocusableElements() { 9430 if (!this.isEditorElementsChanged) return; 9431 this.elements.$focusableContainerElements.off(this.getContentElementEvents()); 9432 this.elements.$focusableContainerElements = this.getFocusableElements(this.elements.$itemContainers); 9433 this.elements.$focusableContainerElements.on(this.getContentElementEvents()); 9434 this.isEditorElementsChanged = false; 9435 } 9436 handleContentElementTabEvents(event) { 9437 const selectors = this.getSettings("selectors"); 9438 const $currentElement = jQuery(event.currentTarget); 9439 const containerSelector = selectors.itemContainer; 9440 const $currentContainer = $currentElement.closest(containerSelector); 9441 const $lastFocusableElement = this.getFocusableElements($currentContainer).last(); 9442 if (!$currentElement.is($lastFocusableElement)) return; 9443 if (!this.isDropdownLayout()) this.closeActiveContentElements(); 9444 const menuItemSelector = selectors.menuItem; 9445 const isLastMenuItem = 0 === $currentContainer.closest(menuItemSelector).next(menuItemSelector).length; 9446 if (this.isDropdownLayout() && isLastMenuItem) { 9447 this.closeActiveContentElements(); 9448 this.closeMenuDropdown(); 9449 } 9450 } 9451 handleContentElementEscapeEvents() { 9452 this.getActiveTitleElement().trigger("focus"); 9453 this.closeActiveContentElements(); 9454 } 9455 closeActiveContentElements() { 9456 elementorFrontend.elements.$window.trigger("elementor/nested-elements/activate-by-keyboard", { widgetId: this.getID() }); 9457 } 9458 linkContainer(event) { 9459 const { container } = event.detail, id = container.model.get("id"), currentId = String(this.$element.data("id")), view = container.view.$el; 9460 if (id === currentId) { 9461 this.updateIndexValues(view); 9462 this.updateListeners(view); 9463 } 9464 } 9465 updateIndexValues(view) { 9466 const { selectors: { directTabTitle, tabDropdown } } = this.getDefaultSettings(), tabTitles = view[0].querySelectorAll(directTabTitle); 9467 let focusTitleCount = 1;
9468 tabTitles.forEach((element) => { 9469 if (element.querySelector("a")) element.querySelector("a").setAttribute("data-focus-index", focusTitleCount++); 9470 if (element.querySelector(tabDropdown)) element.querySelector(tabDropdown).setAttribute("data-focus-index", focusTitleCount++); 9471 }); 9472 } 9473 updateListeners(view) { 9474 this.elements.$focusableMenuElements.off(); 9475 const { selectors: { focusableMenuElement, itemContainer } } = this.getSettings(); 9476 this.elements.$focusableMenuElements = view.find(focusableMenuElement); 9477 this.elements.$itemContainers = view.find(itemContainer); 9478 this.elements.$focusableMenuElements.on(this.getTitleEvents()); 9479 this.isEditorElementsChanged = true; 9480 } 9481 }; 9482 })); 9483 //#endregion 9484 //#region modules/mega-menu/assets/js/frontend/frontend.js 9485 var frontend_default$4 = class extends elementorModules.Module { 9486 static { 9487 __name(this, "default"); 9488 } 9489 constructor() { 9490 super(); 9491 elementorFrontend.elementsHandler.attachHandler("mega-menu", [ 9492 () => __vitePreload(() => Promise.resolve().then(() => (init_mega_menu(), mega_menu_exports)), void 0), 9493 () => __vitePreload(() => Promise.resolve().then(() => (init_stretch_menu_item_content(), stretch_menu_item_content_exports)), void 0), 9494 () => __vitePreload(() => Promise.resolve().then(() => (init_menu_title_keyboard_handler(), menu_title_keyboard_handler_exports)), void 0) 9495 ]); 9496 } 9497 }; 9498 //#endregion 9499 //#region modules/nested-carousel/assets/js/frontend/handlers/nested-carousel.js 9500 var nested_carousel_exports = /* @__PURE__ */ __exportAll({ default: () => NestedCarousel }); 9501 var NestedCarousel; 9502 var init_nested_carousel = __esmMin((() => { 9503 init_run_element_handlers(); 9504 init_asyncToGenerator(); 9505 NestedCarousel = class extends elementorModules.frontend.handlers.CarouselBase { 9506 getDefaultSettings() { 9507 const defaultSettings = super.getDefaultSettings(); 9508 defaultSettings.selectors.carousel = ".e-n-carousel"; 9509 defaultSettings.selectors.slidesWrapper = ".e-n-carousel > .swiper-wrapper"; 9510 return defaultSettings; 9511 } 9512 getSwiperSettings() { 9513 const swiperOptions = super.getSwiperSettings(); 9514 const elementSettings = this.getElementSettings(); 9515 const isRtl = elementorFrontend.config.is_rtl; 9516 const widgetSelector = `.elementor-element-${this.getID()}`; 9517 if (elementorFrontend.isEditMode()) { 9518 delete swiperOptions.autoplay; 9519 swiperOptions.loop = false; 9520 swiperOptions.noSwipingSelector = ".swiper-slide > .e-con .elementor-element"; 9521 } 9522 if ("yes" === elementSettings.arrows) swiperOptions.navigation = { 9523 prevEl: isRtl ? `${widgetSelector} .elementor-swiper-button-next` : `${widgetSelector} .elementor-swiper-button-prev`, 9524 nextEl: isRtl ? `${widgetSelector} .elementor-swiper-button-prev` : `${widgetSelector} .elementor-swiper-button-next` 9525 }; 9526 this.applySwipeOptions(swiperOptions); 9527 return swiperOptions; 9528 } 9529 onInit(...args) { 9530 var _superprop_getOnInit = () => super.onInit; 9531 var _this = this; 9532 return _asyncToGenerator(function* () { 9533 _this.wrapSlideContent(); 9534 _superprop_getOnInit().call(_this, ...args); 9535 _this.ranElementHandlers = false; 9536 })(); 9537 } 9538 initSwiper() { 9539 var _this2 = this; 9540 return _asyncToGenerator(function* () { 9541 const Swiper = elementorFrontend.utils.swiper; 9542 _this2.swiper = yield new Swiper(_this2.elements.$swiperContainer, _this2.getSwiperSettings()); 9543 _this2.elements.$swiperContainer.data("swiper", _this2.swiper); 9544 })(); 9545 } 9546 handleElementHandlers() { 9547 if (this.ranElementHandlers || !this.swiper) return; 9548 runElementHandlers(Array.from(this.swiper.slides).filter((slide) => slide.classList.contains(this.swiper.params.slideDuplicateClass))); 9549 this.ranElementHandlers = true; 9550 } 9551 wrapSlideContent() { 9552 if (!elementorFrontend.isEditMode()) return; 9553 const settings = this.getSettings(); 9554 const slideContentClass = settings.selectors.slideContent.replace(".", ""); 9555 const $widget = this.$element; 9556 let index = 1; 9557 this.findElement(`${settings.selectors.slidesWrapper} > .e-con`).each(function() { 9558 const $currentContainer = jQuery(this); 9559 const hasSwiperSlideWrapper = $currentContainer.closest("div").hasClass(slideContentClass); 9560 const $currentSlide = $widget.find(`${settings.selectors.slidesWrapper} > .${slideContentClass}:nth-child(${index})`); 9561 if (!hasSwiperSlideWrapper) $currentSlide.append($currentContainer); 9562 index++; 9563 }); 9564 } 9565 togglePauseOnHover(toggleOn) { 9566 if (elementorFrontend.isEditMode()) return; 9567 super.togglePauseOnHover(toggleOn); 9568 } 9569 getChangeableProperties() { 9570 return { arrows_position: "arrows_position" }; 9571 } 9572 applySwipeOptions(swiperOptions) { 9573 if (!this.isTouchDevice()) swiperOptions.shortSwipes = false;
9574 else { 9575 swiperOptions.touchRatio = 1; 9576 swiperOptions.longSwipesRatio = .3; 9577 swiperOptions.followFinger = true; 9578 swiperOptions.threshold = 10; 9579 } 9580 } 9581 isTouchDevice() { 9582 return elementorFrontend.utils.environment.isTouchDevice; 9583 } 9584 linkContainer(event) { 9585 var _this3 = this; 9586 return _asyncToGenerator(function* () { 9587 const { container, index, targetContainer, action: { type } } = event.detail, view = container.view.$el; 9588 if (container.model.get("id") === _this3.$element.data("id")) { 9589 const { $slides } = _this3.getDefaultElements(); 9590 let carouselItemWrapper; 9591 let contentContainer; 9592 switch (type) { 9593 case "move": 9594 [carouselItemWrapper, contentContainer] = _this3.move(view, index, targetContainer, $slides); 9595 break; 9596 case "duplicate": 9597 [carouselItemWrapper, contentContainer] = _this3.duplicate(view, index, targetContainer, $slides); 9598 break; 9599 default: break; 9600 } 9601 if (void 0 !== carouselItemWrapper) carouselItemWrapper.appendChild(contentContainer); 9602 _this3.shouldHideNavButtons(view, $slides); 9603 _this3.updateIndexValues($slides); 9604 const isSwiperActive = _this3.swiper && !_this3.swiper.destroyed; 9605 const hasMultipleSlides = $slides.length > 1; 9606 if (!isSwiperActive && hasMultipleSlides) yield _this3.initSwiper(); 9607 else if (isSwiperActive && !hasMultipleSlides) _this3.swiper.destroy(true); 9608 _this3.updateListeners(); 9609 } 9610 })(); 9611 } 9612 updateListeners() { 9613 this.swiper.initialized = false; 9614 this.swiper.init(); 9615 } 9616 move(view, index, targetContainer, slides) { 9617 return [slides[index], targetContainer.view.$el[0]]; 9618 } 9619 duplicate(view, index, targetContainer, slides) { 9620 return [slides[index + 1], targetContainer.view.$el[0]]; 9621 } 9622 updateIndexValues($slides) { 9623 $slides.each((index, element) => { 9624 const newIndex = index + 1; 9625 element.setAttribute("data-slide", newIndex); 9626 }); 9627 } 9628 bindEvents() { 9629 super.bindEvents(); 9630 elementorFrontend.elements.$window.on("elementor/nested-container/atomic-repeater", this.linkContainer.bind(this)); 9631 } 9632 shouldHideNavButtons(view, $slides) { 9633 var _navButtons$; 9634 const navButtons = view[0].querySelectorAll(".elementor-swiper-button"); 9635 const shouldHide = 1 === $slides.length; 9636 if (shouldHide !== ((_navButtons$ = navButtons[0]) === null || _navButtons$ === void 0 ? void 0 : _navButtons$.classList.contains("hide"))) navButtons.forEach((button) => { 9637 button.classList.toggle("hide", shouldHide); 9638 }); 9639 } 9640 }; 9641 })); 9642 //#endregion 9643 //#region modules/nested-carousel/assets/js/frontend/frontend.js 9644 var frontend_default$3 = class extends elementorModules.Module { 9645 static { 9646 __name(this, "default"); 9647 } 9648 constructor() { 9649 super(); 9650 elementorFrontend.elementsHandler.attachHandler("nested-carousel", () => __vitePreload(() => Promise.resolve().then(() => (init_nested_carousel(), nested_carousel_exports)), void 0)); 9651 } 9652 }; 9653 //#endregion 9654 //#region modules/loop-filter/assets/js/frontend/loop-widgets-store.js 9655 init_objectSpread2(); 9656 var LoopWidgetsStore = class { 9657 constructor() { 9658 this.widgets = {}; 9659 } 9660 get() { 9661 return this.widgets; 9662 } 9663 getWidget(widgetId) { 9664 return this.widgets[widgetId]; 9665 } 9666 setWidget(widgetId, widget) { 9667 this.widgets[widgetId] = widget; 9668 } 9669 unsetWidget(widgetId) { 9670 delete this.widgets[widgetId]; 9671 } 9672 getFilters(widgetId) { 9673 return this.getWidget(widgetId).filters; 9674 } 9675 getFilter(widgetId, filterId) { 9676 return this.getWidget(widgetId).filters[filterId]; 9677 } 9678 setFilter(widgetId, filterId, filterData) { 9679 this.getWidget(widgetId).filters[filterId] = filterData; 9680 } 9681 unsetFilter(widgetId, filterId) { 9682 delete this.getWidget(widgetId).filters[filterId]; 9683 } 9684 getFilterTerms(widgetId, filterId) { 9685 var _this$getFilter$filte; 9686 return (_this$getFilter$filte = this.getFilter(widgetId, filterId).filterData.terms) !== null && _this$getFilter$filte !== void 0 ? _this$getFilter$filte : []; 9687 } 9688 setFilterTerms(widgetId, filterId, termData) { 9689 this.getFilter(widgetId, filterId).filterData.terms = termData; 9690 } 9691 getConsolidatedFilters(widgetId) { 9692 return this.getWidget(widgetId).consolidatedFilters; 9693 } 9694 setConsolidatedFilters(widgetId, consolidatedFilters) { 9695 this.getWidget(widgetId).consolidatedFilters = consolidatedFilters; 9696 } 9697 /** 9698 * 9699 * @param {string} widgetId 9700 */ 9701 addWidget(widgetId) { 9702 this.setWidget(widgetId, { 9703 filters: {}, 9704 consolidatedFilters: {} 9705 }); 9706 } 9707 maybeInitializeWidget(widgetId) { 9708 if (!!this.getWidget(widgetId)) return; 9709 this.addWidget(widgetId); 9710 } 9711 maybeInitializeFilter(widgetId, filterId) { 9712 if (!!this.getFilter(widgetId, filterId)) return; 9713 this.setFilter(widgetId, filterId, { filterData: { terms: [] } }); 9714 } 9715 /** 9716 * Consolidates all filters for a loop widget. 9717 * 9718 * filters: { 9719 * filter1: { filterType: 'type1', filterData: { selectedTaxonomy: 'taxonomy1', terms: [ 'term1', 'term2' ] } }, 9720 * filter2: { filterType: 'type1', filterData: { selectedTaxonomy: 'taxonomy1', terms: [ 'term2' ] } }, 9721 * }, 9722 * consolidatedFilters: {}, 9723 * 9724 * @param {string} widgetId 9725 */ 9726 consolidateFilters(widgetId) { 9727 const loopWidgetFilters = this.getFilters(widgetId); 9728 const consolidatedFilters = {}; 9729 for (const filterId in loopWidgetFilters) { 9730 const filter = loopWidgetFilters[filterId]; 9731 const filterType = filter.filterType; 9732 const filterData = filter.filterData; 9733 if (0 === filterData.terms.length) continue; 9734 if (!consolidatedFilters[filterType]) consolidatedFilters[filterType] = {}; 9735 if (!consolidatedFilters[filterType][filterData.selectedTaxonomy]) consolidatedFilters[filterType][filterData.selectedTaxonomy] = []; 9736 if (filterData.terms && (!consolidatedFilters[filterType][filterData.selectedTaxonomy].terms || !consolidatedFilters[filterType][filterData.selectedTaxonomy].terms.includes(filterData.terms))) consolidatedFilters[filterType][filterData.selectedTaxonomy] = { terms: filterData.terms === "string" ? [filterData.terms] : filterData.terms }; 9737 if (filterData.logicalJoin && !consolidatedFilters[filterType][filterData.selectedTaxonomy].logicalJoin) { 9738 var _filterData$logicalJo; 9739 consolidatedFilters[filterType][filterData.selectedTaxonomy] = _objectSpread2
9739(_objectSpread2({}, consolidatedFilters[filterType][filterData.selectedTaxonomy] || {}), {}, { logicalJoin: (_filterData$logicalJo = filterData.logicalJoin) !== null && _filterData$logicalJo !== void 0 ? _filterData$logicalJo : "AND" }); 9740 } 9741 } 9742 this.setConsolidatedFilters(widgetId, consolidatedFilters); 9743 } 9744 }; 9745 //#endregion 9746 //#region modules/loop-filter/assets/js/query-constants.js 9747 var require_query_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => { 9748 module.exports = { queryConstants: { 9749 AND: { 9750 separator: { 9751 decoded: "+", 9752 fromBrowser: " ", 9753 encoded: "%2B" 9754 }, 9755 operator: "AND" 9756 }, 9757 OR: { 9758 separator: { 9759 decoded: "~", 9760 fromBrowser: "~", 9761 encoded: "%7C" 9762 }, 9763 operator: "IN" 9764 }, 9765 NOT: { 9766 separator: { 9767 decoded: "!", 9768 fromBrowser: "!", 9769 encoded: "%21" 9770 }, 9771 operator: "NOT IN" 9772 }, 9773 DISABLED: { 9774 separator: { 9775 decoded: "", 9776 fromBrowser: "", 9777 encoded: "" 9778 }, 9779 operator: "AND" 9780 } 9781 } }; 9782 })); 9783 //#endregion 9784 //#region modules/loop-filter/assets/js/frontend/frontend-module-base.js 9785 init_run_element_handlers(); 9786 init_ajax_helper(); 9787 var import_query_constants$1 = require_query_constants(); 9788 var BaseFilterFrontendModule = class extends elementorModules.Module { 9789 constructor() { 9790 super(); 9791 this.loopWidgetsStore = new LoopWidgetsStore(); 9792 } 9793 /** 9794 * Removes selected filter term from the filter array 9795 * 9796 * @param {string} widgetId 9797 * @param {string} filterId 9798 * @param {string} filterTerm 9799 * @param {string} defaultFilter 9800 */ 9801 removeFilterFromLoopWidget(widgetId, filterId, filterTerm = "", defaultFilter = "") { 9802 if (!this.loopWidgetsStore.getWidget(widgetId)) { 9803 this.loopWidgetsStore.addWidget(widgetId); 9804 this.refreshLoopWidget(widgetId, filterId); 9805 return; 9806 } 9807 if (filterTerm === defaultFilter) this.loopWidgetsStore.unsetFilter(widgetId, filterId); 9808 if (filterTerm !== defaultFilter) { 9809 const newTerms = this.loopWidgetsStore.getFilterTerms(widgetId, filterId).filter(function(e) { 9810 return e !== filterTerm; 9811 }); 9812 this.loopWidgetsStore.setFilterTerms(widgetId, filterId, newTerms); 9813 } 9814 this.refreshLoopWidget(widgetId, filterId); 9815 } 9816 /** 9817 * Sets the filter data for a loop widget. 9818 * 9819 * This function should trigger the following sequence: 9820 * 1. Update the filter data for the passed ID in the loopElements object by adding new filters to the loopWidgetsStore filters array. 9821 * 2. Trigger a rerender of the loop widget if refresh is true. 9822 * 3 Trigger a consolidation of all filters belonging to the passed loop widget ID if refresh is false. 9823 * - This should create an object with filter type keys, and for each type, an object of filter IDs, which contain the filter values. 9824 * - This should also remove duplicates. 9825 * 9826 * @param {string} widgetId 9827 * @param {string} filterId 9828 * @param {Object} filter new data for this filterId in loopWidgetsStore 9829 * @param {boolean} refresh 9830 * @param {string} multipleFiltersLogicalJoin AND / OR / 'DISABLED' for single filter (default) 9831 */ 9832 setFilterDataForLoopWidget(widgetId, filterId, filter, refresh = true, multipleFiltersLogicalJoin = "DISABLED") { 9833 var _a; 9834 this.loopWidgetsStore.maybeInitializeWidget(widgetId); 9835 this.loopWidgetsStore.maybeInitializeFilter(widgetId, filterId); 9836 const logicalJoin = this.validateMultipleFilterOperator(multipleFiltersLogicalJoin); 9837 if ("DISABLED" !== logicalJoin) { 9838 const existingTerms = (_a = this.loopWidgetsStore.getFilterTerms(widgetId, filterId)) != null ? _a : []; 9839 const newTerms = filter.filterData.terms; 9840 filter.filterData.terms = [.../* @__PURE__ */ new Set([...existingTerms, ...newTerms])]; 9841 filter.filterData.logicalJoin = logicalJoin; 9842 } 9843 this.loopWidgetsStore.setFilter(widgetId, filterId, filter); 9844 if (refresh) { 9845 this.refreshLoopWidget(widgetId, filterId); 9846 return; 9847 } 9848 this.loopWidgetsStore.consolidateFilters(widgetId); 9849 } 9850 /** 9851 * Validates the operator values for wp_query. 9852 * @param {string} operator 9853 * @return {*|string} 'AND' | 'OR' | 'DISABLED' 9854 */ 9855 validateMultipleFilterOperator(operator) { 9856 if (!operator || !["AND", "OR"].includes(operator)) return "DISABLED"; 9857 return operator; 9858 } 9859 /** 9860 * 9861 * @return {{}} Query string in object form. 9862 */
9863 getQueryStringInObjectForm() { 9864 var _a; 9865 const queryString = {}; 9866 for (const widgetId in this.loopWidgetsStore.get()) { 9867 const loopWidget = this.loopWidgetsStore.getWidget(widgetId); 9868 for (const filterType in loopWidget.consolidatedFilters) { 9869 const filterData = loopWidget.consolidatedFilters[filterType]; 9870 for (const filterName in filterData) { 9871 const separator = import_query_constants$1.queryConstants[(_a = filterData[filterName].logicalJoin) != null ? _a : "AND"].separator.decoded; 9872 queryString[`e-filter-${widgetId}-${filterName}`] = Object.values(filterData[filterName].terms).join(separator); 9873 } 9874 } 9875 } 9876 return queryString; 9877 } 9878 /** 9879 * Updates the URL query string with the current filter values. 9880 * 9881 * @param {string} widgetId 9882 * @param {string} filterId 9883 */ 9884 updateURLQueryString(widgetId, filterId) { 9885 const existingQueryString = new URL(window.location.href).searchParams; 9886 const queryStringObject = this.getQueryStringInObjectForm(); 9887 const updatedParams = new URLSearchParams(); 9888 existingQueryString.forEach((value, key) => { 9889 if (!key.startsWith("e-filter")) updatedParams.append(key, value); 9890 if (key.startsWith("e-page-" + widgetId)) updatedParams.delete(key); 9891 }); 9892 for (const key in queryStringObject) updatedParams.set(key, queryStringObject[key]); 9893 let queryString = updatedParams.toString(); 9894 queryString = queryString.replace(new RegExp(`${import_query_constants$1.queryConstants.AND.separator.encoded}`, "g"), import_query_constants$1.queryConstants.AND.separator.decoded); 9895 queryString = queryString.replace(new RegExp(`${import_query_constants$1.queryConstants.OR.separator.encoded}`, "g"), import_query_constants$1.queryConstants.OR.separator.decoded); 9896 const helpers = this.getFilterHelperAttributes(filterId); 9897 if (helpers.pageNum > 1) queryString = queryString ? this.formatQueryString(helpers.baseUrl, queryString) : helpers.baseUrl; 9898 else queryString = queryString ? `?${queryString}` : location.pathname; 9899 history.pushState(null, null, queryString); 9900 } 9901 /** 9902 * Formats the query string to remove any duplicate parameters. 9903 * 9904 * @param {string} baseURL 9905 * @param {string} queryString 9906 * @return {*} deduplicated query string 9907 */ 9908 formatQueryString(baseURL, queryString) { 9909 const baseURLParams = baseURL.includes("?") ? new URLSearchParams(baseURL.split("?")[1]) : new URLSearchParams(); 9910 const inputParams = new URLSearchParams(queryString); 9911 for (const param of baseURLParams.keys()) if (inputParams.has(param)) inputParams.delete(param); 9912 for (const excludedVar of ["page", "paged"]) { 9913 baseURLParams.delete(excludedVar); 9914 inputParams.delete(excludedVar); 9915 } 9916 const mergedParams = new URLSearchParams(baseURLParams.toString()); 9917 for (const [param, value] of inputParams.entries()) mergedParams.append(param, value); 9918 return baseURL.split("?")[0] + (mergedParams.toString() ? `?${mergedParams.toString()}` : ""); 9919 } 9920 /** 9921 * 9922 * @param {string} filterId 9923 * @return {{baseUrl: string, pageNum: number}|*|DOMStringMap} Base URL and page number for the loop widget. 9924 */ 9925 getFilterHelperAttributes(filterId) { 9926 const filterWidget = document.querySelector("[data-id=\"" + filterId + "\"]"); 9927 if (!filterWidget) return { 9928 baseUrl: location.href, 9929 pageNum: 1 9930 }; 9931 return filterWidget.querySelector(".e-filter").dataset; 9932 } 9933 /** 9934 * Prepares the data to be sent to the server for the loop widget update. 9935 * 9936 * @param {string} widgetId 9937 * @param {string} filterId 9938 * @return {{post_id: (*|number), widget_id, pagination_base_url: string, widget_filters: *}} data for loop update 9939 */ 9940 prepareLoopUpdateRequestData(widgetId, filterId) { 9941 const widgetFilters = this.loopWidgetsStore.getConsolidatedFilters(widgetId); 9942 const helpers = this.getFilterHelperAttributes(filterId); 9943 const data = { 9944 post_id: this.getClosestDataElementorId(document.querySelector(`.elementor-element-${widgetId}`)) || elementorFrontend.config.post.id, 9945 widget_filters: widgetFilters, 9946 widget_id: widgetId, 9947 pagination_base_url: helpers.baseUrl 9948 }; 9949 if (elementorFrontend.isEditMode()) { 9950 data.widget_model = window.top.$e.components.get("document").utils.findContainerById(widgetId).model.toJSON({ remove: [ 9951 "default", 9952 "editSettings", 9953 "defaultEditSettings" 9954 ] }); 9955 data.is_edit_mode = true; 9956 } 9957 return data; 9958 } 9959 /** 9960 * Returns the closest data-elementor-id attribute value. 9961 * 9962 * @param {Object} element 9963 * @return {string} elementor id of parent 9964 */ 9965 getClosestDataElementorId(element) { 9966 const closestParent = element == null ? void 0 : element.closest("[data-elementor-id]"); 9967 return closestParent ? closestParent.getAttribute("data-elementor-id") : null; 9968 } 9969 /** 9970 * 9971 * @param {string} widgetId 9972 * @param {string} filterId 9973 * @return {{headers: {"Content-Type": string}, method: string, body: string}} Fetch arguments for loop Widget update 9974 */ 9975 getFetchArgumentsForLoopUpdate(widgetId, filterId) { 9976 var _a; 9977 var _b; 9978 const data = this.prepareLoopUpdateRequestData(widgetId, filterId); 9979 const args = { 9980 method: "POST", 9981 headers: { "Content-Type": "application/json" }, 9982 body: JSON.stringify(data) 9983 }; 9984 if (elementorFrontend.isEditMode() && !!((_a = elementorPro.config.loopFilter) == null ? void 0 : _a.nonce)) args.headers["X-WP-Nonce"] = (_b = elementorPro.config.loopFilter) == null ? void 0 : _b.nonce; 9985 return args; 9986 } 9987 /** 9988 * Fetches the updated loop widget markup from the server. 9989 * 9990 * @param {string} widgetId 9991 * @param {string} filterId 9992 * @return {Promise<Response>} Promise for the fetch request. 9993 */ 9994 fetchUpdatedLoopWidgetMarkup(widgetId, filterId) { 9995 return fetch(`${elementorProFrontend.config.urls.rest}elementor-pro/v1/refresh-loop`, this.getFetchArgumentsForLoopUpdate(widgetId, filterId)); 9996 } 9997 createElementFromHTMLString(widgetContainerHTMLString) { 9998 const div = document.createElement("div"); 9999 if (!widgetContainerHTMLString) { 10000 div.classList.add("elementor-widget-container"); 10001 return div; 10002 } 10003 div.innerHTML = widgetContainerHTMLString.trim(); 10004 return div.firstElementChild; 10005 } 10006 refreshLoopWidget(widgetId, filterId) { 10007 this.loopWidgetsStore.consolidateFilters(widgetId);
10008 this.updateURLQueryString(widgetId, filterId); 10009 const widget = document.querySelector(`.elementor-element-${widgetId}`); 10010 if (!widget) return; 10011 if (!this.ajaxHelper) this.ajaxHelper = new AjaxHelper(); 10012 this.ajaxHelper.addLoadingAnimationOverlay(widgetId); 10013 return this.fetchUpdatedLoopWidgetMarkup(widgetId, filterId).then((response) => { 10014 if (!(response instanceof Response) || !(response == null ? void 0 : response.ok) || 400 <= (response == null ? void 0 : response.status)) return {}; 10015 return response.json(); 10016 }).catch(() => { 10017 return {}; 10018 }).then((response) => { 10019 if (!(response == null ? void 0 : response.data) && "" !== (response == null ? void 0 : response.data)) return; 10020 const existingWidgetContainer = widget.querySelector(".elementor-widget-container"); 10021 const newWidgetContainer = this.createElementFromHTMLString(response.data); 10022 widget.replaceChild(newWidgetContainer, existingWidgetContainer); 10023 this.handleElementHandlers(widget); 10024 if (ElementorProFrontendConfig.settings.lazy_load_background_images) document.dispatchEvent(new Event("elementor/lazyload/observe")); 10025 elementorFrontend.elementsHandler.runReadyTrigger(document.querySelector(`.elementor-element-${widgetId}`)); 10026 widget.classList.remove("e-loading"); 10027 }).finally(() => { 10028 this.ajaxHelper.removeLoadingAnimationOverlay(widgetId); 10029 }); 10030 } 10031 handleElementHandlers(newWidgetMarkup) { 10032 runElementHandlers(newWidgetMarkup.querySelectorAll(".e-loop-item")); 10033 } 10034 }; 10035 //#endregion 10036 //#region modules/loop-filter/assets/js/frontend/handlers/taxonomy-filter.js 10037 var taxonomy_filter_exports = /* @__PURE__ */ __exportAll({ default: () => TaxonomyFilter }); 10038 var import_query_constants, TaxonomyFilter; 10039 var init_taxonomy_filter = __esmMin((() => { 10040 init_flex_horizontal_scroll(); 10041 import_query_constants = require_query_constants(); 10042 TaxonomyFilter = class extends elementorModules.frontend.handlers.Base { 10043 constructor(...args) { 10044 super(...args); 10045 this.resizeListenerNestedTabs = null; 10046 } 10047 /** 10048 * 10049 * @return {{filterValues: {default: string}, selectors: {container: string, item: string}}} Default Settings 10050 */ 10051 getDefaultSettings() { 10052 return { 10053 selectors: { 10054 item: ".e-filter-item", 10055 container: ".e-filter" 10056 }, 10057 filterValues: { default: "__all" } 10058 }; 10059 } 10060 /** 10061 * 10062 * @return {{$filterButtons: *, $container: *}} Default Elements 10063 */ 10064 getDefaultElements() { 10065 return { 10066 $filterButtons: this.$element.find(this.getSettings("selectors.item")), 10067 $container: this.$element.find(this.getSettings("selectors.container")) 10068 }; 10069 } 10070 getHeadingEvents() { 10071 const container = this.elements.$container[0]; 10072 return { 10073 mousedown: changeScrollStatus.bind(this, container), 10074 mouseup: changeScrollStatus.bind(this, container), 10075 mouseleave: changeScrollStatus.bind(this, container), 10076 mousemove: setHorizontalTitleScrollValues.bind(this, container, this.getHorizontalScrollSetting()) 10077 }; 10078 } 10079 bindEvents() { 10080 this.elements.$filterButtons.on("click", this.onFilterButtonClick.bind(this)); 10081 this.elements.$container.on(this.getHeadingEvents()); 10082 const settingsObject = { 10083 element: this.elements.$container[0], 10084 direction: this.getItemsAlignment(), 10085 justifyCSSVariable: "--e-filter-justify-content", 10086 horizontalScrollStatus: this.getHorizontalScrollSetting() 10087 }; 10088 this.resizeListenerNestedTabs = setHorizontalScrollAlignment.bind(this, settingsObject); 10089 elementorFrontend.elements.$window.on("resize", this.resizeListenerNestedTabs); 10090 } 10091 /** 10092 * 10093 * @param {string} propertyName 10094 */ 10095 onElementChange(propertyName) { 10096 if (this.checkSliderPropsToWatch(propertyName)) setHorizontalScrollAlignment({ 10097 element: this.elements.$container[0], 10098 direction: this.getItemsAlignment(), 10099 justifyCSSVariable: "--e-filter-justify-content", 10100 horizontalScrollStatus: this.getHorizontalScrollSetting() 10101 }); 10102 } 10103 /** 10104 * 10105 * @param {string} propertyName 10106 * @return {boolean} Is slider property 10107 */ 10108 checkSliderPropsToWatch(propertyName) { 10109 return 0 === propertyName.indexOf("horizontal_scroll") || 0 === propertyName.indexOf("item_al
10109ignment_horizontal"); 10110 } 10111 /** 10112 * Get the filter buttons elements. 10113 * 10114 * If the filter buttons weren't rendered when the handler was initialized, this method will cache the filter 10115 * button elements and add the necessary event listeners. 10116 * 10117 * @return {*} jQuery collection of filter button elements. Might be empty. 10118 */ 10119 getFilterButtonElements() { 10120 var _a; 10121 if ((_a = this.elements) == null ? void 0 : _a.$filterButtons.length) return this.elements.$filterButtons; 10122 this.elements = this.getDefaultElements(); 10123 this.bindEvents(); 10124 return this.elements.$filterButtons; 10125 } 10126 /** 10127 * Get the active filter buttons elements. 10128 * 10129 * @return {*} jQuery collection of the active filter button elements. Might be empty. 10130 */ 10131 getActiveFilterButtonElements() { 10132 return this.getFilterButtonElements().filter("[aria-pressed=\"true\"]"); 10133 } 10134 /** 10135 * 10136 * @param {string} selectedTermSlug 10137 */ 10138 activateFilterButton(selectedTermSlug) { 10139 const $filterButtons = this.getFilterButtonElements(); 10140 const multipleSelectionActive = "yes" === this.getElementSettings("multiple_selection"); 10141 if (!$filterButtons.length) return; 10142 const defaultFilter = this.getSettings("filterValues.default"); 10143 if (!multipleSelectionActive || defaultFilter === selectedTermSlug) $filterButtons.attr("aria-pressed", false); 10144 $filterButtons.filter("[data-filter=\"" + selectedTermSlug + "\"]").attr("aria-pressed", true); 10145 const activeFiltersButtons = this.getCurrentlyActiveFilter(); 10146 if (activeFiltersButtons && activeFiltersButtons.includes(defaultFilter) && defaultFilter !== selectedTermSlug) this.deactivateDefaultFilterButton($filterButtons); 10147 } 10148 /** 10149 * 10150 * @param {string} clickedFilter 10151 */ 10152 deactivateFilterButton(clickedFilter) { 10153 const $filterButtons = this.getFilterButtonElements(); 10154 const multipleSelectionActive = "yes" === this.getElementSettings("multiple_selection"); 10155 if (!$filterButtons.length) return; 10156 const $activeButton = $filterButtons.filter("[data-filter=\"" + clickedFilter + "\"]"); 10157 const defaultFilter = this.getSettings("filterValues.default"); 10158 const currentlyActiveButtons = this.getCurrentlyActiveFilter(); 10159 const isActivateDefaultFilterButtonNeeded = !multipleSelectionActive || !currentlyActiveButtons.includes(defaultFilter) && 1 === currentlyActiveButtons.length; 10160 $activeButton.attr("aria-pressed", false); 10161 if (isActivateDefaultFilterButtonNeeded) this.activateDefaultFilterButton(); 10162 elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(this.getElementSettings("selected_element"), this.getID(), clickedFilter, defaultFilter); 10163 } 10164 activateDefaultFilterButton() { 10165 const $filterButtons = this.getFilterButtonElements(); 10166 const $defaultButton = $filterButtons.filter("[data-filter=\"" + this.getSettings("filterValues.default") + "\"]"); 10167 $filterButtons.attr("aria-pressed", false); 10168 $defaultButton.attr("aria-pressed", true); 10169 } 10170 deactivateDefaultFilterButton() { 10171 this.getFilterButtonElements().filter("[data-filter=\"" + this.getSettings("filterValues.default") + "\"]").attr("aria-pressed", false); 10172 } 10173 /** 10174 * Gets the currently active buttons independent of URL params. 10175 * @return {Array} Currently active filter(s). 10176 */ 10177 getCurrentlyActiveFilter() { 10178 const $activeFilterButtons = this.getActiveFilterButtonElements(); 10179 const currentlyActiveFilterButtons = []; 10180 for (let i = 0; i < $activeFilterButtons.length; i++) currentlyActiveFilterButtons.push($activeFilterButtons[i].dataset.filter); 10181 return currentlyActiveFilterButtons; 10182 } 10183 /** 10184 * Get the filter operator for WP_Query. OR is translated IN. 10185 * @return {string} 'IN' or 'AND' for WP_Query or DISABLED for single selection. 10186 */ 10187 getFilterOperator() { 10188 const elementSettings = this.getElementSettings(); 10189 if (!elementSettings.multiple_selection || !["AND", "OR"].includes(elementSettings.logical_combination)) return "DISABLED"; 10190 return elementSettings.logical_combination; 10191 } 10192 /** 10193 * 10194 * @param {string} selectedTermSlug - Slug of currently selected term relating to last clicked button 10195 */ 10196 filterItems(selectedTermSlug) { 10197 const elementSettings = this.getElementSettings();
10198 const defaultFilterValue = this.getSettings("filterValues.default"); 10199 if (defaultFilterValue === selectedTermSlug) { 10200 elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(elementSettings.selected_element, this.getID(), selectedTermSlug, defaultFilterValue); 10201 return; 10202 } 10203 const multipleSelectionLogicalJoin = this.getFilterOperator(); 10204 elementorProFrontend.modules.taxonomyFilter.setFilterDataForLoopWidget(elementSettings.selected_element, this.getID(), { 10205 filterType: "taxonomy", 10206 filterData: { 10207 selectedTaxonomy: elementSettings.taxonomy, 10208 terms: [selectedTermSlug] 10209 } 10210 }, true, multipleSelectionLogicalJoin); 10211 } 10212 /** 10213 * 10214 * @param {string} filter 10215 */ 10216 setFilter(filter = this.getSettings("filterValues.default")) { 10217 this.filterItems(filter); 10218 this.activateFilterButton(filter); 10219 } 10220 onFilterButtonClick(event) { 10221 var _a; 10222 var _b; 10223 this.removePaginationHiddenClassOnLoopWidgetContainer(); 10224 const currentlyActiveFilterButtons = this.getCurrentlyActiveFilter(); 10225 const clickedFilter = (_b = (_a = event.currentTarget) == null ? void 0 : _a.dataset) == null ? void 0 : _b.filter; 10226 if (this.userClickedOnAllWhileItWasActive(clickedFilter, currentlyActiveFilterButtons)) return; 10227 if (currentlyActiveFilterButtons.includes(clickedFilter)) { 10228 this.deactivateFilterButton(clickedFilter); 10229 return; 10230 } 10231 this.setFilter(clickedFilter); 10232 } 10233 removePaginationHiddenClassOnLoopWidgetContainer() { 10234 const elementSettings = this.getElementSettings(); 10235 const loopWidget = document.querySelector(".elementor-element-" + elementSettings.selected_element); 10236 if (loopWidget) loopWidget.classList.remove("e-load-more-pagination-end"); 10237 } 10238 /** 10239 * 10240 * @param {string} clickedFilter 10241 * @param {Array} currentlyActiveFilter 10242 * @return {boolean} User clicked on all while it was active. 10243 */ 10244 userClickedOnAllWhileItWasActive(clickedFilter, currentlyActiveFilter) { 10245 return currentlyActiveFilter.includes(clickedFilter) && clickedFilter === this.getSettings("filterValues.default"); 10246 } 10247 onDestroy() { 10248 const selectedElementId = this.getElementSettings("selected_element"); 10249 const selectedTaxonomy = this.getElementSettings("taxonomy"); 10250 const filterId = this.getID(); 10251 if (selectedElementId && selectedTaxonomy) elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(selectedElementId, filterId, ""); 10252 super.onDestroy(); 10253 } 10254 populateLoopWidgetsStoreOnInitialPageLoad() { 10255 const elementSettings = this.getElementSettings(); 10256 let selectedTermSlugs = new URLSearchParams(window.location.search).get("e-filter-" + elementSettings.selected_element + "-" + elementSettings.taxonomy); 10257 if (selectedTermSlugs) { 10258 selectedTermSlugs = this.getTermsFromParams(selectedTermSlugs); 10259 const multipleSelectionLogicalJoin = this.getFilterOperator(); 10260 elementorProFrontend.modules.taxonomyFilter.setFilterDataForLoopWidget(elementSettings.selected_element, this.getID(), { 10261 filterType: "taxonomy", 10262 filterData: { 10263 selectedTaxonomy: elementSettings.taxonomy, 10264 terms: selectedTermSlugs 10265 } 10266 }, false, multipleSelectionLogicalJoin); 10267 } 10268 } 10269 getTermsFromParams(params) { 10270 let separator = import_query_constants.queryConstants.AND.separator.fromBrowser; 10271 if (params.includes(import_query_constants.queryConstants.OR.separator.fromBrowser)) separator = import_query_constants.queryConstants.OR.separator.fromBrowser; 10272 return params.split(separator); 10273 } 10274 onInit() { 10275 super.onInit(); 10276 this.populateLoopWidgetsStoreOnInitialPageLoad(); 10277 setHorizontalScrollAlignment({ 10278 element: this.elements.$container[0], 10279 direction: this.getItemsAlignment(), 10280 justifyCSSVariable: "--e-filter-justify-content", 10281 horizontalScrollStatus: this.getHorizontalScrollSetting() 10282 }); 10283 } 10284 getHorizontalScrollSetting() { 10285 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 10286 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), "horizontal_scroll", "", currentDevice); 10287 } 10288 getItemsAlignment() { 10289 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 10290 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), "item_alignment_horizontal", "", currentDevice); 10291 } 10292 }; 10293 })); 10294 //#endregion 10295 //#region modules/loop-filter/assets/js/frontend/frontend.js 10296 var LoopFilter = class extends BaseFilterFrontendModule { 10297 constructor() { 10298 super(); 10299 elementorFrontend.elementsHandler.attachHandler("taxonomy-filter", () => __vitePreload(() => Promise.resolve().then(() =>
10299 (init_taxonomy_filter(), taxonomy_filter_exports)), void 0)); 10300 } 10301 }; 10302 //#endregion 10303 //#region modules/off-canvas/assets/js/frontend/handlers/off-canvas.js 10304 var off_canvas_exports = /* @__PURE__ */ __exportAll({ default: () => OffCanvas }); 10305 var OffCanvas; 10306 var init_off_canvas = __esmMin((() => { 10307 init_modal_keyboard_handler(); 10308 init_run_element_handlers(); 10309 init_defineProperty(); 10310 OffCanvas = class extends elementorModules.frontend.handlers.Base { 10311 constructor(..._args) { 10312 super(..._args); 10313 _defineProperty(this, "keyboardHandler", null); 10314 _defineProperty(this, "isOffCanvasOpenedOnce", false); 10315 } 10316 getDefaultSettings() { 10317 return { selectors: { 10318 wrapper: ".e-off-canvas", 10319 overlay: ".e-off-canvas__overlay", 10320 main: ".e-off-canvas__main", 10321 content: ".e-off-canvas__content", 10322 body: "body" 10323 } }; 10324 } 10325 getDefaultElements() { 10326 const settings = this.getSettings(); 10327 return { 10328 $wrapper: this.$element.find(settings.selectors.wrapper), 10329 $overlay: this.$element.find(settings.selectors.overlay), 10330 $main: this.$element.find(settings.selectors.main), 10331 $content: this.$element.find(settings.selectors.content), 10332 $body: jQuery(settings.selectors.body) 10333 }; 10334 } 10335 onInit() { 10336 super.onInit(); 10337 this.initAriaAttributesToTriggerElements(); 10338 if (this.isEditingMode()) this.maybeDisableScroll(); 10339 else this.addClassToPreviousSiblingInsideASection(); 10340 } 10341 onDestroy() { 10342 super.onDestroy(); 10343 this.enableScroll(); 10344 } 10345 bindEvents() { 10346 this.elements.$overlay.on("click", (event) => { 10347 event.preventDefault(); 10348 this.onClickOverlay(event); 10349 }); 10350 elementorFrontend.elements.$window.on("keydown", this.onCanvasKeyDown.bind(this)); 10351 this.elements.$main.on("animationend animationcancel", this.removeAnimationClasses.bind(this)); 10352 elementorFrontend.elements.$window.on("elementor-pro/off-canvas/toggle-display-mode", this.handleDisplayToggle.bind(this)); 10353 } 10354 unbindEvents() { 10355 this.elements.$overlay.off(); 10356 this.elements.$main.off(); 10357 elementorFrontend.elements.$window.off("keydown", this.onCanvasKeyDown); 10358 elementorFrontend.elements.$window.off("elementor-pro/off-canvas/toggle-display-mode"); 10359 } 10360 handleDisplayToggle(event) { 10361 var _event$originalEvent; 10362 if (event.originalEvent.detail.id !== this.getWidgetId()) return; 10363 const displayMode = event.originalEvent.detail.displayMode; 10364 const currentDisplayMode = this.isVisible() ? "open" : "close"; 10365 const isKeyboardEvent = "" === (event === null || event === void 0 || (_event$originalEvent = event.originalEvent) === null || _event$originalEvent === void 0 || (_event$originalEvent = _event$originalEvent.detail) === null || _event$originalEvent === void 0 || (_event$originalEvent = _event$originalEvent.previousEvent) === null || _event$originalEvent === void 0 ? void 0 : _event$originalEvent.pointerType); 10366 if ("open" === displayMode) this.openOffCanvas(isKeyboardEvent); 10367 else if ("close" === displayMode) this.closeOffCanvas(); 10368 else if ("toggle" === displayMode) this["open" === currentDisplayMode ? "closeOffCanvas" : "openOffCanvas"](isKeyboardEvent); 10369 } 10370 openOffCanvas(isKeyboardEvent = false) { 10371 if (this.isVisible() || this.isInsideCarousel()) return; 10372 this.elements.$wrapper.attr("aria-hidden", "false"); 10373 this.elements.$wrapper.removeAttr("inert"); 10374 this.elements.$wrapper.removeAttr("data-delay-child-handlers"); 10375 this.updateAriaExpandedOfTriggerElements("true"); 10376 this.toggleDraggable(false); 10377 this.maybeOnOpenAnimation(); 10378 this.maybeDisableScroll(); 10379 this.handleElementHandlers(); 10380 if (isKeyboardEvent) this.handleKeyboardA11y(); 10381 } 10382 handleKeyboardA11y() { 10383 this.initKeyboardHandler(); 10384 this.keyboardHandler.onOpenModal(); 10385 } 10386 closeOffCanvas() { 10387 if (!this.isVisible()) return; 10388 this.maybeOnCloseAnimation(); 10389 this.elements.$wrapper.attr("aria-hidden", "true"); 10390 this.elements.$wrapper.attr("inert", ""); 10391 this.updateAriaExpandedOfTriggerElements("false"); 10392 this.toggleDraggable(true); 10393 this.enableScroll(); 10394 } 10395 onCanvasKeyDown(event) { 10396 if ("Escape" !== event.key || "yes" === this.getElementSettings("is_not_close_on_esc_overlay")) return; 10397 this.closeOffCanvas(); 10398 } 10399 onClickOverlay() { 10400 if ("yes" === this.getElementSettings().is_not_close_on_overlay || this.isEditingMode()) return; 10401 this.closeOffCanvas(); 10402 } 10403 maybeOnOpenAnimation() { 10404 const openAnimationClass = this.getResponsiveSetting("entrance_animation") || "none"; 10405 if ("none" === openAnimationClass) this.elements.$wrapper.addClass("no-animation"); 10406 else this.elements.$wrapper.removeClass("no-animation"); 10407 this.elements.$main.addClass(`animated ${openAnimationClass}`); 10408 this.elements.$wrapper.removeClass("animated-reverse-wrapper"); 10409 } 10410 maybeOnCloseAnimation() { 10411 const exitAnimationClass = this.getResponsiveSetting("exit_animation") || "none"; 10412 if ("none" === exitAnimationClass) this.elements.$wrapper.addClass("no-animation"); 10413 else this.elements.$wrapper.removeClass("no-animation"); 10414 this.elements.$main.addClass(`animated reverse ${exitAnimationClass}`); 10415 this.elements.$wrapper.addClass("animated-reverse-wrapper"); 10416 this.elements.$body.addClass("e-off-canvas__no-scroll-animation"); 10417 } 10418 removeAnimationClasses() { 10419 const isExitAnimation = this.elements.$main.hasClass("reverse"); 10420 const openAnimationClass = this.getResponsiveSetting("entrance_animation") || "none"; 10421 const exitAnimationClass = this.getResponsiveSetting("exit_animation") || "none"; 10422 if (isExitAnimation) { 10423 var _this$keyboardHandler; 10424 this.elements.$main.removeClass(`animated reverse ${exitAnimationClass}`); 10425 this.elements.$wrapper.removeClass("animated-reverse-wrapper"); 10426 this.elements.$body.removeClass("e-off-canvas__no-scroll-animation"); 10427 (_this$keyboardHandler = this.keyboardHandler) === null || _this$keyboardHandler === void 0 || _this$keyboardHandler.onCloseModal(); 10428 } else this.elements.$main.removeClass(`animated ${openAnimationClass}`); 10429 } 10430 getResponsiveSetting(controlName) { 10431 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 10432 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), controlName, "",
10432currentDevice); 10433 } 10434 isEditingMode() { 10435 return "yes" === this.getElementSettings("editing_mode") && elementorFrontend.isEditMode(); 10436 } 10437 maybeDisableScroll() { 10438 if ("yes" === this.getElementSettings("prevent_scroll")) this.elements.$body.addClass("e-off-canvas__no-scroll"); 10439 } 10440 enableScroll() { 10441 this.elements.$body.removeClass("e-off-canvas__no-scroll"); 10442 } 10443 toggleDraggable(value) { 10444 if (elementorFrontend.isEditMode() && "0" !== this.elements.$overlay.css("opacity")) this.$element.attr("draggable", value); 10445 } 10446 handleEditingModeToggle() { 10447 if ("yes" === this.getElementSettings("editing_mode")) this.openOffCanvas(); 10448 else this.closeOffCanvas(); 10449 } 10450 getKeyboardHandlingConfig() { 10451 return { 10452 $modalElements: this.elements.$wrapper, 10453 $elementWrapper: this.elements.$content, 10454 modalType: "off-canvas", 10455 modalId: this.getID() 10456 }; 10457 } 10458 initAriaAttributesToTriggerElements() { 10459 this.getTriggerElements().forEach((triggerElement) => { 10460 triggerElement.setAttribute("aria-controls", `off-canvas-${this.getID()}`); 10461 triggerElement.setAttribute("aria-expanded", "false"); 10462 }); 10463 } 10464 getTriggerElements() { 10465 const links = elementorFrontend.elements.window.document.body.querySelectorAll("a"); 10466 const unfilteredTriggerElements = Array.from(links).filter((link) => { 10467 var _link$href; 10468 return (_link$href = link.href) === null || _link$href === void 0 ? void 0 : _link$href.includes("elementor-action"); 10469 }); 10470 const matchingTriggerElements = []; 10471 unfilteredTriggerElements.forEach((triggerElement) => { 10472 if (!this.isActionUrlIdEqualToWidgetId(triggerElement.href)) return false; 10473 matchingTriggerElements.push(triggerElement); 10474 }); 10475 return matchingTriggerElements; 10476 } 10477 updateAriaExpandedOfTriggerElements(isExpanded) { 10478 elementorFrontend.elements.window.document.body.querySelectorAll(`[aria-controls="off-canvas-${this.getID()}"]`).forEach((triggerElement) => { 10479 triggerElement.setAttribute("aria-expanded", isExpanded); 10480 }); 10481 } 10482 isActionUrlIdEqualToWidgetId(encodedUrl) { 10483 const url = decodeURIComponent(encodedUrl); 10484 let settings = {}; 10485 const settingsMatch = url.match(/settings=(.+)/); 10486 if (settingsMatch) settings = JSON.parse(atob(settingsMatch[1])); 10487 return this.getID() === (settings === null || settings === void 0 ? void 0 : settings.id); 10488 } 10489 isVisible() { 10490 return "false" === this.elements.$wrapper.attr("aria-hidden"); 10491 } 10492 maybeDragWidgetsBeneathOverlay() { 10493 this.elements.$overlay.toggleClass("no-pointer-events"); 10494 } 10495 onElementChange(propertyName) { 10496 if ("editing_mode" === propertyName) this.handleEditingModeToggle(); 10497 if ("has_overlay" === propertyName) this.maybeDragWidgetsBeneathOverlay("has_overlay"); 10498 } 10499 handleElementHandlers() { 10500 if (this.isOffCanvasOpenedOnce) return; 10501 runElementHandlers(this.elements.$main[0].querySelectorAll(".e-off-canvas__content")); 10502 this.isOffCanvasOpenedOnce = true; 10503 } 10504 initKeyboardHandler() { 10505 if (!this.keyboardHandler) this.keyboardHandler = new ModalKeyboardHandler(this.getKeyboardHandlingConfig()); 10506 } 10507 addClassToPreviousSiblingInsideASection() { 10508 if (!this.$element[0].closest(".elementor-section")) return; 10509 const previousElement = this.$element[0].previousElementSibling; 10510 previousElement === null || previousElement === void 0 || previousElement.classList.add("e-element-before-off-canvas"); 10511 } 10512 getWidgetId() { 10513 if (!(this.$element.closest(".e-loop-item").length > 0)) return this.getID().toString(); 10514 const id = this.elements.$wrapper.attr("id"); 10515 return id ? id.replace("off-canvas-", "") : this.getID().toString(); 10516 } 10517 isInsideCarousel() { 10518 return this.$element.closest(".swiper-wrapper").length > 0; 10519 } 10520 }; 10521 })); 10522 //#endregion 10523 //#region modules/off-canvas/assets/js/frontend/frontend.js 10524 var frontend_default$2 = class extends elementorModules.Module { 10525 static { 10526 __name(this, "default"); 10527 } 10528 constructor() { 10529 super(); 10530 elementorFrontend.elementsHandler.attachHandler("off-canvas", () => __vitePreload(() => Promise.resolve().then(() => (init_off_canvas(), off_canvas_exports)), void 0)); 10531 elementorFrontend.on("components:init", () => this.onFrontendComponentsInit()); 10532 } 10533 onFrontendComponentsInit() { 10534 this.addUrlActions(); 10535 } 10536 addUrlActions() { 10537 elementorFrontend.utils.urlActions.addAction("off_canvas:open", (settings) => { 10538 this.toggleOffCanvasDisplay(settings); 10539 }); 10540 elementorFrontend.utils.urlActions.addAction("off_canvas:close", (settings) => { 10541 this.toggleOffCanvasDisplay(settings); 10542 }); 10543 elementorFrontend.utils.urlActions.addAction("off_canvas:toggle", (settings) => { 10544 this.toggleOffCanvasDisplay(settings); 10545 }); 10546 } 10547 toggleOffCanvasDisplay(settings) { 10548 window.dispatchEvent(new CustomEvent("elementor-pro/off-canvas/toggle-display-mode", { detail: settings })); 10549 } 10550 }; 10551 //#endregion 10552 //#region ../elementor/assets/dev/js/frontend/handlers/base.js 10553 var require_base = /* @__PURE__ */ __commonJSMin(((exports, module) => { 10554 module.exports = elementorModules.ViewModule.extend({ 10555 $element: null, 10556 editorListeners: null, 10557 onElementChange: null, 10558 onEditSettingsChange: null, 10559 onPageSettingsChange: null, 10560 isEdit: null, 10561 __construct(settings) { 10562 if (!this.isActive(settings)) return; 10563 this.$element = settings.$element; 10564 this.isEdit = this.$element.hasClass("elementor-element-edit-mode"); 10565 if (this.isEdit) this.addEditorListeners(); 10566 }, 10567 isActive() { 10568 return true; 10569 }, 10570 isElementInTheCurrentDocument() { 10571 if (!elementorFrontend.isEditMode()) return false;
10572 return elementor.documents.currentDocument.id.toString() === this.$element[0].closest(".elementor").dataset.elementorId; 10573 }, 10574 findElement(selector) { 10575 var $mainElement = this.$element; 10576 return $mainElement.find(selector).filter(function() { 10577 return jQuery(this).parent().closest(".elementor-element").is($mainElement); 10578 }); 10579 }, 10580 getUniqueHandlerID(cid, $element) { 10581 if (!cid) cid = this.getModelCID(); 10582 if (!$element) $element = this.$element; 10583 return cid + $element.attr("data-element_type") + this.getConstructorID(); 10584 }, 10585 initEditorListeners() { 10586 var self = this; 10587 self.editorListeners = [{ 10588 event: "element:destroy", 10589 to: elementor.channels.data, 10590 callback(removedModel) { 10591 if (removedModel.cid !== self.getModelCID()) return; 10592 self.onDestroy(); 10593 } 10594 }]; 10595 if (self.onElementChange) { 10596 const elementType = self.getWidgetType() || self.getElementType(); 10597 let eventName = "change"; 10598 if ("global" !== elementType) eventName += ":" + elementType; 10599 self.editorListeners.push({ 10600 event: eventName, 10601 to: elementor.channels.editor, 10602 callback(controlView, elementView) { 10603 if (self.getUniqueHandlerID(elementView.model.cid, elementView.$el) !== self.getUniqueHandlerID()) return; 10604 self.onElementChange(controlView.model.get("name"), controlView, elementView); 10605 } 10606 }); 10607 } 10608 if (self.onEditSettingsChange) self.editorListeners.push({ 10609 event: "change:editSettings", 10610 to: elementor.channels.editor, 10611 callback(changedModel, view) { 10612 if (view.model.cid !== self.getModelCID()) return; 10613 const propName = Object.keys(changedModel.changed)[0]; 10614 self.onEditSettingsChange(propName, changedModel.changed[propName]); 10615 } 10616 }); 10617 ["page"].forEach(function(settingsType) { 10618 var listenerMethodName = "on" + settingsType[0].toUpperCase() + settingsType.slice(1) + "SettingsChange"; 10619 if (self[listenerMethodName]) self.editorListeners.push({ 10620 event: "change", 10621 to: elementor.settings[settingsType].model, 10622 callback(model) { 10623 self[listenerMethodName](model.changed); 10624 } 10625 }); 10626 }); 10627 }, 10628 getEditorListeners() { 10629 if (!this.editorListeners) this.initEditorListeners(); 10630 return this.editorListeners; 10631 }, 10632 addEditorListeners() { 10633 var uniqueHandlerID = this.getUniqueHandlerID(); 10634 this.getEditorListeners().forEach(function(listener) { 10635 elementorFrontend.addListenerOnce(uniqueHandlerID, listener.event, listener.callback, listener.to); 10636 }); 10637 }, 10638 removeEditorListeners() { 10639 var uniqueHandlerID = this.getUniqueHandlerID(); 10640 this.getEditorListeners().forEach(function(listener) { 10641 elementorFrontend.removeListeners(uniqueHandlerID, listener.event, null, listener.to); 10642 }); 10643 }, 10644 getElementType() { 10645 return this.$element.data("element_type"); 10646 }, 10647 getWidgetType() { 10648 const widgetType = this.$element.data("widget_type"); 10649 if (!widgetType) return; 10650 return widgetType.split(".")[0]; 10651 }, 10652 getID() { 10653 return this.$element.data("id"); 10654 }, 10655 getModelCID() { 10656 return this.$element.data("model-cid"); 10657 }, 10658 getElementSettings(setting) { 10659 let elementSettings = {}; 10660 const modelCID = this.getModelCID(); 10661 if (this.isEdit && modelCID) { 10662 const settings = elementorFrontend.config.elements.data[modelCID]; 10663 const attributes = settings.attributes; 10664 let type = attributes.widgetType || attributes.elType; 10665 if (attributes.isInner) type = "inner-" + type; 10666 let settingsKeys = elementorFrontend.config.elements.keys[type]; 10667 if (!settingsKeys) { 10668 settingsKeys = elementorFrontend.config.elements.keys[type] = []; 10669 jQuery.each(settings.controls, (name, control) => { 10670 if (control.frontend_available || control.editor_available) settingsKeys.push(name); 10671 }); 10672 } 10673 jQuery.each(settings.getActiveControls(), function(controlKey) { 10674 if (-1 !== settingsKeys.indexOf(controlKey)) { 10675 let value = attributes[controlKey]; 10676 if (value.toJSON) value = value.toJSON(); 10677 elementSettings[controlKey] = value; 10678 } 10679 }); 10680 } else elementSettings = this.$element.data("settings") || {}; 10681 return this.getItems(elementSettings, setting); 10682 }, 10683 getEditSettings(setting) { 10684 var attributes = {}; 10685 if (this.isEdit) attributes = elementorFrontend.config.elements.editSettings[this.getModelCID()].attributes; 10686 return this.getItems(attributes, setting); 10687 }, 10688 getCurrentDeviceSetting(settingKey) { 10689 return elementorFrontend.getCurrentDeviceSetting(this.getElementSettings(), settingKey); 10690 }, 10691 onInit() { 10692 if (this.isActive(this.getSettings())) elementorModules.ViewModule.prototype.onInit.apply(this, arguments); 10693 }, 10694 onDestroy() { 10695 if (this.isEdit) this.removeEditorListeners(); 10696 if (this.unbindEvents) this.unbindEvents(); 10697 } 10698 }); 10699 })); 10700 //#endregion 10701 //#region modules/floating-buttons/assets/js/shared/frontend/handlers/click-tracking.js 10702 var import_base$4, ClickTrackingHandler; 10703 var init_click_tracking = __esmMin((() => { 10704 import_base$4 = /* @__PURE__ */ __toESM(require_base()); 10705 init_defineProperty(); 10706 ClickTrackingHandler = class extends import_base$4.default {
10707 constructor(..._args) { 10708 super(..._args); 10709 _defineProperty(this, "clicks", []); 10710 } 10711 getDefaultSettings() { 10712 return { selectors: { 10713 contentWrapper: ".e-contact-buttons__content-wrapper", 10714 contentWrapperFloatingBars: ".e-floating-bars", 10715 floatingBarCouponButton: ".e-floating-bars__coupon-button", 10716 floatingBarsHeadline: ".e-floating-bars__headline", 10717 contactButtonsVar4: ".e-contact-buttons__contact-icon-link", 10718 contactButtonsVar5: ".e-contact-buttons__chat-button", 10719 contactButtonsVar6: ".e-contact-buttons-var-6", 10720 contactButtonsVar8: ".e-contact-buttons-var-8", 10721 elementorWrapper: "[data-elementor-type=\"floating-buttons\"]", 10722 contactButtonCore: ".e-contact-buttons__send-button" 10723 } }; 10724 } 10725 getDefaultElements() { 10726 const selectors = this.getSettings("selectors"); 10727 return { 10728 contentWrapper: this.$element[0].querySelector(selectors.contentWrapper), 10729 contentWrapperFloatingBars: this.$element[0].querySelector(selectors.contentWrapperFloatingBars), 10730 contactButtonsVar5: this.$element[0].querySelector(selectors.contactButtonsVar5), 10731 contactButtonsVar6: this.$element[0].querySelector(selectors.contactButtonsVar6) 10732 }; 10733 } 10734 bindEvents() { 10735 if (this.elements.contentWrapper) this.elements.contentWrapper.addEventListener("click", this.onChatButtonTrackClick.bind(this)); 10736 if (this.elements.contactButtonsVar5) this.elements.contactButtonsVar5.addEventListener("click", this.onChatButtonTrackClick.bind(this)); 10737 if (this.elements.contactButtonsVar6) this.elements.contactButtonsVar6.addEventListener("click", this.onChatButtonTrackClick.bind(this)); 10738 if (this.elements.contentWrapperFloatingBars) this.elements.contentWrapperFloatingBars.addEventListener("click", this.onChatButtonTrackClick.bind(this)); 10739 window.addEventListener("beforeunload", () => { 10740 if (this.clicks.length > 0) this.sendClicks(); 10741 }); 10742 } 10743 onChatButtonTrackClick(event) { 10744 const targetElement = event.target || event.srcElement; 10745 const selectors = this.getSettings("selectors"); 10746 const buttonSelectors = [ 10747 selectors.contactButtonsVar4, 10748 selectors.contactButtonsVar6, 10749 selectors.floatingBarCouponButton, 10750 selectors.floatingBarsHeadline, 10751 selectors.contactButtonCore 10752 ]; 10753 for (const selector of buttonSelectors) if (targetElement.matches(selector) || targetElement.closest(selector)) this.getDocumentIdAndTrack(targetElement, selectors); 10754 if ((targetElement.matches(selectors.contactButtonsVar5) || targetElement.closest(selectors.contactButtonsVar5)) && targetElement.closest(".e-contact-buttons-var-5")) this.getDocumentIdAndTrack(targetElement, selectors); 10755 } 10756 getDocumentIdAndTrack(targetElement, selectors) { 10757 const documentId = targetElement.closest(selectors.elementorWrapper).dataset.elementorId; 10758 this.trackClick(documentId); 10759 } 10760 trackClick(documentId) { 10761 if (!documentId) return; 10762 this.clicks.push(documentId); 10763 if (this.clicks.length >= 10) this.sendClicks(); 10764 } 10765 sendClicks() { 10766 var _elementorFrontendCon; 10767 var _elementorFrontendCon2; 10768 const formData = new FormData(); 10769 formData.append("action", "elementor_send_clicks"); 10770 formData.append("_nonce", (_elementorFrontendCon = elementorFrontendConfig) === null || _elementorFrontendCon === void 0 || (_elementorFrontendCon = _elementorFrontendCon.nonces) === null || _elementorFrontendCon === void 0 ? void 0 : _elementorFrontendCon.floatingButtonsClickTracking); 10771 this.clicks.forEach((documentId) => formData.append("clicks[]", documentId)); 10772 fetch((_elementorFrontendCon2 = elementorFrontendConfig) === null || _elementorFrontendCon2 === void 0 || (_elementorFrontendCon2 = _elementorFrontendCon2.urls) === null || _elementorFrontendCon2 === void 0 ? void 0 : _elementorFrontendCon2.ajaxurl, { 10773 method: "POST", 10774 body: formData 10775 }).then(() => { 10776 this.clicks = []; 10777 }); 10778 } 10779 }; 10780 })); 10781 //#endregion 10782 //#region modules/floating-buttons/assets/js/frontend/handlers/contact-buttons.js 10783 var contact_buttons_exports = /* @__PURE__ */ __exportAll({ default: () => ContactButtonsHandler }); 10784 var import_base$3, ContactButtonsHandler; 10785 var init_contact_buttons = __esmMin((() => { 10786 import_base$3 = /* @__PURE__ */ __toESM(require_base()); 10787 init_click_tracking(); 10788 init_defineProperty(); 10789 ContactButtonsHandler = class extends import_base$3.default {
10790 constructor(..._args) { 10791 super(..._args); 10792 _defineProperty(this, "clicks", []); 10793 } 10794 getDefaultSettings() { 10795 return { 10796 selectors: { 10797 main: ".e-contact-buttons", 10798 content: ".e-contact-buttons__content", 10799 contentWrapper: ".e-contact-buttons__content-wrapper", 10800 chatButton: ".e-contact-buttons__chat-button", 10801 closeButton: ".e-contact-buttons__close-button", 10802 messageBubbleTime: ".e-contact-buttons__message-bubble-time" 10803 }, 10804 constants: { 10805 entranceAnimation: "style_chat_box_entrance_animation", 10806 exitAnimation: "style_chat_box_exit_animation", 10807 chatButtonAnimation: "style_chat_button_animation", 10808 animated: "animated", 10809 animatedWrapper: "animated-wrapper", 10810 visible: "visible", 10811 reverse: "reverse", 10812 hidden: "hidden", 10813 hasAnimations: "has-animations", 10814 hasEntranceAnimation: "has-entrance-animation", 10815 none: "none" 10816 } 10817 }; 10818 } 10819 getDefaultElements() { 10820 const selectors = this.getSettings("selectors"); 10821 return { 10822 main: this.$element[0].querySelector(selectors.main), 10823 content: this.$element[0].querySelector(selectors.content), 10824 contentWrapper: this.$element[0].querySelector(selectors.contentWrapper), 10825 chatButton: this.$element[0].querySelector(selectors.chatButton), 10826 closeButton: this.$element[0].querySelector(selectors.closeButton), 10827 messageBubbleTime: this.$element[0].querySelector(selectors.messageBubbleTime) 10828 }; 10829 } 10830 getResponsiveSetting(controlName) { 10831 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 10832 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), controlName, "", currentDevice); 10833 } 10834 bindEvents() { 10835 if (this.elements.closeButton) this.elements.closeButton.addEventListener("click", this.closeChatBox.bind(this)); 10836 if (this.elements.chatButton) { 10837 this.elements.chatButton.addEventListener("click", this.onChatButtonClick.bind(this)); 10838 this.elements.chatButton.addEventListener("animationend", this.removeChatButtonAnimationClasses.bind(this)); 10839 } 10840 if (this.elements.content) this.elements.content.addEventListener("animationend", this.removeAnimationClasses.bind(this)); 10841 if (this.elements.contentWrapper) window.addEventListener("keyup", this.onDocumentKeyup.bind(this)); 10842 } 10843 contentWrapperIsHidden(hide) { 10844 if (!this.elements.contentWrapper) return false; 10845 const { hidden } = this.getSettings("constants"); 10846 if (true === hide) { 10847 this.elements.contentWrapper.classList.add(hidden); 10848 this.elements.contentWrapper.setAttribute("aria-hidden", "true"); 10849 return; 10850 } 10851 if (false === hide) { 10852 this.elements.contentWrapper.classList.remove(hidden); 10853 this.elements.contentWrapper.setAttribute("aria-hidden", "false"); 10854 return; 10855 } 10856 return this.elements.contentWrapper.classList.contains(hidden); 10857 } 10858 onDocumentKeyup(event) { 10859 if (event.keyCode !== 27 || !this.elements.main) return; 10860 if (!this.contentWrapperIsHidden() && this.elements.main.contains(document.activeElement)) this.closeChatBox(); 10861 } 10862 onChatButtonTrackClick(event) { 10863 const targetElement = event.target || event.srcElement; 10864 const selectors = this.getSettings("selectors"); 10865 const buttonSelectors = [ 10866 selectors.contactButtonsVar4, 10867 selectors.contactButtonsVar6, 10868 selectors.contactButtonCore 10869 ]; 10870 for (const selector of buttonSelectors) if (targetElement.matches(selector) || targetElement.closest(selector)) this.getDocumentIdAndTrack(targetElement, selectors); 10871 if ((targetElement.matches(selectors.contactButtonsVar5) || targetElement.closest(selectors.contactButtonsVar5)) && targetElement.closest(".e-contact-buttons-var-5")) this.getDocumentIdAndTrack(targetElement, selectors); 10872 } 10873 getDocumentIdAndTrack(targetElement, selectors) { 10874 let documentId = targetElement.closest(selectors.main).dataset.documentId; 10875 if (!documentId) documentId = targetElement.closest(selectors.elementorWrapper).dataset.elementorId; 10876 this.trackClick(documentId); 10877 } 10878 trackClick(documentId) { 10879 if (!documentId) return; 10880 this.clicks.push(documentId); 10881 if (this.clicks.length >= 10) this.sendClicks(); 10882 } 10883 sendClicks() { 10884 var _elementorFrontendCon; 10885 var _elementorFrontendCon2; 10886 const formData = new FormData(); 10887 formData.append("action", "elementor_send_clicks"); 10888 formData.append("_nonce", (_elementorFrontendCon = elementorFrontendConfig) === null || _elementorFrontendCon === void 0 || (_elementorFrontendCon = _elementorFrontendCon.nonces) === null || _elementorFrontendCon === void 0 ? void 0 : _elementorFrontendCon.floatingButtonsClickTracking); 10889 this.clicks.forEach((documentId) => formData.append("clicks[]", documentId)); 10890 fetch((_elementorFrontendCon2 = elementorFrontendConfig) === null || _elementorFrontendCon2 === void 0 || (_elementorFrontendCon2 = _elementorFrontendCon2.urls) === null || _elementorFrontendCon2 === void 0 ? void 0 : _elementorFrontendCon2.ajaxurl, { 10891 method: "POST", 10892 body: formData 10893 }).then(() => { 10894 this.clicks = []; 10895 }); 10896 } 10897 removeAnimationClasses() { 10898 if (!this.elements.content) return; 10899 const { reverse, entranceAnimation, exitAnimation, animated, visible }
10899 = this.getSettings("constants"); 10900 const isExitAnimation = this.elements.content.classList.contains(reverse); 10901 const openAnimationClass = this.getResponsiveSetting(entranceAnimation); 10902 const exitAnimationClass = this.getResponsiveSetting(exitAnimation); 10903 if (isExitAnimation) { 10904 this.elements.content.classList.remove(animated); 10905 this.elements.content.classList.remove(reverse); 10906 if (exitAnimationClass) this.elements.content.classList.remove(exitAnimationClass); 10907 this.elements.content.classList.remove(visible); 10908 } else { 10909 this.elements.content.classList.remove(animated); 10910 if (openAnimationClass) this.elements.content.classList.remove(openAnimationClass); 10911 this.elements.content.classList.add(visible); 10912 } 10913 } 10914 chatBoxEntranceAnimation() { 10915 const { entranceAnimation, animated, animatedWrapper, none } = this.getSettings("constants"); 10916 const entranceAnimationControl = this.getResponsiveSetting(entranceAnimation); 10917 if (!entranceAnimationControl || none === entranceAnimationControl) return; 10918 if (this.elements.content) { 10919 this.elements.content.classList.add(animated); 10920 this.elements.content.classList.add(entranceAnimationControl); 10921 } 10922 if (this.elements.contentWrapper) this.elements.contentWrapper.classList.remove(animatedWrapper); 10923 } 10924 chatBoxExitAnimation() { 10925 const { reverse, exitAnimation, animated, animatedWrapper, none } = this.getSettings("constants"); 10926 const exitAnimationControl = this.getResponsiveSetting(exitAnimation); 10927 if (!exitAnimationControl || none === exitAnimationControl) return; 10928 if (this.elements.content) { 10929 this.elements.content.classList.add(animated); 10930 this.elements.content.classList.add(reverse); 10931 this.elements.content.classList.add(exitAnimationControl); 10932 } 10933 if (this.elements.contentWrapper) this.elements.contentWrapper.classList.add(animatedWrapper); 10934 } 10935 openChatBox() { 10936 const { hasAnimations, visible } = this.getSettings("constants"); 10937 if (this.elements.main && this.elements.main.classList.contains(hasAnimations)) this.chatBoxEntranceAnimation(); 10938 else if (this.elements.content) this.elements.content.classList.add(visible); 10939 if (this.elements.contentWrapper) { 10940 this.contentWrapperIsHidden(false); 10941 if (!elementorFrontend.isEditMode()) { 10942 this.elements.contentWrapper.setAttribute("tabindex", "0"); 10943 this.elements.contentWrapper.focus({ focusVisible: true }); 10944 } 10945 } 10946 if (this.elements.chatButton) this.elements.chatButton.setAttribute("aria-expanded", "true"); 10947 if (this.elements.closeButton) this.elements.closeButton.setAttribute("aria-expanded", "true"); 10948 } 10949 closeChatBox() { 10950 const { hasAnimations, visible } = this.getSettings("constants"); 10951 if (this.elements.main && this.elements.main.classList.contains(hasAnimations)) this.chatBoxExitAnimation(); 10952 else if (this.elements.content) this.elements.content.classList.remove(visible); 10953 if (this.elements.contentWrapper) this.contentWrapperIsHidden(true); 10954 if (this.elements.chatButton) { 10955 this.elements.chatButton.setAttribute("aria-expanded", "false"); 10956 this.elements.chatButton.focus({ focusVisible: true }); 10957 } 10958 if (this.elements.closeButton) this.elements.closeButton.setAttribute("aria-expanded", "false"); 10959 } 10960 onChatButtonClick() { 10961 if (this.elements.contentWrapper && this.contentWrapperIsHidden()) this.openChatBox(); 10962 else this.closeChatBox(); 10963 } 10964 initMessageBubbleTime() { 10965 if (!this.elements.messageBubbleTime) return; 10966 const is12hFormat = "12h" === this.elements.messageBubbleTime.dataset.timeFormat; 10967 const time = new Intl.DateTimeFormat("default", { 10968 hour12: is12hFormat, 10969 hour: "numeric", 10970 minute: "numeric" 10971 }).format(/* @__PURE__ */ new Date()); 10972 this.elements.messageBubbleTime.innerHTML = time; 10973 } 10974 removeChatButtonAnimationClasses() { 10975 if (!this.elements.chatButton) return; 10976 const { chatButtonAnimation, visible } = this.getSettings("constants"); 10977 this.elements.chatButton.classList.remove(chatButtonAnimation); 10978 this.elements.chatButton.classList.add(visible); 10979 } 10980 initChatButtonEntranceAnimation() { 10981 const { none, chatButtonAnimation }
10981 = this.getSettings("constants"); 10982 const entranceAnimationControl = this.getResponsiveSetting(chatButtonAnimation); 10983 if (!entranceAnimationControl || none === entranceAnimationControl) return; 10984 this.elements.chatButton.classList.add(entranceAnimationControl); 10985 } 10986 initDefaultState() { 10987 var _elementor; 10988 if (this.elements.contentWrapper) { 10989 const isHidden = this.contentWrapperIsHidden(); 10990 if (this.elements.chatButton) this.elements.chatButton.setAttribute("aria-expanded", !isHidden); 10991 if (this.elements.closeButton) this.elements.closeButton.setAttribute("aria-expanded", !isHidden); 10992 } 10993 if (elementorFrontend.isEditMode() && "floating-buttons" === ((_elementor = elementor) === null || _elementor === void 0 || (_elementor = _elementor.config) === null || _elementor === void 0 || (_elementor = _elementor.document) === null || _elementor === void 0 ? void 0 : _elementor.type)) this.openChatBox(); 10994 } 10995 setupInnerContainer() { 10996 this.elements.main.closest(".e-con-inner").classList.add("e-con-inner--floating-buttons"); 10997 } 10998 onInit(...args) { 10999 const { hasEntranceAnimation } = this.getSettings("constants"); 11000 super.onInit(...args); 11001 this.clickTrackingHandler = new ClickTrackingHandler({ $element: this.$element }); 11002 if (this.elements.messageBubbleTime) this.initMessageBubbleTime(); 11003 this.initDefaultState(); 11004 if (this.elements.chatButton) { 11005 if (this.elements.chatButton.classList.contains(hasEntranceAnimation)) this.initChatButtonEntranceAnimation(); 11006 } 11007 this.setupInnerContainer(); 11008 } 11009 }; 11010 })); 11011 //#endregion 11012 //#region modules/floating-buttons/assets/js/frontend/handlers/contact-buttons-v10.js 11013 var contact_buttons_v10_exports = /* @__PURE__ */ __exportAll({ default: () => ContactButtonsv10Handler }); 11014 var import_base$2, ContactButtonsv10Handler; 11015 var init_contact_buttons_v10 = __esmMin((() => { 11016 import_base$2 = /* @__PURE__ */ __toESM(require_base()); 11017 init_click_tracking(); 11018 ContactButtonsv10Handler = class extends import_base$2.default { 11019 getDefaultSettings() { 11020 return { 11021 selectors: { 11022 main: ".e-contact-buttons-var-10", 11023 links: ".e-contact-buttons__contact-icon-link" 11024 }, 11025 constants: { active: "active" } 11026 }; 11027 } 11028 getDefaultElements() { 11029 const selectors = this.getSettings("selectors"); 11030 return { 11031 main: this.$element[0].querySelector(selectors.main), 11032 links: this.$element[0].querySelectorAll(selectors.links) 11033 }; 11034 } 11035 isMobileDevice() { 11036 return ["mobile", "mobile_extra"].includes(elementorFrontend.getCurrentDeviceMode()); 11037 } 11038 handleLinkClick(event) { 11039 event.preventDefault(); 11040 const { active } = this.getSettings("constants"); 11041 if (event.currentTarget.classList.contains(active)) { 11042 const href = event.currentTarget.getAttribute("href"); 11043 const target = event.currentTarget.getAttribute("target"); 11044 if (target) window.open(href, target); 11045 else if (href) window.location.href = href; 11046 event.currentTarget.classList.remove(active); 11047 } else { 11048 this.closeAllLinks(); 11049 event.currentTarget.classList.add(active); 11050 } 11051 } 11052 closeAllLinks() { 11053 const { active } = this.getSettings("constants"); 11054 this.elements.links.forEach((link) => link.classList.remove(active)); 11055 } 11056 linksEventListeners() { 11057 if (!this.elements.links.length) return; 11058 if (this.isMobileDevice()) { 11059 this.elements.links.forEach((link) => { 11060 link.addEventListener("click", (event) => { 11061 this.handleLinkClick(event); 11062 }); 11063 }); 11064 document.addEventListener("click", (event) => { 11065 if (!this.elements.main.contains(event.target)) this.closeAllLinks(); 11066 }); 11067 } 11068 } 11069 bindEvents() { 11070 this.linksEventListeners(); 11071 } 11072 setupInnerContainer() { 11073 this.elements.main.closest(".e-con-inner").classList.add("e-con-inner--floating-buttons"); 11074 } 11075 onInit(...args) { 11076 super.onInit(...args); 11077 this.clickTrackingHandler = new ClickTrackingHandler({ $element: this.$element }); 11078 this.setupInnerContainer(); 11079 } 11080 }; 11081 })); 11082 //#endregion 11083 //#region modules/floating-buttons/assets/js/frontend/classes/floatin-bar-dom.js 11084 var FloatingBarDomHelper; 11085 var init_floatin_bar_dom = __esmMin((() => { 11086 FloatingBarDomHelper = class { 11087 constructor($element) { 11088 this.$element = $element; 11089 } 11090 maybeMoveToTop() { 11091 const el = this.$element[0]; 11092 const widget = el.querySelector(".e-floating-bars"); 11093 if (elementorFrontend.isEditMode()) { 11094 widget.classList.add("is-sticky"); 11095 return; 11096 } 11097 if (el.dataset.widget_type.startsWith("floating-bars") && widget.classList.contains("has-vertical-position-top") && !widget.classList.contains("is-sticky")) { 11098 const wpAdminBar = document.getElementById("wpadminbar"); 11099 const elementToInsert = el.closest(".elementor");
11100 if (wpAdminBar) wpAdminBar.after(elementToInsert); 11101 else document.body.prepend(elementToInsert); 11102 } 11103 } 11104 }; 11105 })); 11106 //#endregion 11107 //#region modules/floating-buttons/assets/js/frontend/handlers/floating-bars-v2.js 11108 var floating_bars_v2_exports = /* @__PURE__ */ __exportAll({ default: () => FloatingBarsHandler$1 }); 11109 var import_base$1, FloatingBarsHandler$1; 11110 var init_floating_bars_v2 = __esmMin((() => { 11111 import_base$1 = /* @__PURE__ */ __toESM(require_base()); 11112 init_floatin_bar_dom(); 11113 init_click_tracking(); 11114 FloatingBarsHandler$1 = class extends import_base$1.default { 11115 static { 11116 __name(this, "FloatingBarsHandler"); 11117 } 11118 getDefaultSettings() { 11119 return { 11120 selectors: { 11121 main: ".e-floating-bars", 11122 closeButton: ".e-floating-bars__close-button", 11123 playButton: ".e-floating-bars__play-button", 11124 pauseButton: ".e-floating-bars__pause-button", 11125 headline: ".e-floating-bars__headline", 11126 headlines: ".e-floating-bars__headlines", 11127 headlinesInner: ".e-floating-bars__headlines-inner", 11128 overlay: ".e-floating-bars__overlay" 11129 }, 11130 constants: { 11131 isHidden: "is-hidden", 11132 isSticky: "is-sticky", 11133 hasVerticalPositionTop: "has-vertical-position-top", 11134 hasVerticalPositionBottom: "has-vertical-position-bottom", 11135 isPaused: "is-paused", 11136 animationTypeControl: "style_ticker_animation_type", 11137 autoplay: "autoplay" 11138 } 11139 }; 11140 } 11141 onElementChange(property) { 11142 if ([ 11143 "style_headline_text_typography_font_size", 11144 "style_headlines_icon_size", 11145 "style_floating_bar_padding", 11146 "style_floating_bar_controls_size", 11147 "style_floating_bar_element_spacing" 11148 ].includes(property)) this.initDefaultState(); 11149 } 11150 getDefaultElements() { 11151 const selectors = this.getSettings("selectors"); 11152 return { 11153 main: this.$element[0].querySelector(selectors.main), 11154 closeButton: this.$element[0].querySelector(selectors.closeButton), 11155 pauseButton: this.$element[0].querySelector(selectors.pauseButton), 11156 playButton: this.$element[0].querySelector(selectors.playButton), 11157 headlineAll: this.$element[0].querySelectorAll(selectors.headline), 11158 headlines: this.$element[0].querySelector(selectors.headlines), 11159 headlinesInner: this.$element[0].querySelector(selectors.headlinesInner), 11160 overlay: this.$element[0].querySelector(selectors.overlay) 11161 }; 11162 } 11163 getResponsiveSetting(controlName) { 11164 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 11165 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), controlName, "", currentDevice); 11166 } 11167 bindEvents() { 11168 if (this.elements.closeButton) this.elements.closeButton.addEventListener("click", this.closeFloatingBar.bind(this)); 11169 if (this.elements.pauseButton) this.elements.pauseButton.addEventListener("click", this.pauseCarousel.bind(this)); 11170 if (this.elements.playButton) this.elements.playButton.addEventListener("click", this.playCarousel.bind(this)); 11171 if (this.hasStickyElements()) window.addEventListener("resize", this.handleStickyElements.bind(this)); 11172 } 11173 isMobileDevice() { 11174 return ["mobile", "mobile_extra"].includes(elementorFrontend.getCurrentDeviceMode()); 11175 } 11176 isStickyTop() { 11177 const { isSticky, hasVerticalPositionTop } = this.getSettings("constants"); 11178 return this.elements.main.classList.contains(isSticky) && this.elements.main.classList.contains(hasVerticalPositionTop); 11179 } 11180 isStickyBottom() { 11181 const { isSticky, hasVerticalPositionBottom } = this.getSettings("constants"); 11182 return this.elements.main.classList.contains(isSticky) && this.elements.main.classList.contains(hasVerticalPositionBottom); 11183 } 11184 hasStickyElements() { 11185 return document.querySelectorAll(".elementor-sticky").length > 0; 11186 } 11187 pauseCarousel() { 11188 const { isPaused } = this.getSettings("constants"); 11189 this.elements.headlines.classList.add(isPaused); 11190 if (this.elements.playButton && this.elements.pauseButton) { 11191 this.elements.playButton.setAttribute("aria-hidden", "false"); 11192 this.elements.pauseButton.setAttribute("aria-hidden", "true"); 11193 } 11194 } 11195 playCarousel() { 11196 const { isPaused }
11196 = this.getSettings("constants"); 11197 this.elements.headlines.classList.remove(isPaused); 11198 if (this.elements.playButton && this.elements.pauseButton) { 11199 this.elements.pauseButton.setAttribute("aria-hidden", "false"); 11200 this.elements.playButton.setAttribute("aria-hidden", "true"); 11201 } 11202 } 11203 closeFloatingBar() { 11204 const { isHidden } = this.getSettings("constants"); 11205 if (!elementorFrontend.isEditMode()) { 11206 this.elements.main.classList.add(isHidden); 11207 if (this.hasStickyElements()) this.handleStickyElements(); 11208 else if (this.isStickyTop()) this.removeBodyPadding(); 11209 } 11210 } 11211 focusOnLoad() { 11212 this.elements.main.setAttribute("tabindex", "0"); 11213 this.elements.main.focus({ focusVisible: true }); 11214 } 11215 applyBodyPadding() { 11216 const mainHeight = this.elements.main.offsetHeight; 11217 document.body.style.paddingTop = `${mainHeight}px`; 11218 } 11219 removeBodyPadding() { 11220 document.body.style.paddingTop = "0"; 11221 } 11222 cloneScrollerContent() { 11223 Array.from(this.elements.headlinesInner.children).forEach((item) => { 11224 const duplicatedItem = item.cloneNode(true); 11225 duplicatedItem.setAttribute("aria-hidden", "true"); 11226 duplicatedItem.classList.add("e-floating-bars__headline--clone"); 11227 this.elements.headlinesInner.appendChild(duplicatedItem); 11228 }); 11229 } 11230 cloneHeadlinesToFillContainer() { 11231 let headlinesInnerWidth = this.elements.headlinesInner.offsetWidth; 11232 const headlinesWidth = this.elements.headlines.offsetWidth; 11233 while (headlinesInnerWidth < headlinesWidth) { 11234 this.cloneScrollerContent(); 11235 headlinesInnerWidth = this.elements.headlinesInner.offsetWidth; 11236 } 11237 } 11238 cloneHeadlinesInner() { 11239 const headlinesInnerDuplicate = this.elements.headlinesInner.cloneNode(true); 11240 const overlay = this.elements.overlay; 11241 headlinesInnerDuplicate.classList.add("e-floating-bars__headlines-inner--clone"); 11242 headlinesInnerDuplicate.setAttribute("aria-hidden", "true"); 11243 this.elements.headlines.insertBefore(headlinesInnerDuplicate, overlay); 11244 } 11245 handleBrowserScrollAnimation() { 11246 document.addEventListener("scroll", () => { 11247 const scrollPosition = window.scrollY; 11248 const lastHeadline = this.elements.headlinesInner.lastElementChild; 11249 if (elementorFrontend.config.is_rtl) { 11250 this.elements.headlinesInner.style.transform = `translateX(${scrollPosition}px)`; 11251 if (lastHeadline.lastElementChild.getBoundingClientRect().left >= this.elements.headlines.getBoundingClientRect().left) this.cloneScrollerContent(); 11252 } else { 11253 this.elements.headlinesInner.style.transform = `translateX(-${scrollPosition}px)`; 11254 if (lastHeadline.lastElementChild.getBoundingClientRect().right <= this.elements.headlines.getBoundingClientRect().right) this.cloneScrollerContent(); 11255 } 11256 }); 11257 } 11258 handleTickerClick(event) { 11259 event.preventDefault(); 11260 const { isPlaying } = this.getSettings("constants"); 11261 if (this.elements.headlines.classList.contains(isPlaying)) this.pauseCarousel(); 11262 else { 11263 const href = event.currentTarget.getAttribute("href"); 11264 const target = event.currentTarget.getAttribute("target"); 11265 if (!!target) window.open(href, target); 11266 else if (href) window.location.href = href; 11267 this.playCarousel(); 11268 } 11269 } 11270 handleWPAdminBar() { 11271 const wpAdminBar = elementorFrontend.elements.$wpAdminBar; 11272 if (wpAdminBar.length) this.elements.main.style.top = `${wpAdminBar.height()}px`; 11273 } 11274 handleStickyElements() { 11275 const mainHeight = this.elements.main.offsetHeight; 11276 const wpAdminBar = elementorFrontend.elements.$wpAdminBar; 11277 const stickyElements = document.querySelectorAll(".elementor-sticky:not(.elementor-sticky__spacer)"); 11278 if (0 === stickyElements.length) return; 11279 stickyElements.forEach((stickyElement) => { 11280 var _a; 11281 const dataSettings = stickyElement.getAttribute("data-settings"); 11282 const stickyPosition = (_a = JSON.parse(dataSettings)) == null ? void 0 : _a.sticky; 11283 const isTop = "0px" === stickyElement.style.top || "top" === stickyPosition; 11284 const isBottom = "0px" === stickyElement.style.bottom || "bottom" === stickyPosition; 11285 if (this.isStickyTop() && isTop) if (wpAdminBar.length) stickyElement.style.top = `${mainHeight + wpAdminBar.height()}px`; 11286 else stickyElement.style.top = `${mainHeight}px`; 11287 else if (this.isStickyBottom() && isBottom) stickyElement.style.bottom = `${mainHeight}px`; 11288 if (elementorFrontend.isEditMode()) { 11289 if (isTop) stickyElement.style.top = this.isStickyTop() ? `${mainHeight}px` : "0px"; 11290 else if (isBottom) stickyElement.style.bottom = this.isStickyBottom() ? `${mainHeight}px` : "0px"; 11291 } 11292 }); 11293 document.querySelectorAll(".elementor-sticky__spacer").forEach((stickySpacer) => { 11294 var _a; 11295 const dataSettings = stickySpacer.getAttribute("data-settings"); 11296 const stickyPosition = (_a = JSON.parse(dataSettings)) == null ? void 0 : _a.sticky; 11297 const isTop = "0px" === stickySpacer.style.top || "top" === stickyPosition; 11298 if (this.isStickyTop() && isTop) stickySpacer.style.marginBottom = `${mainHeight}px`; 11299 }); 11300 } 11301 handleClickOutside() { 11302 const { isPlaying }
11302 = this.getSettings("constants"); 11303 document.addEventListener("click", (event) => { 11304 if (!this.elements.headlines.classList.contains(isPlaying) && !this.elements.main.contains(event.target)) this.playCarousel(); 11305 }); 11306 } 11307 initScrollingAnimation() { 11308 const { autoplay, animationTypeControl } = this.getSettings("constants"); 11309 if (autoplay === this.getResponsiveSetting(animationTypeControl)) { 11310 this.cloneHeadlinesInner(); 11311 this.elements.headlines.setAttribute("data-animated", "true"); 11312 this.playCarousel(); 11313 if (this.isMobileDevice()) { 11314 this.elements.headlineAll.forEach((headline) => { 11315 headline.addEventListener("click", this.handleTickerClick.bind(this)); 11316 }); 11317 this.handleClickOutside(); 11318 } 11319 } else this.handleBrowserScrollAnimation(); 11320 } 11321 initDefaultState() { 11322 if (this.isStickyTop()) this.handleWPAdminBar(); 11323 if (this.hasStickyElements()) this.handleStickyElements(); 11324 else if (this.isStickyTop()) this.applyBodyPadding(); 11325 if (this.elements.main && !elementorFrontend.isEditMode()) this.focusOnLoad(); 11326 if (this.elements.headlinesInner) this.cloneHeadlinesToFillContainer(); 11327 if (!window.matchMedia("(prefers-reduced-motion: reduce)").matches) this.initScrollingAnimation(); 11328 } 11329 setupInnerContainer() { 11330 this.elements.main.closest(".e-con-inner").classList.add("e-con-inner--floating-bars"); 11331 this.elements.main.closest(".e-con").classList.add("e-con--floating-bars"); 11332 } 11333 onInit(...args) { 11334 super.onInit(...args); 11335 this.clickTrackingHandler = new ClickTrackingHandler({ $element: this.$element }); 11336 new FloatingBarDomHelper(this.$element).maybeMoveToTop(); 11337 this.initDefaultState(); 11338 this.setupInnerContainer(); 11339 } 11340 }; 11341 })); 11342 //#endregion 11343 //#region modules/notes/assets/js/services/copy-to-clipboard/index.js 11344 /** 11345 * Check if there is access to the clipboard API 11346 * (Usually, when a website doesn't have an SSL certificate, the browser won't expose the clipboard API). 11347 * 11348 * @return {boolean} can copy to clipboard? 11349 */ 11350 function canCopyToClipboard() { 11351 var _navigator; 11352 return !!((_navigator = navigator) === null || _navigator === void 0 ? void 0 : _navigator.clipboard); 11353 } 11354 /** 11355 * Will copy value to the clipboard 11356 * 11357 * @param {string} value 11358 */ 11359 function copyToClipboard(value) { 11360 if (!canCopyToClipboard()) throw new Error("Cannot copy to clipboard, please make sure you are using SSL in your website."); 11361 navigator.clipboard.writeText(value); 11362 } 11363 var init_copy_to_clipboard = __esmMin((() => {})); 11364 //#endregion 11365 //#region modules/floating-buttons/assets/js/frontend/handlers/floating-bars-v3.js 11366 var floating_bars_v3_exports = /* @__PURE__ */ __exportAll({ default: () => FloatingBarsHandler }); 11367 var import_base, FloatingBarsHandler; 11368 var init_floating_bars_v3 = __esmMin((() => { 11369 import_base = /* @__PURE__ */ __toESM(require_base()); 11370 init_copy_to_clipboard(); 11371 init_floatin_bar_dom(); 11372 init_click_tracking(); 11373 FloatingBarsHandler = class extends import_base.default { 11374 getDefaultSettings() { 11375 return { 11376 selectors: { 11377 main: ".e-floating-bars", 11378 mainV3: ".e-floating-bars-var-3", 11379 closeButton: ".e-floating-bars__close-button", 11380 couponButton: ".e-floating-bars__coupon-button", 11381 couponCode: ".e-floating-bars__coupon-code", 11382 codeTextGroup: ".e-floating-bars__coupon-code", 11383 successTextGroup: ".e-floating-bars__coupon-success" 11384 }, 11385 constants: { 11386 couponEntranceAnimation: "style_coupon_animation", 11387 couponEntranceAnimationDelay: "style_coupon_animation_delay", 11388 hasEntranceAnimation: "has-entrance-animation", 11389 visible: "visible", 11390 isSticky: "is-sticky", 11391 hasVerticalPositionTop: "has-vertical-position-top", 11392 hasVerticalPositionBottom: "has-vertical-position-bottom", 11393 isHidden: "is-hidden", 11394 successMessageDurationControl: "style_coupon_success_message_duration", 11395 animated: "animated" 11396 } 11397 }; 11398 } 11399 getDefaultElements() { 11400 const selectors = this.getSettings("selectors"); 11401 return { 11402 main: this.$element[0].querySelector(selectors.main), 11403 mainV3: this.$element[0].querySelector(selectors.mainV3), 11404 mainAll: this.$element[0].querySelectorAll(selectors.main), 11405 closeButton: this.$element[0].querySelector(selectors.closeButton), 11406 couponButton: this.$element[0].querySelector(selectors.couponButton), 11407 couponCode: this.$element[0].querySelector(selectors.couponCode), 11408 codeTextGroup: this.$element[0].querySelector(selectors.codeTextGroup), 11409 successTextGroup: this.$element[0].querySelector(selectors.successTextGroup) 11410 }; 11411 } 11412 getResponsiveSetting(controlName) { 11413 const currentDevice = elementorFrontend.getCurrentDeviceMode(); 11414 return elementorFrontend.utils.controls.getResponsiveControlValue(this.getElementSettings(), controlName, "",
11414currentDevice); 11415 } 11416 bindEvents() { 11417 if (this.elements.closeButton) this.elements.closeButton.addEventListener("click", this.closeFloatingBar.bind(this)); 11418 if (this.elements.couponButton) this.elements.couponButton.addEventListener("animationend", this.handleAnimationEnd.bind(this)); 11419 if (this.elements.main) window.addEventListener("keyup", this.onDocumentKeyup.bind(this)); 11420 if (this.elements.couponButton) this.elements.couponButton.addEventListener("click", this.handleCouponButtonClick.bind(this)); 11421 if (this.hasStickyElements()) window.addEventListener("resize", this.handleStickyElements.bind(this)); 11422 } 11423 isStickyTop() { 11424 const { isSticky, hasVerticalPositionTop } = this.getSettings("constants"); 11425 return this.elements.main.classList.contains(isSticky) && this.elements.main.classList.contains(hasVerticalPositionTop); 11426 } 11427 isStickyBottom() { 11428 const { isSticky, hasVerticalPositionBottom } = this.getSettings("constants"); 11429 return this.elements.main.classList.contains(isSticky) && this.elements.main.classList.contains(hasVerticalPositionBottom); 11430 } 11431 hasStickyElements() { 11432 return document.querySelectorAll(".elementor-sticky").length > 0; 11433 } 11434 focusOnLoad() { 11435 this.elements.main.setAttribute("tabindex", "0"); 11436 this.elements.main.focus({ focusVisible: true }); 11437 } 11438 applyBodyPadding() { 11439 const offsetHeight = this.elements.main.offsetHeight; 11440 document.body.style.paddingTop = `${offsetHeight}px`; 11441 } 11442 removeBodyPadding() { 11443 document.body.style.paddingTop = "0"; 11444 } 11445 handleWPAdminBar() { 11446 const wpAdminBar = elementorFrontend.elements.$wpAdminBar; 11447 if (wpAdminBar.length) this.elements.main.style.top = `${wpAdminBar.height()}px`; 11448 } 11449 handleStickyElements() { 11450 const mainHeight = this.elements.main.offsetHeight; 11451 const wpAdminBar = elementorFrontend.elements.$wpAdminBar; 11452 const stickyElements = document.querySelectorAll(".elementor-sticky:not(.elementor-sticky__spacer)"); 11453 if (0 === stickyElements.length) return; 11454 stickyElements.forEach((stickyElement) => { 11455 var _JSON$parse; 11456 const dataSettings = stickyElement.getAttribute("data-settings"); 11457 const stickyPosition = (_JSON$parse = JSON.parse(dataSettings)) === null || _JSON$parse === void 0 ? void 0 : _JSON$parse.sticky; 11458 const isTop = "0px" === stickyElement.style.top || "top" === stickyPosition; 11459 const isBottom = "0px" === stickyElement.style.bottom || "bottom" === stickyPosition; 11460 if (this.isStickyTop() && isTop) if (wpAdminBar.length) stickyElement.style.top = `${mainHeight + wpAdminBar.height()}px`; 11461 else stickyElement.style.top = `${mainHeight}px`; 11462 else if (this.isStickyBottom() && isBottom) stickyElement.style.bottom = `${mainHeight}px`; 11463 if (elementorFrontend.isEditMode()) { 11464 if (isTop) stickyElement.style.top = this.isStickyTop() ? `${mainHeight}px` : "0px"; 11465 else if (isBottom) stickyElement.style.bottom = this.isStickyBottom() ? `${mainHeight}px` : "0px"; 11466 } 11467 }); 11468 document.querySelectorAll(".elementor-sticky__spacer").forEach((stickySpacer) => { 11469 var _JSON$parse2; 11470 const dataSettings = stickySpacer.getAttribute("data-settings"); 11471 const stickyPosition = (_JSON$parse2 = JSON.parse(dataSettings)) === null || _JSON$parse2 === void 0 ? void 0 : _JSON$parse2.sticky; 11472 const isTop = "0px" === stickySpacer.style.top || "top" === stickyPosition; 11473 if (this.isStickyTop() && isTop) stickySpacer.style.marginBottom = `${mainHeight}px`; 11474 }); 11475 } 11476 closeFloatingBar() { 11477 const { isHidden } = this.getSettings("constants"); 11478 if (!elementorFrontend.isEditMode()) {
11479 this.elements.main.classList.add(isHidden); 11480 if (this.hasStickyElements()) this.handleStickyElements(); 11481 else if (this.isStickyTop()) this.removeBodyPadding(); 11482 } 11483 } 11484 initEntranceAnimation() { 11485 const { animated, couponEntranceAnimation, couponEntranceAnimationDelay, hasEntranceAnimation } = this.getSettings("constants"); 11486 const entranceAnimationClass = this.getResponsiveSetting(couponEntranceAnimation); 11487 const setTimeoutDelay = (this.getResponsiveSetting(couponEntranceAnimationDelay) || 0) + 500; 11488 this.elements.couponButton.classList.add(animated); 11489 this.elements.couponButton.classList.add(entranceAnimationClass); 11490 setTimeout(() => { 11491 this.elements.couponButton.classList.remove(hasEntranceAnimation); 11492 }, setTimeoutDelay); 11493 } 11494 handleAnimationEnd() { 11495 this.removeEntranceAnimationClasses(); 11496 this.focusOnLoad(); 11497 } 11498 removeEntranceAnimationClasses() { 11499 if (!this.elements.couponButton) return; 11500 const { animated, couponEntranceAnimation, visible } = this.getSettings("constants"); 11501 const entranceAnimationClass = this.getResponsiveSetting(couponEntranceAnimation); 11502 this.elements.couponButton.classList.remove(animated); 11503 this.elements.couponButton.classList.remove(entranceAnimationClass); 11504 this.elements.couponButton.classList.add(visible); 11505 } 11506 onDocumentKeyup(event) { 11507 if (event.keyCode !== 27 || !this.elements.main) return; 11508 if (this.elements.main.contains(document.activeElement)) this.closeFloatingBar(); 11509 } 11510 getDuration(duration) { 11511 const isUnitSeconds = "s" === duration.unit; 11512 const DEFAULT_DURATION_SIZE = isUnitSeconds ? "1.5" : "1500"; 11513 const size = "" !== duration.size ? duration.size : DEFAULT_DURATION_SIZE; 11514 return isUnitSeconds ? size * 1e3 : size; 11515 } 11516 handleCouponButtonClick(element) { 11517 const { successMessageDurationControl, isHidden } = this.getSettings("constants"); 11518 const text = this.elements.couponCode.innerText; 11519 const successMessageDuration = this.getResponsiveSetting(successMessageDurationControl); 11520 const duration = this.getDuration(successMessageDuration); 11521 const currentWidth = element.currentTarget.getBoundingClientRect().width; 11522 const currentHeight = element.currentTarget.getBoundingClientRect().height; 11523 this.elements.mainV3.style.setProperty("--e-floating-bars-coupon-width", `${currentWidth}px`); 11524 this.elements.mainV3.style.setProperty("--e-floating-bars-coupon-height", `${currentHeight}px`); 11525 copyToClipboard(text);
11526 this.elements.codeTextGroup.classList.add(isHidden); 11527 this.elements.successTextGroup.classList.remove(isHidden); 11528 setTimeout(() => { 11529 this.elements.codeTextGroup.classList.remove(isHidden); 11530 this.elements.successTextGroup.classList.add(isHidden); 11531 this.elements.mainV3.style.setProperty("--e-floating-bars-coupon-width", "initial"); 11532 this.elements.mainV3.style.setProperty("--e-floating-bars-coupon-height", "initial"); 11533 }, duration); 11534 } 11535 initDefaultState() { 11536 const { hasEntranceAnimation } = this.getSettings("constants"); 11537 if (this.isStickyTop()) this.handleWPAdminBar(); 11538 if (this.hasStickyElements()) this.handleStickyElements(); 11539 else if (this.isStickyTop()) this.applyBodyPadding(); 11540 if (this.elements.main && !this.elements.couponButton.classList.contains(hasEntranceAnimation) && !elementorFrontend.isEditMode()) this.focusOnLoad(); 11541 } 11542 setupInnerContainer() { 11543 this.elements.main.closest(".e-con-inner").classList.add("e-con-inner--floating-bars"); 11544 this.elements.main.closest(".e-con").classList.add("e-con--floating-bars"); 11545 } 11546 onInit(...args) { 11547 const { hasEntranceAnimation } = this.getSettings("constants"); 11548 super.onInit(...args); 11549 this.clickTrackingHandler = new ClickTrackingHandler({ $element: this.$element }); 11550 new FloatingBarDomHelper(this.$element).maybeMoveToTop(); 11551 if (this.elements.couponButton && this.elements.couponButton.classList.contains(hasEntranceAnimation)) this.initEntranceAnimation(); 11552 this.initDefaultState(); 11553 this.setupInnerContainer(); 11554 } 11555 }; 11556 })); 11557 //#endregion 11558 //#region modules/floating-buttons/assets/js/frontend/frontend.js 11559 var frontend_default$1 = class extends elementorModules.Module { 11560 static { 11561 __name(this, "default"); 11562 } 11563 constructor() { 11564 super(); 11565 if (elementorFrontend.config.experimentalFeatures.container) { 11566 [ 11567 "contact-buttons-var-1", 11568 "contact-buttons-var-3", 11569 "contact-buttons-var-4", 11570 "contact-buttons-var-5", 11571 "contact-buttons-var-6", 11572 "contact-buttons-var-7", 11573 "contact-buttons-var-8", 11574 "contact-buttons-var-9" 11575 ].forEach((handler) => { 11576 elementorFrontend.elementsHandler.attachHandler(handler, () => __vitePreload(() => Promise.resolve().then(() => (init_contact_buttons(), contact_buttons_exports)), void 0)); 11577 }); 11578 elementorFrontend.elementsHandler.attachHandler("contact-buttons-var-10", () => __vitePreload(() => Promise.resolve().then(() => (init_contact_buttons_v10(), contact_buttons_v10_exports)), void 0)); 11579 elementorFrontend.elementsHandler.attachHandler("floating-bars-var-2", () => __vitePreload(() => Promise.resolve().then(() => (init_floating_bars_v2(), floating_bars_v2_exports)), void 0)); 11580 elementorFrontend.elementsHandler.attachHandler("floating-bars-var-3", () => __vitePreload(() => Promise.resolve().then(() => (init_floating_bars_v3(), floating_bars_v3_exports)), void 0)); 11581 } 11582 } 11583 }; 11584 //#endregion 11585 //#region modules/search/assets/js/frontend/handlers/search.js 11586 var search_exports = /* @__PURE__ */ __exportAll({ default: () => Search }); 11587 var __defProp$1, __defNormalProp$1, __publicField$1, Search; 11588 var init_search = __esmMin((() => { 11589 init_run_element_handlers(); 11590 __defProp$1 = Object.defineProperty; 11591 __defNormalProp$1 = /* @__PURE__ */ __name((obj, key, value) => key in obj ? __defProp$1(obj, key, { 11592 enumerable: true, 11593 configurable: true, 11594 writable: true, 11595 value 11596 }) : obj[key] = value, "__defNormalProp"); 11597 __publicField$1 = /* @__PURE__ */ __name((obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value), "__publicField"); 11598 Search = class extends elementorModules.frontend.handlers.Base { 11599 constructor() { 11600 super(...arguments); 11601 __publicField$1(this, "debounceTimeoutId"); 11602 __publicField$1(this, "page_number"); 11603 } 11604 __construct(...args) { 11605 super.__construct(...args); 11606 elementorFrontend.hooks.addAction("search:results-displayed", (id) => { 11607 if (id === this.getID()) this.hideOtherResults(); 11608 }); 11609 } 11610 getDefaultSettings() { 11611 return { 11612 selectors: {
11613 searchWrapper: ".e-search", 11614 searchField: ".e-search-input", 11615 submitButton: ".e-search-submit", 11616 clearIcon: ".e-search-input-wrapper > svg, .e-search-input-wrapper > i", 11617 searchIcon: ".e-search-label > svg, .e-search-label > i", 11618 resultsContainer: ".e-search-results-container", 11619 results: ".e-search-results", 11620 links: "a.page-numbers:not(.current)" 11621 }, 11622 classes: { 11623 searchResultsListWrapper: "e-search-results-list", 11624 searchResultsPagination: "elementor-pagination" 11625 } 11626 }; 11627 } 11628 getDefaultElements() { 11629 const selectors = this.getSettings("selectors"); 11630 return { 11631 searchWidget: this.$element[0], 11632 searchWrapper: this.$element[0].querySelector(selectors.searchWrapper), 11633 searchField: this.$element[0].querySelector(selectors.searchField), 11634 submitButton: this.$element[0].querySelector(selectors.submitButton), 11635 clearIcon: this.$element[0].querySelector(selectors.clearIcon), 11636 searchIcon: this.$element[0].querySelector(selectors.searchIcon), 11637 resultsContainer: this.$element[0].querySelector(selectors.resultsContainer), 11638 results: this.$element[0].querySelector(selectors.results), 11639 links: this.$element[0].querySelectorAll(selectors.links) 11640 }; 11641 } 11642 onInit() { 11643 super.onInit(); 11644 this.changeClearIconVisibility(true); 11645 this.updateInputStyle(); 11646 this.toggleSearchResultsVisibility = this.toggleSearchResultsVisibility.bind(this); 11647 document.addEventListener("click", this.toggleSearchResultsVisibility); 11648 document.fonts.ready.then(() => this.updateInputStyle()); 11649 } 11650 onDestroy() { 11651 document.removeEventListener("click", this.toggleSearchResultsVisibility); 11652 } 11653 bindEvents() { 11654 var _a; 11655 this.elements.submitButton.addEventListener("click", this.onSubmit.bind(this)); 11656 this.elements.searchField.addEventListener("input", (event) => { 11657 this.changeClearIconVisibility(!event.target.value.length); 11658 this.debounce(this.onType)(event); 11659 }); 11660 this.elements.searchField.addEventListener("keydown", this.onSearchFieldKeydown.bind(this)); 11661 this.elements.searchWidget.addEventListener("click", this.onClick.bind(this)); 11662 ["focusin", "focusout"].forEach((eventType) => { 11663 this.elements.searchField.addEventListener(eventType, this.toggleWidgetFocusClass.bind(this)); 11664 }); 11665 (_a = this.elements.clearIcon) == null || _a.addEventListener("click", this.onClear.bind(this)); 11666 this.linksEventListeners(); 11667 } 11668 linksEventListeners() { 11669 if (!this.elements.links.length) return; 11670 this.elements.links.forEach((link) => { 11671 link.addEventListener("click", (event) => { 11672 this.handleLinkClick(event); 11673 }); 11674 }); 11675 } 11676 handleLinkClick(event) { 11677 event.preventDefault(); 11678 const nextPageUrl = event == null ? void 0 : event.target.getAttribute("href"); 11679 const pageNumber = new URLSearchParams(new URL(nextPageUrl).search).get("e-search-page"); 11680 this.page_number = pageNumber ? parseInt(pageNumber, 10) : 1; 11681 this.removeLinksListeners(); 11682 this.renderLiveResults(); 11683 } 11684 removeLinksListeners() { 11685 if (!this.elements.links.length) return; 11686 this.elements.links.forEach((link) => { 11687 link.removeEventListener("click", this.handleLinkClick); 11688 }); 11689 } 11690 reInitLinks() { 11691 this.elements.links = document.querySelectorAll(`[data-id="${this.getID()}"] a.page-numbers:not(.current)`); 11692 this.linksEventListeners(); 11693 } 11694 onClick() { 11695 this.elements.resultsContainer.classList.add("hide-loader"); 11696 } 11697 onType(event) { 11698 event.preventDefault(); 11699 this.updateAriaLabel(this.elements.searchField.value); 11700 if (!this.elements.searchField.value.length) { 11701 this.clearResultsMarkup(); 11702 return; 11703 } 11704 const minimumSearchLength = this.getMinimumSearchLength(); 11705 if (this.shouldShowLiveResults() && this.elements.searchField.value.length >= minimumSearchLength) { 11706 this.page_number = 1; 11707 this.renderLiveResults(); 11708 } 11709 } 11710 toggleWidgetFocusClass(event) { 11711 const isFocusIn = "focusin" === event.type; 11712 this.$element[0].classList.toggle("e-focus", isFocusIn); 11713 } 11714 onSubmit(event) { 11715 if (elementorFrontend.isEditMode()) event.preventDefault(); 11716 } 11717 onClear(event) { 11718 event.preventDefault(); 11719 this.elements.searchField.value = ""; 11720 this.clearResultsMarkup(); 11721 this.elements.searchField.focus(); 11722 this.changeClearIconVisibility(true); 11723 } 11724 onSearchFieldKeydown(event) { 11725 if ("Enter" === event.code) { 11726 this.clearResultsMarkup(); 11727 this.onSubmit(event); 11728 } 11729 } 11730 fetchUpdatedSearchWidgetMarkup() { 11731 return fetch(`${elementorProFrontend.config.urls.rest}elementor-pro/v1/refresh-search`, this.getFetchArgumentsForSearchUpdate()); 11732 } 11733 getMinimumSearchLength() { 11734 return this.getElementSettings().minimum_search_characters || 3; 11735 } 11736 shouldShowLiveResults() { 11737 return this.getElementSettings().live_results && this.getElementSettings().template_id; 11738 } 11739 renderLiveResults() { 11740 if (!document.querySelector(`.elementor-element-${this.getID()}`)) return; 11741 if (!this.elements.searchField.value) { 11742 this.clearResultsMarkup(); 11743 return; 11744 } 11745 this.elements.resultsContainer.classList.remove("hide-loader"); 11746 this.elements.resultsContainer.classList.remove("hidden"); 11747 return this.fetchUpdatedSearchWidgetMarkup().then((response) => { 11748 if (!(response instanceof Response) || !(response == null ? void 0 : response.ok) || 400 <= (response == null ? void 0 : response.status)) return {}; 11749 return response.json(); 11750 }).catch(() => { 11751 return {}; 11752 }).then((response) => { 11753 if (!(response == null ? void 0 : response.data)) { 11754 this.updateAriaExpanded(false); 11755 return; 11756 } 11757 const resultNode = this.createResultNode(response); 11758 this.elements.results.replaceChildren(resultNode.resultContentNode); 11759 this.elements.results.append(resultNode.paginationNode); 11760 this.elements.resultsContainer.classList.add("hide-loader"); 11761 this.maybeHandleNoResults(resultNode.resultContentNode); 11762 elementorFrontend.hooks.doAction("search:results-updated"); 11763 }).finally(() => { 11764 runElementHandlers(document.querySelectorAll(`[data-id="${this.getID()}"] .e-loop-item`)); 11765 this.reInitLinks(); 11766 if (ElementorProFrontendConfig.settings.lazy_load_background_images) document.dispatchEvent(new Event("elementor/lazyload/observe")); 11767 }); 11768 } 11769 maybeHandleNoResults(resultsNode) { 11770 const isNoResultsMessage = !!resultsNode.querySelector(".e-search-nothing-found-message"); 11771 this.elements.results.classList[isNoResultsMessage ? "add" : "remove"]("no-results"); 11772 if (!isNoResultsMessage) this.hideOtherResults(); 11773 } 11774 hideOtherResults(id = null) { 11775 if (id && id !== this.getID()) return; 11776 const visibleResultsContainers = document.querySelectorAll(`${this.get
11776Settings("selectors").resultsContainer}:not(.hidden)`); 11777 Array.from(visibleResultsContainers).filter((resultsContainer) => !resultsContainer.closest(`.elementor-element-${this.getID()}`)).forEach((resultsContainer) => resultsContainer.classList.add("hidden")); 11778 } 11779 createResultNode(responseData) { 11780 const resultContentNode = document.createElement("div"); 11781 const searchResultsList = this.getSettings("classes.searchResultsListWrapper"); 11782 const paginationNode = document.createElement("nav"); 11783 const searchResultPagination = this.getSettings("classes.searchResultsPagination"); 11784 const searchResultPaginationAriaLabel = "Pagination"; 11785 paginationNode.setAttribute("class", searchResultPagination); 11786 paginationNode.setAttribute("aria-label", searchResultPaginationAriaLabel); 11787 resultContentNode.setAttribute("class", searchResultsList); 11788 paginationNode.innerHTML = responseData.pagination; 11789 resultContentNode.innerHTML = responseData.data; 11790 const hasResults = resultContentNode.querySelectorAll(".e-loop-item").length > 0; 11791 this.updateAriaExpanded(hasResults); 11792 return { 11793 resultContentNode, 11794 paginationNode 11795 }; 11796 } 11797 updateAriaExpanded(expanded) { 11798 this.elements.searchField.setAttribute("aria-expanded", expanded ? "true" : "false"); 11799 } 11800 updateAriaLabel(searchTerms) { 11801 if (searchTerms) this.elements.resultsContainer.setAttribute("aria-label", `Results for ${searchTerms}`); 11802 else this.elements.resultsContainer.removeAttribute("aria-label"); 11803 } 11804 clearResultsMarkup() { 11805 this.elements.results.innerHTML = ""; 11806 this.updateAriaExpanded(false); 11807 } 11808 getFetchArgumentsForSearchUpdate() { 11809 var _a; 11810 var _b; 11811 const data = this.prepareSearchUpdateRequestData(); 11812 const args = { 11813 method: "POST", 11814 headers: { "Content-Type": "application/json" }, 11815 body: JSON.stringify(data) 11816 }; 11817 if (elementorFrontend.isEditMode() && !!((_a = elementorPro.config.eSearch) == null ? void 0 : _a.nonce)) args.headers["X-WP-Nonce"] = (_b = elementorPro.config.eSearch) == null ? void 0 : _b.nonce; 11818 return args; 11819 } 11820 prepareSearchUpdateRequestData() { 11821 var _a; 11822 var _b; 11823 const widgetId = "" + this.getID(); 11824 const breakpoint = (_b = (_a = elementorFrontend.getCurrentDeviceMode) == null ? void 0 : _a.call(elementorFrontend)) != null ? _b : "desktop"; 11825 const data = { 11826 post_id: this.getClosestDataElementorId(this.$element[0]), 11827 widget_id: widgetId, 11828 search_term: this.elements.searchField.value || "", 11829 page_number: this.page_number, 11830 breakpoint 11831 }; 11832 if (elementorFrontend.isEditMode()) { 11833 data.widget_model = window.top.$e.components.get("document").utils.findContainerById(widgetId).model.toJSON({ remove: [ 11834 "default", 11835 "editSettings", 11836 "defaultEditSettings" 11837 ] }); 11838 data.is_edit_mode = true; 11839 } 11840 return data; 11841 } 11842 getClosestDataElementorId(element) { 11843 const closestParent = element.closest("[data-elementor-id]"); 11844 return closestParent ? closestParent.getAttribute("data-elementor-id") : 0; 11845 } 11846 debounce(callback, timeout = 300) { 11847 return (...args) => { 11848 clearTimeout(this.debounceTimeoutId); 11849 this.debounceTimeoutId = setTimeout(() => callback.apply(this, args), timeout); 11850 }; 11851 } 11852 updateInputStyle(iconSlugs = ["searchIcon", "clearIcon"]) { 11853 var _a; 11854 const cssVariableNamesMap = { 11855 searchIcon: "icon-label", 11856 clearIcon: "icon-clear" 11857 }; 11858 const widgetStyle = this.$element[0].style; 11859 const hiddenRoots = this.getAllDisplayNoneParents(this.$element[0].parentNode); 11860 this.setElementsDisplay(hiddenRoots, "block"); 11861 for (const iconSlug of iconSlugs) { 11862 const { width } = ((_a = this.elements[iconSlug]) == null ? void 0 : _a.getBoundingClientRect()) || { width: 0 }, cssVariableSlug = cssVariableNamesMap[iconSlug]; 11863 widgetStyle.setProperty(`--e-search-${cssVariableSlug}-absolute-width`, width + "px"); 11864 this.elements.searchField.classList[width ? "remove" : "add"](`no-${cssVariableSlug}`); 11865 } 11866 this.setElementsDisplay(hiddenRoots, "");
11867 this.elements.searchWrapper.classList.remove("hidden"); 11868 } 11869 /** 11870 * Sets the clear icon visibility. 11871 * @param { boolean } shouldHide true to hide or false to show. 11872 * @return { void } the width. 11873 */ 11874 changeClearIconVisibility(shouldHide) { 11875 var _a; 11876 (_a = this.elements.clearIcon) == null || _a.classList[shouldHide ? "add" : "remove"]("hidden"); 11877 } 11878 toggleSearchResultsVisibility(event) { 11879 var _a; 11880 var _b; 11881 var _c; 11882 var _d; 11883 const selectors = this.getSettings("selectors"), widgetWrapper = `.elementor-element-${this.getID()}`, { target } = event, isTargetPartOfResults = !!(target == null ? void 0 : target.closest(`${widgetWrapper} ${selectors.resultsContainer}`)) || ((_a = target == null ? void 0 : target.classList) == null ? void 0 : _a.contains(selectors.resultsContainer)) && !!(target == null ? void 0 : target.closest(widgetWrapper)), isSearchContainerClicked = !!(target == null ? void 0 : target.closest(`${widgetWrapper} ${selectors.searchWrapper}`)), isSearchInputClicked = (_b = target == null ? void 0 : target.classList) == null ? void 0 : _b.contains(selectors.searchField.replace(".", "")), isSearchResultsPresent = (_d = (_c = this.elements.resultsContainer) == null ? void 0 : _c.children) == null ? void 0 : _d.length; 11884 if (isTargetPartOfResults) this.hideOtherResults(); 11885 if (!isSearchResultsPresent || isTargetPartOfResults) return; 11886 if (!isSearchInputClicked || !isSearchContainerClicked) this.elements.resultsContainer.classList.add("hidden"); 11887 } 11888 getAllDisplayNoneParents(elementNode, foundElements = []) { 11889 if (!elementNode || elementNode === document.body) return foundElements; 11890 if ("none" === window.getComputedStyle(elementNode).display) foundElements.push(elementNode); 11891 return this.getAllDisplayNoneParents(elementNode.parentNode, foundElements); 11892 } 11893 setElementsDisplay(elements, displayValue) { 11894 elements.forEach((element) => { 11895 element.style.display = displayValue; 11896 }); 11897 } 11898 onElementChange(propertyName) { 11899 const propertyNameCallbackMap = { 11900 search_field_icon_label_size: () => this.updateInputStyle(["searchIcon"]), 11901 icon_clear_size: () => this.updateInputStyle(["clearIcon"]) 11902 }; 11903 if (propertyNameCallbackMap[propertyName]) propertyNameCallbackMap[propertyName](); 11904 } 11905 }; 11906 })); 11907 //#endregion 11908 //#region modules/search/assets/js/frontend/handlers/search-keyboard-handler.js 11909 var search_keyboard_handler_exports = /* @__PURE__ */ __exportAll({ default: () => SearchKeyboardHandler }); 11910 var __defProp, __defNormalProp, __publicField, SearchKeyboardHandler; 11911 var init_search_keyboard_handler = __esmMin((() => { 11912 init_focusable_element_selectors(); 11913 __defProp = Object.defineProperty; 11914 __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { 11915 enumerable: true, 11916 configurable: true, 11917 writable: true, 11918 value 11919 }) : obj[key] = value; 11920 __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); 11921 SearchKeyboardHandler = class extends elementorModules.frontend.handlers.Base { 11922 constructor() { 11923 super(...arguments); 11924 __publicField(this, "focusableResultElements"); 11925 __publicField(this, "currentResultFocusedIndex", -1); 11926 } 11927 __construct(...args) { 11928 super.__construct(...args); 11929 elementorFrontend.hooks.addAction("search:results-updated", this.loadResultElementsEvents.bind(this)); 11930 } 11931 getDefaultSettings() { 11932 return { selectors: { 11933 searchWrapper: ".e-search", 11934 searchField: ".e-search-input", 11935 resultsContainer: ".e-search-results-container", 11936 loopItem: ".e-loop-item", 11937 clearIcon: ".e-search-input-wrapper > svg, .e-search-input-wrapper > i" 11938 } }; 11939 } 11940 getDefaultElements() { 11941 const selectors = this.getSettings("selectors"); 11942 return { 11943 resultsContainer: this.$element[0].querySelector(selectors.resultsContainer), 11944 searchField: this.$element[0].querySelector(selectors.searchField), 11945 clearIcon: this.$element[0].querySelector(selectors.clearIcon) 11946 }; 11947 } 11948 setFocusableElements(elementContainer) {
11949 const focusableSelectors = focusableElementSelectors(); 11950 const focusableElements = elementContainer.querySelectorAll(focusableSelectors); 11951 this.focusableResultElements = Array.from(focusableElements).filter((element) => !element.disabled && !element.inert && element.tabIndex !== -1); 11952 } 11953 isSearchInputFocused() { 11954 return this.elements.searchField === elementorFrontend.elements.window.document.activeElement; 11955 } 11956 bindEvents() { 11957 this.boundHandleKeyboardNavigation = this.handleKeyboardNavigation.bind(this); 11958 this.boundHandleEscapeKey = this.handleEscapeKey.bind(this); 11959 this.elements.searchField.addEventListener("keydown", this.boundHandleKeyboardNavigation); 11960 elementorFrontend.elements.window.document.addEventListener("keydown", this.boundHandleEscapeKey); 11961 this.elements.searchField.addEventListener("focus", this.openResults.bind(this)); 11962 } 11963 loadResultElementsEvents() { 11964 var _a; 11965 this.setFocusableElements(this.$element[0].querySelector(this.getSettings("selectors.resultsContainer"))); 11966 (_a = this.focusableResultElements) == null || _a.forEach((element) => { 11967 element.addEventListener("keydown", this.handleKeyboardNavigation.bind(this)); 11968 }); 11969 } 11970 unbindEvents() { 11971 if (this.boundHandleKeyboardNavigation) this.elements.searchField.removeEventListener("keydown", this.boundHandleKeyboardNavigation); 11972 elementorFrontend.elements.window.document.removeEventListener("keydown", this.boundHandleEscapeKey); 11973 this.elements.searchField.removeEventListener("focus", this.openResults.bind(this)); 11974 } 11975 handleKeyboardNavigation(event) { 11976 switch (event.key) { 11977 case "ArrowDown": 11978 this.focusNextElement(); 11979 break; 11980 case "ArrowUp": 11981 this.focusPreviousElement(); 11982 break; 11983 case "Enter": 11984 this.handleEnterKey(); 11985 break; 11986 } 11987 } 11988 areResultsClosed() { 11989 return 0 === this.elements.resultsContainer.querySelectorAll(this.getSettings("selectors.loopItem")).length || this.elements.resultsContainer.classList.contains("hidden"); 11990 } 11991 openResults() { 11992 if (this.areResultsClosed()) { 11993 this.elements.resultsContainer.classList.remove("hidden"); 11994 elementorFrontend.hooks.doAction("search:results-displayed", this.getID()); 11995 } 11996 } 11997 handleEnterKey() { 11998 this.closeResults(); 11999 } 12000 handleEscapeKey(event) { 12001 if ("Escape" !== event.key) return; 12002 const activeElement = elementorFrontend.elements.window.document.activeElement; 12003 if (this.elements.resultsContainer.contains(activeElement) || false) this.elements.searchField.focus(); 12004 this.closeResults(); 12005 } 12006 focusNextElement() { 12007 if (this.isSearchInputFocused()) this.currentResultFocusedIndex = 0; 12008 else { 12009 this.currentResultFocusedIndex++; 12010 this.checkFocusIndexBounds(); 12011 } 12012 this.updateFocus(); 12013 } 12014 focusPreviousElement() { 12015 if (this.isSearchInputFocused()) this.currentResultFocusedIndex = this.focusableResultElements.length - 1; 12016 else { 12017 this.currentResultFocusedIndex--; 12018 this.checkFocusIndexBounds(); 12019 } 12020 this.updateFocus(); 12021 } 12022 checkFocusIndexBounds() { 12023 if (this.currentResultFocusedIndex >= this.focusableResultElements.length) this.currentResultFocusedIndex = -1; 12024 else if (this.currentResultFocusedIndex < -1) this.currentResultFocusedIndex = this.focusableResultElements.length - 1; 12025 } 12026 updateFocus() { 12027 if (-1 === this.currentResultFocusedIndex) this.focusSearchAndMoveCursorToEnd(); 12028 else this.setFocusToElement(this.focusableResultElements[this.currentResultFocusedIndex]); 12029 } 12030 closeResults() { 12031 this.elements.resultsContainer.classList.add("hidden"); 12032 this.updateAriaExpanded(false); 12033 } 12034 updateAriaExpanded(expanded) { 12035 this.elements.searchField.setAttribute("aria-expanded", expanded); 12036 } 12037 focusSearchAndMoveCursorToEnd() { 12038 const searchField = this.elements.searchField; 12039 const length = searchField.value.length; 12040 this.setFocusToElement(this.elements.searchField); 12041 searchField.setSelectionRange(length, length); 12042 } 12043 setFocusToElement(element) { 12044 element.focus(); 12045 } 12046 }; 12047 })); 12048 //#endregion 12049 //#region modules/search/assets/js/frontend/frontend.js 12050 var frontend_default = class extends elementorModules.Module { 12051 static { 12052 __name(this, "default"); 12053 } 12054 constructor() { 12055 super(); 12056 elementorFrontend.elementsHandler.attachHandler("search", [() => __vitePreload(() => Promise.resolve().then(() => (init_search(), search_exports)), void 0), () => __vitePreload(() => Promise.resolve().then(() => (init_search_keyboard_handler(), search_keyboard_handler_exports
12056)), void 0)]); 12057 } 12058 }; 12059 //#endregion 12060 //#region assets/dev/js/frontend/elements-handlers.js 12061 init_objectSpread2(); 12062 var extendDefaultHandlers = (defaultHandlers) => { 12063 const handlers = { 12064 animatedText: frontend_default$23, 12065 carousel: frontend_default$22, 12066 countdown: frontend_default$21, 12067 dynamicTags: frontend_default$20, 12068 hotspot: frontend_default$19, 12069 form: frontend_default$18, 12070 gallery: frontend_default$17, 12071 lottie: frontend_default$16, 12072 nav_menu: frontend_default$15, 12073 popup: frontend_default$14, 12074 posts: frontend_default$13, 12075 share_buttons: frontend_default$12, 12076 slides: frontend_default$11, 12077 social: frontend_default$10, 12078 themeBuilder: frontend_default$8, 12079 themeElements: frontend_default$7, 12080 woocommerce: frontend_default$6, 12081 tableOfContents: frontend_default$9, 12082 loopBuilder: frontend_default$5, 12083 megaMenu: frontend_default$4, 12084 nestedCarousel: frontend_default$3, 12085 taxonomyFilter: LoopFilter, 12086 offCanvas: frontend_default$2, 12087 contactButtons: frontend_default$1, 12088 search: frontend_default 12089 }; 12090 return _objectSpread2(_objectSpread2({}, defaultHandlers), handlers); 12091 }; 12092 elementorProFrontend.on("elementor-pro/modules/init/before", () => { 12093 elementorFrontend.hooks.addFilter("elementor-pro/frontend/handlers", extendDefaultHandlers); 12094 }); 12095 //#endregion 12096})(wp.i18n); 12097 12098//# sourceMappingURL=elements-handlers.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.