It seems that most of the intranet portals have a lot in common. It could be news feed, last documents, last tasks, “who is new web part” and the rest “catchy” things you may have already seen in your intranet projects. Finally, sort of “about”, “company structure”, “help” or “get started” pages could be one of the “must have” features for every intranet implementation. Recently, I’ve been asked in several projects if there is a way to make up an “office locations page”. This page is supposed to provide a map with all the current offices across the world. It seems to be quite general functionality, so I decided to write a few post around that and shares some thought and insights.
What is the case?
The case is quite simple. There could be a company which has several offices all over the country world. As part of intranet implementations, there could be a requirement to have a page with a map to present office locations. It would also be nice to have editable features to allow content owners manage the data/data mappings behind the map.
Potential implementations
Pure SharePoint implementation
Well, the good news that there is a built-in capabilities which could help such a data-driven map. In general, the idea is to leverage Vision Services and Vision to craft the diagram and bind some of the entities to the external data source. Here are a few posts to the started:
- Publishing Data-Connected Visio Diagrams to Visio Services in SharePoint 2010
- Using Visio Services with SharePoint Lists for interactive Floor Plans and Maps
- MSDN: Visio Services in SharePoint Server 2010
- MSDN: Visio Services in SharePoint 2013
This is a good starting point unless you can write a couple of lines of js code. No code is involved with Vision, everything could be configured with “click-click” experience.
However, Visio Services has some disadvantages regarding licensing, rendering and general look and feel. Also, there are some issues with repeatable deployment between different SharePoint farms. Finally, you really need to know Visio and some progressive stuff about shapes, custom labeling and data connections.
JavaScript, SVG, Bing and Goggle Maps
Well, next step is trying to benefit from already existing js libraries. Brief googling could lead you to such an amazing SVG libraries as jqvmap or Polymaps (surely, there much more of them). Also, there are several libraries for the jQuery wrapping Google Maps or Bing – gmap3, gomap, jquery-bing-maps. Again, there are just lots of the libs. Just take a look on that article – 20+ Useful jQuery Google Maps Plugins – or try to find anything what could suit your needs.
Well, there is no need to invent the bicycle as there are really lots of them on the market. On the other hand, you may stuck with lib’s API, lack of support or documentations. Next, there could be huge “getting started” time for the particular library. You just need to spent some time to get used, to understand how it works and how it could meet your project needs. Also, time to time, some of the libraries just get abandoned. Except that, leveraging features of already existing libraries is a good thing for the good reason.
The Jedi way: crafting the proof-of-concept
Finally, the Jedi way is create something from scratch. That may make sense if you try to avoid a lot of external dependencies in the project, to have everything under control or just have really complex requirement where coding from scratch would worth it.
Let’s see how the “coded-from-scratch” solution could look like. For the fast start, Google Maps API V3 and jsfiddle.net could be used. To craft a demo, we would need a few lines of html, some css styling and a little bit java script magic.
Here is the sample which was done while we discusses some “office-map-page” requirements with one of the customers to present the actual demo/prototype/look and feel:
<div id="map-canvas-1" class="map-cnt"> </div> <div id="map-canvas-2" class="map-cnt"> </div>
Adding some styling:
html, body, .map-cnt { margin: 0; padding: 0; } .map-cnt { width: 600px; height: 300px; border: 3px #dedede solid; margin: 10px; } .office-btn { background-color: white; margin:2px; padding:2px; border:2px #dedede solid; font-size:12px; } .office-btn:hover { border:2px #91cdf2 solid; background-color: #eeeeee; cursor:pointer; }
And, finally, get some java script on top of Google Map API:
var officeMap = { Map: function (container) { var self = this; self._domContainer = container; self._map = null; self._offices = []; self._currentOfficeInfoTip = null; self.loadOffices = function () { var imageUrl = "http://cdn3.iconfinder.com/data/icons/business-and-finance-icons/512/Office_Building-32.png"; self._offices.push({ x: 25.27202, y: 55.307922, title: "Dubai", description: "Technology, investment and manufacturing office.", imageUrl : imageUrl }); self._offices.push({ x: 40.713956, y: -74.00802, title: "New York", description: "Global sales office.", imageUrl : imageUrl }); self._offices.push({ x: 55.771939, y: 37.617188, title: "Moscow", description: "PR & Marketing.", imageUrl : imageUrl }); self._offices.push({ x: -33.890542, y: 151.274856, title: "Sydney", description: "Head Office.", imageUrl : imageUrl }); self._offices.push({ x: 22.352616, y: 114.158936, title: "Hong Kong", description: "Manufacturing, R&D offices.", imageUrl : imageUrl }); self._offices.push({ x: 51.495065, y: -0.134583, title: "London", description: "Tax & Legal offices.", imageUrl : imageUrl }); }; self.initMarker = function (officeLocation) { var officeMarker = new google.maps.Marker({ position: new google.maps.LatLng(officeLocation.x, officeLocation.y), map: self._map, icon: officeLocation.imageUrl }); var officeInfoTip = new google.maps.InfoWindow({ content: officeLocation.description }); google.maps.event.addListener(officeMarker, 'click', function () { if (self._currentOfficeInfoTip !== null) self._currentOfficeInfoTip.close(); officeInfoTip.open(self._map, officeMarker); self._currentOfficeInfoTip = officeInfoTip; }); }; self.initOfficeButton = function (container, officeLocation) { container.innerHTML = officeLocation.title; container.className = "office-btn"; google.maps.event.addDomListener(container, 'click', function () { self._map.setZoom(8); self._map.setCenter(new google.maps.LatLng(officeLocation.x, officeLocation.y)); }); }; self.initShortcut = function (officeLocation) { var officeBtn = document.createElement('div'); self.initOfficeButton(officeBtn, officeLocation); self._map.controls[google.maps.ControlPosition.TOP_CENTER].push(officeBtn); }; self.init = function () { var mapOptions = { zoom: 1, center: new google.maps.LatLng(0, 0), mapTypeId: google.maps.MapTypeId.ROADMAP }; self._map = new google.maps.Map(self._domContainer, mapOptions); self.loadOffices(); for (var key in self._offices) { var currentOffice = self._offices[key]; self.initMarker(currentOffice); self.initShortcut(currentOffice); } self._map.setCenter(new google.maps.LatLng(0, 0)); }; } }; new officeMap.Map(document.getElementById("map-canvas-1")).init(); new officeMap.Map(document.getElementById("map-canvas-2")).init();
So, the result would look like two independed google maps with clickable offices, tooltips and the set of the buttons at the top of the map:
Not bad for the 20-minutes-coded-demo, huh?
What’s next?
Well, we have pretty much interactive demo. Thanks http://jsfiddle.net for the jump start and a nice environment. The next step is wrapping this up to be deployed on your SharePoint site, adding SharePoint lists as an office data source. So, stay turned – this will be covered in the next articles.
Links to get started
- JavaScript Patterns Collection
- Learning JavaScript Design Patterns
- 20+ Useful jQuery Google Maps Plugin
- gmap3, gomap, jquery-bing-maps, jqvmap, Polymaps
- http://jsfiddle.net
Icon for the “office map” demo:
Conclusion
Intranet portal projects have a lot in common. From project to project you may have very similar features like news feeds, last documents, about page and the rest. One of the page you may see in different intranets is an “Office locations page” with dynamic map and office information. There are several ways to implement it, from out of the box SharePoint features utilizing Visio Services to custom js coding. Finally, the particular implementation would depend on the target project requirements, time and resources.
This is the first part of the “SharePoint How-to: Crafting an “Office locations” page” post series. It covers some overview, potential approaches and proof-of-the-concept for the “Office location” solution. Next post will cover wrapping up and delivering this map to your SharePoint site, binding to the SharePoint lists. So, stay turned.