| <!DOCTYPE html> |
| <html> |
| <body> |
| <p>Tests for moving focus by pressing tab key across shadow boundaries.<br> |
| To manually test, press tab key sixteen times then shift+tab sixteen times.<br> |
| It should traverse focusable elements in the increasing numerical order and then in the reverse order.</p> |
| <style> |
| |
| #test-content > * { |
| display: block; |
| width: 350px; |
| height: 150px; |
| border: solid 1px black; |
| margin: 10px; |
| float: left; |
| } |
| |
| pre { |
| padding-top: 1rem; |
| clear: both; |
| } |
| |
| </style> |
| <div id="test-content"> |
| |
| <div id="first" tabindex="1">1. First sequentially focusable element</div> |
| |
| <div id="shadow-without-tabindex"> |
| A non-focusable shadow host should not be focused. |
| <div slot="slot" tabindex="0">5. Slotted content with tabindex=0</div> |
| <div slot="slot" tabindex="3">4. Slotted content with tabindex=4</div> |
| </div> |
| |
| <div id="shadow-with-multiple-slots"> |
| A non-focusable shadow host should not be focused. |
| <div slot="slot2"><div tabindex="2">11. Content in slot 2 with tabindex=1</div></div> |
| <div slot="slot2" tabindex="1">10. Content in slot 2 with tabindex=1</div> |
| <div slot="slot2" tabindex="0">12. Content in slot 2 with tabindex=0</div> |
| <div slot="slot1" tabindex="0">9. Content in slot 1 with tabindex=0</div> |
| <div slot="slot1" tabindex="7">8. Content in slot 1 with tabindex=7</div> |
| </div> |
| |
| <div id="shadow-with-slot-fallback"> |
| A non-focusable shadow host should not be focused. |
| </div> |
| |
| </div> |
| <pre></pre> |
| <script> |
| |
| var oldActiveElement = null; |
| function log() |
| { |
| setTimeout(function () { |
| var newActiveElement = document.activeElement; |
| |
| var shadowRoot = newActiveElement.shadowRoot || newActiveElement.closedShadowRoot; |
| if (shadowRoot) { |
| var activeElementInShadow = shadowRoot.activeElement; |
| if (activeElementInShadow) |
| newActiveElement = activeElementInShadow; |
| } |
| |
| if (oldActiveElement == newActiveElement || newActiveElement == document.body) |
| return; |
| oldActiveElement = newActiveElement; |
| document.querySelector('pre').textContent += newActiveElement.firstChild.textContent.trim() + '\n'; |
| }, 0); |
| } |
| |
| if (window.testRunner) { |
| testRunner.dumpAsText(); |
| testRunner.waitUntilDone(); |
| } |
| |
| window.onload = function () { |
| document.onkeydown = log; |
| |
| for (var element of document.querySelectorAll('#test-content *')) { |
| if (element instanceof HTMLIFrameElement) |
| element.contentDocument.onkeydown = log; |
| else |
| element.onfocus = log; |
| } |
| |
| var hostWithoutTabIndex = document.getElementById('shadow-without-tabindex'); |
| hostWithoutTabIndex.closedShadowRoot = hostWithoutTabIndex.attachShadow({mode: 'closed'}); |
| hostWithoutTabIndex.closedShadowRoot.innerHTML = ` |
| <div tabindex="2" onfocus="log(this)">3. The focusable element in shadow tree with the lowest tabindex</div> |
| <slot name="slot" onfocus="log(this)">Non-focusable slot element should not be focused</slot> |
| <div tabindex="1" onfocus="log(this)">2. The focusable element in shadow tree with the higehst tabindex</div>`; |
| |
| var hostWithMultipleSlots = document.getElementById('shadow-with-multiple-slots'); |
| hostWithMultipleSlots.closedShadowRoot = hostWithMultipleSlots.attachShadow({mode: 'closed'}); |
| hostWithMultipleSlots.closedShadowRoot.innerHTML = ` |
| <slot name="slot1" tabindex="2" onfocus="log(this)" style="display:block;">7. Focusable slot 1</slot> |
| <div tabindex="1" onfocus="log(this)">6. The focusable element in shadow tree with the higehst tabindex</div> |
| <slot name="slot2" onfocus="log(this)">Non-focusable slot 2 should not be focused</slot>`; |
| |
| var shadowWithSlotFallback = document.getElementById('shadow-with-slot-fallback'); |
| shadowWithSlotFallback.closedShadowRoot = shadowWithSlotFallback.attachShadow({mode: 'closed'}); |
| shadowWithSlotFallback.closedShadowRoot.innerHTML = ` |
| <slot name="slot1" onfocus="log(this)"> |
| Non-focusable slot should not be focused. |
| <div tabindex="0">17. Non-focusable slot fallback with tabindex=0</div> |
| <div tabindex="1">16. Non-focusable slot fallback with tabindex=1</div> |
| </slot> |
| <div tabindex="2" onfocus="log(this)">15. Shadow content with tabindex=2</div> |
| <slot name="slot2" tabindex="1" style="display:block;" onfocus="log(this)"> |
| 13. Focusable slot element. |
| <div tabindex="0">14. Focusable slot fallback content with tabindex=0</div> |
| </slot>`; |
| |
| document.getElementById('first').focus(); |
| document.onkeydown(); |
| |
| if (window.eventSender) |
| moveFocusForward(16); |
| } |
| |
| function moveFocusForward(focusCount) |
| { |
| setTimeout(function () { |
| if (!focusCount) |
| return moveFocusBackward(16); |
| eventSender.keyDown('\t'); |
| setTimeout(function () { |
| moveFocusForward(focusCount - 1); |
| }, 1); |
| }, 1); |
| } |
| |
| function moveFocusBackward(focusCount) |
| { |
| setTimeout(function () { |
| if (!focusCount) { |
| document.getElementById('test-content').style.display = 'none'; |
| testRunner.notifyDone(); |
| return; |
| } |
| eventSender.keyDown('\t', ['shiftKey']); |
| setTimeout(function () { |
| moveFocusBackward(focusCount - 1); |
| }, 1); |
| }, 1); |
| } |
| |
| </script> |
| </body> |
| </html> |