Вопрос

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

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

Если мы выделим функцию, вызванную document ready, в отдельную функцию и вызовем ее по истечении тайм-аута в 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);
    });
}

При работе с iframes я счел достаточно хорошим использовать load event вместо document ready event.

Другие советы

Используя 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>

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

Следуя идее доктора Джокепу и Дэвида Мердока, я реализовал более полную версию.IT требует jQuery как для родительского, так и для iframe, и iframe должен находиться под вашим контролем.

код iframe:

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);
    });
});

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

Когда вы нажимаете на ссылку thickbox, которая открывает iframe, он вставляет iframe с идентификатором TB_iframeContent.

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

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

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

Попробуй это,

<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 в сочетании с внутренним 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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top