Geeks With Blogs

News





The SharePoint Hillbilly Fewer Big Words... More Pretty Pictures...

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.

Posted on Wednesday, April 20, 2011 3:30 PM | Back to top


Comments on this post: Using Google Maps to Populate an Address in a SharePoint New Item Form

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Love it, great idea and I can see where this can come in use. Thanks for sharing of what sounds like very limited spare time you have.

Rich
Left by Richard Weston on Apr 20, 2011 3:41 PM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Very cool stuff! Great work Mark and thanks for sharing this!
Left by Muhanad Omar on Apr 20, 2011 5:06 PM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Awesome trick! Thanks for posting this one Mark. And yes, I understand what it feels like to take a break from code ... by coding more. Good stuff. =)
Left by @SPJeff on Apr 20, 2011 10:19 PM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Mark,
I love that you've taken the google maps SharePoint maps combo into the new decade with the update to jQuery. I've been planning an update to my SharePoint Maps Series for a while, and the switch to jQuery is one piece I'll have a good head start on now with your great post!
Thanks,
Tom
Left by Tom Resing on Apr 23, 2011 12:58 PM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Thanks Tom! I wish I had seen you series before starting this.. I could have saved some time and made it even cooler! :)

http://blogs.microlinkllc.com/tresing/archive/2009/06/10/google-maps-and-virtual-earth-now-bing-maps-series-summary.aspx

I'll definitely be checking it out for more ideas... this stuff is kind of addicting when you get started. :)

Thanks again!
Mark
Left by Mark on Apr 23, 2011 1:12 PM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Mark,
You're welcome!
I think you'll find you can do what you want in Bing too after you look at it a little more. I have some bing examples up, but I know the original bing example on the SharePoint Designer Team Blog post did break on a bing maps api version change.
Glad to see another into Mapping Mashups in SharePoint.
Tom
Left by Tom Resing on Apr 23, 2011 1:38 PM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
How do you get this to work on a display form for a single address?

I don't want to click on the map and display the address, just dynamically display the address in the form.

I have a concatenated calculated column with all the info from the 5 separate fields.
Left by L01$Lan3 on Jun 10, 2011 9:30 AM

# re: Using Google Maps to Populate an Address in a SharePoint New Item Form
Requesting Gravatar...
Do you really believe Google would release a version that doesn't work on Internet Explorer? You must be kidding...
Oh well, anyway I was not able to get v3 to work either (but this has certainly more to do with SharePoint quirks than IE). I posted my question on SharePoint Overflow:
http://sharepoint.stackexchange.com/questions/14920/google-maps-v3-on-web-part-page
Left by Christophe on Jun 21, 2011 5:17 AM

# Google Maps v3 Working Example
Requesting Gravatar...
Mark,
I finally got around to digging in to this and decided I wanted a Google Maps v3 version of the code.
I've got a working example on my website that you can try your original and the updated v3 version on.
http://tomresing.com/examples/SitePages/Map%20Examples%20ReadMe.aspx
-Tom
Left by Tom Resing on Sep 04, 2011 2:33 PM

Your comment:
 (will show your gravatar)


Copyright © Mark Rackley | Powered by: GeeksWithBlogs.net