Popup menu

0
79

Introduction

Starting from a code I found HERE I developed a very simple context popup menu.

It has only one level (no nested menus) but could be good for 90% of the web project. The popup menu is implemented with javascript’s ‘function object‘  an “old fashion” development style to keep the code (and use) as simple as possible.

Background

To understand this code is enough

  • to know how to implement an ‘object’ in javascript 
  • have basic knowledge of jQuery
  • have a basic knowledge of CSS.

Using the code

The picture shows how the menu looks like. It is only an example you can do what you want, the only constraint you have is to use the tags <ul> <li>. You can use different tags but you must adapt the code in the function ‘PopupMenu’

Looking at the code you can find two different ways to use the object. 

The ‘jQuery’ way:

line 214 create an instance of the ‘PopupMenu’ object where ‘GroupB’ is the selector for both the gray regions in the picture (so both have the same popup menu) and jQuery binds the events (from the menu items) with the managing function. lines 216-219

The picture below shows the HTML referenced by the javascript code above.

The ‘on line’ way: 

This is the simplest way to use this object: it is enough to create an instance of ‘PopupMenu: Line 266, providing the selector for the element to which you want to add the popup menu and the selector for the menu (the <ul>). In lines 248-250 there is the online definition of the ‘onclick’ events and in lines 268-268 the functions for the events. 

The full-page code 

You can also “Copy and paste” in an HTML file the code below and you will have a fully running example also with images (coded as base64).

The tag <script> as a link to e: http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js or you can reference a copy of jQuery in your machine. 

<!DOCTYPE html>

<html ><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 
 
 <title>jQuery contextMenu</title>
 
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script> 

 <script type="text/javascript"> 
 try{
 
 if (typeof jQuery != 'undefined') { 
 document.write('<label style="color:green;">jQuery running version: </label><b>' + jQuery.fn.jquery + '</b>');
 }
 else{
 document.write('<label style="color:red;"> ** ATTENTION ** </label>' + ' jQuery is not running!');
 } 
 }
 catch(jse){
 document.write(' ** ATTENTION ** ' + jse.message);
 } 
 
 document.write(' - "PopupMenu" is based on code found <a href="https://stackoverflow.com/questions/4495626/making-custom-right-click-context-menus-for-my-web-app" target="_blank">HERE</a>');
 
 
 </script>
 
 <!--</span>
 <style> 
 .custom-menu {
 
 display: none;
 z-index: 1000;
 position: absolute;
 overflow: hidden;
 } 
 </style>

 <!--</span>
 <style> 
 .custom-style{
 
 white-space: nowrap;
 font-family: verdana;
 font-size:13px;
 color: #333;
 border-radius: 2px;
 
 border: solid 1px #ddd; 
 background-color: #FFF; 
 padding: 0; 
 margin: 0;
 -webkit-box-shadow: 10px 10px 20px 0px rgba(119,119,119,1);
 -moz-box-shadow: 10px 10px 20px 0px rgba(119,119,119,1);
 box-shadow: 10px 10px 20px 0px rgba(119,119,119,1); 
 }

 .custom-style li {
 padding: 3px 15px 5px 30px;
 cursor: pointer;
 list-style-type: none;
 }

 .custom-style li:hover {
 background-color: #EEE; 
 }
 
 .custom-style li.image{
 background-repeat: no-repeat;
 background-position: 8px 5px;
 } 
 
 .custom-style li.delete{
 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABESURBVDhPY/j
 } 
 .custom-style li.edit{
 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAEMSURBVDhPnZOhkoNAEETzxzgUDofCITE4HAoFDouiUFQh+AYMoo83y3JJLrkj11VvgWWmmZlNbpI+Zp7n/eLubVmWReM4vmWapjMBuq7TMAy2d260bfuWvu8t2BvyQTgN6roWbNvG5g+t62pfJKZpmjMZbKmqSvBKmFKBj6GiXZYHtpRlKXgl2vPvqYB5YOIHaQZFUQieRen+HQY8k8gzxrucQZ7ngmfRK/skHH1bBez5VswgyzLBveidgTH1++FiQCzt7HIGaZoKrggDYh8MkiQRXBEVEXucmjOI41hwRfweiD1OzRlEUSRgyn/B9Il9MAjDUOBP4zcon9jj2L9nEATBR/g/mBn8H92+AMRlSI4HRnCNAAAAAElFTkSuQmCC')
 } 
 .custom-style li.refresh{
 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAACSSURBVDhPtZJLDsAgCEQ9tRfQw3gir0MziyEjxaafdPESeFCKxmJmn0jlEzxorVmEtVqr9d49V5ZkN0DdnNM98ABoI6AfY6QeeIAVtSk2Ano9zqmIvzFnjegmdF6MhR3/D+ARFH5weQS9RDpCT9JLBNqkm6gH9MADgEeSNapTDzxQsCKeL/M4QIcsH74hlfexcgDQkdsLtKMLtAAAAABJRU5ErkJggg==')
 } 
 .custom-style li.add{
 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAABkSURBVDhPpc1bCkAhCEXR5j8qZ+ZFoTjCLsT7sSTNx3L3XzKYmXfpcCjJRAa6dKPDoSQTGejSjQ6HkkxkoEubNhMs3tDS8kG0mWrn8aILVfw9G0JrQZcObuWDaDPVzmMKi32+PhgFEhDFFe1qAAAAAElFTkSuQmCC')
 }
 </style>
 
 <!--</span>
 <style>
 body{
 color: #444;
 font-family: verdana;
 font-size:13px; 
 padding: 20px; 
 } 
 
 span{ 
 border: dotted 1px #ccc; 
 background-color: #eee;
 margin: 10px 10px;
 width:140px;
 height:40px;
 padding-top:10px;
 display: inline-block;
 text-align:center;
 }
 
 div{
 border: dotted 1px #ccc; 
 margin: 30px 0px;
 padding:10px;
 }
 
 </style>
 
 <script type="text/javascript">
 
 
 
 
 
 
 function PopupMenu(contextElement, popupElement){
 
 
 var THIS = this;
 
 
 this.currentTarget;

 
 this.fadeLeaveTime = 300; 
 this.fadeOpenTime = 100; 
 this.delayTime = 300; 
 this.fadeCloseTyme = 100; 
 
 
 this.$popupElement = $(popupElement);
 
 
 
 
 
 $(contextElement)
 .contextmenu(function (jqEvent){
 
 
 if (jqEvent.ctrlKey){ return; }

 
 jqEvent.preventDefault();
 
 
 THIS.currentTarget = jqEvent.currentTarget;
 
 THIS.$popupElement
 .stop(true, false) 
 .fadeIn(THIS.fadeOpenTime) 
 .delay(THIS.delayTime) 
 .fadeOut(THIS.fadeLeaveTime) 
 .css({ 
 top: (jqEvent.pageY - 0) + "px",
 left: (jqEvent.pageX - 0) + "px"
 });
 }); 
 
 
 
 
 
 function hover_in($element){ 
 $element
 .stop(true, false)
 .fadeIn(THIS.fadeOpenTime);
 } 
 
 function hover_out($element){
 $element.delay(THIS.delayTime).fadeOut(THIS.fadeLeaveTime);
 } 
 
 
 function menuItem_contextmenu(jqEvent, $li){
 jqEvent.preventDefault();
 $li.trigger('click');
 } 
 
 this.$popupElement
 .hover(
 function(){hover_in ($(this))}, 
 function(){hover_out($(this))}
 )
 .find('li')
 .click(function(){ 
 $(this).closest('ul').fadeOut(THIS.fadeCloseTyme);
 })
 .contextmenu( function(jqEvent){
 menuItem_contextmenu(jqEvent, $(this));
 })
 
 
 
 }
 </script> 
 
 <script type="text/javascript">
 
 
 
 
 jQuery(document).ready(function (){ 

 var groupB = new PopupMenu('.groupB', "#pumB"); 

 jQuery('#pumB li').click(function (){
 $(groupB.currentTarget)
 .text($(this).text());
 }); 
 }); 
 
 
 
 </script>
 </head>
 <body> 
 
 <!--</span>
 
 <!--</span> 
 <ul class='custom-menu custom-style' id="pumB">
 <li class="image edit"   >Edit B</li>
 <li class="image delete" >Delete B</li>
 <li class="image refresh">Refresh B</li>
 <li class="image add"    >Add new B</li>
 </ul>
 
 <div> 
 <p>These two elements share the same context popup menu, the click event is managed by jQuery (look at the javascript code).</p>
 <span class="groupB" id="spnB1">Right click me</span>
 <span class="groupB" id="spnB2">Right click me</span> 
 </div> 
 
 <!--</span>
 
 <!--</span>
 <ul class='custom-menu custom-style' id="pumA">
 <li class="image edit"   onclick="liEditA_onclick()"  >Edit A</li>
 <li class="image delete" onclick="liDeleteA_onclick()">Delete A</li>
 <li class="image add"    onclick="liAddA_onclick()"   >Add new A</li>
 </ul>

 <div>
 <p>This element has its own, different, context popup menu and the click event is managed on line (look at the HTML code).</p>
 <span id="spnA">Right click me</span> 
 </div>
 
 <!--</span>
 
 <p>Hit the '<b>Ctrl</b>' key (while right click) to show the 'real' context menu.</p>
 
 </body>
 
 <script type="text/javascript"> 
 
 new PopupMenu('#spnA', "#pumA");
 
 function liEditA_onclick(){
 $('#spnA').text("Edit A");
 }
 
 function liDeleteA_onclick(){
 $('#spnA').text("Delete A");
 }

 function liAddA_onclick(){
 $('#spnA').text("Add A");
 }
 
 
 </script> 
 
 
 <script type="text/javascript"> 
 
 window.onerror = function() {
 document.write('<label style="color:red;">** ATTENTION ** Something went wrong :-(</label>');
 };
 </script>
</html>

Points of Interest

There is an important “point of interest” in the code that is a kind of “ubiquity“: the same ‘onclick’ event that occurs for each of items (<li>) of the popup menu is managed in two different places:

  • In the implementation of the object the onclick (where manages the fadeOut of the popup menu)

  • in the custom code section (where manages the action to perform on click on the menu)

Please note that the both the ‘li’ in the code shown in the pictures are the same DOM element. 

History

LEAVE A REPLY