tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Range_setEnd.html (24081B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>focus move tests caused by a call of Range.setEnd(), Range.setEndAfter() and Range.setEndBefore()</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <body>
      7 <div style="height: 3000px;">Spacer to check whether or not page was scrolled down to focused editor</div>
      8 <p id="staticBefore">static text</p>
      9 <div id="editor" contenteditable><p>content of editor</p></div>
     10 <div id="outerEditor" contenteditable
     11 ><p>content of outer editor</p><div id="staticInEditor" contenteditable="false"
     12 ><p>static content of outer editor</p><div id="innerEditor" contenteditable
     13 ><p>content of inner editor</p></div></div></div>
     14 <p id="staticAfter">static text</p>
     15 <p><a id="anchor" href="about:blank">anchor</a></p>
     16 <script>
     17 "use strict";
     18 
     19 var staticBefore = {
     20    element: document.getElementById("staticBefore"),
     21    textNode: document.getElementById("staticBefore").firstChild,
     22    textLength: document.getElementById("staticBefore").firstChild.length
     23 };
     24 var editor = {
     25    element: document.getElementById("editor"),
     26    textNode: document.getElementById("editor").firstChild.firstChild,
     27    textLength: document.getElementById("editor").firstChild.firstChild.length
     28 };
     29 var outerEditor = {
     30    element: document.getElementById("outerEditor"),
     31    textNode: document.getElementById("outerEditor").firstChild.firstChild,
     32    textLength: document.getElementById("outerEditor").firstChild.firstChild.length
     33 };
     34 var staticInEditor = {
     35    element: document.getElementById("staticInEditor"),
     36    textNode: document.getElementById("staticInEditor").firstChild,
     37    textLength: document.getElementById("staticInEditor").firstChild.length
     38 };
     39 var innerEditor = {
     40    element: document.getElementById("innerEditor"),
     41    textNode: document.getElementById("innerEditor").firstChild.firstChild,
     42    textLength: document.getElementById("innerEditor").firstChild.firstChild.length
     43 };
     44 var staticAfter = {
     45    element: document.getElementById("staticAfter"),
     46    textNode: document.getElementById("staticAfter").firstChild,
     47    textLength: document.getElementById("staticAfter").firstChild.length
     48 };
     49 var anchor = {
     50    element: document.getElementById("anchor"),
     51    textNode: document.getElementById("anchor").firstChild,
     52    textLength: document.getElementById("anchor").firstChild.length
     53 };
     54 
     55 function resetFocusAndSelectionRange(aFocus)
     56 {
     57    document.getSelection().removeAllRanges();
     58    if (document.activeElement) {
     59        document.activeElement.blur();
     60    }
     61    if (aFocus) {
     62        aFocus.element.focus();
     63        document.getSelection().collapse(aFocus.textNode, 0);
     64    } else {
     65        document.getSelection().collapse(staticBefore.textNode, 0);
     66    }
     67    document.documentElement.scrollTop = 0;
     68 }
     69 
     70 function setEnd(aNode, aOffset)
     71 {
     72    document.getSelection().getRangeAt(0).setEnd(aNode, aOffset);
     73 }
     74 
     75 function setEndBefore(aNode, aOffset)
     76 {
     77    document.getSelection().getRangeAt(0).setEndBefore(aNode);
     78 }
     79 
     80 function setEndAfter(aNode, aOffset)
     81 {
     82    document.getSelection().getRangeAt(0).setEndAfter(aNode);
     83 }
     84 
     85 // Range.setEnd*() should work same as collapse if specified end position is before its start.
     86 [{ func: setEnd, doingDescription: "Range.setEnd()" },
     87 { func: setEndBefore, doingDescription: "Range.setEndBefore()" }].forEach((aTest, aIndex, aArray)=>{
     88    test(function() {
     89        resetFocusAndSelectionRange(editor);
     90        document.getSelection().selectAllChildren(editor.textNode);
     91        aTest.func(staticBefore.textNode, 0);
     92        assert_equals(document.activeElement, editor.element);
     93        assert_equals(document.documentElement.scrollTop, 0);
     94    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
     95    test(function() {
     96        resetFocusAndSelectionRange(outerEditor);
     97        document.getSelection().selectAllChildren(outerEditor.textNode);
     98        aTest.func(editor.textNode, 0);
     99        assert_equals(document.activeElement, editor.element);
    100        assert_equals(document.documentElement.scrollTop, 0);
    101    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
    102    test(function() {
    103        resetFocusAndSelectionRange();
    104        document.getSelection().selectAllChildren(staticInEditor.textNode);
    105        aTest.func(outerEditor.textNode, 0);
    106        assert_equals(document.activeElement, outerEditor.element);
    107        assert_equals(document.documentElement.scrollTop, 0);
    108    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection) when active element is the <body>");
    109    test(function() {
    110        resetFocusAndSelectionRange(innerEditor);
    111        document.getSelection().selectAllChildren(innerEditor.textNode);
    112        aTest.func(outerEditor.textNode, 0);
    113        assert_equals(document.activeElement, outerEditor.element);
    114        assert_equals(document.documentElement.scrollTop, 0);
    115    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
    116    test(function() {
    117        resetFocusAndSelectionRange(anchor);
    118        document.getSelection().selectAllChildren(anchor.textNode);
    119        aTest.func(staticAfter.textNode, 0);
    120        assert_equals(document.activeElement, anchor.element);
    121        assert_equals(document.documentElement.scrollTop, 0);
    122    }, "Active element should be 'anchor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (before the selection) when active element is 'anchor'");
    123 
    124    test(function() {
    125        resetFocusAndSelectionRange();
    126        document.getSelection().collapse(staticBefore.textNode, staticBefore.textLength);
    127        aTest.func(staticBefore.textNode, 0);
    128        assert_equals(document.activeElement, document.body);
    129        assert_equals(document.documentElement.scrollTop, 0);
    130    }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is the <body>");
    131    test(function() {
    132        resetFocusAndSelectionRange(editor);
    133        document.getSelection().collapse(editor.textNode, editor.textLength);
    134        aTest.func(staticBefore.textNode, 0);
    135        assert_equals(document.activeElement, editor.element);
    136        assert_equals(document.documentElement.scrollTop, 0);
    137    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor'");
    138    test(function() {
    139        resetFocusAndSelectionRange(outerEditor);
    140        document.getSelection().collapse(outerEditor.textNode, outerEditor.textLength);
    141        aTest.func(editor.textNode, 0);
    142        assert_equals(document.activeElement, editor.element);
    143        assert_equals(document.documentElement.scrollTop, 0);
    144    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor'");
    145    test(function() {
    146        resetFocusAndSelectionRange();
    147        document.getSelection().collapse(staticInEditor.textNode, staticInEditor.textLength);
    148        aTest.func(outerEditor.textNode, 0);
    149        assert_equals(document.activeElement, outerEditor.element);
    150        assert_equals(document.documentElement.scrollTop, 0);
    151    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is the <body> and selection is in 'staticInEditor'");
    152    test(function() {
    153        resetFocusAndSelectionRange(innerEditor);
    154        document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
    155        aTest.func(outerEditor.textNode, 0);
    156        assert_equals(document.activeElement, outerEditor.element);
    157        assert_equals(document.documentElement.scrollTop, 0);
    158    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor'");
    159    test(function() {
    160        resetFocusAndSelectionRange(anchor);
    161        document.getSelection().collapse(anchor.textNode, anchor.textLength);
    162        aTest.func(staticAfter.textNode, 0);
    163        assert_equals(document.activeElement, anchor.element);
    164        assert_equals(document.documentElement.scrollTop, 0);
    165    }, "Active element should be 'anchor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'anchor'");
    166    test(function() {
    167        resetFocusAndSelectionRange();
    168        document.getSelection().collapse(anchor.textNode, anchor.textLength);
    169        aTest.func(anchor.textNode, 0);
    170        assert_equals(document.activeElement, document.body);
    171        assert_equals(document.documentElement.scrollTop, 0);
    172    }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'anchor' (before the collapsed selection) when active element is the <body>");
    173 
    174    test(function() {
    175        resetFocusAndSelectionRange();
    176        document.getSelection().setBaseAndExtent(staticBefore.textNode, staticBefore.textLength,
    177                                                 editor.textNode, editor.textLength);
    178        aTest.func(staticBefore.textNode, 0);
    179        assert_equals(document.activeElement, document.body);
    180        assert_equals(document.documentElement.scrollTop, 0);
    181    }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticBefore' (before the selection, between end of the first text node of 'staticBefore' and end of the first text node of 'editor') when active element is the <body>");
    182    test(function() {
    183        resetFocusAndSelectionRange();
    184        document.getSelection().setBaseAndExtent(editor.textNode, editor.textLength,
    185                                                 outerEditor.textNode, outerEditor.textLength);
    186        aTest.func(editor.textNode, 0);
    187        assert_equals(document.activeElement, editor.element);
    188        assert_equals(document.documentElement.scrollTop, 0);
    189    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (before the selection, between end of the first text node of 'editor' and end of the first text node of 'outerEditor') when active element is the <body>");
    190    test(function() {
    191        resetFocusAndSelectionRange(outerEditor);
    192        document.getSelection().setBaseAndExtent(outerEditor.textNode, outerEditor.textLength,
    193                                                 innerEditor.textNode, innerEditor.textLength);
    194        aTest.func(outerEditor.textNode, 0);
    195        assert_equals(document.activeElement, outerEditor.element);
    196        assert_equals(document.documentElement.scrollTop, 0);
    197    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (before the selection, between end of the first text node of 'outerEditor' and end of the first text node of 'innerEditor') when active element is 'outerEditor'");
    198    test(function() {
    199        resetFocusAndSelectionRange();
    200        document.getSelection().setBaseAndExtent(staticInEditor.textNode, staticInEditor.textLength,
    201                                                 innerEditor.textNode, innerEditor.textLength);
    202        aTest.func(staticInEditor.textNode, 0);
    203        assert_equals(document.activeElement, document.body);
    204        assert_equals(document.documentElement.scrollTop, 0);
    205    }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'staticInEditor' (before the selection, between end of the first text node of 'staticInEditor' and end of the first text node of 'innerEditor') when active element is the <body>");
    206 });
    207 
    208 test(function() {
    209    resetFocusAndSelectionRange();
    210    document.getSelection().selectAllChildren(staticAfter.textNode);
    211    setEndAfter(innerEditor.textNode);
    212    assert_equals(document.activeElement, innerEditor.element);
    213    assert_equals(document.documentElement.scrollTop, 0);
    214 }, "Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticAfter'");
    215 test(function() {
    216    resetFocusAndSelectionRange(innerEditor);
    217    document.getSelection().selectAllChildren(innerEditor.textNode);
    218    setEndAfter(staticInEditor.textNode);
    219    assert_equals(document.activeElement, innerEditor.element);
    220    assert_equals(document.documentElement.scrollTop, 0);
    221 }, "Active element should be 'innerEditor' after Selection.setEndAfter() with the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor'");
    222 test(function() {
    223    resetFocusAndSelectionRange();
    224    document.getSelection().selectAllChildren(staticInEditor.textNode);
    225    setEndAfter(outerEditor.textNode);
    226    assert_equals(document.activeElement, outerEditor.element);
    227    assert_equals(document.documentElement.scrollTop, 0);
    228 }, "Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor'");
    229 test(function() {
    230    resetFocusAndSelectionRange(innerEditor);
    231    document.getSelection().selectAllChildren(innerEditor.textNode);
    232    setEndAfter(outerEditor.textNode);
    233    assert_equals(document.activeElement, outerEditor.element);
    234    assert_equals(document.documentElement.scrollTop, 0);
    235 }, "Active element should be 'outerEditor' after Selection.setEndAfter() with the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
    236 test(function() {
    237    resetFocusAndSelectionRange(outerEditor);
    238    document.getSelection().selectAllChildren(outerEditor.textNode);
    239    setEndAfter(editor.textNode);
    240    assert_equals(document.activeElement, editor.element);
    241    assert_equals(document.documentElement.scrollTop, 0);
    242 }, "Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
    243 test(function() {
    244    resetFocusAndSelectionRange(editor);
    245    document.getSelection().selectAllChildren(editor.textNode);
    246    setEndAfter(staticBefore.textNode);
    247    assert_equals(document.activeElement, editor.element);
    248    assert_equals(document.documentElement.scrollTop, 0);
    249 }, "Active element should be 'editor' after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
    250 test(function() {
    251    resetFocusAndSelectionRange(anchor);
    252    document.getSelection().selectAllChildren(anchor.textNode);
    253    setEndAfter(staticBefore.textNode);
    254    assert_equals(document.activeElement, anchor.element);
    255    assert_equals(document.documentElement.scrollTop, 0);
    256 }, "Active element should be 'anchor' after Selection.setEndAfter() with the first text node of 'staticBefore' (before the selection) when active element is 'anchor'");
    257 
    258 // Range.setEnd*() should blur focused editing host when it expands selection to outside of it.
    259 [{ func: setEnd, doingDescription: "Range.setEnd()" },
    260 { func: setEndAfter, doingDescription: "Range.setEndAfter()" },
    261 { func: setEndBefore, doingDescription: "Range.setEndBefore()" }].forEach((aTest, aIndex, aArray)=>{
    262    test(function() {
    263        resetFocusAndSelectionRange(editor);
    264        document.getSelection().collapse(editor.textNode, 0);
    265        aTest.func(outerEditor.textNode, 0);
    266        assert_equals(document.activeElement, editor.element);
    267        assert_equals(document.documentElement.scrollTop, 0);
    268    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'editor'");
    269    test(function() {
    270        resetFocusAndSelectionRange(outerEditor);
    271        document.getSelection().collapse(outerEditor.textNode, 0);
    272        aTest.func(staticInEditor.textNode, 0);
    273        assert_equals(document.activeElement, outerEditor.element);
    274        assert_equals(document.documentElement.scrollTop, 0);
    275    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the collapsed selection) when active element is 'outerEditor'");
    276    test(function() {
    277        resetFocusAndSelectionRange(outerEditor);
    278        document.getSelection().collapse(outerEditor.textNode, 0);
    279        aTest.func(innerEditor.textNode, 0);
    280        assert_equals(document.activeElement, outerEditor.element);
    281        assert_equals(document.documentElement.scrollTop, 0);
    282    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (after end of the collapsed selection) when active element is 'outerEditor'");
    283    test(function() {
    284        resetFocusAndSelectionRange(outerEditor);
    285        document.getSelection().collapse(outerEditor.textNode, 0);
    286        aTest.func(staticAfter.textNode, 0);
    287        assert_equals(document.activeElement, outerEditor.element);
    288        assert_equals(document.documentElement.scrollTop, 0);
    289    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (after end of the collapsed selection) when active element is 'outerEditor'");
    290    test(function() {
    291        resetFocusAndSelectionRange(editor);
    292        document.getSelection().selectAllChildren(editor.textNode);
    293        aTest.func(outerEditor.textNode, 0);
    294        assert_equals(document.activeElement, editor.element);
    295        assert_equals(document.documentElement.scrollTop, 0);
    296    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'editor'");
    297    test(function() {
    298        resetFocusAndSelectionRange(outerEditor);
    299        document.getSelection().selectAllChildren(outerEditor.textNode);
    300        aTest.func(staticInEditor.textNode, 0);
    301        assert_equals(document.activeElement, outerEditor.element);
    302        assert_equals(document.documentElement.scrollTop, 0);
    303    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (after end of the selection) when active element is 'outerEditor'");
    304    test(function() {
    305        resetFocusAndSelectionRange(outerEditor);
    306        document.getSelection().selectAllChildren(outerEditor.textNode);
    307        aTest.func(innerEditor.textNode, 0);
    308        assert_equals(document.activeElement, outerEditor.element);
    309        assert_equals(document.documentElement.scrollTop, 0);
    310    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (after end of the selection) when active element is 'outerEditor'");
    311    test(function() {
    312        resetFocusAndSelectionRange(outerEditor);
    313        document.getSelection().selectAllChildren(outerEditor.textNode);
    314        aTest.func(staticAfter.textNode, 0);
    315        assert_equals(document.activeElement, outerEditor.element);
    316        assert_equals(document.documentElement.scrollTop, 0);
    317    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticAfter' (after end of the selection) when active element is 'outerEditor'");
    318 });
    319 
    320 // Range.setEnd*() should move focus to an editing host when the range is shrunken into it.
    321 [{ func: setEnd, doingDescription: "Range.setEnd()" },
    322 { func: setEndAfter, doingDescription: "Range.setEndAfter()" }].forEach((aTest, aIndex, aArray)=>{
    323    test(function() {
    324        resetFocusAndSelectionRange();
    325        document.getSelection().setBaseAndExtent(editor.textNode, 0,
    326                                                 outerEditor.textNode, outerEditor.textLength);
    327        aTest.func(editor.textNode, editor.textLength);
    328        assert_equals(document.activeElement, editor.element);
    329        assert_equals(document.documentElement.scrollTop, 0);
    330    }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>");
    331    test(function() {
    332        resetFocusAndSelectionRange(outerEditor);
    333        document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
    334                                                 staticInEditor.textNode, staticInEditor.textLength);
    335        aTest.func(outerEditor.textNode, outerEditor.textLength);
    336        assert_equals(document.activeElement, outerEditor.element);
    337        assert_equals(document.documentElement.scrollTop, 0);
    338    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'outerEditor' and selection end is in 'staticInEditor'");
    339    test(function() {
    340        resetFocusAndSelectionRange(outerEditor);
    341        document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
    342                                                 innerEditor.textNode, innerEditor.textLength);
    343        aTest.func(outerEditor.textNode, outerEditor.textLength);
    344        assert_equals(document.activeElement, outerEditor.element);
    345        assert_equals(document.documentElement.scrollTop, 0);
    346    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'outerEditor' and selection end is in 'innerEditor'");
    347    test(function() {
    348        resetFocusAndSelectionRange();
    349        document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
    350                                                 staticAfter.textNode, staticAfter.textLength);
    351        aTest.func(innerEditor.textNode, innerEditor.textLength);
    352        assert_equals(document.activeElement, innerEditor.element);
    353        assert_equals(document.documentElement.scrollTop, 0);
    354    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'innerEditor' and selection end is in 'staticAfter'");
    355    test(function() {
    356        resetFocusAndSelectionRange();
    357        document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
    358                                                 innerEditor.textNode, innerEditor.textLength);
    359        aTest.func(staticInEditor.textNode, staticInEditor.textLength);
    360        assert_equals(document.activeElement, document.body);
    361        assert_equals(document.documentElement.scrollTop, 0);
    362    }, "Active element should be the <body> after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is the <body>");
    363 });
    364 </script>