1document.addEventListener('DOMContentLoaded', function () { 2 3 // ============================================================ 4 // FIX 1: [aria-*] attributes do not match their roles 5 // Slick dots <li> have role="presentation" but also have 6 // aria-selected, aria-controls, aria-hidden â invalid combo. 7 // Fix: change role to "tab" and remove aria-hidden from <li> 8 // ============================================================ 9 function fixSlickDots() { 10 document.querySelectorAll('#testimonials-slider-1 .slick-dots li').forEach(function (li) { 11 li.setAttribute('role', 'tab'); 12 li.removeAttribute('aria-hidden'); 13 }); 14 15 // ul.slick-dots has role="tablist" â children must be role="tab" 16 // (was "presentation" â now fixed above so tablist is valid) 17 document.querySelectorAll('#testimonials-slider-1 ul.slick-dots').forEach(function (ul) { 18 ul.setAttribute('role', 'tablist'); 19 ul.setAttribute('aria-label', 'Testimonials navigation'); 20 }); 21 } 22 23 // Slick runs after DOMContentLoaded â delay to ensure it has initialised 24 setTimeout(fixSlickDots, 600); 25 26 // Re-apply after every slide change in case Slick resets attributes 27 if (typeof jQuery !== 'undefined') { 28 jQuery('#testimonials-slider-1').on('afterChange', function () { 29 setTimeout(fixSlickDots, 50); 30 }); 31 } 32 33 34 // ============================================================ 35 // FIX 2: [aria-hidden="true"] elements contain focusable descendants 36 // span.link-strong-hovered has aria-hidden="true" but the 37 // #ubtn-5789 button sits inside it and is focusable. 38 // Fix: remove aria-hidden from any wrapper that traps focusable elements 39 // ============================================================ 40 document.querySelectorAll('[aria-hidden="true"]').forEach(function (el) { 41 var focusable = el.querySelectorAll( 42 'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])' 43 ); 44 if (focusable.length > 0) { 45 el.removeAttribute('aria-hidden'); 46 } 47 }); 48 49 50 // ============================================================ 51 // FIX 3a: Button does not have an accessible name 52 // button.anm-close in .footer-announcement has no text or label 53 // ============================================================ 54 var closeBtn = document.querySelector('div.footer-announcement button.anm-close'); 55 if (closeBtn && !closeBtn.getAttribute('aria-label') && !closeBtn.textContent.trim()) { 56 closeBtn.setAttribute('aria-label', 'Close announcement'); 57 } 58 59 60 // ============================================================ 61 // FIX 3b: Link does not have a discernible name 62 // a.navbar-brand contains only images â no text, no aria-label 63 // Fix: add aria-label to the anchor + empty alt on logo images 64 // (empty alt is correct since the link label describes the destination) 65 // ============================================================ 66 var navBrand = document.querySelector('header.navbar a.navbar-brand'); 67 if (navBrand && !navBrand.getAttribute('aria-label') && !navBrand.textContent.trim()) { 68 navBrand.setAttribute('aria-label', 'Expert Village Media - Home'); 69 navBrand.querySelectorAll('img').forEach(function (img) { 70 if (!img.getAttribute('alt')) { 71 img.setAttribute('alt', ''); 72 } 73 }); 74 } 75 76}); 77 78 79document.addEventListener('DOMContentLoaded', function() { 80 var lcpImg = document.querySelector('.home_page_slider_mobile_setup .vc_single_image-wrapper>img.vc_single_image-img'); 81 if (lcpImg) { 82 lcpImg.setAttribute('fetchpriority', 'high'); 83 lcpImg.removeAttribute('loading'); 84 } 85});
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.