iframeドメイン間転送データ(二)----MessengerJS;サブページの親ページデータ転送を実現する.


2つの異なるプロジェクトを行い、iframeはドメインに埋め込まれ、データを転送します.前に、ドメイン間の問題をどのように簡単に処理するか、比較的不器用な解決策を書いたことがあります.中間ページ(html)で、データ伝送の中継局をする.
今回1つのプラグインを発見して、MessengerJSはデータ通信をしに来て、やっとこのパッケージの良いプラグインがこのようなドメインをまたぐ方式をするのは実はとても簡単であることを発見しました;ここで簡単にこのMessengerJSを分析して、コードは比較的に少なくて、そんなに140行の注釈を加えていません;
主にH 5の通信プロトコルpostMessage()メソッドを用いてデータ伝送を行う.postMessage私は1篇のログを書くことができて理解して、今先にMessengerJSを解析します;
MessengerJSソース:
/**
 *     __  ___
 *    /  |/  /___   _____ _____ ___   ____   ____ _ ___   _____
 *   / /|_/ // _ \ / ___// ___// _ \ / __ \ / __ `// _ \ / ___/
 *  / /  / //  __/(__  )(__  )/  __// / / // /_/ //  __// /
 * /_/  /_/ \___//____//____/ \___//_/ /_/ \__, / \___//_/
 *                                        /____/
 *
 * @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, prefix){
        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;
        this.prefix = prefix;
    }

    //   target     ,       ,          
    if ( supportPostMessage ){
        // IE8+          
        Target.prototype.send = function(msg){
            this.target.postMessage(this.prefix + '|' + this.name + '__Messenger__' + msg, '*');
        };
    } else {
        //   IE 6/7
        Target.prototype.send = function(msg){
            var targetFunc = window.navigator[this.prefix + this.name];
            if ( typeof targetFunc == 'function' ) {
                targetFunc(this.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 = [];
        this.prefix = projectName || prefix;
        this.initListen();
    }

    //         
    Messenger.prototype.addTarget = function(target, name){
        var targetObj = new Target(target, name,  this.prefix);
        this.targets[name] = targetObj;
    };

    //        
    Messenger.prototype.initListen = function(){
        var self = this;
        var generalCallback = function(msg){
            if(typeof msg == 'object' && msg.data){
                msg = msg.data;
            }

            var msgPairs = msg.split('__Messenger__');
            var msg = msgPairs[1];
            var pairs = msgPairs[0].split('|');
            var prefix = pairs[0];
            var name = pairs[1];

            for(var i = 0; i < self.listenFunc.length; i++){
                if (prefix + name === self.prefix + self.name) {
                    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[this.prefix + this.name] = generalCallback;
        }
    };

    //     
    Messenger.prototype.listen = function(callback){
        var i = 0;
        var len = this.listenFunc.length;
        var cbIsExist = false;
        for (; i < len; i++) {
            if (this.listenFunc[i] == callback) {
                cbIsExist = true;
                break;
            }
        }
        if (!cbIsExist) {
            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;
})();

分析:
SUPPORTPOSTMESSAGE変数:
現在のブラウザがpostMessageをサポートしているかどうかを検出します.PostMessageはHTML 5に導入された通信APIであり、外部ウィンドウのような安全なドメイン間通信を実現してメッセージを送信することができる.
注意:ie 6/7はpostMessageをサポートしていないため、ie 6/7ではドメイン間通信は通常windowを使用する.name window.navigatorはwindowとname類似の特性を持ち、コールバックメソッドを保存できます.
MessengerJSの実現構想は、高級ブラウザがpostMessageを使用し、postMessageの使用windowをサポートしないことである.navigatorはコールバックメソッドを保存します
Targetクラス:メッセージクラス、送信実行者;
function Target(target, name){
        this.target = target;
        this.name = name;
}
/**
*        
*/
Target.prototype.send = function(msg){
    //     
    this.target.postMessage(this.name);
};

Messengerクラス:
メッセージングクラスは、複数のメッセージオブジェクトを作成し、複数のリスニングイベントを登録し、各メッセージオブジェクトのブロードキャストメッセージがこのメッセージングクラスの下のすべてのリスニングイベントに受信されます.このクラスの主な役割は、ドメイン間で送られてきた情報を傍受することです.
//      
Messenger.prototype.addTarget(target, name);//  target   ,         ;

//        
Messenger.prototype.initListen = function(){};

//     
Messenger.prototype.listen = function(callback){};

//     
Messenger.prototype.clear = function(){};

//     
//      msg,       ,             ,        
Messenger.prototype.send = function(msg){};

例:親ページがiframeスクロールバーを無効にすると、サブページから伝わる高さで親ページのダイナミックスクロール効果を実現します.
iframe親ページ:
//   messenger     ,iframe_parent,        addTarget(target,name)      
// name         
var messenger = new Messenger('iframe_parent');
var iframe = document.getElementById('iframe1');
messenger.addTarget(iframe.contentWindow, 'iframe');

messenger.listen(function (msg) {
        //               ;
        var result = Number(msg);

    $('body,html').animate({scrollTop: msg}, 500);
});

iframe埋め込みサブページ:
// iframe     
var messenger = new Messenger('iframe');
//   iframe_parent        messenger         
messenger.addTarget(window.parent, 'iframe_parent'); 

//    main   
var height = $('.main').height();
messenger.targets['parent'].send(height);
//          
messenger.listen(function (msg) {
    //...
});

まとめ:ドメインをまたぐ方法はたくさんありますが、自分に合ったものを見つけるのが一番です.