1//* 9fbef606107a605d69c0edbcd8029e5d *// 2/* eslint-disable */ 3(function(global, factory) { 4 typeof exports === 'object' && typeof module !== 'undefined' 5 ? factory() 6 : typeof define === 'function' && define.amd 7 ? define(factory) 8 : factory(); 9})(this, function() { 10 'use strict'; 11 12 /** 13 * https://github.com/WICG/focus-visible 14 */ 15 function init() { 16 var hadKeyboardEvent = true; 17 var hadFocusVisibleRecently = false; 18 var hadFocusVisibleRecentlyTimeout = null; 19 20 var inputTypesWhitelist = { 21 text: true, 22 search: true, 23 url: true, 24 tel: true, 25 email: true, 26 password: true, 27 number: true, 28 date: true, 29 month: true, 30 week: true, 31 time: true, 32 datetime: true, 33 'datetime-local': true, 34 }; 35 36 /** 37 * Helper function for legacy browsers and iframes which sometimes focus 38 * elements like document, body, and non-interactive SVG. 39 * @param {Element} el 40 */ 41 function isValidFocusTarget(el) { 42 if ( 43 el && 44 el !== document && 45 el.nodeName !== 'HTML' && 46 el.nodeName !== 'BODY' && 47 'classList' in el && 48 'contains' in el.classList 49 ) { 50 return true; 51 } 52 return false; 53 } 54 55 /** 56 * Computes whether the given element should automatically trigger the 57 * `focus-visible` class being added, i.e. whether it should always match 58 * `:focus-visible` when focused. 59 * @param {Element} el 60 * @returns {boolean} 61 */ 62 function focusTriggersKeyboardModality(el) { 63 var type = el.type; 64 var tagName = el.tagName; 65 66 if (tagName == 'INPUT' && inputTypesWhitelist[type] && !el.readOnly) { 67 return true; 68 } 69 70 if (tagName == 'TEXTAREA' && !el.readOnly) { 71 return true; 72 } 73 74 if (el.isContentEditable) { 75 return true; 76 } 77 78 return false; 79 } 80 81 /** 82 * Add the `focus-visible` class to the given element if it was not added by 83 * the author. 84 * @param {Element} el 85 */ 86 function addFocusVisibleClass(el) { 87 if (el) { 88 if (el.classList.contains('focus-visible')) { 89 return; 90 } 91 el.classList.add('focus-visible'); 92 el.setAttribute('data-focus-visible-added', ''); 93 } 94 } 95 96 /** 97 * Remove the `focus-visible` class from the given element if it was not 98 * originally added by the author. 99 * @param {Element} el 100 */ 101 function removeFocusVisibleClass(el) { 102 if (el){ 103 if (!el.hasAttribute('data-focus-visible-added')) { 104 return; 105 } 106 el.classList.remove('focus-visible'); 107 el.removeAttribute('data-focus-visible-added'); 108 } 109 } 110 111 /** 112 * Treat `keydown` as a signal that the user is in keyboard modality. 113 * Apply `focus-visible` to any current active element and keep track 114 * of our keyboard modality state with `hadKeyboardEvent`. 115 * @param {Event} e 116 */ 117 function onKeyDown(e) { 118 if (isValidFocusTarget(document.activeElement)) { 119 addFocusVisibleClass(document.activeElement); 120 } 121 122 hadKeyboardEvent = true; 123 } 124 125 /** 126 * If at any point a user clicks with a pointing device, ensure that we change 127 * the modality away from keyboard. 128 * This avoids the situation where a user presses a key on an already focused 129 * element, and then clicks on a different element, focusing it with a 130 * pointing device, while we still think we're in keyboard modality. 131 * @param {Event} e 132 */ 133 function onPointerDown(e) { 134 hadKeyboardEvent = false; 135 } 136 137 /** 138 * On `focus`, add the `focus-visible` class to the target if: 139 * - the target received focus as a result of keyboard navigation, or 140 * - the event target is an element that will likely require interaction 141 * via the keyboard (e.g. a text box) 142 * @param {Event} e 143 */ 144 function onFocus(e) { 145 // Prevent IE from focusing the document or HTML element. 146 if (!isValidFocusTarget(e.target)) { 147 return; 148 } 149 150 if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) { 151 addFocusVisibleClass(e.target); 152 } 153 } 154 155 /** 156 * On `blur`, remove the `focus-visible` class from the target. 157 * @param {Event} e 158 */ 159 function onBlur(e) { 160 if (!isValidFocusTarget(e.target)) { 161 return; 162 } 163 164 if ( 165 e.target.classList.contains('focus-visible') || 166 e.target.hasAttribute('data-focus-visible-added') 167 ) { 168 // To detect a tab/window switch, we look for a blur event followed 169 // rapidly by a visibility change. 170 // If we don't see a visibility change within 100ms, it's probably a 171 // regular focus change. 172 hadFocusVisibleRecently = true; 173 window.clearTimeout(hadFocusVisibleRecentlyTimeout); 174 hadFocusVisibleRecentlyTimeout = window.setTimeout(function() { 175 hadFocusVisibleRecently = false;
176 window.clearTimeout(hadFocusVisibleRecentlyTimeout); 177 }, 100); 178 removeFocusVisibleClass(e.target); 179 } 180 } 181 182 /** 183 * If the user changes tabs, keep track of whether or not the previously 184 * focused element had .focus-visible. 185 * @param {Event} e 186 */ 187 function onVisibilityChange(e) { 188 if (document.visibilityState == 'hidden') { 189 // If the tab becomes active again, the browser will handle calling focus 190 // on the element (Safari actually calls it twice). 191 // If this tab change caused a blur on an element with focus-visible, 192 // re-apply the class when the user switches back to the tab. 193 if (hadFocusVisibleRecently) { 194 hadKeyboardEvent = true; 195 } 196 addInitialPointerMoveListeners(); 197 } 198 } 199 200 /** 201 * Add a group of listeners to detect usage of any pointing devices. 202 * These listeners will be added when the polyfill first loads, and anytime 203 * the window is blurred, so that they are active when the window regains 204 * focus. 205 */ 206 function addInitialPointerMoveListeners() { 207 document.addEventListener('mousemove', onInitialPointerMove); 208 document.addEventListener('mousedown', onInitialPointerMove); 209 document.addEventListener('mouseup', onInitialPointerMove); 210 document.addEventListener('pointermove', onInitialPointerMove); 211 document.addEventListener('pointerdown', onInitialPointerMove); 212 document.addEventListener('pointerup', onInitialPointerMove); 213 document.addEventListener('touchmove', onInitialPointerMove); 214 document.addEventListener('touchstart', onInitialPointerMove); 215 document.addEventListener('touchend', onInitialPointerMove); 216 } 217 218 function removeInitialPointerMoveListeners() { 219 document.removeEventListener('mousemove', onInitialPointerMove); 220 document.removeEventListener('mousedown', onInitialPointerMove); 221 document.removeEventListener('mouseup', onInitialPointerMove); 222 document.removeEventListener('pointermove', onInitialPointerMove); 223 document.removeEventListener('pointerdown', onInitialPointerMove); 224 document.removeEventListener('pointerup', onInitialPointerMove); 225 document.removeEventListener('touchmove', onInitialPointerMove); 226 document.removeEventListener('touchstart', onInitialPointerMove); 227 document.removeEventListener('touchend', onInitialPointerMove); 228 } 229 230 /** 231 * When the polfyill first loads, assume the user is in keyboard modality. 232 * If any event is received from a pointing device (e.g. mouse, pointer, 233 * touch), turn off keyboard modality. 234 * This accounts for situations where focus enters the page from the URL bar. 235 * @param {Event} e 236 */ 237 function onInitialPointerMove(e) { 238 // Work around a Safari quirk that fires a mousemove on <html> whenever the 239 // window blurs, even if you're tabbing out of the page. ¯\_(ã)_/¯ 240 if (e.target.nodeName.toLowerCase() === 'html') { 241 return; 242 } 243 244 hadKeyboardEvent = false; 245 removeInitialPointerMoveListeners(); 246 } 247 248 document.addEventListener('keydown', onKeyDown, true); 249 document.addEventListener('mousedown', onPointerDown, true); 250 document.addEventListener('pointerdown', onPointerDown, true); 251 document.addEventListener('touchstart', onPointerDown, true); 252 document.addEventListener('focus', onFocus, true); 253 document.addEventListener('blur', onBlur, true); 254 document.addEventListener('visibilitychange', onVisibilityChange, true); 255 addInitialPointerMoveListeners(); 256 257 document.body.classList.add('js-focus-visible'); 258 } 259 260 /** 261 * Subscription when the DOM is ready 262 * @param {Function} callback 263 */ 264 function onDOMReady(callback) { 265 var loaded; 266 267 /** 268 * Callback wrapper for check loaded state 269 */ 270 function load() { 271 if (!loaded) { 272 loaded = true; 273 274 callback(); 275 } 276 } 277 278 if (['interactive', 'complete'].indexOf(document.readyState) >= 0) { 279 callback(); 280 } else { 281 loaded = false; 282 document.addEventListener('DOMContentLoaded', load, false); 283 window.addEventListener('load', load, false); 284 } 285 } 286 287 if (typeof document !== 'undefined') { 288 onDOMReady(init); 289 } 290}); 291/* eslint-enable */
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.