Мы используем jQuery thickbox для динамического отображения iframe, когда кто-то нажимает на изображение. В этом iframe мы используем galleria библиотеку javascript для отображения нескольких изображений.

Кажется, проблема в том, что $(document).ready в iframe запускается слишком рано, а содержимое iframe еще даже не загружено, поэтому код галереи неправильно применяется к элементам DOM. $(document).ready, кажется, использует родительское состояние готовности iframe, чтобы решить, готов ли iframe.

Если мы извлекаем функцию, вызванную документом, готовым в отдельную функцию, и вызываем ее по истечении времени ожидания 100 мс. Это работает, но мы не можем рисковать в производстве с медленным компьютером.

$(document).ready(function() { setTimeout(ApplyGalleria, 100); });

Мой вопрос: к какому событию jQuery мы должны привязаться, чтобы иметь возможность выполнять наш код, когда готов динамический iframe, а не только его родитель?

Я ответил на аналогичный вопрос (см. Обратный вызов Javascript после завершения загрузки IFRAME? ). Вы можете получить контроль над событием загрузки iframe с помощью следующего кода:

function callIframe(url, callback) {
    $(document.body).append('<IFRAME id="myId" ...>');
    $('iframe#myId').attr('src', url);

    $('iframe#myId').load(function() {
        callback(this);
    });
}

Имея дело с iframe, я нашел хороший достаточно использовать событие загрузки вместо события готовности документа.

Используя jQuery 1.3.2, у меня сработало следующее:

$('iframe').ready(function() {
  $('body', $('iframe').contents()).html('Hello World!');
});

ПЕРЕСМОТР:! На самом деле приведенный выше код иногда выглядит так, как будто он работает в Firefox, а не как в Opera.

Вместо этого я реализовал решение опроса для своих целей. Упрощенно это выглядит так:

$(function() {
  function manipIframe() {
    el = $('body', $('iframe').contents());
    if (el.length != 1) {
      setTimeout(manipIframe, 100);
      return;
    }
    el.html('Hello World!');
  }
  manipIframe();
});

Для этого не требуется код на вызываемых страницах iframe. Весь код находится и выполняется из родительского фрейма / окна.

В IFrames я обычно решаю эту проблему, помещая небольшой скрипт в самый конец блока:

<body>
The content of your IFrame
<script type="text/javascript">
//<![CDATA[
   fireOnReadyEvent();
   parent.IFrameLoaded();
//]]>
</script>
</body>

Это работает для меня большую часть времени. Иногда самое простое и наивное решение является наиболее подходящим.

Следуя идее DrJokepu и Дэвида Мердока, я реализовал более полную версию. Для требуется jQuery как для родителя, так и для iframe, а также для управления iframe.

iframe code:

var iframe = window.frameElement;

if (iframe){
    iframe.contentDocument = document;//normalization: some browsers don't set the contentDocument, only the contentWindow

    var parent = window.parent;
    $(parent.document).ready(function(){//wait for parent to make sure it has jQuery ready
        var parent$ = parent.jQuery;

        parent$(iframe).trigger("iframeloading");

        $(function(){
            parent$(iframe).trigger("iframeready");
        });

        $(window).load(function(){//kind of unnecessary, but here for completion
            parent$(iframe).trigger("iframeloaded");
        });

        $(window).unload(function(e){//not possible to prevent default
            parent$(iframe).trigger("iframeunloaded");
        });

        $(window).on("beforeunload",function(){
            parent$(iframe).trigger("iframebeforeunload");
        });
    });
}

родительский тестовый код:

$(function(){
    $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
        console.log(e.type);
    });
});

Нашел решение проблемы.

Когда вы щелкаете по ссылке на «толстую коробку», которая открывает iframe, он вставляет iframe с идентификатором TB_iframeContent.

Вместо того, чтобы полагаться на событие $(document).ready в коде iframe, мне просто нужно привязать событие загрузки iframe в родительском документе:

$('#TB_iframeContent', top.document).load(ApplyGalleria);

Этот код находится в iframe, но привязывается к событию контроль в родительском документе. Работает в FireFox и IE.

var

<iframe id="testframe" src="about:blank" onload="if (testframe.location.href != 'about:blank') testframe_loaded()"></iframe>

Все, что вам нужно сделать, это создать функцию JavaScript testframe_loaded ().

Я загружаю PDF с jQuery ajax в кеш браузера. Затем я создаю встроенный элемент с данными уже в кеше браузера. Я думаю, это будет работать и с iframe.


var url = "http://example.com/my.pdf";
// show spinner
$.mobile.showPageLoadingMsg('b', note, false);
$.ajax({
    url: url,
    cache: true,
    mimeType: 'application/pdf',
    success: function () {
        // display cached data
        $(scroller).append('<embed type="application/pdf" src="'   url   '" />');
        // hide spinner
        $.mobile.hidePageLoadingMsg();
    }
});

Вы также должны правильно настроить заголовки http.


HttpContext.Response.Expires = 1;
HttpContext.Response.Cache.SetNoServerCaching();
HttpContext.Response.Cache.SetAllowResponseInBrowserHistory(false);
HttpContext.Response.CacheControl = "Private";

В основном то, что уже опубликовали другие, но ИМХО немного чище:

$('<iframe/>', {
    src: 'https://example.com/',
    load: function() {
        alert("loaded")
    }
}).appendTo('body');

Это была именно та проблема, с которой я столкнулся с нашим клиентом. Я создал небольшой плагин jquery, который, кажется, работает для готовности iframe. Он использует опрос для проверки документа iframe readyState в сочетании с внутренним URL документа в сочетании с источником iframe, чтобы убедиться, что iframe фактически «готов».

Проблема с «onload» заключается в том, что вам нужен доступ к фактическому iframe, добавляемому в DOM, если вы этого не сделаете, вам нужно попытаться отловить загрузку iframe, которая, если она кэшируется, может и не быть. Мне нужен был скрипт, который можно было вызывать в любое время и определять, готов ли iframe или нет.

Вот вопрос:

Святой Грааль для определения, загрузил ли локальный iframe

, и вот jsfiddle, который я в конце концов придумал.

https://jsfiddle.net/q0smjkh5/10/

В приведенном выше jsfiddle я жду, когда onload добавит iframe в dom, а затем проверяет состояние готовности внутреннего документа iframe — который должен быть междоменным, потому что он указывает на википедию — но Chrome, похоже, сообщает «завершено». Метод iready плагина затем вызывается, когда iframe фактически готов. Обратный вызов пытается снова проверить состояние готовности внутреннего документа — на этот раз, сообщая о междоменном запросе (что правильно), — в любом случае, похоже, он работает для того, что мне нужно, и надеюсь, что это поможет другим.

<script>
  (function($, document, undefined) {
    $.fn["iready"] = function(callback) {
      var ifr = this.filter("iframe"),
          arg = arguments,
          src = this,
          clc = null, // collection
          lng = 50,   // length of time to wait between intervals
          ivl = -1,   // interval id
          chk = function(ifr) {
            try {
              var cnt = ifr.contents(),
                  doc = cnt[0],
                  src = ifr.attr("src"),
                  url = doc.URL;
              switch (doc.readyState) {
                case "complete":
                  if (!src || src === "about:blank") {
                    // we don't care about empty iframes
                    ifr.data("ready", "true");
                  } else if (!url || url === "about:blank") {
                    // empty document still needs loaded
                    ifr.data("ready", undefined);
                  } else {
                    // not an empty iframe and not an empty src
                    // should be loaded
                    ifr.data("ready", true);
                  }

                  break;
                case "interactive":
                  ifr.data("ready", "true");
                  break;
                case "loading":
                default:
                  // still loading
                  break;   
              }
            } catch (ignore) {
              // as far as we're concerned the iframe is ready
              // since we won't be able to access it cross domain
              ifr.data("ready", "true");
            }

            return ifr.data("ready") === "true";
          };

      if (ifr.length) {
        ifr.each(function() {
          if (!$(this).data("ready")) {
            // add to collection
            clc = (clc) ? clc.add($(this)) : $(this);
          }
        });
        if (clc) {
          ivl = setInterval(function() {
            var rd = true;
            clc.each(function() {
              if (!$(this).data("ready")) {
                if (!chk($(this))) {
                  rd = false;
                }
              }
            });

            if (rd) {
              clearInterval(ivl);
              clc = null;
              callback.apply(src, arg);
            }
          }, lng);
        } else {
          clc = null;
          callback.apply(src, arg);
        }
      } else {
        clc = null;
        callback.apply(this, arguments);
      }
      return this;
    };
  }(jQuery, document));
</script>