1

I'm developing a userscript and one of its functions should be available thru an additional menu item in the native browser context menu.

So, firstly, I'm inserting into body of the page:

<menu type="context" id="mymenu">
    <menuitem label="My Fancy Something"></menuitem>
</menu>

Then comes the attempt to use it, at the body element:

document.body.contextMenu = document.querySelector('#mymenu');

or

document.body.contextMenu = 'mymenu';

Either way, it fails.

console.log(document.body.contextMenu); // returns null

But, when I get to Firefox DOM inspector, and put that attribute into the body tag by hand, it actually works, and makes new context menu element appear in the document.

What am I doing wrong?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
AlexTR
  • 772
  • 8
  • 14

1 Answers1

1

Don't try to set .contextMenu for pretty much the same reason you should avoid things like .onclick(). You will have scope and sandbox problems with that approach.

Set the contextmenu attribute, not the DOM property.

Here is a complete working Greasemonkey script that shows how to add a context menu:

// ==UserScript==
// @name     _Create and wire-in a sample context menu
// @match    https://stackoverflow.com/questions/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/
var myMenu  = $( `
    <menu type="context" id="myFirstContextMenu">
        <menuitem data-bg-color="pink"  label="Set background to pink."></menuitem>
        <menuitem data-bg-color="lime"  label="Set background to lime."></menuitem>
        <menuitem data-bg-color="reset" label="Reset background color."></menuitem>
    </menu>
` ).appendTo ("body");

$("body").attr ("contextmenu", 'myFirstContextMenu');

myMenu.on ("click", "menuitem", function (zEvent) {
    var targBgColor = $(this).data ("bgColor")  ||  "ERROR";

    switch (targBgColor) {
        case "pink":
        case "lime":
            $("body").css ("background-color", targBgColor);
            break;
        case "reset":
            $("body").css ("background-color", "");
            break;
        default:
            alert ('<menuitem> "' + targBgColor + '" not wired-in correctly.');
            break;
    }
} );

Note: This kind of <menu> seems to only be supported by Firefox at the moment.

Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Thanks, that helped. Looks like the way to do it with vanilla js would be document.body.setAttribute('contextMenu','myMenu') – AlexTR Jan 05 '16 at 10:42
  • You're welcome and, yes, `setAttribute()` is the bare-bones JS way. – Brock Adams Jan 05 '16 at 10:56
  • This seems to be broken. I'm not sure when exactly is happened, but it is not working any more with 85.0.2. – myavuzselim Feb 22 '21 at 10:14
  • Yes `menu` is no longer supported from Firefox 85+ see https://caniuse.com/menu and https://github.com/whatwg/html/issues/2730 – sparrowt Nov 11 '21 at 11:35