Creating a tabbed Google Mapping InfoWindow

What can you learn here ?
  • javaScript & CSS snippets
  • how to create tabbed content
  • how to add to an InfoWindow

javaScript: creating tabbed content  get it now

This relates to Data Driven Mapping applications and the javaScript 'howTo' section.

How to create a tabbed InfoWindow

Prior to Google Mapping V3, there was a built in way to do this that seems to have now disappeared. Here is how to use javaScript and CSS to created a tabbed infoWindow (or any other tabbed web element for that matter. 

Here's an example screenshot from this example application. 


The CSS

The use of css styles makes this whole process quite straightforward. The 2 key attributes are
  1. Borders. Changing the borders gives the impression that a particular tab has been 'selected'
  2. Hiding elements. Changing the visibility of each tab blocks allows you to show the selected content.
The  required css classes and the explanations are given below
  1. mcli.  This class is applied to each element that makes up the list of tab names, for example <li class='mcli'>World</li>.  They key items here are 'inline' to keep it all on the same line, and the rounded top right and top left corners (browser permitting). This gives us this effect 
  2. mctabselected. When one of the tabs is selected we show that by removing the border from the tab and making it appear to merge into the tab content. You can do this by simply changing the background color and the bottom border color to the same as the background color of the tab content.
  3. mchover. This class is applied to the hover state of each of the tab elements to give this effect as the mouse passes over 
  4. mcselected. This class is applied to a selected tab content element. each of the corners apart from the top left are given a rounded corner (browser permitting). This allows the tab border and the top left corner to merge.
  5. mchide and mcshow. These are applied to the tab content elements when they are selected.

.mcli {
 display: inline;
 border: 1px solid Teal;
 padding: .2em;
 padding-bottom: 0px;
 background-color: Azure;
 border-top-left-radius: 5px;
 -moz-border-radius-topleft: 5px;
 border-top-right-radius: 5px;
 -moz-border-radius-topright: 5px;
}
.mctabselected {
 background-color: WhiteSmoke;
 border-bottom: 1px solid WhiteSmoke;
}
.mchover:hover {
 background-color: LightSeaGreen;
}
.mcselected {
 background-color: WhiteSmoke;
 margin: 0px;
 padding: .3em;
 border: 1px solid Teal;
 border-bottom-left-radius: 15px;
 -moz-border-radius-bottomleft: 15px;
 border-bottom-right-radius: 15px;
 -moz-border-radius-bottomright: 15px;
 border-top-right-radius: 15px;
 -moz-border-radius-topright: 15px;
}
.mchide {
 display: none;
}
.mcshow {
 display: block;
}

The javaScript

The javascript to make this happen are part of a larger application, but you can extract the intent from the snippets below

set up the class names for later use
     this.cssLi = 'mcli';
     this.cssTab = this.cssLi + ' mchover';
     this.cssTabSelected = this.cssTab + ' mctabselected';
     this.cssSelected = 'mcselected';
     this.cssHide = 'mchide';
     this.cssShow = 'mcshow';
     this.cssChart = 'mchart';

when you create a tab, add a click event to call a function that changes content and class
mcpherAddEvent (this.tab,"click",function(){ mm.fillDiv(conTab);},false ,true) ;

when a tab is selected - change its tab and content class
    mm.infoTabs[i].tab.className = mm.parent.cssTabSelected;
    mm.infoTabs[i].divContainer.className = mm.parent.cssShow + ' ' +
           mm.parent.cssSelected;

when a tab is not selected - change its tab and content class
    mm.infoTabs[i].tab.className = mm.parent.cssTab;
    mm.infoTabs[i].divContainer.className = mm.parent.cssHide;

browser independent add event function you'll need
function mcpherAddEvent (o,e,f,b,complain){
 // because IE is different
 if(o.addEventListener) 
  return(o.addEventListener(e, f, b));
      
 else 
  if (o.attachEvent) 
   return(o.attachEvent('on' + e, f));
  
  else 
     if (complain) 
            alert ('browser doesnt support events');
  
     return(null);
      
}

add to infoWindow .. Maps and Earth Version are not too different, except we need to be concerned with asynchronicity with Earth.
  switch (vm.provider){
  case 'maps':
   var iw = spot.infoWindow = new google.maps.InfoWindow (); 
   iw.setContent (iDiv);
   iw.open(gMap,spot.marker);
   google.maps.event.addListener(iw, 'domready', function() {
    vm.statusUpdate(s,false,null);
   }); 
   break;

  case 'earth':
   var ge = vm.vEarth.ge;
   var iw = spot.balloon = ge.createHtmlDivBalloon('');
   iw.setFeature(spot.placemark);
   iw.setContentDiv(iDiv);
   mcpherPlotBalloon(spot, iw );

   break;

  default:
   alert ('createinfowindowinstanity');
  break;
  }
  return (iw);
 };


As with Flying around with Google Earth things going on in the Google Earth viewport, such as building layers in progress, can destablize the plotting of a balloon. Although IE and Chrome seemed to be able to handle this ok, Firefox would always hang. To get round this, we are going to handle the viewchangeend event to minimize this happening. 

 function mcpherPlotBalloon(spot, iw ){
  var vm = spot.parent;
  var ge = vm.ve.ge;
  vm.statusUpdate ('..waiting for view to settle down',true);
  google.earth.addEventListener(ge.getView(), 
    'viewchangeend', mcpherBalloon(spot,iw));
 }
 function mcpherBalloon(spot, iw ){
  var vm = spot.parent;
  var ge = vm.ve.ge;
  if(spot.timer) clearTimeout(spot.timer);
     spot.timer = setTimeout( function(){ 
         ge.setBalloon(iw);
         vm.statusUpdate ('..information balloon set for ' + spot.title,false);
         }, 100);
 }

Comments