| <!doctype html> | |
| <title>Visual Viewport Scroll Event Order</title> | |
| <meta charset=utf-8> | |
| <link rel="help" href="https://wicg.github.io/visual-viewport/index.html"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="/resources/testdriver.js"></script> | |
| <script src="/resources/testdriver-actions.js"></script> | |
| <script src="/resources/testdriver-vendor.js"></script> | |
| <style> | |
| #target { | |
| width: 100px; | |
| height: 100px; | |
| background-color: red; | |
| position: absolute; | |
| top: 300vh; | |
| } | |
| #scroller1,#scroller2 { | |
| width: 200px; | |
| height: 200px; | |
| overflow: auto; | |
| } | |
| #spacer { | |
| width: 80px; | |
| height: 1000px; | |
| background-image: linear-gradient(45deg, #808080 25%, transparent 25%), | |
| linear-gradient(-45deg, #808080 25%, transparent 25%), | |
| linear-gradient(45deg, transparent 75%, #808080 75%), | |
| linear-gradient(-45deg, transparent 75%, #808080 75%); | |
| background-size: 40px 40px; | |
| background-position: 0 0, 0 20px, 20px -20px, -20px 0px; | |
| } | |
| </style> | |
| <body> | |
| <div id="target"></div> | |
| <div id="scroller1"><div id="spacer"></div></div> | |
| <div id="scroller2"><div id="spacer"></div></div> | |
| </body> | |
| <script> | |
| async function oneRaf() { | |
| return new Promise((resolve) => { | |
| window.requestAnimationFrame(resolve); | |
| }); | |
| } | |
| function pinch_zoom_in() { | |
| return new test_driver.Actions() | |
| .setContext(window) | |
| .addPointer("finger1", "touch") | |
| .addPointer("finger2", "touch") | |
| .pointerMove(400, 250, {origin: "viewport", sourceName: "finger1"}) | |
| .pointerMove(400, 350, {origin: "viewport", sourceName: "finger2"}) | |
| .pointerDown({sourceName: "finger1"}) | |
| .pointerDown({sourceName: "finger2"}) | |
| .pointerMove(400, 200, {origin: "viewport", sourceName: "finger1"}) | |
| .pointerMove(400, 400, {origin: "viewport", sourceName: "finger2"}) | |
| .pointerUp({sourceName: "finger1"}) | |
| .pointerUp({sourceName: "finger2"}) | |
| .send(); | |
| } | |
| const scroller1 = document.getElementById('scroller1'); | |
| const scroller2 = document.getElementById('scroller2'); | |
| promise_test(async t => { | |
| // Pinch-zoom in so that the scrollIntoView call below causes scrolling in | |
| // both the layout and visual viewports within the same rAF. | |
| await pinch_zoom_in(); | |
| assert_greater_than(window.visualViewport.scale, 1, 'Must have zoomed in'); | |
| await oneRaf(); | |
| const scroll_events = []; | |
| // Register the scroll handlers on the window, visualViewport, and both | |
| // <div> scrollers. | |
| { | |
| window.onscroll = () => { scroll_events.push('window-attribute'); } | |
| window.addEventListener('scroll', () => { scroll_events.push('window-addEventListener'); }); | |
| window.visualViewport.onscroll = () => { scroll_events.push('visualViewport-attribute'); } | |
| window.visualViewport.addEventListener('scroll', () => { | |
| scroll_events.push('visualViewport-addEventListener'); }); | |
| scroller1.addEventListener('scroll', | |
| () => { scroll_events.push('scroller1'); }); | |
| scroller2.addEventListener('scroll', | |
| () => { scroll_events.push('scroller2'); }); | |
| } | |
| // Cause scrolling in each scroller and scrollIntoView so that the layout | |
| // and visual viewports both scroll. | |
| scroller1.scrollTop = 200; | |
| document.getElementById('target').scrollIntoView(); | |
| scroller2.scrollTop = 200; | |
| // Wait a rAF since scroll events are delievered as part of the event loop. | |
| await oneRaf(); | |
| // The scroll events must be delivered in the order they were executed, | |
| // scroller1 first, then the viewport (window then visualViewport), then | |
| // scroller2. | |
| assert_equals(scroll_events.toString(), | |
| 'scroller1,' + | |
| 'window-attribute,window-addEventListener,' + | |
| 'visualViewport-attribute,visualViewport-addEventListener,' + | |
| 'scroller2'); | |
| }, "Scroll event ordering"); | |
| </script> |