简体   繁体   English

jQuery/JavaScript:访问 iframe 的内容

[英]jQuery/JavaScript: accessing contents of an iframe

I would like to manipulate the HTML inside an iframe using jQuery.我想使用 jQuery 操作 iframe 中的 HTML。

I thought I'd be able to do this by setting the context of the jQuery function to be the document of the iframe, something like:我想我可以通过将 jQuery 函数的上下文设置为 iframe 的文档来做到这一点,例如:

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

However this doesn't seem to work.但是,这似乎不起作用。 A bit of inspection shows me that the variables in frames['nameOfMyIframe'] are undefined unless I wait a while for the iframe to load.一些检查表明, frames['nameOfMyIframe']中的变量是undefined除非我等待 iframe 加载一段时间。 However, when the iframe loads the variables are not accessible (I get permission denied -type errors).但是,当 iframe 加载时,变量不可访问(我收到permission denied类型错误)。

Does anyone know of a work-around to this?有谁知道解决这个问题的方法?

If the <iframe> is from the same domain, the elements are easily accessible as如果<iframe>来自同一个域,则元素很容易访问

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

Reference 参考

I think what you are doing is subject to the same origin policy .我认为你正在做的事情受到同源政策的约束。 This should be the reason why you are getting permission denied type errors.这应该是您收到权限被拒绝类型错误的原因。

You could use .contents() method of jQuery.您可以使用 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.如果 iframe 与主页在同一域中,则.contents()方法也可用于获取 iframe 的内容文档。

$(document).ready(function(){
    $('#frameID').load(function(){
        $('#frameID').contents().find('body').html('Hey, i`ve changed content of <body>! Yay!!!');
    });
});

If the iframe src is from another domain you can still do it.如果 iframe src 来自另一个域,您仍然可以这样做。 You need to read the external page into PHP and echo it from your domain.您需要将外部页面读入 PHP 并从您的域中回显它。 Like this:像这样:

iframe_page.php iframe_page.php

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

    $domain = file_get_contents($URL);

    echo $domain;
?>

Then something like this:然后是这样的:

display_page.html 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>

The above is an example of how to edit an external page through an iframe without the access denied etc...以上是如何通过 iframe 编辑外部页面而不拒绝访问等的示例...

I find this way cleaner:我发现这种方式更清洁:

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

Use利用

iframe.contentWindow.document

instead of代替

iframe.contentDocument

You need to attach an event to an iframe's onload handler, and execute the js in there, so that you make sure the iframe has finished loading before accessing it.您需要将事件附加到 iframe 的 onload 处理程序,并在其中执行 js,以便确保 iframe 在访问之前已完成加载。

$().ready(function () {
    $("#iframeID").ready(function () { //The function below executes once the iframe has finished loading
        $('some selector', frames['nameOfMyIframe'].document).doStuff();
    });
};

The above will solve the 'not-yet-loaded' problem, but as regards the permissions, if you are loading a page in the iframe that is from a different domain, you won't be able to access it due to security restrictions.以上将解决“尚未加载”的问题,但关于权限,如果您在 iframe 中加载来自不同域的页面,由于安全限制,您将无法访问它。

You can use window.postMessage to call a function between page and his iframe (cross domain or not).您可以使用 window.postMessage 在页面和他的 iframe 之间调用一个函数(跨域与否)。

Documentation 文档

page.html页面.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 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>

I prefer to use other variant for accessing.我更喜欢使用其他变体进行访问。 From parent you can have a access to variable in child iframe.从父级,您可以访问子 iframe 中的变量。 $ is a variable too and you can receive access to its just call window.iframe_id.$ $也是一个变量,您可以访问它只是调用window.iframe_id.$

For example, window.view.$('div').hide() - hide all divs in iframe with id 'view'例如, window.view.$('div').hide() - 隐藏 iframe 中所有 id 为 'view' 的 div

But, it doesn't work in FF.但是,它在 FF 中不起作用。 For better compatibility you should use为了更好的兼容性,您应该使用

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

I create a sample code .我创建了一个示例代码。 Now you can easily understand from different domain you can't access content of iframe .. Same domain we can access iframe content现在你可以很容易地从不同的域理解你不能访问 iframe 的内容 .. 我们可以访问同一个域的 iframe 内容

I share you my code , Please run this code check the console .我与您分享我的代码,请运行此代码检查控制台。 I print image src at console.我在控制台打印图像 src。 There are four iframe , two iframe coming from same domain & other two from other domain(third party) .You can see two image src( https://www.google.com/logos/doodles/2015/googles-new-logo-5078286822539264.3-hp2x.gif有四个 iframe ,两个 iframe 来自同一个域,另外两个来自其他域(第三方)。您可以看到两个图像 src( https://www.google.com/logos/doodles/2015/googles-new-logo -5078286822539264.3-hp2x.gif

and

https://www.google.com/logos/doodles/2015/arbor-day-2015-brazil-5154560611975168-hp2x.gif ) at console and also can see two permission error( 2 Error: Permission denied to access property 'document' https://www.google.com/logos/doodles/2015/arbor-day-2015-brazil-5154560611975168-hp2x.gif )在控制台,也可以看到两个权限错误(2错误:权限被拒绝访问属性'文档'

...irstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument... ...irstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument...

) which is coming from third party iframe. ) 来自第三方 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>

Have you tried the classic, waiting for the load to complete using jQuery's builtin ready function?您是否尝试过使用 jQuery 的内置就绪函数等待加载完成的经典方法?

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

K

For even more robustness:为了更加稳健:

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;
}

and

...
var frame_win = getIframeWindow( frames['nameOfMyIframe'] );

if (frame_win) {
  $(frame_win.contentDocument || frame_win.document).find('some selector').doStuff();
  ...
}
...

我最终在这里寻找没有 jquery 的 iframe 的内容,所以对于寻找它的其他人来说,就是这样:

document.querySelector('iframe[name=iframename]').contentDocument

This solution works same as iFrame.此解决方案的工作原理与 iFrame 相同。 I have created a PHP script that can get all the contents from the other website, and most important part is you can easily apply your custom jQuery to that external content.我创建了一个 PHP 脚本,可以从其他网站获取所有内容,最重要的部分是您可以轻松地将自定义 jQuery 应用于该外部内容。 Please refer to the following script that can get all the contents from the other website and then you can apply your cusom jQuery/JS as well.请参考以下脚本,可以从其他网站获取所有内容,然后您也可以应用您的自定义 jQuery/JS。 This content can be used anywhere, inside any element or any page.此内容可以在任何元素或任何页面内的任何地方使用。

<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;
}

If the code below doesn't work如果下面的代码不起作用

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

Here is the reliable way to make it work:这是使其工作的可靠方法:

$(document).ready(function(){ 
  setTimeout(
    function () {
      $("#iFrame").contents().find("#someDiv").removeClass("hidden");
    },
    300
  );
});

This way the script will run after 300 miliseconds, so it'll get enough time for iFrame to be loaded and then the code will come into action.这样脚本将在 300 毫秒后运行,因此它将有足够的时间加载iFrame ,然后代码将开始运行。 At times the iFrame doesn't load and script tries to execute before it.有时iFrame不会加载,脚本会尝试在它之前执行。 300ms can be tweaked to anything else as per your needs. 300ms可以根据您的需要调整为任何其他内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM