JQuery / JavaScript: доступ к содержимому iframe

Я хотел бы манипулировать HTML внутри iframe, используя jQuery.

Я думал, что смогу сделать это, установив контекст функции jQuery как документ iframe, что-то вроде:

$(function(){ //document ready
    $('some selector', frames['nameOfMyIframe'].document).doStuff()
});

Однако это не похоже на работу. Немного осмотра показывает, что переменные в frames['nameOfMyIframe'], undefinedесли я подожду, пока загрузится iframe. Однако, когда iframe загружает переменные не доступны (я получаю permission deniedошибки -типа).

Кто-нибудь знает обойти это?

13.12.2008 07:20:34
Что содержит iFrame - установлен ли src для другого домена?
James 14.12.2008 00:32:51
если это другой домен, есть ли еще способ получить доступ к его контенту или зарегистрировать событие
adardesign 1.10.2009 15:59:04
Нет, потому что это будет межсайтовый скриптинг, который запрещен по соображениям безопасности. Мое решение состояло в том, чтобы использовать прокси-сервер: передать HTML-код в IFRAME через мой собственный сайт, чтобы он больше не был межсайтовым с точки зрения браузера.
reinierpost 6.04.2010 08:10:23
Это больше кросс-браузер для использования, .contentWindow.documentчем .documentна iframeэлементе. Я предложу изменить выше.
Alan H. 8.07.2011 20:04:03
Одним из способов является расширение Chrome
Muhammad Umer 16.04.2013 13:14:45
14 ОТВЕТОВ
РЕШЕНИЕ

Я думаю, что то, что вы делаете, подчиняется той же политике происхождения . Это должно быть причиной, по которой вы получаете ошибки типа «отказано в разрешении» .

382
13.12.2008 14:14:03
@Pacerier Лучше всего проксировать содержимое iframe на вашем сайте, если вы можете ...
Tracker1 28.02.2012 19:50:18
@ Tracker1: Можете ли вы предложить какой-либо фреймворк / API / шаблон проектирования для реализации этого прокси-решения. Любые ссылки на пример или учебник и т. Д.? Я пытался найти, но не смог найти.
Umer Hayat 27.06.2012 12:26:35
В этом случае он подразумевает использование http-сервера, который обслуживает страницу вашего домена, в качестве прокси-сервера - запросите контент со стороннего сайта и перенаправьте его в http-ответ клиенту. Как вы, вероятно, можете догадаться, это быстро влияет на скорость отклика вашего сайта, поскольку ранее параллельные запросы вместо этого выполняются последовательно с вашим сервером как потенциальное узкое место.
rutherford 5.03.2013 22:12:54
@Pacerier Потенциально любой из методов в принятом ответе здесь: stackoverflow.com/questions/3076414/… или другие (например, использование собственного домена в качестве прокси-сервера), в зависимости от того, чего вы хотите достичь.
Mark Amery 4.08.2013 09:09:56
Для справки, я просто настроил что-то похожее: если вы не хотите, чтобы результат был невероятно медленным, просто настройте свой веб-сервер так, чтобы он перенаправлял запросы ресурсов (CSS / JS / images) на исходный сайт, поэтому ваш прокси только управляет запросами HTML. Я просматриваю удаленный сайт под localhost прямо сейчас, и он абсолютно прозрачен :)
neemzy 7.10.2013 10:16:31

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

$(document).ready(function() {
    $('some selector', frames['nameOfMyIframe'].document).doStuff()
} );

К

2
13.12.2008 08:06:29
Да. Функция готовности начинает выполняться при загрузке основного кадра, а не при загрузке iframe. Ожидание, кажется, небольшая часть проблемы, все же. Я думаю, что это связано с междоменной безопасностью.
rz. 13.12.2008 08:07:49

Вам необходимо прикрепить событие к обработчику загрузки 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 из другого домена, вы не сможете получить к ней доступ из-за ограничений безопасности.

26
13.12.2008 08:22:16
это хорошая идея, на самом деле я пытался это так же, как вы ответили. Тем не менее, это не работает в отношении разрешения «отказано» (оно касается того, что мне нужно ждать перед началом доступа к элементу iframe)
rz. 13.12.2008 08:16:30
на самом деле ... неважно, кажется, что ожидание все еще требуется, даже при этом.
rz. 13.12.2008 08:20:07
Готовая функция работает. Однако, похоже, что он не ждет окончания загрузки содержимого iframe - только для родительского документа, даже если он вызывается для содержимого самого iframe. Я предполагаю, что это также из-за той же политики происхождения.
rz. 14.12.2008 23:15:30
Несколько замечаний по этому коду: вы должны использовать iframe.contentDocument вместо .document, и вы должны использовать .load () вместо .ready (), чтобы избежать ожидания. (Не идеально, но лучше)
Rodrigo Queiro 27.07.2009 22:55:17

Если <iframe>это из того же домена, элементы легко доступны как

$("#iFrame").contents().find("#someDiv").removeClass("hidden");

Ссылка

981
30.07.2015 17:51:05
Знать об одной и той же политике происхождения - это здорово, но это ответ, который делает то, что хотел ОП. Почему другой ответ был выбран как правильный?
Jason Swett 24.11.2010 15:53:25
Вы должны использовать прокси, чтобы получить HTML в вашем источнике. Например, johnchapman.name/…
mhenry1384 17.05.2011 20:12:01
@JasonSwett, я предполагаю, что проблема ОП - действительно same origin policy, и в этом случае этот ответ не является для него решением.
ANeves 4.11.2011 13:38:23
@fizzbuzz Затем вы получаете IFrame точно так же, как и любой другой контент без идентификатора с jQuery: вы выбираете соответствующий тег <IFrame> с CSS, используя имена классов и значения атрибутов, чтобы сузить его при необходимости.
Auspex 20.04.2012 19:36:57
Там нет никакого метода называется содержимым для фрейма.
Renan 24.07.2013 17:57:39

Вы можете использовать .contents()метод jQuery.

Этот .contents()метод также можно использовать для получения документа содержимого iframe, если iframe находится в том же домене, что и главная страница.

$(document).ready(function(){
    $('#frameID').load(function(){
        $('#frameID').contents().find('body').html('Hey, i`ve changed content of <body>! Yay!!!');
    });
});
86
9.09.2019 10:12:34
мне нужно получить содержимое фрейма i, чтобы не устанавливать тело ..... Когда я делаю вышеописанное, оно не работает, всегда возвращайте пустое тело
George Hanna 20.06.2012 09:33:29
@DarkoZ Хм, на самом деле этот ответ пришел первым, так что, если что, другим ответом была копия
michaelpri 27.05.2015 01:54:54
@DarkoZ: оставив исходный комментарий, я вас не опозорил, но я потратил впустую, как 30 секунд, пытаясь понять несущественную проблему :) Так что удаление всей этой дискуссии о плагиатизирующем ответе может быть лучшим.
Dan Dascalescu 29.06.2015 21:01:39
комментарии удалены, чтобы избежать путаницы. Извинения.
Darko Z 30.06.2015 07:33:26

Если iframe src из другого домена, вы все равно можете это сделать. Вам нужно прочитать внешнюю страницу в PHP и отобразить ее с вашего домена. Нравится:

iframe_page.php

<?php
    $URL = "http://external.com";

    $domain = file_get_contents($URL);

    echo $domain;
?>

Тогда как то так:

display_page.html

<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 без доступа и т.д.

43
12.11.2019 16:17:32
Конечно, поскольку ваш сервер получает удаленную страницу, а не браузер пользователя, файлы cookie не будут отправляться на удаленную страницу. YMMV.
Mark Fowler 3.11.2010 07:10:01
@Mark: вы можете легко отправлять файлы cookie, размещенные данные, HTTP-заголовки и еще много чего, если внедрите их с расширением curl. php.net/manual/en/book.curl.php
geon 16.02.2011 14:56:10
@geon: но браузер не будет отправлять куки для внешнего домена на ваш PHP скрипт
ysth 20.02.2011 20:46:04
@basysmith Будьте внимательны: существует причина, по которой same origin policyсуществует, и предложение этого ответа не застраховано от него.
ANeves 4.11.2011 13:34:14
это незаконно в любом случае?
Tallboy 13.02.2012 06:17:25

использование

iframe.contentWindow.document

вместо

iframe.contentDocument
30
30.07.2015 19:15:50
Отличный ответ. Это работает для iFrames в других доменах. Я попробовал это в консоли на Safari и Firefox.
Aneil Mallavarapu 27.12.2010 00:04:05
Я считаю, что это будет работать только для других доменов, если вы делаете это с консоли. Из скрипта доступ не будет разрешен.
yincrash 31.05.2011 15:58:47
Это должен быть принятый ответ. Спасла мою жизнь и работает, когда iframe из другого домена; хотя, как уже упоминалось, только в консоли.
silkfire 26.02.2014 08:47:58
для меня iframe.contentWindow.document не всегда работает. и когда это не так, я обнаружил, что $ (elem) .contents (). get (0) делает
elewinso 22.11.2018 13:02:13
Вы можете выбрать «корневой документ» в консоли браузера. Когда вы выбираете "top", он не будет работать, как доступ к другим источникам. Если вы решите получить доступ от имени документа iframe, конечно, он предоставит вам доступ. Просто потому, что вы не браузер, а владелец браузера.
Sergei Kovalenko 3.09.2019 07:34:04

Я нахожу этот способ чище:

var $iframe = $("#iframeID").contents();
$iframe.find('selector');
32
6.01.2017 12:00:29
Спасла мою задницу - я сходил с ума, используя "$ (" # iframe "). Contents (). Find ()" по какой-то причине не работало ... То же самое делали две строки. Не знаю почему, но это работает.
neminem 12.06.2019 21:26:42

Я предпочитаю использовать другой вариант для доступа. Из parent вы можете получить доступ к переменной в дочернем iframe. $переменная тоже, и вы можете получить доступ к ее просто вызову window.iframe_id.$

Например, window.view.$('div').hide()- скрыть все div в iframe с идентификатором 'view'

Но это не работает в FF. Для лучшей совместимости вы должны использовать

$('#iframe_id')[0].contentWindow.$

4
29.12.2013 22:37:11

Вы можете использовать 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.log(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.log(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>
21
26.02.2016 15:38:04

Я создаю пример кода. Теперь вы можете легко понять из другого домена, что вы не можете получить доступ к контенту 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.log(src);
         }, 2000);


    setTimeout(function(){


        var src = $('.iView1').contents().find(".shrinkToFit").attr('src');
    console.log(src);
         }, 3000);


    setTimeout(function(){


        var src = $('.iView2').contents().find(".shrinkToFit").attr('src');
    console.log(src);
         }, 3000);

         setTimeout(function(){


        var src = $('.iView3').contents().find("img").attr('src');
    console.log(src);
         }, 3000);


    })


</script>
</body>
2
24.09.2015 09:29:04

Для еще большей надежности:

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();
  ...
}
...
0
31.10.2018 21:50:22

Я остановился здесь на поиске содержимого iframe без jquery, так что для всех, кто ищет это, именно так:

document.querySelector('iframe[name=iframename]').contentDocument
1
30.12.2018 23:42:00

Это решение работает так же, как 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;
}
1
15.01.2019 11:06:28