[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 (function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? factory() : 3 typeof define === 'function' && define.amd ? define(factory) : 4 (factory()); 5 }(this, (function () { 'use strict'; 6 7 /** 8 * Applies the :focus-visible polyfill at the given scope. 9 * A scope in this case is either the top-level Document or a Shadow Root. 10 * 11 * @param {(Document|ShadowRoot)} scope 12 * @see https://github.com/WICG/focus-visible 13 */ 14 function applyFocusVisiblePolyfill(scope) { 15 var hadKeyboardEvent = true; 16 var hadFocusVisibleRecently = false; 17 var hadFocusVisibleRecentlyTimeout = null; 18 19 var inputTypesAllowlist = { 20 text: true, 21 search: true, 22 url: true, 23 tel: true, 24 email: true, 25 password: true, 26 number: true, 27 date: true, 28 month: true, 29 week: true, 30 time: true, 31 datetime: true, 32 'datetime-local': true 33 }; 34 35 /** 36 * Helper function for legacy browsers and iframes which sometimes focus 37 * elements like document, body, and non-interactive SVG. 38 * @param {Element} el 39 */ 40 function isValidFocusTarget(el) { 41 if ( 42 el && 43 el !== document && 44 el.nodeName !== 'HTML' && 45 el.nodeName !== 'BODY' && 46 'classList' in el && 47 'contains' in el.classList 48 ) { 49 return true; 50 } 51 return false; 52 } 53 54 /** 55 * Computes whether the given element should automatically trigger the 56 * `focus-visible` class being added, i.e. whether it should always match 57 * `:focus-visible` when focused. 58 * @param {Element} el 59 * @return {boolean} 60 */ 61 function focusTriggersKeyboardModality(el) { 62 var type = el.type; 63 var tagName = el.tagName; 64 65 if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) { 66 return true; 67 } 68 69 if (tagName === 'TEXTAREA' && !el.readOnly) { 70 return true; 71 } 72 73 if (el.isContentEditable) { 74 return true; 75 } 76 77 return false; 78 } 79 80 /** 81 * Add the `focus-visible` class to the given element if it was not added by 82 * the author. 83 * @param {Element} el 84 */ 85 function addFocusVisibleClass(el) { 86 if (el.classList.contains('focus-visible')) { 87 return; 88 } 89 el.classList.add('focus-visible'); 90 el.setAttribute('data-focus-visible-added', ''); 91 } 92 93 /** 94 * Remove the `focus-visible` class from the given element if it was not 95 * originally added by the author. 96 * @param {Element} el 97 */ 98 function removeFocusVisibleClass(el) { 99 if (!el.hasAttribute('data-focus-visible-added')) { 100 return; 101 } 102 el.classList.remove('focus-visible'); 103 el.removeAttribute('data-focus-visible-added'); 104 } 105 106 /** 107 * If the most recent user interaction was via the keyboard; 108 * and the key press did not include a meta, alt/option, or control key; 109 * then the modality is keyboard. Otherwise, the modality is not keyboard. 110 * Apply `focus-visible` to any current active element and keep track 111 * of our keyboard modality state with `hadKeyboardEvent`. 112 * @param {KeyboardEvent} e 113 */ 114 function onKeyDown(e) { 115 if (e.metaKey || e.altKey || e.ctrlKey) { 116 return; 117 } 118 119 if (isValidFocusTarget(scope.activeElement)) { 120 addFocusVisibleClass(scope.activeElement); 121 } 122 123 hadKeyboardEvent = true; 124 } 125 126 /** 127 * If at any point a user clicks with a pointing device, ensure that we change 128 * the modality away from keyboard. 129 * This avoids the situation where a user presses a key on an already focused 130 * element, and then clicks on a different element, focusing it with a 131 * pointing device, while we still think we're in keyboard modality. 132 * @param {Event} e 133 */ 134 function onPointerDown(e) { 135 hadKeyboardEvent = false; 136 } 137 138 /** 139 * On `focus`, add the `focus-visible` class to the target if: 140 * - the target received focus as a result of keyboard navigation, or 141 * - the event target is an element that will likely require interaction 142 * via the keyboard (e.g. a text box) 143 * @param {Event} e 144 */ 145 function onFocus(e) { 146 // Prevent IE from focusing the document or HTML element. 147 if (!isValidFocusTarget(e.target)) { 148 return; 149 } 150 151 if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) { 152 addFocusVisibleClass(e.target); 153 } 154 } 155 156 /** 157 * On `blur`, remove the `focus-visible` class from the target. 158 * @param {Event} e 159 */ 160 function onBlur(e) { 161 if (!isValidFocusTarget(e.target)) { 162 return; 163 } 164 165 if ( 166 e.target.classList.contains('focus-visible') || 167 e.target.hasAttribute('data-focus-visible-added') 168 ) { 169 // To detect a tab/window switch, we look for a blur event followed 170 // rapidly by a visibility change. 171 // If we don't see a visibility change within 100ms, it's probably a 172 // regular focus change. 173 hadFocusVisibleRecently = true; 174 window.clearTimeout(hadFocusVisibleRecentlyTimeout); 175 hadFocusVisibleRecentlyTimeout = window.setTimeout(function() { 176 hadFocusVisibleRecently = false; 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 && e.target.nodeName.toLowerCase() === 'html') { 241 return; 242 } 243 244 hadKeyboardEvent = false; 245 removeInitialPointerMoveListeners(); 246 } 247 248 // For some kinds of state, we are interested in changes at the global scope 249 // only. For example, global pointer input, global key presses and global 250 // visibility change should affect the state at every scope: 251 document.addEventListener('keydown', onKeyDown, true); 252 document.addEventListener('mousedown', onPointerDown, true); 253 document.addEventListener('pointerdown', onPointerDown, true); 254 document.addEventListener('touchstart', onPointerDown, true); 255 document.addEventListener('visibilitychange', onVisibilityChange, true); 256 257 addInitialPointerMoveListeners(); 258 259 // For focus and blur, we specifically care about state changes in the local 260 // scope. This is because focus / blur events that originate from within a 261 // shadow root are not re-dispatched from the host element if it was already 262 // the active element in its own scope: 263 scope.addEventListener('focus', onFocus, true); 264 scope.addEventListener('blur', onBlur, true); 265 266 // We detect that a node is a ShadowRoot by ensuring that it is a 267 // DocumentFragment and also has a host property. This check covers native 268 // implementation and polyfill implementation transparently. If we only cared 269 // about the native implementation, we could just check if the scope was 270 // an instance of a ShadowRoot. 271 if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) { 272 // Since a ShadowRoot is a special kind of DocumentFragment, it does not 273 // have a root element to add a class to. So, we add this attribute to the 274 // host element instead: 275 scope.host.setAttribute('data-js-focus-visible', ''); 276 } else if (scope.nodeType === Node.DOCUMENT_NODE) { 277 document.documentElement.classList.add('js-focus-visible'); 278 document.documentElement.setAttribute('data-js-focus-visible', ''); 279 } 280 } 281 282 // It is important to wrap all references to global window and document in 283 // these checks to support server-side rendering use cases 284 // @see https://github.com/WICG/focus-visible/issues/199 285 if (typeof window !== 'undefined' && typeof document !== 'undefined') { 286 // Make the polyfill helper globally available. This can be used as a signal 287 // to interested libraries that wish to coordinate with the polyfill for e.g., 288 // applying the polyfill to a shadow root: 289 window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill; 290 291 // Notify interested libraries of the polyfill's presence, in case the 292 // polyfill was loaded lazily: 293 var event; 294 295 try { 296 event = new CustomEvent('focus-visible-polyfill-ready'); 297 } catch (error) { 298 // IE11 does not support using CustomEvent as a constructor directly: 299 event = document.createEvent('CustomEvent'); 300 event.initCustomEvent('focus-visible-polyfill-ready', false, false, {}); 301 } 302 303 window.dispatchEvent(event); 304 } 305 306 if (typeof document !== 'undefined') { 307 // Apply the polyfill to the global document, so that no JavaScript 308 // coordination is required to use the polyfill in the top-level document: 309 applyFocusVisiblePolyfill(document); 310 } 311 312 })));
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |