1if ( !window.USC ) { window.USC = {}; } 2require2( ['usc/p/usc-utils', 'usc/p/slide-toggle'], function () { 3 4 window.USC.showHide = function ( e ) { 5 6 var defaultOptions = { 7 // The class added is customizable. 8 className: 'show', 9 // Do you need a class added to the html element? It goes on the container by default. 10 htmlClass: false, 11 // Should the panel slide open and shut? 12 slider: false 13 } 14 15 // Define the elements 16 var el = e.target; 17 var type = e.type; 18 var box = el.closest( '[data-showhide]' ); 19 var panel = box.querySelector( '[data-role="panel"]' ); 20 var btns = Array.from( box.querySelectorAll( '[data-role="btn"]' ) ); 21 var focusable = Array.from( panel.querySelectorAll( 'a, button, input, select, [tabindex="0"], video' )); 22 var lastFocus = focusable.pop(); 23 var returnSpot = btns[0]; 24 var videos = Array.from(panel.querySelectorAll( 'video' )); 25 26 if ( !lastFocus ) lastFocus = panel; 27 28 // Set the options 29 var data = USC.elementData( box ); 30 el.options = Object.assign( {}, defaultOptions, data ); 31 32 // Create the toggling functionality 33 function toggleActive( el, e ) { 34 35 // Check our active state and toggle some functionality 36 var active = ( !panel.getAttribute( 'aria-hidden' ) || panel.getAttribute( 'aria-hidden' ) === "true" ) ? false : true; 37 38 // If the slider option is turned on, trigger the slider functionality 39 if ( el.options.slider === true ) USC.slideToggle( panel, !active ) 40 41 // Toggle our classes and attributes 42 box.classList.toggle( el.options.className ); 43 if ( el.options.htmlClass ) document.documentElement.classList.toggle( el.options.className ); 44 panel.setAttribute( 'aria-hidden', active ); 45 46 // Set the state of the buttons 47 btns.forEach((btn) => { 48 btn.setAttribute('aria-expanded', !active); 49 }); 50 51 // Set the state of videos and set our focus depending on if we're closing or opening a panel 52 if ( active ) { 53 // Loop through and pause our videos if we close a panel 54 videos.forEach( function ( vid ) { 55 try { vid.pause(); } 56 catch ( ex ) { ; } 57 } ); 58 59 // Make focusable items non-focusable if closing 60 focusable.forEach((el) => { 61 el.setAttribute('tabindex','-1'); 62 }); 63 panel.setAttribute('tabindex', '-1'); 64 65 returnSpot.focus(); 66 } else { 67 // Play our first video if we have one when we open a panel 68 if ( videos[0] && videos[0].readyState >= 1 ) { 69 initVideo( videos[0] ).then( video => { 70 try { video.play(); } 71 catch ( ex ) { ; } 72 } ); 73 } 74 75 // Make focusable items focusable when opening 76 focusable.forEach((el) => { 77 el.setAttribute('tabindex','0'); 78 }); 79 panel.setAttribute('tabindex','0'); 80 panel.focus(); 81 } 82 83 } 84 85 // Before we run everything, validate to make sure our targets and types are correct 86 var run; 87 88 // if we click or pressed enter on a button 89 if ( e.keyCode === 13 && el.closest( '[data-role="btn"]' ) || type == 'click' && el.closest( '[data-role="btn"]' ) ) run = true; 90 91 // if we pressed escape on a showhide element 92 if ( e.keyCode == 27 && el.closest( '[data-showhide]' ) ) run = true; 93 94 // if we pressed tab 95 if ( e.keyCode === 9 ) { 96 97 // If shift was held to move back and we're on the panel, toggle the panel 98 if ( e.shiftKey && panel == el ) { 99 run = true; 100 e.preventDefault(); 101 returnSpot.focus(); 102 } 103 // If moving forward and we're currently on our last element, toggle the panel 104 else if ( !e.shiftKey && lastFocus == el ) { 105 run = true; 106 lastFocus = panel; 107 } 108 109 } 110 111 // Fire when ready 112 if ( run === true ) toggleActive( el, e ); 113 114 }; 115 116 function initVideo( video ) { 117 return new Promise( resolve => { 118 if ( !window._sa_videoStart || video.$videoEvents ) { 119 // Make sure we have scorpion analytics on the page, that the video hasn't already been wired up. 120 resolve( video ); 121 return; 122 } else if ( USC.initAnalytics ) { 123 // If the video script has already been loaded, run it. 124 USC.initAnalytics( video ); 125 resolve( video ); 126 return; 127 } 128 129 // Load the video script. 130 require2( '/common/usc/p/video.js' ); 131 132 // As soon as it's loaded we'll resolve the promiser. 133 let _interval = 0; 134 const _max_wait_time = 2000; 135 const _start = performance.now(); 136 const fn = () => { 137 if ( USC.initAnalytics ) { 138 // It's loaded and ready. 139 clearInterval( _interval ); 140 USC.initAnalytics( video ); 141 resolve( video ); 142 return; 143 } 144 145 let _now = performance.now(); 146 if ( _now - _start > _max_wait_time ) { 147 // Can't wait any longer. 148 clearInterval( _interval ); 149 resolve( video ); 150 return; 151 } 152 }; 153 _interval = setInterval( fn, 250 ); 154 } ); 155 } 156 157 if ( window.register ) { 158 window.register( 'usc/p/passive-show-hide' ); 159 } 160 161} );
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.