
Load the HTML
As you might expect there, the HTML file does not contain a huge amount of interesting content in this tutorial. In the head of the file, jQuery is loaded together with a small stylesheet for page layout and a stylesheet for the country flags.
001 <!DOCTYPE HTML> 002 <html> 003 <head> 004 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 005 <title>Highmaps Example</title> 006 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/ jquery/1.8.2/jquery.min.js"></script> 007 <link rel="stylesheet" href="css/style. css"> 008 <link rel="stylesheet" type="text/ css" href="http://cloud.github.com/downloads/ lafeber/world-flags-sprite/flags32.css" /> 009 </head>010
World flags sprite
This space efficient solution by Martign Lafebar weighs in at 172KB for the PNG (a file that is 32 pixel wide by 7808 pixel tall!) and 10KB for the CSS file used to control PNG positioning. The tutorial only uses 28 flags so the file size could actually be reduced by much more. These files are hosted on GitHub together with the generous usage license.
Lay out the chart and map
The info div appears first and contains the relevant flag icon and the country chart. The JS configuration file is responsible for making the correct flag and country name appear together with the chart legend and usage note. The countries’ map is rendered within the container div.
001 <body> 002 <div id="wrapper"> 003 <div id="info"> 004 <span><span id="flag"></ span></span> 005 <h2></h2> 006 <div>Click countries to view history</div> 007 <div id="country-chart"></div> 008 </div> 009 <div id="container"></div> 010 </div>
Run the scripts
At the end of the HTML body, the scripts are loaded. The main configurable file is unemployment.js and derived from the Highcharts ‘rich information on click’ demo file. Then comes the chart library (highcharts.js), the Highmaps module (map.js), the map data for the demo (european-union.js) and a tutorial theme (ub40.js).
001 <script src="js/unemployment.js"></script> 002 <script src="js/highcharts.js"></script> 003 <script src="js/modules/map.js"></script> 004 <script src="js/european-union.js"></ script> 005 <script src="js/themes/ub40.js"></script> 006 </body> 007 </html>
Style the page
The CSS starts with a full page background and is followed by setting a Google Font for all text. Note that @import is not used here for loading the font. The Google Fonts page provides the code for different methods of loading fonts and you might find it useful to try out these different methods.
001 html {
002 background: url(../img/bg.jpg) no-repeat center center fixed;
003 -webkit-background-size: cover;
004 -moz-background-size: cover;
005 -o-background-size: cover;
006 background-size: cover;
007 }
008 body {
009 font-family: 'Raleway', sans-serif;
010 }
Position main elements
The wrappers div is used for centring the content in the browser. Highcharts works well on mobile devices and you can add your content to responsive layouts without creating a load of extra code. The map is floated right and the info box is floated left so that the map doesn’t move when the info box isn’t displayed (in other words when no country is selected).
001 #wrapper {
002 height: 500px;
003 width: 980px;
004 margin: 50px auto;
005 padding: 0;
006 }
007 #container {
008 float: right;
009 height: 500px;
010 width: 570px;
011 }
012 #info {
013 float: left;
014 width: 380px;
015 }
016
Format the info panel content
The country name is displayed as an H2 heading and set to display inline so that it sits alongside the flag sprite. Not all flags are the same shape and vertical-align: bottom is used so that they all sit on the same baseline.
001 #info h2 {
002 display: inline;
003 }
004 #info .f32 .flag {
005 vertical-align: bottom !important;
006 }
007 #info h4 {
008 margin: 2em 0 0 0;
009 }
Encode the data
For simpler datasets, the data can simply be added to the script for loading into arrays. However for larger volumes of data you should use a CSV file. JSONP.PHP is used to get the data. JSONP is used instead of JSON as it works across domains. This step requires server-side processing so you will need to link to a valid JSONP.PHP online.
001 $(function () {
002 $.getJSON('http://yourdomain-goes-here/ highmaps/data/jsonp.php?
003 filename=unemployment.csv&callback=?', function (csv) {
004 function CSVtoArray(text) {
005 return text.replace(/^"/, '') 006 .replace(/",$/, '')
007 .split('","');
008 };
009 csv = csv.split(/n/);
010 var countries = {},
011 mapChart,
012 countryChart,
013 numRegex = /^[0-9.]+$/,
014 quoteRegex = /"/g,
015 categories = CSVtoArray(csv[1]). slice(4);
016
Parse the CSV
The CSV used here is an edited version of the dataset “SL.UEM.TOTL.ZS” from the World Bank which provides a huge amount of data on a diverse range indicators. Each row represents a different country and a new array is created for each, then each item within the row is loaded into the array.
001 $.each(csv.slice(2), function (j, line) {
002 var row = CSVtoArray(line),
003 data = row.slice(4);
004 $.each(data, function (i, val) {
006 val = val.replace(quoteRegex, '');
007 if (numRegex.test(val)) {
008 val = parseInt(val);
009 } else if (!val) {
010 val = null;
011 }
012 data[i] = val;
013 });
014 countries[row[1]] = {
015 name: row[0],
016 code3: row[1],
017 data: data
018 };
019 });
Get the latest percentage
The array is searched and the values for the most recent figures are added to the end of the array using the push() method so that this data may be used in the map. During the search the break statement is used to jump out of the search loop whilst the array contains a value (=== ‘number’). When no data is found the loop carries on to the push().
001 var data = [];
002 for (var code3 in countries) {
003 var value = null,
004 year,
005 itemData = countries[code3].data,
006 i = itemData.length;
007 while (i--) {
008 if (typeof itemData[i] === 'number') {
009 value = itemData[i];
010 year = categories[i];
011 break;
012 }
013 }
014 data.push({
015 name: countries[code3].name,
016 code3: code3,
017 value: value,
018 year: year
019 });
020 }
Add country codes
In preparation for joining the map data with the unemployment data, the two character country codes are loaded from Highcharts and converted to lower case characters so that they may be successfully matched.
001 var mapData = Highcharts. geojson(Highcharts.maps['custom/european- union']);
002 $.each(mapData, function () {
003 this.id = this.properties['hc-key']; // for Chart.get()
004 this.flag = this.id.replace('UK', 'GB'). toLowerCase();
005 });
Total selected points
Highcharts can overlay data so that it may easily be compared. The user simply holds shift and clicks on each country (point) they want to compare. This code checks how many points have been selected. If only one, the country’s flag and name is displayed. If more than one, the title “Comparing countries” is displayed.
001 Highcharts.wrap(Highcharts.Point.prototype, 'select', function (proceed) {
002 proceed.apply(this, Array.prototype. slice.call(arguments, 1));
003 var points = mapChart. getSelectedPoints();
004 if (points.length) {
005 if (points.length === 1) {
006 $('#info #flag').attr('class', 'flag ' + points[0].flag);
007 $('#info h2').html(points[0].name);
008 } else {
009 $('#info #flag').attr('class', 'flag');
010 $('#info h2').html('Comparing countries');
011 }
Configure the country chart
Some chart styling is done here and the rest are done using a separate theme file. Compare this example with the Highcharts rich information, on click demo you will see that as percentages are being used the per cent symbol has been added: ‘{value}%’ for the yAxis label and % for the valueSuffix tooltip.
001 $('#info .subheader').html('<h4>Historic % unemployment</h4><small><em>Shift + Click on map to compare countries</em></small>')
002 if (!countryChart) {
003 countryChart = $('#country-chart'). highcharts({ chart: {
004 height: 396, width: 380, marginTop: 30, spacingLeft: 15 },
005 credits: { enabled: false },
006 title: { text: null },
007 subtitle: { text: null },
008 xAxis: { tickPixelInterval: 60, crosshair: true },
009 yAxis: { title: null, labels: { format: '{value}%' } },
010 tooltip: { shared: true, valueSuffix: '%'},
011 plotOptions: { series: { animation: { duration: 500 },
012 marker: { enabled: false },
013 threshold: 0,
014 pointStart: parseInt(categories[0]),
015 }
016 }
017 }).highcharts();
018 }
Display the chart
The unemployment data is displayed on the chart for each selected country. Colours are assigned for each country from the list of colours specified at the beginning of the theme file.
001 $.each(points, function (i) {
002 // Update
003 if (countryChart.series[i]) {
004 /*$.each(countries[this.code3].data, function (pointI, value) {
005 countryChart.series[i].points[pointI]. update(value, false); 006 });*/
007 countryChart.series[i].update({
008 name: this.name,
009 data: countries[this.code3].data,
010 type: points.length > 1 ? 'line' : 'area'
011 }, false);
012 } else {
013 countryChart.addSeries({
014 name: this.name,
015 data: countries[this.code3].data,
016 type: points.length > 1 ? 'line' : 'area'
017 }, false);
018 }
019 });
Carry on looping
The countryChart is added to and redrawn until all of the selected countries have been displayed. If only one country is selected then the flag, country name and subheader are displayed. If no countries are selected (by single-clicking on the currently selected country) the chart is removed using countryChart.destroy().
001 while (countryChart.series.length > points.length) {
002 countryChart.series[countryChart.series. length - 1].remove(false);
003 }
004 countryChart.redraw();
005 } else {
006 $('#info #flag').attr('class', '');
007 $('#info h2').html('');
008 $('#info .subheader').html('');
009 if (countryChart) {
010 countryChart = countryChart.destroy();
011 }
012 }
013 });
Colour me useful
The colorAxis option within the mapChart has a major impact on the look and usefulness of the map chart. This demo uses a set of colours taken from a currently popular Adobe Color CC set: Neutral Blue. Take some time to explore the colorAxis options so your mapChart is both attractive and useful.
001 colorAxis: {
002 type: 'linear',
003 minColor: '#EEEEFF',
004 maxColor: '#000022',
005 stops: [
006 [0, '#FCFFF5'],
007 [0.25, '#D1DBBD'],
008 [0.5, '#91AA9D'],
009 [0.75, '#3E606F'],
010 [1, '#193441']
011 ]
012 },
Display the map
With its charting heritage, Highmaps content is also treated as a series of datapoints and the options for these are configured here. The unemployment data and map data are both loaded and the unemployment data for each country is linked to the country (joinBy). Finally, in this file there is an option to preselect a country.
001 series : [{
002 data : data,
003 mapData: mapData,
004 joinBy: ['iso-a3', 'code3'],
005 name: 'Current unemployment',
006 allowPointSelect: true,
007 cursor: 'pointer',
008 states: {
009 select: {
010 color: '#A4A800',
011 borderColor: '#A4A800',
012 dashStyle: 'solid'
013 }
014 }
015 }]
016 }).highcharts();
017 // Pre-select a country
018 mapChart.get('gb').select();
019 });
020
