1/** 2 * UMBC Site Search â open/close fullscreen overlay + accessibility 3 * 4 * Triggers: any element matching OPEN_SELECTOR opens the modal. 5 * Close: #close button, Escape key, or clicking the backdrop. 6 */ 7( function () { 8 'use strict'; 9 10 var OPEN_SELECTOR = '.umbc-search-icon, .full-screen.umbc-search-icon, .astra-search-icon, .full-screen.astra-search-icon'; 11 var modal = null; 12 var closeBtn = null; 13 var lastFocus = null; 14 15 function openModal() { 16 if ( ! modal ) { return; } 17 modal.classList.add( 'active' ); 18 modal.removeAttribute( 'aria-hidden' ); 19 lastFocus = document.activeElement; 20 var input = modal.querySelector( '#desktop-search-input, .search-field' ); 21 if ( input ) { 22 setTimeout( function () { input.focus(); }, 50 ); 23 } 24 document.body.style.overflow = 'hidden'; 25 } 26 27 function closeModal() { 28 if ( ! modal ) { return; } 29 modal.classList.remove( 'active' ); 30 modal.setAttribute( 'aria-hidden', 'true' ); 31 document.body.style.overflow = ''; 32 if ( lastFocus ) { 33 lastFocus.focus(); 34 lastFocus = null; 35 } 36 } 37 38 function init() { 39 modal = document.getElementById( 'ast-seach-full-screen-form' ); 40 closeBtn = document.getElementById( 'close' ); 41 42 if ( ! modal ) { return; } 43 44 modal.setAttribute( 'aria-hidden', 'true' ); 45 46 // Open triggers 47 document.querySelectorAll( OPEN_SELECTOR ).forEach( function ( el ) { 48 el.addEventListener( 'click', function ( e ) { 49 e.preventDefault(); 50 openModal(); 51 } ); 52 } ); 53 54 // Close button 55 if ( closeBtn ) { 56 closeBtn.addEventListener( 'click', closeModal ); 57 } 58 59 // Escape key + focus trap 60 modal.addEventListener( 'keydown', function ( e ) { 61 if ( e.key === 'Escape' || e.keyCode === 27 ) { 62 closeModal(); 63 return; 64 } 65 if ( e.key !== 'Tab' ) { return; } 66 67 var focusable = Array.from( modal.querySelectorAll( 68 'button:not([disabled]), input, select, textarea, a[href], [tabindex]:not([tabindex="-1"])' 69 ) ); 70 if ( focusable.length === 0 ) { return; } 71 72 var first = focusable[0]; 73 var last = focusable[ focusable.length - 1 ]; 74 75 if ( e.shiftKey && document.activeElement === first ) { 76 e.preventDefault(); 77 last.focus(); 78 } else if ( ! e.shiftKey && document.activeElement === last ) { 79 e.preventDefault(); 80 first.focus(); 81 } 82 } ); 83 84 // Click backdrop to close (but not clicks inside the form) 85 modal.addEventListener( 'click', function ( e ) { 86 if ( ! e.target.closest( '.ast-search-wrapper, #close' ) ) { 87 closeModal(); 88 } 89 } ); 90 } 91 92 if ( document.readyState === 'loading' ) { 93 document.addEventListener( 'DOMContentLoaded', init ); 94 } else { 95 init(); 96 } 97 98} )();
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.