PageSourceSearch

https://www.kbc.co.ke/wp-content/themes/foxiz/assets/js/global.js?ver=2.7.0

js kbc.co.ke collected 2026-10-02 03:14:53 UTC 129,724 bytes, 3,159 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
1720            if (self.themeSettings && self.themeSettings.adDetectorMethod) {
1721                if (self.crwDetect()) {
1722                    return false;
1723                }
1724
1725                setTimeout(() => {
1726                    if (self.themeSettings.adDetectorMethod == 2) {
1727                        self.advanceAdBlockDetector();
1728                    } else {
1729                        self.basicAdBlockDetector();
1730                    }
1731                }, 1500);
1732            }
1733        };
1734
1735        Module.basicAdBlockDetector = function () {
1736
1737            const self = this;
1738            const checktag = $('#rb-checktag');
1739            const placebo = $('.rb-adbanner');
1740
1741            if (checktag.length === 0) {
1742                return false;
1743            }
1744            if (placebo.height() < 1) {
1745                self.siteAccessFlag = true;
1746                $.magnificPopup.close();
1747                setTimeout(() => {
1748                    self.siteAccessNotification();
1749                }, 200);
1750            }
1751        };
1752
1753        Module.advanceAdBlockDetector = async function () {
1754            const self = this;
1755            const googleAdUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
1756            const isAdBlocked = await (async () => {
1757                try {
1758                    const controller = new AbortController();
1759                    const timeoutId = setTimeout(() => controller.abort(), 3000);
1760                    await fetch(googleAdUrl, {method: 'HEAD', signal: controller.signal});
1761                    clearTimeout(timeoutId);
1762                    return false;
1763                } catch (error) {
1764                    return true;
1765                }
1766            })();
1767            if (isAdBlocked) {
1768                self.siteAccessFlag = true;
1769                self.siteAccessNotification();
1770            }
1771        };
1772
1773        Module.siteAccessNotification = function () {
1774            $.magnificPopup.open({
1775                type: 'inline',
1776                preloader: false,
1777                showCloseBtn: false,
1778                closeBtnInside: false,
1779                enableEscapeKey: false,
1780                closeOnBgClick: false,
1781                removalDelay: 9999999,
1782                items: {
1783                    src: $('#tmpl-rb-site-access').html(),
1784                    type: 'inline'
1785                },
1786                mainClass: 'rb-popup-center site-access-popup',
1787                fixedBgPos: true,
1788                fixedContentPos: true,
1789            });
1790
1791            window.addEventListener('contextmenu', event => event.preventDefault());
1792        }
1793
1794        /** build gallery lightbox */
1795        Module.galleryLightbox = function () {
1796
1797            const self = this;
1798            if (!self.galleriesData) {
1799                return;
1800            }
1801
1802            $('.gallery-popup-trigger').on('click', function (e) {
1803                e.preventDefault();
1804                e.stopPropagation();
1805
1806                const target = $(this);
1807                const slideIndex = target.data('index');
1808
1809                $.magnificPopup.open({
1810                    type: 'inline',
1811                    mainClass: 'rb-gallery-popup rb-popup-center',
1812                    closeMarkup: '<button title="%title%" class="mfp-close mfp-button"><i class="rbi rbi-close"></i></button>',
1813                    closeOnBgClick: false,
1814                    removalDelay: 400,
1815                    showCloseBtn: true,
1816                    fixedBgPos: true,
1817                    fixedContentPos: true,
1818                    preloader: false,
1819                    gallery: {
1820                        enabled: true,
1821                        preload: [0, 2],
1822                        arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-button mfp-arrow-%dir%"><i class="rbi rbi-%dir%"></i></button>',
1823                        tCounter: '<span>%curr% / %total%</span>'
1824                    },
1825                    callbacks: {
1826                        open: function () {
1827                            let itemsArray = Object.values(self.galleriesData);
1828                            let targetIndex = itemsArray.findIndex(item => item.key === slideIndex);
1829                            if (targetIndex !== -1) {
1830                                $.magnificPopup.instance.goTo(targetIndex);
1831                            }
1832                        },
1833                        change: function () {
1834
1835                            let imgContainer = $('.gallery-popup-content');
1836                            let loader = imgContainer.find('.rb-loader');
1837                            let img = imgContainer.find('img');
1838                            loader.show();
1839
1840                            if (!img.length) {
1841                                loader.hide();
1842                                return;
1843                            }
1844
1845                            let loaderTimeout = setTimeout(() => {
1846                                loader.fadeIn(200);
1847                            }, 300); // Show loader only if image takes longer  300ms
1848
1849                            img.on('load', function () {
1850                                clearTimeout(loaderTimeout); // Prevent loader from showing if image loads within 300ms
1851                                loader.hide();
1852                            }).on('error', function () {
1853                                clearTimeout(loaderTimeout);
1854                                loader.hide();
1855                            });
1856                        },
1857                        afterClose: function () {
1858                            $.magnificPopup.instance.popupsCache = {};
1859                        },
1860                        buildControls: function () {
1861                            if (this.arrowLeft && this.arrowRight) {
1862                                this.contentContainer.find('.gallery-popup-nav').append(this.arrowLeft.add(this.arrowRight));
1863                            }
1864                        }
1865                    },
1866                    inline: {
1867                        markup:
1868                            '<div class="gallery-popup-header light-scheme">' +
1869                            '<div class="mfp-counter"></div><div class="mfp-title h5"></div>' +
1870                            '<div class="popup-header-right"><div class="mfp-close"></div></div>' +
1871                            '</div><div class="gallery-popup-nav"></div>' +
1872                            '<div class="gallery-popup-content"><i class="rb-loader"></i>' +
1873                            '<div class="gallery-popup-image mfp-image"></div>' +
1874                            '<div class="gallery-popup-entry light-scheme">' +
1875                            '<div class="h4 mfp-excerpt"></div>' +
1876                            '<div class="description-text mfp-description"></div>' +
1877                            '</div>' +
1878                            '</div>'
1879                    },
1880                    items: Object.values(self.galleriesData)
1881                });
1882
1883                return false;
1884            });
1885        };
1886
1887        /** single featured lightbox */
1888        Module.singleFeaturedLightbox = function () {
1889            $('.featured-lightbox-trigger').on('click', function (e) {
1890
1891                e.preventDefault();
1892                e.stopPropagation();
1893
1894                const trigger = $(this);
1895                const source = '<img src="' + trigger.data('source') + '" alt="' + $(this).find('img').attr('alt') + '">';
1896                const caption = trigger.data('caption');
1897                const attribution = trigger.data('attribution');
1898
1899                $.magnificPopup.open({
1900                    mainClass: 'rb-popup-center popup-no-overflow',
1901                    closeOnBgClick: true,
1902                    removalDelay: 400,
1903                    showCloseBtn: true,
1904                    fixedBgPos: true,
1905                    fixedContentPos: true,
1906                    preloader: false,
1907                    closeMarkup: '<button title="%title%" class="mfp-close rb-popup-close"><i class="rbi rbi-close"></i></button>',
1908                    callbacks: {
1909                        afterClose: function () {
1910                            $.magnificPopup.instance.popupsCache = {};
1911                        },
1912                    },
1913                    inline: {
1914                        markup:
1915                            '<div class="featured-popup-image"><div class="mfp-source"></div>' +
1916                            '<div class="mfp-close rb-popup-close"></div></div>' +
1917                            '<div class="gallery-popup-entry light-scheme">' +
1918                            '<div class="h4 mfp-excerpt"></div>' +
1919                            '<div class="description-text mfp-description"></div>' +
1920                            '</div>'
1921                    },
1922                    items: {
1923                        source: source,
1924                        excerpt: caption,
1925                        description: attribution,
1926                    },
1927                });
1928            });
1929        }
1930
1931        /** Ajax pagination */
1932        Module.paginationNextPrev = function () {
1933            const self = this;
1934            self._body.on('click', '.pagination-trigger', function (e) {
1935
1936                e.preventDefault();
1937                e.stopPropagation();
1938                const paginationTrigger = $(this);
1939                if (paginationTrigger.hasClass('is-disable')) {
1940                    return;
1941                }
1942
1943                const block = paginationTrigger.parents('.block-wrap');
1944                const uuid = block.attr('id');
1945
1946                if (!self.ajaxData[uuid]) {
1947                    self.ajaxData[uuid] = self.getBlockSettings(uuid);
1948                }
1949                if (self.ajaxData[uuid] && self.ajaxData[uuid].processing) {
1950                    return;
1951                }
1952                self.ajaxData[uuid].processing = true;
1953                const type = paginationTrigger.data('type');
1954                self.ajaxStartAnimation(block, 'replace');
1955                self.ajaxReplaceLoad(block, uuid, type);
1956            });
1957        }
1958
1959        Module.ajaxReplaceLoad = function (block, uuid, type) {
1960
1961            const self = this;
1962
1963            if (!self.ajaxData[uuid].paged) {
1964                self.ajaxData[uuid].paged = 1;
1965            }
1966            if ('prev' === type) {
1967                self.ajaxData[uuid].page_next = parseInt(self.ajaxData[uuid].paged) - 1;
1968            } else {
1969                self.ajaxData[uuid].page_next = parseInt(self.ajaxData[uuid].paged) + 1;
1970            }
1971
1972            const cacheID = self.cacheData.getCacheID(uuid, self.ajaxData[uuid].page_next);
1973
1974            /** use cache */
1975            if (self.cacheData.exist(cacheID)) {
1976                const cache = self.cacheData.get(cacheID);
1977                if ('undefined' !== typeof cache.paged) {
1978                    self.ajaxData[uuid].paged = cache.paged;
1979                }
1980                setTimeout(function () {
1981                    self.ajaxRenderHTML(block, uuid, cache, 'replace');
1982                }, 200)
1983
1984            } else {
1985                /** POST AJAX */
1986                $.ajax({
1987                    type: 'GET',
1988                    url: self.ajaxURL,
1989                    data: {
1990                        action: 'rblivep',
1991                        data: self.ajaxData[uuid]
1992                    },
1993                    success: function (response) {
1994                        response = JSON.parse(JSON.stringify(response));
1995                        if ('undefined' !== typeof response.paged) {
1996                            self.ajaxData[uuid].paged = response.paged;
1997                        }
1998                        self.cacheData.set(cacheID, response);
1999                        self.ajaxRenderHTML(block, uuid, response, 'replace');
2000                    }
2001                });
2002            }
2003        }
2004
2005        Module.paginationLoadMore = function () {
2006            const self = this;
2007            self._body.on('click', '.loadmore-trigger', function (e) {
2008
2009                e.preventDefault();
2010                e.stopPropagation();
2011
2012                const paginationTrigger = $(this);
2013                if (paginationTrigger.hasClass('is-disable')) {
2014                    return;
2015                }
2016
2017                const block = paginationTrigger.parents('.block-wrap');
2018                const uuid = block.attr('id');
2019
2020                if (!self.ajaxData[uuid]) {
2021                    self.ajaxData[uuid] = self.getBlockSettings(uuid);
2022                }
2023                if (self.ajaxData[uuid] && self.ajaxData[uuid].processing) {
2024                    return;
2025                }
2026                self.ajaxData[uuid].processing = true;
2027                self.ajaxStartAnimation(block, 'append');
2028                self.ajaxAppendLoad(block, uuid);
2029            })
2030        }
2031
2032        Module.paginationInfinite = function () {
2033
2034            const self = this;
2035
2036            const infiniteElements = $('.pagination-infinite');
2037            if (infiniteElements.length > 0) {
2038                infiniteElements.each(function () {
2039                    const paginationTrigger = $(this);
2040                    if (!paginationTrigger.hasClass('is-disable')) {
2041                        const block = paginationTrigger.parents('.block-wrap');
2042                        if ((block.hasClass('is-hoz-scroll') || block.hasClass('is-mhoz-scroll') || block.hasClass('is-thoz-scroll')) && window.outerWidth < 1025) {
2043                            paginationTrigger.addClass('is-disable');
2044                            return;
2045                        }
2046                        const uuid = block.attr('id');
2047                        const wPointID = 'infinite' + uuid;
2048                        if (!self.ajaxData[uuid]) {
2049                            self.ajaxData[uuid] = self.getBlockSettings(uuid);
2050                        }
2051                        const params = {
2052                            element: paginationTrigger,
2053                            offset: 'bottom-in-view',
2054                            handler: function (direction) {
2055                                if (self.ajaxData[uuid] && self.ajaxData[uuid].processing) {
2056                                    return;
2057                                }
2058                                if ('down' == direction) {
2059                                    self.ajaxData[uuid].processing = true;
2060                                    self.ajaxStartAnimation(block, 'append');
2061                                    self.ajaxAppendLoad(block, uuid);
2062                                }
2063                            }
2064                        }
2065                        self.wPoint[wPointID] = new Waypoint(params);
2066                    }
2067                });
2068            }
2069        }
2070
2071        Module.ajaxAppendLoad = function (block, uuid) {
2072            const self = this;
2073            if (!self.ajaxData[uuid].paged) {
2074                self.ajaxData[uuid].paged = 1;
2075            }
2076            if (self.ajaxData[uuid].paged >= self.ajaxData[uuid].page_max) {
2077                return;
2078            }
2079            self.ajaxData[uuid].page_next = parseInt(self.ajaxData[uuid].paged) + 1;
2080            $.ajax({
2081                type: 'GET',
2082                url: self.ajaxURL,
2083                data: {
2084                    action: 'rblivep',
2085                    data: self.ajaxData[uuid]
2086                },
2087                success: function (response) {
2088                    response = JSON.parse(JSON.stringify(response));
2089                    if ('undefined' !== typeof response.paged) {
2090                        self.ajaxData[uuid].paged = response.paged;
2091                    }
2092                    if ('undefined' !== typeof response.notice) {
2093                        response.content = response.content + response.notice;
2094                    }
2095                    self.ajaxRenderHTML(block, uuid, response, 'append');
2096                }
2097            });
2098        }
2099
2100        Module.liveSearch = function () {
2101
2102            const liveSearch = $('.live-search-form');
2103            if (liveSearch.length === 0) {
2104                return;
2105            }
2106
2107            const self = this;
2108
2109            liveSearch.each(function () {
2110                const liveSearchEl = $(this);
2111                const input = liveSearchEl.find('input[type="text"]');
2112                const responseWrap = liveSearchEl.find('.live-search-response');
2113                const animation = liveSearchEl.find('.live-search-animation');
2114                const limit = liveSearchEl.data('limit');
2115                const search = liveSearchEl.data('search');
2116                const follow = liveSearchEl.data('follow');
2117                const tax = liveSearchEl.data('tax');
2118                const dsource = liveSearchEl.data('dsource');
2119                const ptype = liveSearchEl.data('ptype');
2120
2121                input.attr('autocomplete', 'off');
2122
2123                input.on('focus', function () {
2124                    const param = $(this).val();
2125                    if (param && !responseWrap.is(':empty')) {
2126                        responseWrap.css('height', 'auto').fadeIn(200);
2127                    }
2128                });
2129
2130                const delay = (function () {
2131                    let timer = 0;
2132                    return function (callback, ms) {
2133                        clearTimeout(timer);
2134                        timer = setTimeout(callback, ms);
2135                    };
2136                })();
2137
2138                input.keyup(function () {
2139                    const param = $(this).val();
2140                    delay(function () {
2141                        if (param) {
2142                            liveSearchEl.addClass('search-loading');
2143                            setTimeout(function () {
2144                                animation.fadeIn(100);
2145                            }, 120);
2146
2147                            $.ajax({
2148                                type: 'GET',
2149                                url: self.ajaxURL,
2150                                data: {
2151                                    action: 'rbsearch',
2152                                    s: param,
2153                                    limit: limit,
2154                                    search: search,
2155                                    follow: follow,
2156                                    tax: tax,
2157                                    dsource: dsource,
2158                                    ptype: ptype,
2159                                },
2160                                success: function (data) {
2161                                    data = $.parseJSON(JSON.stringify(data));
2162                                    animation.fadeOut(200);
2163                                    setTimeout(function () {
2164                                        liveSearchEl.removeClass('search-loading');
2165                                    }, 200);
2166                                    responseWrap.hide().empty().css('height', responseWrap.height());
2167                                    responseWrap.html(data);
2168                                    if ('category' === search && follow && typeof FOXIZ_PERSONALIZE !== 'undefined') {
2169                                        FOXIZ_PERSONALIZE.syncLayoutCategories();
2170                                    }
2171                                    responseWrap.css('height', 'auto').fadeIn(200);
2172                                }
2173                            });
2174                        } else {
2175                            responseWrap.fadeOut(200, function () {
2176                                responseWrap.empty().css('height', 'auto');
2177                            });
2178                        }
2179                    }, 300);
2180                })
2181            });
2182        }
2183
2184        /** personalized block */
2185        Module.personalizeBlocks = function () {
2186            const self = this;
2187            const elements = $('.is-ajax-block');
2188            if (elements.length > 0) {
2189                const blockRequests = elements.map(function () {
2190                    const block = $(this);
2191                    const uuid = block.attr('id');
2192                    if (!self.ajaxData[uuid]) {
2193                        self.ajaxData[uuid] = self.getBlockSettings(uuid);
2194                    }
2195
2196                    if (self.ajaxData[uuid].content_source &&
2197                        self.ajaxData[uuid].content_source === 'recommended' &&
2198                        typeof foxizQueriedIDs !== 'undefined' && foxizQueriedIDs.data
2199                    ) {
2200                        self.ajaxData[uuid].post_not_in = foxizQueriedIDs.data;
2201                    }
2202
2203                    self.ajaxData[uuid].uID = self.getStorage('RBUUID', '0');
2204
2205                    return $.ajax({
2206                        type: 'GET',
2207                        url: self.ajaxURL,
2208                        data: {
2209                            action: 'rbpersonalizeb',
2210                            data: self.ajaxData[uuid]
2211                        }
2212                    });
2213                });
2214
2215                Promise.all(blockRequests).then(responses => {
2216                    responses.forEach((response, index) => {
2217                        const block = $(elements[index]);
2218                        block.html(response).fadeIn(200);
2219                        block.dequeue();
2220                    });
2221                    self.reloadBlockFunc();
2222                });
2223            }
2224        };
2225
2226        /** personalized categories */
2227        Module.personalizeCategories = function () {
2228
2229            const self = this;
2230            const elements = $('.is-ajax-categories');
2231            if (elements.length > 0) {
2232                const categoryRequests = elements.map(function () {
2233                    const block = $(this);
2234                    const uuid = block.attr('id');
2235                    if (!self.ajaxData[uuid]) {
2236                        self.ajaxData[uuid] = self.getBlockSettings(uuid);
2237                    }
2238                    return $.ajax({
2239                        type: 'GET',
2240                        url: self.ajaxURL,
2241                        data: {
2242                            action: 'rbpersonalizecat',
2243                            data: self.ajaxData[uuid]
2244                        }
2245                    });
2246                });
2247
2248                Promise.all(categoryRequests).then(responses => {
2249                    responses.forEach((response, index) => {
2250                        const block = $(elements[index]);
2251                        block.html(response).fadeIn(200);
2252                        block.dequeue();
2253                    });
2254
2255                    if (typeof FOXIZ_PERSONALIZE !== 'undefined') {
2256                        FOXIZ_PERSONALIZE.syncLayoutCategories();
2257                    }
2258                    self.reloadBlockFunc();
2259                });
2260            }
2261        };
2262
2263        Module.readingCollect = function () {
2264            const self = this;
2265            if (self.themeSettings.yesReadingHis === undefined) {
2266                return;
2267            }
2268            $.ajax({
2269                type: 'GET',
2270                url: self.ajaxURL,
2271                data: {
2272                    action: 'rbcollect',
2273                    id: self.themeSettings.yesReadingHis
2274                }
2275            });
2276        };
2277
2278        /** header notification */
2279        Module.newsNotification = function () {
2280
2281            const notificationWrapper = $('.rb-notification');
2282            if (notificationWrapper.length < 1) {
2283                return false;
2284            }
2285            const notificationID = this.personalizeUID + '-notification';
2286            const notificationCount = this.personalizeUID + '-notification-count';
2287
2288            const self = this;
2289            const dot = $('.notification-info');
2290            const content = self.getTTLStorage(notificationID);
2291            const count = self.getTTLStorage(notificationCount);
2292            let reload = notificationWrapper.data('interval');
2293            if (!reload || isNaN(reload) || reload <= 0) {
2294                reload = 6;
2295            }
2296            if (!content) {
2297                $.ajax({
2298                    type: 'GET',
2299                    url: self.ajaxURL,
2300                    data: {
2301                        action: 'rbnotification',
2302                    },
2303                    success: function (response) {
2304                        response = $.parseJSON(JSON.stringify(response));
2305                        self.SetTTLStorage(notificationID, response.content, reload);
2306                        self.SetTTLStorage(notificationCount, response.count, reload);
2307                        notificationWrapper.append(response.content);
2308                        if (response.count) {
2309                            dot.append(response.count);
2310                            dot.css('opacity', 1);
2311                        }
2312                    }
2313                });
2314            } else {
2315                notificationWrapper.append(content);
2316                dot.append(count);
2317            }
2318        };
2319
2320        /** register cache object */
2321        Module.cacheData = {
2322
2323            data: {},
2324            get: function (id) {
2325                return this.data[id];
2326            },
2327
2328            set: function (id, data) {
2329                this.remove(id);
2330                this.data[id] = data;
2331            },
2332
2333            remove: function (id) {
2334                delete this.data[id];
2335            },
2336
2337            getCacheID: function (blockID, currentPage) {
2338                return JSON.stringify('RB_' + blockID + '_' + currentPage);
2339            },
2340
2341            exist: function (id) {
2342                return this.data.hasOwnProperty(id) && this.data[id] !== null;
2343            }
2344        }
2345
2346        /**
2347         * ajax start animation
2348         * @param block
2349         * @param action
2350         */
2351        Module.ajaxStartAnimation = function (block, action) {
2352
2353            const inner = block.find('.block-inner');
2354            block.find('.pagination-trigger').addClass('is-disable');
2355            inner.stop();
2356
2357            if ('replace' === action) {
2358                inner.css('min-height', inner.outerHeight());
2359                inner.fadeTo('200', 0.05);
2360                inner.after('<i class="rb-loader loader-absolute"></i>');
2361            } else {
2362                block.find('.loadmore-trigger').addClass('loading');
2363                block.find('.rb-loader').css({'display': 'block'}).delay(200).animate({opacity: 1}, 200);
2364            }
2365        }
2366
2367        /**
2368         * render ajax
2369         * @param block
2370         * @param uuid
2371         * @param response
2372         * @param action
2373         */
2374        Module.ajaxRenderHTML = function (block, uuid, response, action) {
2375
2376            const self = this;
2377
2378            block.delay(50).queue(function () {
2379                const uuid = block.attr('id');
2380                const inner = block.find('.block-inner');
2381                block.find('.pagination-trigger').removeClass('is-disable');
2382                inner.stop();
2383
2384                if ('replace' === action) {
2385                    inner.html(response.content);
2386                    block.find('.rb-loader').animate({opacity: 0}, 200, function () {
2387                        $(this).remove();
2388                    })
2389                    inner.css('min-height', '');
2390                    inner.fadeTo(200, 1);
2391
2392                } else {
2393                    const content = $(response.content);
2394                    inner.append(content);
2395                    content.addClass('is-invisible');
2396                    content.addClass('opacity-animate');
2397
2398                    block.find('.rb-loader').animate({opacity: 0}, 200, function () {
2399                        $(this).css({'display': 'none'});
2400                    });
2401                    setTimeout(function () {
2402                        content.removeClass('is-invisible');
2403                    }, 200);
2404                    block.find('.loadmore-trigger').removeClass('loading');
2405                }
2406
2407                /** reload */
2408                self.ajaxTriggerState(block, uuid);
2409                self.ajaxData[uuid].processing = false;
2410                block.dequeue();
2411                self.reloadBlockFunc();
2412            });
2413        }
2414
2415        /**
2416         * set
2417         * @param block
2418         * @param uuid
2419         */
2420        Module.ajaxTriggerState = function (block, uuid) {
2421            const self = this;
2422            block.find('.pagination-trigger').removeClass('is-disable');
2423            if (self.ajaxData[uuid].paged < 2) {
2424                block.find('[data-type="prev"]').addClass('is-disable');
2425            } else if (self.ajaxData[uuid].paged >= self.ajaxData[uuid].page_max) {
2426                block.find('[data-type="next"]').addClass('is-disable');
2427                block.find('.loadmore-trigger').addClass('is-disable').hide();
2428                block.find('.pagination-infinite').addClass('is-disable').hide();
2429            }
2430        }
2431
2432        Module.getBlockSettings = function (uuid) {
2433            const settings = typeof window[uuid] !== 'undefined' ? window[uuid] : undefined;
2434            return this.cleanNull(settings);
2435        }
2436
2437        Module.cleanNull = function (data) {
2438            if (typeof data === 'string') {
2439                return data;
2440            }
2441
2442            if (data && typeof data === 'object') {
2443                Object.keys(data).forEach(key => {
2444                    if (data[key] === '' || data[key] === null) {
2445                        delete data[key];
2446                    }
2447                });
2448            }
2449
2450            return data;
2451        };
2452
2453        /* SINGLE INFINITE */
2454        Module.singleInfiniteLoadNext = function () {
2455
2456            const infiniteWrapper = $('#single-post-infinite');
2457            const self = this;
2458
2459            if (!infiniteWrapper.length || self.disabledLoadNext()) {
2460                return;
2461            }
2462
2463            self.singleLoadNextCounter = 1;
2464            self.singleLoadNextLimit = self.themeSettings?.singleLoadNextLimit ? parseInt(self.themeSettings.singleLoadNextLimit, 10) : 20;
2465
2466            const infiniteLoadPoint = $('#single-infinite-point');
2467            const animationIcon = infiniteLoadPoint.find('.rb-loader');
2468            const rootURL = new URL(window.location.href);
2469            const rootGetParams = rootURL.searchParams;
2470
2471            const loadNextParams = {
2472                element: infiniteLoadPoint,
2473                offset: 'bottom-in-view',
2474                handler: function (direction) {
2475                    if (self.ajaxData.singleProcessing || direction === 'up' || self.singleLoadNextCounter > self.singleLoadNextLimit) {
2476                        return;
2477                    }
2478                    const nextPostURL = new URL(infiniteWrapper.data('nextposturl'));
2479                    nextPostURL.searchParams.set('rbsnp', '1');
2480                    if (rootGetParams) {
2481                        rootGetParams.forEach((value, key) => {
2482                            if (key !== 'rbsnp' && 'p' !== key) {
2483                                nextPostURL.searchParams.set(key, value);
2484                            }
2485                        });
2486                    }
2487                    self.ajaxData.singleProcessing = true;
2488                    animationIcon.css('display', 'block').animate({opacity: 1}, 200);
2489
2490                    $.ajax({
2491                        type: 'GET',
2492                        url: nextPostURL.toString(),
2493                        dataType: 'html',
2494                        success: function (response) {
2495                            response = $('<div id="temp-dom"></div>').append($.parseHTML(response)).find('.single-post-outer');
2496                            const nextPostURL = response.data('nextposturl');
2497
2498                            if (nextPostURL) {
2499                                infiniteWrapper.data('nextposturl', nextPostURL);
2500                            } else {
2501                                infiniteWrapper.removeAttr('id');
2502                                infiniteLoadPoint.remove();
2503                            }
2504
2505                            animationIcon.animate({opacity: 0}, 200).delay(200).css('display', 'none');
2506                            infiniteWrapper.append(response);
2507                            self.ajaxData.singleProcessing = false;
2508                            self.singleLoadNextCounter++;
2509
2510                            setTimeout(function () {
2511                                self.reInitAll();
2512                                if (typeof FOXIZ_CORE_SCRIPT !== 'undefined') {
2513                                    FOXIZ_CORE_SCRIPT.loadGoogleAds(response);
2514                                    FOXIZ_CORE_SCRIPT.loadInstagram(response);
2515                                    FOXIZ_CORE_SCRIPT.loadTwttr();
2516                                }
2517                            }, 1);
2518                        }
2519                    });
2520                }
2521            };
2522
2523            self.wPoint.ajaxSingleNextPosts = new Waypoint(loadNextParams);
2524        };
2525
2526        Module.singleScrollRefresh = function () {
2527
2528            const infiniteWrapper = $('#single-post-infinite');
2529            if (!infiniteWrapper.length) {
2530                return;
2531            }
2532            const self = this;
2533            self.articleData = [];
2534            const articleOuter = infiniteWrapper.find('.single-post-outer');
2535
2536            if (articleOuter.length > 0) {
2537                self.inviewPostID = articleOuter.eq(0).data('postid');
2538
2539                articleOuter.each(function () {
2540                    const article = $(this);
2541                    const itemData = {
2542                        postID: article.data('postid'),
2543                        postURL: article.data('postlink'),
2544                        postTitle: article.find('h1.s-title').text(),
2545                        shareList: article.find('.sticky-share-list-buffer').html(),
2546                        top: article.offset().top,
2547                        bottom: article.offset().top + article.outerHeight(true)
2548                    };
2549
2550                    if (self.readIndicator.length > 0) {
2551                        const content = article.find('.rbct').eq(0);
2552                        itemData.indicatorTop = content.offset().top;
2553                        itemData.indicatorHeight = content.outerHeight(true) - self._window.height();
2554                    }
2555                    self.articleData.push(itemData);
2556                });
2557
2558                const onScroll = () => {
2559                    self.animationFrame(self.scrollToUpdateArticle.bind(self));
2560                };
2561                if (window.addEventListener) {
2562                    window.addEventListener('scroll', onScroll, false);
2563                }
2564            }
2565        }
2566
2567        /** scrollToUpdateArticle */
2568        Module.scrollToUpdateArticle = function () {
2569            const self = this;
2570            const scroll = self._window.scrollTop();
2571
2572            self.articleData.every(article => {
2573                if (scroll > (article.top + 5) && scroll < (article.bottom - 5)) {
2574                    if (article.indicatorTop) {
2575                        self.readIndicatorPercent = Math.min(((scroll - article.indicatorTop) / article.indicatorHeight) * 100, 100);
2576                        if (self.readIndicatorPercent <= 100) {
2577                            self.readIndicator.css('width', `${self.readIndicatorPercent}%`);
2578                        }
2579                    }
2580
2581                    if (article.postID !== self.inviewPostID) {
2582                        self.inviewPostID = article.postID;
2583                        if (article.postURL) {
2584                            history.replaceState(null, null, article.postURL);
2585                        }
2586                        document.title = article.postTitle;
2587                        $('.single-post-outer').removeClass('activated');
2588                        $('[data-postid="' + article.postID + '"]').addClass('activated');
2589                        $('#s-title-sticky .sticky-title').hide().html(article.postTitle).fadeIn(300);
2590                        $('#s-title-sticky .sticky-share-list').html(article.shareList);
2591                        self._body.find('.floating-video').removeClass('floating-activated');
2592
2593                        if (typeof FOXIZ_CORE_SCRIPT !== 'undefined') {
2594                            FOXIZ_CORE_SCRIPT.updateGA(article);
2595                        }
2596                    }
2597                    return false;
2598                }
2599
2600                return true;
2601
2602            });
2603        }
2604
2605        /**
2606         * @returns {boolean}
2607         */
2608        Module.crwDetect = function () {
2609            const botPatterns = [
2610                /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
2610oysmcm|yammybot|ahrefsbot|pingdom.com_bot|kraken|yandexbot|twitterbot|tweetmemebot|openhosebot|queryseekerspider|linkdexbot|grokkit-crawler|livelapbot|germcrawler|domaintunocrawler|grapeshotcrawler|cloudflare-alwaysonline/i
2611            ];
2612
2613            const userAgent = navigator.userAgent;
2614            return botPatterns.some(pattern => pattern.test(userAgent));
2615        };
2616
2617        /**
2618         *
2619         * @returns {boolean}
2620         */
2621        Module.disabledLoadNext = function () {
2622
2623            if (this.themeSettings.crwLoadNext) {
2624                return false;
2625            }
2626
2627            return this.crwDetect();
2628        }
2629
2630        /** productQuantity */
2631        Module.productQuantity = function () {
2632            this._document.on('click', '.quantity .quantity-btn', function (e) {
2633
2634                e.preventDefault();
2635                e.stopPropagation();
2636
2637                const button = $(this);
2638                const input = button.parent().find('input');
2639
2640                let step = 1;
2641                let min = 1;
2642                let max = 9999;
2643                let value_old = parseInt(input.val());
2644                let value_new = parseInt(input.val());
2645
2646                if (input.attr('step')) {
2647                    step = parseInt(input.attr('step'));
2648                }
2649
2650                if (input.attr('min')) {
2651                    min = parseInt(input.attr('min'));
2652                }
2653
2654                if (input.attr('max')) {
2655                    max = parseInt(input.attr('max'));
2656                }
2657
2658                if (button.hasClass('up')) {
2659                    if (value_old < max) {
2660                        value_new = value_old + step;
2661                    } else {
2662                        value_new = 1;
2663                    }
2664                } else if (button.hasClass('down')) {
2665                    if (value_old > min) {
2666                        value_new = value_old - step;
2667                    } else {
2668                        value_new = 0;
2669                    }
2670                }
2671
2672                if (!input.attr('disabled')) {
2673                    input.val(value_new).change();
2674                }
2675            });
2676        }
2677
2678        Module.cartNotification = function () {
2679            const self = this;
2680            const element = $('#add-cart-popup');
2681
2682            self._body.on('added_to_cart', function () {
2683                element.fadeIn(200);
2684                self.cartNotificationTimeOut = setTimeout(function () {
2685                    element.fadeOut(200);
2686                }, 5000);
2687                self.hoveringNotification(element);
2688            });
2689        }
2690
2691        Module.hoveringNotification = function (element) {
2692            const self = this;
2693
2694            element.on('mouseenter', function () {
2695                clearTimeout(self.cartNotificationTimeOut);
2696            });
2697
2698            element.on('mouseleave', function () {
2699                setTimeout(function () {
2700                    element.fadeOut(200);
2701                }, 1500);
2702            });
2703        }
2704
2705        /** like/dislike */
2706        Module.likeToggle = function () {
2707
2708            const self = this;
2709            let reaction = '';
2710            self._body.on('click', '.like-trigger, .dislike-trigger', function (e) {
2711
2712                e.preventDefault();
2713                e.stopPropagation();
2714
2715                const target = $(this);
2716                const wrap = target.parent('[data-like]');
2717                const pid = wrap.data('like');
2718
2719                if (!pid || self.isProgress) return;
2720
2721                self.isProgress = true;
2722                const storageKey = self.getLikeKey(pid);
2723                const isLike = target.hasClass('like-trigger');
2724                const isDislike = target.hasClass('dislike-trigger');
2725                const sibEl = target.siblings();
2726                const likeCountEl = wrap.find('.like-count');
2727                const dislikeCountEl = wrap.find('.dislike-count');
2728                let likeCountText = likeCountEl.text();
2729                let dislikeCountText = dislikeCountEl.text();
2730
2731                if (isLike) {
2732                    if (!target.hasClass('triggered')) {
2733                        reaction = 'like';
2734                        if (!/[kKmM]/.test(likeCountText)) {
2735                            likeCountText = parseInt(likeCountText);
2736                            if (isNaN(likeCountText)) {
2737                                likeCountText = 0;
2738                            }
2739                            likeCountEl.text(likeCountText + 1);
2740                        }
2741                        target.addClass('triggered');
2742
2743                        if (sibEl.hasClass('triggered')) {
2744                            sibEl.removeClass('triggered');
2745                            if (!/[kKmM]/.test(dislikeCountText)) {
2746                                dislikeCountText = parseInt(dislikeCountText) - 1;
2747                                if (isNaN(dislikeCountText) || dislikeCountText < 1) {
2748                                    dislikeCountText = '';
2749                                }
2750                                dislikeCountEl.text(dislikeCountText);
2751                            }
2752                        }
2753                        self.setStorage(storageKey, 'like');
2754                    } else {
2755                        reaction = 'rmlike';
2756                        if (!/[kKmM]/.test(likeCountText)) {
2757                            likeCountText = parseInt(likeCountText) - 1;
2758                            if (isNaN(likeCountText) || likeCountText < 1) {
2759                                likeCountText = '';
2760                            }
2761                            likeCountEl.text(likeCountText);
2762                        }
2763                        target.removeClass('triggered');
2764                        self.deleteStorage(storageKey);
2765                    }
2766                } else if (isDislike) {
2767                    if (!target.hasClass('triggered')) {
2768                        reaction = 'dislike';
2769                        if (!/[kKmM]/.test(dislikeCountText)) {
2770                            dislikeCountText = parseInt(dislikeCountText);
2771                            if (isNaN(dislikeCountText)) {
2772                                dislikeCountText = 0;
2773                            }
2774                            dislikeCountEl.text(dislikeCountText + 1);
2775                        }
2776                        target.addClass('triggered');
2777                        if (sibEl.hasClass('triggered')) {
2778                            sibEl.removeClass('triggered');
2779                            if (!/[kKmM]/.test(likeCountText)) {
2780                                likeCountText = parseInt(likeCountText) - 1;
2781                                if (isNaN(likeCountText) || likeCountText < 1) {
2782                                    likeCountText = '';
2783                                }
2784                                likeCountEl.text(likeCountText);
2785                            }
2786                        }
2787                        self.setStorage(storageKey, 'dislike');
2788                    } else {
2789                        reaction = 'rmdislike';
2790                        if (!/[kKmM]/.test(dislikeCountText)) {
2791                            likeCountText = parseInt(likeCountText) - 1;
2792                            if (isNaN(likeCountText) || likeCountText < 1) {
2793                                likeCountText = '';
2794                            }
2795                            dislikeCountEl.text(likeCountText);
2796                        }
2797                        target.removeClass('triggered');
2798                        self.deleteStorage(storageKey);
2799                    }
2800                }
2801
2802                $.ajax({
2803                    type: 'GET',
2804                    url: self.ajaxURL,
2805                    data: {
2806                        uuid: self.personalizeUID,
2807                        action: 'rbvoting',
2808                        value: reaction,
2809                        pid: pid,
2810                    },
2811                    complete: () => {
2812                        self.isProgress = false;
2813                    }
2814                })
2815            })
2816        }
2817
2818        /** sync layout */
2819        Module.syncLayoutLike = function () {
2820
2821            this.isProgress = true;
2822            const likeElements = document.querySelectorAll('[data-like]:not(.loaded)');
2823            const jsCount = this._body.hasClass('is-jscount');
2824            let count, countEl;
2825
2826            for (const el of likeElements) {
2827                el.classList.add('loaded');
2828                const key = this.getLikeKey(el.getAttribute('data-like'));
2829                const triggered = this.getStorage(key);
2830
2831                if (!triggered) continue;
2832
2833                const likeEl = el.querySelector('.el-like');
2834                const dislikeEl = el.querySelector('.el-dislike');
2835
2836                if (!likeEl || !dislikeEl) continue;
2837
2838                if (triggered === 'like') {
2839                    likeEl.classList.add('triggered');
2840                    countEl = jsCount ? likeEl.querySelector('.like-count') : null;
2841                    if (countEl) {
2842                        count = parseInt(countEl.textContent.trim()) || 0;
2843                        countEl.textContent = count + 1;
2844                    }
2845                } else if (triggered === 'dislike') {
2846                    dislikeEl.classList.add('triggered');
2847                    countEl = jsCount ? dislikeEl.querySelector('.dislike-count') : null;
2848                    if (countEl) {
2849                        count = parseInt(countEl.textContent.trim()) || 0;
2850                        countEl.textContent = count + 1;
2851                    }
2852                }
2853            }
2854
2855            this.isProgress = false;
2856        };
2857
2858        /** like key */
2859        Module.getLikeKey = function (id) {
2860            return this.personalizeUID + '-like-' + id;
2861        }
2862
2863        /** live blog */
2864        Module.liveBlog = function () {
2865            const self = this;
2866
2867            const liveEntry = $('.rb-live-entry');
2868
2869            if (liveEntry.length === 0) {
2870                return false;
2871            }
2872
2873            let intervalId;
2874            const interval = Math.max(30, this.themeSettings.liveInterval || 0);
2875            const liveSwitcher = $('#live-interval-switcher');
2876            const storedSetting = this.getStorage('liveIntervalCheckbox');
2877
2878            const updateInterval = () => {
2879                clearInterval(intervalId);
2880                if (liveSwitcher.prop('checked')) {
2881                    intervalId = setInterval(() => this.updateLiveBlog(liveEntry), interval * 1000);
2882                    self.setStorage('liveIntervalCheckbox', 'yes');
2883                } else {
2884                    self.setStorage('liveIntervalCheckbox', 'no');
2885                }
2886            };
2887
2888            if (storedSetting !== null) {
2889                liveSwitcher.prop('checked', storedSetting === 'yes');
2890            } else {
2891                self.setStorage('liveIntervalCheckbox', 'yes');
2892            }
2893
2894            updateInterval();
2895            liveSwitcher.on('change', updateInterval);
2896        };
2897
2898        Module.updateLiveBlog = function (liveEntry) {
2899
2900            const self = this;
2901            const liveURL = new URL(window.location.href);
2902            liveURL.searchParams.set('rblive', '1');
2903            $.ajax({
2904                type: 'GET',
2905                url: liveURL.toString(),
2906                dataType: 'html',
2907                success: function (response) {
2908                    response = $('<div id="temp-dom"></div>').append($.parseHTML(response)).find('#rb-live-content');
2909                    liveEntry.html(response.html());
2910                    const liveCountElement = liveEntry.prev().find('.live-count');
2911                    if (liveCountElement.length) {
2912                        liveCountElement.text(response.data('total'));
2913                    }
2914                    setTimeout(function () {
2915                        self.reInitAll();
2916                        if (typeof FOXIZ_CORE_SCRIPT !== 'undefined') {
2917                            FOXIZ_CORE_SCRIPT.loadGoogleAds(response);
2918                            FOXIZ_CORE_SCRIPT.loadInstagram(response);
2919                            FOXIZ_CORE_SCRIPT.loadTwttr();
2920                        }
2921                    }, 1);
2922                }
2923            });
2924        }
2925
2926        Module.accordion = function () {
2927            $('.gb-accordion').each(function () {
2928                const accordion = $(this);
2929                if (accordion.hasClass('yesLoaded')) return;
2930
2931                accordion.addClass('yesLoaded');
2932                const accordionItems = accordion.find('.gb-accordion-item');
2933
2934                if (accordion.hasClass('yes-open')) {
2935                    accordionItems.first().addClass('active').find('.accordion-item-content').css('display', 'block');
2936                }
2937
2938                accordion.on('click', '.accordion-item-header', function (e) {
2939                    e.preventDefault();
2940
2941                    const header = $(this);
2942                    const item = header.closest('.gb-accordion-item');
2943                    const content = item.find('.accordion-item-content');
2944
2945                    if (item.hasClass('active')) {
2946                        item.removeClass('active');
2947                        content.stop().slideUp(200);
2948                    } else {
2949                        const activeItem = accordionItems.filter('.active');
2950                        activeItem.removeClass('active').find('.accordion-item-content').stop().slideUp(200);
2951                        item.addClass('active');
2952                        content.stop().slideDown(200);
2953                    }
2954                });
2955            });
2956        };
2957
2958        Module.resIframeClassic = function () {
2959
2960            if (!document.body.classList.contains('res-iframe-classic')) return
2961            const iframes = document.querySelectorAll('.rbct iframe');
2962            iframes.forEach(iframe => {
2963                const parent = iframe.parentElement;
2964                const grandParent = parent.parentElement;
2965                const greatGrandParent = grandParent.parentElement;
2966
2967                if ([parent, grandParent, greatGrandParent].some(element => {
2968                    const classNames = Array.from(element.classList);
2969                    return classNames.some(className => className.indexOf('wp-block') !== -1);
2970                })) return;
2971
2972                if (!iframe.parentElement.classList.contains('rb-video-ires')) {
2973                    if (iframe.src.includes('youtube.com') || iframe.src.includes('youtu.be') || iframe.src.includes('vimeo.com') || iframe.src.includes('dailymotion.com')) {
2974                        iframe.parentElement.classList.add('rb-video-ires');
2975                    }
2976                }
2977            });
2978        }
2979
2980        Module.taxBasedAccordion = function () {
2981
2982            const self = this;
2983            $('.block-tax-accordion').each(function () {
2984                const accordion = $(this);
2985                if (accordion.hasClass('is-loaded')) {
2986                    return;
2987                }
2988                accordion.addClass('is-loaded');
2989                const accordionItems = accordion.find('.tax-accordion-item');
2990                const lastOpenedTab = self.getStorage(accordion.attr('id') + '_lastOpenedTab', null);
2991
2992                if (lastOpenedTab) {
2993                    const tabToOpen = accordion.find('[data-tab="' + lastOpenedTab + '"] .tax-accordion-sub');
2994                    if (tabToOpen.length !== 0) {
2995                        tabToOpen.show();
2996                    }
2997                }
2998
2999                accordionItems.each(function () {
3000                    const item = $(this);
3001                    const trigger = item.find('.tax-accordion-trigger');
3002                    const subMenu = item.find('.tax-accordion-sub');
3003
3004                    trigger.click(function () {
3005                        if (!subMenu.is(':visible')) {
3006                            accordion.find('.tax-accordion-sub').not(subMenu).slideUp();
3007                        }
3008                        subMenu.slideToggle(function () {
3009                            if (subMenu.is(':visible')) {
3010                                self.setStorage(accordion.attr('id') + '_lastOpenedTab', item.attr('data-tab'));
3011                            } else {
3012                                self.deleteStorage(accordion.attr('id') + '_lastOpenedTab');
3013                            }
3014                        });
3015                    });
3016                });
3017            });
3018        };
3019
3020
3021        Module.sequentialGalleryDisplay = function () {
3022            const galleries = Array.from(document.querySelectorAll('.gallery-animated'));
3023            galleries.forEach(gallery => {
3024                const images = Array.from(gallery.querySelectorAll('.e-gallery-item'));
3025                new Waypoint({
3026                    element: gallery,
3027                    handler: function (direction) {
3028                        if (direction === 'down') {
3029                            images.forEach((image, index) => {
3030                                requestAnimationFrame(() => {
3031                                    setTimeout(() => {
3032                                        image.classList.add('gallery-visible');
3033                                    }, index * 120);
3034                                });
3035                            });
3036                            this.destroy();
3037                        }
3038                    },
3039                    offset: '80%'
3040                });
3041            });
3042        };
3043
3044
3045        Module.reloadCaptchaPopups = function (delay = 50) {
3046            setTimeout(() => {
3047                const $content = $($.magnificPopup?.instance?.content || []);
3048                if (!$content.length) return;
3049
3050                const removeDuplicateCaptchas = form => {
3051                    const seen = new Set();
3052                    $(form)
3053                        .find('.g-recaptcha, .h-captcha, .cf-turnstile, .turnstile-widget, .frc-captcha, [data-arkose-public-key], .arkose-enforcement, .geetest_holder, .geetest_panel')
3054                        .each(function () {
3055                            const cls = this.className;
3056                            const type = ['g-recaptcha', 'h-captcha', 'cf-turnstile', 'turnstile-widget', 'frc-captcha', 'arkose', 'geetest']
3057                                .find(t => cls.includes(t) || $(this).data('arkose-public-key') || $(this).hasClass('arkose-enforcement'));
3058                            if (!type) return;
3059                            const key = `${type}`;
3060                            if (seen.has(key)) {
3061                                $(this).remove();
3062                            } else {
3063                                seen.add(key);
3064                            }
3065                        });
3066                };
3067
3068                try {
3069                    // Remove duplicates per form
3070                    $content.find('form').each(function () {
3071                        removeDuplicateCaptchas(this);
3072                    });
3073
3074                    // Google reCAPTCHA
3075                    if (typeof grecaptcha !== 'undefined' && grecaptcha?.reset) {
3076                        $content.find('.g-recaptcha').each(function () {
3077                            const wid = this.dataset.widgetId;
3078                            if (wid) {
3079                                try { grecaptcha.reset(Number(wid)); } catch {}
3080                            }
3081                        });
3082                    }
3083
3084                    // Cloudflare Turnstile
3085                    if (typeof turnstile !== 'undefined' && turnstile?.reset) {
3086                        $content.find('.cf-turnstile, .turnstile-widget').each(function () {
3087                            const iframe = this.querySelector('iframe');
3088                            const wid = iframe?.dataset?.wid;
3089                            if (wid) {
3090                                try { turnstile.reset(wid); } catch {}
3091                            }
3092                        });
3093                    }
3094
3095                    // hCaptcha
3096                    if (typeof hcaptcha !== 'undefined' && hcaptcha?.reset) {
3097                        $content.find('.h-captcha').each(function () {
3098                            const wid = this.dataset.widgetId;
3099                            if (wid) {
3100                                try { hcaptcha.reset(Number(wid)); } catch {}
3101                            }
3102                        });
3103                    }
3104
3105                    // FriendlyCaptcha
3106                    if (typeof friendlycaptcha !== 'undefined' && friendlycaptcha?.widget) {
3107                        $content.find('.frc-captcha').each(function () {
3108                            const stored = $(this).data('frc-widget');
3109                            if (stored?.reset) {
3110                                try { stored.reset(); } catch {}
3111                            }
3112                        });
3113                    }
3114
3115                    // Arkose Labs
3116                    if (window?.arkose?.reset || typeof ECArkose !== 'undefined') {
3117                        const $arkoseEls = $content.find('[data-arkose-public-key], .arkose-enforcement');
3118                        if ($arkoseEls.length) {
3119                            try {
3120                                window?.arkose?.reset?.();
3121                                ECArkose?.reset?.();
3122                            } catch {}
3123                        }
3124                    }
3125
3126                    // GeeTest
3127                    if (typeof initGeetest !== 'undefined' || typeof GeetInit !== 'undefined') {
3128                        $content.find('.geetest_holder, .geetest_panel').each(function () {
3129                            const inst = this.geetestInstance;
3130                            if (inst?.reset) {
3131                                try { inst.reset(); } catch {}
3132                            }
3133                        });
3134                    }
3135
3136                } catch (err) {}
3137            }, delay);
3138        };
3139
3140        return Module;
3141
3142    }(FOXIZ_MAIN_SCRIPT || {}, jQuery)
3143)
3144
3145/** init */
3146jQuery(document).ready(function ($) {
3147    FOXIZ_MAIN_SCRIPT.init();
3148});
3149
3150/** Elementor editor */
3151jQuery(window).on('elementor/frontend/init', function () {
3152
3153    if (typeof elementorFrontend !== 'undefined' && typeof elementorFrontend.isEditMode === 'function' && elementorFrontend.isEditMode()) {
3154        FOXIZ_MAIN_SCRIPT.isElementorEditor = true;
3155        FOXIZ_MAIN_SCRIPT.editorDarkModeInit = false;
3156
3157        elementorFrontend.hooks.addAction('frontend/element_ready/widget', FOXIZ_MAIN_SCRIPT.initElementor);
3158    }
3159});

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.