You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[cssom-view-1] Update spec text for visual viewport scroll and scrollend events (#8205)
Adds normative text for firing the scrollend event on the VisualViewport.
scroll was already specified but incorrectly. The text as written meant that a scroll event would have to be dispatched at VisualViewport whenever the document scrolls, even if the VisualViewport didn't scroll.
This PR splits the perform a scroll steps into one for scrolling boxes (the existing one) and one for viewports (newly added). The viewport version distributes the scroll between the visual and layout viewports and the uses the scrolling box version to perform the scroll of each.
Fixes#8103
The {{VisualViewport}} object has an <dfn for=visualviewport>associated document</dfn>, which is a {{Document}} object.
282
347
It is the <a for="/">associated document</a> of the owner {{Window}} of {{VisualViewport}}. The <a>layout viewport</a>
283
348
is the owner {{Window}}'s <a>viewport</a>.
@@ -363,10 +428,50 @@ the following steps must be run:
363
428
Note: <code>behavior: "instant"</code> always performs an <a>instant scroll</a> by this algorithm.
364
429
365
430
Note: If the scroll position did not change as a result of the user interaction or programmatic invocation, where no translations were applied as a result, then no <a event>scrollend</a> event fires because no scrolling occured.
366
-
367
-
Note: In the case the VisualViewport was scrolled, yielding no translation changes in the document, emit the <a event>scrollend</a> on the VisualViewport just as the <a event>scroll</a> event is emitted for VisualViewport scrolling.
368
431
</ol>
369
432
433
+
When a user agent is to <dfn for="viewport" export>perform a scroll</dfn> of a <a>viewport</a> to a given position <var>position</var> and optionally a scroll behavior <var>behavior</var>
434
+
(which is "<code>auto</code>" if omitted) it must perform a coordinated viewport scroll by following these steps:
435
+
436
+
1. Let <var>doc</var> be the <a>viewport's</a> associated {{Document}}.
437
+
1. Let <var>vv</var> be the {{VisualViewport}} whose <a for=visualviewport>associated document</a> is <var>doc</var>.
438
+
1. Let <var>maxX</var> be the difference between <a>viewport</a>'s <a>scrolling box</a>'s width and the value of <var>vv</var>'s <a attribute
439
+
for=VisualViewport lt=width>width</a> attribute.
440
+
1. Let <var>maxY</var> be the difference between <a>viewport</a>'s <a>scrolling box</a>'s height and the value of <var>vv</var>'s <a attribute
1. Let <var>dx</var> be the horizontal component of <var>position</var> - the value <var>vv</var>'s <a attribute for=VisualViewport lt=pageLeft>pageLeft</a> attribute
443
+
1. Let <var>dy</var> be the vertical component of <var>position</var> - the value of <var>vv</var>'s <a attribute for=VisualViewport lt=pageTop>pageTop</a> attribute
444
+
1. Let <var>visual x</var> be the value of <var>vv</var>'s <a attribute for=VisualViewport lt=offsetLeft>offsetLeft</a> attribute.
445
+
1. Let <var>visual y</var> be the value of <var>vv</var>'s <a attribute for=VisualViewport lt=offsetTop>offsetTop</a> attribute.
446
+
1. Let <var>visual dx</var> be min(<var>maxX</var>, max(0, <var>visual x</var> + <var>dx</var>)) - <var>visual x</var>.
447
+
1. Let <var>visual dy</var> be min(<var>maxY</var>, max(0, <var>visual y</var> + <var>dy</var>)) - <var>visual y</var>.
448
+
1. Let <var>layout dx</var> be <var>dx</var> - <var>visual dx</var>
449
+
1. Let <var>layout dy</var> be <var>dy</var> - <var>visual dy</var>
450
+
1. Let <var>element</var> be <var>doc</var>'s root element if there is one, null otherwise.
451
+
1. <a for="/">Perform a scroll</a> of the <a>viewport</a>'s <a>scrolling box</a> to its current scroll position + (<var>layout dx</var>, <var>layout dy</var>) with <var>element</var> as the
452
+
associated element, and <var>behavior</var> as the scroll behavior.
453
+
1. <a for="/">Perform a scroll</a> of <var>vv</var>'s <a>scrolling box</a> to its current scroll position + (<var>visual dx</var>, <var>visual dy</var>) with <var>element</var> as the associated
454
+
element, and <var>behavior</var> as the scroll behavior.
455
+
456
+
Note: Conceptually, the visual viewport is scrolled until it "bumps up" against the layout viewport
457
+
edge and then "pushes" the layout viewport by applying the scroll delta to the layout viewport.
458
+
However, the scrolls in the steps above are computed ahead of time and applied in the opposite order
459
+
so that the layout viewport is scrolled before the visual viewport. This is done for historical
460
+
reasons to ensure consistent scroll event ordering. See the <a href="#example-vvanimation">example
461
+
above</a> for a visual depiction.
462
+
463
+
<div class='example'>
464
+
The user pinch-zooms into the document and ticks their mouse wheel, requesting the user agent scroll the document down by 50px. Because the document
465
+
is pinch-zoomed in, the visual viewport has 20px of room to scroll. The user agent distributes the scroll by scrolling the visual viewport down by
466
+
20px and the layout viewport by 30px.
467
+
</div>
468
+
469
+
<div class='example'>
470
+
The user is viewing a document in a mobile user agent. The document focuses an offscreen text input element, showing a virtual keyboard which shrinks
471
+
the visual viewport. The user agent must now bring the element into view in the visual viewport. The user agent scrolls the layout viewport so that
472
+
the element is visible within it, then the visual viewport so that the element is visible to the user.
473
+
</div>
474
+
370
475
Scroll is <dfn lt="scroll completed">completed</dfn> when the scroll position has no more pending updates or translations and the user has completed their gesture. Scroll position updates include smooth or instant mouse wheel scrolling, keyboard scrolling, scroll-snap events, or other APIs and gestures which cause the scroll position to update and possibly interpolate. User gestures like touch panning or trackpad scrolling aren't complete until pointers or keys have released.
371
476
372
477
When a user agent is to perform a <dfn export id=concept-smooth-scroll>smooth scroll</dfn> of a <a>scrolling box</a><var>box</var> to <var>position</var>,
@@ -386,7 +491,7 @@ To <dfn export>scroll to the beginning of the document</dfn> for a document <var
386
491
<a>scrolling area</a> with the <a>beginning edges</a> of <var>viewport</var>.
387
492
<li>If <var>position</var> is the same as <var>viewport</var>'s current scroll position, and <var>viewport</var> does not have an ongoing
388
493
<a>smooth scroll</a>, abort these steps.
389
-
<li><a>Perform a scroll</a> of <var>viewport</var> to <var>position</var>,
494
+
<li><a for="viewport">Perform a scroll</a> of <var>viewport</var> to <var>position</var>,
390
495
and <var>document</var>'s [=root element=] as the associated element, if there is one, or null otherwise.
391
496
</ol>
392
497
@@ -579,10 +684,13 @@ steps must be run:
579
684
1. If <var>position</var> is the same as the <a>viewport’s</a> current scroll position,
580
685
and the <a>viewport</a> does not have an ongoing <a>smooth scroll</a>, abort these steps.
581
686
1. Let <var>document</var> be the <a>viewport’s</a> associated {{Document}}.
582
-
1. <a>Perform a scroll</a> of the <a>viewport</a> to <var>position</var>,
687
+
1. <a for="viewport">Perform a scroll</a> of the <a>viewport</a> to <var>position</var>,
583
688
<var>document</var>'s [=root element=] as the associated element, if there is one, or null otherwise,
584
689
and the scroll behavior being the value of the {{ScrollOptions/behavior}} dictionary member of <var>options</var>.
585
690
691
+
Issue: User agents do not agree whether this uses the (coordinated) <a>viewport</a><a for="viewport">perform a scroll</a> or the
692
+
<a>scrolling box</a><a for="/">perform a scroll</a> on the layout viewport's scrolling box.
693
+
586
694
When the <dfn method for=Window lt="scrollTo(options)|scrollTo(x, y)">scrollTo()</dfn> method is invoked, the
587
695
user agent must act as if the {{Window/scroll()}} method was invoked with the same arguments.
588
696
@@ -1371,14 +1479,15 @@ a <a>scrolling box</a> <var>scrolling box</var>, in order of innermost to outerm
1371
1479
1. <dl class=switch>
1372
1480
<dt>If <var>scrolling box</var> is associated with an element
1373
1481
<dd>
1374
-
Let <var>associated element</var>be the element.
1375
-
1482
+
<a for="/">Perform a scroll</a> of the element's <var>scrolling box</var>to <var>position</var>, with the element as the associated element and
1483
+
<var>behavior</var> as the scroll behavior.
1376
1484
<dt>If <var>scrolling box</var> is associated with a <a>viewport</a>
1377
1485
<dd>
1378
-
Let <var>document</var> be the <a>viewport’s</a> associated {{Document}}.
1379
-
Let <var>associated element</var> be <var>document</var>'s [=root element=], if there is one, or null otherwise.
1486
+
1. Let <var>document</var> be the <a>viewport’s</a> associated {{Document}}.
1487
+
1. Let <var>root element</var> be <var>document</var>'s [=root element=], if there is one, or null otherwise.
1488
+
1. <a for="viewport">Perform a scroll</a> of the <a>viewport</a> to <var>position</var>, with <var>root element</var> as the associated element and <var>behavior</var>
1489
+
as the scroll behavior.
1380
1490
</dl>
1381
-
1. <a>Perform a scroll</a> of <var>scrolling box</var> to <var>position</var>, <var>associated element</var> as the associated element and <var>behavior</var> as the scroll behavior.
1382
1491
1383
1492
1384
1493
To <dfn>scroll an element</dfn><var>element</var> to <var>x</var>,<var>y</var> optionally with a scroll behavior <var>behavior</var> (which is "<code>auto</code>" if omitted) means to:
@@ -1400,7 +1509,7 @@ To <dfn>scroll an element</dfn> <var>element</var> to <var>x</var>,<var>y</var>
1400
1509
</dl>
1401
1510
1. Let <var>position</var> be the scroll position <var>box</var> would have by aligning <a>scrolling area</a> x-coordinate <var>x</var> with the left of <var>box</var> and aligning <a>scrolling area</a> y-coordinate <var>y</var> with the top of <var>box</var>.
1402
1511
1. If <var>position</var> is the same as <var>box</var>'s current scroll position, and <var>box</var> does not have an ongoing <a>smooth scroll</a>, abort these steps.
1403
-
1. <a>Perform a scroll</a> of <var>box</var> to <var>position</var>, <var>element</var> as the associated element and <var>behavior</var> as the scroll behavior.
1512
+
1. <a for="/">Perform a scroll</a> of <var>box</var> to <var>position</var>, <var>element</var> as the associated element and <var>behavior</var> as the scroll behavior.
1404
1513
1405
1514
1406
1515
@@ -1793,24 +1902,33 @@ Whenever an element gets scrolled (whether in response to user interaction or by
1793
1902
1. If the element is already in <var>doc</var>'s <a>pending scroll event targets</a>, abort these steps.
1794
1903
1. Append the element to <var>doc</var>'s <a>pending scroll event targets</a>.
1795
1904
1905
+
Whenever a <a>visual viewport</a> gets scrolled (whether in response to user interaction or by an API), the user agent must run these steps:
1906
+
1907
+
1. Let <var>vv</var> be the {{VisualViewport}} object that was scrolled.
1908
+
1. Let <var>doc</var> be <var>vv</var>'s <a for=visualviewport>associated document</a>.
1909
+
1. If <var>vv</var> is already in <var>doc</var>'s <a>pending scroll event targets</a>, abort these steps.
1910
+
1. Append <var>vv</var> to <var>doc</var>'s <a>pending scroll event targets</a>.
1911
+
1796
1912
When asked to <dfn export for=Document>run the scroll steps</dfn> for a {{Document}}<var>doc</var>, run these steps:
1797
1913
1798
1914
1. For each item <var>target</var> in <var>doc</var>'s <a>pending scroll event targets</a>,
1799
1915
in the order they were added to the list, run these substeps:
1800
1916
1801
-
1. If <var>target</var> is a {{Document}}, <a>fire an event</a> named <a event>scroll</a> that bubbles at <var>target</var> and <a>fire an event</a>
1802
-
named <a event>scroll</a> at the {{VisualViewport}} that is associated with <var>target</var>.
1917
+
1. If <var>target</var> is a {{Document}}, <a>fire an event</a> named <a event>scroll</a> that bubbles at <var>target</var>.
1803
1918
1. Otherwise, <a>fire an event</a> named <a event>scroll</a> at <var>target</var>.
Whenever scrolling is <a lt="scroll completed">completed</a>, the user agent must run these steps:
1807
1922
1808
-
1. If scrolling was done on a <a>viewport</a>, let <var>doc</var> be the <a>viewport’s</a> associated {{Document}} and <var>target</var> be the <a>viewport</a>.
1809
-
Otherwise, scrolling is done on an element and let <var>doc</var> be the element's <a>node document</a> and <var>target</var> be the element.
1810
-
1. If <var>target</var> is already in <var>doc</var>'s <a>pending scrollend event targets</a>, abort these steps.
1811
-
1. Append <var>target</var> to <var>doc</var>'s <a>pending scrollend event targets</a>.
1812
-
1. For each item <var>target</var> in <var>doc</var>'s <a>pending scrollend event targets</a>, in the order they were added to the list, run these substeps:
1923
+
Issue: In what order are scrollend events dispatched? Ordered based on scroll start or scroll completion?
1813
1924
1925
+
1. For each scrolling box <var>box</var> that was scrolled:
1926
+
1. If <var>box</var> belongs to a <a>viewport</a>, let <var>doc</var> be the <a>viewport’s</a> associated {{Document}} and <var>target</var> be the <a>viewport</a>.
1927
+
If <var>box</var> belongs to a {{VisualViewport}}, let <var>doc</var> be the {{VisualViewport}}'s <a for=visualviewport>associated document</a> and <var>target</var>
1928
+
be the {{VisualViewport}}. Otherwise, <var>box</var> belongs to an element and let <var>doc</var> be the element's <a>node document</a> and <var>target</var> be the element.
1929
+
1. If <var>target</var> is already in <var>doc</var>'s <a>pending scrollend event targets</a>, abort these steps.
1930
+
1. Append <var>target</var> to <var>doc</var>'s <a>pending scrollend event targets</a>.
1931
+
1. For each item <var>target</var> in <var>doc</var>'s <a>pending scrollend event targets</a>, in the order they were added to the list, run these substeps:
1814
1932
1. If <var>target</var> is a {{Document}}, <a>fire an event</a> named <a event>scrollend</a> that bubbles at <var>target</var>.
1815
1933
1. Otherwise, <a>fire an event</a> named <a event>scrollend</a> at <var>target</var>.
<td>Fired at the {{Document}} or element when scroll is <a lt="scroll completed">completed</a>: the <a>viewport</a> or element has been scrolled, the scroll sequence has ended and any scroll offset changes have been applied.
1962
+
<td>{{Document}}, elements, {{VisualViewport}}
1963
+
<td>Fired at the {{VisualViewport}}, {{Document}}, or element when a scroll is <a lt="scroll completed">completed</a>: the
1964
+
{{VisualViewport}}, <a>viewport</a>, or element has been scrolled, the scroll sequence has ended and any scroll offset changes have
0 commit comments