How can I access the contents of an iframe with JavaScript/jQuery?

Viewed 729631

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?

15 Answers

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

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

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();
  ...
}
...

I ended up here looking for getting the content of an iframe without jquery, so for anyone else looking for that, it is just this:

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

This solution works same as 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. 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. 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. At times the iFrame doesn't load and script tries to execute before it. 300ms can be tweaked to anything else as per your needs.

Related