Forward Compatibility w/ WebKit & Blink
Newer versions of WebKit and Blink will support both `document.body.scrollTop` and `document.documentElement.scrollTop`. Therefore, implementing cross-browser compatibility by summing the two will no longer work. This changes React to use `getUnboundedScrollPosition` so we get the fix and consistency in one change! See: https://rniwa.com/2013-10-29/web-compatibility-story-of-scrolltop-and-scrollleft/
Tim Yung committed
Oct 30, 2013 at 16:47 UTC
7789a3243860029741bbb3ae93f6c495c12266ad
3 files changed
+62
-4
src/dom/ViewportMetrics.js
+5
-4
@@ -18,6 +18,8 @@
18
19
"use strict";
20
21
+var getUnboundedScrollPosition = require('getUnboundedScrollPosition');
22
+
23
var ViewportMetrics = {
24
25
currentScrollLeft: 0,
@@ -25,10 +27,9 @@ var ViewportMetrics = {
27
currentScrollTop: 0,
28
29
refreshScrollValues: function() {
28
- ViewportMetrics.currentScrollLeft =
29
- document.body.scrollLeft + document.documentElement.scrollLeft;
30
- ViewportMetrics.currentScrollTop =
31
- document.body.scrollTop + document.documentElement.scrollTop;
30
+ var scrollPosition = getUnboundedScrollPosition(window);
31
+ ViewportMetrics.currentScrollLeft = scrollPosition.x;
32
+ ViewportMetrics.currentScrollTop = scrollPosition.y;
33
}
34
35
};
src/vendor/core/dom/getDocumentScrollElement.js
new
+27
@@ -0,0 +1,27 @@
1
+/**
2
+ * @providesModule getDocumentScrollElement
3
+ * @typechecks
4
+ */
5
+
6
+"use strict";
7
+
8
+// TODO: Replace this with a UserAgent module.
9
+var isWebkit = navigator.userAgent.indexOf('AppleWebKit') > -1;
10
+
11
+/**
12
+ * Gets the element with the document scroll properties such as `scrollLeft` and
13
+ * `scrollHeight`. This may differ across different browsers.
14
+ *
15
+ * NOTE: The return value can be null if the DOM is not yet ready.
16
+ *
17
+ * @param {?DOMDocument} doc Defaults to current document.
18
+ * @return {?DOMElement}
19
+ */
20
+function getDocumentScrollElement(doc) {
21
+ doc = doc || document;
22
+ return !isWebkit && doc.compatMode === 'CSS1Compat' ?
23
+ doc.documentElement :
24
+ doc.body;
25
+}
26
+
27
+module.exports = getDocumentScrollElement;
src/vendor/core/dom/getUnboundedScrollPosition.js
new
+30
@@ -0,0 +1,30 @@
1
+/**
2
+ * @providesModule getUnboundedScrollPosition
3
+ * @typechecks
4
+ */
5
+
6
+"use strict";
7
+
8
+var getDocumentScrollElement = require('getDocumentScrollElement');
9
+
10
+/**
11
+ * Gets the scroll position of the supplied element or window.
12
+ *
13
+ * The return values are unbounded, unlike `getScrollPosition`. This means they
14
+ * may be negative or exceed the element boundaries (which is possible using
15
+ * inertial scrolling).
16
+ *
17
+ * @param {DOMWindow|DOMElement} scrollable
18
+ * @return {object} Map with `x` and `y` keys.
19
+ */
20
+function getUnboundedScrollPosition(scrollable) {
21
+ if (scrollable === window) {
22
+ return getUnboundedScrollPosition(getDocumentScrollElement());
23
+ }
24
+ return {
25
+ x: scrollable.scrollLeft,
26
+ y: scrollable.scrollTop
27
+ };
28
+}
29
+
30
+module.exports = getUnboundedScrollPosition;