Implement the updated port/area-based Scroll Snap Module Level 1 Spec
[WebKit-https.git] / LayoutTests / tiled-drawing / scrolling / scroll-snap / scroll-snap-mandatory-overflow.html
1 <!DOCTYPE html>
2 <html>
3     <head>
4         <style>
5             .horizontalGallery {
6                 width: 300px;
7                 height: 300px;
8                 overflow-y: hidden;
9                 overflow-x: auto;
10                 margin-bottom: 2px;
11                 scroll-snap-type: x mandatory;
12             }
13             .horizontalGalleryDrawer {
14                 width: 1800px;
15                 height: 300px;
16             }
17             .verticalGallery {
18                 width: 300px;
19                 height: 300px;
20                 display: inline-block;
21                 overflow-x: hidden;
22                 overflow-y: auto;
23                 margin-top: 2px;
24                 scroll-snap-type: y mandatory;
25             }
26             .verticalGalleryDrawer {
27                 width: 300px;
28                 height: 1800px;
29             }
30             .colorBox {
31                 height: 300px;
32                 width: 300px;
33                 float: left;
34                 scroll-snap-align: start;
35             }
36             #itemH0, #itemV0 { background-color: red; }
37             #itemH1, #itemV1 { background-color: green; }
38             #itemH2, #itemV2 { background-color: blue; }
39             #itemH3, #itemV3 { background-color: aqua; }
40             #itemH4, #itemV4 { background-color: yellow; }
41             #itemH5, #itemV5 { background-color: fuchsia; }
42         </style>
43         <script src="../../../resources/js-test.js"></script>
44         <script>
45         window.jsTestIsAsync = true;
46
47         var divScrollPositionBeforeGlide;
48         var divScrollPositionBeforeSnap;
49
50         function locationInWindowCoordinates(element)
51         {
52             var position = {};
53             position.x = element.offsetLeft;
54             position.y = element.offsetTop;
55
56             while (element.offsetParent) {
57                 position.x = position.x + element.offsetParent.offsetLeft;
58                 position.y = position.y + element.offsetParent.offsetTop;
59                 if (element == document.getElementsByTagName("body")[0])
60                     break;
61
62                 element = element.offsetParent;
63             }
64
65             return position;
66         }
67
68         function checkForScrollSnap(targetLabel)
69         {
70             var divTarget = document.getElementById(targetLabel);
71
72             var actualPosition = divTarget.scrollTop;
73             if (targetLabel == 'horizontalTarget')
74                 actualPosition = divTarget.scrollLeft;
75
76             // The div should have snapped back to the previous position
77             if (actualPosition != divScrollPositionBeforeSnap)
78                 testFailed("div did not snap back to proper location for " + targetLabel +". Expected " + divScrollPositionBeforeSnap + ", but got " + actualPosition);
79             else
80                 testPassed("div honored snap points.");
81
82             if (targetLabel == 'horizontalTarget')
83                 setTimeout(function() { scrollGlideTest('verticalTarget') }, 0);
84             else   
85                 finishJSTest();
86         }
87
88         function scrollSnapTest(targetLabel)
89         {
90             debug("Testing scroll-snap snap for " + targetLabel + ":");
91             var divTarget = document.getElementById(targetLabel);
92  
93             var dx = 0;
94             var dy = 0;
95             if (targetLabel == 'horizontalTarget') {
96                 divScrollPositionBeforeSnap = divTarget.scrollLeft;
97                 dx = -1;
98             } else {
99                 divScrollPositionBeforeSnap = divTarget.scrollTop;
100                 dy = -1;
101             }
102
103             var windowPosition = locationInWindowCoordinates(divTarget);
104
105             var startPosX = windowPosition.x + 0.5 * divTarget.clientWidth;
106             var startPosY = windowPosition.y + 0.5 * divTarget.clientHeight;
107             eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iFrame
108             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'began', 'none');
109             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'changed', 'none');
110             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'changed', 'none');
111             eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none');
112             eventSender.callAfterScrollingCompletes(function() { return checkForScrollSnap(targetLabel); });
113         }
114
115         function checkForScrollGlide(targetLabel)
116         {
117             var divTarget = document.getElementById(targetLabel);
118
119             var actualPosition = divTarget.scrollTop;
120             var expectedPosition = divTarget.clientHeight;
121             if (targetLabel == 'horizontalTarget') {
122                 actualPosition = divTarget.scrollLeft;
123                 expectedPosition = divTarget.clientWidth;
124             }
125
126             // The div should have scrolled (glided) to the next snap point.
127             if (actualPosition == expectedPosition)
128                 testPassed("div scrolled to next window.");
129             else
130                 testFailed("div did not honor snap points. Expected " + expectedPosition + ", but got " + actualPosition);
131
132             setTimeout(function() { scrollSnapTest(targetLabel) }, 0);
133         }
134
135         function scrollGlideTest(targetLabel)
136         {
137             debug("Testing scroll-snap glide for " + targetLabel + ":");
138             var divTarget = document.getElementById(targetLabel);
139  
140             var dx = 0;
141             var dy = 0;
142             if (targetLabel == 'horizontalTarget') {
143                 divScrollPositionBeforeGlide = divTarget.scrollLeft;
144                 dx = -1;
145             } else {
146                 divScrollPositionBeforeGlide = divTarget.scrollTop;
147                 dy = -1;
148             }
149
150             var windowPosition = locationInWindowCoordinates(divTarget);
151
152             var startPosX = windowPosition.x + 0.5 * divTarget.clientWidth;
153             var startPosY = windowPosition.y + 0.5 * divTarget.clientHeight;
154             eventSender.mouseMoveTo(startPosX, startPosY);
155             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'began', 'none');
156             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'changed', 'none');
157             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'changed', 'none');
158             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'changed', 'none');
159             eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none');
160             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'none', 'begin');
161             eventSender.mouseScrollByWithWheelAndMomentumPhases(dx, dy, 'none', 'continue');
162             eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end');
163             eventSender.callAfterScrollingCompletes(function() { return checkForScrollGlide(targetLabel); });
164         }
165
166         function onLoad()
167         {
168             if (window.eventSender) {
169                 eventSender.monitorWheelEvents();
170                 setTimeout(function() { scrollGlideTest('horizontalTarget') }, 0);
171             } else {
172                 var messageLocationH = document.getElementById('itemH0');
173                 var message = document.createElement('div');
174                 message.innerHTML = "<p>This test is better run under DumpRenderTree.<br/>To manually test it, place the mouse pointer<br/>"
175                     + "inside the red region at the top of the page,<br/>and then use the mouse wheel or a two-finger<br/>swipe to make a"
176                     + "small swipe gesture with<br/>some momentum.<br/><br/>"
177                     + "The region should scroll to show a green region.<br/><br/>"
178                     + "Next, perform a small scroll gesture that does<br/>not involve momentum. You should begin to<br/>see one of the colors "
179                     + "to the side of the current<br/>green box. When you release the wheel, the<br/>region should scroll back to a single color.";
180                 messageLocationH.appendChild(message);
181
182                 var messageLocationV = document.getElementById('itemV0');
183                 var message = document.createElement('div');
184                 message.innerHTML = "<p>You should also be able to repeat these tests steps for this vertical region.<br/>"
185                 messageLocationV.appendChild(message);
186             }
187         }
188         </script>
189     </head>
190     <body onload="onLoad();">
191         <div style="position: relative; width: 300px">
192             <div>Tests that the scroll-snap feature works properly in overflow regions.</div>
193             <div class="horizontalGallery" id="horizontalTarget">
194                 <div class="horizontalGalleryDrawer">
195                     <div id="itemH0" class="colorBox"></div>
196                     <div id="itemH1" class="colorBox"></div>
197                     <div id="itemH2" class="colorBox"></div>
198                     <div id="itemH3" class="colorBox"></div>
199                     <div id="itemH4" class="colorBox"></div>
200                     <div id="itemH5" class="colorBox"></div>
201                 </div>
202             </div>
203             <div class="verticalGallery" id="verticalTarget">
204                 <div class="verticalGalleryDrawer">
205                     <div id="itemV0" class="colorBox"></div>
206                     <div id="itemV1" class="colorBox"></div>
207                     <div id="itemV2" class="colorBox"></div>
208                     <div id="itemV3" class="colorBox"></div>
209                     <div id="itemV4" class="colorBox"></div>
210                     <div id="itemV5" class="colorBox"></div>
211                 </div>
212             </div>
213             <div id="console"></div>
214         </div>
215     </body>
216 </html>