Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expose IFrame's DOM using jQuery?

I have a prototype representing a particual IFrame. That prototype have a function called GoToUrl(...) that opens the given url within the IFrame.

My question is: How do I create an "InternalDOM" property and make this property refer to the "window" object (the root DOM object) of the IFrame inside? In such way that: If my IFrame exposes a page which has an object X in it's "window" object I could do:

MyFrameObject.GoToUrl(pageXurl); MyFrameObject.InternalDOM.X 

Any help would be appreciated.

PS: I would accept answers not necessarily related to jQuery but I would prefer a jQuery solution.

like image 318
André Pena Avatar asked Oct 31 '09 10:10

André Pena


People also ask

Can you access the content of an iframe?

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.

How do I select an iframe element?

You can use this function to query for any element on the page, regardless of if it is nested inside of an iframe (or many iframes): function querySelectorAllInIframes(selector) { let elements = []; const recurse = (contentWindow = window) => { const iframes = contentWindow. document. body.

What is #document in iframe?

Definition and Usage. The contentDocument property returns the Document object generated by a frame or iframe element. This property can be used in the host window to access the Document object that belongs to a frame or iframe element.


2 Answers

To get the window object for a frame you can use the window.frames array:

var iframewindow= frames['iframe_name']; 

This requires that you give the <iframe> an old-school name attribute instead-of-or-as-well-as the id. Alternatively if you know the order of iframes on the page you can index them numerically:

var iframewindow= frames[0]; 

It's generally more flexible to get the iframe window from the iframe element in the DOM, but this requires some compatibility code to cope with IE:

var iframe= document.getElementById('iframe_id'); var iframewindow= iframe.contentWindow? iframe.contentWindow : iframe.contentDocument.defaultView; 

jQuery defines the contents() method to grab the document node, but it doesn't give you a cross-browser way to go from the document to the window, so you're still stuck with:

var iframe= $('#iframe_id')[0]; var iframewindow= iframe.contentWindow? iframe.contentWindow : iframe.contentDocument.defaultView; 

which isn't really a big win.

(Note: be very careful using jQuery for cross-frame-scripting. Each frame needs its own copy of jQuery and methods from one frame's copy won't necessarily work on nodes from the other. Cross-frame-scripting is a topic fraught with traps.)

like image 174
bobince Avatar answered Sep 28 '22 21:09

bobince


To sum it up

Access iframe content from parent page

var iframe = $('iframe').contents(); // iframe.find('..') ... 

Access parent page content from iframe

var parent = $(window.parent.document); // parent.find('..') ... 

This applies only when the parent and the iframe pages are on same domain.

EDIT: On load child iframes example:

parent html

<iframe id="iframe1" src="iframe1.html"></iframe> <iframe id="iframe2" src="iframe2.html"></iframe> 

parent js

$(function () {     var iframe1 = null,         iframe2 = null;      // IE8/7     var frameInterval = window.setInterval(function () {         iframe1 = $('#iframe1').contents();         iframe2 = $('#iframe2').contents();         if ($('head', iframe1).length && $('head', iframe2).length) {             window.clearInterval(frameInterval);         }     }, 100);      // on iframe loaded     $('#iframe1').on('load', function (e) {         iframe1 = $('#iframe1').contents();     });     $('#iframe2').on('load', function (e) {         iframe2 = $('#iframe2').contents();     }); }); 

All major browsers including IE9 work with the on('load') lines. Only IE8/7 need the interval block.

like image 31
simo Avatar answered Sep 28 '22 22:09

simo