Skip to content
This repository has been archived by the owner on Jun 28, 2023. It is now read-only.

Commit

Permalink
- Correct implementation of document.getScrollTop/left.
Browse files Browse the repository at this point in the history
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: gwtproject#9542
Bug-Link: gwtproject#9542
Change-Id: I02fe4de00a3f646687f0550e603fc7bb4aca1b80
  • Loading branch information
jDramaix authored and hjohannsen committed Jun 22, 2018
1 parent 090ef8e commit 0f6c2b7
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 45 deletions.
19 changes: 15 additions & 4 deletions user/src/com/google/gwt/dom/client/DOMImpl.java
Expand Up @@ -266,15 +266,15 @@ public native Element getPreviousSiblingElement(Element elem) /*-{
}-*/;

public int getScrollLeft(Document doc) {
return doc.getViewportElement().getScrollLeft();
return ensureDocumentScrollingElement(doc).getScrollLeft();
}

public int getScrollLeft(Element elem) {
return toInt32(getSubPixelScrollLeft(elem));
}

public int getScrollTop(Document doc) {
return doc.getViewportElement().getScrollTop();
return ensureDocumentScrollingElement(doc).getScrollTop();
}

public native String getStyleProperty(Style style, String name) /*-{
Expand Down Expand Up @@ -376,21 +376,32 @@ public native void setInnerText(Element elem, String text) /*-{
}-*/;

public void setScrollLeft(Document doc, int left) {
doc.getViewportElement().setScrollLeft(left);
ensureDocumentScrollingElement(doc).setScrollLeft(left);
}

public native void setScrollLeft(Element elem, int left) /*-{
elem.scrollLeft = left;
}-*/;

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));
}
Expand Down
5 changes: 0 additions & 5 deletions user/src/com/google/gwt/dom/client/DOMImplIE9.java
Expand Up @@ -91,11 +91,6 @@ public void setScrollLeft(Element elem, int left) {
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
Expand Down
20 changes: 20 additions & 0 deletions user/src/com/google/gwt/dom/client/DOMImplStandard.java
Expand Up @@ -132,4 +132,24 @@ public native boolean isOrHasChild(Node parent, Node child) /*-{
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;
}-*/;

}
38 changes: 2 additions & 36 deletions user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
Expand Up @@ -210,7 +210,7 @@ public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
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);
}
Expand All @@ -219,18 +219,11 @@ public int getAbsoluteLeft(Element elem) {
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)) {
Expand All @@ -240,30 +233,13 @@ public int getScrollLeft(Element elem) {
return super.getScrollLeft(elem);
}

@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.
return typeof elem.tabIndex != 'undefined' ? elem.tabIndex : -1;
}-*/;

@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)) {
Expand All @@ -272,16 +248,6 @@ public void setScrollLeft(Element elem, int left) {
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';
}-*/;
Expand Down
6 changes: 6 additions & 0 deletions user/src/com/google/gwt/dom/client/DOMImplWebkit.java
Expand Up @@ -62,5 +62,11 @@ public void setDraggable(Element elem, String draggable) {
elem.getStyle().clearProperty("webkitUserDrag");
}
}

@Override
Element getLegacyDocumentScrollingElement(Document doc) {
// Old WebKit needs body.scrollLeft in both quirks mode and strict mode.
return doc.getBody();
}
}

2 changes: 2 additions & 0 deletions user/src/com/google/gwt/dom/client/Document.java
Expand Up @@ -1406,6 +1406,7 @@ public final native String getReferrer() /*-{
* @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();
}

Expand Down Expand Up @@ -1438,6 +1439,7 @@ public final int getScrollTop() {
* @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();
}

Expand Down

0 comments on commit 0f6c2b7

Please sign in to comment.