{{>guide-examples-style}}

Understanding the problem

You want to add a custom context menu to an element, so you add a "contextmenu" event listener to the element. That listener is going to do two basic things:

  1. Prevent the display of the browser's context menu
  2. Position your custom context menu over top of/relative to the target of the event

The code will look something like this:

``` function onContextmenu(e) { e.preventDefault(); if (!contextmenu) { contextmenu = new Y.Overlay({ bodyContent: "", visible: false, constrain: true }); contextmenu.render(Y.one("body")); } contextmenu.set("xy", [e.pageX, e.pageY]); contextmenu.show(); } btn.on("contextmenu", onContextmenu); ```

This code will work great if the "contextmenu" is triggered via the mouse. However, the "contextmenu" event is one of those device-independent events: can be triggered via the mouse, or the keyboard (on Windows using the Menu key, or the Shift + F10 shortcut). When it's triggered via the keyboard you will run into problems. Here's an overview of the obstacles and inconsistencies by browser + platform:

Internet Explorer

Firefox on Windows

Chrome on Windows

Safari, Chrome and Firefox on the Mac

Opera

Here's a working example. The following button has a custom context menu. Try to invoke it via the keyboard to see the problems yourself:

The value of the "contextmenu" synthetic event

Returning to the task at hand, as a developer you just want to bind a single "contextmenu" event listener and have it do the right thing regardless of how the event was triggered. This is what the "contextmenu" synthetic event does; it fixes all the aforementioned problems and inconsistencies while maintaining the same signature as a standard "contextmenu" DOM event. Additionally, it provides two bits of sugar:

  1. Prevents the display of the browser's context menu. (Since you're likely going to be doing that anyway.)
  2. Follows Safari's model such that when the "contextmenu" event is fired via the keyboard, the x and y coordinates of the event will reference the center of the target.

All that's required to use the "contextmenu" synthetic event is to add "event-contextmenu" to the use() statement.

``` YUI().use("event-contextmenu", function (Y) { }); ```

Here's a working example: The following button has a custom context menu. On Windows the context menu can be invoked by pressing either Menu or using Shift + F10, on the Mac use Shift + Ctrl + Alt + M.

Here's the code for the example:

``` YUI().use("event-contextmenu", "overlay", function (Y) { var btn = Y.one("#btn-2"), contextmenu; function onContextmenu(e) { if (!contextmenu) { contextmenu = new Y.Overlay({ bodyContent: "", visible: false, constrain: true }); contextmenu.render(Y.one("body")); } contextmenu.set("xy", [e.pageX, e.pageY]); contextmenu.show(); } btn.on("contextmenu", onContextmenu); }); ```