In this article I will demonstrate how to implement the JQVMAP jQuery plugin into an XPage. There are 4 maps to chose from but users are able to create their own and add more maps if they need to. In addition to the out of the box functionality I have added some XPage lookup data to demonstrate the integration potential. As I have written this article ideas and thoughts have come at me quick and fast and this is much larger than I had originally intended. If you need maps on your website this is a fantastic flexible solution.
JQVMAP
Demonstration
The XPages integration of JQVMAP is demonstrated here
This capability does not yet work properly in IE – Chrome/Safari/Firefox only.
Download
The demonstration database can be downloaded from the link above or from here
Introduction
JQVMAP is a jQuery plugin based on the original jVectorMap plugin. The plugin provides an abundance of parameterized options for the developer to create their own maps, add color, add interactivity and provide a very slick solution to a broad requirement of many customers, to provide mapping capabilities to their website.

Users are able to select either a country or state and pertinent information regarding their selection will be displayed on the page.
How does it work?
I added jQuery and the relevant map files to my database’s WebContent folder.
They are referenced in the XPage as follows:
<xp:this.resources> <xp:script src="js/jquery-1.7.1.min.js" clientSide="true"></xp:script> <xp:script src="js/jquery.vmap.js" clientSide="true"></xp:script> <xp:script src="js/vmap/jquery.vmap.world.js" clientSide="true"></xp:script> <xp:script src="js/vmap/jquery.vmap.sampledata.js" clientSide="true"></xp:script> <xp:styleSheet href="css/jqvmap.css"></xp:styleSheet> </xp:this.resources>
Adding a Map
Implementing the basic JQVMAP is as simple as adding the following jQuery to your XPage
jQuery(document).ready(function() { jQuery('#vmap').vectorMap({ map: 'germany_en' }); });
There are many paramaters which can be added to the map, most of which are self explanatory. For a full list of all the parameters available check out the project on github.
Colorizing the map
The example comes with a sampledata.js file which contains 2010 GDP information and is formatted like this:
var sample_data = {“af”:”16.63″,”al”:”11.58″,”dz”:”158.97″,”ao”:”85.81″,”ag”:”1.1″,”ar”:”351.02″,”am”:”8.83″,”au”:”1219.72″,”at”:”366.26″,”az”:”52.17″,”bs”:”7.54″,”bh”:”21.73″,”bd”:”105.4″,”bb”:”3.96″,”by”:”52.89″,”be”:”461.33″,”bz”:”1.43″,”bj”:”6.49″,”bt”:”1.4″,”bo”:”19.18″,”ba”:”16.2″,”bw”:”12.5″,”br”:”2023.53″,”bn”:”11.96″,”bg”:”44.84″,”bf”:”8.67″,”bi”:”1.47″ etc etc
When the map is built the data is passed into the plugin via these parameters
values: sample_data, scaleColors: ['#C8EEFF', '#006491'],
The plugin then determines the color scale between the two passed in color parameters and scales each region based on the data provided. And quite frankly that rocks, bigtime! Changing the scale colors can do this to your maps and is very effective if you are looking to show coal usage or rainforest or anything where color enhances the information

So where’s the XPage stuff?
I have added some XPage functionality to the world map in two ways – a partial refresh and a REST service.
As the user mouses over a region there is a callback to the REST service to provide me some JSON from the database. Adding the REST service creates the JSON from the vwCountryDoc view
<xe:restService id="restService1" pathInfo="countryLookup"> <xe:this.service> <xe:viewJsonService viewName="vwCountryDoc" var="entry" contentType="text/plain" count="1" defaultColumns="true"> <xe:this.keys> <![CDATA[#{javascript:return facesContext.getExternalContext().getRequest().getParameter("code")}]]> </xe:this.keys> </xe:viewJsonService> </xe:this.service> </xe:restService>
creates http://demo.xomino.com/xomino/jQinX.nsf/xJQVMAP.xsp/countryLookup?code=gb
{ "@entryid":"77-A19E1314CB4B2C0B852579FE0047FF23", "@unid":"A19E1314CB4B2C0B852579FE0047FF23", "@noteid":"505E", "@position":"77", "@siblings":248, "@form":"CountryDoc", "CountryCode":"GB", "Name":"United Kingdom", "POP":"62,262,000", "Areakm":"242,900", "Aream":"93,800", "Life":"79.4", "HighestPeak":"Ben Nevis\t1,344 m (4,409 ft)\t" }
We add onRegionOver and onRegionOut callbacks to the map creation and with that we are able to read the JSON, parse the information (building a table) into a hidden span, and show it/hide it depending on the callback.
jQuery('#vmap').vectorMap({ map: '#{javascript: getComponent("comboBox1").getValue()}', backgroundColor: '#333333', color: '#ffffff', hoverOpacity: 0.7, selectedColor: '#666666', enableZoom: true, showTooltip: false, values: sample_data, scaleColors: ['#C8EEFF', '#006491'], normalizeFunction: 'polynomial', onRegionOver: function (event, code, region){ url="xJQVMAP.xsp/countryLookup?code="+code; //get the REST stream $.getJSON(url, function (data){ temp=region; temp=temp.replace(/ /g, '_'); var theTable='<table cellpadding=2 border=0 class="hoverTable"><tr><td>' theTable += '<img src="http://www.flagslist.com/clist/flags/'+temp+'.png" height=30 width=60 border=0/></td>' theTable += "<td><h1 style='color: white'>"+data[0].Name+"</h1></td></tr>" theTable += "<tr><td>Population</td><td>"+data[0].POP+"</td></tr>" theTable += "<tr><td>Life Expectency</td><td>"+data[0].Life+"</td></tr>" theTable += "<tr><td>Area km/<sup>2</sup></td><td>"+data[0].Areakm+"</td></tr>" theTable += "<tr><td>Highest Peak</td><td>"+data[0].HighestPeak+"</td></tr>" theTable+= "</table>" $(".hoverShow").html(theTable).css('display', 'block') console.log(theTable) }); }, onRegionOut: function(element, code, region) { $(".hoverShow").html('&nsbp;').css('display', 'none') }, onRegionClick: function(element, code, region) { //message only relevent to the world map var temp="#{javascript: getComponent("comboBox1").getValue()}" if (temp != "world_en"){ return false} var message = 'You clicked "' + region + '" which has the code: ' + code.toUpperCase() + "\n\n2010 GDP:" + sample_data; alert(message); sTemp='<img src="http://www.flagslist.com/clist/flags/'+region.replace(/ /g, '_')+'.png" height=30 width=60 border=0/>' $("[id$=code1]").val(code); $('#flag').html(sTemp) $("[id$=button1]").click() } }); });
And this creates the Top Left table in the example

You will see there is an onRegionClick event as well. When the user clicks on the region I am triggering a hidden button to be clicked and that runs a partiaRefresh on the bottom left section which displays information from the database via computed fields. This also pulls data from the sampledata.js and displays the GDP value
<xp:table id="countryData" style="width: 700px" cellpadding="5"> <xp:tr> <xp:this.rendered><![CDATA[#{javascript:return (getComponent('comboBox1').getValue() == "world_en") }]]></xp:this.rendered> <xp:td style="width: 100px"></xp:td> <xp:td> <div id="flag" style="width: 200px"> <xp:text escape="false" id="computedField4"> <xp:this.value escaped="false"> <![CDATA[#{javascript:var temp = getComponent("code1").getValue(); var temp1 = @DbLookup(@DbName(), "vwCountryDoc", temp, 2); return '<img src="http://www.flagslist.com/clist/flags/'+temp1.replace(/ /g, '_')+'.png" height=30 width=60 border=0 />' }]]> </xp:this.value> </xp:text> </div> </xp:td> </xp:tr> <xp:tr> <xp:this.rendered><![CDATA[#{javascript:return (getComponent('comboBox1').getValue() == "world_en") }]]></xp:this.rendered> <xp:td>Country Code:</xp:td> <xp:td> <xp:inputText id="code1" defaultValue="GB" style="border: 1px solid white"> </xp:inputText> </xp:td> </xp:tr> <xp:tr> <xp:this.rendered><![CDATA[#{javascript:return (getComponent('comboBox1').getValue() == "world_en") }]]></xp:this.rendered> <xp:td>Name:</xp:td> <xp:td> <xp:text escape="true" id="computedField1"> <xp:this.value> <![CDATA[#{javascript:var temp = getComponent("code1").getValue(); @DbLookup(@DbName(), "vwCountryDoc", temp, 2)}]]> </xp:this.value> </xp:text> </xp:td> </xp:tr> <xp:tr> <xp:this.rendered><![CDATA[#{javascript:return (getComponent('comboBox1').getValue() == "world_en") }]]></xp:this.rendered> <xp:td>Population</xp:td> <xp:td> <xp:text escape="true" id="computedField2"> <xp:this.value> <![CDATA[#{javascript:var temp = getComponent("code1").getValue(); @DbLookup(@DbName(), "vwCountryDoc", temp, 3)}]]> </xp:this.value> </xp:text> </xp:td> </xp:tr> <xp:tr> <xp:this.rendered><![CDATA[#{javascript:return (getComponent('comboBox1').getValue() == "world_en") }]]></xp:this.rendered> <xp:td>Area</xp:td> <xp:td> <xp:text escape="true" id="computedField3"> <xp:this.value> <![CDATA[#{javascript:var temp = getComponent("code1").getValue(); @DbLookup(@DbName(), "vwCountryDoc", temp, 4)}]]> </xp:this.value> </xp:text> </xp:td> </xp:tr> </xp:table>
This builds the popup and bottom left information

CallBack events
Because of the callback events we are also able to add/display change other data on the screen. Taken directly from the site we have the following events available.
- onLabelShow function(element, label, code)
- Callback function which will be called before label is shown. Label DOM object and country code will be passed to the callback as arguments.
- onRegionOver function(element, code, region)
- Callback function which will be called when the mouse cursor enters the region path. Country code will be passed to the callback as argument.
- onRegionOut function(element, code, region)
- Callback function which will be called when the mouse cursor leaves the region path. Country code will be passed to the callback as argument.
- onRegionClick function(element, code, region)
- Callback function which will be called when the user clicks the region path. Country code will be passed to the callback as argument.
Demonstration
The XPages integration of JQVMAP is demonstrated here
Download
The demonstration database can be downloaded from the link above or from here
[…] the original here: jQuery in XPages #10 – JQVMAP (Vector Maps) « Xomino Bookmark on Delicious Digg this post Recommend on Facebook share via Reddit Share with Stumblers […]
Very nice Mark, another great article.
And on http://www.naturalearthdata.com is a lot of material which could be added according to the read.me on git.
shapefile like on http://www.eea.europa.eu/data-and-maps/data/eea-reference-grids should be possible.
So a lot of possibilities.
there goes another weekend fiddling with this. Hopefully it rains
I love the flexibility of this plugin – thanks for the examples Ruud 🙂