| @@ -1,0 +1,568 @@ | ||
| 1 | +(function ($) { | |
| 2 | + $(window).on('elementor/frontend/init', function () { | |
| 3 | + elementorFrontend.hooks.addAction( | |
| 4 | + 'frontend/element_ready/king-addons-mega-menu.default', | |
| 5 | + function ($scope) { | |
| 6 | + const $mainMenu = $scope.find('.king-addons-mega-menu'); | |
| 7 | + if (!$mainMenu.length) return; | |
| 8 | + | |
| 9 | + // Ensure data-dropdown-animation attribute is set | |
| 10 | + let animation = $mainMenu.attr('data-dropdown-animation'); | |
| 11 | + if (!animation) { | |
| 12 | + animation = $mainMenu.data('dropdown-animation') || 'fade'; | |
| 13 | + $mainMenu.attr('data-dropdown-animation', animation); | |
| 14 | + } | |
| 15 | + | |
| 16 | + // Remove previous animation classes and add the current one | |
| 17 | + $mainMenu.removeClass(function (i, c) { | |
| 18 | + return (c.match(/king-addons-animation-[^\s]+/g) || []).join(' '); | |
| 19 | + }); | |
| 20 | + if ([ | |
| 21 | + 'fade-up', | |
| 22 | + 'fade-down', | |
| 23 | + 'fade-left', | |
| 24 | + 'fade-right', | |
| 25 | + 'zoom-in', | |
| 26 | + 'zoom-out', | |
| 27 | + 'fade', | |
| 28 | + 'slide', | |
| 29 | + 'none' | |
| 30 | + ].includes(animation)) { | |
| 31 | + $mainMenu.addClass('king-addons-animation-' + animation); | |
| 32 | + } | |
| 33 | + | |
| 34 | + // Dropdown open/close logic (do not set any left/right/transform styles) | |
| 35 | + $mainMenu.find('.king-addons-menu-items > li').each(function () { | |
| 36 | + const $menuItem = $(this); | |
| 37 | + const $dropdowns = $menuItem.find('> ul.sub-menu, > .king-addons-template-content, > .king-addons-submenu'); | |
| 38 | + if ($dropdowns.length) { | |
| 39 | + $menuItem.off('mouseenter mouseleave'); | |
| 40 | + $menuItem.on('mouseenter', function () { | |
| 41 | + if (window.innerWidth > 1024) { | |
| 42 | + $dropdowns.each(function () { | |
| 43 | + kingAddonsDropdownFitToScreen(this); | |
| 44 | + }); | |
| 45 | + } | |
| 46 | + }); | |
| 47 | + $menuItem.on('mouseleave', function () { | |
| 48 | + $dropdowns.removeClass('king-addons-dropdown-open'); | |
| 49 | + }); | |
| 50 | + } | |
| 51 | + }); | |
| 52 | + | |
| 53 | + // Full-width dropdown logic (only set width, do not set left/right/transform) | |
| 54 | + $mainMenu.filter('.king-addons-dropdown-width-full').each(function () { | |
| 55 | + const $menu = $(this); | |
| 56 | + const $window = $(window); | |
| 57 | + const setDropdownWidth = () => { | |
| 58 | + const windowWidth = $window.width(); | |
| 59 | + $menu.find('.king-addons-menu-items > li > ul.sub-menu, .king-addons-menu-items > li > .king-addons-template-content').css('width', windowWidth + 'px'); | |
| 60 | + }; | |
| 61 | + setDropdownWidth(); | |
| 62 | + $window.on('resize', setDropdownWidth); | |
| 63 | + }); | |
| 64 | + | |
| 65 | + // Accessibility: keyboard navigation | |
| 66 | + $mainMenu.find('.king-addons-menu-items > li > a').on('keydown', function (e) { | |
| 67 | + if (e.key === 'Enter' || e.key === ' ') { | |
| 68 | + e.preventDefault(); | |
| 69 | + $(this).trigger('click'); | |
| 70 | + const $firstLink = $(this).siblings('.sub-menu, .king-addons-template-content').find('a').first(); | |
| 71 | + if ($firstLink.length) { | |
| 72 | + $firstLink.focus(); | |
| 73 | + } | |
| 74 | + } | |
| 75 | + }); | |
| 76 | + | |
| 77 | + // Escape key closes dropdowns | |
| 78 | + $(document).on('keydown.kingAddonsMegaMenu', function (e) { | |
| 79 | + if (e.key === 'Escape') { | |
| 80 | + $mainMenu.find('.king-addons-menu-items li').removeClass('focus'); | |
| 81 | + $mainMenu.find('.sub-menu, .king-addons-template-content').css({ opacity: '', visibility: '' }); | |
| 82 | + } | |
| 83 | + }); | |
| 84 | + | |
| 85 | + // ARIA attributes | |
| 86 | + $mainMenu.find('.king-addons-menu-items li').each(function () { | |
| 87 | + const $li = $(this); | |
| 88 | + if ($li.has('.sub-menu, .king-addons-template-content').length) { | |
| 89 | + $li.attr('aria-haspopup', 'true'); | |
| 90 | + $li.find('> a').attr('aria-expanded', 'false'); | |
| 91 | + $li.on('mouseenter focus', function () { | |
| 92 | + $li.find('> a').attr('aria-expanded', 'true'); | |
| 93 | + }); | |
| 94 | + $li.on('mouseleave blur', function () { | |
| 95 | + $li.find('> a').attr('aria-expanded', 'false'); | |
| 96 | + }); | |
| 97 | + } | |
| 98 | + }); | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + // Mobile menu toggle logic | |
| 103 | + const $mobileToggle = $scope.find('.king-addons-mobile-menu-toggle'); | |
| 104 | + const $mobileMenu = $scope.find('.king-addons-mobile-menu'); | |
| 105 | + const $mobileClose = $scope.find('.king-addons-mobile-menu-close'); | |
| 106 | + | |
| 107 | + $mobileToggle.on('click', function (e) { | |
| 108 | + e.preventDefault(); | |
| 109 | + $mobileMenu.slideToggle(250); | |
| 110 | + $mobileToggle.toggleClass('active'); | |
| 111 | + }); | |
| 112 | + | |
| 113 | + $mobileClose.on('click', function (e) { | |
| 114 | + e.preventDefault(); | |
| 115 | + $mobileMenu.slideUp(250); | |
| 116 | + $mobileToggle.removeClass('active'); | |
| 117 | + }); | |
| 118 | + | |
| 119 | + // Mobile menu dropdown logic | |
| 120 | + $mobileMenu.find('.menu-item-has-children > a').on('click', function (e) { | |
| 121 | + // Only handle in mobile menu | |
| 122 | + if (window.innerWidth > 1024) return; | |
| 123 | + e.preventDefault(); | |
| 124 | + const $parent = $(this).parent(); | |
| 125 | + const $submenu = $parent.children('ul.sub-menu, ul.king-addons-submenu, .king-addons-template-content'); | |
| 126 | + // Toggle current submenu | |
| 127 | + $submenu.slideToggle(250); | |
| 128 | + $parent.toggleClass('king-addons-mobile-menu__item--open'); | |
| 129 | + // Optionally close other open submenus (accordion behavior) | |
| 130 | + $parent.siblings('.menu-item-has-children').removeClass('king-addons-mobile-menu__item--open') | |
| 131 | + .children('ul.sub-menu, ul.king-addons-submenu, .king-addons-template-content').slideUp(250); | |
| 132 | + }); | |
| 133 | + | |
| 134 | + // Initialize center logo positioning | |
| 135 | + kingAddonsCenterLogoPositioning($mainMenu); | |
| 136 | + | |
| 137 | + // Initialize Lottie animations for logos (with library loading wait) | |
| 138 | + waitForLottieAndInitialize($mainMenu); | |
| 139 | + } | |
| 140 | + ); | |
| 141 | + }); | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Force transform: none !important and left: 0 !important for all .sub-menu, .king-addons-submenu, and .king-addons-template-content in mega menu on mobile width | |
| 145 | + */ | |
| 146 | + function kingAddonsMobileMenuTransformReset() { | |
| 147 | + const isMobile = window.innerWidth <= 1024; | |
| 148 | + const subMenus = document.querySelectorAll('.king-addons-mega-menu .sub-menu, .king-addons-mega-menu .king-addons-submenu, .king-addons-mega-menu .king-addons-template-content'); | |
| 149 | + subMenus.forEach(function(subMenu) { | |
| 150 | + if (isMobile) { | |
| 151 | + subMenu.style.setProperty('transform', 'none', 'important'); | |
| 152 | + subMenu.style.setProperty('left', '0', 'important'); | |
| 153 | + } else { | |
| 154 | + subMenu.style.removeProperty('transform'); | |
| 155 | + subMenu.style.removeProperty('left'); | |
| 156 | + } | |
| 157 | + }); | |
| 158 | + } | |
| 159 | + | |
| 160 | + function kingAddonsMobileMenuHideOnDesktop() { | |
| 161 | + if (window.innerWidth > 1024) { | |
| 162 | + document.querySelectorAll('.king-addons-mobile-menu').forEach(function(menu) { | |
| 163 | + if (menu.style.display !== 'none') { | |
| 164 | + if (window.jQuery) { | |
| 165 | + jQuery(menu).slideUp(0); | |
| 166 | + } else { | |
| 167 | + menu.style.display = 'none'; | |
| 168 | + } | |
| 169 | + } | |
| 170 | + // Close all open dropdowns inside mobile menu | |
| 171 | + menu.querySelectorAll('.menu-item-has-children.king-addons-mobile-menu__item--open').forEach(function(item) { | |
| 172 | + item.classList.remove('king-addons-mobile-menu__item--open'); | |
| 173 | + }); | |
| 174 | + menu.querySelectorAll('ul.sub-menu, ul.king-addons-submenu, .king-addons-template-content').forEach(function(sub) { | |
| 175 | + if (window.jQuery) { | |
| 176 | + jQuery(sub).slideUp(0); | |
| 177 | + } else { | |
| 178 | + sub.style.display = 'none'; | |
| 179 | + } | |
| 180 | + }); | |
| 181 | + }); | |
| 182 | + document.querySelectorAll('.king-addons-mobile-menu-toggle.active').forEach(function(toggle) { | |
| 183 | + toggle.classList.remove('active'); | |
| 184 | + }); | |
| 185 | + } | |
| 186 | + } | |
| 187 | + | |
| 188 | + window.addEventListener('resize', kingAddonsMobileMenuTransformReset); | |
| 189 | + document.addEventListener('DOMContentLoaded', kingAddonsMobileMenuTransformReset); | |
| 190 | + window.addEventListener('resize', kingAddonsMobileMenuHideOnDesktop); | |
| 191 | + document.addEventListener('DOMContentLoaded', kingAddonsMobileMenuHideOnDesktop); | |
| 192 | + | |
| 193 | + /** | |
| 194 | + * Ensure dropdown (template, sub-menu, custom submenu) fits inside viewport on desktop | |
| 195 | + * Observer is temporarily disconnected to avoid infinite loop | |
| 196 | + */ | |
| 197 | + function kingAddonsDropdownFitToScreen(dropdown) { | |
| 198 | + if (window.innerWidth <= 1024) return; | |
| 199 | + // Temporarily disconnect observer to avoid loop | |
| 200 | + if (dropdown._kingAddonsObserver) dropdown._kingAddonsObserver.disconnect(); | |
| 201 | + dropdown.style.left = ''; | |
| 202 | + dropdown.style.right = ''; | |
| 203 | + dropdown.style.transform = ''; | |
| 204 | + const rect = dropdown.getBoundingClientRect(); | |
| 205 | + const viewportWidth = window.innerWidth; | |
| 206 | + let changed = false; | |
| 207 | + if (rect.right > viewportWidth) { | |
| 208 | + const overflowRight = rect.right - viewportWidth; | |
| 209 | + dropdown.style.left = (dropdown.offsetLeft - overflowRight) + 'px'; | |
| 210 | + changed = true; | |
| 211 | + } | |
| 212 | + if (rect.left < 0) { | |
| 213 | + dropdown.style.left = (dropdown.offsetLeft - rect.left) + 'px'; | |
| 214 | + changed = true; | |
| 215 | + } | |
| 216 | + // Reconnect observer after change | |
| 217 | + if (dropdown._kingAddonsObserver) { | |
| 218 | + dropdown._kingAddonsObserver.observe(dropdown, { attributes: true, attributeFilter: ['class', 'style'] }); | |
| 219 | + } | |
| 220 | + } | |
| 221 | + | |
| 222 | + /** | |
| 223 | + * Observe dropdowns and fix their position as soon as they become visible (desktop only) | |
| 224 | + */ | |
| 225 | + function kingAddonsObserveDropdowns() { | |
| 226 | + if (window.innerWidth <= 1024) return; | |
| 227 | + const dropdowns = document.querySelectorAll('.king-addons-template-content, .sub-menu, .king-addons-submenu'); | |
| 228 | + dropdowns.forEach(function(dropdown) { | |
| 229 | + // Avoid multiple observers | |
| 230 | + if (dropdown._kingAddonsObserved) return; | |
| 231 | + dropdown._kingAddonsObserved = true; | |
| 232 | + const observer = new MutationObserver(function(mutations) { | |
| 233 | + mutations.forEach(function(mutation) { | |
| 234 | + if ( | |
| 235 | + mutation.attributeName === 'class' || mutation.attributeName === 'style' | |
| 236 | + ) { | |
| 237 | + // Check if dropdown is visible | |
| 238 | + const style = window.getComputedStyle(dropdown); | |
| 239 | + if (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0') { | |
| 240 | + kingAddonsDropdownFitToScreen(dropdown); | |
| 241 | + } | |
| 242 | + } | |
| 243 | + }); | |
| 244 | + }); | |
| 245 | + dropdown._kingAddonsObserver = observer; | |
| 246 | + observer.observe(dropdown, { attributes: true, attributeFilter: ['class', 'style'] }); | |
| 247 | + }); | |
| 248 | + } | |
| 249 | + window.addEventListener('DOMContentLoaded', kingAddonsObserveDropdowns); | |
| 250 | + window.addEventListener('resize', kingAddonsObserveDropdowns); | |
| 251 | + | |
| 252 | + /** | |
| 253 | + * Handle center logo positioning by inserting logo between menu items | |
| 254 | + * Supports responsive positioning (desktop/tablet/mobile) | |
| 255 | + */ | |
| 256 | + function kingAddonsCenterLogoPositioning($mainMenu) { | |
| 257 | + const centerLogo = $mainMenu.attr('data-center-logo'); | |
| 258 | + if (centerLogo !== 'true') return; | |
| 259 | + | |
| 260 | + // Get responsive logo positions | |
| 261 | + const logoPositionDesktop = $mainMenu.attr('data-logo-position-desktop') || 'left'; | |
| 262 | + const logoPositionTablet = $mainMenu.attr('data-logo-position-tablet') || logoPositionDesktop; | |
| 263 | + const logoPositionMobile = $mainMenu.attr('data-logo-position-mobile') || logoPositionDesktop; | |
| 264 | + | |
| 265 | + // Determine current device and position | |
| 266 | + let currentPosition = logoPositionDesktop; | |
| 267 | + if (window.innerWidth <= 767) { | |
| 268 | + currentPosition = logoPositionMobile; | |
| 269 | + } else if (window.innerWidth <= 1024) { | |
| 270 | + currentPosition = logoPositionTablet; | |
| 271 | + } | |
| 272 | + | |
| 273 | + // Remove any existing center logo | |
| 274 | + $mainMenu.find('.king-addons-center-logo-inserted').remove(); | |
| 275 | + $mainMenu.removeClass('king-addons-center-logo-active'); | |
| 276 | + | |
| 277 | + // Only proceed if current position is center | |
| 278 | + if (currentPosition !== 'center') return; | |
| 279 | + if (window.innerWidth <= 1024) return; | |
| 280 | + | |
| 281 | + const splitAt = parseInt($mainMenu.attr('data-split-at')) || 2; | |
| 282 | + const $menuItems = $mainMenu.find('.king-addons-menu-items > li'); | |
| 283 | + const $logoPlaceholder = $mainMenu.find('.king-addons-center-logo-placeholder'); | |
| 284 | + | |
| 285 | + if ($menuItems.length > splitAt && $logoPlaceholder.length) { | |
| 286 | + // Clone logo and insert it after the split position | |
| 287 | + const $logoClone = $logoPlaceholder.children().first().clone(true, true); | |
| 288 | + | |
| 289 | + // Clean any previously injected Lottie DOM from the clone | |
| 290 | + // (cloning after Lottie init copies <svg>/<canvas> which would produce duplicates) | |
| 291 | + $logoClone.find('.king-addons-lottie-animations').each(function() { | |
| 292 | + const $container = jQuery(this); | |
| 293 | + // Remove any rendered content and runtime flags | |
| 294 | + $container.empty(); | |
| 295 | + $container.removeData('lottie-initialized'); | |
| 296 | + $container.removeData('lottie-animation'); | |
| 297 | + }); | |
| 298 | + $logoClone.addClass('king-addons-center-logo-inserted'); | |
| 299 | + | |
| 300 | + // Insert logo after the specified menu item | |
| 301 | + $menuItems.eq(splitAt - 1).after($logoClone); | |
| 302 | + | |
| 303 | + // Add special class to menu for center layout | |
| 304 | + $mainMenu.addClass('king-addons-center-logo-active'); | |
| 305 | + | |
| 306 | + // Ensure Lottie animations are initialized for cloned logo, if any | |
| 307 | + try { | |
| 308 | + // Initialize Lottie only for not-yet-initialized elements to avoid duplicates | |
| 309 | + $mainMenu.find('.king-addons-lottie-animations').each(function() { | |
| 310 | + const $el = jQuery(this); | |
| 311 | + if (!$el.data('lottie-initialized')) { | |
| 312 | + kingAddonsInitializeLottieLogos($mainMenu); | |
| 313 | + return false; // one pass is enough; internal init loops through all | |
| 314 | + } | |
| 315 | + }); | |
| 316 | + } catch (e) {} | |
| 317 | + } | |
| 318 | + } | |
| 319 | + | |
| 320 | + /** | |
| 321 | + * Check if Lottie library is available under different global names | |
| 322 | + */ | |
| 323 | + function getLottieLibrary() { | |
| 324 | + // Check common global names for lottie library | |
| 325 | + if (typeof lottie !== 'undefined') { | |
| 326 | + return lottie; | |
| 327 | + } | |
| 328 | + if (typeof window.lottie !== 'undefined') { | |
| 329 | + return window.lottie; | |
| 330 | + } | |
| 331 | + if (typeof window.Lottie !== 'undefined') { | |
| 332 | + return window.Lottie; | |
| 333 | + } | |
| 334 | + if (typeof window.bodymovin !== 'undefined') { | |
| 335 | + return window.bodymovin; | |
| 336 | + } | |
| 337 | + return null; | |
| 338 | + } | |
| 339 | + | |
| 340 | + /** | |
| 341 | + * Wait for Lottie library to load and then initialize animations | |
| 342 | + */ | |
| 343 | + function waitForLottieAndInitialize($mainMenu) { | |
| 344 | + let attempts = 0; | |
| 345 | + const maxAttempts = 50; // 5 seconds max wait | |
| 346 | + | |
| 347 | + function checkLottie() { | |
| 348 | + const lottieLib = getLottieLibrary(); | |
| 349 | + if (lottieLib) { | |
| 350 | + // console.log('Lottie library found, initializing animations'); | |
| 351 | + kingAddonsInitializeLottieLogos($mainMenu); | |
| 352 | + } else if (attempts < maxAttempts) { | |
| 353 | + attempts++; | |
| 354 | + setTimeout(checkLottie, 100); | |
| 355 | + } else { | |
| 356 | + // console.log('Lottie library not loaded after 5 seconds'); | |
| 357 | + // Try one more time with alternative approach | |
| 358 | + tryAlternativeLottieInit($mainMenu); | |
| 359 | + } | |
| 360 | + } | |
| 361 | + | |
| 362 | + checkLottie(); | |
| 363 | + } | |
| 364 | + | |
| 365 | + /** | |
| 366 | + * Alternative initialization approach for edge cases | |
| 367 | + */ | |
| 368 | + function tryAlternativeLottieInit($mainMenu) { | |
| 369 | + // Wait for window load event | |
| 370 | + if (document.readyState === 'complete') { | |
| 371 | + setTimeout(function() { | |
| 372 | + const lottieLib = getLottieLibrary(); | |
| 373 | + if (lottieLib) { | |
| 374 | + // console.log('Lottie library found on window load, initializing'); | |
| 375 | + kingAddonsInitializeLottieLogos($mainMenu); | |
| 376 | + } | |
| 377 | + }, 500); | |
| 378 | + } else { | |
| 379 | + window.addEventListener('load', function() { | |
| 380 | + setTimeout(function() { | |
| 381 | + const lottieLib = getLottieLibrary(); | |
| 382 | + if (lottieLib) { | |
| 383 | + // console.log('Lottie library found after window load, initializing'); | |
| 384 | + kingAddonsInitializeLottieLogos($mainMenu); | |
| 385 | + } | |
| 386 | + }, 500); | |
| 387 | + }); | |
| 388 | + } | |
| 389 | + } | |
| 390 | + | |
| 391 | + /** | |
| 392 | + * Initialize Lottie animations for logos | |
| 393 | + */ | |
| 394 | + function kingAddonsInitializeLottieLogos($mainMenu) { | |
| 395 | + const $lottieElements = $mainMenu.find('.king-addons-lottie-animations'); | |
| 396 | + | |
| 397 | + if ($lottieElements.length === 0) return; | |
| 398 | + | |
| 399 | + $lottieElements.each(function() { | |
| 400 | + const $element = $(this); | |
| 401 | + const settings = $element.data('settings'); | |
| 402 | + const jsonUrl = $element.data('json-url'); | |
| 403 | + | |
| 404 | + if (!jsonUrl) return; | |
| 405 | + | |
| 406 | + // Skip if already initialized | |
| 407 | + if ($element.data('lottie-initialized')) return; | |
| 408 | + | |
| 409 | + try { | |
| 410 | + // Check if lottie is available | |
| 411 | + const lottieLib = getLottieLibrary(); | |
| 412 | + if (lottieLib) { | |
| 413 | + const animationSettings = { | |
| 414 | + container: this, | |
| 415 | + renderer: settings.lottie_renderer || 'svg', | |
| 416 | + loop: settings.loop === 'yes', | |
| 417 | + autoplay: settings.autoplay === 'yes', | |
| 418 | + path: jsonUrl, | |
| 419 | + rendererSettings: { | |
| 420 | + preserveAspectRatio: 'xMidYMid slice' | |
| 421 | + } | |
| 422 | + }; | |
| 423 | + | |
| 424 | + const animation = lottieLib.loadAnimation(animationSettings); | |
| 425 | + | |
| 426 | + // Store animation instance | |
| 427 | + $element.data('lottie-animation', animation); | |
| 428 | + $element.data('lottie-initialized', true); | |
| 429 | + | |
| 430 | + // Set speed if specified | |
| 431 | + if (settings.speed) { | |
| 432 | + animation.setSpeed(parseFloat(settings.speed)); | |
| 433 | + } | |
| 434 | + | |
| 435 | + // Set direction if reversed | |
| 436 | + if (settings.reverse === 'true') { | |
| 437 | + animation.setDirection(-1); | |
| 438 | + } | |
| 439 | + | |
| 440 | + // Handle triggers | |
| 441 | + if (settings.trigger === 'hover') { | |
| 442 | + const isInNavigation = $element.closest('.king-addons-mega-menu').length > 0; | |
| 443 | + $element.on('mouseenter', function() { | |
| 444 | + animation.play(); | |
| 445 | + }); | |
| 446 | + $element.on('mouseleave', function() { | |
| 447 | + // Do not pause on mouseleave while a King Addons popup is open | |
| 448 | + if (isInNavigation && document.querySelector('.king-addons-pb-template-popup.king-addons-pb-popup-open')) { | |
| 449 | + animation.play(); | |
| 450 | + return; | |
| 451 | + } | |
| 452 | + animation.pause(); | |
| 453 | + }); | |
| 454 | + } else if (settings.trigger === 'viewport') { | |
| 455 | + // For navigation logos, viewport trigger should be more permissive | |
| 456 | + // Check if element is in navigation context | |
| 457 | + const isInNavigation = $element.closest('.king-addons-mega-menu').length > 0; | |
| 458 | + | |
| 459 | + if (isInNavigation) { | |
| 460 | + // For navigation logos, just start playing and keep playing | |
| 461 | + // Navigation is typically always visible | |
| 462 | + animation.play(); | |
| 463 | + } else { | |
| 464 | + // For non-navigation elements, use standard viewport detection | |
| 465 | + const observer = new IntersectionObserver((entries) => { | |
| 466 | + entries.forEach(entry => { | |
| 467 | + if (entry.isIntersecting) { | |
| 468 | + animation.play(); | |
| 469 | + } else { | |
| 470 | + animation.pause(); | |
| 471 | + } | |
| 472 | + }); | |
| 473 | + }); | |
| 474 | + observer.observe(this); | |
| 475 | + } | |
| 476 | + } | |
| 477 | + | |
| 478 | + // console.log('Lottie animation initialized for:', jsonUrl); | |
| 479 | + } else { | |
| 480 | + // console.log('Lottie library not available'); | |
| 481 | + } | |
| 482 | + } catch (error) { | |
| 483 | + // console.log('Lottie initialization failed:', error); | |
| 484 | + } | |
| 485 | + }); | |
| 486 | + } | |
| 487 | + | |
| 488 | + // Handle center logo repositioning on window resize | |
| 489 | + $(window).on('resize', function() { | |
| 490 | + $('.king-addons-mega-menu[data-center-logo="true"]').each(function() { | |
| 491 | + const $menu = $(this); | |
| 492 | + kingAddonsCenterLogoPositioning($menu); | |
| 493 | + // Ensure cloned logo does not carry previous rendered SVG/canvas | |
| 494 | + $menu.find('.king-addons-center-logo-inserted .king-addons-lottie-animations').each(function() { | |
| 495 | + const $container = jQuery(this); | |
| 496 | + if (!$container.data('lottie-initialized')) { | |
| 497 | + $container.empty(); | |
| 498 | + } | |
| 499 | + }); | |
| 500 | + // Re-initialize Lottie only for missing instances | |
| 501 | + try { | |
| 502 | + $menu.find('.king-addons-lottie-animations').each(function() { | |
| 503 | + const $el = jQuery(this); | |
| 504 | + if (!$el.data('lottie-initialized')) { | |
| 505 | + kingAddonsInitializeLottieLogos($menu); | |
| 506 | + return false; | |
| 507 | + } | |
| 508 | + }); | |
| 509 | + } catch (e) {} | |
| 510 | + }); | |
| 511 | + }); | |
| 512 | + | |
| 513 | + // Additional Lottie initialization fallback | |
| 514 | + // This handles cases where Lottie loads after our initial check | |
| 515 | + $(document).ready(function() { | |
| 516 | + // Wait a bit for all scripts to load, then try Lottie initialization again | |
| 517 | + setTimeout(function() { | |
| 518 | + $('.king-addons-mega-menu').each(function() { | |
| 519 | + const $menu = $(this); | |
| 520 | + const $lottieElements = $menu.find('.king-addons-lottie-animations'); | |
| 521 | + | |
| 522 | + // Only initialize elements that haven't been initialized yet | |
| 523 | + $lottieElements.each(function() { | |
| 524 | + const $element = $(this); | |
| 525 | + const lottieLib = getLottieLibrary(); | |
| 526 | + if (!$element.data('lottie-initialized') && lottieLib) { | |
| 527 | + kingAddonsInitializeLottieLogos($menu); | |
| 528 | + } | |
| 529 | + }); | |
| 530 | + }); | |
| 531 | + }, 1000); | |
| 532 | + }); | |
| 533 | + | |
| 534 | + // Resume navigation logo Lottie animations when a King Addons popup opens | |
| 535 | + function kingAddonsKeepNavLottieRunning() { | |
| 536 | + const resumeAll = () => { | |
| 537 | + document.querySelectorAll('.king-addons-mega-menu .king-addons-lottie-animations').forEach(function(el) { | |
| 538 | + const $el = jQuery(el); | |
| 539 | + const anim = $el.data('lottie-animation'); | |
| 540 | + if (anim) { | |
| 541 | + anim.play(); | |
| 542 | + } | |
| 543 | + }); | |
| 544 | + }; | |
| 545 | + // Resume when class changes on popups (open/close) | |
| 546 | + const popups = document.querySelectorAll('.king-addons-pb-template-popup'); | |
| 547 | + popups.forEach(function(popup) { | |
| 548 | + const observer = new MutationObserver(function(mutations) { | |
| 549 | + mutations.forEach(function(mutation) { | |
| 550 | + if (mutation.attributeName === 'class') { | |
| 551 | + resumeAll(); | |
| 552 | + } | |
| 553 | + }); | |
| 554 | + }); | |
| 555 | + observer.observe(popup, { attributes: true, attributeFilter: ['class'] }); | |
| 556 | + }); | |
| 557 | + // Resume on resize (desktop breakpoint changes) | |
| 558 | + window.addEventListener('resize', function() { | |
| 559 | + resumeAll(); | |
| 560 | + }); | |
| 561 | + // Resume on scroll (in case of transient viewport observers) | |
| 562 | + window.addEventListener('scroll', function() { | |
| 563 | + resumeAll(); | |
| 564 | + }, { passive: true }); | |
| 565 | + } | |
| 566 | + document.addEventListener('DOMContentLoaded', kingAddonsKeepNavLottieRunning); | |
| 567 | + | |
| 568 | +})(jQuery); | |