PageSourceSearch

https://sahdiagnostics.com/wp-content/themes/sah/js/app.js?ver=1791429377

js sahdiagnostics.com collected 2026-10-08 03:16:41 UTC 18,373 bytes, 498 lines download raw bytes

1var resizerTimeout = false,
2    resizerDelay = 250,
3    resizerCalls = 0,
4    viewportWidth = window.innerWidth;
5
6function openSelectorBox(event) {
7    event.preventDefault();
8    event.currentTarget.parentNode.querySelector('.wp-block-services-content__nav-items').classList.add('open');
9}
10
11function closeSelectorBox(selectorBox) {
12    if (selectorBox) {
13        selectorBox.classList.remove('open');
14    }
15}
16
17/* Remove the selected clone (mobile) */
18function removeSelected(toRemove) {
19    if (toRemove) {
20        toRemove.remove();
21    }
22}
23
24/* Add the selected clone (mobile) */
25function addSelected(selector) {
26    var selectedClone = selector.cloneNode(true);
27    var selectorBox = selector.parentNode.parentNode;
28    if (selectedClone) {
29        selectedClone.classList.add('service-selected');
30        selectedClone.classList.add('service-box-trigger');
31        if (selectorBox) {
32            selectorBox.parentNode.prepend(selectedClone);
33            selectedClone.addEventListener('click', openSelectorBox)
34        }
35    }
36}
37
38function debouncer( func , timeout ) {
39    var timeoutID , timeout = timeout || 200;
40    return function () {
41        var scope = this , args = arguments;
42        clearTimeout( timeoutID );
43        timeoutID = setTimeout( function () {
44            func.apply( scope , Array.prototype.slice.call( args ) );
45        } , timeout );
46    }
47}
48
49/* Open target service  */
50function openTarget(target_id) {
51    var target = document.getElementById(target_id);
52    if (target) {
53        target.classList.add('active');
54
55        var thingy = document.querySelector('.wp-block-services-content__nav');
56        var rect = thingy.getBoundingClientRect();
57
58        setTimeout(() => {
59            window.scrollPageTo(rect.bottom + window.scrollY, 300);
60        }, 500);
61    }
62
63
64    var targetTrigger = document.querySelector('.wp-block-services-content__nav-item[data-target="' + target_id + '"]')
65    if (targetTrigger) {
66        targetTrigger.classList.add('active');
67    }
68}
69
70/* Close all targets and reset nav items */
71function closeTargets() {
72    var targets = document.querySelectorAll('.wp-block-services-content__service');
73    for (var tt = 0; tt < targets.length; ++tt) {
74        targets[tt].classList.remove('active');
75    }
76
77    var navItems = document.querySelectorAll('.wp-block-services-content__nav-item.active');
78    for (var ni = 0; ni < navItems.length; ++ni) {
79        navItems[ni].classList.remove('active');
80    }
81}
82
83/* Run when nav item selected */
84function chooseService(target) {
85    closeTargets();
86    openTarget(target);
87}
88
89/*var isInViewport = function (elem) {
90    var bounding = elem.getBoundingClientRect();
91    return (
92        bounding.top >= 0 &&
93        bounding.left >= 0 &&
94        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
95        bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
96    );
97};*/
98
99var isInViewport = function(el, percentVisible) {
100    let
101        rect = el.getBoundingClientRect(),
102        windowHeight = (window.innerHeight || document.documentElement.clientHeight);
103
104    return !(
105        Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100)) < percentVisible ||
106        Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
107    )
108};
109
110function counterAnimationHandler(targets) {
111    targets.forEach(counter => {
112        counter.innerText = '0' //set default counter value
113        counter.dataset.count = 0;
114        const updateCounter = () => {
115            const target = +counter.getAttribute('data-target') //define increase couter to it's data-target
116            const count = +counter.dataset.count //define increase couter on innerText
117            const increment = target / 90 // define increment as counter increase value / speed
118
119            if (count < target) {
120                const newCount = Math.ceil(count + increment);
121                counter.dataset.count = newCount;
122                counter.innerText = numberWithCommas(newCount);
123                setTimeout(updateCounter, 1);
124            } else {
125                counter.innerText = numberWithCommas(target); //if default value is bigger that date-target, show data-target
126            }
127        }
128
129        updateCounter() //call the function event
130    })
131
132    function numberWithCommas(x) {
133        return x.toLocaleString();
134    }
135}
136
137function scrollPageTo (to, duration=500) {
138    //t = current time
139    //b = start value
140    //c = change in value
141    //d = duration
142    const easeInOutQuad = function (t, b, c, d) {
143        t /= d/2;
144        if (t < 1) return c/2*t*t + b;
145        t--;
146        return -c/2 * (t*(t-2) - 1) + b;
147    };
148
149    return new Promise((resolve, reject) => {
150        const element = document.scrollingElement;
151
152        if (typeof to === 'string') {
153            to = document.querySelector(to) || reject();
154        }
155        if (typeof to !== 'number') {
156            to = to.getBoundingClientRect().top + element.scrollTop;
157        }
158
159        let start = element.scrollTop,
160            change = to - start,
161            currentTime = 0,
162            increment = 20;
163
164        const animateScroll = function() {
165            currentTime += increment;
166            let val = easeInOutQuad(currentTime, start, change, duration);
167            element.scrollTop = val;
168            if(currentTime < duration) {
169                setTimeout(animateScroll, increment);
170            } else {
171                resolve();
172            }
173        };
174        animateScroll();
175    });
176}
177
178window.addEventListener('load', function() {
179
180    var mobileMenuButton = document.getElementById('mobileMenuButton');
181    if (mobileMenuButton){
182        mobileMenuButton.addEventListener('click', (event) => {
183            event.preventDefault();
184            event.currentTarget.classList.toggle('menu-icon-active');
185            document.body.classList.toggle('menu--active')
186        })
187    }
188
189    var megaMenuLis = document.querySelectorAll('li.has-children');
190    if (megaMenuLis.length > 0) {
191
192        var myListener = function () {
193            document.removeEventListener('mousemove', myListener, false);
194            for (var mml = 0; mml < megaMenuLis.length; ++mml) {
195                megaMenuLis[mml].addEventListener('mouseover', function(e) {
196                    if (window.innerWidth >= 960) {
197                        e.currentTarget.classList.add('menu-hover');
198                    }
199                });
200                megaMenuLis[mml].addEventListener('mouseout', function(e) {
201                    if (window.innerWidth >= 960) {
202                        e.currentTarget.classList.remove('menu-hover');
203                    }
204                });
205            }
206        };
207        document.addEventListener('mousemove', myListener, false);
208    }
209
210    // Header find out more buttons
211    var findOutMore = document.querySelectorAll('.find-out-more');
212    if (findOutMore.length > 0) {
213        for (var fom = 0; fom < findOutMore.length; ++fom) {
214            findOutMore[fom].addEventListener('click', (event) => {
215                event.preventDefault();
216                var parentEl = event.currentTarget.parentNode.parentNode.parentNode;
217                var rect = parentEl.getBoundingClientRect();
218                window.scrollPageTo(rect.bottom, 300);
219            })
220        }
221    }
222
223
224    var servicesContent = document.querySelectorAll('.wp-block-services-content');
225    if (servicesContent.length > 0)
226    {
227        // Check for hashtags && service selector existence
228        var findNavs = document.querySelectorAll('.wp-block-services-content__nav');
229        if (window.location.hash && findNavs.length > 0 && window.location.hash !== '#services') {
230            var originalString = window.location.hash;
231            var parts = originalString.split("#");
232            var newTarget = parts[0] + "service_" + parts[1];
233            chooseService(newTarget);
234        }
235
236        // On mobile, hide the default active service
237        if (viewportWidth < 960) {
238            var check = document.querySelector('.wp-block-services-content__service.active');
239            if (check) {
240                check.classList.remove('active');
241            }
242        }
243
244        // Service / Specialty selector
245        var selector = document.querySelectorAll('.service-box-trigger');
246        if (selector.length > 0) {
247            for (var s = 0; s < selector.length; ++s) {
248                selector[s].addEventListener('click', openSelectorBox)
249            }
250        }
251
252        var selectorTrigger = document.querySelectorAll('.wp-block-services-content__nav-item');
253        for (var st = 0; st < selectorTrigger.length; ++st) {
254            selectorTrigger[st].addEventListener('click', (event) => {
255                var target = event.currentTarget.dataset.target;
256
257                var selector = event.currentTarget;
258                var viewportWidth = window.innerWidth;
259                if (viewportWidth < 960) {
260                    var toRemove = selector.parentNode.parentNode.parentNode.querySelector('.service-selected');
261                    removeSelected(toRemove);
262                }
263                if (selector) {
264                    var selectorBox = selector.parentNode.parentNode;
265                    closeSelectorBox(selectorBox);
266                    if (viewportWidth < 960) {
267                        addSelected(selector);
268                    }
269                }
270
271                chooseService(target);
272            })
273        }
274
275
276    }
277
278    var servicesNav = document.querySelector('.wp-block-services-content__nav-items__inner');
279    if (servicesNav) {
280        jQuery(servicesNav).slick({
281            slidesToShow: 5,
282            draggable: false,
283            prevArrow: servicesNav.nextElementSibling.querySelector('.hex-button-prev'),
284            nextArrow: servicesNav.nextElementSibling.querySelector('.hex-button-next'),
285            responsive: [
286                {
287                    breakpoint: 1023,
288                    settings: "unslick"
289                }
290            ]
291        })
292    }
293
294    var hexRows = document.querySelectorAll('.wp-block-hex-rows__grid');
295    if (hexRows.length > 0) {
296        for (var hr = 0; hr < hexRows.length; ++hr) {
297            jQuery(hexRows[hr]).slick({
298                slidesToShow: 1,
299                prevArrow: hexRows[hr].nextElementSibling.querySelector('.hex-button-prev'),
300                nextArrow: hexRows[hr].nextElementSibling.querySelector('.hex-button-next'),
301                centerMode: true,
302                variableWidth: true,
303                mobileFirst: true,
304                responsive: [
305                    {
306                        breakpoint: 959,
307                        settings: "unslick"
308                    }
309                ]
310            })
311        }
312    }
313
314    var testimonials_carousels = document.querySelectorAll(".wp-block-testimonials__grid:not
314(.slick-initialized)");
315    if (testimonials_carousels.length > 0) {
316        for (var i = 0; i < testimonials_carousels.length; ++i) {
317            var config = {
318                infinite: false,
319                prevArrow: testimonials_carousels[i].nextElementSibling.querySelector('.hex-button-prev'),
320                nextArrow: testimonials_carousels[i].nextElementSibling.querySelector('.hex-button-next'),
321                mobileFirst: true,
322                slidesToShow: 1,
323                responsive: [
324                    {
325                        breakpoint: 767,
326                        settings: {
327                            slidesToShow: 2,
328                            slidesToScroll: 1,
329                            variableWidth: true,
330                        },
331                    },
332                    {
333                        breakpoint: 959,
334                        settings: {
335                            slidesToShow: 2,
336                            slidesToScroll: 1,
337                        },
338                    }
339                ]
340            }
341
342            jQuery(testimonials_carousels[i]).slick(config);
343        }
344    }
345
346    var cards_carousels = document.querySelectorAll(".wp-block-cards__grid:not(.slick-initialized)");
347    if (cards_carousels.length > 0) {
348        for (var cc = 0; cc < cards_carousels.length; ++cc) {
349            var card_carousels_config = {
350                infinite: false,
351                prevArrow: cards_carousels[cc].nextElementSibling.querySelector('.hex-button-prev'),
352                nextArrow: cards_carousels[cc].nextElementSibling.querySelector('.hex-button-next'),
353                mobileFirst: true,
354                responsive: [
355                    {
356                        breakpoint: 767,
357                        settings: "unslick"
358                    }
359                ]
360            }
361            jQuery(cards_carousels[cc]).slick(card_carousels_config);
362        }
363    }
364
365    var frameworkSlider = document.querySelectorAll('.wp-block-framework-slider__slider');
366    if (frameworkSlider.length > 0) {
367        for (var fs = 0; fs < frameworkSlider.length; ++fs) {
368            jQuery(frameworkSlider[fs]).slick({
369                slidesToShow: 1,
370                prevArrow: frameworkSlider[fs].nextElementSibling.querySelector('.hex-button-prev'),
371                nextArrow: frameworkSlider[fs].nextElementSibling.querySelector('.hex-button-next'),
372                centerMode: false,
373                infinite: false,
374                mobileFirst: true,
375                responsive: [
376                    {
377                        breakpoint: 767,
378                        settings: {
379                            slidesToShow: 2
380                        }
381                    }
382                ]
383            })
384        }
385    }
386
387    var gallerySlider = document.querySelectorAll('.wp-block-gallery-text__slider');
388    if (gallerySlider.length > 0) {
389        for (var gs = 0; gs < gallerySlider.length; ++gs) {
390            jQuery(gallerySlider[gs]).slick({
391                slidesToShow: 1,
392                prevArrow: gallerySlider[gs].nextElementSibling.querySelector('.hex-button-prev'),
393                nextArrow: gallerySlider[gs].nextElementSibling.querySelector('.hex-button-next'),
394                centerMode: false,
395                mobileFirst: true,
396                fade: true,
397                responsive: [
398                    {
399                        breakpoint: 959,
400                        settings: {
401                            prevArrow: gallerySlider[gs].parentNode.nextElementSibling.querySelector('.wp-block-gallery-text__gallery-nav--desktop .hex-button-prev'),
402                            nextArrow: gallerySlider[gs].parentNode.nextElementSibling.querySelector('.wp-block-gallery-text__gallery-nav--desktop .hex-button-next'),
403                        },
404                    }
405                ]
406            })
407        }
408    }
409
410    var readMoreLinks = document.querySelectorAll('.open-text-extra');
411    if (readMoreLinks.length > 0) {
412        for (var rm = 0; rm < readMoreLinks.length; ++rm) {
413            readMoreLinks[rm].addEventListener('click', (event) => {
414                event.preventDefault();
415                var realTarget = event.currentTarget.previousSibling.previousSibling;
416                realTarget.classList.toggle('active');
417            });
418        }
419    }
420
421});
422
423window.addEventListener('scroll', function(event) {
424    var statsBlock = document.querySelectorAll('.wp-block-stats__grid');
425    if (statsBlock.length > 0) {
426        for (var sb = 0; sb < statsBlock.length; sb++) {
427            if (isInViewport(statsBlock[sb], 30)) {
428                if (!statsBlock[sb].classList.contains('stats-loaded')) {
429                    counterAnimationHandler(document.querySelectorAll('.wp-block-stats__stat-title'));
430                    statsBlock[sb].classList.add('stats-loaded');
431                }
432            }
433        }
434    }
435});
436
437window.addEventListener('resize', function(event) {
438    clearTimeout(resizerTimeout);
439    resizerTimeout = setTimeout(resizeFunction, resizerDelay);
440})
441
442function resizeFunction() {
443
444    resizerCalls += 1;
445
446    var servicesNav = document.querySelector('.wp-block-services-content__nav-items__inner');
447    if (servicesNav) {
448        jQuery(servicesNav).slick({
449            slidesToShow: 5,
450            draggable: false,
451            prevArrow: servicesNav.nextElementSibling.querySelector('.hex-button-prev'),
452            nextArrow: servicesNav.nextElementSibling.querySelector('.hex-button-next'),
453            responsive: [
454                {
455                    breakpoint: 1023,
456                    settings: "unslick"
457                }
458            ]
459        })
460    }
461
462    var hexRows = document.querySelectorAll('.wp-block-hex-rows__grid:not(.slick-initialized)');
463    if (hexRows.length > 0) {
464        for (var hr = 0; hr < hexRows.length; ++hr) {
465            jQuery(hexRows[hr]).slick({
466                slidesToShow: 1,
467                centerMode: true,
468                variableWidth: true,
469                mobileFirst: true,
470                responsive: [
471                    {
472                        breakpoint: 959,
473                        settings: "unslick"
474                    }
475                ]
476            })
477        }
478    }
479
480    var cards_carousels = document.querySelectorAll(".wp-block-cards__grid:not(.slick-initialized)");
481    if (cards_carousels.length > 0) {
482        for (var cc = 0; cc < cards_carousels.length; ++cc) {
483            jQuery(cards_carousels[cc]).slick({
484                infinite: false,
485                prevArrow: cards_carousels[cc].nextElementSibling.querySelector('.hex-button-prev'),
486                nextArrow: cards_carousels[cc].nextElementSibling.querySelector('.hex-button-next'),
487                mobileFirst: true,
488                responsive: [
489                    {
490                        breakpoint: 767,
491                        settings: "unslick"
492                    }
493                ]
494            });
495        }
496    }
497
498}

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.