"Uncaught ReferenceError: chart is not defined"

22,503

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.

Share:
22,503
kcbaker
Author by

kcbaker

Updated on November 27, 2020

Comments

  • kcbaker
    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:

    1. The Highcharts reference (http://www.highcharts.com/docs/working-with-data/preprocessing-live-data), which suggests a setup similar to mine;
    2. I've tried defining the chart variable on its own line (which of course defines chart for my console.log, but does not define the chart.series required on the next line);
    3. I've researched stackoverflow and other docs for variable scope, but I think I'm handling it properly based on my research.
    4. I've tried reversing the order - putting the getBirds() function above the chart definition.

    I'm at a loss. Any help provided is much appreciated; thanks in advance!