Skip to content Skip to sidebar Skip to footer

Can I Add A Context Menu To A Widget?

I'm trying to add a context menu to a widget This is the menu: var widgets = require('sdk/widget'); var tabs = require('sdk/tabs'); var contextMenu = require('sdk/context-menu');

Solution 1:

Done here is what it looks like:

final look

Ok man here is the simplified example. And I'll upload your xpi in a second. //create and add the panel now var doc = document; var myElement= doc.getElementById('ElementToAttachPanelToId'); //we attach menu to this element

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');

we can add menu to anything by setting the context attribute of it to the id of the menu we want to give it

To see the jsonToDOM function see this gist here. Install your addon as is, then copy the code from this Gist and paste it into scratchpad and run it, then right click on your widget and it will pop up. GIST IS HERE: Noitidart / _ff-addon-snippet-CreateMenuWithSubmenuAndAttachToWidget.js

Now in your main.js I couldn't test it because it doesn't have permission to require("chrome"). If it doesnt work add in at the top of your main.js var {Cc, Ci, Cu} = require("chrome"); Cu.import("resource://gre/modules/Services.jsm"); and then compile and upload again, Ill test do it and send back.

Ok anyways, if it works on first shot here it is, the code to paste into your main.js. It wasn't hard I just copied the bootstrap boilerplate into your addon sdk, because Im pretty sure the addon sdk doesnt allow you to do this. It looks long but its a bunch of copy and pasting, Especially the jsonToDOM function, read about this stuff in the bottom of the gist I linked you.

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 codevar {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/Services.jsm");

var windowListener = {
    //DO NOT EDIT HEREonOpenWindow: function(aXULWindow) {
        // Wait for the window to finish loadinglet 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 windowsvarDOMWindows = 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 windowsvarDOMWindows = 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 HEREloadIntoWindow: function (aDOMWindow, aXULWindow) {
        varwindow = aDOMWindow;
        if (!window) { return; }

        createAndAttachMenu(window);

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

        destroyMenu(window);

    }
};

functioncreateAndAttachMenu(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 itvar 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');
}

functiondestroyMenu(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;
functionjsonToDOM(xml, doc, nodes) {
    functionnamespace(name) {
        var m = /^(?:(.*):)?(.*)$/.exec(name);        
        return [jsonToDOM.namespaces[m[1]], m[2]];
    }

    functiontag(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 stuffvar 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')
    });
});

Post a Comment for "Can I Add A Context Menu To A Widget?"