Using Google Maps to Populate an Address in a SharePoint New Item Form

Originally posted on: http://geekswithblogs.net/SoYouKnow/archive/2011/04/20/using-google-maps-to-populate-an-address-in-a-sharepoint.aspx

Only a truly geeky developer can understand the concept that I’ve been working and writing so much code lately they I need to take a break by… well.. writing more code…

Anyway! My brain needed a break from my current assignments so I decided to tackle a question I saw posted about populating address fields in SharePoint with a click on a location from a map plugin. It seemed like a nice challenge and something I KNEW could be tackled as long as the proper map API existed… This turned out to be super simple when all was said and done…

By the way this works in both SharePoint 2010 and the SharePoint formerly known as MOSS.

Google Maps or Bing?

At first I needed to decide whether to use Google Maps or Bing Maps… I was really hoping to take advantage of Bing because, well.. you would think it would make more sense to have two Microsoft products working together. Unfortunately, I could not find any way to “Reverse Geocode” (basically get an address from a latitude and longitude) out of the box with Bing.  I’m assuming there’s an additional web service I could call to get an address from a Lat/Long, but I just wanted to get a proof of concept going and show it could be done. So, if you just HAVE to use Bing, you could, but you need to find a Web Service that will get the address for you.

Fortunately, Google Maps already has the functionality for Reverse Geocoding built in so I didn’t have to do any additional web service calls or research. I decided to go with that. Smile  I first looked at using V3 of Google Maps, but apparently it uses HTML 5 and we all know how well IE plays with HTML 5.  So, I dropped back down to V2. I imagine the code for V3 would be very similar.  I found 95% of what I needed in the Google Maps Documentation under the “Reverse Geocoding” section at: http://code.google.com/apis/maps/documentation/javascript/v2/services.html 

The Script

Under the aforementioned section is an example that uses Reverse Geocoding.. like I said.. this is 95% of what you need.  It looks like:

var map;
var geocoder;
var address;

function initialize() {
  map = new GMap2(document.getElementById("map_canvas"));
  map.setCenter(new GLatLng(40.730885,-73.997383), 15);
  map.addControl(new GLargeMapControl);
  GEvent.addListener(map, "click", getAddress);
  geocoder = new GClientGeocoder();
}

function getAddress(overlay, latlng) {
  if (latlng != null) {
    address = latlng;
    geocoder.getLocations(latlng, showAddress);
  }
}

function showAddress(response) {
  map.clearOverlays();
  if (!response || response.Status.code != 200) {
    alert("Status Code:" + response.Status.code);
  } else {
    place = response.Placemark[0];
    point = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
    marker = new GMarker(point);
    map.addOverlay(marker);
    marker.openInfoWindowHtml(
        '<b>orig latlng:</b>' + response.name + '<br/>' + 
        '<b>latlng:</b>' + place.Point.coordinates[1] + "," + place.Point.coordinates[0] + '<br>' +
        '<b>Status Code:</b>' + response.Status.code + '<br>' +
        '<b>Status Request:</b>' + response.Status.request + '<br>' +
        '<b>Address:</b>' + place.address + '<br>' +
        '<b>Accuracy:</b>' + place.AddressDetails.Accuracy + '<br>' +
        '<b>Country code:</b> ' + place.AddressDetails.Country.CountryNameCode);
  }
}

From looking at this example Script you can see under the “showAddress” function it is popping up a “marker” with the address (place.address).  We simply need to grab this address and push it to our SharePoint Form.  The address is in one long string “1234 Main St., Harrison, AR 72601, USA” so we will need to parse the string to break out each individual element.  For the purposes of this prototype I just did a split at the commas and spaces, this works a majority of the time for US addresses but no way in the world will it work for most countries or street addresses that may contain a comma.  So, again, this is not production quality code, you aren’t paying me for that. That quick and dirty code looks like:

var values = place.address.split(",");
var address = values[0];
var city = values[1];
var state = values[2].split(" ")[1];
var zip = values[2].split(" ")[2];
var country = values[3]

Now we need to stuff these values into our SharePoint form fields. jQuery makes this very easy.  You can set a SharePoint Form field on the New and Edit forms using the syntax “$(“input[title='<field name>’]”).val(<value>);”.  So the previous code becomes:

var values = place.address.split(",");
var address = values[0];
var city = values[1];
var state = values[2].split(" ")[1];
var zip = values[2].split(" ")[2];
var country = values[3]
        
$("input[title='Country']").val(country);    
$("input[title='Zip']").val(zip);    
$("input[title='State']").val(state);    
$("input[title='City']").val(city);    
$("input[title='Address']").val(address);    

This of course assumes your SharePoint List has the fields “Country”, “Zip”, “State”, “City”, and “Address”.  If not, change the script accordingly.  So, when we add our modifications to the example from Google we get (note that I removed the ‘pop-up’ marker that was there before, you can leave that in there if you want):

 var map;
    var geocoder;
    var address;
 
    function initialize() {
      map = new GMap2(document.getElementById("map_canvas"));
      map.setCenter(new GLatLng(40.730885,-73.997383), 15);
      map.setUIToDefault();
      GEvent.addListener(map, "click", getAddress);
      geocoder = new GClientGeocoder();
    }
    
    function getAddress(overlay, latlng) {
      if (latlng != null) {
        address = latlng;
        geocoder.getLocations(latlng, showAddress);
      }
    }
 
    function showAddress(response) {
      map.clearOverlays();
      if (!response || response.Status.code != 200) {
        alert("Status Code:" + response.Status.code);
      } else {
        place = response.Placemark[0];
        point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);
        marker = new GMarker(point);
        map.addOverlay(marker);
        
        var values = place.address.split(",");
        var address = values[0];
        var city = values[1];
        var state = values[2].split(" ")[1];
        var zip = values[2].split(" ")[2];
        var country = values[3]
        
        $("input[title='Country']").val(country);    
        $("input[title='Zip']").val(zip);    
        $("input[title='State']").val(state);    
        $("input[title='City']").val(city);    
        $("input[title='Address']").val(address);    
        
      }
    }

Okay.. that’s all fine and dandy, but we need to format this in such a way that we can drop it into a js file that we can easily use it in SharePoint by linking a CEWP to it. We also need to make sure to load the GoogleMaps library and jQuery. You will also need to request a Google Maps API Key from Google. It’s a completely painless process. So, when we do all that, our script becomes:

<script type="text/javascript" src=http://maps.google.com/maps?file=api&amp;v=2&amp;key=<GET YOUR OWN GOOGLE MAP KEY>></script>
<script type="text/javascript" src="../../scripts/jquery.min.js"></script>

<script type="text/javascript">

   var map;
    var geocoder;
    var address;
 
    function initialize() {
      map = new GMap2(document.getElementById("map_canvas"));
      map.setCenter(new GLatLng(40.730885,-73.997383), 15);
      map.setUIToDefault();
      GEvent.addListener(map, "click", getAddress);
      geocoder = new GClientGeocoder();
    }
    
    function getAddress(overlay, latlng) {
      if (latlng != null) {
        address = latlng;
        geocoder.getLocations(latlng, showAddress);
      }
    }
 
    function showAddress(response) {
      map.clearOverlays();
      if (!response || response.Status.code != 200) {
        alert("Status Code:" + response.Status.code);
      } else {
        place = response.Placemark[0];
        point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);
        marker = new GMarker(point);
        map.addOverlay(marker);
        
        var values = place.address.split(",");
        var address = values[0];
        var city = values[1];
        var state = values[2].split(" ")[1];
        var zip = values[2].split(" ")[2];
        var country = values[3]
        
        $("input[title='Country']").val(country);    
        $("input[title='Zip']").val(zip);    
        $("input[title='State']").val(state);    
        $("input[title='City']").val(city);    
        $("input[title='Address']").val(address);    
        
      }
    }
 

jQuery(document).ready(function($){
        initialize();
    });

</script>

 <div id="map_canvas" style="width: 500px; height: 400px"></div> 

Integrating Into SharePoint

Okay, now that the script is complete, we need to get it integrated in SharePoint and working on a SharePoint page that contains our NewForm (or EditForm) that we want to populate.  You will need to:

1) Upload the script above to a document library (along with jQuery.min if you haven’t done so already)

2) Create a new page and place a “New Item Form” or “Edit Item Form” for your list item on it (or use the default NewForm.aspx or EditForm.aspx)

3) Place a Content Editor Web Part (CEWP) on the page (you can get the default page into edit mode in SharePoint 2007 by appending “&ToolPaneView=2” in the url for the page.)

4) In the “Content Link” section of the Web Part Properties of the CEWP, put the path to your script from #1 above.

image image

SharePoint 2007

SharePoint 2010

5) That’s it! Your done! Save the page / stop editing / whatever…

Seriously? That’s it?

Yep.. that’s it… Now when you click on a location on the map, the corresponding fields should be populated with the address from the Google Map.  Click on OK to save your entry.

image

Again, you would need to tweak the script to make it work for ALL address types… but you can handle that can’t you?

Still don’t believe me? Well, you can try out a live demo thanks to the awesome Mack Sigman (@Mack_Sigman) who set up a site collection for me so I could show you guys this tip.

http://www.fedspug.org/sites/sphillbilly/SitePages/MapsExample.aspx

 

Okay.. You’re not impressed.. What’s next?

So… I decided to add another field to my Address list that stores the address unparsed. I then dropped a DVWP on the page that displays all the addresses and added a column that pushes this unparsed address back to the Google Maps API to display the location on the map. Feel free to play with that too.

<update>

Remember my mantra? Use the KISS principle… after getting  a decent nights rest I realized it made zero sense to store the unparsed address as separate field to push back to Google Maps for two big reasons:

1) If you manually enter an address there is no “unparsed” address to store.

2) It’s making a simple problem more difficult.

What I ended up doing was creating a new Calculated Column field that concatenates the address fields in the form and then that calculated field is what I push to Google Maps.  So, you Mavericks that are manually inputting an address and saying “haha.. it doesn’t work”.. well.. that works now…

So.. basically… you SHOULD be able to enter any address manually, save it, and then click the “View In Map” link to see it in the map.

I also added a button just above the Map… If you manually enter an address then click that button, the map should display that address (kind of a poor man’s address verification?). 

</update>

image

Hope you learned something, or at least weren’t completely bored… Thanks again for stopping by.

Families in Germany who are facing divers health problem, such persons can buy drugs from the Web without prescription. With the market flooded with divers web-sites selling sundry medicaments, purchasing medicines from th WEB is no longer a trouble for common man. Certain medications are used to treat infections caused by dental abscesses. Of course it isn’t all. If you’re concerned about erectile health problem, you probably know about Xenical and Hoodia. Probably every adult knows about Garcinia. (Read more PhentermineXenical). The symptoms of sexual health problems in men switch on impossibility to have an erection sufficient for sexual functioning. Certain medications may add to sex drive difficulties, so its substantial to cooperate with your soundness care professional so that the prescription can be tailored to your needs. Preparatory to taking Levitra or other preparation, speak to your dispenser if you have any allergies. Talk to your health care provider for more details. Preparatory to ordering this remedy, tell your doc if you are allergic to anything.