| <!DOCTYPE html> |
| <style> |
| host { |
| border: solid 1px red; |
| padding: 5px; |
| } |
| .sample{ |
| border: solid 1px green; |
| padding: 10px; |
| } |
| </style> |
| <div> |
| <div id="sample1" class="sample">012<host id="host1">host1</host>345</div> |
| <div id="sample2" class="sample" contenteditable>012<host id="host2">host2</host>345</div> |
| <div id="sample3" class="sample">012<host id="host3">host3abc<host id="host4">host4</host>host3def</host>345</div> |
| <div id="sample4" class="sample">012<host id="host5">host5</host>345</div> |
| </div> |
| <p>end of document</p> |
| <script src="../../resources/js-test.js"></script> |
| <script> |
| description('SelectAll and Shadow DOM Tree'); |
| |
| function installShadowTree(host) { |
| var shadowRoot = host.createShadowRoot(); |
| shadowRoot.innerHTML = '<i>BEFORE</i> <b><content></b> <i>AFTER</i>'; |
| } |
| |
| var selection = window.getSelection(); |
| |
| // In this file, we use following symbols in pictures in comment. |
| // ^=anchor position, |=focus position, [...]=shadow DOM boundary. |
| |
| debug('Select all from host content in shadow tree => select all on document'); |
| // before 012 [BEFORE ^host1| AFTER] 345 |
| // select all |
| // after ^... 012 [^BEFORE host1 AFTER] 345 ...| |
| var host1 = document.getElementById('host1'); |
| installShadowTree(host1); |
| selection.collapse(host1, 0); |
| document.execCommand('selectAll'); |
| shouldBeEqualToString('selection.anchorNode.nodeValue', 'SelectAll and Shadow DOM Tree'); |
| shouldBe('selection.anchorOffset', '0'); |
| shouldBeEqualToString('selection.focusNode.nodeValue', 'end of document'); |
| shouldBe('selection.focusOffset', '15'); |
| |
| debug('\nSelect all from "EFO" in shadow tree => select descendants of immediate child of shadow root containing start position'); |
| // before 012 [B^EFO|RE host1 AFTER] 345 |
| // select all |
| // after 012 [^BEFORE| host2 AFTER] 345 |
| selection.collapse(host1.shadowRoot.firstChild.firstChild, 1); |
| selection.extend(host1.shadowRoot.firstChild.firstChild, 4); |
| document.execCommand('selectAll'); |
| shouldBe('selection.anchorNode', 'host1.parentNode'); |
| shouldBe('selection.anchorOffset', '1'); |
| shouldBe('selection.focusNode', 'host1.parentNode'); |
| shouldBe('selection.focusOffset', '1'); |
| var selectionInHost1 = host1.shadowRoot.getSelection(); |
| shouldBeEqualToString('selectionInHost1.anchorNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost1.anchorOffset', '0'); |
| shouldBeEqualToString('selectionInHost1.focusNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost1.focusOffset', '6'); |
| |
| debug('\nSelect all from host content in editable => select all in editable rather than whole document'); |
| // before 012 [BEFORE |host2 AFTER] 345 |
| // select all |
| // after ^012 [BEFORE host2 AFTER] 345| |
| var host2 = document.getElementById('host2'); |
| installShadowTree(host2); |
| selection.collapse(host2, 0); |
| document.execCommand('selectAll'); |
| shouldBeEqualToString('selection.anchorNode.nodeValue', '012'); |
| shouldBe('selection.anchorOffset', '0'); |
| shouldBeEqualToString('selection.focusNode.nodeValue', '345'); |
| shouldBe('selection.anchorOffset', '0'); |
| |
| debug('\nSelect all from "EFO" in shadow tree => select descendants of immediate child of shadow root containing start position, host editable doesn\'t affect select all'); |
| // before 012 [B^EFO|RE host2 AFTER] 345 |
| // select all |
| // after 012 [^BEFORE| host2 AFTER] 345 |
| selection.collapse(host2.shadowRoot.firstChild.firstChild, 1); |
| selection.extend(host2.shadowRoot.firstChild.firstChild, 4); |
| document.execCommand('selectAll'); |
| shouldBe('selection.anchorNode', 'host2.parentNode'); |
| shouldBe('selection.anchorOffset', '1'); |
| shouldBe('selection.focusNode', 'host2.parentNode'); |
| shouldBe('selection.focusOffset', '1'); |
| var selectionInHost2 = host2.shadowRoot.getSelection(); |
| shouldBeEqualToString('selectionInHost2.anchorNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost2.anchorOffset', '0'); |
| shouldBeEqualToString('selectionInHost2.focusNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost2.focusOffset', '6'); |
| |
| debug('\nSelect all from host content in nested shadow tree => select all on document'); |
| // before 012 [BEFORE host3abc[BFORE |host4 AFTER] host3def AFTER] 345 |
| // select all |
| // after ^ ... 012 [BEFORE host3abc[BEFORE host4 AFTER] host3def AFTER] 345 ... | |
| var host3 = document.getElementById('host3'); |
| installShadowTree(host3); |
| var host4 = document.getElementById('host4'); |
| installShadowTree(host4); |
| selection.collapse(host4, 0); |
| document.execCommand('selectAll'); |
| shouldBeEqualToString('selection.anchorNode.nodeValue', 'SelectAll and Shadow DOM Tree'); |
| shouldBe('selection.anchorOffset', '0'); |
| shouldBeEqualToString('selection.focusNode.nodeValue', 'end of document'); |
| shouldBe('selection.focusOffset', '15'); |
| |
| debug('\nSelect all from "EFO" in nested shadow tree => select descendants of immediate child of shadow root containing start position'); |
| // before 012 [BEFORE host3abc[B^EFO|RE host4 AFTER] host3def AFTER] 345 |
| // select all |
| // after 012 [BEFORE host3abc[^BEFORE| host4 AFTER] host3def AFTER] 345 |
| selection.collapse(host4.shadowRoot.firstChild.firstChild, 1); |
| selection.extend(host4.shadowRoot.firstChild.firstChild, 4); |
| document.execCommand('selectAll'); |
| shouldBe('selection.anchorNode', 'host4.parentNode'); |
| shouldBe('selection.anchorOffset', '1'); |
| shouldBe('selection.focusNode', 'host4.parentNode'); |
| shouldBe('selection.focusOffset', '1'); |
| |
| var selectionInHost3 = host3.shadowRoot.getSelection(); |
| shouldBe('selectionInHost3.anchorNode', 'null'); |
| shouldBe('selectionInHost3.anchorOffset', '0'); |
| shouldBe('selectionInHost3.focusNode', 'null'); |
| shouldBe('selectionInHost3.focusOffset', '0'); |
| |
| var selectionInHost4 = host4.shadowRoot.getSelection(); |
| shouldBeEqualToString('selectionInHost4.anchorNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost4.anchorOffset', '0'); |
| shouldBeEqualToString('selectionInHost4.focusNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost4.focusOffset', '6'); |
| |
| debug('\nSelect all from selecting node in youngest shadow DOM tree => select descendants of immediate child of shadow root containing start position'); |
| var host5 = document.getElementById('host5'); |
| installShadowTree(host5); |
| host5.createShadowRoot().innerHTML = '<i>BEFORE</i><b><shadow></shadow></b><i>AFTER</i>'; |
| var selectionInHost5 = host5.shadowRoot.getSelection(); |
| selection.collapse(host5.shadowRoot.firstChild.firstChild, 1); |
| selection.extend(host5.shadowRoot.firstChild.firstChild, 4); |
| document.execCommand('selectAll'); |
| shouldBeEqualToString('selectionInHost5.anchorNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost5.anchorOffset', '0'); |
| shouldBeEqualToString('selectionInHost5.focusNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost5.focusOffset', '6'); |
| |
| debug('\nSelect all from selecting node in oldest shadow DOM tree => select descendants of immediate child of shadow root containing start position'); |
| selection.collapse(host5.shadowRoot.olderShadowRoot.firstChild.firstChild, 1); |
| selection.extend(host5.shadowRoot.olderShadowRoot.firstChild.firstChild, 4); |
| document.execCommand('selectAll'); |
| selectionInHost5 = host5.shadowRoot.olderShadowRoot.getSelection(); |
| console.log(selectionInHost5); |
| shouldBeEqualToString('selectionInHost5.anchorNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost5.anchorOffset', '0'); |
| shouldBeEqualToString('selectionInHost5.focusNode.nodeValue', 'BEFORE'); |
| shouldBe('selectionInHost5.focusOffset', '6'); |
| </script> |