D3: Visualize Data w/ Bar Chart - Script Error. (:0)

I could not pass spec 13 and 14. I did what that last two specs required.
Can anyone enlighten me what this error actually means?

Script error. (:0)
Error: Script error. (:0)

My pen:
https://codepen.io/shugyoza/pen/MWvMqoq?editors=1111

Also I’m wondering with this code block:

  const mousemove = (d, i) => {
    tooltip
      .html(`Year: ${i[0]}<br/>GDP: ${i[1]} Billion`)
      .style("left", `${(event.pageX - 70)}px`)
      .style("top", `${(event.pageY - 70)}px`)
  }

The dataset (d) is a 2D array. The subArray[0] is the YYYY-MM-DD and subArray[1] is the $GDP. Theoretically, I have to put d[0] and d[1] to access their value as d is suppose to represent the element of the dataset, which is the subArray. But when I did that, the tooltip prints undefined for both of them. The i, theoretically is suppose to represent the index of elements in the dataset array. But somehow when I put i[0] and i[1] it works the way I expect d[0] and d[1] to work. If anyone might have a good explanation for that, please.

Thank you!

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36

Challenge: Visualize Data with a Bar Chart

Link to the challenge:

Have a look at the other tooltip threads here for more explanation, but your main problem is that your mousemove function is labeled (d, i) which used to mean (datum, index) but since you are using D3v7 actually means (event, datum). So your d is the mouse event and your i is the datum for the current bar, which is why your data is in i. You get undefined the other way because the event object is not an array and doesn’t have 0 or 1 properties.

Most of the examples and documentation of D3 on the web are for D3 version 3 or 4 and are hopelessly out of date. The best source is the documentation at the D3 github repo.

Thanks a lot! By the way, just to make sure, are you just addressing my second question or your answer also relevant to the error I got (first question)? Thank you!

I was focused on your event function calls as that seemed to be where most of the problem was. I went back and looked at your tooltip code and ran the tests again and the reason you’re not passing the tooltip tests is that you are not adding the attributes that the tests are testing (id and data-date). You will need to add these to the tooltip for each bar; that’s where some examples from the forum might be helpful.

Thanks! But I already have that user story incorporated:

  const tooltip = d3.select("#chart")
    .append("div")
    .attr("class", "tooltip")
    .attr("id", "tooltip")
    .style("position", "absolute")
    .style("opacity", 1)
    .style("background-color", "white")
    .style("border", "orange")
    .style("border-width", "1px")
    .style("border-radius", "5px")
    .style("padding", "5px")
  const rect = graph.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("data-date", (d) => d[0])
    .attr("data-gdp", (d) => d[1])
    .attr("x", (d, i) => margin + i * 3)
    .attr("y", (d, i) => yScale(d[1]))
    .attr("width", 2.8)
    .attr("height", (d, i) => display.height - margin - yScale(d[1]))
    .attr("class", "bar") // adding hover feat.
    .on("mouseover", mouseover)
    .on("mouseleave", mouseleave)

Even right now, if we use browser dev console, the tooltip element is visible right in the center of the chart, still the spec did not pass. I can’t think of any other possible element to put id=“tooltip” other than the tooltip div itself, and seems to me that “data-date” could only be an attribute of rects.
This is my last pen:

https://codepen.io/shugyoza/pen/jOGOrVo

Because the error message is not informative at all, I’m flying blind right now. I don’t know what the spec is looking for. I’m not even sure that the script is running (whichever). I checked the test bundle, and it’s not digestible nor can be broken down for individual test.

If you have just any input or suggestion where I should do my research, please let me know. Otherwise I think I’ll just leave this as is right now, move on to the next projects, and will revisit this sometime in the future?

"bar-chart":{name:"D3: Bar Chart",URL:ge+"/d3-bar-chart/index.html",codepen:"https://codepen.io/freeCodeCamp/pen/GrZVaM",test:function(){describe("#BarChartTests",(function(){describe("#Technology Stack",(function(){it(V,(function(){return!0}))})),describe("#Content",(function(){it('My chart should have a title with a corresponding\n      id="title"',(function(){o.assert.isNotNull(document.getElementById("title"),'Could not find element with id="title" ')})),it('My Chart should have a <g> element x-axis with a \n      corresponding id="x-axis"',(function(){o.assert.isAbove(document.querySelectorAll("g#x-axis").length,0,'Could not find a <g> SVG element with id="x-axis" ')})),it('My Chart should have a <g> element y-axis with a \n      corresponding id="y-axis"',(function(){o.assert.isAbove(document.querySelectorAll("g#y-axis").length,0,'Could not find a <g> SVG element with id="y-axis" ')})),it('Both axes should contain multiple tick labels, each with \n      the corresponding class="tick" ',(function(){o.assert.isAbove(n()("#x-axis .tick").length,1,"There are not enough tick labels on the x-axis "),o.assert.isAbove(n()("#y-axis .tick").length,1,"There are not enough tick labels on the y-axis ")})),it('My Chart should have a <rect> element for each data point \n      with a corresponding class="bar" displaying the data',(function(){o.assert.isAbove(document.querySelectorAll("rect.bar").length,0,'Could not find any <rect> elements with class="bar" '),o.assert.equal(document.querySelectorAll("rect.bar").length,275,"The number of bars is not equal to the number of data points ")})),it('Each bar should have the properties "data-date" and\n      "data-gdp" containing date and GDP values',(function(){var e=document.querySelectorAll("rect.bar");o.assert.isAtLeast(e.length,1,'no <rect> elements with the class of "bar" are detected '),e.forEach((function(e){o.assert.isNotNull(e.getAttribute("data-date"),'Could not find property "data-date" in bar '),o.assert.isNotNull(e.getAttribute("data-gdp"),'Could not find property "data-gdp" in bar ')}))})),it('The bar elements\' "data-date" properties should match the \n      order of the provided data',(function(e){n.a.getJSON("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json",(function(t){try{var r=document.querySelectorAll("rect.bar");o.assert.isAtLeast(r.length,1,'no <rect> elements with the class of "bar" are detected '),r.forEach((function(e,r){var a=e.getAttribute("data-date");o.assert.equal(a,t.data[r][0],"Bars should have date data in the same order as the provided data ")})),e()}catch(t){e(t)}}))})),it('The bar elements\' "data-gdp" properties should match the \n      order of the provided data',(function(e){n.a.getJSON("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json",(function(t){try{var r=document.querySelectorAll("rect.bar");o.assert.isAtLeast(r.length,1,'no <rect> elements with the class of "bar" are detected '),r.forEach((function(e,r){var a=e.getAttribute("data-gdp");o.assert.equal(a,t.data[r][1],"Bars should have gdp data in the same order as the provided data ")})),e()}catch(t){e(t)}}))})),it("Each bar element's height should accurately represent the \n      data's corresponding GDP",(function(){var e=document.querySelectorAll("rect.bar"),t=parseFloat(e[0].getAttribute("data-gdp"))/parseFloat(e[0].getAttribute("height"));e.forEach((function(e){var r=e.getAttribute("data-gdp"),a=e.getAttribute("height"),n=parseFloat(r)/parseFloat(a);o.assert.equal(t.toFixed(3),n.toFixed(3),"The heights of the bars should correspond to the data values ")}))})),it("The data-date attribute and its corresponding bar element \n      should align with the corresponding value on the x-axis.",(function(){var e=document.querySelector("#x-axis"),t=document.querySelectorAll(".bar"),r=e.querySelectorAll(".tick");o.assert.isAbove(t.length,0,'there are no <rect> elements with the class of "bar" '),o.assert.isTrue(le(t,r,"x","data-date","year","topLeft"),"x values don't line up with x locations ")})),it("The data-gdp attribute and its corresponding bar element \n      should align with the corresponding value on the y-axis.",(function(){var e=document.querySelector("#y-axis"),t=document.querySelectorAll(".bar"),r=e.querySelectorAll(".tick");o.assert.isAbove(t.length,0,'there are no <rect> elements with the class of "bar" '),o.assert.isTrue(le(t,r,"y","data-gdp","thousand","topLeft"),"y values don't line up with y locations ")}))})),pe(document.querySelectorAll(".bar"),"data-date","data-date")}))}},
[1],10)/60;break;case"month":r=ue.indexOf(r.toLowerCase());break;case"thousand":r=r.split(",").join("")}return parseFloat(r)}(e,n)})),l=u[u.length-1]>u[0],c=u[1]-u[0];u=[u[0]-c].concat(J()(u),[u[u.length-1]+c]);var h=[].map.call(t,(function(e){return function(e){var t;if(!e.querySelector("line"))throw new Error("Tick does not contain the required line element.");return t=e.querySelector("line").getBoundingClientRect().top,{x:e.querySelector("line").getBoundingClientRect().left,y:t}}(e)[s]})),f=h[1]>h[0],p=h[1]-h[0];return h=[h[0]-p].concat(J()(h),[h[h.length-1]+p]),e.forEach((function(e){var t=function(e,t,r){var a=e.getBoundingClientRect(),n=/y/g.test(t)?a.top:a.left;return"center"===r&&(n+=(/y/g.test(t)?a.height:a.width)/2),n}(e,r,o),s=function(e,t,r){for(var a=0,n=t.length;a!==n;){var o=Math.floor((a+n)/2);t[o]===e?a=n=o+1:r&&t[o]>e||!r&&t[o]<e?n=o:a=o+1}return 0===a||a===t.length?[]:[a-1,a]}(function(e,t,r){var a;switch(r){case"year":a=new Date(e.getAttribute(t)).getFullYear();break;case"minute":a=new Date(e.getAttribute(t)).getMinutes()+new Date(e.getAttribute(t)).getSeconds()/60;break;case"month":a=isNaN(parseInt(e.getAttribute(t),10))?ue.indexOf(e.getAttribute(t).toLowerCase()):e.getAttribute(t);break;default:a=e.getAttribute(t)}return parseFloat(a)}(e,a,n),u,l);if(s.length>0){var c,p;if(f){var d=se()(s,2);c=d[0],p=d[1]}else{var g=se()(s,2);p=g[0],c=g[1]}var m=h[c],y=h[p];m-3<=t&&t<=y+3&&i++}})),i===e.length}function ce(e){var t=window.getComputedStyle(e,null);return n()(e).is(":hidden")||"0"===t.opacity||"hidden"===t.visibility||"none"===t.display}function he(e){return Math.floor(Math.random()*e)}function fe(e,t){var r;document.createEvent?(r=document.createEvent("MouseEvent")).initMouseEvent(t,!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null):r=new MouseEvent(t),e.dispatchEvent(r)}function pe(e,t,r){describe("#TooltipTests",(function(){it('I can mouse over an area and see a tooltip with a corresponding id="tooltip" which displays more information about the area ',K()(z.a.mark((function t(){var r,a,n,i,s,u;return z.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return 500,r=2e3,this.timeout(500+r+1e3),a=he(e.length),fe(n=e[a],"mouseover"),fe(n,"mousemove"),fe(n,"mouseenter"),t.next=10,re(500);case 10:i=document.getElementById("tooltip");try{o.assert.isNotNull(i,'There should be an element with id="tooltip"'),s=ce(i),o.assert.isFalse(s,"Tooltip should be visible when mouse is on an area")}finally{fe(n,"mouseout"),fe(n,"mouseleave")}return t.next=14,re(r);case 14:u=ce(i),o.assert.isTrue(u,"Tooltip should be hidden when mouse is not on an area");case 16:case"end":return t.stop()}}),t,this)})))),it('My tooltip should have a "'.concat(t,'" property that corresponds\n    to the "').concat(r,'" of the active area.'),K()(z.a.mark((function a(){var n,i,s;return z.a.wrap((function(a){for(;;)switch(a.prev=a.next){case 0:return n=he(e.length),fe(i=e[n],"mouseover"),fe(i,"mousemove"),fe(i,"mouseenter"),a.next=7,re(500);case 7:try{s=document.getElementById("tooltip"),o.assert.isNotNull(s,'There should be an element with id="tooltip"'),o.assert.isNotNull(s.getAttribute(t),'Could not find property "'.concat(t,'" in tooltip ')),o.assert.equal(s.getAttribute(t),i.getAttribute(r),"Tooltip's \"".concat(t,'" property should be equal to the ')+"active area's \"".concat(r,'" property'))}finally{fe(i,"mouseout"),fe(i,"mouseleave")}case 8:case"end":return a.stop()}}),a)}))))}))}var de=r(9);var ge="file:///".concat(F.a.resolve("./build/pages/").split(F.a.sep).join("/")),me={"tribute-page":{name:"Tribute Page",URL:ge+"/tribute-

Thank you! I really appreciate your help.

The key is that you need a different tooltip for each bar. You can access the tooltip element you created where ever it’s defined and change its attributes, for instance from the mouse event functions (you’ve got it 90% finished in mouseover as it is).

There’s also a small problem here:

  const mouseleave = (event, datum) => {
    tooltip
      .style("opacity", 0)
    d3.select(this)
      .style("stroke", "none")
      .style("opacity", .8)
  }

I’m not sure if this is a typo or not, regardless, this is not bound inside arrow functions and this code is causing part of your test errors.

1 Like

Thank you!
It made sense after I work on the Scatterplot project. It passed all the spec now after I moved the .html from tooltip mouseover to rect, and have the .html in tooltip mouseover to just pass whatever in the .html rect using the event.target.innerHTML, also adding the .attr(“data-date”,…) to tooltip mouseover.

https://codepen.io/shugyoza/pen/PoJwXrw