1/* 2 * This script does the following: 3 * - Converts anchor links href="#foo" to the proper URL href="https://www.site.org/dbpage...#foo" 4 * - Listens for the "click" event on these links, then corrects the scroll position. 5 * Why use requestAnimationFrame()? 6 * 1) setTimeout() is less reliable. 7 * 2) Listening for 'hashchange' on window won't trigger if you click the same section twice in a row. 8 * 9 * Also aded: Code for improving "Visually impaired" mode 10 */ 11document.addEventListener('DOMContentLoaded', function () 12{ 13 const pageURLWithoutHash = window.location.href.replace(/#[^#]*$/, '') 14 const html = document.querySelector('html') 15 const pageLinks = document.querySelectorAll('a[href^="#"]:not([href^="#tab-"])') 16 const header = document.querySelector('header') 17 const themeIsStockholm = Boolean(document.querySelector('head link[rel="stylesheet"][href*="themes/Stockholm"]')) 18 const themeIsMercury = Boolean(document.querySelector('head link[rel="stylesheet"][href*="themes/Mercury"]')) 19 20 for (const pageLink of pageLinks) 21 { 22 // This ignores tab links, e.g. on https://www.barbershop.org.au/Contact 23 if (pageLink.parentElement.parentElement.classList.contains('tabList')) 24 continue 25 26 pageLink.href = pageLink.href.replace(window.location.origin + '/', pageURLWithoutHash) 27 pageLink.addEventListener('click', function () 28 { 29 const originalScrollTop = html.scrollTop 30 31 function tryUpdateScroll() 32 { 33 const scrollTop = html.scrollTop 34 35 if (scrollTop === originalScrollTop) 36 { 37 window.requestAnimationFrame(tryUpdateScroll) 38 } 39 else 40 { 41 const stockholmHeaderIsSticky = themeIsStockholm && window.matchMedia('(min-width: 1001px)').matches 42 const mercuryHeaderIsSticky = themeIsMercury && window.matchMedia('(min-width: 641px)').matches 43 44 if (stockholmHeaderIsSticky || mercuryHeaderIsSticky) 45 { 46 html.scrollTop -= header.getBoundingClientRect().height 47 } 48 html.scrollTop -= 15 49 } 50 } 51 52 tryUpdateScroll() 53 }) 54 } 55}) 56 57/* Accessibility improvements */ 58 59document.addEventListener('DOMContentLoaded', () => { 60 document.body.insertAdjacentHTML('beforeend', ` 61 <span id="search-announcement" aria-live="assertive" class="ui-helper-hidden-accessible"></span> 62 `) 63 const searchAnnouncement = document.getElementById('search-announcement') 64 const searchBox = document.getElementById('_searchq') 65 searchBox.addEventListener('keydown', (ev) => { 66 if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') { 67 const focusedResult = document.querySelector('#ui-id-1 .ui-state-focus') 68 if (!focusedResult) return 69 focusedResult.innerHTML = focusedResult.innerHTML.replace(/<br>/g, '<br>\n') 70 searchAnnouncement.textContent = focusedResult.textContent.replace(/\n/g, ', ') 71 } 72 }) 73}) 74 75$(document).ready(() => { 76 let previousFocus 77 jQuery('body').on('dialogopen', (ev) => { 78 previousFocus = document.activeElement 79 ev.target.parentElement.focus() 80 }) 81 jQuery('body').on('dialogclose', (ev) => { 82 if (window.location.href.includes('dbpage.php?pg=newmemwiz')) { 83 const selectedStep = document.querySelector('.selectedstep') 84 selectedStep.setAttribute('tabindex', '-1') 85 selectedStep.focus() 86 } else { 87 previousFocus.focus() 88 } 89 previousFocus = null 90 }) 91})
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.