跨域 Iframe 通信解决方案(兼容 IE 系列浏览器。)
实现思路:
1、postMessage(IE8+, Firefox 3.1+, Opera 9+, Safari, and Chrome)
2、利用window.navigator共享信息,使支持IE6,IE7
i、父窗口向子窗口iframe发送信息:
document.getElementById("childiframe").contentWindow .postMessage(
"我是父窗口",
"http://child.com:8080" //可以*通配符代替,表示支持所有域
);
上面的代码表示父窗口向子iframe:childiframe,域名为"http://child.com:8080" 发送 "我是父窗口"的消息
ii、子iframe
window.addEventListener("message", function( event ) {
// 把父窗口发送过来的数据显示在子窗口中
document.getElementById("content").innerHTML+=event.data+"<br/>";
}, false );
iii、父窗口如果有多个子iframe,那么父窗口可以向多个子窗口发送消息
利用Object-orient-programing ,父窗口和多个子窗口分别实例化一个Message对象,各个窗口的message对象里开辟一个内存可以保存多个目标对象Target,意思是要发送消息到这些目标,
Target对象实现自己的send方法 ,send考虑到浏览器的兼容性,Target对象里保存了target和name信息,target表示要发送的窗口,name是发送目标的名称 ,name的作用仅仅是支持IE6、7中使用到(在window.navigator标示一个唯一send的回调函数)
var prefix = "arale-messenger",
supportPostMessage = 'postMessage' in window;
// Target 类, 消息对象
function Target(target, name){
var errMsg = '';
if(arguments.length < 2){
errMsg = 'target error - target and name are both required';
} else if (typeof target != 'object'){
errMsg = 'target error - target itself must be window object';
} else if (typeof name != 'string'){
errMsg = 'target error - target name must be string type';
}
if(errMsg){
throw new Error(errMsg);
}
this.target = target;
this.name = name;
} // 往 target 发送消息, 出于安全考虑, 发送消息会带上前缀
if ( supportPostMessage ){
// IE8+ 以及现代浏览器支持
Target.prototype.send = function(msg){
this.target.postMessage(prefix + msg, '*');
};
} else {
// 兼容IE 6/7 利用window.navigator共享信息,使支持IE6,IE7
Target.prototype.send = function(msg){
var targetFunc = window.navigator[prefix + this.name];
if ( typeof targetFunc == 'function' ) {
targetFunc(prefix + msg, window);
} else {
throw new Error("target callback function is not defined");
}
};
}
iiii: 每个窗口都实例化的Message类:
targets 里保存目标发送对象,name当前窗口的名字,最后会传给Target,也是只在兼容IE6、7中用到。
listenFunc :保存监听的回调,一个页面可以实现多个监听。
initListen :ie6、7中保存全局回调函数,以方便在Target的send中触发
IE8+和现代化浏览器中监听message事件。
// 信使类
// 创建Messenger实例时指定, 必须指定Messenger的名字, (可选)指定项目名, 以避免Mashup类应用中的冲突
// !注意: 父子页面中projectName必须保持一致, 否则无法匹配
function Messenger(messengerName, projectName){
this.targets = {};
this.name = messengerName;
this.listenFunc = [];
prefix = projectName || prefix;
this.initListen();
} // 添加一个消息对象
Messenger.prototype.addTarget = function(target, name){
var targetObj = new Target(target, name);
this.targets[name] = targetObj;
}; // 初始化消息监听
Messenger.prototype.initListen = function(){
var self = this;
var generalCallback = function(msg){
if(typeof msg == 'object' && msg.data){
msg = msg.data;
}
// 剥离消息前缀
msg = msg.slice(prefix.length);
for(var i = 0; i < self.listenFunc.length; i++){
self.listenFunc[i](msg);
}
}; if ( supportPostMessage ){
if ( 'addEventListener' in document ) {
window.addEventListener('message', generalCallback, false);
} else if ( 'attachEvent' in document ) {
window.attachEvent('onmessage', generalCallback);
}
} else {
// 兼容IE 6/7
window.navigator[prefix + this.name] = generalCallback;
}
}; // 监听消息
Messenger.prototype.listen = function(callback){
this.listenFunc.push(callback);
};
// 注销监听
Messenger.prototype.clear = function(){
this.listenFunc = [];
};
// 广播消息
Messenger.prototype.send = function(msg){
var targets = this.targets,
target;
for(target in targets){
if(targets.hasOwnProperty(target)){
targets[target].send(msg);
}
}
};
完整demo:
完整代码:
message.js
(function(w){
// 消息前缀, 建议使用自己的项目名, 避免多项目之间的冲突
var prefix = "arale-messenger",
supportPostMessage = 'postMessage' in window; // Target 类, 消息对象
function Target(target, name){
var errMsg = '';
if(arguments.length < 2){
errMsg = 'target error - target and name are both required';
} else if (typeof target != 'object'){
errMsg = 'target error - target itself must be window object';
} else if (typeof name != 'string'){
errMsg = 'target error - target name must be string type';
}
if(errMsg){
throw new Error(errMsg);
}
this.target = target;
this.name = name;
} // 往 target 发送消息, 出于安全考虑, 发送消息会带上前缀
if ( supportPostMessage ){
// IE8+ 以及现代浏览器支持
Target.prototype.send = function(msg){
this.target.postMessage(prefix + msg, '*');
};
} else {
// 兼容IE 6/7
Target.prototype.send = function(msg){
var targetFunc = window.navigator[prefix + this.name];
if ( typeof targetFunc == 'function' ) {
targetFunc(prefix + msg, window);
} else {
throw new Error("target callback function is not defined");
}
};
} // 信使类
// 创建Messenger实例时指定, 必须指定Messenger的名字, (可选)指定项目名, 以避免Mashup类应用中的冲突
// !注意: 父子页面中projectName必须保持一致, 否则无法匹配
function Messenger(messengerName, projectName){
this.targets = {};
this.name = messengerName;
this.listenFunc = [];
prefix = projectName || prefix;
this.initListen();
} // 添加一个消息对象
Messenger.prototype.addTarget = function(target, name){
var targetObj = new Target(target, name);
this.targets[name] = targetObj;
}; // 初始化消息监听
Messenger.prototype.initListen = function(){
var self = this;
var generalCallback = function(msg){
if(typeof msg == 'object' && msg.data){
msg = msg.data;
}
// 剥离消息前缀
msg = msg.slice(prefix.length);
for(var i = 0; i < self.listenFunc.length; i++){
self.listenFunc[i](msg);
}
}; if ( supportPostMessage ){
if ( 'addEventListener' in document ) {
window.addEventListener('message', generalCallback, false);
} else if ( 'attachEvent' in document ) {
window.attachEvent('onmessage', generalCallback);
}
} else {
// 兼容IE 6/7
window.navigator[prefix + this.name] = generalCallback;
}
}; // 监听消息
Messenger.prototype.listen = function(callback){
this.listenFunc.push(callback);
};
// 注销监听
Messenger.prototype.clear = function(){
this.listenFunc = [];
};
// 广播消息
Messenger.prototype.send = function(msg){
var targets = this.targets,
target;
for(target in targets){
if(targets.hasOwnProperty(target)){
targets[target].send(msg);
}
}
}; w["Messenger"]=Messenger;
})(window);
child.html:
<!doctype html>
<html>
<head>
<script type="text/javascript" src="message.js"></script>
<script>
window.onload=function(){
var messenger = new Messenger('iframe1', 'MessengerProject');
messenger.addTarget(window.parent, 'parent');
messenger.targets['parent'].send('发给父页面的消息');
messenger.listen(function(msg) {
document.getElementById("msg").innerHTML=msg;
});
}
</script>
</head>
<body>
child
<div id="msg"></div>
</body>
</html>
parent.html
<!doctype html>
<html>
<head>
<script type="text/javascript" src="message.js"></script>
<script>
window.onload=function(){
var messenger = new Messenger('parent', 'MessengerProject');
var iframe1=window.iframe1;
messenger.addTarget(iframe1.contentWindow, 'iframe1');
messenger.targets['iframe1'].send('发给子页面1的消息');
messenger.listen(function(msg) {
document.getElementById("msg").innerHTML=msg;
});
}
</script>
</head>
<body>
parent
<div id="msg"></div>
<iframe id="iframe1" src="child.html" width=100 height=100>
</body>
</html>
跨域 Iframe 通信解决方案(兼容 IE 系列浏览器。)的更多相关文章
- 跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
采用JavaScript来控制iframe元素的高度是iframe高度自适应的关键,同时由于JavaScript对不同域名下权限的控制,引发出同域.跨域两种情况. 由于客户端js使用浏览器的同源安全策 ...
- 完美实现跨域Iframe高度自适应【Iframe跨域高度自适应解决方案】
Iframe的强大功能偶就不多说了,它不但被开发人员经常运用,而且黑客们也常常使用它,总之用过的人知道它的强大之处,但是Iframe有个致命的“BUG”就是iframe的高度无法自动适应,这一点让很多 ...
- javascript跨域通信(一):利用location.hash实现跨域iframe自适应
页面域关系: a.html所属域A:www.A.comb.html所属域B:www.B.com 问题本质: js对跨域iframe访问问题,因为要控制a.html中iframe的高度和宽度就必须首先读 ...
- Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)
Ajax跨域问题及解决方案 目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...
- ajax跨域原理以及解决方案
说明 跨域主要是由于浏览器的“同源策略”引起,分为多种类型,本文主要探讨Ajax请求跨域问题 前言 强烈推荐阅读参考来源中的文章,能够快速帮助了解跨域的原理 参考来源 本文参考了以下来源 浏览器同源政 ...
- 跨域问题,解决方案-Nginx反向代理
跨域问题,解决之道 跨域问题,在日常开发过程中,是一个非常熟悉的名词.今天的话题,结合我之前的项目场景,讨论下<跨域问题,解决之道>. 跨域是什么 跨域问题,是由于JavaScript出于 ...
- 谷歌、火狐浏览器下实现JS跨域iframe高度自适应的完美解决方法,跨域调用JS不再是难题!
谷歌.火狐浏览器下实现JS跨域iframe高度自适应的解决方法 导读:今天开发的时候遇到个iframe自适应高度的问题,相信大家对这个不陌生,但是一般我们都是在同一个项目使用iframe嵌套页面,这个 ...
- ajax 跨域访问的解决方案
ajax 跨域访问的解决方案 一.什么是跨域: 1.什么样的请求属于跨域: 域名,端口有任何一个不相同都属于跨域: 二.跨域的常用几种解决方案: 1.jsonp: 2.iframe: 3.webcon ...
- Web学习之跨域问题及解决方案
在做前端开发时,我们时常使用ajax与服务器通信获取资源,享受ajax便利的同时,也知道它有限制:跨域安全限制,即同源策略. 同源策略(SOP),核心是确保不同源提供的文件之间是相互独立的 默认情况下 ...
随机推荐
- Linux智能小开关rfkill
Linux智能小开关rfkill Rfkill,当中rf是Radio frequency(射频).主要作用是一个专门管理开关的子系统,举例说明Android手机的通知栏能够方便地开关Airplane/ ...
- SQL SERVER FOR 多列字符串连接 XML PATH 及 STUFF
原文:SQL SERVER FOR 多列字符串连接 XML PATH 及 STUFF 本来用 Writer 写一篇关于一列多行合并的博客来的,结果快写完了时候,在一个插入代码时候,崩了,重新打开,居然 ...
- linux环境下的线程的创建问题
pthread_create函数用于创建一个线程 函数原型 #include<pthread.h> int pthread_create(pthread_t *restrict tidp, ...
- Python学习入门基础教程(learning Python)--3.1Python的if分支语句
本节研究一下if分支语句. if分支语句是Python下逻辑条件控制语句,用于条件执行某些语句的控制操作,当if后的条件conditon满足时,if其下的语句块被执行,但当if的控制条件condito ...
- The JSR-133 Cookbook for Compiler Writers(an unofficial guide to implementing the new JMM)
The JSR-133 Cookbook for Compiler Writers by Doug Lea, with help from members of the JMM mailing lis ...
- Android 从硬件到应用程序:一步一步爬上去 5 -- 在Frameworks蒂姆层硬件服务
Android Frameworks层提供硬件服务,Android系统APP能够调用这些硬件服务,而硬件则完全控制.实现应有的功能.上一页下一页.为了这一个frameworks高层的应用java接口硬 ...
- BestCoder Round#8 1003
dp[i][j] 表示以i结尾的长度为j的递增子序列dp[i][j] = sum(dp[k][j]) k<i && a[i] >a[j]如果只是单纯的循环for(j ...
- C++ 操作 MySQL
使用VS2008如IDE, 准备操作: 1. 项目属性 C++ 其他包括文件夹 为 mysql 安装文件夹的include 如:"C:\Program Files (x86)\MySQL\ ...
- CSS检测的高像素密度屏幕设备
iPhone4尽管是640px解析度,但它的屏幕宽度(device-width)目前只有320px和iPhone3G相同.只是iPhone4S的像素密度2. 然后使用meta viewport什么时候 ...
- 【NO.3】 c program to caculate and display sum of two matrix
source code: #include "stdafx.h" /* display sum of two matrix*/ int _tmain(int argc, _TCHA ...