Share via


SharePoint 2010: How to Integrate jVectorMap

Introduction

jVectorMap is a light-weight JavaScript-based vector mapping library. It supports the development of interactive maps that run on the client. As it is JavaScript-based, it is fully compatible with all browsers supporting JavaScript. In this posting, we'll explore how to integrate a jVectorMap display with SharePoint Server 2010. By working through this article, you will gain fundamental experience with integrating jVectorMap with the SharePoint platform.  You'll be using SharePoint Designer 2010 as the primary development environment.
 
We'll begin by reviewing the file and folder structure of the downloaded package, and then modifying its structure and pruning as needed. Next, we'll upload the cleaned up package to a convenient site using SharePoint Designer 2010.  Then, we'll create and edit a page, adding the necessary library references and markup to present a simple map on a site page.  We'll then do a few cleanup tasks and even implement a modal popup dialog.  Later, we will customize the region popups and also add country flags to the popup.  Next, we'll remove the embedded JSON array and instead use REST to pull the data from SharePoint list containing the region data. Finally, we'll revise the script to use the list web service to pull the data from the same SharePoint list.

Create the Package

  1. From the jVectorMap download page, download the Full Project.
  2. Extract the folder, and then double-click on the index.html file in order to gain a sense of how the functioning map appears.
  3. Create a new folder named jVectorMap having the following subfolders and contents:
    1. css
      • jquery-jvectormap.css
    2. images
      • Nothing for now.  This will be populated later.
    3. jQuery:
      • jquery-1.8.2.js
      • jquery-jvectormap.js
      • jquery-mousewheel.js
    4. js:
      • This will be empty for now.
    5. lib:
      • Leave all of the files originally in this folder unchanged.There should be a total of 24.
    6. maps:
      • jquery-jvectormap-map.js
      • jquery-jvectormap-us-aea-en.js
      • jquery-jvectormap-us-lcc-en.js
      • jquery-jvectormap-us-merc-en.js
      • jquery-jvectormap-us-mill-en.js
      • jquery-jvectormap-world-mill-en.js
    7. [root]
      • index.html
  4. All other files can be deleted.
  5. After making these changes, you will see something like this:
  6. You don't need to organize the jVectorMap, jQuery and other files this way.  It isn't required.  However, I have found this organization useful and convenient in planning for future maintenance and modification.
  7. Launch SharePoint Designer 2010, and then Import the folder package to the Site Pages folder on the site.

Create the Initial Site Page

  1. Open the original index.html file that came with jVectorMap, and review the necessary library references that will need to be added.

  2. In SharePoint Designer, create a new web part page.  Just one web part zone is needed. For this article, it will be named demo.aspx.

  3. Checkout demo.aspx, and then open it in Advanced Mode.

  4. Remove all markup between the PlaceHolderMain content tags and replace with the following:

    1. All of the JavaScript library references; the
    2. CSS reference; the
    3. JavaScript code; and all of the
    4. HTML markup between the body tags on the original page.  Note: you can leave out the empty DIV tag set with height 400px.
  5. Update all of the CSS and JavaScript libraries paths.

  6. Open a browser, and then connect to the new page.  Aside from the usual SharePoint page artifacts, you should see the map appear the same as previously:

  7. Now let's do some cleanup. We'll start by revising the button markup. Button tags cause a page reload, and this is unnecessary and distracting.  Therefore, in the markup, replace all button elements with input elements, and, of course, naming them appropriately.  For example, replace this markup

    <button id="focus-single">Focus on Australia</button>
    

    with this:

    <input id="focus-single" name="Button1" type="button" value="Focus on Australia" />
    
  8. Do this for the other two buttons as well.

  9. After implementing this modification, clicking the Focus on Australia button should not cause a page reload.

  10. Another cleanup item is the initial zoom level.  Let's modify this so that the whole map is displayed when initially connecting to the page.  To do this, look for the scale parameter (you'll find it in the focusOn parameter array) and set it to 1.  Save the page and reload the browser to test.

  11. One remaining cleanup is to implement the jQuery ready function.  In demo.aspx, look for this code and comment it out or remove it:

    1.jQuery.noConflict();
    2.jQuery(function(){
    3.  var $ = jQuery;
    
  12. Then replace it with this single line:

    $(document).ready(function(){
    
  13. This completes this procedure.

Add a Modal Popup

  1. We'll implement a modal popup using the  showModalDialog method of  SP.UI.ModalDialog.

  2. We'll need this image:

  3. Add this image to the images folder, naming it help.png.

  4. Add the following declarations to the project css file, jquery-jvectormap.css:

    1.#helpbtn {
    2.  position: absolute;
    3.  left: 5px;
    4.  top: 3px;
    5.}
    6.#helpbtn img {
    7.  border: 0;
    8.}
    
  5. And then revise the css for the zoom buttons to the following:

    1..jvectormap-zoomin {
    2.    top: 5px;
    3.    left: 55px;
    4.}
    5..jvectormap-zoomout {
    6.    top: 25px;
    7.    left: 55px;
    8.}
    
  6. Close the css file, and then add the following to the demo.aspx file, just after the other DIV tags in the body section:

    <div id="helpbtn"><a href="#" class="helpDialog"><img src="image/help.png" alt="Help" /></a></div>
    
  7. Add a simple ASP.NET page (not a Web Part page) to the Sitepages/jVectorMap folder, naming it helpdialog.aspx:

  8. Open this file for editing, remove the form tags between the body tags, and then insert some placeholder text (e.g., lorem ipsum dolor...); then save and close this file.

  9. In demo.aspx, in the href parameter for the helpbutton, add the following:

    JavaScript:showHelpDialog();
    
  10. Then add the following JavaScript function in the same script block as the jVectorMap script:

    1.function showHelpDialog(){
    2.  var options = {
    3.  title: "jVectorMap help",
    4.  width: 400,
    5.  height: 300,
    6.  url: "helpDialog.aspx"  };
    7.  SP.UI.ModalDialog.showModalDialog(options);
    8.};
    
  11. Save and then close demo.aspx.

  12. Refresh the browser, and then click on the new help button.  You'll see something like this:

  13. This completes this procedure.

Customize Region Popups

  1. Checkout your jVectorMap page file.

  2. Open in Designer, and then click Advanced Mode.

  3. In Code view, search for the series array parameter. 

  4. Select the opening bracket after series:, right-click it, and then select Find Matching Brace.

  5. Just after this matching closing brace, enter a comma (","), as you will be entering a custom event handler.

  6. On a new line, after the comma, enter the following block of text:

    onRegionLabelShow: function(event, label, code){
      label.html(' ' + label.html() + 
      '<hr noshade="noshade" style="height: 1px"/>My text ');
    }
    
  7. Save the file (but don't check it back in just yet) and then refresh the browser.

  8. Move the cursor over a region, and the customized popup should appear as shown below:

  9. Just edit the text in the onRegionLabelShow event handler as desired.

  10. Check the file back in.

  11. This completes this procedure.

Add Country Flags to Region Popups

  1. Checkout your jVectorMap page file.

  2. Create a new asset library on the target site, naming it CountryFlags.

  3. Build a library of country flag images, and then rename the image files according to their digraph values.  PNG image format works best.  Thus, for example, Germany's flag image would be DE.PNG.  If you're uncertain what digraphs to use,  open the jquery-jvectormap-world-mill-en.js file.  Each region entry begins with its diagraph and you'll find the country name embedded in each entry.  Note that not all regions have approved digraphs, and you'll find that this JS file uses some custom digraph codes for some regions.

  4. Add the library to the CountryFlag's asset library on the target site.  The relative URL (with respect to the web application) to any image might be: /[yoursite]/CountryFlags/DE.PNG.

  5. Revise the onRegionLabelShow event handler as follows:

    1.onRegionLabelShow: function(event, label, code){
    2.  var imgString = '<img src="/test/CountryFlags/' + code.toString() + '.png" /> '
    3.  label.html(imgString + label.html() + 
    4.  '<hr noshade="noshade" style="height: 1px"/>My text ');
    5.}
    
  6. Save the file (but don't check it back in just yet) and then refresh the browser.

  7. Move the cursor over a region, and the customized popup will now display with the appropriate country flag as shown below:

  8. Check the file back in.

  9. This completes this procedure.

Add Data to Region Popups

  1. In SharePoint Designer, checkout your jVectorMap page file.

  2. Open the target page in Code view.

  3. Revise the onRegionLabelShow event handler as follows:

    onRegionLabelShow: function(event, label, code){
    label.html('<img src="/test/CountryFlags/' + code.toString() + '.png" /> ' + label.html() + 
      '<hr noshade="noshade" style="height: 1px"/>Nominal GDP (Billions US$): ' + chkValue(cdata[code]));
    }
    
  4. Save the file (but don't check it back in just yet) and then refresh the browser.

  5. Move the cursor over a region, and the customized popup will now display with the appropriate country flag as shown below.

  6. Check the file back in.

  7. This completes this procedure.

Integrate with List Data through REST

  1. Create a new list on the target site, naming it RegionData.  It has two fields: Title and GDP, both configured as text.

  2. Add to this list the region data provided in the original jVectorMap package (182 regions with data).

  3. Add the following to the base site URL: _vti_bin/listdata.svc.  Thus, for a server-name spdev12 and site test, the REST list service URL would be:

    http://spdev12/test/_vti_bin/listdata.svc

  4. Connect to this URL to see the list of services available.

  5. Add the following to this URL: /RegionData()?$select=Title,GDP.  Thus, the new URL will be:

    http://spdev12/test/_vti_bin/listdata.svc/RegionData()?$select=Title,GDP

  6. Checkout the target page displaying the jVectorMap.

  7. Open the page in Code view.

  8. Remove (or comment out)  this statement:

    $(document).ready(function(){
    
  9. And then replace with these statements:

    var qryWCFUrl = "http://spdev12/test/_vti_bin/listdata.svc/RegionData()?$select=Title,GDP";
    $.getJSON(qryWCFUrl, function  (results) {
    
  10. Add the following block of JavaScript code just after the statements added above:

    var mycdata;
    var myString = "{";
    $.each(results.d.results, function  (i, item) { 
      myString = myString + '"' + item.Title + '":"' + item.GDP + '",';
    });
    myString = myString.substring(0, myString.length-1) + '}';
    mycdata = JSON.parse(myString);
    
  11. Look for the values parameter in the series array.  You'll find the long list of region digraph/value pairs here.  This is the JSON array.

  12. Remove every thing between the brackets, "{" and "}", including the brackets, and then replace with mycdata.

  13. Also, replace cdata with mycdata in the region popup script.

  14. Save the file (but don't check it back in just yet) and then refresh the browser.

  15. The map displays exactly the same:

  16. Check the file back in.

  17. This completes this procedure.

Integrate with List Data using List Web Service

  1. Open a browser and navigate to the target site.  In this instance, the target site is /Test.

  2. Append the following to this URL: _vti_bin/lists.asmx in order to verify available services:

  3. In SharePoint Designer, checkout your jVectorMap page file (or copy it).

  4. Open the file in Code view.

  5. Remove everything between the JavaScript tags, and replace with this:

    01.function showHelpDialog(){
    02.  var options = {
    03.     title: "jVectorMap help",
    04.     width: 400,
    05.     height: 300,
    06.     url: "helpDialog.aspx"  };
    07. SP.UI.ModalDialog.showModalDialog(options);
    08.};
    09.$(document).ready(function(){
    10.  //Define the SOAP envelope
    11.  var soapEnv = 
    12.    "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
    13.       <soap:Body> \
    14.     <GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \
    15.       <listName>RegionData</listName> \
    16.       <query> \
    17.         <Query> \
    18.         </Query> \
    19.       </query> \
    20.       <viewFields> \
    21.         <ViewFields> \
    22.           <FieldRef Name='Title'  /> \
    23.           <FieldRef Name='GDP' /> \
    24.         </ViewFields> \
    25.       </viewFields> \
    26.       <rowLimit>99999</rowLimit> \
    27.       <queryOptions xmlns:SOAPSDK9='http://schemas.microsoft.com/sharepoint/soap/' > \
    28.         <QueryOptions/> \
    29.       </queryOptions> \
    30.     </GetListItems> \
    31.       </soap:Body> \
    32.     </soap:Envelope>";
    33.  //Get the data via the web service call
    34.  jQuery.ajax({
    35.    url: "/test/_vti_bin/lists.asmx",
    36.    type: "POST",
    37.    dataType: "xml",
    38.    data: soapEnv,
    39.    complete: ProcessListItems,
    40.    contentType: "text/xml; charset=\"utf-8\""
    41.  });
    42.  //Extract the desired data from the response and build the data string
    43.  function ProcessListItems(xData, status) {
    44.    var myString = "{";
    45.    var mycdata;
    46.    jQuery(xData.responseXML).find("z\\:row").each(function () {
    47.      myString = myString + '"'  + $(this).attr("ows_Title") + '":"' + $(this).attr("ows_GDP") + '",';
    48.  });
    49.  //Final cleanup of the string and convert to JSON array object
    50.  myString = myString.substring(0, myString.length-1) + '}';
    51.  mycdata = JSON.parse(myString)
    52.  //Utility function to check variable contents
    53.  function chkValue(val){
    54.    if (typeof val ==="undefined"){
    55.      x = 0;
    56.    }
    57.    else{
    58.      x = val;
    59.    }
    60.    return x;
    61.  };
    62.  //Define event handlers
    63.  $('#focus-single').click(function(){
    64.    $('#map1').vectorMap('set', 'focus',  'AU');
    65.  });
    66.  $('#focus-multiple').click(function(){
    67.    $('#map1').vectorMap('set', 'focus', ['AU', 'JP']);
    68.  });
    69.  $('#focus-init').click(function(){
    70.    $('#map1').vectorMap('set', 'focus', 1, 0, 0);
    71.  });
    72.  $('#get-data').click(function(){ 
    73.    alert(JSON.stringify(mycdata));
    74.  });
    75.  //Instantiate jVectorMap object
    76.  $('#map1').vectorMap({
    77.    map: 'world_mill_en',
    78.      focusOn: {
    79.        x: 0.5,
    80.        y: 0.5,
    81.        scale: 1
    82.      },
    83.      series: {
    84.        regions: [{
    85.          scale: ['#C8EEFF',  '#0071A4'],
    86.          normalizeFunction: 'polynomial',
    87.          values: mycdata
    88.        }]
    89.      },
    90.      onRegionLabelShow: function(event, label, code){
    91.        label.html('<img src="/test/CountryFlags/' + 
    92.        code.toString() + '.png" /> '  + label.html() + 
    93.        '<hr noshade="noshade" style="height: 1px"/>Nominal GDP (Billions US$): '  + 
    94.        chkValue(mycdata[code]));
    95.      } //closes onRegionLabelShow
    96.    }); //Closes jVectorMap
    97.  }; //Closes ProcessListItems
    98.}); //Closes document.ready
    
  6. Save the file (but don't check it back in just yet).

  7. On the SharePoint Designer 2010 Page ribbon, click Preview in Browser.

  8. The map displays exactly the same, which it should.

  9. Check the file back in and close SharePoint Designer.

  10. This completes this procedure.

For Further Attention

There is a fractional but noticeable delay (in the SharePoint implementation), in the appearance of the popup, as you move the mouse cursor over a region.  Compare this response with that displayed in the downloaded package running on the desktop, where the popup appears instantaneously.  I'm not sure how to address this performance issue; input? Ideas?  Thoughts?  Comments welcome.

Summary

This article has presented one method for integrating the light-weight jVectorMap vector-mapping client with SharePoint Server 2010. It presents a simple walkthrough to expose interested readers to some of the basic features and capabilities of jVectorMap and their implementation on the SharePoint Server 2010 framework.  The final SharePoint Designer 2010 page script/markup developed in this article are available in the TechNet Gallery here: jVectorMap / SharePoint 2010 Integration Script.

References

Notes

  • Incidentally, the country shading that you see is based upon nominal GDP in billions of US$. A link to that Wikipedia-based data is in the References section.