【问题标题】:Works as javascript, but doesn't work as a Greasemonkey script?作为 javascript 工作,但不能作为 Greasemonkey 脚本工作?
【发布时间】:2011-09-24 12:42:18
【问题描述】:

我正在制作一个 Greasemonkey 脚本,以便在 cnn.com 上的视频旁边添加下载链接。

我使用 HTML 页面的保存版本来测试我的脚本,并且能够让它完美地工作。然后当我将javascript放入Greasemonkey并在实际站点上尝试时,它不起作用。

这不是完整的脚本,而是有问题的脚本部分。它只是应该在每个 div 的底部添加一个带有“sec_video_box”类的链接(如图所示)。

// ==UserScript==
// @name           CNN Download
// @namespace      Cool
// @description    CNN Download
// @include        http://*cnn.com/video/*
// ==/UserScript==

var getClass = function(clssName, rootNode /*optional*/){

    var root = rootNode || document,
    clssEls = [],
    elems,
    clssReg = new RegExp("\\b"+clssName+"\\b");

    // use the built in getElementsByClassName if available
    if (document.getElementsByClassName){
        return root.getElementsByClassName(clssName);
    }

    // otherwise loop through all(*) nodes and add matches to clssEls
    elems = root.getElementsByTagName('*');
    for (var i = 0, len = elems.length; i < len; i+=1){
        if (clssReg.test(elems[i].className)) clssEls.push(elems[i])
    }

    return clssEls;

};

function insertlinks() { 
    var boxes = getClass("sec_video_box");

    for (i=0; i<boxes.length; i++) { 
            var theboxid = boxes[i].getAttribute("id");
            document.getElementById(theboxid).innerHTML = document.getElementById(theboxid).innerHTML + '<a href="'+ theboxid +'">link</a>';
    } 
}

window.onload = insertlinks ();


谁能告诉我我做错了什么?

【问题讨论】:

  • 要注意的一点是,您可能应该使用 addEventListener 或 attachEvent 来监视正在加载的文档,因为在其他人的页面中分配给 window.onload 可能会击败他们的 onload 处理程序,或者他们可能会击败您的处理程序。
  • 我试过了,还是不行。我不确定出了什么问题。

标签: javascript greasemonkey


【解决方案1】:

该脚本的 3 个最大问题是:

  1. 你不能那样使用window.onload;见GM Pitfall #2: Event Handlers。始终使用 addEventListener() 或 jQuery。
  2. 无论如何,这些视频对象在文档加载后都是 AJAX-in。
  3. 这些视频对象可以通过 AJAX 进行更改;因此您需要监控新对象。

有一些小问题,但首先要注意整个现有脚本可以用jQuery简化为:

// ==UserScript==
// @name            CNN Download
// @namespace       Cool
// @description     CNN Download
// @include         http://*cnn.com/video/*
// @require         http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
// ==/UserScript==

function insertlinks () {
    var boxes = $(".sec_video_box");

    boxes.each ( function () {
        var theboxid    = this.id;
        $(this).append ('<a href="'+ theboxid +'">link</a>');
    } );
}

$(window).load (insertlinks);

(重要提示:此示例代码仍然无法运行。)




处理 AJAX 问题,就变成了:

// ==UserScript==
// @name            CNN Download
// @namespace       Cool
// @description     CNN Download
// @include         http://*cnn.com/video/*
// @require         http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
// ==/UserScript==

function insertlink (jNode) {
    var theboxid    = jNode.attr ('id');
    jNode.append ('<a href="' + theboxid + '">link</a>');
}

waitForKeyElements (".sec_video_box", insertlink, false);

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);

    if (targetNodes  &&  targetNodes.length > 0) {
        /*--- Found target node(s).  Go through each and act if they
            are new.
        */
        targetNodes.each ( function () {
            var jThis        = $(this);
            var alreadyFound = jThis.data ('alreadyFound')  ||  false;

            if (!alreadyFound) {
                //--- Call the payload function.
                actionFunction (jThis);
                jThis.data ('alreadyFound', true);
            }
        } );
        btargetsFound   = true;
    }
    else {
        btargetsFound   = false;
    }

    //--- Get the timer-control variable for this selector.
    var controlObj      = waitForKeyElements.controlObj  ||  {};
    var controlKey      = selectorTxt.replace (/[^\w]/g, "_");
    var timeControl     = controlObj [controlKey];

    //--- Now set or clear the timer as appropriate.
    if (btargetsFound  &&  bWaitOnce  &&  timeControl) {
        //--- The only condition where we need to clear the timer.
        clearInterval (timeControl);
        delete controlObj [controlKey]
    }
    else {
        //--- Set a timer, if needed.
        if ( ! timeControl) {
            timeControl = setInterval ( function () {
                    waitForKeyElements (    selectorTxt,
                                            actionFunction,
                                            bWaitOnce,
                                            iframeSelector
                                        );
                },
                500
            );
            controlObj [controlKey] = timeControl;
        }
    }
    waitForKeyElements.controlObj   = controlObj;
}

(确实有效。)

【讨论】:

  • 感谢您的帮助!我在 Chrome(我的主浏览器)中尝试了该脚本,但没有成功。在 Firefox 中它可以工作,但它每 500 毫秒为每个 div 添加一个新的“链接”。在 Chrome 中,我尝试修改 Chrome 扩展目录中的“manifest.json”文件以包含“jquery.js”,因为我认为这是问题所在,但它仍然没有工作。
  • 没关系,我通过将整个jquery.js 文件粘贴到greasemonkey 脚本中来让它在Chrome 中工作。非常感谢您的帮助!!!
  • 很奇怪。我在 Firefox 中测试了脚本,它运行良好;它使用.data() 功能为每个视频只写一次链接。 ...另外,请在您的问题中说明您使用的是 Chrome。 Greasemonkey 脚本和 Chrome 用户脚本之间存在主要区别。 ......无论如何,你得到了它的工作;很高兴为您提供帮助!
【解决方案2】:
window.onload = insertlinks;

删除(),它们会导致函数立即运行并将返回值(在本例中为null)分配给onload。在本地,这很好,因为加载几乎是即时的。但是在线会失败。

【讨论】:

  • 我试过了,结果还是一样。还有其他建议吗?
  • 尝试在for 循环之前添加alert(boxes),确保它符合您的预期。
猜你喜欢
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
相关资源
最近更新 更多