<!doctype html>
<html>
    <head>
        <title>Button touch-action test</title>
        <meta name="assert" content="TA15.11 -The touch-action CSS property applies to button elements.">
        <meta name="viewport" content="width=device-width">
        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
        <script src="/resources/testharness.js"></script>
        <script src="/resources/testharnessreport.js"></script>
        <script src="pointerevent_support.js"></script>
        <style>
            #target0 {
            height: 150px;
            width: 200px;
            overflow-y: auto;
            background: black;
            padding: 100px;
            position: relative;
            }
            button {
            touch-action: none;
            width: 350px;
            height: 350px;
            border: 2px solid red;
            }
        </style>
    </head>
    <body onload="run()">
        <h2>Pointer Events touch-action attribute support</h2>
        <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
        <p>Note: this test is for touch only</p>
        <div id="target0">
            <button>Test Button</button>
        </div>
        <br>
        <input type="button" id="btnComplete" value="Complete test">

        <script type='text/javascript'>
            var detected_pointertypes = {};
            var xScrollIsReceived = false;
            var yScrollIsReceived = false;
            var xScr0, yScr0, xScr1, yScr1;
            var scrollReturnInterval = 1000;
            var isFirstPart = true;
            setup({ explicit_timeout: true });
            add_completion_callback(showPointerTypes);

            function run() {
                var target0 = document.getElementById("target0");
                var btnComplete = document.getElementById("btnComplete");

                //TA 15.11
                var test_touchaction_div = async_test("touch-action attribute test out of element");
                var test_touchaction_button = async_test("touch-action attribute test in element");

                xScr0 = target0.scrollLeft;
                yScr0 = target0.scrollTop;

                on_event(btnComplete, 'click', function(event) {
                    test_touchaction_button.step(function() {
                        assert_equals(target0.scrollLeft, 0, "button scroll x offset should be 0 in the end of the test");
                        assert_equals(target0.scrollTop, 0, "button scroll y offset should be 0 in the end of the test");
                        assert_true(xScrollIsReceived && yScrollIsReceived, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
                    });
                    test_touchaction_button.done();
                    updateDescriptionComplete();
                });

                on_event(btnComplete, 'pointerdown', function(event) {
                    detected_pointertypes[event.pointerType] = true;
                });

                on_event(target0, 'scroll', function(event) {
                    if(isFirstPart) {
                        xScr1 = target0.scrollLeft;
                        yScr1 = target0.scrollTop;

                        if(xScr1 != xScr0) {
                            xScrollIsReceived = true;
                        }

                        if(yScr1 != yScr0) {
                            test_touchaction_div.step(function () {
                                yScrollIsReceived = true;
                            });
                            updateDescriptionSecondStepTouchActionElement(target0, scrollReturnInterval);
                        }

                        if(xScrollIsReceived && yScrollIsReceived) {
                            test_touchaction_div.done();
                            updateDescriptionThirdStepTouchActionElement(target0, scrollReturnInterval);
                            setTimeout(function() {
                                isFirstPart = false;
                            }, 2 * scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
                        }
                    }
                    else {
                        test_touchaction_button.step(failOnScroll, "scroll received while shouldn't");
                    }
                });
            }
        </script>
        <h1>touch-action: none</h1>
        <div id="complete-notice">
            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
        </div>
        <div id="log"></div>
    </body>
</html>