Kyle
Kyle

Reputation: 1183

Problems displaying external data with cal-heatmap

I'm using the D3 calendar heat-map library, cal-heatmap.

I have an external JSON file hosted on GitHub that I'm getting via a jQuery .getJSON callback function. I'm parsing the original data in the JSON file to the format compatible with cal-heatmap.

The data is parsed and converted fine, but it isn't being loaded in the calendar. I've tried using the various cal-heatmap afterLoad and afterLoadData events to load the data, but the data is still not displaying.

I have a copy of the project on JSbin.

// global data variable
var data = null;

// Convert running log JSON data into readable format for heatmap calendar
function convertRunningLog() {

    // set get URL
    var json_url = "https://raw.githubusercontent.com/kylesb/static/master/JSON/running_log.json";
    // declare object variable
    var ob = {};

    // Get running log file from repository
    $.getJSON(json_url, function(result){

        // for each data entry
        for (var i = 0; i < result.data.length; i++) {

            // get date and miles
            var apoche  = date_to_epoch(result['data'][i]['date']).toString();
            var miles   = parseFloat(result['data'][i]['miles']); 

            // set date and miles
            ob[apoche.toString()] = miles;
        }
        var json_string = JSON.stringify(ob);
        data = JSON.parse(json_string);
        console.log(data);
        return data;
    });
}

// Convert strings to date objects 
function date_to_epoch(key) { 
    var epoch_seconds = new Date(key).getTime();
    return Math.floor (epoch_seconds / 1000);
}

// initilize the calendar
// ------------------------
var cal = new CalHeatMap();
cal.init({
  itemSelector: "#cal",
  domain: "month",
  subDomain: "x_day",
  data: convertRunningLog(),
  start: new Date(2016, 0, 5),
  cellSize: 20,
  cellPadding: 5,
  domainGutter: 20,
  range: 1,
  domainDynamicDimension: false,
  previousSelector: "#example-g-PreviousDomain-selector",
  nextSelector: "#example-g-NextDomain-selector",

  subDomainTextFormat: "%d",
  legend: [0.5, 1, 1.5, 2]
});

Upvotes: 0

Views: 1464

Answers (1)

Mark
Mark

Reputation: 108512

$.getJSON is an async call. It returns immediately and invokes the result callback when it completes. As such, your convertRunningLog function returns nothing. In order for it to work, your CalHeatMap code needs to be in the result callback. Further, if you are only using jquery for the ajax call, you can use d3s corresponding method and save yourself the load time of jquery.

<!DOCTYPE html>
<html>

<head>
  <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  <script data-require="[email protected]" data-semver="2.1.4" src="https://code.jquery.com/jquery-2.1.4.js"></script>
  <link rel="stylesheet" href="https://rawgit.com/wa0x6e/cal-heatmap/master/cal-heatmap.css" />
  <script src="https://rawgit.com/wa0x6e/cal-heatmap/master/cal-heatmap.js"></script>
</head>

<body>
  <div id="cal"></div>
  <script>
    // global data variable
    var data = null;

    // Convert running log JSON data into readable format for heatmap calendar
    function convertRunningLog() {

      // set get URL
      var json_url = "https://raw.githubusercontent.com/kylesb/static/master/JSON/running_log.json";
      // declare object variable
      var ob = {};

      // Get running log file from repository
      d3.json(json_url, function(error, result) {
        
        // for each data entry
        for (var i = 0; i < result.data.length; i++) {

          // get date and miles
          var apoche = date_to_epoch(result['data'][i]['date']).toString();
          var miles = parseFloat(result['data'][i]['miles']);

          // set date and miles
          ob[apoche.toString()] = miles;
        }
        
        var json_string = JSON.stringify(ob);
        data = JSON.parse(json_string);

        var cal = new CalHeatMap();
        cal.init({
          itemSelector: "#cal",
          domain: "month",
          subDomain: "x_day",
          data: data,
          start: new Date(2016, 0, 5),
          cellSize: 20,
          cellPadding: 5,
          domainGutter: 20,
          range: 1,
          domainDynamicDimension: false,
          previousSelector: "#example-g-PreviousDomain-selector",
          nextSelector: "#example-g-NextDomain-selector",

          subDomainTextFormat: "%d",
          legend: [0.5, 1, 1.5, 2]
        });


      });
    }

    // Convert strings to date objects 
    function date_to_epoch(key) {
      var epoch_seconds = new Date(key).getTime();
      return Math.floor(epoch_seconds / 1000);
    }

    convertRunningLog();
    
  </script>
</body>

</html>

Upvotes: 1

Related Questions