content/base/test/test_range_bounds.html

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 <!DOCTYPE HTML>
     2 <html>
     3 <!--
     4 https://bugzilla.mozilla.org/show_bug.cgi?id=421640
     5 -->
     6 <head>
     7   <title>Test for Bug 396392</title>
     8   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
     9   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
    10   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
    11   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
    12 </head>
    13 <body>
    14 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=396392">Mozilla Bug Range getClientRects and getBoundingClientRect</a>
    15 <div id="content" style="font-family:monospace;font-size:12px;width:100px">
    16 <p>000000<span>0</span></p><div>00000<span>0</span></div><p>0000<span>0000</span>0000</p><div><span>000000000000 00000000000000 000000</span></div><div>000000000000 00000000000003 100305</div>
    17 </div>
    18 <div id="mixeddir" style="font-family:monospace;font-size:12px;width:100px"><span>english <bdo id="bdo" dir="rtl">rtl-overide english</bdo> word</span></div>
    19 <div id="mixeddir2" style="font-family:monospace;font-size:12px"><span>english <bdo id="bdo2" dir="rtl">rtl-override english</bdo> word</span></div>
    20 <pre id="test">
    21 <script class="testbody" type="text/javascript">
    23 var isLTR=true;
    24 function isEmptyRect(rect, name) {
    25   name = (isLTR ? 'isLTR ' : 'isRTL ') + name;
    26   is(rect.left, 0, name+'empty rect should have left = 0');
    27   is(rect.right, 0, name+'empty rect should have right = 0');
    28   is(rect.top, 0, name+'empty rect should have top = 0');
    29   is(rect.bottom, 0, name+'empty rect should have bottom = 0');
    30   is(rect.width, 0, name+'empty rect should have width = 0');
    31   is(rect.height, 0, name+'empty rect should have height = 0');
    32 }
    34 function isEmptyRectList(rectlist, name) {
    35   name = (isLTR ? 'isLTR ' : 'isRTL ') + name;
    36   is(rectlist.length, 0, name + 'empty rectlist should have zero rects');
    37 }
    39 // round coordinates to the nearest 1/256 of a pixel
    40 function roundCoord(x) {
    41   return Math.round(x * 256) / 256;
    42 }
    44 function _getRect(r) {
    45   if (r.length) //array
    46     return "{left:"+roundCoord(r[0])+",right:"+roundCoord(r[1])+
    47       ",top:"   +roundCoord(r[2])+",bottom:"+roundCoord(r[3])+
    48       ",width:"+roundCoord(r[4])+",height:"+roundCoord(r[5])+"}";
    49   else
    50     return "{left:"+roundCoord(r.left)+",right:"+roundCoord(r.right)+
    51       ",top:"+roundCoord(r.top)+",bottom:"+roundCoord(r.bottom)+
    52       ",width:"+roundCoord(r.width)+",height:"+roundCoord(r.height)+"}";
    53 }
    55 function runATest(obj) {
    56   var range = document.createRange();
    57   try {
    58     range.setStart(obj.range[0],obj.range[1]);
    59     if (obj.range.length>2) {
    60        range.setEnd(obj.range[2]||obj.range[0], obj.range[3]);
    61     }
    62     //test getBoundingClientRect()
    63     var rect = range.getBoundingClientRect();
    64     var testname = (isLTR ? 'isLTR ' : 'isRTL ') + 
    65       'range.getBoundingClientRect for ' + obj.name;
    66     if (obj.rect) {
    67       is(_getRect(rect),_getRect(obj.rect), testname);
    68     } else {
    69       isEmptyRect(rect,testname+": ");
    70     }
    71     //test getClientRects()
    72     var rectlist = range.getClientRects();
    73     testname = (isLTR ? 'isLTR ' : 'isRTL ') +
    74       'range.getClientRects for '+obj.name;
    75     if (!obj.rectList) {
    76       //rectList is not specified, use obj.rect to figure out rectList
    77       obj.rectList = obj.rect?[obj.rect]:[];
    78     }
    79     if (!obj.rectList.length) {
    80       isEmptyRectList(rectlist, testname+": ");
    81     } else {
    82       is(rectlist.length, obj.rectList.length, testname+' should return '+obj.rectList.length+' rects.');
    83       if(!obj.rectList.forEach){
    84         //convert RectList to a real array
    85         obj.rectList=Array.prototype.slice.call(obj.rectList, 0);
    86       }
    87       obj.rectList.forEach(function(rect,i) {
    88         is(_getRect(rectlist[i]),_getRect(rect),testname+": item at "+i);
    89       });
    90     }
    91   } finally {
    92     range.detach();
    93   }
    94 }
    95 /** Test for Bug 396392 **/
    96 function doTest(){
    97   var root = document.getElementById('content');
    98   var firstP = root.firstElementChild, spanInFirstP = firstP.childNodes[1],
    99     firstDiv = root.childNodes[2], spanInFirstDiv = firstDiv.childNodes[1],
   100     secondP = root.childNodes[3], spanInSecondP = secondP.childNodes[1],
   101     secondDiv = root.childNodes[4], spanInSecondDiv = secondDiv.firstChild,
   102     thirdDiv = root.childNodes[5];
   103   var firstPRect = firstP.getBoundingClientRect(),
   104     spanInFirstPRect = spanInFirstP.getBoundingClientRect(),
   105     firstDivRect = firstDiv.getBoundingClientRect(),
   106     spanInFirstDivRect = spanInFirstDiv.getBoundingClientRect(),
   107     secondPRect = secondP.getBoundingClientRect(),
   108     secondDivRect = secondDiv.getBoundingClientRect(),
   109     spanInSecondPRect = spanInSecondP.getBoundingClientRect(),
   110     spanInSecondDivRect = spanInSecondDiv.getBoundingClientRect(),
   111     spanInSecondDivRectList = spanInSecondDiv.getClientRects();
   112   var widthPerchar = spanInSecondPRect.width / spanInSecondP.firstChild.length;
   113   var testcases = [
   114     {name:'nodesNotInDocument', range:[document.createTextNode('abc'), 1], 
   115       rect:null},
   116     {name:'collapsedInBlockNode', range:[firstP, 2], rect:null},
   117     {name:'collapsedAtBeginningOfTextNode', range:[firstP.firstChild, 0],
   118       rect:[spanInFirstPRect.left - 6 * widthPerchar, 
   119       spanInFirstPRect.left - 6 * widthPerchar, spanInFirstPRect.top, 
   120       spanInFirstPRect.bottom, 0, spanInFirstPRect.height]},
   121     {name:'collapsedWithinTextNode', range:[firstP.firstChild, 1], 
   122       rect:[spanInFirstPRect.left  - 5 * widthPerchar, 
   123         spanInFirstPRect.left  - 5 * widthPerchar,
   124         spanInFirstPRect.top, spanInFirstPRect.bottom, 0, spanInFirstPRect.height]},
   125     {name:'collapsedAtEndOfTextNode', range:[firstP.firstChild, 6], 
   126       rect:[spanInFirstPRect.left, spanInFirstPRect.left,
   127         spanInFirstPRect.top, spanInFirstPRect.bottom, 0, spanInFirstPRect.height]},
   128     {name:'singleBlockNode', range:[root, 1, root, 2], rect:firstPRect},
   129     {name:'twoBlockNodes', range:[root, 1, root, 3],
   130       rect:[firstPRect.left, firstPRect.right, firstPRect.top,
   131         firstDivRect.bottom, firstPRect.width,
   132         firstDivRect.bottom - firstPRect.top],
   133       rectList:[firstPRect, firstDivRect]},
   134     {name:'endOfTextNodeToEndOfAnotherTextNodeInAnotherBlock',
   135       range:[spanInFirstP.firstChild, 1, firstDiv.firstChild, 5],
   136       rect:[spanInFirstDivRect.left - 5*widthPerchar, spanInFirstDivRect.left,
   137         spanInFirstDivRect.top, spanInFirstDivRect.bottom, 5 * widthPerchar, 
   138         spanInFirstDivRect.height]},
   139     {name:'startOfTextNodeToStartOfAnotherTextNodeInAnotherBlock', 
   140       range:[spanInFirstP.firstChild, 0, firstDiv.firstChild, 0],
   141       rect:[spanInFirstPRect.left, spanInFirstPRect.left + widthPerchar, spanInFirstPRect.top,
   142         spanInFirstPRect.bottom, widthPerchar, spanInFirstPRect.height]},
   143     {name:'endPortionOfATextNode', range:[firstP.firstChild, 3, 
   144         firstP.firstChild, 6],
   145       rect:[spanInFirstPRect.left - 3*widthPerchar, spanInFirstPRect.left,
   146         spanInFirstPRect.top, spanInFirstPRect.bottom, 3*widthPerchar, spanInFirstPRect.height]},
   147     {name:'startPortionOfATextNode', range:[firstP.firstChild, 0, 
   148         firstP.firstChild, 3],
   149       rect:[spanInFirstPRect.left - 6*widthPerchar, 
   150         spanInFirstPRect.left - 3*widthPerchar, spanInFirstPRect.top,
   151         spanInFirstPRect.bottom, 3 * widthPerchar, spanInFirstPRect.height]},
   152     {name:'spanTextNodes', range:[secondP.firstChild, 1, secondP.lastChild, 1],
   153       rect:[spanInSecondPRect.left - 3*widthPerchar, spanInSecondPRect.right + 
   154         widthPerchar, spanInSecondPRect.top, spanInSecondPRect.bottom,
   155         spanInSecondPRect.width + 4*widthPerchar, spanInSecondPRect.height],
   156       rectList:[[spanInSecondPRect.left - 3*widthPerchar, spanInSecondPRect.left,
   157         spanInSecondPRect.top, spanInSecondPRect.bottom, 3 * widthPerchar,
   158         spanInSecondPRect.height],
   159 	spanInSecondPRect,
   160 	[spanInSecondPRect.right, spanInSecondPRect.right + widthPerchar,
   161           spanInSecondPRect.top, spanInSecondPRect.bottom, widthPerchar,
   162           spanInSecondPRect.height]]}
   163   ];
   164   testcases.forEach(runATest);
   166   // testcases that have different ranges in LTR and RTL
   167   var directionDependentTestcases;
   168   if (isLTR) {
   169     directionDependentTestcases = [
   170       {name:'spanAcrossLines',range:[spanInSecondDiv.firstChild, 1, spanInSecondDiv.firstChild, 30],
   171        rect: spanInSecondDivRect,
   172        rectList:[[spanInSecondDivRectList[0].left+widthPerchar,
   173         spanInSecondDivRectList[0].right, spanInSecondDivRectList[0].top,
   174 	spanInSecondDivRectList[0].bottom, spanInSecondDivRectList[0].width - widthPerchar,
   175 	spanInSecondDivRectList[0].height],
   176 	spanInSecondDivRectList[1],
   177 	[spanInSecondDivRectList[2].left,
   178 	spanInSecondDivRectList[2].right - 4 * widthPerchar, spanInSecondDivRectList[2].top,
   179 	spanInSecondDivRectList[2].bottom, 
   180 	spanInSecondDivRectList[2].width - 4 * widthPerchar,
   181 	spanInSecondDivRectList[2].height]]},
   182       {name:'textAcrossLines',range:[thirdDiv.firstChild, 13, thirdDiv.firstChild, 28],
   183         rect: [spanInSecondDivRectList[1].left, spanInSecondDivRectList[1].right,
   184           spanInSecondDivRectList[1].top + secondDivRect.height, 
   185           spanInSecondDivRectList[1].bottom + secondDivRect.height,
   186           spanInSecondDivRectList[1].width, spanInSecondDivRectList[1].height]}
   187     ];
   188   } else {
   189     directionDependentTestcases = [
   190       {name:'spanAcrossLines',range:[spanInSecondDiv.firstChild, 1, spanInSecondDiv.firstChild, 30],
   191        rect: spanInSecondDivRect,
   192        rectList:[[spanInSecondDivRectList[0].left+widthPerchar,
   193         spanInSecondDivRectList[0].right, spanInSecondDivRectList[0].top,
   194 	spanInSecondDivRectList[0].bottom, spanInSecondDivRectList[0].width - widthPerchar,
   195 	spanInSecondDivRectList[0].height],
   196 	spanInSecondDivRectList[1],
   197 	spanInSecondDivRectList[2],
   198 	spanInSecondDivRectList[3],
   199 	[spanInSecondDivRectList[4].left,
   200 	spanInSecondDivRectList[4].right - 4 * widthPerchar,
   201         spanInSecondDivRectList[4].top,
   202 	spanInSecondDivRectList[4].bottom, 
   203 	spanInSecondDivRectList[4].width - 4 * widthPerchar,
   204 	spanInSecondDivRectList[4].height]]},
   205       {name:'textAcrossLines',range:[thirdDiv.firstChild, 13, thirdDiv.firstChild, 28],
   206         rect: [spanInSecondDivRectList[2].left, spanInSecondDivRectList[2].right,
   207           spanInSecondDivRectList[2].top + secondDivRect.height, 
   208           spanInSecondDivRectList[2].bottom + secondDivRect.height,
   209 	       spanInSecondDivRectList[2].width, spanInSecondDivRectList[2].height],
   210        rectList:[[spanInSecondDivRectList[2].left, spanInSecondDivRectList[2].right,
   211           spanInSecondDivRectList[2].top + secondDivRect.height, 
   212           spanInSecondDivRectList[2].bottom + secondDivRect.height,
   213           spanInSecondDivRectList[2].width, spanInSecondDivRectList[2].height],
   214           [spanInSecondDivRectList[2].left, spanInSecondDivRectList[2].left,
   215           spanInSecondDivRectList[2].top + secondDivRect.height, 
   216           spanInSecondDivRectList[2].bottom + secondDivRect.height,
   217           0, spanInSecondDivRectList[2].height]]}
   218      ];
   219   }
   220   directionDependentTestcases.forEach(runATest);
   221 }
   222 function testMixedDir(){
   223   var root = document.getElementById('mixeddir');
   224   var firstSpan = root.firstElementChild, firstSpanRect=firstSpan.getBoundingClientRect(),
   225       firstSpanRectList = firstSpan.getClientRects();
   226   runATest({name:'mixeddir',range:[firstSpan.firstChild,0,firstSpan.lastChild,firstSpan.lastChild.length],
   227              rect: firstSpanRect, rectList:firstSpanRectList});
   229   root = document.getElementById('mixeddir2');
   230   firstSpan = root.firstElementChild;
   231   firstSpanRect = firstSpan.getBoundingClientRect();
   232   bdo = document.getElementById('bdo2');
   233   bdoRect=bdo.getBoundingClientRect();
   234   var widthPerChar = bdoRect.width / bdo.firstChild.length;
   235   runATest({name:'mixeddirPartial', range:[firstSpan.firstChild, 3, 
   236 					   bdo.firstChild, 7],
   237 	rect: [firstSpanRect.left + 3*widthPerChar, bdoRect.right,
   238 	       bdoRect.top, bdoRect.bottom,
   239 	       (firstSpan.firstChild.length + bdo.firstChild.length - 3) *
   240 	        widthPerChar,
   241 	       bdoRect.height],
   242 	rectList:[[firstSpanRect.left + 3*widthPerChar,
   243 		   bdoRect.left,
   244 		   firstSpanRect.top, firstSpanRect.bottom,
   245 		   (firstSpan.firstChild.length - 3) * widthPerChar,
   246 		   firstSpanRect.height],
   247 		  [bdoRect.right - 7 * widthPerChar, bdoRect.right,
   248 		   bdoRect.top, bdoRect.bottom,
   249 		   7*widthPerChar, bdoRect.height]]});
   250 }
   251 function test(){
   252   //test ltr
   253   doTest();
   254   testMixedDir();
   256   isLTR = false;
   257   var root = document.getElementById('content');
   258   root.dir = 'rtl';
   260   //test rtl
   261   doTest();
   262   testMixedDir();
   264   SimpleTest.finish();
   265 }
   267 window.onload = function() {
   268   SimpleTest.waitForExplicitFinish();
   269   setTimeout(test, 0);
   270 };
   272 </script>
   273 </pre>
   274 </body>
   275 </html>

mercurial