IE теряет содержимое iframe после клавиши назад / вперед - PullRequest
1 голос
/ 12 февраля 2012

Эта проблема возникает только в IE (по крайней мере, 8 и 9). После динамического добавления элемента в DOM содержимое встроенного iframe теряется при повторном входе на страницу с помощью клавиши BACK / FORWARD. Воспроизведите проблему всего два небольших файла HTML.


Первый файл - iframe.htm:

<!DOCTYPE html>
<html>
<head>
    <title>IE iframe bug</title>
    <script type="text/javascript">
        function mytrace(msg) {
            var t = document.createTextNode(msg);
            var b = document.createElement('br');
            var d = document.getElementById("trace_output")
            d.appendChild(t);
            d.appendChild(b); /// will work if commented
        }
        function submitListing() {
            mytrace('submitListing()');
            var doc = document.getElementById("output_iframe")
                .contentWindow.document;
            var d = new Date;
            doc.location.replace('report.htm?invalidateCache=' + d.getTime());
            //mytrace('submitListing(): out');
        }
    </script>
</head>
<body>
    <div id="trace_output"><br /></div>
    <input type="button" onclick="submitListing();" value="Run" /><br />
    <iframe id="output_iframe" src=""></iframe>
</body>
</html>


Второй файл - report.htm:

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <a href="http://google.com" target="_top">LINK</a>
</body>
</html>


Действия по воссозданию проблемы (НАЗАД): 1013 *

  1. Поместить вышеуказанное содержимое в два файла
  2. Просмотр файла iframe.htm
  3. Нажмите кнопку Run, чтобы загрузить report.htm в iframe
  4. Нажмите на ссылку LINK, чтобы загрузить другую страницу
  5. Нажмите кнопку НАЗАД браузера, чтобы вернуться на страницу с кэшем (lmao)
  6. содержимое iframe пропало !!!! (только в IE - safari, chrome, firefox сохраняют содержимое)

Также .. (ПРЯМОЙ КЛЮЧ)

  1. Просмотр произвольной страницы (для истории http://www.google.com работ)
  2. Загрузите iframe.htm в ту же вкладку
  3. Нажмите кнопку Run, чтобы загрузить report.htm в iframe
  4. Нажмите кнопку НАЗАД браузера, чтобы вернуться на первую страницу
  5. Нажмите кнопку браузера ВПЕРЕД, чтобы вернуться к iframe.htm
  6. содержимое iframe снова исчезло !!


Теперь закомментируйте строку:

d.appendChild(b)

Это одно изменение позволяет всем работать в IE. Тем не менее, мое решение должно выполнять такие виды DOM-манипуляций (тяжелое приложение jQuery / AJAX) и иметь возможность восстанавливать iframe через действия браузера BACK / FORWARD.

Похоже, мне придется запомнить содержимое iframe, чтобы я мог восстановить его при доступе к странице с помощью клавиш BACK / FORWARD. Я не в восторге от этого, потому что иногда содержание iframe будет довольно большим, и это может занять немного памяти и времени, чтобы сделать еще одну копию встроенного документа для восстановления. Я хотел бы услышать некоторые другие идеи о том, как я мог бы подойти к этому. Заранее спасибо.

EDIT

Следующая замена iframe.htm поможет обойти проблему с IE. Я собираюсь переписать это с помощью jQuery и добавить немного логики для восстановления позиций прокрутки. Я надеялся на что-то более элегантное, но это делает работу.

<!DOCTYPE html>
<html>
<head>
    <title>IE iframe bug</title>
    <script type="text/javascript">
        function myTrace(msg) {
            var t = document.createTextNode(msg);
            var b = document.createElement('br');
            var d = document.getElementById("trace_output")
            d.appendChild(t);
            d.appendChild(b); 
        }
        var make_backup ="false";
        function submitListing() {
            make_backup = "true";
            myTrace('submitListing()');
            var doc = document.getElementById("output_iframe").contentWindow.document;
            var d = new Date;
            doc.location.replace('report.htm?invalidateCache=' + d.getTime());
            //myTrace('submitListing(): out');
        }
        function iframe_load() {
            myTrace("iframe loaded, is_cached=" + document.getElementById("is_cached").value);
            if (make_backup == "true") { // only when submitting
                var htm, doc;
                make_backup = "false"
                doc = document.getElementById("output_iframe").contentWindow.document;
                htm = doc.documentElement.innerHTML;
                document.getElementById("iframe_backup").value = htmlEscape(htm);
            }
        }
        function bodyLoaded() {
            var is_cached = document.getElementById("is_cached");
            if (is_cached.value == "false") {  // initial page load 
                is_cached.value = "true";
            }
            else { // BACK or FORWARD,  restore DOM where needed 
                var htm;
                htm = htmlUnescape(document.getElementById("iframe_backup").value);
                var doc;
                doc = document.getElementById("output_iframe").contentWindow.document;
                doc.open();
                doc.writeln(htm);
                doc.close();
            }
        }
        function htmlEscape(str) {
            return String(str).replace(/&/g, '&amp;').replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        }
        function htmlUnescape(str) {
            return String(str).replace(/&amp;/g,'&').replace(/&quot;/g,'"')
            .replace(/&#39;/g,"'").replace(/&lt;/g,'<').replace(/&gt;/g,'>');
        }
    </script>
</head>
<body onload="bodyLoaded();">
    <div id="trace_output" style="height: 300px; border-width:1; background-color: Silver"><br></div>
    <input id="is_cached" type="hidden" value="false">
    <input id="iframe_backup" type="hidden">
    <input type="button" onclick="submitListing();" value="Run"><br>
    <iframe id="output_iframe" src="" onload="iframe_load();"></iframe>
</body>
</html>

РЕДАКТИРОВАТЬ 2

Переписано с помощью jQuery:

<!DOCTYPE html>
<html>
<head>
    <title>IE iframe workaround2</title>
    <script type="text/javascript" src="Scripts/jquery-1.7.1.js"></script>
    <script type="text/javascript">

        var make_backup = "false";

        $(document).ready(function () {
            myTrace('document ready()');
            var is_cached = $("#is_cached");
            if (is_cached.val() == "false") {  // initial page load 
                is_cached.val("true");
            }
            else { // BACK or FORWARD,  restore DOM where needed 
                if ($.browser.msie) { // IE loses iframe content; restore 
                    var htm = htmlUnescape($("#iframe_backup").val());
                    var doc = $("#output_iframe")[0].contentWindow.document;
                    doc.open();
                    doc.writeln(htm);
                    doc.close();
                    myTrace('iframe contents restored');
                }
            }
            $('#output_iframe').load(function () {
                myTrace("iframe_loaded");
                if (make_backup == "true") { // only when submitting
                    make_backup = "false"
                    if ($.browser.msie) {
                        var doc = $("#output_iframe")[0].contentWindow.document;
                        var htm = doc.documentElement.innerHTML;
                        $("#iframe_backup").val(htmlEscape(htm));
                        myTrace('iframe contents backed up');
                    }
                }
            });
            $('#submit_listing').click(function () {
                make_backup = "true";
                myTrace('submitListing()');
                var doc = $("#output_iframe")[0].contentWindow.document;
                var d = new Date;
                doc.location.replace('report.htm?invalidateCache='+d.getTime());
            });
        });
        function myTrace(msg) {
            $('#trace_output').append(msg + '<br>'); 
        }
        function htmlEscape(str) {
            return String(str).replace(/&/g, '&amp;').replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        }
        function htmlUnescape(str) {
            return String(str).replace(/&amp;/g,'&').replace(/&quot;/g,'"')
            .replace(/&#39;/g,"'").replace(/&lt;/g,'<').replace(/&gt;/g,'>');
        }
    </script>
</head>
<body>
    <div id="trace_output" 
         style="height: 300px; border-width:1; background-color: Silver">
         <br></div>
    <div style="display: block;">
        <input id="is_cached" type="text" value="false">
        <input id="iframe_backup" type="text" type="hidden"></div>
    <input id="submit_listing" type="button" value="Run"><br>
    <iframe id="output_iframe" src=""></iframe>
</body>
</html>
...