PageSourceSearch

https://decibelclinic.com/wp-content/themes/decibel/assets/js/function.js

js decibelclinic.com collected 2026-10-08 16:17:57 UTC 26,491 bytes, 726 lines download raw bytes

vendor: 6,797 bytes, lines 1-194
1(function($) {
2    "use strict";
3
4    var $window = $(window);
5    var $body = $('body');
6
7    /* Slick library JS */
8    var
9        defaults = {
10            label: 'MENU',
11            duplicate: true,
12            duration: 200,
13            easingOpen: 'swing',
14            easingClose: 'swing',
15            closedSymbol: '►',
16            openedSymbol: '▼',
17            prependTo: 'body',
18            appendTo: '',
19            parentTag: 'a',
20            closeOnClick: false,
21            allowParentLinks: false,
22            nestedParentLinks: true,
23            showChildren: false,
24            removeIds: true,
25            removeClasses: false,
26            removeStyles: false,
27            brand: '',
28            animations: 'jquery',
29            init: function() {},
30            beforeOpen: function() {},
31            beforeClose: function() {},
32            afterOpen: function() {},
33            afterClose: function() {}
34        },
35        mobileMenu = 'slicknav',
36        prefix = 'slicknav',
37        Keyboard = {
38            DOWN: 40,
39            ENTER: 13,
40            ESCAPE: 27,
41            LEFT: 37,
42            RIGHT: 39,
43            SPACE: 32,
44            TAB: 9,
45            UP: 38,
46        };
47
48    function Plugin(element, options) {
49        this.element = element;
50
51        // jQuery has an extend method which merges the contents of two or
52        // more objects, storing the result in the first object. The first object
53        // is generally empty as we don't want to alter the default options for
54        // future instances of the plugin
55        this.settings = $.extend({}, defaults, options);
56
57        // Don't remove IDs by default if duplicate is false
58        if (!this.settings.duplicate && !options.hasOwnProperty("removeIds")) {
59            this.settings.removeIds = false;
60        }
61
62        this._defaults = defaults;
63        this._name = mobileMenu;
64
65        this.init();
66    }
67
68    Plugin.prototype.init = function() {
69        var $this = this,
70            menu = $(this.element),
71            settings = this.settings,
72            iconClass,
73            menuBar;
74
75        // clone menu if needed
76        if (settings.duplicate) {
77            $this.mobileNav = menu.clone();
78        } else {
79            $this.mobileNav = menu;
80        }
81
82        // remove IDs if set
83        if (settings.removeIds) {
84            $this.mobileNav.removeAttr('id');
85            $this.mobileNav.find('*').each(function(i, e) {
86                $(e).removeAttr('id');
87            });
88        }
89
90        // remove classes if set
91        if (settings.removeClasses) {
92            $this.mobileNav.removeAttr('class');
93            $this.mobileNav.find('*').each(function(i, e) {
94                $(e).removeAttr('class');
95            });
96        }
97
98        // remove styles if set
99        if (settings.removeStyles) {
100            $this.mobileNav.removeAttr('style');
101            $this.mobileNav.find('*').each(function(i, e) {
102                $(e).removeAttr('style');
103            });
104        }
105
106        // styling class for the button
107        iconClass = prefix + '_icon';
108
109        if (settings.label === '') {
110            iconClass += ' ' + prefix + '_no-text';
111        }
112
113        if (settings.parentTag == 'a') {
114            settings.parentTag = 'a href="#"';
115        }
116
117        // create menu bar
118        $this.mobileNav.attr('class', prefix + '_nav');
119        menuBar = $('<div class="' + prefix + '_menu"></div>');
120        if (settings.brand !== '') {
121            var brand = $('<div class="' + prefix + '_brand">' + settings.brand + '</div>');
122            $(menuBar).append(brand);
123        }
124        $this.btn = $(
125            ['<' + settings.parentTag + ' aria-haspopup="true" role="button" tabindex="0" class="' + prefix + '_btn ' + prefix + '_collapsed">',
126                '<span class="' + prefix + '_menutxt">' + settings.label + '</span>',
127                '<span class="' + iconClass + '">',
128                '<span class="' + prefix + '_icon-bar"></span>',
129                '<span class="' + prefix + '_icon-bar"></span>',
130                '<span class="' + prefix + '_icon-bar"></span>',
131                '</span>',
132                '</' + settings.parentTag + '>'
133            ].join('')
134        );
135        $('.navbar-toggle').append($this.btn);
136        if (settings.appendTo !== '') {
137            $(settings.appendTo).append(menuBar);
138        } else {
139            $(settings.prependTo).prepend(menuBar);
140        }
141        menuBar.append($this.mobileNav);
142
143        // iterate over structure adding additional structure
144        var items = $this.mobileNav.find('li');
145        $(items).each(function() {
146            var item = $(this),
147                data = {};
148            data.children = item.children('ul').attr('role', 'menu');
149            item.data('menu', data);
150
151            // if a list item has a nested menu
152            if (data.children.length > 0) {
153
154                // select all text before the child menu
155                // check for anchors
156
157                var a = item.contents(),
158                    containsAnchor = false,
159                    nodes = [];
160
161                $(a).each(function() {
162                    if (!$(this).is('ul')) {
163                        nodes.push(this);
164                    } else {
165                        return false;
166                    }
167
168                    if ($(this).is("a")) {
169                        containsAnchor = true;
170                    }
171                });
172
173                var wrapElement = $(
174                    '<' + settings.parentTag + ' role="menuitem" aria-haspopup="true" tabindex="-1" class="' + prefix + '_item"/>'
175                );
176
177                // wrap item text with tag and add classes unless we are separating parent links
178                if ((!settings.allowParentLinks || settings.nestedParentLinks) || !containsAnchor) {
179                    var $wrap = $(nodes).wrapAll(wrapElement).parent();
180                    $wrap.addClass(prefix + '_row');
181                } else
182                    $(nodes).wrapAll('<span class="' + prefix + '_parent-link ' + prefix + '_row"/>').parent();
183
184                if (!settings.showChildren) {
185                    item.addClass(prefix + '_collapsed');
186                } else {
187                    item.addClass(prefix + '_open');
188                }
189
190                item.addClass(prefix + '_parent');
191
192                // create parent arrow. wrap with link if parent links and separating
193                var arrowElement = $('<span class="' + prefix + '_arrow">' + (settings.showChildren ? settings.openedSymbol : settings.closedSymbol) + '</span>');
194
195                if (settings.allowParentLinks && !settings.nestedParentLinks && containsAnchor)
196                    arrowElement = arrowElement.wrap(wrapElement).parent();
197
198                //append arrow
199                $(nodes).last().after(arrowElement);
200
201
202            } else if (item.children().length === 0) {
203                item.addClass(prefix + '_txtnode');
204            }
205
206            // accessibility for links
207            item.children('a').attr('role', 'menuitem').on("click", function(event) {
208                //Ensure that it's not a parent
209                if (settings.closeOnClick && !$(event.target).parent().closest('li').hasClass(prefix + '_parent')) {
210                    //Emulate menu close if set
211                    $($this.btn).trigger('click');
212                }
213            });
214
215            //also close on click if parent links are set
216            if (settings.closeOnClick && settings.allowParentLinks) {
217
218                item.children('a').children('a').on("click", function(event) {
219                    //Emulate menu close
220                    $($this.btn).trigger('click');
221                });
222
223                item.find('.' + prefix + '_parent-link a:not(.' + prefix + '_item)').on("click", function(event) {
224                    //Emulate menu close
225                    $($this.btn).trigger('click');
226                });
227            }
228        });
229
230        // structure is in place, now hide appropriate items
231        $(items).each(function() {
232            var data = $(this).data('menu');
233            if (!settings.showChildren) {
234                $this._visibilityToggle(data.children, null, false, null, true);
235            }
236        });
237
238        // finally toggle entire menu
239        $this._visibilityToggle($this.mobileNav, null, false, 'init', true);
240
241        // accessibility for menu button
242        $this.mobileNav.attr('role', 'menu');
243
244        // outline prevention when using mouse
245        $(document).on("mousedown", function() {
246            $this._outlines(false);
247        });
248
249        $(document).on("keyup", function() {
250            $this._outlines(true);
251        });
252
253        // menu button click
254        $($this.btn).on("click", function(e) {
255            e.preventDefault();
256            $this._menuToggle();
257        });
258
259        // click on menu parent
260        $this.mobileNav.on('click', '.' + prefix + '_item', function(e) {
261            e.preventDefault();
262            $this._itemClick($(this));
263        });
264
265        // check for keyboard events on menu button and menu parents
266        $($this.btn).on("keydown", function(e) {
267            var ev = e || event;
268
269            switch (ev.keyCode) {
270                case Keyboard.ENTER:
271                case Keyboard.SPACE:
272                case Keyboard.DOWN:
273                    e.preventDefault();
274                    if (ev.keyCode !== Keyboard.DOWN || !$($this.btn).hasClass(prefix + '_open')) {
275                        $this._menuToggle();
276                    }
277
278                    $($this.btn).next().find('[role="menuitem"]').first().trigger("focus");
279                    break;
280            }
281
282
283        });
284
285        $this.mobileNav.on('keydown', '.' + prefix + '_item', function(e) {
286            var ev = e || event;
287
288            switch (ev.keyCode) {
289                case Keyboard.ENTER:
290                    e.preventDefault();
291                    $this._itemClick($(e.target));
292                    break;
293                case Keyboard.RIGHT:
294                    e.preventDefault();
295                    if ($(e.target).parent().hasClass(prefix + '_collapsed')) {
296                        $this._itemClick($(e.target));
297                    }
298                    $(e.target).next().find('[role="menuitem"]').first().trigger("focus");
299                    break;
300            }
301        });
302
303        $this.mobileNav.on('keydown', '[role="menuitem"]', function(e) {
304            var ev = e || event;
305
306            switch (ev.keyCode) {
307                case Keyboard.DOWN:
308                    e.preventDefault();
309                    var allItems = $(e.target).parent().parent().children().children('[role="menuitem"]:visible');
310                    var idx = allItems.index(e.target);
311                    var nextIdx = idx + 1;
312                    if (allItems.length <= nextIdx) {
313                        nextIdx = 0;
314                    }
315                    var next = allItems.eq(nextIdx);
316                    next.trigger("focus");
317                    break;
318                case Keyboard.UP:
319                    e.preventDefault();
320                    var allItems = $(e.target).parent().parent().children().children('[role="menuitem"]:visible');
321                    var idx = allItems.index(e.target);
322                    var next = allItems.eq(idx - 1);
323                    next.trigger("focus");
324                    break;
325                case Keyboard.LEFT:
326                    e.preventDefault();
327                    if ($(e.target).parent().parent().parent().hasClass(prefix + '_open')) {
328                        var parent = $(e.target).parent().parent().prev();
329                        parent.trigger("focus");
330                        $this._itemClick(parent);
331                    } else if ($(e.target).parent().parent().hasClass(prefix + '_nav')) {
332                        $this._menuToggle();
333                        $($this.btn).trigger("focus");
334                    }
335                    break;
336                case Keyboard.ESCAPE:
337                    e.preventDefault();
338                    $this._menuToggle();
339                    $($this.btn).trigger("focus");
340                    break;
341            }
342        });
343
344        // allow links clickable within parent tags if set
345        if (settings.allowParentLinks && settings.nestedParentLinks) {
346            $('.' + prefix + '_item a').on("click", function(e) {
347                e.stopImmediatePropagation();
348            });
349        }
350    };
351
352    //toggle menu
353    Plugin.prototype._menuToggle = function(el) {
354        var $this = this;
355        var btn = $this.btn;
356        var mobileNav = $this.mobileNav;
357
358        if (btn.hasClass(prefix + '_collapsed')) {
359            btn.removeClass(prefix + '_collapsed');
360            btn.addClass(prefix + '_open');
361        } else {
362            btn.removeClass(prefix + '_open');
363            btn.addClass(prefix + '_collapsed');
364        }
365        btn.addClass(prefix + '_animating');
366        $this._visibilityToggle(mobileNav, btn.parent(), true, btn);
367    };
368
369    // toggle clicked items
370    Plugin.prototype._itemClick = function(el) {
371        var $this = this;
372        var settings = $this.settings;
373        var data = el.data('menu');
374        if (!data) {
375            data = {};
376            data.arrow = el.children('.' + prefix + '_arrow');
377            data.ul = el.next('ul');
378            data.parent = el.parent();
379            //Separated parent link structure
380            if (data.parent.hasClass(prefix + '_parent-link')) {
381                data.parent = el.parent().parent();
382                data.ul = el.parent().next('ul');
383            }
384            el.data('menu', data);
385        }
386        if (data.parent.hasClass(prefix + '_collapsed')) {
vendor: 7,830 bytes, lines 387-595
387            data.arrow.html(settings.openedSymbol);
388            data.parent.removeClass(prefix + '_collapsed');
389            data.parent.addClass(prefix + '_open');
390            data.parent.addClass(prefix + '_animating');
391            $this._visibilityToggle(data.ul, data.parent, true, el);
392        } else {
393            data.arrow.html(settings.closedSymbol);
394            data.parent.addClass(prefix + '_collapsed');
395            data.parent.removeClass(prefix + '_open');
396            data.parent.addClass(prefix + '_animating');
397            $this._visibilityToggle(data.ul, data.parent, true, el);
398        }
399    };
400
401    // toggle actual visibility and accessibility tags
402    Plugin.prototype._visibilityToggle = function(el, parent, animate, trigger, init) {
403        var $this = this;
404        var settings = $this.settings;
405        var items = $this._getActionItems(el);
406        var duration = 0;
407        if (animate) {
408            duration = settings.duration;
409        }
410
411        function afterOpen(trigger, parent) {
412            $(trigger).removeClass(prefix + '_animating');
413            $(parent).removeClass(prefix + '_animating');
414
415            //Fire afterOpen callback
416            if (!init) {
417                settings.afterOpen(trigger);
418            }
419        }
420
421        function afterClose(trigger, parent) {
422            el.attr('aria-hidden', 'true');
423            items.attr('tabindex', '-1');
424            $this._setVisAttr(el, true);
425            el.hide(); //jQuery 1.7 bug fix
426
427            $(trigger).removeClass(prefix + '_animating');
428            $(parent).removeClass(prefix + '_animating');
429
430            //Fire init or afterClose callback
431            if (!init) {
432                settings.afterClose(trigger);
433            } else if (trigger == 'init') {
434                settings.init();
435            }
436        }
437
438        if (el.hasClass(prefix + '_hidden')) {
439            el.removeClass(prefix + '_hidden');
440            //Fire beforeOpen callback
441            if (!init) {
442                settings.beforeOpen(trigger);
443            }
444            if (settings.animations === 'jquery') {
445                el.stop(true, true).slideDown(duration, settings.easingOpen, function() {
446                    afterOpen(trigger, parent);
447                });
448            } else if (settings.animations === 'velocity') {
449                el.velocity("finish").velocity("slideDown", {
450                    duration: duration,
451                    easing: settings.easingOpen,
452                    complete: function() {
453                        afterOpen(trigger, parent);
454                    }
455                });
456            }
457            el.attr('aria-hidden', 'false');
458            items.attr('tabindex', '0');
459            $this._setVisAttr(el, false);
460        } else {
461            el.addClass(prefix + '_hidden');
462
463            //Fire init or beforeClose callback
464            if (!init) {
465                settings.beforeClose(trigger);
466            }
467
468            if (settings.animations === 'jquery') {
469                el.stop(true, true).slideUp(duration, this.settings.easingClose, function() {
470                    afterClose(trigger, parent)
471                });
472            } else if (settings.animations === 'velocity') {
473
474                el.velocity("finish").velocity("slideUp", {
475                    duration: duration,
476                    easing: settings.easingClose,
477                    complete: function() {
478                        afterClose(trigger, parent);
479                    }
480                });
481            }
482        }
483    };
484
485    // set attributes of element and children based on visibility
486    Plugin.prototype._setVisAttr = function(el, hidden) {
487        var $this = this;
488
489        // select all parents that aren't hidden
490        var nonHidden = el.children('li').children('ul').not('.' + prefix + '_hidden');
491
492        // iterate over all items setting appropriate tags
493        if (!hidden) {
494            nonHidden.each(function() {
495                var ul = $(this);
496                ul.attr('aria-hidden', 'false');
497                var items = $this._getActionItems(ul);
498                items.attr('tabindex', '0');
499                $this._setVisAttr(ul, hidden);
500            });
501        } else {
502            nonHidden.each(function() {
503                var ul = $(this);
504                ul.attr('aria-hidden', 'true');
505                var items = $this._getActionItems(ul);
506                items.attr('tabindex', '-1');
507                $this._setVisAttr(ul, hidden);
508            });
509        }
510    };
511
512    // get all 1st level items that are clickable
513    Plugin.prototype._getActionItems = function(el) {
514        var data = el.data("menu");
515        if (!data) {
516            data = {};
517            var items = el.children('li');
518            var anchors = items.find('a');
519            data.links = anchors.add(items.find('.' + prefix + '_item'));
520            el.data('menu', data);
521        }
522        return data.links;
523    };
524
525    Plugin.prototype._outlines = function(state) {
526        if (!state) {
527            $('.' + prefix + '_item, .' + prefix + '_btn').css('outline', 'none');
528        } else {
529            $('.' + prefix + '_item, .' + prefix + '_btn').css('outline', '');
530        }
531    };
532
533    Plugin.prototype.toggle = function() {
534        var $this = this;
535        $this._menuToggle();
536    };
537
538    Plugin.prototype.open = function() {
539        var $this = this;
540        if ($this.btn.hasClass(prefix + '_collapsed')) {
541            $this._menuToggle();
542        }
543    };
544
545    Plugin.prototype.close = function() {
546        var $this = this;
547        if ($this.btn.hasClass(prefix + '_open')) {
548            $this._menuToggle();
549        }
550    };
551
552    $.fn[mobileMenu] = function(options) {
553        var args = arguments;
554
555        // Is the first parameter an object (options), or was omitted, instantiate a new instance
556        if (options === undefined || typeof options === 'object') {
557            return this.each(function() {
558
559                // Only allow the plugin to be instantiated once due to methods
560                if (!$.data(this, 'plugin_' + mobileMenu)) {
561
562                    // if it has no instance, create a new one, pass options to our plugin constructor,
563                    // and store the plugin instance in the elements jQuery data object.
564                    $.data(this, 'plugin_' + mobileMenu, new Plugin(this, options));
565                }
566            });
567
568            // If is a string and doesn't start with an underscore or 'init' function, treat this as a call to a public method.
569        } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
570
571            // Cache the method call to make it possible to return a value
572            var returns;
573
574            this.each(function() {
575                var instance = $.data(this, 'plugin_' + mobileMenu);
576
577                // Tests that there's already a plugin-instance and checks that the requested public method exists
578                if (instance instanceof Plugin && typeof instance[options] === 'function') {
579
580                    // Call the method of our plugin instance, and pass it the supplied arguments.
581                    returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
582                }
583            });
584
585            // If the earlier cached method gives a value back return the value, otherwise return this to preserve chainability.
586            return returns !== undefined ? returns : this;
587        }
588    };
589    /* End Slick library  */
590
591
592    /* Preloader Effect */
593    $window.on('load', function() {
594        $(".preloader").fadeOut(600);
595    });
596
597    /* Slick Menu JS */
598    if ($('.main-menu').length) {
599        $('.main-menu').slicknav({
600            label: '',
601            prependTo: '.responsive-menu'
602        });
603    }
604
605    /* Image Reveal Animation */
606    if ($('.at-animation-image-style-1').length) {
607        gsap.registerPlugin(ScrollTrigger);
608        let revealContainers = document.querySelectorAll(".at-animation-image-style-1");
609        revealContainers.forEach((container) => {
610            let image = container.querySelector("img");
611            let tl = gsap.timeline({
612                scrollTrigger: {
613                    trigger: container,
614                    toggleActions: "play none none none"
615                }
616            });
617            tl.set(container, {
618                autoAlpha: 1
619            });
620            tl.from(container, 1, {
621                xPercent: -100,
622                ease: Power2.out
623            });
624            tl.from(image, 1, {
625                xPercent: 100,
626                scale: 1,
627                delay: -1,
628                ease: Power2.out
629            });
630        });
631    }
632
633    /* Text Effect Animation */
634    if ($('.at-animation-heading-style-1 .elementor-heading-title, .at-animation-heading-style-1 .ekit-heading--title').length) {
635        let staggerAmount = 0.05,
636            translateXValue = 0,
637            delayValue = 0.5,
638            animatedTextElements = document.querySelectorAll('.at-animation-heading-style-1 .elementor-heading-title, .at-animation-heading-style-1 .ekit-heading--title');
639
640        animatedTextElements.forEach((element) => {
641            let animationSplitText = new SplitText(element, {
642                type: "chars, words"
643            });
644            gsap.from(animationSplitText.words, {
645                duration: 1,
646                delay: delayValue,
647                x: 20,
648                autoAlpha: 0,
649                stagger: staggerAmount,
650                scrollTrigger: {
651                    trigger: element,
652                    start: "top 85%"
653                },
654            });
655        });
656
657    }
658
659    if ($('.at-animation-heading-style-2 .elementor-heading-title, .at-animation-heading-style-2 .ekit-heading--title').length) {
660
661        let staggerAmount = 0.03,
662            translateXValue = 20,
663            delayValue = 0.1,
664            easeType = "power2.out",
665            animatedTextElements = document.querySelectorAll('.at-animation-heading-style-2 .elementor-heading-title, .at-animation-heading-style-2 .ekit-heading--title');
666
667        animatedTextElements.forEach((element) => {
668            let animationSplitText = new SplitText(element, {
669                type: "chars, words"
670            });
671            gsap.from(animationSplitText.chars, {
672                duration: 1,
673                delay: delayValue,
674                x: translateXValue,
675                autoAlpha: 0,
676                stagger: staggerAmount,
677                ease: easeType,
678                scrollTrigger: {
679                    trigger: element,
680                    start: "top 85%"
681                },
682            });
683        });
684
685    }
686
687    if ($('.at-animation-heading-style-3 .elementor-heading-title, .at-animation-heading-style-3 .ekit-heading--title').length) {
688        let animatedTextElements = document.querySelectorAll('.at-animation-heading-style-3 .elementor-heading-title, .at-animation-heading-style-3 .ekit-heading--title');
689
690        animatedTextElements.forEach((element) => {
691            //Reset if needed
692            if (element.animation) {
693                element.animation.progress(1).kill();
694                element.split.revert();
695            }
696
697            element.split = new SplitText(element, {
698                type: "lines,words,chars",
699                linesClass: "split-line",
700            });
701            gsap.set(element, {
702                perspective: 400
703            });
704
705            gsap.set(element.split.chars, {
706                opacity: 0,
707                x: "50",
708            });
709
710            element.animation = gsap.to(element.split.chars, {
711                scrollTrigger: {
712                    trigger: element,
713                    start: "top 90%"
714                },
715                x: "0",
716                y: "0",
717                rotateX: "0",
718                opacity: 1,
719                duration: 1,
720                ease: Back.easeOut,
721                stagger: 0.02,
722            });
723        });
724    }
725
726})(jQuery);

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.