Fixes DOMImplSafari.getAbsoluteLeft/Top() to account for position:fixed (issue 3859). Review: http://gwt-code-reviews.appspot.com/51809 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5761 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/DOMImplSafari.java b/user/src/com/google/gwt/dom/client/DOMImplSafari.java index cd5b387..9d29a57 100644 --- a/user/src/com/google/gwt/dom/client/DOMImplSafari.java +++ b/user/src/com/google/gwt/dom/client/DOMImplSafari.java
@@ -83,10 +83,15 @@ curr = curr.parentNode; } } - + while (elem) { left += elem.offsetLeft; + if (doc.defaultView.getComputedStyle(elem, '')['position'] == 'fixed') { + left += doc.body.scrollLeft; + return left; + } + // Safari 3 does not include borders with offsetLeft, so we need to add // the borders of the parent manually. var parent = elem.offsetParent; @@ -105,7 +110,7 @@ } return left; }-*/; - + @Override public native int getAbsoluteTop(Element elem) /*-{ // Unattached elements and elements (or their ancestors) with style @@ -124,10 +129,15 @@ curr = curr.parentNode; } } - + while (elem) { top += elem.offsetTop; + if (doc.defaultView.getComputedStyle(elem, '')['position'] == 'fixed') { + top += doc.body.scrollTop; + return top; + } + // Safari 3 does not include borders with offsetTop, so we need to add the // borders of the parent manually. var parent = elem.offsetParent;
diff --git a/user/test/com/google/gwt/dom/client/ElementTest.java b/user/test/com/google/gwt/dom/client/ElementTest.java index 4a2ff44..5c8ab14 100644 --- a/user/test/com/google/gwt/dom/client/ElementTest.java +++ b/user/test/com/google/gwt/dom/client/ElementTest.java
@@ -198,7 +198,7 @@ assertEquals(absLeft, elem.getAbsoluteLeft()); assertEquals(absTop, elem.getAbsoluteTop()); - if (isIE() && !doc.isCSS1Compat()) { + if (isIE6or7() && !doc.isCSS1Compat()) { // In IE/quirk, the interior decorations are considered part of the // width/height, so there's no need to account for them here. assertEquals(absLeft + width, elem.getAbsoluteRight()); @@ -228,6 +228,11 @@ div.getStyle().setLeft(1000, Unit.PX); div.getStyle().setTop(1000, Unit.PX); + DivElement fixedDiv = doc.createDivElement(); + body.appendChild(fixedDiv); + fixedDiv.setInnerText("foo"); + fixedDiv.getStyle().setPosition(Position.FIXED); + // Get the absolute position of the element when the body is unscrolled. int absLeft = div.getAbsoluteLeft(); int absTop = div.getAbsoluteTop(); @@ -245,6 +250,15 @@ // getAbsoluteLeft/Top() yet again for FF2. assertTrue(Math.abs(absLeft - div.getAbsoluteLeft()) <= 1); assertTrue(Math.abs(absTop - div.getAbsoluteTop()) <= 1); + + // Ensure that the 'position:fixed' div's absolute position includes the + // body's scroll position. + // + // Don't do this on IE6/7 or old Gecko, which don't support position:fixed. + if (!isIE6or7() && !isOldGecko()) { + assertTrue(fixedDiv.getAbsoluteLeft() >= body.getScrollLeft()); + assertTrue(fixedDiv.getAbsoluteTop() >= body.getScrollTop()); + } } /** @@ -581,8 +595,34 @@ return {}; }-*/; - private native boolean isIE() /*-{ + // Stolen from UserAgent.gwt.xml. + private native boolean isIE6or7() /*-{ var ua = navigator.userAgent.toLowerCase(); - return ua.indexOf("msie") != -1; + if (ua.indexOf("msie") != -1) { + if (document.documentMode >= 8) { + return false; + } + return true; + } + return false; + }-*/; + + // Stolen from UserAgent.gwt.xml. + private native boolean isOldGecko() /*-{ + var makeVersion = function(result) { + return (parseInt(result[1]) * 1000) + parseInt(result[2]); + }; + + var ua = navigator.userAgent.toLowerCase(); + if (ua.indexOf("gecko") != -1) { + var result = /rv:([0-9]+)\.([0-9]+)/.exec(ua); + if (result && result.length == 3) { + if (makeVersion(result) >= 1008) { + return false; + } + } + return true; + } + return false; }-*/; }