<commit_before>
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="stylesheet" href="https://use.typekit.net/ezo4zbn.css">
<style type="text/css">
body {
  margin: 20px;
  font-family: acumin-pro-condensed, arial, sans;
  line-height: 1.3em;
  width: 1180px;
}

h3 {
  margin: 0 0 4px 4px;
  line-height: 1.05em;
}

.label {
  font-size: 18px;
}

.legend{
  opacity: 1;
  transition: opacity 0.3s;
}

.axis text {
  font-size: 14px;
  fill: #333;
}

.axis path,
.axis line {
  fill: none;
  stroke-width:1px;
  stroke: #e7e7e7;
}

circle {
  stroke: #fff;
  stroke-width: 1px;
  opacity: 0.8;
}

.bubble {
  opacity: 1;
  transition: opacity 0.3s;
}

path.country {
  opacity: 1;
  transition: opacity 0.3s;
}

.stroke {
  fill: none;
  stroke: #bbb;
  stroke-width: 2px;
}

.fill {
  fill: #fff;
}

.graticule {
  fill: none;
  stroke: #777;
  stroke-width: 0.5px;
  stroke-opacity: 0.5;
}

.land {
  fill: #ddd;
}

.boundary {
  fill: none;
  stroke: #fff;
  stroke-width: 0.5px;
}
#tooltip {
  width: 480px;
  padding: 6px 12px;
}
#tooltip h3 {
  margin: 0 0 12px 0;
}

.multiple {
  width: 180px;
  height: 120px;
  float: left;
  position: relative;
  background: #fcfcfc;
  border: 1px solid #d0d0d0;
  margin: 4px;
  cursor: pointer;
}

.multiple h3 {
  position: relative;
  font-size: 16px;
  width: 180px;
  z-index: 5;
  margin: 1px 0 0 5px;
}

.multiple svg {
  position: absolute;
  top: 40px;
  z-index: 4;
}

.multiple path.spark {
  stroke-width: 2px;
  stroke: #7D0063;
  fill: none;
}

#year-slider {
  margin: 0 0px 0 0;
}
</style>
<body>
<h1>Exploring Country-level GHG-GDP Divergence</h1>
<div style="border: 1px solid #d0d0d0; display: inline-block; padding: 8px 16px; font-size: 18px;">
  Time Range &nbsp;
  <input type="range" min=2000 max=2016 step=1 value=2000 id="year-slider" style="width: 200px">
</div><br/>
<div id="tooltip" style="display: none; position: absolute; z-index: 100; pointer-events: none; background: rgba(255,255,255,0.8); border: 2px solid #d0d0d0;">
</div>
</body>
<script src="//d3js.org/d3.v4.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>

<script>

var year = 2000;
var active_metric = "CO2";
var active_ymetric = "GDP";
var clicked_country = null;

var exclude = ["AFG", "COD", "LBY", "LCA", "LIE", "LSO", "MCO", "MDA", "NRU", "PRK", "ROU", "SMR", "SOM", "SSD", "SYR", "TLS", "TUV", "WLD"];

var metrics = ["index_territorial", "consumption_co2", "GDP", "CO2", "abs_carbon", "life_expectancy_at_birth_total_years_sp_dyn_le00_in", "individuals_using_the_internet_of_population_it_net_user_z", "employment_to_population_ratio_15_total_modeled_ilo_est", "abs_gdp", "access_to_electricity_of_population_eg_elc_accs_zs", "household_final_consumption_expenditure_per_capita_constant_20", "merchandise_imports_current_us_tm_val_mrch_cd_wt", "industry_value_added_constant_2010_us_nv_ind_totl_kd", "net_migration_sm_pop_netm", "total_natural_resources_rents_of_gdp_ny_gdp_totl_rt_zs", "renewable_energy_consumption_of_total_final_energy_consumpti", "urban_population_of_total_sp_urb_totl_in_zs", "proportion_of_seats_held_by_women_in_national_parliaments"];

var format = d3.format(".0%");

var default_format = d3.format(",.2r");

var format_si = d3.format(".2s");

function format_abbrev(x) {
  var s = format_si(x);
  switch (s[s.length - 1]) {
    case "G": return s.slice(0, -1) + "B";
  }
  return s;
}

var metric_lookup = {
  "GDP": {
    "key": "GDP",
    "name": "GDP Change",
    "units": "",
    "scale": "d3.scaleLinear",
    "format": format,
    "extent": [-0.3,0.3],
    "longextent": [-0.5,3]
  },
  "CO2": {
    "key": "CO2",
    "name": "Fossil fuels and cement production emissions by country (territorial, GCB)",
    "units": "change based on Mt C",
    "scale": "d3.scaleLinear",
    "format": format,
    "extent": [-0.3,0.3],
    "longextent": [-0.5,3]
  },
  "abs_carbon": {
    "key": "abs_carbon",
    "name": "Fossil fuels and cement production emissions by country (territorial, GCB)",
    "units": "Mt C",
    "scale": "d3.scaleLinear",
    "format": default_format,
    "extent": [0,10000],
    "longextent": [-0.5,3]
  },
  "consumption_co2": {
    "key": "consumption_co2",
    "name": "Consumption emissions (GCB)",
    "units": "change based on Mt C",
    "scale": "d3.scaleLinear",
    "format": format,
    "extent": [-0.3,0.3],
    "longextent": [-0.5,3]
  },
  "index_territorial": {
    "key": "index_territorial",
    "name": "Territorial ICGGD",
    "units": "",
    "scale": "d3.scaleLinear",
    "format": default_format,
    "extent": [-1,2],
    "longextent": [-0.5,3]
  },
  "life_expectancy_at_birth_total_years_sp_dyn_le00_in": {
    "key": "life_expectancy_at_birth_total_years_sp_dyn_le00_in",
    "name": "Life expectancy at birth, total",
    "units": "years",
    "scale": "d3.scaleLinear",
    "format": default_format
  },
  "individuals_using_the_internet_of_population_it_net_user_z": {
    "key": "individuals_using_the_internet_of_population_it_net_user_z",
    "name": "Individuals using the Internet",
    "units": "of population",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "employment_to_population_ratio_15_total_modeled_ilo_est": {
    "key": "employment_to_population_ratio_15_total_modeled_ilo_est",
    "name": "Employment to population ratio, 15+, total (modeled ILO estimate)",
    "units": "",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "abs_gdp": {
    "key": "abs_gdp",
    "name": "GDP",
    "units": "constant 2010 US$",
    "scale": "d3.scaleLinear",
    "format": format_si,
    "extent": [0,2e13],
    "longextent": [1,1e15]
  },
  "access_to_electricity_of_population_eg_elc_accs_zs": {
    "key": "access_to_electricity_of_population_eg_elc_accs_zs",
    "name": "Access to electricity",
    "units": "of population",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "household_final_consumption_expenditure_per_capita_constant_20": {
    "key": "household_final_consumption_expenditure_per_capita_constant_20",
    "name": "Household final consumption expenditure per capita",
    "units": "constant 2010 US$",
    "scale": "d3.scaleLinear",
    "format": default_format
  },
  "merchandise_imports_current_us_tm_val_mrch_cd_wt": {
    "key": "merchandise_imports_current_us_tm_val_mrch_cd_wt",
    "name": "Merchandise imports",
    "units": "change of current US$",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "industry_value_added_constant_2010_us_nv_ind_totl_kd": {
    "key": "industry_value_added_constant_2010_us_nv_ind_totl_kd",
    "name": "Industry, value added",
    "units": "change of constant 2010 US$",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "net_migration_sm_pop_netm": {
    "key": "net_migration_sm_pop_netm",
    "name": "Net migration",
    "units": "number of persons",
    "scale": "d3.scaleLinear",
    "format": format_abbrev
  },
  "total_natural_resources_rents_of_gdp_ny_gdp_totl_rt_zs": {
    "key": "total_natural_resources_rents_of_gdp_ny_gdp_totl_rt_zs",
    "name": "Total natural resources rents",
    "units": "of GDP",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "renewable_energy_consumption_of_total_final_energy_consumpti": {
    "key": "renewable_energy_consumption_of_total_final_energy_consumpti",
    "name": "Renewable energy consumption",
    "units": "change of share of total final energy consumption",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "urban_population_of_total_sp_urb_totl_in_zs": {
    "key": "urban_population_of_total_sp_urb_totl_in_zs",
    "name": "Urban population",
    "units": "of total",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "proportion_of_seats_held_by_women_in_national_parliaments": {
    "key": "proportion_of_seats_held_by_women_in_national_parliaments",
    "name": "Proportion of seats held by women in national parliaments",
    "units": "of total seats",
    "scale": "d3.scaleLinear",
    "format": format
  }
}

var margin = { top: 50, right: 20, bottom: 50, left: 50 };
var width = 530 - margin.left - margin.right;
var height = 560 - margin.top - margin.bottom;

var lookup = {};

var tooltip = d3.select("#tooltip");

var map_width = 620;
var map_height = 560;

var svg = d3.select("body")
  .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var map_container = d3.select("body")
  .append("div")
    .style("width", map_width + "px")
    .style("height", map_height + "px")
    .style("position", "relative")
    .style("display", "inline-block");

var map_svg = map_container
  .append("svg")
    .attr("width", map_width)
    .attr("height", map_height);

map_container.append("a")
  .text("Colored by Territorial ICGGD Value")
  .attr("href", "../scatterplot/04_divergence_final.html")
  .style("position", "absolute")
  .style("top", (map_height-40) + "px")
  .style("left", (map_width/2-40) + "px")

d3.select("body")
  .append("h3")
  .attr("class", "country-label")
  .text(function(d) { return "Global"; });

d3.select("body")
  .append("div")
  .attr("id", "multiples");

var multiples = d3.select("#multiples")
  .selectAll("div")
  .data(metrics)
  .enter().append("div")
  .attr("class", "multiple")

multiples.append("h3")
  .text(function(d) { return metric_lookup[d].name; });

multiples.append("h3")
  .attr("class", function(d) { return "multiple-value multiple-value-" + d })
  .text(function(d) { return ""; });

multiples.append("svg")
  .attr("height", "120px")
  .attr("width", "180px")

var xscale = d3.scaleLinear()
  .domain([-0.5,0.5])
  .range([0,width])
  .clamp("true");

var yscale = d3.scaleLinear()
  .domain([-0.5,0.5])
  .range([height,0])
  .clamp("true");

var radius = d3.scaleSqrt()
  .range([2.5,20])
  .domain([0, 3000]);

var color = d3.scaleThreshold()
  .domain([-0.05, -0.02, 0, 0.05, 0.1])
  .range(["#d73027","#f46d43","#fdae61","#abd9e9","#74add1","#4575b4"]);
  
var colorMap = d3.scaleThreshold()
  .domain([-0.05, 0, 0.5, 0.75, 1])
  .range(["#d73027","#f46d43","#fdae61","#abd9e9","#74add1","#4575b4"]);

var xAxis = d3.axisBottom()
  .tickSize(-height)
  .tickFormat(function(d) {
//    if (d == -0.25) return "<" + format(d);
//    if (d == 0.25) return ">" + format(d);
    return format(d);
  })
  .scale(xscale);

var yAxis = d3.axisLeft()
  .tickFormat(function(d) {
//    if (d == 0) { return "N/A"; }
    return format(d);
  })
  .tickSize(-width)
  .scale(yscale)


/* Map */

var projection = d3.geoTimes()
    .scale((map_width - 4) / (1.5 * Math.PI))
    .translate([map_width / 2, map_height / 2])
    .precision(0.1);

var path = d3.geoPath()
    .projection(projection);

var graticule = d3.geoGraticule();

var isoLookup = {};
var idLookup = {};

var selected_country = "WLD";

map_svg.append("defs").append("path")
    .datum(graticule.outline())
    .attr("id", "sphere")
    .attr("d", path);

map_svg.append("use")
    .attr("class", "stroke")
    .attr("xlink:href", "#sphere");

map_svg.append("use")
    .attr("class", "fill")
    .attr("xlink:href", "#sphere");

map_svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);



// The rest of the code follows this function call
// which ensures the data is loaded before graphing it
d3.queue()
  .defer(d3.csv, "../final-data/GDP\ annual\ change\ 2000-15\ 9.28.17.csv")
  .defer(d3.csv, "../final-data/CO2 annual change data 2000-2015 9.18.17.csv")
  .defer(d3.csv, "../final-data/wb_data\ 9.29.17.csv")
  .defer(d3.csv, "../final-data/absolute\ country\ GDP\ 1999-2015.csv")
  .defer(d3.csv, "../final-data/absolute\ country\ annual\ carbon\ emissions\ 2000-2015.csv")
  .defer(d3.csv, "../final-data/consumption\ CO2\ annual\ change\ data\ 2000-2015\ 9.28.17.csv")
  .defer(d3.csv, "../data/Index\ calculated\ with\ Territorial\ Emissions\ and\ GDP.csv")
  .await(function(error, raw_gdp, raw_co2, wb_data, abs_gdp, abs_carbon, consumption_co2, index_territorial) {


    // Fill in lookup table

    raw_gdp.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["GDP"] = d;
    });
    raw_co2.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["CO2"] = d;
    });
    abs_gdp.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["abs_gdp"] = d;
    });
    abs_carbon.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["abs_carbon"] = d;
    });
    consumption_co2.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["consumption_co2"] = d;
    });
    index_territorial.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["index_territorial"] = d;
    });

    wb_data.forEach(function(d) {
      metrics.forEach(function(metric) {
        if (metric in d) {
          lookup[d["country_code"]] = lookup[d["country_code"]] || {};
          lookup[d["country_code"]][metric] = lookup[d["country_code"]][metric] || {};
          lookup[d["country_code"]][metric][d.year] = d[metric];
        }
      });
    });



    // set up xscale for plumb lines
    // logic for calculating extent, choosing preset if available

    var multiple_xscale = d3.scaleLinear().domain([2000,2015]).range([12, 168]);
    
    metrics.forEach(function(metric) {
      var calculated_extent = d3.extent(wb_data.filter(function(d) { return d.year.indexOf("-") < 0 && d.country_code !== "WLD"; }), function(d) { return +d[metric]; })
      var calculated_long_extent = d3.extent(wb_data.filter(function(d) { return d.year.indexOf("-") > -1 && d.country_code !== "WLD"; }), function(d) { return +d[metric]; })
      
      // perhaps, won't need longextent? so don't set it as it's own variable?
      // preset is the default, if it is not present, will use the calcualted extent / long_extent
      var extent = metric_lookup[metric].extent = metric_lookup[metric].extent || calculated_extent;
      metric_lookup[metric].longextent = metric_lookup[metric].longextent || calculated_long_extent;
      

      var yscale = metric_lookup[metric].yscale = d3.scaleLinear().domain(extent).range([70,6]).clamp(true);
      metric_lookup[metric].scale = d3.scaleLinear().domain(extent).range([0,width]).clamp(true);

      // draws the plumb line
      // *QQ* and the yAxis? confused because don't see
      metric_lookup[metric].line = d3.line()
        .defined(function(d) { return d.value != "" && !isNaN(d.value); })
        .x(function(d) { return multiple_xscale(d.year); })
        .y(function(d) { return yscale(d.value); });
      metric_lookup[metric].yAxis = d3.axisLeft()
        .tickFormat(metric_lookup[metric].format)
        .tickSize(-200)
        .scale(metric_lookup[metric].scale)
    });

    // Create spark lines
    // *QQ* not quite sure how spark lines are associated with metric_lookup[metric].line

    multiples.select("svg")
      .append("path")
      .attr("class", "spark")

    // Create tracking lines & years
    multiples.select("svg")
      .append("line")
      .attr("class", "plumb")
      .attr("x1", multiple_xscale(2000))
      .attr("x2", multiple_xscale(2000))
      .attr("y1", 6)
      .attr("y2", 70)
      .style("stroke", "#bbb")

    multiples.select("svg")
      .append("text")
      .attr("class", "multiple-year-label")
      .attr("x", multiple_xscale(2000))
      .attr("y", 78)
      .style("text-anchor", "middle")
      .style("stroke", "#bbb")
      .style("font-size", "12px")
      .text(2000)



      // Starting to set up the Scatterplot
      // grab countries, set axes and tick text location

    // Grab all countries
    var countries = d3.keys(lookup);

    // Draw X axis
    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .attr("class", "x axis")
      .call(xAxis);

    // Place text relative to the X axis
    svg.selectAll(".x.axis text")
      .attr("y", 8);

    // Draw Y Axis
    svg.append("g")
      .attr("transform", "translate(0,0)")
      .attr("class", "y axis")
      .call(yAxis);

    // *QQ* no placing .y.axis text?

    // Drawing middle lines - xaxis and yaxis
    // held constant on xscale(0) or yscale(0)
    svg
      .append("line")
      .attr("class", "dark-line-1")
      .style("stroke", "#777")
      .style("stroke-width", 1)
      .attr("x1", xscale(0))
      .attr("x2", xscale(0))
      .attr("y1", 0)
      .attr("y2", height)

    svg
      .append("line")
      .attr("class", "dark-line-2")
      .style("stroke", "#777")
      .style("stroke-width", 1)
      .attr("x1", 0)
      .attr("x2", width)
      .attr("y1", yscale(0))
      .attr("y2", yscale(0))

      // TO DO
      // Current implementation of clicked_country
      // needs additional logic to stop actions in
      // mouseover and mouseout if there is an active clicked_country
      // EDIT
      // Used if(clicked_country){return clicked_country} to shortcircuit


    // draw bubbles
    var group = svg.selectAll("g.bubble")
      .data(countries.filter(function(d) { 
        // only include those not in the exclude list
        return d && exclude.indexOf(d) == -1;
      }))
      .enter().append("g")
      .sort(function(a,b) {
        // if function returns positive, b was bigger than a
        // used for sorting, defaults to descending
        // sort by absolute carbon amount
        // https://stackoverflow.com/questions/15704128/how-can-i-efficiently-convert-data-from-string-to-int-within-a-d3-method-chain
        // + converts a numeric string into a number
        return +lookup[b]["abs_carbon"][year].replace(",","") - (+lookup[a]["abs_carbon"][year].replace(",",""));
      })
      .attr("class", "bubble")
      .attr("transform", function(d) {
        // scale x, y location by value of the x metric in a given year, in country d
        return "translate(" + xscale(+lookup[d][active_metric][year]) + "," + yscale(+lookup[d][active_ymetric][year]) + ")"
      });

    group
      .append("circle")
      // the circle gets drawn here... above was only a reference
      // to the center of a bubble element
      .attr("r", function(d) {
        return radius(+lookup[d]["abs_carbon"][year].replace(",",""));
      })
      .style("fill", function(d) {
        return "#777";
      })
      // on click, announce name in console
      .on("click", function(d) {
        clicked_country = d
        console.log(d); 

        // TO DO 
        // expand this function to set chosen_country
        // same behavior as mouseover
        // will persist until user clicks on another country
        // or a background svg in front of everything as a click wall

      })
      .on("mouseover", function(d) {

        // rename d as country for clarify
        var country = d;

        // if country is explicitly excluded, or doesn't show up in lookup return gray
        // lookup is built from all of the wb_data 
        // *QQ* the second check may be unnecessary... will it ever be true?
        if (exclude.indexOf(country) > -1) { return "#eaeaea"; }
        if (!(country in lookup)) { return "#eaeaea"; }

        // Adding this as an attempt to shortcircuit mouseover behaviir
        // if there is an active clicked_country
        if (clicked_country) { return clicked_country}

        // *QQ* The following code should only run if there was no active clicked_country
        selected_country = country;

        // store data associated with this country
        // must be in data load await() callback to ensure data is ready for this step
        var datum = lookup[country];

        // change labels to be mousedover country's name
        // *QQ* it seems like idLookup is being created below, after loading the map
        // Why is this OK?
        d3.selectAll(".country-label").text(idLookup[d].name);

        // redraw the map to highlight the country being mousedover
        map_svg.selectAll("path.country")
          .style("opacity", function(p) {
            return p.id == String(+idLookup[d]["country-code"]) ? 1 : 0.3;
          })
          .style("stroke", function(p) {
            return p.id == String(+idLookup[d]["country-code"]) ? "#222" : null;
          });
          
        // Set text for tooltip

        // TO DO - Done?
        // cut down what gets displayed here to only be the x- and y-metric
        // *QQ* is the addition below sufficient?

        tooltip.style("display", null).html("");
        tooltip.append("h3").text(idLookup[d].name);
        d3.keys(datum).forEach(function(metric) {
          // Added the && and || clause
          if (datum[metric][year] && (metric == active_ymetric || metric == active_metric) ) {
            var div = tooltip.append("div");
            div.append("span").text(metric_lookup[metric].name + ": ");
            div.append("span").text(metric_lookup[metric].format(+datum[metric][year]));
            div.append("span").text(" " + metric_lookup[metric].units);
          }
        });

        // uses the .raise() function to bring a point above others
        svg.selectAll(".bubble")
          .filter(function(p) {
            return country == p;
          })
          .raise();
        // setting style of circle to show bold line around circumference
        svg.selectAll(".bubble circle")
          .style("stroke", function(p) {
            return country == p ? "#111" : null;
          })
          .style("stroke-width", function(p) {
            return country == p ? "2px" : null;
          });

        // outsource this operation to this function
        updateDataValues();
      })
      // Cause tooltip to follow mouse as user moves
      .on("mousemove", function(d) {
        return tooltip.style("top", (d3.event.pageY-52) + "px").style("left", (d3.event.pageX+18) + "px");
      })
      // Right now, will trigger back to WLD

      // TO DO
      // consider how onclick, onmouseover, and onmouseout interact
      // onclick (country): sets selected_country to chosen country
      //// clicked_country = d

      // onmouseover: sets selected_country to chosen country
      //// selected_country = clicked_country || d
      // onmouseout: sets selected_country back to WLD
      //// selected_country = clicked_country || d
      // onclick (canvas of scatterplot or map): sets selected_country back to WLD
      //// clicked_country = null

      .on("mouseout", function() {

        // Attempt to short-circuit if there is an active clicked_country
        if (clicked_country) { return clicked_country; }

        // The following code should only run if there is no active clicked_country
        selected_country = clicked_country || "WLD";
        d3.selectAll(".country-label").text("Global");
        map_svg.selectAll("path.country")
          .style("opacity", 1)
          .style("stroke", null);
        svg.selectAll(".bubble circle")
          .style("stroke", function(p) {
            return null;
          })
          .style("stroke-width", function(p) {
            return null;
          });

        d3.selectAll("path.spark")
          .attr("d", "");

        tooltip.style("display", "none");

        updateDataValues();
      })


      // Label displaying which y-metric is active
    svg.append("text")
      .attr("x", 6)
      .attr("y", -5)
      .attr("class", "label active-ymetric-label")
      .text(metric_lookup[active_ymetric].name + " (" + metric_lookup[active_ymetric].units+ ")");
      // Label displaying current years being shown
    var year_label = svg.append("text")
      .attr("x", width-2)
      .attr("y", -5)
      .attr("class", "label")
      .attr("text-anchor", "end")
      .style("font-weight", "bold")
      .style("font-size", "36px")
      .text("1999-2000");
      // Label showing which x-metric is active
    svg.append("text")
      .attr("x", width-2)
      .attr("y", height-6)
      .attr("text-anchor", "end")
      .attr("class", "label active-metric-label")
      .text(metric_lookup[active_metric].name + " (" + metric_lookup[active_ymetric].units+ ")");



    /* Map */

    // TO DO
    // update this to reference the official WRI geojson map bounds
    // check commands which use topojson...

    // *QQ* Convert wri-bounds to topojson? 
    // Does make them smaller, then don't have to chage the add code :)

    d3.json("../data/wri-bounds-topo.json", function(error, world) {
      if (error) throw error;

      // Experimental logs
      console.log(world)
      console.log(world.objects)
      console.log(world.objects.countries)
      console.log(topojson.feature(world, world.objects.countries).features)

      map_svg.selectAll("path.country")
        .data(topojson.feature(world, world.objects.countries).features)
        // Try this!
        // If it doesn't work... figure out how this wri-bounds json is passed 
        // .data(world.iso_a3)
        .enter().append("path")
          .attr("class", "country")
          .attr("d", path);

      // Create lat-lon mesh as background
      map_svg.insert("path", ".graticule")
          .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
          .attr("class", "boundary")
          .attr("d", path);


      // After ensuring the map data has loaded, load the keys between map objects and data
      d3.csv("../data/iso-3166.csv", function(error, isoCodes) {
        // Are these two redundant?
        isoCodes.forEach(function(d) {
          isoLookup[String(+d["country-code"])] = d;
        });
        isoCodes.forEach(function(d) {
          idLookup[d["alpha-3"]] = d;
        });

        // Set country name
        // may have to change idLookup[d].name, depending on whether name
        // was an attribute of the Stamen map objects
        group
          .append("text")
          .attr("y", -20)
          .attr("text-anchor", "middle")
          .style("font-weight", "bold")
          .text(function(d) {
            return d in idLookup ? idLookup[d].name : "";
          })
          .style("display", "none");

        //<commit_msg>needed to add update logic in the onclick for the circles<commit_after>
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="stylesheet" href="https://use.typekit.net/ezo4zbn.css">
<style type="text/css">
body {
  margin: 20px;
  font-family: acumin-pro-condensed, arial, sans;
  line-height: 1.3em;
  width: 1180px;
}

h3 {
  margin: 0 0 4px 4px;
  line-height: 1.05em;
}

.label {
  font-size: 18px;
}

.legend{
  opacity: 1;
  transition: opacity 0.3s;
}

.axis text {
  font-size: 14px;
  fill: #333;
}

.axis path,
.axis line {
  fill: none;
  stroke-width:1px;
  stroke: #e7e7e7;
}

circle {
  stroke: #fff;
  stroke-width: 1px;
  opacity: 0.8;
}

.bubble {
  opacity: 1;
  transition: opacity 0.3s;
}

path.country {
  opacity: 1;
  transition: opacity 0.3s;
}

.stroke {
  fill: none;
  stroke: #bbb;
  stroke-width: 2px;
}

.fill {
  fill: #fff;
}

.graticule {
  fill: none;
  stroke: #777;
  stroke-width: 0.5px;
  stroke-opacity: 0.5;
}

.land {
  fill: #ddd;
}

.boundary {
  fill: none;
  stroke: #fff;
  stroke-width: 0.5px;
}
#tooltip {
  width: 480px;
  padding: 6px 12px;
}
#tooltip h3 {
  margin: 0 0 12px 0;
}

.multiple {
  width: 180px;
  height: 120px;
  float: left;
  position: relative;
  background: #fcfcfc;
  border: 1px solid #d0d0d0;
  margin: 4px;
  cursor: pointer;
}

.multiple h3 {
  position: relative;
  font-size: 16px;
  width: 180px;
  z-index: 5;
  margin: 1px 0 0 5px;
}

.multiple svg {
  position: absolute;
  top: 40px;
  z-index: 4;
}

.multiple path.spark {
  stroke-width: 2px;
  stroke: #7D0063;
  fill: none;
}

#year-slider {
  margin: 0 0px 0 0;
}
</style>
<body>
<h1>Exploring Country-level GHG-GDP Divergence</h1>
<div style="border: 1px solid #d0d0d0; display: inline-block; padding: 8px 16px; font-size: 18px;">
  Time Range &nbsp;
  <input type="range" min=2000 max=2016 step=1 value=2000 id="year-slider" style="width: 200px">
</div><br/>
<div id="tooltip" style="display: none; position: absolute; z-index: 100; pointer-events: none; background: rgba(255,255,255,0.8); border: 2px solid #d0d0d0;">
</div>
</body>
<script src="//d3js.org/d3.v4.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>

<script>

var year = 2000;
var active_metric = "CO2";
var active_ymetric = "GDP";
var clicked_country = null;

var exclude = ["AFG", "COD", "LBY", "LCA", "LIE", "LSO", "MCO", "MDA", "NRU", "PRK", "ROU", "SMR", "SOM", "SSD", "SYR", "TLS", "TUV", "WLD"];

var metrics = ["index_territorial", "consumption_co2", "GDP", "CO2", "abs_carbon", "life_expectancy_at_birth_total_years_sp_dyn_le00_in", "individuals_using_the_internet_of_population_it_net_user_z", "employment_to_population_ratio_15_total_modeled_ilo_est", "abs_gdp", "access_to_electricity_of_population_eg_elc_accs_zs", "household_final_consumption_expenditure_per_capita_constant_20", "merchandise_imports_current_us_tm_val_mrch_cd_wt", "industry_value_added_constant_2010_us_nv_ind_totl_kd", "net_migration_sm_pop_netm", "total_natural_resources_rents_of_gdp_ny_gdp_totl_rt_zs", "renewable_energy_consumption_of_total_final_energy_consumpti", "urban_population_of_total_sp_urb_totl_in_zs", "proportion_of_seats_held_by_women_in_national_parliaments"];

var format = d3.format(".0%");

var default_format = d3.format(",.2r");

var format_si = d3.format(".2s");

function format_abbrev(x) {
  var s = format_si(x);
  switch (s[s.length - 1]) {
    case "G": return s.slice(0, -1) + "B";
  }
  return s;
}

var metric_lookup = {
  "GDP": {
    "key": "GDP",
    "name": "GDP Change",
    "units": "",
    "scale": "d3.scaleLinear",
    "format": format,
    "extent": [-0.3,0.3],
    "longextent": [-0.5,3]
  },
  "CO2": {
    "key": "CO2",
    "name": "Fossil fuels and cement production emissions by country (territorial, GCB)",
    "units": "change based on Mt C",
    "scale": "d3.scaleLinear",
    "format": format,
    "extent": [-0.3,0.3],
    "longextent": [-0.5,3]
  },
  "abs_carbon": {
    "key": "abs_carbon",
    "name": "Fossil fuels and cement production emissions by country (territorial, GCB)",
    "units": "Mt C",
    "scale": "d3.scaleLinear",
    "format": default_format,
    "extent": [0,10000],
    "longextent": [-0.5,3]
  },
  "consumption_co2": {
    "key": "consumption_co2",
    "name": "Consumption emissions (GCB)",
    "units": "change based on Mt C",
    "scale": "d3.scaleLinear",
    "format": format,
    "extent": [-0.3,0.3],
    "longextent": [-0.5,3]
  },
  "index_territorial": {
    "key": "index_territorial",
    "name": "Territorial ICGGD",
    "units": "",
    "scale": "d3.scaleLinear",
    "format": default_format,
    "extent": [-1,2],
    "longextent": [-0.5,3]
  },
  "life_expectancy_at_birth_total_years_sp_dyn_le00_in": {
    "key": "life_expectancy_at_birth_total_years_sp_dyn_le00_in",
    "name": "Life expectancy at birth, total",
    "units": "years",
    "scale": "d3.scaleLinear",
    "format": default_format
  },
  "individuals_using_the_internet_of_population_it_net_user_z": {
    "key": "individuals_using_the_internet_of_population_it_net_user_z",
    "name": "Individuals using the Internet",
    "units": "of population",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "employment_to_population_ratio_15_total_modeled_ilo_est": {
    "key": "employment_to_population_ratio_15_total_modeled_ilo_est",
    "name": "Employment to population ratio, 15+, total (modeled ILO estimate)",
    "units": "",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "abs_gdp": {
    "key": "abs_gdp",
    "name": "GDP",
    "units": "constant 2010 US$",
    "scale": "d3.scaleLinear",
    "format": format_si,
    "extent": [0,2e13],
    "longextent": [1,1e15]
  },
  "access_to_electricity_of_population_eg_elc_accs_zs": {
    "key": "access_to_electricity_of_population_eg_elc_accs_zs",
    "name": "Access to electricity",
    "units": "of population",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "household_final_consumption_expenditure_per_capita_constant_20": {
    "key": "household_final_consumption_expenditure_per_capita_constant_20",
    "name": "Household final consumption expenditure per capita",
    "units": "constant 2010 US$",
    "scale": "d3.scaleLinear",
    "format": default_format
  },
  "merchandise_imports_current_us_tm_val_mrch_cd_wt": {
    "key": "merchandise_imports_current_us_tm_val_mrch_cd_wt",
    "name": "Merchandise imports",
    "units": "change of current US$",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "industry_value_added_constant_2010_us_nv_ind_totl_kd": {
    "key": "industry_value_added_constant_2010_us_nv_ind_totl_kd",
    "name": "Industry, value added",
    "units": "change of constant 2010 US$",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "net_migration_sm_pop_netm": {
    "key": "net_migration_sm_pop_netm",
    "name": "Net migration",
    "units": "number of persons",
    "scale": "d3.scaleLinear",
    "format": format_abbrev
  },
  "total_natural_resources_rents_of_gdp_ny_gdp_totl_rt_zs": {
    "key": "total_natural_resources_rents_of_gdp_ny_gdp_totl_rt_zs",
    "name": "Total natural resources rents",
    "units": "of GDP",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "renewable_energy_consumption_of_total_final_energy_consumpti": {
    "key": "renewable_energy_consumption_of_total_final_energy_consumpti",
    "name": "Renewable energy consumption",
    "units": "change of share of total final energy consumption",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "urban_population_of_total_sp_urb_totl_in_zs": {
    "key": "urban_population_of_total_sp_urb_totl_in_zs",
    "name": "Urban population",
    "units": "of total",
    "scale": "d3.scaleLinear",
    "format": format
  },
  "proportion_of_seats_held_by_women_in_national_parliaments": {
    "key": "proportion_of_seats_held_by_women_in_national_parliaments",
    "name": "Proportion of seats held by women in national parliaments",
    "units": "of total seats",
    "scale": "d3.scaleLinear",
    "format": format
  }
}

var margin = { top: 50, right: 20, bottom: 50, left: 50 };
var width = 530 - margin.left - margin.right;
var height = 560 - margin.top - margin.bottom;

var lookup = {};

var tooltip = d3.select("#tooltip");

var map_width = 620;
var map_height = 560;

var svg = d3.select("body")
  .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var map_container = d3.select("body")
  .append("div")
    .style("width", map_width + "px")
    .style("height", map_height + "px")
    .style("position", "relative")
    .style("display", "inline-block");

var map_svg = map_container
  .append("svg")
    .attr("width", map_width)
    .attr("height", map_height);

map_container.append("a")
  .text("Colored by Territorial ICGGD Value")
  .attr("href", "../scatterplot/04_divergence_final.html")
  .style("position", "absolute")
  .style("top", (map_height-40) + "px")
  .style("left", (map_width/2-40) + "px")

d3.select("body")
  .append("h3")
  .attr("class", "country-label")
  .text(function(d) { return "Global"; });

d3.select("body")
  .append("div")
  .attr("id", "multiples");

var multiples = d3.select("#multiples")
  .selectAll("div")
  .data(metrics)
  .enter().append("div")
  .attr("class", "multiple")

multiples.append("h3")
  .text(function(d) { return metric_lookup[d].name; });

multiples.append("h3")
  .attr("class", function(d) { return "multiple-value multiple-value-" + d })
  .text(function(d) { return ""; });

multiples.append("svg")
  .attr("height", "120px")
  .attr("width", "180px")

var xscale = d3.scaleLinear()
  .domain([-0.5,0.5])
  .range([0,width])
  .clamp("true");

var yscale = d3.scaleLinear()
  .domain([-0.5,0.5])
  .range([height,0])
  .clamp("true");

var radius = d3.scaleSqrt()
  .range([2.5,20])
  .domain([0, 3000]);

var color = d3.scaleThreshold()
  .domain([-0.05, -0.02, 0, 0.05, 0.1])
  .range(["#d73027","#f46d43","#fdae61","#abd9e9","#74add1","#4575b4"]);
  
var colorMap = d3.scaleThreshold()
  .domain([-0.05, 0, 0.5, 0.75, 1])
  .range(["#d73027","#f46d43","#fdae61","#abd9e9","#74add1","#4575b4"]);

var xAxis = d3.axisBottom()
  .tickSize(-height)
  .tickFormat(function(d) {
//    if (d == -0.25) return "<" + format(d);
//    if (d == 0.25) return ">" + format(d);
    return format(d);
  })
  .scale(xscale);

var yAxis = d3.axisLeft()
  .tickFormat(function(d) {
//    if (d == 0) { return "N/A"; }
    return format(d);
  })
  .tickSize(-width)
  .scale(yscale)


/* Map */

var projection = d3.geoTimes()
    .scale((map_width - 4) / (1.5 * Math.PI))
    .translate([map_width / 2, map_height / 2])
    .precision(0.1);

var path = d3.geoPath()
    .projection(projection);

var graticule = d3.geoGraticule();

var isoLookup = {};
var idLookup = {};

var selected_country = "WLD";

map_svg.append("defs").append("path")
    .datum(graticule.outline())
    .attr("id", "sphere")
    .attr("d", path);

map_svg.append("use")
    .attr("class", "stroke")
    .attr("xlink:href", "#sphere");

map_svg.append("use")
    .attr("class", "fill")
    .attr("xlink:href", "#sphere");

map_svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);



// The rest of the code follows this function call
// which ensures the data is loaded before graphing it
d3.queue()
  .defer(d3.csv, "../final-data/GDP\ annual\ change\ 2000-15\ 9.28.17.csv")
  .defer(d3.csv, "../final-data/CO2 annual change data 2000-2015 9.18.17.csv")
  .defer(d3.csv, "../final-data/wb_data\ 9.29.17.csv")
  .defer(d3.csv, "../final-data/absolute\ country\ GDP\ 1999-2015.csv")
  .defer(d3.csv, "../final-data/absolute\ country\ annual\ carbon\ emissions\ 2000-2015.csv")
  .defer(d3.csv, "../final-data/consumption\ CO2\ annual\ change\ data\ 2000-2015\ 9.28.17.csv")
  .defer(d3.csv, "../data/Index\ calculated\ with\ Territorial\ Emissions\ and\ GDP.csv")
  .await(function(error, raw_gdp, raw_co2, wb_data, abs_gdp, abs_carbon, consumption_co2, index_territorial) {


    // Fill in lookup table

    raw_gdp.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["GDP"] = d;
    });
    raw_co2.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["CO2"] = d;
    });
    abs_gdp.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["abs_gdp"] = d;
    });
    abs_carbon.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["abs_carbon"] = d;
    });
    consumption_co2.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["consumption_co2"] = d;
    });
    index_territorial.forEach(function(d) {
      lookup[d["ISO"]] = lookup[d["ISO"]] || {};
      lookup[d["ISO"]]["index_territorial"] = d;
    });

    wb_data.forEach(function(d) {
      metrics.forEach(function(metric) {
        if (metric in d) {
          lookup[d["country_code"]] = lookup[d["country_code"]] || {};
          lookup[d["country_code"]][metric] = lookup[d["country_code"]][metric] || {};
          lookup[d["country_code"]][metric][d.year] = d[metric];
        }
      });
    });



    // set up xscale for plumb lines
    // logic for calculating extent, choosing preset if available

    var multiple_xscale = d3.scaleLinear().domain([2000,2015]).range([12, 168]);
    
    metrics.forEach(function(metric) {
      var calculated_extent = d3.extent(wb_data.filter(function(d) { return d.year.indexOf("-") < 0 && d.country_code !== "WLD"; }), function(d) { return +d[metric]; })
      var calculated_long_extent = d3.extent(wb_data.filter(function(d) { return d.year.indexOf("-") > -1 && d.country_code !== "WLD"; }), function(d) { return +d[metric]; })
      
      // perhaps, won't need longextent? so don't set it as it's own variable?
      // preset is the default, if it is not present, will use the calcualted extent / long_extent
      var extent = metric_lookup[metric].extent = metric_lookup[metric].extent || calculated_extent;
      metric_lookup[metric].longextent = metric_lookup[metric].longextent || calculated_long_extent;
      

      var yscale = metric_lookup[metric].yscale = d3.scaleLinear().domain(extent).range([70,6]).clamp(true);
      metric_lookup[metric].scale = d3.scaleLinear().domain(extent).range([0,width]).clamp(true);

      // draws the plumb line
      // *QQ* and the yAxis? confused because don't see
      metric_lookup[metric].line = d3.line()
        .defined(function(d) { return d.value != "" && !isNaN(d.value); })
        .x(function(d) { return multiple_xscale(d.year); })
        .y(function(d) { return yscale(d.value); });
      metric_lookup[metric].yAxis = d3.axisLeft()
        .tickFormat(metric_lookup[metric].format)
        .tickSize(-200)
        .scale(metric_lookup[metric].scale)
    });

    // Create spark lines
    // *QQ* not quite sure how spark lines are associated with metric_lookup[metric].line

    multiples.select("svg")
      .append("path")
      .attr("class", "spark")

    // Create tracking lines & years
    multiples.select("svg")
      .append("line")
      .attr("class", "plumb")
      .attr("x1", multiple_xscale(2000))
      .attr("x2", multiple_xscale(2000))
      .attr("y1", 6)
      .attr("y2", 70)
      .style("stroke", "#bbb")

    multiples.select("svg")
      .append("text")
      .attr("class", "multiple-year-label")
      .attr("x", multiple_xscale(2000))
      .attr("y", 78)
      .style("text-anchor", "middle")
      .style("stroke", "#bbb")
      .style("font-size", "12px")
      .text(2000)



      // Starting to set up the Scatterplot
      // grab countries, set axes and tick text location

    // Grab all countries
    var countries = d3.keys(lookup);

    // Draw X axis
    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .attr("class", "x axis")
      .call(xAxis);

    // Place text relative to the X axis
    svg.selectAll(".x.axis text")
      .attr("y", 8);

    // Draw Y Axis
    svg.append("g")
      .attr("transform", "translate(0,0)")
      .attr("class", "y axis")
      .call(yAxis);

    // *QQ* no placing .y.axis text?

    // Drawing middle lines - xaxis and yaxis
    // held constant on xscale(0) or yscale(0)
    svg
      .append("line")
      .attr("class", "dark-line-1")
      .style("stroke", "#777")
      .style("stroke-width", 1)
      .attr("x1", xscale(0))
      .attr("x2", xscale(0))
      .attr("y1", 0)
      .attr("y2", height)

    svg
      .append("line")
      .attr("class", "dark-line-2")
      .style("stroke", "#777")
      .style("stroke-width", 1)
      .attr("x1", 0)
      .attr("x2", width)
      .attr("y1", yscale(0))
      .attr("y2", yscale(0))

      // TO DO
      // Current implementation of clicked_country
      // needs additional logic to stop actions in
      // mouseover and mouseout if there is an active clicked_country
      // EDIT
      // Used if(clicked_country){return clicked_country} to shortcircuit


    // draw bubbles
    var group = svg.selectAll("g.bubble")
      .data(countries.filter(function(d) { 
        // only include those not in the exclude list
        return d && exclude.indexOf(d) == -1;
      }))
      .enter().append("g")
      .sort(function(a,b) {
        // if function returns positive, b was bigger than a
        // used for sorting, defaults to descending
        // sort by absolute carbon amount
        // https://stackoverflow.com/questions/15704128/how-can-i-efficiently-convert-data-from-string-to-int-within-a-d3-method-chain
        // + converts a numeric string into a number
        return +lookup[b]["abs_carbon"][year].replace(",","") - (+lookup[a]["abs_carbon"][year].replace(",",""));
      })
      .attr("class", "bubble")
      .attr("transform", function(d) {
        // scale x, y location by value of the x metric in a given year, in country d
        return "translate(" + xscale(+lookup[d][active_metric][year]) + "," + yscale(+lookup[d][active_ymetric][year]) + ")"
      });

    group
      .append("circle")
      // the circle gets drawn here... above was only a reference
      // to the center of a bubble element
      .attr("r", function(d) {
        return radius(+lookup[d]["abs_carbon"][year].replace(",",""));
      })
      .style("fill", function(d) {
        return "#777";
      })
      // on click, announce name in console
      .on("click", function(d) {
        clicked_country = d
        console.log(d); 
        update_to_selected_region(clicked_country)

        // TO DO 
        // expand this function to set chosen_country
        // same behavior as mouseover
        // will persist until user clicks on another country
        // or a background svg in front of everything as a click wall

      })
      .on("mouseover", function(d) {

        // rename d as country for clarify
        var country = d;

        // if country is explicitly excluded, or doesn't show up in lookup return gray
        // lookup is built from all of the wb_data 
        // *QQ* the second check may be unnecessary... will it ever be true?
        if (exclude.indexOf(country) > -1) { return "#eaeaea"; }
        if (!(country in lookup)) { return "#eaeaea"; }

        // Adding this as an attempt to shortcircuit mouseover behaviir
        // if there is an active clicked_country
        if (clicked_country) { return clicked_country}

        // *QQ* The following code should only run if there was no active clicked_country
        selected_country = country;

        // store data associated with this country
        // must be in data load await() callback to ensure data is ready for this step
        var datum = lookup[country];

        // change labels to be mousedover country's name
        // *QQ* it seems like idLookup is being created below, after loading the map
        // Why is this OK?
        d3.selectAll(".country-label").text(idLookup[d].name);

        // redraw the map to highlight the country being mousedover
        map_svg.selectAll("path.country")
          .style("opacity", function(p) {
            return p.id == String(+idLookup[d]["country-code"]) ? 1 : 0.3;
          })
          .style("stroke", function(p) {
            return p.id == String(+idLookup[d]["country-code"]) ? "#222" : null;
          });
          
        // Set text for tooltip

        // TO DO - Done?
        // cut down what gets displayed here to only be the x- and y-metric
        // *QQ* is the addition below sufficient?

        tooltip.style("display", null).html("");
        tooltip.append("h3").text(idLookup[d].name);
        d3.keys(datum).forEach(function(metric) {
          // Added the && and || clause
          if (datum[metric][year] && (metric == active_ymetric || metric == active_metric) ) {
            var div = tooltip.append("div");
            div.append("span").text(metric_lookup[metric].name + ": ");
            div.append("span").text(metric_lookup[metric].format(+datum[metric][year]));
            div.append("span").text(" " + metric_lookup[metric].units);
          }
        });

        // uses the .raise() function to bring a point above others
        svg.selectAll(".bubble")
          .filter(function(p) {
            return country == p;
          })
          .raise();
        // setting style of circle to show bold line around circumference
        svg.selectAll(".bubble circle")
          .style("stroke", function(p) {
            return country == p ? "#111" : null;
          })
          .style("stroke-width", function(p) {
            return country == p ? "2px" : null;
          });

        // outsource this operation to this function
        updateDataValues();
      })
      // Cause tooltip to follow mouse as user moves
      .on("mousemove", function(d) {
        return tooltip.style("top", (d3.event.pageY-52) + "px").style("left", (d3.event.pageX+18) + "px");
      })
      // Right now, will trigger back to WLD

      // TO DO
      // consider how onclick, onmouseover, and onmouseout interact
      // onclick (country): sets selected_country to chosen country
      //// clicked_country = d

      // onmouseover: sets selected_country to chosen country
      //// selected_country = clicked_country || d
      // onmouseout: sets selected_country back to WLD
      //// selected_country = clicked_country || d
      // onclick (canvas of scatterplot or map): sets selected_country back to WLD
      //// clicked_country = null

      .on("mouseout", function() {

        // Attempt to short-circuit if there is an active clicked_country
        if (clicked_country) { return clicked_country; }

        // The following code should only run if there is no active clicked_country
        selected_country = clicked_country || "WLD";
        d3.selectAll(".country-label").text("Global");
        map_svg.selectAll("path.country")
          .style("opacity", 1)
          .style("stroke", null);
        svg.selectAll(".bubble circle")
          .style("stroke", function(p) {
            return null;
          })
          .style("stroke-width", function(p) {
            return null;
          });

        d3.selectAll("path.spark")
          .attr("d", "");

        tooltip.style("display", "none");

        updateDataValues();
      })


      // Label displaying which y-metric is active
    svg.append("text")
      .attr("x", 6)
      .attr("y", -5)
      .attr("class", "label active-ymetric-label")
      .text(metric_lookup[active_ymetric].name + " (" + metric_lookup[active_ymetric].units+ ")");
      // Label displaying current years being shown
    var year_label = svg.append("text")
      .attr("x", width-2)
      .attr("y", -5)
      .attr("class", "label")
      .attr("text-anchor", "end")
      .style("font-weight", "bold")
      .style("font-size", "36px")
      .text("1999-2000");
      // Label showing which x-metric is active
    svg.append("text")
      .attr("x", width-2)
      .attr("y", height-6)
      .attr("text-anchor", "end")
      .attr("class", "label active-metric-label")
      .text(metric_lookup[active_metric].name + " (" + metric_lookup[active_ymetric].units+ ")");



    /* Map */

    // TO DO
    // update this to reference the official WRI geojson map bounds
    // check commands which use topojson...

    // *QQ* Convert wri-bounds to topojson? 
    // Does make them smaller, then don't have to chage the add code :)

    d3.json("../data/wri-bounds-topo.json", function(error, world) {
      if (error) throw error;

      // Experimental logs
      console.log(world)
      console.log(world.objects)
      console.log(world.objects.countries)
      console.log(topojson.feature(world, world.objects.countries).features)

      map_svg.selectAll("path.country")
        .data(topojson.feature(world, world.objects.countries).features)
        // Try this!
        // If it doesn't work... figure out how this wri-bounds json is passed 
        // .data(world.iso_a3)
        .enter().append("path")
          .attr("class", "country")
          .attr("d", path);

      // Create lat-lon mesh as background
      map_svg.insert("path", ".graticule")
          .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
          .attr("class", "boundary")
          .attr("d", path);


      // After ensuring the map data has loaded, load the keys between map objects and data
      d3.csv("../data/iso-3166.csv", function(error, isoCodes) {
        
        // TO DO
        // investigate how this works as a key between the map and the wb data

        // Are these two redundant?
        isoCodes.forEach(function(d) {
          isoLookup[String(+d["country-code"])] = d;
        });
        isoCodes.forEach(function(d) {
          idLookup[d["alpha-3"]] = d;
        });



        // Set country name
        // may have to change idLookup[d].name, depending on whether name
        // was an attribute of the Stamen map objects
        group
          .append("text")
          .attr("y", -20)
          .attr("text-anchor", "middle")
          .style("font-weight", "bold")
          .text(function(d) {
            return d in idLookup ? idLookup[d].name : "";
          })
          .style("display", "none");

        //
{'fraction_non_alphanumeric': 0.1697981116724376, 'fraction_numerical': 0.024483926510378232, 'mean_word_length': 2.920771513353116, 'pattern_counts': {'":': 244, '<': 51, '<?xml version=': 0, '>': 53, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6599837', 'n_tokens_mistral': 19259, 'n_tokens_neox': 18146, 'n_words': 4037}