diff --git a/README.md b/README.md
index ac845b5..97c12e3 100644
--- a/README.md
+++ b/README.md
@@ -71,14 +71,29 @@ Since modern browsers have native cross-document communication method(the PostMe
messenger.send(msg);
6. 现在看到iframe收到消息的alert提示了吗?
-
+
## Demo ##
http://biqing.github.io/labs/messenger/parent.html
-
+
+或者用Node.js开启测试服务器,在`test`文件夹内的:
+``
+$ node server
+``
+然后打开该地址:locallhost:80进行测试。
## 关于消息安全性 ##
由于任何iframe都可以收到广播的消息,建议传递消息时使用JSON String的形式,使用一个字段做消息有效性的验证。如果怕一个固定值(如项目名)不安全,可以使用一个简单的加密算法,并对业务脚本进行压缩混淆,此时的安全风险可以降到最低。
## 问题与建议 ##
使用中难免遇到问题,欢迎提问与建议 : )
-[提交Issue](https://github.com/biqing/MessengerJS/issues/new)
\ No newline at end of file
+[提交Issue](https://github.com/biqing/MessengerJS/issues/new)
+
+# 根据前辈的Messenger写成了Messenger2 #
+支持消息标记,比如监听一个名为 `test`的消息名称,发送的时候只发送消息个`test`的监听事件。
+
+ //iframe 1
+ ifr.listen('test',function(data){
+ console.log('post'+data+'from test');
+ });
+ //iframe 2
+ ifr2.to('ifr',0).post('test','test1');
diff --git a/messenger2.js b/messenger2.js
new file mode 100644
index 0000000..f072e7c
--- /dev/null
+++ b/messenger2.js
@@ -0,0 +1,99 @@
+window.Messenger = (function(w,jQuery){
+ var prefix = '[_Project_Name]';
+
+ var ie = w.navigator.appName !== 'Netscape';
+ var parent = w.parent;
+ var nv = ie ? parent.navigator : void(0);
+
+ var Messenger = function (myName){
+ if(ie)this.self = nv[myName] = new Watcher();
+ this.evNames = {};
+ this.data = [];
+ return this;
+ };
+
+ var iePostMessage = {};
+ var usePostMessage = {};
+ //ie下的通信
+ //监视器
+ function Watcher(){
+ this.targets = {};
+ }
+ Watcher.prototype.addListener = function(evName,callback){
+ var targets = this.targets;
+ targets[evName] = callback;
+ };
+ Watcher.prototype.emit = function(evName,msg){
+ var targets = this.targets;
+ targets[evName](msg);
+ };
+ //ie post
+ iePostMessage.to = function(target,n){
+ this.tName = target;
+ return this;
+ };
+ iePostMessage.post = function(evName,msg){
+ var self = this;
+ var name = self.tName;
+ parent['ifr'].onload = function(){
+ self.target = nv[name];
+ self.target.emit(evName,msg);
+ }
+ return this;
+ };
+ iePostMessage.listen = function(evName,callback){
+ this.self.addListener(evName,callback);
+ return this;
+ };
+ //post message
+ usePostMessage.post = function(evName,msg){
+ var self = this;
+ var data = self.data;
+ var tg = self.target;
+ data.push({name:evName,msg:msg});
+ self._onload(function(){
+ tg.contentWindow.postMessage(data,tg.src);
+ });
+ return this;
+ };
+ usePostMessage.to = function(target,n){
+ var self = this;
+ self.tName = target;
+ if(n === void(0)){
+ self.target = document.querySelector('#'+self.tName);
+ }else{
+ self.ftf = !0;
+ self.target = {contentWindow : parent.frames[n],src:'*'}
+ }
+ return this;
+ };
+ usePostMessage.listen = function(evName,callback){
+ var self = this;
+ var name = evName;
+ var names = self.evNames;
+ names[name] = callback;
+ var wrap = function(event){
+ var data = event.data;
+ var ns = names;
+ var n = name;
+ data.forEach(function(v){
+ var evN = v.name;
+ if(n && n!==evN)return;
+ var msg = v.msg;
+ if(n==evN || (!n && ns[evN]))ns[evN](msg);
+ });
+ };
+ w.onmessage = wrap;
+ return this;
+ };
+ Messenger.prototype = ie ? iePostMessage : usePostMessage;
+ Messenger.prototype._onload = function(fn){
+ var self = this;
+ if(self.ftf){
+ fn();
+ }else if(w == parent){
+ self.target.onload = fn;
+ }
+ }
+ return Messenger;
+})(window,window.jQuery);
diff --git a/demo/child.html b/test/child.html
similarity index 97%
rename from demo/child.html
rename to test/child.html
index 3bedf21..6348b62 100644
--- a/demo/child.html
+++ b/test/child.html
@@ -1,44 +1,44 @@
-
-
-
-
-
- iframe communication (child window page)
-
-
-
-
-
-
- child window
- This is a child window under the domain:
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ iframe communication (child window page)
+
+
+
+
+
+
+ child window
+ This is a child window under the domain:
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/iframe1.html b/test/iframe1.html
similarity index 94%
rename from demo/iframe1.html
rename to test/iframe1.html
index 2a7f1d8..e2fd168 100644
--- a/demo/iframe1.html
+++ b/test/iframe1.html
@@ -1,53 +1,53 @@
-
-
-
-
-
- iframe communication (iframe page)
-
-
-
-
-
-
- iframe1
- This is a iframe under the domain:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+ iframe communication (iframe page)
+
+
+
+
+
+
+ iframe1
+ This is a iframe under the domain:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/iframe2.html b/test/iframe2.html
similarity index 97%
rename from demo/iframe2.html
rename to test/iframe2.html
index 203f088..3e52c3f 100644
--- a/demo/iframe2.html
+++ b/test/iframe2.html
@@ -1,53 +1,53 @@
-
-
-
-
-
- iframe communication (iframe page)
-
-
-
-
-
-
- iframe2
- This is a iframe under the domain:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ iframe communication (iframe page)
+
+
+
+
+
+
+ iframe2
+ This is a iframe under the domain:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/messenger.js b/test/messenger.js
new file mode 100644
index 0000000..7fa8abf
--- /dev/null
+++ b/test/messenger.js
@@ -0,0 +1,123 @@
+/**
+ * __ ___
+ * / |/ /___ _____ _____ ___ ____ ____ _ ___ _____
+ * / /|_/ // _ \ / ___// ___// _ \ / __ \ / __ `// _ \ / ___/
+ * / / / // __/(__ )(__ )/ __// / / // /_/ // __// /
+ * /_/ /_/ \___//____//____/ \___//_/ /_/ \__, / \___//_/
+ * /____/
+ *
+ * @description MessengerJS, a common cross-document communicate solution.
+ * @author biqing kwok
+ * @version 2.0
+ * @license release under MIT license
+ */
+
+window.Messenger = (function(){
+
+ // 消息前缀, 建议使用自己的项目名, 避免多项目之间的冲突
+ // !注意 消息前缀应使用字符串类型
+ var prefix = "[PROJECT_NAME]",
+ supportPostMessage = 'postMessage' in window;
+
+ // Target 类, 消息对象
+ function Target(target, name){
+ var errMsg = '';
+ if(arguments.length < 2){
+ errMsg = 'target error - target and name are both requied';
+ } 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;
+ if(typeof prefix !== 'string') {
+ prefix = prefix.toString();
+ }
+ 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);
+ }
+ }
+ };
+
+ return Messenger;
+})();
diff --git a/demo/parent.html b/test/parent.html
similarity index 83%
rename from demo/parent.html
rename to test/parent.html
index 0156eb9..a8bc66c 100644
--- a/demo/parent.html
+++ b/test/parent.html
@@ -1,76 +1,76 @@
-
-
-
-
-
- Demo - MessengerJS
-
-
-
-
-
-
-
Demo of MessengerJS
-
Github project page
-
- parent
- Domain of the parent page
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+ Demo - MessengerJS
+
+
+
+
+
+
+
Demo of MessengerJS
+
Github project page
+
+ parent
+ Domain of the parent page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/server.js b/test/server.js
new file mode 100644
index 0000000..3814024
--- /dev/null
+++ b/test/server.js
@@ -0,0 +1 @@
+require('./server/index.js')();
diff --git a/test/server/http.js b/test/server/http.js
new file mode 100644
index 0000000..38bccf4
--- /dev/null
+++ b/test/server/http.js
@@ -0,0 +1,30 @@
+var u = require('url');
+var fs = require('fs');
+
+var http = require('http').createServer(function(req,res){
+ var path = require('url').parse(req.url).pathname;
+ if(req.method == 'GET'){
+ switch(path){
+ case '/':
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ fs.readFile('./parent.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/child.html':
+ fs.readFile('./child.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/messenger.js':
+ res.writeHead(200, {'Content-Type': 'application/x-javascript'});
+ fs.readFile('./messenger.js',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ default:
+ res.end('not path');
+ }
+ }
+}).listen(80);
+console.log('serve open - locallhost:80');
diff --git a/test/server/http1.js b/test/server/http1.js
new file mode 100644
index 0000000..6ad6d7a
--- /dev/null
+++ b/test/server/http1.js
@@ -0,0 +1,26 @@
+var u = require('url');
+var fs = require('fs');
+
+var http = require('http').createServer(function(req,res){
+
+ var path = require('url').parse(req.url).pathname;
+
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ if(req.method == 'GET'){
+ switch(path){
+ case '/':
+ fs.readFile('./iframe1.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/messenger.js':
+ res.writeHead(200, {'Content-Type': 'application/x-javascript'});
+ fs.readFile('./messenger.js',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ default:
+ res.end('not path');
+ }
+ }
+}).listen(8080);
diff --git a/test/server/http2.js b/test/server/http2.js
new file mode 100644
index 0000000..3abb7a2
--- /dev/null
+++ b/test/server/http2.js
@@ -0,0 +1,26 @@
+var u = require('url');
+var fs = require('fs');
+
+var http = require('http').createServer(function(req,res){
+
+ var path = require('url').parse(req.url).pathname;
+
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ if(req.method == 'GET'){
+ switch(path){
+ case '/':
+ fs.readFile('./iframe2.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/messenger.js':
+ res.writeHead(200, {'Content-Type': 'application/x-javascript'});
+ fs.readFile('./messenger.js',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ default:
+ res.end('not path');
+ }
+ }
+}).listen(3000);
diff --git a/test/server/index.js b/test/server/index.js
new file mode 100644
index 0000000..ebadb38
--- /dev/null
+++ b/test/server/index.js
@@ -0,0 +1,7 @@
+var cp = require('child_process');
+function server(){
+ var child = cp.fork('./server/http.js');
+ var child1 = cp.fork('./server/http1.js');
+ var child2 = cp.fork('./server/http2.js');
+}
+module.exports = server;
diff --git a/test2/iframe1.html b/test2/iframe1.html
new file mode 100644
index 0000000..6e82eff
--- /dev/null
+++ b/test2/iframe1.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Document
+
+
+ 0sdasdasdas
+
+
+
+
diff --git a/test2/iframe2.html b/test2/iframe2.html
new file mode 100644
index 0000000..682b4f6
--- /dev/null
+++ b/test2/iframe2.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Document
+
+
+ if2
+
+
+
+
diff --git a/test2/messenger.js b/test2/messenger.js
new file mode 100644
index 0000000..f072e7c
--- /dev/null
+++ b/test2/messenger.js
@@ -0,0 +1,99 @@
+window.Messenger = (function(w,jQuery){
+ var prefix = '[_Project_Name]';
+
+ var ie = w.navigator.appName !== 'Netscape';
+ var parent = w.parent;
+ var nv = ie ? parent.navigator : void(0);
+
+ var Messenger = function (myName){
+ if(ie)this.self = nv[myName] = new Watcher();
+ this.evNames = {};
+ this.data = [];
+ return this;
+ };
+
+ var iePostMessage = {};
+ var usePostMessage = {};
+ //ie下的通信
+ //监视器
+ function Watcher(){
+ this.targets = {};
+ }
+ Watcher.prototype.addListener = function(evName,callback){
+ var targets = this.targets;
+ targets[evName] = callback;
+ };
+ Watcher.prototype.emit = function(evName,msg){
+ var targets = this.targets;
+ targets[evName](msg);
+ };
+ //ie post
+ iePostMessage.to = function(target,n){
+ this.tName = target;
+ return this;
+ };
+ iePostMessage.post = function(evName,msg){
+ var self = this;
+ var name = self.tName;
+ parent['ifr'].onload = function(){
+ self.target = nv[name];
+ self.target.emit(evName,msg);
+ }
+ return this;
+ };
+ iePostMessage.listen = function(evName,callback){
+ this.self.addListener(evName,callback);
+ return this;
+ };
+ //post message
+ usePostMessage.post = function(evName,msg){
+ var self = this;
+ var data = self.data;
+ var tg = self.target;
+ data.push({name:evName,msg:msg});
+ self._onload(function(){
+ tg.contentWindow.postMessage(data,tg.src);
+ });
+ return this;
+ };
+ usePostMessage.to = function(target,n){
+ var self = this;
+ self.tName = target;
+ if(n === void(0)){
+ self.target = document.querySelector('#'+self.tName);
+ }else{
+ self.ftf = !0;
+ self.target = {contentWindow : parent.frames[n],src:'*'}
+ }
+ return this;
+ };
+ usePostMessage.listen = function(evName,callback){
+ var self = this;
+ var name = evName;
+ var names = self.evNames;
+ names[name] = callback;
+ var wrap = function(event){
+ var data = event.data;
+ var ns = names;
+ var n = name;
+ data.forEach(function(v){
+ var evN = v.name;
+ if(n && n!==evN)return;
+ var msg = v.msg;
+ if(n==evN || (!n && ns[evN]))ns[evN](msg);
+ });
+ };
+ w.onmessage = wrap;
+ return this;
+ };
+ Messenger.prototype = ie ? iePostMessage : usePostMessage;
+ Messenger.prototype._onload = function(fn){
+ var self = this;
+ if(self.ftf){
+ fn();
+ }else if(w == parent){
+ self.target.onload = fn;
+ }
+ }
+ return Messenger;
+})(window,window.jQuery);
diff --git a/test2/parent.html b/test2/parent.html
new file mode 100644
index 0000000..7b7acfc
--- /dev/null
+++ b/test2/parent.html
@@ -0,0 +1,15 @@
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
diff --git a/test2/server.js b/test2/server.js
new file mode 100644
index 0000000..3814024
--- /dev/null
+++ b/test2/server.js
@@ -0,0 +1 @@
+require('./server/index.js')();
diff --git a/test2/server/http.js b/test2/server/http.js
new file mode 100644
index 0000000..a8ef8b0
--- /dev/null
+++ b/test2/server/http.js
@@ -0,0 +1,25 @@
+var u = require('url');
+var fs = require('fs');
+
+var http = require('http').createServer(function(req,res){
+ var path = require('url').parse(req.url).pathname;
+ if(req.method == 'GET'){
+ switch(path){
+ case '/':
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ fs.readFile('./parent.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/messenger.js':
+ res.writeHead(200, {'Content-Type': 'application/x-javascript'});
+ fs.readFile('./messenger.js',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ default:
+ res.end('not path');
+ }
+ }
+}).listen(80);
+console.log('serve open - locallhost:80');
diff --git a/test2/server/http1.js b/test2/server/http1.js
new file mode 100644
index 0000000..a3a222b
--- /dev/null
+++ b/test2/server/http1.js
@@ -0,0 +1,24 @@
+var u = require('url');
+var fs = require('fs');
+
+var http = require('http').createServer(function(req,res){
+ var path = require('url').parse(req.url).pathname;
+ if(req.method == 'GET'){
+ switch(path){
+ case '/':
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ fs.readFile('./iframe1.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/messenger.js':
+ res.writeHead(200, {'Content-Type': 'application/x-javascript'});
+ fs.readFile('./messenger.js',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ default:
+ res.end('not path');
+ }
+ }
+}).listen(8080);
diff --git a/test2/server/http2.js b/test2/server/http2.js
new file mode 100644
index 0000000..a03dfbc
--- /dev/null
+++ b/test2/server/http2.js
@@ -0,0 +1,24 @@
+var u = require('url');
+var fs = require('fs');
+
+var http = require('http').createServer(function(req,res){
+ var path = require('url').parse(req.url).pathname;
+ if(req.method == 'GET'){
+ switch(path){
+ case '/':
+ res.writeHead(200, {'Content-Type': 'text/html'});
+ fs.readFile('./iframe2.html',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ case '/messenger.js':
+ res.writeHead(200, {'Content-Type': 'application/x-javascript'});
+ fs.readFile('./messenger.js',function(err,data){
+ res.end(data,'utf8');
+ });
+ break;
+ default:
+ res.end('not path');
+ }
+ }
+}).listen(3000);
diff --git a/test2/server/index.js b/test2/server/index.js
new file mode 100644
index 0000000..739b72f
--- /dev/null
+++ b/test2/server/index.js
@@ -0,0 +1,7 @@
+var cp = require('child_process');
+function server(){
+ var child = cp.fork('./server/http.js');
+ var child1 = cp.fork('./server/http1.js');
+ var child1 = cp.fork('./server/http2.js');
+}
+module.exports = server;