PageSourceSearch

https://diakonie-heidenheim.de/templates/gridbox/js/gridbox.js?2.20.3.1

js diakonie-heidenheim.de collected 2026-10-08 07:19:56 UTC 55,295 bytes, 1,499 lines download raw bytes

1/**
2* @package   Gridbox template
3* @author    Balbooa http://www.balbooa.com/
4* @copyright Copyright @ Balbooa
5* @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
6*/
7
8class GridboxCaptcha {
9    static captcha = null;
10    static loaded = false;
11    static type = '';
12    static queue = [];
13    static data = {};
14
15    static setCaptcha(captcha) {
16        this.captcha = captcha;
17        this.loaded = true;
18        this.init();
19    }
20
21    static check(id) {
22        return app.items[id] && app.items[id].recaptcha == this.type;
23    }
24
25    static init() {
26        this.queue.forEach(element => {
27            this.create(element);
28        });
29    }
30
31    static create(element) {
32        if (element.rendered) {
33            return;
34        }
35
36        this.set(element);
37    }
38
39    static set(element) {
40        const div = document.createElement('div');
41        div.id = `gridbox-recaptcha-${Date.now()}`;
42        div.className = 'gridbox-recaptcha';
43        div.dataset.captcha = this.type;
44        element.append(div);
45        this.render(div);
46        element.rendered = true;
47    }
48
49    static render(div) {
50        throw new Error('Implement method render in child class')
51    }
52
53    static getSetting(key) {
54        return window.gridboxCaptchaSettings[key] ?? '';
55    }
56
57    static async getResponse(id, element) {
58        return '';
59    }
60
61    static reset(id) {
62
63    }
64}
65
66class GridboxGoogleRecaptcha extends GridboxCaptcha {
67    static type = 'recaptcha';
68
69    static async getResponse(id, element) {
70        const token = await this.captcha.execute(this.getSetting('public_key'), {
71            action: 'submit'
72        });
73        element.innerHTML = `<input type="hidden" name="g-recaptcha-response" value="${token}">`;
74
75        return token;
76    }
77
78    static render(div) {
79        GridboxCaptcha.data[div.id] = this.captcha.render(div, {
80            sitekey: this.getSetting('public_key'),
81            theme: this.getSetting('theme'),
82            size: this.getSetting('size'),
83            callback: GridboxCaptchaHelper.clearAlerts
84        });
85    }
86}
87
88class GridboxInvisibleRecaptcha extends GridboxGoogleRecaptcha {
89    static type = 'recaptcha_invisible';
90
91    static render(div) {
92        GridboxCaptcha.data[div.id] = this.captcha.render(div, {
93            sitekey: this.getSetting('public_key'),
94            badge: this.getSetting('badge'),
95            size: 'invisible',
96            callback: GridboxCaptchaHelper.clearAlerts
97        });
98        this.captcha.execute(GridboxCaptcha.data[div.id]);
99    }
100}
101
102class GridboxTurnstileCaptcha extends GridboxCaptcha {
103    static type = 'turnstile';
104
105    static async getResponse(id, element) {
106        return !this.captcha.isExpired(id) ? this.captcha.getResponse(id) : '';
107    }
108
109    static render(div) {
110        GridboxCaptcha.data[div.id] = this.captcha.render(div, {
111            sitekey: this.getSetting('site_key'),
112            theme: this.getSetting('theme'),
113            size: this.getSetting('size'),
114            callback: GridboxCaptchaHelper.clearAlerts
115        });
116    }
117
118    static reset(id) {
119        const widgetId = GridboxCaptcha.data[id];
120        this.captcha.reset(widgetId);
121    }
122}
123
124class GridboxCaptchaFactory {
125    /** @type {Object<string, typeof GridboxCaptcha>} */
126    static map = {
127        turnstile: GridboxTurnstileCaptcha,
128        recaptcha: GridboxGoogleRecaptcha,
129        recaptcha_invisible: GridboxInvisibleRecaptcha
130    }
131
132    /** @param {string} key */
133    static has(key) {
134        return key in this.map;
135    }
136
137    /**
138     * @param {string} key
139     * @returns {typeof GridboxCaptcha}
140     */
141    static get(key) {
142        return this.map[key];
143    }
144}
145
146class GridboxCaptchaHelper {
147
148    static factory = GridboxCaptchaFactory;
149
150    static getIfExist(element) {
151        const captcha = element.dataset.type;
152        if (!this.factory.has(captcha)) {
153            return null;
154        }
155
156        return this.factory.get(captcha)
157    }
158
159    static createIfExist(element) {
160        const captcha = this.getIfExist(element);
161        if (!captcha) {
162            return;
163        }
164
165        if (!captcha.loaded) {
166            captcha.queue.push(element);
167            return;
168        }
169
170        captcha.create(element);
171    }
172
173    static async #isValidResponse(element) {
174        if (!this.factory.has(element.dataset.captcha)) {
175            return false;
176        }
177
178        const widgetId = GridboxCaptcha.data[element.id];
179        const captcha = this.factory.get(element.dataset.captcha);
180        const response = await captcha.getResponse(widgetId, element);
181
182        return response != '';
183    }
184
185    static async checkResponse(element) {
186        if (!element) {
187            return true;
188        }
189
190        const recaptcha = element.querySelector('.gridbox-recaptcha');
191        if (!recaptcha) {
192            return false;
193        }
194
195        return await this.#isValidResponse(recaptcha);
196    }
197
198    static clearAlerts() {
199        const instance = 'login' in app ? app.login : app.checkoutForm;
200        if (!instance) {
201            return;
202        }
203
204        document.querySelectorAll('.gridbox-recaptcha').forEach(element => {
205            instance.removeAlertTooltip(element);
206        });
207    }
208
209    static setCaptcha(type, captcha) {
210        const instance = GridboxCaptchaHelper.factory.get(type);
211        instance.setCaptcha(captcha);
212        instance.loaded = true;
213    }
214}
215
216function gridboxTurnstileOnload() {
217    GridboxCaptchaHelper.setCaptcha('turnstile', turnstile);
218}
219
220function gridboxRecaptchaOnload() {
221    GridboxCaptchaHelper.setCaptcha('recaptcha', grecaptcha);
222}
223
224function gridboxInvisibleRecaptchaOnload() {
225    GridboxCaptchaHelper.setCaptcha('recaptcha_invisible', grecaptcha);
226}
227
228if (window.integrations && window.integrations.facebook) {
229    window.fbAsyncInit = () => {
230        app.facebook.initialize();
231    }
232}
233
234var $g = jQuery,
235    delay = '',
236    itemsInit = [],
237    app = {
238        hash: window.location.hash,
239        view : 'desktop',
240        modules : {},
241        loading : {},
242        edit : {},
243        items : {},
244        isExternal: function(link){
245            return link.indexOf('https://') != -1 || link.indexOf('http://') != -1;
246        },
247        facebook: {
248            load: () => {
249                app.loading.facebook = true;
250                let js = document.createElement('script');
251                if (document.getElementById('facebook-jssdk')) return;
252                js.id = 'facebook-jssdk';
253                js.src = "https://connect.facebook.net/en_US/sdk.js";
254                js.crossorigin = 'anonymous';
255                document.head.append(js);
256            },
257            initialize: () => {
258                FB.init({
259                    appId : window.integrations.facebook,
260                    autoLogAppEvents : true,
261                    xfbml : true,
262                    version : 'v25.0'
263                });
264            },
265            getUserInfo: (response) => {
266                return new Promise((resolve, reject) => {
267                    if (response.status === 'connected') {
268                        FB.api('/'+response.authResponse.userID+'/?fields=id,name,email,picture', 'GET', {}, (fields) => {
269                            let data = {
270                                    name: fields.name,
271                                    email: fields.email,
272                                    avatar: fields.picture.data.url,
273                                    id: fields.id
274                                }
275                            resolve(data);
276                        });
277                    }
278                });
279            }
280        },
281        google: {
282            load: (callback, selector, options) => {
283                let js = document.createElement('script');
284                js.src = 'https://accounts.google.com/gsi/client'
285                js.onload = () => {
286                    app.google.initialize(callback, selector, options);
287                }
288                document.head.append(js);
289            },
290            initialize: (callback, selector, options) => {
291                google.accounts.id.initialize({
292                    client_id: window.integrations.google,
293                    callback: callback
294                });
295                setTimeout(() => {
296                    document.querySelectorAll(selector).forEach((parent) => {
297                        google.accounts.id.renderButton(parent, options);
298                    });
299                }, 1000);
300            },
301            renderButton: (selector, options) => {
302                document.querySelectorAll(selector).forEach((parent) => {
303                    google.accounts.id.renderButton(parent, options);
304                });
305            },
306            JSONWebToken: (token) => {
307                let url = token.split('.')[1],
308                    base = url.replace(/-/g, '+').replace(/_/g, '/'),
309                    json = decodeURIComponent(window.atob(base).split('').map(function(c) {
310                        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
311                    }).join(''));
312
313                return JSON.parse(json);
314            },
315            getUserInfo: function(profile){
316                let data = {
317                        name: profile.name,
318                        email: profile.email,
319                        avatar: profile.picture,
320                        id: profile.sub
321                    }
322
323                return data;
324            }
325        },
326        decimalAdjust: function(type, value, exp){
327            if (typeof exp === 'undefined' || +exp === 0) {
328                return Math[type](value);
329            }
330            value = +value;
331            exp = +exp;
332            if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
333                return NaN;
334            }
335            value = value.toString().split('e');
336            value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
337            value = value.toString().split('e');
338
339            return +(value[0]+'e'+(value[1] ? (+value[1] + exp) : exp));
340        },
341        strrev: function(string){
342            let ret = '', i = 0;
343            for (i = string.length - 1; i >= 0; i--) {
344                ret += string[i];
345            }
346
347            return ret;
348        },
349        renderPrice: function(value, thousand, separator, decimals, rate){
350            rate = !rate ? 1 : rate;
351            value *= rate;
352            value = app.decimalAdjust('round', value, decimals * -1);
353            value = String(value);
354            let delta = value < 0 ? '-' : '',
355                priceArray = value.replace('-', '').trim().split('.'),
356                priceThousand = priceArray[0],
357                priceDecimal = priceArray[1] ? priceArray[1] : '',
358                price = '';
359            if (priceThousand.length > 3 && thousand != '') {
360                for (let i = 0; i < priceThousand.length; i++) {
361                    if (i % 3 == 0 && i != 0) {
362                        price += thousand;
363                    }
364                    price += priceThousand[priceThousand.length - 1 - i];
365                }
366                price = app.strrev(price);
367            } else {
368                price += priceThousand;
369            }
370            if (decimals != 0) {
371                price += separator;
372                for (let i = 0; i < decimals; i++) {
373                    price += priceDecimal[i] ? priceDecimal[i] : '0';
374                }
375            }
376
377            return delta+price;
378        },
379        getObject: function(key){
380            var object = $g.extend(true, {}, app.items[key].desktop);
381            if (app.view != 'desktop') {
382                for (var ind in breakpoints) {
383                    if (!app.items[key][ind]) {
384                        app.items[key][ind] = {};
385                    }
386                    object = $g.extend(true, {}, object, app.items[key][ind]);
387                    if (ind == app.view) {
388                        break;
389                    }
390                }
391            }
392
393            return object;
394        },
395        hideNotice:function(){
396            app.notification.classList.remove('notification-in');
397            app.notification.classList.add('animation-out');
398        },
399        checkOverlay: function(obj, key){
400            $g('.ba-item-overlay-section').each(function(){
401                $g(this).find('.ba-overlay-section-backdrop').appendTo(document.body);
402            });
403        },
404        _: function(key){
405            return gridboxLanguage[key] ?? key;
406        },
407        checkGridboxPaymentError: function(){
408            let gridbox_payment_error = localStorage.getItem('gridbox_payment_error');
409            if (gridbox_payment_error) {
410                app.showNotice(gridbox_payment_error, 'ba-alert');
411                localStorage.removeItem('gridbox_payment_error');
412            }
413        },
414        loadNotice: function(){
415            return new Promise(function(resolve, reject) {
416                fetch(JUri+'components/com_gridbox/libraries/css/plugins/notification.css').then(function(request){
417                    return request.text();
418                }).then(function(text){
419                    let style = document.createElement('style');
420                    document.head.append(style);
421                    style.innerHTML = text;
422                    app.notification = document.createElement('div');
423                    app.notification.id = 'ba-notification';
424                    app.notification.innerHTML = '<i class="zmdi zmdi-close"></i><h4>'+app._('ERROR')+'</h4><p></p>';
425                    app.notification.querySelector('.zmdi-close').addEventListener('click', function(){
426                        app.hideNotice();
427                    });
428                    document.body.appendChild(app.notification);
429                    resolve();
430                });
431            });
432        },
433        showNotice: function(message, className){
434            if (!app.notification) {
435                app.loadNotice().then(() => {
436                    app.showNotice(message, className);
437                });
438                return false;
439            }
440            app.notification.showCallback = function(){};
441            if (!className) {
442                className = '';
443            }
444            if (app.notification.classList.contains('notification-in')) {
445                app.notification.showCallback = function(){
446                    app.notification.showCallback = function(){};
447                    app.addNoticeText(message, className);
448                };
449            } else {
450                app.addNoticeText(message, className);
451            }
452        },
453        addNoticeText: function(message, className){
454            var time = 3000;
455            if (className == 'ba-alert') {
456                time = 6000;
457            }
458            app.notification.querySelector('p').innerHTML = message;
459            if (className) {
460                app.notification.classList.add(className);
461            } else {
462                app.notification.classList.remove('ba-alert');
463            }
464            app.notification.classList.remove('animation-out')
465            app.notification.classList.add('notification-in');
466            clearTimeout(app.notification.hideDelay);
467            app.notification.hideDelay = setTimeout(function(){
468                app.hideNotice();
469                setTimeout(function(){
470                    if (className) {
471                        app.notification.classList.remove(className);
472                    }
473                    app.notification.showCallback();
474                }, 400);
475            }, time);
476        },
477        disabledAnimation: {
478            'sticky-header': true,
479            'lightbox': true
480        },
481        checkAnimation: function(){
482            app.viewportItems = [];
483            app.motionItems = [];
484            $g('.ba-section, .ba-row, .ba-grid-column').each(function(){
485                if (!app.items[this.id]) {
486                    return;
487                }
488                let object = $g.extend(true, {}, app.items[this.id].desktop.animation);
489                let motion = $g.extend(true, {}, app.items[this.id].desktop.motions ?? {});
490                let inMotion = false;
491                const canAnimate = !app.disabledAnimation[app.items[this.id].type];
492                const motions = {
493                    desktop: motion
494                };
495                if (app.view != 'desktop') {
496                    for (let ind in breakpoints) {
497                        if (!app.items[this.id][ind]) {
498                            app.items[this.id][ind] = {
499                                animation : {}
500                            }
501                        }
502                        object = $g.extend(true, {}, object, app.items[this.id][ind].animation);
503                        if (ind == app.view) {
504                            break;
505                        }
506                    }
507                }
508                for (let ind in breakpoints) {
509                    if (!app.items[this.id][ind]) {
510                        app.items[this.id][ind] = {
511                            animation : {}
512                        }
513                    }
514                    motion = $g.extend(true, {}, motion, app.items[this.id][ind]?.motions ?? motion);
515                    motions[ind] = motion;
516                }
517                if (object.effect && canAnimate) {
518                    app.viewportItems.push({
519                        animation: object,
520                        item: $g(this)
521                    });
522                } else if (!object.effect && canAnimate && $g(this).viewportChecker) {
523                    $g(this).viewportChecker(object)
524                } else if (object.effect) {
525                    this.classList.add('visible');
526                }
527                for (let ind in motions) {
528                    for (let key in motions[ind]) {
529                        if (motions[ind][key].enable) {
530                            app.motionItems.push({
531                                motions: motions,
532                                item: $g(this)
533                            });
534                            inMotion = true;
535                            break;
536                        }
537                    }
538                    if (inMotion) {
539                        break;
540                    }
541                }
542                if ($g(this).motion && !inMotion) {
543                    $g(this).motion(motions);
544                }
545            });
546            $g('.ba-item').each(function(){
547                if (app.items[this.id] && app.items[this.id].desktop && app.items[this.id].desktop.appearance) {
548                    let object = $g.extend(true, {}, app.items[this.id].desktop.appearance),
549                        motion = app.items[this.id].desktop.motions ? $g.extend(true, {}, app.items[this.id].desktop.motions) : {},
550                        inMotion = false,
551                        motions = {
552                            desktop: motion
553                        };
554                    if (app.view != 'desktop') {
555                        for (let ind in breakpoints) {
556                            if (!app.items[this.id][ind]) {
557                                app.items[this.id][ind] = {
558                                    appearance : {}
559                                };
560                            }
561                            object = $g.extend(true, {}, object, app.items[this.id][ind].appearance);
562                            if (ind == app.view) {
563                                break;
564                            }
565                        }
566                    }
567                    for (let ind in breakpoints) {
568                        motion = app.items[this.id][ind].motions ? $g.extend(true, {}, motion, app.items[this.id][ind].motions) : motion;
569                        motions[ind] = motion;
570                    }
571                    if (object.effect) {
572                        app.viewportItems.push({
573                            animation: object,
574                            item: $g(this)
575                        });
576                    } else if (!object.effect && $g(this).viewportChecker) {
577                        $g(this).viewportChecker(object)
578                    } else if (object.effect) {
579                        this.classList.add('visible');
580                    }
581                    for (let ind in motions) {
582                        for (let key in motions[ind]) {
583                            if (motions[ind][key].enable) {
584                                app.motionItems.push({
585                                    motions: motions,
586                                    item: $g(this)
587                                });
588                                inMotion = true;
589                                break;
590                            }
591                        }
592                        if (inMotion) {
593                            break;
594                        }
595                    }
596                    if ($g(this).motion && !inMotion) {
597                        $g(this).motion(motions);
598                    }
599                }
600            });
601            if (app.viewportItems.length > 0 || app.motionItems.length > 0) {
602                app.checkModule('loadAnimations');
603            }
604        },
605        checkModule : function(name, obj){
606            if (name == 'loadVideoApi' && app.modules[name] && obj && obj.data.type != 'youtube+vimeo'
607                && app.modules[name].data.type != 'youtube+vimeo' && app.modules[name].data.type != obj.data.type) {
608                obj.data.type = 'youtube+vimeo';
609            } else if (typeof(obj) != 'undefined') {
610                app.modules[name] = obj;
611            }
612            if (typeof(app[name]) == 'undefined' && !app.loading[name]) {
613                app.loading[name] = true;
614                app.loadModule(name);
615            } else if (typeof(app[name]) != 'undefined') {
616                if (typeof(obj) != 'undefined') {
617                    app[name](obj.data, obj.selector);
618                } else {
619                    app[name]();
620                }
621            }
622        },
623        checkVideoBackground : function(){
624            let flag = false;
625            $g('.ba-section, .ba-row, .ba-grid-column').each(function(){
626                if (app.items[this.id] && app.items[this.id].desktop.background.type == 'video') {
627                    flag = true;
628                    return false;
629                }
630            });
631            $g('.ba-item-flipbox').each(function(){
632                if (app.items[this.id] && app.items[this.id].sides.frontside.desktop.background
633                    && app.items[this.id].sides.frontside.desktop.background.type == 'video') {
634                    flag = true;
635                    return false;
636                }
637                if (app.items[this.id] && app.items[this.id].sides.backside.desktop.background
638                    && app.items[this.id].sides.backside.desktop.background.type == 'video') {
639                    flag = true;
640                    return false;
641                }
642            });
643            if (app.theme.desktop.background.type == 'video') {
644                flag = true;
645            }
646            if (flag) {
647                app.checkModule('createVideo', {});
648            }
649        },
650        loadModule : function(key){
651            if (key != 'setCalendar' && key != 'defaultElementsStyle' && key != 'gridboxLanguage' &&
652                key != 'shapeDividers' && key != 'presetsPatern') {
653                var script = document.createElement('script');
654                script.src = JUri+'components/com_gridbox/libraries/modules/'+key+'.js?'+gridboxVersion;
655                document.head.append(script);
656                return false;
657            }
658            $g.ajax({
659                type:"POST",
660                dataType:'text',
661                url:"index.php?option=com_gridbox&task=editor.loadModule&module="+key+"&"+gridboxVersion,
662                data:{
663                    module : key
664                },
665                complete: function(msg){
666                    let script = document.createElement('script');
667                    document.head.append(script);
668                    script.innerHTML = msg.responseText;
669                }
670            });
671        },
672        checkView: function(){
673            var width = $g(window).width();
674            app.view = 'desktop';
675            for (var ind in breakpoints) {
676                if (width <= breakpoints[ind]) {
677                    app.view = ind;
678                }
679            }
680        },
681        resize: function(){
682            clearTimeout(delay);
683            app.checkView();
684            delay = setTimeout(function(){
685                if ('setPostMasonryHeight' in window) {
686                    $g('.ba-blog-posts-wrapper.ba-masonry-layout').each(function(){
687                        var key = $g(this).closest('.ba-item').attr('id');
688                        setPostMasonryHeight(key);
689                    });
690                }
691                if ('setGalleryMasonryHeight' in window) {
692                    $g('.gridbox-gallery-wrapper.simple-gallery-masonry-layout').each(function(){
693                        setGalleryMasonryHeight(this.closest('.ba-item').id);
694                    });
695                }
696            }, 300);
697        },
698        checkCommentInTabs: function(hash){
699            $g('a.'+hash.replace('#', '')).first().each(function(){
700                let tab = this.closest('.tab-pane, .accordion-body');
701                if (tab && !tab.classList.contains('active') && !tab.classList.contains('in')) {
702                    $g('a[href="#'+tab.id+'"]').trigger('click');
703                }
704            });
705        },
706        gridboxLoaded: function(){
707            app.checkView();
708            app.checkAnimation();
709            checkOnePage();
710            $g(window).on('resize', app.resize);
711            if (!$g('body').hasClass('gridbox')) {
712                $g(window).on('scroll.onepage', checkOnePageActive);
713            }
714            $g(window).on('scroll', function(){
715                var top = window.pageYOffset;
716                if (!('lastPageYOffset' in window)) {
717                    window.lastPageYOffset = top;
718                }
719                $g('header')[top > 40 ? 'addClass' : 'removeClass']('fixed-header');
720                $g('.ba-sticky-header').each(function(){
721                    this.closest('header, footer, .body').classList.add('ba-sticky-header-parent');
722                    if (this.querySelector('.ba-sticky-header > .ba-section')) {
723                        var section = this.querySelector('.ba-sticky-header > .ba-section'),
724                            obj = app.items[section.id],
725                            offset = obj.desktop.offset;
726                        if (app.view != 'desktop') {
727                            for (var ind in breakpoints) {
728                                if (!obj[ind]) {
729                                    obj[ind] = {};
730                                }
731                                offset = obj[ind].offset ? obj[ind].offset : offset;
732                                if (ind == app.view) {
733                                    break;
734                                }
735                            }
736                        }
737                        if (!this.classList.contains('visible-sticky-header')) {
738                            if (top >= offset * 1 &&
739                                (!obj.scrollup || (obj.scrollup && top - window.lastPageYOffset < 0))) {
740                                this.classList.add('visible-sticky-header');
741                                document.body.classList.add('sticky-header-opened');
742                                if (obj.desktop.animation.effect) {
743                                    section.classList.add(obj.desktop.animation.effect);
744                                    setTimeout(function(){
745                                        section.classList.remove(obj.desktop.animation.effect);
746                                    }, obj.desktop.animation.delay * 1000 + obj.desktop.animation.duration * 1000);
747                                }
748                                $g(window).trigger('scroll');
749                            }
750                        }
751                        if ((top < offset * 1 && !obj.scrollup) || (obj.scrollup && (top - window.lastPageYOffset > 0 || top <= offset * 1))) {
752                            this.classList.remove('visible-sticky-header');
753                            document.body.classList.remove('sticky-header-opened');
754                        }
755                    }
756                });
757                window.lastPageYOffset = top;
758            });
759            $g(window).trigger('scroll');
760            $g('.ba-item [contenteditable]').removeAttr('contenteditable');
761            if ($g('.ba-item-overlay-section').length > 0) {
762                app.checkModule('checkOverlay');
763            }
764            $g('.ba-item-main-menu, .ba-item-one-page-menu, .ba-item-overlay-section').each(function(){
765                if (app.items[this.id]) {
766                    var obj = {
767                        data : app.items[this.id],
768                        selector : this.id
769                    };
770                    itemsInit.push(obj);
771                }
772            });
773            $g('.ba-item').not('.ba-item-main-menu, .ba-item-one-page-menu, .ba-item-overlay-section').each(function(){
774                if (app.items[this.id]) {
775                    var obj = {
776                        data : app.items[this.id],
777                        selector : this.id
778                    };
779                    itemsInit.push(obj);
780                }
781            });
782            if (itemsInit.length > 0) {
783                itemsInit.reverse();
784                app.checkModule('initItems', itemsInit.pop());
785            }
786            app.checkVideoBackground();
787            $g('.ba-lightbox-backdrop').on('keyup', function(event){
788                if (event.key == 'Escape') {
789                    $g(this).find('.ba-lightbox-close').first().click();
790                }
791            }).find('.ba-lightbox-close').on('click keyup', function(event){
792                app.AccessibilityHelper.processAction(event, () => {
793                    const lightbox = this.closest('.ba-lightbox-backdrop');
794                    lightboxVideoClose(lightbox);
795                    lightbox.classList.remove('visible-lightbox');
796                    app.AccessibilityHelper.releaseTrap(lightbox.querySelector('.ba-wrapper'));
797                    document.body.classList.remove('lightbox-open');
798                });
799            });
800            $g('.ba-lightbox-backdrop').each(function(){
801                let obj = app.items[this.dataset.id];
802                if (obj.type == 'cookies' || !obj.session.enable) {
803                    initLightbox(this, obj);
804                } else {
805                    let flag = true;
806                    if (localStorage[this.dataset.id]) {
807                        let date =  new Date().getTime(),
808                            expires = new Date(localStorage[this.dataset.id]);
809                        expires.getTime();
810                        if (date >= expires) {
811                            flag = true;
812                            localStorage.removeItem(this.dataset.id);
813                        } else {
814                            flag = false;
815                        }
816                    }
817                    if (flag) {
818                        let expiration = new Date();
819                        expiration.setDate(expiration.getDate() + obj.session.duration * 1);
820                        localStorage.setItem(this.dataset.id, expiration);
821                        initLightbox(this, obj);
822                    }
823                }
824            });
825            $g('.ba-section, .ba-row, .ba-grid-column').each(function(){
826                if (app.items[this.id] && app.items[this.id].parallax && app.items[this.id].parallax.enable) {
827                    app.checkModule('loadParallax');
828                    return false;
829                }
830            });
831            if (document.querySelector('.open-calendar-dialog')) {
832                app.loadModule('calendar');
833            }
834        }
835    };
836
837app.fetch = async function(url, data, isFile) {
838    const module = await import(`${JUri}components/com_gridbox/assets/modules/Request.js`)
839
840    return await module.default.post(url, data, isFile);
841}
842
843app.getFormData = async function(data, isFile) {
844    const module = await import(`${JUri}components/com_gridbox/assets/modules/Request.js`)
845
846    return await module.default.getBody(data, isFile);
847}
848
849app.preloaded = {
850    total: 0,
851    loaded: 0,
852    loadGridbox: function(){
853        app.lazyLoad ? app.lazyLoad.check() : '';
854        app.preloaded.end = true;
855        app.gridboxLoaded();
856    },
857    callback: function(){
858        app.preloaded.loaded++;
859        if (app.preloaded.total <= app.preloaded.loaded && !app.preloaded.end && document.readyState != 'loading') {
860            app.preloaded.loadGridbox();
861        }
862    }
863}
864
865document.querySelectorAll('link[rel="preload"][as="style"]').forEach(function(link){
866    link.onload = app.preloaded.callback;
867    link.onerror = app.preloaded.callback;
868    app.preloaded.total++;
869});
870
871class CustomSelect {
872    constructor(element)
873    {
874        this.$select = $g(element);
875        this.$textInput = this.$select.find('input[type="text"]');
876        this.$hiddenInput = this.$select.find('input[type="hidden"]');
877        this.$list = this.$select.find('ul');
878
879        this.currentIndex = -1;
880
881        this.setupAria();
882        this.attachEvents();
883    }
884
885    getOptions()
886    {
887        return this.$list.find('li');
888    }
889
890    setupAria()
891    {
892        const listId = 'listbox-' + Math.random().toString(36).substr(2, 6);
893
894        this.$select.attr({
895            'role': 'combobox',
896            'aria-haspopup': 'listbox',
897            'aria-expanded': 'false',
898        });
899
900        this.$list.attr({
901            'role': 'listbox',
902            'tabindex': '-1',
903            'id': listId
904        });
905
906        this.$textInput.attr({
907            'readonly': 'true',
908            'aria-controls': listId
909        });
910    }
911
912    attachEvents()
913    {
914        this.$select.on('click', 'i, input', () => {
915            if (!this.$list.hasClass('visible-select')) {
916                setTimeout(() => this.openList(), 100);
917            }
918        });
919
920        this.$select.on('click', 'li', (event) => {
921            const index = this.getOptions().index(event.currentTarget);
922            this.selectOption(index);
923        });
924
925        this.$select.on('keydown', (e) => this.handleKeydown(e));
926    }
927
928    openList()
929    {
930        const options = this.getOptions();
931        this.$list.addClass('visible-select');
932        this.$select.attr('aria-expanded', 'true');
933
934        options.removeClass('focused');
935
936        const selectedIndex = options.index(options.filter('.selected'));
937        this.currentIndex = selectedIndex >= 0 ? selectedIndex : 0;
938
939        if (options.length > 0) {
940            options.eq(this.currentIndex).addClass('focused');
941        }
942
943        this.$select.trigger('show');
944    }
945
946    closeList()
947    {
948        this.$list.removeClass('visible-select');
949        this.$select.attr('aria-expanded', 'false');
950        this.getOptions().removeClass('focused');
951    }
952
953    selectOption(index)
954    {
955        const options = this.getOptions();
956        const $opt = options.eq(index);
957
958        options.removeClass('selected');
959        $opt.addClass('selected');
960
961        this.$textInput.val($opt.text().trim());
962        this.$hiddenInput.val($opt.data('value')).trigger('change');
963
964        this.currentIndex = index;
965
966        this.$select.trigger('customAction');
967        this.closeList();
968    }
969
970    handleKeydown(e)
971    {
972        const options = this.getOptions();
973        if (options.length === 0) return;
974
975        if (e.key === ' ' || e.key === 'Enter') {
976            e.preventDefault();
977            if (!this.$list.hasClass('visible-select')) {
978                this.openList();
979            } else {
980                this.selectOption(this.currentIndex);
981            }
982        } else if (e.key === 'ArrowDown') {
983            e.preventDefault();
984            if (!this.$list.hasClass('visible-select')) {
985                this.openList();
986            } else {
987                this.currentIndex = (this.currentIndex + 1) % options.length;
988                this.updateFocus();
989            }
990        } else if (e.key === 'ArrowUp') {
991            e.preventDefault();
992            if (!this.$list.hasClass('visible-select')) {
993                this.openList();
994            } else {
995                this.currentIndex = (this.currentIndex - 1 + options.length) % options.length;
996                this.updateFocus();
997            }
998        } else if (e.key === 'Escape') {
999            this.closeList();
1000        }
1001    }
1002
1003    updateFocus()
1004    {
1005        const options = this.getOptions();
1006        options.removeClass('focused');
1007        options.eq(this.currentIndex).addClass('focused');
1008    }
1009
1010    static initAll(selector = '.ba-custom-select')
1011    {
1012        $g(selector).each(function () {
1013            new CustomSelect(this);
1014        });
1015    }
1016}
1017
1018document.addEventListener("DOMContentLoaded", function(){
1019    $g('link[rel="preload"][as="style"]').attr('rel', 'stylesheet');
1020    document.body.style.opacity = '';
1021    document.body.style.overflow = '';
1022    document.body.style.margin = '';
1023    let preloader = document.querySelector('.ba-item-preloader');
1024    if (preloader) {
1025        setTimeout(function(){
1026            preloader.classList.add('preloader-animation-out');
1027            app.checkGridboxPaymentError();
1028        }, preloader.dataset.delay * 1000);
1029    } else {
1030        app.checkGridboxPaymentError();
1031    }
1032    if ('setPostMasonryHeight' in window) {
1033        $g('.ba-blog-posts-wrapper.ba-masonry-layout').each(function(){
1034            var key = $g(this).closest('.ba-item').attr('id');
1035            setPostMasonryHeight(key);
1036        });
1037    }
1038    if ('setGalleryMasonryHeight' in window) {
1039        $g('.gridbox-gallery-wrapper.simple-gallery-masonry-layout').each(function(){
1040            setGalleryMasonryHeight(this.closest('.ba-item').id);
1041        });
1042    }
1043    if (app.hash == '#total-count-wrapper' || app.hash == '#total-reviews-count-wrapper') {
1044        let item = $g('a.'+app.hash.replace('#', ''));
1045        app.checkCommentInTabs(app.hash);
1046        app.scrollIntoView(item);
1047    }
1048    $g('body').on('click', function(){
1049        $g('.visible-select').removeClass('visible-select');
1050        if (app.storeSearch && app.storeSearch.visible) {
1051            app.storeSearch.clearSearch();
1052        }
1053    }).on('hide', '.modal', function(){
1054        this.classList.add('ba-modal-close');
1055        setTimeout(function(){
1056            $g('.ba-modal-close').removeClass('ba-modal-close');
1057        }, 500);
1058    });
1059
1060    CustomSelect.initAll();
1061
1062    $g('.intro-post-reviews a, .intro-post-comments a').on('click', function(){
1063        let item = $g('a.'+this.hash.replace('#', ''));
1064        app.checkCommentInTabs(this.hash);
1065        app.scrollIntoView(item);
1066    });
1067    $g('li.megamenu-item').on('mouseenter', function(){
1068        var rectangle = this.getBoundingClientRect(),
1069            left = rectangle.left * -1,
1070            wrapper = $g(this).find(' > div.tabs-content-wrapper'),
1071            width = document.documentElement.clientWidth,
1072            maxwidth = width - rectangle.right;
1073        if (wrapper.hasClass('megamenu-center') && wrapper.hasClass('ba-container')) {
1074            left = $g(this).width() / 2;
1075        }
1076        if (rectangle.left < maxwidth) {
1077            maxwidth = rectangle.left;
1078        }
1079        if (!wrapper.hasClass('megamenu-center')) {
1080            maxwidth = width - rectangle.left;
1081        } else if (wrapper.hasClass('ba-container')) {
1082            left -= wrapper.outerWidth() / 2;
1083        }
1084        if (wrapper.hasClass('megamenu-center')) {
1085            maxwidth = (maxwidth + (rectangle.right - rectangle.left) / 2) * 2;
1086        }
1087        if ($g(this).closest('.ba-menu-wrapper').hasClass('vertical-menu')) {
1088            maxwidth = width - rectangle.right;
1089        }
1090        wrapper.css({
1091            'margin-left' : left+'px',
1092            'width' : width+'px',
1093            'max-width' : maxwidth+'px'
1094        });
1095    });
1096    $g('.ba-item-main-menu').closest('.ba-row').addClass('row-with-menu');
1097    for (var key in gridboxItems) {
1098        if (key != 'theme') {
1099            app.items = $g.extend(true, app.items, gridboxItems[key]);
1100        }
1101    }
1102    app.theme = gridboxItems.theme;
1103    if (app.preloaded.total == 0) {
1104        app.gridboxLoaded();
1105    } else if (app.preloaded.total <= app.preloaded.loaded && !app.preloaded.end) {
1106        app.preloaded.loadGridbox();
1107    }
1108});
1109
1110var lightboxVideo = {};
1111
1112function lightboxVideoClose(item)
1113{
1114    var iframes = item.querySelectorAll('.ba-item-custom-html iframe, .ba-item-video iframe');
1115    for (var i = 0; i < iframes.length; i++) {
1116        var src = iframes[i].src,
1117            videoId = iframes[i].id;
1118        if (src && src.indexOf('youtube.com') !== -1 && 'pauseVideo' in lightboxVideo[videoId]) {
1119            lightboxVideo[videoId].pauseVideo();
1120        } else if (src && src.indexOf('vimeo.com') !== -1 && 'pause' in lightboxVideo[videoId]) {
1121            lightboxVideo[videoId].pause();
1122        }
1123    }
1124    iframes = item.querySelectorAll('.ba-item-video video, .ba-item-custom-html video');
1125    for (var i = 0; i < iframes.length; i++) {
1126        var videoId = iframes[i].id;
1127        lightboxVideo[videoId].pause();
1128    }
1129}
1130
1131function lightboxVideoOpen(item)
1132{
1133    if (item.querySelectorAll('.video-lazy-load-thumbnail')) {
1134        $g(item).find('.video-lazy-load-thumbnail').trigger('click');
1135    }
1136    var iframes = item.querySelectorAll('.ba-item-custom-html iframe, .ba-item-video iframe'),
1137        youtube = false,
1138        vimeo = false,
1139        id = +new Date();
1140    for (var i = 0; i < iframes.length; i++) {
1141        var src = iframes[i].src,
1142            videoId;
1143        if (src && src.indexOf('youtube.com') !== -1) {
1144            if (!app.youtube) {
1145                youtube = true;
1146            } else {
1147                if (src.indexOf('enablejsapi=1') === -1) {
1148                    if (src.indexOf('?') === -1) {
1149                        src += '?';
1150                    } else {
1151                        src += '&'
1152                    }
1153                    src += 'enablejsapi=1';
1154                    iframes[i].src = src;
1155                }
1156                if (!iframes[i].id) {
1157                    iframes[i].id = id++;
1158                }
1159                videoId = iframes[i].id;
1160                if (!lightboxVideo[videoId] || !('playVideo' in lightboxVideo[videoId])) {
1161                    lightboxVideo[videoId] = new YT.Player(videoId, {
1162                        events: {
1163                            onReady: function(event){
1164                                lightboxVideo[videoId].playVideo();
1165                            }
1166                        }
1167                    });
1168                } else {
1169                    lightboxVideo[videoId].playVideo();
1170                }
1171            }
1172        } else if (src && src.indexOf('vimeo.com') !== -1) {
1173            if (!app.vimeo) {
1174                vimeo = true;
1175            } else {
1176                if (!iframes[i].id) {
1177                    iframes[i].id = id++;
1178                }
1179                videoId = iframes[i].id;
1180                if (!lightboxVideo[videoId] || !('play' in lightboxVideo[videoId])) {
1181                    src = src.split('/');
1182                    src = src.slice(-1);
1183                    src = src[0].split('?');
1184                    src = src[0];
1185                    var options = {
1186                        id: src * 1,
1187                        loop: true,
1188                    };
1189                    lightboxVideo[videoId] = new Vimeo.Player(videoId, options);
1190                }
1191                lightboxVideo[videoId].play();
1192            }
1193        }
1194    }
1195    iframes = item.querySelectorAll('.ba-item-video video, .ba-item-custom-html video');
1196    for (var i = 0; i < iframes.length; i++) {
1197        if (!iframes[i].id) {
1198            iframes[i].id = id++;
1199        }
1200        videoId = iframes[i].id;
1201        if (!lightboxVideo[videoId]) {
1202            lightboxVideo[videoId] = iframes[i];
1203        }
1204        lightboxVideo[videoId].play();
1205    }
1206    if (youtube || vimeo) {
1207        var object = {
1208            data : {}
1209        };
1210        if (youtube && !vimeo) {
1211            object.data.type = 'youtube';
1212        } else if (vimeo && !youtube) {
1213            object.data.type = 'vimeo';
1214        } else {
1215            object.data.type = 'youtube+vimeo';
1216        }
1217        app.checkModule('loadVideoApi', object);
1218    }
1219    if (youtube) {
1220        lightboxVideo.overlay = item;
1221    } else if (vimeo) {
1222        lightboxVideo.overlay = item;
1223    }
1224
1225    return !youtube && !vimeo;
1226}
1227
1228function initLightbox($this, obj)
1229{
1230    var obj = app.items[$this.dataset.id];
1231    if (obj.type == 'cookies') {
1232        if (localStorage['ba-item-cookie']) {
1233            return false;
1234        }
1235        $g($this).find('.ba-item-button[data-cookie="accept"]').on('click', function(event){
1236            event.preventDefault();
1237            localStorage.setItem('ba-item-cookie', 'accept');
1238            $g(this).closest('.ba-lightbox-backdrop').removeClass('visible-lightbox');
1239            $g('body').removeClass('lightbox-open');
1240        });
1241        showLightbox($this);
1242    } else if (obj.trigger.type == 'time-delay') {
1243        setTimeout(function(){
1244            showLightbox($this);
1245        }, obj.trigger.time);
1246    } else if (obj.trigger.type == 'scrolling') {
1247        lightboxScroll($this, obj.trigger.scroll * 1);
1248    } else if (obj.trigger.type == 'exit-intent') {
1249        $g(document).one('mouseleave.ba-lightbox'+$this.dataset.id, function(){
1250            showLightbox($this);
1251        });
1252    } else {
1253        lightboxScroll($this, 100);
1254    }
1255}
1256
1257function lightboxScroll($this, scroll)
1258{
1259    let top, docHeight, htmlHeight;
1260    $g(window).on('scroll.ba-lightbox'+$this.dataset.id+' load.ba-lightbox'+$this.dataset.id, function(){
1261        top = $g(window).scrollTop();
1262        docHeight = document.documentElement.clientHeight
1263        htmlHeight = Math.max(
1264            document.body.scrollHeight, document.documentElement.scrollHeight,
1265            document.body.offsetHeight, document.documentElement.offsetHeight,
1266            document.body.clientHeight, document.documentElement.clientHeight
1267        );
1268        let x = (docHeight + top) * 100 / htmlHeight;
1269        if (x >= scroll || (scroll > 97 && x >= 97)) {
1270            $g(window).off('scroll.ba-lightbox'+$this.dataset.id+' load.ba-lightbox'+$this.dataset.id);
1271            showLightbox($this);
1272        }
1273    });
1274}
1275
1276function showLightbox($this)
1277{
1278    const obj = app.getObject($this.dataset.id);
1279    if (!lightboxVideoOpen($this) || obj.disable == 1) {
1280        return false;
1281    }
1282    const section = $this.querySelector(':scope > .ba-wrapper > .ba-section')
1283    $this.querySelector('.close-lightbox .ba-lightbox-close')?.setAttribute('tabindex', 0);
1284    $this.classList.add('visible-lightbox');
1285
1286    if (obj.animation.effect) {
1287        section.classList.add(obj.animation.effect);
1288        setTimeout(function(){
1289            section.classList.remove(obj.animation.effect);
1290        }, obj.animation.delay * 1000 + obj.animation.duration * 1000);
1291    }
1292
1293    if (obj.position == 'lightbox-center') {
1294        document.body.classList.add('lightbox-open');
1295    }
1296    if (app.AccessibilityHelper) {
1297        app.AccessibilityHelper.trapFocus($this.querySelector('.ba-wrapper'), 350);
1298    }
1299}
1300
1301function compileOnePageValue(item)
1302{
1303    if (item.length == 0) {
1304        return 0;
1305    }
1306    var value = item.offset().top,
1307        header = $g('header.header'),
1308        comp = header[0] ? getComputedStyle(header[0]) : {},
1309        top = window.pageYOffset,
1310        stickies = $g('.ba-sticky-header'),
1311        sticky = 0;
1312    if (item.closest('.ba-wrapper').parent().hasClass('header')) {
1313        value = 0;
1314    } else {
1315        stickies.each(function(){
1316            if (this.offsetHeight > 0) {
1317                let section = this.querySelector('.ba-sticky-header > .ba-section'),
1318                    obj = app.items[section.id],
1319                    offset = obj ? obj.desktop.offset : 0;
1320                if (app.view != 'desktop') {
1321                    for (var ind in breakpoints) {
1322                        if (!obj[ind]) {
1323                            obj[ind] = {};
1324                        }
1325                        offset = obj[ind].offset ? obj[ind].offset : offset;
1326                        if (ind == app.view) {
1327                            break;
1328                        }
1329                    }
1330                }
1331                if (obj && ((!obj.scrollup && offset < value) || (obj.scrollup && offset < value && value < top))) {
1332                    sticky = this.offsetHeight > sticky ? this.offsetHeight : sticky;
1333                }
1334            }
1335        });
1336        if ((!header.hasClass('sidebar-menu') || (app.view != 'desktop' && app.view != 'laptop'))
1337            && comp.position == 'fixed') {
1338            sticky = header[0].offsetHeight > sticky ? header[0].offsetHeight : sticky;
1339            if (header.find('.resizing-header').length > 0) {
1340                var resizingSection = getComputedStyle(header.find('.resizing-header')[0]);
1341                value += resizingSection.paddingTop.replace('px', '') * 1;
1342                value += resizingSection.paddingBottom.replace('px', '') * 1;
1343            }
1344        }
1345        value -= sticky;
1346    }
1347
1348    return Math.ceil(value);
1349}
1350
1351function checkOnePage()
1352{
1353    var alias = location.hash.replace('#', '');
1354    alias = decodeURIComponent(alias);
1355    if (alias && document.querySelector('.main-menu a[data-alias="'+alias+'"]')) {
1356        $g('.main-menu a[data-alias="'+alias+'"]').each(function(){
1357            const id = (this.dataset.anchor || this.hash).replace('#', '');
1358            let item = $g('#' + id);
1359            if ($g(this.parentNode).height() > 0 && id && item.length > 0) {
1360                $g(this).closest('ul').find('.active').removeClass('active');
1361                $g('.main-menu ul.nav.menu').find(`a[href*="#${id}"], a[data-anchor="${id}"]`)
1362                    .parent().addClass('active');
1363                app.scrollIntoView(item);
1364                return false;
1365            }
1366        });
1367    } else if ((alias == 'total-reviews-count-wrapper' || alias == 'total-count-wrapper')
1368        && document.querySelector('a.'+alias)) {
1369        let item = $g('a.'+alias);
1370        app.scrollIntoView(item);
1371    } else {
1372         checkOnePageActive();
1373    }
1374}
1375
1376app.scrollIntoView = function(item){
1377    let value = compileOnePageValue(item);
1378    if (window.pageYOffset != value) {
1379        $g('html, body').stop().animate({
1380            'scrollTop' : value
1381        }, 1000);
1382    }
1383}
1384
1385window.onePageScroll = true;
1386
1387function checkOnePageActive()
1388{
1389    if (!window.onePageScroll) {
1390        return;
1391    }
1392    var items = [],
1393        alias = '',
1394        replace = null,
1395        flag = false;
1396    $g('.main-menu ul li a[data-alias]').each(function(){
1397        const id = this.dataset.anchor ? '#' + this.dataset.anchor : this.hash;
1398        if (this.offsetHeight > 0 && id && $g(id).height() > 0) {
1399            var computed = getComputedStyle(document.querySelector(id));
1400            if (computed.display != 'none') {
1401                items.push(this);
1402            }
1403        }
1404    });
1405    items.sort(function(item1, item2){
1406        var target1 = $g(item1.dataset.anchor ? '#' + item1.dataset.anchor : item1.hash),
1407            target2 = $g(item2.dataset.anchor ? '#' + item2.dataset.anchor : item2.hash),
1408            top1 = target1.closest('header.header').length == 0 ? target1.offset().top : 0,
1409            top2 = target2.closest('header.header').length == 0 ? target2.offset().top : 0;
1410        if (top1 > top2) {
1411            return 1;
1412        } else if (top1 < top2) {
1413            return -1;
1414        } else {
1415            return 0;
1416        }
1417    });
1418    let url = ''
1419    for (var i = items.length - 1; i >= 0; i--) {
1420        alias = items[i].dataset.alias;
1421        if (decodeURI(window.location.hash) == '#'+alias) {
1422            replace = location.href.replace(window.location.hash, '');
1423        }
1424        const id = (items[i].dataset.anchor || items[i].hash).replace('#', '')
1425        const item = $g('#' + id);
1426        let value = compileOnePageValue(item);
1427        if (value <= Math.ceil(window.pageYOffset) + 1) {
1428            flag = true;
1429            url = location.href.replace(window.location.hash, '')+'#'+alias;
1430            $g('.main-menu ul').find(`a[href*="#${id}"], a[data-anchor="${id}"]`)
1431                .closest('ul')
1432                .find('.active').removeClass('active current');
1433            $g('.main-menu ul').find(`a[href*="#${id}"], a[data-anchor="${id}"]`)
1434                .parent().addClass('active');
1435            break;
1436        }
1437    }
1438    if (!flag) {
1439        $g('.main-menu ul.nav.menu .active').removeClass('active');
1440        replace ? window.history.replaceState(null, null, replace) : '';
1441    } else if (decodeURI(window.location.hash) != '#'+alias) {
1442        window.history.replaceState(null, null, url);
1443    }
1444}
1445
1446window.addEventListener('resize', function(){
1447    document.documentElement.style.setProperty('--vh', window.innerHeight * 0.01+'px');
1448});
1449
1450jQuery(window).on('popstate.onepage', function(){
1451    window.onePageScroll = false;
1452    setTimeout(function(){
1453        window.onePageScroll = true;
1454    }, 300);
1455});
1456
1457/*
1458    Default joomla
1459*/
1460
1461document.addEventListener('DOMContentLoaded', function(){
1462    ImportHelper.resolve('AccessibilityHelper', '').then(module => {
1463        /** @type {typeof import('../../../components/com_gridbox/assets/modules/AccessibilityHelper.js').default} */
1464        app.AccessibilityHelper = module;
1465    });
1466    document.documentElement.style.setProperty('--vh', window.innerHeight * 0.01+'px');
1467    $g('*[rel=tooltip]').tooltip();
1468    $g('.radio.btn-group label').addClass('btn');
1469    $g('fieldset.btn-group').each(function() {
1470        if (this.disabled) {
1471            $g(this).css('pointer-events', 'none').off('click');
1472            $g(this).find('.btn').addClass('disabled');
1473        }
1474    });
1475    $g(".btn-group label:not(.active)").click(function(){
1476        var label = $g(this),
1477            input = $g('#'+label.attr('for'));
1478        if (!this.checked) {
1479            label.closest('.btn-group').find("label").removeClass('active btn-success btn-danger btn-primary');
1480            if (input.val() == '') {
1481                label.addClass('active btn-primary');
1482            } else if (input.val() == 0) {
1483                label.addClass('active btn-danger');
1484            } else {
1485                label.addClass('active btn-success');
1486            }
1487            input.prop('checked', true).trigger('change');
1488        }
1489    });
1490    $g(".btn-group input[checked=checked]").each(function(){
1491        if (this.value == '') {
1492            $g("label[for="+this.id+"]").addClass('active btn-primary');
1493        } else if (this.value == 0) {
1494            $g("label[for="+this.id+"]").addClass('active btn-danger');
1495        } else {
1496            $g("label[for="+this.id+"]").addClass('active btn-success');
1497        }
1498    });
1499});

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.