1

I have a javascript array of objects, where some objects have a key called "note". Others do not have this property.

I've created an html table from the javascript array, where (when available) the note numbers are appended to the main value in the table cell that correspond's to an object's year and country.

I want to print a corresponding definition below the table for each note, depending on the note's value. The definitions will come from a separate js array-- I've included an excerpt. There are about 70 definitions in all, and I just want to print the ones where the "note" value exists within the table. Here is a screenshot of what this would look like:

enter image description here

I'm a bit stuck in thinking how to do this. Any thoughts? I appreciate it!

Here is a jsfiddle.

Full code below, too:

<!DOCTYPE html>
<html>
<head>
    <style>
        body{
            font-family:Arial, sans-serif;
            font-size:14px;
        }
        table{
            border-spacing:0;
            padding:0;
        }
        #buildcontent{
            margin-left:100px;
            margin-top:20px;
            margin-right:100px;
        }
        #buildcontent table#years{
            clear:both;
        }
        #buildcontent table#countries{
            width:100%;
        }
        thead#years td{
            border-top:1px solid #ddd;
          border-bottom:0px;
          font-weight:bold;
            padding-top:3px;
            height:18px;
            padding-left:5px;
            padding-right:35px;
        }
        th{
          text-align:left;
          font-weight:normal !important;
          border-top:1px solid #ddd;
          border-left:1px solid #ddd;
          border-bottom:1px solid #ddd;
            height:25px;
            padding-left:5px;
            width: 90px;
        }
        td{
          border:1px solid #ddd;
            width:30px;
            height:25px;
            padding-left:5px;
        }
        tr.row-odd,
        .row-odd{
            background: #eee;
        }
        .note{
            color:steelblue;
            font-size:10px;
        }
    </style>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>
    <title>table with notes</title>
</head>
<body>
    <div id="content">
    </div>
<script>

fullData = [
    {
        "id": 103006,
        "iso3": "AFG",
        "country": "Afghanistan",
        "year": 2014,
        "value": 3.23,
        "note": 70011
    },
    {
        "id": 103006,
        "iso3": "ALB",
        "country": "Albania",
        "year": 2014,
        "value": 9.256,
        "note": 69011
    },
    {
        "id": 103006,
        "iso3": "DZA",
        "country": "Algeria",
        "year": 2014,
        "value": 7.611,
        "note": 69011
    },
    {
        "id": 103006,
        "iso3": "AND",
        "country": "Andorra",
        "year": 2014,
        "value": 9.582,
        "note": 69111
    },
    {
        "id": 103006,
        "iso3": "AGO",
        "country": "Angola",
        "year": 2014,
        "value": 4.726,
        "note": 69011
    },
    {
        "id": 103006,
        "iso3": "ATG",
        "country": "Antigua and Barbuda",
        "year": 2014,
        "value": 9.236,
        "note": 69011
    },
    {
        "id": 103006,
        "iso3": "ARG",
        "country": "Argentina",
        "year": 2014,
        "value": 9.834,
        "note": 69411
    },
    {
        "id": 103006,
        "iso3": "ARM",
        "country": "Armenia",
        "year": 2014,
        "value": 10.87,
        "note": 70011
    },
    {
        "id": 103006,
        "iso3": "AUS",
        "country": "Australia",
        "year": 2014,
        "value": 12.963
    },
    {
        "id": 103006,
        "iso3": "AUT",
        "country": "Austria",
        "year": 2014,
        "value": 10.834
    },
    {
        "id": 103006,
        "iso3": "AZE",
        "country": "Azerbaijan",
        "year": 2014,
        "value": 11.16
    },
    {
        "id": 103006,
        "iso3": "BHS",
        "country": "Bahamas",
        "year": 2014,
        "value": 10.945
    },
    {
        "id": 103006,
        "iso3": "BHR",
        "country": "Bahrain",
        "year": 2014,
        "value": 9.419
    },
    {
        "id": 103006,
        "iso3": "BGD",
        "country": "Bangladesh",
        "year": 2014,
        "value": 5.073
    },
    {
        "id": 103006,
        "iso3": "BRB",
        "country": "Barbados",
        "year": 2014,
        "value": 10.457
    },
    {
        "id": 103006,
        "iso3": "BLR",
        "country": "Belarus",
        "year": 2014,
        "value": 11.977
    },
    {
        "id": 103006,
        "iso3": "BEL",
        "country": "Belgium",
        "year": 2014,
        "value": 11.273
    },
    {
        "id": 103006,
        "iso3": "BLZ",
        "country": "Belize",
        "year": 2014,
        "value": 10.488
    },
    {
        "id": 103006,
        "iso3": "BEN",
        "country": "Benin",
        "year": 2014,
        "value": 3.3
    },
    {
        "id": 103006,
        "iso3": "BTN",
        "country": "Bhutan",
        "year": 2014,
        "value": 3.01
    },
    {
        "id": 103006,
        "iso3": "BOL",
        "country": "Bolivia (Plurinational State of)",
        "year": 2014,
        "value": 8.154
    },
    {
        "id": 103006,
        "iso3": "BIH",
        "country": "Bosnia and Herzegovina",
        "year": 2014,
        "value": 8.326
    },
    {
        "id": 103006,
        "iso3": "BWA",
        "country": "Botswana",
        "year": 2014,
        "value": 8.87
    },
    {
        "id": 103006,
        "iso3": "BRA",
        "country": "Brazil",
        "year": 2014,
        "value": 7.66
    },
    {
        "id": 103006,
        "iso3": "BRN",
        "country": "Brunei Darussalam",
        "year": 2014,
        "value": 8.77
    },
    {
        "id": 103006,
        "iso3": "BGR",
        "country": "Bulgaria",
        "year": 2014,
        "value": 10.566
    },
    {
        "id": 103006,
        "iso3": "BFA",
        "country": "Burkina Faso",
        "year": 2014,
        "value": 1.374
    },
    {
        "id": 103006,
        "iso3": "BDI",
        "country": "Burundi",
        "year": 2014,
        "value": 2.686
    },
    {
        "id": 103006,
        "iso3": "CPV",
        "country": "Cabo Verde",
        "year": 2014,
        "value": 4.683
    },
    {
        "id": 103006,
        "iso3": "KHM",
        "country": "Cambodia",
        "year": 2014,
        "value": 4.369
    },
    {
        "id": 103006,
        "iso3": "CMR",
        "country": "Cameroon",
        "year": 2014,
        "value": 5.96
    },
    {
        "id": 103006,
        "iso3": "CAN",
        "country": "Canada",
        "year": 2014,
        "value": 13.004
    },
    {
        "id": 103006,
        "iso3": "CAF",
        "country": "Central African Republic",
        "year": 2014,
        "value": 4.224
    },
    {
        "id": 103006,
        "iso3": "TCD",
        "country": "Chad",
        "year": 2014,
        "value": 1.929
    },
    {
        "id": 103006,
        "iso3": "CHL",
        "country": "Chile",
        "year": 2014,
        "value": 9.787
    },
    {
        "id": 103006,
        "iso3": "CHN",
        "country": "China",
        "year": 2014,
        "value": 7.54
    },
    {
        "id": 103006,
        "iso3": "COL",
        "country": "Colombia",
        "year": 2014,
        "value": 7.35
    },
    {
        "id": 103006,
        "iso3": "COM",
        "country": "Comoros",
        "year": 2014,
        "value": 4.602
    },
    {
        "id": 103006,
        "iso3": "COG",
        "country": "Congo",
        "year": 2014,
        "value": 6.09
    },
    {
        "id": 103006,
        "iso3": "COD",
        "country": "Congo (Democratic Republic of the)",
        "year": 2014,
        "value": 6.01
    },
    {
        "id": 103006,
        "iso3": "CRI",
        "country": "Costa Rica",
        "year": 2014,
        "value": 8.368
    },
    {
        "id": 103006,
        "iso3": "CIV",
        "country": "Côte d'Ivoire",
        "year": 2014,
        "value": 4.26
    },
    {
        "id": 103006,
        "iso3": "HRV",
        "country": "Croatia",
        "year": 2014,
        "value": 11.027
    },
    {
        "id": 103006,
        "iso3": "CUB",
        "country": "Cuba",
        "year": 2014,
        "value": 11.514
    },
    {
        "id": 103006,
        "iso3": "CYP",
        "country": "Cyprus",
        "year": 2014,
        "value": 11.619
    },
    {
        "id": 103006,
        "iso3": "CZE",
        "country": "Czech Republic",
        "year": 2014,
        "value": 12.32
    }
];
definitions = [
    {
        "note": 69111,
        "def": "This is the first definition."
    },
    {
        "note": 70011,
        "def": "This is the second definition."     
    }
];

        // add years for select indicator
        var nestyr = d3.nest()
            .key(function(d) { return d.year; })
            .sortKeys(d3.ascending)
            .map(fullData);

        var yearstring = Object.keys(nestyr);

        var width = 200, height = 25;
        var minInd = d3.min(fullData, function(d) { return d.value;} )
        var maxInd = d3.max(fullData, function(d) { return d.value;} )

        var tableData = [],
            countries = {};
            fullData.forEach(function (d) {
            var country = countries[d.country];
            if (!country) {
                tableData.push(country = countries[d.country] = {});
                }
                if ( d.note ){
                      country[d.year] = d.value + " <span class='note'>" + d.note + "</span>";
                      countries[d.country]['note'] = d.note;
                } else{
                        country[d.year] = d.value;
                }
            countries[d.country].Country = d.country;
        });

        yearstring.unshift("Country");

        // render the table(s)
        tabulate(tableData, yearstring);

function tabulate(newData, columns) {
            var table = d3.select('#content').append('table')
            var thead = table.append('thead')
            var tbody = table.append('tbody');

      var type = d3.nest()
              .key(function(d) { return d.country; })
                .sortKeys(d3.ascending)
              .entries(fullData);

            // append the header row
            thead.append('tr')
              .selectAll('th')
              .data(columns).enter()
              .append('th')
                .text(function (column) { return column; });

            // create a row for each object in the data
            var rows = tbody.selectAll('tr')
              .data(newData)
              .enter()
              .append('tr');

              // add stripes to the table
            rows.attr("class", function(d, i){ if (i++ % 2 === 0){return 'row-even'}else {return 'row-odd'}});

            // create a cell in each row for each column
            var cells = rows.selectAll('td')
              .data(function (row) {
                return columns.map(function (column) {
                  return {column: column, value: row[column]};
                });
              })
              .enter()
              .append('td')
                    .attr("class", function (d,i) { return columns[i]; })
                .html(function (d) { return d.value; });

          return table;
};


</script>
</body>
</html>
3
  • I don't really get what you want, could you give us a example output? Commented Dec 4, 2015 at 19:51
  • 1
    I added a screenshot showing desired output and edited my question. Thanks. Commented Dec 4, 2015 at 20:36
  • Would it be possible to switch from an array to an object for the "definitions"? that would remove much overhead when looking for a key. Commented Dec 4, 2015 at 20:50

2 Answers 2

1

It would make things a lot shorter and easier, more efficient, if we switched to an object instead of an array for the notes. This way you can easily query for the key in question.

definitions = [
    {
        "note": 69111,
        "def": "This is the first definition."
    },
    {
        "note": 70011,
        "def": "This is the second definition."     
    }
];

to

definitions = {
      "69111": "This is the first definition.",
        "70011": "This is the second definition."
};

When you perform your check for a note (and one is found), use it as the key for the object. First, let's set up a string outside the loop that will contain our footnotes, which we can then fill within the loop.

Then, to prevent the generation of several instances of the same note (where countries share the same note key), we should make a list of the notes we have, also outside of the loop, which we will update every time we add a note.

Then we can add the desired text to the string that holds our notes (if it actually exists), and when the loop is over, append it to the content.

var notes="";   // this holds our string, containing all the needed footnotes, but not more
var added=[];   // a list of the footnotes we've already included

...and inside loop:

if ( d.note ){
country[d.year] = d.value + " <span class='note'>" + d.note + "</span>";
countries[d.country]['note'] = d.note;
if(added.indexOf(d.note)==-1){  // only when we HAVEN'T added it yet...
if(undefined!=definitions[d.note]){   // ...and there is actually a note available...
notes+=definitions[d.note]+"<br />";  // add it to the string
added.push(d.note);  // add the key to the list, so we won't add it again later
}
}

This works: http://jsfiddle.net/svArtist/txc16240/

Sign up to request clarification or add additional context in comments.

1 Comment

This works really well. Thank you for taking the time to explain it so well!
1

If you're not able to change the definitions Javascript, as Ben Philipp suggested, I made the following changes:

  1. A plain object to store the IDs used var usedDefinitions = {};
  2. After reading each note, create its key in the object usedDefinitions[d.note] = true;
  3. After tabulating, running a simple loop to check which definitions you should paint, like this:

--

var usedDefinitionsArray = [];
for(var definition in definitions){
  if(usedDefinitions[definitions[definition].note]){
    usedDefinitionsArray.push(definitions[definition].note+': '+definitions[definition].def);
  }
}
$('#content').append(usedDefinitionsArray.join('<br>'));

Here you go: http://jsfiddle.net/8crumgu3/4/

2 Comments

I was able to change the definitions to an object, but thank you for providing this solution too. It's good to see how I could use this approach.
@sprucegoose Ok, cool, no problem. As long as it works for you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.