tor-browser

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

Range_setStart.html (23562B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>focus move tests caused by a call of Range.setStart(), Range.setStartAfter() and Range.setStartBefore()</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 setStart(aNode, aOffset)
     71 {
     72    document.getSelection().getRangeAt(0).setStart(aNode, aOffset);
     73 }
     74 
     75 function setStartBefore(aNode, aOffset)
     76 {
     77    document.getSelection().getRangeAt(0).setStartBefore(aNode);
     78 }
     79 
     80 function setStartAfter(aNode, aOffset)
     81 {
     82    document.getSelection().getRangeAt(0).setStartAfter(aNode);
     83 }
     84 
     85 // Range.setStart*() should work same as collapse if specified start position is after its end.
     86 [{ func: setStart, doingDescription: "Range.setStart()" },
     87 { func: setStartAfter, doingDescription: "Range.setStartAfter()" }].forEach((aTest, aIndex, aArray)=>{
     88    test(function() {
     89        resetFocusAndSelectionRange();
     90        document.getSelection().selectAllChildren(staticBefore.textNode);
     91        aTest.func(editor.textNode, editor.textLength);
     92        assert_equals(document.activeElement, editor.element);
     93        assert_equals(document.documentElement.scrollTop, 0);
     94    }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection) when active element is the <body>");
     95    test(function() {
     96        resetFocusAndSelectionRange(editor);
     97        document.getSelection().selectAllChildren(editor.textNode);
     98        aTest.func(outerEditor.textNode, outerEditor.textLength);
     99        assert_equals(document.activeElement, outerEditor.element);
    100        assert_equals(document.documentElement.scrollTop, 0);
    101    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection) when active element is 'editor'");
    102    test(function() {
    103        resetFocusAndSelectionRange(outerEditor);
    104        document.getSelection().selectAllChildren(outerEditor.textNode);
    105        aTest.func(staticInEditor.textNode, staticInEditor.textLength);
    106        assert_equals(document.activeElement, outerEditor.element);
    107        assert_equals(document.documentElement.scrollTop, 0);
    108    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection) when active element is 'outerEditor'");
    109    test(function() {
    110        resetFocusAndSelectionRange();
    111        document.getSelection().selectAllChildren(staticInEditor.textNode);
    112        aTest.func(innerEditor.textNode, innerEditor.textLength);
    113        assert_equals(document.activeElement, innerEditor.element);
    114        assert_equals(document.documentElement.scrollTop, 0);
    115    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection) when active element is the <body> and selection is in 'staticInEditor'");
    116    test(function() {
    117        resetFocusAndSelectionRange(innerEditor);
    118        document.getSelection().selectAllChildren(innerEditor.textNode);
    119        aTest.func(staticAfter.textNode, staticAfter.textLength);
    120        assert_equals(document.activeElement, innerEditor.element);
    121        assert_equals(document.documentElement.scrollTop, 0);
    122    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the selection) when active element is 'innerEditor'");
    123 
    124    test(function() {
    125        resetFocusAndSelectionRange();
    126        document.getSelection().collapse(staticBefore.textNode, 0);
    127        aTest.func(editor.textNode, editor.textLength);
    128        assert_equals(document.activeElement, editor.element);
    129        assert_equals(document.documentElement.scrollTop, 0);
    130    }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the collapsed selection) when active element is the <body>");
    131    test(function() {
    132        resetFocusAndSelectionRange(editor);
    133        document.getSelection().collapse(editor.textNode, 0);
    134        aTest.func(outerEditor.textNode, outerEditor.textLength);
    135        assert_equals(document.activeElement, outerEditor.element);
    136        assert_equals(document.documentElement.scrollTop, 0);
    137    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'editor'");
    138    test(function() {
    139        resetFocusAndSelectionRange(outerEditor);
    140        document.getSelection().collapse(outerEditor.textNode, 0);
    141        aTest.func(staticInEditor.textNode, staticInEditor.textLength);
    142        assert_equals(document.activeElement, outerEditor.element);
    143        assert_equals(document.documentElement.scrollTop, 0);
    144    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'outerEditor'");
    145    test(function() {
    146        resetFocusAndSelectionRange();
    147        document.getSelection().collapse(staticInEditor.textNode, 0);
    148        aTest.func(innerEditor.textNode, innerEditor.textLength);
    149        assert_equals(document.activeElement, innerEditor.element);
    150        assert_equals(document.documentElement.scrollTop, 0);
    151    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (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, 0);
    155        aTest.func(staticAfter.textNode, staticAfter.textLength);
    156        assert_equals(document.activeElement, innerEditor.element);
    157        assert_equals(document.documentElement.scrollTop, 0);
    158    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the collapsed selection) when active element is 'innerEditor'");
    159 
    160    test(function() {
    161        resetFocusAndSelectionRange();
    162        document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
    163                                                 editor.textNode, 0);
    164        aTest.func(editor.textNode, editor.textLength);
    165        assert_equals(document.activeElement, editor.element);
    166        assert_equals(document.documentElement.scrollTop, 0);
    167    }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection, between start of the first text node of 'staticBefore' and start of the first text node of 'editor') when active element is the <body>");
    168    test(function() {
    169        resetFocusAndSelectionRange();
    170        document.getSelection().setBaseAndExtent(editor.textNode, 0,
    171                                                 outerEditor.textNode, 0);
    172        aTest.func(outerEditor.textNode, outerEditor.textLength);
    173        assert_equals(document.activeElement, outerEditor.element);
    174        assert_equals(document.documentElement.scrollTop, 0);
    175    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection, between start of the first text node of 'editor' and start of the first text node of 'outerEditor') when active element is the <body>");
    176    test(function() {
    177        resetFocusAndSelectionRange(outerEditor);
    178        document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
    179                                                 staticInEditor.textNode, 0);
    180        aTest.func(staticInEditor.textNode, staticInEditor.textLength);
    181        assert_equals(document.activeElement, outerEditor.element);
    182        assert_equals(document.documentElement.scrollTop, 0);
    183    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'staticInEditor') when active element is 'outerEditor'");
    184    test(function() {
    185        resetFocusAndSelectionRange(outerEditor);
    186        document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
    187                                                 innerEditor.textNode, 0);
    188        aTest.func(innerEditor.textNode, innerEditor.textLength);
    189        assert_equals(document.activeElement, innerEditor.element);
    190        assert_equals(document.documentElement.scrollTop, 0);
    191    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'outerEditor' and start of the first text node of 'innerEditor') when active element is 'outerEditor'");
    192    test(function() {
    193        resetFocusAndSelectionRange();
    194        document.getSelection().setBaseAndExtent(staticInEditor.textNode, 0,
    195                                                 innerEditor.textNode, 0);
    196        aTest.func(innerEditor.textNode, innerEditor.textLength);
    197        assert_equals(document.activeElement, innerEditor.element);
    198        assert_equals(document.documentElement.scrollTop, 0);
    199    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'innerEditor' (before the selection, between start of the first text node of 'staticInEditor' and start of the first text node of 'innerEditor') when active element is the <body>");
    200    test(function() {
    201        resetFocusAndSelectionRange();
    202        document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
    203                                                 staticAfter.textNode, 0);
    204        aTest.func(staticAfter.textNode, staticAfter.textLength);
    205        assert_equals(document.activeElement, document.body);
    206        assert_equals(document.documentElement.scrollTop, 0);
    207    }, "Active element should be the <body> after " + aTest.doingDescription + " with end of the first text node of 'staticAfter' (before the selection, between start of the first text node of 'innerEditor' and start of the first text node of 'staticAfter') when active element is the <body>");
    208 });
    209 
    210 test(function() {
    211    resetFocusAndSelectionRange();
    212    document.getSelection().selectAllChildren(staticBefore.textNode);
    213    setStartBefore(editor.textNode);
    214    assert_equals(document.activeElement, editor.element);
    215    assert_equals(document.documentElement.scrollTop, 0);
    216 }, "Active element should be 'editor' after Range.setStartBefore() with the first text node of 'editor' (before the selection) when active element is the <body>");
    217 test(function() {
    218    resetFocusAndSelectionRange(editor);
    219    document.getSelection().selectAllChildren(editor.textNode);
    220    setStartBefore(outerEditor.textNode);
    221    assert_equals(document.activeElement, outerEditor.element);
    222    assert_equals(document.documentElement.scrollTop, 0);
    223 }, "Active element should be 'outerEditor' after Range.setStartBefore() with the first text node of 'outerEditor' (before the selection) when active element is 'editor'");
    224 test(function() {
    225    resetFocusAndSelectionRange(outerEditor);
    226    document.getSelection().selectAllChildren(outerEditor.textNode);
    227    setStartBefore(innerEditor.textNode);
    228    assert_equals(document.activeElement, innerEditor.element);
    229    assert_equals(document.documentElement.scrollTop, 0);
    230 }, "Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'outerEditor'");
    231 test(function() {
    232    resetFocusAndSelectionRange(innerEditor);
    233    document.getSelection().selectAllChildren(innerEditor.textNode);
    234    setStartBefore(staticAfter.textNode);
    235    assert_equals(document.activeElement, innerEditor.element);
    236    assert_equals(document.documentElement.scrollTop, 0);
    237 }, "Active element should be 'innerEditor' after Range.setStartBefore() with the first text node of 'innerEditor' (before the selection) when active element is 'innerEditor'");
    238 test(function() {
    239    resetFocusAndSelectionRange();
    240    document.getSelection().selectAllChildren(staticAfter.textNode);
    241    setStartBefore(anchor.textNode);
    242    assert_equals(document.activeElement, document.body);
    243    assert_equals(document.documentElement.scrollTop, 0);
    244 }, "Active element should be the <body> after Range.setStartBefore() with the first text node of 'anchor' (before the selection) when active element is the <body>");
    245 
    246 // Range.setStart*() should blur focused editing host when it expands selection to outside of it.
    247 [{ func: setStart, doingDescription: "Range.setStart()" },
    248 { func: setStartAfter, doingDescription: "Range.setStartAfter()" },
    249 { func: setStartBefore, doingDescription: "Range.setStartBefore()" }].forEach((aTest, aIndex, aArray)=>{
    250    test(function() {
    251        resetFocusAndSelectionRange(editor);
    252        document.getSelection().collapse(editor.textNode, editor.textLength);
    253        aTest.func(staticBefore.textNode, staticBefore.textLength);
    254        assert_equals(document.activeElement, editor.element);
    255        assert_equals(document.documentElement.scrollTop, 0);
    256    }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'staticBefore' (before the collapsed selection) when active element is 'editor'");
    257    test(function() {
    258        resetFocusAndSelectionRange(outerEditor);
    259        document.getSelection().collapse(outerEditor.textNode, outerEditor.textLength);
    260        aTest.func(editor.textNode, editor.textLength);
    261        assert_equals(document.activeElement, outerEditor.element);
    262        assert_equals(document.documentElement.scrollTop, 0);
    263    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the collapsed selection) when active element is 'outerEditor'");
    264    test(function() {
    265        resetFocusAndSelectionRange(innerEditor);
    266        document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
    267        aTest.func(outerEditor.textNode, outerEditor.textLength);
    268        assert_equals(document.activeElement, outerEditor.element);
    269        assert_equals(document.documentElement.scrollTop, 0);
    270    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the collapsed selection) when active element is 'innerEditor'");
    271    test(function() {
    272        resetFocusAndSelectionRange(innerEditor);
    273        document.getSelection().collapse(innerEditor.textNode, innerEditor.textLength);
    274        aTest.func(staticInEditor.textNode, staticInEditor.textLength);
    275        assert_equals(document.activeElement, innerEditor.element);
    276        assert_equals(document.documentElement.scrollTop, 0);
    277    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the collapsed selection) when active element is 'innerEditor'");
    278 
    279    test(function() {
    280        resetFocusAndSelectionRange(editor);
    281        document.getSelection().selectAllChildren(editor.textNode);
    282        aTest.func(staticBefore.textNode, staticBefore.textLength);
    283        assert_equals(document.activeElement, editor.element);
    284        assert_equals(document.documentElement.scrollTop, 0);
    285    }, "Active element should be 'editor' after " + aTest.doingDescription + " with end of the first text node of 'staticBefore' (before the selection) when active element is 'editor'");
    286    test(function() {
    287        resetFocusAndSelectionRange(outerEditor);
    288        document.getSelection().selectAllChildren(outerEditor.textNode);
    289        aTest.func(editor.textNode, editor.textLength);
    290        assert_equals(document.activeElement, outerEditor.element);
    291        assert_equals(document.documentElement.scrollTop, 0);
    292    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'editor' (before the selection) when active element is 'outerEditor'");
    293    test(function() {
    294        resetFocusAndSelectionRange(innerEditor);
    295        document.getSelection().selectAllChildren(innerEditor.textNode);
    296        aTest.func(outerEditor.textNode, outerEditor.textLength);
    297        assert_equals(document.activeElement, outerEditor.element);
    298        assert_equals(document.documentElement.scrollTop, 0);
    299    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with end of the first text node of 'outerEditor' (before the selection) when active element is 'innerEditor'");
    300    test(function() {
    301        resetFocusAndSelectionRange(innerEditor);
    302        document.getSelection().selectAllChildren(innerEditor.textNode);
    303        aTest.func(staticInEditor.textNode, staticInEditor.textLength);
    304        assert_equals(document.activeElement, innerEditor.element);
    305        assert_equals(document.documentElement.scrollTop, 0);
    306    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with end of the first text node of 'staticInEditor' (before the selection) when active element is 'innerEditor'");
    307 });
    308 
    309 // Range.setStart*() should move focus to an editing host when the range is shrunken into it.
    310 [{ func: setStart, doingDescription: "Range.setStart()" },
    311 { func: setStartBefore, doingDescription: "Range.setStartBefore()" }].forEach((aTest, aIndex, aArray)=>{
    312    test(function() {
    313        resetFocusAndSelectionRange();
    314        document.getSelection().setBaseAndExtent(staticBefore.textNode, 0,
    315                                                 editor.textNode, editor.textLength);
    316        aTest.func(editor.textNode, 0);
    317        assert_equals(document.activeElement, editor.element);
    318        assert_equals(document.documentElement.scrollTop, 0);
    319    }, "Active element should be 'editor' after " + aTest.doingDescription + " with start of the first text node of 'editor' (shrunken into 'editor') when active element is the <body>");
    320    test(function() {
    321        resetFocusAndSelectionRange(editor);
    322        document.getSelection().setBaseAndExtent(editor.textNode, 0,
    323                                                 outerEditor.textNode, outerEditor.textLength);
    324        aTest.func(outerEditor.textNode, 0);
    325        assert_equals(document.activeElement, outerEditor.element);
    326        assert_equals(document.documentElement.scrollTop, 0);
    327    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'outerEditor' (shrunken into 'outerEditor') when active element is 'editor'");
    328    test(function() {
    329        resetFocusAndSelectionRange(outerEditor);
    330        document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
    331                                                 staticInEditor.textNode, staticInEditor.textLength);
    332        aTest.func(staticInEditor.textNode, 0);
    333        assert_equals(document.activeElement, outerEditor.element);
    334        assert_equals(document.documentElement.scrollTop, 0);
    335    }, "Active element should be 'outerEditor' after " + aTest.doingDescription + " with start of the first text node of 'staticInEditor' (shrunken into 'staticInEditor') when active element is 'outerEditor'");
    336    test(function() {
    337        resetFocusAndSelectionRange(outerEditor);
    338        document.getSelection().setBaseAndExtent(outerEditor.textNode, 0,
    339                                                 innerEditor.textNode, innerEditor.textLength);
    340        aTest.func(innerEditor.textNode, 0);
    341        assert_equals(document.activeElement, innerEditor.element);
    342        assert_equals(document.documentElement.scrollTop, 0);
    343    }, "Active element should be 'innerEditor' after " + aTest.doingDescription + " with start of the first text node of 'innerEditor' (shrunken into 'innerEditor') when active element is 'outerEditor'");
    344    test(function() {
    345        resetFocusAndSelectionRange();
    346        document.getSelection().setBaseAndExtent(innerEditor.textNode, 0,
    347                                                 anchor.textNode, anchor.textLength);
    348        aTest.func(anchor.textNode, 0);
    349        assert_equals(document.activeElement, document.body);
    350        assert_equals(document.documentElement.scrollTop, 0);
    351    }, "Active element should be the <body> after " + aTest.doingDescription + " with start of the first text node of 'anchor' (shrunken into 'anchor') when active element is the <body>");
    352 });
    353 </script>