By rz.


2008-12-13 07:20:34 8 Comments

I would like to manipulate the HTML inside an iframe using jQuery.

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:

$(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. However, when the iframe loads the variables are not accessible (I get permission denied-type errors).

Does anyone know of a work-around to this?

11 comments

@zupa 2012-08-03 19:17:51

I find this way cleaner:

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

@B.Asselin 2014-02-02 14:34:25

You can use window.postMessage to call a function between page and his iframe (cross domain or not).

Documentation

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>

@Zisu 2015-09-24 09:29:04

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

I share you my code , Please run this code check the console . I print image src at console. 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

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'

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

) which is coming from third party 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>

@user 2010-12-02 10:20:33

Use

iframe.contentWindow.document

instead of

iframe.contentDocument

@Aneil Mallavarapu 2010-12-27 00:04:05

Great answer. This works for iFrames in other domains. I tried this in the console on Safari and Firefox.

@yincrash 2011-05-31 15:58:47

I believe it will only work for other domains if you're doing it from the console. From a script, access will not be allowed.

@silkfire 2014-02-26 08:47:58

This should be the accepted answer. Saved my life and works when the iframe is from a different domain; although as mentioned, only in the console.

@Daniel Sokolowski 2015-01-30 02:16:55

Or a 'bookmarklet' - en.wikipedia.org/wiki/Bookmarklet

@cregox 2015-05-11 20:40:49

Nowadays, it doesn't work even from console

@Yasir Laghari 2009-10-28 18:54:19

If the <iframe> is from the same domain, the elements are easily accessible as

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

Reference

@Jason Swett 2010-11-24 15:53:25

Knowing about the same origin policy is great but this is the answer that does what the OP wanted. Why did the other answer get picked as the right one?

@mhenry1384 2011-05-17 20:12:01

You have to use a proxy to get the HTML in your origin. For example, johnchapman.name/…

@ANeves 2011-11-04 13:38:23

@JasonSwett, my guess is that OP's problem is indeed the same origin policy, in which case this answer is not a solution for him.

@fizzbuzz 2012-02-08 07:23:28

What if the iframe has no "id" ?

@Auspex 2012-04-20 19:36:57

@fizzbuzz Then you get the IFrame the same way you'd get any other id-less content with jQuery: you select the appropriate <IFrame> tag with CSS, using class names and attribute values to narrow it down if necessary.

@Renan 2013-07-24 17:57:39

There is no method called contents for the iframe.

@Jonathan Marzullo 2013-11-20 14:42:09

@Yasir Laghari the reference link above gives a malicious website warning when you click on it! :(

@pwnsauce 2013-11-21 19:21:27

I noticed $("#iframe")[0].contentWindow.document which was always returning an empty document object in our code, changing it to $("#iframe").contents()[0] returns the correct document object! In my case, both the iframe and parent page were from the same domain.

@Kremena Lalova 2014-04-16 13:43:31

I am getting a security error... Failed to read the 'contentDocument' property from 'HTMLIFrameElement' Is there a way to pass it?

@Stijn de Witt 2014-09-12 11:58:44

Security error: See other answer about same origin policy. No method contents on iframe: It's a jQuery method... Notice the $(...)

@brichins 2015-10-06 03:01:40

For anyone wondering about why this isn't the accepted answer - note the dates. This came a year after the question was asked; would be nice if OP would change the accepted answer, but 5+ years on it's not likely. May be a question for Meta if it bothers anyone; I found what I needed and upvoted.

@Evgeny Karpov 2012-09-02 15:21:04

I prefer to use other variant for accessing. From parent you can have a access to variable in child iframe. $ is a variable too and you can receive access to its just call window.iframe_id.$

For example, window.view.$('div').hide() - hide all divs in iframe with id 'view'

But, it doesn't work in FF. For better compatibility you should use

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

@basysmith 2010-06-27 10:15:18

If the iframe src is from another domain you can still do it. You need to read the external page into PHP and echo it from your domain. Like this:

iframe_page.php

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

    $domain = file_get_contents($URL)

    echo $domain
?>

Then something like this:

display_page.html

<html>
<head>
  <title>Test</title>
 </head>
<script type="text/javascript" src="//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...

@Mark Fowler 2010-11-03 07:10:01

Of course, because your server is getting the remote page not the user's browser, no cookies will be sent to the remote page. YMMV.

@geon 2011-02-16 14:56:10

@Mark: You can easily send cookies, posted data, HTTP headers and whatnot if you implement it with the curl extension. php.net/manual/en/book.curl.php

@ysth 2011-02-20 20:46:04

@geon: but the browser won't send cookies for the foreign domain to your PHP script

@geon 2011-02-22 10:05:58

@Mark: As far as the browser knows, no foreign domain is involved. The browser will talk to your server (including cookies, posted data and headers), which will in turn talk to the foreign domain. (Unless it uses tricks like cookies set/read by images, etc, which could be fixed by parsing the HTML and routing them through PHP as well.)

@Justin 2011-02-24 02:07:27

@geon What Mark means is that the browser won't send any cookies intended for the foreign domain to your domain, (for example it wouldn't send cookies from bank.com to mydomain.com), and so the user will see the page as it would be without cookies (ie. logged out)

@ANeves 2011-11-04 13:34:14

@basysmith Be mindful: there is a reason why the same origin policy exists, and this answer's proposal is not immune to it.

@Tallboy 2012-02-13 06:17:25

is it illegal in any way to do this?

@Gerben Van Dijk 2012-10-08 11:57:28

I know it's an old thread, but won't this method have consequenses for the 1: the loading time, as the server first loads an external url and then sends it to the client, and 2: for the data usage of your own hosting package?

@msa7 2013-04-04 08:05:23

If you on Ruby on Rails it set header X-Frame-Options=DENY. So to make iFrame proxy add response.headers["X-Frame-Options"] = nil to proxy action

@Mori 2013-11-29 06:53:02

But doesn't it break the layout when the target page has non-absolute URLs and relative links?

@Stijn de Witt 2014-09-12 12:01:15

@GerbenVanDijk Yes and yes. But sometimes it's the only way... Some sites however offer JS API's to get data in a structured way, cross-domain. In such cases you should use that instead of proxying to prevent the issues you mentioned

@W1ldworm 2017-03-13 04:05:28

Would this work when the content of iframe is supposed to be JS?

@Jeff Xiao 2017-09-30 08:22:54

to php newbies: ; is needed in statements in iframe_page.php, e.g. $URL = "http://external.com";

@davryusha 2010-04-02 18:27:46

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

@George Hanna 2012-06-20 09:33:29

i need to get the i frame content not to set the body ..... When i do the above it doesn't works always return empty Body

@michaelpri 2015-05-27 01:54:54

@DarkoZ Um, actually this answer came first, so if anything, the other answer was the copy

@Dan Dascalescu 2015-06-29 21:01:39

@DarkoZ: leaving the original comment didn't make me shame you, but I did waste like 30 seconds trying to understand a non-issue :) So removing this whole discussion about a plagiarizing answer might be best.

@Darko Z 2015-06-30 07:33:26

comments removed to prevent confusion. apologies.

@Onur Bebin 2008-12-13 08:25:40

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.

@Pacerier 2011-09-09 16:39:24

so what's the workaround solution ?

@Tracker1 2012-02-28 19:50:18

@Pacerier Best bet is to proxy the content of the iframe on your site, if you can...

@Umer Hayat 2012-06-27 12:26:35

@Tracker1: Can you suggest any framework/api/design pattern for implementing this proxy solution. Any links to example or tutorial etc? I have tried to search but couldn't find any.

@rutherford 2013-03-05 22:12:54

In this case, he means use the http server that is serving your domain's page as the proxy - request the content from the 3rd party site and forward it on in the http response to the client. As you can probably guess, it quickly impacts the responsiveness of your site as previously parallel requests are instead executed in series with your server as a potential bottleneck.

@Mark Amery 2013-08-04 09:09:56

@Pacerier Potentially any of the methods in the accepted answer here: stackoverflow.com/questions/3076414/… or others (like using your own domain as a proxy), depending upon what you want to achieve.

@neemzy 2013-10-07 10:16:31

For the record, I just set up something similar : if you don't want the result to be incredibly slow, just set up your web server to directly reroute asset requests (CSS/JS/images) to the original website, so your proxy only manages HTML requests. I'm browsing a distant site under localhost right now and it's absolutely transparent :)

@Andreas Grech 2008-12-13 08:11:29

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.

$().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.

@rz. 2008-12-13 08:16:30

this is a good idea, in fact I was trying it just as you answered. However, it doesn't work around the permission denied (it does address my having to wait before starting to access the iframe stuff)

@rz. 2008-12-13 08:20:07

actually... nevermind, it seems that the wait is still required even when doing this.

@Salamander2007 2008-12-13 22:05:59

Sooo... the ready function doesn't work?

@rz. 2008-12-14 23:15:30

The ready function works. However, it seems that it doesn't wait for the contents of the iframe to finish loading -- only for the parent document even when invoked on the contents of the iframe itself. I imagine it is also because of the same origin policy.

@Rodrigo Queiro 2009-07-27 22:55:17

A couple of notes on this code: you should use iframe.contentDocument instead of .document, and you should use .load() instead of .ready() to avoid the wait. (Not perfect, but better)

@CHI Coder 007 2013-03-28 16:34:39

@RodrigoQueiro Which usage of ready should be load? Both?

@Khb 2008-12-13 08:06:29

Have you tried the classic, waiting for the load to complete using jQuery's builtin ready function?

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

K

@rz. 2008-12-13 08:07:49

Yes. The ready function starts executing when the main frame is loaded -- not when the iframe is loaded. The wait seems to be a small part of the problem, though. I think it has to do with cross-domain security.

Related Questions

Sponsored Content

38 Answered Questions

[SOLVED] Setting "checked" for a checkbox with jQuery?

26 Answered Questions

65 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 4791560 View
  • 6026 Score
  • 65 Answer
  • Tags:   javascript arrays

49 Answered Questions

[SOLVED] How do I check if an element is hidden in jQuery?

88 Answered Questions

[SOLVED] How do JavaScript closures work?

52 Answered Questions

[SOLVED] How do I include a JavaScript file in another JavaScript file?

34 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

48 Answered Questions

15 Answered Questions

[SOLVED] "Thinking in AngularJS" if I have a jQuery background?

Sponsored Content