encodeURI Быть переопределенным в сафари

обзор

Поэтому я написал плагин Video.js, который отправляет отчеты в Google Analytics и в наши собственные отчеты.

Каждый запрос JSONP, который мы отправляем обратно на нашу страницу, кодируется с использованием encodeURIComponent с использованием этого метода. Первые несколько правильно сработали. Затем начинается ошибка с TypeError: '[object Object]' is not a function (evaluating 'encodeURIComponent(p)'), Это происходит только в Safari. (Я на сафари 7.0.1 на OSX Mavericks)

Я даже пытался сделать всю строку 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(опция)

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 теперь последний объект, с которым он был вызван.

Есть идеи?

1 ответ

Решение

В каждом из слушателей отслеживания событий есть / было videoData = getVideoData() как только я добавил var в videoData проблема прекратилась Кто-нибудь видит, почему это может быть причиной? Я понимаю, что это было установлено в глобальную переменную, но как encodeURIComponent устанавливается в объект?

Другие вопросы по тегам