在IE8+中,我遇到了Ext.History实用程序(3.4.0版)正常工作的问题。它在Quirks模式下工作,但不能在IE8标准模式(IE8)或IE9标准模式(IE9)下使用文档模式。怪癖模式对我们不起作用,因为它不能正确地呈现我们的CSS。
我已经从应用程序中剥离了除历史实用程序之外的所有内容,现在有两个文件(除了extjs文件):
index.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<script type="text/javascript" src="ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>
<script type="text/javascript" src="myapp.js"></script>
</head>
<body>
<div>
<div align="center">
<table width="97%" border="0" cellpadding="0" cellspacing="0" >
<tr>
<td>
<a href="#link1">Link1</a> |
<a href="#link2">Link2</a> |
<a href="#link3">Link3</a> |
<a href="#link4">Link4</a> |
<a href="#link5">link5</a>
</td>
</tr>
</table>
</div>
</div>
<!-- Fields required for history management -->
<form id="history-form" class="x-hidden">
<input type="hidden" id="x-history-field"/>
<iframe id="x-history-frame"></iframe>
</form>
</body>
</html>
myapp.js:
Ext.ns('MyApp');
Ext.onReady(function()
{
Ext.History.init();
Ext.History.on('change', function(token){}, this);
});
当我在web服务器中加载应用程序时,转到index.html,然后单击link1,地址栏显示#link1。然后单击link2,地址栏显示#link2。然后单击link3,地址栏显示#link3。
使用带有IE7仿真的IE中的后退按钮,在Chrome或火狐浏览器中,地址栏将从#link3转到#link2。当我再次点击后退按钮时,地址栏从#link2变成了#link1。这是我所期望的行为。
但是,在适当的文档标准模式下使用IE8或IE9时,当我再次单击“后退”按钮时,地址栏从#link2回到#link3。再单击back按钮,用户将在#link2和#link3之间切换。这种行为是意外的,并且会导致我们的应用程序无法正常工作。
请注意,这是Sencha示例在3.4.0中的工作方式:
(页面以Quirks模式呈现,但如果您将其更改为IE8标准或IE9标准,它将不起作用)。
它在4.1中似乎工作正常:
(只允许我发布两个链接,但您可能可以找到它...)
我不能访问Ext3.4.1,但是这个问题没有在错误修复中列出。我见过一个线程(here),它建议更改文档类型会起作用,但事实似乎并非如此(我已经尝试了所有文档类型……)。
请注意,我们的应用程序的许多部分都在使用History实用程序进行导航,因此移除它不是一个可接受的解决方案。
有没有人能给我提点建议,让它正常工作?
发布于 2013-02-24 13:28:44
这就是我最终解决这个问题的方法:
我创建了一个新的补丁javascript文件,并将其包含在ext文件之后。
/*
@Author: RWR 20130224
This fixes the issue with backward traversal of history in IE8 & higher in standard document mode.
This class was challenging to override (http://www.sencha.com/forum/showthread.php?46306-Help-How-to-extend-Ext.History)
I ended up pasting all of the source original code here and making the necessary changes.
NOTE that this may be patched in version 3.4.1. It is definitely patched in 4.1. When upgrading, validate that this patch is still required.
*/
NewHistory = (function () {
var iframe, hiddenField;
var ready = false;
var currentToken;
var oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
function getHash() {
var href = location.href, i = href.indexOf("#"),
hash = i >= 0 ? href.substr(i + 1) : null;
if (Ext.isGecko) {
hash = decodeURIComponent(hash);
}
return hash;
}
function doSave() {
hiddenField.value = currentToken;
}
function handleStateChange(token) {
currentToken = token;
Ext.History.fireEvent('change', token);
}
function updateIFrame (token) {
var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
try {
var doc = iframe.contentWindow.document;
doc.open();
doc.write(html);
doc.close();
return true;
} catch (e) {
return false;
}
}
function checkIFrame() {
if (!iframe.contentWindow || !iframe.contentWindow.document) {
setTimeout(checkIFrame, 10);
return;
}
var doc = iframe.contentWindow.document;
var elem = doc.getElementById("state");
var token = elem ? elem.innerText : null;
var hash = getHash();
setInterval(function () {
doc = iframe.contentWindow.document;
elem = doc.getElementById("state");
var newtoken = elem ? elem.innerText : null;
var newHash = getHash();
if (newtoken !== token) {
token = newtoken;
handleStateChange(token);
location.hash = token;
hash = token;
doSave();
} else if (newHash !== hash) {
hash = newHash;
updateIFrame(newHash);
}
}, 50);
ready = true;
Ext.History.fireEvent('ready', Ext.History);
}
function startUp() {
currentToken = hiddenField.value ? hiddenField.value : getHash();
if (oldIEMode) {
checkIFrame();
} else {
var hash = getHash();
setInterval(function () {
var newHash = getHash();
if (newHash !== hash) {
hash = newHash;
handleStateChange(hash);
doSave();
}
}, 50);
ready = true;
Ext.History.fireEvent('ready', Ext.History);
}
}
return {
/**
* The id of the hidden field required for storing the current history token.
* @type String
* @property s
*/
fieldId: 'x-history-field',
/**
* The id of the iframe required by IE to manage the history stack.
* @type String
* @property s
*/
iframeId: 'x-history-frame',
events:{},
/**
* Initialize the global History instance.
* @param {Boolean} onReady (optional) A callback function that will be called once the history
* component is fully initialized.
* @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser window.
*/
init: function (onReady, scope) {
if(ready) {
Ext.callback(onReady, scope, [this]);
return;
}
if(!Ext.isReady){
Ext.onReady(function(){
Ext.History.init(onReady, scope);
});
return;
}
hiddenField = Ext.getDom(Ext.History.fieldId);
if (oldIEMode) {
iframe = Ext.getDom(Ext.History.iframeId);
}
this.addEvents(
/**
* @event ready
* Fires when the Ext.History singleton has been initialized and is ready for use.
* @param {Ext.History} The Ext.History singleton.
*/
'ready',
/**
* @event change
* Fires when navigation back or forwards within the local page's history occurs.
* @param {String} token An identifier associated with the page state at that point in its history.
*/
'change'
);
if(onReady){
this.on('ready', onReady, scope, {single:true});
}
startUp();
},
/**
* Add a new token to the history stack. This can be any arbitrary value, although it would
* commonly be the concatenation of a component id and another id marking the specifc history
* state of that component. Example usage:
* <pre><code>
// Handle tab changes on a TabPanel
tabPanel.on('tabchange', function(tabPanel, tab){
Ext.History.add(tabPanel.id + ':' + tab.id);
});
</code></pre>
* @param {String} token The value that defines a particular application-specific history state
* @param {Boolean} preventDuplicates When true, if the passed token matches the current token
* it will not save a new history step. Set to false if the same state can be saved more than once
* at the same history stack location (defaults to true).
*/
add: function (token, preventDup) {
if(preventDup !== false){
if(this.getToken() == token){
return true;
}
}
if (oldIEMode) {
return updateIFrame(token);
} else {
location.hash = token;
return true;
}
},
/**
* Programmatically steps back one step in browser history (equivalent to the user pressing the Back button).
*/
back: function(){
history.go(-1);
},
/**
* Programmatically steps forward one step in browser history (equivalent to the user pressing the Forward button).
*/
forward: function(){
history.go(1);
},
/**
* Retrieves the currently-active history token.
* @return {String} The token
*/
getToken: function() {
return ready ? currentToken : getHash();
}
};
})();
Ext.apply(NewHistory, new Ext.util.Observable());
Ext.apply(Ext.History, NewHistory);
发布于 2013-02-24 00:51:55
这实际上是非常简单的。我下载了Ext4.1并查看了他们对Ext.util.History类做了什么。他们为oldIEMode定义了一个变量,并将其用于3.4中使用Ext.isIE的所有条件句。
因此,我编辑了ext-all-debug.js中的Ext.History类,并在顶部定义了以下变量:
var oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
类中有三个条件语句在检查Ext.isIE,我用oldIEMode替换了它们。
我重新构建并部署了应用程序,问题得到了解决。
编辑ext-all.js不是最佳实践,但是我应该能够改写这个类。
https://stackoverflow.com/questions/15042460
复制相似问题