| <!DOCTYPE html> |
| <script src="../../../resources/js-test.js"></script> |
| <template id="ShadowTemplate"> |
| <ul> |
| <li tabindex="0" id="one">One</li> |
| <li tabindex="0" id="two">Two</li> |
| <li id="three">Three</li> |
| </ul> |
| </template> |
| <template id="NoFocusableShadowTemplate"> |
| <ul> |
| <li id="one">One</li> |
| <li id="two">Two</li> |
| <li id="three">Three</li> |
| </ul> |
| </template> |
| <body> |
| <input id="input0"> |
| <x-shadow id="xshadow0"></x-shadow> |
| <x-shadow id="xshadow1" tabindex="0"></x-shadow> |
| <x-shadow id="xshadow2" tabindex="0" delegatesFocus></x-shadow> |
| <x-shadow-nofocus id="xshadow3"></x-shadow-nofocus> |
| <x-shadow-nofocus id="xshadow4" tabindex="0"></x-shadow-nofocus> |
| <x-shadow-nofocus id="xshadow5" tabindex="0" delegatesFocus></x-shadow-nofocus> |
| </body> |
| <script> |
| function registerShadow(templateId, tagName) { |
| var template = document.getElementById(templateId); |
| var proto = Object.create(HTMLElement.prototype); |
| proto.createdCallback = function() { |
| var delegatesFocus = this.hasAttribute('delegatesFocus'); |
| this.attachShadow({'mode': 'open', 'delegatesFocus': delegatesFocus}).appendChild( |
| document.importNode(template.content, true)); |
| }; |
| document.registerElement(tagName, { prototype: proto }); |
| } |
| |
| registerShadow('ShadowTemplate', 'x-shadow'); |
| registerShadow('NoFocusableShadowTemplate', 'x-shadow-nofocus'); |
| |
| debug('xshadow0 is not focusable without tabindex.'); |
| xshadow0.focus(); |
| shouldBeEqualToString('document.activeElement.tagName', 'BODY'); |
| shouldBeNull('xshadow0.shadowRoot.activeElement'); |
| |
| debug('xshadow1 becomes focusable with tabindex.'); |
| xshadow1.focus(); |
| shouldBeEqualToString('document.activeElement.id', 'xshadow1'); |
| shouldBeNull('xshadow1.shadowRoot.activeElement'); |
| |
| debug('on focus(), focusable xshadow2 with delegatesFocus=true delegates focus into its inner element.'); |
| xshadow2.focus(); |
| shouldBeEqualToString('document.activeElement.id', 'xshadow2'); |
| shouldBeEqualToString('xshadow2.shadowRoot.activeElement.id', 'one'); |
| |
| debug('if an element within shadow is focused, focusing on shadow host should not slide focus to its inner element.'); |
| xshadow2.shadowRoot.querySelector('#two').focus(); |
| shouldBeEqualToString('document.activeElement.id', 'xshadow2'); |
| shouldBeEqualToString('xshadow2.shadowRoot.activeElement.id', 'two'); |
| |
| debug('xshadow2.focus() shouldn\'t move focus to #one when its inner element is already focused.'); |
| xshadow2.focus(); |
| shouldBeEqualToString('document.activeElement.id', 'xshadow2'); |
| shouldBeEqualToString('xshadow2.shadowRoot.activeElement.id', 'two'); |
| |
| // Focus outside shadow DOMs. |
| input0.focus(); |
| |
| debug('focus() inside shadow DOM should not focus its shadow host, nor focusable siblings.'); |
| // within shadow root. This is different from mouse click behavior. |
| xshadow1.shadowRoot.querySelector('#three').focus(); |
| shouldBeEqualToString('document.activeElement.id', 'input0'); |
| xshadow2.shadowRoot.querySelector('#three').focus(); |
| shouldBeEqualToString('document.activeElement.id', 'input0'); |
| |
| debug('If any element including shadow host is not focusable, focus doesn\'t change.'); |
| xshadow3.focus(); |
| shouldBeEqualToString('document.activeElement.id', 'input0'); |
| |
| debug('If no element is focusable within shadow root, but the shadow host is focusable, then the host gets focus regardless of delegatesFocus.'); |
| xshadow4.focus(); |
| shouldBeEqualToString('document.activeElement.id', 'xshadow4'); |
| xshadow5.focus(); |
| shouldBeEqualToString('document.activeElement.id', 'xshadow5'); |
| </script> |