Friday, November 6, 2009

Javascript/Firefox: context menu popup

The context menu of Firefox behaves differently between the Windows and Linux platforms. On Linux, the context menu pops up as soon as you press down the right button of the mouse; While on Windows, it shows when you press down and release the right button.

The Linux style behavior makes it difficult for an extension to capture and hack the mousedown event. We can do a little hack to emulate the Windows style behavior on the Linux platform.

The idea is that we capture the mousedown event and suppress the context menu. When the user release the mouse button, we capture the mouseup event and fire a fake contextmenu event.

Here is the demo source code.

1. Capture the mousedown event and suppress the context menu.

1.1 Capture the mousedown event
addEventListener("mousedown", myMouseDown, true);

function myMouseDown(event)
   if (2 == event.button)    // right-click
      if (navigator.platform != "Win32")   // No need for Windows
         // Capture the contextmenu event.
         addEventListener("contextmenu", myNoContextMenu, true);

         // remove the listener right after to avoid mess up the other
         // contextmenu events.
         setTimeout(function(){ removeEventListener("contextmenu", myNoContextMenu, true); }, 0);

1.2 Suppress the context menu
function myNoContextMenu(event)
   // Prevent the default action, i.e. context menu poping up

2. Capture the mouseup event and pop up the context menu.

1.1 Capture the mouseup event
addEventListener("mouseup", myMouseUp, true);

function myMouseUp(event)
   if (2 == event.button)   // right-click

1.2 Pop up the context menu
function myShowContextMenu(event)
   if (navigator.platform == "Win32")
      return;  // on Window context menu is already shown on mouseup.

   // create a contextmenu event.
   var newEv = event.view.document.createEvent("MouseEvents");
   newEv.initMouseEvent("contextmenu", true, true, event.view, 1,
             event.screenX, event.screenY, event.clientX, event.clientY,
             false, false, false, false, 2, null);

   // fire the new event.

No comments:

Post a Comment