How to operate on an iframe: 1. Control the JavaScript code outside the iframe from inside the iframe. 2. Operate on a child iframe from the parent frame.
Get the content inside an iframe
The two main APIs are contentWindow and contentDocument.
iframe.contentWindow gets the window object of the iframe.
iframe.contentDocument gets the document object of the iframe.
These two APIs are only methods provided by DOM nodes (that is, objects in the getELement series).
var iframe = document.getElementById("iframe1");
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
console.log("window",iwindow);//Get the window object of the iframe
console.log("document",idoc); //Get the document of the iframe
console.log("html",idoc.documentElement);//Get the html of the iframe
console.log("head",idoc.head); //Get the head
console.log("body",idoc.body); //Get the body
The actual result is as follows:
Another simpler way is to use the Name attribute together with the frames provided by window.
<iframe src ="/index.html" id="ifr1" name="ifr1" scrolling="yes">
<p>Your browser does not support iframes.</p>
</iframe>
<script type="text/javascript">
console.log(window.frames['ifr1'].window);
console.dir(document.getElementById("ifr1").contentWindow);
</script>
Actually, what window.frames[‘ifr1’] returns is the window object, that is:
window.frames['ifr1']===window
Here it just depends on which way you want to use to get the window object; both work, though I personally prefer the second one, using frames[xxx], because, well, it uses fewer letters~
Then you can manipulate the DOM content inside the iframe.
Getting parent content from within an iframe
By the same token, in the same domain, if the parent page can access the child iframe’s content, then the child iframe can likewise manipulate the parent page’s content. Inside an iframe, you can access it through several APIs mounted on window.
window.parent gets the parent window object; if the parent is still an iframe, then it is that iframe’s window object
window.top gets the window object of the top-level container, that is, the document of the page you opened
window.self returns a reference to the current window. It can be understood as window===window.self(obviously)
As shown in the figure: here’s an example~
OK, after getting it, we can perform the relevant operations.
In same-domain iframes, we can cleverly use some iframe black magic to pull off a few tricks.
iframe polling
It is said that a very, very long time ago, we implemented asynchronous request sending with iframes~!
How could that be!!! There is indeed historical evidence (google it yourself),
Back then, in order to avoid page navigation, forms were submitted through iframes. Now, front-end development is freaking fast, with websocket, SSE, ajax, and more. The emergence of these godlike skills has overturned iframes,
and now they can basically only survive in IE8 and IE9 browsers.
But I thought that meant we no longer needed to understand iframes, yet reality is just that cruel: we still need to support IE8+. So, we still need to get familiar with the trick of using iframes
to implement long polling and long connections.
iframe Long Polling
If you’ve written ajax before, you should know that long polling means calling the original function again
when ajax’s readyState =
4.
It’s the same with iframes here: create an iframe asynchronously, then reload it,
coordinate with the backend,
decide with the backend team where to put the returned information, and then just retrieve the information from there.
Here it is placed directly in the body.
var iframeCon = docuemnt.querySelector('#container'),
text; //Information to pass
var iframe = document.createElement('iframe'),
iframe.id = "frame",
iframe.style = "display:none;",
iframe.name="polling",
iframe.src="target.html";
iframeCon.appendChild(iframe);
iframe.onload= function(){
var iloc = iframe.contentWindow.location,
idoc = iframe.contentDocument;
setTimeout(function(){
text = idoc.getElementsByTagName('body')[0].textContent;
console.log(text);
iloca.reload(); //Refresh the page, get the information again, and trigger the onload function
},2000);
}
This achieves the effect of ajax long polling.
Of course, here it only uses reload to fetch data. You can also send information by adding and removing iframes; it all depends on the specific scenario. In addition, asynchronous loading of js files can also be implemented in iframes. However, iframes and the main page share the same connection pool, so it’s still quite a pain. Nowadays, they have basically been replaced by XHR and hard
calllback, so I won’t go into much detail here.
1. Code for js in an iframe child page to operate on parent page elements:
window.parent.document.getElementByIdx_x("parent page element id");
2. Code for js in the parent page to get elements from the iframe child page:
window.frames["iframe_ID"].document.getElementByIdx_x("child page element id");
3. Code for jquery in an iframe child page to get parent page elements:
$("#objid",parent.document)
4.
$("#objid",document.frames('iframename').document)
5. Call methods and variables defined in the parent page from within an iframe:
window.parent.window.parentMethod(); window.parent.window.parentValue;
6. Operate on methods and variables of the iframe child page from the parent page
window.frames["iframe_ID"].window.childMethod(); window.frames["iframe_ID"].window.childValue;
1. Communication between parent and child pages under the same domain
Parent page parent.html
<html>
<head>
<script type="text/javascript">
function say(){
alert("parent.html");
}
function callChild(){
myFrame.window.say();
myFrame.window.document.getElementById("button").value="Call finished";
}
</script>
</head>
<body>
<input id="button" type="button" value="Call the say() function in child.html" onclick="callChild()"/>
<iframe name="myFrame" src="http://caibaojian.com/child.html"></iframe>
</body>
</html>
Child page child.html
<html>
<head>
<script type="text/javascript">
function say(){
alert("child.html");
}
function callParent(){
parent.say();
parent.window.document.getElementById("button").value="Call finished";
}
</script>
</head>
<body>
<input id="button" type="button" value="Call the say() function in parent.html" onclick="callParent()"/>
</body>
</html>
Notes
Make sure the iframe has finished loading before operating on it. If you start calling its methods or variables before it has fully loaded, errors will occur. There are two ways to determine whether the iframe has finished loading:
1. Use the onload event on the iframe
2. Use document.readyState==”complete” to determine it
2. Cross-domain parent-child page communication methods
If the iframe links to an external page, then due to security mechanisms, the same-domain communication method cannot be used.
1. The parent page passes data to the child page
The trick is to use the hash value of the location object to pass communication data. After setting the iframe’s src on the parent page, append an extra data string to it, and then have the child page immediately obtain that data in some way, for example:
1.1
In the child page, use the setInterval method to set a timer and listen for changes to location.href to obtain the data information above
1.2. Then the child page performs the corresponding logical processing based on this data information
2. The child page passes data to the parent page
The implementation trick is to use a proxy iframe, which is embedded in the child page and must remain in the same domain as the parent page. Then, by fully leveraging the implementation principle of the first communication method mentioned above, the child page’s data can be passed to the proxy iframe. Since the proxy iframe and the main page are in the same domain, the main page can then use the same-origin approach to obtain that data. Use
window.top or window.parent.parent to get a reference to the browser’s top-level window object.
I previously wrote an article about iframe adaptive height, which was implemented through iframe operations on child pages. You can take a look as well.
Reference: http://www.cnblogs.com/sydeveloper/p/3712863.html