[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/vendor/focus-visible/js/ -> focus-visible.js (source)

   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  })));


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer