我可以向窗口小部件添加上下文菜单吗?

时间:2014-03-10 12:59:50

标签: javascript firefox-addon

我正在尝试向窗口小部件添加上下文菜单 这是菜单:

var widgets = require("sdk/widget");
var tabs = require("sdk/tabs");
var contextMenu = require("sdk/context-menu");

var menu = widgets.Widget({
    id: "menu",
    label: "Menu",
    contentURL: data.url("icon.png"),
    onClick: function() {
        //show a menu here
    }
});

是否可以在此图标中添加菜单?
或者以某种方式点击显示上下文菜单?

1 个答案:

答案 0 :(得分:1)

这里完成的是它的样子:

final look

这里的好人是简化的例子。我会在一秒钟内上传你的xpi。     //立即创建并添加面板     var doc = document;     var myElement = doc.getElementById(' ElementToAttachPanelToId'); //我们将菜单附加到此元素

var myMenuJson = 
                ['xul:menupopup', {id: 'myMenu1'},
                    ['xul:menuitem', {label:'menu item1'}],
                    ['xul:menu', {label:'menu item2 is submenu1'},
                        ['xul:menupopup', {},
                            ['xul:menuitem', {label:'submenu1 item1'}],
                            ['xul:menuitem', {label:'submenu1 item2'}],
                            ['xul:menuitem', {label:'submenu1 item3'}]
                        ]
                    ],
                    ['xul:menuitem', {label:'menu item3 is before a seperator'}],
                    ['xul:menuseparator', {}],
                    ['xul:menuitem', {label:'menu item4 is after a seperator'}]
                ];

var mainPopupSet = doc.getElementById('mainPopupSet');
mainPopupSet.appendChild(jsonToDOM(myMenuJson, doc, {}));

myElement.setAttribute('context', 'myMenu1');

我们可以通过将菜单的上下文属性设置为我们想要的菜单的id来将菜单添加到任何内容

要查看jsonToDOM函数,请在此处查看此要点。按原样安装您的插件,然后从此Gist复制代码并将其粘贴到暂存器中并运行它,然后右键单击您的小部件,它将弹出。 GIST IS HERE: Noitidart / _ff-addon-snippet-CreateMenuWithSubmenuAndAttachToWidget.js

现在在你的main.js我无法测试它,因为它没有require("chrome")的权限。如果它不起作用,请在main.js var {Cc, Ci, Cu} = require("chrome"); Cu.import("resource://gre/modules/Services.jsm");的顶部添加,然后再次编译并上传,我会测试并发回。

好吧无论如何,如果它适用于第一次拍摄,那就是粘贴到你的main.js的代码。我只是将bootstrap样板复制到你的插件sdk中并不难,因为我很确定addon sdk不允许你这样做。它看起来很长但是它的一堆复制和粘贴,特别是jsonToDOM函数,在我链接你的要点的底部读到了这些东西。

var data = require("sdk/self").data;

var panel = require("sdk/panel").Panel({
    width: 200,
    height: 150,
    contentURL: data.url("menu.html"),
    contentScriptFile: data.url("menu.js")
});

var menu = require("sdk/widget").Widget({
    id: "open-traveleye",
    label: "TravelEye",
    contentURL: data.url("earth-icon.png"),
    panel: panel
});

//putting this after the .Widget thing as we need the widget insert into browser before running this code
var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/Services.jsm");

var windowListener = {
    //DO NOT EDIT HERE
    onOpenWindow: function(aXULWindow) {
        // Wait for the window to finish loading
        let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
        aDOMWindow.addEventListener('load', function() {
            aDOMWindow.removeEventListener('load', arguments.callee, false);
            windowListener.loadIntoWindow(aDOMWindow);
        }, false);
    },
    onCloseWindow: function(aXULWindow) {},
    onWindowTitleChange: function(aXULWindow, aNewTitle) {},
    register: function() {
         // Load into any existing windows
        var DOMWindows = Services.wm.getEnumerator('navigator:browser');
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            windowListener.loadIntoWindow(aDOMWindow);
        }
         // Listen to new windows
         wm.addListener(windowListener);
    },
    unregister: function() {
        // Unload from any existing windows
        var DOMWindows = Services.wm.getEnumerator('navigator:browser');
        while (DOMWindows.hasMoreElements()) {
            let aDOMWindow = DOMWindows.getNext();
            windowListener.unloadFromWindow(aDOMWindow;
        }
        //Stop listening so future added windows dont get this attached
        wm.removeListener(windowListener);
    },
    //END - DO NOT EDIT HERE
    loadIntoWindow: function (aDOMWindow, aXULWindow) {
        var window = aDOMWindow;
        if (!window) { return; }

        createAndAttachMenu(window);

    },
    unloadFromWindow: function (aDOMWindow, aXULWindow) {
        var window = aDOMWindow;
        if (!window) { return; }

        destroyMenu(window);

    }
};

function createAndAttachMenu(window) {
    var doc = window.document;
    var myWidget = doc.getElementById('widget:jid1-lwNbwJJiiMXM4A@jetpack-open-traveleye'); //we add the menu to this widget, we can add menu to anything by setting the context attribute of it to the id of the menu we want to give it

    var myMenuJson = 
                    ['xul:menupopup', {id: 'myMenu1'},
                        ['xul:menuitem', {label:'menu item1'}],
                        ['xul:menu', {label:'menu item2 is submenu1'},
                            ['xul:menupopup', {},
                                ['xul:menuitem', {label:'submenu1 item1'}],
                                ['xul:menuitem', {label:'submenu1 item2'}],
                                ['xul:menuitem', {label:'submenu1 item3'}]
                            ]
                        ],
                        ['xul:menuitem', {label:'menu item3 is before a seperator'}],
                        ['xul:menuseparator', {}],
                        ['xul:menuitem', {label:'menu item4 is after a seperator'}]
                    ];

    var mainPopupSet = doc.getElementById('mainPopupSet');
    mainPopupSet.appendChild(jsonToDOM(myMenuJson, doc, {}));

    myWidget.setAttribute('context', 'myMenu1');
}

function destroyMenu(window) {
    var myMenu = doc.getElementById('myMenu1');
    if (myMenu) {
        myMenu.parentNode.removeChild(myMenu);
    }
}

/*dom insertion library function from MDN - https://developer.mozilla.org/en-US/docs/XUL_School/DOM_Building_and_HTML_Insertion*/
jsonToDOM.namespaces = {
    html: 'http://www.w3.org/1999/xhtml',
    xul: 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'
};
jsonToDOM.defaultNamespace = jsonToDOM.namespaces.html;
function jsonToDOM(xml, doc, nodes) {
    function namespace(name) {
        var m = /^(?:(.*):)?(.*)$/.exec(name);        
        return [jsonToDOM.namespaces[m[1]], m[2]];
    }

    function tag(name, attr) {
        if (Array.isArray(name)) {
            var frag = doc.createDocumentFragment();
            Array.forEach(arguments, function (arg) {
                if (!Array.isArray(arg[0]))
                    frag.appendChild(tag.apply(null, arg));
                else
                    arg.forEach(function (arg) {
                        frag.appendChild(tag.apply(null, arg));
                    });
            });
            return frag;
        }

        var args = Array.slice(arguments, 2);
        var vals = namespace(name);
        var elem = doc.createElementNS(vals[0] || jsonToDOM.defaultNamespace, vals[1]);

        for (var key in attr) {
            var val = attr[key];
            if (nodes && key == 'key')
                nodes[val] = elem;

            vals = namespace(key);
            if (typeof val == 'function')
                elem.addEventListener(key.replace(/^on/, ''), val, false);
            else
                elem.setAttributeNS(vals[0] || '', vals[1], val);
        }
        args.forEach(function(e) {
            try {
                elem.appendChild(
                                    Object.prototype.toString.call(e) == '[object Array]'
                                    ?
                                        tag.apply(null, e)
                                    :
                                        e instanceof doc.defaultView.Node
                                        ?
                                            e
                                        :
                                            doc.createTextNode(e)
                                );
            } catch (ex) {
                elem.appendChild(doc.createTextNode(ex));
            }
        });
        return elem;
    }
    return tag.apply(null, xml);
}
/*end - dom insertion library function from MDN*/

//end added stuff

var tabs = require("sdk/tabs");
panel.port.on("noformatting", function() {
    tabs.activeTab.attach({
        contentScriptFile: data.url('no-formatting.js')
    });
});

panel.port.on("bold", function() {
    tabs.activeTab.attach({
        contentScriptFile: data.url('bold.js')
    });
});

panel.port.on("italic", function() {
    tabs.activeTab.attach({
        contentScriptFile: data.url('italic.js')
    });
});

panel.port.on("eye", function() {
    tabs.activeTab.attach({
        contentScriptFile: data.url('eye.js')
    });
});