(function($) { 'use strict'; // KEYBOARD EVENT DETECTION FUNCTION function isActivationKey(e) { // Modern approach with proper fallback return (e.key === 'Enter' || e.key === ' ') || (e.keyCode === 13 || e.keyCode === 32); } // Check if element fully in viewport function isScrolledIntoViewport(elem) { const $elem = $(elem); const docViewTop = $(window).scrollTop(); const docViewBottom = docViewTop + $(window).height(); const elemTop = $elem.offset().top; const elemBottom = elemTop + $elem.outerHeight(); return (elemBottom <= docViewBottom) && (elemTop >= docViewTop); } // AOS initialization from classes. $("[class*='aos-']").each(function(){ var $el = $(this), cls = this.className; if (cls.indexOf('aos-init') !== -1) return; var m = cls.match(/aos-([a-z-]+)(?:\s|$)/); if (m) $el.attr('data-aos', m[1]).addClass('aos-init'); m = cls.match(/aos-duration-(\d+)(?:\s|$)/); if (m) $el.attr('data-aos-duration', m[1]); m = cls.match(/aos-delay-(\d+)(?:\s|$)/); if (m) $el.attr('data-aos-delay', m[1]); }); AOS.init({ once: true, duration: 800 }); // Add class to body on window load $(window).on('load', () => $("body").addClass("site-loaded")); if (typeof SmoothScroll === 'function' && $('body').hasClass('blogsy-smooth-scroll')) { SmoothScroll({ keyboardSupport: false }); } // Offcanvas click handlers $('.offcanvas-container').on('click', e => e.stopPropagation()); $('body').on('click keydown', '.offcanvas-opener', function(e) { if (e.type === 'click' || (e.type === 'keydown' && isActivationKey(e))) { if (e.type === 'keydown') e.preventDefault(); e.stopPropagation(); const $offcanvas = $(this).closest('.blogsy-offcanvas'); setTimeout(() => $offcanvas.find('.offcanvas-close').focus(), 100); $offcanvas.find('.offcanvas-container-inner').on('keydown', handleKeyboardNavigation); $offcanvas.find('.offcanvas-wrapper').addClass('open'); } }); $(document).on('click', '.offcanvas-wrapper', function(e) { if (e.target === this) { $('.offcanvas-wrapper').removeClass('open'); const $offcanvas = $(this).closest('.blogsy-offcanvas'); $offcanvas.find('.offcanvas-opener').focus(); $offcanvas.find('.offcanvas-container-inner').off('keydown', handleKeyboardNavigation); } }); $('.offcanvas-close').on('click keydown', function(e) { if (e.type === 'click' || (e.type === 'keydown' && isActivationKey(e))) { if (e.type === 'keydown') e.preventDefault(); $('.offcanvas-wrapper').removeClass('open'); const $offcanvas = $(this).closest('.blogsy-offcanvas'); $offcanvas.find('.offcanvas-opener').focus(); $offcanvas.find('.offcanvas-container-inner').off('keydown', handleKeyboardNavigation); } }); // Popup search handlers $('body').on('click keydown', '.popup-search-opener', function(e) { if (e.type === 'click' || (e.type === 'keydown' && isActivationKey(e))) { if (e.type === 'keydown') e.preventDefault(); e.stopPropagation(); let $wrapper; const $style3Wrapper = $('.popup-search-wrapper.style-3'); if ($style3Wrapper.length) { // Style-3 specific handling $('.pt-header-inner .blogsy-header-nav-wrapper').css('display', 'none'); $wrapper = $style3Wrapper; $wrapper.css({ 'display': 'flex', 'flex-direction': 'column', 'justify-content': 'center', 'flex': '1 0 auto', 'max-width': '100%' }); const $popupSearch = $wrapper.find('.popup-search'); $popupSearch.addClass('open'); // Add keyboard trap handler $popupSearch.off('keydown', handleKeyboardNavigation); $popupSearch.on('keydown', handleKeyboardNavigation); // Focus search field after delay setTimeout(() => { $wrapper.find('.search-field').first().focus(); }, 150); } else { // Style-1 handling (default) $wrapper = $(this).closest('.popup-search-wrapper'); const $popupSearch = $wrapper.find('.popup-search'); $popupSearch.addClass('open'); $popupSearch.off('keydown', handleKeyboardNavigation); $popupSearch.on('keydown', handleKeyboardNavigation); setTimeout(() => { $wrapper.find('.search-field').first().focus(); }, 150); } } }); $('.popup-search-form').on('click', e => e.stopPropagation()); // Close search popup function function closeSearchPopup() { const $style3Wrapper = $('.popup-search-wrapper.style-3'); if ($style3Wrapper.length && $style3Wrapper.css('display') !== 'none') { // Style-3 close handling $('.pt-header-inner .blogsy-header-nav-wrapper').css('display', ''); $style3Wrapper.css('display', 'none'); const $popupSearch = $style3Wrapper.find('.popup-search'); $popupSearch.removeClass('open'); $popupSearch.off('keydown', handleKeyboardNavigation); // Return focus to opener button setTimeout(() => { $('.popup-search-opener').first().focus(); }, 50); } else { // Style-1 close handling const $allPopups = $('.popup-search.open'); $allPopups.each(function() { const $popup = $(this); const $wrapper = $popup.closest('.popup-search-wrapper'); $popup.removeClass('open'); $popup.off('keydown', handleKeyboardNavigation); // Return focus to opener setTimeout(() => { $wrapper.find('.popup-search-opener').first().focus(); }, 50); }); } } // Close button handler $('body').on('click keydown', '.popup-search-close', function(e) { if (e.type === 'click' || (e.type === 'keydown' && isActivationKey(e))) { if (e.type === 'keydown') e.preventDefault(); e.stopPropagation(); closeSearchPopup(); } }); // Escape key handler $(document).on('keydown', function(e) { if (e.key === 'Escape' || e.keyCode === 27) { const $openPopup = $('.popup-search.open'); if ($openPopup.length) { closeSearchPopup(); } } }); // Click outside to close $('body').on('click', function(e) { const $target = $(e.target); // Don't close if clicking inside search or on opener if ($target.closest('.popup-search-container').length || $target.closest('.popup-search-opener').length) { return; } // Check if any popup is open if ($('.popup-search.open').length) { closeSearchPopup(); } }); // Time update display const $timeElem = $('#blogsy-time'); if ($timeElem.length) $timeElem.text(new Date().toLocaleTimeString()); // Date update display with locale formatting const $dateElem = $('#blogsy-date'); if ($dateElem.length) { const locale = $('html').attr('lang') || 'en'; const options = { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' }; $dateElem.text(new Date().toLocaleString(locale, options)); } // Keyboard navigation trap in modals/popups function handleKeyboardNavigation(e) { const selectors = 'input, a, button, [tabindex]:not([tabindex="-1"])'; const elements = $(this).find(selectors).filter(':visible'); const firstEl = elements.first()[0]; const lastEl = elements.last()[0]; if ((e.key === 'Tab' || e.keyCode === 9)) { if (!e.shiftKey && document.activeElement === lastEl) { e.preventDefault(); firstEl.focus(); } else if (e.shiftKey && document.activeElement === firstEl) { e.preventDefault(); lastEl.focus(); } } } // Sticky header on scroll $(window).on('scroll', () => { const $stickyHeader = $('#site-sticky-header'); if (!$stickyHeader.length) return; const stickyPos = $('#site-header').outerHeight() + 500; const scroll = $(window).scrollTop(); if (scroll > stickyPos) { $stickyHeader.addClass('fixed'); const stickyHeight = $stickyHeader.outerHeight(); $('.sidebar-container.sticky .sidebar-container-inner, .e-con.blogsy-sticky-column').css('top', stickyHeight + 10); } else { $stickyHeader.removeClass('fixed'); $stickyHeader.find('.popup-search, .offcanvas-wrapper').removeClass('open'); $('.sidebar-container.sticky .sidebar-container-inner, .e-con.blogsy-sticky-column').css('top', 10); } }); // Prevent empty anchor jumps in header nav $('.blogsy-header-nav li > a[href="#"], .blogsy-header-nav li > a[href=""], .blogsy-header-nav li > a:not([href])').on('click keydown', function(e) { // Only prevent empty/invalid links, not all links const href = $(this).attr('href'); if (!href || href === '#' || href === '') { e.preventDefault(); return false; } }); // Header vertical nav toggles $('.blogsy-header-v-nav li.menu-item-has-children > .blogsy-mobile-toggle, .blogsy-header-v-nav li.page_item_has_children > .blogsy-mobile-toggle').on('click keydown', function(e) { if (e.type === 'click' || (e.type === 'keydown' && isActivationKey(e))) { if (e.type === 'keydown') e.preventDefault(); $(this).parent().toggleClass('open').children('.sub-menu, .children').slideToggle(); } }); function blogsyMenuFocus() { let self = this; while (self && !self.classList.contains('blogsy-header-nav-wrapper') && !self.classList.contains('blogsy-header-v-nav-wrapper')) { if (self.tagName.toLowerCase() === 'li') { self.classList.toggle('hovered'); const hasSubmenu = self.querySelector('ul'); if (hasSubmenu) { self.setAttribute('aria-expanded', self.classList.contains('hovered')); } } self = self.parentElement; } } // Menu Accessibility Setup Function function setupMenuAccessibility() { if (!document.body.classList.contains('blogsy-menu-accessibility')) return; document.querySelectorAll('.blogsy-header-nav-wrapper, .blogsy-header-v-nav-wrapper').forEach(menu => { // Set aria-haspopup for all submenus menu.querySelectorAll('ul').forEach(subMenu => { subMenu.parentNode.setAttribute('aria-haspopup', 'true'); }); // Remove old listeners first to prevent duplicates menu.querySelectorAll('a').forEach(link => { link.removeEventListener('focus', blogsyMenuFocus, true); link.removeEventListener('blur', blogsyMenuFocus, true); }); // Add focus/blur listeners to all links (including dynamically added ones) menu.querySelectorAll('a').forEach(link => { link.addEventListener('focus', blogsyMenuFocus, true); link.addEventListener('blur', blogsyMenuFocus, true); }); }); } // Run initially setupMenuAccessibility(); // Custom debounce function function blogsyDebounce(func, wait) { let timeout; return function() { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, arguments), wait); }; } // Mobile detection - adds/removes body class based on breakpoint function blogsyCheckMobileMenu() { const responsiveBreakpoint = blogsy_ajax_object.header_breakpoint || 1025; // Update body class if mobile breakpoint is reached if (window.innerWidth < responsiveBreakpoint) { document.body.classList.add('blogsy-is-mobile'); } else { if (document.body.classList.contains('blogsy-is-mobile')) { document.body.classList.remove('blogsy-is-mobile'); } } } // Smart Submenus - Prevents submenu overflow function blogsySmartSubmenus() { if (document.body.classList.contains('blogsy-is-mobile')) return; var winRight = window.innerWidth; const menuSelectors = '.blogsy-header-nav .sub-menu, .blogsy-header-nav .children'; const submenus = document.querySelectorAll(menuSelectors); if (!submenus.length) return; submenus.forEach((item) => { const parentLi = item.closest('li'); if (!parentLi) return; parentLi.classList.remove('opens-left', 'opens-right'); // Store original styles const originalDisplay = item.style.display; const originalVisibility = item.style.visibility; const originalOpacity = item.style.opacity; // Temporarily show for calculation item.style.display = 'block'; item.style.visibility = 'visible'; item.style.opacity = '0'; // Get position const rect = item.getBoundingClientRect(); const elPosLeft = rect.left; const elPosRight = rect.right; // Restore original styles item.style.display = originalDisplay; item.style.visibility = originalVisibility; item.style.opacity = originalOpacity; // Apply positioning classes (with threshold for browser rounding) if (elPosRight > winRight - 1) { parentLi.classList.add('opens-left'); } else if (elPosLeft < 1) { parentLi.classList.add('opens-right'); } }); } // Initialize mobile detection and smart submenus on DOM ready blogsyCheckMobileMenu(); blogsySmartSubmenus(); // Navigation overflow menu function setOverflowMenu() { const { navigation_cutoff: cutoffOption, navigation_cutoff_upto: cutoffUpto, navigation_cutoff_text: cutoffText } = blogsy_ajax_object; const responsiveBreakpoint = blogsy_ajax_object.header_breakpoint || 1025; const moreMenuIcon = ` `; const createMoreMenuItem = (hasSubMenu) => { const className = hasSubMenu ? 'menu-item-has-children' : 'page_item_has_children'; const submenuClass = hasSubMenu ? 'sub-menu' : 'children'; return $(``); }; function createOverflowMenu($navContainer, startIndex) { const $childItems = $navContainer.children(`li:nth-child(n+${startIndex + 1})`); let $customItem = $navContainer.find(".menu-item-custom-more"); if (!$customItem.length && $childItems.length) { const hasSubMenu = $navContainer.find('.sub-menu').length > 0; $childItems.remove(); $customItem = createMoreMenuItem(hasSubMenu); $navContainer.append($customItem); $customItem.find('.sub-menu, .children').append($childItems); } } function restoreMenuItems($customItem) { const $cutOffItems = $customItem.find('.sub-menu > li, .children > li'); const $parentMenu = $customItem.closest('.blogsy-header-nav'); $customItem.remove(); $parentMenu.append($cutOffItems); } if (cutoffOption && cutoffUpto > 0 && $(window).width() >= responsiveBreakpoint) { const startIndex = cutoffUpto - 1; const $navContainers = $("#site-header .blogsy-header-nav-wrapper .blogsy-header-nav, #site-sticky-header .blogsy-header-nav-wrapper .blogsy-header-nav"); $navContainers.each(function() { createOverflowMenu($(this), startIndex); }); } else { const $customItems = $(".blogsy-header-nav-wrapper .blogsy-header-nav .menu-item-custom-more"); $customItems.each(function() { restoreMenuItems($(this)); }); } // Re-setup menu accessibility after overflow menu changes setupMenuAccessibility(); // Recalculate smart submenus after menu structure changes blogsySmartSubmenus(); } // Run on window resize $(window).on('resize', blogsyDebounce(function() { setOverflowMenu(); blogsyCheckMobileMenu(); blogsySmartSubmenus(); }, 100)); // Run once when page loads $(window).on('load', function() { setOverflowMenu(); blogsyCheckMobileMenu(); blogsySmartSubmenus(); }); // Back to top button and scroll indicator const backToTopButton = document.getElementById('back-to-top'); if (backToTopButton) { const activeClass = 'show'; const offset = 200; // Scroll to top function const scrollToTop = function() { window.scrollTo({ top: 0, behavior: 'smooth' }); }; // Get progress path elements const progressPath = backToTopButton.querySelector('.scroll-top-progress path'); if (progressPath) { const pathLength = progressPath.getTotalLength(); // Initialize progress circle progressPath.style.transition = progressPath.style.WebkitTransition = 'none'; progressPath.style.strokeDasharray = `${pathLength} ${pathLength}`; progressPath.style.strokeDashoffset = pathLength; progressPath.getBoundingClientRect(); progressPath.style.transition = progressPath.style.WebkitTransition = 'stroke-dashoffset 10ms linear'; // Update progress circle const updateProgress = function() { const scroll = window.scrollY || window.pageYOffset || document.documentElement.scrollTop; const docHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight ); const windowHeight = Math.max( document.documentElement.clientHeight, window.innerHeight || 0 ); const height = docHeight - windowHeight; const progress = pathLength - (scroll * pathLength / height); progressPath.style.strokeDashoffset = progress; }; updateProgress(); // Scroll event listener window.addEventListener('scroll', function() { updateProgress(); const scrollPos = window.scrollY || window.pageYOffset || document.documentElement.scrollTop; if (scrollPos > offset) { backToTopButton.classList.add(activeClass); } else { backToTopButton.classList.remove(activeClass); } }); } // Click event listener backToTopButton.addEventListener('click', scrollToTop); // Keyboard support (Enter/Space) backToTopButton.addEventListener('keydown', function(e) { if (isActivationKey(e)) { e.preventDefault(); scrollToTop(); } }); } // Dark mode toggle switch $('body').on('click keydown', '.dark-mode-switcher', function(e) { if (e.type === 'click' || (e.type === 'keydown' && isActivationKey(e))) { if (e.type === 'keydown') e.preventDefault(); const $html = $('html'); const $body = $('body'); const isDark = $html.attr('scheme') === 'dark'; $body.addClass('noTransition'); if (isDark) { $html.attr('scheme', 'light'); setCookie('blogsyDarkMode', 'disabled', 30); } else { $html.attr('scheme', 'dark'); setCookie('blogsyDarkMode', 'enabled', 30); } setTimeout(() => $body.removeClass('noTransition'), 200); } function setCookie(name, value, days) { if (navigator.cookieEnabled) { const date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); document.cookie = `${name}=${value}; path=/; expires=${date.toUTCString()};`; } } }); // Custom mouse cursor if ($(".blogsy-mouse-cursor").length) { $(document) .on('mousemove', e => { $(".blogsy-mouse-cursor").addClass('visible').css('transform', `translate(${e.clientX}px, ${e.clientY}px)`); }) .on('mouseleave', () => $(".blogsy-mouse-cursor").removeClass('visible')); const hoverSelectors = 'a, .popup-search-opener, .offcanvas-opener, .offcanvas-close, .popup-search-close, .toc-header-collapse, .dark-mode-switcher, .comments-compact-btn, .footer-canvas-menu-btn, button, input[type="button"], input[type="reset"], input[type="submit"]'; $('body').on('mouseenter', hoverSelectors, () => $(".blogsy-mouse-cursor").addClass('hovered')); $('body').on('mouseleave', hoverSelectors, () => $(".blogsy-mouse-cursor").removeClass('hovered')); } // Share link copy functionality $(".single-share-box-link .share-link-btn").on('click', function() { const $text = $(".single-share-box-link .share-link-text"); $text.select(); document.execCommand('copy'); $('.single-share-box-link .copied-popup-text').addClass('show'); setTimeout(() => $('.single-share-box-link .copied-popup-text').removeClass('show'), 2000); }); // Compact comments expand button $('.comments-compact-btn').on('click', function() { $('.comments-compact-btn').remove(); $('.comment-list-wrapper').removeClass('compact'); }); // Infinite scroll load more $(window).on('scroll', () => { $(".blogsy-post-load-more.infinite-scroll").each(function() { if (isScrolledIntoViewport($(this))) { $(this).trigger('click'); } }); }); // Load more posts AJAX handler $('.blogsy-post-load-more').on('click', function(e) { e.preventDefault(); const $btn = $(this); if ($btn.hasClass('hide')) return; const $loader = $btn.next('.blogsy-post-load-more-loader'); const $scope = $btn.closest('.blogsy-posts-container').find('.blogsy-posts-wrapper'); const widgetId = $btn.data('widget-id'); const postId = $btn.data('post-id'); const nextPage = $btn.data('current-page') + 1; $.post({ url: blogsy_ajax_object.AjaxUrl, data: { action: 'blogsy_get_load_more_posts', nonce: blogsy_ajax_object.nonce_get_load_more_posts, widgetId, postId, pageNumber: nextPage, qVars: typeof blogsyLoadMoreQVars !== 'undefined' ? blogsyLoadMoreQVars : '', }, dataType: 'json', beforeSend() { $btn.addClass('hide'); $loader.addClass('show'); }, success(response) { if (response.data) { let items = $(response.data); $scope.append(items); if ($scope.hasClass('layout-masonry')) $scope.masonry('appended', items); } if (response.no_more) { $loader.remove(); $btn.remove(); } else { $btn.data('current-page', nextPage); } }, complete() { $btn.removeClass('hide'); $loader.removeClass('show'); } }); }); // Prevent empty social icon clicks $('.blogsy-social-icons a[href=""], .blogsy-social-icons a[href="#"]').on('click', e => e.preventDefault()); // Peony hero slider setup function blogsyHeroSlider(el) { const $sliderWrapper = el.find('.blogsy-posts-carousel-wrapper'); if (!$sliderWrapper.length) return; const sliderSettings = $sliderWrapper.data('settings'); const sliderSelector = '#' + $sliderWrapper.attr('id') + ' .main-slider'; const $thumbsWrapper = el.find('.thumbs-slider-wrapper'); let mainSwiper; let thumbsSwiper; // If thumbs wrapper exists, initialize thumbs and link controllers if ($thumbsWrapper.length) { const thumbsSettings = $thumbsWrapper.data('settings'); const thumbsSelector = '#' + $thumbsWrapper.attr('id') + ' .thumbs-slider'; thumbsSwiper = new Swiper(thumbsSelector, thumbsSettings); mainSwiper = new Swiper(sliderSelector, sliderSettings); mainSwiper.controller.control = thumbsSwiper; thumbsSwiper.controller.control = mainSwiper; } else { // Only initialize main slider if thumbs not present mainSwiper = new Swiper(sliderSelector, sliderSettings); } } blogsyHeroSlider($('#blogsy-hero')); // Post carousel slider function blogsyPymlSlider(el) { const $carouselPosts = el.find('.blogsy-posts-wrapper.layout-carousel .blogsy-posts-carousel-wrapper'); if ($carouselPosts.length) { const carouselSettings = $carouselPosts.data('settings'); const carouselSelector = '#' + $carouselPosts.attr('id') + ' .swiper'; new Swiper(carouselSelector, carouselSettings); } } blogsyPymlSlider($('#blogsy-pyml')); /** * Stories Popup */ const StoriesPopup = { container: $('.blogsy-stories'), activeStoryId: null, allStoryIds: [], activeStoryCount: null, storiesWrap: $('.blogsy-stories .blogsy-stories-box'), storiesPopup: $('.blogsy-stories .stories-popup .stories-popup__inner'), actionButtons: $('.blogsy-stories .stories-popup__actions'), storyArrows: $('.blogsy-stories .stories-popup__arrows'), swiper: null, secondarySwiper: null, swiperInstances: {}, isPaused: false, outsideClickEnabled: false, isRtl: document.documentElement.dir === "rtl" || document.body.dir === "rtl", pendingTimeouts: [], isStoriesOpen: false, init: function() { if (!this.container.length) return; this.outsideClickEnabled = this.container.hasClass('outside-click--enabled'); this.countClick(); this.storyClick(); this.close(); this.pause(); this.closePopupOnESCPress(); $('body').css({ '--expandWidth-timer': `${5000 / 1000}s` }); let self = this; this.container.find('.stories-popup__slide').each(function() { let _this = $(this); let storyId = _this.data('id'); if (storyId) { self.allStoryIds.push(storyId); } }); }, countClick: function() { this.container.on('click', '.stories-popup__slide .story-count', function(event) { event.stopPropagation(); event.preventDefault(); }); }, storyClick: function() { let self = this; this.container.on('click', '.stories-popup__slide', function(e) { e.preventDefault(); let _this = $(this), storyId = _this.data('id'), count = _this.data('count'); let max_inner_items = _this.closest('.blogsy-stories').data('max-inner-items') ?? 4; if (!storyId) return; self.activeStoryId = storyId; self.activeStoryCount = count; self.storiesPopup.parent().addClass(`cat-${storyId}`); $('body').addClass('stories--open'); self.isStoriesOpen = true; // NEW: Mark stories as open if (!self.container.hasClass('added')) { self.ajaxCall(max_inner_items); } else { self.openStory(); } }); }, openStory: function() { let self = this; self.initMainSwiper(); self.storiesPopup.parent().addClass('open'); let storyWrap = self.storiesPopup.find(`.stories-popup__story-wrap[data-id="${self.activeStoryId}"]`); if (storyWrap.length) { self.initSecondarySwiper(storyWrap); self.addBackDrop(storyWrap.find('.image-wrapper img').first()); self.actionButtons.appendTo(storyWrap.parent()); self.storyArrows.appendTo(storyWrap.parent()); } // Navigate to active story if (self.swiper) { let slideIndex = self.swiper.slides.findIndex(slide => $(slide).data('id') == self.activeStoryId ); if (slideIndex !== -1) { self.swiper.slideTo(slideIndex, 0); } } self.container.addClass('added'); }, ajaxCall: function(max_inner_items) { let self = this; $.ajax({ method: 'POST', url: blogsy_ajax_object.AjaxUrl, data: { action: 'blogsy_stories_ajax_call', _wpnonce: blogsy_ajax_object.nonce_story, storyIds: self.allStoryIds, count: self.activeStoryCount, inner_count: max_inner_items }, beforeSend: function() { self.storiesWrap.addClass('retrieving-stories'); self.storiesWrap.css('cursor', 'wait'); }, success: function(result) { let { success, data } = result; if (success && data) { self.storiesPopup.html(data); self.openStory(); self.storiesPopup.parent().addClass('open'); } else { console.error('Failed to load stories'); } }, error: function(xhr, status, error) { console.error('AJAX Error:', error); }, complete: function() { self.storiesWrap.removeClass('retrieving-stories'); self.storiesWrap.css('cursor', 'default'); } }); }, initMainSwiper: function() { let self = this; // Destroy existing instance if (self.swiper) { self.swiper.destroy(true, true); self.swiper = null; } // Initialize main swiper self.swiper = new Swiper(self.storiesWrap.get(0), { slidesPerView: 1, effect: 'fade', fadeEffect: { crossFade: true }, loop: false, speed: 300, allowTouchMove: true, direction: 'horizontal', rtl: self.isRtl, spaceBetween: 15, navigation: { nextEl: '.blogsy-stories .stories-popup__arrows .swiper-button-next', prevEl: '.blogsy-stories .stories-popup__arrows .swiper-button-prev', disabledClass: 'disabled' }, on: { init: function() { self.updateArrowsState(this); }, slideChange: function() { self.onMainSlideChange(this); } } }); }, onMainSlideChange: function(swiperInstance) { let self = this; let currentSlide = $(swiperInstance.slides[swiperInstance.activeIndex]); let newStoryId = currentSlide.data('id'); let storyWrap = self.storiesPopup.find(`.stories-popup__story-wrap[data-id="${newStoryId}"]`); //let storyWrap = currentSlide.find('.stories-popup__story-wrap'); if (!storyWrap.length) return; // CRITICAL FIX: Cancel pending timeouts when switching stories // This prevents timeouts from previous stories from firing self.cancelPendingTimeouts(); // Destroy previous secondary swiper if (self.secondarySwiper && self.activeStoryId !== newStoryId) { self.secondarySwiper.destroy(true, true); self.secondarySwiper = null; } self.activeStoryId = newStoryId; // Update category class self.storiesPopup.parent().removeClass((index, className) => { return (className.match(/\bcat-\S+/g) || []).join(' '); }).addClass(`cat-${self.activeStoryId}`); // Initialize secondary swiper for new slide self.initSecondarySwiper(storyWrap); // Move action buttons and arrows self.actionButtons.appendTo(storyWrap.parent()); self.storyArrows.appendTo(storyWrap.parent()); // Update ambient background self.addBackDrop(storyWrap.find('.image-wrapper img').first()); // Update arrows state self.updateArrowsState(swiperInstance); }, initSecondarySwiper: function(selector) { let self = this; let $wrapper = $(selector); if (!$wrapper.length) return; let swiperContainer = $wrapper.find('.swiper').get(0); if (!swiperContainer) return; // Destroy existing secondary swiper if (self.secondarySwiper) { self.secondarySwiper.destroy(true, true); self.secondarySwiper = null; } // Initialize secondary swiper self.secondarySwiper = new Swiper(swiperContainer, { slidesPerView: 1, effect: 'fade', fadeEffect: { crossFade: true }, loop: false, speed: 300, autoplay: { delay: 5000, disableOnInteraction: false, pauseOnMouseEnter: false }, allowTouchMove: true, direction: 'horizontal', rtl: self.isRtl, pagination: { el: $wrapper.find('.swiper-pagination').get(0), clickable: true, renderBullet: function(index, className) { return ``; } }, navigation: { nextEl: $wrapper.find('.swiper-button-next').get(0), prevEl: $wrapper.find('.swiper-button-prev').get(0) }, on: { init: function() { // Update ambient on init let activeSlide = $(this.slides[this.activeIndex]); self.addBackDrop(activeSlide.find('.image-wrapper img')); self.checkThumbnail(activeSlide); }, slideChange: function() { self.onSecondarySlideChange(this); } } }); }, onSecondarySlideChange: function(swiperInstance) { let self = this; let currentIndex = swiperInstance.activeIndex; let slide = $(swiperInstance.slides[currentIndex]); // Update ambient self.addBackDrop(slide.find('.image-wrapper img')); // Check thumbnail self.checkThumbnail(slide); //Total slides let totalSlides = swiperInstance.slides.length; // Check if last slide let isLastSlide = currentIndex === (swiperInstance.slides.length - 1); if (isLastSlide) { // Create a timeout handle and store it let timeoutId = setTimeout(() => { // Check if stories are still open before executing if (!self.isStoriesOpen) { return; } if ( self.swiper && !self.swiper.destroyed && self.swiper.slides && self.swiper.slides.length > 0 && !self.swiper.isEnd ) { self.swiper.slideNext(); } else { self.closeStories(); } // Remove this timeout from pending list self.pendingTimeouts = self.pendingTimeouts.filter(id => id !== timeoutId); }, 4400); // Add to pending timeouts list self.pendingTimeouts.push(timeoutId); } }, checkThumbnail: function(slide) { let innerStory = slide.closest('.stories-popup__story'); if (slide.hasClass('no-thumb')) { innerStory.addClass('no-thumb'); } else { innerStory.removeClass('no-thumb'); } }, updateArrowsState: function(swiperInstance) { let $prevArrow = $('.blogsy-stories .stories-popup__arrows .swiper-button-prev'); let $nextArrow = $('.blogsy-stories .stories-popup__arrows .swiper-button-next'); if (swiperInstance.isBeginning) { $prevArrow.addClass('disabled'); } else { $prevArrow.removeClass('disabled'); } if (swiperInstance.isEnd) { $nextArrow.addClass('disabled'); } else { $nextArrow.removeClass('disabled'); } }, close: function() { let self = this; self.container.find('.stories-popup__button.close').on('click', function() { self.closeStories(); }); }, closeStories: function() { let self = this; self.isStoriesOpen = false; self.cancelPendingTimeouts(); $('body').removeClass('stories--open'); self.storiesPopup.parent().removeClass('open'); if (self.swiper && !self.swiper.destroyed && self.swiper.el) { self.swiper.destroy(true, true); self.swiper = null; } if (self.secondarySwiper && !self.secondarySwiper.destroyed && self.secondarySwiper.el) { self.secondarySwiper.destroy(true, true); self.secondarySwiper = null; } self.container.find('.stories-popup__backdrop').css({ 'background-image': '' }); // Reset pause button + SVG icons const $pauseBtn = self.container.find('.stories-popup__button.pause'); $pauseBtn.removeClass('paused'); $pauseBtn.find('.blogsy-svg-icon--play').css('display', 'none'); $pauseBtn.find('.blogsy-svg-icon--pause').css('display', 'inline-block'); self.activeStoryId = null; self.activeStoryCount = null; self.storiesPopup.parent().removeClass(function(index, className) { return (className.match(/\bcat-[^\s]+/g) || []).join(' '); }); self.storiesWrap.find('.stories-popup__slide').removeAttr('style'); }, pause: function() { let self = this; self.container.find('.stories-popup__button.pause').on('click', function() { let _this = $(this); // Toggle paused class first _this.toggleClass('paused'); // SVG visibility toggle if (_this.hasClass('paused')) { // Paused state: show play, hide pause _this.find('.blogsy-svg-icon--pause').css('display', 'none'); _this.find('.blogsy-svg-icon--play').css('display', 'inline-block'); } else { // Playing state: show pause, hide play _this.find('.blogsy-svg-icon--play').css('display', 'none'); _this.find('.blogsy-svg-icon--pause').css('display', 'inline-block'); } // Swiper autoplay control if (self.secondarySwiper && self.secondarySwiper.autoplay) { if (_this.hasClass('paused')) { self.secondarySwiper.autoplay.stop(); } else { self.secondarySwiper.autoplay.start(); } } }); }, addBackDrop: function(imageTag) { let $img = $(imageTag); if ($img.length) { let storyImage = $img.attr('src'); if (storyImage) { this.container.find('.stories-popup__backdrop').css({ 'background-image': 'url(' + storyImage + ')' }); } }else{ this.container.find('.stories-popup__backdrop').css({ 'background-image': 'none' }); } }, closePopupOnESCPress: function() { let self = this; $(document).on('keydown.StoriesPopup', function(event) { if (event.keyCode === 27 && $('body').hasClass('stories--open')) { self.closeStories(); } }); }, // NEW: Helper method to cancel all pending timeouts cancelPendingTimeouts: function() { this.pendingTimeouts.forEach(timeoutId => { clearTimeout(timeoutId); }); this.pendingTimeouts = []; } }; // Initialize on DOM ready $(document).ready(function() { StoriesPopup.init(); }); // Expose globally window.blogsy = window.blogsy || {}; window.blogsy.blogsyHeroSlider = blogsyHeroSlider; window.blogsy.blogsyPymlSlider = blogsyPymlSlider; })(jQuery);