Sunday, August 29, 2010

Right-click menu on Google Maps

A right-click menu is an easy, yet extremely useful and intuitive, feature to add to most applications. This holds especially true for mapping applications where location-specific functions are desired, such as adding a destination or zooming.

The first point of business is to create the HTML for the actual menu. In this case, we will create a new DIV object with several links to javascript functions.

contextmenu = document.createElement("div");
contextmenu.className = 'contextmenu';

contextmenu.innerHTML = '<a href="javascript:void(0)" onclick="zoomIn()" id="menu1"><div class="context">  Zoom in  </div></a>'
   + '<a href="javascript:void(0)" onclick="zoomOut()" id="menu2"><div class="context">  Zoom out  </div></a>'
   + '<a href="javascript:void(0)" onclick="zoomInHere()" id="menu3"><div class="context">  Zoom in here  </div></a>'
   + '<a href="javascript:void(0)" onclick="zoomOutHere()" id="menu4"><div class="context">  Zoom out here  </div></a>'
   + '<a href="javascript:void(0)" onclick="centreMapHere()" id="menu5"><div class="context">  Centre map here  </div></a>'
   + '<a href="javascript:void(0)" onclick="addDestinationHere()" id="menu6"><div class="context">  Add destination  </div></a>';

Then we append the new code to the map DIV. We will set the visibility of the DIV to false by default, and then we will set it to true whenever we want the menu to appear.

$(map.getDiv()).append(contextmenu);

So, at this point we have the code for our context menu, and it is now appended to the map DIV. The next step is to make the context menu visible when the user performs a right-click event. We also want to position the menu at the location of the user click. For now we will add a listener for the right-click event, which will call another function with the location (Latitude/Longitude) as an argument.

google.maps.event.addListener(map, "rightclick", function(event) {
   showContextMenu(event.latLng);
});

The showContextMenu() function must do three things: (1) display the context menu, (2) set the location of the context menu to the click location, and (3) store the click location for use by any of the menu functions. The first item is fairly simple, and it consists of setting the visibility to true. And for the third item we store the Latitude/Longitude parameter into a global variable. The second item is a bit trickier, so we'll separate it into another function setMenyXY().

function showContextMenu(currentLatLng) {
   setMenuXY(currentLatLng);
   clickedLoc = currentLatLng;
   contextmenu.style.visibility = "visible";
}

The setMenuXY() function is a bit more code, but the concept is simple. We first store the width and height for the map and menu. We then test the click location to make sure we are never positioned outside the map; if we are, then we adjust the location to within the confines of the map. Then we set the left and right properties for the context menu to the desired location.

function setMenuXY(currentLatLng){
   var mapWidth = $('#map_canvas').width();
   var mapHeight = $('#map_canvas').height();
   var menuWidth = $('.contextmenu').width();
   var menuHeight = $('.contextmenu').height();
   var clickedPosition = getCanvasXY(currentLatLng);
   var x = clickedPosition.x ;
   var y = clickedPosition.y ;

   if((mapWidth - x ) < menuWidth)
      x = x - menuWidth;
   if((mapHeight - y ) < menuHeight)
      y = y - menuHeight;

   $('.contextmenu').css('left',x);
   $('.contextmenu').css('top' ,y);
}
Now, you will notice that there is one small problem with the menu. Most right-click menus will disappear when the user left-clicks elsewhere in the object, and this menu seems to persist until an item is selected on the meny. So, we will add another event handler that will set the visibility of the context menu to false whenever a left-click event is performed.
google.maps.event.addListener(map, "click", function(event) {
   contextmenu.style.visibility="hidden";
});

And that's your right-click menu! My next post, which should be fairly short, will detail the actual code for each function contained in the context menu (zoom, add destination, etc.).

No comments:

Post a Comment