"Uncaught ReferenceError: chart is not defined"
Solution 1
The reason is likely that you cannot refer to a variable during its stages of declaration. I'm guessing that the load function is being called as it's being declared. Luckily, you can refer to the object during the function declaration. Try the following block of code.
function getBirds(e) {
var now = new Date(),
et = now.getTime() / 1000, //PHP TS
st = et - 10, //30 seconds prior in PHP
chart = this;
if (chart.series.length > 0) {
...declaring the chart
variable in the var block inside.
Solution 2
Trying out examples from highchart page I found out that variable chart
is available only after $.json()
or $ajax()
call. If you try to use chart
before that it returns undefined
. Because it is and it is set only after $.json().
Their examples with json or ajax are set this way:
var chart;
function requestData() {...}
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'chart_container',
defaultSeriesType: 'spline',
events: {
load: requestData
}
...
});
I did similarly with your example. From getBirds()
I commented out some lines before json call:
console.log(chart);
if (chart.series.length > 0) {
var series = chart.series[0];
var length = series.length + 1;
var shift = series.data.length > 20;
}
and moved them after json call.
And changed this line:
//newdata['name'] = species;
newdata['name'] = scode;
And stop here:
for (j=0;j<length;j++) {
because of error:
Uncaught TypeError: Cannot call method 'push' of undefined
at line
newseries['data'].push(count);
It fails because there is no array. Hope this help.
kcbaker
Updated on November 27, 2020Comments
-
kcbaker over 3 years
all,
I'm working with the following HTML/Javascript code:
<!doctype html> <html> <head> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <!-- google fonts from CDN --> <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,600' rel='stylesheet' type='text/css'> <!-- highcharts --> <script src="http://code.highcharts.com/highcharts.js"></script> <style> html, body { width: 95%; margin: auto; font-family: 'Open Sans',sans-serif; } #chart_container { width:100%; height:500px; } </style> </head> <body> <h1>Live Data</h1> <div id="chart_container"> </div> </body> <script type="text/javascript"> $(document).ready(function() { chart = new Highcharts.Chart({ chart: { renderTo: 'chart_container', defaultSeriesType: 'line', events: { load: getBirds } }, title: { text: 'DRHW Live Data Stream' }, xAxis: { type: 'datetime', tickPixelInterval: 150, maxZoom: 20 * 1000 }, yAxis: { title: { text: 'Count Observed' } }, series: [ ], legend: { layout: 'horiztonal', align: 'center' } }); function getBirds() { var now = new Date(); var et = now.getTime() / 1000; //PHP TS var st = et - 10; //30 seconds prior in PHP console.log(chart); if (chart.series.length > 0) { var series = chart.series[0]; var length = series.length + 1; var shift = series.data.length > 20; } $.getJSON("https://path/to/json&callback=?", function(result) { var data = result.data;if (data.length == 0) { return; } else { additions = new Array(); for (i=0;i<data.length;i++) { if (data[i].qstype != "1") { species = data[i].answers[0]['answer']; scode = species.substring(0,species.search(" - ")).trim() count = (data[i].answers[1]['answer'] * 1); newdata = new Object(); newdata['name'] = species; newdata['count'] = count; additions.push(newdata); } } //now, for each addition, you need to loop through the existing data structures, and see if the thing exists. if it does, add the data; if not, add the thing, then add the data. var existingdata = chart.series; for (i=0;i<additions.length;i++) { isnewpoint = true; for (j=0;j<existingdata.length;j++) { if (existingdata[j].name == additions[i].name) { isnewpoint = false count = additions[i].count; point = [now.getTime(),count]; chart.series[j].addPoint(point, true, shift); shift = false; //this way, only one shift occurs - the first time through adding a new point to an existing data set. this will control against future shifting, either from other datapoints having new points added, } } if (isnewpoint) { newseries = new Object(); count = additions[i].count; newseries['name'] = additions[i].name; for (j=0;j<length;j++) { newseries['data'].push(0); } newseries['data'].push(count); chart.series.push(newseries); } } //we have now looped through and added a new data point to all species where new data was created in this pull. We still need to add a new point to those that were not affected. existingdata = chart.series; for (i=0;i<existingdata.length;i++) { getname = existingdata[i].name; getlength = existingdata[i].data.length; if (getlength<length) { //which we established earlier as one MORE than existed previously, prior to the addition point = [now.getTime(),0] chart.series[i].addPoint(point, true, shift); } } } setTimeout(getBirds,10000); }); } }); </script> </html>
The problem that I'm having is pretty straightforward (but driving me nuts!), and early on in the js block. Though I'm defining the variable 'chart' as the new Highcharts chart, and I'm setting 'getBirds' as the function to load once that's loaded, the console.log line tells me that the chart is undefined, and the line below it throws an error (
Uncaught TypeError: Cannot read property 'series' of undefined
).I've checked the following:
- The Highcharts reference (http://www.highcharts.com/docs/working-with-data/preprocessing-live-data), which suggests a setup similar to mine;
- I've tried defining the
chart
variable on its own line (which of course defines chart for my console.log, but does not define thechart.series
required on the next line); - I've researched stackoverflow and other docs for variable scope, but I think I'm handling it properly based on my research.
- I've tried reversing the order - putting the
getBirds()
function above thechart
definition.
I'm at a loss. Any help provided is much appreciated; thanks in advance!