1
votes

I'm creating a map in mapbox with marker points from a CSV file using omnivore. I've successfully figured out how to add highcharts maps on popup to each marker, but I can't get it to work pulling the data from the same CSV. I have figured out how to add highcharts but only by pasting in the data, however instead of manually adding series data, I'd like to pull the data from the existing CSV file and iterate through each column by year for the highchart popup.

Could someone please help me add a series from my CSV data? Attempts to replicate have failed.

Here is my current working example (with highcharts popup not using the data from my CSV file):

(also on jfiddle but you will need to add csv locally:) https://jsfiddle.net/mofq60zq/

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Styled markers from CSV data</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />

<script src="jquery1.6.4.min.js"></script><!-- jquery-1.6.4.min.js -->
    <script src="jqueryui1.8.16.custom.min.js"></script><!-- jquery-ui-1.8.16.custom.min.js -->

<script src='https://api.mapbox.com/mapbox.js/v2.2.4/mapbox.js'></script>
<link href='https://api.mapbox.com/mapbox.js/v2.2.4/mapbox.css' rel='stylesheet' />

<script src='https://cdnjs.cloudflare.com/ajax/libs/highcharts/4.1.1/highcharts.js'></script>
<style>
  body { margin:0; padding:0; }
  #map { position:absolute; top:0; bottom:0; width:100%; }

.search-ui {
  position:absolute;
  top:10px;
  right:10px;
  z-index:1000;
  }

.sparkline {
       height: 100px;
       width: 200px;
   }
</style>
</head>
<body>
<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-omnivore/v0.2.0/leaflet-omnivore.min.js'></script>

<div id='map'></div>
<input id='search' class='search-ui' placeholder='Enter country code' />
<script>
L.mapbox.accessToken = 'pk.eyJ1IjoiZXRwLXByb2plY3QiLCJhIjoiY2lqbDc0dWQwMDAxeHUya280OTE5dGs0NCJ9.viXLMvWxmTv3_uZyvjKsOA';
var map = L.mapbox.map('map', 'mapbox.streets')
    .setView([49.4987919, 13.9583693], 4);

// omnivore will AJAX-request this file behind the scenes and parse it:
// note that there are considerations:
// - The CSV file must contain latitude and longitude values, in column
//   named roughly latitude and longitude
// - The file must either be on the same domain as the page that requests it,
//   or both the server it is requested from and the user's browser must
//   support CORS.

// The omnivore functions take three arguments:
//
// - a URL of the file to fetch
// - options to the parser
// - a custom layer
//
// And they return the custom layer, which is by default an L.geoJson layer.
//
// The second two arguments are each optional. In this case we're supplying
// no arguments to the parser (null), but supplying a custom layer:
// an instance of L.mapbox.featureLayer
// This means that rows with simplestyle properties will be styled as they
// would be in GeoJSON and elsewhere.
//omnivore.csv('gtftest.csv', null, L.mapbox.featureLayer()).addTo(map);

omnivore.csv('gtftest.csv')
    .on('ready', function(layer) {

        this.eachLayer(function(marker) {
            if (marker.toGeoJSON().properties.Type === 'H') {

                marker.setIcon(L.mapbox.marker.icon({
                    'marker-color': '#ff8888',
                    'marker-size': 'small',
                    'marker-image': 'H.png'
                }));

            } else if   (marker.toGeoJSON().properties.Type === 'LNG') {
                    // The argument to L.mapbox.marker.icon is based on the
                    // simplestyle-spec: see that specification for a full
                    // description of options.
                    marker.setIcon(L.mapbox.marker.icon({
                        'marker-color': '#ff0000',
                        'marker-size': 'small',
                        'marker-image': 'LNG.png'
                    }));
            }
            else {
                marker.setIcon(L.mapbox.marker.icon({}));
            }


            ////HIGHCHARTS HERE////


            var lineChartOptions = {
                        title: {
                            text: null
                        },
                        legend: {
                            enabled: false
                        },
                        credits: {
                            enabled: false
                        },
                        exporting: {
                            enabled: false
                        },
                        tooltip: {
                            backgroundColor: {
                                linearGradient: [0, 0, 0, 60],
                                stops: [
                                    [0, '#FFFFFF'],
                                    [1, '#E0E0E0']
                                ]
                            },
                            borderWidth: 1,
                            useHTML: true,
                            borderColor: '#AAA'
                        },
                        yAxis: {
                            min: 0,
                            lineWidth: 1,
                            tickWidth: 1,
                            title: {
                                text: null
                            },
                            labels: {
                                style: {
                                    'fontSize': '10px'
                                }
                            }
                        },
                        xAxis: {
                            type: 'datetime',
                            labels: {
                                style: {
                                    'fontSize': '10px'
                                }
                            }
                        },
                        plotOptions: {
                            series: {
                                cursor: 'pointer',
                                connectNulls: false
                            }
                        }
                    };




                lineChartOptions.tooltip.formatter = function() {
                            var y = "$" + this.y;
                            return '<center>' + Highcharts.dateFormat('%b \'%y', new Date(this.x)) + '</center></b><center><b>' + y + '</b></center>';
                        };
                lineChartOptions.series = [{
                            pointInterval: 24 * 3600 * 1000 * 30.41667,
                            pointStart: 1393632000000,
                            data: [
                            58044, 60871, 29738, null, 804997, 628727, 20678, null,
                            100606, 122195, 981459, 39840]
                        }];


                 // HTML content for port pop-up
                       var popupContent = '<div id="popup_template">' +
                    '<div class="port_header marker-title">' +marker.toGeoJSON().properties.Borderpoint +'</div>' +
                    '<div class="est_value marker-title">'+
                           'Est. Value: $' + marker.toGeoJSON().properties.Value
                           +'</div>' +
                    '<div id="est_value_sparkline" class="sparkline"></div>';


                var container = $('<div id="popup_template"/>');


                container.html( '<div class="port_header marker-title">' +marker.toGeoJSON().properties.Borderpoint +'</div>' +
                    '<div class="est_value marker-title">'+
                           'Est. Value: $' + marker.toGeoJSON().properties.Value
                           +'</div>' +
                    '<div id="est_value_sparkline" class="sparkline"></div>');

            // Delegate all event handling for the container itself and its contents to the container
            container.find('#est_value_sparkline').highcharts(lineChartOptions);


                marker.bindPopup(container[0]);
            //});






       ///END HIGHCHARTS


 });
    })
    .addTo(map);



</script>
</body>
</html>

Here is my CSV file, which I'd like to use for the highcharts as well:

    Borderpoint,Exit,Entry,Value,Type,Lat,Lon,Oct-08,Nov-08,Dec-08,Jan-09,Feb-09,Mar-09,Apr-09,May-09,Jun-09,Jul-09,Aug-09,Sep-09,Oct-09,Nov-09,Dec-09,Jan-10,Feb-10,Mar-10,Apr-10,May-10,Jun-10,Jul-10,Aug-10,Sep-10,Oct-10,Nov-10,Dec-10,Jan-11,Feb-11,Mar-11,Apr-11,May-11,Jun-11,Jul-11,Aug-11,Sep-11,Oct-11,Nov-11,Dec-11,Jan-12,Feb-12,Mar-12,Apr-12,May-12,Jun-12,Jul-12,Aug-12,Sep-12,Oct-12,Nov-12,Dec-12,Jan-13,Feb-13,Mar-13,Apr-13,May-13,Jun-13,Jul-13,Aug-13,Sep-13,Oct-13,Nov-13,Dec-13,Jan-14,Feb-14,Mar-14,Apr-14,May-14,Jun-14,Jul-14,Aug-14,Sep-14,Oct-14,Nov-14,Dec-14,Jan-15,Feb-15,Mar-15,Apr-15,May-15,Jun-15,Jul-15,Aug-15,Sep-15,Oct-15
Adriatic LNG,Liquefied Natural Gas,Italy,1.10,LNG,45.057529,12.247078,0,0,0,0,0,0,0,0,0,0,0,0,331,456,656,602,581,657,622,608,439,582,529,627,556,648,638,625,616,637,659,685,646,623,405,490,577,531,575,598,493,657,601,581,497,396,269,594,401,556,563,514,544,503,463,416,488,542,357,273,486,321,442,352,363,265,360,536,442,536,178,115,510,353,437,623,531,435,531,538,435,397,490,448,532
Almeria,Algeria,Spain,0.93,H,36.8392791,-2.4699896,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,220,257,280,219,142,280,272,256,241,297,336,347,237,288,254,196,171,222,348,362,394,449,487,570,588,532,483,513,324,482,609,607,607,621,576,613,542,520,544,412,395,533,603,557,562,552,435,403,569,516,530,586,616,569,635
Alveringem,Belgium,France,N/A,H,51.0167,2.7167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Alveringem,France,Belgium,N/A,H,51.0167,2.7167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5
Badajoz,Spain,Portugal,0.50,H,38.8789,-7.0084523,153,183,85,199,104,9,190,0,0,0,0,0,189,178,247,249,239,246,84,188,145,179,144,159,178,200,244,226,205,213,167,291,291,58,157,203,264,170,103,200,248,254,244,225,218,104,121,147,145,242,230,247,198,209,238,129,139,233,141,179,239,240,222,230,243,280,225,243,193,200,227,262,277,226,146,277,140,141,248,278,325,329,298,294,270
Badajoz,Portugal,Spain,0.50,H,38.8789,-7.0084523,0,0,0,0,12,2,0,0,0,0,0,0,3,9,10,5,4,2,0,0,0,1,22,24,22,24,48,0,0,0,0,0,0,0,0,9,0,0,0,0,0,8,1,2,0,0,0,0,0,8,12,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

What I would like to do is replace the linechart in the popup with the data from my CSV file (using data from headers Oct '08 -Oct 15 - columns 8++) but I can't find a way to add the series using omnivore CSV to GeoJSON - can someone help me plot this graph in my marker pop up? Thank you!

1

1 Answers

2
votes

Okay, so when omnivore imports your csv file, it's bringing all the data of each row as properties of a javascript object..The problem is that you want to show time series data(meaning ordered data, from your csv), but there is no inherent order to keys in a javascript object. So you can't just loop thru the keys and expect the order to be right.

So I grabbed the key order from your csv, and declared it as an array like

var keyOrder = ["Oct-08","Nov-08","Dec-08","Jan-09","Feb-09","Mar-09","Apr-09","May-09","Jun-09","Jul-09","Aug-09","Sep-09","Oct-09","Nov-09","Dec-09","Jan-10","Feb-10","Mar-10","Apr-10","May-10","Jun-10","Jul-10","Aug-10","Sep-10","Oct-10","Nov-10","Dec-10","Jan-11","Feb-11","Mar-11","Apr-11","May-11","Jun-11","Jul-11","Aug-11","Sep-11","Oct-11","Nov-11","Dec-11","Jan-12","Feb-12","Mar-12","Apr-12","May-12","Jun-12","Jul-12","Aug-12","Sep-12","Oct-12","Nov-12","Dec-12","Jan-13","Feb-13","Mar-13","Apr-13","May-13","Jun-13","Jul-13","Aug-13","Sep-13","Oct-13","Nov-13","Dec-13","Jan-14","Feb-14","Mar-14","Apr-14","May-14","Jun-14","Jul-14","Aug-14","Sep-14","Oct-14","Nov-14","Dec-14","Jan-15","Feb-15","Mar-15","Apr-15","May-15","Jun-15","Jul-15","Aug-15","Sep-15","Oct-15"];

Then I replaced your normal highchart initialization with the below code, which loops through your properties and grabs the values in the proper order.

var thisData = [];

for (var i = 0; i < keyOrder.length; i++) {
    thisData.push(parseInt(marker.feature.properties[keyOrder[i]]));
}

lineChartOptions.series = [{
    pointInterval: 24 * 3600 * 1000 * 30.41667,
    pointStart: 1393632000000,
    data: thisData
}];

You can take a look at the entire file here. This produces your popup linecharts as I believe you intended.