我的一位客户有很多基于大量CMS(Wordpress,Drupal等)的网站。他想要一个通用目录,专业人员可以在其中注册和共享信息。它是“通用的”,因为它可以安装在任何网站上(根据网站的业务而拒绝)。
我在iframe中开发了它,因为它可以安装在任何CMS上,还有其他很好的理由这样做(CSS,SEO ...)。但是,由于iframe浏览对于导航栏是透明的,我需要做一些技巧,允许访问者复制/粘贴专业人士的网址,分享和收藏他们。我使用history.js来更新导航栏的URL,当直接访问iframe时,我将用户重定向到右侧“主要网站”的页面。
但点击“后退”按钮后出现问题。由于某些原因,第二次单击“返回”时未正确触发“statechange
”事件。
正如您在日志div中看到的,当您单击B和C时,您将获得:
Push: /a.html
Push: /b.html
statechange trigered
Push: /c.html
statechange trigered
如果你回去一次,你会得到:
statechange trigered
Pop: /b.html
如果你第二次回去,你会得到:
Push: /c.html
statechange trigered
而不是:
statechange trigered
Pop: /a.html
所以我的问题:
这里发生了什么?
main.html中
<iframe id="my-test" src="a.html" width="500" height="500"></iframe>
<div id="log"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.0.6/jquery.browser.min.js"></script>
<script src="history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script type="text/javascript">
var test_url = 'http://so.ocarina.fr/test';
// used to avoid listening events trigered by the script itself
var manual_state_change = true;
// used to avoid pushing the previous page
var is_back = false;
$(document).ready(function () {
$('#my-test').load(function () {
// when iframe has loaded, we replace the navbar's url by
// the one from iframe's source.
if (!window.is_back) {
window.manual_state_change = false;
var History = window.History;
if (History.enabled) {
var url = $('#my-test').get(0).contentWindow.location.href;
if (url.indexOf('blank') > 0) {
return;
}
if (url.indexOf('test') > 0) {
url = url.substring(url.indexOf('test') + 4);
if (url.length === 0) {
url = '/';
}
}
$('#log').append('Push: ' + url + '<br/>');
var title = $("#my-test").contents().find("title").html();
document.title = title;
History.pushState({url: decodeURIComponent(url + '')}, title, window.test_url + decodeURIComponent(url + ''));
window.manual_state_change = true;
}
}
window.is_back = false;
}).trigger('load'); // triggered once to replace main.html by a.html
var History = window.History;
if (History.enabled) {
History.Adapter.bind(window, 'statechange', function () {
// if user clicks back, we should change the iframe's location
// to the backward url from history stack.
$('#log').append('statechange trigered <br/>');
if (window.manual_state_change === true) {
window.manual_state_change = false;
var state = History.getState();
var url = state.data.url;
$('#log').append('Pop: ' + url + '<br/>');
window.is_back = true;
$('#my-test').attr('src', window.test_url + url);
$('#my-test')[0].contentWindow.location = window.test_url + url;
window.manual_state_change = true;
}
});
}
});
</script>
a.html
<title>Test A</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test A</p>
<a href="b.html">Go to test B</a>
</div>
b.html
<title>Test B</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test B</p>
<a href="c.html">Go to test C</a>
</div>
c.html
<title>Test C</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test C</p>
<p>Go back to A using your backward button...</p>
</div>
答案 0 :(得分:0)
我终于发现了我的错误:点击我的iframe链接时,浏览器已经在历史记录中添加了一个条目,因此我不应该使用pushState
添加条目,而只是替换使用replaceState
的当前历史记录条目。
奖励:我们不需要处理状态转换,浏览器会像往常一样自然地做任何事情。酷!
我的代码变为:
<iframe id="my-test" src="a.html" width="500" height="500"></iframe>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.0.6/jquery.browser.min.js"></script>
<script src="history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script type="text/javascript">
var test_url = 'http://so.ocarina.fr/test2';
$(document).ready(function () {
$('#my-test').load(function () {
// when iframe has loaded, we replace the navbar's url by
// the one from iframe's source.
var History = window.History;
if (History.enabled) {
var url = $('#my-test').get(0).contentWindow.location.href;
if (url.indexOf('blank') > 0) {
return;
}
if (url.indexOf('test') > 0) {
url = url.substring(url.indexOf('test2') + 5);
if (url.length === 0) {
url = '/';
}
}
var title = $("#my-test").contents().find("title").html();
document.title = title;
History.replaceState({}, title, window.test_url + decodeURIComponent(url + '')); // YES!
}
}).trigger('load'); // triggered once to replace main.html by a.html
});
</script>