diff --git a/wtfocus.js b/wtfocus.js index ef4df13..33125eb 100644 --- a/wtfocus.js +++ b/wtfocus.js @@ -768,3 +768,14 @@ function WTFocus() { startFocusPoint.focus(); } WTFocus(); + + +// Select all iframes except those with the style display: none (only applies to inline CSS\) +// Create a script with the WTFocus code and append the script to every iframe. +// Enables the WTFocus selector to work within iframes +document.querySelectorAll('iframe:not([style*="display:none"]):not([style*="display: none"])').forEach(iframe => { + var s = document.createElement('script'); + var innerDoc = iframe.contentDocument || iframe.contentWindow.document; + s.text = "\"use strict\";\r\n\r\nfunction WTFocus() {\r\n const startFocusPoint = document.activeElement;\r\n let elCount = 1;\r\n let consoleOutput = \"\";\r\n let textOutput = \"\";\r\n let currentFocusedEl = document.activeElement;\r\n const focusables = document.querySelectorAll(\'a[href],button,select,input:not([type=\"hidden\"]),textarea,summary,area,[tabindex]:not(#WTFocusPanel):not([tabindex^=\"-1\"]),[contenteditable]:not([contenteditable=\"false\"])\');\r\n \/\/styles\r\n const style_title_formatting = \"background:#193c10;color:white;\";\r\n const style_overridden_formatting = \"background:#fff;color:darkgreen;font-weight:bold;text-decoration:line-through\";\r\n const style_good_formatting = \"font-weight:bold;color:#99f170;background:#333;display:inline-block;padding:3px;\";\r\n const style_bad_formatting = \"color:pink;background:#333;padding:3px;\";\r\n const style_ok_formatting = \"color:black;background:#fefbe3;font-weight:bold;\";\r\n const style_unimportant_formatting = \"color:#333;background:#fff;\";\r\n \/\/panel\r\n const WTFocusPanel = document.createElement(\"div\");\r\n const WTFocusCurtain = document.createElement(\"div\");\r\n const WTFpanelOffset = 20;\r\n const WTFpanelWidth = 400;\r\n const WTFfocusOutlineWidth = 7;\r\n const indicator = \'\uD83D\uDC49\uD83C\uDFFD<\/span>Accessible name provided by<\/span> \';\r\n const warning = \'\uD83D\uDEA8<\/span> Warning<\/span>\';\r\n let accNameLabel = \"Accessible name: \";\r\n\r\n let strPageOutput = \"\";\r\n\r\n let isGood = false;\r\n let isBad = false;\r\n let isDupeAccName = false;\r\n let dupeAccNameIsNoAccName = false;\r\n let currentActiveEl;\r\n\r\n let curtainsMode = false;\r\n let showDetails = false;\r\n\r\n function findAncestor(el, sel) {\r\n while ((el = el.parentElement) && !(el.matches || el.matchesSelector).call(el, sel));\r\n return el;\r\n }\r\n function insertAfter(newNode, referenceNode) {\r\n referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);\r\n }\r\n function resetGoodBadState() {\r\n isGood = false;\r\n isBad = false;\r\n }\r\n function addToConsoleOutput(text){\r\n consoleOutput+=text;\r\n }\r\n function log(text, el, style, isCurrent, showInCurtainsMode) {\r\n el = el.split(\"<\").join(\"<\").split(\">\").join(\">\");\r\n strPageOutput += \"\';\r\n if (isGood) {\r\n strPageOutput += indicator;\r\n }\r\n if (isBad) {\r\n strPageOutput += warning;\r\n }\r\n strPageOutput += text + \"<\/span> \" + el + \"<\/li>\\n\";\r\n el = el.replace(\"<\", \"<\").replace(\">\", \">\");\r\n }\r\n function addFocusStyles() {\r\n const focusStyles = document.createElement(\"style\");\r\n focusStyles.setAttribute(\"type\", \"text\/css\");\r\n focusStyles.setAttribute(\"id\", \"panelStyles\");\r\n focusStyles.textContent = \".dupeAccName {outline:4px dashed #CC3300!important;outline-offset:\" + WTFfocusOutlineWidth + \"px!important;overflow:visible;} .WTFocusTempFocusStyle:focus {outline:\" + WTFfocusOutlineWidth + \"px solid black!important;outline-offset:\" + WTFfocusOutlineWidth + \"px!important;overflow:visible;\/*background:yellow!important;color:black!important;*\/} .WTFocusTempFocusStyle.dupeAccName:focus {outline-color:#CC3300!important;} .visually-hidden {clip-path: inset(100%);clip: rect(1px, 1px, 1px, 1px);height: 1px;overflow: hidden;position: absolute;white-space: nowrap;width: 1px;}#WTFocusCurtain {background:black;position: fixed;top: 0;bottom: 0;left: 0;right: 0;z-index:49999}\";\r\n document.querySelector(\"body\").appendChild(focusStyles);\r\n }\r\n function addPanelStyles(WTFpanelWidth) {\r\n const consoleStyle = document.createElement(\"style\");\r\n consoleStyle.setAttribute(\"type\", \"text\/css\");\r\n consoleStyle.setAttribute(\"id\", \"focusStyles\");\r\n consoleStyle.textContent =\r\n \"#WTFocusPanel.error {background:darkred;} #WTFocusPanel.warning {background:#CC3300;} #WTFocusPanel.curtainsMode.error {background:black;} #WTFocusPanel.curtainsMode {z-index:50000;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);} #WTFocusPanel.curtainsMode.warning {background:black;} #WTFocusPanel[hidden] {display:none;} #WTFocusPanel * {text-align:left} #WTFocusPanel {border:2px solid #fff;z-index:1000;text-shadow:none;font-family:sans-serif;display:block;text-align:left;position: absolute;z-index:10000;background: black;padding: 20px 20px;width:\" +\r\n WTFpanelWidth +\r\n \"px;font-size:16px;} #WTFocusPanel button {font-weight:bold;background:none;color:#fff;padding:3px 10px;font-size:14px;border:1px solid #fff;display:inline-block;margin:10px 1em -10px 0;} #WTFocusPanel ul,#WTFocusPanel li {margin:0;padding:0;list-style:none} #WTFocusPanel li {margin:3px 0;background:#fff;color:#333;padding:2px} #WTFocusPanel li.outline {outline:4px solid rgb(58, 190, 58);outline-offset:-4px;padding:8px} #WTFocusPanel.error:before {background:darkred} #WTFocusPanel.warning:before {background:#CC3300} #WTFocusPanel:before {content:\'\';display:block;height:20px;width:20px;transform:rotate(45deg);position:absolute;background:#000;left:-12px;top:3px;border:2px solid #fff;border-right:none;border-top:none;} #WTFocusPanel.toBottom:before {top:auto;bottom:3px} #WTFocusPanel.toLeft:before {left:auto;right:-12px;border:2px solid #fff;border-left:none;border-bottom:none;} #WTFocusPanel.curtainsMode {outline:10px solid orange;} #WTFocusPanel.curtainsMode:before {display:none;} #WTFocusPanel.curtainsMode li {display:none;} #WTFocusPanel.curtainsMode li.visible {display:block;} #WTFocusPanel.curtainsMode li span {display:none!important;} #WTFocusPanel details summary {color:white} #WTFocusPanel.curtainsMode details {display:none}#WTFocusPanel a[download]{display:block;margin:0.5em 0;color:#fff;text-decoration:underline;border:none;padding:0;}\";\r\n document.querySelector(\"head\").appendChild(consoleStyle);\r\n }\r\n function promptForLoggingType() {\r\n if (document.querySelector(\"#WTFocusCurtain\")) {\r\n removePanel();\r\n }\r\n strPageOutput = \"\";\r\n addPanelStyles(WTFpanelWidth);\r\n addCurtainToPage();\r\n addPanelToPage();\r\n }\r\n function addCurtainToPage() {\r\n WTFocusCurtain.setAttribute(\"id\", \"WTFocusCurtain\");\r\n WTFocusCurtain.setAttribute(\"hidden\", \"hidden\");\r\n document.querySelector(\"body\").appendChild(WTFocusCurtain);\r\n }\r\n function addPanelToPage() {\r\n WTFocusPanel.setAttribute(\"id\", \"WTFocusPanel\");\r\n if (curtainsMode) WTFocusPanel.setAttribute(\"class\", \"curtainsMode\");\r\n WTFocusPanel.setAttribute(\"aria-live\", \"polite\");\r\n WTFocusPanel.setAttribute(\"tabindex\", \"-1\");\r\n WTFocusPanel.setAttribute(\"hidden\", \"hidden\");\r\n WTFocusPanel.setAttribute(\"role\", \"region\");\r\n WTFocusPanel.setAttribute(\"aria-label\", \"Accessibility properties panel\");\r\n document.querySelector(\"body\").appendChild(WTFocusPanel);\r\n keypressListeners();\r\n }\r\n function addButtons() {\r\n const consoleCloseButton = document.createElement(\"button\");\r\n consoleCloseButton.textContent = \"Close (Esc)\";\r\n consoleCloseButton.setAttribute(\"type\", \"button\");\r\n consoleCloseButton.setAttribute(\"class\", \"panel-btn\");\r\n consoleCloseButton.addEventListener(\"click\", () => {\r\n removePanel();\r\n });\r\n const toggleModeButton = document.createElement(\"button\");\r\n toggleModeButton.textContent = \"Change Mode (M)\";\r\n toggleModeButton.setAttribute(\"type\", \"button\");\r\n toggleModeButton.setAttribute(\"class\", \"panel-btn\");\r\n toggleModeButton.addEventListener(\"click\", (e) => {\r\n toggleMode();\r\n });\r\n const downloadLink = document.createElement(\"a\");\r\n const downloadWarningPreamble = \"IMPORTANT DISCLAIMER!\\n\\nThis text file is a *very approximate representation* \\nof what this page may be like for screen reader users:\\n\\n\u2022 It lists all the focusable elements (at the point \\n of running the script) but may not include every \\n element. For example, any element that is temporarily \\n set to be non-focusable with `tabindex=\\\"-1\\\"`, such as \\n an inactive tab in a group of tab controls, will not \\n be shown here.\\n\u2022 It lists the accessible name and the role \\n (e.g. link, button)\\n\u2022 Where there is an accessible description \\n (provided by `aria-describedby` or a `title` \\n attribute), this is included too\";\r\n downloadLink.textContent = \"Download summary (S)\";\r\n downloadLink.setAttribute(\"href\",\"data:text\/plain;charset=utf-8,\" + encodeURIComponent(consoleOutput));\r\n downloadLink.setAttribute(\"download\", \"simple-screen-reader-emulation\");\r\n downloadLink.addEventListener(\"click\", (e) => {\r\n alert(downloadWarningPreamble);\r\n });\r\n WTFocusPanel.appendChild(consoleCloseButton);\r\n WTFocusPanel.appendChild(toggleModeButton);\r\n WTFocusPanel.appendChild(downloadLink);\r\n }\r\n\r\n function downloadSummary() {\r\n document.querySelector(\"#WTFocusPanel a[download]\").click(); \r\n }\r\n\r\n\r\n function hidePanel() {\r\n document.querySelector(\"#WTFocusPanel\").setAttribute(\"hidden\", \"hidden\");\r\n }\r\n function toggleMode() {\r\n if (curtainsMode) {\r\n document.querySelector(\"#WTFocusPanel\").classList.remove(\"curtainsMode\");\r\n document.querySelector(\"#WTFocusPanel\").removeAttribute(\"style\");\r\n document.querySelector(\"#WTFocusCurtain\").setAttribute(\"hidden\",\"hidden\");\r\n curtainsMode=false;\r\n accNameLabel = \"Accessible name: \";\r\n } else {\r\n document.querySelector(\"#WTFocusPanel\").classList.add(\"curtainsMode\");\r\n document.querySelector(\"#WTFocusCurtain\").removeAttribute(\"hidden\");\r\n curtainsMode=true;\r\n accNameLabel = \"\";\r\n }\r\n positionPanelOnPage(currentFocusedEl);\r\n currentFocusedEl.focus();\r\n }\r\n function removePanel() {\r\n document.querySelector(\"#WTFocusCurtain\").remove();\r\n document.querySelector(\"#WTFocusPanel\").remove();\r\n document.querySelector(\"#panelStyles\").remove();\r\n document.querySelector(\"#focusStyles\").remove();\r\n }\r\n function toggleMoreDetails(){\r\n document.querySelector(\"#WTFocusPanel summary\").click();\r\n showDetails = !showDetails;\r\n }\r\n function keypressListeners() {\r\n window.addEventListener(\"keyup\", (event) => {\r\n if (event.key === \"Escape\" && document.querySelector(\"#WTFocusPanel\")) {\r\n removePanel();\r\n }\r\n });\r\n window.addEventListener(\"keyup\", (event) => {\r\n if (event.key.toLowerCase() === \"m\" && document.querySelector(\"#WTFocusPanel\")) {\r\n toggleMode();\r\n }\r\n if (event.key.toLowerCase() === \"d\" && document.querySelector(\"#WTFocusPanel\")) {\r\n toggleMoreDetails();\r\n }\r\n if (event.key.toLowerCase() === \"s\" && document.querySelector(\"#WTFocusPanel\")) {\r\n downloadSummary();\r\n }\r\n });\r\n }\r\n function positionPanelOnPage(focusable) {\r\n const rect = focusable.getBoundingClientRect();\r\n const scroll = document.documentElement.scrollTop;\r\n const panelRightCoord = rect.right + WTFpanelOffset + WTFpanelWidth;\r\n const panelHeight = WTFocusPanel.offsetHeight;\r\n const panelBottomCoord = scroll + rect.top + panelHeight;\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n if (curtainsMode) {\r\n document.querySelector(\"#WTFocusPanel\").removeAttribute(\"style\");\r\n }\r\n else {\r\n if (panelRightCoord > viewportWidth) {\r\n if (panelBottomCoord > viewportHeight) {\r\n WTFocusPanel.style.top = \"auto\";\r\n WTFocusPanel.style.bottom = viewportHeight - (scroll + rect.bottom) - 10 + \"px\";\r\n WTFocusPanel.classList.add(\"toBottom\");\r\n } else {\r\n WTFocusPanel.style.top = scroll + rect.top + \"px\";\r\n WTFocusPanel.style.bottom = \"auto\";\r\n WTFocusPanel.classList.remove(\"toBottom\");\r\n }\r\n WTFocusPanel.style.left = \"auto\";\r\n WTFocusPanel.style.right = viewportWidth - rect.left + WTFpanelOffset - WTFfocusOutlineWidth + \"px\";\r\n WTFocusPanel.classList.add(\"toLeft\");\r\n } else {\r\n if (panelBottomCoord > viewportHeight) {\r\n WTFocusPanel.style.top = \"auto\";\r\n WTFocusPanel.style.bottom = viewportHeight - (scroll + rect.bottom) - 10 + \"px\";\r\n WTFocusPanel.classList.add(\"toBottom\");\r\n } else {\r\n WTFocusPanel.style.top = scroll + rect.top + \"px\";\r\n WTFocusPanel.style.bottom = \"auto\";\r\n WTFocusPanel.classList.remove(\"toBottom\");\r\n }\r\n WTFocusPanel.style.left = rect.right + WTFpanelOffset - WTFfocusOutlineWidth + \"px\";\r\n WTFocusPanel.style.right = \"auto\";\r\n WTFocusPanel.classList.remove(\"toLeft\");\r\n }\r\n\r\n }\r\n }\r\n\r\n addFocusStyles();\r\n promptForLoggingType();\r\n addButtons();\r\n\r\n let accNamesFound = [];\r\n Array.from(focusables).forEach(function (focusable) {\r\n focusable.classList.add(\"WTFocusTempFocusStyle\");\r\n\r\n const styleEls = focusable.querySelectorAll(\"style\");\r\n Array.from(styleEls).forEach(function (styleEl) {\r\n styleEl.remove();\r\n });\r\n\r\n focusable.addEventListener(\"focus\", () => {\r\n let elementRole = focusable.getAttribute(\"role\");\r\n let focussedTagName = focusable.tagName.toLowerCase();\r\n if (elementRole) {\r\n } else {\r\n if ((focussedTagName==\"article\")||(focussedTagName==\"button\")||(focussedTagName==\"dialog\")||(focussedTagName==\"figure\")||(focussedTagName==\"img\")||(focussedTagName==\"main\")||(focussedTagName==\"math\")) {\r\n elementRole = focussedTagName;\r\n }\r\n if (focussedTagName==\"summary\") {\r\n elementRole = \"button\";\r\n }\r\n if (focussedTagName==\"aside\") {\r\n elementRole = \"complementary\";\r\n }\r\n if (focussedTagName==\"dd\") {\r\n elementRole = \"definition\";\r\n }\r\n if (focussedTagName==\"html\") {\r\n elementRole = \"document\";\r\n }\r\n if ((focussedTagName==\"details\")||(focussedTagName==\"fieldset\")||(focussedTagName==\"optgroup\")) {\r\n elementRole = \"group\";\r\n }\r\n if ((focussedTagName==\"menu\")||(focussedTagName==\"ol\")||(focussedTagName==\"ul\")) {\r\n elementRole = \"list\";\r\n }\r\n if (focussedTagName==\"datalist\") {\r\n elementRole = \"listbox\";\r\n }\r\n if (focussedTagName==\"li\") {\r\n elementRole = \"listitem\";\r\n }\r\n if (focussedTagName==\"nav\") {\r\n elementRole = \"navigation\";\r\n }\r\n if (focussedTagName==\"progress\") {\r\n elementRole = \"progressbar\";\r\n }\r\n if (focussedTagName==\"hr\") {\r\n elementRole = \"separator\";\r\n }\r\n if (focussedTagName==\"output\") {\r\n elementRole = \"status\";\r\n }\r\n if ((focussedTagName==\"dfn\")||(focussedTagName==\"dt\")) {\r\n elementRole = \"term\";\r\n }\r\n if (focussedTagName==\"a\") {\r\n elementRole = \"link\";\r\n }\r\n if (focussedTagName==\"select\") {\r\n elementRole = \"listbox\";\r\n }\r\n if (focussedTagName==\"textarea\") {\r\n elementRole = \"textbox\";\r\n }\r\n if (focussedTagName==\"input\") {\r\n let type = focusable.getAttribute(\"type\").toLowerCase();\r\n if (type===\"email\") {\r\n elementRole = \"textbox\";\r\n }\r\n if (type===\"text\") {\r\n elementRole = \"textbox\";\r\n }\r\n if (type===\"range\") {\r\n elementRole = \"slider\";\r\n }\r\n if (type===\"number\") {\r\n elementRole = \"spinbutton\";\r\n }\r\n if ((type===\"checkbox\")||(type===\"radio\")) {\r\n elementRole = type;\r\n }\r\n if ((type===\"button\")||(type===\"image\")||(type===\"reset\")||(type===\"submit\")) {\r\n elementRole = \"button\";\r\n }\r\n }\r\n }\r\n currentFocusedEl = focusable;\r\n removeDupeIndicators();\r\n let containsImages = false;\r\n isGood = false;\r\n isBad = false;\r\n\r\n const imgs = focusable.querySelectorAll(\"img, [role=\'image\'][aria-label], [role=\'img\'][aria-label]\");\r\n containsImages = imgs.length > 0;\r\n\r\n if (containsImages) {\r\n Array.from(imgs).forEach(function (image) {\r\n const newSpan = document.createElement(\"SPAN\");\r\n newSpan.setAttribute(\"class\", \"visually-hidden\");\r\n newSpan.setAttribute(\"style\", \"clip-path: inset(100%);clip: rect(1px, 1px, 1px, 1px);height: 1px;overflow: hidden;position: absolute;white-space: nowrap;width: 1px;\");\r\n newSpan.setAttribute(\"data-temp-node\", \"true\");\r\n if (image.getAttribute(\"alt\")) {\r\n newSpan.textContent = \" \" + image.getAttribute(\"alt\") + \" \";\r\n }\r\n if (image.getAttribute(\"role\") && image.getAttribute(\"aria-label\")) {\r\n newSpan.textContent = \" \" + image.getAttribute(\"aria-label\") + \" \";\r\n }\r\n insertAfter(newSpan, image);\r\n });\r\n }\r\n setTimeout(function () {\r\n focusable.classList.add(\"WTFocusTempFocusStyle\");\r\n }, 100);\r\n\r\n strPageOutput = \"\";\r\n\r\n const tagName = focusable.tagName.toLowerCase();\r\n let tagRole = focusable.getAttribute(\"role\");\r\n if (tagRole) {\r\n tagRole = focusable.getAttribute(\"role\").toLowerCase();\r\n }\r\n let tagDetails = \"<\" + tagName + \">\";\r\n let superfluousRole = false;\r\n let hasDescribedBy = false;\r\n let ariaDescribedByText = \"\";\r\n let identicalAriaLabel = false;\r\n let betterAsNativeHTMLelement = false;\r\n if (tagRole) {\r\n tagDetails = \"<\" + tagName + \' role=\"\' + tagRole + \'\">\';\r\n if ((tagRole === \"link\" && tagName === \"a\") || (tagRole === \"button\" && tagName === \"button\") || (tagRole === \"image\" && tagName === \"img\") || (tagRole === \"img\" && tagName === \"img\") || (tagRole === \"navigation\" && tagName === \"nav\") || (tagRole === \"heading\" && (tagName === \"h1\" || tagName === \"h2\" || tagName === \"h3\" || tagName === \"h4\" || tagName === \"h5\" || tagName === \"h6\"))) {\r\n superfluousRole = true;\r\n }\r\n if ((tagRole === \"link\" && tagName !== \"a\") || (tagRole === \"button\" && tagName !== \"button\") || ((tagRole === \"image\" || tagRole === \"image\") && tagName !== \"img\") || (tagRole === \"navigation\" && tagName !== \"nav\") || (tagRole === \"heading\" && !(tagName === \"h1\" || tagName === \"h2\" || tagName === \"h3\" || tagName === \"h4\" || tagName === \"h5\" || tagName === \"h6\"))) {\r\n betterAsNativeHTMLelement = true;\r\n }\r\n }\r\n if (focusable.getAttribute(\"aria-describedby\")) {\r\n hasDescribedBy = true;\r\n }\r\n\r\n let textContent = focusable.textContent;\r\n let ariaLabel = focusable.ariaLabel;\r\n let ariaLabelledBy = focusable.getAttribute(\"aria-labelledby\");\r\n let placeholder = focusable.getAttribute(\"placeholder\");\r\n let ariaLabelledBySource;\r\n let ariaDescribedBySource;\r\n let accNameFromAriaLabelledBySrc = \"\";\r\n let descriptionFromAriaDescribedBySrc = \"\";\r\n let value = focusable.getAttribute(\"value\");\r\n let title = focusable.getAttribute(\"title\");\r\n let accName = \"\";\r\n let visibleLabelText = \"\";\r\n let wrappedLabel = false;\r\n let linkedLabel = false;\r\n let accNameSource = \"\";\r\n let ariaHiddenElementsPresent = false;\r\n\r\n positionPanelOnPage(focusable);\r\n\r\n textContent = textContent.trim();\r\n\r\n \/\/ Real labels\r\n const parentLabel = findAncestor(focusable, \"label\");\r\n if (parentLabel) {\r\n wrappedLabel = true;\r\n visibleLabelText = parentLabel.textContent.trim();\r\n accName = visibleLabelText;\r\n }\r\n\r\n if (focusable.getAttribute(\"id\")) {\r\n const linkedLabelEl = document.querySelector(\"[for=\'\" + focusable.getAttribute(\"id\") + \"\']\");\r\n if (linkedLabelEl) {\r\n linkedLabel = true;\r\n visibleLabelText = linkedLabelEl.textContent;\r\n }\r\n }\r\n\r\n if (!(wrappedLabel || linkedLabel)) {\r\n visibleLabelText = \"N\/A\";\r\n }\r\n if (!textContent) {\r\n textContent = \"N\/A\";\r\n }\r\n if (!value) {\r\n value = \"N\/A\";\r\n }\r\n if (!title) {\r\n title = \"N\/A\";\r\n }\r\n if (!placeholder) {\r\n placeholder = \"N\/A\";\r\n }\r\n if (!ariaLabel) {\r\n ariaLabel = \"N\/A\";\r\n }\r\n if (!ariaLabelledBy) {\r\n ariaLabelledBy = \"N\/A\";\r\n } else {\r\n ariaLabelledBySource = ariaLabelledBy;\r\n const ariaLabelledBySources = ariaLabelledBySource.split(\" \");\r\n if (ariaLabelledBySources.length > 1) {\r\n Array.from(ariaLabelledBySources).forEach(function (sourceNode) {\r\n if (document.querySelector(\"#\" + sourceNode)) {\r\n accNameFromAriaLabelledBySrc += document.querySelector(\"#\" + sourceNode).textContent + \" \";\r\n } else {\r\n accNameFromAriaLabelledBySrc += \"\u2753\u2753\u2753 \";\r\n }\r\n });\r\n accNameFromAriaLabelledBySrc = accNameFromAriaLabelledBySrc.trim();\r\n } else {\r\n accNameFromAriaLabelledBySrc = document.querySelector(\"#\" + ariaLabelledBySource).textContent;\r\n }\r\n }\r\n\r\n\r\n const hiddenElements = focusable.querySelectorAll(\"[aria-hidden=\'true\'],[role=\'presentation\']\");\r\n let textContentWithAriaHiddenRemoved = textContent;\r\n if (hiddenElements.length > 0) {\r\n ariaHiddenElementsPresent = true;\r\n Array.from(hiddenElements).forEach(function (hiddenElement) {\r\n const tempText = hiddenElement.textContent;\r\n if (tempText !== \"\") {\r\n textContentWithAriaHiddenRemoved = textContentWithAriaHiddenRemoved.split(tempText).join(\" \");\r\n }\r\n });\r\n textContentWithAriaHiddenRemoved = textContentWithAriaHiddenRemoved.trim();\r\n }\r\n\r\n if (tagName === \"input\") {\r\n const inputType = focusable.getAttribute(\"type\");\r\n if (inputType === \"submit\") {\r\n if (value === \"N\/A\") {\r\n accName = \"Submit\";\r\n accNameSource = \"Not provided (using default)\";\r\n }\r\n }\r\n if (inputType === \"image\") {\r\n if (value === \"N\/A\") {\r\n accName = \"Submit\";\r\n accNameSource = \"Not provided (using default)\";\r\n }\r\n }\r\n if (inputType === \"cancel\") {\r\n if (value === \"N\/A\") {\r\n accName = \"Cancel\";\r\n accNameSource = \"Not provided (using default)\";\r\n }\r\n }\r\n }\r\n\r\n if (title !== \"N\/A\") {\r\n accName = title;\r\n accNameSource = \"title attribute\";\r\n }\r\n if (value !== \"N\/A\") {\r\n accName = value;\r\n accNameSource = \"value attribute\";\r\n }\r\n if (placeholder !== \"N\/A\") {\r\n accName = placeholder;\r\n accNameSource = \"placeholder attribute\";\r\n }\r\n if (textContent !== \"N\/A\") {\r\n accName = textContentWithAriaHiddenRemoved;\r\n accNameSource = \"Inner text content\";\r\n }\r\n if (visibleLabelText !== \"N\/A\") {\r\n accName = visibleLabelText;\r\n accNameSource = \"