chromium/third_party/blink/web_tests/fast/events/offsetX-offsetY.html

<html>
<head>
  <title>Test offsetX/offsetY on various types of elements</title>
  <script type="text/javascript" charset="utf-8">
    if (window.testRunner) {
        testRunner.dumpAsText();
        testRunner.waitUntilDone();
    }

    function mousemoved(e)
    {
      var resultBox = document.getElementById('mousepos');
      var offsets = 'element id: ' + e.target.id + '<br> clientX: ' + e.clientX + ' clientY: ' + e.clientY + '<br>';
      offsets += 'offsetX: ' + e.offsetX + ' offsetY: ' + e.offsetY;
      resultBox.innerHTML = offsets;
    }

    function log(s)
    {
      var resultsDiv = document.getElementById('results');
      resultsDiv.innerHTML += s + '<br>';
    }

    function test()
    {
      // Scroll so that frame view offsets are non-zero
      window.scrollTo(20, 100);

      document.getElementById('overflow').scrollLeft = 0;
      document.getElementById('overflow').scrollTop = 60;

      // In non-test mode, show the mouse coords for testing
      if (!window.testRunner)
        document.body.addEventListener('mousemove', mousemoved, false);

      var offsetX = 32;
      var offsetY = 37;
      var borderSize = 15;
      var positions = sumPositions(document.getElementById('abs-box'));
      var clientX = positions.offsetLeft - positions.scrollLeft + offsetX;
      var clientY = positions.offsetTop - positions.scrollTop + offsetY;
      dispatchEvent(clientX, clientY, 'abs-box', offsetX-borderSize, offsetY-borderSize);

      offsetX = 22;
      offsetY = 24;
      positions = sumPositions(document.getElementById('rel-box'));
      clientX = positions.offsetLeft + positions.clientLeft - positions.scrollLeft + offsetX;
      clientY = positions.offsetTop + positions.clientLeft - positions.scrollTop + offsetY;
      dispatchEvent(clientX, clientY, 'rel-box', offsetX, offsetY);

      offsetX = 10;
      offsetY = 10;
      positions = sumPositions(document.getElementById('fixed-box'));
      clientX = positions.offsetLeft + offsetX;
      clientY = positions.offsetTop + offsetY;
      dispatchEvent(clientX, clientY, 'fixed-box', offsetX, offsetY);

      offsetX = 4;
      offsetY = 4;
      positions = sumPositions(document.getElementById('with-bordertopextra'));
      clientX = positions.offsetLeft - positions.scrollLeft + offsetX;
      clientY = positions.offsetTop - positions.scrollTop + offsetY;
      dispatchEvent(clientX, clientY, 'with-bordertopextra', offsetX, offsetY);

      offsetX = 35;
      offsetY = 5;
      positions = sumPositions(document.getElementById('in-columns'));
      clientX = positions.offsetLeft + positions.clientLeft - positions.scrollLeft + offsetX;
      clientY = positions.offsetTop + positions.clientTop - positions.scrollTop + offsetY;
      dispatchEvent(clientX, clientY, 'in-columns', offsetX, offsetY);

      offsetX = 7;
      offsetY = 6;
      positions = sumPositions(document.getElementById('inside-overflow'));
      clientY = positions.offsetTop + positions.clientTop - positions.scrollTop + offsetY;

      var content = document.getElementById('overflow-contents');
      positions = sumPositions(content);
      var inside = document.getElementById('inside-overflow');
      var overflow = document.getElementById('overflow');
      var borderWidth = 2;
      var scrollbarWidth = overflow.offsetWidth - overflow.clientWidth - 2*borderWidth;
      clientX = positions.offsetLeft + overflow.clientLeft + content.clientWidth - scrollbarWidth - inside.clientWidth - window.scrollX + offsetX;
      dispatchEvent(clientX, clientY, 'inside-overflow', offsetX, offsetY);

      offsetX = 11;
      offsetY = 16;
      positions = sumPositions(document.getElementById('transformed'));
      var sin20 = Math.sin(-20 * Math.PI / 180);
      var cos20 = Math.cos(-20 * Math.PI / 180);
      clientX = positions.offsetLeft + positions.clientLeft - positions.scrollLeft + 100 + Math.round(100 - (100 - offsetX) * cos20 - (60 - offsetY) * sin20);
      clientY = positions.offsetTop + positions.clientTop - positions.scrollTop + 50 + Math.round(60 + (100 - offsetX) * sin20 - (60 - offsetY) * cos20);
      dispatchEvent(clientX, clientY, 'transformed', offsetX, offsetY);
            
      if (window.testRunner)
        testRunner.notifyDone();
    }

    function sumPositions(element)
    {
        var offsetLeft = 0;
        var offsetTop = 0;
        var clientLeft = 0;
        var clientTop = 0;
        var scrollLeft = 0;
        var scrollTop = 0;
        while (element) {
            offsetLeft += element.offsetLeft;
            offsetTop += element.offsetTop;
            clientLeft += element.clientLeft;
            clientTop += element.clientTop;
            scrollLeft += element.scrollLeft;
            scrollTop += element.scrollTop;
            element = element.offsetParent;
        }
        return { 'offsetLeft': offsetLeft, 'offsetTop': offsetTop, 'clientLeft': clientLeft, 'clientTop': clientTop, 'scrollLeft': scrollLeft, 'scrollTop': scrollTop };
    }

    function dispatchEvent(clientX, clientY, expectedElementID, expectedOffsetX, expectedOffsetY)
    {
      var ev = document.createEvent("MouseEvent");
      ev.initMouseEvent("click", true, true, window, 1, 1, 1, clientX, clientY, false, false, false, false, 0, document);
      ev.expectedElement = expectedElementID;
      ev.expectedOffsetX = expectedOffsetX;
      ev.expectedOffsetY = expectedOffsetY;
      var target = document.elementFromPoint(ev.clientX, ev.clientY);
      target.dispatchEvent(ev);
    }

    function clicked(event)
    {
      var element = event.target;
      
      var result;
      if (element.id == event.expectedElement &&
          event.offsetX == event.expectedOffsetX &&
          event.offsetY == event.expectedOffsetY)
        result = 'PASS: event hit ' + element.id + ' at offset (' + event.offsetX + ', ' + event.offsetY + ')';
      else
        result = 'FAIL: event expected to hit ' + event.expectedElement + ' at (' + event.expectedOffsetX + ', ' + event.expectedOffsetY + ') but hit ' + element.id + ' at (' + event.offsetX + ', ' + event.offsetY + ')';

      log(result);
    }

    window.addEventListener('load', function() {
      window.setTimeout(test, 0);
    }, false);
  </script>
  <style type="text/css" media="screen">

    body {
      height: 2048px;
      width: 2048px;
      margin: 0;
      cursor: crosshair;
    }

    .box {
      height: 200px;
      width: 200px;
      margin: 20px;
      background-color: gray;
    }

    #abs-box {
      position: absolute;
      top: 125px;
      left: 100px;
      height: 100px;
      width: 200px;
      border: 15px solid gray;
    }

    #rel-box {
      position: relative;
      height: 100px;
      width: 200px;
      left: 40px;
      top: -50px;
      background-color: #CCC;
    }

    #fixed-box {
      position: fixed;
      top: 20px;
      left: 400px;
      width: 300px;
      height: 50px;
      background-color: #AAA;
    }

    #columns {
      position: absolute;
      -webkit-column-count: 3;
      width: 400px;
      top: 200px;
      left: 460px;
      border: 2px solid black;
    }

    #in-columns {
      display: block;
      height: 40px;
      width: 60%;
      margin: 0 auto;
      text-align: center;
      background-color: gray;
    }

    #transformed {
      height: 120px;
      width: 200px;
      background-color: #DDD;
      transform: translate(100px, 50px) rotate(20deg);
    }
    #overflow {
      overflow: scroll;
      position: absolute;
      width: 300px;
      top: 440px;
      left: 460px;
      height: 200px;
      border: 2px solid black;
      direction: rtl;
    }

    #overflow-contents {
      height: 500px;
      width: 120%;
      background-color: #BBB;
    }

    #inside-overflow {
      width: 50%;
      background-color: gray;
    }
    
    #results {
      position: absolute;
      left: 30px;
      top: 700px;
    }

    #mousepos {
      position: absolute;
      left: 30px;
      top: 650px;
      color: gray;
      font-size: smaller;
    }

    tr {
/*      transform: rotate(10deg);*/
    }
  </style>
</head>
<body onclick="clicked(event)">

<div id="filler" style="position: absolute; top: 0; width: 100%; height: 100%"></div>

<!-- Test assumes offsetX/offsetY are relative to border box, but see
     http://www.quirksmode.org/dom/w3c_cssom.html#mousepos -->
<div id="abs-box">
  Absolute position
  <div id="rel-box">
    Relative position
  </div>
  <div id="fixed-box">
    Fixed position
  </div>
</div>

<table border="2" cellspacing="3" cellpadding="2" style="width: 400px; margin-top: 280px; margin-left: 40px;">
  <tr><th>First</th><th>Second</th></tr>
  <tr style="vertical-align: center;"><td>This cell has borderTopExtra<div class="box" id="with-bordertopextra" style="position: relative; height: 20px; margin: 4px;"></div></td><td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  </td></tr>
</table>

<div id="columns">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. <span id="in-columns">In columns</span> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>

<div id="transformed">
  Div with transform
</div>

<div id="overflow">
  <div id="overflow-contents">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    <div id="inside-overflow">In RTL overflow</div> 
    <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </div>
</div>
<div id="results"></div>
<div id="mousepos"></div>

</body>
</html>