isTabbable: function()

in src/core/util/util.js [1070:1135]


    isTabbable: function(element) {
      var frameElement = $mdUtil.getFrameElement($mdUtil.getWindow(element));

      if (frameElement) {
        // Frame elements inherit their tabindex onto all child elements.
        if ($mdUtil.getTabIndexValue(frameElement) === -1) {
          return false;
        }

        // Browsers disable tabbing to an element inside of an invisible frame.
        if (!$mdUtil.isVisible(frameElement)) {
          return false;
        }
      }

      var nodeName = element.nodeName.toLowerCase();
      var tabIndexValue = $mdUtil.getTabIndexValue(element);

      if (element.hasAttribute('contenteditable')) {
        return tabIndexValue !== -1;
      }

      if (nodeName === 'iframe' || nodeName === 'object') {
        // The frame or object's content may be tabbable depending on the content, but it's
        // not possibly to reliably detect the content of the frames. We always consider such
        // elements as non-tabbable.
        return false;
      }

      // In iOS, the browser only considers some specific elements as tabbable.
      if (isIos && !$mdUtil.isPotentiallyTabbableIOS(element)) {
        return false;
      }

      if (nodeName === 'audio') {
        // Audio elements without controls enabled are never tabbable, regardless
        // of the tabindex attribute explicitly being set.
        if (!element.hasAttribute('controls')) {
          return false;
        }
        // Audio elements with controls are by default tabbable unless the
        // tabindex attribute is set to `-1` explicitly.
        return tabIndexValue !== -1;
      }

      if (nodeName === 'video') {
        // For all video elements, if the tabindex attribute is set to `-1`, the video
        // is not tabbable. Note: We cannot rely on the default `HTMLElement.tabIndex`
        // property as that one is set to `-1` in Chrome, Edge and Safari v13.1. The
        // tabindex attribute is the source of truth here.
        if (tabIndexValue === -1) {
          return false;
        }
        // If the tabindex is explicitly set, and not `-1` (as per check before), the
        // video element is always tabbable (regardless of whether it has controls or not).
        if (tabIndexValue !== null) {
          return true;
        }
        // Otherwise (when no explicit tabindex is set), a video is only tabbable if it
        // has controls enabled. Firefox is special as videos are always tabbable regardless
        // of whether there are controls or not.
        return isFirefox || element.hasAttribute('controls');
      }

      return element.tabIndex >= 0;
    },