/* eslint-disable */ // @ts-nocheck // Copied from https://github.com/medialize/ally.js // License: MIT // Copyright (c) 2015 Rodney Rehm // // Entrypoint: ally.js/maintain/tab-focus "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return _default; } }); const _interop_require_default = require("@swc/helpers/_/_interop_require_default"); const _platform = /*#__PURE__*/ _interop_require_default._(require("next/dist/compiled/platform")); const _cssescape = /*#__PURE__*/ _interop_require_default._(require("next/dist/compiled/css.escape")); // input may be undefined, selector-tring, Node, NodeList, HTMLCollection, array of Nodes // yes, to some extent this is a bad replica of jQuery's constructor function function nodeArray(input) { if (!input) { return []; } if (Array.isArray(input)) { return input; } // instanceof Node - does not work with iframes if (input.nodeType !== undefined) { return [ input ]; } if (typeof input === "string") { input = document.querySelectorAll(input); } if (input.length !== undefined) { return [].slice.call(input, 0); } throw new TypeError("unexpected input " + String(input)); } function contextToElement(_ref) { var context = _ref.context, _ref$label = _ref.label, label = _ref$label === undefined ? "context-to-element" : _ref$label, resolveDocument = _ref.resolveDocument, defaultToDocument = _ref.defaultToDocument; var element = nodeArray(context)[0]; if (resolveDocument && element && element.nodeType === Node.DOCUMENT_NODE) { element = element.documentElement; } if (!element && defaultToDocument) { return document.documentElement; } if (!element) { throw new TypeError(label + " requires valid options.context"); } if (element.nodeType !== Node.ELEMENT_NODE && element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) { throw new TypeError(label + " requires options.context to be an Element"); } return element; } function getShadowHost() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, context = _ref.context; var element = contextToElement({ label: "get/shadow-host", context: context }); // walk up to the root var container = null; while(element){ container = element; element = element.parentNode; } // https://developer.mozilla.org/docs/Web/API/Node.nodeType // NOTE: Firefox 34 does not expose ShadowRoot.host (but 37 does) if (container.nodeType === container.DOCUMENT_FRAGMENT_NODE && container.host) { // the root is attached to a fragment node that has a host return container.host; } return null; } function getDocument(node) { if (!node) { return document; } if (node.nodeType === Node.DOCUMENT_NODE) { return node; } return node.ownerDocument || document; } function isActiveElement(context) { var element = contextToElement({ label: "is/active-element", resolveDocument: true, context: context }); var _document = getDocument(element); if (_document.activeElement === element) { return true; } var shadowHost = getShadowHost({ context: element }); if (shadowHost && shadowHost.shadowRoot.activeElement === element) { return true; } return false; } // [elem, elem.parent, elem.parent.parent, …, html] // will not contain the shadowRoot (DOCUMENT_FRAGMENT_NODE) and shadowHost function getParents() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, context = _ref.context; var list = []; var element = contextToElement({ label: "get/parents", context: context }); while(element){ list.push(element); // IE does know support parentElement on SVGElement element = element.parentNode; if (element && element.nodeType !== Node.ELEMENT_NODE) { element = null; } } return list; } // Element.prototype.matches may be available at a different name // https://developer.mozilla.org/en/docs/Web/API/Element/matches var names = [ "matches", "webkitMatchesSelector", "mozMatchesSelector", "msMatchesSelector" ]; var name = null; function findMethodName(element) { names.some(function(_name) { if (!element[_name]) { return false; } name = _name; return true; }); } function elementMatches(element, selector) { if (!name) { findMethodName(element); } return element[name](selector); } // deep clone of original platform var platform = JSON.parse(JSON.stringify(_platform.default)); // operating system var os = platform.os.family || ""; var ANDROID = os === "Android"; var WINDOWS = os.slice(0, 7) === "Windows"; var OSX = os === "OS X"; var IOS = os === "iOS"; // layout var BLINK = platform.layout === "Blink"; var GECKO = platform.layout === "Gecko"; var TRIDENT = platform.layout === "Trident"; var EDGE = platform.layout === "EdgeHTML"; var WEBKIT = platform.layout === "WebKit"; // browser version (not layout engine version!) var version = parseFloat(platform.version); var majorVersion = Math.floor(version); platform.majorVersion = majorVersion; platform.is = { // operating system ANDROID: ANDROID, WINDOWS: WINDOWS, OSX: OSX, IOS: IOS, // layout BLINK: BLINK, GECKO: GECKO, TRIDENT: TRIDENT, EDGE: EDGE, WEBKIT: WEBKIT, // INTERNET EXPLORERS IE9: TRIDENT && majorVersion === 9, IE10: TRIDENT && majorVersion === 10, IE11: TRIDENT && majorVersion === 11 }; function before() { var data = { // remember what had focus to restore after test activeElement: document.activeElement, // remember scroll positions to restore after test windowScrollTop: window.scrollTop, windowScrollLeft: window.scrollLeft, bodyScrollTop: document.body.scrollTop, bodyScrollLeft: document.body.scrollLeft }; // wrap tests in an element hidden from screen readers to prevent them // from announcing focus, which can be quite irritating to the user var iframe = document.createElement("iframe"); iframe.setAttribute("style", "position:absolute; position:fixed; top:0; left:-2px; width:1px; height:1px; overflow:hidden;"); iframe.setAttribute("aria-live", "off"); iframe.setAttribute("aria-busy", "true"); iframe.setAttribute("aria-hidden", "true"); document.body.appendChild(iframe); var _window = iframe.contentWindow; var _document = _window.document; _document.open(); _document.close(); var wrapper = _document.createElement("div"); _document.body.appendChild(wrapper); data.iframe = iframe; data.wrapper = wrapper; data.window = _window; data.document = _document; return data; } // options.element: // {string} element name // {function} callback(wrapper, document) to generate an element // options.mutate: (optional) // {function} callback(element, wrapper, document) to manipulate element prior to focus-test. // Can return DOMElement to define focus target (default: element) // options.validate: (optional) // {function} callback(element, focusTarget, document) to manipulate test-result function test(data, options) { // make sure we operate on a clean slate data.wrapper.innerHTML = ""; // create dummy element to test focusability of var element = typeof options.element === "string" ? data.document.createElement(options.element) : options.element(data.wrapper, data.document); // allow callback to further specify dummy element // and optionally define element to focus var focus = options.mutate && options.mutate(element, data.wrapper, data.document); if (!focus && focus !== false) { focus = element; } // element needs to be part of the DOM to be focusable !element.parentNode && data.wrapper.appendChild(element); // test if the element with invalid tabindex can be focused focus && focus.focus && focus.focus(); // validate test's result return options.validate ? options.validate(element, focus, data.document) : data.document.activeElement === focus; } function after(data) { // restore focus to what it was before test and cleanup if (data.activeElement === document.body) { document.activeElement && document.activeElement.blur && document.activeElement.blur(); if (platform.is.IE10) { // IE10 does not redirect focus to when the activeElement is removed document.body.focus(); } } else { data.activeElement && data.activeElement.focus && data.activeElement.focus(); } document.body.removeChild(data.iframe); // restore scroll position window.scrollTop = data.windowScrollTop; window.scrollLeft = data.windowScrollLeft; document.body.scrollTop = data.bodyScrollTop; document.body.scrollLeft = data.bodyScrollLeft; } function detectFocus(tests) { var data = before(); var results = {}; Object.keys(tests).map(function(key) { results[key] = test(data, tests[key]); }); after(data); return results; } // this file is overwritten by `npm run build:pre` var version$1 = "1.4.1"; /* Facility to cache test results in localStorage. USAGE: cache.get('key'); cache.set('key', 'value'); */ function readLocalStorage(key) { // allow reading from storage to retrieve previous support results // even while the document does not have focus var data = void 0; try { data = window.localStorage && window.localStorage.getItem(key); data = data ? JSON.parse(data) : {}; } catch (e) { data = {}; } return data; } function writeLocalStorage(key, value) { if (!document.hasFocus()) { // if the document does not have focus when tests are executed, focus() may // not be handled properly and events may not be dispatched immediately. // This can happen when a document is reloaded while Developer Tools have focus. try { window.localStorage && window.localStorage.removeItem(key); } catch (e) { // ignore } return; } try { window.localStorage && window.localStorage.setItem(key, JSON.stringify(value)); } catch (e) { // ignore } } var userAgent = typeof window !== "undefined" && window.navigator.userAgent || ""; var cacheKey = "ally-supports-cache"; var cache = readLocalStorage(cacheKey); // update the cache if ally or the user agent changed (newer version, etc) if (cache.userAgent !== userAgent || cache.version !== version$1) { cache = {}; } cache.userAgent = userAgent; cache.version = version$1; var cache$1 = { get: function get() { return cache; }, set: function set(values) { Object.keys(values).forEach(function(key) { cache[key] = values[key]; }); cache.time = new Date().toISOString(); writeLocalStorage(cacheKey, cache); } }; function cssShadowPiercingDeepCombinator() { var combinator = void 0; // see https://dev.w3.org/csswg/css-scoping-1/#deep-combinator // https://bugzilla.mozilla.org/show_bug.cgi?id=1117572 // https://code.google.com/p/chromium/issues/detail?id=446051 try { document.querySelector("html >>> :first-child"); combinator = ">>>"; } catch (noArrowArrowArrow) { try { // old syntax supported at least up to Chrome 41 // https://code.google.com/p/chromium/issues/detail?id=446051 document.querySelector("html /deep/ :first-child"); combinator = "/deep/"; } catch (noDeep) { combinator = ""; } } return combinator; } var gif = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; // https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-usemap var focusAreaImgTabindex = { element: "div", mutate: function mutate(element) { element.innerHTML = '' + '' + ''; return element.querySelector("area"); } }; // https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-usemap var focusAreaTabindex = { element: "div", mutate: function mutate(element) { element.innerHTML = '' + '' + ''; return false; }, validate: function validate(element, focusTarget, _document) { if (platform.is.GECKO) { // fixes https://github.com/medialize/ally.js/issues/35 // Firefox loads the DataURI asynchronously, causing a false-negative return true; } var focus = element.querySelector("area"); focus.focus(); return _document.activeElement === focus; } }; // https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-usemap var focusAreaWithoutHref = { element: "div", mutate: function mutate(element) { element.innerHTML = '' + '' + ''; return element.querySelector("area"); }, validate: function validate(element, focusTarget, _document) { if (platform.is.GECKO) { // fixes https://github.com/medialize/ally.js/issues/35 // Firefox loads the DataURI asynchronously, causing a false-negative return true; } return _document.activeElement === focusTarget; } }; var focusAudioWithoutControls = { name: "can-focus-audio-without-controls", element: "audio", mutate: function mutate(element) { try { // invalid media file can trigger warning in console, data-uri to prevent HTTP request element.setAttribute("src", gif); } catch (e) { // IE9 may throw "Error: Not implemented" } } }; var invalidGif = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; // NOTE: https://github.com/medialize/ally.js/issues/35 // https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-usemap var focusBrokenImageMap = { element: "div", mutate: function mutate(element) { element.innerHTML = '' + ''; return element.querySelector("area"); } }; // Children of focusable elements with display:flex are focusable in IE10-11 var focusChildrenOfFocusableFlexbox = { element: "div", mutate: function mutate(element) { element.setAttribute("tabindex", "-1"); element.setAttribute("style", "display: -webkit-flex; display: -ms-flexbox; display: flex;"); element.innerHTML = 'hello'; return element.querySelector("span"); } }; // fieldset[tabindex=0][disabled] should not be focusable, but Blink and WebKit disagree // @specification https://www.w3.org/TR/html5/disabled-elements.html#concept-element-disabled // @browser-issue Chromium https://crbug.com/453847 // @browser-issue WebKit https://bugs.webkit.org/show_bug.cgi?id=141086 var focusFieldsetDisabled = { element: "fieldset", mutate: function mutate(element) { element.setAttribute("tabindex", 0); element.setAttribute("disabled", "disabled"); } }; var focusFieldset = { element: "fieldset", mutate: function mutate(element) { element.innerHTML = "legend

content

"; } }; // elements with display:flex are focusable in IE10-11 var focusFlexboxContainer = { element: "span", mutate: function mutate(element) { element.setAttribute("style", "display: -webkit-flex; display: -ms-flexbox; display: flex;"); element.innerHTML = 'hello'; } }; // form[tabindex=0][disabled] should be focusable as the // specification doesn't know the disabled attribute on the form element // @specification https://www.w3.org/TR/html5/forms.html#the-form-element var focusFormDisabled = { element: "form", mutate: function mutate(element) { element.setAttribute("tabindex", 0); element.setAttribute("disabled", "disabled"); } }; // NOTE: https://github.com/medialize/ally.js/issues/35 // fixes https://github.com/medialize/ally.js/issues/20 // https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-ismap var focusImgIsmap = { element: "a", mutate: function mutate(element) { element.href = "#void"; element.innerHTML = ''; return element.querySelector("img"); } }; // NOTE: https://github.com/medialize/ally.js/issues/35 // https://developer.mozilla.org/docs/Web/HTML/Element/img#attr-usemap var focusImgUsemapTabindex = { element: "div", mutate: function mutate(element) { element.innerHTML = '' + ''; return element.querySelector("img"); } }; var focusInHiddenIframe = { element: function element(wrapper, _document) { var iframe = _document.createElement("iframe"); // iframe must be part of the DOM before accessing the contentWindow is possible wrapper.appendChild(iframe); // create the iframe's default document () var iframeDocument = iframe.contentWindow.document; iframeDocument.open(); iframeDocument.close(); return iframe; }, mutate: function mutate(iframe) { iframe.style.visibility = "hidden"; var iframeDocument = iframe.contentWindow.document; var input = iframeDocument.createElement("input"); iframeDocument.body.appendChild(input); return input; }, validate: function validate(iframe) { var iframeDocument = iframe.contentWindow.document; var focus = iframeDocument.querySelector("input"); return iframeDocument.activeElement === focus; } }; var result = !platform.is.WEBKIT; function focusInZeroDimensionObject() { return result; } // Firefox allows *any* value and treats invalid values like tabindex="-1" // @browser-issue Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054 var focusInvalidTabindex = { element: "div", mutate: function mutate(element) { element.setAttribute("tabindex", "invalid-value"); } }; var focusLabelTabindex = { element: "label", mutate: function mutate(element) { element.setAttribute("tabindex", "-1"); }, validate: function validate(element, focusTarget, _document) { // force layout in Chrome 49, otherwise the element won't be focusable /* eslint-disable no-unused-vars */ var variableToPreventDeadCodeElimination = element.offsetHeight; /* eslint-enable no-unused-vars */ element.focus(); return _document.activeElement === element; } }; var svg = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtb" + "G5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBpZD0ic3ZnIj48dGV4dCB4PSIxMCIgeT0iMjAiIGlkPSJ" + "zdmctbGluay10ZXh0Ij50ZXh0PC90ZXh0Pjwvc3ZnPg=="; // Note: IE10 on BrowserStack does not like this test var focusObjectSvgHidden = { element: "object", mutate: function mutate(element) { element.setAttribute("type", "image/svg+xml"); element.setAttribute("data", svg); element.setAttribute("width", "200"); element.setAttribute("height", "50"); element.style.visibility = "hidden"; } }; // Note: IE10 on BrowserStack does not like this test var focusObjectSvg = { name: "can-focus-object-svg", element: "object", mutate: function mutate(element) { element.setAttribute("type", "image/svg+xml"); element.setAttribute("data", svg); element.setAttribute("width", "200"); element.setAttribute("height", "50"); }, validate: function validate(element, focusTarget, _document) { if (platform.is.GECKO) { // Firefox seems to be handling the object creation asynchronously and thereby produces a false negative test result. // Because we know Firefox is able to focus object elements referencing SVGs, we simply cheat by sniffing the user agent string return true; } return _document.activeElement === element; } }; // Every Environment except IE9 considers SWF objects focusable var result$1 = !platform.is.IE9; function focusObjectSwf() { return result$1; } var focusRedirectImgUsemap = { element: "div", mutate: function mutate(element) { element.innerHTML = '' + ''; // focus the , not the
return element.querySelector("img"); }, validate: function validate(element, focusTarget, _document) { var target = element.querySelector("area"); return _document.activeElement === target; } }; // see https://jsbin.com/nenirisage/edit?html,js,console,output var focusRedirectLegend = { element: "fieldset", mutate: function mutate(element) { element.innerHTML = 'legend'; // take care of focus in validate(); return false; }, validate: function validate(element, focusTarget, _document) { var focusable = element.querySelector('input[tabindex="-1"]'); var tabbable = element.querySelector('input[tabindex="0"]'); // Firefox requires this test to focus the
first, while this is not necessary in // https://jsbin.com/nenirisage/edit?html,js,console,output element.focus(); element.querySelector("legend").focus(); return _document.activeElement === focusable && "focusable" || _document.activeElement === tabbable && "tabbable" || ""; } }; // https://github.com/medialize/ally.js/issues/21 var focusScrollBody = { element: "div", mutate: function mutate(element) { element.setAttribute("style", "width: 100px; height: 50px; overflow: auto;"); element.innerHTML = '
scrollable content
'; return element.querySelector("div"); } }; // https://github.com/medialize/ally.js/issues/21 var focusScrollContainerWithoutOverflow = { element: "div", mutate: function mutate(element) { element.setAttribute("style", "width: 100px; height: 50px;"); element.innerHTML = '
scrollable content
'; } }; // https://github.com/medialize/ally.js/issues/21 var focusScrollContainer = { element: "div", mutate: function mutate(element) { element.setAttribute("style", "width: 100px; height: 50px; overflow: auto;"); element.innerHTML = '
scrollable content
'; } }; var focusSummary = { element: "details", mutate: function mutate(element) { element.innerHTML = "foo

content

"; return element.firstElementChild; } }; function makeFocusableForeignObject() { // Constructs // without raising a Trusted Types violation var foreignObject = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject"); foreignObject.width.baseVal.value = 30; foreignObject.height.baseVal.value = 30; foreignObject.appendChild(document.createElement("input")); foreignObject.lastChild.type = "text"; return foreignObject; } function focusSvgForeignObjectHack(element) { // Edge13, Edge14: foreignObject focus hack // https://jsbin.com/kunehinugi/edit?html,js,output // https://jsbin.com/fajagi/3/edit?html,js,output var isSvgElement = element.ownerSVGElement || element.nodeName.toLowerCase() === "svg"; if (!isSvgElement) { return false; } // inject and focus an element into the SVG element to receive focus var foreignObject = makeFocusableForeignObject(); element.appendChild(foreignObject); var input = foreignObject.querySelector("input"); input.focus(); // upon disabling the activeElement, IE and Edge // will not shift focus to like all the other // browsers, but instead find the first focusable // ancestor and shift focus to that input.disabled = true; // clean up element.removeChild(foreignObject); return true; } function generate(element) { return '' + element + ""; } function focus(element) { if (element.focus) { return; } try { HTMLElement.prototype.focus.call(element); } catch (e) { focusSvgForeignObjectHack(element); } } function validate(element, focusTarget, _document) { focus(focusTarget); return _document.activeElement === focusTarget; } var focusSvgFocusableAttribute = { element: "div", mutate: function mutate(element) { element.innerHTML = generate('a'); return element.querySelector("text"); }, validate: validate }; var focusSvgTabindexAttribute = { element: "div", mutate: function mutate(element) { element.innerHTML = generate('a'); return element.querySelector("text"); }, validate: validate }; var focusSvgNegativeTabindexAttribute = { element: "div", mutate: function mutate(element) { element.innerHTML = generate('a'); return element.querySelector("text"); }, validate: validate }; var focusSvgUseTabindex = { element: "div", mutate: function mutate(element) { element.innerHTML = generate([ 'link', '' ].join("")); return element.querySelector("use"); }, validate: validate }; var focusSvgForeignobjectTabindex = { element: "div", mutate: function mutate(element) { element.innerHTML = generate(''); // Safari 8's quersSelector() can't identify foreignObject, but getElementyByTagName() can return element.querySelector("foreignObject") || element.getElementsByTagName("foreignObject")[0]; }, validate: validate }; // Firefox seems to be handling the SVG-document-in-iframe creation asynchronously // and thereby produces a false negative test result. Thus the test is pointless // and we resort to UA sniffing once again. // see http://jsbin.com/vunadohoko/1/edit?js,console,output var result$2 = Boolean(platform.is.GECKO && typeof SVGElement !== "undefined" && SVGElement.prototype.focus); function focusSvgInIframe() { return result$2; } var focusSvg = { element: "div", mutate: function mutate(element) { element.innerHTML = generate(""); return element.firstChild; }, validate: validate }; // Firefox allows *any* value and treats invalid values like tabindex="-1" // @browser-issue Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054 var focusTabindexTrailingCharacters = { element: "div", mutate: function mutate(element) { element.setAttribute("tabindex", "3x"); } }; var focusTable = { element: "table", mutate: function mutate(element, wrapper, _document) { // IE9 has a problem replacing TBODY contents with innerHTML. // https://stackoverflow.com/a/8097055/515124 // element.innerHTML = 'cell'; var fragment = _document.createDocumentFragment(); fragment.innerHTML = "cell"; element.appendChild(fragment); } }; var focusVideoWithoutControls = { element: "video", mutate: function mutate(element) { try { // invalid media file can trigger warning in console, data-uri to prevent HTTP request element.setAttribute("src", gif); } catch (e) { // IE9 may throw "Error: Not implemented" } } }; // https://jsbin.com/vafaba/3/edit?html,js,console,output var result$3 = platform.is.GECKO || platform.is.TRIDENT || platform.is.EDGE; function tabsequenceAreaAtImgPosition() { return result$3; } var testCallbacks = { cssShadowPiercingDeepCombinator: cssShadowPiercingDeepCombinator, focusInZeroDimensionObject: focusInZeroDimensionObject, focusObjectSwf: focusObjectSwf, focusSvgInIframe: focusSvgInIframe, tabsequenceAreaAtImgPosition: tabsequenceAreaAtImgPosition }; var testDescriptions = { focusAreaImgTabindex: focusAreaImgTabindex, focusAreaTabindex: focusAreaTabindex, focusAreaWithoutHref: focusAreaWithoutHref, focusAudioWithoutControls: focusAudioWithoutControls, focusBrokenImageMap: focusBrokenImageMap, focusChildrenOfFocusableFlexbox: focusChildrenOfFocusableFlexbox, focusFieldsetDisabled: focusFieldsetDisabled, focusFieldset: focusFieldset, focusFlexboxContainer: focusFlexboxContainer, focusFormDisabled: focusFormDisabled, focusImgIsmap: focusImgIsmap, focusImgUsemapTabindex: focusImgUsemapTabindex, focusInHiddenIframe: focusInHiddenIframe, focusInvalidTabindex: focusInvalidTabindex, focusLabelTabindex: focusLabelTabindex, focusObjectSvg: focusObjectSvg, focusObjectSvgHidden: focusObjectSvgHidden, focusRedirectImgUsemap: focusRedirectImgUsemap, focusRedirectLegend: focusRedirectLegend, focusScrollBody: focusScrollBody, focusScrollContainerWithoutOverflow: focusScrollContainerWithoutOverflow, focusScrollContainer: focusScrollContainer, focusSummary: focusSummary, focusSvgFocusableAttribute: focusSvgFocusableAttribute, focusSvgTabindexAttribute: focusSvgTabindexAttribute, focusSvgNegativeTabindexAttribute: focusSvgNegativeTabindexAttribute, focusSvgUseTabindex: focusSvgUseTabindex, focusSvgForeignobjectTabindex: focusSvgForeignobjectTabindex, focusSvg: focusSvg, focusTabindexTrailingCharacters: focusTabindexTrailingCharacters, focusTable: focusTable, focusVideoWithoutControls: focusVideoWithoutControls }; function executeTests() { var results = detectFocus(testDescriptions); Object.keys(testCallbacks).forEach(function(key) { results[key] = testCallbacks[key](); }); return results; } var supportsCache = null; function _supports() { if (supportsCache) { return supportsCache; } supportsCache = cache$1.get(); if (!supportsCache.time) { cache$1.set(executeTests()); supportsCache = cache$1.get(); } return supportsCache; } var supports = void 0; // https://www.w3.org/TR/html5/infrastructure.html#rules-for-parsing-integers // NOTE: all browsers agree to allow trailing spaces as well var validIntegerPatternNoTrailing = /^\s*(-|\+)?[0-9]+\s*$/; var validIntegerPatternWithTrailing = /^\s*(-|\+)?[0-9]+.*$/; function isValidTabindex(context) { if (!supports) { supports = _supports(); } var validIntegerPattern = supports.focusTabindexTrailingCharacters ? validIntegerPatternWithTrailing : validIntegerPatternNoTrailing; var element = contextToElement({ label: "is/valid-tabindex", resolveDocument: true, context: context }); // Edge 14 has a capitalization problem on SVG elements, // see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9282058/ var hasTabindex = element.hasAttribute("tabindex"); var hasTabIndex = element.hasAttribute("tabIndex"); if (!hasTabindex && !hasTabIndex) { return false; } // older Firefox and Internet Explorer don't support tabindex on SVG elements var isSvgElement = element.ownerSVGElement || element.nodeName.toLowerCase() === "svg"; if (isSvgElement && !supports.focusSvgTabindexAttribute) { return false; } // @browser-issue Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054 if (supports.focusInvalidTabindex) { return true; } // an element matches the tabindex selector even if its value is invalid var tabindex = element.getAttribute(hasTabindex ? "tabindex" : "tabIndex"); // IE11 parses tabindex="" as the value "-32768" // @browser-issue Trident https://connect.microsoft.com/IE/feedback/details/1072965 if (tabindex === "-32768") { return false; } return Boolean(tabindex && validIntegerPattern.test(tabindex)); } function tabindexValue(element) { if (!isValidTabindex(element)) { return null; } // Edge 14 has a capitalization problem on SVG elements, // see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9282058/ var hasTabindex = element.hasAttribute("tabindex"); var attributeName = hasTabindex ? "tabindex" : "tabIndex"; // @browser-issue Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054 var tabindex = parseInt(element.getAttribute(attributeName), 10); return isNaN(tabindex) ? -1 : tabindex; } // this is a shared utility file for focus-relevant.js and tabbable.js // separate testing of this file's functions is not necessary, // as they're implicitly tested by way of the consumers function isUserModifyWritable(style) { // https://www.w3.org/TR/1999/WD-css3-userint-19990916#user-modify // https://github.com/medialize/ally.js/issues/17 var userModify = style.webkitUserModify || ""; return Boolean(userModify && userModify.indexOf("write") !== -1); } function hasCssOverflowScroll(style) { return [ style.getPropertyValue("overflow"), style.getPropertyValue("overflow-x"), style.getPropertyValue("overflow-y") ].some(function(overflow) { return overflow === "auto" || overflow === "scroll"; }); } function hasCssDisplayFlex(style) { return style.display.indexOf("flex") > -1; } function isScrollableContainer(element, nodeName, parentNodeName, parentStyle) { if (nodeName !== "div" && nodeName !== "span") { // Internet Explorer advances scrollable containers and bodies to focusable // only if the scrollable container is
or - this does *not* // happen for
,
, … return false; } if (parentNodeName && parentNodeName !== "div" && parentNodeName !== "span" && !hasCssOverflowScroll(parentStyle)) { return false; } return element.offsetHeight < element.scrollHeight || element.offsetWidth < element.scrollWidth; } var supports$1 = void 0; function isFocusRelevantRules() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, context = _ref.context, _ref$except = _ref.except, except = _ref$except === undefined ? { flexbox: false, scrollable: false, shadow: false } : _ref$except; if (!supports$1) { supports$1 = _supports(); } var element = contextToElement({ label: "is/focus-relevant", resolveDocument: true, context: context }); if (!except.shadow && element.shadowRoot) { // a ShadowDOM host receives focus when the focus moves to its content return true; } var nodeName = element.nodeName.toLowerCase(); if (nodeName === "input" && element.type === "hidden") { // input[type="hidden"] supports.cannot be focused return false; } if (nodeName === "input" || nodeName === "select" || nodeName === "button" || nodeName === "textarea") { return true; } if (nodeName === "legend" && supports$1.focusRedirectLegend) { // specifics filtered in is/focusable return true; } if (nodeName === "label") { // specifics filtered in is/focusable return true; } if (nodeName === "area") { // specifics filtered in is/focusable return true; } if (nodeName === "a" && element.hasAttribute("href")) { return true; } if (nodeName === "object" && element.hasAttribute("usemap")) { // object[usemap] is not focusable in any browser return false; } if (nodeName === "object") { var svgType = element.getAttribute("type"); if (!supports$1.focusObjectSvg && svgType === "image/svg+xml") { // object[type="image/svg+xml"] is not focusable in Internet Explorer return false; } else if (!supports$1.focusObjectSwf && svgType === "application/x-shockwave-flash") { // object[type="application/x-shockwave-flash"] is not focusable in Internet Explorer 9 return false; } } if (nodeName === "iframe" || nodeName === "object") { // browsing context containers return true; } if (nodeName === "embed" || nodeName === "keygen") { // embed is considered focus-relevant but not focusable // see https://github.com/medialize/ally.js/issues/82 return true; } if (element.hasAttribute("contenteditable")) { // also see CSS property user-modify below return true; } if (nodeName === "audio" && (supports$1.focusAudioWithoutControls || element.hasAttribute("controls"))) { return true; } if (nodeName === "video" && (supports$1.focusVideoWithoutControls || element.hasAttribute("controls"))) { return true; } if (supports$1.focusSummary && nodeName === "summary") { return true; } var validTabindex = isValidTabindex(element); if (nodeName === "img" && element.hasAttribute("usemap")) { // Gecko, Trident and Edge do not allow an image with an image map and tabindex to be focused, // it appears the tabindex is overruled so focus is still forwarded to the return validTabindex && supports$1.focusImgUsemapTabindex || supports$1.focusRedirectImgUsemap; } if (supports$1.focusTable && (nodeName === "table" || nodeName === "td")) { // IE10-11 supports.can focus and
return true; } if (supports$1.focusFieldset && nodeName === "fieldset") { // IE10-11 supports.can focus
return true; } var isSvgElement = nodeName === "svg"; var isSvgContent = element.ownerSVGElement; var focusableAttribute = element.getAttribute("focusable"); var tabindex = tabindexValue(element); if (nodeName === "use" && tabindex !== null && !supports$1.focusSvgUseTabindex) { // cannot be made focusable by adding a tabindex attribute anywhere but Blink and WebKit return false; } if (nodeName === "foreignobject") { // can only be made focusable in Blink and WebKit return tabindex !== null && supports$1.focusSvgForeignobjectTabindex; } if (elementMatches(element, "svg a") && element.hasAttribute("xlink:href")) { return true; } if ((isSvgElement || isSvgContent) && element.focus && !supports$1.focusSvgNegativeTabindexAttribute && tabindex < 0) { // Firefox 51 and 52 treat any natively tabbable SVG element with // tabindex="-1" as tabbable and everything else as inert // see https://bugzilla.mozilla.org/show_bug.cgi?id=1302340 return false; } if (isSvgElement) { return validTabindex || supports$1.focusSvg || supports$1.focusSvgInIframe || // Internet Explorer understands the focusable attribute introduced in SVG Tiny 1.2 Boolean(supports$1.focusSvgFocusableAttribute && focusableAttribute && focusableAttribute === "true"); } if (isSvgContent) { if (supports$1.focusSvgTabindexAttribute && validTabindex) { return true; } if (supports$1.focusSvgFocusableAttribute) { // Internet Explorer understands the focusable attribute introduced in SVG Tiny 1.2 return focusableAttribute === "true"; } } // https://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute if (validTabindex) { return true; } var style = window.getComputedStyle(element, null); if (isUserModifyWritable(style)) { return true; } if (supports$1.focusImgIsmap && nodeName === "img" && element.hasAttribute("ismap")) { // IE10-11 considers the in focusable // https://github.com/medialize/ally.js/issues/20 var hasLinkParent = getParents({ context: element }).some(function(parent) { return parent.nodeName.toLowerCase() === "a" && parent.hasAttribute("href"); }); if (hasLinkParent) { return true; } } // https://github.com/medialize/ally.js/issues/21 if (!except.scrollable && supports$1.focusScrollContainer) { if (supports$1.focusScrollContainerWithoutOverflow) { // Internet Explorer does will consider the scrollable area focusable // if the element is a
or a and it is in fact scrollable, // regardless of the CSS overflow property if (isScrollableContainer(element, nodeName)) { return true; } } else if (hasCssOverflowScroll(style)) { // Firefox requires proper overflow setting, IE does not necessarily // https://developer.mozilla.org/docs/Web/CSS/overflow return true; } } if (!except.flexbox && supports$1.focusFlexboxContainer && hasCssDisplayFlex(style)) { // elements with display:flex are focusable in IE10-11 return true; } var parent = element.parentElement; if (!except.scrollable && parent) { var parentNodeName = parent.nodeName.toLowerCase(); var parentStyle = window.getComputedStyle(parent, null); if (supports$1.focusScrollBody && isScrollableContainer(parent, nodeName, parentNodeName, parentStyle)) { // scrollable bodies are focusable Internet Explorer // https://github.com/medialize/ally.js/issues/21 return true; } // Children of focusable elements with display:flex are focusable in IE10-11 if (supports$1.focusChildrenOfFocusableFlexbox) { if (hasCssDisplayFlex(parentStyle)) { return true; } } } // NOTE: elements marked as inert are not focusable, // but that property is not exposed to the DOM // https://www.w3.org/TR/html5/editing.html#inert return false; } // bind exceptions to an iterator callback isFocusRelevantRules.except = function() { var except = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var isFocusRelevant = function isFocusRelevant(context) { return isFocusRelevantRules({ context: context, except: except }); }; isFocusRelevant.rules = isFocusRelevantRules; return isFocusRelevant; }; // provide isFocusRelevant(context) as default iterator callback var isFocusRelevant = isFocusRelevantRules.except({}); function findIndex(array, callback) { // attempt to use native or polyfilled Array#findIndex first if (array.findIndex) { return array.findIndex(callback); } var length = array.length; // shortcut if the array is empty if (length === 0) { return -1; } // otherwise loop over array for(var i = 0; i < length; i++){ if (callback(array[i], i, array)) { return i; } } return -1; } function getContentDocument(node) { try { // works on and