2 D3.js bar charts on the same HTML. One D3 script breaks the other

  d3.js, html, javascript

I am relatively new to D3 and javascript. I am trying to insert two d3 bar charts on the same page. The two bar charts function in basically the same way. They each have a drop down selector which allows the user to filter the data visualized, and a checkbox which allows the user to sort the data visualized.

Currently, both bar charts will load, and the drop down selector works for both, but the toggle only works for either one or the other. I suspect this has something to do with loading the two scripts. From what I can tell, whichever script is written last on the html page, overrides the other. Also, the sort works if you select it and then use the drop down, but when you uncheck the box the bars disappear.

The code is not throwing any errors, but the bars simply disappear when you select the toggle checkbox. I have run console.logs to confirm what data is being accessed, and sure enough, when you select the toggle checkbox, you get an empty array. I have tried renaming variables, loading a duplicate of the csv so each chart referenced a different data source and played around with the placement of the scripts, but I can’t seem to find what is causing the conflict.

I am attaching my code. Any guidance will be appreciated. I really want to figure this out, and I suspect this is going to teach me something important. Thank you in advance.

I will include 3 snippets.

  1. HTML
  2. prcpTrends.js
  3. precipitation.js
<!--HTML code for bar charts in question. -->
<!-- Start precipitation by weather station bar chart -->
<div class="row">       
          <div
          id="precipitationVisualization"
          class="col-md-6 col-sm-6 mb-4"
        >
        Choose Weather Station:
        <select id="weatherStation"></select>
        <input type="checkbox" id="sortPRCP">   
    Toggle sort by Precipitation Volume
          <div class="row">         
              <svg id="prcpTrends" width="768" height="400"></svg>              
            <div id="tooltipTrends">
              <!-- Station Name:<span id="stationName" class="info"></span><br>  -->
              Annual Precipitation:<span id="annualPrecipitationTrends" class="info"></span><br>          
            </div>               
          </div>      
        </div>
        
        
        <!-- Start precipitation by year bar chart -->
          <div
          id="precipitationVisualization"
          class="col-md-6 col-sm-6 mb-4"
        >
        Choose year:
        <select id="year"></select>
        <input type="checkbox" id="sort">   
    Toggle sort by Precipitation Volume
          <div class="row">         
              <svg id="precipitation_barchart" width="768" height="400"></svg>              
            <div id="tooltip">
              <!-- Station Name:<span id="stationName" class="info"></span><br>  -->
              Annual Precipitation:<span id="annualPrecipitation" class="info"></span><br>          
            </div>               
          </div>      
        </div>
        </div>
        
       

        <script src="../static/d3.js"></script>
        <script src="https://d3js.org/d3-scale.v3.min.js" defer></script>
        <script src="https://d3js.org/d3-axis.v1.min.js" defer></script>
        <script src="../static/precipitation.js"></script>
        <script src="../static/prcpTrends.js"></script>
    
</body>
</html>
d3.csv("/static/Horry_County_Precipitation.csv").then (d => chartTrend(d));

function chartTrend(csv) {
    csv.forEach(function(d) {
        d.DATE = d.DATE;
        d.PRCP = +d.PRCP;
        return d;
        
    })

    const weatherStation = csv
    .map((a) => a.NAME)
    .filter((value, index, self) => self.indexOf(value) === index);
    weatherStation.sort(function (a, b) {
    return b - a;
  });
  console.log(weatherStation)

  d3
    .select("#weatherStation")
    .selectAll("option")
    .data(weatherStation)
    .enter()
    .append("option")
    .text((d) => d);

  var svg = d3.select("#prcpTrends"),
    margin = { top: 70, right: -35, bottom: 50, left: 110 },
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;

//   Setting x Scale
  const x = d3
    .scaleBand()
    .range([margin.left, width - margin.right])
    .padding(0.1)
    .paddingOuter(0.2);

  var y = d3.scaleLinear().range([height - margin.bottom, margin.top]);

  var colorScale =  d3.scaleOrdinal()
.range(["#ed5151", "#149ece", "#3caf99", "#004c73", "#fc921f", "#a8a800", "#f789d8", "#732600", "#ff00c5", "#9e559c", "#a7c636", "#7f7f7f", "#6b6bd6", "#a87000"]);

  var xAxis = (g) =>
    g
      .attr("transform", "translate(0," + (height - margin.bottom) + ")")
      .call(d3.axisBottom(x).tickSizeOuter(0))
      .selectAll('text')
      .attr("y", 10)
      .attr("x", 0)
    //   .attr("dy", ".35em")
    //   .attr("transform", "rotate(60)")
    //   .style("text-anchor", "start");

 var yAxis = (g) =>
    g
      .attr("transform", "translate(" + margin.left + ",0)")
      .call(d3.axisLeft(y)
      .ticks(5)
      .tickSize(-width));

  svg.append("g").attr("class", "x-axis");

  svg
    .append("g")
    .attr("class", "y-axis")
    .append("text")
    .attr("class", "yAxisPRCP")
    .attr("y", -30)
    .attr("x", -85)
    .attr("transform", `rotate(-90)`)
    // .attr("fill", "#635f5d")
    // .style("font-size", "2.5em")
    .text("Precipitation (in)");

  svg
    .append("text")
    .attr("y", 40)
    .attr("x", 185)
    .attr("class", "title")
    .text("Weather Station Precipitation Totals");

  update(d3.select("#weatherStation").property("value"), 0);

  function update(name, speed) {
    var data = csv.filter(d => d.NAME == name);
console.log(data)
    y.domain([0, d3.max(data, (d) => d.PRCP)]).nice();

    svg.selectAll(".y-axis").transition().duration(speed).call(yAxis);

    data.sort(
      d3.select("#sortPRCP").property("checked")
        ? (a, b) => b.PRCP - a.PRCP
        : (a, b) => a.NAME - b.NAME
    );

    x.domain(data.map((d) => d.DATE));

    svg.selectAll(".x-axis").transition().duration(speed).call(xAxis);

    var bar = svg.selectAll(".bar").data(data, (d) => d.DATE);

    bar.exit().remove();

    var bar1 = bar
      .enter()
      .append("rect")
      .attr("class", "bar")
      .style("fill", "#149ece")
      .attr("opacity", ".5")
      .attr("width", x.bandwidth())
      .attr("height", (d) => y(0) - y(d.PRCP));
      
     bar1
        .merge(bar)
        .transition()
      .duration(speed)
      .attr("x", (d) => x(d.DATE))
      .attr("y", (d) => y(d.PRCP))
      .attr("width", x.bandwidth())
      .attr("height", (d) => y(0) - y(d.PRCP));


    // Adding Tooltip Behavior
    bar1
      .on("mouseover", function (event, d) {
        d3.select(this).style("fill", "#ebe028");
        d3.select("#stationName").text(" "+  d.NAME)
        d3.select("#annualPrecipitationTrends").text(" "+ d.PRCP + " inches");

        //Position the tooltip <div> and set its content
        let x = event.pageX -500;
        let y = event.pageY - 1000;

        //Position tooltip and make it visible
        d3.select("#tooltipTrends")
          .style("left", x + "px")
          .style("top", y + "px")
          .style("opacity", 1);
      })

      .on("mouseout", function () {
        d3.select(this).style("fill", "#149ece");

        //Hide the tooltip
        d3.select("#tooltipTrends").style("opacity", "0");
      });
  }
  chartTrend.update = update; 
}


var select = d3
  .select("#weatherStation")
  .style("border-radius", "5px")
  .on("change", function () {
    chartTrend.update(this.value, 750);
  });

var checkbox = d3
  .select("#sortPRCP")
  .style("margin-left", "1%")
  .on("click", function () {
    chartTrend.update(select.property("value"), 750);
  });
d3.csv("/static/Horry_County_Precipitation.csv").then (d => chart(d));

function chart(csv) {
    csv.forEach(function(d) {
        d.DATE = d.DATE;
        d.PRCP = +d.PRCP;
        return d;
        
    })


    const years = csv
    .map((a) => a.DATE)
    .filter((value, index, self) => self.indexOf(value) === index);
  years.sort(function (a, b) {
    return b - a;
  });
  // console.log(years)

  d3
    .select("#year")
    .selectAll("option")
    .data(years)
    .enter()
    .append("option")
    .text((d) => d);

  var svg = d3.select("#precipitation_barchart"),
    margin = { top: 70, right: -35, bottom: 50, left: 110 },
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;

  // Setting x Scale
  const x = d3
    .scaleBand()
    .range([margin.left, width - margin.right])
    .padding(0.1)
    .paddingOuter(0.2);

  var y = d3.scaleLinear().range([height - margin.bottom, margin.top]);

  var colorScale =  d3.scaleOrdinal()
.range(["#ed5151", "#149ece", "#3caf99", "#004c73", "#fc921f", "#a8a800", "#f789d8", "#732600", "#ff00c5", "#9e559c", "#a7c636", "#7f7f7f", "#6b6bd6", "#a87000"]);

  var xAxis = (g) =>
    g
      .attr("transform", "translate(0," + (height - margin.bottom) + ")")
      .call(d3.axisBottom(x).tickSizeOuter(0))
      .selectAll('text')
      .attr("y", 0)
      .attr("x", 9)
      .attr("dy", ".35em")
      .attr("transform", "rotate(60)")
      .style("text-anchor", "start");

 var yAxis = (g) =>
    g
      .attr("transform", "translate(" + margin.left + ",0)")
      .call(d3.axisLeft(y)
      .ticks(5)
      .tickSize(-width));

  svg.append("g").attr("class", "x-axis");

  svg
    .append("g")
    .attr("class", "y-axis")
    .append("text")
    .attr("class", "yAxisPRCP")
    .attr("y", -30)
    .attr("x", -85)
    .attr("transform", `rotate(-90)`)
    // .attr("fill", "#635f5d")
    // .style("font-size", "2.5em")
    .text("Precipitation (in)");

  svg
    .append("text")
    .attr("y", 35)
    .attr("x", 270)
    .attr("class", "title")
    .text("Annual Precipitation Totals");

  update(d3.select("#year").property("value"), 0);

  function update(year, speed) {
    var data = csv.filter(d => d.DATE == year);
// console.log(data)
    y.domain([0, d3.max(data, (d) => d.PRCP)]).nice();

    svg.selectAll(".y-axis").transition().duration(speed).call(yAxis);

    data.sort(
      d3.select("#sort").property("checked")
        ? (a, b) => b.PRCP - a.PRCP
        : (a, b) => a.NAME - b.NAME
    );

    x.domain(data.map((d) => d.NAME));

    svg.selectAll(".x-axis").transition().duration(speed).call(xAxis);

    var bar = svg.selectAll(".bar").data(data, (d) => d.NAME);

    bar.exit().remove();

    var bar1 = bar
      .enter()
      .append("rect")
      .attr("class", "bar")
      .style("fill", function (d){ return colorScale(d.NAME); })
      .attr("opacity", ".5")
      .attr("width", x.bandwidth())
      .attr("height", (d) => y(0) - y(d.PRCP));
      
     bar1
        .merge(bar)
        .transition()
      .duration(speed)
      .attr("x", (d) => x(d.NAME))
      .attr("y", (d) => y(d.PRCP))
      .attr("width", x.bandwidth())
      .attr("height", (d) => y(0) - y(d.PRCP));


    // Adding Tooltip Behavior
    bar1
      .on("mouseover", function (event, d) {
        d3.select(this).style("fill", "#ebe028");
        d3.select("#stationName").text(" "+  d.NAME)
        d3.select("#annualPrecipitation").text(" "+ d.PRCP + " inches");

        //Position the tooltip <div> and set its content
        let x = event.pageX -1100;
        let y = event.pageY - 1000;

        //Position tooltip and make it visible
        d3.select("#tooltip")
          .style("left", x + "px")
          .style("top", y + "px")
          .style("opacity", 1);
      })

      .on("mouseout", function () {
        d3.select(this).style("fill", function (d){ return colorScale(d.NAME); });

        //Hide the tooltip
        d3.select("#tooltip").style("opacity", "0");
      });
  }
  chart.update = update; 
}


var select = d3
  .select("#year")
  .style("border-radius", "5px")
  .on("change", function () {
    chart.update(this.value, 750);
  });

var checkbox = d3
  .select("#sort")
  .style("margin-left", "30%")
  .on("click", function () {
    chart.update(select.property("value"), 750);
  });

Source: Ask Javascript Questions

LEAVE A COMMENT