content/base/test/test_range_bounds.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/test/test_range_bounds.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,275 @@
     1.4 +<!DOCTYPE HTML>
     1.5 +<html>
     1.6 +<!--
     1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=421640
     1.8 +-->
     1.9 +<head>
    1.10 +  <title>Test for Bug 396392</title>
    1.11 +  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    1.12 +  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
    1.13 +  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
    1.14 +  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
    1.15 +</head>
    1.16 +<body>
    1.17 +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=396392">Mozilla Bug Range getClientRects and getBoundingClientRect</a>
    1.18 +<div id="content" style="font-family:monospace;font-size:12px;width:100px">
    1.19 +<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>
    1.20 +</div>
    1.21 +<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>
    1.22 +<div id="mixeddir2" style="font-family:monospace;font-size:12px"><span>english <bdo id="bdo2" dir="rtl">rtl-override english</bdo> word</span></div>
    1.23 +<pre id="test">
    1.24 +<script class="testbody" type="text/javascript">
    1.25 +
    1.26 +var isLTR=true;
    1.27 +function isEmptyRect(rect, name) {
    1.28 +  name = (isLTR ? 'isLTR ' : 'isRTL ') + name;
    1.29 +  is(rect.left, 0, name+'empty rect should have left = 0');
    1.30 +  is(rect.right, 0, name+'empty rect should have right = 0');
    1.31 +  is(rect.top, 0, name+'empty rect should have top = 0');
    1.32 +  is(rect.bottom, 0, name+'empty rect should have bottom = 0');
    1.33 +  is(rect.width, 0, name+'empty rect should have width = 0');
    1.34 +  is(rect.height, 0, name+'empty rect should have height = 0');
    1.35 +}
    1.36 +
    1.37 +function isEmptyRectList(rectlist, name) {
    1.38 +  name = (isLTR ? 'isLTR ' : 'isRTL ') + name;
    1.39 +  is(rectlist.length, 0, name + 'empty rectlist should have zero rects');
    1.40 +}
    1.41 +
    1.42 +// round coordinates to the nearest 1/256 of a pixel
    1.43 +function roundCoord(x) {
    1.44 +  return Math.round(x * 256) / 256;
    1.45 +}
    1.46 +
    1.47 +function _getRect(r) {
    1.48 +  if (r.length) //array
    1.49 +    return "{left:"+roundCoord(r[0])+",right:"+roundCoord(r[1])+
    1.50 +      ",top:"   +roundCoord(r[2])+",bottom:"+roundCoord(r[3])+
    1.51 +      ",width:"+roundCoord(r[4])+",height:"+roundCoord(r[5])+"}";
    1.52 +  else
    1.53 +    return "{left:"+roundCoord(r.left)+",right:"+roundCoord(r.right)+
    1.54 +      ",top:"+roundCoord(r.top)+",bottom:"+roundCoord(r.bottom)+
    1.55 +      ",width:"+roundCoord(r.width)+",height:"+roundCoord(r.height)+"}";
    1.56 +}
    1.57 +
    1.58 +function runATest(obj) {
    1.59 +  var range = document.createRange();
    1.60 +  try {
    1.61 +    range.setStart(obj.range[0],obj.range[1]);
    1.62 +    if (obj.range.length>2) {
    1.63 +       range.setEnd(obj.range[2]||obj.range[0], obj.range[3]);
    1.64 +    }
    1.65 +    //test getBoundingClientRect()
    1.66 +    var rect = range.getBoundingClientRect();
    1.67 +    var testname = (isLTR ? 'isLTR ' : 'isRTL ') + 
    1.68 +      'range.getBoundingClientRect for ' + obj.name;
    1.69 +    if (obj.rect) {
    1.70 +      is(_getRect(rect),_getRect(obj.rect), testname);
    1.71 +    } else {
    1.72 +      isEmptyRect(rect,testname+": ");
    1.73 +    }
    1.74 +    //test getClientRects()
    1.75 +    var rectlist = range.getClientRects();
    1.76 +    testname = (isLTR ? 'isLTR ' : 'isRTL ') +
    1.77 +      'range.getClientRects for '+obj.name;
    1.78 +    if (!obj.rectList) {
    1.79 +      //rectList is not specified, use obj.rect to figure out rectList
    1.80 +      obj.rectList = obj.rect?[obj.rect]:[];
    1.81 +    }
    1.82 +    if (!obj.rectList.length) {
    1.83 +      isEmptyRectList(rectlist, testname+": ");
    1.84 +    } else {
    1.85 +      is(rectlist.length, obj.rectList.length, testname+' should return '+obj.rectList.length+' rects.');
    1.86 +      if(!obj.rectList.forEach){
    1.87 +        //convert RectList to a real array
    1.88 +        obj.rectList=Array.prototype.slice.call(obj.rectList, 0);
    1.89 +      }
    1.90 +      obj.rectList.forEach(function(rect,i) {
    1.91 +        is(_getRect(rectlist[i]),_getRect(rect),testname+": item at "+i);
    1.92 +      });
    1.93 +    }
    1.94 +  } finally {
    1.95 +    range.detach();
    1.96 +  }
    1.97 +}
    1.98 +/** Test for Bug 396392 **/
    1.99 +function doTest(){
   1.100 +  var root = document.getElementById('content');
   1.101 +  var firstP = root.firstElementChild, spanInFirstP = firstP.childNodes[1],
   1.102 +    firstDiv = root.childNodes[2], spanInFirstDiv = firstDiv.childNodes[1],
   1.103 +    secondP = root.childNodes[3], spanInSecondP = secondP.childNodes[1],
   1.104 +    secondDiv = root.childNodes[4], spanInSecondDiv = secondDiv.firstChild,
   1.105 +    thirdDiv = root.childNodes[5];
   1.106 +  var firstPRect = firstP.getBoundingClientRect(),
   1.107 +    spanInFirstPRect = spanInFirstP.getBoundingClientRect(),
   1.108 +    firstDivRect = firstDiv.getBoundingClientRect(),
   1.109 +    spanInFirstDivRect = spanInFirstDiv.getBoundingClientRect(),
   1.110 +    secondPRect = secondP.getBoundingClientRect(),
   1.111 +    secondDivRect = secondDiv.getBoundingClientRect(),
   1.112 +    spanInSecondPRect = spanInSecondP.getBoundingClientRect(),
   1.113 +    spanInSecondDivRect = spanInSecondDiv.getBoundingClientRect(),
   1.114 +    spanInSecondDivRectList = spanInSecondDiv.getClientRects();
   1.115 +  var widthPerchar = spanInSecondPRect.width / spanInSecondP.firstChild.length;
   1.116 +  var testcases = [
   1.117 +    {name:'nodesNotInDocument', range:[document.createTextNode('abc'), 1], 
   1.118 +      rect:null},
   1.119 +    {name:'collapsedInBlockNode', range:[firstP, 2], rect:null},
   1.120 +    {name:'collapsedAtBeginningOfTextNode', range:[firstP.firstChild, 0],
   1.121 +      rect:[spanInFirstPRect.left - 6 * widthPerchar, 
   1.122 +      spanInFirstPRect.left - 6 * widthPerchar, spanInFirstPRect.top, 
   1.123 +      spanInFirstPRect.bottom, 0, spanInFirstPRect.height]},
   1.124 +    {name:'collapsedWithinTextNode', range:[firstP.firstChild, 1], 
   1.125 +      rect:[spanInFirstPRect.left  - 5 * widthPerchar, 
   1.126 +        spanInFirstPRect.left  - 5 * widthPerchar,
   1.127 +        spanInFirstPRect.top, spanInFirstPRect.bottom, 0, spanInFirstPRect.height]},
   1.128 +    {name:'collapsedAtEndOfTextNode', range:[firstP.firstChild, 6], 
   1.129 +      rect:[spanInFirstPRect.left, spanInFirstPRect.left,
   1.130 +        spanInFirstPRect.top, spanInFirstPRect.bottom, 0, spanInFirstPRect.height]},
   1.131 +    {name:'singleBlockNode', range:[root, 1, root, 2], rect:firstPRect},
   1.132 +    {name:'twoBlockNodes', range:[root, 1, root, 3],
   1.133 +      rect:[firstPRect.left, firstPRect.right, firstPRect.top,
   1.134 +        firstDivRect.bottom, firstPRect.width,
   1.135 +        firstDivRect.bottom - firstPRect.top],
   1.136 +      rectList:[firstPRect, firstDivRect]},
   1.137 +    {name:'endOfTextNodeToEndOfAnotherTextNodeInAnotherBlock',
   1.138 +      range:[spanInFirstP.firstChild, 1, firstDiv.firstChild, 5],
   1.139 +      rect:[spanInFirstDivRect.left - 5*widthPerchar, spanInFirstDivRect.left,
   1.140 +        spanInFirstDivRect.top, spanInFirstDivRect.bottom, 5 * widthPerchar, 
   1.141 +        spanInFirstDivRect.height]},
   1.142 +    {name:'startOfTextNodeToStartOfAnotherTextNodeInAnotherBlock', 
   1.143 +      range:[spanInFirstP.firstChild, 0, firstDiv.firstChild, 0],
   1.144 +      rect:[spanInFirstPRect.left, spanInFirstPRect.left + widthPerchar, spanInFirstPRect.top,
   1.145 +        spanInFirstPRect.bottom, widthPerchar, spanInFirstPRect.height]},
   1.146 +    {name:'endPortionOfATextNode', range:[firstP.firstChild, 3, 
   1.147 +        firstP.firstChild, 6],
   1.148 +      rect:[spanInFirstPRect.left - 3*widthPerchar, spanInFirstPRect.left,
   1.149 +        spanInFirstPRect.top, spanInFirstPRect.bottom, 3*widthPerchar, spanInFirstPRect.height]},
   1.150 +    {name:'startPortionOfATextNode', range:[firstP.firstChild, 0, 
   1.151 +        firstP.firstChild, 3],
   1.152 +      rect:[spanInFirstPRect.left - 6*widthPerchar, 
   1.153 +        spanInFirstPRect.left - 3*widthPerchar, spanInFirstPRect.top,
   1.154 +        spanInFirstPRect.bottom, 3 * widthPerchar, spanInFirstPRect.height]},
   1.155 +    {name:'spanTextNodes', range:[secondP.firstChild, 1, secondP.lastChild, 1],
   1.156 +      rect:[spanInSecondPRect.left - 3*widthPerchar, spanInSecondPRect.right + 
   1.157 +        widthPerchar, spanInSecondPRect.top, spanInSecondPRect.bottom,
   1.158 +        spanInSecondPRect.width + 4*widthPerchar, spanInSecondPRect.height],
   1.159 +      rectList:[[spanInSecondPRect.left - 3*widthPerchar, spanInSecondPRect.left,
   1.160 +        spanInSecondPRect.top, spanInSecondPRect.bottom, 3 * widthPerchar,
   1.161 +        spanInSecondPRect.height],
   1.162 +	spanInSecondPRect,
   1.163 +	[spanInSecondPRect.right, spanInSecondPRect.right + widthPerchar,
   1.164 +          spanInSecondPRect.top, spanInSecondPRect.bottom, widthPerchar,
   1.165 +          spanInSecondPRect.height]]}
   1.166 +  ];
   1.167 +  testcases.forEach(runATest);
   1.168 +
   1.169 +  // testcases that have different ranges in LTR and RTL
   1.170 +  var directionDependentTestcases;
   1.171 +  if (isLTR) {
   1.172 +    directionDependentTestcases = [
   1.173 +      {name:'spanAcrossLines',range:[spanInSecondDiv.firstChild, 1, spanInSecondDiv.firstChild, 30],
   1.174 +       rect: spanInSecondDivRect,
   1.175 +       rectList:[[spanInSecondDivRectList[0].left+widthPerchar,
   1.176 +        spanInSecondDivRectList[0].right, spanInSecondDivRectList[0].top,
   1.177 +	spanInSecondDivRectList[0].bottom, spanInSecondDivRectList[0].width - widthPerchar,
   1.178 +	spanInSecondDivRectList[0].height],
   1.179 +	spanInSecondDivRectList[1],
   1.180 +	[spanInSecondDivRectList[2].left,
   1.181 +	spanInSecondDivRectList[2].right - 4 * widthPerchar, spanInSecondDivRectList[2].top,
   1.182 +	spanInSecondDivRectList[2].bottom, 
   1.183 +	spanInSecondDivRectList[2].width - 4 * widthPerchar,
   1.184 +	spanInSecondDivRectList[2].height]]},
   1.185 +      {name:'textAcrossLines',range:[thirdDiv.firstChild, 13, thirdDiv.firstChild, 28],
   1.186 +        rect: [spanInSecondDivRectList[1].left, spanInSecondDivRectList[1].right,
   1.187 +          spanInSecondDivRectList[1].top + secondDivRect.height, 
   1.188 +          spanInSecondDivRectList[1].bottom + secondDivRect.height,
   1.189 +          spanInSecondDivRectList[1].width, spanInSecondDivRectList[1].height]}
   1.190 +    ];
   1.191 +  } else {
   1.192 +    directionDependentTestcases = [
   1.193 +      {name:'spanAcrossLines',range:[spanInSecondDiv.firstChild, 1, spanInSecondDiv.firstChild, 30],
   1.194 +       rect: spanInSecondDivRect,
   1.195 +       rectList:[[spanInSecondDivRectList[0].left+widthPerchar,
   1.196 +        spanInSecondDivRectList[0].right, spanInSecondDivRectList[0].top,
   1.197 +	spanInSecondDivRectList[0].bottom, spanInSecondDivRectList[0].width - widthPerchar,
   1.198 +	spanInSecondDivRectList[0].height],
   1.199 +	spanInSecondDivRectList[1],
   1.200 +	spanInSecondDivRectList[2],
   1.201 +	spanInSecondDivRectList[3],
   1.202 +	[spanInSecondDivRectList[4].left,
   1.203 +	spanInSecondDivRectList[4].right - 4 * widthPerchar,
   1.204 +        spanInSecondDivRectList[4].top,
   1.205 +	spanInSecondDivRectList[4].bottom, 
   1.206 +	spanInSecondDivRectList[4].width - 4 * widthPerchar,
   1.207 +	spanInSecondDivRectList[4].height]]},
   1.208 +      {name:'textAcrossLines',range:[thirdDiv.firstChild, 13, thirdDiv.firstChild, 28],
   1.209 +        rect: [spanInSecondDivRectList[2].left, spanInSecondDivRectList[2].right,
   1.210 +          spanInSecondDivRectList[2].top + secondDivRect.height, 
   1.211 +          spanInSecondDivRectList[2].bottom + secondDivRect.height,
   1.212 +	       spanInSecondDivRectList[2].width, spanInSecondDivRectList[2].height],
   1.213 +       rectList:[[spanInSecondDivRectList[2].left, spanInSecondDivRectList[2].right,
   1.214 +          spanInSecondDivRectList[2].top + secondDivRect.height, 
   1.215 +          spanInSecondDivRectList[2].bottom + secondDivRect.height,
   1.216 +          spanInSecondDivRectList[2].width, spanInSecondDivRectList[2].height],
   1.217 +          [spanInSecondDivRectList[2].left, spanInSecondDivRectList[2].left,
   1.218 +          spanInSecondDivRectList[2].top + secondDivRect.height, 
   1.219 +          spanInSecondDivRectList[2].bottom + secondDivRect.height,
   1.220 +          0, spanInSecondDivRectList[2].height]]}
   1.221 +     ];
   1.222 +  }
   1.223 +  directionDependentTestcases.forEach(runATest);
   1.224 +}
   1.225 +function testMixedDir(){
   1.226 +  var root = document.getElementById('mixeddir');
   1.227 +  var firstSpan = root.firstElementChild, firstSpanRect=firstSpan.getBoundingClientRect(),
   1.228 +      firstSpanRectList = firstSpan.getClientRects();
   1.229 +  runATest({name:'mixeddir',range:[firstSpan.firstChild,0,firstSpan.lastChild,firstSpan.lastChild.length],
   1.230 +             rect: firstSpanRect, rectList:firstSpanRectList});
   1.231 +
   1.232 +  root = document.getElementById('mixeddir2');
   1.233 +  firstSpan = root.firstElementChild;
   1.234 +  firstSpanRect = firstSpan.getBoundingClientRect();
   1.235 +  bdo = document.getElementById('bdo2');
   1.236 +  bdoRect=bdo.getBoundingClientRect();
   1.237 +  var widthPerChar = bdoRect.width / bdo.firstChild.length;
   1.238 +  runATest({name:'mixeddirPartial', range:[firstSpan.firstChild, 3, 
   1.239 +					   bdo.firstChild, 7],
   1.240 +	rect: [firstSpanRect.left + 3*widthPerChar, bdoRect.right,
   1.241 +	       bdoRect.top, bdoRect.bottom,
   1.242 +	       (firstSpan.firstChild.length + bdo.firstChild.length - 3) *
   1.243 +	        widthPerChar,
   1.244 +	       bdoRect.height],
   1.245 +	rectList:[[firstSpanRect.left + 3*widthPerChar,
   1.246 +		   bdoRect.left,
   1.247 +		   firstSpanRect.top, firstSpanRect.bottom,
   1.248 +		   (firstSpan.firstChild.length - 3) * widthPerChar,
   1.249 +		   firstSpanRect.height],
   1.250 +		  [bdoRect.right - 7 * widthPerChar, bdoRect.right,
   1.251 +		   bdoRect.top, bdoRect.bottom,
   1.252 +		   7*widthPerChar, bdoRect.height]]});
   1.253 +}
   1.254 +function test(){
   1.255 +  //test ltr
   1.256 +  doTest();
   1.257 +  testMixedDir();
   1.258 +
   1.259 +  isLTR = false;
   1.260 +  var root = document.getElementById('content');
   1.261 +  root.dir = 'rtl';
   1.262 +
   1.263 +  //test rtl
   1.264 +  doTest();
   1.265 +  testMixedDir();
   1.266 +
   1.267 +  SimpleTest.finish();
   1.268 +}
   1.269 +
   1.270 +window.onload = function() {
   1.271 +  SimpleTest.waitForExplicitFinish();
   1.272 +  setTimeout(test, 0);
   1.273 +};
   1.274 +
   1.275 +</script>
   1.276 +</pre>
   1.277 +</body>
   1.278 +</html>

mercurial