PageSourceSearch

https://navhindtimes.in/wp-content/themes/foxiz/assets/js/global.js?ver=2.7.3

js navhindtimes.in collected 2026-10-02 05:04:11 UTC 135,767 bytes, 3,317 lines download raw bytes

1/**  FOXIZ MAN SCRIPT */
2var FOXIZ_MAIN_SCRIPT = (function (Module, $) {
3        'use strict';
4
5        Module.initParams = function () {
6            this.yesStorage = this.isStorageAvailable();
7            this.themeSettings = typeof foxizParams !== 'undefined' ? foxizParams : {};
8            this.galleriesData = typeof foxizGalleriesData !== 'undefined' ? foxizGalleriesData : {};
9            this.ajaxURL = typeof foxizCoreParams !== 'undefined' ? foxizCoreParams.ajaxurl || '' : '';
10            this.ajaxData = {};
11            this.siteAccessFlag = false;
12            this._document = $(document);
13            this._body = $('body');
14            this._window = $(window);
15            this.html = $('html, body');
16            this.outerHTML = $('html');
17            this.iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
18            this.wPoint = {};
19            this.sticky = {};
20            this.eSticky = {};
21            this.YTPlayers = {};
22            this.articleData = [];
23            this.readIndicatorPercent = 0;
24            this.isProgress = false;
25            this.readIndicator = $('#reading-progress');
26            this.popupNewsletterEl = $('#rb-popup-newsletter');
27
28            this.personalizeUID = (typeof FOXIZ_CORE_SCRIPT !== "undefined" && FOXIZ_CORE_SCRIPT.personalizeUID !== undefined)
29                ? FOXIZ_CORE_SCRIPT.personalizeUID
30                : 'u0';
31        }
32
33        Module.init = function () {
34            this.initParams();
35            this.syncLayoutLike();
36            this.topSpacing();
37            this.siteAccessDetector();
38            this.headerDropdown();
39            this.mobileCollapse();
40            this.initSubMenuPos();
41            this.privacyTrigger();
42            this.popupNewsletter();
43            this.documentClick();
44            this.backTop();
45            this.readIndicatorInit();
46            this.fontResizer();
47            this.breakingNews();
48            this.sequentialGalleryDisplay();
49            this.sliders();
50            this.carousels();
51            this.liveSearch();
52            this.personalizeBlocks();
53            this.personalizeCategories();
54            this.likeToggle();
55            this.singleInfiniteLoadNext();
56            this.loginPopup();
57            this.popupTemplate();
58            this.loadYoutubeIframe();
59            this.browserResize();
60            this.footerSlideUp();
61            this.cartNotification();
62            this.newsNotification();
63            this.tocToggle();
64            this.delayLoad();
65            this.showPostComment();
66            this.replyReview();
67            this.paginationNextPrev();
68            this.paginationLoadMore();
69            this.paginationInfinite();
70            this.productQuantity();
71            this.readingCollect();
72            this.liveBlog();
73            this.neededReloadFuncs();
74        }
75
76        Module.neededReloadFuncs = function () {
77            this.hoverTipsy();
78            this.scrollToComment();
79            this.usersRating();
80            this.singleGallery();
81            this.floatingVideo();
82            this.videoPreview();
83            this.floatingVideoRemove();
84            this.scrollTableContent();
85            this.singleScrollRefresh();
86            this.playerAutoPlay();
87            this.hoverEffects();
88            this.highlightShares();
89            this.galleryLightbox();
90            this.singleFeaturedLightbox();
91            this.accordion();
92            this.resIframeClassic();
93            this.taxBasedAccordion();
94            this.scrollBarSlider();
95        }
96
97        Module.reInitAll = function () {
98
99            this._window.trigger('load');
100            this.syncLayoutLike();
101            if (typeof FOXIZ_PERSONALIZE !== 'undefined') {
102                FOXIZ_PERSONALIZE.syncPersonalizeLayout();
103            }
104            if (typeof RB_REACTION !== 'undefined') {
105                RB_REACTION.syncReactLayout();
106            }
107            this.neededReloadFuncs();
108            Waypoint.refreshAll();
109        }
110
111        /** sync layout & reload features */
112        Module.reloadBlockFunc = function () {
113            this._window.trigger('load');
114
115            if (typeof FOXIZ_PERSONALIZE !== 'undefined') {
116                FOXIZ_PERSONALIZE.syncLayoutBookmarks();
117            }
118            this.syncLayoutLike();
119            this.videoPreview();
120            this.hoverTipsy();
121            Waypoint.refreshAll();
122        }
123
124        Module.initElementor = function () {
125            if ('undefined' !== typeof initDarkMode && !FOXIZ_MAIN_SCRIPT.editorDarkModeInit) {
126                FOXIZ_MAIN_SCRIPT.editorDarkModeInit = true;
127                initDarkMode();
128            }
129            FOXIZ_MAIN_SCRIPT.breakingNews();
130            FOXIZ_MAIN_SCRIPT.carousels();
131            FOXIZ_MAIN_SCRIPT.sliders();
132        }
133
134        Module.isRTL = function () {
135            return this._body.hasClass('rtl');
136        }
137
138        Module.animationFrame = function (callback) {
139            const func = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
140                window.webkitRequestAnimationFrame || this.animationFrameFallback
141            func.call(window, callback)
142        }
143
144        Module.animationFrameFallback = function (callback) {
145            window.setTimeout(callback, 1000 / 60)
146        }
147
148        /**
149         *
150         * @returns {boolean}
151         */
152        Module.isStorageAvailable = function () {
153            let storage;
154            try {
155                storage = window['localStorage'];
156                storage.setItem('__rbStorageSet', 'x');
157                storage.removeItem('__rbStorageSet');
158                return true;
159            } catch (e) {
160                return false;
161            }
162        }
163
164        /**
165         * set localStorage
166         * @param key
167         * @param data
168         */
169        Module.setStorage = function (key, data) {
170            this.yesStorage && localStorage.setItem(key, typeof data === 'string' ? data : JSON.stringify(data));
171        }
172
173        /**
174         * get localStorage
175         * @param key
176         * @param defaultValue
177         * @returns {any}
178         */
179        Module.getStorage = function (key, defaultValue) {
180            if (!this.yesStorage) return null;
181            const data = localStorage.getItem(key);
182            if (data === null) return defaultValue;
183            try {
184                return JSON.parse(data);
185            } catch (e) {
186                return data;
187            }
188        }
189
190        /**
191         * delelte localStorage
192         * @param key
193         */
194        Module.deleteStorage = function (key) {
195            this.yesStorage && localStorage.removeItem(key);
196        }
197
198        /**
199         *
200         * @param id
201         * @param value
202         * @param ttl
203         * @constructor
204         */
205        Module.SetTTLStorage = function (id, value, ttl) {
206            const data = {
207                value: value,
208                ttl: Date.now() + ttl * 3600000
209            };
210
211            this.setStorage(id, data);
212        }
213
214        /**
215         *
216         * @param id
217         * @returns {null|*}
218         */
219        Module.getTTLStorage = function (id) {
220
221            const data = this.getStorage(id);
222            if (data && Date.now() <= data.ttl) {
223                return data.value;
224            }
225            this.deleteStorage(id);
226            return null;
227        };
228
229        /** on load */
230        Module.delayLoad = function () {
231            const self = this;
232            setTimeout(function () {
233                self.stickyNavBar();
234                self.stickyHeaderBuilder();
235            }, 100)
236        }
237
238        /** resize */
239        Module.browserResize = function () {
240            const self = this;
241
242            self._window.on('resize', function () {
243                self.topSpacing();
244                self.calcSubMenuPos();
245            })
246        }
247
248        /* ================================ HEADERS ================================ */
249        Module.hoverTipsy = function () {
250
251            if (!$.fn.rbTipsy) {
252                return false;
253            }
254
255            this._body.find('[data-copy]').rbTipsy({
256                title: 'data-copy',
257                fade: true,
258                opacity: 1,
259                trigger: 'hover',
260                gravity: 's'
261            });
262
263            if (window.innerWidth > 1024) {
264                this._body.find('#site-header [data-title]').rbTipsy({
265                    title: 'data-title',
266                    fade: true,
267                    opacity: 1,
268                    trigger: 'hover',
269                    gravity: 'n'
270                });
271
272                this._body.find('.site-wrap [data-title]').rbTipsy({
273                    title: 'data-title',
274                    fade: true,
275                    opacity: 1,
276                    trigger: 'hover',
277                    gravity: 's'
278                });
279            }
280        }
281
282        /** font resizer */
283        Module.fontResizer = function () {
284            const self = this;
285            let size = self.yesStorage ? sessionStorage.getItem('rubyResizerStep') : 1;
286
287            self._body.on('click', '.font-resizer-trigger', function (e) {
288                e.preventDefault();
289                e.stopPropagation();
290                size++;
291                if (3 < size) {
292                    size = 1;
293                    self._body.removeClass('medium-entry-size big-entry-size')
294                } else {
295                    if (2 == size) {
296                        self._body.addClass('medium-entry-size').removeClass('big-entry-size');
297                    } else {
298                        self._body.addClass('big-entry-size').removeClass('medium-entry-size')
299                    }
300                }
301
302                self.yesStorage && sessionStorage.setItem('rubyResizerStep', size);
303            });
304        }
305
306        /** hover */
307        Module.hoverEffects = function () {
308            const selectors = $('.effect-fadeout');
309
310            if (selectors.length === 0) {
311                return;
312            }
313            selectors.off('mouseenter mouseleave').on('mouseenter', function (e) {
314                e.stopPropagation();
315                const target = $(this);
316                if (!target.hasClass('activated')) {
317                    target.addClass('activated');
318                }
319            }).on('mouseleave', function () {
320                $(this).removeClass('activated');
321            });
322        }
323
324        Module.videoPreview = function () {
325            let playPromise;
326
327            $('.preview-trigger').on('mouseenter', function () {
328                const target = $(this);
329                const wrap = target.find('.preview-video');
330                if (!wrap.hasClass('video-added')) {
331                    const video = '<video preload="auto" muted loop><source src="' + wrap.data('source') + '" type="' + wrap.data('type') + '"></video>';
332                    wrap.append(video).addClass('video-added');
333                }
334                target.addClass('show-preview');
335                wrap.css('z-index', 3);
336                const el = target.find('video')[0];
337                if (el) {
338                    playPromise = el.play();
339                }
340            }).on('mouseleave', function () {
341                const target = $(this);
342                target.find('.preview-video').css('z-index', 1);
343                const el = target.find('video')[0];
344                if (el && playPromise !== undefined) {
345                    playPromise.then(_ => {
346                        el.pause();
347                    }).catch();
348                }
349            });
350        }
351
352        Module.playerAutoPlay = function () {
353            const self = this;
354            const items = $('.is-autoplay');
355            const nonResIframe = $('.entry-content > iframe');
356
357            if (items != null && items.length > 0) {
358                items.each(function () {
359                    const el = $(this);
360                    if (!el.hasClass('is-loaded')) {
361                        self.wPoint['iframe'] = new Waypoint({
362                            element: el,
363                            handler: function () {
364                                const iframe = el.find('iframe');
365                                self.initAutoPlay(iframe);
366                                el.addClass('is-loaded');
367                                this.destroy();
368                            },
369                            offset: '60%'
370                        });
371                    }
372                })
373            }
374
375            if (nonResIframe != null && nonResIframe.length > 0) {
376                nonResIframe.each(function () {
377                    const el = $(this);
378                    if (!el.hasClass('is-loaded')) {
379                        const iURL = el.attr('src');
380                        if (iURL.indexOf('youtube.com') > 0 || iURL.indexOf('youtu.be') > 0 || iURL.indexOf('vimeo.com') > 0) {
381                            el.wrap('<div class="rb-ires is-loaded"></div>');
382                        }
383                    }
384                })
385            }
386        }
387
388        Module.initAutoPlay = function (item) {
389            if (item.length > 0 && undefined !== item[0]) {
390                const src = item[0].src;
391                if (src.indexOf('?') > -1) {
392                    item[0].src += "&autoplay=1";
393                } else {
394                    item[0].src += "?autoplay=1";
395                }
396            }
397        }
398
399        Module.tocToggle = function () {
400            this._document.on('click', '.toc-toggle', function (e) {
401                e.preventDefault();
402                e.stopPropagation();
403
404                const target = $(this);
405                const content = target.parents('.ruby-table-contents').find('.toc-content');
406                content.toggle(200);
407                target.toggleClass('activate');
408            });
409        };
410
411        /** Header JS functions */
412        Module.headerDropdown = function () {
413
414            const self = this;
415            $('.more-trigger').on('click', function (e) {
416
417                e.preventDefault();
418                e.stopPropagation();
419
420                /** re calc menu  */
421                self.calcSubMenuPos();
422
423                const target = $(this);
424                const holder = target.parents('.header-wrap').find('.more-section-outer');
425
426                if (!holder.hasClass('dropdown-activated')) {
427                    self._body.find('.dropdown-activated').removeClass('dropdown-activated');
428                    holder.addClass('dropdown-activated');
429                } else {
430                    holder.removeClass('dropdown-activated');
431                }
432                if (target.hasClass('search-btn')) {
433                    setTimeout(function () {
434                        holder.find('input[type="text"]').focus()
435                    }, 150);
436                }
437
438                return false;
439            });
440
441            /** search trigger */
442            $('.search-trigger').on('click', function (e) {
443                e.preventDefault();
444                e.stopPropagation();
445                const holder = $(this).parent('.header-dropdown-outer');
446                if (!holder.hasClass('dropdown-activated')) {
447                    self._body.find('.dropdown-activated').removeClass('dropdown-activated');
448                    holder.addClass('dropdown-activated');
449                    setTimeout(function () {
450                        holder.find('input[type="text"]').focus()
451                    }, 150);
452                } else {
453                    holder.removeClass('dropdown-activated');
454                }
455                return false;
456            });
457
458            /** header dropdown */
459            $('.dropdown-trigger').on('click', function (e) {
460                e.preventDefault();
461                e.stopPropagation();
462                const holder = $(this).parent('.header-dropdown-outer');
463                if (!holder.hasClass('dropdown-activated')) {
464                    self._body.find('.dropdown-activated').removeClass('dropdown-activated');
465                    holder.addClass('dropdown-activated');
466                } else {
467                    holder.removeClass('dropdown-activated');
468                }
469            });
470        }
471
472        Module.topSpacing = function () {
473            const self = this;
474            if (self._body.hasClass('top-spacing')) {
475                const height = $('.top-site-ad').outerHeight();
476                $('.site-outer').css('margin-top', height);
477            }
478        }
479
480        /** outside click */
481        Module.documentClick = function () {
482
483            const self = this;
484            const wrapper = $('.more-section-outer, .header-dropdown-outer, .mobile-collapse, .mfp-wrap');
485            const inlineSearchForm = $('.is-form-layout');
486
487            document.addEventListener('click', function (e) {
488
489                if (!wrapper.is(e.target) && wrapper.has(e.target).length === 0) {
490                    wrapper.removeClass('dropdown-activated');
491                    self.outerHTML.removeClass('collapse-activated');
492                }
493
494                if (!inlineSearchForm.is(e.target) && inlineSearchForm.has(e.target).length === 0) {
495                    inlineSearchForm.find('.live-search-response').fadeOut(500);
496                }
497            });
498        }
499
500        /** calc mega menu position */
501        Module.initSubMenuPos = function () {
502            const self = this;
503            let trigger = false;
504
505            /** add delay to ensure image loaded */
506            setTimeout(function () {
507                self.calcSubMenuPos();
508            }, 1000);
509
510            /** re calc when hovering */
511            $('.menu-has-child-mega').on('mouseenter', function () {
512                if (!trigger) {
513                    self.calcSubMenuPos();
514                }
515                trigger = true;
516            })
517        }
518
519        Module.calcSubMenuPos = function () {
520
521            if (window.outerWidth < 1025) {
522                return false;
523            }
524
525            const self = this;
526            const megaParents = $('.menu-has-child-mega');
527            const headerWrapper = $('#site-header');
528
529            /** for mega wide */
530            if (megaParents.length > 0) {
531                megaParents.each(function () {
532                    const item = $(this);
533                    item.find('.mega-dropdown').css({
534                        'width': self._body.width(),
535                        'left': -item.offset().left,
536                    });
537                    item.addClass('mega-menu-loaded')
538                })
539            }
540
541            /** sub-menu left right direction */
542            if (headerWrapper.length > 0) {
543
544                let headerLeftOffset = headerWrapper.offset().left;
545                let headerWidth = headerWrapper.width();
546                let headerRightOffset = headerLeftOffset + headerWidth;
547
548                const flexDropdown = $('.flex-dropdown');
549
550                /** sub menu direction */
551                const subElements = $('ul.sub-menu');
552                if (subElements.length > 0) {
553                    subElements.each(function () {
554                        const item = $(this);
555                        let itemLeftOffset = item.offset().left;
556                        let itemRightOffset = itemLeftOffset + item.width() + 100;
557                        if (itemRightOffset > headerRightOffset) {
558                            item.addClass('left-direction');
559                        }
560                    })
561                }
562
563                /** calc dropdown flex width */
564                if (flexDropdown.length > 0) {
565                    flexDropdown.each(function () {
566                        const item = $(this);
567                        const parentItem = item.parent();
568                        if (parentItem.hasClass('is-child-wide') || item.hasClass('mega-has-left')) {
569                            return;
570                        }
571                        const itemWidth = item.width();
572                        const itemHalfWidth = itemWidth / 2;
573                        const parentItemOffset = parentItem.offset().left;
574                        const parentHalfWidth = parentItem.width() / 2;
575                        const parentItemCenterOffset = parentItemOffset + parentHalfWidth;
576                        const rightSpacing = headerRightOffset - parentItemCenterOffset;
577                        const leftSpacing = parentItemCenterOffset - headerLeftOffset;
578
579                        if (itemWidth >= headerWidth) {
580                            item.css({
581                                'width': headerWidth - 2,
582                                'left': -parentItemOffset
583                            });
584                        } else if (itemHalfWidth > rightSpacing) {
585                            item.css({
586                                'right': -rightSpacing + parentHalfWidth + 1,
587                                'left': 'auto',
588                            });
589                        } else if (itemHalfWidth > leftSpacing) {
590                            item.css({
591                                'left': -leftSpacing + parentHalfWidth + 1,
592                                'right': 'auto',
593                            });
594                        } else {
595                            item.css({
596                                'right': 'auto',
597                                'left': -itemHalfWidth + parentHalfWidth,
598                            });
599                        }
600                    });
601                }
602            }
603        }
604
605        /**
606         *
607         * @returns {boolean}
608         */
609        Module.stickyNavBar = function () {
610
611            const self = this;
612
613            /** turn off sticky on editor mode */
614            if (self._body.hasClass('elementor-editor-active')) {
615                return false;
616            }
617
618            self.sticky.section = $('#sticky-holder');
619            self.sticky.outer = $('#navbar-outer');
620
621            if ((!self._body.hasClass('is-mstick') && !self._body.hasClass('yes-tstick')) || self.sticky.outer.length < 1 || self.sticky.section.length < 1) {
622                return false;
623            }
624
625            self.sticky.smartSticky = !!self._body.hasClass('is-smart-sticky');
626            self.sticky.isSticky = false;
627            self.sticky.lastScroll = 0;
628
629            if (self._body.hasClass('yes-tstick')) {
630                self.sticky.isTitleSticky = true;
631            } else {
632                self.sticky.isTitleSticky = 0;
633            }
634
635            self.sticky.additionalOffset = 200;
636            if (window.innerWidth > 1024) {
637                if (self.sticky.isTitleSticky) {
638                    self.sticky.additionalOffset = 450;
639                } else {
640                    self.sticky.additionalOffset = 0;
641                }
642            }
643
644            if (self._body.hasClass('admin-bar')) {
645                self.sticky.adminBarSpacing = 32;
646            } else {
647                self.sticky.adminBarSpacing = 0;
648            }
649
650            self.sticky.topOffset = self.sticky.section.offset().top;
651            self.sticky.stickySectionHeight = self.sticky.section.outerHeight();
652
653            self.sticky.outer.css('min-height', self.sticky.outer.outerHeight());
654            self.sticky.activatePos = self.sticky.topOffset + 1 + self.sticky.stickySectionHeight + self.sticky.additionalOffset;
655            self.sticky.deactivePos = self.sticky.topOffset - self.sticky.adminBarSpacing + self.sticky.additionalOffset;
656
657            if (window.addEventListener) {
658                if (self.sticky.smartSticky) {
659                    window.addEventListener('scroll', function () {
660                        self.animationFrame(self.initSmartStickyNavBar.bind(self));
661                    }, false);
662                } else {
663                    window.addEventListener('scroll', function () {
664                        self.animationFrame(self.initStickyNavBar.bind(self));
665                    }, false);
666                }
667            }
668
669            self._window.on('unstickMenu', function () {
670                self.sticky.outer.css('min-height', self.sticky.outer.outerHeight());
671                self.sticky.stickySectionHeight = self.sticky.section.outerHeight();
672                self.sticky.topOffset = self.sticky.section.offset().top;
673                self.sticky.activatePos = self.sticky.topOffset + 1 + self.sticky.stickySectionHeight + self.sticky.additionalOffset;
674                self.sticky.deactivePos = self.sticky.topOffset - self.sticky.adminBarSpacing + self.sticky.additionalOffset;
675            });
676        }
677
678        Module.initStickyNavBar = function () {
679            const self = this;
680            const scroll = self._window.scrollTop();
681
682            if (!self.sticky.isSticky && scroll > self.sticky.activatePos) {
683                self.sticky.isSticky = true;
684                self._body.addClass('stick-animated sticky-on');
685                self.sticky.stickAnimatedTimeout = setTimeout(function () {
686                    self._body.removeClass('stick-animated');
687                }, 200);
688            } else if (self.sticky.isSticky && scroll <= self.sticky.deactivePos) {
689                self.sticky.isSticky = false;
690                self._body.removeClass('sticky-on stick-animated');
691                self._window.trigger('unstickMenu');
692            }
693        }
694
695        Module.initSmartStickyNavBar = function () {
696            const self = this;
697            const scroll = self._window.scrollTop();
698
699            if (!self.sticky.isSticky && scroll > self.sticky.activatePos && scroll < self.sticky.lastScroll) {
700                self.sticky.isSticky = true;
701                self._body.addClass('stick-animated sticky-on');
702                self.sticky.stickAnimatedTimeout = setTimeout(function () {
703                    self._body.removeClass('stick-animated');
704                }, 200);
705            } else if (self.sticky.isSticky && (scroll <= self.sticky.deactivePos || scroll > self.sticky.lastScroll)) {
706                self.sticky.isSticky = false;
707                self._body.removeClass('sticky-on stick-animated');
708                if (scroll <= self.sticky.deactivePos) {
709                    self._window.trigger('unstickESection');
710                }
711            }
712            self.sticky.lastScroll = scroll;
713        }
714
715        /** header sticky template */
716        Module.stickyHeaderBuilder = function () {
717
718            const self = this;
719
720            /** turn off sticky on editor mode */
721            if (self._body.hasClass('elementor-editor-active')) {
722                return false;
723            }
724
725            let stickySection = $('.header-template .e-section-sticky').first();
726            const hasTitleSticky = $('body.single-post #s-title-sticky').first();
727
728            if (stickySection.length < 1) {
729                return false;
730            }
731
732            if (hasTitleSticky.length > 0) {
733                self._body.addClass('yes-tstick');
734                self.eSticky.isTitleSticky = true;
735            } else {
736                self.eSticky.isTitleSticky = 0;
737            }
738
739            self.eSticky.additionalOffset = 200;
740            if (window.innerWidth > 1024) {
741                if (self.eSticky.isTitleSticky) {
742                    self.eSticky.additionalOffset = 450;
743                } else {
744                    self.eSticky.additionalOffset = 0;
745                }
746            }
747
748            self.eSticky.smartSticky = !!stickySection.hasClass('is-smart-sticky');
749
750            /** mobile sticky for header template */
751            if (window.innerWidth <= 1024) {
752                stickySection.removeClass('e-section-sticky');
753                stickySection = $('#header-template-holder').addClass('e-section-sticky');
754            }
755
756            self.eSticky.section = stickySection;
757            self.eSticky.outer = stickySection.parent();
758
759            self.eSticky.adminBarSpacing = 0;
760            self.eSticky.isSticky = false;
761            self.eSticky.lastScroll = 0;
762            self.eSticky.stickySectionHeight = stickySection.outerHeight();
763            self.eSticky.topOffset = stickySection.offset().top;
764
765            /** set min height */
766            if (self._body.hasClass('admin-bar')) {
767                self.eSticky.adminBarSpacing = 32;
768            }
769            self.eSticky.outer.css('min-height', self.eSticky.outer.outerHeight());
770            self.eSticky.activatePos = self.eSticky.topOffset + 1 + self.eSticky.stickySectionHeight + self.eSticky.additionalOffset;
771            self.eSticky.deactivePos = self.eSticky.topOffset - self.eSticky.adminBarSpacing + self.eSticky.additionalOffset;
772
773            if (window.addEventListener) {
774                if (self.eSticky.smartSticky) {
775                    window.addEventListener('scroll', function () {
776                        self.animationFrame(self.initSmartStickyESection.bind(self));
777                    }, false);
778                } else {
779                    window.addEventListener('scroll', function () {
780                        self.animationFrame(self.initStickyESection.bind(self));
781                    }, false);
782                }
783            }
784
785            /** re-calc height values */
786            self._window.on('unstickESection', function () {
787                self.eSticky.outer.css('min-height', self.eSticky.outer.outerHeight());
788                self.eSticky.stickySectionHeight = self.eSticky.section.outerHeight();
789                self.eSticky.topOffset = self.eSticky.section.offset().top;
790                self.eSticky.activatePos = self.eSticky.topOffset + 1 + self.eSticky.stickySectionHeight + self.eSticky.additionalOffset;
791                self.eSticky.deactivePos = self.eSticky.topOffset - self.eSticky.adminBarSpacing + self.eSticky.additionalOffset;
792            });
793        }
794
795        Module.initStickyESection = function () {
796            const self = this;
797            const scroll = self._window.scrollTop();
798            if (!self.eSticky.isSticky && scroll > self.eSticky.activatePos) {
799                self.eSticky.isSticky = true;
800                self._body.addClass('stick-animated sticky-on');
801                self.eSticky.stickAnimatedTimeout = setTimeout(function () {
802                    self._body.removeClass('stick-animated');
803                }, 200);
804            } else if (self.eSticky.isSticky && scroll <= self.eSticky.deactivePos) {
805                self.eSticky.isSticky = false;
806                self._body.removeClass('sticky-on stick-animated');
807                self._window.trigger('unstickESection');
808            }
809        }
810
811        Module.initSmartStickyESection = function () {
812            const self = this;
813            const scroll = self._window.scrollTop();
814
815            if (!self.eSticky.isSticky && scroll > self.eSticky.activatePos && scroll < self.eSticky.lastScroll) {
816                self.eSticky.isSticky = true;
817                self._body.addClass('stick-animated sticky-on');
818                self.eSticky.stickAnimatedTimeout = setTimeout(function () {
819                    self._body.removeClass('stick-animated');
820                }, 200);
821            } else if (self.eSticky.isSticky && (scroll <= self.eSticky.deactivePos || scroll > self.eSticky.lastScroll)) {
822                self.eSticky.isSticky = false;
823                self._body.removeClass('sticky-on stick-animated');
824                if (scroll <= self.eSticky.deactivePos) {
825                    self._window.trigger('unstickESection');
826                }
827            }
828
829            self.eSticky.lastScroll = scroll;
830        }
831
832        /** mobileCollapse */
833        Module.mobileCollapse = function () {
834            const self = this;
835            const $mobileMenuTrigger = $('.mobile-menu-trigger');
836            const $outerHTML = self.outerHTML;
837            const $mobileSearchForm = $outerHTML.find('.mobile-search-form input[type="text"]');
838
839            $mobileMenuTrigger.on('click', function (e) {
840                e.preventDefault();
841                e.stopPropagation();
842                const target = $(this);
843
844                if (target.hasClass('mobile-search-icon')) {
845                    setTimeout(function () {
846                        $mobileSearchForm.focus();
847                    }, 100);
848                }
849
850                const isCollapseActivated = $outerHTML.hasClass('collapse-
850activated');
851                $outerHTML.toggleClass('collapse-activated', !isCollapseActivated);
852            });
853        }
854
855        /**
856         * privacy trigger
857         */
858        Module.privacyTrigger = function () {
859            const self = this;
860            $('#privacy-trigger').on('click', function (e) {
861                e.preventDefault();
862                e.stopPropagation();
863                self.setStorage('RubyPrivacyAllowed', '1');
864                $('#rb-privacy').slideUp(200, function () {
865                    $(this).remove();
866                });
867                return false;
868            });
869        }
870
871        /** back top */
872        Module.backTop = function () {
873            if (this._body.hasClass('is-backtop')) {
874                $().UItoTop({
875                    text: '<i class="rbi rbi-darrow-top"></i>',
876                });
877            }
878        }
879
880        /** login popup */
881        Module.loginPopup = function () {
882
883            const self = this;
884            const form = $('#rb-user-popup-form');
885            if (form.length < 1) {
886                return false;
887            }
888            this._document.on('click', '.login-toggle', (e) => {
889                e.preventDefault();
890                e.stopPropagation();
891                $.magnificPopup.open({
892                    type: 'inline',
893                    preloader: false,
894                    removalDelay: 400,
895                    showCloseBtn: true,
896                    closeBtnInside: true,
897                    closeOnBgClick: false,
898                    items: {
899                        src: form,
900                        type: 'inline'
901                    },
902                    mainClass: 'rb-popup-center',
903                    closeMarkup: '<span class="close-popup-btn mfp-close"><span class="close-icon"></span></span>',
904                    fixedBgPos: true,
905                    fixedContentPos: true,
906                    callbacks: {open: () => self.reloadCaptchaPopups()}
907                });
908            });
909        };
910
911        /** popup template blocks */
912        Module.popupTemplate = function () {
913
914            const templateCache = {};
915            this._document.on('click', '.popup-trigger-btn', (e) => {
916
917                e.preventDefault();
918                e.stopPropagation();
919
920                const target = $(e.target);
921                const templateID = target.data('trigger') || '';
922                const position = target.data('position') || '';
923
924                if (!templateCache[templateID]) {
925                    const template = $(`#tmpl-${templateID}`);
926                    if (template.length === 0) {
927                        return;
928                    }
929                    templateCache[templateID] = template.html();
930                }
931                $.magnificPopup.open({
932                    type: 'inline',
933                    preloader: false,
934                    removalDelay: 400,
935                    showCloseBtn: true,
936                    closeBtnInside: true,
937                    closeOnBgClick: true,
938                    allowHTMLInTemplate: true,
939                    items: {
940                        src: templateCache[templateID],
941                        type: 'inline'
942                    },
943                    mainClass: `is-template-popup popup-${templateID} ${position}`,
944                    closeMarkup: '<span class="close-popup-btn mfp-close"><span class="close-icon"></span></span>',
945                    fixedBgPos: true,
946                    fixedContentPos: true,
947                    callbacks: {open: () => self.reloadCaptchaPopups()},
948                });
949            });
950        };
951
952        /** newsletter */
953        Module.popupNewsletter = function () {
954
955            const self = this;
956            if (self.popupNewsletterEl.length > 0) {
957                const display = self.popupNewsletterEl.data('display');
958                self.newsletterExpired = self.popupNewsletterEl.data('expired');
959                self.newsletterDisplayOffset = self.popupNewsletterEl.data('offset');
960                const delay = self.popupNewsletterEl.data('delay');
961                const oldExpired = self.getStorage('RubyNewsletterExpired');
962
963                if (self.newsletterExpired === 0) {
964                    self.deleteStorage('RubyNewsletter');
965                }
966
967                if (!oldExpired || self.newsletterExpired !== oldExpired) {
968                    self.setStorage('RubyNewsletterExpired', self.newsletterExpired);
969                    self.deleteStorage('RubyNewsletter');
970                }
971
972                if (!self.getTTLStorage('RubyNewsletter')) {
973                    if (!display || 'scroll' === display) {
974                        if (window.addEventListener) {
975                            window.addEventListener('scroll', function () {
976                                self.animationFrame(self.scrollPopupNewsletter.bind(self));
977                            }, false);
978                        }
979                    } else {
980                        setTimeout(function () {
981                            self.popupNewsletterInit();
982                        }, delay);
983                    }
984                }
985            }
986        }
987
988        Module.scrollPopupNewsletter = function () {
989            const self = this;
990            if (!self.newsletterPopupFlag && self._window.scrollTop() > self.newsletterDisplayOffset) {
991                self.newsletterPopupFlag = true;
992                self.popupNewsletterInit();
993            }
994        }
995
996        Module.popupNewsletterInit = function () {
997
998            const self = this;
999            if (self.siteAccessFlag) {
1000                return;
1001            }
1002
1003            if (!self.popupNewsletterEl.hasClass('is-pos-fixed')) {
1004                $.magnificPopup.open({
1005                    type: 'inline',
1006                    preloader: false,
1007                    closeBtnInside: true,
1008                    removalDelay: 400,
1009                    showCloseBtn: true,
1010                    closeOnBgClick: false,
1011                    disableOn: 1024,
1012                    items: {
1013                        src: '#rb-popup-newsletter',
1014                        type: 'inline'
1015                    },
1016                    mainClass: 'rb-popup-center',
1017                    fixedBgPos: true,
1018                    fixedContentPos: true,
1019                    closeMarkup: '<span class="close-popup-btn mfp-close"><span class="close-icon"></span></span>',
1020                    callbacks: {
1021                        open: () => self.reloadCaptchaPopups(),
1022                        close: function () {
1023                            if (self.siteAccessFlag) {
1024                                return;
1025                            }
1026                            self.SetTTLStorage('RubyNewsletter', 1, self.newsletterExpired * 24);
1027                        }
1028                    }
1029                });
1030            } else {
1031                self.popupNewsletterEl.removeClass('is-hidden');
1032                setTimeout(() => {
1033                    self.popupNewsletterEl.addClass('yes-show');
1034                }, 10);
1035                const closeBtn = self.popupNewsletterEl.find('.close-popup-btn');
1036                closeBtn.on('click', function () {
1037                    self.SetTTLStorage('RubyNewsletter', 1, self.newsletterExpired * 24);
1038                    self.popupNewsletterEl.removeClass('yes-show');
1039                    setTimeout(() => {
1040                        self.popupNewsletterEl.addClass('is-hidden');
1041                    }, 400);
1042                });
1043            }
1044        }
1045
1046        /** footer slide up */
1047        Module.footerSlideUp = function () {
1048            const target = $('#footer-slideup');
1049            if (target.length > 0) {
1050                const self = this;
1051                self.footerSlideUpExpired = target.data('expired');
1052                const delay = target.data('delay');
1053                const oldExpired = self.getStorage('footerSlideUpExpired');
1054                if (!oldExpired || self.footerSlideUpExpired != oldExpired) {
1055                    self.setStorage('footerSlideUpExpired', self.footerSlideUpExpired);
1056                    self.deleteStorage('footerSlideUp');
1057                }
1058                if (!self.getTTLStorage('footerSlideUp')) {
1059                    setTimeout(function () {
1060                        self.footerSlideUpInit();
1061                    }, delay);
1062                }
1063                /** show hide toggle */
1064                setTimeout(function () {
1065                    self.footerSlideUpToggle();
1066                }, delay);
1067            }
1068        }
1069
1070        Module.footerSlideUpToggle = function () {
1071            const self = this;
1072            $('.slideup-toggle').off('click').on('click', function (e) {
1073                e.preventDefault();
1074                e.stopPropagation();
1075                self.footerSlideUpInit();
1076                return false;
1077            });
1078        }
1079
1080        Module.footerSlideUpInit = function () {
1081            if (this._body.hasClass('yes-f-slideup')) {
1082                this._body.removeClass('yes-f-slideup');
1083                this.SetTTLStorage('footerSlideUp', 1, this.footerSlideUpExpired * 24);
1084            } else {
1085                this._body.addClass('yes-f-slideup');
1086                this.deleteStorage('footerSlideUp');
1087            }
1088        }
1089
1090        /** youtube iframe */
1091        Module.loadYoutubeIframe = function () {
1092
1093            const self = this;
1094            const blockPlaylist = $('.yt-playlist');
1095            if (blockPlaylist.length > 0) {
1096                const tag = document.createElement('script');
1097                tag.src = "//www.youtube.com/iframe_api";
1098                const firstScriptTag = document.getElementsByTagName('script')[0];
1099                firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
1100            }
1101
1102            window.onYouTubeIframeAPIReady = function () {
1103                $('.yt-playlist').each(function () {
1104                    const target = $(this);
1105                    const iframe = target.find('.yt-player');
1106                    const videoID = target.data('id');
1107                    const blockID = target.data('block');
1108                    self.YTPlayers[blockID] = new YT.Player(iframe.get(0), {
1109                        height: '540',
1110                        width: '960',
1111                        videoId: videoID,
1112                        events: {
1113                            'onReady': self.videoPlayToggle,
1114                            'onStateChange': self.videoPlayToggle
1115                        }
1116                    });
1117                });
1118
1119                $('.plist-item').on('click', function (e) {
1120                    e.preventDefault();
1121                    e.stopPropagation();
1122
1123                    const target = $(this);
1124                    const wrapper = target.closest('.yt-playlist');
1125                    const currentBlockID = wrapper.data('block');
1126                    const videoID = target.data('id');
1127                    const title = target.find('.plist-item-title').text();
1128                    const meta = target.data('index');
1129
1130                    Object.keys(self.YTPlayers).forEach(function (id) {
1131                        self.YTPlayers[id].pauseVideo();
1132                    });
1133                    self.YTPlayers[currentBlockID].loadVideoById({
1134                        'videoId': videoID
1135                    });
1136
1137                    wrapper.find('.yt-trigger').addClass('is-playing');
1138                    wrapper.find('.play-title').hide().text(title).fadeIn(200);
1139                    wrapper.find('.video-index').text(meta);
1140                });
1141            }
1142        }
1143
1144        Module.videoPlayToggle = function () {
1145
1146            const players = FOXIZ_MAIN_SCRIPT.YTPlayers;
1147
1148            $('.yt-trigger').on('click', function (e) {
1149                e.preventDefault();
1150                e.stopPropagation();
1151
1152                const target = $(this);
1153                const currentBlockID = target.closest('.yt-playlist').data('block');
1154                const currentState = players[currentBlockID].getPlayerState();
1155                const isPlaying = [1, 3].includes(currentState);
1156                if (!isPlaying) {
1157                    players[currentBlockID].playVideo();
1158                    target.addClass('is-playing');
1159                } else {
1160                    players[currentBlockID].pauseVideo();
1161                    target.removeClass('is-playing');
1162                }
1163            });
1164        }
1165
1166        /** Comment scripts */
1167        Module.showPostComment = function () {
1168            const self = this;
1169
1170            this._document.on('click', '.smeta-sec .meta-comment', function (e) {
1171                e.stopPropagation();
1172                const commentBtn = $('.show-post-comment');
1173                if (commentBtn.length > 0) {
1174                    self.html.animate({scrollTop: commentBtn.offset().top}, 300);
1175                    commentBtn.trigger('click');
1176                }
1177            });
1178
1179            this._document.on('click', '.show-post-comment', function (e) {
1180                e.preventDefault();
1181                e.stopPropagation();
1182                const target = $(this);
1183                const wrap = target.parent();
1184
1185                target.fadeOut(200, function () {
1186                    target.remove();
1187                    wrap.find('.is-invisible').removeClass('is-invisible');
1188                    wrap.next('.comment-holder').removeClass('is-hidden');
1189                })
1190            });
1191        }
1192
1193        /** table scroll */
1194        Module.scrollTableContent = function () {
1195
1196            const self = this;
1197            const behavior = self._body.hasClass('toc-smooth') ? 'smooth' : 'instant';
1198
1199            self._document.on('click', '.anchor-link', function (e) {
1200                e.stopPropagation();
1201
1202                const targetClass = $(this).data('index');
1203                if (!targetClass) return;
1204
1205                let $scrollElement = $(`.${targetClass}`);
1206
1207                // if target not found, search inside its parent .s-ct
1208                if (!$scrollElement.length) {
1209                    const $parentContainer = $(this).closest('.s-ct');
1210                    if ($parentContainer.length) {
1211                        $scrollElement = $parentContainer.find('.restrict-box, .continue-reading-btn').first();
1212                    }
1213                }
1214
1215                if (!$scrollElement.length) return;
1216
1217                setTimeout(() => {
1218                    window.scrollTo({
1219                        top: $scrollElement.offset().top,
1220                        behavior: behavior,
1221                    });
1222                }, 10);
1223            });
1224        };
1225
1226        /** scroll to comment  */
1227        Module.scrollToComment = function () {
1228            const self = this;
1229            const hash = window.location.hash;
1230            if (hash === '#respond' || hash.startsWith('#comment')) {
1231                const commentBtn = $('.show-post-comment').first();
1232                if (commentBtn.length === 0) {
1233                    return;
1234                }
1235                self.html.animate({scrollTop: commentBtn.offset().top - 200}, 400);
1236                commentBtn.trigger('click');
1237            }
1238        }
1239
1240        Module.replyReview = function () {
1241            this._document.on('click', '.comment-reply-link', function () {
1242                const target = $(this);
1243                const wrapper = target.parents('.rb-reviews-area');
1244                const cancelLink = $('#cancel-comment-reply-link');
1245                if (wrapper.length > 0) {
1246                    wrapper.find('.rb-form-rating').addClass('is-hidden');
1247                    cancelLink.on('click', function () {
1248                        wrapper.find('.rb-form-rating').removeClass('is-hidden');
1249                    });
1250                }
1251            });
1252        }
1253
1254        /** user rating */
1255        Module.usersRating = function () {
1256            const self = this;
1257            const reviewsForm = self._body.find('.rb-reviews-form');
1258            if (reviewsForm.length > 0) {
1259                reviewsForm.each(function () {
1260                    const reviewForm = $(this);
1261                    if (!reviewForm.hasClass('is-loaded')) {
1262                        reviewForm.addClass('is-loaded');
1263                        const ratingForm = reviewForm.find('.rb-form-rating');
1264                        const selection = reviewForm.find('.rb-rating-selection');
1265                        const text = reviewForm.find('.rating-alert').html();
1266                        let ratingValue = null;
1267
1268                        selection.val('');
1269                        selection.hide();
1270                        selection.before(
1271                            '<div class="rb-review-stars">\
1272                                <span>\
1273                                    <a class="star" data-rating="1" href="#"><i class="rbi rbi-star-o"></i></a>\
1274                                    <a class="star" data-rating="2" href="#"><i class="rbi rbi-star-o"></i></a>\
1275                                    <a class="star" data-rating="3" href="#"><i class="rbi rbi-star-o"></i></a>\
1276                                    <a class="star" data-rating="4" href="#"><i class="rbi rbi-star-o"></i></a>\
1277                                    <a class="star" data-rating="5" href="#"><i class="rbi rbi-star-o"></i></a>\
1278                                </span>\
1279                            </div>'
1280                        );
1281
1282                        ratingForm.on('click', 'a.star', function (e) {
1283                            e.preventDefault();
1284                            e.stopPropagation();
1285                            const star = $(this);
1286                            ratingValue = star.data('rating');
1287                            star.siblings('a').removeClass('active');
1288                            star.addClass('active');
1289                            ratingForm.addClass('selected');
1290                        });
1291
1292                        reviewForm.on('click', '#respond #submit', function () {
1293                            selection.val(ratingValue);
1294                            if (!selection.val()) {
1295                                window.alert(text);
1296                                return false;
1297                            }
1298                        });
1299                    }
1300                });
1301            }
1302        }
1303
1304        /**
1305         *
1306         * @returns {boolean}
1307         */
1308        Module.readIndicatorInit = function () {
1309
1310            const self = this;
1311            if (!self._body.hasClass('single') || self.readIndicator.length < 1) {
1312                return false;
1313            }
1314
1315            let content = $('.entry-content').first();
1316            if (!content.length) return false;
1317
1318            self.indicatorTop = content.offset().top;
1319            self.indicatorHeight = content.outerHeight(true) - self._window.height();
1320            /** delay for load images */
1321            setTimeout(function () {
1322                self.indicatorTop = content.offset().top;
1323                self.indicatorHeight = content.outerHeight(true) - self._window.height();
1324            }, 1000)
1325
1326            if (window.addEventListener) {
1327                window.addEventListener('scroll', function () {
1328                    self.animationFrame(self.readIndicatorCalc.bind(self));
1329                }, false);
1330            }
1331        }
1332
1333        Module.readIndicatorCalc = function () {
1334            const self = this;
1335            const scroll = self._window.scrollTop();
1336            self.readIndicatorPercent = Math.min(((scroll - self.indicatorTop) / self.indicatorHeight) * 100, 100);
1337            if (self.readIndicatorPercent <= 100) {
1338                self.readIndicator.css('width', self.readIndicatorPercent + '%');
1339            }
1340        }
1341
1342        /** breaking news */
1343        Module.breakingNews = function () {
1344            const self = this;
1345            const breakingNews = $('.breaking-news-slider')
1346
1347            if (breakingNews.length < 1) {
1348                return false;
1349            }
1350
1351            breakingNews.each(function () {
1352                const el = $(this);
1353                let params = {
1354                    slidesPerView: 1,
1355                    loop: true,
1356                }
1357                if (el.data('play')) {
1358                    params.autoplay = {
1359                        delay: el.data('speed') || self.themeSettings.sliderSpeed,
1360                        stopOnLastSlide: false,
1361                        disableOnInteraction: self.isElementorEditor ? true : (window.outerWidth < 1025),
1362                        pauseOnMouseEnter: true
1363                    };
1364                }
1365                params.navigation = {
1366                    nextEl: el.find('.breaking-news-next')[0],
1367                    prevEl: el.find('.breaking-news-prev')[0]
1368                }
1369                new RBSwiper(this, params);
1370            });
1371        }
1372
1373        /** overlay slider */
1374        Module.sliders = function () {
1375
1376            const self = this;
1377            const sliders = $('.post-slider');
1378            if (sliders.length < 1) {
1379                return false;
1380            }
1381
1382            sliders.each(function () {
1383                const slider = $(this);
1384                let params = {
1385                    grabCursor: true,
1386                    allowTouchMove: true,
1387                    effect: self.themeSettings.sliderEffect,
1388                    loop: true,
1389                }
1390                if (slider.data('play')) {
1391                    params.autoplay = {
1392                        delay: slider.data('speed') || self.themeSettings.sliderSpeed,
1393                        stopOnLastSlide: true,
1394                        disableOnInteraction: self.isElementorEditor ? true : (window.outerWidth < 1025),
1395                        pauseOnMouseEnter: true
1396                    };
1397                }
1398
1399                params.pagination = {
1400                    el: slider.find('.slider-pagination')[0],
1401                    clickable: true,
1402                };
1403
1404                params.navigation = {
1405                    nextEl: slider.find('.slider-next')[0],
1406                    prevEl: slider.find('.slider-prev')[0]
1407                }
1408                new RBSwiper(this, params);
1409            });
1410        }
1411
1412        /** carousel blocks */
1413        Module.carousels = function () {
1414            const self = this;
1415            const carousels = $('.post-carousel');
1416            if (carousels.length < 1) {
1417                return false;
1418            }
1419            carousels.each(function () {
1420                const carousel = $(this);
1421                let params = {
1422                    grabCursor: true,
1423                    allowTouchMove: true,
1424                    freeMode: false,
1425                    loop: true
1426                }
1427                params.slidesPerView = carousel.data('mcol');
1428                params.spaceBetween = carousel.data('mgap');
1429                params.centeredSlides = carousel.data('centered');
1430
1431                params.navigation = {
1432                    nextEl: carousel.find('.slider-next')[0],
1433                    prevEl: carousel.find('.slider-prev')[0]
1434                }
1435                if (carousel.find('.slider-pagination')[0]) {
1436                    params.pagination = {
1437                        el: carousel.find('.slider-pagination')[0],
1438                        type: 'bullets',
1439                        clickable: true,
1440                    };
1441                }
1442
1443                if (carousel.data('play')) {
1444                    params.autoplay = {
1445                        delay: carousel.data('speed') || self.themeSettings.sliderSpeed,
1446                        stopOnLastSlide: false,
1447                        disableOnInteraction: self.isElementorEditor ? true : (window.outerWidth < 1025),
1448                        pauseOnMouseEnter: true
1449                    };
1450                }
1451
1452                if (carousel.data('fmode')) {
1453                    params.freeMode = true;
1454                }
1455                params.breakpoints = {
1456                    768: {
1457                        slidesPerView: carousel.data('tcol'),
1458                        spaceBetween: carousel.data('tgap')
1459                    },
1460                    1025: {
1461                        slidesPerView: carousel.data('col'),
1462                        spaceBetween: carousel.data('gap')
1463                    },
1464                    1500: {
1465                        slidesPerView: carousel.data('wcol'),
1466                        spaceBetween: carousel.data('gap')
1467                    }
1468                };
1469                params.on = {
1470                    afterInit: function (swiper) {
1471                        const wrap = $(swiper.$wrapperEl);
1472                        $(swiper.$wrapperEl).find('.p-box').css('height', wrap.height());
1473                    },
1474                    resize: function (swiper) {
1475                        const wrap = $(swiper.$wrapperEl);
1476                        $(swiper.$wrapperEl).find('.p-box').css('height', wrap.height());
1477                    },
1478                };
1479
1480                new RBSwiper(this, params);
1481            });
1482        }
1483
1484        /* ================================ SINGLE GALLERY ================================ */
1485        Module.singleGallery = function () {
1486
1487            const self = this;
1488            const gallerySections = self._body.find('.featured-gallery-wrap');
1489            if (gallerySections.length === 0) {
1490                return;
1491            }
1492
1493            gallerySections.each(function () {
1494                const section = $(this);
1495                if (!section.hasClass('is-loaded')) {
1496                    const index = section.data('gallery');
1497                    const sliderEl = section.find('.gallery-slider').attr('id');
1498                    const sliderNavEl = section.find('.gallery-slider-nav').attr('id');
1499                    const carouselEl = section.find('.gallery-carousel').attr('id');
1500                    const coverflowEL = section.find('.gallery-coverflow').attr('id');
1501
1502                    if (sliderEl && sliderNavEl) {
1503
1504                        const navEl = $('#' + sliderNavEl);
1505                        const navSlidesCount = navEl.find('.swiper-slide').length;
1506                        const shouldLoopNav = navSlidesCount >= 6;
1507                        const viewSlides = Math.min(navSlidesCount, 6);
1508
1509                        if (!shouldLoopNav) {
1510                            navEl.css('max-width', `${navSlidesCount * 125}px`);
1511                        }
1512
1513                        const galleryNav = new RBSwiper('#' + sliderNavEl, {
1514                            spaceBetween: 15,
1515                            slidesPerView: viewSlides,
1516                            freeMode: self.themeSettings.sliderFMode,
1517                            grabCursor: true,
1518                            loop: shouldLoopNav,
1519                            watchSlidesVisibility: shouldLoopNav,
1520                            watchSlidesProgress: true,
1521                            on: {
1522                                init: function () {
1523                                    $(this.$wrapperEl).removeClass('pre-load');
1524                                },
1525                            },
1526                        });
1527
1528                        const gallerySlider = new RBSwiper('#' + sliderEl, {
1529                            spaceBetween: 0,
1530                            grabCursor: true,
1531                            loop: true,
1532                            pagination: {
1533                                el: '.swiper-pagination-' + index,
1534                                type: 'progressbar',
1535                                clickable: true,
1536                            },
1537                            on: {
1538                                init: function () {
1539                                    section.addClass('is-loaded');
1540                                },
1541                            },
1542                            thumbs: {
1543                                swiper: galleryNav
1544                            }
1545                        });
1546
1547                        gallerySlider.on('slideChange', function () {
1548                            const index = this.activeIndex;
1549                            if (index) {
1550                                const label = $(this.$el).next().find('.current-slider-count');
1551                                label.fadeOut(0, function () {
1552                                    $(this).html(index <= label.data('total') ? index : 1).fadeIn(50);
1553                                });
1554                            }
1555                        });
1556                    }
1557
1558                    if ('undefined' !== typeof carouselEl) {
1559                        new RBSwiper('#' + carouselEl, {
1560                            spaceBetween: 20,
1561                            slidesPerView: 'auto',
1562                            freeMode: self.themeSettings.sliderFMode,
1563                            loop: false,
1564                            grabCursor: true,
1565                            scrollbar: {
1566                                el: '.swiper-scrollbar-' + index,
1567                                hide: true,
1568                            },
1569                            on: {
1570                                init: function () {
1571                                    $(this.$wrapperEl).removeClass('pre-load');
1572                                    section.addClass('is-loaded');
1573                                },
1574                            },
1575                        });
1576                    }
1577
1578                    if ('undefined' !== typeof coverflowEL) {
1579                        new RBSwiper('#' + coverflowEL, {
1580                            effect: "coverflow",
1581                            grabCursor: true,
1582                            centeredSlides: true,
1583                            slidesPerView: 1.2,
1584                            coverflowEffect: {
1585                                rotate: 50,
1586                                stretch: 0,
1587                                depth: 250,
1588                                modifier: 1,
1589                                slideShadows: true,
1590                            },
1591                            breakpoints: {
1592                                768: {
1593                                    slidesPerView: 3
1594                                }
1595                            },
1596                            on: {
1597                                init: function () {
1598                                    $(this.$wrapperEl).removeClass('pre-load');
1599                                    section.addClass('is-loaded');
1600                                },
1601                            },
1602                            pagination: {
1603                                el: '.swiper-pagination-' + index,
1604                                clickable: true,
1605                            },
1606                        });
1607                    }
1608                }
1609            });
1610        }
1611
1612        Module.scrollBarSlider = function () {
1613
1614            const self = this;
1615            const items = $('.gb-slider-scrollbar');
1616            if (!items.length) return;
1617
1618            items.each(function (index, itemEl) {
1619                if ($(itemEl).hasClass('is-loaded')) return;
1620
1621                const autoplay = $(itemEl).data('autoplay') === 1;
1622                const caption = $(itemEl).closest('.gb-image-slider').find('.gb-image-caption');
1623                const scrollbarEl = $(itemEl).find('.swiper-scrollbar')[0];
1624
1625                $(itemEl).find('.swiper-wrapper').children().addClass('swiper-slide');
1626
1627                const updateCaption = (swiper) => {
1628                    const captionText = $(swiper.slides[swiper.activeIndex]).find('.wp-element-caption').html() || '';
1629                    caption.fadeOut(150, () => caption.html(captionText).fadeIn(200));
1630                };
1631
1632                new RBSwiper(itemEl, {
1633                    slidesPerView: 1,
1634                    loop: false,
1635                    grabCursor: true,
1636                    autoplay: autoplay ? {
1637                        delay: self.themeSettings.sliderSpeed || 5000,
1638                        disableOnInteraction: self.isElementorEditor ? true : window.outerWidth < 1025,
1639                    } : false,
1640                    scrollbar: {
1641                        el: scrollbarEl,
1642                        hide: false,
1643                    },
1644                    on: {
1645                        init() {
1646                            $(itemEl).removeClass('pre-load').addClass('is-loaded');
1647                            updateCaption(this);
1648                        },
1649                        sl
1649ideChange() {
1650                            updateCaption(this);
1651                        },
1652                    },
1653                });
1654            });
1655        };
1656
1657        Module.highlightShares = function () {
1658
1659            const self = this;
1660
1661            if (!self.themeSettings.highlightShares || (window.matchMedia && window.matchMedia('(pointer: coarse)').matches)) {
1662                return;
1663            }
1664
1665            const config = {
1666                selectableElements: ['.is-highlight-shares'],
1667                twitterUsername: self.themeSettings.twitterName,
1668                facebook: !!self.themeSettings.highlightShareFacebook,
1669                twitter: !!self.themeSettings.highlightShareTwitter
1670            };
1671
1672            const extra = self.themeSettings.highlightShareReddit ? [{
1673                icon: '<i class="rbi rbi-reddit"></i>',
1674                url: 'https://reddit.com/submit?url=PAGE_URL&title=TEXT_SELECTION'
1675            }] : [];
1676
1677            Sharect.config(config).appendCustomShareButtons(extra).init();
1678        }
1679
1680        /**
1681         *
1682         * @returns {boolean}
1683         */
1684        Module.floatingVideo = function () {
1685
1686            const self = this;
1687            const floating = $('.floating-video').not('.is-loaded');
1688
1689            if (floating.length === 0 || window.outerWidth < 1025) {
1690                return false;
1691            }
1692
1693            self.wPoint['Floating'] = new Waypoint({
1694                element: floating,
1695                offset: -floating.height(),
1696                handler: function (direction) {
1697                    self._body.find('.floating-video').addClass('is-loaded').removeClass('floating-activated');
1698                    self._body.find('.floating-close').remove();
1699                    if ('down' == direction) {
1700                        this.element.addClass(' floating-activated');
1701                        this.element.find('.float-holder').prepend('<a class="floating-close close-popup-btn" href="#"><span class="close-icon"></span></a>');
1702                    }
1703                }
1704            });
1705        }
1706
1707        Module.floatingVideoRemove = function () {
1708            const self = this;
1709            self._body.on('click', '.floating-close', function (e) {
1710                e.preventDefault();
1711                e.stopPropagation();
1712                self._body.find('.floating-video').removeClass('floating-activated');
1713                self.wPoint['Floating'].destroy();
1714            })
1715        }
1716
1717        Module.siteAccessDetector = function () {
1718            const self = this;
1719            const method = self.themeSettings?.adDetectorMethod;
1720
1721            if (!method || self.siteAccessFlag || self.crwDetect()) {
1722                return;
1723            }
1724
1725            setTimeout(() => {
1726                if (self.siteAccessFlag) return;
1727
1728                switch (parseInt(method)) {
1729                    case 1:
1730                        self.baitElementDetector();
1731                        break;
1732                    case 2:
1733                        self.externalScriptDetector();
1734                        break;
1735                    case 3:
1736                        self.combinedDetector();
1737                        break;
1738                }
1739            }, 1500);
1740        };
1741
1742        Module.baitElementDetector = function () {
1743            const self = this;
1744            const bait = self.createBaitElement();
1745            document.body.appendChild(bait);
1746
1747            setTimeout(() => {
1748                const isBlocked = self.checkBaitElement(bait);
1749                bait.remove();
1750
1751                if (isBlocked) {
1752                    self.siteAccessFlag = true;
1753                    $.magnificPopup.close();
1754                    setTimeout(() => {
1755                        self.siteAccessNotification();
1756                    }, 200);
1757                }
1758            }, 100);
1759        };
1760
1761        Module.externalScriptDetector = function () {
1762            const self = this;
1763            const testUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
1764            const script = document.createElement('script');
1765            script.src = testUrl;
1766            script.async = true;
1767
1768            let completed = false;
1769
1770            const complete = (blocked) => {
1771                if (completed) return;
1772                completed = true;
1773                script.remove();
1774
1775                if (blocked) {
1776                    self.siteAccessFlag = true;
1777                    $.magnificPopup.close();
1778                    setTimeout(() => {
1779                        self.siteAccessNotification();
1780                    }, 200);
1781                }
1782            };
1783
1784            script.onerror = () => complete(true);
1785            script.onload = () => complete(false);
1786            setTimeout(() => complete(true), 5000);
1787
1788            document.head.appendChild(script);
1789        };
1790
1791        Module.combinedDetector = function () {
1792            const self = this;
1793            const bait = self.createBaitElement();
1794            document.body.appendChild(bait);
1795
1796            setTimeout(() => {
1797                const baitBlocked = self.checkBaitElement(bait);
1798                bait.remove();
1799
1800                if (baitBlocked) {
1801                    self.siteAccessFlag = true;
1802                    $.magnificPopup.close();
1803                    setTimeout(() => {
1804                        self.siteAccessNotification();
1805                    }, 200);
1806                    return;
1807                }
1808
1809                self.externalScriptDetector();
1810            }, 100);
1811        };
1812
1813        Module.createBaitElement = function () {
1814            const container = document.createElement('div');
1815            container.id = 'rb-adcheck';
1816            container.setAttribute('aria-hidden', 'true');
1817            container.style.cssText = 'position:absolute;bottom:0;left:0;z-index:-1;pointer-events:none;overflow:hidden;';
1818
1819            const inner = document.createElement('div');
1820            inner.id = 'google_ads_iframe_test';
1821            inner.className = 'adsbygoogle ad-slot adbanner ads-banner banner_ad ad-placeholder pub_300x250 textads adsbox';
1822            inner.setAttribute('data-ad-slot', 'test');
1823            inner.style.cssText = 'width:300px;height:250px;background:transparent;';
1824
1825            container.appendChild(inner);
1826            return container;
1827        };
1828
1829        Module.checkBaitElement = function (container) {
1830            const inner = container.querySelector('.adsbygoogle');
1831
1832            if (!inner || !document.body.contains(inner)) {
1833                return true;
1834            }
1835
1836            const style = window.getComputedStyle(inner);
1837            const rect = inner.getBoundingClientRect();
1838
1839            return (
1840                rect.height < 1 ||
1841                rect.width < 1 ||
1842                style.display === 'none' ||
1843                style.visibility === 'hidden' ||
1844                parseFloat(style.opacity) === 0 ||
1845                inner.offsetParent === null
1846            );
1847        };
1848
1849        Module.siteAccessNotification = function () {
1850            $.magnificPopup.open({
1851                type: 'inline',
1852                preloader: false,
1853                showCloseBtn: false,
1854                closeBtnInside: false,
1855                enableEscapeKey: false,
1856                closeOnBgClick: false,
1857                removalDelay: 9999999,
1858                items: {
1859                    src: $('#tmpl-rb-site-access').html(),
1860                    type: 'inline'
1861                },
1862                mainClass: 'rb-popup-center site-access-popup',
1863                fixedBgPos: true,
1864                fixedContentPos: true,
1865            });
1866
1867            window.addEventListener('contextmenu', event => event.preventDefault());
1868        }
1869
1870        /** build gallery lightbox */
1871        Module.galleryLightbox = function () {
1872
1873            const self = this;
1874            if (!self.galleriesData) {
1875                return;
1876            }
1877
1878            $('.gallery-popup-trigger').on('click', function (e) {
1879                e.preventDefault();
1880                e.stopPropagation();
1881
1882                const target = $(this);
1883                const slideIndex = target.data('index');
1884
1885                $.magnificPopup.open({
1886                    type: 'inline',
1887                    mainClass: 'rb-gallery-popup rb-popup-center',
1888                    closeMarkup: '<button title="%title%" class="mfp-close mfp-button"><i class="rbi rbi-close"></i></button>',
1889                    closeOnBgClick: false,
1890                    removalDelay: 400,
1891                    showCloseBtn: true,
1892                    fixedBgPos: true,
1893                    fixedContentPos: true,
1894                    preloader: false,
1895                    gallery: {
1896                        enabled: true,
1897                        preload: [0, 2],
1898                        arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-button mfp-arrow-%dir%"><i class="rbi rbi-%dir%"></i></button>',
1899                        tCounter: '<span>%curr% / %total%</span>'
1900                    },
1901                    callbacks: {
1902                        open: function () {
1903                            let itemsArray = Object.values(self.galleriesData);
1904                            let targetIndex = itemsArray.findIndex(item => item.key === slideIndex);
1905                            if (targetIndex !== -1) {
1906                                $.magnificPopup.instance.goTo(targetIndex);
1907                            }
1908                        },
1909                        change: function () {
1910
1911                            let imgContainer = $('.gallery-popup-content');
1912                            let loader = imgContainer.find('.rb-loader');
1913                            let img = imgContainer.find('img');
1914                            loader.show();
1915
1916                            if (!img.length) {
1917                                loader.hide();
1918                                return;
1919                            }
1920
1921                            let loaderTimeout = setTimeout(() => {
1922                                loader.fadeIn(200);
1923                            }, 300); // Show loader only if image takes longer  300ms
1924
1925                            img.on('load', function () {
1926                                clearTimeout(loaderTimeout); // Prevent loader from showing if image loads within 300ms
1927                                loader.hide();
1928                            }).on('error', function () {
1929                                clearTimeout(loaderTimeout);
1930                                loader.hide();
1931                            });
1932                        },
1933                        afterClose: function () {
1934                            $.magnificPopup.instance.popupsCache = {};
1935                        },
1936                        buildControls: function () {
1937                            if (this.arrowLeft && this.arrowRight) {
1938                                this.contentContainer.find('.gallery-popup-nav').append(this.arrowLeft.add(this.arrowRight));
1939                            }
1940                        }
1941                    },
1942                    inline: {
1943                        markup:
1944                            '<div class="gallery-popup-header light-scheme">' +
1945                            '<div class="mfp-counter"></div><div class="mfp-title h5"></div>' +
1946                            '<div class="popup-header-right"><div class="mfp-close"></div></div>' +
1947                            '</div><div class="gallery-popup-nav"></div>' +
1948                            '<div class="gallery-popup-content"><i class="rb-loader"></i>' +
1949                            '<div class="gallery-popup-image mfp-image"></div>' +
1950                            '<div class="gallery-popup-entry light-scheme">' +
1951                            '<div class="h4 mfp-excerpt"></div>' +
1952                            '<div class="description-text mfp-description"></div>' +
1953                            '</div>' +
1954                            '</div>'
1955                    },
1956                    items: Object.values(self.galleriesData)
1957                });
1958
1959                return false;
1960            });
1961        };
1962
1963        /** single featured lightbox */
1964        Module.singleFeaturedLightbox = function () {
1965            $('.featured-lightbox-trigger').on('click', function (e) {
1966
1967                e.preventDefault();
1968                e.stopPropagation();
1969
1970                const trigger = $(this);
1971                const source = '<img src="' + trigger.data('source') + '" alt="' + $(this).find('img').attr('alt') + '">';
1972                const caption = trigger.data('caption');
1973                const attribution = trigger.data('attribution');
1974
1975                $.magnificPopup.open({
1976                    mainClass: 'rb-popup-center popup-no-overflow',
1977                    closeOnBgClick: true,
1978                    removalDelay: 400,
1979                    showCloseBtn: true,
1980                    fixedBgPos: true,
1981                    fixedContentPos: true,
1982                    preloader: false,
1983                    closeMarkup: '<button title="%title%" class="mfp-close rb-popup-close"><i class="rbi rbi-close"></i></button>',
1984                    callbacks: {
1985                        afterClose: function () {
1986                            $.magnificPopup.instance.popupsCache = {};
1987                        },
1988                    },
1989                    inline: {
1990                        markup:
1991                            '<div class="featured-popup-image"><div class="mfp-source"></div>' +
1992                            '<div class="mfp-close rb-popup-close"></div></div>' +
1993                            '<div class="gallery-popup-entry light-scheme">' +
1994                            '<div class="h4 mfp-excerpt"></div>' +
1995                            '<div class="description-text mfp-description"></div>' +
1996                            '</div>'
1997                    },
1998                    items: {
1999                        source: source,
2000                        excerpt: caption,
2001                        description: attribution,
2002                    },
2003                });
2004            });
2005        }
2006
2007        /** Ajax pagination */
2008        Module.paginationNextPrev = function () {
2009            const self = this;
2010            self._body.on('click', '.pagination-trigger', function (e) {
2011
2012                e.preventDefault();
2013                e.stopPropagation();
2014                const paginationTrigger = $(this);
2015                if (paginationTrigger.hasClass('is-disable')) {
2016                    return;
2017                }
2018
2019                const block = paginationTrigger.parents('.block-wrap');
2020                const uuid = block.attr('id');
2021
2022                if (!self.ajaxData[uuid]) {
2023                    self.ajaxData[uuid] = self.getBlockSettings(uuid);
2024                }
2025                if (self.ajaxData[uuid] && self.ajaxData[uuid].processing) {
2026                    return;
2027                }
2028                self.ajaxData[uuid].processing = true;
2029                const type = paginationTrigger.data('type');
2030                self.ajaxStartAnimation(block, 'replace');
2031                self.ajaxReplaceLoad(block, uuid, type);
2032            });
2033        }
2034
2035        Module.ajaxReplaceLoad = function (block, uuid, type) {
2036
2037            const self = this;
2038
2039            if (!self.ajaxData[uuid].paged) {
2040                self.ajaxData[uuid].paged = 1;
2041            }
2042            if ('prev' === type) {
2043                self.ajaxData[uuid].page_next = parseInt(self.ajaxData[uuid].paged) - 1;
2044            } else {
2045                self.ajaxData[uuid].page_next = parseInt(self.ajaxData[uuid].paged) + 1;
2046            }
2047
2048            const cacheID = self.cacheData.getCacheID(uuid, self.ajaxData[uuid].page_next);
2049
2050            /** use cache */
2051            if (self.cacheData.exist(cacheID)) {
2052                const cache = self.cacheData.get(cacheID);
2053                if ('undefined' !== typeof cache.paged) {
2054                    self.ajaxData[uuid].paged = cache.paged;
2055                }
2056                setTimeout(function () {
2057                    self.ajaxRenderHTML(block, uuid, cache, 'replace');
2058                }, 200)
2059
2060            } else {
2061                /** POST AJAX */
2062                $.ajax({
2063                    type: 'GET',
2064                    url: self.ajaxURL,
2065                    data: {
2066                        action: 'rblivep',
2067                        data: self.ajaxData[uuid]
2068                    },
2069                    success: function (response) {
2070                        response = JSON.parse(JSON.stringify(response));
2071                        if ('undefined' !== typeof response.paged) {
2072                            self.ajaxData[uuid].paged = response.paged;
2073                        }
2074                        self.cacheData.set(cacheID, response);
2075                        self.ajaxRenderHTML(block, uuid, response, 'replace');
2076                    }
2077                });
2078            }
2079        }
2080
2081        Module.paginationLoadMore = function () {
2082            const self = this;
2083            self._body.on('click', '.loadmore-trigger', function (e) {
2084
2085                e.preventDefault();
2086                e.stopPropagation();
2087
2088                const paginationTrigger = $(this);
2089                if (paginationTrigger.hasClass('is-disable')) {
2090                    return;
2091                }
2092
2093                const block = paginationTrigger.parents('.block-wrap');
2094                const uuid = block.attr('id');
2095
2096                if (!self.ajaxData[uuid]) {
2097                    self.ajaxData[uuid] = self.getBlockSettings(uuid);
2098                }
2099                if (self.ajaxData[uuid] && self.ajaxData[uuid].processing) {
2100                    return;
2101                }
2102                self.ajaxData[uuid].processing = true;
2103                self.ajaxStartAnimation(block, 'append');
2104                self.ajaxAppendLoad(block, uuid);
2105            })
2106        }
2107
2108        Module.paginationInfinite = function () {
2109
2110            const self = this;
2111
2112            const infiniteElements = $('.pagination-infinite');
2113            if (infiniteElements.length > 0) {
2114                infiniteElements.each(function () {
2115                    const paginationTrigger = $(this);
2116                    if (!paginationTrigger.hasClass('is-disable')) {
2117                        const block = paginationTrigger.parents('.block-wrap');
2118                        if ((block.hasClass('is-hoz-scroll') || block.hasClass('is-mhoz-scroll') || block.hasClass('is-thoz-scroll')) && window.outerWidth < 1025) {
2119                            paginationTrigger.addClass('is-disable');
2120                            return;
2121                        }
2122                        const uuid = block.attr('id');
2123                        const wPointID = 'infinite' + uuid;
2124                        if (!self.ajaxData[uuid]) {
2125                            self.ajaxData[uuid] = self.getBlockSettings(uuid);
2126                        }
2127                        const params = {
2128                            element: paginationTrigger,
2129                            offset: '120%',
2130                            handler: function (direction) {
2131                                if (self.ajaxData[uuid] && self.ajaxData[uuid].processing) {
2132                                    return;
2133                                }
2134                                if ('down' == direction) {
2135                                    self.ajaxData[uuid].processing = true;
2136                                    self.ajaxStartAnimation(block, 'append');
2137                                    self.ajaxAppendLoad(block, uuid);
2138                                }
2139                            }
2140                        }
2141                        self.wPoint[wPointID] = new Waypoint(params);
2142                    }
2143                });
2144            }
2145        }
2146
2147        Module.ajaxAppendLoad = function (block, uuid) {
2148            const self = this;
2149            if (!self.ajaxData[uuid].paged) {
2150                self.ajaxData[uuid].paged = 1;
2151            }
2152            if (self.ajaxData[uuid].paged >= self.ajaxData[uuid].page_max) {
2153                return;
2154            }
2155            self.ajaxData[uuid].page_next = parseInt(self.ajaxData[uuid].paged) + 1;
2156            $.ajax({
2157                type: 'GET',
2158                url: self.ajaxURL,
2159                data: {
2160                    action: 'rblivep',
2161                    data: self.ajaxData[uuid]
2162                },
2163                success: function (response) {
2164                    response = JSON.parse(JSON.stringify(response));
2165                    if ('undefined' !== typeof response.paged) {
2166                        self.ajaxData[uuid].paged = response.paged;
2167                    }
2168                    if ('undefined' !== typeof response.notice) {
2169                        response.content = response.content + response.notice;
2170                    }
2171                    self.ajaxRenderHTML(block, uuid, response, 'append');
2172                }
2173            });
2174        }
2175
2176        Module.liveSearch = function () {
2177
2178            const liveSearch = $('.live-search-form');
2179            if (liveSearch.length === 0) {
2180                return;
2181            }
2182
2183            const self = this;
2184
2185            liveSearch.each(function () {
2186                const liveSearchEl = $(this);
2187                const input = liveSearchEl.find('input[type="text"]');
2188                const responseWrap = liveSearchEl.find('.live-search-response');
2189                const animation = liveSearchEl.find('.live-search-animation');
2190                const limit = liveSearchEl.data('limit');
2191                const search = liveSearchEl.data('search');
2192                const follow = liveSearchEl.data('follow');
2193                const tax = liveSearchEl.data('tax');
2194                const dsource = liveSearchEl.data('dsource');
2195                const ptype = liveSearchEl.data('ptype');
2196
2197                input.attr('autocomplete', 'off');
2198
2199                input.on('focus', function () {
2200                    const param = $(this).val();
2201                    if (param && !responseWrap.is(':empty')) {
2202                        responseWrap.css('height', 'auto').fadeIn(200);
2203                    }
2204                });
2205
2206                const delay = (function () {
2207                    let timer = 0;
2208                    return function (callback, ms) {
2209                        clearTimeout(timer);
2210                        timer = setTimeout(callback, ms);
2211                    };
2212                })();
2213
2214                input.keyup(function () {
2215                    const param = $(this).val();
2216                    delay(function () {
2217                        if (param) {
2218                            liveSearchEl.addClass('search-loading');
2219                            setTimeout(function () {
2220                                animation.fadeIn(100);
2221                            }, 120);
2222
2223                            $.ajax({
2224                                type: 'GET',
2225                                url: self.ajaxURL,
2226                                data: {
2227                                    action: 'rbsearch',
2228                                    s: param,
2229                                    limit: limit,
2230                                    search: search,
2231                                    follow: follow,
2232                                    tax: tax,
2233                                    dsource: dsource,
2234                                    ptype: ptype,
2235                                },
2236                                success: function (data) {
2237                                    data = $.parseJSON(JSON.stringify(data));
2238                                    animation.fadeOut(200);
2239                                    setTimeout(function () {
2240                                        liveSearchEl.removeClass('search-loading');
2241                                    }, 200);
2242                                    responseWrap.hide().empty().css('height', responseWrap.height());
2243                                    responseWrap.html(data);
2244                                    if ('category' === search && follow && typeof FOXIZ_PERSONALIZE !== 'undefined') {
2245                                        FOXIZ_PERSONALIZE.syncLayoutCategories();
2246                                    }
2247                                    responseWrap.css('height', 'auto').fadeIn(200);
2248                                }
2249                            });
2250                        } else {
2251                            responseWrap.fadeOut(200, function () {
2252                                responseWrap.empty().css('height', 'auto');
2253                            });
2254                        }
2255                    }, 300);
2256                })
2257            });
2258        }
2259
2260        /** personalized block */
2261        Module.personalizeBlocks = function () {
2262            const self = this;
2263            const elements = $('.is-ajax-block');
2264            if (elements.length > 0) {
2265                const blockRequests = elements.map(function () {
2266                    const block = $(this);
2267                    const uuid = block.attr('id');
2268                    if (!self.ajaxData[uuid]) {
2269                        self.ajaxData[uuid] = self.getBlockSettings(uuid);
2270                    }
2271
2272                    if (self.ajaxData[uuid].content_source &&
2273                        self.ajaxData[uuid].content_source === 'recommended' &&
2274                        typeof foxizQueriedIDs !== 'undefined' && foxizQueriedIDs.data
2275                    ) {
2276                        self.ajaxData[uuid].post_not_in = foxizQueriedIDs.data;
2277                    }
2278
2279                    self.ajaxData[uuid].uID = self.getStorage('RBUUID', '0');
2280
2281                    return $.ajax({
2282                        type: 'GET',
2283                        url: self.ajaxURL,
2284                        data: {
2285                            action: 'rbpersonalizeb',
2286                            data: self.ajaxData[uuid]
2287                        }
2288                    });
2289                });
2290
2291                Promise.all(blockRequests).then(responses => {
2292                    responses.forEach((response, index) => {
2293                        const block = $(elements[index]);
2294                        block.html(response).fadeIn(200);
2295                        block.dequeue();
2296                    });
2297                    self.reloadBlockFunc();
2298                });
2299            }
2300        };
2301
2302        /** personalized categories */
2303        Module.personalizeCategories = function () {
2304
2305            const self = this;
2306            const elements = $('.is-ajax-categories');
2307            if (elements.length > 0) {
2308                const categoryRequests = elements.map(function () {
2309                    const block = $(this);
2310                    const uuid = block.attr('id');
2311                    if (!self.ajaxData[uuid]) {
2312                        self.ajaxData[uuid] = self.getBlockSettings(uuid);
2313                    }
2314                    return $.ajax({
2315                        type: 'GET',
2316                        url: self.ajaxURL,
2317                        data: {
2318                            action: 'rbpersonalizecat',
2319                            data: self.ajaxData[uuid]
2320                        }
2321                    });
2322                });
2323
2324                Promise.all(categoryRequests).then(responses => {
2325                    responses.forEach((response, index) => {
2326                        const block = $(elements[index]);
2327                        block.html(response).fadeIn(200);
2328                        block.dequeue();
2329                    });
2330
2331                    if (typeof FOXIZ_PERSONALIZE !== 'undefined') {
2332                        FOXIZ_PERSONALIZE.syncLayoutCategories();
2333                    }
2334                    self.reloadBlockFunc();
2335                });
2336            }
2337        };
2338
2339        Module.readingCollect = function () {
2340            const self = this;
2341            if (self.themeSettings.yesReadingHis === undefined) {
2342                return;
2343            }
2344            $.ajax({
2345                type: 'GET',
2346                url: self.ajaxURL,
2347                data: {
2348                    action: 'rbcollect',
2349                    id: self.themeSettings.yesReadingHis
2350                }
2351            });
2352        };
2353
2354        /** header notification */
2355        Module.newsNotification = function () {
2356
2357            const notificationWrapper = $('.rb-notification');
2358            if (notificationWrapper.length < 1) {
2359                return false;
2360            }
2361
2362            const self = this;
2363            const storageKey = this.personalizeUID + '-notification';
2364            const dot = $('.notification-info');
2365
2366            // Get reload interval (now in minutes, default 15)
2367            let reload = notificationWrapper.data('interval');
2368            if (!reload || isNaN(reload) || reload <= 0) {
2369                reload = 15;
2370            }
2371
2372            // Helper: count NEW post IDs (in current but not in viewed)
2373            function countNewPosts(currentIds, viewedIds) {
2374                if (!currentIds) return 0;
2375                if (!viewedIds) return currentIds.split(',').length;
2376
2377                const current = currentIds.split(',');
2378                const viewed = viewedIds.split(',');
2379                let count = 0;
2380                for (let i = 0; i < current.length; i++) {
2381                    if (viewed.indexOf(current[i]) === -1) {
2382                        count++;
2383                    }
2384                }
2385                return count;
2386            }
2387
2388            // Get cached data (contains: content, count, ids, viewedIds, ttl)
2389            const cached = self.getStorage(storageKey);
2390
2391            // Show cached content immediately for instant UX
2392            if (cached && cached.content) {
2393                notificationWrapper.append(cached.content);
2394                // Show count of NEW posts only (not total)
2395                const newCount = countNewPosts(cached.ids, cached.viewedIds);
2396                if (newCount > 0) {
2397                    dot.append(newCount);
2398                    dot.css('opacity', 1);
2399                }
2400            }
2401
2402            // Hide dot when user opens notification dropdown
2403            $('.notification-trigger').on('click', function () {
2404                dot.css('opacity', 0).empty();
2405                // Mark current IDs as viewed
2406                const current = self.getStorage(storageKey);
2407                if (current && current.ids) {
2408                    current.viewedIds = current.ids;
2409                    self.setStorage(storageKey, current);
2410                }
2411            });
2412
2413            // Check if refresh needed (expired or no cache)
2414            const isExpired = !cached || !cached.ttl || Date.now() > cached.ttl;
2415
2416            if (isExpired) {
2417                $.ajax({
2418                    type: 'GET',
2419                    url: self.ajaxURL,
2420                    data: {action: 'rbnotification'},
2421                    success: function (response) {
2422                        response = $.parseJSON(JSON.stringify(response));
2423
2424                        const newIds = response.ids || '';
2425                        const oldIds = cached ? (cached.ids || '') : '';
2426                        const viewedIds = cached ? (cached.viewedIds || '') : '';
2427
2428                        // Store new data with TTL in minutes (preserve viewedIds)
2429                        self.setStorage(storageKey, {
2430                            content: response.content,
2431                            count: response.count,
2432                            ids: newIds,
2433                            viewedIds: viewedIds,
2434                            ttl: Date.now() + reload * 60000
2435                        });
2436
2437                        // Update DOM if: no local cache (first load) OR post IDs changed
2438                        if (!cached || newIds !== oldIds) {
2439                            notificationWrapper.empty().append(response.content);
2440                            dot.empty();
2441                            // Show count of NEW posts only (or total if first load)
2442                            const newCount = countNewPosts(newIds, viewedIds);
2443                            if (newCount > 0) {
2444                                dot.append(newCount);
2445                                dot.css('opacity', 1);
2446                            }
2447                        }
2448                    }
2449                });
2450            }
2451        };
2452
2453        /** register cache object */
2454        Module.cacheData = {
2455
2456            data: {},
2457            get: function (id) {
2458                return this.data[id];
2459            },
2460
2461            set: function (id, data) {
2462                this.remove(id);
2463                this.data[id] = data;
2464            },
2465
2466            remove: function (id) {
2467                delete this.data[id];
2468            },
2469
2470            getCacheID: function (blockID, currentPage) {
2471                return JSON.stringify('RB_' + blockID + '_' + currentPage);
2472            },
2473
2474            exist: function (id) {
2475                return this.data.hasOwnProperty(id) && this.data[id] !== null;
2476            }
2477        }
2478
2479        /**
2480         * ajax start animation
2481         * @param block
2482         * @param action
2483         */
2484        Module.ajaxStartAnimation = function (block, action) {
2485
2486            const inner = block.find('.block-inner');
2487            block.find('.pagination-trigger').addClass('is-disable');
2488            inner.stop();
2489
2490            if ('replace' === action) {
2491                inner.css('min-height', inner.outerHeight());
2492                inner.fadeTo('200', 0.05);
2493                inner.after('<i class="rb-loader loader-absolute"></i>');
2494            } else {
2495                block.find('.loadmore-trigger').addClass('loading');
2496                block.find('.rb-loader').css({'display': 'block'}).delay(200).animate({opacity: 1}, 200);
2497            }
2498        }
2499
2500        /**
2501         * render ajax
2502         * @param block
2503         * @param uuid
2504         * @param response
2505         * @param action
2506         */
2507        Module.ajaxRenderHTML = function (block, uuid, response, action) {
2508
2509            const self = this;
2510
2511            block.delay(50).queue(function () {
2512                const uuid = block.attr('id');
2513                const inner = block.find('.block-inner');
2514                block.find('.pagination-trigger').removeClass('is-disable');
2515                inner.stop();
2516
2517                if ('replace' === action) {
2518                    inner.html(response.content);
2519                    block.find('.rb-loader').animate({opacity: 0}, 200, function () {
2520                        $(this).remove();
2521                    })
2522                    inner.css('min-height', '');
2523                    inner.fadeTo(200, 1);
2524
2525                } else {
2526                    const content = $(response.content);
2527                    inner.append(content);
2528                    content.addClass('is-invisible');
2529                    content.addClass('opacity-animate');
2530
2531                    block.find('.rb-loader').animate({opacity: 0}, 200, function () {
2532                        $(this).css({'display': 'none'});
2533                    });
2534                    setTimeout(function () {
2535                        content.removeClass('is-invisible');
2536                    }, 200);
2537                    block.find('.loadmore-trigger').removeClass('loading');
2538                }
2539
2540                /** reload */
2541                self.ajaxTriggerState(block, uuid);
2542                self.ajaxData[uuid].processing = false;
2543                block.dequeue();
2544                self.reloadBlockFunc();
2545            });
2546        }
2547
2548        /**
2549         * set
2550         * @param block
2551         * @param uuid
2552         */
2553        Module.ajaxTriggerState = function (block, uuid) {
2554            const self = this;
2555            block.find('.pagination-trigger').removeClass('is-disable');
2556            if (self.ajaxData[uuid].paged < 2) {
2557                block.find('[data-type="prev"]').addClass('is-disable');
2558            } else if (self.ajaxData[uuid].paged >= self.ajaxData[uuid].page_max) {
2559                block.find('[data-type="next"]').addClass('is-disable');
2560                block.find('.loadmore-trigger').addClass('is-disable').hide();
2561                block.find('.pagination-infinite').addClass('is-disable').hide();
2562            }
2563        }
2564
2565        Module.getBlockSettings = function (uuid) {
2566            const settings = typeof window[uuid] !== 'undefined' ? window[uuid] : undefined;
2567            return this.cleanNull(settings);
2568        }
2569
2570        Module.cleanNull = function (data) {
2571            if (typeof data === 'string') {
2572                return data;
2573            }
2574
2575            if (data && typeof data === 'object') {
2576                Object.keys(data).forEach(key => {
2577                    if (data[key] === '' || data[key] === null) {
2578                        delete data[key];
2579                    }
2580                });
2581            }
2582
2583            return data;
2584        };
2585
2586        /* SINGLE INFINITE */
2587        Module.singleInfiniteLoadNext = function () {
2588
2589            const infiniteWrapper = $('#single-post-infinite');
2590            const self = this;
2591
2592            if (!infiniteWrapper.length || self.disabledLoadNext()) {
2593                return;
2594            }
2595
2596            self.singleLoadNextCounter = 1;
2597            self.singleLoadNextLimit = self.themeSettings?.singleLoadNextLimit ? parseInt(self.themeSettings.singleLoadNextLimit, 10) : 20;
2598
2599            const infiniteLoadPoint = $('#single-infinite-point');
2600            const animationIcon = infiniteLoadPoint.find('.rb-loader');
2601            const rootURL = new URL(window.location.href);
2602            const rootGetParams = rootURL.searchParams;
2603
2604            const loadNextParams = {
2605                element: infiniteLoadPoint,
2606                offset: '125%',
2607                handler: function (direction) {
2608                    if (self.ajaxData.singleProcessing || direction === 'up' || self.singleLoadNextCounter > self.singleLoadNextLimit) {
2609                        return;
2610                    }
2611                    const nextPostURL = new URL(infiniteWrapper.data('nextposturl'));
2612                    nextPostURL.searchParams.set('rbsnp', '1');
2613                    if (rootGetParams) {
2614                        rootGetParams.forEach((value, key) => {
2615                            if (key !== 'rbsnp' && 'p' !== key) {
2616                                nextPostURL.searchParams.set(key, value);
2617                            }
2618                        });
2619                    }
2620                    self.ajaxData.singleProcessing = true;
2621                    animationIcon.css('display', 'block').animate({opacity: 1}, 200);
2622
2623                    $.ajax({
2624                        type: 'GET',
2625                        url: nextPostURL.toString(),
2626                        dataType: 'html',
2627                        success: function (response) {
2628                            response = $('<div id="temp-dom"></div>').append($.parseHTML(response)).find('.single-post-outer');
2629                            const nextPostURL = response.data('nextposturl');
2630
2631                            if (nextPostURL) {
2632                                infiniteWrapper.data('nextposturl', nextPostURL);
2633                            } else {
2634                                infiniteWrapper.removeAttr('id');
2635                                infiniteLoadPoint.remove();
2636                            }
2637
2638                            animationIcon.animate({opacity: 0}, 200).delay(200).css('display', 'none');
2639                            infiniteWrapper.append(response);
2640                            self.ajaxData.singleProcessing = false;
2641                            self.singleLoadNextCounter++;
2642
2643                            setTimeout(function () {
2644                                self.reInitAll();
2645                                if (typeof FOXIZ_CORE_SCRIPT !== 'undefined') {
2646                                    FOXIZ_CORE_SCRIPT.loadGoogleAds(response);
2647                                    FOXIZ_CORE_SCRIPT.loadInstagram(response);
2648                                    FOXIZ_CORE_SCRIPT.loadTwttr();
2649                                }
2650                            }, 1);
2651                        }
2652                    });
2653                }
2654            };
2655
2656            self.wPoint.ajaxSingleNextPosts = new Waypoint(loadNextParams);
2657        };
2658
2659        Module.singleScrollRefresh = function () {
2660
2661            const infiniteWrapper = $('#single-post-infinite');
2662            if (!infiniteWrapper.length) {
2663                return;
2664            }
2665            const self = this;
2666            self.articleData = [];
2667            const articleOuter = infiniteWrapper.find('.single-post-outer');
2668
2669            if (articleOuter.length > 0) {
2670                self.inviewPostID = articleOuter.eq(0).data('postid');
2671
2672                articleOuter.each(function () {
2673                    const article = $(this);
2674                    const itemData = {
2675                        postID: article.data('postid'),
2676                        postURL: article.data('postlink'),
2677                        postTitle: article.find('h1.s-title').text(),
2678                        shareList: article.find('.sticky-share-list-buffer').html(),
2679                        top: article.offset().top,
2680                        bottom: article.offset().top + article.outerHeight(true)
2681                    };
2682
2683                    if (self.readIndicator.length > 0) {
2684                        const content = article.find('.rbct').eq(0);
2685                        itemData.indicatorTop = content.offset().top;
2686                        itemData.indicatorHeight = content.outerHeight(true) - self._window.height();
2687                    }
2688                    self.articleData.push(itemData);
2689                });
2690
2691                const onScroll = () => {
2692                    self.animationFrame(self.scrollToUpdateArticle.bind(self));
2693                };
2694                if (window.addEventListener) {
2695                    window.addEventListener('scroll', onScroll, false);
2696                }
2697            }
2698        }
2699
2700        /** scrollToUpdateArticle */
2701        Module.scrollToUpdateArticle = function () {
2702            const self = this;
2703            const scroll = self._window.scrollTop();
2704
2705            self.articleData.every(article => {
2706                if (scroll > (article.top + 5) && scroll < (article.bottom - 5)) {
2707                    if (article.indicatorTop) {
2708                        self.readIndicatorPercent = Math.min(((scroll - article.indicatorTop) / article.indicatorHeight) * 100, 100);
2709                        if (self.readIndicatorPercent <= 100) {
2710                            self.readIndicator.css('width', `${self.readIndicatorPercent}%`);
2711                        }
2712                    }
2713
2714                    if (article.postID !== self.inviewPostID) {
2715                        self.inviewPostID = article.postID;
2716                        if (article.postURL) {
2717                            history.replaceState(null, null, article.postURL);
2718                        }
2719                        document.title = article.postTitle;
2720                        $('.single-post-outer').removeClass('activated');
2721                        $('[data-postid="' + article.postID + '"]').addClass('activated');
2722                        $('#s-title-sticky .sticky-title').hide().html(article.postTitle).fadeIn(300);
2723                        $('#s-title-sticky .sticky-share-list').html(article.shareList);
2724                        self._body.find('.floating-video').removeClass('floating-activated');
2725
2726                        if (typeof FOXIZ_CORE_SCRIPT !== 'undefined') {
2727                            FOXIZ_CORE_SCRIPT.updateGA(article);
2728                        }
2729                    }
2730                    return false;
2731                }
2732
2733                return true;
2734
2735            });
2736        }
2737
2738        /**
2739         * @returns {boolean}
2740         */
2741        Module.crwDetect = function () {
2742            const botPatterns = [
2743                /alexa|altavista|ask jeeves|attentio|baiduspider|bingbot|chtml generic|crawler|fastmobilecrawl|feedfetcher-google|firefly|froogle|gigabot|googlebot|googlebot-mobile|heritrix|httrack|ia_archiver|irlbot|iescholar|infoseek|jumpbot|linkcheck|lycos|mediapartners|mediobot|motionbot|msnbot|mshots|openbot|pss-webkit-request|pythumbnail|scooter|slurp|snapbot|spider|taptubot|technoratisnoop|teoma|twiceler|yahooseeker|yaho
2743oysmcm|yammybot|ahrefsbot|pingdom.com_bot|kraken|yandexbot|twitterbot|tweetmemebot|openhosebot|queryseekerspider|linkdexbot|grokkit-crawler|livelapbot|germcrawler|domaintunocrawler|grapeshotcrawler|cloudflare-alwaysonline/i
2744            ];
2745
2746            const userAgent = navigator.userAgent;
2747            return botPatterns.some(pattern => pattern.test(userAgent));
2748        };
2749
2750        /**
2751         *
2752         * @returns {boolean}
2753         */
2754        Module.disabledLoadNext = function () {
2755
2756            if (this.themeSettings.crwLoadNext) {
2757                return false;
2758            }
2759
2760            return this.crwDetect();
2761        }
2762
2763        /** productQuantity */
2764        Module.productQuantity = function () {
2765            this._document.on('click', '.quantity .quantity-btn', function (e) {
2766
2767                e.preventDefault();
2768                e.stopPropagation();
2769
2770                const button = $(this);
2771                const input = button.parent().find('input');
2772
2773                let step = 1;
2774                let min = 1;
2775                let max = 9999;
2776                let value_old = parseInt(input.val());
2777                let value_new = parseInt(input.val());
2778
2779                if (input.attr('step')) {
2780                    step = parseInt(input.attr('step'));
2781                }
2782
2783                if (input.attr('min')) {
2784                    min = parseInt(input.attr('min'));
2785                }
2786
2787                if (input.attr('max')) {
2788                    max = parseInt(input.attr('max'));
2789                }
2790
2791                if (button.hasClass('up')) {
2792                    if (value_old < max) {
2793                        value_new = value_old + step;
2794                    } else {
2795                        value_new = 1;
2796                    }
2797                } else if (button.hasClass('down')) {
2798                    if (value_old > min) {
2799                        value_new = value_old - step;
2800                    } else {
2801                        value_new = 0;
2802                    }
2803                }
2804
2805                if (!input.attr('disabled')) {
2806                    input.val(value_new).change();
2807                }
2808            });
2809        }
2810
2811        Module.cartNotification = function () {
2812            const self = this;
2813            const element = $('#add-cart-popup');
2814
2815            self._body.on('added_to_cart', function () {
2816                element.fadeIn(200);
2817                self.cartNotificationTimeOut = setTimeout(function () {
2818                    element.fadeOut(200);
2819                }, 5000);
2820                self.hoveringNotification(element);
2821            });
2822        }
2823
2824        Module.hoveringNotification = function (element) {
2825            const self = this;
2826
2827            element.on('mouseenter', function () {
2828                clearTimeout(self.cartNotificationTimeOut);
2829            });
2830
2831            element.on('mouseleave', function () {
2832                setTimeout(function () {
2833                    element.fadeOut(200);
2834                }, 1500);
2835            });
2836        }
2837
2838        /** like/dislike */
2839        Module.likeToggle = function () {
2840
2841            const self = this;
2842            let reaction = '';
2843            self._body.on('click', '.like-trigger, .dislike-trigger', function (e) {
2844
2845                e.preventDefault();
2846                e.stopPropagation();
2847
2848                const target = $(this);
2849                const wrap = target.parent('[data-like]');
2850                const pid = wrap.data('like');
2851
2852                if (!pid || self.isProgress) return;
2853
2854                self.isProgress = true;
2855                const storageKey = self.getLikeKey(pid);
2856                const isLike = target.hasClass('like-trigger');
2857                const isDislike = target.hasClass('dislike-trigger');
2858                const sibEl = target.siblings();
2859                const likeCountEl = wrap.find('.like-count');
2860                const dislikeCountEl = wrap.find('.dislike-count');
2861                let likeCountText = likeCountEl.text();
2862                let dislikeCountText = dislikeCountEl.text();
2863
2864                if (isLike) {
2865                    if (!target.hasClass('triggered')) {
2866                        reaction = 'like';
2867                        if (!/[kKmM]/.test(likeCountText)) {
2868                            likeCountText = parseInt(likeCountText);
2869                            if (isNaN(likeCountText)) {
2870                                likeCountText = 0;
2871                            }
2872                            likeCountEl.text(likeCountText + 1);
2873                        }
2874                        target.addClass('triggered');
2875
2876                        if (sibEl.hasClass('triggered')) {
2877                            sibEl.removeClass('triggered');
2878                            if (!/[kKmM]/.test(dislikeCountText)) {
2879                                dislikeCountText = parseInt(dislikeCountText) - 1;
2880                                if (isNaN(dislikeCountText) || dislikeCountText < 1) {
2881                                    dislikeCountText = '';
2882                                }
2883                                dislikeCountEl.text(dislikeCountText);
2884                            }
2885                        }
2886                        self.setStorage(storageKey, 'like');
2887                    } else {
2888                        reaction = 'rmlike';
2889                        if (!/[kKmM]/.test(likeCountText)) {
2890                            likeCountText = parseInt(likeCountText) - 1;
2891                            if (isNaN(likeCountText) || likeCountText < 1) {
2892                                likeCountText = '';
2893                            }
2894                            likeCountEl.text(likeCountText);
2895                        }
2896                        target.removeClass('triggered');
2897                        self.deleteStorage(storageKey);
2898                    }
2899                } else if (isDislike) {
2900                    if (!target.hasClass('triggered')) {
2901                        reaction = 'dislike';
2902                        if (!/[kKmM]/.test(dislikeCountText)) {
2903                            dislikeCountText = parseInt(dislikeCountText);
2904                            if (isNaN(dislikeCountText)) {
2905                                dislikeCountText = 0;
2906                            }
2907                            dislikeCountEl.text(dislikeCountText + 1);
2908                        }
2909                        target.addClass('triggered');
2910                        if (sibEl.hasClass('triggered')) {
2911                            sibEl.removeClass('triggered');
2912                            if (!/[kKmM]/.test(likeCountText)) {
2913                                likeCountText = parseInt(likeCountText) - 1;
2914                                if (isNaN(likeCountText) || likeCountText < 1) {
2915                                    likeCountText = '';
2916                                }
2917                                likeCountEl.text(likeCountText);
2918                            }
2919                        }
2920                        self.setStorage(storageKey, 'dislike');
2921                    } else {
2922                        reaction = 'rmdislike';
2923                        if (!/[kKmM]/.test(dislikeCountText)) {
2924                            likeCountText = parseInt(likeCountText) - 1;
2925                            if (isNaN(likeCountText) || likeCountText < 1) {
2926                                likeCountText = '';
2927                            }
2928                            dislikeCountEl.text(likeCountText);
2929                        }
2930                        target.removeClass('triggered');
2931                        self.deleteStorage(storageKey);
2932                    }
2933                }
2934
2935                $.ajax({
2936                    type: 'GET',
2937                    url: self.ajaxURL,
2938                    data: {
2939                        uuid: self.personalizeUID,
2940                        action: 'rbvoting',
2941                        value: reaction,
2942                        pid: pid,
2943                    },
2944                    complete: () => {
2945                        self.isProgress = false;
2946                    }
2947                })
2948            })
2949        }
2950
2951        /** sync layout */
2952        Module.syncLayoutLike = function () {
2953
2954            this.isProgress = true;
2955            const likeElements = document.querySelectorAll('[data-like]:not(.loaded)');
2956            const jsCount = this._body.hasClass('is-jscount');
2957            let count, countEl;
2958
2959            for (const el of likeElements) {
2960                el.classList.add('loaded');
2961                const key = this.getLikeKey(el.getAttribute('data-like'));
2962                const triggered = this.getStorage(key);
2963
2964                if (!triggered) continue;
2965
2966                const likeEl = el.querySelector('.el-like');
2967                const dislikeEl = el.querySelector('.el-dislike');
2968
2969                if (!likeEl || !dislikeEl) continue;
2970
2971                if (triggered === 'like') {
2972                    likeEl.classList.add('triggered');
2973                    countEl = jsCount ? likeEl.querySelector('.like-count') : null;
2974                    if (countEl) {
2975                        count = parseInt(countEl.textContent.trim()) || 0;
2976                        countEl.textContent = count + 1;
2977                    }
2978                } else if (triggered === 'dislike') {
2979                    dislikeEl.classList.add('triggered');
2980                    countEl = jsCount ? dislikeEl.querySelector('.dislike-count') : null;
2981                    if (countEl) {
2982                        count = parseInt(countEl.textContent.trim()) || 0;
2983                        countEl.textContent = count + 1;
2984                    }
2985                }
2986            }
2987
2988            this.isProgress = false;
2989        };
2990
2991        /** like key */
2992        Module.getLikeKey = function (id) {
2993            return this.personalizeUID + '-like-' + id;
2994        }
2995
2996        /** live blog */
2997        Module.liveBlog = function () {
2998            const self = this;
2999
3000            const liveEntry = $('.rb-live-entry');
3001
3002            if (liveEntry.length === 0) {
3003                return false;
3004            }
3005
3006            let intervalId;
3007            let delayTimeoutId;
3008            const interval = Math.min(1800, Math.max(15, this.themeSettings.liveInterval || 1800));
3009            const liveSwitcher = $('#live-interval-switcher');
3010            const storedSetting = this.getStorage('liveIntervalCheckbox');
3011
3012            // Start the regular interval (no initial delay)
3013            const startInterval = () => {
3014                clearInterval(intervalId);
3015                intervalId = setInterval(() => this.updateLiveBlog(liveEntry), interval * 1000);
3016            };
3017
3018            // Stop all timers
3019            const stopAll = () => {
3020                clearInterval(intervalId);
3021                clearTimeout(delayTimeoutId);
3022            };
3023
3024            // Handle manual toggle with 5s delay to avoid rapid triggering
3025            const handleToggle = () => {
3026                stopAll();
3027
3028                if (liveSwitcher.prop('checked')) {
3029                    // Delay 3s before first load, then continue with regular interval
3030                    delayTimeoutId = setTimeout(() => {
3031                        this.updateLiveBlog(liveEntry);
3032                        startInterval();
3033                    }, 3000);
3034                    self.setStorage('liveIntervalCheckbox', 'yes');
3035                } else {
3036                    self.setStorage('liveIntervalCheckbox', 'no');
3037                }
3038            };
3039
3040            // Initialize from stored setting
3041            if (storedSetting !== null) {
3042                liveSwitcher.prop('checked', storedSetting === 'yes');
3043            } else {
3044                self.setStorage('liveIntervalCheckbox', 'yes');
3045            }
3046
3047            // On page load: start interval immediately if checked (no delay)
3048            if (liveSwitcher.prop('checked')) {
3049                startInterval();
3050            }
3051
3052            // On manual toggle: use 5s delay
3053            liveSwitcher.on('change', handleToggle);
3054        };
3055
3056        Module.updateLiveBlog = function (liveEntry) {
3057
3058            const self = this;
3059            const liveURL = new URL(window.location.href);
3060            liveURL.searchParams.set('rblive', '1');
3061            $.ajax({
3062                type: 'GET',
3063                url: liveURL.toString(),
3064                dataType: 'html',
3065                success: function (response) {
3066                    response = $('<div id="temp-dom"></div>').append($.parseHTML(response)).find('#rb-live-content');
3067                    liveEntry.html(response.html());
3068                    const liveCountElement = liveEntry.prev().find('.live-count');
3069                    if (liveCountElement.length) {
3070                        liveCountElement.text(response.data('total'));
3071                    }
3072                    setTimeout(function () {
3073                        self.reInitAll();
3074                        if (typeof FOXIZ_CORE_SCRIPT !== 'undefined') {
3075                            FOXIZ_CORE_SCRIPT.loadGoogleAds(response);
3076                            FOXIZ_CORE_SCRIPT.loadInstagram(response);
3077                            FOXIZ_CORE_SCRIPT.loadTwttr();
3078                        }
3079                    }, 1);
3080                }
3081            });
3082        }
3083
3084        Module.accordion = function () {
3085            $('.gb-accordion').each(function () {
3086                const accordion = $(this);
3087                if (accordion.hasClass('yesLoaded')) return;
3088
3089                accordion.addClass('yesLoaded');
3090                const accordionItems = accordion.find('.gb-accordion-item');
3091
3092                if (accordion.hasClass('yes-open')) {
3093                    accordionItems.first().addClass('active').find('.accordion-item-content').css('display', 'block');
3094                }
3095
3096                accordion.on('click', '.accordion-item-header', function (e) {
3097                    e.preventDefault();
3098
3099                    const header = $(this);
3100                    const item = header.closest('.gb-accordion-item');
3101                    const content = item.find('.accordion-item-content');
3102
3103                    if (item.hasClass('active')) {
3104                        item.removeClass('active');
3105                        content.stop().slideUp(200);
3106                    } else {
3107                        const activeItem = accordionItems.filter('.active');
3108                        activeItem.removeClass('active').find('.accordion-item-content').stop().slideUp(200);
3109                        item.addClass('active');
3110                        content.stop().slideDown(200);
3111                    }
3112                });
3113            });
3114        };
3115
3116        Module.resIframeClassic = function () {
3117
3118            if (!document.body.classList.contains('res-iframe-classic')) return
3119            const iframes = document.querySelectorAll('.rbct iframe');
3120            iframes.forEach(iframe => {
3121                const parent = iframe.parentElement;
3122                const grandParent = parent.parentElement;
3123                const greatGrandParent = grandParent.parentElement;
3124
3125                if ([parent, grandParent, greatGrandParent].some(element => {
3126                    const classNames = Array.from(element.classList);
3127                    return classNames.some(className => className.indexOf('wp-block') !== -1);
3128                })) return;
3129
3130                if (!iframe.parentElement.classList.contains('rb-video-ires')) {
3131                    if (iframe.src.includes('youtube.com') || iframe.src.includes('youtu.be') || iframe.src.includes('vimeo.com') || iframe.src.includes('dailymotion.com')) {
3132                        iframe.parentElement.classList.add('rb-video-ires');
3133                    }
3134                }
3135            });
3136        }
3137
3138        Module.taxBasedAccordion = function () {
3139
3140            const self = this;
3141            $('.block-tax-accordion').each(function () {
3142                const accordion = $(this);
3143                if (accordion.hasClass('is-loaded')) {
3144                    return;
3145                }
3146                accordion.addClass('is-loaded');
3147                const accordionItems = accordion.find('.tax-accordion-item');
3148                const lastOpenedTab = self.getStorage(accordion.attr('id') + '_lastOpenedTab', null);
3149
3150                if (lastOpenedTab) {
3151                    const tabToOpen = accordion.find('[data-tab="' + lastOpenedTab + '"] .tax-accordion-sub');
3152                    if (tabToOpen.length !== 0) {
3153                        tabToOpen.show();
3154                    }
3155                }
3156
3157                accordionItems.each(function () {
3158                    const item = $(this);
3159                    const trigger = item.find('.tax-accordion-trigger');
3160                    const subMenu = item.find('.tax-accordion-sub');
3161
3162                    trigger.click(function () {
3163                        if (!subMenu.is(':visible')) {
3164                            accordion.find('.tax-accordion-sub').not(subMenu).slideUp();
3165                        }
3166                        subMenu.slideToggle(function () {
3167                            if (subMenu.is(':visible')) {
3168                                self.setStorage(accordion.attr('id') + '_lastOpenedTab', item.attr('data-tab'));
3169                            } else {
3170                                self.deleteStorage(accordion.attr('id') + '_lastOpenedTab');
3171                            }
3172                        });
3173                    });
3174                });
3175            });
3176        };
3177
3178
3179        Module.sequentialGalleryDisplay = function () {
3180            const galleries = Array.from(document.querySelectorAll('.gallery-animated'));
3181            galleries.forEach(gallery => {
3182                const images = Array.from(gallery.querySelectorAll('.e-gallery-item'));
3183                new Waypoint({
3184                    element: gallery,
3185                    handler: function (direction) {
3186                        if (direction === 'down') {
3187                            images.forEach((image, index) => {
3188                                requestAnimationFrame(() => {
3189                                    setTimeout(() => {
3190                                        image.classList.add('gallery-visible');
3191                                    }, index * 120);
3192                                });
3193                            });
3194                            this.destroy();
3195                        }
3196                    },
3197                    offset: '90%'
3198                });
3199            });
3200        };
3201
3202
3203        Module.reloadCaptchaPopups = function (delay = 50) {
3204            setTimeout(() => {
3205                const $content = $($.magnificPopup?.instance?.content || []);
3206                if (!$content.length) return;
3207
3208                const removeDuplicateCaptchas = form => {
3209                    const seen = new Set();
3210                    $(form)
3211                        .find('.g-recaptcha, .h-captcha, .cf-turnstile, .turnstile-widget, .frc-captcha, [data-arkose-public-key], .arkose-enforcement, .geetest_holder, .geetest_panel')
3212                        .each(function () {
3213                            const cls = this.className;
3214                            const type = ['g-recaptcha', 'h-captcha', 'cf-turnstile', 'turnstile-widget', 'frc-captcha', 'arkose', 'geetest']
3215                                .find(t => cls.includes(t) || $(this).data('arkose-public-key') || $(this).hasClass('arkose-enforcement'));
3216                            if (!type) return;
3217                            const key = `${type}`;
3218                            if (seen.has(key)) {
3219                                $(this).remove();
3220                            } else {
3221                                seen.add(key);
3222                            }
3223                        });
3224                };
3225
3226                try {
3227                    // Remove duplicates per form
3228                    $content.find('form').each(function () {
3229                        removeDuplicateCaptchas(this);
3230                    });
3231
3232                    // Google reCAPTCHA
3233                    if (typeof grecaptcha !== 'undefined' && grecaptcha?.reset) {
3234                        $content.find('.g-recaptcha').each(function () {
3235                            const wid = this.dataset.widgetId;
3236                            if (wid) {
3237                                try { grecaptcha.reset(Number(wid)); } catch {}
3238                            }
3239                        });
3240                    }
3241
3242                    // Cloudflare Turnstile
3243                    if (typeof turnstile !== 'undefined' && turnstile?.reset) {
3244                        $content.find('.cf-turnstile, .turnstile-widget').each(function () {
3245                            const iframe = this.querySelector('iframe');
3246                            const wid = iframe?.dataset?.wid;
3247                            if (wid) {
3248                                try { turnstile.reset(wid); } catch {}
3249                            }
3250                        });
3251                    }
3252
3253                    // hCaptcha
3254                    if (typeof hcaptcha !== 'undefined' && hcaptcha?.reset) {
3255                        $content.find('.h-captcha').each(function () {
3256                            const wid = this.dataset.widgetId;
3257                            if (wid) {
3258                                try { hcaptcha.reset(Number(wid)); } catch {}
3259                            }
3260                        });
3261                    }
3262
3263                    // FriendlyCaptcha
3264                    if (typeof friendlycaptcha !== 'undefined' && friendlycaptcha?.widget) {
3265                        $content.find('.frc-captcha').each(function () {
3266                            const stored = $(this).data('frc-widget');
3267                            if (stored?.reset) {
3268                                try { stored.reset(); } catch {}
3269                            }
3270                        });
3271                    }
3272
3273                    // Arkose Labs
3274                    if (window?.arkose?.reset || typeof ECArkose !== 'undefined') {
3275                        const $arkoseEls = $content.find('[data-arkose-public-key], .arkose-enforcement');
3276                        if ($arkoseEls.length) {
3277                            try {
3278                                window?.arkose?.reset?.();
3279                                ECArkose?.reset?.();
3280                            } catch {}
3281                        }
3282                    }
3283
3284                    // GeeTest
3285                    if (typeof initGeetest !== 'undefined' || typeof GeetInit !== 'undefined') {
3286                        $content.find('.geetest_holder, .geetest_panel').each(function () {
3287                            const inst = this.geetestInstance;
3288                            if (inst?.reset) {
3289                                try { inst.reset(); } catch {}
3290                            }
3291                        });
3292                    }
3293
3294                } catch (err) {}
3295            }, delay);
3296        };
3297
3298        return Module;
3299
3300    }(FOXIZ_MAIN_SCRIPT || {}, jQuery)
3301)
3302
3303/** init */
3304jQuery(document).ready(function ($) {
3305    FOXIZ_MAIN_SCRIPT.init();
3306});
3307
3308/** Elementor editor */
3309jQuery(window).on('elementor/frontend/init', function () {
3310
3311    if (typeof elementorFrontend !== 'undefined' && typeof elementorFrontend.isEditMode === 'function' && elementorFrontend.isEditMode()) {
3312        FOXIZ_MAIN_SCRIPT.isElementorEditor = true;
3313        FOXIZ_MAIN_SCRIPT.editorDarkModeInit = false;
3314
3315        elementorFrontend.hooks.addAction('frontend/element_ready/widget', FOXIZ_MAIN_SCRIPT.initElementor);
3316    }
3317});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.