waitForKeyElements不等待某些浏览器上加载ajax的数据?

时间:2015-10-30 05:46:36

标签: javascript ajax cross-browser greasemonkey tampermonkey

在我的Greasemonkey脚本/ Tampermonkey在Google Chrome中完美运行,但在Firefox中:

waitForKeyElements ("table#ID-rowTable tr td span._GAmD", replaceAffid);

不等待加载AJAX的内容。

以下是我的脚本的相关部分:

// ==UserScript==
// @name        ChangeProvider
// @description Change Provider Name
// @include     https://analytics.google.com/analytics/web/*
// @version     1
// @grant       GM_xmlhttpRequest
// ==/UserScript==

<snip>...

waitForKeyElements ("table#ID-rowTable tr td span._GAmD", replaceAffid);

<snip>...

function waitForKeyElements (
    selectorTxt,    /* Required: The jQuery selector string that
                        specifies the desired element(s).
                    */
    actionFunction, /* Required: The code to run when elements are
                        found. It is passed a jNode to the matched
                        element.
                    */
    bWaitOnce,      /* Optional: If false, will continue to scan for
                        new elements even after the first match is
                        found.
                    */
    iframeSelector  /* Optional: If set, identifies the iframe to
                        search.
                    */
) {
    var targetNodes, btargetsFound;

    if (typeof iframeSelector == "undefined")
        targetNodes     = $(selectorTxt);
    else
        targetNodes     = $(iframeSelector).contents ()
                                           .find (selectorTxt);

<snip>...


完整代码为at pastebin.com

1 个答案:

答案 0 :(得分:1)

问题是:

  1. waitForKeyElements()需要jQuery。

  2. 脚本必须 提供jQuery(推荐),或使用@grant none模式并在已使用jQuery的页面上运行(a脆弱的做事方式,AKA“定时炸弹代码”)。

  3. Tampermonkey有一个错误和可能的安全漏洞,因此它并不总是 沙箱正常。这意味着脚本可以(有时)看到页面的jQuery,即使@grant不是none.这也允许脚本在Chrome中运行(现在)但是依赖它是非常冒险的事情。

  4. 使用@grant GM_ ...
  5. Firefox正确沙箱范围,因此脚本无法看到该网页的jQuery。

  6. 如果您有looked at Firefox's Browser Console,则会看到错误消息指出您的问题。

  7. 解决方案是:在没有@require jQuery的情况下不要使用waitForKeyElements!
    实际上,您应该同时需要两个库as shown in this answer,因为它(A)运行速度更快,(B)仅在安装/编辑用户脚本时获取一次代码,而(C)使得更清晰,更容易格罗克代码。

    因此,您的整个脚本将变为:

    // ==UserScript==
    // @name        GoogleAnalytics Change Provider
    // @description Change Provider Name
    // @include     https://analytics.google.com/analytics/web/*
    // @version     1
    // @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @require     https://gist.github.com/raw/2625891/waitForKeyElements.js
    // @grant       GM_xmlhttpRequest
    // ==/UserScript==
    var providers = new Array ();
    
    GM_xmlhttpRequest ( {
        method: "GET",
        url: "http://localhost:3000/api/t2_provider_list",
        onload: function (response) {
            var provider_list = JSON.parse (response.responseText);
    
            for (i = 0; i < provider_list.length; i++) {
                providers[provider_list[i].analytics_prefix] = provider_list[i].provider_name;
            }
            waitForKeyElements ("table#ID-rowTable tr td span._GAmD", replaceAffid);
        }
    } );
    
    /*--- replaceAffid ():  Match the fields with a given pattern 
    and replace with the provider name and affid
    */
    function replaceAffid () {
        console.log (providers);
        var regExp = /([a-z,A-Z,0-9]+)---([a-z,A-Z,0-9,_,-]+)/g;
    
        var spans = document.evaluate ("//span[contains(@class, '_GAmD') and not(contains(@class, '_GAe'))]/text()", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
        console.log (spans);
        for (var i = 0; i < spans.snapshotLength; i++) {
            match = regExp.exec (spans.snapshotItem (i).textContent);
    
            if (match != null) {
                if (typeof providers[match[1]] === undefined) {
                    // do nothing
                } else {
                    spans.snapshotItem (i).textContent = "Provider: " + providers[match[1]] + " \n\r  Affid: " + match[2];
                }
            }
        }
    }
    

    最后,它看起来像是粘贴在旧版本的waitForKeyElements中 Since May of 2012,该函数的文本接近顶部:

      

    重要说明:此函数要求您的脚本加载jQuery。

    如果您从one of my old answers抓取了该功能的副本,我道歉。我刚刚更新它以避免重复这种混乱。