Click here to Skip to main content
Click here to Skip to main content

JavaScript Context Menu Control

By , 23 Jun 2008
 

demo.gif

Introduction

I’m going to introduce here a JavaScript Context Menu control. It is a cross-browser JavaScript class that runs on various browsers except Opera as Opera doesn’t support the oncontextmenu event.

Background

Around one and a half years ago, I had created a context menu to display on a GridView control to perform some actions in a project. That project was IE based. So, the context menu was IE specific, and not cross-browser compatible. Also, it was a mixture of JavaScript and HTML: I had created its layout using the HTML table and div elements and displayed it using JavaScript. I wanted to develop it as a cross-browser JavaScript class. So, I started its development, and after spending some time on the Internet and books, I succeeded.

Constructor

The constructor of the context menu class takes an argument of the type Object Literal. The definition of the Object Literal argument for this control is given below:

var Arguments = {
   Base: _Base, // Base reference where Context Menu to be displayed.
   Width: _Width, // Width of the Context Menu in integer.
   FontColor: _FontColor, // Font Color of each Context Menu item.
   HoverFontColor: _HoverFontColor, // Hover Font Color of each Context Menu item.
   HoverBackgroundColor: _HoverBackgroundColor, // Hover Background Color
                                                // of each Context Menu item.
   HoverBorderColor: _HoverBorderColor, // Hover Border Color of each Context Menu item.
   OnClickEventListener: _OnClickEventListener // Reference of the click event handler.
};

//Example:

var Arguments = {
   Base: document.getElementById('div'),
   Width: 200,
   FontColor: black,
   HoverFontColor: white,
   HoverBackgroundColor: blue,
   HoverBorderColor: orange,
   OnClickEventListener: ClickEventHandler  
};

You can assign each property of the Object Literal argument to null. In this case, each property will acquire its default value as:

var Arguments = {
   Base: null, // Default Value: document.documentElement.
   Width: null, // Default Value: 200.
   FontColor: null, // Default Value: ‘black’.
   HoverFontColor: null, // Default Value: ‘white’.
   HoverBackgroundColor: null, // Default Value: '#2257D5'.
   HoverBorderColor: null, // Default Value: ‘orange’.
   OnClickEventListener: null //Default anonymous method.
};

Methods

The context menu control has the following public methods:

  • AddItem(ImagePath, ItemText, IsDisabled, CommandName) - Used to add a context menu item.

    It takes four arguments:

    • ImagePath: Path of the item image.
    • ItemText: The item text.
    • IsDisabled: Indicates whether the item is to be disabled or not.
    • CommandName: The command name of the item.
  • AddSeparatorItem(): Used to add a separator item.
  • Display(e): Used to display the context menu.
  • Hide(): Used to hide the context menu.
  • Dispose(): Used to destroy the context menu.
  • GetTotalItems(): Used to get the count of total items including the separator items.

Properties

The context menu control has only a public property. It only displays the current version of the context menu control. It does nothing else.

  • Version: Displays the current version.

Events

The context menu control has only one event – The Click event that fires when items other than the separator items are clicked.

  • Click: Fires when an item is clicked.

The local anonymous method that responds to the Click event (i.e., the event handler) has the following signature:

var EventHandlerName = function(Sender, EventArgs)
{
   ...
}

where Sender is the reference of the element that raises the click event (i.e., the tr element) and EventArgs is the Object Literal that contains the necessary information regarding Click event. The EventArgs Object Literal has the following definition:

var EventArgs = {
   CommandName: _CommandName, // Base Command name of the Item.
   Text: _Text, // Item Text.
   IsDisabled: _IsDisabled, // Indicate whether Item to be disabled or not.
   ImageUrl: _ImageUrl // Path of the Item image. 
};

Note that the Click event handler is a C# style event handler.

Using the Control

Add a reference to the ContextMenu.js file in your web page, as:

<script type="text/javascript" src="JS/ContextMenu.js"></script>

Create a div element on the web page, as:

<div id="div" style="width: 925px; height: 300px; background-color: silver;">
</div>

Now, create a script tag in the head section of the web page and add the following code in the window.onload event:

<script type="text/javascript">
    var oCustomContextMenu = null;
    var oBase = null;
    
    window.onload = function()
    {
        oBase = document.getElementById('div');
        
        var Arguments = {
            Base: oBase,
            Width: 200,
            FontColor: null,
            HoverFontColor: null,
            HoverBackgroundColor: null,
            HoverBorderColor: null,
            ClickEventListener: OnClick
        };
        
        oCustomContextMenu = new CustomContextMenu(Arguments); 
                        
        oCustomContextMenu.AddItem('Images/ei0019-48.gif', 'Add', false, 'Add');
        oCustomContextMenu.AddItem('Images/save.png', 'Save', true, 'Save');
        oCustomContextMenu.AddSeparatorItem();
        oCustomContextMenu.AddItem('Images/ei0020-48.gif', 'Update', false, 'Update');
        oCustomContextMenu.AddSeparatorItem();
        oCustomContextMenu.AddItem(null, 'Cancel', false, 'Cancel');
    } 
</script>

First, get the reference of the Base object and create an Arguments Object Literal with the necessary properties. After that, instantiate a context menu object using the new keyword and add the context menu items. Don’t forget the Click event wire up in the Arguments Object Literal:

ClickEventListener: OnClick 

Now, create a Click event handler as a local anonymous method:

var OnClick = function(Sender, EventArgs)
{
    //Code
    …
    oCustomContextMenu.Hide();
} 

//Example:

var OnClick = function(Sender, EventArgs)
{
    switch(EventArgs.CommandName)
    {
        case 'Add':
            alert('Text: ' + EventArgs.Text);
            alert('IsDisabled: ' + EventArgs.IsDisabled);
            alert('ImageUrl: ' + EventArgs.ImageUrl);
            break;
        case 'Save':
            alert('Text: ' + EventArgs.Text);
            alert('IsDisabled: ' + EventArgs.IsDisabled);
            alert('ImageUrl: ' + EventArgs.ImageUrl);
            break;
        case 'Update':
            alert('Text: ' + EventArgs.Text);
            alert('IsDisabled: ' + EventArgs.IsDisabled);
            alert('ImageUrl: ' + EventArgs.ImageUrl);
            break;
        case 'Cancel':
           alert('Text: ' + EventArgs.Text);
           alert('IsDisabled: ' + EventArgs.IsDisabled);
           alert('ImageUrl: ' + EventArgs.ImageUrl);
           break;
    }
    
    oCustomContextMenu.Hide();
}

This method will get called when you click on any item of the context menu. Don’t forget to invoke the Hide method at last in the event handler.

Now, attach the oncontextmenu event on the div that has been created earlier:

<  oncontextmenu="javascript:return oCustomContextMenu.Display(event);"  >

Invoke the Dispose method in the window.onunload event in order to destroy the context menu object:

window.onunload = function(){ oCustomContextMenu.Dispose(); }

Conclusion

So this is my approach. I was working for a long time to create C# like event handlers for JavaScript classes and finally, I’ve done it. Please let me know of any bugs and suggestions to improve this context menu control.

Browser Compatibility

I have tested this control on various browsers and it works fine except on Opera as Opera doesn’t support the oncontextmenu event. If any one has information regarding simulating the oncontextmenu event on Opera, kindly let me know. The following are the supported browsers:

Browsers.png

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Samir NIGAM
Team Leader
India India
Member
SAMIR NIGAM is a CodeProject MVP, a Microsoft Certified Technology
Specialist (MCTS)
as well as a Microsoft Certified Professional Developer (MCPD)
in C# for web-based applications. He is an insightful IT professional with
results-driven comprehensive technical skill having rich, hands-on work experience
in web-based applications using ASP.NET, C#, AJAX, Microsoft
Enterprise Library
, MS SQL Server 2005.
He has earned his master degree (MCA) from U.P. Technical University, Lucknow,
INDIA, his post graduate dipoma (PGDCA ) from Institute of Engineering and
Rural Technology, Allahabad, INDIA and his bachelor degree (BSc - Mathematics)
from University of Allahabad, Allahabad, INDIA.
He has good knowledge of Object Oriented Programming, 3-Tier Architecture
and Algorithm Analysis & Design as well as good command over cross-browser
client side programming using JavaScript.
Awards:


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionMy vote of 6member_skidrow_vn_21 Aug '11 - 22:10 
Best Of Best OMG | :OMG: Thumbs Up | :thumbsup:
AnswerRe: My vote of 6memberSamir NIGAM21 Aug '11 - 22:15 
Thanks a lot.
Samir NIGAM
My Articles

QuestionHow to add Multlevelmemberkeyur soni25 Jul '11 - 21:59 
Hello sir,
 
Can you please tell me how i can add multilevel in context menu.
 
like
 
Add
Update
Selete
Single Select
Multiple Selete
 
Here i want add Single Select , Multiple Selete in second level....
when i mouse over Select it will show me Single and multiple select.
 
Please help...
GeneralMy vote of 5memberjasv25 May '11 - 6:15 
Exactly what I was looking for. Well explained without noise of other parts of a project. Thanks.
GeneralRe: My vote of 5memberSamir NIGAM21 Aug '11 - 22:16 
Thanks a lot.
Samir NIGAM
My Articles

QuestionDisplay many context menumemberMember 29335001 May '11 - 23:38 
Can you pls help me to display multiple of context menus in the sam page.
I mean dynamic div(s) with dynamic id(s) to enable display different context menus even click on any div
 
How i can pass different id(s) ex:div1, div2, div3.... to this line
oBase = document.getElementById('div');
QuestionNot able to get Exact Sender when context Menu is opened?memberShailendra_atrey14 Nov '10 - 23:33 
I am developing a MVC application using Telerik Treeview.
I am trying to show Context menu as you have mention in this article.
I am able to show context Menu but not able to trap the sender TreeViewNode.
 
Here is my code snippet how m using
 
Script file code
 
<script type="text/javascript">
var oCustomContextMenu = null;
var oBase = null;
window.onload = function () {
oBase = document.getElementById('MyTreeView');
 
var Arguments = {
Base: oBase,
Width: 200,
FontColor: null,
HoverFontColor: null,
HoverBackgroundColor: null,
HoverBorderColor: null,
ClickEventListener: OnClick
};
 
oCustomContextMenu = new CustomContextMenu(Arguments);
 
oCustomContextMenu.AddItem('Images/ei0019-48.gif', 'Add', false, 'Add');
oCustomContextMenu.AddItem('Images/save.png', 'Save', true, 'Save');
oCustomContextMenu.AddSeparatorItem();
oCustomContextMenu.AddItem('Images/ei0020-48.gif', 'Update', false, 'Update');
oCustomContextMenu.AddSeparatorItem();
oCustomContextMenu.AddItem(null, 'Cancel', false, 'Cancel');
}
 
var OnClick = function (Sender, EventArgs) {
debugger;
switch (EventArgs.CommandName) {
case 'Add':
var slelectedNode = $("MyTreeView");
alert('Text: ' + EventArgs.Text);
alert('IsDisabled: ' + EventArgs.IsDisabled);
alert('ImageUrl: ' + EventArgs.ImageUrl);
break;
case 'Save':
alert('Text: ' + EventArgs.Text);
alert('IsDisabled: ' + EventArgs.IsDisabled);
alert('ImageUrl: ' + EventArgs.ImageUrl);
break;
case 'Update':
alert('Text: ' + EventArgs.Text);
alert('IsDisabled: ' + EventArgs.IsDisabled);
alert('ImageUrl: ' + EventArgs.ImageUrl);
break;
case 'Cancel':
alert('Text: ' + EventArgs.Text);
alert('IsDisabled: ' + EventArgs.IsDisabled);
alert('ImageUrl: ' + EventArgs.ImageUrl);
break;
}
 
oCustomContextMenu.Hide();
}
 
window.onunload = function () { oCustomContextMenu.Dispose(); }
</script>
 
View code
<%= Html.Telerik().TreeView().Name("MyTreeView").ShowLines(true).Name("TreeView").Items(items => items.Add().Text("Item1").HtmlAttributes(new { oncontextmenu = "javascript:return oCustomContextMenu.Display(event);" }).Items(subItems => subItems.Add().Text("SubItem1")))%>

 
What i am finding is , Sender of OnClick event is not The Treeview node.
 

am i missing something? Please let me know
GeneralEnable a Disabled Menu [modified]memberSatish Panchware6 Jan '10 - 2:53 
pls tell me how can i enable a disabled menu, I am trying to set using Sender.parentElement.firstChild.isDisabled
 
satish
modified on Wednesday, January 6, 2010 9:01 AM

GeneralFIREFOX functionality and POPUPMENU location FIXmembercjsmithMRC14 Jul '09 - 15:40 
Want to first and foremost say thank you for this code and contribution to people. This is great, good work sir!!
Now to give a little back..
 
This will allow functionality in Firefox and related browsers and not just IE and correct that bug where the popup menu would display in the wrong
place when scrolling to other areas (ex: within a gridview)
 
How to use: Just copy and paste.
 
Just FYI:
Adjust your menuOffset # by how large your menu is to tighten things up, upwards or downwards if needed but will depend on your menu size.
 

I'm using 350 at this line {if(e.clientY > 350) because in a resolution of 1024x768 its about half way down the screen i want to start offsetting the menu so the menu will never go below the bottom of the screen and will stay visible to the user at all times. (its annoying to pop a menu and then have to scroll down to see it all)
 
Inside the ContextMenu.js file..
 
comment out your old Display function and replace with:
 
this.Display = function(e)
{
var browserName = "";
var ua = navigator.userAgent.toLowerCase();
if ( ua.indexOf( "opera" ) != -1 ) {
browserName = "opera";
}
else if ( ua.indexOf( "msie" ) != -1 ) {
browserName = "msie";
}
else if ( ua.indexOf( "safari" ) != -1 ) {
browserName = "safari";
}
else if ( ua.indexOf( "mozilla" ) != -1 ) {
if ( ua.indexOf( "firefox" ) != -1 ) {
browserName = "firefox";
}
else {
browserName = "mozilla";
}
}
if(browserName == "msie") {
e = window.event;
}
var menuOffset = 2;
var xLeft = mouseX(e) - menuOffset;
if(browserName == "msie") {
if(e.clientY > 350) {
menuOffset = 210;
}
}
else{
if(e.pageY > 350) {
menuOffset = 210;
}
}
var yTop = mouseY(e) - menuOffset;

ContextMenuDiv.style.visibility = 'hidden';
ContextMenuDiv.style.left = xLeft + 'px';
ContextMenuDiv.style.top = yTop + 'px';
ContextMenuDiv.style.visibility = 'visible';

return false;
}
function mouseX(e)
{
 
if (e.pageX) {
return e.pageX;
}
else if (e.clientX){
return e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
}
else {
return null;
}
}
function mouseY(e)
{
 
if (e.pageY) {
return e.pageY;
}
else if (e.clientY) {
return e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
}
else {
return null;
}
}
 

Enjoy! And Thanks Samir!
GeneralRe: FIREFOX functionality and POPUPMENU location FIXmvpSamir NIGAM14 Jul '09 - 20:43 
Thanks a lot friend. I'll try to update code soon.
 
Samir NIGAM
My Articles

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 24 Jun 2008
Article Copyright 2008 by Samir NIGAM
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid