An error occurred when trying to access the 'getHours' property of an undefined variable

I have been working on creating a basic bar chart using financial data in JSON format.

An error message keeps appearing when I try to utilize my parsed time data. Despite console logging the data and verifying that it has been parsed correctly, I encounter this peculiar error:

d3.v3.min.js:1 Uncaught TypeError: Cannot read property 'getHours' of undefined
    at H (d3.v3.min.js:1)
    at SVGTextElement.t (d3.v3.min.js:1)
    at SVGTextElement.arguments.length.each.function.n.textContent (d3.v3.min.js:3)
    at d3.v3.min.js:3
    at Y (d3.v3.min.js:1)
    at Array.Co.each (d3.v3.min.js:3)
    at Array.Co.text (d3.v3.min.js:3)
    at SVGGElement.<anonymous> (d3.v3.min.js:5)
    at d3.v3.min.js:3
    at Y (d3.v3.min.js:1)

This issue is challenging to troubleshoot as the error points towards d3.v3.min.js rather than any specific part of my code. My suspicion is that the problem lies within the `d3.extent` function used for the x-axis instead of `d3.max`.

The section causing the error is represented by the following code snippet:

<!DOCTYPE html>
<meta charset="utf-8">

<head>
    <style>

    .axis {
      font: 10px sans-serif;
    }

    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }

    </style>
</head>

<body>

<script src="http://d3js.org/d3.v3.min.js"></script>

<script>

var margin = {top: 20, right: 20, bottom: 70, left: 40},
    width = 600 - margin.left - margin.right,
    height = 300 - margin.top - margin.bottom;

// Parse the date / time
var parseDate = d3.time.format("%H:%M:%S.%L").parse;

var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);

var y = d3.scale.linear().range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickFormat(d3.time.format("%H:%M:%S.%L"));

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(10);

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 + ")");

d3.json("https://gist.githubusercontent.com/kvyb/cba0e652b7fd9349604cf45ced75fbf9/raw/3f824e76c38479a1a327abbb5c85a5962fec6f21/schudata.json", function(error, data) {

    data["bboList"].forEach(function(d) {
        d.timeStr = parseDate(d.timeStr);
        d.value = +d.ask;
        console.log(d.timeStr)
    });

  x.domain(d3.extent(data, function(d) { return d.timeStr; }));
  y.domain([0, d3.max(data, function(d) { return d.value; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
    .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", "-.55em")
      .attr("transform", "rotate(-90)" );

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Value ($)");

  svg.selectAll("bar")
      .data(data)
    .enter().append("rect")
      .style("fill", "steelblue")
      .attr("x", function(d) { return x(d.timeStr); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); });

});

</script>

</body>

P.S.

Another issue not directly related to this question is worth mentioning.

In order to render the bars properly, I made the following replacement:

var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);

replaced with

var x = d3.time.scale().range([0, width]);

and adjusted the width of the bars to a fixed value.

Answer №1

It seems that the issue lies within the usage of d3.extent...

Absolutely, your observation is spot on, and the reason behind it is straightforward: d3.extent requires an array as its first parameter. However, your data is not an array; instead, it's an object with two properties, each containing an array.

Hence, you need to select one of the arrays to define your domains (and subsequently, your bar chart data):

x.domain(d3.extent(data["bboList"], function(d) {
    return d.timeStr;
}));
y.domain([0, d3.max(data["bboList"], function(d) {
    return d.value;
})]);

Below is the corrected code snippet for your reference:

var margin = {top: 20, right: 20, bottom: 70, left: 40},
    width = 600 - margin.left - margin.right,
    height = 300 - margin.top - margin.bottom;

// Parsing the date / time
var parseDate = d3.time.format("%H:%M:%S.%L").parse;

var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);

var y = d3.scale.linear().range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickFormat(d3.time.format("%H:%M:%S.%L"));

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(10);

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 + ")");

d3.json("https://gist.githubusercontent.com/kvyb/cba0e652b7fd9349604cf45ced75fbf9/raw/3f824e76c38479a1a327abbb5c85a5962fec6f21/schudata.json", function(error, data) {

    data["bboList"].forEach(function(d) {
        d.timeStr = parseDate(d.timeStr);
        d.value = +d.ask;
    });

  x.domain(d3.extent(data["bboList"], function(d) { return d.timeStr; }));
  y.domain([0, d3.max(data["bboList"], function(d) { return d.value; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
    .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", "-.55em")
      .attr("transform", "rotate(-90)" );

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Value ($)");

  svg.selectAll("bar")
      .data(data["bboList"])
    .enter().append("rect")
      .style("fill", "steelblue")
      .attr("x", function(d) { return x(d.timeStr); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); });

});
path, line {
  fill: none;
  stroke: black;
}
<script src="https://d3js.org/d3.v3.min.js"></script>

Note: My response only addresses your query regarding the error message ("Cannot read property 'getHours' of undefined"). There might still be issues in rendering those bars accurately.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process through which React form elements receive the event parameter?

I'm currently working on a form component that looks like this: import React from 'react'; class CommentBox extends React.Component { constructor(props) { super(props); this.state = { value: '' } this.han ...

Toggle the element within the selected row using Jquery

In order to create a client list, users must click on rows to select them and then submit the selections to the database for a cron job to send out emails. Instead of using checkboxes, I am attempting to highlight rows by including two hidden elements - o ...

What could be causing me to receive a 401 error when making a Rails jQuery POST request?

I am currently utilizing devise within a rails application. I have successfully logged into my rails server (devise) using the following curl command: curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X POST h ...

Putting retrieved data from firebase into an array using Angular and Firebase format

Hey everyone, I'm currently facing an issue with formatting my Firebase data into an array. Below is the service where I am retrieving data from Firebase: File name: subcategory.service.ts export class SubcategoryService { subcategoryRef: Angula ...

Issue in Android Studio: The element value must be a constant expression

I have encountered an issue while trying to assign a value to @GET. When I directly input a value, my API call works fine. However, if I attempt to retrieve the value from another class, I receive an error stating that the element value must be a constant ...

What is the reason behind an Express function requiring both the Request and Response as parameters?

Exploring the world of node.js and familiarizing myself with Express. The code snippet below has left me puzzled: var server = http.createServer(handleRequest); function handleRequest(req, res) { var path = req.url; switch (path) { case "/n": ...

Decoding JSON data using the cJSON library

Struggling to extract accurate values from a JSON file using cJSON. Although the code is error-free, the desired values are not being retrieved. test.json { "log_enable": "1", "log_level": "1", "dev ...

The system is unable to interpret the symbol property 'Symbol(Symbol.iterator)' because it is not defined

I have created a custom .any() method for Array objects to loop through an array and check if any item passes a specified function: Array.prototype.any = (comparator) => { for(let item of this){ if(comparator(item)){ return true ...

What could be the reason behind the disruption in this JavaScript associative array?

I'm facing an issue with my associative array, which I have confirmed through console.log to be initially: this.RegionsChecked = {"US":true,"APAC":true,"Canada":true,"France":true,"Germany":true,"India":true,"Japan":true,"LATAM":true,"MEA":true,"UK": ...

Weapons of Mass Destruction - receive markdown content

My application is utilizing a markdown editor from Google Code. $(document).ready(function () { var converter = Markdown.getSanitizingConverter(); var editor = new Markdown.Editor(converter); editor.run(); }); <div class="wmd-panel"> ...

Retrieve the json information stored in MongoDB

Having trouble querying a complex structure in my JSON data. Here is a snippet of the data: { "_id" : ObjectId("5282bf9ce4b05216ca1b68f8"), "authorID" : ObjectId("5282a8c3e4b0d7f4f4d07b9a"), "blogID" : "7180831558698033600", "blogs" : { ...

The issue of asynchronous behavior causing malfunctioning of the PayPal button

import { PayPalButton } from 'react-paypal-button-v2' <PayPalButton amount={total} onSuccess={tranSuccess} /> const tranSuccess = async(payment) => { c ...

PhpStorm 2019.2 introduces Material UI components that have optional props instead of being mandatory

My PhpStorm 2019.2 keeps showing me a notification that the Button component from Material UI needs to have an added href prop because it is required. However, when I refer to the Material UI API, I see something different. Take a look at this screenshot: ...

Using the "number" input type gives the user the ability to easily remove numbers and leave the input field

I have integrated angularJS with rzSlider to provide users the option of manually entering a number value or using the slider to input the value. However, I'm facing an issue where if a user drags the slider and then deletes the entire input from the ...

Guide to modifying the root directory when deploying a Typescript cloud function from a monorepo using cloud build

Within my monorepo, I have a folder containing Typescript cloud functions that I want to deploy using GCP cloud build. Unfortunately, it appears that cloud build is unable to locate the package.json file within this specific folder. It seems to be expectin ...

Webpack is unable to locate a specific custom JavaScript file

Currently, we are in the process of transitioning from grunt to webpack for our project. Within our project, we have a JS file named boiler that is used to define the core classes which are frequently accessed. __boiler__.js define(function (require) { ...

How to Trigger a Google Apps Script Function from an HTML Page

I lead a sports team and created a website for it. I'm interested in adding a button to an admin page that allows me to send a quick email to all team members at once. The message would typically read: "Important update - please check the website for ...

Shortcuts for $scope variables in AngularJS templates

Within my controller, I often set: $scope.currentThing.data For different parts of my template, sometimes I require currentThing.data.response[0].hello and other times currentThing.data.otherStuff[0].goodbye //or currentThing.data.anotherThing[0].goo ...

Passing an array from PHP to JavaScript without using JSON

I'm currently working on a project for school and I've hit a roadblock. My task involves accessing a database, converting the rows into an array, and then passing it to a JavaScript file to generate a graphic using the Google Charts API. Unfortu ...

jQuery fails to retrieve JSONP data from an external source

I want to determine if a stream is live on justin.tv. They offer an easy-to-use JSON API, where by querying http://api.justin.tv/api/stream/list.json?channel=channel_name it will provide specific JSON information if the stream is indeed live. var url = ...