Работает как javascript, но не работает как скрипт Greasemonkey? - PullRequest
1 голос
/ 24 сентября 2011

Я делаю скрипт 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 ]

1 голос
/ 25 сентября 2011

3 самые большие проблемы с этим скриптом:

  1. Вы не можете использовать window.onload таким образом; см. GM Подводный камень # 2: Обработчики событий . Всегда используйте addEventListener() или jQuery.
  2. Эти видеообъекты в любом случае AJAXed-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;
}

(который работает.)

1 голос
/ 24 сентября 2011
window.onload = insertlinks;

Удалите (), они вызывают немедленное выполнение функции, и возвращаемое значение (в данном случае null) присваивается onload.Локально, это нормально, так как загрузка происходит почти мгновенно.Однако в сети произойдет сбой.

...