<!DOCTYPE html>
<html>
<head>
    <title>Touch Adjustment : content editable div - bug 97576</title>
    <script src="../resources/js-test-pre.js"></script>
    <script src="resources/touchadjustment.js"></script>
    <style>
        body {
            font-size: 12px;
            line-height: 14px;
        }

        #text-area,
        #rich-text {
            background: #eee;
            border: none;
            margin: 0 5px;
            padding: 0;
        }

        #rich-text {
            margin-top: 50px;
            outline: none;
            width: 300px;
        }
    </style>
</head>

<body>

<div id=sandbox>
    <textarea id="text-area" rows="5" cols="40">A lengthy line of text.

Another line of text separated by a blank line.</textarea>

    <div id="rich-text" contentEditable>
        <b>Hello</b><br><br><i>World</i>
    </div>
</div>

<p id='description'></p>
<div id='console'></div>

<script>
    var element;
    var rowHeight;
    var touchOffset = 4;
    var touchRadius = 20;
    var origin;
    var adjustedNode;
    var adjustedPoint;

    function testTouchOnRow(row, offset) {
        var bounds = findAbsoluteBounds(element);
        var midPoint = bounds.left + 0.5 * bounds.width;
        var x = bounds.left + 2 * touchRadius;  
        var y = bounds.top + (row + 0.5) * rowHeight + offset; // Vertically centered on row when offset is zero.
        var point = touchPoint(x, y, touchRadius, touchRadius);
        adjustedPoint = adjustTouchPoint(point);
        origin = bounds.top;
        shouldEvaluateTo('Math.floor((adjustedPoint.y - origin) / rowHeight)', row);
    }

    function testDirectTouches() {
        debug('test direct touches');
        // Touches centered on the blank line should not be adjusted a neighboring text line.
        for (var row = 0; row < 3; row++) {
            for (var offset = -touchOffset; offset <= touchOffset; offset += touchOffset) {
                testTouchOnRow(row, offset);
            }
        }
    }

    function testTouchOnBoundary(position) {
        var touchpoint = offsetTouchPoint(findAbsoluteBounds(element), position, touchOffset, touchRadius, touchRadius);
        testTouchPoint(touchpoint, element);
    }

    function testIndirectTouches() {
      debug('test indirect touches');
      testTouchOnBoundary('bottom');
      testTouchOnBoundary('left');
      testTouchOnBoundary('right');
      testTouchOnBoundary('top');
    }

    function runTests()
    {
        if (window.testRunner && window.internals && internals.touchNodeAdjustedToBestClickableNode) {
            description('Tests touch adjustment on a text-area.');
            debug('test textarea');
            element = document.getElementById('text-area');
            rowHeight = 15; // Height of each row is line-height + 1
            testDirectTouches();
            testIndirectTouches();
            debug('test richly editable div');
            element = document.getElementById('rich-text');
            rowHeight = 14;
            testDirectTouches();
            testIndirectTouches();
        }
    }
    runTests();
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
