Tuesday, February 16, 2010

Add A Google Map To XPages

A snapshot of the Lotus XPage embedded Google Map

The goal of this XPage practice is to add a web search function for a traditional Lotus CRM database with a embedded Google Map view. A Google map with address markers will be displayed under based upon the customers search result .

This is the original view of the Notes database which I used for the data source, the database need to be fully indexed for search function to perform correctly -
 

This XPage named "search4" was created under the same database and the layout of this XPage includes three Panels - first is for the search bar, second is for the View control and the third is for the Google Map canvas.

First Panel has two components, one is the "Edie Box" for the search string, we need to bind it to the "View Scope" and name it "searchString".

The second component is the search Button which need to add a "Simple Action" under its onClick event, then choose "Open Page" as the function, the name of the Page should be "computed" -
"search4.xsp?search=" + viewScope.searchString


The View (data grid) for the search result is named "viewPanel1" (default), I selected the data source from Domino view "location"
add following content at "search" field which should be a server side JavaScript(compute dynamically) -
context.getUrlParameter("search");
The third Panel is the easiest one which you just need to give it a name for Google Map API can access it, we named it "map" (actually, it become "view:_id1:map" on web page).

Make "dojoParseOnLoad" on XPage property as "true" since we need to use dojoAddOnLoad to load our JavaScript codes after page loaded.

There is a JavaScript library (geo4.js) needed inside this database script library. The purpose of this library is to dynamically load the Google Javascript header after page load , and to execute the Google API for populating the address markers on the map. I use the the Google Maps API geocoding service via the GClientGeocoder object to decode the address and create marker. To make my life easier, I did some hacks to avoid the javascript variable conversion which I still have problem dealing with, I had to manually find out the name of the table and div on the web page I need and hard-code them on the geo4.js (red section).

Following is the JavaScript codes - geo4.js stored at script library.
var map;

function loadScript() {
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.src = "http://maps.google.com/maps?file=api&v=2.x&key=your_google_api_key&async=2&callback=loadMap";
  document.body.appendChild(script);
}
 
function loadMap() {
  map = new GMap2(document.getElementById("view:_id1:map"));
  map.setCenter(new GLatLng(38.4419, -102.1419), 4);
  map.setUIToDefault();
  mapMe();
  }
 
function mapMe() {
var tb=document.getElementById("view:_id1:viewPanel1");
var tr=tb.getElementsByTagName("tr");

for (i=1; i<tr.length; i++)
var td=tr[i].getElementsByTagName("td");

var sp=td[4].getElementsByTagName("span");
if (sp[0] != undefined)
showAddress(sp[0].firstChild.data, map);

  }
}
 
  function showAddress(address, m) {
      var geocoder = new GClientGeocoder();
      geocoder.getLatLng(
        address,
        function(point) {
          if (!point) {
           // alert(address + " not found");
          } else {
           
            var marker = new GMarker(point);
            m.addOverlay(marker);
                var html = address;
              GEvent.addListener(marker, "click", function() {
             marker.openInfoWindowHtml(html);
              })   
            //marker.openInfoWindowHtml(address);
          }
        }
      );
    }
   
  function showAddressInfo(address, m) {
      var geocoder = new GClientGeocoder();
      geocoder.getLatLng(
        address,
        function(point) {
          if (!point) {
           // alert(address + " not found");
          } else {
           
            var marker = new GMarker(point);
            m.addOverlay(marker);
                var html = address;
              GEvent.addListener(marker, "click", function() {
             marker.openInfoWindowHtml(html);
              })   
            marker.openInfoWindowHtml(address);
          }
        }
      )
    }
   
    dojo.addOnLoad(loadScript);

You can download the design template of this Notes database by clicking here

4 comments:

  1. hello,

    I trying this solution and i have a problem whe the points to piant are more than 10. any idea?

    thanks

    ReplyDelete
  2. You should be able to add more than 10 points into Google Map w/o any problem. Maybe Email me the codes to expcocoATgmail.com, I can take a look for you.

    Horace

    ReplyDelete
  3. Hello,

    is there any solution for the problem with displaying more then 10 points? I have the problem too.

    thanks

    ReplyDelete
  4. Hi

    I have tried implementing this as it is exactly what we need but No map is generated. I have the api key, but I think that the problem might be in the mapMe function. It maybe that the elements you are getting there are labelled differently on my page, I don't see yetwhat the code is trying to get? Sorry, fairly new at this, could you help enlighten me.

    Thanks

    Matt

    ReplyDelete