jQuery.готов в динамически вставить iframe в
мы используем jQuery thickbox для динамического отображения iframe, когда кто-то нажимает на картинку. В этом iframe мы используем галерея библиотека javascript для отображения нескольких изображений.
проблема, кажется, в том, что $(document).ready в iframe, похоже, слишком рано запускается, и содержимое iframe еще даже не загружено, поэтому код galleria не применяется должным образом к элементам DOM. $(document).ready Кажется, использовать элемент iframe родительское состояние готовности решать если iframe готов.
Если мы извлекаем функцию называют документ готов в отдельную функцию и вызывать ее после таймаут 100 мс. Это работает, но мы не можем рисковать в производстве с медленным компьютером.
$(document).ready(function() { setTimeout(ApplyGalleria, 100); });
мой вопрос: к какому событию jQuery мы должны привязаться, чтобы иметь возможность выполнять наш код, когда динамический iframe готов, а не только его родитель?
9 ответов:
Я ответил на аналогичный вопрос (см. 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>эта работа большую часть времени для меня. Иногда самое простое и наивное решение является наиболее подходящим.
после идеи DrJokepu и Дэвида Мердока я реализовал более полную версию. Это требует 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";
в основном то, что другие уже опубликовали, но IMHO немного чище:
$('<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>
Comments