Skip to content

Commit

Permalink
update to messenger@2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
afc163 committed Mar 18, 2014
1 parent ac4a6be commit 56740a6
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 563 deletions.
5 changes: 5 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

---

## 2.0.0

根据最新的 biqing/MessengerJS 重抄了一遍实现,并更新了文档和演示。考虑后续删除这个模块。


## 1.0.2

`tag:new` [#3](https://github.com/aralejs/messenger/issues/3) 新增 destroy 销毁方法。
Expand Down
57 changes: 18 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,64 +6,43 @@

跨域 Iframe 通信解决方案,兼容主流和 IE 系列浏览器。

本文档参考 https://github.com/biqing/MessengerJS/blob/master/README.md

<span style="font-size:100px;line-height:0.7;color:rgb(116, 106, 76);">☏</span>

---

## API

### target `selector`

收发信息的目标页面。

### onmessage `function`
## Usage

接受消息的处理函数,第一个参数为收到的信息。

## 方法

### send `function`

使用 send 方法来给目标页面发送信息,接受一个字符串作为参数。
### 父页面

```js
messenger.send('The Message.');
```

## 最佳实践
// 初始化父页面的信使
var messenger = new Messenger('parent', 'MessengerProject');

### 父页面
// 绑定子页面 iframe
messenger.addTarget(iframe1.contentWindow, 'iframe1');
messenger.addTarget(iframe2.contentWindow, 'iframe2');

```js
// target 参数为 iframe
var messenger = new Messenger({
target: '#iframe',
onmessage: function(msg) {
console.log(msg);
}
});
// 给子页面发消息
messenger.send('发给子页面的消息');
messenger.targets['iframe1'].send('发给子页面1的消息');

// 或者给所有子页面发消息
messenger.send('发给所有子页面的消息');
```

### 子页面

```js
// target 参数为 parent
var messenger = new Messenger({
target: parent,
onmessage: function(msg) {
console.log(msg);
}
});
// 初始化子页面的信使
// 注意,第二个参数 `MessengerProject` 必须和父页面的信使保持一致,
var messenger = new Messenger('iframe1', 'MessengerProject');

// 给父页面发消息
messenger.send('发给父页面的消息');
messenger.targets['parent'].send('发给父页面的消息');
```

## 感谢

本组件源码来自 [https://github.com/biqing/MessengerJS](https://github.com/biqing/MessengerJS)


[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/aralejs/messenger/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

287 changes: 99 additions & 188 deletions dist/messenger-debug.js
Original file line number Diff line number Diff line change
@@ -1,198 +1,109 @@
define("arale/messenger/1.0.2/messenger-debug", [ "$-debug" ], function(require, exports, module) {
var $ = require("$-debug");
function Messenger(config) {
var win = config.target || parent;
try {
if (!$.isWindow(win)) {
win = $(win).get(0);
if (win && win.tagName === "IFRAME") {
win = win.contentWindow;
}
}
} catch (e) {}
// save the pointer to the window which is interacting with
this.win = win;
this.onmessage = config.onmessage || function() {};
this.init();
}
// postMessage API is supported
Messenger.prototype.init = function() {
var self = this;
this._receiver = function(event) {
// Some IE-component browsers fails if you compare
// window objects with '===' or '!=='.
if (event.source != self.win) return;
(self.onmessage || function() {}).call(self, event.data);
};
if (window.addEventListener) window.addEventListener("message", this._receiver, false); else if (window.attachEvent) window.attachEvent("onmessage", this._receiver);
};
Messenger.prototype.send = function(data) {
this.win.postMessage(data, "*");
};
// in IE, postMessage API is not supported
if (!window.postMessage && window.attachEvent) {
// redefine the init method
Messenger.prototype.init = function() {
var isSameOrigin = false;
// test if the two document is same origin
try {
isSameOrigin = !!this.win.location.href;
} catch (ex) {}
if (isSameOrigin) {
this.send = this.sendForSameOrigin;
this.initForSameOrigin();
return;
define("arale/messenger/2.0.0/messenger-debug", [], function(require, exports, module) {
/**
* __ ___
* / |/ /___ _____ _____ ___ ____ ____ _ ___ _____
* / /|_/ // _ \ / ___// ___// _ \ / __ \ / __ `// _ \ / ___/
* / / / // __/(__ )(__ )/ __// / / // /_/ // __// /
* /_/ /_/ \___//____//____/ \___//_/ /_/ \__, / \___//_/
* /____/
*
* @description MessengerJS, a common cross-document communicate solution.
* @author biqing kwok
* @version 2.0
* @license release under MIT license
*/
module.exports = function() {
// 消息前缀, 建议使用自己的项目名, 避免多项目之间的冲突
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";
}
// different origin case
// init the message queue, which can guarantee the messages won't be lost
this.queue = [];
if (window.parent == this.win) {
this.initForParent();
} else {
this.initForFrame();
if (errMsg) {
throw new Error(errMsg);
}
};
Messenger.prototype.initForSameOrigin = function() {
var self = this;
this._dataavailable = function(event) {
if (!event.eventType || event.eventType !== "message" || event.eventSource != self.win) return;
(self.onmessage || function() {}).call(self, event.eventData);
this.target = target;
this.name = name;
}
// 往 target 发送消息, 出于安全考虑, 发送消息会带上前缀
if (supportPostMessage) {
// IE8+ 以及现代浏览器支持
Target.prototype.send = function(msg) {
this.target.postMessage(prefix + msg, "*");
};
document.attachEvent("ondataavailable", this._dataavailable);
};
Messenger.prototype.sendForSameOrigin = function(data) {
var self = this;
setTimeout(function() {
var event = self.win.document.createEventObject();
event.eventType = "message";
event.eventSource = window;
event.eventData = data;
self.win.document.fireEvent("ondataavailable", event);
});
};
// create two iframe in iframe page
Messenger.prototype.initForParent = function() {
var fragment = document.createDocumentFragment();
var style = "width: 1px; height: 1px; position: absolute; left: -999px; top: -999px;";
var senderFrame = document.createElement("iframe");
senderFrame.src = 'javascript:""';
senderFrame.style.cssText = style;
fragment.appendChild(senderFrame);
var receiverFrame = document.createElement("iframe");
receiverFrame.src = 'javascript:""';
receiverFrame.style.cssText = style;
fragment.appendChild(receiverFrame);
document.body.insertBefore(fragment, document.body.firstChild);
this.senderWin = senderFrame.contentWindow;
this.receiverWin = receiverFrame.contentWindow;
this.startReceive();
// for destroy
this._fragment = fragment;
};
// parent page wait the messenger iframe is ready
Messenger.prototype.initForFrame = function() {
this.senderWin = null;
this.receiverWin = null;
var self = this;
this.timerId = setInterval(function() {
self.waitForFrame();
}, 50);
};
// parent page polling the messenger iframe
// when all is ready, start trying to receive message
Messenger.prototype.waitForFrame = function() {
var senderWin;
var receiverWin;
try {
senderWin = this.win[1];
receiverWin = this.win[0];
} catch (ex) {}
if (!senderWin || !receiverWin) return;
clearInterval(this.timerId);
this.senderWin = senderWin;
this.receiverWin = receiverWin;
if (this.queue.length) this.flush();
this.startReceive();
};
// polling the messenger iframe's window.name
Messenger.prototype.startReceive = function() {
var self = this;
this.timerId = setInterval(function() {
self.tryReceive();
}, 50);
} 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.tryReceive = function() {
try {
// If we can access name, we have already got the data.
this.receiverWin.name;
return;
} catch (ex) {}
// if the name property can not be accessed, try to change the messenger iframe's location to 'about blank'
this.receiverWin.location.replace('javascript:"";');
// We have to delay receiving to avoid access-denied error.
// 初始化消息监听
Messenger.prototype.initListen = function() {
var self = this;
setTimeout(function() {
self.receive();
}, 0);
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;
}
};
// recieve and parse the data, call the listener function
Messenger.prototype.receive = function() {
var rawData = null;
try {
rawData = this.receiverWin.name;
} catch (ex) {}
if (!rawData) return;
this.receiverWin.name = "";
var self = this;
var dataList = rawData.substring(1).split("|");
for (var i = 0; i < dataList.length; i++) (function() {
var data = decodeURIComponent(dataList[i]);
setTimeout(function() {
(self.onmessage || function() {}).call(self, data);
}, 0);
})();
// 监听消息
Messenger.prototype.listen = function(callback) {
this.listenFunc.push(callback);
};
// send data via push the data into the message queue
Messenger.prototype.send = function(data) {
this.queue.push(data);
if (!this.senderWin) return;
this.flush();
// 注销监听
Messenger.prototype.clear = function() {
this.listenFunc = [];
};
Messenger.prototype.flush = function() {
var dataList = [];
for (var i = 0; i < this.queue.length; i++) dataList[i] = encodeURIComponent(this.queue[i]);
var encodedData = "|" + dataList.join("|");
try {
this.senderWin.name += encodedData;
this.queue.length = 0;
} catch (ex) {
this.senderWin.location.replace("about:blank");
var self = this;
setTimeout(function() {
self.flush();
}, 0);
// 广播消息
Messenger.prototype.send = function(msg) {
var targets = this.targets, target;
for (target in targets) {
if (targets.hasOwnProperty(target)) {
targets[target].send(msg);
}
}
};
}
Messenger.prototype.destroy = function() {
// 删除定时器
clearInterval(this.timerId);
// 解除绑定事件
if (this._receiver) {
if (window.removeEventListener) window.removeEventListener("message", this._receiver, false); else if (window.detachEvent) window.detachEvent("onmessage", this._receiver);
}
// 解除绑定事件 ie
if (document.detachEvent && this._dataavailable) {
document.detachEvent("ondataavailable", this._dataavailable);
}
// 删除fragment
this._fragment && document.body.removeChild(this._fragment);
// 删除实例属性
for (var p in this) {
if (this.hasOwnProperty(p)) {
delete this[p];
}
}
};
module.exports = Messenger;
});
return Messenger;
}();
});
2 changes: 1 addition & 1 deletion dist/messenger.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 56740a6

Please sign in to comment.