Я хотел бы управлять HTML внутри iframe с помощью jQuery.
Я думал, что смогу сделать это, установив контекст функции jQuery как документ iframe, что-то вроде:
$(function(){ //document ready
$('some selector', frames['nameOfMyIframe'].document).doStuff()
});
Однако, похоже, это не работает. Небольшой осмотр показывает мне, что переменные в frames['nameOfMyIframe'] - это undefined, если я не подожду некоторое время, пока загрузится iframe. Однако при загрузке iframe переменные недоступны (я получаю ошибки типа permission denied).
Кто-нибудь знает, как можно обойти это?
если это другой домен, есть ли еще способ получить доступ к его содержимому или зарегистрировать событие
Нет, потому что это будет межсайтовый скриптинг, что запрещено по соображениям безопасности. Мое решение состояло в том, чтобы использовать прокси: дословно передать HTML в IFRAME через мой собственный сайт, чтобы он больше не был межсайтовым с точки зрения браузера.
Использование .contentWindow.document в элементе .document более кроссбраузерно, чем iframe. Я предлагаю изменение, указанное выше.
один из способов - хромированные расширения



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы пробовали классический вариант, ожидая завершения загрузки с помощью встроенной функции готовности jQuery?
$(document).ready(function() {
$('some selector', frames['nameOfMyIframe'].document).doStuff()
} );
K
да. Функция готовности начинает выполняться, когда загружается основной фрейм, а не когда загружается iframe. Однако ожидание, похоже, - небольшая часть проблемы. Я думаю, это связано с междоменной безопасностью.
Вам нужно прикрепить событие к обработчику onload iframe и выполнить там js, чтобы убедиться, что iframe завершил загрузку, прежде чем обращаться к нему.
$().ready(function () {
$("#iframeID").ready(function () { //The function below executes once the iframe has finished loading
$('some selector', frames['nameOfMyIframe'].document).doStuff();
});
};
Вышеупомянутое решит проблему «еще не загружено», но что касается разрешений, если вы загружаете в iframe страницу из другого домена, вы не сможете получить к ней доступ из-за ограничений безопасности.
это хорошая идея, на самом деле я пробовал именно так, как вы ответили. Однако это не работает с отказом в разрешении (это касается моей необходимости ждать, прежде чем начать доступ к материалам iframe)
на самом деле ... неважно, кажется, что ожидание все еще требуется, даже когда это делается.
Готовая функция работает. Однако кажется, что он не дожидается завершения загрузки содержимого iframe - только для родительского документа, даже когда он вызывается для содержимого самого iframe. Я полагаю, что это также из-за той же политики происхождения.
Несколько замечаний по этому коду: вы должны использовать iframe.contentDocument вместо .document, и вы должны использовать .load () вместо .ready (), чтобы избежать ожидания. (Не идеально, но лучше)
Я думаю, что то, что вы делаете, регулируется та же политика происхождения. Это должно быть причиной того, что вы получаете ошибки тип запрещен в разрешении.
@Pacerier Лучше всего проксировать содержимое iframe на вашем сайте, если вы можете ...
@ Tracker1: Можете ли вы предложить какой-либо шаблон проектирования / api / framework для реализации этого прокси-решения. Есть ссылки на пример или учебник и т. д.? Я пытался поискать, но не нашел.
В этом случае он имеет в виду использовать http-сервер, который обслуживает страницу вашего домена, в качестве прокси-сервера - запросить контент со стороннего сайта и переслать его в http-ответе клиенту. Как вы, вероятно, догадались, это быстро влияет на скорость отклика вашего сайта, поскольку ранее параллельные запросы вместо этого выполняются последовательно с вашим сервером, что является потенциальным узким местом.
@Pacerier. Возможно любой из методов в принятом ответе здесь: stackoverflow.com/questions/3076414/… или другие (например, использование вашего собственного домена в качестве прокси), в зависимости от того, чего вы хотите достичь.
Для записи я просто настроил нечто подобное: если вы не хотите, чтобы результат был невероятно медленным, просто настройте свой веб-сервер для прямого перенаправления запросов ресурсов (CSS / JS / изображения) на исходный веб-сайт, чтобы ваш прокси управляет только HTML-запросами. Я сейчас просматриваю удаленный сайт под localhost, и он абсолютно прозрачен :)
Если <iframe> из того же домена, элементы легко доступны как
$("#iFrame").contents().find("#someDiv").removeClass("hidden");
Знание об одной и той же политике происхождения - это здорово, но это ответ, который делает то, что хотел OP. Почему второй ответ был выбран как правильный?
Вы должны использовать прокси, чтобы получить HTML в вашем origin. Например, johnchapman.name/…
@JasonSwett, я предполагаю, что проблема OP действительно связана с same origin policy, и в этом случае этот ответ не является для него решением.
Что делать, если iframe не имеет идентификатора?
@fizzbuzz Затем вы получаете IFrame так же, как и любой другой контент без идентификатора с помощью jQuery: вы выбираете соответствующий тег <IFrame> с помощью CSS, используя имена классов и значения атрибутов, чтобы сузить его, если это необходимо.
Для iframe не существует метода содержание.
@Yasir Laghari - ссылка на ссылку выше дает предупреждение о вредоносном веб-сайте, когда вы нажимаете на нее! :(
Я заметил, что $("#iframe")[0].contentWindow.document всегда возвращал пустой объект документа в нашем коде, а изменение его на $("#iframe").contents()[0] возвращает правильный объект документа! В моем случае и iframe, и родительская страница были из одного домена.
Я получаю сообщение об ошибке безопасности ... Не удалось прочитать свойство contentDocument из HTMLIFrameElement. Есть ли способ передать его?
Ошибка безопасности: см. Другой ответ о той же политике происхождения. Нет метода contents в iframe: это метод jQuery ... Обратите внимание на $(...)
Для тех, кто задается вопросом, почему это не принятый ответ - обратите внимание на даты. Это произошло через год после того, как был задан вопрос; было бы неплохо, если бы OP изменил принятый ответ, но через 5+ лет это маловероятно. Может быть, вопрос к Мете, если это кого-то беспокоит; Я нашел то, что мне нужно, и проголосовал за.
Вы можете использовать метод jQuery .contents().
The
.contents()method can also be used to get the content document of an iframe, if the iframe is on the same domain as the main page.
$(document).ready(function(){
$('#frameID').load(function(){
$('#frameID').contents().find('body').html('Hey, i`ve changed content of <body>! Yay!!!');
});
});
Мне нужно получить содержимое i-кадра, чтобы не устанавливать тело ..... Когда я делаю это, это не работает, всегда возвращаю пустое тело
@DarkoZ Эм, на самом деле этот ответ пришел первым, так что, во всяком случае, другим ответом была копия
@DarkoZ: оставление исходного комментария не заставило меня стыдить вас, но я потратил около 30 секунд, пытаясь понять, что не является проблемой :) Так что лучше всего удалить всю дискуссию о плагиате.
комментарии удалены во избежание путаницы. извинения.
Если src iframe из другого домена, вы все равно можете это сделать. Вам нужно прочитать внешнюю страницу в PHP и повторить ее из своего домена. Как это:
<?php
$URL = "http://external.com";
$domain = file_get_contents($URL);
echo $domain;
?>
Тогда примерно так:
<html>
<head>
<title>Test</title>
</head>
<script type = "text/javascript" src = "http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
cleanit = setInterval ( "cleaning()", 500 );
});
function cleaning(){
if ($('#frametest').contents().find('.selector').html() == "somthing"){
clearInterval(cleanit);
$('#selector').contents().find('.Link').html('ideate tech');
}
}
</script>
<body>
<iframe name = "frametest" id = "frametest" src = "http://yourdomain.com/iframe_page.php" ></iframe>
</body>
</html>
Выше приведен пример того, как редактировать внешнюю страницу через iframe без отказа в доступе и т. д.
Конечно, поскольку ваш сервер получает удаленную страницу, а не браузер пользователя, файлы cookie не будут отправляться на удаленную страницу. YMMV.
@Mark: вы можете легко отправлять файлы cookie, опубликованные данные, заголовки HTTP и многое другое, если вы реализуете это с расширением curl. php.net/manual/en/book.curl.php
@geon: но браузер не будет отправлять файлы cookie для чужого домена в ваш PHP-скрипт
@Mark: Насколько известно браузеру, чужой домен не задействован. Браузер будет взаимодействовать с сервером ваш (включая файлы cookie, опубликованные данные и заголовки), который, в свою очередь, будет взаимодействовать с чужим доменом. (Если он не использует уловки, такие как установка / чтение файлов cookie изображениями и т. д., Которые можно было бы исправить, проанализировав HTML и перенаправив их через PHP.)
@geon Отметка означает, что браузер не будет отправлять файлы cookie, предназначенные для чужого домена, в ваш домен (например, он не будет отправлять файлы cookie с bank.com на mydomain.com), и поэтому пользователь будет видеть страницу так, как он быть без файлов cookie (т.е. выйти из системы)
@basysmith Будьте внимательны: существует причина, по которой существует same origin policy, и предложение этого ответа не застраховано от нее.
это незаконно?
Я знаю, что это старый поток, но не будет ли этот метод иметь последствия для 1: время загрузки, поскольку сервер сначала загружает внешний URL-адрес, а затем отправляет его клиенту, и 2: для использования данных на вашем собственном хостинге упаковка?
Если вы используете Ruby on Rails, он устанавливает заголовок X-Frame-Options = DENY. Итак, чтобы заставить прокси iFrame добавить response.headers["X-Frame-Options"] = nil в действие прокси
Но разве это не нарушает макет, когда целевая страница имеет неабсолютные URL-адреса и относительные ссылки?
@GerbenVanDijk Да и да. Но иногда это единственный способ ... Однако некоторые сайты предлагают JS API для получения данных структурированным способом, междоменным. В таких случаях вы должны использовать это вместо прокси, чтобы предотвратить проблемы, которые вы упомянули.
Будет ли это работать, если предполагается, что содержимое iframe будет JS?
для новичков в php: ; необходим в операторах iframe_page.php, например. $URL = "http://external.com";
Использовать
iframe.contentWindow.document
вместо
iframe.contentDocument
Отличный ответ. Это работает для iFrames в других доменах. Я пробовал это в консоли Safari и Firefox.
Я считаю, что это будет работать для других доменов, только если вы делаете это с консоли. Из сценария доступ не будет разрешен.
Это должен быть принятый ответ. Спас мне жизнь и работает, когда iframe из другого домена; хотя как уже упоминалось, только в консоли.
у меня iframe.contentWindow.document не всегда работает. и когда это не так, я обнаружил, что $ (elem) .contents (). get (0) делает
вы можете выбрать «корневой документ» в консоли браузера. Когда вы выберете «верхний», это не сработает, так как доступ к разным источникам. Если вы выберете доступ от имени документа iframe, конечно, он предоставит вам доступ. Просто потому, что вы не браузер, а его владелец.
Я нахожу этот способ чище:
var $iframe = $("#iframeID").contents();
$iframe.find('selector');
Спас мою задницу - я сходил с ума, используя "$ (" # iframe "). Contents (). Find ()" по какой-то причине не работал ... то же самое в двух строках. Не знаю почему, но это работает.
Я предпочитаю использовать другой вариант доступа.
От родителя вы можете получить доступ к переменной в дочернем iframe.
$ - тоже переменная, и вы можете получить доступ к ее вызову.
window.iframe_id.$
Например, window.view.$('div').hide() - скрыть все div в iframe с id 'view'
Но в FF это не работает. Для лучшей совместимости вы должны использовать
$('#iframe_id')[0].contentWindow.$
Вы можете использовать window.postMessage для вызова функции между страницей и его iframe (кросс-домен или нет).
page.html
<!DOCTYPE html>
<html>
<head>
<title>Page with an iframe</title>
<meta charset = "UTF-8" />
<script src = "http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
var Page = {
id:'page',
variable:'This is the page.'
};
$(window).on('message', function(e) {
var event = e.originalEvent;
if (window.console) {
console.info(event);
}
alert(event.origin + '\n' + event.data);
});
function iframeReady(iframe) {
if (iframe.contentWindow.postMessage) {
iframe.contentWindow.postMessage('Hello ' + Page.id, '*');
}
}
</script>
</head>
<body>
<h1>Page with an iframe</h1>
<iframe src = "iframe.html" onload = "iframeReady(this);"></iframe>
</body>
</html>
iframe.html
<!DOCTYPE html>
<html>
<head>
<title>iframe</title>
<meta charset = "UTF-8" />
<script src = "http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
var Page = {
id:'iframe',
variable:'The iframe.'
};
$(window).on('message', function(e) {
var event = e.originalEvent;
if (window.console) {
console.info(event);
}
alert(event.origin + '\n' + event.data);
});
$(window).on('load', function() {
if (window.parent.postMessage) {
window.parent.postMessage('Hello ' + Page.id, '*');
}
});
</script>
</head>
<body>
<h1>iframe</h1>
<p>It's the iframe.</p>
</body>
</html>
Я создаю образец кода. Теперь вы можете легко понять, из другого домена вы не можете получить доступ содержимое iframe. В том же домене мы можем получить доступ к содержимому iframe
Я делюсь с вами своим кодом, пожалуйста, запустите этот код проверьте консоль. Я печатаю изображение src на консоли. Есть четыре iframe, два iframe из того же домена и два других из другого домена (стороннего). Вы можете увидеть два изображения src (https://www.google.com/logos/doodles/2015/googles-new-logo-5078286822539264.3-hp2x.gif
а также
https://www.google.com/logos/doodles/2015/arbor-day-2015-brazil-5154560611975168-hp2x.gif ) на консоли, а также можно увидеть две ошибки разрешения ( 2 Ошибка: отказано в доступе к свойству "документ"
... irstChild)}, содержимое: function (a) {return m.nodeName (a, "iframe")? a.contentDocument ...
), который исходит от стороннего iframe.
<body id = "page-top" data-spy = "scroll" data-target = ".navbar-fixed-top">
<p>iframe from same domain</p>
<iframe frameborder = "0" scrolling = "no" width = "500" height = "500"
src = "iframe.html" name = "imgbox" class = "iView">
</iframe>
<p>iframe from same domain</p>
<iframe frameborder = "0" scrolling = "no" width = "500" height = "500"
src = "iframe2.html" name = "imgbox" class = "iView1">
</iframe>
<p>iframe from different domain</p>
<iframe frameborder = "0" scrolling = "no" width = "500" height = "500"
src = "https://www.google.com/logos/doodles/2015/googles-new-logo-5078286822539264.3-hp2x.gif" name = "imgbox" class = "iView2">
</iframe>
<p>iframe from different domain</p>
<iframe frameborder = "0" scrolling = "no" width = "500" height = "500"
src = "http://d1rmo5dfr7fx8e.cloudfront.net/" name = "imgbox" class = "iView3">
</iframe>
<script type='text/javascript'>
$(document).ready(function(){
setTimeout(function(){
var src = $('.iView').contents().find(".shrinkToFit").attr('src');
console.info(src);
}, 2000);
setTimeout(function(){
var src = $('.iView1').contents().find(".shrinkToFit").attr('src');
console.info(src);
}, 3000);
setTimeout(function(){
var src = $('.iView2').contents().find(".shrinkToFit").attr('src');
console.info(src);
}, 3000);
setTimeout(function(){
var src = $('.iView3').contents().find("img").attr('src');
console.info(src);
}, 3000);
})
</script>
</body>
Для большей надежности:
function getIframeWindow(iframe_object) {
var doc;
if (iframe_object.contentWindow) {
return iframe_object.contentWindow;
}
if (iframe_object.window) {
return iframe_object.window;
}
if (!doc && iframe_object.contentDocument) {
doc = iframe_object.contentDocument;
}
if (!doc && iframe_object.document) {
doc = iframe_object.document;
}
if (doc && doc.defaultView) {
return doc.defaultView;
}
if (doc && doc.parentWindow) {
return doc.parentWindow;
}
return undefined;
}
а также
...
var frame_win = getIframeWindow( frames['nameOfMyIframe'] );
if (frame_win) {
$(frame_win.contentDocument || frame_win.document).find('some selector').doStuff();
...
}
...
Я закончил здесь поиском содержимого iframe без jquery, поэтому для всех, кто ищет это, это просто:
document.querySelector('iframe[name=iframename]').contentDocument
Это решение работает так же, как iFrame. Я создал сценарий PHP, который может получать все содержимое с другого веб-сайта, и наиболее важная часть - вы можете легко применить свой собственный jQuery к этому внешнему содержимому. Пожалуйста, обратитесь к следующему сценарию, который может получить все содержимое с другого веб-сайта, а затем вы также можете применить свой cusom jQuery / JS. Этот контент можно использовать где угодно, внутри любого элемента или любой страницы.
<div id='myframe'>
<?php
/*
Use below function to display final HTML inside this div
*/
//Display Frame
echo displayFrame();
?>
</div>
<?php
/*
Function to display frame from another domain
*/
function displayFrame()
{
$webUrl = 'http://[external-web-domain.com]/';
//Get HTML from the URL
$content = file_get_contents($webUrl);
//Add custom JS to returned HTML content
$customJS = "
<script>
/* Here I am writing a sample jQuery to hide the navigation menu
You can write your own jQuery for this content
*/
//Hide Navigation bar
jQuery(\".navbar.navbar-default\").hide();
</script>";
//Append Custom JS with HTML
$html = $content . $customJS;
//Return customized HTML
return $html;
}
Как это будет работать? Если вы добавляете строку $ customJS к $ content, разве у вас не будет элемент сценария ПОСЛЕ закрывающего тега html (внешнего домена)?
Что содержит iFrame - установлен ли его src на другой домен?