GM_registerMenuCommand未定义。

3
大家好。我很困惑为什么在运行我创建的用户脚本时,我一直收到“GM_registerMenuCommand未定义”的错误。我已经尝试在Firefox中使用Scriptish 1.0b9和最新版本的Greasemonkey。我甚至禁用了除Scriptish之外的所有插件,以查看是否存在冲突,但没有成功。
我在我的用户脚本中使用jQuery,使用Erik Vold的这个模板。在尝试这个模板之前,我把完全相同的代码块放在Joan Piedra提出的模板中,一切正常。不幸的是,Piedra的模板在Chrome中不起作用,考虑到Chrome日益增长的用户群,我认为这是必要的。引发错误的片段如下:
    // a function that loads jQuery and calls a callback function when jQuery has finished loading
function addJQuery(callback) {
  var script = document.createElement("script");
  script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js");
  script.addEventListener('load', function() {
    var script = document.createElement("script");
    script.textContent = "(" + callback.toString() + ")();";
    document.body.appendChild(script);
  }, false);
  document.body.appendChild(script);
}

// the guts of this userscript
function main() {


var isLevelupMove = false;
var isTutorMove = false;
var isTM = false;
var TMhead = $('#moves\\:machine');
var hasSecondEvo = false;
var hasFinalEvo1 = false;
var hasFinalEvo2 = false;
var header = $('.header-row').eq(1);
var TMmoves = new Array();

//This section deals with the user-defined colors 

GM_registerMenuCommand("Color for pre-evolutionary-only moves", prevoColorPrompt);
GM_registerMenuCommand("Color for first evolution-only moves", evoColorPrompt);

if(localStorage.getItem('prevoColor') == null || localStorage.getItem('evoColor') == null)
{
    localStorage.setItem('prevoColor', 'red');
    localStorage.setItem('evoColor', 'orange');
}
var prevoColor = localStorage.getItem('prevoColor');
var evoColor = localStorage.getItem('evoColor');

function prevoColorPrompt()
{
    var input = prompt("Please enter a desired 6-digit hex color-code for pre-evolutionary pokemon:") 
    localStorage.setItem('prevoColor', '#'+input);
}

function evoColorPrompt()
{
    var input = prompt("Please enter the desired 6-digit hex color-code for first-evolution pokemon:") 
    localStorage.setItem('evoColor', '#'+input);
}

//This loop tests each 'th' element in a sample header row, determining how many Evos are currently present in the chart.

$('.header-row').eq(1).find('th').each(function(index) 
{
    if($(this).find('a').length != 0)
    {
        switch(index)
        {
            case 2:
            hasSecondEvo = true;
            break;

            case 3:
            hasFinalEvo1 = true;
            break;

            case 4:
            hasFinalEvo2 = true;
            break;
        }
    }
});

//All 'tr' siblings are TM moves, since it's the last section on the page
//This array puts only the names of the available TMs into the TMmoves array
TMhead.nextAll().each(function(index)
{
    TMmoves.push($(this).children(":first").find('a').eq(0).html());
});

$('tr').each(function(index) 
{
    var moveName = $(this).children(":first").find('a').eq(0).html();   
    moveName = $.trim(moveName);

    switch($(this).attr('id'))
    {
        case 'moves:level-up':
            isLevelupMove = true;   
            break;

        case 'moves:egg':
            isLevelupMove = false;
            break;  

        case 'moves:tutor':
            isTutorMove = true;

        case 'moves:machine':
            isTM = true;    
    }

    if(isLevelupMove || isTutorMove)
    {
        var babyMoveCell = $(this).find('td').eq(0);
        babyMoveText = $.trim(babyMoveCell.html());

        secondEvoCell = babyMoveCell.next();
        secondEvoText = $.trim(secondEvoCell.html());

        finalEvo1Cell = secondEvoCell.next();
        finalEvo1Text = $.trim(finalEvo1Cell.html());

        finalEvo2Cell = finalEvo1Cell.next();
        finalEvo2Text = $.trim(finalEvo2Cell.html());

        //This checks if evolutions have checkmarks

        if(babyMoveText.length > 0)
        {
            if(hasSecondEvo && secondEvoText.length == 0 || hasFinalEvo1 && finalEvo1Text.length == 0 || 
                hasFinalEvo2 && finalEvo2Text.length == 0)
            {
                //See if the move is a TM before proceeding 
                var tm = tmCheck(moveName);

                if(!tm)
                {

                    if(secondEvoText.length > 0)
                    {       
                        babyMoveCell.css("color", evoColor);
                        secondEvoCell.css("color", evoColor);
                        babyMoveCell.prev().find('a').eq(0).css("color", evoColor); //highlights move name
                    }
                    else
                    {
                        babyMoveCell.css("color", prevoColor);
                        babyMoveCell.prev().find('a').eq(0).css("color", prevoColor);
                    }
                }
            }
        }
        else if(secondEvoText.length > 0)
        {
            if(hasFinalEvo1 && finalEvo1Text.length == 0 || hasFinalEvo2 && finalEvo2Text.length == 0)
            {
                var tm = tmCheck(moveName); 

                if(!tm)
                {
                    secondEvoCell.css("color", evoColor);
                    babyMoveCell.prev().find('a').eq(0).css("color", evoColor);
                }
            }
        }
    }

});

function tmCheck(input)
{
    var isTM = false;

    //Iterate through TMmoves array to see if the input matches any entries
    for(var i = 0; i < TMmoves.length; i++)
    {   
        if(input == TMmoves[i])
        {
            isTM = true;
            break;
        }
    }

    if(isTM == true)
        return true;
    else
        return false;       
}

//alert("evoColor: " + localStorage.getItem('evoColor') + ". prevoColor: " + localStorage.getItem('prevoColor'))

}//end main()

// load jQuery and execute the main function
addJQuery(main);

这是我正在尝试实现的用户脚本。如果有人对我为什么会出现错误有任何建议或想法,我很乐意听取!


你在Chrome或Firefox上遇到这个错误了吗? - Brock Adams
两个都可以。如果我能在Firefox上使用它,我会选择Tampermonkey和Chrome。 - KongMD
这个脚本在我使用的 Firefox 3.6 上似乎可以正常工作。你使用的是 Firefox 4 吗?建议卸载 GM 和 Scriptish,重启 Firefox ,只安装 GM,看看是否解决了问题。请问在 Firefox 或 Firebug 的控制台中精确的错误信息是什么? - Brock Adams
链接的那个脚本是能够正常工作的。我在原帖中发布了出现错误的脚本。对于造成的困惑,我表示抱歉! - KongMD
这是我完全可用的解决方法: http://codereview.stackexchange.com/questions/26902/working-gm-setvalue-and-gm-getvalue-inside-jquery-greasemonkey-access-violatio享受吧! - eapo
2个回答

2
这个方法行不通,因为如果你仔细看一下 addJQuery 的功能,你会意识到它会将你传递给它的函数代码注入到一个 script 元素中,并将其添加到 body 元素的末尾。
这意味着你现在是在网站的脚本空间中工作,所以所有的 GM_*都不可用。你可以做的是将一些需要这些函数的代码移到 main 函数外部,但请记住,Greasemonkey沙盒意味着在 main 函数内运行的代码无法直接与其外部的代码通信。你可以通过间接通信来实现,例如观察DOM操作或甚至unsafeWindow,但从你的代码来看,它似乎不容易分离。

unsafeWindow 在 Chrome 中不起作用,而 GM_ 函数根本就没有定义。 - Brock Adams
@BrockAdams 当然,但我的理念一直是,如果您需要跨浏览器的GM脚本,那么您不应该使用其中任何一个 - 即使在某些浏览器中也不支持@require - Yi Jiang
真的,但是OP的主要关注点似乎是FF和Chrome。Chrome的Tampermonkey扩展程序提供了对@require的支持,甚至还有对unsafeWindow的有限支持,但原生的纯Chrome并没有。 - Brock Adams

1

这种方法行不通,因为addJQuery()没有将工作区对象传输到页面范围内,而是从源代码重新创建您的代码。

这意味着GM_函数无法使用,因为沙盒和addJQuery()创建的代码副本之间没有链接。

如果您的脚本需要GM_函数,则只需使用带有// @require指令的纯GM代码,例如jQuery。在Chrome中,您唯一的选择是Tampermonkey。

在这两种情况下,不需要类似于addJQuery()的技巧。


感谢您的帮助,布洛克!这个脚本现在在Chrome中能够正常工作,但是如果尝试通过Tampermonkey改变颜色,它会出问题。我没有在Chrome的Javascript控制台中看到任何东西,在输入十六进制颜色代码后,菜单命令从Tampermonkey菜单中消失了。如果您想自己尝试,我正在使用的部分适用于Chrome的最新版本是脚本页面上的最新版本(在原始帖子中链接)。 - KongMD
你现在使用的是这个脚本的第三个版本吗?(它似乎刚刚有所改变。)有一件事:它正在使用jQuery 1.5.1。GM以前只能可靠地与jQuery 1.3.2一起使用,但我还没有测试过它是否适用于GM 9或更高版本。我现在得走了,几个小时后再看看。 - Brock Adams
好的,我一直在调试,并尝试了一些事情(但没有成功)。列出了任何控制台错误: 1)将jQuery版本更改为1.3.2 2)在页面加载后从控制台调用localStorage.getItem('prevoColor')(两个值都为null) 3)完全更改从localStorage到get / setValue 4)从控制台调用GM_getValue = ReferenceError:GM_getValue未定义 5)在Chrome选项中删除veekun.com的localStorage条目。抱歉这有些杂乱 - 我不见得支持miniMarkdown的无序列表。 - KongMD
@KongMD,是的,这些评论并不是用来发布问题的。;) 我认为我们已经回答了最初的问题。请针对继续出现的问题提出新的问题。这可以减少混淆,帮助其他人在搜索类似症状时更容易找到。 - Brock Adams
是的,你是对的。新帖子在这里 - KongMD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接