4umi.com/web/javascript/contextmenu

Double your contextmenu

Dynamic Javascript

A contextmenu is a menu much like the menus in the menubar. The only difference is in the way it is triggered or opened. This allows for a more direct contact with the context at hand.

What is?

Often called the right-click menu, it is opened by pressing the alternative button on a device with two buttons where the button on the left is the default one. Many left-handed people do not know this, but there are mirrored versions of your computer mouse for the right-handed. The Macintosh mouse has only one button and provides the additional functionality when the user holds it down for a second. Also, in Internet Explorer the Shift+F10 function key combination will display the contextmenu. Microsoft occasionally refers to it as the shortcut menu.

The idea

Most scripts that deal with right-clicks are anti-right-click scripts. They attempt to disable any and all functionality, usually in the mistaken belief that doing so will protect or hide source code, images or other material that the owner does not want copied. Such attempts are fruitless, as all who might be interested know.
Other right-click scripts produce a nice contextmenu of their own, but at the expense of losing the default contextmenu. Not so with this one. It toggles between the normal menu and the page-specific one. Try it, right-click twice.

This code makes use of system fonts and colors, meaning that the menu will look different on different machines, but each time it will be in line with the client's expectations. For more on system colors, see our list of system colors as implemented by the version 5+ browsers.

Browser support for this contextmenu has been expanded with the help of Yep in news:comp.lang.javascript.

<html>
<head>
<script type="text/javascript">
var about="...";
var rmenu = new Array(
"Alert","alert('Hello world.')",
"Confirm","if(confirm('Are you sure?'))alert('Good.');",
"Prompt","q=prompt('What would you like to see?');"+
           "alert(q.toUpperCase())",
"hr",
"About","na=window.open('','','width=400,height=160,"+
          "left=200,top=120');"+
          "na.document.open();na.document.write(about);"+
          "na.document.close();"
);

var tid;
function isvis(){
var els=getCM();
if(els) tid=els.style ? els.style.visibility : els.visibility;
}

function getCM(){
var d=document, el=null;
if(d.all){el=d.all.contextMenu}
else if(d.getElementById){el=d.getElementById("contextMenu")}
else if(d.layers){el=d.layers["contextMenu"]}
return el;
}

function hideMenu() {
var el=getCM(); if(!el) return;
if(el.style) el.style.visibility="hidden";
else el.visibility="hide";
}

function showMenu (evt) {
if(tid=="visible"||tid=="show") {
hideMenu(evt);
return true;
}

if(!evt) evt = window.event || {};
var d=document,
      e = {x:evt.x || evt.pageX || 0, y:evt.y || evt.pageY || 0},
      CM=getCM();

if(CM){
var
clientDim=(d.body && typeof d.body.clientWidth!="undefined") ?
       {w:d.body.clientWidth, h:d.body.clientHeight} :
       {w:window.innerWidth, h:window.innerHeight},
CMDim={w:CM.offsetWidth||0, h:CM.offsetHeight || 0},
shift={
       x:(clientDim.w-e.x<CMDim.w) ? CMDim.w : 0,
       y:(clientDim.h-e.y<CMDim.h) ? CMDim.h : 0},
scroll=(d.body && typeof d.body.scrollLeft!="undefined") ?
       {x:d.body.scrollLeft, y:d.body.scrollTop} :
       {x:window.pageXOffset, y:window.pageYOffset};

if(CM.style){
      CM.style.left = ((scroll.x+e.x-shift.x)||0) + "px";
      CM.style.top = ((scroll.y+e.y-shift.y)||0) + "px";
      CM.style.visibility = "visible";
      return false;
} else {
      if(evt.which == 3) {
        CM.left = e.x;
        CM.top = e.y;
        CM.visibility = "show";
        return false;
      } else hideMenu();
}
} return true;
}

if(typeof window.onscroll != "undefined")
window.onscroll=hideMenu;

//ie, gecko
document.onmousedown = isvis;
document.onmouseup = hideMenu;
document.oncontextmenu = showMenu;

if(document.captureEvents &&
!window.opera && document.layers) {
//nn4, exclude opera and gecko
document.captureEvents(Event.MOUSEDOWN);
document.onmousedown = function(evt) {
isvis(evt);
return showMenu(evt);
}
} else if(window.opera) {
//Opera
document.onmouseup=null;
document.onmousedown = function(evt){
if(evt && evt.ctrlKey){
      isvis(evt);
      return showMenu(evt);
}else hideMenu(evt);
}
}

function writemenu(){
var txt = "<div id=\"contextMenu\">"+
            "<table border=\"0\" cellpadding=\"0\" "+
            "cellspacing=\"0\">";
for(var i=0;i<rmenu.length; i+=2){
if(rmenu[i]=="hr") {
      txt+="<tr><td><hr width='95%'><\/td><\/tr>";
      i--;
} else {
      txt+="<tr>"+
            "<td>"+
             "<a href=\"#\" "+
                "onclick=\"" + rmenu[i+1] + ";return false\" "+
                "class=\"menoff\" "+
                "onmouseover=\""+
                 "this.className='menon';"+
       //"window.status=this.onclick.toString().substring(21);"+
                 "return true\" "+
                "onmouseout=\""+
                 "this.className='menoff';"+
       //"status='';"+
                 "return true\">"+
              rmenu[i]+
              "<\/a>"+
             "<\/td>"+
            "<\/tr>";
}
} document.write(txt+"<\/table><\/div>");
}
</script>

<style type="text/css">
#contextMenu {
position: absolute;
visibility: hidden;
layer-background-color: ThreeDFace;
border: 2px outset ThreeDHighLight;
background-color: ThreeDFace;
}

.menoff{
font: Menu;
color: MenuText;
padding:0 20px 0 10px;
margin: 2px 0;
}
.menon{
font: Menu;
color: HighlightText;
background-color: Highlight;
padding:0 20px 0 10px;
margin: 2px 0;
}

div#contextMenu a{
text-decoration: none;
width:100px; /*Needed for Opera*/
cursor:default;
}

/*
Mozilla behaves correctly,
but in this case that's too bad so fix it :-)
*/
div#contextMenu td:hover a{color: HighlightText;}
div#contextMenu t
d:hover{
color: HighlightText; background-color: Highlight;
}</style> </head>
<body>
Content goes here.
<script type="text/javascript">
writemenu();
</script>
</body>
</html>