0

概要

そこで、Google アナリティクスとカスタム レポートに報告する Video.js プラグインを作成しました。

ページに送り返す各 JSONP リクエストは、このメソッドを使用して、encodeURIComponent を使用してエンコードされます。最初のいくつかは正しく起動します。その後、エラーが発生し始めますTypeError: '[object Object]' is not a function (evaluating 'encodeURIComponent(p)')。これは Safari でのみ発生します。(OSX Mavericks で safari 7.0.1 を使用しています)

を使用して URL 文字列全体を実行しようとしましたencodeURIが、その関数にも同じことが起こります。

問題を示すために [JS FIDDLE][2] を作成しました。サンプルコードだけで再作成できなかったので、関連するすべてのファイルを外部リソースに含めました。実行されない場合は、約 85% の確率でページを再実行してください。

関数のステップスルー

最初に追跡するイベントを追加します

this.on('play',onPlay);
this.on('pause',onPause);

イベントが発生すると、これらの関数によってキャッチされます

function onPlay( e ) {
    videoData = getVideoData();
    doTracking({
        'category': videoData.cid,
        'action': videoData.vid,
        'label': 'Play',
        'value': null
    });
}

function onPause( e ) {
    videoData = getVideoData();
    doTracking({
        'category': videoData.cid,
        'action': videoData.vid,
        'label': 'Pause',
        'value': getTime()
    });
}

ビデオデータを取得するもの

function getVideoData() {
    var src = videojsRef.player().currentSrc();
    var srcSplit = src.split('/');

    var filename = srcSplit[srcSplit.length-1];
    var filenameSplit = filename.split('.');

    var cid = filenameSplit[0];
    var vid = filenameSplit[1];
    var type = filenameSplit[2];

    var returnObj = {
        'cid': cid,
        'vid': vid,
        'filename': filename
    };

    return returnObj;
}

そして、両方のトラッキング関数を呼び出す単なるヘルパー関数である「doTracking」を呼び出します。

function doTracking( opt ) {

    if ( gaType && bvReady ) { // Are both tracking types initialized
        // Send to google
        googleTrack( opt );

        // Send to BetterVideo
        bvTrack( opt );
    } else {
        queue.push( opt );
    }
}

bvTrack( opt ) を呼び出すもの

function bvTrack( opt ) {
    var args = {
        pid: playerid,
        cid: opt.category,
        vcd: opt.action,
        a: opt.label,
        callback: '{callback}'          
    };

    if ( opt.value !== null ) {
        args.val = opt.value;
    }

    // Heres where the trouble starts
    new videojs.JSONP('http://jsfiddle.net/echo/jsonp/?'+serializeToQuery(args), function( response ) {
        console.log('[BV Reporting] Tracking Response: ', arguments );
    })
}

データはここでシリアル化されます

function serializeToQuery( obj ) {
    var str = [];
    console.log( "serializeToQuery", obj );
    for(var p in obj) {

        if ( obj.hasOwnProperty(p) ) {
            console.log( '    property', p, obj[p]);
            console.log( '        encodeURIComponent', typeof encodeURIComponent == 'function' ? 'function' : encodeURIComponent );
            console.log( '        encoded property', encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); 
        }
    }   
    return str.join("&");
}

そして、d3.js にインスパイアされた JSONPに渡されます (SO でここで見つけたと思います)。

videojs.JSONP = function (url, callback) {
    var docHead = document.getElementsByTagName('head')[0];
    function rand() {
        var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
        c = '', i = -1;
        while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
        return c;
    }

    function create(url) {
        var e = url.match(/callback=jsonp.(\w+)/),
        c = e ? e[1] : rand();
        videojs.JSONP[c] = function(data) {
            callback(data);
            delete videojs.JSONP[c];
            docHead.removeChild(script);
        };
        return 'videojs.JSONP.' + c;
    }

    var cb = create(url),
        script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url.replace(/(\{|%7B)callback(\}|%7D)/, cb);
        docHead.appendChild(script)
};

出力

serializeToQuery Object { 
                            a: "Pause"
                            callback: "{callback}"
                            cid: "oceans"
                            pid: "885FA551-A873-4BB9-891A-ABC08CD47D36"
                            val: 6
                            vcd: "mp4"
                        }
    property pid 885FA551-A873-4BB9-891A-ABC08CD47D36
        encodeURIComponent function
        encoded property pid=885FA551-A873-4BB9-891A-ABC08CD47D36
    property cid oceans
        encodeURIComponent function
        encoded property cid=oceans
    property vcd mp4
        encodeURIComponent function
        encoded property vcd=mp4
    property a Pause
        encodeURIComponent function
        encoded property a=Pause
    property callback {callback}
        encodeURIComponent function
        encoded property callback=%7Bcallback%7D
    property val 6
        encodeURIComponent function
        encoded property val=6

しかし、2 ~ 3 回の JSONP 呼び出しの後、次のように出力されます。

serializeToQuery Object {
                            a: "Play"
                            callback: "{callback}"
                            cid: "oceans"
                            pid: "885FA551-A873-4BB9-891A-ABC08CD47D36"
                            vcd: "mp4"
                        }

    property pid 885FA551-A873-4BB9-891A-ABC08CD47D36 
        encodeURIComponent  Object {
                                        cid: "oceans"
                                        filename: "oceans.mp4"
                                        vid: "mp4"
                                    }

[Error] TypeError: '[object Object]' is not a function (evaluating 'encodeURIComponent(p)')
    serializeToQuery (videojs.bvReporting.js, line 531)
    bvTrack (videojs.bvReporting.js, line 481)
    doTracking (videojs.bvReporting.js, line 329)
    onPlay (videojs.bvReporting.js, line 113)
    ret (video.dev.js, line 769)
    dispatcher (video.dev.js, line 295)
    trigger (video.dev.js, line 529)
    trigger (video.dev.js, line 1868)
    eventHandler (video.dev.js, line 5376)
    ret (video.dev.js, line 769)
    dispatcher (video.dev.js, line 295)

ご覧のとおりencodeURIComponent、最後に呼び出されたオブジェクトです。

何か案は?

4

1 に答える 1

0

追跡イベント リスナーのそれぞれにある /videoData = getVideoData() いったん問題に追加varするvideoDataと停止しました。なぜそれが原因なのか誰にもわかりますか?グローバル変数に設定されていたことは理解していますが、encodeURIComponent はどのようにオブジェクトに設定されるのでしょうか?

于 2014-02-11T15:53:46.477 に答える