【问题标题】:jQuery indexOf error for xdomain.js cross-domain link scriptxdomain.js 跨域链接脚本的 jQuery indexOf 错误
【发布时间】:2012-02-26 09:29:38
【问题描述】:

我正在使用脚本来检测跨域链接以进行谷歌分析跨域跟踪。原始脚本 (xdomain.js) 由 Luna Metrics 的优秀人员提供。这是我修改后的脚本,在 StackOverflow 上向 educardocereto 致敬,建议更改以在 GATC 中启用 setAllowAnchor(我已在第 40 行注释了控制台错误首先指向的位置):

var jQueryXD = jQuery.noConflict();
/* I added var because page loads 2 versions 
    of jquery - not the source of the problem.*/

function listenToClicks()
{
    var domains=["domain1.com", "domain2.com"];
    var fileTypes=[".pdf"];

    jQueryXD('a').each(function(index) {
        var link = jQueryXD(this);
        var href = link.attr('href');

        jQueryXD.each(fileTypes, function(i) {
            if(jQueryXD(link).attr('href').indexOf(this)!=-1){ //this is line 40
                valid = false;
                jQueryXD(link).bind('click', function(c) {
                    c.preventDefault();
                    _gat._getTrackerByName()._trackEvent('Download', 'Click - ' +      jQueryXD(link).attr('href'));
                    setTimeout('document.location = "' + jQueryXD(link).attr('href') + '"', 100);
                });
            }
        });

        var valid = false;
        jQueryXD.each(domains, function(j) {
            try
            {
                if((jQueryXD(link).attr('href').indexOf(this)!=-1)&&(window.location.href.indexOf(this)==-1)){  
                    valid = true;

                    if (valid)
                    {
                        jQueryXD(link).bind('click', function(l) {
                            if(typeof(_gat)=="object"){
                                l.preventDefault();
                                if (jQueryXD(link).attr('target') != "_blank")
                                {                               // _gaq.push(['_link',jQueryXD(link).attr('href')]);
                                    _gaq.push(['_link',jQueryXD(link).attr('href'), true]); // mod
                                }
                                else
                                {
                                    var tracker = _gat._getTrackerByName();
                                    //var fullUrl = tracker._getLinkerUrl(jQueryXD(link).attr('href'));
                                    var fullUrl = tracker._getLinkerUrl(jQueryXD(link).attr('href'), true); //mod
                                    window.open(fullUrl);
                                }
                            }
                        });
                    }
                }

            }
            catch(e)
            {
                //Bad A tag
            }           
        });

        var rootDomain = document.domain.split(".")[document.domain.split(".").length - 2] + "." + document.domain.split(".")[document.domain.split(".").length - 1];

        if ( (href.match(/^http/)) && (href.indexOf(rootDomain) == -1) && !valid) {
            jQueryXD(link).bind('click', function(d) {
                    d.preventDefault();
                    _gat._getTrackerByName()._trackEvent('Outbound Link', href);
                    setTimeout('document.location = "' + href + '"', 100);
                });            
        }
    });

}

jQueryXD(document).ready(function() {
    listenToClicks();
});

Chrome javascript 控制台的输出:

 Uncaught TypeError: 
Cannot call method 'indexOf' of undefined        xdomain-nfi-nfs-anchormod-noconflict.js:40
    jQueryXD.each.valid                          xdomain-nfi-nfs-anchormod-noconflict.js:40
    jQuery.extend.each                           jquery-1.2.6.min.js:21
    (anonymous function)                         xdomain-nfi-nfs-anchormod-noconflict.js:39
    jQuery.extend.each                           jquery-1.2.6.min.js:21
    jQuery.fn.jQuery.each                        jquery-1.2.6.min.js:12
    listenToClicks                               xdomain-nfi-nfs-anchormod-noconflict.js:35
    (anonymous function)                         xdomain-nfi-nfs-anchormod-noconflict.js:100
    jQuery.fn.extend.ready                       jquery-1.2.6.min.js:27
    jQuery.extend.ready.jQuery.readyList         jquery-1.2.6.min.js:27
    jQuery.extend.each                           jquery-1.2.6.min.js:21
    jQuery.extend.ready                          jquery-1.2.6.min.js:27

所以,至少它似乎没有混淆两个 jquery 实例。我也用 jquery 1.7.1 试过了。我使用的是 1.2.6,因为该脚本似乎已经在该版本上进行了大多数测试。

【问题讨论】:

    标签: javascript jquery google-analytics cross-domain


    【解决方案1】:

    在这里你缓存 jQuerified 元素和 href attr。

    var link = jQueryXD(this);
    var href = link.attr('href');
    

    比你后来为什么这样做:

    jQueryXD(link).attr('href').indexOf(this)
    

    您可以调用link.attr('href').indexOf(this),因为link 已经是一个jQuery 对象,或者您可以直接使用缓存的href 并执行此操作href.indexOf(this)

    我仍然认为当链接没有 href 属性时会发生您看到的错误。所以你最好在继续你的逻辑之前检查 href 是否未定义。

    我在 jQuery 1.2.6 和 1.7 上都对其进行了测试。它似乎工作正常。

    这是完成的脚本。

    var jQueryXD = jQuery.noConflict();
    /* I added var because page loads 2 versions 
        of jquery - not the source of the problem.*/
    
    function listenToClicks() {
        var domains = ["domain1.com", "domain2.com"];
        var fileTypes = [".pdf"];
    
        jQueryXD('a').each(function(index) {
            var link = jQueryXD(this);
            var href = link.attr('href');
            if(!href){
                // This element doesnt have a href
                return true;
            }
    
            var valid = false;
            jQueryXD.each(fileTypes, function(i) {
                if (href.indexOf(this) != -1) { //this is line 40
                    valid = false;
                    link.bind('click', function(c) {
                        c.preventDefault();
                        _gat._getTrackerByName()._trackEvent('Download', 'Click - ' + link.attr('href'));
                        setTimeout('document.location = "' + href + '"', 100);
                    });
                }
            });
    
            jQueryXD.each(domains, function(j) {
                try {
                    if ((href.indexOf(this) != -1) && (window.location.href.indexOf(this) == -1)) {
                        valid = true;
    
                        if (valid) {
                            link.bind('click', function(l) {
                                if (typeof(_gat) == "object") {
                                    l.preventDefault();
                                    if (link.attr('target') != "_blank") { // _gaq.push(['_link',jQueryXD(link).attr('href')]);
                                        _gaq.push(['_link', href, true]); // mod
                                    }
                                    else {
                                        var tracker = _gat._getTrackerByName();
                                        //var fullUrl = tracker._getLinkerUrl(href);
                                        var fullUrl = tracker._getLinkerUrl(href, true); //mod
                                        window.open(fullUrl);
                                    }
                                }
                            });
                        }
                    }
    
                }
                catch (e) {
                    //Bad A tag
                }
            });
    
            var rootDomain = document.domain.split(".")[document.domain.split(".").length - 2] + "." + document.domain.split(".")[document.domain.split(".").length - 1];
    
            if ((href.match(/^http/)) && (href.indexOf(rootDomain) == -1) && !valid) {
                jQueryXD(link).bind('click', function(d) {
                    d.preventDefault();
                    _gat._getTrackerByName()._trackEvent('Outbound Link', href);
                    setTimeout('document.location = "' + href + '"', 100);
                });
            }
        });
    
    }
    
    jQueryXD(document).ready(function() {
        listenToClicks();
    });
    

    但您可能在这里重新发明轮子。有一些更好的脚本可以实现相同的目标。我想你可能有兴趣研究GAS。它是 ga.js 的一个包装器,它扩展并添加了一堆东西,包括 crossDomain 和 downloadTracking。

    剧透:我是GAS的主要开发者。

    https://github.com/CardinalPath/gas

    【讨论】:

    • 我刚下载了 GAS;哇——看起来这就是我现在将要使用的...在高级 Web Metrics 组中最近有一个 LinkedIn post 重新滚动跟踪(我看到 GAS 也在这样做),Brian Clifton 加入了。跨度>
    • 在 setAllowAnchor 切换到 '#' 分隔符方面,GAS 中有什么需要注意的吗?
    • GAS 在 _setAllowHash 方面非常聪明。如果您使用 ['_setAllowHash', true],则所有 xdomain 链接都将被标记为尊重这一点。如果您发现任何问题,请告诉我。这是我公司的一个项目,所以我们非常重视错误并倾向于很快修复它们
    • 嗨 Eduardo - 你的意思是我认为 setAllowAnchor 不是 setAllowHash(已弃用)?
    • 是的,对不起,我的意思是 _setAllowAnchor。你说得对 _SetAllowHash 已被弃用,不在 GAS 中使用
    猜你喜欢
    • 2012-12-19
    • 2010-11-06
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    相关资源
    最近更新 更多