1// ======================== Analytics: Gravity Forms dataLayer push =============================== 2/** 3 * Push a `form_submitted` event to the GTM dataLayer when a Gravity Form 4 * confirms successfully. GTM's built-in form trigger doesn't reliably 5 * catch Gravity Forms' AJAX submits, so we hook into GF's own jQuery 6 * event (`gform_confirmation_loaded`) which fires for both AJAX and 7 * non-AJAX confirmations. 8 * 9 * Matches the existing GTM Custom Event trigger "Form Submitted" which 10 * fans out to GA4, Facebook, Google Ads, and Microsoft Ads tags. 11 * Available dataLayer variables: form_id, form_title. 12 */ 13(function () { 14 if (typeof window.jQuery === 'undefined') return; 15 16 window.dataLayer = window.dataLayer || []; 17 18 jQuery(document).on('gform_confirmation_loaded', function (event, formId) { 19 var formEl = document.getElementById('gform_wrapper_' + formId); 20 var formTitle = formEl ? (formEl.querySelector('.gform_title') || {}).textContent : ''; 21 22 window.dataLayer.push({ 23 event: 'form_submitted', 24 form_id: formId, 25 form_title: (formTitle || '').trim() 26 }); 27 }); 28}()); 29 30// ======================== Chat widget =============================== 31 32/** 33 * Programmatically open the RingCentral chat window. 34 * Retries up to 5 times (500ms apart) while the widget loads. 35 */ 36function openChat(retry) { 37 retry = retry || 0; 38 39 var trigger = document.querySelector('.dimelo_chat_item_action') 40 || document.querySelector('.dimelo-chat-bubble'); 41 42 if (trigger) { 43 trigger.click(); 44 return; 45 } 46 47 if (retry < 5) { 48 setTimeout(function () { openChat(retry + 1); }, 500); 49 } 50} 51 52// Delegate clicks on every .button--live-chat instance 53document.addEventListener('click', function (e) { 54 if (e.target.closest('.button--live-chat')) { 55 e.preventDefault(); 56 openChat(); 57 } 58}); 59 60// ======================== Homepage header â at-top state =============================== 61 62(function () { 63 if (!document.body.classList.contains('home')) return; 64 65 var header = document.querySelector('header.elementor-location-header'); 66 if (!header) return; 67 68 // Add immediately â the <header> element exists in the initial HTML 69 header.classList.add('header--at-top'); 70 71 function onScroll() { 72 if (window.scrollY === 0) { 73 header.classList.add('header--at-top'); 74 } else { 75 header.classList.remove('header--at-top'); 76 } 77 } 78 79 window.addEventListener('scroll', onScroll, { passive: true }); 80})(); 81 82// =================== rank math breadcrumbs single blog limit ===================== 83 84document.addEventListener('DOMContentLoaded', function () { 85 const lastBreadcrumb = document.querySelector('.rank-math-breadcrumb .last'); 86 87 if (lastBreadcrumb) { 88 const fullText = lastBreadcrumb.textContent.trim(); 89 const words = fullText.split(' '); 90 91 if (words.length > 6) { 92 const truncated = words.slice(0, 6).join(' ') + 'â¦'; 93 lastBreadcrumb.innerHTML = `<span class="truncated">${truncated}</span>`; 94 } 95 } 96}); 97// ======================== Function to add/remove class based on scroll on header =============================== 98jQuery(document).ready(function($) { 99 // Function to add/remove class based on scroll 100 function checkScroll() { 101 if ($(window).scrollTop() > 50) { 102 $('.light-header-wy').addClass('scrolled'); 103 } else { 104 $('.light-header-wy').removeClass('scrolled'); 105 } 106 } 107 108 // Run on scroll 109 $(window).on('scroll', checkScroll); 110 111 // Run on page load 112 checkScroll(); 113}); 114 115// ======================== Menu fadein =============================== 116jQuery(document).ready(function($){ 117 $('.menu-wy .e-n-menu-item').hover( 118 function() { 119 // Fade all other menu titles except the hovered one 120 $('.menu-wy .e-n-menu-item').not(this).children('.e-n-menu-title').css({ 121 'opacity': '0.7', 122 'transition': 'opacity 0.3s' 123 }); 124 // Make hovered menu fully visible 125 $(this).children('.e-n-menu-title').css({ 126 'opacity': '1', 127 'transition': 'opacity 0.3s' 128 }); 129 }, 130 function() { 131 // Reset opacity when hover out 132 $('.menu-wy .e-n-menu-item .e-n-menu-title').css({ 133 'opacity': '1', 134 'transition': 'opacity 0.3s' 135 }); 136 } 137 ); 138});
139// =================== Google Review navigation Arrow Trigger ===================== 140jQuery(document).ready(function ($) { 141 142 $('.left-icon-wy').addClass('disabled'); 143 144 function updateArrowState() { 145 146 const $prev = $('.ti-prev'); 147 const $next = $('.ti-next'); 148 149 // LEFT DISABLED 150 if ($prev.css('display') === 'none') { 151 $('.left-icon-wy').addClass('disabled'); 152 } else { 153 $('.left-icon-wy').removeClass('disabled'); 154 } 155 156 // RIGHT DISABLED 157 if ($next.css('display') === 'none') { 158 $('.right-icon-wy').addClass('disabled'); 159 } else { 160 $('.right-icon-wy').removeClass('disabled'); 161 } 162 } 163 164 // Wait for Trustindex to fully initialize 165 setTimeout(updateArrowState, 2000); 166 167 // When internal arrows clicked 168 $(document).on('click', '.ti-prev, .ti-next', function () { 169 setTimeout(updateArrowState, 300); 170 }); 171 172 // Custom arrow clicks 173 $('.left-icon-wy .elementor-icon').on('click', function (e) { 174 e.preventDefault(); 175 if ($('.left-icon-wy').hasClass('disabled')) return; 176 $('.ti-prev').trigger('click'); 177 }); 178 179 $('.right-icon-wy .elementor-icon').on('click', function (e) { 180 e.preventDefault(); 181 if ($('.right-icon-wy').hasClass('disabled')) return; 182 $('.ti-next').trigger('click'); 183 }); 184 185}); 186 187// stop auto scrolling 188 189window.addEventListener("load", function () { 190 191 const interval = setInterval(function () { 192 const widgets = document.querySelectorAll('.ti-widget[data-layout-category="slider"]'); 193 194 widgets.forEach(widget => { 195 if (widget.tiWidget && widget.tiWidget.slider) { 196 // Stop autoplay without destroying slider 197 if (typeof widget.tiWidget.slider.stopAutoplay === "function") { 198 widget.tiWidget.slider.stopAutoplay(); 199 } 200 } 201 }); 202 203 }, 500); 204 205}); 206// =================== Slick Carousel in Single Doctor page ===================== 207jQuery(document).ready(function ($) { 208 $('.associated-services-carousel').slick({ 209 slidesToShow: 5, 210 slidesToScroll: 1, 211 arrows: true, 212 dots: false, 213 infinite: true, 214 215 prevArrow: ` 216 <button type="button" class="slick-prev custom-arrow"> 217 <img src="/wp-content/uploads/2026/01/Button-Previous.svg"> 218 </button> 219 `, 220 nextArrow: ` 221 <button type="button" class="slick-next custom-arrow"> 222 <img src="/wp-content/uploads/2026/01/Button-Next.svg"> 223 </button> 224 `, 225 226 responsive: [ 227 { 228 breakpoint: 1024, 229 settings: { slidesToShow: 4 } 230 }, 231 { 232 breakpoint: 920, 233 settings: { slidesToShow: 3 } 234 }, 235 { 236 breakpoint: 767, 237 settings: { slidesToShow: 2 } 238 } 239 ] 240 }); 241}); 242 243// =================== Slick Carousel in Single services page ===================== 244jQuery(document).ready(function ($) { 245 $('.treatment-cards').slick({ 246 slidesToShow: 4, 247 slidesToScroll: 1, 248 infinite: true, 249 arrows: true, 250 dots: false, 251 centerMode: false, 252 253 prevArrow: ` 254 <button type="button" class="slick-prev custom-arrow"> 255 <img src="/wp-content/uploads/2026/01/Button-Previous.svg"> 256 </button> 257 `, 258 nextArrow: ` 259 <button type="button" class="slick-next custom-arrow"> 260 <img src="/wp-content/uploads/2026/01/Button-Next.svg"> 261 </button> 262 `, 263 264 responsive: [ 265 { 266 breakpoint: 1024, 267 settings: { slidesToShow: 3 } 268 }, 269 { 270 breakpoint: 767, 271 settings: { 272 slidesToShow: 1.12, 273 infinite: false 274 } 275 } 276 ] 277 }); 278}); 279// =================== Tab content ===================== 280// document.addEventListener('DOMContentLoaded', function () { 281 282// const tabButtons = document.querySelectorAll('.tab-button'); 283// const tabPanes = document.querySelectorAll('.tab-pane'); 284// const nextButton = document.getElementById('nextButton'); 285// const nextLabel = document.getElementById('nextTabLabel'); 286 287// let currentIndex = 0; 288 289// /* Activate Tab */ 290// function activateTab(index) { 291// if (index < 0 || index >= tabButtons.length) return; 292 293// // Remove active states 294// tabButtons.forEach(btn => btn.classList.remove('active'));
295// tabPanes.forEach(pane => pane.classList.remove('active')); 296 297// // Activate current 298// tabButtons[index].classList.add('active'); 299// tabPanes[index].classList.add('active'); 300 301// currentIndex = index; 302// updateNextLabel(); 303// } 304// // console.log(currentIndex,'index'); 305 306// /* Update Next Tab Label */ 307// function updateNextLabel() { 308// const nextIndex = currentIndex + 1; 309 310// if (nextIndex < tabButtons.length) { 311// nextLabel.textContent = tabButtons[nextIndex].textContent; 312// nextButton.style.display = 'inline-flex'; 313// } else { 314// nextLabel.textContent = ''; 315// nextButton.style.display = 'none'; 316// } 317// } 318 319// /* Tab Click */ 320// tabButtons.forEach((button, index) => { 321// button.addEventListener('click', () => { 322// activateTab(index); 323// }); 324// }); 325 326// /* Next Button Click */ 327// // nextButton.addEventListener('click', (e) => { 328// // e.preventDefault(); 329// // activateTab(currentIndex + 1); 330// // }); 331// if (nextButton) { 332// nextButton.addEventListener('click', (e) => { 333// e.preventDefault(); 334// activateTab(currentIndex + 1); 335// }); 336// } 337 338// /* Init */ 339// updateNextLabel(); 340 341// }); 342 343 344 345 346// jQuery(document).ready(function ($) { 347// const $tabs = $('.tab-button'); 348// const $panes = $('.tab-pane'); 349// const $dropdown = $('#tabsDropdown'); 350// const $nextBtn = $('#nextButton'); 351// const $nexttabLabel = $('.next-tab-label '); 352 353// function updateNextButton(index) { 354// if (index == $tabs.length - 1) { 355// $nextBtn.hide(); 356// $nexttabLabel.hide(); 357// } else { 358// $nextBtn.show(); // any other tab â show again 359// $nexttabLabel.show(); 360// } 361// } 362 363// function activateTab(index) { 364// index = parseInt(index); // important for dropdown 365 366// $tabs.removeClass('active'); 367// $panes.removeClass('active'); 368 369// $tabs.eq(index).addClass('active'); 370// $panes.eq(index).addClass('active'); 371 372// $dropdown.val(index); 373 374// updateNextButton(index); // ð IMPORTANT 375// } 376 377// // Desktop click 378// $tabs.on('click', function () { 379// activateTab($(this).data('tab')); 380// }); 381 382// // Dropdown change 383// $dropdown.on('change', function () { 384// activateTab($(this).val()); 385// }); 386 387// // Next button click 388// $nextBtn.on('click', function () { 389// let current = $('.tab-button.active').data('tab'); 390// let next = current + 1; 391 392// if (next >= $tabs.length) return; // stop on last 393// activateTab(next); 394// }); 395 396// // Init first tab 397// activateTab(0); 398// }); 399 400 401 402document.addEventListener('DOMContentLoaded', function () { 403 404 const tabButtons = document.querySelectorAll('.tab-button'); 405 const tabPanes = document.querySelectorAll('.tab-pane'); 406 const dropdown = document.getElementById('tabsDropdown'); 407 const nextButton = document.getElementById('nextButton'); 408 const nextLabel = document.querySelector('.next-tab-label'); 409 410 let currentIndex = 0; 411 412 function updateNextButton(index) { 413 if (!nextButton) return; 414 415 if (index >= tabButtons.length - 1) { 416 nextButton.style.display = 'none'; 417 if (nextLabel) nextLabel.style.display = 'none'; 418 } else { 419 nextButton.style.display = 'inline-flex'; 420 if (nextLabel) nextLabel.style.display = 'inline'; 421 422 if (nextLabel) { 423 nextLabel.textContent = tabButtons[index + 1].textContent; 424 } 425 } 426 } 427 428 function activateTab(index) { 429 index = parseInt(index); 430 if (index < 0 || index >= tabButtons.length) return; 431 432 tabButtons.forEach(btn => btn.classList.remove('active')); 433 tabPanes.forEach(pane => pane.classList.remove('active')); 434 435 tabButtons[index].classList.add('active'); 436 tabPanes[index].classList.add('active'); 437 438 if (dropdown) dropdown.value = index; 439 440 currentIndex = index; 441 updateNextButton(index); 442 } 443 444 // Tab Click 445 tabButtons.forEach((button, index) => { 446 button.addEventListener('click', function () { 447 activateTab(index); 448 }); 449 }); 450 451 // Dropdown Change (Mobile) 452 if (dropdown) { 453 dropdown.addEventListener('change', function () { 454 activateTab(this.value); 455 }); 456 } 457 458 // Next Button 459 if (nextButton) { 460 nextButton.addEventListener('click', function (e) { 461 e.preventDefault(); 462 activateTab(currentIndex + 1); 463 }); 464 } 465 466 // Init 467 activateTab(0); 468}); 469// =================== Filter counter ===================== 470 471document.addEventListener("DOMContentLoaded", function() { 472 // Select all filter buttons except "All" 473 const buttons = document.querySelectorAll('.blog-taxonomy-filter-wy .e-filter-item[data-filter]:not([data-filter="__all"])'); 474 475 buttons.forEach(button => { 476 const categorySlug = button.getAttribute('data-filter'); 477 478 // Fetch category info from WP REST API 479 fetch(`/wp-json/wp/v2/categories?slug=${categorySlug}`) 480 .then(response => response.json()) 481 .then(data => { 482 if (data && data[0] && typeof data[0].count !== 'undefined') { 483 const count = data[0].count; 484 485 // Create a <span> for the count 486 let countSpan = document.createElement('span'); 487 countSpan.className = 'category-count'; 488 countSpan.textContent = ` (${count})`; 489 490 // Append the count <span> inside the button 491 button.appendChild(countSpan); 492 493 } 494 }) 495 .catch(err => console.error(err)); 496 }); 497}); 498// =================== Services Page Faqs ===================== 499jQuery(document).ready(function($){ 500 $('.services-main-faqs .e-n-accordion details').attr('open', true); 501}); 502 503 504// =================== Viewport entrance animations ===================== 505(function () { 506 document.addEventListener('DOMContentLoaded', function () { 507 var targets = document.querySelectorAll('[data-animate]'); 508 if (!targets.length) return; 509 510 var observer = new IntersectionObserver(function (entries) {
511 entries.forEach(function (entry) { 512 if (entry.isIntersecting) { 513 entry.target.classList.add('is-visible'); 514 observer.unobserve(entry.target); 515 } 516 }); 517 }, { 518 threshold: 0.15 519 }); 520 521 targets.forEach(function (el) { 522 observer.observe(el); 523 }); 524 }); 525})();
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.