How to get a tooltip to appear instantly? And Inconsistent error on tooltip test #2

So, I’m currently working on the Bar Chart project and I can’t get the tooltip to display instantly on mouseover in order to pass tests #13 and #14. Here’s my code so far:

document.addEventListener("DOMContentLoaded", function() {
  $.getJSON(
    "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json",
    function(dataset) {
      console.log(dataset);
      const padding = 2;
      const numberOfElements = dataset.data.length;
      const h = 500;
      const w = 3 * numberOfElements;

      const yScale = d3
        .scaleLinear()
        .domain([0, d3.max(dataset.data, (d, i) => dataset.data[i][1])])
        .range([0, h]);
      const container = d3
        .select("body")
        .append("svg")
        .attr("height", h)
        .attr("width", w);
      container
        .selectAll("rect")
        .data(dataset.data)
        .enter()
        .append("rect")
        .attr("class", "bar")
        .attr("data-date", (d, i) => dataset.data[i][0])
        .attr("data-gdp", (d, i) => dataset.data[i][1])
        .attr("x", (d, i) => 3 * i)
        .attr("y", (d, i) => 500 - yScale(dataset.data[i][1]))
        .attr("width", 2)
        .attr("height", (d, i) => yScale(dataset.data[i][1]))
        .attr("fill", "red")
        .append("title")
        .attr("id", "tooltip")
        .attr("data-date", (d, i) => dataset.data[i][0])
        .text((d, i) => dataset.data[i][0])
        .on("mouseover", (d) => {
          this.style("visibility", "visible");
        });
    }
  );
});

You can not change the built-in tooltip (when using tittle attribute) display delay, because that is implemented via each browser, but you can create your own tooltip and manipulate it.

First, create a div element before the chart inside the getJSON callback function, which will be the custom tooltip and give it a class of “tooltip” which will need to be defined in CSS.

const tooltip = d3
  .select("body")
  .append("div")
  .attr("class", "tooltip");

Second, create a “tooltip” class in CSS something like this below:

.tooltip {	
  position: absolute;			
  text-align: center;			
  width: 100px;								
  padding: 2px;				
  font: 12px sans-serif;		
  background: white;	
  border: 1px solid black;		
  border-radius: 2px;			
  pointer-events: none;		
  color: black;
  opacity: 0;
}

Last, get rid of all of this below:

.append("title")
.attr("id", "tooltip")
.attr("data-date", (d, i) => dataset.data[i][0])
.text((d, i) => dataset.data[i][0])
.on("mouseover", (d) => {
  this.style("visibility", "visible");
});

and replace with something like this below:

.on("mouseover", d => {
  tooltip
  .text(d[0])
  .style("left", d3.event.pageX + "px")
  .style("top", d3.event.pageY - 28 + "px")
  .transition()
  .duration(200)
  .style("opacity", 1)
})
on("mouseout", () => {
   tooltip
  .transition()
  .duration(200)
  .style("opacity", 0);
});
1 Like

I’m still failing Test #14 despite after inspecting the elements they have the correct property value… My tooltip declaration is now:

const tooltip = d3
        .select("body")
        .data(dataset.data)
        .enter()
        .append("div")
        .attr("class", "tooltip")
        .attr("id", "tooltip")
        .attr("data-date", (d) => d[0]);

Sure.

I’m failing the second tooltip test depsite it working as expected when I hover a bar on the chart. Also, the test error is different every time without changing the code. For example:

Tooltip’s “data-date” property should be equal to the active area’s “data-date” property: expected ‘2010-10-01’ to equal ‘2001-10-01’

Tooltip’s “data-date” property should be equal to the active area’s “data-date” property: expected ‘1965-1-01’ to equal ‘2002-01-01’

I’m not sure what’s causing this… Here’s my code:

document.addEventListener("DOMContentLoaded", function() {
  $.getJSON(
    "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json",
    function(dataset) {
      console.log(dataset);
      const padding = 60;
      const numberOfElements = dataset.data.length;
      const h = 500 + padding;
      const w = 3 * numberOfElements + padding;
      const yScale = d3
        .scaleLinear()
        .domain([0, d3.max(dataset.data, (d, i) => dataset.data[i][1])])
        .range([0, h - padding]);
      const tooltip = d3
        .select("body")
        .append("div")
        .attr("class", "tooltip")
        .attr("id", "tooltip");
      const container = d3
        .select("body")
        .append("svg")
        .attr("height", h + padding)
        .attr("width", w + padding);
      container
        .selectAll("rect")
        .data(dataset.data)
        .enter()
        .append("rect")
        .attr("class", "bar")
        .attr("data-date", d => d[0])
        .attr("data-gdp", d => d[1])
        .attr("x", (d, i) => padding + 3 * i)
        .attr("y", d => h - yScale(d[1]))
        .attr("width", 2)
        .attr("height", d => yScale(d[1]))
        .attr("fill", "red")
        .on("mouseover", (d,i) => {
          tooltip
            .text(d[0])
            .style("left", d3.event.pageX + "px")
            .style("top", d3.event.pageY - 28 + "px")
            .transition()
            .duration(200)
            .style("opacity", 1)
            .attr("data-date", () => dataset.data[i][0]);
        })
        .on("mouseout", () => {
          tooltip
            .transition()
            .duration(200)
            .style("opacity", 0);
        });
      const xAxisScale = d3
        .scaleLinear()
        .domain([1947, 2015])
        .range([padding, w - 2]);
      const xAxis = d3.axisBottom(xAxisScale).tickFormat(d3.format("d"));
      container
        .append("g")
        .attr("id", "x-axis")
        .attr("transform", "translate(0," + (h ) + ")")
        .call(xAxis);
      xAxis.ticks(5);
      const yAxisScale = d3
        .scaleLinear()
        .domain([0, d3.max(dataset.data, (d, i) => dataset.data[i][1])])
        .range([h - padding, 0]);
      const yAxis = d3.axisLeft(yAxisScale).tickFormat(d3.format("d"));
      container
        .append("g")
        .attr("id", "y-axis")
        .attr("transform", "translate(" + padding + "," + padding +")")
        .call(yAxis);
      yAxis.ticks(1000);
    }
  );
});

Turns out for some reason it didn’t like these 2 lines:

.transition()
.duration(200)