2

This is a sample dynamically updated chart: http://www.highcharts.com/demo/dynamic-update

The chart is updated every second with the the date as the x value and a random number as the y value.

load: function() {            
    // set up the updating of the chart each second
    var series = this.series[0];
    setInterval(function() {
        var x = (new Date()).getTime(), // current time
            y = Math.random();
        series.addPoint([x, y], true, true);
    }, 1000);
}

How would I rewrite load to fetch x and y from another webpage using AJAX, rather than generating the values within the function?

outis
  • 75,655
  • 22
  • 151
  • 221
Corey
  • 257
  • 1
  • 4
  • 14
  • I need an example of calling a server page to update the value of x and y – Corey Dec 20 '11 at 03:48
  • and an example of the server page itself – Corey Dec 20 '11 at 03:49
  • possible duplicate of [Passing PHP variables back to JavaScript variables on original page as Ajax](http://stackoverflow.com/questions/7083998/passing-php-variables-back-to-javascript-variables-on-original-page-as-ajax) – outis Dec 20 '11 at 10:33
  • possible dup of [how to pass these strings from php to javascript](http://stackoverflow.com/questions/3174092/) – outis Dec 20 '11 at 10:41
  • thanks for the edit outis that is what i meant – Corey Dec 21 '11 at 00:01

2 Answers2

3

I take it what you want is the sample load method but with the lines that set x and y replaced with an AJAX call. You'll need to perform a fairly basic continuation-passing code transformation, turning the code after the point you want the asynchronous call into a function that's passed to the asynchronous call. "Continuation" simply means "the rest of the calculation, from a given point forward". In the code sample, that's the call to series.addPoint. The pattern for this is you transform:

function f(...) {
    (1)
    result = sync(...);
    (2)
}

into:

function f(...) {
    (1)
    async(..., function (result) {
          (2)
      });
}

If (2) returned a value in the original function, then the call to f must also be rewritten using continuation passing style, adding an extra parameter to hold the continuation.

The other thing you should do is make sure the PHP script outputs the numeric pair as valid JSON, either as an array of two numbers (which can be passed directly to the series.addPoint call after parsing), or as an object with properties "x" and "y".

Note that, due to the nature of network communication, the data may not arrive in a timely manner, resulting in a graph with irregular intervals.

Here's the gist, wrapping up the nuts-and-bolts of the asynchronous call into a function named ajaj. The sample assumes the browser supports the necessary standards for XMLHttpRequest and the JSON parser.

/* Asynchronous Javascript And Json */
function ajaj(url, succeed, fail) {
    if (! fail) {
        fail = function() {};
    }
    var xhr = new XMLHttpRequest;
    xhr.open('GET', url);
    xhr.onreadystatechange = function() {
        if (xhr.readyState==4) {
            if (200 <= xhr.status && xhr.status < 300) {
                succeed(JSON.parse(xhr.responseText));
            } else {
                // error
                fail(xhr.status, xhr.statusText, xhr.responseText);
            }
        }
    };
    xhr.send();
    return xhr;
}

...

    url: '...',

    load: function() {
        // ensure only one data load interval is running for this object
        if (this.updateInterval) {
            return;
        }
        // set up the updating of the chart each second
        var series = this.series[0];

        this.updateInterval = setInterval(function() {
            ajaj(this.url, 
                 function(point) { // success
                     series.addPoint(point, true, true);
                 },
                 function(status, statusText, response) { // failure
                     ...
                 }
            );
        }, 1000);
    }

JS libraries provide their own version of ajaj, often with more features. If you're doing anything of any complexity for a production site, look into adopting one. If you're using jQuery (as the tag suggests), you can, for example, use jQuery.get:

    load: function() {
        if (this.updateInterval) {
            return;
        }
        // set up the updating of the chart each second
        var series = this.series[0];

        this.updateInterval = setInterval(function() {
            jQuery.get(this.url, 
                 function(point, textStatus, jqXHR) { // success
                     series.addPoint(point, true, true);
                 }, 'json'
            );
        }, 1000);
    }

The server side of things is dead simple. time() returns a Unix timestamp, rand() returns a (not very) pseudorandom number (though good enough for a demo), and json_encode(), well, you can figure that out.

<?php
header('Content-type: application/json');

echo json_encode(
        array(
            time(),
            rand() / getrandmax(),
        ));
outis
  • 75,655
  • 22
  • 151
  • 221
1

I think you want a recursive call to setTimeout:

function update(series){
    var x = (new Date()).getTime(), // current time
        y = Math.random();
    series.addPoint([x, y], true, true);
    setTimeout(function() { update(series); }, 1000);
}

And then:

load: function() {            
    var series = this.series[0];
    update(series);
}

Or better yet, try something like this:

function update(){
    var series = yourChart.series[0];
    var x = (new Date()).getTime(), // current time
        y = Math.random();
    series.addPoint([x, y], true, true);
    setTimeout(update, 1000);
}

And then:

load: update

EDIT

If you're wanting to get a random number as an integer, something like this should do it (depending on the range of the number you want)

Math.floor(Math.random() * 10)

random will return a number in the range [0, 1), and floor will chop off any decimal points.

See random docs

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • sorry this is not exactly what im looking for. I need code to dynamically set the value of x and y, every second. what i really need to see is how to send a request and save the response in x or y as an int – Corey Dec 20 '11 at 03:50
  • 1
    @user475160 Adam seems to have a pretty good approach; keep in mind that as long as you're using Ajax (and setTimeout for that matter) the "every second" part of your problem is going to be an estimate at best. Network conditions and the nature of setTimeout will make to-the-second precision an impossible task. – Greg Pettit Dec 20 '11 at 04:01
  • You both do not understand what I'm trying to do – Corey Dec 20 '11 at 08:25
  • I am trying to replace x and y with my own values, using AJAX requests to a server. The code as implemented is not using AJAX. Your suggestion code is not using AJAX. I am not interested in random numbers. I do not need the setTimeout function. I need an AJAX function that calls the server, asks for two values. and stores them in X and Y. In other words, x = the response to a request to a php file on my server, and y = the response to an AJAX request to a php file on my server – Corey Dec 20 '11 at 08:31
  • @user475160 - it looks like outis has given you a pretty good answer for this – Adam Rackis Dec 20 '11 at 15:39