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

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

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

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

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

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

Что содержит iFrame - установлен ли его src на другой домен?

James 14.12.2008 03:32

если это другой домен, есть ли еще способ получить доступ к его содержимому или зарегистрировать событие

adardesign 01.10.2009 19:59

Нет, потому что это будет межсайтовый скриптинг, что запрещено по соображениям безопасности. Мое решение состояло в том, чтобы использовать прокси: дословно передать HTML в IFRAME через мой собственный сайт, чтобы он больше не был межсайтовым с точки зрения браузера.

reinierpost 06.04.2010 12:10

Использование .contentWindow.document в элементе .document более кроссбраузерно, чем iframe. Я предлагаю изменение, указанное выше.

Alan H. 09.07.2011 00:04

один из способов - хромированные расширения

Muhammad Umer 16.04.2013 17:14
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
818
5
682 800
14
Перейти к ответу Данный вопрос помечен как решенный

Ответы 14

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

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

K

да. Функция готовности начинает выполняться, когда загружается основной фрейм, а не когда загружается iframe. Однако ожидание, похоже, - небольшая часть проблемы. Я думаю, это связано с междоменной безопасностью.

rz. 13.12.2008 11:07

Вам нужно прикрепить событие к обработчику 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)

rz. 13.12.2008 11:16

на самом деле ... неважно, кажется, что ожидание все еще требуется, даже когда это делается.

rz. 13.12.2008 11:20

Готовая функция работает. Однако кажется, что он не дожидается завершения загрузки содержимого iframe - только для родительского документа, даже когда он вызывается для содержимого самого iframe. Я полагаю, что это также из-за той же политики происхождения.

rz. 15.12.2008 02:15

Несколько замечаний по этому коду: вы должны использовать iframe.contentDocument вместо .document, и вы должны использовать .load () вместо .ready (), чтобы избежать ожидания. (Не идеально, но лучше)

Rodrigo Queiro 28.07.2009 02:55
Ответ принят как подходящий

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

@Pacerier Лучше всего проксировать содержимое iframe на вашем сайте, если вы можете ...

Tracker1 28.02.2012 23:50

@ Tracker1: Можете ли вы предложить какой-либо шаблон проектирования / api / framework для реализации этого прокси-решения. Есть ссылки на пример или учебник и т. д.? Я пытался поискать, но не нашел.

Umer Hayat 27.06.2012 16:26

В этом случае он имеет в виду использовать http-сервер, который обслуживает страницу вашего домена, в качестве прокси-сервера - запросить контент со стороннего сайта и переслать его в http-ответе клиенту. Как вы, вероятно, догадались, это быстро влияет на скорость отклика вашего сайта, поскольку ранее параллельные запросы вместо этого выполняются последовательно с вашим сервером, что является потенциальным узким местом.

rutherford 06.03.2013 02:12

@Pacerier. Возможно любой из методов в принятом ответе здесь: stackoverflow.com/questions/3076414/… или другие (например, использование вашего собственного домена в качестве прокси), в зависимости от того, чего вы хотите достичь.

Mark Amery 04.08.2013 13:09

Для записи я просто настроил нечто подобное: если вы не хотите, чтобы результат был невероятно медленным, просто настройте свой веб-сервер для прямого перенаправления запросов ресурсов (CSS / JS / изображения) на исходный веб-сайт, чтобы ваш прокси управляет только HTML-запросами. Я сейчас просматриваю удаленный сайт под localhost, и он абсолютно прозрачен :)

neemzy 07.10.2013 14:16

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

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

Справка

Знание об одной и той же политике происхождения - это здорово, но это ответ, который делает то, что хотел OP. Почему второй ответ был выбран как правильный?

Jason Swett 24.11.2010 18:53

Вы должны использовать прокси, чтобы получить HTML в вашем origin. Например, johnchapman.name/…

mhenry1384 18.05.2011 00:12

@JasonSwett, я предполагаю, что проблема OP действительно связана с same origin policy, и в этом случае этот ответ не является для него решением.

ANeves thinks SE is evil 04.11.2011 17:38

Что делать, если iframe не имеет идентификатора?

Aman Aggarwal 08.02.2012 11:23

@fizzbuzz Затем вы получаете IFrame так же, как и любой другой контент без идентификатора с помощью jQuery: вы выбираете соответствующий тег <IFrame> с помощью CSS, используя имена классов и значения атрибутов, чтобы сузить его, если это необходимо.

Auspex 20.04.2012 23:36

Для iframe не существует метода содержание.

Geeky Guy 24.07.2013 21:57

@Yasir Laghari - ссылка на ссылку выше дает предупреждение о вредоносном веб-сайте, когда вы нажимаете на нее! :(

Jonathan Marzullo 20.11.2013 18:42

Я заметил, что $("#iframe")[0].contentWindow.document всегда возвращал пустой объект документа в нашем коде, а изменение его на $("#iframe").contents()[0] возвращает правильный объект документа! В моем случае и iframe, и родительская страница были из одного домена.

pwnsauce 21.11.2013 23:21

Я получаю сообщение об ошибке безопасности ... Не удалось прочитать свойство contentDocument из HTMLIFrameElement. Есть ли способ передать его?

Kremena Lalova 16.04.2014 17:43

Ошибка безопасности: см. Другой ответ о той же политике происхождения. Нет метода contents в iframe: это метод jQuery ... Обратите внимание на $(...)

Stijn de Witt 12.09.2014 15:58

Для тех, кто задается вопросом, почему это не принятый ответ - обратите внимание на даты. Это произошло через год после того, как был задан вопрос; было бы неплохо, если бы OP изменил принятый ответ, но через 5+ лет это маловероятно. Может быть, вопрос к Мете, если это кого-то беспокоит; Я нашел то, что мне нужно, и проголосовал за.

brichins 06.10.2015 06:01

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

George Hanna 20.06.2012 13:33

@DarkoZ Эм, на самом деле этот ответ пришел первым, так что, во всяком случае, другим ответом была копия

michaelpri 27.05.2015 04:54

@DarkoZ: оставление исходного комментария не заставило меня стыдить вас, но я потратил около 30 секунд, пытаясь понять, что не является проблемой :) Так что лучше всего удалить всю дискуссию о плагиате.

Dan Dascalescu 30.06.2015 00:01

комментарии удалены во избежание путаницы. извинения.

Darko Z 30.06.2015 10:33

Если src iframe из другого домена, вы все равно можете это сделать. Вам нужно прочитать внешнюю страницу в 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 без отказа в доступе и т. д.

Конечно, поскольку ваш сервер получает удаленную страницу, а не браузер пользователя, файлы cookie не будут отправляться на удаленную страницу. YMMV.

Mark Fowler 03.11.2010 10:10

@Mark: вы можете легко отправлять файлы cookie, опубликованные данные, заголовки HTTP и многое другое, если вы реализуете это с расширением curl. php.net/manual/en/book.curl.php

geon 16.02.2011 17:56

@geon: но браузер не будет отправлять файлы cookie для чужого домена в ваш PHP-скрипт

ysth 20.02.2011 23:46

@Mark: Насколько известно браузеру, чужой домен не задействован. Браузер будет взаимодействовать с сервером ваш (включая файлы cookie, опубликованные данные и заголовки), который, в свою очередь, будет взаимодействовать с чужим доменом. (Если он не использует уловки, такие как установка / чтение файлов cookie изображениями и т. д., Которые можно было бы исправить, проанализировав HTML и перенаправив их через PHP.)

geon 22.02.2011 13:05

@geon Отметка означает, что браузер не будет отправлять файлы cookie, предназначенные для чужого домена, в ваш домен (например, он не будет отправлять файлы cookie с bank.com на mydomain.com), и поэтому пользователь будет видеть страницу так, как он быть без файлов cookie (т.е. выйти из системы)

Justin 24.02.2011 05:07

@basysmith Будьте внимательны: существует причина, по которой существует same origin policy, и предложение этого ответа не застраховано от нее.

ANeves thinks SE is evil 04.11.2011 17:34

это незаконно?

Tallboy 13.02.2012 10:17

Я знаю, что это старый поток, но не будет ли этот метод иметь последствия для 1: время загрузки, поскольку сервер сначала загружает внешний URL-адрес, а затем отправляет его клиенту, и 2: для использования данных на вашем собственном хостинге упаковка?

Gerben Van Dijk 08.10.2012 15:57

Если вы используете Ruby on Rails, он устанавливает заголовок X-Frame-Options = DENY. Итак, чтобы заставить прокси iFrame добавить response.headers["X-Frame-Options"] = nil в действие прокси

Sergey Makridenkov 04.04.2013 12:05

Но разве это не нарушает макет, когда целевая страница имеет неабсолютные URL-адреса и относительные ссылки?

Mori 29.11.2013 10:53

@GerbenVanDijk Да и да. Но иногда это единственный способ ... Однако некоторые сайты предлагают JS API для получения данных структурированным способом, междоменным. В таких случаях вы должны использовать это вместо прокси, чтобы предотвратить проблемы, которые вы упомянули.

Stijn de Witt 12.09.2014 16:01

Будет ли это работать, если предполагается, что содержимое iframe будет JS?

W1ldworm 13.03.2017 07:05

для новичков в php: ; необходим в операторах iframe_page.php, например. $URL = "http://external.com";

XoXo 30.09.2017 11:22

Использовать

iframe.contentWindow.document

вместо

iframe.contentDocument

Отличный ответ. Это работает для iFrames в других доменах. Я пробовал это в консоли Safari и Firefox.

Aneil Mallavarapu 27.12.2010 03:04

Я считаю, что это будет работать для других доменов, только если вы делаете это с консоли. Из сценария доступ не будет разрешен.

yincrash 31.05.2011 19:58

Это должен быть принятый ответ. Спас мне жизнь и работает, когда iframe из другого домена; хотя как уже упоминалось, только в консоли.

silkfire 26.02.2014 12:47

у меня iframe.contentWindow.document не всегда работает. и когда это не так, я обнаружил, что $ (elem) .contents (). get (0) делает

elewinso 22.11.2018 16:02

вы можете выбрать «корневой документ» в консоли браузера. Когда вы выберете «верхний», это не сработает, так как доступ к разным источникам. Если вы выберете доступ от имени документа iframe, конечно, он предоставит вам доступ. Просто потому, что вы не браузер, а его владелец.

Sergei Kovalenko 03.09.2019 10:34

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

var $iframe = $("#iframeID").contents();
$iframe.find('selector');

Спас мою задницу - я сходил с ума, используя "$ (" # iframe "). Contents (). Find ()" по какой-то причине не работал ... то же самое в двух строках. Не знаю почему, но это работает.

neminem 13.06.2019 00:26

Я предпочитаю использовать другой вариант доступа. От родителя вы можете получить доступ к переменной в дочернем 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 (внешнего домена)?

ultrageek 09.08.2020 09:12

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