作为JavaScript工作,但不作为Greasemonkey脚本工作?

时间:2011-09-24 12:42:18

标签: javascript greasemonkey

我正在制作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 ();


Pic: JS works; GM doesn't.

有人可以告诉我我做错了什么吗?

2 个答案:

答案 0 :(得分:1)

window.onload = insertlinks;

删除(),它们会导致函数立即运行,并且返回值(在这种情况下为null)被分配给onload。在本地,这很好,因为装载几乎是即时的。然而,在线,它将失败。

答案 1 :(得分:1)

该脚本存在的三大问题是:

  1. 你不能那样使用window.onload;见GM Pitfall #2: Event Handlers。始终使用addEventListener()或jQuery。
  2. 无论如何,在加载文档后,这些视频对象都是AJAX-in。
  3. 这些视频对象可以通过AJAX进行更改;因此,您需要监控新对象。
  4. 有一些小问题,但首先请注意,使用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;
    }
    

    (哪个确实有效。)