Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将使用sdk/上下文菜单API创建的菜单项添加到上下文菜单的顶部_Javascript_Firefox Addon_Firefox Addon Sdk - Fatal编程技术网

Javascript 将使用sdk/上下文菜单API创建的菜单项添加到上下文菜单的顶部

Javascript 将使用sdk/上下文菜单API创建的菜单项添加到上下文菜单的顶部,javascript,firefox-addon,firefox-addon-sdk,Javascript,Firefox Addon,Firefox Addon Sdk,我正在开发一个Mozilla插件SDK扩展,它使用API提供了一个右键单击上下文菜单选项,并在特定网站上执行一些操作。除了上下文菜单项被添加到列表的底部之外,一切都正常。我希望它是上下文菜单中的第一项。我找了好一阵子想知道怎么做,但运气不好 下面是我用来创建上下文菜单项的代码(修改为混淆正在使用它的站点): 使用Add-on-sdkapi,除了上下文菜单的底部之外,无法直接将项目添加到任何位置。没有一种方便的方法可以让它在顶部结束。但是,如果需要,可以添加它,然后将其移动到顶部或上下文菜单中的其

我正在开发一个Mozilla插件SDK扩展,它使用API提供了一个右键单击上下文菜单选项,并在特定网站上执行一些操作。除了上下文菜单项被添加到列表的底部之外,一切都正常。我希望它是上下文菜单中的第一项。我找了好一阵子想知道怎么做,但运气不好

下面是我用来创建上下文菜单项的代码(修改为混淆正在使用它的站点):

使用Add-on-sdkapi,除了上下文菜单的底部之外,无法直接将项目添加到任何位置。没有一种方便的方法可以让它在顶部结束。但是,如果需要,可以添加它,然后将其移动到顶部或上下文菜单中的其他位置。但是,附加SDK无法通过任何附加SDK API实现这一点

注意:将上下文菜单项移动到菜单顶部会改变Firefox加载项添加的上下文菜单项的正常操作。如果我加载一个假定其上下文菜单项位于列表顶部的加载项,我将不会高兴。如果它至少没有提供选项()使上下文菜单项位于底部或我选择的位置,我很可能会写一篇关于AMO的负面评论。将其放置在上下文菜单的顶部会假定您的附加组件将是该上下文菜单中使用最多的选项。这种情况在很大程度上取决于用户、您的加载项以及用户如何使用您的加载项。另一方面,如果这是我一直使用的一个选项,我会很高兴看到它位于顶部,并与其他菜单项分开

使上下文菜单项显示在顶部的一种方法: 您当前的代码会在一个上下文菜单中显示链接,其底部添加了一个条目,
AddonName(d)
,看起来像:

上下文菜单是存在于每个Firefox窗口中的XUL DOM的一部分。似乎Add-on SDK只允许将项目添加到页面内容区域内元素的上下文菜单中。因此,在XUL DOM中,受影响的上下文菜单是具有
id=“contentAreaContextMenu”
menupopup

一旦上下文菜单项的
menuitem
存在,您就可以操纵XUL DOM将其移动到
firstChild
,从而将其置于上下文菜单的顶部。但是,SDK不会将上下文菜单项的
menuitem
插入XUL DOM,直到第一次显示它(或者至少直到第一次显示它)。因此,您不能只调用
cm.Item()
,然后立即更改XUL DOM

更复杂的是,XUL DOM操作必须发生在主代码中,而您只能从内容脚本得知上下文菜单即将显示(因此,
menuitem
在XUL DOM中)。因此,我们必须监听
context
事件,并向主脚本传递一条消息,以启动上下文菜单的XUL DOM操作

请记住,
let cmItem=cm.Item()
返回的对象实际上不是对XUL DOM中
menuitem
的引用。这是因为XUL DOM中的
menuitem
在每个Firefox窗口的XUL DOM中都作为单独的对象存在。因此,我们必须在XUL DOM中搜索以找到正确的
menuitem
元素。因为它是每个Firefox窗口的一个单独的XUL DOM,所以我们需要确保它在所有窗口中都发生。在这种情况下,在内容脚本中侦听
上下文
事件会导致每次显示上下文菜单时发生此更改。因此,我们不需要在每个Firefox窗口中专门进行更改,因为每次显示上下文菜单时都会进行更改

在XUL DOM中搜索正确的
menuitem
的另一个复杂因素是,加载项SDK不提供应用于在XUL DOM中创建的
menuitem
id
属性。因此,我们必须根据
标签
属性的值来查找项目。这意味着您不需要更改该属性,也不需要跟踪更改,以便搜索正确的
菜单项。在下面的示例代码中,假定标签没有更改

现在,我们需要将内容脚本传递的消息用于指示将要显示上下文菜单的消息,以及在单击上下文菜单项时发送
node.href
。为了做到这一点,现在传递的是一个对象,该对象具有一个
type
属性,该属性指示正在传递的消息的类型(一个
单击
,或一个
上下文
)和来自单击的
数据

注意:附加SDK还在附加SDK添加的菜单项上方的上下文菜单中添加了。可能是在添加的每个上下文菜单项之间创建了分隔符,或者在每个附加SDK扩展添加的所有上下文菜单项之间创建了分隔符。然而,在简单的测试中,似乎只有一个分隔符被添加,即使对于多个附加SDK扩展也是如此。为了使它看起来干净,您需要在输入后的上下文菜单顶部添加一个。如果确实添加了一个,则需要确保在禁用加载项时将其删除。移动此分隔符将假定您是唯一添加到上下文菜单的附加SDK扩展。我没有在下面的示例代码中操作此
menuseparator

以下代码将使用
cm.Item()
创建的单个
menuitem
从上下文菜单中的任何位置移动到上下文菜单的顶部:

let cm = require("sdk/context-menu");
let cmLabel = "AddonName(d)";
cm.Item({
    label: cmLabel,
    context: [ cm.SelectorContext("a[href]") ],
    contentScript: 'self.on("click", function (node, data) {' +
               '  self.postMessage({type:"click", data:node.href});' +
               '});' +
               'self.on("context", function (node) {' +
               '  self.postMessage({type:"context"});' +
               '  return true;' +
               '});',
    accessKey: "d",
    onMessage: function (message) {
        if(message.type === "click") {
            console.log("context menu selected on:" + message.data);
        } else if (message.type === "context") {
            adjustContextMenuOrder(cmLabel);
        }
     }
});

function adjustContextMenuOrder(label) {
    curWindow = require('sdk/window/utils').getMostRecentBrowserWindow();
    let contextMenulist = curWindow.document.getElementById("contentAreaContextMenu");
    //Get a list of elements with a matching label property.
    let itemList = contextMenulist.querySelectorAll('[label="' + label + '"]');
    menuitem = itemList[0]; //Assume the first one found is the one we want.
    if(menuitem === undefined) {
        return; //Did not find the menuitem.
    }
    let parent = menuitem.parentNode;
    parent.insertBefore(menuitem, parent.firstChild); //Move found element to the top.
}
T
let cm = require("sdk/context-menu");
let cmLabel = "AddonName(d)";
cm.Item({
    label: cmLabel,
    context: [ cm.SelectorContext("a[href]") ],
    contentScript: 'self.on("click", function (node, data) {' +
               '  self.postMessage({type:"click", data:node.href});' +
               '});' +
               'self.on("context", function (node) {' +
               '  self.postMessage({type:"context"});' +
               '  return true;' +
               '});',
    accessKey: "d",
    onMessage: function (message) {
        if(message.type === "click") {
            console.log("context menu selected on:" + message.data);
        } else if (message.type === "context") {
            adjustContextMenuOrder(cmLabel);
        }
     }
});

function adjustContextMenuOrder(label) {
    curWindow = require('sdk/window/utils').getMostRecentBrowserWindow();
    let contextMenulist = curWindow.document.getElementById("contentAreaContextMenu");
    //Get a list of elements with a matching label property.
    let itemList = contextMenulist.querySelectorAll('[label="' + label + '"]');
    menuitem = itemList[0]; //Assume the first one found is the one we want.
    if(menuitem === undefined) {
        return; //Did not find the menuitem.
    }
    let parent = menuitem.parentNode;
    parent.insertBefore(menuitem, parent.firstChild); //Move found element to the top.
}