Google Maps Display Template – SharePoint 2013 – Part 2

As described in my previous post we will be creating a display template for Google maps. When you did not have the change to read part 1 you can do this by using the below link:

Google Maps Display Template – SharePoint 2013 – Part 1 

In part one we created the item display template and because we could not insert the JavaScript of adding markers to the map in the display template we have inserted the information in hidden inputs.

First of there is 1 important thing to notice. If you would like to use Google maps on you page you have to add a JavaScript file on you page. Within display control template you can use a specific method called “$includeScript();”. This method will include the script to the page for you. But there is a catch for as far as I could investigate if your JavaScript file doesn’t end  with “.js” it will not be included on the page. The Google maps API is a file that does not end with “.js”. The only option you have is to add the Google API file by using a script editor.

Embed Code Toolbar

Embed code

<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

In the control template we will begin by reading out that information and placing them on the map.

To get a new control template you will need to copy an existing control template, for this example we will create a copy of the “Control_List.html” and rename it to “Control_GoogleMaps.html”.

On each hidden input we have specified an id in order to retrieve the values, the id consist of a text value and the number of the result. In the Control Display Template we can retrieve the number of the result by using the “ctx” object and the property “CurrentItemIdx”. Each marker will become an Item in the “markers” array and will be a array itself. In the iteration we also construct the information window for each marker.

var markers = new Array();

for(var i=0;i<=ctx.CurrentItemIdx;i++){
    var inputValue = document.getElementById(i+'-Location').value
    var itemArray = inputValue.split(";");

     var contentString = '<div style="height:100px;" id="content">'+ 
     '<b>' + itemArray[0] + '</b>'+
     '<hr><div id="bodyDescription" style="margin-top:2px;">'+ itemArray[3] + '</div>' +
     '<div id="bodyAddress" style="margin-top:2px;">'+ itemArray[4] + '</div>' +
     '<a href="'+ itemArray[5] + '"><div style="font-weight:bold;margin-top:5px;">Office Information</div></a></div>';

     itemArray[3] = contentString;
     markers[i] = itemArray;             
}

When we have the information of the markers we can start by placing the markers on the map. For more information on how to use the Google Maps API go here.

var mapOptions = {
     zoom: 4,
     mapTypeId: google.maps.MapTypeId.HYBRID
}

var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var bounds = new google.maps.LatLngBounds();

var infowindow = new google.maps.InfoWindow(), marker, i;
for (i = 0; i < markers.length; i++) {  
    
    var title = markers[i][0];
    var latitude = markers[i][1];
    var longitude = markers[i][2];
    var pointLatlng = new google.maps.LatLng(latitude,longitude);
    bounds.extend(pointLatlng);
        
    marker = new google.maps.Marker({
                position: pointLatlng ,
                map: map,
                title:title,
                icon:'/PublishingImages/point.png'
    });
    
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        infowindow.setContent(markers[i][3]);
        infowindow.open(map, marker);
      }
    })(marker, i));
}

map.fitBounds(bounds);

By saving each point within a LatLngBounds object in the example above the bounds object we can specify on the map that it has to load all point within the first view by using the method “map.fitBounds(bounds)”. 

When tying this all together you will get a control display template like below:

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> 
<head>
<title>Google Maps</title>

<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:MasterPageDescription msdt:dt="string">This is the default Maps Display Template that will show a map with all of the items. For this map you should have managed properties with the longtitude and latitude of locations. Also make sure you reference the google map api: (https://maps.googleapis.com/maps/api/js?v=3.exp)</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106601</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>

<body>
    
    <script>
        $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
    </script>

    <div id="Control_List">
    <!--#_ 
    if (!$isNull(ctx.ClientControl) && !$isNull(ctx.ClientControl.shouldRenderControl) && !ctx.ClientControl.shouldRenderControl()){
        return "";
    }

    ctx.ListDataJSONGroupsKey = "ResultTables";
    var $noResults = Srch.ContentBySearch.getControlTemplateEncodedNoResultsMessage(ctx.ClientControl);
    var noResultsClassName = "ms-srch-result-noResults";
    _#-->
    
         _#= ctx.RenderGroups(ctx) =#_
        
    <!--#_

    function initialize() {

          var mapOptions = {
                zoom: 4,
              mapTypeId: google.maps.MapTypeId.HYBRID
          }

          var markers = new Array();
          var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
          var bounds = new google.maps.LatLngBounds();

          for(var i=0;i<=ctx.CurrentItemIdx;i++){
              var inputValue = document.getElementById(i+'-Location').value
              var itemArray = inputValue.split(";");

              var contentString = '<div style="height:100px;" id="content">'+ 
                 '<b>' + itemArray[0] + '</b>'+
                 '<hr><div id="bodyDescription" style="margin-top:2px;">'+ itemArray[3] + '</div>' +
                 '<div id="bodyAddress" style="margin-top:2px;">'+ itemArray[4] + '</div>' +
                 '<a href="'+ itemArray[5] + '"><div style="font-weight:bold;margin-top:5px;">Office Information</div></a></div>';

            itemArray[3] = contentString;
            markers[i] = itemArray;             
          }
    
          var infowindow = new google.maps.InfoWindow(), marker, i;
    
          for (i = 0; i < markers.length; i++) {  

               var title = markers[i][0];
               var latitude = markers[i][1];
               var longitude = markers[i][2];
               var pointLatlng = new google.maps.LatLng(latitude,longitude);
               bounds.extend(pointLatlng);
        
               marker = new google.maps.Marker({
                  position: pointLatlng ,
                  map: map,
                  title:title,
                  icon:'/PublishingImages/point.png'
               });
    
               google.maps.event.addListener(marker, 'click', (function(marker, i) {
                  return function() {
                     infowindow.setContent(markers[i][3]);
                     infowindow.open(map, marker);
               }
            })(marker, i));
        }
        map.fitBounds(bounds);
    }

    google.maps.event.addDomListener(window, 'load', initialize);
    _#-->

        <div id="map-canvas" style="height:500px;"></div>
    </div>
</body>
</html>

And finally when you place this all on a page it will look something like this:

Google Maps Display Template

Related Posts

Forcing a Device Channel Device channels are a way of using different master pages for different devices. MSDN describes the functionality as followed:   “Browsing ...
Offline Installation SharePoint 2013 In many situation you would like to do a offline installation of SharePoint 2013 or you are required to do a offline installation because you do not h...
Custom list view by using the “JS Link” property. Customizing a list view could be done by using XSLT in previous version of SharePoint. In SharePoint 2013 this van be done by using the “JS Link” func...
User automatically removed from SharePoint Group During my current project we received an access request from a user. We did what we normally do, we checked the request and added the user in the appr...
Unable to start User Profile Synchronization Service A few days ago I wrote a post about loading modules in PowerShell by default: “Load modules by default when opening PowerShell”. Today we had to setup...
Filtering SharePoint Search Results by Content Source Working for one my projects we were looking for a solution to only retrieve search results for a specific Content Source. In our scenario we had a Ext...

3 comments

  • Error Message in Content Search web part:

    Display Error: The display template had an error. You can correct it by fixing the template or by changing the display template used in either the Web Part properties or Result Types.

    containerId is not defined (CoreRender: ~sitecollection/_catalogs/masterpage/Display Templates/Content Web Parts/Item_GoogleMarker.js)

    google is not defined (CoreRender: ~sitecollection/_catalogs/masterpage/Display Templates/Content Web Parts/Control_GoogleMaps.js)

    Also, how to overcome search result limitation of 50 items?

    • Hi Sam,

      For your first question I think there is something wrong with the containerId you are using. Besides that it is also looking for the google maps javascript. You maybe loading it at the wrong time.

      You could send me a mail if you would like me to assists you.

      Besides that I never had to override the limitation of 50 results. If paging is not doing the trick you could maybe try the following: http://sharepoint-community.net/forum/topics/how-to-override-content-by-search-web-part-s-limit-of-50-results

      Matt Stark has a solution by using javascript never tried it do.

      • jQuery placed in the master page
        Script Editor as first web part in the page and placed script link for maps.googleapis.com
        Content Search Web part and changed query to return the list items (Returning result)
        Changed display template Control to “Googld Maps” and Item to “Google Map Marker”
        Changed property mappings as you mentioned

        But returns the same error:
        containerId is not defined (CoreRender: ~sitecollection/_catalogs/masterpage/Display Templates/Content Web Parts/Item_GoogleMarker.js)

        Don’t know where i am going wrong…

Leave a Reply

Your email address will not be published. Required fields are marked *

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