dominoGuru.com
Your Development & Design Resource
The worst [but easiest] way to integrate Google Maps in your IBM Lotus Notes Domino XPage-based applications...
02/17/2011 09:49 PM by Chris Toohey
While certainly not a Best Practice, here is a technique that people unfamiliar with JavaScript and possibly scared-off by the Google Maps API can employ to embed a NotesDocument-context based Google Map Widget in their XPages apps.
This technique was used for a simple XPages-based Web Browser and Lotus Notes Client dashboard for a Mobile Device-friendly Personal Address Book Request Proxy... which was the demo application I built for my recent GBS Group Talk webinar, "Mobilize Your Apps with XPages".
To start, I'll show you the end-result:
Simple, and this map uses the address data from the XPage NotesDocument Data Source which surfaces the given Person NotesDocument.
Instead of deep-diving into the Google Maps API -- which is easy enough and certainly more powerful than the technique I'm about to show you... -- I went to Google Maps and looked up an example address (in this case, GBS US Corporate Headquarters): 140 Bluffs Parkway Canton GA 30114.
At the top-right of the Google Maps... map [?!], you'll see a Link button, which gives you cross-browser-friendly HTML markup:
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?f=q&source=s_q&hl=
en&geocode=&q=140+Bluffs+Parkway+
Canton+GA+30114&aq=0&sspn=0.011584,0.022724&ie=UTF8&
amp;hq=&hnear=140+Bluffs+Pkwy,+Canton,+Cherokee,+Georgia+30114
&t=h&view=map&z=14&ll=34.25752,-84.475041&am
p;output=embed"></iframe><br /><small><a
href="http://maps.google.com/maps?f=q&source=embed&h
l=en&geocode=&
q=140+Bluffs+Parkway+Canton+GA+30114&aq=0&sspn=0.011584,0.022724
&ie=UTF8&hq=&hnear=140+Bluffs+Pkwy,+Canton,+Cherokee,+Ge
orgia+
30114&t=h&view=map&z=14&ll=34.25752,-84.475041&q
uot; style="color:#0000FF;text-align:left">View
Larger Map</a></small>
The IFRAME gives us a static map, which we can easily embed in any website... but we want it to be dynamically driven from the Data Source NotesData on our XPage.
If you look at the above markup, you'll notice a mix of address with latitude & longitude coordinates... so the first thing we'll need to do is add the Google-hosted Google Maps API JavaScript Library as a CSJS Resource, which we'll use to geocode our NotesData:
<xp:script src="http://maps.google.com/maps/api/js?sensor=false"
span>
clientSide="true">
</xp:script>
Now we'll want to surface the address for use as both the address and for geocoding:
<xp:scriptBlock
id="scriptBlock3">
<xp:this.value><![CDATA[#{javascript:var address =
thisdoc.getItemValueString("officestreetaddress");
var address = address + " " +
thisdoc.getItemValueString("officecity");
var address = address + " " +
thisdoc.getItemValueString("officestate");
var address = address + " " +
thisdoc.getItemValueString("officezip");
return "var address = \"" + address +
"\"";}]]></xp:this.value>
</xp:scriptBlock>
Hacktastic, right?! But wait, there's more...
Let's include another CSJS Resource - this time, an in-NSF JavaScript Library Design Element named "GoogleMaps.js:
var newyork = "40.69847032728747,
-73.9514422416687"
function codeAddress(sAddress) {
var geocoder =
new google.maps.Geocoder();
geocoder.geocode( { 'address': sAddress}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
return results[0].geometry.location;
} else {
return newyork;
}
});
}
function writeMaps(sourceAddress) {
var cAddress =
codeAddress(sourceAddress);
document.write('<iframe width="100%"
height="350" frameborder="0" scrolling="no"
marginheight="0" marginwidth="0"
src="http://maps.google.com/maps?f=q&source=s_q&hl=en&a
mp;geocode=&q=' + sourceAddress + '&aq=0&sll='
+ cAddress + '&sspn=0.011584,0.022724&ie=UTF8&hq=&
;hnear=' + sourceAddress + '&t=h&z=4&ll=' + cAddress + '&output=embed"></iframe><br
/><small><a
href="http://maps.google.com/maps?f=q&source=embed&hl=en&am
p;amp;geocode=&q=' + sourceAddress
+ '&aq=0&sll=' +
cAddress + '&sspn=0.011584,0.022724&ie=UTF8&hq=&
;hnear=' + sourceAddress + '&t=h&z=4&ll=' + cAddress + '" style="color:#0000FF;text-align:left">View
Larger Map</a></small>');
}
Now, to use this, we'll need another scriptBlock Control on our XPage, where
we pass-thru the recently-surfaced address
JavaScript variable:
<xp:scriptBlock
id="scriptBlock4">
<xp:this.value><![CDATA[
if (address != "")
{
writeMaps(address);
}
]]></xp:this.value>
</xp:scriptBlock>
The result is our NotesDocument-context based Google Maps widget... all without needing to learn the Google Maps API.
... of course, you're really limited to what you can do with this outside of displaying the content within an IFRAME Element on your XPage - so I would absolutely recommend getting a jump on the Google Maps API, and it's one of those sexy things that can really make an app pop... which is what can often make your users excited about using your applications!
But I also posted this example to show you how you can easily surface things
like @IsNewDoc()
for CSJS [especially external use] demands:
<xp:scriptBlock
id="globalvariables">
<![CDATA[var isnewdoc = #{javascript:return
@IsNewDoc()};]]>
</xp:scriptBlock>
... as well as highlight a simple and often overlooked method for integrating with web services or other technologies that is often overlooked (or in a situation where said web service or technology doesn't provide an API). The IFRAME gets the job done here, and this technique - of course cleaned-up and extended - might just help you someday.
That, and I think it made for a really slick yet simple and quick demo:
The recorded webinar, slidedeck, and demo application - which is a hybrid remote content proxy for a Personal Address Book NotesDatabase which delivers customized UIs/UXs for the Notes Client and Web Browser, iPhone and iPad, Android and BlackBerry (both OS6 and a watered-down version of OS5 and lower) - should be posted online soon in case you didn't get to attend yesterday (or you did, and you want the code..).