Accessibility / Keyboard / Keyboard Trap Tester

The Keyboard Trap Tester bookmarklet automatically simulates Tab key presses to detect keyboard traps - focus cycles where users cannot navigate away using only the keyboard. Displays a panel with test progress, highlights trapped elements in red, and reports the iteration count where cycles were detected. Run again to remove.

WCAG SC 2.1.2: No Keyboard Trap
Run Keyboard Trap Tester

Test run or drag to
bookmarklets bar to install

javascript:%21function()%7B%22use%20strict%22%3Btry%7Bconst%20t%3Ddocument.getElementById(%22kbd-trap-tester-host%22)%3Bt%26%26t.remove()%3Bconst%20n%3Ddocument.getElementById(%22ktt-highlight-style%22)%3Bn%26%26n.remove()%3Bdocument.querySelectorAll(%22.ktt-trap%2C%20.ktt-visited%2C%20.ktt-current%22).forEach(t%3D%3E%7Bt.classList.remove(%22ktt-trap%22%2C%22ktt-visited%22%2C%22ktt-current%22)%7D)%3Bconst%20e%3Ddocument.createElement(%22div%22)%3Be.id%3D%22kbd-trap-tester-host%22%2Ce.style.cssText%3D%22position%3Afixed%3Btop%3A10px%3Bright%3A10px%3Bz-index%3A999999%3Bwidth%3A420px%3Bmax-height%3A85vh%3B%22%2Cdocument.body.appendChild(e)%3Bconst%20o%3De.attachShadow(%7Bmode%3A%22open%22%7D)%2Cr%3Ddocument.createElement(%22style%22)%3Br.textContent%3D%22%5Cn%20%20%20%20%20%20*%20%7B%20box-sizing%3A%20border-box%3B%20%7D%5Cn%20%20%20%20%20%20.ktt-panel%20%7B%5Cn%20%20%20%20%20%20%20%20font-family%3A%20-apple-system%2C%20BlinkMacSystemFont%2C%20%27Segoe%20UI%27%2C%20Roboto%2C%20sans-serif%3B%5Cn%20%20%20%20%20%20%20%20background%3A%20white%3B%5Cn%20%20%20%20%20%20%20%20border%3A%202px%20solid%20%23333%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%208px%3B%5Cn%20%20%20%20%20%20%20%20box-shadow%3A%200%204px%2020px%20rgba(0%2C0%2C0%2C0.3)%3B%5Cn%20%20%20%20%20%20%20%20display%3A%20flex%3B%5Cn%20%20%20%20%20%20%20%20flex-direction%3A%20column%3B%5Cn%20%20%20%20%20%20%20%20max-height%3A%2085vh%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-header%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23333%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20white%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%2012px%2016px%3B%5Cn%20%20%20%20%20%20%20%20display%3A%20flex%3B%5Cn%20%20%20%20%20%20%20%20justify-content%3A%20space-between%3B%5Cn%20%20%20%20%20%20%20%20align-items%3A%20center%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%206px%206px%200%200%3B%5Cn%20%20%20%20%20%20%20%20flex-shrink%3A%200%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-title%20%7B%5Cn%20%20%20%20%20%20%20%20font-weight%3A%20600%3B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.875rem%3B%5Cn%20%20%20%20%20%20%20%20margin%3A%200%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-close%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20none%3B%5Cn%20%20%20%20%20%20%20%20border%3A%20none%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20white%3B%5Cn%20%20%20%20%20%20%20%20font-size%3A%201.25rem%3B%5Cn%20%20%20%20%20%20%20%20cursor%3A%20pointer%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%200%3B%5Cn%20%20%20%20%20%20%20%20width%3A%2028px%3B%5Cn%20%20%20%20%20%20%20%20height%3A%2028px%3B%5Cn%20%20%20%20%20%20%20%20display%3A%20flex%3B%5Cn%20%20%20%20%20%20%20%20align-items%3A%20center%3B%5Cn%20%20%20%20%20%20%20%20justify-content%3A%20center%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%204px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-close%3Ahover%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20rgba(255%2C255%2C255%2C0.2)%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-content%20%7B%5Cn%20%20%20%20%20%20%20%20padding%3A%2016px%3B%5Cn%20%20%20%20%20%20%20%20overflow-y%3A%20auto%3B%5Cn%20%20%20%20%20%20%20%20flex%3A%201%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-status%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23f5f5f5%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%2012px%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%206px%3B%5Cn%20%20%20%20%20%20%20%20margin-bottom%3A%2016px%3B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.8125rem%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-status.testing%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23fff3cd%3B%5Cn%20%20%20%20%20%20%20%20border%3A%202px%20solid%20%23ffc107%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-status.complete%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23e6ffed%3B%5Cn%20%20%20%20%20%20%20%20border%3A%202px%20solid%20%2328a745%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-status.traps-found%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23ffe6e6%3B%5Cn%20%20%20%20%20%20%20%20border%3A%202px%20solid%20%23dc3545%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-status%20strong%20%7B%5Cn%20%20%20%20%20%20%20%20display%3A%20block%3B%5Cn%20%20%20%20%20%20%20%20margin-bottom%3A%208px%3B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.875rem%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-progress%20%7B%5Cn%20%20%20%20%20%20%20%20width%3A%20100%25%3B%5Cn%20%20%20%20%20%20%20%20height%3A%208px%3B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23ddd%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%204px%3B%5Cn%20%20%20%20%20%20%20%20overflow%3A%20hidden%3B%5Cn%20%20%20%20%20%20%20%20margin%3A%208px%200%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-progress-bar%20%7B%5Cn%20%20%20%20%20%20%20%20height%3A%20100%25%3B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23007bff%3B%5Cn%20%20%20%20%20%20%20%20transition%3A%20width%200.3s%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-trap-item%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23ffe6e6%3B%5Cn%20%20%20%20%20%20%20%20border%3A%201px%20solid%20%23dc3545%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%206px%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%2012px%3B%5Cn%20%20%20%20%20%20%20%20margin-bottom%3A%2012px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-trap-header%20%7B%5Cn%20%20%20%20%20%20%20%20font-weight%3A%20600%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20%23dc3545%3B%5Cn%20%20%20%20%20%20%20%20margin-bottom%3A%208px%3B%5Cn%20%20%20%20%20%20%20%20display%3A%20flex%3B%5Cn%20%20%20%20%20%20%20%20align-items%3A%20center%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-trap-header%20svg%20%7B%5Cn%20%20%20%20%20%20%20%20margin-right%3A%208px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-trap-info%20%7B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.75rem%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20%23333%3B%5Cn%20%20%20%20%20%20%20%20margin-bottom%3A%204px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-trap-info%20strong%20%7B%5Cn%20%20%20%20%20%20%20%20display%3A%20inline%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20%23666%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-trap-cycle%20%7B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.6875rem%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20%23666%3B%5Cn%20%20%20%20%20%20%20%20background%3A%20white%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%206px%208px%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%204px%3B%5Cn%20%20%20%20%20%20%20%20margin-top%3A%208px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-section-title%20%7B%5Cn%20%20%20%20%20%20%20%20font-weight%3A%20600%3B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.8125rem%3B%5Cn%20%20%20%20%20%20%20%20margin-bottom%3A%208px%3B%5Cn%20%20%20%20%20%20%20%20margin-top%3A%2016px%3B%5Cn%20%20%20%20%20%20%20%20padding-bottom%3A%204px%3B%5Cn%20%20%20%20%20%20%20%20border-bottom%3A%201px%20solid%20%23ddd%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-element-list%20%7B%5Cn%20%20%20%20%20%20%20%20max-height%3A%20200px%3B%5Cn%20%20%20%20%20%20%20%20overflow-y%3A%20auto%3B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23f9f9f9%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%204px%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%208px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-element-item%20%7B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.6875rem%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%204px%206px%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%203px%3B%5Cn%20%20%20%20%20%20%20%20margin%3A%202px%200%3B%5Cn%20%20%20%20%20%20%20%20cursor%3A%20pointer%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-element-item%3Ahover%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23e0e0e0%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-empty%20%7B%5Cn%20%20%20%20%20%20%20%20color%3A%20%23999%3B%5Cn%20%20%20%20%20%20%20%20font-style%3A%20italic%3B%5Cn%20%20%20%20%20%20%20%20text-align%3A%20center%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%2012px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-btn%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23007bff%3B%5Cn%20%20%20%20%20%20%20%20color%3A%20white%3B%5Cn%20%20%20%20%20%20%20%20border%3A%20none%3B%5Cn%20%20%20%20%20%20%20%20padding%3A%208px%2016px%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%204px%3B%5Cn%20%20%20%20%20%20%20%20font-size%3A%200.8125rem%3B%5Cn%20%20%20%20%20%20%20%20cursor%3A%20pointer%3B%5Cn%20%20%20%20%20%20%20%20width%3A%20100%25%3B%5Cn%20%20%20%20%20%20%20%20margin-top%3A%208px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-btn%3Ahover%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%230056b3%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-btn%3Adisabled%20%7B%5Cn%20%20%20%20%20%20%20%20background%3A%20%23ccc%3B%5Cn%20%20%20%20%20%20%20%20cursor%3A%20not-allowed%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20.ktt-spinner%20%7B%5Cn%20%20%20%20%20%20%20%20display%3A%20inline-block%3B%5Cn%20%20%20%20%20%20%20%20width%3A%2014px%3B%5Cn%20%20%20%20%20%20%20%20height%3A%2014px%3B%5Cn%20%20%20%20%20%20%20%20border%3A%202px%20solid%20%23f3f3f3%3B%5Cn%20%20%20%20%20%20%20%20border-top%3A%202px%20solid%20%23007bff%3B%5Cn%20%20%20%20%20%20%20%20border-radius%3A%2050%25%3B%5Cn%20%20%20%20%20%20%20%20animation%3A%20ktt-spin%201s%20linear%20infinite%3B%5Cn%20%20%20%20%20%20%20%20margin-left%3A%208px%3B%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%40keyframes%20ktt-spin%20%7B%5Cn%20%20%20%20%20%20%20%200%25%20%7B%20transform%3A%20rotate(0deg)%3B%20%7D%5Cn%20%20%20%20%20%20%20%20100%25%20%7B%20transform%3A%20rotate(360deg)%3B%20%7D%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%22%2Co.appendChild(r)%3Bconst%20s%3Ddocument.createElement(%22div%22)%3Bs.className%3D%22ktt-panel%22%2Co.appendChild(s)%2Cs.innerHTML%3D%27%5Cn%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-header%22%3E%5Cn%20%20%20%20%20%20%20%20%3Ch2%20class%3D%22ktt-title%22%3EKeyboard%20Trap%20Tester%3C%2Fh2%3E%5Cn%20%20%20%20%20%20%20%20%3Cbutton%20class%3D%22ktt-close%22%20aria-label%3D%22Close%22%20onclick%3D%22cleanupKTT()%22%3E%26times%3B%3C%2Fbutton%3E%5Cn%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-content%22%3E%5Cn%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-status%20testing%22%20id%3D%22ktt-status%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%3Cstrong%3EReady%20to%20Test%3C%2Fstrong%3E%5Cn%20%20%20%20%20%20%20%20%20%20%3Cdiv%3EThis%20tool%20will%20simulate%20Tab%20key%20presses%20to%20detect%20keyboard%20traps.%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%3Cdiv%20style%3D%22margin-top%3A8px%3Bfont-size%3A0.6875rem%3Bcolor%3A%23666%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20Warning%3A%20This%20will%20temporarily%20change%20focus%20as%20it%20tests.%20The%20test%20will%20stop%20automatically.%5Cn%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%3Cbutton%20class%3D%22ktt-btn%22%20id%3D%22ktt-start-btn%22%20onclick%3D%22startKeyboardTrapTest()%22%3EStart%20Test%3C%2Fbutton%3E%5Cn%20%20%20%20%20%20%20%20%3Cdiv%20id%3D%22ktt-results%22%3E%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%27%3Bconst%20i%3Ddocument.createElement(%22style%22)%3Bfunction%20a(t)%7Btry%7Breturn%20t.focus()%2Ct%3D%3D%3Ddocument.activeElement%7Dcatch(t)%7Breturn%211%7D%7Dfunction%20d(t)%7Blet%20n%3D0%3Bfor(const%5Be%2Co%5Dof%20t)n%2B%3Do%3Breturn%20n%7Dfunction%20l(t%2Cn%2Ce)%7Bconst%20r%3Do.getElementById(%22ktt-status%22)%3Br%26%26(r.className%3D%60ktt-status%20%24%7Bt%7D%60%2Cr.innerHTML%3D%60%3Cstrong%3E%24%7Bn%7D%3C%2Fstrong%3E%3Cdiv%3E%24%7Be%7D%3C%2Fdiv%3E%60)%7Dfunction%20c(t)%7Blet%20n%3Do.getElementById(%22ktt-progress-container%22)%3Bif(%21n)%7Bn%3Ddocument.createElement(%22div%22)%2Cn.id%3D%22ktt-progress-container%22%2Cn.innerHTML%3D%27%3Cdiv%20class%3D%22ktt-progress%22%3E%3Cdiv%20class%3D%22ktt-progress-bar%22%20id%3D%22ktt-progress-bar%22%3E%3C%2Fdiv%3E%3C%2Fdiv%3E%27%3Bconst%20t%3Do.getElementById(%22ktt-status%22)%3Bt%26%26t.appendChild(n)%7Dconst%20e%3Do.getElementById(%22ktt-progress-bar%22)%3Be%26%26(e.style.width%3Dt%2B%22%25%22)%7Dfunction%20p(t%2Cn)%7Bo.getElementById(%22ktt-status%22)%3Bconst%20e%3Do.getElementById(%22ktt-results%22)%3Bif(t.hasTraps)%7Bl(%22traps-found%22%2C%22Keyboard%20Traps%20Detected%21%22%2C%60Tested%20%24%7Bt.visitedCount%7D%20element(s)%20before%20detecting%20a%20cycle.%60)%2Ct.traps.forEach(t%3D%3E%7Bt.element%26%26t.element.classList.add(%22ktt-trap%22)%2Ct.cycleStart%26%26t.cycleStart.classList.add(%22ktt-trap%22)%7D)%3Blet%20n%3D%27%3Cdiv%20class%3D%22ktt-section-title%22%3ETraps%20Found%3A%3C%2Fdiv%3E%27%3Bt.traps.forEach((t%2Ce)%3D%3E%7Bconst%20o%3Dm(t.element)%3Bn%2B%3D%60%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-trap-item%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-trap-header%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20fill%3D%22currentColor%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20d%3D%22M8%200a8%208%200%20100%2016A8%208%200%20008%200zm1%2012H7v-2h2v2zm0-3H7V4h2v5z%22%2F%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fsvg%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Trap%20%23%24%7Be%2B1%7D%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-trap-info%22%3E%3Cstrong%3EElement%3A%3C%2Fstrong%3E%20%24%7Bo%7D%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-trap-info%22%3E%3Cstrong%3EIteration%3A%3C%2Fstrong%3E%20%24%7Bt.iteration%7D%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-trap-cycle%22%3EFocus%20cycles%20between%20this%20element%20and%20previous%20elements%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%60%7D)%2Ce.innerHTML%3Dn%7Delse%20l(%22complete%22%2C%22No%20Keyboard%20Traps%20Found%22%2C%60Successfully%20tested%20through%20%24%7Bt.visitedCount%7D%20element(s)%20without%20detecting%20cycles.%60)%2Ce.innerHTML%3D%60%5Cn%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-section-title%22%3EFocusable%20Elements%20Tested%3A%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-element-list%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%24%7Bn.map(t%3D%3E%60%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22ktt-element-item%22%20onclick%3D%22highlightKTTElement(this%2C%20%27%24%7Bt.tagName.toLowerCase()%7D%27)%22%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24%7Bm(t)%7D%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%20%20%20%20%60).join(%22%22)%7D%5Cn%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%5Cn%20%20%20%20%20%20%20%20%60%7Dfunction%20m(t)%7Bif(%21t%7C%7Ct%3D%3D%3Ddocument.body)return%22document.body%22%3Bconst%20n%3Dt.tagName.toLowerCase()%2Ce%3Dt.id%3F%60%23%24%7Bt.id%7D%60%3A%22%22%2Co%3Dt.className%3F%60.%24%7Bt.className.split(%22%20%22).join(%22.%22)%7D%60%3A%22%22%2Cr%3Dt.textContent%3Ft.textContent.substring(0%2C30).trim()%3A%22%22%3Breturn%60%24%7Bn%7D%24%7Be%7D%24%7Bo%7D%24%7Br%3F%60%20-%20%22%24%7Br%7D%22%60%3A%22%22%7D%60%7Di.id%3D%22ktt-highlight-style%22%2Ci.textContent%3D%22%5Cn%20%20%20%20%20%20.ktt-trap%20%7B%20outline%3A%204px%20solid%20%23dc3545%20%21important%3B%20outline-offset%3A%202px%20%21important%3B%20background%3A%20rgba(220%2C53%2C69%2C0.1)%20%21important%3B%20%7D%5Cn%20%20%20%20%20%20.ktt-visited%20%7B%20outline%3A%202px%20solid%20%236c757d%20%21important%3B%20outline-offset%3A%201px%20%21important%3B%20%7D%5Cn%20%20%20%20%20%20.ktt-current%20%7B%20outline%3A%203px%20solid%20%23007bff%20%21important%3B%20outline-offset%3A%202px%20%21important%3B%20%7D%5Cn%20%20%20%20%22%2Cdocument.head.appendChild(i)%2Cwindow.startKeyboardTrapTest%3Dasync%20function()%7Bconst%20t%3DArray.from(document.querySelectorAll(%5B%22a%5Bhref%5D%22%2C%22button%3Anot(%5Bdisabled%5D)%22%2C%22textarea%3Anot(%5Bdisabled%5D)%22%2C%27input%3Anot(%5Btype%3D%22hidden%22%5D)%3Anot(%5Bdisabled%5D)%27%2C%22select%3Anot(%5Bdisabled%5D)%22%2C%27%5Btabindex%5D%3Anot(%5Btabindex%3D%22-1%22%5D)%27%2C%27%5Bcontenteditable%3D%22true%22%5D%27%2C%22summary%22%2C%22area%5Bhref%5D%22%5D.join(%22%2C%20%22))).filter(t%3D%3E%7Bconst%20n%3Dwindow.getComputedStyle(t)%3Breturn%22none%22%21%3D%3Dn.display%26%26%22hidden%22%21%3D%3Dn.visibility%26%26%220%22%21%3D%3Dn.opacity%7D).sort((t%2Cn)%3D%3E%7Bconst%20e%3DparseInt(t.getAttribute(%22tabindex%22)%7C%7C%220%22)%2Co%3DparseInt(n.getAttribute(%22tabindex%22)%7C%7C%220%22)%3Breturn%20e%21%3D%3Do%3Fe-o%3A0%7D)%3Bif(0%3D%3D%3Dt.length)return%20void%20l(%22complete%22%2C%22No%20Focusable%20Elements%22%2C%22No%20focusable%20elements%20found%20on%20this%20page.%22)%3Bo.getElementById(%22ktt-status%22)%2Co.getElementById(%22ktt-results%22)%3Bconst%20n%3Do.getElementById(%22ktt-start-btn%22)%3Bn.disabled%3D%210%2Cn.innerHTML%3D%27Testing...%20%3Cspan%20class%3D%22ktt-spinner%22%3E%3C%2Fspan%3E%27%2Cl(%22testing%22%2C%22Testing%20in%20Progress%22%2C%60Found%20%24%7Bt.length%7D%20focusable%20element(s).%20Simulating%20Tab%20key%20presses...%60)%3Bconst%20e%3Dnew%20Map%2Cr%3D%7Btraps%3A%5B%5D%2CtotalElements%3At.length%2CvisitedCount%3A0%2ChasTraps%3A%211%7D%2Cs%3D3*t.length%3Blet%20i%3D0%2Cm%3Dnull%3Bconst%20u%3Ddocument.activeElement%3Bfor(%3Bi%3Cs%3B)%7Bi%2B%2B%2Cr.visitedCount%2B%2B%3Bconst%20n%3Ddocument.activeElement%3Bif(n%3D%3D%3Ddocument.body)break%3Bconst%20o%3Dn%7C%7C%22body%22%2Cl%3De.get(o)%7C%7C0%3Bif(e.set(o%2Cl%2B1)%2Cn%26%26n%21%3D%3Ddocument.body%26%26(n.classList.add(%22ktt-current%22)%2CsetTimeout(()%3D%3En.classList.remove(%22ktt-current%22)%2C50))%2Cl%3E%3D2)%7Br.hasTraps%3D%210%2Cr.traps.push(%7Belement%3An%2CcycleStart%3Am%2Citeration%3Ai%2CcycleLength%3Ad(e%2Cn)%7D)%3Bbreak%7Dm%3Dn%3Bconst%20p%3Dnew%20KeyboardEvent(%22keydown%22%2C%7Bkey%3A%22Tab%22%2CkeyCode%3A9%2Cwhich%3A9%2Cbubbles%3A%210%2Ccancelable%3A%210%7D)%3Bdocument.dispatchEvent(p)%3Bconst%20u%3Dt.indexOf(n)%3Bu%3E%3D0%26%26u%3Ct.length-1%26%26a(t%5Bu%2B1%5D)%2Cawait%20new%20Promise(t%3D%3EsetTimeout(t%2C10))%3Bc(Math.min(i%2Fs*100%2C100))%7Ddocument.querySelectorAll(%22.ktt-current%22).forEach(t%3D%3Et.classList.remove(%22ktt-current%22))%3Btry%7Bu%26%26%22function%22%3D%3Dtypeof%20u.focus%26%26u.focus()%7Dcatch(t)%7B%7Dp(r%2Ct)%2Cn.innerHTML%3D%22Test%20Again%22%2Cn.disabled%3D%211%7D%2Cwindow.highlightKTTElement%3Dfunction(t)%7Bdocument.querySelectorAll(%22.ktt-visited%22).forEach(t%3D%3Et.classList.remove(%22ktt-visited%22))%2Ct.classList.add(%22ktt-visited%22)%7D%2Cwindow.cleanupKTT%3Dfunction()%7Bdocument.getElementById(%22kbd-trap-tester-host%22)%3F.remove()%2Cdocument.getElementById(%22ktt-highlight-style%22)%3F.remove()%2Cdocument.querySelectorAll(%22.ktt-trap%2C%20.ktt-visited%2C%20.ktt-current%22).forEach(t%3D%3E%7Bt.classList.remove(%22ktt-trap%22%2C%22ktt-visited%22%2C%22ktt-current%22)%7D)%2Cdelete%20window.startKeyboardTrapTest%2Cdelete%20window.cleanupKTT%2Cdelete%20window.highlightKTTElement%7D%2Cconsole.log(%22%5BKeyboard%20Trap%20Tester%5D%20-%20Ready%22)%7Dcatch(u)%7Balert(%22Bookmarklet%20Error%3A%20%22%2Bu.message)%7D%7D()%2Cconsole.log(%22%5CnSource%3A%20https%3A%2F%2Fgithub.com%2Fpattespatte%2Fpublic-bookmarklets%2F%5CnBookmarklet%20name%3A%20Keyboard%20Trap%20Tester%5Cn%22)%3B
← Back to all bookmarklets