focus-method-with-delegatesFocus.html (3735B)
1 <!DOCTYPE html> 2 <script src="/resources/testharness.js"></script> 3 <script src="/resources/testharnessreport.js"></script> 4 <script src="/resources/testdriver.js"></script> 5 <script src="/resources/testdriver-vendor.js"></script> 6 <script src="resources/shadow-dom.js"></script> 7 8 <template id='ShadowTemplate'> 9 <ul> 10 <li tabindex='0' id='one'>One</li> 11 <li tabindex='0' id='two'>Two</li> 12 <li id='three'>Three</li> 13 </ul> 14 </template> 15 <template id='NoFocusableShadowTemplate'> 16 <ul> 17 <li id='one'>One</li> 18 <li id='two'>Two</li> 19 <li id='three'>Three</li> 20 </ul> 21 </template> 22 <body> 23 <input id='input0'> 24 <x-shadow id='xshadow0'></x-shadow> 25 <x-shadow id='xshadow1' tabindex='0'></x-shadow> 26 <x-shadow id='xshadow2' tabindex='0' delegatesFocus></x-shadow> 27 <x-shadow-nofocus id='xshadow3'></x-shadow-nofocus> 28 <x-shadow-nofocus id='xshadow4' tabindex='0'></x-shadow-nofocus> 29 <x-shadow-nofocus id='xshadow5' tabindex='0' delegatesFocus></x-shadow-nofocus> 30 </body> 31 <script> 32 'use strict'; 33 34 function registerShadow(templateId, tagName) { 35 const template = document.getElementById(templateId); 36 37 customElements.define(tagName, class extends HTMLElement { 38 connectedCallback() { 39 const delegatesFocus = this.hasAttribute('delegatesFocus'); 40 this.attachShadow({mode: 'open', delegatesFocus: delegatesFocus}) 41 .appendChild(document.importNode(template.content, true)); 42 } 43 }); 44 } 45 46 registerShadow('ShadowTemplate', 'x-shadow'); 47 registerShadow('NoFocusableShadowTemplate', 'x-shadow-nofocus'); 48 49 test(() => { 50 xshadow0.focus(); 51 assert_equals(document.activeElement.tagName, 'BODY'); 52 assert_equals(xshadow0.shadowRoot.activeElement, null); 53 }, 'xshadow0 is not focusable without tabindex.'); 54 55 test(() => { 56 xshadow1.focus(); 57 assert_equals(document.activeElement.id, 'xshadow1'); 58 assert_equals(xshadow1.shadowRoot.activeElement, null); 59 }, 'xshadow1 becomes focusable with tabindex.'); 60 61 test(() => { 62 xshadow2.focus(); 63 assert_equals(document.activeElement.id, 'xshadow2'); 64 assert_equals(xshadow2.shadowRoot.activeElement.id, 'one'); 65 }, 'on focus(), focusable xshadow2 with delegatesFocus=true delegates focus into its inner element.'); 66 67 test(() => { 68 xshadow2.shadowRoot.querySelector('#two').focus(); 69 assert_equals(document.activeElement.id, 'xshadow2'); 70 assert_equals(xshadow2.shadowRoot.activeElement.id, 'two'); 71 }, 'if an element within shadow is focused, focusing on shadow host should not slide focus to its inner element.'); 72 73 test(() => { 74 xshadow2.focus(); 75 assert_equals(document.activeElement.id, 'xshadow2'); 76 assert_equals(xshadow2.shadowRoot.activeElement.id, 'two'); 77 }, 'xshadow2.focus() shouldn\'t move focus to #one when its inner element is already focused.'); 78 79 test(() => { 80 // Focus outside shadow DOMs. 81 input0.focus(); 82 83 // within shadow root. This is different from mouse click behavior. 84 xshadow1.shadowRoot.querySelector('#three').focus(); 85 assert_equals(document.activeElement.id, 'input0'); 86 xshadow2.shadowRoot.querySelector('#three').focus(); 87 assert_equals(document.activeElement.id, 'input0'); 88 }, 'focus() inside shadow DOM should not focus its shadow host, nor focusable siblings.'); 89 90 test(() => { 91 xshadow3.focus(); 92 assert_equals(document.activeElement.id, 'input0'); 93 }, 'If any element including shadow host is not focusable, focus doesn\'t change.'); 94 95 test(() => { 96 xshadow4.focus(); 97 assert_equals(document.activeElement.id, 'xshadow4'); 98 xshadow5.focus(); 99 assert_equals(document.activeElement.id, 'xshadow4'); 100 }, 'If no element is focusable within a delegatesFocus shadow root, the host can\'t get focus regardless of host\'s tabIndex.'); 101 </script>