JQuery. уже в динамически вставленном iframe
Мы используем jQuery thickbox для динамического отображения iframe, когда кто-то нажимает на изображение. В этом iframe мы используем galleria javascript-библиотеку для отображения нескольких изображений.
Проблема заключается в том, что $(document).ready
в iframe, похоже, срабатывает слишком рано, а содержимое iframe еще не загружено, поэтому код шкалы не применяется должным образом к элементам DOM. $(document).ready
, похоже, использует состояние готовности родителя iframe, чтобы решить, готов ли iframe.
Если мы выберем функцию, вызванную документом, готовой в отдельной функции и вызовите ее после таймаута 100 мкс. Он работает, но мы не можем воспользоваться этой возможностью на медленном компьютере.
$(document).ready(function() { setTimeout(ApplyGalleria, 100); });
Мой вопрос: какое событие jQuery мы должны связывать, чтобы иметь возможность выполнять наш код, когда динамический iframe готов, а не только родительский?
Ответы
Ответ 1
Я ответил на аналогичный вопрос (см. обратный вызов 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 я нашел достаточно хорошим, чтобы использовать событие загрузки вместо события готовности документа.
Ответ 2
Использование 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. Весь код сохраняется и выполняется из родительского фрейма/окна.
Ответ 3
В IFrames я обычно решаю эту проблему, помещая небольшой script в самый конец блока:
<body>
The content of your IFrame
<script type="text/javascript">
//<![CDATA[
fireOnReadyEvent();
parent.IFrameLoaded();
//]]>
</script>
</body>
Эта работа большую часть времени для меня. Иногда наиболее подходящим является самое простое и наивное решение.
Ответ 4
Следуя идее д-ра Джокепу и Дэвида Мердока, я реализовал более полную версию.
Для этого требуется 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);
});
});
Ответ 5
Найден решение проблемы.
Когда вы нажимаете ссылку на толстую ячейку, открывающую iframe, она вставляет iframe с идентификатором TB_iframeContent.
Вместо того, чтобы полагаться на событие $(document).ready
в коде iframe, мне просто нужно привязать к событию загрузки iframe в родительском документе:
$('#TB_iframeContent', top.document).load(ApplyGalleria);
Этот код находится в iframe, но привязывается к событию элемента управления в родительском документе. Он работает в FireFox и IE.
Ответ 6
Попробуйте это,
<iframe id="testframe" src="about:blank" onload="if (testframe.location.href != 'about:blank') testframe_loaded()"></iframe>
Все, что вам нужно сделать, это создать функцию JavaScript testframe_loaded().
Ответ 7
Я загружаю 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";
Ответ 8
В основном то, что другие уже опубликовали, но IMHO немного чище:
$('<iframe/>', {
src: 'https://example.com/',
load: function() {
alert("loaded")
}
}).appendTo('body');
Ответ 9
Это была проблема, с которой я столкнулся с нашим клиентом. Я создал небольшой плагин jquery, который, похоже, работает для готовности iframe. Он использует опрос для проверки документа iframe readyState в сочетании с внутренним URL-адресом документа в сочетании с источником iframe, чтобы убедиться, что iframe фактически "готов".
Проблема с "onload" заключается в том, что вам нужен доступ к фактическому iframe, добавляемому в DOM, если вы этого не сделаете, вам нужно попытаться поймать загрузку iframe, которая, если она кэширована, тогда вы не можете. Мне нужен был script, который можно было бы вызвать в любое время, и определить, был ли iframe "готов" или нет.
Здесь вопрос:
Святой грааль для определения того, загружен ли локальный iframe
и здесь jsfiddle я в конце концов придумал.
https://jsfiddle.net/q0smjkh5/10/
В jsfiddle выше, я жду, когда onload добавит iframe в dom, а затем проверит состояние готовности внутреннего документа iframe - что должно быть перекрестным доменом, поскольку оно указывает на википедию, но Chrome, похоже, сообщает "complete". Затем метод plug-in 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>