[javascript] Nested iframes, AKA Iframe Inception

Using jQuery I am trying to access div id="element".

<body>
    <iframe id="uploads">
        <iframe>
            <div id="element">...</div>
        </iframe>
    </iframe>
</body>

All iframes are on the same domain with no www / non-www issues.

I have successfully selected elements within the first iframe but not the second nested iframe.

I have tried a few things, this is the most recent (and a pretty desperate attempt).

var iframe = jQuery('#upload').contents();
var iframeInner = jQuery(iframe).find('iframe').contents();
var iframeContent = jQuery(iframeInner).contents().find('#element');

// iframeContent is null

Edit: To rule out a timing issue I used a click event and waited a while.

jQuery().click(function(){
   var iframe = jQuery('#upload').contents().find('iframe');
   console.log(iframe.find('#element')); // [] null
});

Any ideas? Thanks.

Update: I can select the second iframe like so...

var iframe = jQuery('#upload').contents().find('iframe');

The problem now seems to be that the src is empty as the iframe is generated with javascript. So the iframe is selected but the content length is 0.

This question is related to javascript jquery iframe

The answer is


Hey I got something that seems to be doing what you want a do. It involves some dirty copying but works. You can find the working code here

So here is the main html file :

<!DOCTYPE html>
<html>
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

    <script type="text/javascript">
        $(document).ready(function(){
            Iframe = $('#frame1');

            Iframe.on('load', function(){
                IframeInner = Iframe.contents().find('iframe');

                IframeInnerClone = IframeInner.clone();

                IframeInnerClone.insertAfter($('#insertIframeAfter')).css({display:'none'});

                IframeInnerClone.on('load', function(){
                    IframeContents = IframeInner.contents();

                    YourNestedEl = IframeContents.find('div');

                    $('<div>Yeepi! I can even insert stuff!</div>').insertAfter(YourNestedEl)
                });
            });
        });
    </script>
</head>
<body>
    <div id="insertIframeAfter">Hello!!!!</div>
    <iframe id="frame1" src="Test_Iframe.html">

    </iframe>
</body>
</html>

As you can see, once the first Iframe is loaded, I get the second one and clone it. I then reinsert it in the dom, so I can get access to the onload event. Once this one is loaded, I retrieve the content from non-cloned one (must have loaded as well, since they use the same src). You can then do wathever you want with the content.

Here is the Test_Iframe.html file :

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div>Test_Iframe</div>
    <iframe src="Test_Iframe2.html">
    </iframe>
</body>
</html>

and the Test_Iframe2.html file :

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div>I am the second nested iframe</div>
</body>
</html>

You should use live method for elements which are rendered later, like colorbox, hidden fields or iframe

$(".inverter-value").live("change",function() {
     elem = this
    $.ajax({
      url: '/main/invertor_attribute/',
      type: 'POST',
      aysnc: false,
      data: {id: $(this).val() },
      success: function(data){
       // code
      },
      dataType: 'html'
    });
  });

var iframeInner = jQuery(iframe).find('iframe').contents();

var iframeContent = jQuery(iframeInner).contents().find('#element');

iframeInner contains elements from

<div id="element">other markup goes here</div> 

and iframeContent will find for elements which are inside of

 <div id="element">other markup goes here</div> 

(find doesn't search on current element) that's why it is returning null.


I guess your problem is that jQuery is not loaded in your iframes.

The safest approach is to rely on pure DOM-based methods to parse your content.

Or else, start with jQuery, and then once inside your iframes, test once if typeof window.jQuery == 'undefined', if it's true, jQuery is not enabled inside it and fallback on DOM-based method.


I think the best way to reach your div:

var your_element=$('iframe#uploads').children('iframe').children('div#element');

It should work well.


You probably have a timing issue. Your document.ready commend is probably firing before the the second iFrame is loaded. You dont have enough info to help much further- but let us know if that seems like the possible issue.


Thing is, the code you provided won't work because the <iframe> element has to have a "src" property, like:

<iframe id="uploads" src="http://domain/page.html"></iframe>

It's ok to use .contents() to get the content:

$('#uploads).contents() will give you access to the second iframe, but if that iframe is "INSIDE" the http://domain/page.html document the #uploads iframe loaded.

To test I'm right about this, I created 3 html files named main.html, iframe.html and noframe.html and then selected the div#element just fine with:

$('#uploads').contents().find('iframe').contents().find('#element');

There WILL be a delay in which the element will not be available since you need to wait for the iframe to load the resource. Also, all iframes have to be on the same domain.

Hope this helps ...

Here goes the html for the 3 files I used (replace the "src" attributes with your domain and url):

main.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>main.html example</title>

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

    <script>
        $(function () {
            console.log( $('#uploads').contents().find('iframe').contents().find('#element') ); // nothing at first

            setTimeout( function () {
                console.log( $('#uploads').contents().find('iframe').contents().find('#element') ); // wait and you'll have it
            }, 2000 );

        });
    </script>
</head>
<body>
    <iframe id="uploads" src="http://192.168.1.70/test/iframe.html"></iframe>
</body>

iframe.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>iframe.html example</title>
</head>
<body>
    <iframe src="http://192.168.1.70/test/noframe.html"></iframe>
</body>

noframe.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>noframe.html example</title>
</head>
<body>
    <div id="element">some content</div>
</body>

If browser supports iframe, then DOM inside iframe come from src attribute of respective tag. Contents that are inside iframe tag are used as a fall back mechanism where browser does not supports iframe tag.

Ref: http://www.w3schools.com/tags/tag_iframe.asp


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to iframe

Getting all files in directory with ajax YouTube Autoplay not working Inserting the iframe into react component How to disable auto-play for local video in iframe iframe refuses to display iFrame onload JavaScript event YouTube iframe embed - full screen Change New Google Recaptcha (v2) Width load iframe in bootstrap modal Responsive iframe using Bootstrap