Creating SharePoint 2013 Geolocation field using Google Maps

SharePoint 2013 Preview introduces a new field type named Geolocation that enables you to annotate SharePoint lists with location information. In columns of type Geolocation, you can enter location information as a pair of latitude and longitude coordinates in decimal degrees, or retrieve the coordinates of the user’s current location from the browser if it implements the W3C Geolocation API. For more information about the Geolocation field, see Integrating location and map functionality in SharePoint 2013.

By default location is rendered using Bing Maps but it could be customized, for example by creating custom Geolocation field that renders Nokia Maps as described here.

What about another Map providers, let’s take a look on how to implement geolocation field that renders Google Maps.

First of all we need to create custom Geolocation field, for details  see How to: Create a custom Geolocation field that renders using Nokia Maps.
Here we will only  implement Geolocation field template for Google Maps, all the remaining steps the same as described in How to: Create a custom Geolocation field that renders using Nokia Maps. This is client side rendering template file that  JSLink method of the field class points to, for more information see  How to: Customize a field type using client-side rendering

Below is presented  GMapsGeolocatioFieldTemplate.js rendering template for Google Maps.

function $_global_googlemapscontrol() {
(function() {
if (typeof GMapsControlTemplate == "object") {
return;
}
window.GMapsControlTemplate = (function() {
return {
GMapsControl_Display: function(rCtx) {
if (rCtx == null || rCtx.CurrentFieldValue == null || rCtx.CurrentFieldValue == '')
return '';
var _myData = SPClientTemplates.Utility.GetFormContextForCurrentField(rCtx);
if (_myData == null || _myData.fieldSchema == null)
return '';
_myData.registerInitCallback(_myData.fieldName, InitControl);
var gMapRedirectControl;
var _inputId_gMapRedirectControl = _myData.fieldName + '_' +
_myData.fieldSchema.Id + '_$gMapField';
var fldvalue = GMapsControlTemplate.ParseGeolocationValue(rCtx.CurrentFieldValue);
var googleStaticMapUrl = GMapsControlTemplate.GetGoogleStaticMapUrl(fldvalue, 400, 300);
var result = '<div>';
result += GMapsControlTemplate.GetRenderableFieldValue(fldvalue);
result += '<BR />';
result += '<a id="' + STSHtmlEncode(_inputId_gMapRedirectControl) + '" href="javascript:">';
result += '<img src="' + googleStaticMapUrl + '" alt="Google Maps" />'
result += '</a>';
result += '</div>';
return result;
function RedirectToGMaps() {
var googleMapStaticUrl = document.getElementById(_inputId_gMapRedirectControl).childNodes[0].src;
window.open(googleMapStaticUrl);
}
function InitControl() {
gMapRedirectControl = document.getElementById(_inputId_gMapRedirectControl);
if (gMapRedirectControl != null)
AddEvtHandler(gMapRedirectControl, "onclick", RedirectToGMaps);
}
},
GetGoogleStaticMapUrl: function(fldvalue, width, height) {
var googleStaticMapUrl = 'http://maps.googleapis.com/maps/api/staticmap&#39;;
googleStaticMapUrl += '?center=' + fldvalue.latitude + ',' + fldvalue.longitude;
googleStaticMapUrl += '&zoom=11';
googleStaticMapUrl += '&size=' + width + 'x' + height;
googleStaticMapUrl += '&markers=color:blue%7Clabel:S%7C' + fldvalue.latitude + ',' + fldvalue.longitude;
googleStaticMapUrl += '&sensor=false';
return googleStaticMapUrl;
},
GetGoogleMapUrl: function (fldvalue) {
var googleMapUrl = 'https://maps.google.com/maps&#39;;
googleMapUrl += '?z=11';
googleMapUrl += '&t=m';
googleMapUrl += '&q=loc:' + fldvalue.latitude + '+' + fldvalue.longitude;
return googleMapUrl;
},
RedirectToGMaps: function(googleMapStaticUrl) {
var url = googleMapStaticUrl.replace("&nord", "");
window.open(url);
},
ParseGeolocationValue: function(fieldValue) {
var spatialtype = "POINT";
var space = ' ';
var openingBracket = '(';
var closingBracket = ')';
var point = new Object();
point.longitude = null;
point.latitude = null;
point.altitude = null;
point.measure = null;
if (fieldValue == null || fieldValue == '')
return null;
var valueIndex = 0;
var valueLength = fieldValue.length;
var subStr;
var argIndex = 0;
var index = fieldValue.indexOf(openingBracket, valueIndex);
if (index <= valueIndex) {
return null;
}
var headEnd = index;
if (fieldValue.charCodeAt(index 1) == space.charCodeAt(0)) {
headEnd;
}
subStr = fieldValue.substr(valueIndex, headEnd valueIndex);
if (spatialtype.toLowerCase() != subStr.toLowerCase()) {
return null;
}
valueIndex = index + 1;
while (valueIndex < valueLength) {
index = fieldValue.indexOf(space, valueIndex);
if (index <= valueIndex) {
index = fieldValue.indexOf(closingBracket, valueIndex);
}
if (index <= valueIndex) {
return null;
}
subStr = fieldValue.substr(valueIndex, index valueIndex);
if (argIndex == 0) {
point.longitude = parseFloat(subStr);
}
else if (argIndex == 1) {
point.latitude = parseFloat(subStr);
}
else if (argIndex == 2) {
point.altitude = parseFloat(subStr);
}
else if (argIndex == 3) {
point.measure = parseFloat(subStr);
}
argIndex++;
valueIndex = index + 1;
}
if (argIndex < 2) {
return null;
}
return point;
},
BuildGeolocationValue: function(latitude, longitude) {
var geolocationValue = 'Point (' + longitude + ' ' + latitude + ')';
return geolocationValue;
},
GetRenderableFieldValue: function(fieldValue) {
var fldValue = 'Longitude: ' + fieldValue.longitude + ', Latitude: ' + fieldValue.latitude;
return fldValue;
},
GMapsControl_Edit: function(rCtx) {
if (rCtx == null)
return '';
var _myData = SPClientTemplates.Utility.GetFormContextForCurrentField(rCtx);
if (_myData == null || _myData.fieldSchema == null)
return '';
downloadJS('http://maps.google.com/maps/api/js?sensor=false&callback=initialize&#39;);
_myData.registerInitCallback(_myData.fieldName, InitControl);
var fldvalue = GMapsControlTemplate.ParseGeolocationValue(rCtx.CurrentFieldValue);
var controlIdHeader = _myData.fieldName + '_' + _myData.fieldSchema.Id + '_$';
var mapDiv = '';
var searchControl;
var gMapField;
var _inputId_gMapField = controlIdHeader + 'gMapField';
var _inputId_locationDisplayControl = controlIdHeader + 'locationDisplayControl';
var _inputId_nativeGeolocationValue = controlIdHeader + 'nativeGeolocationValue';
var googleStaticMapUrl = '';
mapDiv += '<div>';
mapDiv += '<H3><label id="' + _inputId_locationDisplayControl + '">';
if (fldvalue != null) {
mapDiv += GMapsControlTemplate.GetRenderableFieldValue(fldvalue);
}
mapDiv += '</H3></label>';
mapDiv += '<label id="' + _inputId_nativeGeolocationValue
+ '" style="visibility: hidden;">';
if (fldvalue != null) {
mapDiv += 'Point(' + fldvalue.longitude + ' ' + fldvalue.latitude +')';
}
mapDiv += '</label>';
mapDiv += '<a id="' + STSHtmlEncode(_inputId_gMapField) + '" href="javascript:">';
mapDiv += '<img alt="Loading…" src="';
if (fldvalue != null) {
googleStaticMapUrl = GMapsControlTemplate.GetGoogleStaticMapUrl(fldvalue, 400, 300);
mapDiv += googleStaticMapUrl;
}
mapDiv += '" />';
mapDiv += '</a>';
mapDiv += '</div>';
var _inputId_address = controlIdHeader + "address";
var _inputId_searchButton = controlIdHeader + "searchButton";
var result = '<div id="mainDiv">';
result += '<div id="inputControls">';
result += '<div id="searchControls">';
result += '<table>';
result += '<tr>';
result += '<td width=100%>';
result += '<input type="text" id="' + _inputId_address + '" value="" style="width: 100%;"/>';
result += '</td>';
result += '<td style="width: 100%; text-align: right;">';
result += '<input type="button" id="' + _inputId_searchButton
+ '" value="Search" style="width: 70%;" />';
result += '</td>';
result += '</tr>';
result += '</table>';
result += '</div>';
result += '<div id="mapControls" width=50px />';
result += mapDiv;
result += '</div>';
result += '</div>';
function downloadJS(jsFile) {
var thescript = document.createElement('script');
thescript.setAttribute('type','text/javascript');
//thescript.setAttribute('charset','UTF-8');
thescript.setAttribute('src',jsFile);
document.getElementsByTagName('head')[0].appendChild(thescript);
}
function RedirectToGMaps() {
var googleMapStaticUrl = document.getElementById(_inputId_gMapField).childNodes[0].src;
window.open(googleMapStaticUrl);
}
function InitControl() {
gMapField = document.getElementById(_inputId_gMapField);
if (gMapField != null) {
AddEvtHandler(gMapField, "onclick", RedirectToGMaps);
var fldValue = document.getElementById(_inputId_nativeGeolocationValue).textContent;
if(typeof fldValue == "undefined" || fldValue == '')
{
gMapField.setAttribute('style', 'visibility: hidden;');
}
}
searchControl = document.getElementById(_inputId_searchButton);
if (searchControl != null)
AddEvtHandler(searchControl, "onclick", GeocodeAddress);
}
function GeocodeAddress() {
if (typeof google == "undefined" || typeof google.maps.Geocoder == "undefined")
{
alert('Google Maps not loaded completelly!');
return;
}
var addressControl = document.getElementById(_inputId_address);
if (addressControl == null)
return;
var address = addressControl.value;
geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
/*map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});*/
var point = new Object();
point.latitude = results[0].geometry.location.lat();
point.longitude = results[0].geometry.location.lng();
UpdateGeolocationValue(point.latitude, point.longitude);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function UpdateGeolocationValue(latitude, longitude) {
// Update native value.
document.getElementById(_inputId_nativeGeolocationValue).textContent =
GMapsControlTemplate.BuildGeolocationValue(latitude, longitude);
// Update display value.
var point = new Object();
point.latitude = latitude;
point.longitude = longitude;
document.getElementById(_inputId_locationDisplayControl).textContent =
GMapsControlTemplate.GetRenderableFieldValue(point);
// Update Map control.
var googleStaticMapUrl = GMapsControlTemplate.GetGoogleStaticMapUrl(point, 400, 400);
document.getElementById(_inputId_gMapField).childNodes[0].src
= googleStaticMapUrl;
gMapField.setAttribute('style', 'visibility: none;');
}
_myData.registerGetValueCallback(_myData.fieldName, function() {
var newValue = document.getElementById(_inputId_nativeGeolocationValue).textContent;
if(newValue == '')
return '';
var newFldValue = GMapsControlTemplate.ParseGeolocationValue(newValue);
return "Point(" + String(newFldValue.longitude) + " " + String(newFldValue.latitude) + ")";
});
return result;
},
GMapsControl_View: function(inCtx, field, listItem, listSchema) {
if (field.XSLRender == '1') {
return listItem[field.Name].toString();
}
else {
var fldvalue = GMapsControlTemplate.ParseGeolocationValue(listItem[field.Name]);
var ret = [];
if (fldvalue != null) {
ret.push("<a class=\"js-locationfield-callout\" href=\"javascript:void(0)\" liid=\"");
ret.push(GenerateIID(inCtx));
ret.push("\" fld=\"");
ret.push(field.Name);
ret.push("\" ><img title=\"");
ret.push(STSHtmlEncode(Strings.STS.L_Clippy_Tooltip));
ret.push("\"border=0 src=\"" + "/_layouts/15/images/callout-target.png");
ret.push("\"/></a>");
}
return ret.join('');
}
},
SetupMappyHoverHandlers: function(inCtx) {
EnsureScriptFunc("callout.js", "Callout", function() {
EnsureScriptFunc("core.js", "GetListItemByIID", function() {
EnsureScriptFunc("mquery.js", "m$", function() {
((m$('.js-locationfield-callout')).not(".js-locationfield-calloutInitialized")).forEach(function(e) {
var listItemID = e.getAttribute("liid");
var fieldName = e.getAttribute("fld");
var calloutTitle = '';
var calloutContent = [];
var listItem = GetListItemByIID(listItemID);
var values = GMapsControlTemplate.ParseGeolocationValue(listItem[fieldName]);
var width=300;
var googleMapStaticUrl = GMapsControlTemplate.GetGoogleStaticMapUrl
(values, width, 300);
calloutContent.push("<div><div class='ms-positionRelative' id='loc_mapcontainer_");
calloutContent.push(listItemID);
calloutContent.push("_");
calloutContent.push(fieldName);
//calloutContent.push("' ></div></div>");
calloutContent.push("' ></div>");
calloutContent.push("<div>");
calloutContent.push('<img src="' + googleMapStaticUrl + '" alt="Google Maps" />');
calloutContent.push("</div>");
calloutContent.push("</div>");
var callout = CalloutManager.createNew({
launchPoint: e,
openOptions: {
closeCalloutOnBlur: true,
event: "click",
showCloseButton: true
},
ID: listItemID + "_" + fieldName,
title: calloutTitle,
content: calloutContent.join(''),
contentWidth: width+40
});
callout.addAction(new CalloutAction({
text: "Browse on Google Maps",
onClickCallback: function () {
var googleMapUrl = GMapsControlTemplate.GetGoogleMapUrl(values);
GMapsControlTemplate.RedirectToGMaps(googleMapUrl);
}
}));
(m$(e)).addClass("js-locationfield-calloutInitialized");
});
});
});
});
},
GMapsControl_PreRender: function(inCtx) {
},
GMapsControl_PostRender: function(inCtx) {
if (ctx != null && ctx.BaseViewID != null && inCtx != null && inCtx.BaseViewID != null) {
if (inCtx.BaseViewID == ctx.BaseViewID) {
GMapsControlTemplate.SetupMappyHoverHandlers(inCtx);
}
}
}
};
})();
function _registerGMapsControlTemplate() {
var googleMapsControlContext = {};
googleMapsControlContext.Templates = {};
googleMapsControlContext.OnPreRender = GMapsControlTemplate.GMapsControl_PreRender;
googleMapsControlContext.OnPostRender = GMapsControlTemplate.GMapsControl_PostRender;
googleMapsControlContext.Templates.Fields = {
// Provide custom field name while registering .
'GMapFieldGeolocation': {
'View': GMapsControlTemplate.GMapsControl_View,
'DisplayForm': GMapsControlTemplate.GMapsControl_Display,
'EditForm': GMapsControlTemplate.GMapsControl_Edit,
'NewForm': GMapsControlTemplate.GMapsControl_Edit
}
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(googleMapsControlContext);
}
ExecuteOrDelayUntilScriptLoaded(_registerGMapsControlTemplate, 'clienttemplates.js');
})();
}
window.initialize = function () { }
$_global_googlemapscontrol();

SharePoint 2013 project with implementation of custom geolocation field that renders Google Maps may be found here.

Results

  • Creating Google Maps Geolocation column
  • List view with Google Maps Geolocation column
  • Create or edit form with Google Maps Geolocation column

For searching locations on Edit form is used Google Geocoding API.

References

7 thoughts on “Creating SharePoint 2013 Geolocation field using Google Maps

  1. I downloaded your .wsp, installed and deployed it successfully, but I cant find the GoogleMaps-Column anywhere on my farm. Where to find the column?

    • Hi Moritz,
      there are several ways on how to add custom Gelocation column that renders Google Maps
      a)create new List or Library, for example Custom List (View Site Contents add an app Custom List) and add new column to it (it is named Google Maps Geolocation column)
      b) use an existing List or Library, for example Documents library and add new column to it the same way as before
      c) add this column programmatically to new or existing library as described here http://msdn.microsoft.com/en-us/library/jj164050(v=office.15).aspx. For specified example use for field Type GMapFieldGeolocation instead of Geolocation.

      P.S. I will try to find out why it is not shown in Site Columns and let you know.
      Thanks on pointing on this issue!
      Vadim

  2. Pingback: Bringing Map functionality into SharePoint 2010: Rendering Map List View | vgrem's Blog

  3. Pingback: google maps geolocation - Search Yours

  4. Pingback: Working with Geo Location Fields in SharePoint 2013 | unnie ayilliath

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.