For a website project I want to embed Maps from the HighCharts Javascript library into a webpage. There are numerous modules in Drupal that allow integration with HighCharts and Drupal, but few that allow Map visualizations easily in Drupal. So as a workaround for these modules and Drupal I opted to reuse existing modules in my Drupal 7 site to create Map field(s) in Drupal the Display Suite (DS) module.
Existing Modules that allow Integration of HighCharts and Drupal 7:
Name / Versions | Pros | Cons |
Highcharts Module 1.0-alpha6 / 2.x-dev |
|
|
Charts Module 2.0-rc1 / 2.x-dev |
|
|
Visualization API 8.x-1.0beta1, 7.x-1.0beta2 |
|
|
My Solution for a simple Map in Drupal 7 tied to a content type:
This solution requires that you make use of Display Suite and are comfortable with Custom Fields in DS.
Simply create a DS field for my content type:
and then add the following code to a field:
<?php // Add highcharts dependencies // Example from: // http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/maps/demo/us-data-labels/ //drupal_add_js('http://code.highcharts.com/highcharts.js', 'external'); drupal_add_js('https://code.highcharts.com/maps/highmaps.js', 'external'); drupal_add_js('https://code.highcharts.com/maps/modules/data.js', 'external'); drupal_add_js('https://code.highcharts.com/maps/modules/exporting.js', 'external'); drupal_add_js('https://code.highcharts.com/mapdata/countries/us/custom/us-small.js', 'external'); $js =<<<EOFJS jQuery(document).ready(function () { // Load the data from the HTML table and tag it with an upper case name used for joining var data = [], // Get the map data mapData = Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small']); Highcharts.data({ table: document.getElementById('data'), startColumn: 1, startRow: 1, complete: function (options) { jQuery.each(options.series[0].data, function () { data.push({ ucName: this[0], value: this[1] }); }); } }); // Process mapdata jQuery.each(mapData, function () { var path = this.path, copy = { path: path }; // This point has a square legend to the right if (path[1] === 9727) { // Identify the box Highcharts.seriesTypes.map.prototype.getBox.call(0, [copy]); // Place the center of the data label in the center of the point legend box this.middleX = ((path[1] + path[4]) / 2 - copy._minX) / (copy._maxX - copy._minX); // eslint-disable-line no-underscore-dangle this.middleY = ((path[2] + path[7]) / 2 - copy._minY) / (copy._maxY - copy._minY); // eslint-disable-line no-underscore-dangle } // Tag it for joining this.ucName = this.name.toUpperCase(); }); // Initiate the chart jQuery('#prez_map').highcharts('Map', { title: { text: 'US unemployment rate 2015' }, subtitle: { text: 'Small US map with data labels' }, mapNavigation: { enabled: true, enableButtons: false }, xAxis: { labels: { enabled: false } }, colorAxis: {}, series: [{ mapData: mapData, data: data, joinBy: 'ucName', name: 'Unemployment rate per 2015', states: { hover: { color: '#BADA55' } }, dataLabels: { enabled: true, formatter: function () { return this.point.properties['hc-a2']; }, style: { fontSize: '10px' } }, tooltip: { valueSuffix: '%' } }, { type: 'mapline', data: Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small'], 'mapline'), color: 'silver' }] }); }); EOFJS; drupal_add_js($js, 'inline'); $content = array( 'highcharts_map' => array( '#type' => 'markup', '#markup' => "<div id='prez_map'></div>" ), ); return drupal_render($content);
There you have it. An example screenshot of this field on an example site is:
Now admittely, this sample setup is simply taking 1 of the Demos of the HighMaps examples and shoving it onto a Drupal node page. But, that is essentially what I want to happen. I will of course in the near future make the following amendments to this code:
- Make use of either drupal_add_js or #attached within the render array to include the JS dependencies.
- Create additional fields, or Paragraphs configurations which the DS field will inspect and use as map data to render the maps more dynamically for the few types of maps I want to show on my site.
This DS usage and Field configuration is simply the most basic building blocks I’ve thought of to create the necessary codebase within Drupal to meet my clients needs.
Looking for quality web hosting? Look no further than Arvixe Web Hosting!