- Correct implementation of document.getScrollTop/left.
For old browsers (<= ie10), we keep the old logic and relies on a
quirk/strict mode check to find the document scroll element.
For other browsers, we check first of document.scrollingElement exists
and use it computing scrollTop/Left. If not we use document.body for
webkit browser or rely on the quirk/strict mode check for other
browsers.
We default to document.documentElement if all the logic above return
null (SVG document)
- Fix getAbsoluteLeft/Top computation for webkit browsers to rely on the
correct implementation of document.getScrollLeft/Top.
Bug: #9542
Bug-Link: https://github.com/gwtproject/gwt/issues/9542
Change-Id: I02fe4de00a3f646687f0550e603fc7bb4aca1b80
diff --git a/user/src/com/google/gwt/dom/client/DOMImpl.java b/user/src/com/google/gwt/dom/client/DOMImpl.java
index 24f17e2..b6df165 100644
--- a/user/src/com/google/gwt/dom/client/DOMImpl.java
+++ b/user/src/com/google/gwt/dom/client/DOMImpl.java
@@ -266,7 +266,7 @@
}-*/;
public int getScrollLeft(Document doc) {
- return doc.getViewportElement().getScrollLeft();
+ return ensureDocumentScrollingElement(doc).getScrollLeft();
}
public int getScrollLeft(Element elem) {
@@ -274,7 +274,7 @@
}
public int getScrollTop(Document doc) {
- return doc.getViewportElement().getScrollTop();
+ return ensureDocumentScrollingElement(doc).getScrollTop();
}
public native String getStyleProperty(Style style, String name) /*-{
@@ -376,7 +376,7 @@
}-*/;
public void setScrollLeft(Document doc, int left) {
- doc.getViewportElement().setScrollLeft(left);
+ ensureDocumentScrollingElement(doc).setScrollLeft(left);
}
public native void setScrollLeft(Element elem, int left) /*-{
@@ -384,13 +384,24 @@
}-*/;
public void setScrollTop(Document doc, int top) {
- doc.getViewportElement().setScrollTop(top);
+ ensureDocumentScrollingElement(doc).setScrollTop(top);
}
public native String toString(Element elem) /*-{
return elem.outerHTML;
}-*/;
+ private Element ensureDocumentScrollingElement(Document document) {
+ // In some case (e.g SVG document and old Webkit browsers), getDocumentScrollingElement can
+ // return null. In this case, default to documentElement.
+ Element scrollingElement = getDocumentScrollingElement(document);
+ return scrollingElement != null ? scrollingElement : document.getDocumentElement();
+ }
+
+ Element getDocumentScrollingElement(Document doc) {
+ return doc.getViewportElement();
+ }
+
public int touchGetClientX(Touch touch) {
return toInt32(touchGetSubPixelClientX(touch));
}
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE9.java b/user/src/com/google/gwt/dom/client/DOMImplIE9.java
index 63626e9..12e1564 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE9.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE9.java
@@ -91,11 +91,6 @@
setScrollLeftImpl(elem, left);
}
- @Override
- public void setScrollLeft(Document doc, int left) {
- setScrollLeft(doc.getDocumentElement(), left);
- }
-
private native double getBoundingClientRectLeft(Element elem) /*-{
// getBoundingClientRect() throws a JS exception if the elem is not attached
// to the document, so we wrap it in a try/catch block
diff --git a/user/src/com/google/gwt/dom/client/DOMImplStandard.java b/user/src/com/google/gwt/dom/client/DOMImplStandard.java
index 9811b27..ca0b7f0 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplStandard.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplStandard.java
@@ -132,4 +132,24 @@
public native void setInnerText(Element elem, String text) /*-{
elem.textContent = text || '';
}-*/;
+
+ @Override
+ Element getDocumentScrollingElement(Document doc) {
+ // Uses http://dev.w3.org/csswg/cssom-view/#dom-document-scrolling element to
+ // avoid trying to guess about browser behavior.
+ if (getNativeDocumentScrollingElement(doc) != null) {
+ return getNativeDocumentScrollingElement(doc);
+ }
+
+ return getLegacyDocumentScrollingElement(doc);
+ }
+
+ Element getLegacyDocumentScrollingElement(Document doc) {
+ return doc.getViewportElement();
+ }
+
+ final native Element getNativeDocumentScrollingElement(Document doc) /*-{
+ return doc.scrollingElement;
+ }-*/;
+
}
diff --git a/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java b/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
index 34e3671..7e9f530 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
@@ -210,7 +210,7 @@
public int getAbsoluteLeft(Element elem) {
ClientRect rect = getBoundingClientRect(elem);
double left = rect != null ? rect.getSubPixelLeft()
- + elem.getOwnerDocument().getBody().getScrollLeft()
+ + getScrollLeft(elem.getOwnerDocument())
: getAbsoluteLeftUsingOffsets(elem);
return toInt32(left);
}
@@ -219,19 +219,12 @@
public int getAbsoluteTop(Element elem) {
ClientRect rect = getBoundingClientRect(elem);
double top = rect != null ? rect.getSubPixelTop()
- + elem.getOwnerDocument().getBody().getScrollTop()
+ + getScrollTop(elem.getOwnerDocument())
: getAbsoluteTopUsingOffsets(elem);
return toInt32(top);
}
@Override
- public native int getScrollLeft(Document doc) /*-{
- // Safari always applies document scrolling to the body element, even in strict mode.
- // The behavior of Chrome depends of the doctype mode.
- return doc.documentElement.scrollLeft || doc.body.scrollLeft;
- }-*/;
-
- @Override
public int getScrollLeft(Element elem) {
if (!elem.hasTagName(BodyElement.TAG) && isRTL(elem)) {
return super.getScrollLeft(elem)
@@ -241,13 +234,6 @@
}
@Override
- public native int getScrollTop(Document doc) /*-{
- // Safari always applies document scrolling to the body element, even in strict mode.
- // The behavior of Chrome depends of the doctype mode.
- return doc.documentElement.scrollTop || doc.body.scrollTop;
- }-*/;
-
- @Override
public native int getTabIndex(Element elem) /*-{
// tabIndex is undefined for divs and other non-focusable elements prior to
// Safari 4.
@@ -255,16 +241,6 @@
}-*/;
@Override
- public native void setScrollLeft(Document doc, int left) /*-{
- // Safari always applies document scrolling to the body element, even in strict mode. The
- // behavior of Chrome depends of the doctype mode.
- // This instruction will be ignored by safari and chrome in quirks mode.
- doc.documentElement.scrollLeft = left;
- // Will be ignored by chrome in strict mode.
- doc.body.scrollLeft = left;
- }-*/;
-
- @Override
public void setScrollLeft(Element elem, int left) {
if (!elem.hasTagName(BodyElement.TAG) && isRTL(elem)) {
left += elem.getScrollWidth() - elem.getClientWidth();
@@ -272,16 +248,6 @@
super.setScrollLeft(elem, left);
}
- @Override
- public native void setScrollTop(Document doc, int top) /*-{
- // Safari always applies document scrolling to the body element, even in strict mode. The
- // behavior of Chrome depends of the doctype mode.
- // This instruction will be ignored by safari and by chrome in quirks mode.
- doc.documentElement.scrollTop = top;
- // Will be ignored by chrome in strict mode.
- doc.body.scrollTop = top;
- }-*/;
-
protected native boolean isRTL(Element elem) /*-{
return elem.ownerDocument.defaultView.getComputedStyle(elem, '').direction == 'rtl';
}-*/;
diff --git a/user/src/com/google/gwt/dom/client/DOMImplWebkit.java b/user/src/com/google/gwt/dom/client/DOMImplWebkit.java
index cc80997..8433a5b 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplWebkit.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplWebkit.java
@@ -62,5 +62,11 @@
elem.getStyle().clearProperty("webkitUserDrag");
}
}
+
+ @Override
+ Element getLegacyDocumentScrollingElement(Document doc) {
+ // Old WebKit needs body.scrollLeft in both quirks mode and strict mode.
+ return doc.getBody();
+ }
}
diff --git a/user/src/com/google/gwt/dom/client/Document.java b/user/src/com/google/gwt/dom/client/Document.java
index dbcfca7..6eb119c 100644
--- a/user/src/com/google/gwt/dom/client/Document.java
+++ b/user/src/com/google/gwt/dom/client/Document.java
@@ -1413,6 +1413,7 @@
* @return the height of the document's scrollable area
*/
public final int getScrollHeight() {
+ // TODO(dramaix): Use document.scrollingElement when its available. See getScrollLeft().
return getViewportElement().getScrollHeight();
}
@@ -1445,6 +1446,7 @@
* @return the width of the document's scrollable area
*/
public final int getScrollWidth() {
+ // TODO(dramaix): Use document.scrollingElement when its available. See getScrollLeft().
return getViewportElement().getScrollWidth();
}