First of all, iframe communication is divided into: same-domain communication and cross-domain communication.
1. Communication in the same domain
The so-called same-domain communication refers to the nested iframe of a.html page under http://localhost/demo/iframe/iframeA.html
For example: <iframe src="http://localhost/demo/iframe/iframeB.html" id="iframeA" name="iframeA">The data of these two pages communicate. For example, I want to call the function in the child page on the parent page A.html, which is easy for us to think of document.getElementById('iframeA').contentWindow.b(); under Google, where b is a function in the child page B.html. But there is a problem with this call that I have been struggling with for a long time, that is, since I have reported such an error under Firefox, as follows:
b is not a function, but I clearly defined such a function on the subpage, so why does such an error occur? After careful analysis and Google, I found that there is a problem that needs to be understood. When the iframe has not been loaded, I will execute this js and report such an error. So I tried to use the iframe.onload function under Firefox to test it. Sure enough, there was no error, it was correct, so I was sure that it was this problem. So I want to write a compatible IE and Firefox Google to write a function to confirm that the iframe has been loaded! , in fact, give a callback function to call our above method.
Based on the above ideas, you can write a code like this:
<iframe src="http://localhost/demo/iframe/iframeB.html" id="iframeA" name="iframeA"></iframe> <div id="topName">topNdddddddddddddddddddddddddddddddddddddddddd</div> <script> function A(){ alert("A"); } var iframe = document.getElementById('iframeA'); iframeIsLoad(iframe,function(){ var obj = document.getElementById('iframeA').contentWindow; obj.b(); }); function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } } </script>The B.html code is as follows:
var b = function(){ alert("B"); } It is very simple to call the function of the parent page on the child page. Just do this and it will be OK, window.parent.A();
The child page takes the value of the parent page element: window.parent.document.getElementById("topName").innerHTML and other methods.
Two: iframe cross-domain communication.
Iframe cross-domain access is generally divided into two situations. The first is cross-domain with the same main domain and different subdomains. The second type is: different main domains cross domains.
1. It is a cross-domain between different subdomains under the same main domain; it can be solved by setting the same main domain through document.domain.
If I have a domain abc.example.com, there is a page called abc.html, and an iframe is nested on the page as follows: <iframe src="http://def.example.com/demo/def.html" id="iframe2" style="display:none;"></iframe>, I want to access the def.html under the def domain in the page abc.html We all know that due to the limitations of the same-origin policy of the security browser, js cannot operate pages with different ports under different protocols under different domains, so cross-domain access is solved. If the parent page abc.html has a js function: function test(){console.log(1);}; I want to call this function on the subpage or call parent.test(); In this way, by looking at the cross-domain under Firefox, the solution is to add a sentence document.domain = 'example.com' at the top of each js function, and it can be solved.
The abc.html code is as follows:
<iframe src="http://def.example.com/demo/def.html" id="iframe2" style="display:none;"></iframe>// The function that calls the parent page across domain subpages (assuming it is the test function below) document.domain = 'example.com';function test(){console.log(1);};The def.html code is as follows:
/* * The method of the child page calling the parent page*/document.domain = 'example.com';//window.top.test(); window.parent.test();
Or these two pages, I want the parent page to call the child page as follows:
a.html code is as follows:
/* * Functions that want to call child pages across domain parent page*/document.domain = 'example.com';var iframe = document.getElementById('iframe2');iframeIsLoad(iframe,function(){ var obj = iframe.contentWindow; obj.child();});function iframeIsLoad(iframe,callback){ if(iframe.attachEvent) { iframe.attachEvent('onload',function(){ callback && callback(); }); }else { iframe.onload = function(){ callback && callback(); } } } }If there is a child function code on the def.html page now:
document.domain = 'example.com';function child(){console.log('I am a child page');}You can call across domains whether it is a child page calling the parent page or a parent page calling the child page. Everything is OK!
2. It is different main domains and cross domains;
Although Google has several methods for cross-domain issues on different main domains, including location.hash method, window.name method, html5 and flash, etc., I think the following iframe method is worth learning.
As shown in the figure below: The page request.html of domain a.com (i.e. http://a.com/demo/ajax/ajaxproxy/request.html) is nested with an iframe pointing to domain b.com (http://b.com/demo/ajaxproxy/response.html), and the proxy.html of domain a.com is nested with the proxy.html of domain a.com.
Idea: To implement the request.html page under the a.com domain request process.php under the domain b.com, you can pass the request parameter to the response.html through the url, and initiate a real ajax request from the response.html to process.php (response.html and process.php belong to the domain b.com), and then pass the returned result to proxy.html through the url. Finally, since proxy.html and request.html are in the same domain, you can use window.top to return the result in request.html to complete the real cross-domain.
OK, let's take a look at the page structure first
Under the a.com domain, there are:
request.html
proxy.html
Under the b.com domain, there are:
response.html
process.php
Let’s take a look at the request.html page as follows:
<!DOCTYPE HTML><html> <head> <title> New Document </title> </head> <body> <p id="result">The response result will be filled in here</p> <a id="sendBtn" href="javascript:void(0)">Click to send a cross-domain request</a> <iframe id="serverIf" style="display:none"></iframe> <script> document.getElementById('sendBtn').onclick = function() { var url = 'http://b.com/demo/ajax/ajaxproxy/reponse.html', fn = 'GetPerson', //This is the method defined in response.html reqdata = '{"id" : 24}', //This is the requested parameter callback = "CallBack"; //This is the callback function executed after the entire request process is completed, executing the last action CrossRequest(url, fn, reqdata, callback); //Send a request} function CrossRequest(url,fn,reqdata,callback) { var server = document.getElementById('serverIf'); server.src = url + '?fn=' +encodeURIComponent(fn) + "&data=" +encodeURIComponent(reqdata) + "&callback="+encodeURIComponent(callback); } //Callback function function CallBack(data) { var str = "My name is " + data.name + ". I am a " + data.sex + ". I am " + data.age + " years old."; document.getElementById("result").innerHTML = str; } </script> </body></html> This page is actually about telling response.html: I want you to execute the method you defined GetPerson , and use the parameter '{"id": 24}' I gave you. response.html is purely responsible for passing the method name CallBack to the next brother proxy.html. proxy.html can execute it after getting the method name CallBack , because proxy.html and request.html are in the same domain.
The response.html code is as follows:
<!DOCTYPE HTML><html> <head> <title> New Document </title> </head> <body> <iframe id="proxy"></iframe> <script> // General method ajax request function _request (reqdata,url,callback) { var xmlhttp; if(window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); }else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function(){ if(xmlhttp.readyState == 4 && xmlhttp.status == 200) { var data = xmlhttp.responseText; callback(data); } } xmlhttp.open('POST',url); xmlhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8"); xmlhttp.send(reqdata); } // General method to get url parameters function _getQuery(key) { var query = location.href.split('?')[1], value = decodeURIComponent(query.split(key + "=")[1].split("&")[0]); return value; } //Send ajax request to process.php function GetPerson(reqdata,callback) { var url = 'http://b.com/demo/ajax/ajaxproxy/process.php'; var fn = function(data) { var proxy = document.getElementById('proxy'); proxy.src = "http://a.com/demo/ajax/ajaxproxy/Proxy.html?data=" + encodeURIComponent(data) + "&callback=" + encodeURIComponent(callback); }; _request(reqdata, url, fn); } (function(){ var fn = _getQuery('fn'), reqdata = _getQuery("data"), callback = _getQuery("callback"); eval(fn + "('" + reqdata +"', '" + callback + "')"); })(); </script> </body></html>This is actually to receive the request from request.html and get the request parameters and methods, and then issue a real ajax request to the server process.php, and then pass the data returned from the server and the callback function name passed from request.html to proxy.html.
Next, let’s take a look at the php code as follows , which is actually just to return a json data:
<?php $data = json_decode(file_get_contents("php://input")); header("Content-Type: application/json; charset=utf-8"); echo ('{"id" : ' . $data->id . ', "age" : 24, "sex" : "boy", "name" : "huangxueming"}');?>Finally, there is the proxy.html code:
<!DOCTYPE HTML><html> <head> <title> New Document </title> </head> <body> <script> function _getUrl(key) {//General method, get URL parameters var query = location.href.split("?")[1], value = decodeURIComponent(query.split(key + "=")[1].split("&")[0]); return value; } (function() { var callback = _getUrl("callback"), data = _getUrl("data"); eval("window.top." + decodeURIComponent(callback) + "(" + decodeURIComponent(data) + ")"); })(); </script> </body></html>This is also the last step. proxy finally got the callback function name transmitted from request.html through response.html and the response data transmitted directly from response.html, and used window.top to execute the callback function defined in request.html.
3. The problem of high adaptability of iframes.
Iframe height adaptation is divided into two types: one is adaptation under the same domain and the other is adaptation under the cross domain . Let’s take a look at the problem of high adaptation in the same domain.
1. Problems with highly adaptable iframes in the same domain:
Idea: Get the nested iframe element, get the final height of the nested page through JavaScript, and then set it on the main page to achieve it.
If our demo has iframe1.html and iframe2.html
The following is the following code:
<!DOCTYPE HTML><html> <head> <title> New Document </title> <style> *{margin:0;padding:0;} </style> </head> <body> <iframe src="http://a.com/demo/ajax/iframeheight/iframe2.html" frameborder="0" id="iframe"></iframe> <script> window.onload = function() { var iframeid = document.getElementById('iframe'); if(iframeid && !window.opera) { if(iframeid.contentDocument && iframeid.contentDocument.body.offsetHeight) { iframeid.height = iframeid.contentDocument.body.offsetHeight; }else if(iframeid.Document && iframeid.Document.body.scrollHeight){ iframeid.height = iframeid.Document.body.scrollHeight; } } } </script> </body></html>iframe2.html
<!DOCTYPE HTML><html> <head> <title> New Document </title> <style> *{margin:0;padding:0;} </style> </head> <body> <div style="height:500px;"></div> </body></html>You can dynamically set the height of iframe1 page to iframe2 height.
2. Iframes are highly adaptable across domains.
First of all, we know that we cannot control the cross-domain of iframes with the above js method, so we can only use the intermediate key to nest an iframe2.html page under the b.com domain on the iframe1.html page under the a.com domain, and then I nest an iframe3.html page with the same domain as iframe1.html on the iframe2.html page. In this way, iframe1.html and iframe3.html can communicate without barriers, because the page iframe2.html nests iframe3.html, so iframe2.html can rewrite the href value of iframe3.html.
Contents in iframe1:
The iframe1.html content mainly accepts the content transmitted from the iframe3.html page and completes the corresponding operation. The iframe1.html code is as follows:
<iframe src="http://b.com/demo/ajax/iframeheight/iframe2.html" id="iframe"></iframe> <script> var ifr_el = document.getElementById("iframe"); function getIfrData(data){ ifr_el.style.height = data+"px"; }</script>Content in iframe2.html:
How does the iframe2.html content pass the value to the iframe3.html page? I just said that the value is passed to the href of the iframe3.html page, so just modify the iframe's src. Because there is no need to refresh the C page, it can be passed to the iframe3.html page by hash. The code of iframe2.html is as follows:
<!DOCTYPE HTML><html> <head> <title> New Document </title> <style> *{margin:0;padding:0;} </style> </head> <body> <iframe id="iframe" src="http://a.com/demo/ajax/iframeheight/iframe3.html"></iframe> <script> var oldHeight = 0, ifr_el = document.getElementById("iframe"); t && clearInterval(t); var t = setInterval(function(){ var height = document.body.scrollHeight; if(oldHeight != height) { oldHeight = height; ifr_el.src += '#' +oldHeight; } },200); </script> </body></html>You can see that by default, the height of the iframe1.html page I give iframe2.html is 200 pixels, but in iframe2.html I give iframe3.html the height of the iframe3.html is 230 pixels, so under normal circumstances there is a scroll bar. Now I want to get the height of the scroll bar in iframe2.html, pass the height to the src through iframe3.html, and then get the height value in the iframe3.html page to pass it to iframe1.html (because iframe1.html and iframe3.html are in the same domain), so iframe1.html can get this height value, and then set the height itself, it is OK.
The only function of the iframe3.html page is to receive the value passed in by the iframe2.html page through the href and pass it to the iframe1.html page. The value passed to the iframe2.html page can be checked continuously through a timer to see if the location.href has been changed, but this feels very inefficient. Another way is to listen for the changes of href through onhashchange event (IE8+, Chrome5.0+, Firefox3.6+, Safari5.0+, Opera10.6+) in the new browser.
The iframe3.html code is as follows:
<script> var oldHeight = 0; t && clearInterval(t); var t = setInterval(function(){ var height = location.href.split('#')[1]; if(height && height != oldHeight) { oldHeight = height; if(window.parent.parent.getIfrData) { window.parent.parent.getIfrData(oldHeight); } } } },200); </script>This can solve the problem of achieving the height of iframe adaptability through cross-domain.
4. Summary
The above is the entire content of this article. I hope it will be helpful to everyone's study and work. If you have any questions, please leave a message to discuss.