A disturbing mistery

I’m tackling the “Heat Map” project and I’m almost done. It can be found on codepen.
But the tests doesn’t pass. Both tooltip errors are returned to me:

1. I can mouse over an area and see a tooltip with a
corresponding id = "tooltip" which displays more information 
about the area

2. My tooltip should have a "data-year" property that
corresponds to the "data-year" of the active area.

If I hover the mouse over an element, I see the tooltip, which contains different information for each element.

And each tooltip has an “id=tooltip” and a “data-year” property which is exactly the same as that of the hotspot (I added a console.log() to verify that).

But then why on heart don’t the tests pass?

Right off the bat, one problem I can see is that each hover event is creating a new id attribute - they are never cleared:
Screen Shot 2021-03-07 at 12.27.53 PM

So something odd is going on there. Remember that ids must be unique.

Thank you. I’ve modified the code for mouse events this way:

.on('mouseover', function (d) {
  d3.select(event.currentTarget)
  .attr('stroke', '#d53e4f')
  .attr('stroke-width', '2px')
  .append('title')
  .attr('id', 'tooltip')
  .attr('data-year', d => d.year)
  .text(d => `${months[d.month][1]} ${d.year}\n${(d.temp).toPrecision(3)}°`)
})
.on('mouseout', function(d) {
   d3.select(event.currentTarget)
   .attr('stroke', 'none')
   .attr('stroke-width', '0')
   .selectAll('#tooltip')
   .remove()
 })

It eliminates (for some misterious reasons) the second error for the tooltip, but doesn’t eliminates the fundamental one:

1. I can mouse over an area and see a tooltip with a
corresponding id = "tooltip" which displays more information 
about the area

As you can see in codepen, the tooltip is present and kicking. Why the sistem tests refuses to see it?

Hi,

I can see the tooltip but it doesn’t appear immediately and I think that is the problem.
I think it is slow for two reasons:

  1. I would use ‘mouseenter’ and mouseleave’ events. If I use ‘mouseover’ in my own heat map, it slows down.
  2. d3.select(event.currentTarget). I have used the properties of d itself without selecting again. If you console.log d you can see lots of properties.
.on('mouseenter', (d) => {
       console.log(d) // find useful properties here 
         //and use them without using .select
}

Greets,
Karin

Thanks, many thanks for your answer.
You touched a good point: on mouseover is slow, it is much better on mouseenter.

Well, I changed the code this way:

.on('mouseenter', function (d) {
  d3.select(this)
    .attr('stroke', '#d53e4f')
    .attr('stroke-width', '2px')
    .append('title')
    .attr('id', 'tooltip')
    .attr('data-year', d => d.year)
    .text(d => `${months[d.month][1]} ${d.year}\n${(d.temp).toPrecision(3)}°`)
})
.on('mouseleave', function(d) {
  d3.select(this)
    .attr('stroke', 'none')
    .attr('stroke-width', '0')
    .selectAll('#tooltip')
    .remove()
  })

I used d3.select(this) because it seems to be a standard technique with such situations (also this source and this source and many more). The tests don’t pass.

I don’t know any techniques for transforming a D3 element without selecting it. If it exists, it seems to me that the FCC course on d3 does not mention it.

It seems to me that my project respects all the specifics of the problem: the tooltip is visible and has its own id.

It is very tiring and frustrating to have to look for an error without even knowing if the error really exists or is it just a “stylistic” claim.
PLEASE, if anyone knows please tell me explicitly what the real hidden specification of the problem is, so that I can implement it without being forced to chase ghosts.

(I read that the test assert is as follows

var t = this, a = arguments;
return new Promise (
  (function (n, o) {
    var s = e.apply (t, a); 
    function i (e) {r (s, n, o, i, l , "next", e)}
    function l (e) {r (s, n, o, i, l, "throw", e)} i (void 0)}
  )
)

I don’t know how to read it. What does it mean?)

It looks like the delay in the tooltip generating is causing the test to not see it… I’ve swapped out your code with mine which sticks a div on top of the rectangles and just makes it visible or not on hover and it’s instantaneous - this passes the test.

Here’s the snippet of the code to see if you can refactor yours in any way, I can’t say for sure this is the issue, but it is certainly passing the tests for me.

    const tooltip = d3
    .select("body")
    .append("div")
    .attr("id", "tooltip")
    .style("opacity", 0)
    .style("position", "absolute");

  const mousemove = (event, d) => {
    let pageX = event.pageX;
    let pageY = event.pageY;

    const text = d3
      .select("#tooltip")
      .attr("data-year", d.year)
      .html("<p>" + d.year + ": "+"&deg;C</p>")
      .style("left", pageX + "px")
      .style("top", pageY + "px");
  };

        const rectWidth = 6;
        const rectHeight = ((h - (paddingBottom * 2)) / 13) - 2;
        const colorIndex = (value) => Math.trunc((value * colors.length) / maxTemp - 1)

        chart.selectAll('rect')
          .data(dataset)
          .enter()
          .append('rect')
          .attr('class', 'cell')
          .attr('data-month', d => d.month)
          .attr('data-year', d => d.year)
          .attr('data-temp', d => d.variance)
          .attr('x', d => xScale(d.year))
          .attr('y', d => yScale(d.month))
          .attr('width', rectWidth)
          .attr('height', rectHeight)
          .attr('fill', d => colors[colorIndex(d.temp)])
          .on("mouseover", (d, i) => d3.select("#tooltip").style("opacity", "1"))
          .on("mouseleave", (d, i) => d3.select("#tooltip").style("opacity", "0"))
          .on("mousemove", mousemove);

and some css for styling:

#tooltip {
  display: flex;
  color: white;
  align-items: center;
  justify-content: center;
  font-family: monospace;
  text-align: center;
  width: 110px;
  height: 50px;
  padding: 2px;
  font: 12px;
  background: DimGray;
  box-shadow: 1px 1px 10px;
  border-radius: 4px;
  pointer-events: none;
}

Yes, this way the tests pass. Sincerely many thanks.

I knew that technique and had used it in another project.


At the end of this misadventure I have to say one thing. It is not correct to let people to waste time and effort just for the sake of using “vagueness” in the description of the specifications.

The specification literally says:

16: I can mouse over an area and see a tooltip with
a corresponding id = "tooltip" which displays more
information about the area.

so my solution was correct. There was only one “hidden” specification: the title element cannot be used for the implementation of the tooltip. It vould have been enough to say it.

And it’s not the first time the system test hasn’t accepted my correct solution.

There should be more respect for people and their efforts.

Glad you got it working Sergio! :slight_smile: