Browse Source

fixes #2931. Added own slightly modified History implementation for IE.

svn changeset:8419/svn branch:6.0
tags/6.7.0.beta1
Matti Tahvonen 15 years ago
parent
commit
483bfaced7

+ 6
- 0
src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml View File

@@ -24,6 +24,12 @@
<inherits name="com.google.gwt.json.JSON" />

<source path="client" />
<!-- Use our own history impl for IE to workaround #2931. -->
<replace-with class="com.vaadin.terminal.gwt.client.HistoryImplIEVaadin">
<when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
<when-property-is name="user.agent" value="ie6"/>
</replace-with>

<entry-point class="com.vaadin.terminal.gwt.client.DefaultWidgetSet" />
</module>

+ 191
- 0
src/com/vaadin/terminal/gwt/client/HistoryImplIEVaadin.java View File

@@ -0,0 +1,191 @@
/*
* 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.vaadin.terminal.gwt.client;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.impl.HistoryImpl;

/**
* A slightly modified version of GWT's HistoryImplIE6 to bypass bug #2931. Also
* combined with HistoryImplFrame.
*
* This class should be removed if GWT issue 3890 gets resolved. (Also remember
* to removed deferred binding rule from .gwt.xml file).
*/
public class HistoryImplIEVaadin 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
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);
}

/**
* Sanitizes an untrusted string to be used in an HTML context. NOTE: This
* method of escaping strings should only be used on Internet Explorer.
*
* @param maybeHtml
* untrusted string that may contain html
* @return sanitized string
*/
@SuppressWarnings("unused")
private static String escapeHtml(String maybeHtml) {
final Element div = DOM.createDiv();
DOM.setInnerText(div, maybeHtml);
return DOM.getInnerHTML(div);
}

/**
* 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.
*/
@SuppressWarnings("unused")
private static native String getLocationHash()
/*-{
var href = $wnd.location.href;
var hashLoc = href.lastIndexOf("#");
return (hashLoc > 0) ? href.substring(hashLoc) : "";
}-*/;

@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();

initUrlCheckTimer();
return true;
}

protected native String getTokenElementContent(Element tokenElement)
/*-{
return tokenElement.innerText;
}-*/;

protected native void initHistoryToken()
/*-{
// Assume an empty token.
var token = '';
// Get the initial token from the url's hash component.
var hash = @com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::getLocationHash()();
if (hash.length > 0) {
try {
token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
} catch (e) {
// Clear the bad hash (this can't have been a valid token).
$wnd.location.hash = '';
}
}
@com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
}-*/;

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);
};
}-*/;

protected native void navigateFrame(String token)
/*-{
var escaped = @com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::escapeHtml(Ljava/lang/String;)(token);
var doc = this.@com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::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();
}-*/;

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
// or selects a 'favorite', but only the #hash part changes). When this
// occurs, we _must_ reload the page. This is because IE has a really
// nasty bug that totally mangles its history stack and causes the location
// bar in the UI to stop working under these circumstances.
var historyImplRef = this;
var urlChecker = function() {
$wnd.setTimeout(urlChecker, 250);
var hash = @com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::getLocationHash()();
if (hash.length > 0) {
var token = '';
try {
token = historyImplRef.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
} catch (e) {
// If there's a bad hash, always reload. This could only happen if
// if someone entered or linked to a bad url.
$wnd.location.reload();
}

var historyToken = @com.google.gwt.user.client.impl.HistoryImpl::getToken()();
if (token != historyToken) {
$wnd.location.reload();
}
}
};
urlChecker();
}-*/;

}

Loading…
Cancel
Save