preloaded-modules.js (63086B)
1 /*! elementor - v3.4.4 - 13-09-2021 */ 2 (self["webpackChunkelementor"] = self["webpackChunkelementor"] || []).push([["preloaded-modules"],{ 3 4 /***/ "../assets/dev/js/frontend/handlers/accordion.js": 5 /*!*******************************************************!*\ 6 !*** ../assets/dev/js/frontend/handlers/accordion.js ***! 7 \*******************************************************/ 8 /***/ ((__unused_webpack_module, exports, __webpack_require__) => { 9 10 "use strict"; 11 12 13 var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js"); 14 15 Object.defineProperty(exports, "__esModule", ({ 16 value: true 17 })); 18 exports.default = void 0; 19 20 var _baseTabs = _interopRequireDefault(__webpack_require__(/*! ./base-tabs */ "../assets/dev/js/frontend/handlers/base-tabs.js")); 21 22 class Accordion extends _baseTabs.default { 23 getDefaultSettings() { 24 const defaultSettings = super.getDefaultSettings(); 25 return { ...defaultSettings, 26 showTabFn: 'slideDown', 27 hideTabFn: 'slideUp' 28 }; 29 } 30 31 } 32 33 exports.default = Accordion; 34 35 /***/ }), 36 37 /***/ "../assets/dev/js/frontend/handlers/alert.js": 38 /*!***************************************************!*\ 39 !*** ../assets/dev/js/frontend/handlers/alert.js ***! 40 \***************************************************/ 41 /***/ ((__unused_webpack_module, exports) => { 42 43 "use strict"; 44 45 46 Object.defineProperty(exports, "__esModule", ({ 47 value: true 48 })); 49 exports.default = void 0; 50 51 class Alert extends elementorModules.frontend.handlers.Base { 52 getDefaultSettings() { 53 return { 54 selectors: { 55 dismissButton: '.elementor-alert-dismiss' 56 } 57 }; 58 } 59 60 getDefaultElements() { 61 const selectors = this.getSettings('selectors'); 62 return { 63 $dismissButton: this.$element.find(selectors.dismissButton) 64 }; 65 } 66 67 bindEvents() { 68 this.elements.$dismissButton.on('click', this.onDismissButtonClick.bind(this)); 69 } 70 71 onDismissButtonClick() { 72 this.$element.fadeOut(); 73 } 74 75 } 76 77 exports.default = Alert; 78 79 /***/ }), 80 81 /***/ "../assets/dev/js/frontend/handlers/base-tabs.js": 82 /*!*******************************************************!*\ 83 !*** ../assets/dev/js/frontend/handlers/base-tabs.js ***! 84 \*******************************************************/ 85 /***/ ((__unused_webpack_module, exports) => { 86 87 "use strict"; 88 89 90 Object.defineProperty(exports, "__esModule", ({ 91 value: true 92 })); 93 exports.default = void 0; 94 95 class baseTabs extends elementorModules.frontend.handlers.Base { 96 getDefaultSettings() { 97 return { 98 selectors: { 99 tablist: '[role="tablist"]', 100 tabTitle: '.elementor-tab-title', 101 tabContent: '.elementor-tab-content' 102 }, 103 classes: { 104 active: 'elementor-active' 105 }, 106 showTabFn: 'show', 107 hideTabFn: 'hide', 108 toggleSelf: true, 109 hidePrevious: true, 110 autoExpand: true, 111 keyDirection: { 112 ArrowLeft: elementorFrontendConfig.is_rtl ? 1 : -1, 113 ArrowUp: -1, 114 ArrowRight: elementorFrontendConfig.is_rtl ? -1 : 1, 115 ArrowDown: 1 116 } 117 }; 118 } 119 120 getDefaultElements() { 121 const selectors = this.getSettings('selectors'); 122 return { 123 $tabTitles: this.findElement(selectors.tabTitle), 124 $tabContents: this.findElement(selectors.tabContent) 125 }; 126 } 127 128 activateDefaultTab() { 129 const settings = this.getSettings(); 130 131 if (!settings.autoExpand || 'editor' === settings.autoExpand && !this.isEdit) { 132 return; 133 } 134 135 const defaultActiveTab = this.getEditSettings('activeItemIndex') || 1, 136 originalToggleMethods = { 137 showTabFn: settings.showTabFn, 138 hideTabFn: settings.hideTabFn 139 }; // Toggle tabs without animation to avoid jumping 140 141 this.setSettings({ 142 showTabFn: 'show', 143 hideTabFn: 'hide' 144 }); 145 this.changeActiveTab(defaultActiveTab); // Return back original toggle effects 146 147 this.setSettings(originalToggleMethods); 148 } 149 150 handleKeyboardNavigation(event) { 151 const tab = event.currentTarget, 152 $tabList = jQuery(tab.closest(this.getSettings('selectors').tablist)), 153 $tabs = $tabList.find(this.getSettings('selectors').tabTitle), 154 isVertical = 'vertical' === $tabList.attr('aria-orientation'); 155 156 switch (event.key) { 157 case 'ArrowLeft': 158 case 'ArrowRight': 159 if (isVertical) { 160 return; 161 } 162 163 break; 164 165 case 'ArrowUp': 166 case 'ArrowDown': 167 if (!isVertical) { 168 return; 169 } 170 171 event.preventDefault(); 172 break; 173 174 case 'Home': 175 event.preventDefault(); 176 $tabs.first().focus(); 177 return; 178 179 case 'End': 180 event.preventDefault(); 181 $tabs.last().focus(); 182 return; 183 184 default: 185 return; 186 } 187 188 const tabIndex = tab.getAttribute('data-tab') - 1, 189 direction = this.getSettings('keyDirection')[event.key], 190 nextTab = $tabs[tabIndex + direction]; 191 192 if (nextTab) { 193 nextTab.focus(); 194 } else if (-1 === tabIndex + direction) { 195 $tabs.last().focus(); 196 } else { 197 $tabs.first().focus(); 198 } 199 } 200 201 deactivateActiveTab(tabIndex) { 202 const settings = this.getSettings(), 203 activeClass = settings.classes.active, 204 activeFilter = tabIndex ? '[data-tab="' + tabIndex + '"]' : '.' + activeClass, 205 $activeTitle = this.elements.$tabTitles.filter(activeFilter), 206 $activeContent = this.elements.$tabContents.filter(activeFilter); 207 $activeTitle.add($activeContent).removeClass(activeClass); 208 $activeTitle.attr({ 209 tabindex: '-1', 210 'aria-selected': 'false', 211 'aria-expanded': 'false' 212 }); 213 $activeContent[settings.hideTabFn](); 214 $activeContent.attr('hidden', 'hidden'); 215 } 216 217 activateTab(tabIndex) { 218 const settings = this.getSettings(), 219 activeClass = settings.classes.active, 220 $requestedTitle = this.elements.$tabTitles.filter('[data-tab="' + tabIndex + '"]'), 221 $requestedContent = this.elements.$tabContents.filter('[data-tab="' + tabIndex + '"]'), 222 animationDuration = 'show' === settings.showTabFn ? 0 : 400; 223 $requestedTitle.add($requestedContent).addClass(activeClass); 224 $requestedTitle.attr({ 225 tabindex: '0', 226 'aria-selected': 'true', 227 'aria-expanded': 'true' 228 }); 229 $requestedContent[settings.showTabFn](animationDuration, () => elementorFrontend.elements.$window.trigger('resize')); 230 $requestedContent.removeAttr('hidden'); 231 } 232 233 isActiveTab(tabIndex) { 234 return this.elements.$tabTitles.filter('[data-tab="' + tabIndex + '"]').hasClass(this.getSettings('classes.active')); 235 } 236 237 bindEvents() { 238 this.elements.$tabTitles.on({ 239 keydown: event => { 240 // Support for old markup that includes an `<a>` tag in the tab 241 if (jQuery(event.target).is('a') && `Enter` === event.key) { 242 event.preventDefault(); 243 } // We listen to keydowon event for these keys in order to prevent undesired page scrolling 244 245 246 if (['End', 'Home', 'ArrowUp', 'ArrowDown'].includes(event.key)) { 247 this.handleKeyboardNavigation(event); 248 } 249 }, 250 keyup: event => { 251 switch (event.key) { 252 case 'ArrowLeft': 253 case 'ArrowRight': 254 this.handleKeyboardNavigation(event); 255 break; 256 257 case 'Enter': 258 case 'Space': 259 event.preventDefault(); 260 this.changeActiveTab(event.currentTarget.getAttribute('data-tab')); 261 break; 262 } 263 }, 264 click: event => { 265 event.preventDefault(); 266 this.changeActiveTab(event.currentTarget.getAttribute('data-tab')); 267 } 268 }); 269 } 270 271 onInit(...args) { 272 super.onInit(...args); 273 this.activateDefaultTab(); 274 } 275 276 onEditSettingsChange(propertyName) { 277 if ('activeItemIndex' === propertyName) { 278 this.activateDefaultTab(); 279 } 280 } 281 282 changeActiveTab(tabIndex) { 283 const isActiveTab = this.isActiveTab(tabIndex), 284 settings = this.getSettings(); 285 286 if ((settings.toggleSelf || !isActiveTab) && settings.hidePrevious) { 287 this.deactivateActiveTab(); 288 } 289 290 if (!settings.hidePrevious && isActiveTab) { 291 this.deactivateActiveTab(tabIndex); 292 } 293 294 if (!isActiveTab) { 295 this.activateTab(tabIndex); 296 } 297 } 298 299 } 300 301 exports.default = baseTabs; 302 303 /***/ }), 304 305 /***/ "../assets/dev/js/frontend/handlers/counter.js": 306 /*!*****************************************************!*\ 307 !*** ../assets/dev/js/frontend/handlers/counter.js ***! 308 \*****************************************************/ 309 /***/ ((__unused_webpack_module, exports) => { 310 311 "use strict"; 312 313 314 Object.defineProperty(exports, "__esModule", ({ 315 value: true 316 })); 317 exports.default = void 0; 318 319 class Counter extends elementorModules.frontend.handlers.Base { 320 getDefaultSettings() { 321 return { 322 selectors: { 323 counterNumber: '.elementor-counter-number' 324 } 325 }; 326 } 327 328 getDefaultElements() { 329 const selectors = this.getSettings('selectors'); 330 return { 331 $counterNumber: this.$element.find(selectors.counterNumber) 332 }; 333 } 334 335 onInit() { 336 super.onInit(); 337 elementorFrontend.waypoint(this.elements.$counterNumber, () => { 338 const data = this.elements.$counterNumber.data(), 339 decimalDigits = data.toValue.toString().match(/\.(.*)/); 340 341 if (decimalDigits) { 342 data.rounding = decimalDigits[1].length; 343 } 344 345 this.elements.$counterNumber.numerator(data); 346 }); 347 } 348 349 } 350 351 exports.default = Counter; 352 353 /***/ }), 354 355 /***/ "../assets/dev/js/frontend/handlers/image-carousel.js": 356 /*!************************************************************!*\ 357 !*** ../assets/dev/js/frontend/handlers/image-carousel.js ***! 358 \************************************************************/ 359 /***/ ((__unused_webpack_module, exports) => { 360 361 "use strict"; 362 363 364 Object.defineProperty(exports, "__esModule", ({ 365 value: true 366 })); 367 exports.default = void 0; 368 369 class ImageCarousel extends elementorModules.frontend.handlers.SwiperBase { 370 getDefaultSettings() { 371 return { 372 selectors: { 373 carousel: '.elementor-image-carousel-wrapper', 374 slideContent: '.swiper-slide' 375 } 376 }; 377 } 378 379 getDefaultElements() { 380 const selectors = this.getSettings('selectors'); 381 const elements = { 382 $swiperContainer: this.$element.find(selectors.carousel) 383 }; 384 elements.$slides = elements.$swiperContainer.find(selectors.slideContent); 385 return elements; 386 } 387 388 getSwiperSettings() { 389 const elementSettings = this.getElementSettings(), 390 slidesToShow = +elementSettings.slides_to_show || 3, 391 isSingleSlide = 1 === slidesToShow, 392 elementorBreakpoints = elementorFrontend.config.responsive.activeBreakpoints, 393 defaultSlidesToShowMap = { 394 mobile: 1, 395 tablet: isSingleSlide ? 1 : 2 396 }; 397 const swiperOptions = { 398 slidesPerView: slidesToShow, 399 loop: 'yes' === elementSettings.infinite, 400 speed: elementSettings.speed, 401 handleElementorBreakpoints: true 402 }; 403 swiperOptions.breakpoints = {}; 404 let lastBreakpointSlidesToShowValue = slidesToShow; 405 Object.keys(elementorBreakpoints).reverse().forEach(breakpointName => { 406 // Tablet has a specific default `slides_to_show`. 407 const defaultSlidesToShow = defaultSlidesToShowMap[breakpointName] ? defaultSlidesToShowMap[breakpointName] : lastBreakpointSlidesToShowValue; 408 swiperOptions.breakpoints[elementorBreakpoints[breakpointName].value] = { 409 slidesPerView: +elementSettings['slides_to_show_' + breakpointName] || defaultSlidesToShow, 410 slidesPerGroup: +elementSettings['slides_to_scroll_' + breakpointName] || 1 411 }; 412 lastBreakpointSlidesToShowValue = +elementSettings['slides_to_show_' + breakpointName] || defaultSlidesToShow; 413 }); 414 415 if ('yes' === elementSettings.autoplay) { 416 swiperOptions.autoplay = { 417 delay: elementSettings.autoplay_speed, 418 disableOnInteraction: 'yes' === elementSettings.pause_on_interaction 419 }; 420 } 421 422 if (isSingleSlide) { 423 swiperOptions.effect = elementSettings.effect; 424 425 if ('fade' === elementSettings.effect) { 426 swiperOptions.fadeEffect = { 427 crossFade: true 428 }; 429 } 430 } else { 431 swiperOptions.slidesPerGroup = +elementSettings.slides_to_scroll || 1; 432 } 433 434 if (elementSettings.image_spacing_custom) { 435 swiperOptions.spaceBetween = elementSettings.image_spacing_custom.size; 436 } 437 438 const showArrows = 'arrows' === elementSettings.navigation || 'both' === elementSettings.navigation, 439 showDots = 'dots' === elementSettings.navigation || 'both' === elementSettings.navigation; 440 441 if (showArrows) { 442 swiperOptions.navigation = { 443 prevEl: '.elementor-swiper-button-prev', 444 nextEl: '.elementor-swiper-button-next' 445 }; 446 } 447 448 if (showDots) { 449 swiperOptions.pagination = { 450 el: '.swiper-pagination', 451 type: 'bullets', 452 clickable: true 453 }; 454 } 455 456 return swiperOptions; 457 } 458 459 async onInit(...args) { 460 super.onInit(...args); 461 const elementSettings = this.getElementSettings(); 462 463 if (!this.elements.$swiperContainer.length || 2 > this.elements.$slides.length) { 464 return; 465 } 466 467 const Swiper = elementorFrontend.utils.swiper; 468 this.swiper = await new Swiper(this.elements.$swiperContainer, this.getSwiperSettings()); // Expose the swiper instance in the frontend 469 470 this.elements.$swiperContainer.data('swiper', this.swiper); 471 472 if ('yes' === elementSettings.pause_on_hover) { 473 this.togglePauseOnHover(true); 474 } 475 } 476 477 updateSwiperOption(propertyName) { 478 const elementSettings = this.getElementSettings(), 479 newSettingValue = elementSettings[propertyName], 480 params = this.swiper.params; // Handle special cases where the value to update is not the value that the Swiper library accepts. 481 482 switch (propertyName) { 483 case 'image_spacing_custom': 484 params.spaceBetween = newSettingValue.size || 0; 485 break; 486 487 case 'autoplay_speed': 488 params.autoplay.delay = newSettingValue; 489 break; 490 491 case 'speed': 492 params.speed = newSettingValue; 493 break; 494 } 495 496 this.swiper.update(); 497 } 498 499 getChangeableProperties() { 500 return { 501 pause_on_hover: 'pauseOnHover', 502 autoplay_speed: 'delay', 503 speed: 'speed', 504 image_spacing_custom: 'spaceBetween' 505 }; 506 } 507 508 onElementChange(propertyName) { 509 const changeableProperties = this.getChangeableProperties(); 510 511 if (changeableProperties[propertyName]) { 512 // 'pause_on_hover' is implemented by the handler with event listeners, not the Swiper library. 513 if ('pause_on_hover' === propertyName) { 514 const newSettingValue = this.getElementSettings('pause_on_hover'); 515 this.togglePauseOnHover('yes' === newSettingValue); 516 } else { 517 this.updateSwiperOption(propertyName); 518 } 519 } 520 } 521 522 onEditSettingsChange(propertyName) { 523 if ('activeItemIndex' === propertyName) { 524 this.swiper.slideToLoop(this.getEditSettings('activeItemIndex') - 1); 525 } 526 } 527 528 } 529 530 exports.default = ImageCarousel; 531 532 /***/ }), 533 534 /***/ "../assets/dev/js/frontend/handlers/progress.js": 535 /*!******************************************************!*\ 536 !*** ../assets/dev/js/frontend/handlers/progress.js ***! 537 \******************************************************/ 538 /***/ ((__unused_webpack_module, exports) => { 539 540 "use strict"; 541 542 543 Object.defineProperty(exports, "__esModule", ({ 544 value: true 545 })); 546 exports.default = void 0; 547 548 class Progress extends elementorModules.frontend.handlers.Base { 549 getDefaultSettings() { 550 return { 551 selectors: { 552 progressNumber: '.elementor-progress-bar' 553 } 554 }; 555 } 556 557 getDefaultElements() { 558 const selectors = this.getSettings('selectors'); 559 return { 560 $progressNumber: this.$element.find(selectors.progressNumber) 561 }; 562 } 563 564 onInit() { 565 super.onInit(); 566 elementorFrontend.waypoint(this.elements.$progressNumber, () => { 567 const $progressbar = this.elements.$progressNumber; 568 $progressbar.css('width', $progressbar.data('max') + '%'); 569 }); 570 } 571 572 } 573 574 exports.default = Progress; 575 576 /***/ }), 577 578 /***/ "../assets/dev/js/frontend/handlers/tabs.js": 579 /*!**************************************************!*\ 580 !*** ../assets/dev/js/frontend/handlers/tabs.js ***! 581 \**************************************************/ 582 /***/ ((__unused_webpack_module, exports, __webpack_require__) => { 583 584 "use strict"; 585 586 587 var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js"); 588 589 Object.defineProperty(exports, "__esModule", ({ 590 value: true 591 })); 592 exports.default = void 0; 593 594 var _baseTabs = _interopRequireDefault(__webpack_require__(/*! ./base-tabs */ "../assets/dev/js/frontend/handlers/base-tabs.js")); 595 596 class Tabs extends _baseTabs.default { 597 getDefaultSettings() { 598 const defaultSettings = super.getDefaultSettings(); 599 return { ...defaultSettings, 600 toggleSelf: false 601 }; 602 } 603 604 } 605 606 exports.default = Tabs; 607 608 /***/ }), 609 610 /***/ "../assets/dev/js/frontend/handlers/text-editor.js": 611 /*!*********************************************************!*\ 612 !*** ../assets/dev/js/frontend/handlers/text-editor.js ***! 613 \*********************************************************/ 614 /***/ ((__unused_webpack_module, exports) => { 615 616 "use strict"; 617 618 619 Object.defineProperty(exports, "__esModule", ({ 620 value: true 621 })); 622 exports.default = void 0; 623 624 class TextEditor extends elementorModules.frontend.handlers.Base { 625 getDefaultSettings() { 626 return { 627 selectors: { 628 paragraph: 'p:first' 629 }, 630 classes: { 631 dropCap: 'elementor-drop-cap', 632 dropCapLetter: 'elementor-drop-cap-letter' 633 } 634 }; 635 } 636 637 getDefaultElements() { 638 const selectors = this.getSettings('selectors'), 639 classes = this.getSettings('classes'), 640 $dropCap = jQuery('<span>', { 641 class: classes.dropCap 642 }), 643 $dropCapLetter = jQuery('<span>', { 644 class: classes.dropCapLetter 645 }); 646 $dropCap.append($dropCapLetter); 647 return { 648 $paragraph: this.$element.find(selectors.paragraph), 649 $dropCap: $dropCap, 650 $dropCapLetter: $dropCapLetter 651 }; 652 } 653 654 wrapDropCap() { 655 const isDropCapEnabled = this.getElementSettings('drop_cap'); 656 657 if (!isDropCapEnabled) { 658 // If there is an old drop cap inside the paragraph 659 if (this.dropCapLetter) { 660 this.elements.$dropCap.remove(); 661 this.elements.$paragraph.prepend(this.dropCapLetter); 662 this.dropCapLetter = ''; 663 } 664 665 return; 666 } 667 668 const $paragraph = this.elements.$paragraph; 669 670 if (!$paragraph.length) { 671 return; 672 } 673 674 const paragraphContent = $paragraph.html().replace(/ /g, ' '), 675 firstLetterMatch = paragraphContent.match(/^ *([^ ] ?)/); 676 677 if (!firstLetterMatch) { 678 return; 679 } 680 681 const firstLetter = firstLetterMatch[1], 682 trimmedFirstLetter = firstLetter.trim(); // Don't apply drop cap when the content starting with an HTML tag 683 684 if ('<' === trimmedFirstLetter) { 685 return; 686 } 687 688 this.dropCapLetter = firstLetter; 689 this.elements.$dropCapLetter.text(trimmedFirstLetter); 690 const restoredParagraphContent = paragraphContent.slice(firstLetter.length).replace(/^ */, match => { 691 return new Array(match.length + 1).join(' '); 692 }); 693 $paragraph.html(restoredParagraphContent).prepend(this.elements.$dropCap); 694 } 695 696 onInit(...args) { 697 super.onInit(...args); 698 this.wrapDropCap(); 699 } 700 701 onElementChange(propertyName) { 702 if ('drop_cap' === propertyName) { 703 this.wrapDropCap(); 704 } 705 } 706 707 } 708 709 exports.default = TextEditor; 710 711 /***/ }), 712 713 /***/ "../assets/dev/js/frontend/handlers/toggle.js": 714 /*!****************************************************!*\ 715 !*** ../assets/dev/js/frontend/handlers/toggle.js ***! 716 \****************************************************/ 717 /***/ ((__unused_webpack_module, exports, __webpack_require__) => { 718 719 "use strict"; 720 721 722 var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js"); 723 724 Object.defineProperty(exports, "__esModule", ({ 725 value: true 726 })); 727 exports.default = void 0; 728 729 var _baseTabs = _interopRequireDefault(__webpack_require__(/*! ./base-tabs */ "../assets/dev/js/frontend/handlers/base-tabs.js")); 730 731 class Toggle extends _baseTabs.default { 732 getDefaultSettings() { 733 const defaultSettings = super.getDefaultSettings(); 734 return { ...defaultSettings, 735 showTabFn: 'slideDown', 736 hideTabFn: 'slideUp', 737 hidePrevious: false, 738 autoExpand: 'editor' 739 }; 740 } 741 742 } 743 744 exports.default = Toggle; 745 746 /***/ }), 747 748 /***/ "../assets/dev/js/frontend/handlers/video.js": 749 /*!***************************************************!*\ 750 !*** ../assets/dev/js/frontend/handlers/video.js ***! 751 \***************************************************/ 752 /***/ ((__unused_webpack_module, exports) => { 753 754 "use strict"; 755 756 757 Object.defineProperty(exports, "__esModule", ({ 758 value: true 759 })); 760 exports.default = void 0; 761 762 class Video extends elementorModules.frontend.handlers.Base { 763 getDefaultSettings() { 764 return { 765 selectors: { 766 imageOverlay: '.elementor-custom-embed-image-overlay', 767 video: '.elementor-video', 768 videoIframe: '.elementor-video-iframe' 769 } 770 }; 771 } 772 773 getDefaultElements() { 774 const selectors = this.getSettings('selectors'); 775 return { 776 $imageOverlay: this.$element.find(selectors.imageOverlay), 777 $video: this.$element.find(selectors.video), 778 $videoIframe: this.$element.find(selectors.videoIframe) 779 }; 780 } 781 782 handleVideo() { 783 if (this.getElementSettings('lightbox')) { 784 return; 785 } 786 787 if ('youtube' === this.getElementSettings('video_type')) { 788 this.apiProvider.onApiReady(apiObject => { 789 this.elements.$imageOverlay.remove(); 790 this.prepareYTVideo(apiObject, true); 791 }); 792 } else { 793 this.elements.$imageOverlay.remove(); 794 this.playVideo(); 795 } 796 } 797 798 playVideo() { 799 if (this.elements.$video.length) { 800 // this.youtubePlayer exists only for YouTube videos, and its play function is different. 801 if (this.youtubePlayer) { 802 this.youtubePlayer.playVideo(); 803 } else { 804 this.elements.$video[0].play(); 805 } 806 807 return; 808 } 809 810 const $videoIframe = this.elements.$videoIframe, 811 lazyLoad = $videoIframe.data('lazy-load'); 812 813 if (lazyLoad) { 814 $videoIframe.attr('src', lazyLoad); 815 } 816 817 $videoIframe[0].src = this.apiProvider.getAutoplayURL($videoIframe[0].src); 818 } 819 820 async animateVideo() { 821 const lightbox = await elementorFrontend.utils.lightbox; 822 lightbox.setEntranceAnimation(this.getCurrentDeviceSetting('lightbox_content_animation')); 823 } 824 825 async handleAspectRatio() { 826 const lightbox = await elementorFrontend.utils.lightbox; 827 lightbox.setVideoAspectRatio(this.getElementSettings('aspect_ratio')); 828 } 829 830 async hideLightbox() { 831 const lightbox = await elementorFrontend.utils.lightbox; 832 lightbox.getModal().hide(); 833 } 834 835 prepareYTVideo(YT, onOverlayClick) { 836 const elementSettings = this.getElementSettings(), 837 playerOptions = { 838 videoId: this.videoID, 839 events: { 840 onReady: () => { 841 if (elementSettings.mute) { 842 this.youtubePlayer.mute(); 843 } 844 845 if (elementSettings.autoplay || onOverlayClick) { 846 this.youtubePlayer.playVideo(); 847 } 848 }, 849 onStateChange: event => { 850 if (event.data === YT.PlayerState.ENDED && elementSettings.loop) { 851 this.youtubePlayer.seekTo(elementSettings.start || 0); 852 } 853 } 854 }, 855 playerVars: { 856 controls: elementSettings.controls ? 1 : 0, 857 rel: elementSettings.rel ? 1 : 0, 858 playsinline: elementSettings.play_on_mobile ? 1 : 0, 859 modestbranding: elementSettings.modestbranding ? 1 : 0, 860 autoplay: elementSettings.autoplay ? 1 : 0, 861 start: elementSettings.start, 862 end: elementSettings.end 863 } 864 }; // To handle CORS issues, when the default host is changed, the origin parameter has to be set. 865 866 if (elementSettings.yt_privacy) { 867 playerOptions.host = 'https://www.youtube-nocookie.com'; 868 playerOptions.origin = window.location.hostname; 869 } 870 871 this.youtubePlayer = new YT.Player(this.elements.$video[0], playerOptions); 872 } 873 874 bindEvents() { 875 this.elements.$imageOverlay.on('click', this.handleVideo.bind(this)); 876 } 877 878 onInit() { 879 super.onInit(); 880 const elementSettings = this.getElementSettings(); 881 882 if (elementorFrontend.utils[elementSettings.video_type]) { 883 this.apiProvider = elementorFrontend.utils[elementSettings.video_type]; 884 } else { 885 this.apiProvider = elementorFrontend.utils.baseVideoLoader; 886 } 887 888 if ('youtube' !== elementSettings.video_type) { 889 // Currently the only API integration in the Video widget is for the YT API 890 return; 891 } 892 893 this.videoID = this.apiProvider.getVideoIDFromURL(elementSettings.youtube_url); // If there is an image overlay, the YouTube video prep method will be triggered on click 894 895 if (!this.videoID) { 896 return; 897 } // If the user is using an image overlay, loading the API happens on overlay click instead of on init. 898 899 900 if (elementSettings.show_image_overlay && elementSettings.image_overlay.url) { 901 return; 902 } 903 904 if (elementSettings.lazy_load) { 905 this.intersectionObserver = elementorModules.utils.Scroll.scrollObserver({ 906 callback: event => { 907 if (event.isInViewport) { 908 this.intersectionObserver.unobserve(this.elements.$video.parent()[0]); 909 this.apiProvider.onApiReady(apiObject => this.prepareYTVideo(apiObject)); 910 } 911 } 912 }); // We observe the parent, since the video container has a height of 0. 913 914 this.intersectionObserver.observe(this.elements.$video.parent()[0]); 915 return; 916 } // When Optimized asset loading is set to off, the video type is set to 'Youtube', and 'Privacy Mode' is set 917 // to 'On', there might be a conflict with other videos that are loaded WITHOUT privacy mode, such as a 918 // video bBackground in a section. In these cases, to avoid the conflict, a timeout is added to postpone the 919 // initialization of the Youtube API object. 920 921 922 if (!elementorFrontend.config.experimentalFeatures['e_optimized_assets_loading']) { 923 setTimeout(() => { 924 this.apiProvider.onApiReady(apiObject => this.prepareYTVideo(apiObject)); 925 }, 0); 926 } else { 927 this.apiProvider.onApiReady(apiObject => this.prepareYTVideo(apiObject)); 928 } 929 } 930 931 onElementChange(propertyName) { 932 if (0 === propertyName.indexOf('lightbox_content_animation')) { 933 this.animateVideo(); 934 return; 935 } 936 937 const isLightBoxEnabled = this.getElementSettings('lightbox'); 938 939 if ('lightbox' === propertyName && !isLightBoxEnabled) { 940 this.hideLightbox(); 941 return; 942 } 943 944 if ('aspect_ratio' === propertyName && isLightBoxEnabled) { 945 this.handleAspectRatio(); 946 } 947 } 948 949 } 950 951 exports.default = Video; 952 953 /***/ }), 954 955 /***/ "../assets/dev/js/frontend/preloaded-modules.js": 956 /*!******************************************************!*\ 957 !*** ../assets/dev/js/frontend/preloaded-modules.js ***! 958 \******************************************************/ 959 /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { 960 961 "use strict"; 962 963 964 var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js"); 965 966 var _accordion = _interopRequireDefault(__webpack_require__(/*! ./handlers/accordion */ "../assets/dev/js/frontend/handlers/accordion.js")); 967 968 var _alert = _interopRequireDefault(__webpack_require__(/*! ./handlers/alert */ "../assets/dev/js/frontend/handlers/alert.js")); 969 970 var _counter = _interopRequireDefault(__webpack_require__(/*! ./handlers/counter */ "../assets/dev/js/frontend/handlers/counter.js")); 971 972 var _progress = _interopRequireDefault(__webpack_require__(/*! ./handlers/progress */ "../assets/dev/js/frontend/handlers/progress.js")); 973 974 var _tabs = _interopRequireDefault(__webpack_require__(/*! ./handlers/tabs */ "../assets/dev/js/frontend/handlers/tabs.js")); 975 976 var _toggle = _interopRequireDefault(__webpack_require__(/*! ./handlers/toggle */ "../assets/dev/js/frontend/handlers/toggle.js")); 977 978 var _video = _interopRequireDefault(__webpack_require__(/*! ./handlers/video */ "../assets/dev/js/frontend/handlers/video.js")); 979 980 var _imageCarousel = _interopRequireDefault(__webpack_require__(/*! ./handlers/image-carousel */ "../assets/dev/js/frontend/handlers/image-carousel.js")); 981 982 var _textEditor = _interopRequireDefault(__webpack_require__(/*! ./handlers/text-editor */ "../assets/dev/js/frontend/handlers/text-editor.js")); 983 984 var _lightbox = _interopRequireDefault(__webpack_require__(/*! elementor-frontend/utils/lightbox/lightbox */ "../assets/dev/js/frontend/utils/lightbox/lightbox.js")); 985 986 elementorFrontend.elements.$window.on('elementor/frontend/init', () => { 987 elementorFrontend.elementsHandler.elementsHandlers = { 988 'accordion.default': _accordion.default, 989 'alert.default': _alert.default, 990 'counter.default': _counter.default, 991 'progress.default': _progress.default, 992 'tabs.default': _tabs.default, 993 'toggle.default': _toggle.default, 994 'video.default': _video.default, 995 'image-carousel.default': _imageCarousel.default, 996 'text-editor.default': _textEditor.default 997 }; 998 elementorFrontend.on('components:init', () => { 999 // We first need to delete the property because by default it's a getter function that cannot be overwritten. 1000 delete elementorFrontend.utils.lightbox; 1001 elementorFrontend.utils.lightbox = new _lightbox.default(); 1002 }); 1003 }); 1004 1005 /***/ }), 1006 1007 /***/ "../assets/dev/js/frontend/utils/lightbox/lightbox.js": 1008 /*!************************************************************!*\ 1009 !*** ../assets/dev/js/frontend/utils/lightbox/lightbox.js ***! 1010 \************************************************************/ 1011 /***/ ((module, __unused_webpack_exports, __webpack_require__) => { 1012 1013 "use strict"; 1014 1015 1016 var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js"); 1017 1018 var _screenfull = _interopRequireDefault(__webpack_require__(/*! ./screenfull */ "../assets/dev/js/frontend/utils/lightbox/screenfull.js")); 1019 1020 module.exports = elementorModules.ViewModule.extend({ 1021 oldAspectRatio: null, 1022 oldAnimation: null, 1023 swiper: null, 1024 player: null, 1025 getDefaultSettings: function () { 1026 return { 1027 classes: { 1028 aspectRatio: 'elementor-aspect-ratio-%s', 1029 item: 'elementor-lightbox-item', 1030 image: 'elementor-lightbox-image', 1031 videoContainer: 'elementor-video-container', 1032 videoWrapper: 'elementor-fit-aspect-ratio', 1033 playButton: 'elementor-custom-embed-play', 1034 playButtonIcon: 'fa', 1035 playing: 'elementor-playing', 1036 hidden: 'elementor-hidden', 1037 invisible: 'elementor-invisible', 1038 preventClose: 'elementor-lightbox-prevent-close', 1039 slideshow: { 1040 container: 'swiper-container', 1041 slidesWrapper: 'swiper-wrapper', 1042 prevButton: 'elementor-swiper-button elementor-swiper-button-prev', 1043 nextButton: 'elementor-swiper-button elementor-swiper-button-next', 1044 prevButtonIcon: 'eicon-chevron-left', 1045 nextButtonIcon: 'eicon-chevron-right', 1046 slide: 'swiper-slide', 1047 header: 'elementor-slideshow__header', 1048 footer: 'elementor-slideshow__footer', 1049 title: 'elementor-slideshow__title', 1050 description: 'elementor-slideshow__description', 1051 counter: 'elementor-slideshow__counter', 1052 iconExpand: 'eicon-frame-expand', 1053 iconShrink: 'eicon-frame-minimize', 1054 iconZoomIn: 'eicon-zoom-in-bold', 1055 iconZoomOut: 'eicon-zoom-out-bold', 1056 iconShare: 'eicon-share-arrow', 1057 shareMenu: 'elementor-slideshow__share-menu', 1058 shareLinks: 'elementor-slideshow__share-links', 1059 hideUiVisibility: 'elementor-slideshow--ui-hidden', 1060 shareMode: 'elementor-slideshow--share-mode', 1061 fullscreenMode: 'elementor-slideshow--fullscreen-mode', 1062 zoomMode: 'elementor-slideshow--zoom-mode' 1063 } 1064 }, 1065 selectors: { 1066 image: '.elementor-lightbox-image', 1067 links: 'a, [data-elementor-lightbox]', 1068 slideshow: { 1069 activeSlide: '.swiper-slide-active', 1070 prevSlide: '.swiper-slide-prev', 1071 nextSlide: '.swiper-slide-next' 1072 } 1073 }, 1074 modalOptions: { 1075 id: 'elementor-lightbox', 1076 entranceAnimation: 'zoomIn', 1077 videoAspectRatio: 169, 1078 position: { 1079 enable: false 1080 } 1081 } 1082 }; 1083 }, 1084 getModal: function () { 1085 if (!module.exports.modal) { 1086 this.initModal(); 1087 } 1088 1089 return module.exports.modal; 1090 }, 1091 initModal: function () { 1092 const modal = module.exports.modal = elementorFrontend.getDialogsManager().createWidget('lightbox', { 1093 className: 'elementor-lightbox', 1094 closeButton: true, 1095 closeButtonOptions: { 1096 iconClass: 'eicon-close', 1097 attributes: { 1098 tabindex: 0, 1099 role: 'button', 1100 'aria-label': elementorFrontend.config.i18n.close + ' (Esc)' 1101 } 1102 }, 1103 selectors: { 1104 preventClose: '.' + this.getSettings('classes.preventClose') 1105 }, 1106 hide: { 1107 onClick: true 1108 } 1109 }); 1110 modal.on('hide', function () { 1111 modal.setMessage(''); 1112 }); 1113 }, 1114 showModal: function (options) { 1115 if (options.url && !options.url.startsWith('http')) { 1116 return; 1117 } 1118 1119 this.elements.$closeButton = this.getModal().getElements('closeButton'); 1120 this.$buttons = this.elements.$closeButton; 1121 this.focusedButton = null; 1122 const self = this, 1123 defaultOptions = self.getDefaultSettings().modalOptions; 1124 self.id = options.id; 1125 self.setSettings('modalOptions', jQuery.extend(defaultOptions, options.modalOptions)); 1126 const modal = self.getModal(); 1127 modal.setID(self.getSettings('modalOptions.id')); 1128 1129 modal.onShow = function () { 1130 DialogsManager.getWidgetType('lightbox').prototype.onShow.apply(modal, arguments); 1131 self.setEntranceAnimation(); 1132 }; 1133 1134 modal.onHide = function () { 1135 DialogsManager.getWidgetType('lightbox').prototype.onHide.apply(modal, arguments); 1136 modal.getElements('message').removeClass('animated'); 1137 1138 if (_screenfull.default.isFullscreen) { 1139 self.deactivateFullscreen(); 1140 } 1141 1142 self.unbindHotKeys(); 1143 }; 1144 1145 switch (options.type) { 1146 case 'video': 1147 self.setVideoContent(options); 1148 break; 1149 1150 case 'image': 1151 const slides = [{ 1152 image: options.url, 1153 index: 0, 1154 title: options.title, 1155 description: options.description 1156 }]; 1157 options.slideshow = { 1158 slides, 1159 swiper: { 1160 loop: false, 1161 pagination: false 1162 } 1163 }; 1164 1165 case 'slideshow': 1166 self.setSlideshowContent(options.slideshow); 1167 break; 1168 1169 default: 1170 self.setHTMLContent(options.html); 1171 } 1172 1173 modal.show(); 1174 }, 1175 createLightbox: function (element) { 1176 let lightboxData = {}; 1177 1178 if (element.dataset.elementorLightbox) { 1179 lightboxData = JSON.parse(element.dataset.elementorLightbox); 1180 } 1181 1182 if (lightboxData.type && 'slideshow' !== lightboxData.type) { 1183 this.showModal(lightboxData); 1184 return; 1185 } 1186 1187 if (!element.dataset.elementorLightboxSlideshow) { 1188 const slideshowID = 'single-img'; 1189 this.showModal({ 1190 type: 'image', 1191 id: slideshowID, 1192 url: element.href, 1193 title: element.dataset.elementorLightboxTitle, 1194 description: element.dataset.elementorLightboxDescription, 1195 modalOptions: { 1196 id: 'elementor-lightbox-slideshow-' + slideshowID 1197 } 1198 }); 1199 return; 1200 } 1201 1202 const initialSlideURL = element.dataset.elementorLightboxVideo || element.href; 1203 this.openSlideshow(element.dataset.elementorLightboxSlideshow, initialSlideURL); 1204 }, 1205 setHTMLContent: function (html) { 1206 if (window.elementorCommon) { 1207 elementorCommon.helpers.hardDeprecated('elementorFrontend.utils.lightbox.setHTMLContent', '3.1.4'); 1208 } 1209 1210 this.getModal().setMessage(html); 1211 }, 1212 setVideoContent: function (options) { 1213 const $ = jQuery, 1214 classes = this.getSettings('classes'), 1215 $videoContainer = $('<div>', { 1216 class: `${classes.videoContainer} ${classes.preventClose}` 1217 }), 1218 $videoWrapper = $('<div>', { 1219 class: classes.videoWrapper 1220 }), 1221 modal = this.getModal(); 1222 let $videoElement; 1223 1224 if ('hosted' === options.videoType) { 1225 const videoParams = $.extend({ 1226 src: options.url, 1227 autoplay: '' 1228 }, options.videoParams); 1229 $videoElement = $('<video>', videoParams); 1230 } else { 1231 let apiProvider = elementorFrontend.utils.baseVideoLoader; 1232 1233 if (-1 !== options.url.indexOf('vimeo.com')) { 1234 apiProvider = elementorFrontend.utils.vimeo; 1235 } else if (options.url.match(/^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com)/)) { 1236 apiProvider = elementorFrontend.utils.youtube; 1237 } 1238 1239 $videoElement = $('<iframe>', { 1240 src: apiProvider.getAutoplayURL(options.url), 1241 allowfullscreen: 1 1242 }); 1243 } 1244 1245 $videoContainer.append($videoWrapper); 1246 $videoWrapper.append($videoElement); 1247 modal.setMessage($videoContainer); 1248 this.setVideoAspectRatio(); 1249 const onHideMethod = modal.onHide; 1250 1251 modal.onHide = function () { 1252 onHideMethod(); 1253 this.$buttons = jQuery(); 1254 this.focusedButton = null; 1255 modal.getElements('message').removeClass('elementor-fit-aspect-ratio'); 1256 }; 1257 }, 1258 getShareLinks: function () { 1259 const { 1260 i18n 1261 } = elementorFrontend.config, 1262 socialNetworks = { 1263 facebook: i18n.shareOnFacebook, 1264 twitter: i18n.shareOnTwitter, 1265 pinterest: i18n.pinIt 1266 }, 1267 $ = jQuery, 1268 classes = this.getSettings('classes'), 1269 selectors = this.getSettings('selectors'), 1270 $linkList = $('<div>', { 1271 class: classes.slideshow.shareLinks 1272 }), 1273 $activeSlide = this.getSlide('active'), 1274 $image = $activeSlide.find(selectors.image), 1275 videoUrl = $activeSlide.data('elementor-slideshow-video'); 1276 let itemUrl; 1277 1278 if (videoUrl) { 1279 itemUrl = videoUrl; 1280 } else { 1281 itemUrl = $image.attr('src'); 1282 } 1283 1284 $.each(socialNetworks, (key, networkLabel) => { 1285 const $link = $('<a>', { 1286 href: this.createShareLink(key, itemUrl), 1287 target: '_blank' 1288 }).text(networkLabel); 1289 $link.prepend($('<i>', { 1290 class: 'eicon-' + key 1291 })); 1292 $linkList.append($link); 1293 }); 1294 1295 if (!videoUrl) { 1296 $linkList.append($('<a>', { 1297 href: itemUrl, 1298 download: '' 1299 }).text(i18n.downloadImage).prepend($('<i>', { 1300 class: 'eicon-download-bold', 1301 'aria-label': i18n.download 1302 }))); 1303 } 1304 1305 return $linkList; 1306 }, 1307 createShareLink: function (networkName, itemUrl) { 1308 const options = {}; 1309 1310 if ('pinterest' === networkName) { 1311 options.image = encodeURIComponent(itemUrl); 1312 } else { 1313 const hash = elementorFrontend.utils.urlActions.createActionHash('lightbox', { 1314 id: this.id, 1315 url: itemUrl 1316 }); 1317 options.url = encodeURIComponent(location.href.replace(/#.*/, '')) + hash; 1318 } 1319 1320 return ShareLink.getNetworkLink(networkName, options); 1321 }, 1322 getSlideshowHeader: function () { 1323 const { 1324 i18n 1325 } = elementorFrontend.config, 1326 $ = jQuery, 1327 showCounter = 'yes' === elementorFrontend.getKitSettings('lightbox_enable_counter'), 1328 showFullscreen = 'yes' === elementorFrontend.getKitSettings('lightbox_enable_fullscreen'), 1329 showZoom = 'yes' === elementorFrontend.getKitSettings('lightbox_enable_zoom'), 1330 showShare = 'yes' === elementorFrontend.getKitSettings('lightbox_enable_share'), 1331 classes = this.getSettings('classes'), 1332 slideshowClasses = classes.slideshow, 1333 elements = this.elements; 1334 1335 if (!(showCounter || showFullscreen || showZoom || showShare)) { 1336 return; 1337 } 1338 1339 elements.$header = $('<header>', { 1340 class: slideshowClasses.header + ' ' + classes.preventClose 1341 }); 1342 1343 if (showShare) { 1344 elements.$iconShare = $('<i>', { 1345 class: slideshowClasses.iconShare, 1346 role: 'button', 1347 'aria-label': i18n.share, 1348 'aria-expanded': false 1349 }).append($('<span>')); 1350 const $shareLinks = $('<div>'); 1351 $shareLinks.on('click', e => { 1352 e.stopPropagation(); 1353 }); 1354 elements.$shareMenu = $('<div>', { 1355 class: slideshowClasses.shareMenu 1356 }).append($shareLinks); 1357 elements.$iconShare.add(elements.$shareMenu).on('click', this.toggleShareMenu); 1358 elements.$header.append(elements.$iconShare, elements.$shareMenu); 1359 this.$buttons = this.$buttons.add(elements.$iconShare); 1360 } 1361 1362 if (showZoom) { 1363 elements.$iconZoom = $('<i>', { 1364 class: slideshowClasses.iconZoomIn, 1365 role: 'switch', 1366 'aria-checked': false, 1367 'aria-label': i18n.zoom 1368 }); 1369 elements.$iconZoom.on('click', this.toggleZoomMode); 1370 elements.$header.append(elements.$iconZoom); 1371 this.$buttons = this.$buttons.add(elements.$iconZoom); 1372 } 1373 1374 if (showFullscreen) { 1375 elements.$iconExpand = $('<i>', { 1376 class: slideshowClasses.iconExpand, 1377 role: 'switch', 1378 'aria-checked': false, 1379 'aria-label': i18n.fullscreen 1380 }).append($('<span>'), $('<span>')); 1381 elements.$iconExpand.on('click', this.toggleFullscreen); 1382 elements.$header.append(elements.$iconExpand); 1383 this.$buttons = this.$buttons.add(elements.$iconExpand); 1384 } 1385 1386 if (showCounter) { 1387 elements.$counter = $('<span>', { 1388 class: slideshowClasses.counter 1389 }); 1390 elements.$header.append(elements.$counter); 1391 } 1392 1393 return elements.$header; 1394 }, 1395 toggleFullscreen: function () { 1396 if (_screenfull.default.isFullscreen) { 1397 this.deactivateFullscreen(); 1398 } else if (_screenfull.default.isEnabled) { 1399 this.activateFullscreen(); 1400 } 1401 }, 1402 toggleZoomMode: function () { 1403 if (1 !== this.swiper.zoom.scale) { 1404 this.deactivateZoom(); 1405 } else { 1406 this.activateZoom(); 1407 } 1408 }, 1409 toggleShareMenu: function () { 1410 if (this.shareMode) { 1411 this.deactivateShareMode(); 1412 } else { 1413 this.elements.$shareMenu.html(this.getShareLinks()); 1414 this.activateShareMode(); 1415 } 1416 }, 1417 activateShareMode: function () { 1418 const classes = this.getSettings('classes'); 1419 this.elements.$container.addClass(classes.slideshow.shareMode); 1420 this.elements.$iconShare.attr('aria-expanded', true); // Prevent swiper interactions while in share mode 1421 1422 this.swiper.detachEvents(); // Temporarily replace tabbable buttons with share-menu items 1423 1424 this.$originalButtons = this.$buttons; 1425 this.$buttons = this.elements.$iconShare.add(this.elements.$shareMenu.find('a')); 1426 this.shareMode = true; 1427 }, 1428 deactivateShareMode: function () { 1429 const classes = this.getSettings('classes'); 1430 this.elements.$container.removeClass(classes.slideshow.shareMode); 1431 this.elements.$iconShare.attr('aria-expanded', false); 1432 this.swiper.attachEvents(); 1433 this.$buttons = this.$originalButtons; 1434 this.shareMode = false; 1435 }, 1436 activateFullscreen: function () { 1437 const classes = this.getSettings('classes'); 1438 1439 _screenfull.default.request(this.elements.$container.parents('.dialog-widget')[0]); 1440 1441 this.elements.$iconExpand.removeClass(classes.slideshow.iconExpand).addClass(classes.slideshow.iconShrink).attr('aria-checked', 'true'); 1442 this.elements.$container.addClass(classes.slideshow.fullscreenMode); 1443 }, 1444 deactivateFullscreen: function () { 1445 const classes = this.getSettings('classes'); 1446 1447 _screenfull.default.exit(); 1448 1449 this.elements.$iconExpand.removeClass(classes.slideshow.iconShrink).addClass(classes.slideshow.iconExpand).attr('aria-checked', 'false'); 1450 this.elements.$container.removeClass(classes.slideshow.fullscreenMode); 1451 }, 1452 activateZoom: function () { 1453 const swiper = this.swiper, 1454 elements = this.elements, 1455 classes = this.getSettings('classes'); 1456 swiper.zoom.in(); 1457 swiper.allowSlideNext = false; 1458 swiper.allowSlidePrev = false; 1459 swiper.allowTouchMove = false; 1460 elements.$container.addClass(classes.slideshow.zoomMode); 1461 elements.$iconZoom.removeClass(classes.slideshow.iconZoomIn).addClass(classes.slideshow.iconZoomOut); 1462 }, 1463 deactivateZoom: function () { 1464 const swiper = this.swiper, 1465 elements = this.elements, 1466 classes = this.getSettings('classes'); 1467 swiper.zoom.out(); 1468 swiper.allowSlideNext = true; 1469 swiper.allowSlidePrev = true; 1470 swiper.allowTouchMove = true; 1471 elements.$container.removeClass(classes.slideshow.zoomMode); 1472 elements.$iconZoom.removeClass(classes.slideshow.iconZoomOut).addClass(classes.slideshow.iconZoomIn); 1473 }, 1474 getSlideshowFooter: function () { 1475 const $ = jQuery, 1476 classes = this.getSettings('classes'), 1477 $footer = $('<footer>', { 1478 class: classes.slideshow.footer + ' ' + classes.preventClose 1479 }), 1480 $title = $('<div>', { 1481 class: classes.slideshow.title 1482 }), 1483 $description = $('<div>', { 1484 class: classes.slideshow.description 1485 }); 1486 $footer.append($title, $description); 1487 return $footer; 1488 }, 1489 setSlideshowContent: function (options) { 1490 const { 1491 i18n 1492 } = elementorFrontend.config, 1493 $ = jQuery, 1494 isSingleSlide = 1 === options.slides.length, 1495 hasTitle = '' !== elementorFrontend.getKitSettings('lightbox_title_src'), 1496 hasDescription = '' !== elementorFrontend.getKitSettings('lightbox_description_src'), 1497 showFooter = hasTitle || hasDescription, 1498 classes = this.getSettings('classes'), 1499 slideshowClasses = classes.slideshow, 1500 $container = $('<div>', { 1501 class: slideshowClasses.container 1502 }), 1503 $slidesWrapper = $('<div>', { 1504 class: slideshowClasses.slidesWrapper 1505 }); 1506 let $prevButton, $nextButton; 1507 options.slides.forEach(slide => { 1508 let slideClass = slideshowClasses.slide + ' ' + classes.item; 1509 1510 if (slide.video) { 1511 slideClass += ' ' + classes.video; 1512 } 1513 1514 const $slide = $('<div>', { 1515 class: slideClass 1516 }); 1517 1518 if (slide.video) { 1519 $slide.attr('data-elementor-slideshow-video', slide.video); 1520 const $playIcon = $('<div>', { 1521 class: classes.playButton 1522 }).html($('<i>', { 1523 class: classes.playButtonIcon, 1524 'aria-label': i18n.playVideo 1525 })); 1526 $slide.append($playIcon); 1527 } else { 1528 const $zoomContainer = $('<div>', { 1529 class: 'swiper-zoom-container' 1530 }), 1531 $slidePlaceholder = $('<div class="swiper-lazy-preloader"></div>'), 1532 imageAttributes = { 1533 'data-src': slide.image, 1534 class: classes.image + ' ' + classes.preventClose + ' swiper-lazy' 1535 }; 1536 1537 if (slide.title) { 1538 imageAttributes['data-title'] = slide.title; 1539 imageAttributes.alt = slide.title; 1540 } 1541 1542 if (slide.description) { 1543 imageAttributes['data-description'] = slide.description; 1544 imageAttributes.alt += ' - ' + slide.description; 1545 } 1546 1547 const $slideImage = $('<img>', imageAttributes); 1548 $zoomContainer.append([$slideImage, $slidePlaceholder]); 1549 $slide.append($zoomContainer); 1550 } 1551 1552 $slidesWrapper.append($slide); 1553 }); 1554 this.elements.$container = $container; 1555 this.elements.$header = this.getSlideshowHeader(); 1556 $container.prepend(this.elements.$header).append($slidesWrapper); 1557 1558 if (!isSingleSlide) { 1559 $prevButton = $('<div>', { 1560 class: slideshowClasses.prevButton + ' ' + classes.preventClose, 1561 'aria-label': i18n.previous 1562 }).html($('<i>', { 1563 class: slideshowClasses.prevButtonIcon 1564 })); 1565 $nextButton = $('<div>', { 1566 class: slideshowClasses.nextButton + ' ' + classes.preventClose, 1567 'aria-label': i18n.next 1568 }).html($('<i>', { 1569 class: slideshowClasses.nextButtonIcon 1570 })); 1571 $container.append($nextButton, $prevButton); 1572 this.$buttons = this.$buttons.add($nextButton).add($prevButton); 1573 } 1574 1575 if (showFooter) { 1576 this.elements.$footer = this.getSlideshowFooter(); 1577 $container.append(this.elements.$footer); 1578 } 1579 1580 this.setSettings('hideUiTimeout', ''); 1581 $container.on('click mousemove keypress', this.showLightboxUi); 1582 const modal = this.getModal(); 1583 modal.setMessage($container); 1584 const onShowMethod = modal.onShow; 1585 1586 modal.onShow = async () => { 1587 onShowMethod(); 1588 const swiperOptions = { 1589 pagination: { 1590 el: '.' + slideshowClasses.counter, 1591 type: 'fraction' 1592 }, 1593 on: { 1594 slideChangeTransitionEnd: this.onSlideChange 1595 }, 1596 lazy: { 1597 loadPrevNext: true 1598 }, 1599 zoom: true, 1600 spaceBetween: 100, 1601 grabCursor: true, 1602 runCallbacksOnInit: false, 1603 loop: true, 1604 keyboard: true, 1605 handleElementorBreakpoints: true 1606 }; 1607 1608 if (!isSingleSlide) { 1609 swiperOptions.navigation = { 1610 prevEl: $prevButton, 1611 nextEl: $nextButton 1612 }; 1613 } 1614 1615 if (options.swiper) { 1616 $.extend(swiperOptions, options.swiper); 1617 } 1618 1619 const Swiper = elementorFrontend.utils.swiper; 1620 this.swiper = await new Swiper($container, swiperOptions); // Expose the swiper instance in the frontend 1621 1622 $container.data('swiper', this.swiper); 1623 this.setVideoAspectRatio(); 1624 this.playSlideVideo(); 1625 1626 if (showFooter) { 1627 this.updateFooterText(); 1628 } 1629 1630 this.bindHotKeys(); 1631 this.makeButtonsAccessible(); 1632 }; 1633 }, 1634 makeButtonsAccessible: function () { 1635 this.$buttons.attr('tabindex', 0).on('keypress', event => { 1636 const ENTER_KEY = 13, 1637 SPACE_KEY = 32; 1638 1639 if (ENTER_KEY === event.which || SPACE_KEY === event.which) { 1640 jQuery(event.currentTarget).trigger('click'); 1641 } 1642 }); 1643 }, 1644 showLightboxUi: function () { 1645 const slideshowClasses = this.getSettings('classes').slideshow; 1646 this.elements.$container.removeClass(slideshowClasses.hideUiVisibility); 1647 clearTimeout(this.getSettings('hideUiTimeout')); 1648 this.setSettings('hideUiTimeout', setTimeout(() => { 1649 if (!this.shareMode) { 1650 this.elements.$container.addClass(slideshowClasses.hideUiVisibility); 1651 } 1652 }, 3500)); 1653 }, 1654 bindHotKeys: function () { 1655 this.getModal().getElements('window').on('keydown', this.activeKeyDown); 1656 }, 1657 unbindHotKeys: function () { 1658 this.getModal().getElements('window').off('keydown', this.activeKeyDown); 1659 }, 1660 activeKeyDown: function (event) { 1661 this.showLightboxUi(); 1662 const TAB_KEY = 9; 1663 1664 if (event.which === TAB_KEY) { 1665 const $buttons = this.$buttons; 1666 let focusedButton, 1667 isFirst = false, 1668 isLast = false; 1669 $buttons.each(index => { 1670 const item = $buttons[index]; 1671 1672 if (jQuery(item).is(':focus')) { 1673 focusedButton = item; 1674 isFirst = 0 === index; 1675 isLast = $buttons.length - 1 === index; 1676 return false; 1677 } 1678 }); 1679 1680 if (event.shiftKey) { 1681 if (isFirst) { 1682 event.preventDefault(); 1683 $buttons.last().trigger('focus'); 1684 } 1685 } else if (isLast || !focusedButton) { 1686 event.preventDefault(); 1687 $buttons.first().trigger('focus'); 1688 } 1689 } 1690 }, 1691 setVideoAspectRatio: function (aspectRatio) { 1692 aspectRatio = aspectRatio || this.getSettings('modalOptions.videoAspectRatio'); 1693 const $widgetContent = this.getModal().getElements('widgetContent'), 1694 oldAspectRatio = this.oldAspectRatio, 1695 aspectRatioClass = this.getSettings('classes.aspectRatio'); 1696 this.oldAspectRatio = aspectRatio; 1697 1698 if (oldAspectRatio) { 1699 $widgetContent.removeClass(aspectRatioClass.replace('%s', oldAspectRatio)); 1700 } 1701 1702 if (aspectRatio) { 1703 $widgetContent.addClass(aspectRatioClass.replace('%s', aspectRatio)); 1704 } 1705 }, 1706 getSlide: function (slideState) { 1707 return jQuery(this.swiper.slides).filter(this.getSettings('selectors.slideshow.' + slideState + 'Slide')); 1708 }, 1709 updateFooterText: function () { 1710 if (!this.elements.$footer) { 1711 return; 1712 } 1713 1714 const classes = this.getSettings('classes'), 1715 $activeSlide = this.getSlide('active'), 1716 $image = $activeSlide.find('.elementor-lightbox-image'), 1717 titleText = $image.data('title'), 1718 descriptionText = $image.data('description'), 1719 $title = this.elements.$footer.find('.' + classes.slideshow.title), 1720 $description = this.elements.$footer.find('.' + classes.slideshow.description); 1721 $title.text(titleText || ''); 1722 $description.text(descriptionText || ''); 1723 }, 1724 playSlideVideo: function () { 1725 const $activeSlide = this.getSlide('active'), 1726 videoURL = $activeSlide.data('elementor-slideshow-video'); 1727 1728 if (!videoURL) { 1729 return; 1730 } 1731 1732 const classes = this.getSettings('classes'), 1733 $videoContainer = jQuery('<div>', { 1734 class: classes.videoContainer + ' ' + classes.invisible 1735 }), 1736 $videoWrapper = jQuery('<div>', { 1737 class: classes.videoWrapper 1738 }), 1739 $playIcon = $activeSlide.children('.' + classes.playButton); 1740 let videoType, apiProvider; 1741 $videoContainer.append($videoWrapper); 1742 $activeSlide.append($videoContainer); 1743 1744 if (-1 !== videoURL.indexOf('vimeo.com')) { 1745 videoType = 'vimeo'; 1746 apiProvider = elementorFrontend.utils.vimeo; 1747 } else if (videoURL.match(/^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com)/)) { 1748 videoType = 'youtube'; 1749 apiProvider = elementorFrontend.utils.youtube; 1750 } 1751 1752 const videoID = apiProvider.getVideoIDFromURL(videoURL); 1753 apiProvider.onApiReady(apiObject => { 1754 if ('youtube' === videoType) { 1755 this.prepareYTVideo(apiObject, videoID, $videoContainer, $videoWrapper, $playIcon); 1756 } else if ('vimeo' === videoType) { 1757 this.prepareVimeoVideo(apiObject, videoID, $videoContainer, $videoWrapper, $playIcon); 1758 } 1759 }); 1760 $playIcon.addClass(classes.playing).removeClass(classes.hidden); 1761 }, 1762 prepareYTVideo: function (YT, videoID, $videoContainer, $videoWrapper, $playIcon) { 1763 const classes = this.getSettings('classes'), 1764 $videoPlaceholderElement = jQuery('<div>'); 1765 let startStateCode = YT.PlayerState.PLAYING; 1766 $videoWrapper.append($videoPlaceholderElement); // Since version 67, Chrome doesn't fire the `PLAYING` state at start time 1767 1768 if (window.chrome) { 1769 startStateCode = YT.PlayerState.UNSTARTED; 1770 } 1771 1772 $videoContainer.addClass('elementor-loading' + ' ' + classes.invisible); 1773 this.player = new YT.Player($videoPlaceholderElement[0], { 1774 videoId: videoID, 1775 events: { 1776 onReady: () => { 1777 $playIcon.addClass(classes.hidden); 1778 $videoContainer.removeClass(classes.invisible); 1779 this.player.playVideo(); 1780 }, 1781 onStateChange: event => { 1782 if (event.data === startStateCode) { 1783 $videoContainer.removeClass('elementor-loading' + ' ' + classes.invisible); 1784 } 1785 } 1786 }, 1787 playerVars: { 1788 controls: 0, 1789 rel: 0 1790 } 1791 }); 1792 }, 1793 prepareVimeoVideo: function (Vimeo, videoId, $videoContainer, $videoWrapper, $playIcon) { 1794 const classes = this.getSettings('classes'), 1795 vimeoOptions = { 1796 id: videoId, 1797 autoplay: true, 1798 transparent: false, 1799 playsinline: false 1800 }; 1801 this.player = new Vimeo.Player($videoWrapper, vimeoOptions); 1802 this.player.ready().then(() => { 1803 $playIcon.addClass(classes.hidden); 1804 $videoContainer.removeClass(classes.invisible); 1805 }); 1806 }, 1807 setEntranceAnimation: function (animation) { 1808 animation = animation || elementorFrontend.getCurrentDeviceSetting(this.getSettings('modalOptions'), 'entranceAnimation'); 1809 const $widgetMessage = this.getModal().getElements('message'); 1810 1811 if (this.oldAnimation) { 1812 $widgetMessage.removeClass(this.oldAnimation); 1813 } 1814 1815 this.oldAnimation = animation; 1816 1817 if (animation) { 1818 $widgetMessage.addClass('animated ' + animation); 1819 } 1820 }, 1821 openSlideshow: function (slideshowID, initialSlideURL) { 1822 const $allSlideshowLinks = jQuery(this.getSettings('selectors.links')).filter((index, element) => { 1823 const $element = jQuery(element); 1824 return slideshowID === element.dataset.elementorLightboxSlideshow && !$element.parent('.swiper-slide-duplicate').length && !$element.parents('.slick-cloned').length; 1825 }); 1826 const slides = []; 1827 let initialSlideIndex = 0; 1828 $allSlideshowLinks.each(function () { 1829 const slideVideo = this.dataset.elementorLightboxVideo; 1830 let slideIndex = this.dataset.elementorLightboxIndex; 1831 1832 if (undefined === slideIndex) { 1833 slideIndex = $allSlideshowLinks.index(this); 1834 } 1835 1836 if (initialSlideURL === this.href || slideVideo && initialSlideURL === slideVideo) { 1837 initialSlideIndex = slideIndex; 1838 } 1839 1840 const slideData = { 1841 image: this.href, 1842 index: slideIndex, 1843 title: this.dataset.elementorLightboxTitle, 1844 description: this.dataset.elementorLightboxDescription 1845 }; 1846 1847 if (slideVideo) { 1848 slideData.video = slideVideo; 1849 } 1850 1851 slides.push(slideData); 1852 }); 1853 slides.sort((a, b) => a.index - b.index); 1854 this.showModal({ 1855 type: 'slideshow', 1856 id: slideshowID, 1857 modalOptions: { 1858 id: 'elementor-lightbox-slideshow-' + slideshowID 1859 }, 1860 slideshow: { 1861 slides: slides, 1862 swiper: { 1863 initialSlide: +initialSlideIndex 1864 } 1865 } 1866 }); 1867 }, 1868 onSlideChange: function () { 1869 this.getSlide('prev').add(this.getSlide('next')).add(this.getSlide('active')).find('.' + this.getSettings('classes.videoWrapper')).remove(); 1870 this.playSlideVideo(); 1871 this.updateFooterText(); 1872 } 1873 }); 1874 1875 /***/ }), 1876 1877 /***/ "../assets/dev/js/frontend/utils/lightbox/screenfull.js": 1878 /*!**************************************************************!*\ 1879 !*** ../assets/dev/js/frontend/utils/lightbox/screenfull.js ***! 1880 \**************************************************************/ 1881 /***/ ((module) => { 1882 1883 "use strict"; 1884 1885 1886 (function () { 1887 'use strict'; 1888 1889 var document = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {}; 1890 var isCommonjs = true && module.exports; 1891 1892 var fn = function () { 1893 var val; 1894 var fnMap = [['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'], // New WebKit 1895 ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'], // Old WebKit 1896 ['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'], ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'], ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']]; 1897 var i = 0; 1898 var l = fnMap.length; 1899 var ret = {}; 1900 1901 for (; i < l; i++) { 1902 val = fnMap[i]; 1903 1904 if (val && val[1] in document) { 1905 var valLength = val.length; 1906 1907 for (i = 0; i < valLength; i++) { 1908 ret[fnMap[0][i]] = val[i]; 1909 } 1910 1911 return ret; 1912 } 1913 } 1914 1915 return false; 1916 }(); 1917 1918 var eventNameMap = { 1919 change: fn.fullscreenchange, 1920 error: fn.fullscreenerror 1921 }; 1922 var screenfull = { 1923 request: function (element) { 1924 return new Promise(function (resolve, reject) { 1925 var onFullScreenEntered = function () { 1926 this.off('change', onFullScreenEntered); 1927 resolve(); 1928 }.bind(this); 1929 1930 this.on('change', onFullScreenEntered); 1931 element = element || document.documentElement; 1932 Promise.resolve(element[fn.requestFullscreen]()).catch(reject); 1933 }.bind(this)); 1934 }, 1935 exit: function () { 1936 return new Promise(function (resolve, reject) { 1937 if (!this.isFullscreen) { 1938 resolve(); 1939 return; 1940 } 1941 1942 var onFullScreenExit = function () { 1943 this.off('change', onFullScreenExit); 1944 resolve(); 1945 }.bind(this); 1946 1947 this.on('change', onFullScreenExit); 1948 Promise.resolve(document[fn.exitFullscreen]()).catch(reject); 1949 }.bind(this)); 1950 }, 1951 toggle: function (element) { 1952 return this.isFullscreen ? this.exit() : this.request(element); 1953 }, 1954 onchange: function (callback) { 1955 this.on('change', callback); 1956 }, 1957 onerror: function (callback) { 1958 this.on('error', callback); 1959 }, 1960 on: function (event, callback) { 1961 var eventName = eventNameMap[event]; 1962 1963 if (eventName) { 1964 document.addEventListener(eventName, callback, false); 1965 } 1966 }, 1967 off: function (event, callback) { 1968 var eventName = eventNameMap[event]; 1969 1970 if (eventName) { 1971 document.removeEventListener(eventName, callback, false); 1972 } 1973 }, 1974 raw: fn 1975 }; 1976 1977 if (!fn) { 1978 if (isCommonjs) { 1979 module.exports = { 1980 isEnabled: false 1981 }; 1982 } else { 1983 window.screenfull = { 1984 isEnabled: false 1985 }; 1986 } 1987 1988 return; 1989 } 1990 1991 Object.defineProperties(screenfull, { 1992 isFullscreen: { 1993 get: function () { 1994 return Boolean(document[fn.fullscreenElement]); 1995 } 1996 }, 1997 element: { 1998 enumerable: true, 1999 get: function () { 2000 return document[fn.fullscreenElement]; 2001 } 2002 }, 2003 isEnabled: { 2004 enumerable: true, 2005 get: function () { 2006 // Coerce to boolean in case of old WebKit 2007 return Boolean(document[fn.fullscreenEnabled]); 2008 } 2009 } 2010 }); 2011 2012 if (isCommonjs) { 2013 module.exports = screenfull; 2014 } else { 2015 window.screenfull = screenfull; 2016 } 2017 })(); 2018 2019 /***/ }) 2020 2021 }, 2022 /******/ __webpack_require__ => { // webpackRuntimeModules 2023 /******/ "use strict"; 2024 /******/ 2025 /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId)) 2026 /******/ __webpack_require__.O(0, ["frontend","frontend-modules"], () => (__webpack_exec__("../assets/dev/js/frontend/preloaded-modules.js"))); 2027 /******/ var __webpack_exports__ = __webpack_require__.O(); 2028 /******/ } 2029 ]); 2030 //# sourceMappingURL=preloaded-modules.js.map