Click here to Skip to main content
15,879,096 members
Articles / Programming Languages / PHP

Google Maps in HTML, ASP.NET, PHP, JSP, etc. with Ease

Rate me:
Please Sign up or sign in to vote.
4.84/5 (119 votes)
1 Dec 2009CPOL16 min read 919.4K   17.2K   356   127
The article will guide you with complete knowledge of how to add a Google map in your webpage with knowledge of JavaScript, use of Geocoder, use of InfoWindow, use of Marker, Tabbed Markers, Maximising marker, creating context menu, streetview in your map

Table of Contents


Introduction

This article will guide you with a bit of knowledge about the use of JavaScript, and more precisely will enable you to use Google Maps in your webpage with ease. Google brought web services that anyone can connect to and use their services without any cost. Well, there is some restriction for the use of gmap. They have two versions of maps, one for standard purpose which will come for free, and another one is Google map Enterprise Solution.

Well, simply if you want to add a Google map to your website and which can be seen from anywhere outside, means can be accessible to just using a link, you don't need to pay Google for using their API. But if you want to restrict access to maps behind a valid login, then you need to pay Google. I am using a simple HTML page for adding up gmap. And later on, I will use others also to make the gmap look very lively.

The only thing that you need in case of using gmap to your application is an Google account. You can sign up for an account for free. Just go here.

You could sign up for an account for free, and then you can use Google maps to your website by clicking on "Create an account now". After you create an account, just use your userid and password to login when required.

Background

For using Google Maps in your website, the thing you need is a bit of knowledge of JavaScript, means how to call a function from web controls. I will describe everything, but you need to catch up all those.

Sample Examples

I am creating an HTML page for implementing this project. You can use any projects to implement maps dynamically using any server side languages.

Example 1: Getting Started

JavaScript
//Use of Gmap in your web page

// 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>My Locations</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
    key=ABQIAAAAcl" type="text/javascript"></script>
<script type="text/javascript">

function load() 
{
      if (GBrowserIsCompatible()) {
        var point;
        var map=new GMap2(document.getElementById("map"));
         map.addControl(new GOverviewMapControl());
     map.enableDoubleClickZoom();
     map.enableScrollWheelZoom();
     map.addControl(new GMapTypeControl());
     map.addControl(new GSmallMapControl());
         var address='<img src="myimage.gif" width=150 height=40/><br/>' + 
         <font size="2" face="Arial"><b>INDIA</b><br/><br/>Home.<br/>' + 
     New York City<br/><br/>America<br/>Ph.: 23743823</font>';
         var marker = new GMarker(point);
         map.setCenter(point,17);
         map.addOverlay(marker);
         map.setMapType(G_HYBRID_MAP);
         GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(address);});
         marker.openInfoWindowHtml(address); 
               
      }
    }
 </script>
<body onload="load();" onunload="GUnload()" style=" 
        background-color:Transparent">
<div id="map" style="width: 900px; height: 500px"></div>
</body>
</html>

Coming to the code, first in your webpage, you need to add one <div> where we are going to load the Google map. I have taken a div similar to that and named it as "map". The width and height will specify how much the size of the page will be.

JavaScript
<div id="map" style="width: 900px; height: 500px"></div> 

Now, I have called a JavaScript function when body loads, thus, in my sample application, as soon as the page comes to your browser, you will see a gmap loaded. So I have created a JavaScript load function which will be called as soon as I open the webpage. Now during the page load, we have added a dynamic JavaScript file which will be dependent on webhost. The line...

JavaScript
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
   key=ABQIAAAAcl" type="text/javascript"></script>

...adds up a file from Google. This is essential, because that file will create the entire map for you. Just one thing that you need is to generate an API KEY for your web host. Be it local host, use http://localhost to it. Just click below and get the key.

Image 1

You will get a key from here, just replace the key in the key attribute of the JavaScript line.

After you do that, I have used GBrowserIsCompatible(), it's a function which will return true only if your browser is compatible with gmap. The next line will load the gmap control to the div control. GMap2 function takes the control to load and returns a map object which can be referenced later on. Next, map.addControl(new GOverviewMapControl()); will add a new control to the map, called GOverviewMapControl.

Overview Map Contro

It will be an overview of the map just in the right hand bottom corner to the map.

I can add more controls through addControl Function. I have used GSmallMapControl().

Image 3 to add a zoom control to the map, and also new GMapTypeControl()

Image 4 as new map type control in a similar way. There are mainly 3 types of map, they are Normal, Satellite and Hybrid. Those options could be found on your map.

The enableDoubleClickZoom and enableScrollWheelZoom will enable those features simply to your map.

After that, I have placed a marker on my application. Markers are images that can be placed over the map to point a location. To place a marker, you need a latitude and longitude which should be passed throught GLatLng() function to get a valid point. I have also made an HTML that could be shown to the map. I have let a var address to store the HTML. Later on, I have created a marker into the map using those latitude and longitude. The GMarker will create one marker and addOverlay() will add the marker in the form.

The GEvent.addListener will add one listener to the map through which the map respond. I have added a click event listener to my map, so that when one clicks on the map, it will show the InfoWindow of the marker. openInfoWindowHtml() will open the info window HTML for me. That's all. You have created a simple map and added to your HTML page.

Take a look at the snapshot:

Screenshot - coolcode1.jpg

Example 2: Create Polylines on Custom Map

Now let us make it more advanced adding polylines to it.

JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:v="urn:schemas-microsoft-com:vml">
<head>
    <title>Untitled Page</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
key=ABQIA" type="text/javascript"></script>
    <script type="text/javascript">
    function loadEarth(mapdiv) {
   if (GBrowserIsCompatible()) {
      var point;
      if(!mapdiv)return true;
      var map=new GMap2(document.getElementById("map"));
      map.addControl(new GOverviewMapControl());
      map.enableDoubleClickZoom();
      map.enableScrollWheelZoom();
      map.addControl(new GMapTypeControl());
      map.addControl(new GSmallMapControl());
      var marker = new GMarker(new GLatLng(37.4419,-122.1419));
      map.setCenter(new GLatLng(37.4419,-122.1419),17);
      GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml("hii");});
      map.addOverlay(marker);
        map.setCenter(new GLatLng(37.4419, -122.1419), 16);
      map.setMapType(G_SATELLITE_MAP);
      var polyline = new GPolyline([new GLatLng(37.4419, -122.1419),
    new GLatLng(37.4519, -122.1519),
    new GLatLng( 37.4619, -122.1819)], "#3333cc", 10);
      }
      map.addOverlay(polyline);
 }
    </script>
</head>
 <body onload="loadEarth('map')" onunload="GUnload()" style=" 
                background-color:Transparent">
    <div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>

In the above example, I have taken 3 points just after creation of markers and drawn polyline over those points.

GPolyline() will create a polyline object using an array of points, with a specific color, here I have taken the color using hexadecimal code and the width, which is 10 here. After that, I have used addOverlay function to add the polyline to our actual map.

Remember to add the vml namespace in case of using polylines. We also need to use strict DTD standard to show polylines on the map.

JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:v="urn:schemas-microsoft-com:vml">

Otherwise, the polyline will not be shown to your map. Take a look at the snapshot:

Screenshot - coolcode2.jpg

Example 3: Geocode Address for Lat/Lon

In my next example, I would use Geocoder functionality to my map, so that you could search any address from a search textbox, and the geocoder will search those addresses for you.

JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Coder Page</title>
     <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAA"
      type="text/javascript"></script>
    <script language="'Javascript'" type='text/javascript'>
     var map = null;
    var geocoder = null;
    function load() {
      if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(37.4419, -122.1419), 13);
        geocoder = new GClientGeocoder();
      }
    }
    function showAddress(address) {
      if (geocoder) {
        geocoder.getLatLng(
          address,
          function(point) {
            if (!point) {
              alert(address + " not found");
            } else {
              map.setCenter(point, 17);
              var marker = new GMarker(point);
              map.addOverlay(marker);
              marker.openInfoWindowHtml(address);
            }
          }
        );
      }
    }
 
</script>    
</head>
  <body onload="load()" onunload="GUnload()">
     
        <input type="text" size="60" name="address" id="addr"
        value="India" />
        <input type="button" value="Go!" 
    onclick="showAddress(document.getElementById("addr").value); 
                        return false"/>
      </p>
      <div id="map" style="width: 500px; height: 300px"></div>
   
  </body>
</html> 

In the above example, I have added another function that will enable us to call any address and the address will be replaced with a point in terms of latitude and longitude. The GClientGeocoder() will return a geocode object to the client browser which could be later used to get a point from any text address. Google has approximated this search will take 1.73 seconds for each geocode call. So it's not that much slow. Now for searching an address, I have created a button and a textbox, which will be used to get address from the user. The showaddress function will take one address from the user and create a marker just into that location, and open the infowindow of that marker. If no points are found, it returns an alert. So on clicking the button, it will call the showaddress function, and it will show the location.

Look at the SnapShot of what we built so far:

Screenshot - coolcode3.jpg

Example 4 : Create Context Menu

Well, in my next example, I am adding an example that can demonstrate the use of gmap in a better way. I am adding context menu. See the code first:

JavaScript
var map = null;
    var geocoder = null;
    var contextmenu;
    function load(loc) {
      if (GBrowserIsCompatible()) {
        var point;
        map=new GMap2(document.getElementById("map"));
     
        map.addControl(new GOverviewMapControl());
        map.enableDoubleClickZoom();
        map.enableScrollWheelZoom();
        map.addControl(new GMapTypeControl());
        map.addControl(new GLargeMapControl());
        createContextMenu(map); 
        var address='<font size="2" face="Arial"><b>INDIA</b><br/>
          <br/>XYZ Inc.<br/>New York City <br/>
          America<br/>Ph.: 343254543</font>';
        point = new GLatLng(22.592057,88.421815);
               
        var marker = new GMarker(point);
        map.setCenter(point,17);
        map.addOverlay(marker);
        map.setMapType(G_HYBRID_MAP);
        GEvent.addListener(marker, 
          "click", function() {marker.openInfoWindowHtml(address);});
        marker.openInfoWindowHtml(address); 
           
      }
    }   
  
  function createContextMenu(map)
   {
      contextmenu = document.createElement("div");
      contextmenu.style.visibility="hidden";
      contextmenu.style.background="#ffffff";
      contextmenu.style.border="1px solid #8888FF";

contextmenu.innerHTML = '<a href="javascript:zoomIn()">
  <div class="context">  Zoom in  </div></a>'
+ '<a href="javascript:zoomOut()">
  <div class="context">  Zoom out  </div></a>'
+ '<a href="javascript:zoomInHere()">
  <div class="context">  Zoom in here  </div></a>'
+ '<a href="javascript:zoomOutHere()">
  <div class="context">  Zoom out here  </div></a>'
+ '<a href="javascript:centreMapHere()">
  <div class="context">  Centre map here  </div></a>';

      map.getContainer().appendChild(contextmenu);
      GEvent.addListener(map,"singlerightclick",function(pixel,tile) 
      {
          clickedPixel = pixel;
          var x=pixel.x;
          var y=pixel.y;
          if (x > map.getSize().width - 120) 
          { 
            x = map.getSize().width - 120 
          }
          if (y > map.getSize().height - 100) 
          { 
            y = map.getSize().height - 100 
          }
          var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(x,y));  
          pos.apply(contextmenu);
          contextmenu.style.visibility = "visible";
     });
     GEvent.addListener(map, "click", function() 
     {
          contextmenu.style.visibility="hidden";
     });
 }
 function zoomIn() 
 {
            map.zoomIn();
            contextmenu.style.visibility="hidden";
 }      
 function zoomOut() 
 {
           map.zoomOut();
           contextmenu.style.visibility="hidden";
 }      
 function zoomInHere() 
 {
           var point = map.fromContainerPixelToLatLng(clickedPixel)
           map.zoomIn(point,true);
           contextmenu.style.visibility="hidden";
 }      
 function zoomOutHere() 
 {
          var point = map.fromContainerPixelToLatLng(clickedPixel)
          map.setCenter(point,map.getZoom()-1); 
          contextmenu.style.visibility="hidden";
 }      
 function centreMapHere() 
 {
         var point = map.fromContainerPixelToLatLng(clickedPixel)
         map.setCenter(point);
         contextmenu.style.visibility="hidden";
 }

In this example, I have added a custom div control when the user right clicks anywhere in the map. The event that should be registered when user right clicks the map is GEvent.addListener(map,"singlerightclick",function(pixel,tile). I have created on the same point where the right click occurs, by getting the points from pixel. The div have some function calls when option is clicked. Those calls the map.zoomIn, ZoomOut functions. The container is set to hidden when the option works just to eliminate the custom div control from the map.

Check the snapshot:

Screenshot - coolimage4.jpg

Example 5: Tabbed Infowindow with Maximize Capability

Well, in this example, I will give you idea about how to create tabbed info window and also an option to maximize the infowindow so that you can show a webpage within it. Just take a look at the code below:

JavaScript
var map = null;
var geocoder = null;
function load(loc) {
   if (GBrowserIsCompatible()) {
         var point;
         var map=new GMap2(document.getElementById("map"));
         map.addControl(new GOverviewMapControl());
       map.enableDoubleClickZoom();
       map.enableScrollWheelZoom();
       map.addControl(new GMapTypeControl());
       map.addControl(new GSmallMapControl());
       var address='<font size="2" face="Arial"><b>INDIA</b><br/><br/>
   XYZ Inc.<br/>New York City <br/>America<br/>Ph.: 343254543</font>';
      point = new GLatLng(22.592057,88.421815);
       var marker = new GMarker(point);
       map.setCenter(point,17);
       map.addOverlay(marker);
       map.setMapType(G_HYBRID_MAP);
       GEvent.addListener(marker, "click", function() {
       marker.openInfoWindowTabsHtml(
   [new GInfoWindowTab("BASIC",address),
   new GInfoWindowTab("Advanced","<b>Dont forget to click on
   <br/>Maximize button on this window with + sign</b>")],
   {maxUrl:"http://dotnetricks.blogspot.com"});
     });
     }
   }

Well, you can see the line GEvent.addListener where instead of calling openInfoWindow, we are calling openInfoWindowTabsHtml. This function will enable us to create a tabbed window. The arguments are array of Tabs that could be found from GInfoWindowTab, which takes two arguments, the first one is header, and the second is the content in HTML. The second argument of openInfoWindowTabsHtml is options, where I have used maxUrl option, which will create a maximize button on the window. I can use this option in normal markers too. Now let's look at the snapshots:

Screenshot - coolimage5.jpg

This window is showing the tabbed window with two tabs:

  1. Basic and
  2. Advanced

When you click on the + button just beside the Close button, It will open an HTML window within the gmap. See the snapshot:

Screenshot - coolimage6.jpg

Example 6 : Trap Client Events for Data

In this demo, I will be using a new event handler called Dragend and moveend handler. Take a look at the simple code:

JavaScript
 <script type="text/javascript">

function load() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.addControl (new GSmallMapControl());
map.addControl(new GMapTypeControl());
var center = new GLatLng(-22.98699983834975, -43.210344314575195);
map.setCenter(center, 11);
map.setMapType(G_SATELLITE_MAP);
geocoder = new GClientGeocoder();

var marker = new GMarker(center, {draggable: true}); 
map.addOverlay(marker);
document.getElementById("lat").value = center.lat();
document.getElementById("lng").value = center.lng ();

geocoder = new GClientGeocoder();

GEvent.addListener(marker, "dragend", function() {
var point =marker.getPoint();
map.panTo(point);
document.getElementById("lat").value = point.lat();
document.getElementById("lng").value = point.lng();
});

GEvent.addListener(map, "moveend", function() {
map.clearOverlays();
var center = map.getCenter();
var marker = new GMarker(center, {draggable: true});
map.addOverlay(marker);
document.getElementById ("lat").value = center.lat();
document.getElementById("lng").value = center.lng();

GEvent.addListener(marker, "dragend", function() {
var point =marker.getPoint();
map.panTo(point);
document.getElementById("lat").value = point.lat();
document.getElementById("lng").value = point.lng();
});
});
}
}

function showAddress(address) {
var map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
if (geocoder) {
geocoder.getLatLng (
address,
function(point) {
if (!point) {
alert(address + " city not found !");
}
else {
document.getElementById("lat").value = point.lat();
document.getElementById("lng").value = point.lng();
map.clearOverlays()
map.setCenter(point, 14);
var marker = new GMarker(point, {draggable: true}); 
map.addOverlay(marker);

GEvent.addListener(marker, "dragend", function() {
var pt =marker.getPoint();
map.panTo(pt);
document.getElementById("lat").value = pt.lat();
document.getElementById("lng").value = pt.lng();
});

GEvent.addListener(map, "moveend", function() {
map.clearOverlays();
var center = map.getCenter();
var marker = new GMarker(center, {draggable: true});
map.addOverlay(marker);
document.getElementById ("lat").value = center.lat();
document.getElementById("lng").value = center.lng();

GEvent.addListener(marker, "dragend", function() {
var pt =marker.getPoint();
map.panTo(pt);
document.getElementById("lat").value = pt.lat();
document.getElementById("lng").value = pt.lng();
});
});
}}
);
}}
    </script>

In this example, when the use drags the map, it will automatically place coordinates to the form text boxes called lat and lng. To do this, I have made an overlay marker, and then retrieved the point using getPoint() function.

Screenshot - coolimage7.jpg

This is a simple example... just a demo. I have also included the geocoder, so that one can also search for a location.

Example 7: MarkerManager and Sidebar

In this example, you will be using MarkerManager and Sidebar to display marker links.

The Marker Manager of Google is used to manage large number of markers. See the example below:

JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Google Maps</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
         key=ABQIAAAAclK0B2lXQwV5lPy1rLiTFBSN1aiKepvDswXjKa4j2DDWdYvOjh
         QMO1tywqS8ObgP5dtO70AyyArhzA" type="text/javascript"></script>
  </head>
  <body onunload="GUnload()">

    <!-- you can use tables or divs for the overall layout -->

    <table border=1>
      <tr>
        <td>
           <div id="map" style="width: 550px; height: 450px"></div>
        </td>
        <td width = 150 valign="top" style="text-decoration: underline; color: #4444ff;">
           <div id="side_bar"></div>
        </td>
      </tr>

    </table>
    <script type="text/javascript">
    //<![CDATA[

    if (GBrowserIsCompatible()) {
                
      // this variable will collect the html which will eventually be placed
      // in the side_bar
      var side_bar_html = "";
    
      // arrays to hold copies of the markers and html used by the side_bar
      // because the function closure trick doesnt work there
      var gmarkers = [];
      var i = 0;

      var lastlinkid;

      // A function to create the marker and set up the event window
      function createMarker(point,name,html) {
        var marker = new GMarker(point);
        var linkid = "link"+i;
        GEvent.addListener(marker, "click", function() {
          marker.openInfoWindowHtml(html);
          document.getElementById(linkid).style.background="#ffff00";
          lastlinkid=linkid;
        });
        // save the info we need to use later for the side_bar
        gmarkers[i] = marker;
        // add a line to the side_bar html
        side_bar_html += '<div id="'+linkid+'">
                         <a href="javascript:Linkclicked(' + i + ')">'
           + name + '</a><br></div>';
        i++;
        return marker;
      }

      // This function picks up the click and opens the corresponding info window
      function Linkclicked(i) {
        GEvent.trigger(gmarkers[i], "click");
      }

      // create the map
      var map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      map.setCenter(new GLatLng( 43.907787,-79.359741), 8);
      var mm = new GMarkerManager(map);
      
      // add the points    
      var point = new GLatLng(43.65654,-79.90138);
      var marker = createMarker(point,"This place","This is The First Info")

      var point = new GLatLng(43.91892,-78.89231);
      var marker = createMarker(point,"That place","This is The Second Info")

      var point = new GLatLng(43.82589,-78.89231);
      var marker = createMarker(point,"The other place","This is The Third Info")
                       
      GEvent.addListener(map,"infowindowclose", function() {
        document.getElementById(lastlinkid).style.background="#ffffff";
      });

        mm.addMarkers(gmarkers,0,17);
        mm.refresh();
                       
      // put the assembled side_bar_html contents into the side_bar div
      document.getElementById("side_bar").innerHTML = side_bar_html;      
    }

    else {
      alert("Sorry, the Google Maps API is not compatible with this browser");
    }
    
    //]]>
    </script>
  </body>

</html>

Here, I have placed one marker manager and an array. I have put all the markers to the markermanager so that it can be refreshed, deleted, or added later. The links are created using the array and is properly mapped with correct marker. Check out the link:

Use_of_Google_Map/markermanager.jpg

Example 8: Drawing Custom Markers

It is a common problem of making background color of a info window to be changed to a custom color. General sense, you can make the background of one div to a color, but it will not change the extreme boundaries of the info window. So I have extended Tom Morgans Marker to create a marker that looks entirely different from the markers in common. Take a look at the example:

Use_of_Google_Map/ex7.jpg

To use Tom Morgans Marker, just download this JavaScript from here: Click here.

Here is the code below:

JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Google Maps</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
        key=ABQIAAAAclK0B2lXQwV5lPy1rLiTFBSN1aiKepvDswXjKa4j2DDWdYvOjhQMO1tywqS
        8ObgP5dtO70AyyArhzA" type="text/javascript"></script>
    <script src="tlabel.2.05.js" type="text/javascript"></script>
  </head>
  <body onunload="GUnload()">

    <div id="map" style="width: 550px; height: 450px"></div>

    <script type="text/javascript">
    //<![CDATA[

    if (GBrowserIsCompatible()) {
        var openbubble=true;
        var agent = navigator.userAgent.toLowerCase();
    // For IE We need to Do this
        if ((agent.indexOf("msie") > -1) && (agent.indexOf("opera") < 1)){
        var loader = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(
            src='gmarker.png', sizingMethod='crop');";
        icon = '<div  style="height:34px; width:20px; ' +loader+ '" ></div>'
      }  

      var n=0;
        function createTLabel(point,html) {
        var label = new TLabel();
         label.id = 'Label '+n;
         label.anchorLatLng = point;
         label.anchorPoint = 'bottomCenter';
         label.content = html;
         label.markerOffset = new GSize(-1,-5);
         map.addTLabel(label);
         var obj=document.getElementById(label.id);
         GEvent.addDomListener(obj, "click", function() {
                //map.openInfoWindowHtml(point, html, {pixelOffset: new GSize(0,-34)} );
         });         

         n++;
      }
      
      var map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      map.setCenter(new GLatLng(43.907787,-79.359741),8);
      // Creating the HTML to show markers
      var hContent = '<div style="padding: 0px 0px 13px 0px; background: url(
          images/pt_bot_ctr_ora.png) no-repeat bottom center;">
          <div style="text-align: center; background-color: #f2c30c; padding: 2px;
           font-size: 0.75em; font-weight: bold;" onclick="openInfo(\'hInfo\')">MyInfo
           </div>';
      hContent+='<div id="hInfo" style="position: absolute; display: none;">';
      hContent+='<div style="width: 81px; background-color: #000; padding: 3px;
           font-size: 0.75em; color: #fff; text-align: left; border: 1px solid #f2c30c;">
           This is my content</div>';
      hContent+='</div></div>';
      createTLabel(new GLatLng(43.65654,-79.90138),hContent);
    }
   
    else {
      alert("Sorry, the Google Maps API is not compatible with this browser");
    }
    function openInfo(d)
    {
        var obj = document.getElementById(d);
        if(openbubble==true)
        {
            obj.style.display="block";
            openbubble=false;
        }
        else
        {
            obj.style.display="none";
            openbubble=true;
        }
    }
    //]]>
    </script>
  </body>

</html>

You can use Gmarker array to store the labels for future reference, and also you can add one event to the map so that each open marker hides through a loop.

Example 9: Invoke AJAX from GMAP & GPolygon

In this example, I am giving you a brief Idea of XMLhttpRequest and Drawing GPolygons.

First of all, look at the example and code below. I am explaining them after that.

JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Polygon Demo</title>

    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;
    key=ABQIAAAAclK0B2lXQwV5lPy1rL"
        type="text/javascript"></script>

    <script type="text/javascript">
    
    var map = null;
    var polys = [];
    var labels = [];
    var xmlDoc=null;
      
    function load() 
    {
          if (GBrowserIsCompatible()) 
          {
            var point;
            map = new GMap2(document.getElementById("map"));
            map.addControl(new GLargeMapControl());
            map.addControl(new GMapTypeControl());
            map.setCenter(new GLatLng(42.16,-100.72),4);         
    
        // Read the data from states.xml
          
          var request = GXmlHttp.create();
          request.open("GET", "states.xml", true);
          request.onreadystatechange = function() 
          {
            if (request.readyState == 4) 
            {
              xmlDoc = GXml.parse(request.responseText);
              
            
              var states = xmlDoc.documentElement.getElementsByTagName("state");

              // read each line
              for (var a = 0; a < states.length; a++) 
              {
                // get any state attributes
                var label  = states[a].getAttribute("name");
                var colour = states[a].getAttribute("colour");
                // read each point on that line
                var points = states[a].getElementsByTagName("point");
                var stateoptions = document.getElementById("xmlStates");
                var optn = document.createElement("OPTION");
                optn.text = states[a].getAttribute("name");
                optn.value = states[a].getAttribute("name");
                stateoptions.options.add(optn);
              }
            }
          }
          request.send(null);
         }
         else {
          alert("Sorry, the Google Maps API is not compatible with this browser");
        }
    }
    function loadselectedpoint()
    {
            if(xmlDoc==null){alert('null');return;}
              var state = document.getElementById("xmlStates").value;
              var states = xmlDoc.documentElement.getElementsByTagName("state");

              for (var a = 0; a < states.length; a++) 
              {
                
                var label  = states[a].getAttribute("name");
                var colour = states[a].getAttribute("colour");
                var points = states[a].getElementsByTagName("point");
                if(states[a].getAttribute("name")==state)
                {
                
                 var pts = [];
                  for (var i = 0; i < points.length; i++) 
                  {
                     pts[i] = new GLatLng(parseFloat(points[i].getAttribute("lat")),
                                          parseFloat(points[i].getAttribute("lng")));
                  }
                  var poly = 
            new GPolygon(pts,"#000000",1,1,colour,0.5,{clickable:true});
        GEvent.addListener(poly,'click',function(point)
        {
        map.openInfoWindowHtml(point, "Polygon is clicked!!")
        });
                  polys.push(poly);
                  map.clearOverlays();
                  map.addOverlay(poly);
                 }
              }             
            }        
   
    //]]>
    </script>

</head>
<body onload="load();" onunload="GUnload()" style="background-color: Transparent">
    States :  
    <select id="xmlStates" onchange="loadselectedpoint()">
    </select>
    <br /><br />
    <div id="map" style="width: 900px; height: 500px">
    </div>
</body>
</html>

In the above code, I have made one Select box, where all the States load, upon selecting one state, it will display the entire boundary of the state. Please take a look at the demo below:

Use_of_Google_Map/gpoly.jpg

In the example above, I have used two new classes:

  1. GXmlHttp: This class is the primary AJAX calling class which creates an XMLHttpRequest Object and places Asynchronous server calls. I have used this class to load the points from an external XML File which is asynchronously called and downloaded from the server. I have used this file to load the markings and also to load the Select Control. The OnReadyStateChanged is an event for any XMLHttpRequest object that is triggered when state is changed to the object. The Readystate evaluates to 4 when the last call made is successful, and the response is transmitted to the responseText property.
  2. GXml: It's a class provided by Google that enables you to parse XML in your application. I have used this class to manage the XML data that comes through AJAX calls.
  3. GPolygon: This class is used to make an overlay to the map. The constructor takes 7 arguments. The first argument is for an array of points, which are the GLatlng combinations. The second argument is the Color for Boundaries, third for weight of border, fourth is color of border, fifth is the opacity of the border, sixth is fill color, and seventh is the opacity of the fill color. You can also produce click event for the Polygon.

Example 10: StreetView with Maximize & Close Buttons

Recently, a new addition is made to Google map which allows us to view the actual street view of the Road. This is really interesting. It was there for quite a few months in maps.google.com and finally it has been released to the API.

To invoke streetview in the map, we need to create an object of GStreetViewPanorama. The streetview loads the map in a flash object, so it is highly recommended to install the latest version of flash player before you try out StreetView. Here is the code below:

JavaScript
var street;
function initialize() {
  var position = new GLatLng(42.345573,-71.098326);
  var opt = { latlng:position,enableFullScreen: true };
  street = new GStreetviewPanorama(document.getElementById("divp"), opt);
  GEvent.addListener(divp, "error", handleNoFlash);
}
    
    function handleNoFlash(errorCode) {
      if (errorCode == FLASH_UNAVAILABLE) {
        alert("Error: Flash doesn't appear to be supported by your browser");
      else if (errorCode == NO_NEARBY_PANO) {
                alert("Error : StreetView is Unavailable for current location");
        }
      return;
      }
    }

In the code, we create an object of GStreetViewPanorama by passing an object of div container where the panorama will be loaded. We pass Lat/Lon as option. enableFullScreen determines whether to show the maximise button to the panorama.

Use_of_Google_Map/pano1.JPG

If you click on link in the marker window, it will open the Streetview which looks like:

Use_of_Google_Map/pano2.JPG

If you click on the above pictures, you can see the online demonstration of the feature. Just go to View-Source to find out the entire source code or you may download the source added with this article as well.

Here, I have placed a marker with a link to show the StreetView of a selected point. You might also use the right-click context menu to show the StreetViewPanorama of any point over the map.

Note: StreetViewPanorama will not load if the point is not over a Road where PANO data is available. You might use:

JavaScript
var gstclient = new GStreetviewClient();
gstClient.getNearestPanoramaLatLng(new GLatLong(px,py), panoCallback));

function panoCallback(point){
        //show panorama here.
} 

Thus, you can make use of panoCallback which receives the nearest GLatLong point from the point passed in.

Frequently Asked Questions

Guys, first of all, I must thank you all for making this article a huge success. I got lots of mail from you everyday and love to answer them. I found some questions that are being asked to me very often. I want to discuss them with you so that I would have to answer less to your queries.

1. Where Do I Find XML File to Draw Polygons in Example 9?

Answer: Actually, the XML file is called using AJAX XMLHttpRequest Object to the server. I have uploaded the file to my website. Please take a look at:

The data is taken from Census Bureau Data of US. If you need current data, you need to login here and get the recent changes (of course if Govt officially modifies their site with recent changes).

2. How to Get Territory based on US Zip Codes?

Answer: US Zip Code data is also available from various sources. I have made a database on Census Data based on Zip location so that one can easily use that data to create custom boundary from the Example 9 I gave you.

3. How to Measure Distance Between 2 Geo Points?

Answer: To determine the distance between 2 geo points, you can use two approaches.

The first one is to get Actual Distance Between 2 geo points which could be calculated using Great Circle Formula. I have created one SQL server Function which will give you some idea on how to calculate this:

SQL
CREATE FUNCTION [dbo].[GETDISTANCE]
(
	@FIRSTLAT DECIMAL(17,7),
	@FIRSTLON DECIMAL(17,7),
	@SECONDLAT DECIMAL(17,7),
	@SECONDLON DECIMAL(17,7)
)  
RETURNS varchar(100) AS 

-- =============================================================================
-- Author:		<Author, Abhishek Sur, Codeproject.COM.>
-- Create date:		<Create Date,03/24/2008>
-- Description:		<Description,Returns Distance between two GEO Points 
--                             on Great Circle>
-- =============================================================================

BEGIN 
DECLARE
	@LONDIFF float,@a Bigint,@b float,@f float,@U1 float,@U2 float,@sinU1 float,
       @cosU1 float,@sinU2 float,@cosU2 float,@lambda float,
	@lambdaP float,@iterLimit Int,@sinLambda float,@cosLambda float,
	@sinSigma float,@cosSigma float,@sigma float,@alpha float,
	@cosSqAlpha float,@cos2SigmaM float,@C float,@uSq float,@CAPA float,
	@CAPB float,@deltaSigma float,@s float

if(abs(@FIRSTLAT) > 90 or abs(@FIRSTLON) > 180 or abs(@SECONDLAT) >90 or 
     abs(@SECONDLON) > 180)
	return 'Not Valid Data'
if(@FIRSTLAT = @SECONDLAT and @FIRSTLON = @SECONDLON)
	return '0 m'

-- CONVERT TO RADIAN
set @FIRSTLAT = (@FIRSTLAT * 3.14159265358979)/180
set @FIRSTLON = (@FIRSTLON * 3.14159265358979)/180
set @SECONDLAT = (@SECONDLAT * 3.14159265358979)/180
set @SECONDLON = (@SECONDLON * 3.14159265358979)/180

set @LONDIFF = @SECONDLON - @FIRSTLON

set @a = 6378137
set @b = 6356752.3142
set @f = 1/298.257223563

SET @U1 = atan((1-@f) * tan(@FIRSTLAT))
SET @U2 = atan((1-@f) * tan(@SECONDLAT))
SET @sinU1 = sin(@U1)
SET @cosU1 = cos(@U1)
SET @sinU2 = sin(@U2)
SET @cosU2 = cos(@U2)
SET @lambda = @LONDIFF
SET @lambdaP = 2 * PI()
SET @iterLimit = 20

while (abs(@lambda-@lambdaP) > 1.0E and @iterLimit > 0) 
Begin
	SET @iterLimit=@iterLimit-1
	SET @sinLambda = sin(@lambda)
	SET @cosLambda = cos(@lambda)
  	SET @sinSigma = sqrt((@cosU2 * @sinLambda) * (@cosU2*@sinLambda) + 
  (@cosU1*@sinU2-@sinU1*@cosU2*@cosLambda) * (@cosU1*@sinU2-@sinU1*@cosU2*@cosLambda))
  	SET @cosSigma = @sinU1*@sinU2 + @cosU1*@cosU2*@cosLambda
	SET @sigma = atan(@sinSigma/@cosSigma)
  	SET @alpha = asin(@cosU1 * @cosU2 * @sinLambda / @sinSigma)
	SET @cosSqAlpha = cos(@alpha) * cos(@alpha)
	SET @cos2SigmaM = @cosSigma - 2*@sinU1*@sinU2/@cosSqAlpha
	SET @C = @f/16*@cosSqAlpha*(4+@f*(4-3*@cosSqAlpha))
	SET @lambdaP = @lambda
	SET @lambda = @LONDIFF + (1-@C) * @f * sin(@alpha) * 
  (@sigma + @C * @sinSigma * (@cos2SigmaM+ @C* @cosSigma*(-1+2*@cos2SigmaM*@cos2SigmaM)))
 END

if (@iterLimit=0) 
	return 'Not Valid Data' -- formula failed to converge

 SET @uSq = @cosSqAlpha*(@a*@a-@b*@b)/(@b*@b)
 SET @CAPA = 1 + @uSq/16384*(4096+@uSq*(-768+@uSq*(320-175*@uSq)))
 SET @CAPB = @uSq/1024 * (256+@uSq*(-128+@uSq*(74-47*@uSq)))
 SET @deltaSigma = @CAPB*@sinSigma*(@cos2SigmaM+@CAPB/4*(@cosSigma*
   (-1+2*@cos2SigmaM*@cos2SigmaM) - @CAPB/6*@cos2SigmaM*
    (-3+4*@sinSigma*@sinSigma)*(-3+4*@cos2SigmaM*@cos2SigmaM)))
 SET @s = @b*@CAPA*(@sigma-@deltaSigma)
 
declare @dist float
declare @retval float

  SET @dist = @s / 1000;
  if (@dist < 1) 
  begin
	
	set @retval = round(1000 * @dist,3)
	--set @retval = @retval * 1.0936133
	return Convert(varchar,(@retval)) + ' Metres'  
  end
  else
  begin
	set @retval = round(1000 * @dist,3)/1000
	set @retval = round(@retval * 0.621371192,3)
	return CAST(@retval as varchar(12)) + ' Miles'
  End
return '0 m'
End

You can also use client end JavaScript to do this. Just get the logic from here. For formula reference, you can follow this link.

Secondly, you can use GDirection functionality to get the actual walking distance between the two points:

JavaScript
var fromAddress = 'San Francisco';
var toAddress = 'Mountain View';
var gdir = new GDirections(map, document.getElementById("directions"));
GEvent.addListener(gdir, "load", onGDirectionsLoad);
GEvent.addListener(gdir, "error", handleErrors);

gdir.load("from: " + fromAddress + " to: " + toAddress,
                { "locale": "en-US" });

function handleErrors(){
   if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
     alert("Geo Address Not Found.\nError code: " + gdir.getStatus().code);
   else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
     alert("Server Error occurred.\n Error code: " + gdir.getStatus().code);
   else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
     alert("Missing Query.\n Error code: " + gdir.getStatus().code);
   else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)  
    alert("Address Unavailable.\n Error code: " + gdir.getStatus().code);
   else if (gdir.getStatus().code == G_GEO_BAD_KEY)
     alert("Api Key not supported. \n Error code: " + gdir.getStatus().code);
   else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
     alert("Bad Request.\n Error code: " + gdir.getStatus().code);
   else alert("An unknown error occurred.");
}

function onGDirectionsLoad(){ 
document.getElementById("getStatus").innerHTML = gdir.getStatus().code;
}

You use either one of them based on your requirement.

4. How Can I Change Marker Icon in the Map?

Answer: Are you bored of the same Red Marker Icon? If so, you can change the Icon of the marker using GIcon.

JavaScript
var new_icon = new GIcon();
new_icon.image = "http://yourserver.com/images/cross.png";
new_icon.size = new GSize(16,16);
new_icon.iconAnchor = new GPoint(8,9); 
new_icon.infoWindowAnchor = new GPoint(7,7);
marker = new GMarker(point,{Icon:new_icon,draggable:false});
map.addOverlay( new_marker );

The Icon will be changed. You can also use marker.setImage(http://yourserver.com/images/cross.png') function to change the image of the marker icon.

But note that setImage will not update the Shadow property of GIcon.

5. How Can I Overlay an Image in a Map?

Answer: Obviously, there is an option to generate maps with your custom overlay image. Let us see the example:

JavaScript
function initialize() {
  if (GBrowserIsCompatible()) {
      var map = new GMap2(document.getElementById("map_canvas"));
        map.setCenter(new GLatLng(40.740, -74.18), 12);
    // ground overlay
   var boundaries = new GLatLngBounds(new GLatLng(40.716216,-74.213393), 
                                      new GLatLng(40.765641,-74.139235));
        var oldmap = new GGroundOverlay("http://imageserv.com/myimage.jpg", boundaries);
        map.setUIToDefault();
        map.addOverlay(oldmap);
      }
    }

This will overlay the image on the boundaries provided.

6. Can I Use US Zip Code to Draw Custom Polygons?

Answer: I have shown you how to draw custom polygon shapes based on data using AJAX. You can easily find database which provides information on US zip codes and draw shapes on the map. I have uploaded an SQL server Database backup. You can find that here.

Download the file. Unzip it and restore to SQL Server. You will find the data in a table called USZIPINFO. The schema of the table is:

<code>[countrycode], [postalcode],[placename],[state], [county],[community],[latitude], [longitude]<br>
[accuracy]

You can use this database to get the US Zip information country wise.

7. What are the Limitations of the Use of Google Map in Commercial Sites?

Answer: As far as I know, Google Maps is a free service and you can use it freely in your commercial web sites, provided the map should be available freely from anywhere. By this word, I mean the map should instantly appear from your site by just pasting the proper link to the address bar. The Map should not be hidden behind a login to your website authentication. If you are doing something other than that, you can use Google Custom Enterprize map.

Points to Remember

The points that you should always remember:

  1. If you have found a message like "API key is not correctly registered for that site," you should change the key element of the JavaScript tag to a valid key. You could get the key from this page.
  2. Never use Google maps for showing illegal content. This may be violation to rights.
  3. For enterprise solutions, there may be a situation where you have to secure the map behind login. In that case, you should pay Google for enterprise gmap control.

History

It was really a fun creating map examples for all of you. I tried to put most of the basics in this article but there is a lot more to go. You can just copy and place code to a Notepad, generate your API key, replace it in your JavaScript, and get your application to run.

Second Version: In this update, I have added another feature to show custom context menu. Just check the last example for that.

Third Version: 27nd September, 2009: After getting tons of mails to my mailbox, I added one FAQ section to describe the question that is asked the most.

Latest Version: 2nd December, 2009: Street View panorama example added.

References

For further reading, you might start from:

Thank you for reading about my application.

License

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


Written By
President
India India
Did you like his post?

Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.

Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook

Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.

Working as a VP product of APPSeCONNECT, an integration platform of future, he does all sort of innovation around the product.

Have any problem? Write to him in his Forum.

You can also mail him directly to abhi2434@yahoo.com

Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com

Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing

Comments and Discussions

 
GeneralMy vote of 5 Pin
sujikumar26-Sep-10 20:28
sujikumar26-Sep-10 20:28 
GeneralMy vote of 5 Pin
P. Madhu Sudhan Reddy16-Sep-10 3:25
P. Madhu Sudhan Reddy16-Sep-10 3:25 
GeneralMy vote of 5 Pin
Dalek Dave6-Aug-10 0:21
professionalDalek Dave6-Aug-10 0:21 
GeneralMy vote of 5 Pin
rcdc6927-Jul-10 0:27
rcdc6927-Jul-10 0:27 
GeneralExcellent Work Pin
PsychoQuilla6-Jul-10 5:09
PsychoQuilla6-Jul-10 5:09 
GeneralRe: Excellent Work Pin
Abhishek Sur6-Jul-10 22:06
professionalAbhishek Sur6-Jul-10 22:06 
GeneralRe: Excellent Work Pin
PsychoQuilla7-Jul-10 4:34
PsychoQuilla7-Jul-10 4:34 
GeneralHi, I've used this code. Its running. In Example1 You have used imge (myimage.gif). How to create this image. I want.. Pls help Pin
Sripriya Balakrishnan23-May-10 22:11
Sripriya Balakrishnan23-May-10 22:11 
function load()
{
if (GBrowserIsCompatible()) {
var point;
var map=new GMap2(document.getElementById("map"));
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
map.enableScrollWheelZoom();
map.addControl(new GMapTypeControl());
map.addControl(new GSmallMapControl());
var address='<img src="myimage.gif" width=150 height=40/><br/>' +
'<font size="2" face="Arial"><b>INDIA</b><br/><br/>Home.<br/>' +
'New York City<br/><br/>America<br/>Ph.: 23743823</font>';
var marker = new GMarker(point);
map.setCenter(point,17);
map.addOverlay(marker);
map.setMapType(G_HYBRID_MAP);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml(address);});
marker.openInfoWindowHtml(address);

}
}

thanks
Generalasp.net and google map store location Pin
Mary Jane Rutkowski22-Mar-10 10:08
Mary Jane Rutkowski22-Mar-10 10:08 
GeneralEXAMPLE 7 : MarkerManager and Sidebar Pin
abu sabha28-Jan-10 0:07
abu sabha28-Jan-10 0:07 
GeneralRe: EXAMPLE 7 : MarkerManager and Sidebar Pin
Abhishek Sur28-Jan-10 22:24
professionalAbhishek Sur28-Jan-10 22:24 
GeneralUnable to load map. JScript error Pin
nainakarri27-Jan-10 21:54
nainakarri27-Jan-10 21:54 
GeneralRe: Unable to load map. JScript error Pin
Abhishek Sur28-Jan-10 22:10
professionalAbhishek Sur28-Jan-10 22:10 
GeneralRe: Unable to load map. JScript error Pin
nainakarri2-Feb-10 19:15
nainakarri2-Feb-10 19:15 
GeneralNice to see Pin
thatraja15-Jan-10 21:51
professionalthatraja15-Jan-10 21:51 
GeneralRe: Nice to see Pin
Abhishek Sur28-Jan-10 22:06
professionalAbhishek Sur28-Jan-10 22:06 
Generaldatabase Pin
abu sabha6-Jan-10 5:49
abu sabha6-Jan-10 5:49 
GeneralRe: database Pin
Abhishek Sur6-Jan-10 21:16
professionalAbhishek Sur6-Jan-10 21:16 
GeneralRe: database Pin
abu sabha7-Jan-10 3:07
abu sabha7-Jan-10 3:07 
GeneralPracticality Pin
gstolarov5-Dec-09 6:21
gstolarov5-Dec-09 6:21 
GeneralRe: Practicality Pin
Abhishek Sur6-Dec-09 21:04
professionalAbhishek Sur6-Dec-09 21:04 
QuestionHow to move the marker? Pin
boris-chan1-Dec-09 14:48
boris-chan1-Dec-09 14:48 
AnswerRe: How to move the marker? Pin
Abhishek Sur1-Dec-09 20:55
professionalAbhishek Sur1-Dec-09 20:55 
GeneralGPS Coordinate system Pin
John Underwood31-Oct-09 14:13
John Underwood31-Oct-09 14:13 
GeneralRe: GPS Coordinate system Pin
Abhishek Sur4-Nov-09 21:53
professionalAbhishek Sur4-Nov-09 21:53 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.