Adds IE8 user-agent and fixes outstanding bugs in IE8-super-standards mode.
Review: http://gwt-code-reviews.appspot.com/29803
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5292 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/DOM.gwt.xml b/user/src/com/google/gwt/dom/DOM.gwt.xml
index e6c8d89..a0cd339 100644
--- a/user/src/com/google/gwt/dom/DOM.gwt.xml
+++ b/user/src/com/google/gwt/dom/DOM.gwt.xml
@@ -30,6 +30,11 @@
<when-property-is name="user.agent" value="safari"/>
</replace-with>
+ <replace-with class="com.google.gwt.dom.client.DOMImplIE8">
+ <when-type-is class="com.google.gwt.dom.client.DOMImpl"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </replace-with>
+
<replace-with class="com.google.gwt.dom.client.DOMImplIE6">
<when-type-is class="com.google.gwt.dom.client.DOMImpl"/>
<when-property-is name="user.agent" value="ie6"/>
@@ -47,6 +52,9 @@
<replace-with class="com.google.gwt.dom.client.StyleInjector.StyleInjectorImplIE">
<when-type-is class="com.google.gwt.dom.client.StyleInjector.StyleInjectorImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
</replace-with>
</module>
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE6.java b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
index 59c6af0..d348747 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE6.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
@@ -19,180 +19,22 @@
* Internet Explorer 6 implementation of
* {@link com.google.gwt.user.client.impl.DOMImpl}.
*/
-class DOMImplIE6 extends DOMImpl {
-
- /**
- * This field *must* be filled in from JSNI code before dispatching an event
- * on IE. It should be set to the 'this' context of the handler that receives
- * the event, then restored to its initial value when the dispatcher is done.
- * See {@link com.google.gwt.user.client.impl.DOMImplIE6#initEventSystem()}
- * for an example of how this should be done.
- */
- private static EventTarget currentEventTarget;
-
- @Override
- public native NativeEvent createHtmlEvent(Document doc, String type, boolean canBubble,
- boolean cancelable) /*-{
- // NOTE: IE doesn't support changing bubbling and canceling behavior (this
- // is documented publicly in Document.createHtmlEvent()).
- var evt = doc.createEventObject();
- evt.type = type;
- return evt;
- }-*/;
-
- @Override
- public native InputElement createInputRadioElement(Document doc, String name) /*-{
- return doc.createElement("<INPUT type='RADIO' name='" + name + "'>");
- }-*/;
-
- @Override
- public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble,
- boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey,
- boolean metaKey, int keyCode, int charCode) /*-{
- // NOTE: IE doesn't support changing bubbling and canceling behavior (this
- // is documented publicly in Document.createKeyEvent()).
- var evt = doc.createEventObject();
- evt.type = type;
- evt.ctrlKey = ctrlKey;
- evt.altKey = altKey;
- evt.shiftKey = shiftKey;
- evt.metaKey = metaKey;
- evt.keyCode = keyCode;
- evt.charCode = charCode;
-
- return evt;
- }-*/;
-
- @Override
- public native NativeEvent createMouseEvent(Document doc, String type, boolean canBubble,
- boolean cancelable, int detail, int screenX, int screenY, int clientX,
- int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey,
- boolean metaKey, int button, Element relatedTarget) /*-{
- // NOTE: IE doesn't support changing bubbling and canceling behavior (this
- // is documented publicly in Document.createMouseEvent()).
- var evt = doc.createEventObject();
- evt.type = type;
- evt.detail = detail;
- evt.screenX = screenX;
- evt.screenY = screenY;
- evt.clientX = clientX;
- evt.clientY = clientY;
- evt.ctrlKey = ctrlKey;
- evt.altKey = altKey;
- evt.shiftKey = shiftKey;
- evt.metaKey = metaKey;
- evt.button = button;
-
- // It would make sense to set evt.[fromElement | toElement] here, because
- // that's what IE uses. However, setting these properties has no effect for
- // some reason. So instead we set releatedTarget, and explicitly check for
- // its existence in eventGetFromElement() and eventGetToElement().
- evt.relatedTarget = relatedTarget;
-
- return evt;
- }-*/;
-
- /**
- * Supports creating a select control with the multiple attribute to work
- * around a bug in IE6 where changing the multiple attribute in a setAttribute
- * call can cause subsequent setSelected calls to misbehave. Although this bug
- * is fixed in IE7, this DOMImpl specialization is used for both IE6 and IE7,
- * but it should be harmless.
- */
- @Override
- public native SelectElement createSelectElement(Document doc, boolean multiple) /*-{
- var html = multiple ? "<SELECT MULTIPLE>" : "<SELECT>";
- return doc.createElement(html);
- }-*/;
-
- public native void dispatchEvent(Element target, NativeEvent evt) /*-{
- target.fireEvent("on" + evt.type, evt);
- }-*/;
-
- @Override
- public EventTarget eventGetCurrentTarget(NativeEvent event) {
- return currentEventTarget;
- }
-
- @Override
- public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
- return Math.round(-evt.wheelDelta / 40) || 0;
- }-*/;
-
- @Override
- public native EventTarget eventGetRelatedTarget(NativeEvent evt) /*-{
- // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
- // explicitly sets relatedTarget when synthesizing mouse events).
- return evt.relatedTarget ||
- (evt.type == "mouseout" ? evt.toElement:evt.fromElement);
- }-*/;
-
- @Override
- public native EventTarget eventGetTarget(NativeEvent evt) /*-{
- return evt.srcElement;
- }-*/;
-
- @Override
- public native void eventPreventDefault(NativeEvent evt) /*-{
- evt.returnValue = false;
- }-*/;
-
- @Override
- public native void eventStopPropagation(NativeEvent evt) /*-{
- evt.cancelBubble = true;
- }-*/;
-
- @Override
- public native String eventToString(NativeEvent evt) /*-{
- if (evt.toString) return evt.toString();
- return "[event" + evt.type + "]";
- }-*/;
+class DOMImplIE6 extends DOMImplTrident {
@Override
public int getAbsoluteLeft(Element elem) {
Document doc = elem.getOwnerDocument();
- return (int) Math.floor(getBoundingClientRectLeft(elem)
+ return (int) Math.floor(super.getAbsoluteLeft(elem)
/ getZoomMultiple(doc) + doc.getScrollLeft());
}
@Override
public int getAbsoluteTop(Element elem) {
Document doc = elem.getOwnerDocument();
- return (int) Math.floor(getBoundingClientRectTop(elem)
+ return (int) Math.floor(super.getAbsoluteTop(elem)
/ getZoomMultiple(doc) + doc.getScrollTop());
}
- /**
- * IE returns a numeric type for some attributes that are really properties,
- * such as offsetWidth. We need to coerce these to strings to prevent a
- * runtime JS exception.
- */
- @Override
- public native String getAttribute(Element elem, String name) /*-{
- var attr = elem.getAttribute(name);
- return attr == null? '' : attr + '';
- }-*/;
-
- @Override
- public int getBodyOffsetLeft(Document doc) {
- return getClientLeft(doc.getViewportElement());
- }
-
- @Override
- public int getBodyOffsetTop(Document doc) {
- return getClientTop(doc.getViewportElement());
- }
-
- @Override
- public native String getInnerText(Element elem) /*-{
- return elem.innerText;
- }-*/;
-
- @Override
- public native Element getParentElement(Element elem) /*-{
- return elem.parentElement;
- }-*/;
-
@Override
public int getScrollLeft(Element elem) {
if (isRTL(elem)) {
@@ -223,29 +65,6 @@
}
@Override
- public native boolean isOrHasChild(Element parent, Element child) /*-{
- // An extra equality check is required due to the fact that
- // elem.contains(elem) is false if elem is not attached to the DOM.
- return (parent === child) || parent.contains(child);
- }-*/;
-
- @Override
- public native void selectAdd(SelectElement select, OptionElement option,
- OptionElement before) /*-{
- // IE only accepts indices for the second argument.
- if (before) {
- select.add(option, before.index);
- } else {
- select.add(option);
- }
- }-*/;
-
- @Override
- public native void setInnerText(Element elem, String text) /*-{
- elem.innerText = text || '';
- }-*/;
-
- @Override
public void setScrollLeft(Element elem, int left) {
if (isRTL(elem)) {
left += elem.getScrollWidth() - elem.getClientWidth();
@@ -253,40 +72,6 @@
super.setScrollLeft(elem, left);
}
- private native int 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
- try {
- return elem.getBoundingClientRect().left;
- } catch (e) {
- return 0;
- }
- }-*/;
-
- private native int getBoundingClientRectTop(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
- try {
- return elem.getBoundingClientRect().top;
- } catch (e) {
- return 0;
- }
- }-*/;
-
- /**
- * clientLeft is non-standard and not implemented on all browsers.
- */
- private native int getClientLeft(Element elem) /*-{
- return elem.clientLeft;
- }-*/;
-
- /**
- * clientTop is non-standard and not implemented on all browsers.
- */
- private native int getClientTop(Element elem) /*-{
- return elem.clientTop;
- }-*/;
-
/**
* Get the zoom multiple based on the current IE zoom level. A multiple of 2.0
* means that the user has zoomed in to 200%.
@@ -302,8 +87,4 @@
doc.getBody().getOffsetWidth();
}
}
-
- private native boolean isRTL(Element elem) /*-{
- return elem.currentStyle.direction == 'rtl';
- }-*/;
}
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE8.java b/user/src/com/google/gwt/dom/client/DOMImplIE8.java
new file mode 100644
index 0000000..e3b3826
--- /dev/null
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE8.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dom.client;
+
+class DOMImplIE8 extends DOMImplTrident {
+}
diff --git a/user/src/com/google/gwt/dom/client/DOMImplTrident.java b/user/src/com/google/gwt/dom/client/DOMImplTrident.java
new file mode 100644
index 0000000..e51398b
--- /dev/null
+++ b/user/src/com/google/gwt/dom/client/DOMImplTrident.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dom.client;
+
+abstract class DOMImplTrident extends DOMImpl {
+
+ /**
+ * This field *must* be filled in from JSNI code before dispatching an event
+ * on IE. It should be set to the 'this' context of the handler that receives
+ * the event, then restored to its initial value when the dispatcher is done.
+ * See {@link com.google.gwt.user.client.impl.DOMImplTrident#initEventSystem()}
+ * for an example of how this should be done.
+ */
+ private static EventTarget currentEventTarget;
+
+ @Override
+ public native NativeEvent createHtmlEvent(Document doc, String type, boolean canBubble,
+ boolean cancelable) /*-{
+ // NOTE: IE doesn't support changing bubbling and canceling behavior (this
+ // is documented publicly in Document.createHtmlEvent()).
+ var evt = doc.createEventObject();
+ evt.type = type;
+ return evt;
+ }-*/;
+
+ @Override
+ public native InputElement createInputRadioElement(Document doc, String name) /*-{
+ return doc.createElement("<INPUT type='RADIO' name='" + name + "'>");
+ }-*/;
+
+ @Override
+ public native NativeEvent createKeyEvent(Document doc, String type, boolean canBubble,
+ boolean cancelable, boolean ctrlKey, boolean altKey, boolean shiftKey,
+ boolean metaKey, int keyCode, int charCode) /*-{
+ // NOTE: IE doesn't support changing bubbling and canceling behavior (this
+ // is documented publicly in Document.createKeyEvent()).
+ var evt = doc.createEventObject();
+ evt.type = type;
+ evt.ctrlKey = ctrlKey;
+ evt.altKey = altKey;
+ evt.shiftKey = shiftKey;
+ evt.metaKey = metaKey;
+ evt.keyCode = keyCode;
+ evt.charCode = charCode;
+
+ return evt;
+ }-*/;
+
+ @Override
+ public native NativeEvent createMouseEvent(Document doc, String type, boolean canBubble,
+ boolean cancelable, int detail, int screenX, int screenY, int clientX,
+ int clientY, boolean ctrlKey, boolean altKey, boolean shiftKey,
+ boolean metaKey, int button, Element relatedTarget) /*-{
+ // NOTE: IE doesn't support changing bubbling and canceling behavior (this
+ // is documented publicly in Document.createMouseEvent()).
+ var evt = doc.createEventObject();
+ evt.type = type;
+ evt.detail = detail;
+ evt.screenX = screenX;
+ evt.screenY = screenY;
+ evt.clientX = clientX;
+ evt.clientY = clientY;
+ evt.ctrlKey = ctrlKey;
+ evt.altKey = altKey;
+ evt.shiftKey = shiftKey;
+ evt.metaKey = metaKey;
+ evt.button = button;
+
+ // It would make sense to set evt.[fromElement | toElement] here, because
+ // that's what IE uses. However, setting these properties has no effect for
+ // some reason. So instead we set releatedTarget, and explicitly check for
+ // its existence in eventGetFromElement() and eventGetToElement().
+ evt.relatedTarget = relatedTarget;
+
+ return evt;
+ }-*/;
+
+ /**
+ * Supports creating a select control with the multiple attribute to work
+ * around a bug in IE6 where changing the multiple attribute in a setAttribute
+ * call can cause subsequent setSelected calls to misbehave. Although this bug
+ * is fixed in IE7, this DOMImpl specialization is used for both IE6 and IE7,
+ * but it should be harmless.
+ */
+ @Override
+ public native SelectElement createSelectElement(Document doc, boolean multiple) /*-{
+ var html = multiple ? "<SELECT MULTIPLE>" : "<SELECT>";
+ return doc.createElement(html);
+ }-*/;
+
+ public native void dispatchEvent(Element target, NativeEvent evt) /*-{
+ target.fireEvent("on" + evt.type, evt);
+ }-*/;
+
+ @Override
+ public EventTarget eventGetCurrentTarget(NativeEvent event) {
+ return currentEventTarget;
+ }
+
+ @Override
+ public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
+ return Math.round(-evt.wheelDelta / 40) || 0;
+ }-*/;
+
+ @Override
+ public native EventTarget eventGetRelatedTarget(NativeEvent evt) /*-{
+ // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
+ // explicitly sets relatedTarget when synthesizing mouse events).
+ return evt.relatedTarget ||
+ (evt.type == "mouseout" ? evt.toElement:evt.fromElement);
+ }-*/;
+
+ @Override
+ public native EventTarget eventGetTarget(NativeEvent evt) /*-{
+ return evt.srcElement;
+ }-*/;
+
+ @Override
+ public native void eventPreventDefault(NativeEvent evt) /*-{
+ evt.returnValue = false;
+ }-*/;
+
+ @Override
+ public native void eventStopPropagation(NativeEvent evt) /*-{
+ evt.cancelBubble = true;
+ }-*/;
+
+ @Override
+ public native String eventToString(NativeEvent evt) /*-{
+ if (evt.toString) return evt.toString();
+ return "[event" + evt.type + "]";
+ }-*/;
+
+ @Override
+ public int getAbsoluteLeft(Element elem) {
+ return getBoundingClientRectLeft(elem);
+ }
+
+ @Override
+ public int getAbsoluteTop(Element elem) {
+ return getBoundingClientRectTop(elem);
+ }
+
+ /**
+ * IE returns a numeric type for some attributes that are really properties,
+ * such as offsetWidth. We need to coerce these to strings to prevent a
+ * runtime JS exception.
+ */
+ @Override
+ public native String getAttribute(Element elem, String name) /*-{
+ var attr = elem.getAttribute(name);
+ return attr == null ? '' : attr + '';
+ }-*/;
+
+ @Override
+ public int getBodyOffsetLeft(Document doc) {
+ return getClientLeft(doc.getViewportElement());
+ }
+
+ @Override
+ public int getBodyOffsetTop(Document doc) {
+ return getClientTop(doc.getViewportElement());
+ }
+
+ @Override
+ public native String getInnerText(Element elem) /*-{
+ return elem.innerText;
+ }-*/;
+
+ @Override
+ public native Element getParentElement(Element elem) /*-{
+ return elem.parentElement;
+ }-*/;
+
+ @Override
+ public int getScrollLeft(Element elem) {
+ if (isRTL(elem)) {
+ // IE8 returns increasingly *positive* values as you scroll left in RTL.
+ return -super.getScrollLeft(elem);
+ }
+ return super.getScrollLeft(elem);
+ }
+
+ @Override
+ public native boolean isOrHasChild(Element parent, Element child) /*-{
+ // An extra equality check is required due to the fact that
+ // elem.contains(elem) is false if elem is not attached to the DOM.
+ return (parent === child) || parent.contains(child);
+ }-*/;
+
+ @Override
+ public native void selectAdd(SelectElement select, OptionElement option,
+ OptionElement before) /*-{
+ // IE only accepts indices for the second argument.
+ if (before) {
+ select.add(option, before.index);
+ } else {
+ select.add(option);
+ }
+ }-*/;
+
+ @Override
+ public native void setInnerText(Element elem, String text) /*-{
+ elem.innerText = text || '';
+ }-*/;
+
+ @Override
+ public void setScrollLeft(Element elem, int left) {
+ if (isRTL(elem)) {
+ // IE8 returns increasingly *positive* values as you scroll left in RTL.
+ left = -left;
+ }
+ super.setScrollLeft(elem, left);
+ }
+
+ private native int 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
+ try {
+ return elem.getBoundingClientRect().left;
+ } catch (e) {
+ return 0;
+ }
+ }-*/;
+
+ private native int getBoundingClientRectTop(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
+ try {
+ return elem.getBoundingClientRect().top;
+ } catch (e) {
+ return 0;
+ }
+ }-*/;
+
+ /**
+ * clientLeft is non-standard and not implemented on all browsers.
+ */
+ private native int getClientLeft(Element elem) /*-{
+ return elem.clientLeft;
+ }-*/;
+
+ /**
+ * clientTop is non-standard and not implemented on all browsers.
+ */
+ private native int getClientTop(Element elem) /*-{
+ return elem.clientTop;
+ }-*/;
+
+ protected native boolean isRTL(Element elem) /*-{
+ return elem.currentStyle.direction == 'rtl';
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/dom/client/Element.java b/user/src/com/google/gwt/dom/client/Element.java
index 4745c28..ab15aaa 100644
--- a/user/src/com/google/gwt/dom/client/Element.java
+++ b/user/src/com/google/gwt/dom/client/Element.java
@@ -516,4 +516,15 @@
// on some browsers.
this.title = title || '';
}-*/;
+
+ /**
+ * Determines whether an element has an attribute with a given name.
+ *
+ * @param name the name of the attribute
+ * @return whether this element has the specified attribute
+ */
+ public final boolean hasAttribute(String name) {
+ String value = this.getAttribute(name);
+ return value != null && value.length() > 0;
+ }
}
diff --git a/user/src/com/google/gwt/user/ClippedImage.gwt.xml b/user/src/com/google/gwt/user/ClippedImage.gwt.xml
index d333d77..5a58532 100644
--- a/user/src/com/google/gwt/user/ClippedImage.gwt.xml
+++ b/user/src/com/google/gwt/user/ClippedImage.gwt.xml
@@ -27,7 +27,7 @@
<inherits name="com.google.gwt.core.Core" />
<inherits name="com.google.gwt.user.UserAgent" />
- <!-- IE needs a different implementation -->
+ <!-- IE6 needs a different implementation. IE8 does not. -->
<replace-with
class="com.google.gwt.user.client.ui.impl.ClippedImageImplIE6">
<when-type-is
diff --git a/user/src/com/google/gwt/user/DOM.gwt.xml b/user/src/com/google/gwt/user/DOM.gwt.xml
index 936c6e3..110d6e0 100644
--- a/user/src/com/google/gwt/user/DOM.gwt.xml
+++ b/user/src/com/google/gwt/user/DOM.gwt.xml
@@ -31,6 +31,11 @@
<when-property-is name="user.agent" value="safari"/>
</replace-with>
+ <replace-with class="com.google.gwt.user.client.impl.DOMImplIE8">
+ <when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </replace-with>
+
<replace-with class="com.google.gwt.user.client.impl.DOMImplIE6">
<when-type-is class="com.google.gwt.user.client.impl.DOMImpl"/>
<when-property-is name="user.agent" value="ie6"/>
diff --git a/user/src/com/google/gwt/user/Focus.gwt.xml b/user/src/com/google/gwt/user/Focus.gwt.xml
index 9c591a8..f3f83f2 100644
--- a/user/src/com/google/gwt/user/Focus.gwt.xml
+++ b/user/src/com/google/gwt/user/Focus.gwt.xml
@@ -17,29 +17,29 @@
<!-- This module is typically inherited via com.google.gwt.user.User -->
<!-- -->
<module>
- <inherits name="com.google.gwt.core.Core"/>
- <inherits name="com.google.gwt.user.UserAgent"/>
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name="com.google.gwt.user.UserAgent"/>
- <!-- old Mozilla needs a different implementation -->
- <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplOld">
- <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
- <any>
- <when-property-is name="user.agent" value="gecko"/>
- </any>
- </replace-with>
+ <!-- old Mozilla needs a different implementation -->
+ <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplOld">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
+ <any>
+ <when-property-is name="user.agent" value="gecko"/>
+ </any>
+ </replace-with>
- <!-- Safari needs a different hidden input -->
- <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplSafari">
- <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
- <when-property-is name="user.agent" value="safari"/>
- </replace-with>
+ <!-- Safari needs a different hidden input -->
+ <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplSafari">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
+ <when-property-is name="user.agent" value="safari"/>
+ </replace-with>
- <!-- IE's implementation traps exceptions on invalid setFocus() -->
- <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplIE6">
- <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
- <any>
- <when-property-is name="user.agent" value="ie6"/>
- </any>
- </replace-with>
-
+ <!-- IE's implementation traps exceptions on invalid setFocus() -->
+ <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplIE6">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
+ </replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/Form.gwt.xml b/user/src/com/google/gwt/user/Form.gwt.xml
index 0db301e..c02bfb8 100644
--- a/user/src/com/google/gwt/user/Form.gwt.xml
+++ b/user/src/com/google/gwt/user/Form.gwt.xml
@@ -17,16 +17,19 @@
<!-- This module is typically inherited via com.google.gwt.user.User. -->
<!-- -->
<module>
- <inherits name="com.google.gwt.core.Core"/>
- <inherits name="com.google.gwt.user.UserAgent"/>
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name="com.google.gwt.user.UserAgent"/>
- <!-- Fall through to this rule for everything but IE -->
- <replace-with class="com.google.gwt.user.client.ui.impl.FormPanelImpl">
- <when-type-is class="com.google.gwt.user.client.ui.impl.FormPanelImpl"/>
- </replace-with>
+ <!-- Fall through to this rule for everything but IE -->
+ <replace-with class="com.google.gwt.user.client.ui.impl.FormPanelImpl">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.FormPanelImpl"/>
+ </replace-with>
- <replace-with class="com.google.gwt.user.client.ui.impl.FormPanelImplIE6">
- <when-type-is class="com.google.gwt.user.client.ui.impl.FormPanelImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
- </replace-with>
+ <replace-with class="com.google.gwt.user.client.ui.impl.FormPanelImplIE6">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.FormPanelImpl"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
+ </replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/History.gwt.xml b/user/src/com/google/gwt/user/History.gwt.xml
index a6bfaec..bad06a1 100644
--- a/user/src/com/google/gwt/user/History.gwt.xml
+++ b/user/src/com/google/gwt/user/History.gwt.xml
@@ -20,11 +20,6 @@
<inherits name="com.google.gwt.core.Core"/>
<inherits name="com.google.gwt.user.UserAgent"/>
- <!-- Fall through to this rule for all other browsers. -->
- <replace-with class="com.google.gwt.user.client.impl.HistoryImplStandard">
- <when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
- </replace-with>
-
<!-- Mozilla has a slightly different history implementation than the -->
<!-- standard case. -->
<replace-with class="com.google.gwt.user.client.impl.HistoryImplMozilla">
@@ -35,15 +30,16 @@
</any>
</replace-with>
- <!-- IE has a completely different history implementation. -->
- <replace-with class="com.google.gwt.user.client.impl.HistoryImplIE6">
- <when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
- </replace-with>
-
- <!-- Safari has yet another history implementation. -->
+ <!-- Safari has yet another slightly different implementation. -->
<replace-with class="com.google.gwt.user.client.impl.HistoryImplSafari">
<when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
<when-property-is name="user.agent" value="safari"/>
</replace-with>
+
+ <!-- IE6 has a completely different history implementation. IE8 used the -->
+ <!-- standard implementation. -->
+ <replace-with class="com.google.gwt.user.client.impl.HistoryImplIE6">
+ <when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
+ <when-property-is name="user.agent" value="ie6"/>
+ </replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/Hyperlink.gwt.xml b/user/src/com/google/gwt/user/Hyperlink.gwt.xml
index e667c13..787fbc7 100644
--- a/user/src/com/google/gwt/user/Hyperlink.gwt.xml
+++ b/user/src/com/google/gwt/user/Hyperlink.gwt.xml
@@ -14,6 +14,9 @@
<replace-with class="com.google.gwt.user.client.ui.impl.HyperlinkImplIE">
<when-type-is class="com.google.gwt.user.client.ui.impl.HyperlinkImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
</replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/Popup.gwt.xml b/user/src/com/google/gwt/user/Popup.gwt.xml
index b5d06bf..ee886c8 100644
--- a/user/src/com/google/gwt/user/Popup.gwt.xml
+++ b/user/src/com/google/gwt/user/Popup.gwt.xml
@@ -20,11 +20,6 @@
<inherits name="com.google.gwt.core.Core"/>
<inherits name="com.google.gwt.user.UserAgent"/>
- <!-- Fall through to this rule is the browser isn't IE or Mozilla -->
- <replace-with class="com.google.gwt.user.client.ui.impl.PopupImpl">
- <when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl"/>
- </replace-with>
-
<!-- Mozilla needs a different implementation due to issue #410 -->
<replace-with class="com.google.gwt.user.client.ui.impl.PopupImplMozilla">
<when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl"/>
@@ -33,8 +28,9 @@
<when-property-is name="user.agent" value="gecko1_8"/>
</any>
</replace-with>
-
- <!-- IE has a completely different popup implementation -->
+
+ <!-- IE6 has a completely different popup implementation. It is no longer -->
+ <!-- necessary on IE8. -->
<replace-with class="com.google.gwt.user.client.ui.impl.PopupImplIE6">
<when-type-is class="com.google.gwt.user.client.ui.impl.PopupImpl"/>
<when-property-is name="user.agent" value="ie6"/>
diff --git a/user/src/com/google/gwt/user/RichText.gwt.xml b/user/src/com/google/gwt/user/RichText.gwt.xml
index ff2fb56..76dba69 100644
--- a/user/src/com/google/gwt/user/RichText.gwt.xml
+++ b/user/src/com/google/gwt/user/RichText.gwt.xml
@@ -15,45 +15,48 @@
<!-- Deferred binding rules for browser selection. -->
<!-- -->
<module>
- <inherits name="com.google.gwt.core.Core" />
- <inherits name="com.google.gwt.user.UserAgent" />
+ <inherits name="com.google.gwt.core.Core" />
+ <inherits name="com.google.gwt.user.UserAgent" />
- <!-- IE-specific implementation -->
- <replace-with
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImplIE6">
- <when-type-is
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
- <when-property-is name="user.agent" value="ie6" />
- </replace-with>
+ <!-- IE-specific implementation -->
+ <replace-with
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImplIE6">
+ <when-type-is
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
+ <any>
+ <when-property-is name="user.agent" value="ie6" />
+ <when-property-is name="user.agent" value="ie8" />
+ </any>
+ </replace-with>
- <!-- Mozilla-specific implementation -->
- <replace-with
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImplMozilla">
- <when-type-is
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
- <any>
- <when-property-is name="user.agent" value="gecko1_8" />
- <when-property-is name="user.agent" value="gecko" />
- </any>
- </replace-with>
+ <!-- Mozilla-specific implementation -->
+ <replace-with
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImplMozilla">
+ <when-type-is
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
+ <any>
+ <when-property-is name="user.agent" value="gecko1_8" />
+ <when-property-is name="user.agent" value="gecko" />
+ </any>
+ </replace-with>
- <!-- Safari-specific implementation -->
- <replace-with
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImplSafari">
- <when-type-is
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
- <any>
- <when-property-is name="user.agent" value="safari" />
- </any>
- </replace-with>
+ <!-- Safari-specific implementation -->
+ <replace-with
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImplSafari">
+ <when-type-is
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
+ <any>
+ <when-property-is name="user.agent" value="safari" />
+ </any>
+ </replace-with>
- <!-- Opera-specific implementation -->
- <replace-with
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImplOpera">
- <when-type-is
- class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
- <any>
- <when-property-is name="user.agent" value="opera" />
- </any>
- </replace-with>
+ <!-- Opera-specific implementation -->
+ <replace-with
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImplOpera">
+ <when-type-is
+ class="com.google.gwt.user.client.ui.impl.RichTextAreaImpl" />
+ <any>
+ <when-property-is name="user.agent" value="opera" />
+ </any>
+ </replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/SplitPanel.gwt.xml b/user/src/com/google/gwt/user/SplitPanel.gwt.xml
index a0bb8db..9e09bcc 100644
--- a/user/src/com/google/gwt/user/SplitPanel.gwt.xml
+++ b/user/src/com/google/gwt/user/SplitPanel.gwt.xml
@@ -22,7 +22,10 @@
<replace-with class="com.google.gwt.user.client.ui.HorizontalSplitPanel.ImplIE6">
<when-type-is class="com.google.gwt.user.client.ui.HorizontalSplitPanel.Impl"/>
- <when-property-is name="user.agent" value="ie6"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
</replace-with>
<replace-with class="com.google.gwt.user.client.ui.HorizontalSplitPanel.ImplSafari">
@@ -36,7 +39,9 @@
<replace-with class="com.google.gwt.user.client.ui.VerticalSplitPanel.ImplIE6">
<when-type-is class="com.google.gwt.user.client.ui.VerticalSplitPanel.Impl"/>
- <when-property-is name="user.agent" value="ie6"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
</replace-with>
-
</module>
diff --git a/user/src/com/google/gwt/user/TextBox.gwt.xml b/user/src/com/google/gwt/user/TextBox.gwt.xml
index 1b27b62..fc99c19 100644
--- a/user/src/com/google/gwt/user/TextBox.gwt.xml
+++ b/user/src/com/google/gwt/user/TextBox.gwt.xml
@@ -17,17 +17,20 @@
<!-- This module is typically inherited via com.google.gwt.user.User -->
<!-- -->
<module>
- <inherits name="com.google.gwt.core.Core"/>
- <inherits name="com.google.gwt.user.UserAgent"/>
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name="com.google.gwt.user.UserAgent"/>
- <!-- Fall through to this rule is the browser isn't IE -->
- <replace-with class="com.google.gwt.user.client.ui.impl.TextBoxImpl">
- <when-type-is class="com.google.gwt.user.client.ui.impl.TextBoxImpl"/>
- </replace-with>
+ <!-- Fall through to this rule is the browser isn't IE -->
+ <replace-with class="com.google.gwt.user.client.ui.impl.TextBoxImpl">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.TextBoxImpl"/>
+ </replace-with>
- <!-- IE has a completely different TextBox implementation -->
- <replace-with class="com.google.gwt.user.client.ui.impl.TextBoxImplIE6">
- <when-type-is class="com.google.gwt.user.client.ui.impl.TextBoxImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
- </replace-with>
+ <!-- IE has a completely different TextBox implementation -->
+ <replace-with class="com.google.gwt.user.client.ui.impl.TextBoxImplIE6">
+ <when-type-is class="com.google.gwt.user.client.ui.impl.TextBoxImpl"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
+ </replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/Tree.gwt.xml b/user/src/com/google/gwt/user/Tree.gwt.xml
index 626f52e..94b14e5 100644
--- a/user/src/com/google/gwt/user/Tree.gwt.xml
+++ b/user/src/com/google/gwt/user/Tree.gwt.xml
@@ -20,6 +20,9 @@
<!-- IE-specific implementation -->
<replace-with class="com.google.gwt.user.client.ui.TreeItem.TreeItemImplIE6">
<when-type-is class="com.google.gwt.user.client.ui.TreeItem.TreeItemImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
</replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/UserAgent.gwt.xml b/user/src/com/google/gwt/user/UserAgent.gwt.xml
index d073cd7..af299b3 100644
--- a/user/src/com/google/gwt/user/UserAgent.gwt.xml
+++ b/user/src/com/google/gwt/user/UserAgent.gwt.xml
@@ -19,12 +19,12 @@
<module>
<!-- Browser-sensitive code should use the 'user.agent' property -->
- <define-property name="user.agent" values="ie6,gecko,gecko1_8,safari,opera"/>
+ <define-property name="user.agent" values="ie6,ie8,gecko,gecko1_8,safari,opera"/>
<property-provider name="user.agent"><![CDATA[
var ua = navigator.userAgent.toLowerCase();
var makeVersion = function(result) {
- return (parseInt(result[1]) * 1000) + parseInt(result[2]);
+ return (parseInt(result[1]) * 1000) + parseInt(result[2]);
};
if (ua.indexOf("opera") != -1) {
@@ -32,10 +32,15 @@
} else if (ua.indexOf("webkit") != -1) {
return "safari";
} else if (ua.indexOf("msie") != -1) {
- var result = /msie ([0-9]+)\.([0-9]+)/.exec(ua);
- if (result && result.length == 3) {
- if (makeVersion(result) >= 6000) {
- return "ie6";
+ if (document.documentMode >= 8) {
+ return "ie8";
+ } else {
+ var result = /msie ([0-9]+)\.([0-9]+)/.exec(ua);
+ if (result && result.length == 3) {
+ var v = makeVersion(result);
+ if (v >= 6000) {
+ return "ie6";
+ }
}
}
} else if (ua.indexOf("gecko") != -1) {
diff --git a/user/src/com/google/gwt/user/Window.gwt.xml b/user/src/com/google/gwt/user/Window.gwt.xml
index 9511634..8ae46ce 100644
--- a/user/src/com/google/gwt/user/Window.gwt.xml
+++ b/user/src/com/google/gwt/user/Window.gwt.xml
@@ -22,6 +22,9 @@
<replace-with class="com.google.gwt.user.client.impl.WindowImplIE">
<when-type-is class="com.google.gwt.user.client.impl.WindowImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
</replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
index 3ce49bd..d71460d 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
@@ -15,202 +15,9 @@
*/
package com.google.gwt.user.client.impl;
-import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
-
/**
* Internet Explorer 6 implementation of
* {@link com.google.gwt.user.client.impl.DOMImpl}.
*/
-class DOMImplIE6 extends DOMImpl {
-
- @SuppressWarnings("unused")
- private static JavaScriptObject dispatchEvent;
-
- @SuppressWarnings("unused")
- private static JavaScriptObject dispatchDblClickEvent;
-
- @Override
- public native Element eventGetFromElement(Event evt) /*-{
- // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
- // explicitly sets relatedTarget when synthesizing mouse events).
- return evt.relatedTarget || evt.fromElement;
- }-*/;
-
- @Override
- public native Element eventGetToElement(Event evt) /*-{
- // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
- // explicitly sets relatedTarget when synthesizing mouse events).
- return evt.relatedTarget || evt.toElement;
- }-*/;
-
- @Override
- public native Element getChild(Element elem, int index) /*-{
- return elem.children[index];
- }-*/;
-
- @Override
- public native int getChildCount(Element elem) /*-{
- return elem.children.length;
- }-*/;
-
- @Override
- public native int getChildIndex(Element parent, Element child) /*-{
- var count = parent.children.length;
- for (var i = 0; i < count; ++i) {
- if (child === parent.children[i]) {
- return i;
- }
- }
- return -1;
- }-*/;
-
- @Override
- public native void initEventSystem() /*-{
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent = function() {
- // IE doesn't define event.currentTarget, so we squirrel it away here. It
- // also seems that IE won't allow you to add expandos to the event object,
- // so we have to store it in a global. This is ok because only one event
- // can actually be dispatched at a time.
- var oldEventTarget = @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget;
- @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget = this;
-
- if ($wnd.event.returnValue == null) {
- $wnd.event.returnValue = true;
- if (!@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event)) {
- @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget = oldEventTarget;
- return;
- }
- }
-
- var listener, curElem = this;
- while (curElem && !(listener = curElem.__listener)) {
- curElem = curElem.parentElement;
- }
-
- if (listener) {
- if (@com.google.gwt.user.client.impl.DOMImpl::isMyListener(Ljava/lang/Object;)(listener)) {
- @com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/user/client/Element;Lcom/google/gwt/user/client/EventListener;)($wnd.event, curElem, listener);
- }
- }
-
- @com.google.gwt.dom.client.DOMImplIE6::currentEventTarget = oldEventTarget;
- };
-
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchDblClickEvent = function() {
- var newEvent = $doc.createEventObject();
- // Synthesize a click event if one hasn't already been synthesized.
- if ($wnd.event.returnValue == null) {
- $wnd.event.srcElement.fireEvent('onclick', newEvent);
- }
- if (this.__eventBits & 2) {
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent.call(this);
- } else if ($wnd.event.returnValue == null) {
- // Ensure that we preview the event even if we aren't handling it.
- $wnd.event.returnValue = true;
- @com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event);
- }
- };
-
- // We need to create these delegate functions to fix up the 'this' context.
- // Normally, 'this' is the firing element, but this is only true for
- // 'onclick = ...' event handlers, not for handlers setup via attachEvent().
- var bodyDispatcher = function() { @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent.call($doc.body); };
- var bodyDblClickDispatcher = function() { @com.google.gwt.user.client.impl.DOMImplIE6::dispatchDblClickEvent.call($doc.body); };
-
- $doc.body.attachEvent('onclick', bodyDispatcher);
- $doc.body.attachEvent('onmousedown', bodyDispatcher);
- $doc.body.attachEvent('onmouseup', bodyDispatcher);
- $doc.body.attachEvent('onmousemove', bodyDispatcher);
- $doc.body.attachEvent('onmousewheel', bodyDispatcher);
- $doc.body.attachEvent('onkeydown', bodyDispatcher);
- $doc.body.attachEvent('onkeypress', bodyDispatcher);
- $doc.body.attachEvent('onkeyup', bodyDispatcher);
- $doc.body.attachEvent('onfocus', bodyDispatcher);
- $doc.body.attachEvent('onblur', bodyDispatcher);
- $doc.body.attachEvent('ondblclick', bodyDblClickDispatcher);
- $doc.body.attachEvent('oncontextmenu', bodyDispatcher);
- }-*/;
-
- @Override
- public native void insertChild(Element parent, Element child, int index) /*-{
- if (index >= parent.children.length)
- parent.appendChild(child);
- else
- parent.insertBefore(child, parent.children[index]);
- }-*/;
-
- @Override
- public void releaseCapture(Element elem) {
- maybeInitializeEventSystem();
- releaseCaptureImpl(elem);
- }
-
- @Override
- public void setCapture(Element elem) {
- maybeInitializeEventSystem();
- setCaptureImpl(elem);
- }
-
- @Override
- public void sinkEvents(Element elem, int bits) {
- maybeInitializeEventSystem();
- sinkEventsImpl(elem, bits);
- }
-
- private native void releaseCaptureImpl(Element elem) /*-{
- elem.releaseCapture();
- }-*/;
-
- private native void setCaptureImpl(Element elem) /*-{
- elem.setCapture();
- }-*/;
-
- private native void sinkEventsImpl(Element elem, int bits) /*-{
- var chMask = (elem.__eventBits || 0) ^ bits;
- elem.__eventBits = bits;
- if (!chMask) return;
-
- if (chMask & 0x00001) elem.onclick = (bits & 0x00001) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- // Add a ondblclick handler if onclick is desired to ensure that
- // a user's double click will result in two onclick events.
- if (chMask & (0x00003)) elem.ondblclick = (bits & (0x00003)) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchDblClickEvent : null;
- if (chMask & 0x00004) elem.onmousedown = (bits & 0x00004) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00008) elem.onmouseup = (bits & 0x00008) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00010) elem.onmouseover = (bits & 0x00010) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00020) elem.onmouseout = (bits & 0x00020) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00040) elem.onmousemove = (bits & 0x00040) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00080) elem.onkeydown = (bits & 0x00080) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00100) elem.onkeypress = (bits & 0x00100) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00200) elem.onkeyup = (bits & 0x00200) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00400) elem.onchange = (bits & 0x00400) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x00800) elem.onfocus = (bits & 0x00800) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x01000) elem.onblur = (bits & 0x01000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x02000) elem.onlosecapture = (bits & 0x02000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x04000) elem.onscroll = (bits & 0x04000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x08000) elem.onload = (bits & 0x08000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x10000) elem.onerror = (bits & 0x10000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x20000) elem.onmousewheel = (bits & 0x20000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- if (chMask & 0x40000) elem.oncontextmenu = (bits & 0x40000) ?
- @com.google.gwt.user.client.impl.DOMImplIE6::dispatchEvent : null;
- }-*/;
+class DOMImplIE6 extends DOMImplTrident {
}
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplIE8.java b/user/src/com/google/gwt/user/client/impl/DOMImplIE8.java
new file mode 100644
index 0000000..e8ea7b8
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplIE8.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.impl;
+
+public class DOMImplIE8 extends DOMImplTrident {
+}
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplTrident.java b/user/src/com/google/gwt/user/client/impl/DOMImplTrident.java
new file mode 100644
index 0000000..4923ff5
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplTrident.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.impl;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+
+public abstract class DOMImplTrident extends DOMImpl {
+
+ @SuppressWarnings("unused")
+ private static JavaScriptObject dispatchEvent;
+
+ @SuppressWarnings("unused")
+ private static JavaScriptObject dispatchDblClickEvent;
+
+ @Override
+ public native Element eventGetFromElement(Event evt) /*-{
+ // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
+ // explicitly sets relatedTarget when synthesizing mouse events).
+ return evt.relatedTarget || evt.fromElement;
+ }-*/;
+
+ @Override
+ public native Element eventGetToElement(Event evt) /*-{
+ // Prefer 'relatedTarget' if it's set (see createMouseEvent(), which
+ // explicitly sets relatedTarget when synthesizing mouse events).
+ return evt.relatedTarget || evt.toElement;
+ }-*/;
+
+ @Override
+ public native Element getChild(Element elem, int index) /*-{
+ return elem.children[index];
+ }-*/;
+
+ @Override
+ public native int getChildCount(Element elem) /*-{
+ return elem.children.length;
+ }-*/;
+
+ @Override
+ public native int getChildIndex(Element parent, Element child) /*-{
+ var count = parent.children.length;
+ for (var i = 0; i < count; ++i) {
+ if (child === parent.children[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }-*/;
+
+ @Override
+ public native void initEventSystem() /*-{
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent = function() {
+ // IE doesn't define event.currentTarget, so we squirrel it away here. It
+ // also seems that IE won't allow you to add expandos to the event object,
+ // so we have to store it in a global. This is ok because only one event
+ // can actually be dispatched at a time.
+ var oldEventTarget = @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget;
+ @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = this;
+
+ if ($wnd.event.returnValue == null) {
+ $wnd.event.returnValue = true;
+ if (!@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event)) {
+ @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = oldEventTarget;
+ return;
+ }
+ }
+
+ var listener, curElem = this;
+ while (curElem && !(listener = curElem.__listener)) {
+ curElem = curElem.parentElement;
+ }
+
+ if (listener) {
+ if (@com.google.gwt.user.client.impl.DOMImpl::isMyListener(Ljava/lang/Object;)(listener)) {
+ @com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/user/client/Element;Lcom/google/gwt/user/client/EventListener;)($wnd.event, curElem, listener);
+ }
+ }
+
+ @com.google.gwt.dom.client.DOMImplTrident::currentEventTarget = oldEventTarget;
+ };
+
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchDblClickEvent = function() {
+ var newEvent = $doc.createEventObject();
+ // Synthesize a click event if one hasn't already been synthesized.
+ if ($wnd.event.returnValue == null) {
+ $wnd.event.srcElement.fireEvent('onclick', newEvent);
+ }
+ if (this.__eventBits & 2) {
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent.call(this);
+ } else if ($wnd.event.returnValue == null) {
+ // Ensure that we preview the event even if we aren't handling it.
+ $wnd.event.returnValue = true;
+ @com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event);
+ }
+ };
+
+ // We need to create these delegate functions to fix up the 'this' context.
+ // Normally, 'this' is the firing element, but this is only true for
+ // 'onclick = ...' event handlers, not for handlers setup via attachEvent().
+ var bodyDispatcher = function() { @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent.call($doc.body); };
+ var bodyDblClickDispatcher = function() { @com.google.gwt.user.client.impl.DOMImplTrident::dispatchDblClickEvent.call($doc.body); };
+
+ $doc.body.attachEvent('onclick', bodyDispatcher);
+ $doc.body.attachEvent('onmousedown', bodyDispatcher);
+ $doc.body.attachEvent('onmouseup', bodyDispatcher);
+ $doc.body.attachEvent('onmousemove', bodyDispatcher);
+ $doc.body.attachEvent('onmousewheel', bodyDispatcher);
+ $doc.body.attachEvent('onkeydown', bodyDispatcher);
+ $doc.body.attachEvent('onkeypress', bodyDispatcher);
+ $doc.body.attachEvent('onkeyup', bodyDispatcher);
+ $doc.body.attachEvent('onfocus', bodyDispatcher);
+ $doc.body.attachEvent('onblur', bodyDispatcher);
+ $doc.body.attachEvent('ondblclick', bodyDblClickDispatcher);
+ $doc.body.attachEvent('oncontextmenu', bodyDispatcher);
+ }-*/;
+
+ @Override
+ public native void insertChild(Element parent, Element child, int index) /*-{
+ if (index >= parent.children.length)
+ parent.appendChild(child);
+ else
+ parent.insertBefore(child, parent.children[index]);
+ }-*/;
+
+ @Override
+ public void releaseCapture(Element elem) {
+ maybeInitializeEventSystem();
+ releaseCaptureImpl(elem);
+ }
+
+ @Override
+ public void setCapture(Element elem) {
+ maybeInitializeEventSystem();
+ setCaptureImpl(elem);
+ }
+
+ @Override
+ public void sinkEvents(Element elem, int bits) {
+ maybeInitializeEventSystem();
+ sinkEventsImpl(elem, bits);
+ }
+
+ private native void releaseCaptureImpl(Element elem) /*-{
+ elem.releaseCapture();
+ }-*/;
+
+ private native void setCaptureImpl(Element elem) /*-{
+ elem.setCapture();
+ }-*/;
+
+ private native void sinkEventsImpl(Element elem, int bits) /*-{
+ var chMask = (elem.__eventBits || 0) ^ bits;
+ elem.__eventBits = bits;
+ if (!chMask) return;
+
+ if (chMask & 0x00001) elem.onclick = (bits & 0x00001) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ // Add a ondblclick handler if onclick is desired to ensure that
+ // a user's double click will result in two onclick events.
+ if (chMask & (0x00003)) elem.ondblclick = (bits & (0x00003)) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchDblClickEvent : null;
+ if (chMask & 0x00004) elem.onmousedown = (bits & 0x00004) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00008) elem.onmouseup = (bits & 0x00008) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00010) elem.onmouseover = (bits & 0x00010) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00020) elem.onmouseout = (bits & 0x00020) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00040) elem.onmousemove = (bits & 0x00040) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00080) elem.onkeydown = (bits & 0x00080) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00100) elem.onkeypress = (bits & 0x00100) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00200) elem.onkeyup = (bits & 0x00200) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00400) elem.onchange = (bits & 0x00400) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x00800) elem.onfocus = (bits & 0x00800) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x01000) elem.onblur = (bits & 0x01000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x02000) elem.onlosecapture = (bits & 0x02000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x04000) elem.onscroll = (bits & 0x04000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x08000) elem.onload = (bits & 0x08000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x10000) elem.onerror = (bits & 0x10000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x20000) elem.onmousewheel = (bits & 0x20000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ if (chMask & 0x40000) elem.oncontextmenu = (bits & 0x40000) ?
+ @com.google.gwt.user.client.impl.DOMImplTrident::dispatchEvent : null;
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
index b4a05d6..57c9f59 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
@@ -28,10 +28,14 @@
/**
* Native implementation associated with
* {@link com.google.gwt.user.client.History}.
- *
* User classes should not use this class directly.
+ *
+ * <p>
+ * This base version uses the HTML5 standard window.onhashchange event to
+ * determine when the URL hash identifier changes.
+ * </p>
*/
-public abstract class HistoryImpl implements HasValueChangeHandlers<String>,
+public class HistoryImpl implements HasValueChangeHandlers<String>,
HasHandlers {
public static native String getToken() /*-{
@@ -70,7 +74,29 @@
return handlers;
}
- public abstract boolean init();
+ public native boolean init() /*-{
+ var token = '';
+
+ // Get the initial token from the url's hash component.
+ var hash = $wnd.location.hash;
+ if (hash.length > 0) {
+ token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
+ }
+
+ @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
+
+ var historyImpl = this;
+ $wnd.onhashchange = function() {
+ var token = '', hash = $wnd.location.hash;
+ if (hash.length > 0) {
+ token = historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
+ }
+
+ historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token);
+ };
+
+ return true;
+ }-*/;
public final void newItem(String historyToken, boolean issueEvent) {
historyToken = (historyToken == null) ? "" : historyToken;
@@ -102,9 +128,17 @@
return encodeURI(fragment).replace("#", "%23");
}-*/;
- protected abstract void nativeUpdate(String historyToken);
+ /**
+ * The standard updateHash implementation assigns to location.hash() with an
+ * encoded history token.
+ */
+ protected native void nativeUpdate(String historyToken) /*-{
+ $wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
+ }-*/;
- protected abstract void nativeUpdateOnEvent(String historyToken);
+ protected void nativeUpdateOnEvent(String historyToken) {
+ // Do nothing, the hash is already updated.
+ }
private void fireHistoryChanged(String newToken) {
UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java b/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
deleted file mode 100644
index 956a978..0000000
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.user.client.impl;
-
-import com.google.gwt.user.client.Element;
-
-/**
- * An IFRAME implementation of
- * {@link com.google.gwt.user.client.impl.HistoryImpl}.
- */
-abstract class HistoryImplFrame extends HistoryImpl {
-
- private static native Element findHistoryFrame() /*-{
- return $doc.getElementById('__gwt_historyFrame');
- }-*/;
-
- private static native Element getTokenElement(Element historyFrame) /*-{
- // Initialize the history iframe. If '__gwt_historyToken' already exists, then
- // we're probably backing into the app, so _don't_ set the iframe's location.
- if (historyFrame.contentWindow) {
- var doc = historyFrame.contentWindow.document;
- return doc.getElementById('__gwt_historyToken');
- }
- }-*/;
-
- protected Element historyFrame;
-
- @Override
- public boolean init() {
- historyFrame = findHistoryFrame();
- if (historyFrame == null) {
- return false;
- }
-
- initHistoryToken();
-
- // Initialize the history iframe. If a token element already exists, then
- // we're probably backing into the app, so _don't_ create a new item.
- Element tokenElement = getTokenElement(historyFrame);
- if (tokenElement != null) {
- setToken(getTokenElementContent(tokenElement));
- } else {
- navigateFrame(getToken());
- }
-
- injectGlobalHandler();
- return true;
- }
-
- protected abstract String getTokenElementContent(Element tokenElement);
-
- protected abstract void initHistoryToken();
-
- protected abstract void injectGlobalHandler();
-
- @Override
- protected final void nativeUpdate(String historyToken) {
- /*
- * Must update the location hash since it isn't already correct.
- */
- updateHash(historyToken);
- navigateFrame(historyToken);
- }
-
- @Override
- protected final void nativeUpdateOnEvent(String historyToken) {
- updateHash(historyToken);
- }
-
- protected abstract void navigateFrame(String historyToken);
-
- protected abstract void updateHash(String historyToken);
-
-}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
index f2e3606..7651454 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
@@ -19,9 +19,10 @@
import com.google.gwt.user.client.Element;
/**
- * Internet Explorer 6 implementation HistoryImplFrame.
+ * History implementation for IE6 and IE7, which do not support the onhashchange
+ * event, and for which {@link HistoryImplTimer} will not work either.
*/
-class HistoryImplIE6 extends HistoryImplFrame {
+class HistoryImplIE6 extends HistoryImpl {
/**
* Sanitizes an untrusted string to be used in an HTML context. NOTE: This
@@ -37,6 +38,10 @@
return DOM.getInnerHTML(div);
}
+ private static native Element findHistoryFrame() /*-{
+ return $doc.getElementById('__gwt_historyFrame');
+ }-*/;
+
/**
* For IE6, reading from $wnd.location.hash drops part of the fragment if the
* fragment contains a '?'. To avoid this bug, we use location.href instead.
@@ -48,22 +53,59 @@
return (hashLoc > 0) ? href.substring(hashLoc) : "";
}-*/;
+ private static native Element getTokenElement(Element historyFrame) /*-{
+ // Initialize the history iframe. If '__gwt_historyToken' already exists, then
+ // we're probably backing into the app, so _don't_ set the iframe's location.
+ if (historyFrame.contentWindow) {
+ var doc = historyFrame.contentWindow.document;
+ return doc.getElementById('__gwt_historyToken');
+ }
+ }-*/;
+
+ protected Element historyFrame;
+
@Override
public boolean init() {
- if (!super.init()) {
+ historyFrame = findHistoryFrame();
+ if (historyFrame == null) {
return false;
}
+
+ initHistoryToken();
+
+ // Initialize the history iframe. If a token element already exists, then
+ // we're probably backing into the app, so _don't_ create a new item.
+ Element tokenElement = getTokenElement(historyFrame);
+ if (tokenElement != null) {
+ setToken(getTokenElementContent(tokenElement));
+ } else {
+ navigateFrame(getToken());
+ }
+
+ injectGlobalHandler();
initUrlCheckTimer();
return true;
}
@Override
- protected native String getTokenElementContent(Element tokenElement) /*-{
+ protected final void nativeUpdate(String historyToken) {
+ /*
+ * Must update the location hash since it isn't already correct.
+ */
+ updateHash(historyToken);
+ navigateFrame(historyToken);
+ }
+
+ @Override
+ protected final void nativeUpdateOnEvent(String historyToken) {
+ updateHash(historyToken);
+ }
+
+ private native String getTokenElementContent(Element tokenElement) /*-{
return tokenElement.innerText;
}-*/;
- @Override
- protected native void initHistoryToken() /*-{
+ private native void initHistoryToken() /*-{
// Assume an empty token.
var token = '';
// Get the initial token from the url's hash component.
@@ -79,29 +121,6 @@
@com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
}-*/;
- @Override
- protected native void injectGlobalHandler() /*-{
- var historyImplRef = this;
-
- $wnd.__gwt_onHistoryLoad = function(token) {
- historyImplRef.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token);
- };
- }-*/;
-
- @Override
- protected native void navigateFrame(String token) /*-{
- var escaped = @com.google.gwt.user.client.impl.HistoryImplIE6::escapeHtml(Ljava/lang/String;)(token);
- var doc = this.@com.google.gwt.user.client.impl.HistoryImplFrame::historyFrame.contentWindow.document;
- doc.open();
- doc.write('<html><body onload="if(parent.__gwt_onHistoryLoad)parent.__gwt_onHistoryLoad(__gwt_historyToken.innerText)"><div id="__gwt_historyToken">' + escaped + '</div></body></html>');
- doc.close();
- }-*/;
-
- @Override
- protected native void updateHash(String token) /*-{
- $wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(token);
- }-*/;
-
private native void initUrlCheckTimer() /*-{
// This is the URL check timer. It detects when an unexpected change
// occurs in the document's URL (e.g. when the user enters one manually
@@ -122,7 +141,7 @@
// if someone entered or linked to a bad url.
$wnd.location.reload();
}
-
+
var historyToken = @com.google.gwt.user.client.impl.HistoryImpl::getToken()();
if (historyToken && (token != historyToken)) {
$wnd.location.reload();
@@ -131,4 +150,24 @@
};
urlChecker();
}-*/;
+
+ private native void injectGlobalHandler() /*-{
+ var historyImplRef = this;
+
+ $wnd.__gwt_onHistoryLoad = function(token) {
+ historyImplRef.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token);
+ };
+ }-*/;
+
+ private native void navigateFrame(String token) /*-{
+ var escaped = @com.google.gwt.user.client.impl.HistoryImplIE6::escapeHtml(Ljava/lang/String;)(token);
+ var doc = this.@com.google.gwt.user.client.impl.HistoryImplIE6::historyFrame.contentWindow.document;
+ doc.open();
+ doc.write('<html><body onload="if(parent.__gwt_onHistoryLoad)parent.__gwt_onHistoryLoad(__gwt_historyToken.innerText)"><div id="__gwt_historyToken">' + escaped + '</div></body></html>');
+ doc.close();
+ }-*/;
+
+ private native void updateHash(String token) /*-{
+ $wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(token);
+ }-*/;
}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java b/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java
index b0b7b3b..6d0da57 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java
@@ -18,8 +18,8 @@
/**
* History implementation for Mozilla-based browsers.
*/
-class HistoryImplMozilla extends HistoryImplStandard {
-
+class HistoryImplMozilla extends HistoryImplTimer {
+
@Override
protected String decodeFragment(String encodedFragment) {
// Mozilla browsers pre-decode the result of location.hash, so there's no
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
index 6986312..d3ffaa0 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
@@ -17,69 +17,15 @@
/**
* Safari implementation of
- * {@link com.google.gwt.user.client.impl.HistoryImplStandard}.
+ * {@link com.google.gwt.user.client.impl.HistoryImplTimer}.
*
* This implementation works on both Safari 2 and 3, by detecting the version
* and reverting to a stub implementation for Safari 2.
*/
-class HistoryImplSafari extends HistoryImplStandard {
-
- static boolean isOldSafari = detectOldSafari();
-
- static native boolean detectOldSafari() /*-{
- var exp = / AppleWebKit\/([\d]+)/;
- var result = exp.exec(navigator.userAgent);
- if (result) {
- // The standard history implementation works fine on WebKit >= 522
- // (Safari 3 beta).
- if (parseInt(result[1]) >= 522) {
- return false;
- }
- }
-
- // The standard history implementation works just fine on the iPhone, which
- // unfortunately reports itself as WebKit/420+.
- if (navigator.userAgent.indexOf('iPhone') != -1) {
- return false;
- }
-
- return true;
- }-*/;
+class HistoryImplSafari extends HistoryImplTimer {
@Override
- public boolean init() {
- if (isOldSafari) {
- initImpl();
- return true;
- } else {
- return super.init();
- }
- }
-
- @Override
- protected void nativeUpdate(String historyToken) {
- if (isOldSafari) {
- oldNativeUpdate(historyToken);
- } else {
- newNativeUpdate(historyToken);
- }
- }
- // HasXHandler(Selection.Handler
-
- private native void initImpl() /*-{
- var token = '';
-
- // Get the initial token from the url's hash component.
- var hash = $wnd.location.hash;
- if (hash.length > 0) {
- token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
- }
-
- @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
- this.@com.google.gwt.user.client.impl.HistoryImpl::fireHistoryChangedImpl(Ljava/lang/String;)($wnd.__gwt_historyToken);
- }-*/;
-
- private native void newNativeUpdate(String historyToken) /*-{
+ protected native void nativeUpdate(String historyToken) /*-{
// Safari gets into a weird state (issue 2905) when setting the hash
// component of the url to an empty string, but works fine as long as you
// at least add a '#' to the end of the url. So we get around this by
@@ -87,19 +33,4 @@
$wnd.location = $wnd.location.href.split('#')[0] + '#' +
this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
}-*/;
-
- private native void oldNativeUpdate(String historyToken) /*-{
- // Use a bizarre meta refresh trick to update the url's hash, without
- // creating a history entry.
- var meta = $doc.createElement('meta');
- meta.setAttribute('http-equiv','refresh');
-
- var newUrl = $wnd.location.href.split('#')[0] + '#' + this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
- meta.setAttribute('content','0.01;url=' + newUrl);
-
- $doc.body.appendChild(meta);
- window.setTimeout(function() {
- $doc.body.removeChild(meta);
- }, 1);
- }-*/;
}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java b/user/src/com/google/gwt/user/client/impl/HistoryImplTimer.java
similarity index 74%
rename from user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
rename to user/src/com/google/gwt/user/client/impl/HistoryImplTimer.java
index 0fb2b83..825fecd 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplTimer.java
@@ -16,9 +16,10 @@
package com.google.gwt.user.client.impl;
/**
- * Standard history implementation, currently used only on Opera browsers.
+ * Base class for history implementations that use a timer rather than the
+ * onhashchange event.
*/
-class HistoryImplStandard extends HistoryImpl {
+class HistoryImplTimer extends HistoryImpl {
@Override
public native boolean init() /*-{
@@ -49,17 +50,4 @@
$wnd.__checkHistory();
return true;
}-*/;
-
- /**
- * The standard updateHash implementation assigns to location.hash() with an
- * encoded history token.
- */
- protected native void nativeUpdate(String historyToken) /*-{
- $wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
- }-*/;
-
- @Override
- protected void nativeUpdateOnEvent(String historyToken) {
- // Do nothing, the hash is already updated.
- }
}
diff --git a/user/src/com/google/gwt/xml/XML.gwt.xml b/user/src/com/google/gwt/xml/XML.gwt.xml
index b9bf1a1..035a447 100644
--- a/user/src/com/google/gwt/xml/XML.gwt.xml
+++ b/user/src/com/google/gwt/xml/XML.gwt.xml
@@ -15,32 +15,34 @@
<!-- XML parsing support. -->
<!-- -->
<module>
- <inherits name="com.google.gwt.core.Core"/>
- <inherits name="com.google.gwt.user.UserAgent"/>
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name="com.google.gwt.user.UserAgent"/>
- <!-- Fall through to this rule for all other browsers -->
- <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplStandard">
- <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
- </replace-with>
+ <!-- Fall through to this rule for all other browsers -->
+ <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplStandard">
+ <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
+ </replace-with>
- <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplMozillaOld">
- <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
- <when-property-is name="user.agent" value="gecko"/>
- </replace-with>
+ <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplMozillaOld">
+ <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
+ <when-property-is name="user.agent" value="gecko"/>
+ </replace-with>
- <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplOpera">
- <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
- <when-property-is name="user.agent" value="opera"/>
- </replace-with>
+ <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplOpera">
+ <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
+ <when-property-is name="user.agent" value="opera"/>
+ </replace-with>
- <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplIE6">
- <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
- <when-property-is name="user.agent" value="ie6"/>
- </replace-with>
+ <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplIE6">
+ <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
+ <any>
+ <when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
+ </any>
+ </replace-with>
- <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplSafari">
- <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
- <when-property-is name="user.agent" value="safari"/>
- </replace-with>
-
+ <replace-with class="com.google.gwt.xml.client.impl.XMLParserImplSafari">
+ <when-type-is class="com.google.gwt.xml.client.impl.XMLParserImpl"/>
+ <when-property-is name="user.agent" value="safari"/>
+ </replace-with>
</module>
diff --git a/user/super/com/google/gwt/emul/EmulationWithUserAgent.gwt.xml b/user/super/com/google/gwt/emul/EmulationWithUserAgent.gwt.xml
index 4add1cf..2080888 100644
--- a/user/super/com/google/gwt/emul/EmulationWithUserAgent.gwt.xml
+++ b/user/super/com/google/gwt/emul/EmulationWithUserAgent.gwt.xml
@@ -26,6 +26,7 @@
<when-type-is class="com.google.gwt.core.client.impl.StringBufferImpl"/>
<any>
<when-property-is name="user.agent" value="ie6"/>
+ <when-property-is name="user.agent" value="ie8"/>
</any>
</replace-with>