1/** 2 * Weglot language-switcher accessibility shim â tracker rows 21, 55 and the vendor half of 20. 3 * 4 * The switcher DOM is built by the Weglot plugin's own front-end JavaScript, so no template in 5 * this theme can reach it. It ships as: 6 * 7 * <div role="listbox" aria-activedescendant="weglot-language-en" 8 * aria-label="Language Switcher: English" class="weglot_switcher â¦"> 9 * <div class="language-option" aria-label="Language selected: English"> 10 * <a role="none" id="weglot-language-en" href="â¦">English</a> 11 * </div> 12 * </div> 13 * 14 * Three separate scan findings come out of that: 15 * 16 * 1. role="listbox" may only contain role="option" children. It contains a generic <div> 17 * and a link, so the listbox is invalid (ARIA 5.2.6, row 21). 18 * 2. role="none" on an <a> is ignored â a link cannot be made presentational while it is 19 * still focusable and has an href (row 55). 20 * 3. aria-label on <div class="language-option"> â a bare div is role=generic, which 21 * prohibits naming, so the label is discarded (ARIA 5.2.8.6, vendor half of row 20). 22 * 23 * The fix is to stop pretending this is a listbox. It is not a selection widget: each option is 24 * a link that navigates to the translated URL. Describing it as navigation is both honest and 25 * valid, and it resolves all three findings without inventing option semantics that the markup 26 * does not support. 27 * 28 * Deliberately conservative: 29 * - only ARIA attributes are touched; no elements, classes, hrefs or handlers are altered, 30 * so Weglot's own click behaviour is untouched; 31 * - `tabindex` is left alone â Weglot may rely on it for focus management; 32 * - it is idempotent, and re-runs if Weglot re-renders the switcher (it does, on language 33 * change and on some navigation). 34 */ 35(function () { 36 'use strict'; 37 38 function fixSwitcher(root) { 39 var switchers = root.querySelectorAll('.weglot_switcher[role="listbox"]'); 40 41 Array.prototype.forEach.call(switchers, function (sw) { 42 // A language switcher is navigation, not a listbox. role=navigation also permits an 43 // accessible name, so the existing aria-label on the container stays valid. 44 sw.setAttribute('role', 'navigation'); 45 sw.removeAttribute('aria-activedescendant'); 46 }); 47 48 // The option wrappers are generic <div>s and cannot carry a name; the link inside already 49 // provides one. Scoped to the switcher so nothing else on the page is affected. 50 var wrappers = root.querySelectorAll('.weglot_switcher .language-option[aria-label]'); 51 Array.prototype.forEach.call(wrappers, function (el) { 52 el.removeAttribute('aria-label'); 53 }); 54 55 // role="none" on a focusable link with an href is ignored by browsers anyway; removing it 56 // lets the anchor be announced as the link it actually is. 57 var links = root.querySelectorAll( 58 '.weglot_switcher a[role="none"], .weglot_switcher a[role="presentation"]' 59 ); 60 Array.prototype.forEach.call(links, function (a) { 61 a.removeAttribute('role'); 62 }); 63 } 64 65 function init() { 66 fixSwitcher(document); 67 68 // Weglot rebuilds the switcher on language change and on some navigations, which would 69 // restore the original attributes. Watch for that and re-apply. childList/subtree only â 70 // observing attributes here would re-trigger on our own writes. 71 if (typeof MutationObserver !== 'function' || !document.body) { 72 return; 73 } 74 75 var pending = false; 76 var observer = new MutationObserver(function () { 77 if (pending) { 78 return; 79 } 80 pending = true; 81 window.setTimeout(function () { 82 pending = false; 83 fixSwitcher(document); 84 }, 100); 85 }); 86 87 observer.observe(document.body, { childList: true, subtree: true }); 88 } 89 90 if (document.readyState === 'loading') { 91 document.addEventListener('DOMContentLoaded', init); 92 } else { 93 init(); 94 } 95})();
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.