FancyBox 2 を iframe モードで使用して、モーダル編集ダイアログを実装しようとしています。編集フォームのある iframe を閉じたら、特定のコードを実行して、親ウィンドウでコンテンツのリロードなどのアクションを実行できるようにしたいと考えています。iframe のフォームは、サーバー側の検証のために、ajax ではなく通常のフォーム投稿を使用しており、複数の送信を受け取ることができます。
ダイアログが閉じられた後にメイン ページでコードを実行するために、FancyBox afterClose プロパティを設定します。
問題: フォーム データの送信/検証が成功した後に iframe を単純に閉じると、iframe が閉じ、afterClose コードが期待どおりに正しく実行されます。問題は、それまでにウィンドウの履歴が追加のエントリで破損することです。つまり、iframe が閉じられたら、iframe をホストしていたページの前のページに戻るには、戻るボタンを複数回 (iframe 内の送信数に等しい) クリックする必要があります。
これを回避するために、iframe の履歴の深さを追跡し、window.history.go(-depth) を実行してから、parent.$.fancybox.close() を実行して iframe を閉じようとしました。これにより、履歴の問題が処理されますが、afterClose コードが実行されなくなります。いくつかの実験では、履歴を元の iframe ページに戻すと、afterClose が実行されないように FancyBox が強制終了されることが示されました (parent.$.fancybox.close() は実行されません)。
質問: iframe にロードされた元のページに到達するのに十分な回数戻るボタンを押すと、FancyBox iframe が破棄される理由を知っている人はいますか? これを防ぐことはできますか?FancyBox iFrame を閉じたときに iFrame の履歴を巻き戻す別の方法はありますか?
例: 問題はこのページに示されています。同じソースを以下に示します。
FancyBoxMain.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Main</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<link rel="stylesheet" href="http://fancyapps.com/fancybox/source/jquery.fancybox.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://fancyapps.com/fancybox/source/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
function popup() {
var options = {
type: 'iframe',
href: 'FancyBoxPopup.html',
height: 250,
modal: true,
autoSize: false,
afterClose: function () { alert('Executing afterClose.'); }
};
$.fancybox.open(options);
};
</script>
</head>
<body>
<input type="button" onclick="popup();" value="Popup"/>
</body>
</html>
FancyBoxPopup.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Popup</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
var url;
var depth;
$(function() {
var pos = window.location.href.indexOf('?');
depth = pos == -1 ? 0 : parseInt(window.location.href.substr(pos + 1));
$('#depth').text(depth);
url = pos == -1 ? window.location.href : window.location.href.substr(0, pos);
if (depth > 0) {
$('#actions').show();
}
});
</script>
</head>
<body style="padding: 0; margin: 0;">
<div>
Depth:
<span id="depth"></span>
<input type="button" value="Add" onclick="window.location.href = '?' + (depth + 1).toString();" />
</div>
<div id="actions" style=" display: none;padding: 0; margin: 0;">
<input type="button" value="Close FancyBox" onclick="parent.$.fancybox.close();"/>
<input type="button" value="Rewind History, before closing FancyBox" onclick="history.go(-depth); parent.$.fancybox.close();"/>
<input type="button" value="Back" onclick="window.history.back();" />
<div>Bad behavior:
<ul>
<li>Simply closing FancyBox allows the afterClose handler to run. The problem is that when depth > 0, the iFrame's history is kept, breaking correct functionality of the browser's back button.</li>
<li>Rewinding history back to 0 depth kills FancyBox, preventing the afterClose handler from firing. You can see this step-by-step by clicking the back button.</li>
</ul>
</div>
</div>
</body>
</html>