Wednesday, 11 February 2015

Passing JSON data to build Morris.js plot Dynamically (using SetInterval)

In the previous article, I used Morris.js library to plot graphs ;

Beside the fact of fetching JSON data to populate the graphs, I wanted to dynamically refleshed the plot with a certain time interval ;

As everybody knows, "Google is your freind", isn't it ?

I did find a web site showing how to do it  :
  • http://cirkit.io/index.php/simple-real-time-graphs-with-morris-js-and-jquery/

However, I found that the solution will depend on the graph you would like to generate ;

Thus, for the donut pie chart, I have to duplicate the building of the graph by calling

                var DonutGraph = new  Morris.Donut({
                    element: 'morris-donut-chart',
                    data: json
                });
within updateLiveDonutGraph function instead of calling   "DonutGraph .setData(json);" as I did with others graphs (Line and Bar kinds of graphs)!!

My initial JavaScript script was that one (retrieving JSON data from local server):

$(document).ready(function(){
    $.getJSON("http://localhost/boot/get_montant_commande_par_type_30_jours_glissants_line.php", function (json) {
        Morris.Line({
            element: 'graph_line',
            data: json,
            xkey: 'date',
            ykeys: ['annulation', 'geste_co','expedie'],
            labels: ['Annulations', 'Gestes commerciaux',"Commande non annulées"]
        });
    });
    $.getJSON("http://localhost/boot/get_nb_commande_statut_fraud_5_jours_glissants_bar.php", function (json) {
        Morris.Bar({
            element: 'graph_bar',
            data: json,
            xkey: 'date_purchase',
            ykeys: ['y0', 'y40', 'y80','y90','y100'],
            labels: ['0', '40', '80','90','100']
        }).on('click', function(i, row){
            console.log(i, row);
        });
    });
    $.getJSON("http://localhost/boot/get_repartition_order_status_today_morris_donut.php", function (json) {
        Morris.Donut({
            element: 'morris-donut-chart',
            data: json
        });
    });
});


Since I wanted as well to refresh data, let's say, every minutes: my final solution was the following one:

$(document).ready(function(){
    
    var delay = 60000;
    
    $("#hour_donut").html(getActualHour());
    $("#date_donut").html(getActualDate());
    $("#hour_bar").html(getActualHour());
    $("#date_bar").html(getActualDate());
    $("#hour_line").html(getActualHour());
    $("#date_line").html(getActualDate());
    
    $.getJSON("http://localhost/boot/get_nb_commande_statut_fraud_5_jours_glissants_bar.php", function (json) { 
        var BarGraph = new Morris.Bar({
            element: 'graph_bar',
            data: json,
            xkey: 'date_purchase',
            ykeys: ['y0', 'y40', 'y80','y90','y100'],
            labels: ['0', '40', '80','90','100']
        });
        setInterval(function() { updateLiveBarGraph(BarGraph); }, delay);
    });

    $.getJSON("http://localhost/boot/get_montant_commande_par_type_30_jours_glissants_line.php", function (json) { 
        var LineGraph = new Morris.Line({
            element: 'graph_line',
            data: json,
            xkey: 'date',
            ykeys: ['annulation', 'geste_co','expedie'],
            labels: ['Annulations', 'Gestes commerciaux',"Commande non annulées"]
        });
        setInterval(function() { updateLiveLineGraph(LineGraph); }, delay);
    });

    $.getJSON("http://localhost/boot/get_repartition_order_status_today_morris_donut.php", function (json) { 
        var DonutGraph = new  Morris.Donut({
            element: 'morris-donut-chart',
            data: json
        });
        setInterval(function() { 
            updateLiveDonutGraph();
            }, delay);
    });

    function updateLiveDonutGraph() {
        // Make our API call again, requesting fresh data
        $.getJSON("http://localhost/boot/get_repartition_order_status_today_morris_donut.php",
            function(json) {
                // Set the already-initialised graph to use this new data
                var DonutGraph = new  Morris.Donut({
                    element: 'morris-donut-chart',
                    data: json
                });
        });                    
        $("#hour_donut").html(getActualHour());
        $("#date_donut").html(getActualDate());
    }
    function updateLiveBarGraph(BarGraph) {
        // Make our API call again, requesting fresh data
        $.getJSON("http://localhost/boot/get_nb_commande_statut_fraud_5_jours_glissants_bar.php", function (json) { 
            BarGraph.setData(json);
        });
        $("#hour_bar").html(getActualHour());
        $("#date_bar").html(getActualDate());
    }

    function updateLiveLineGraph(LineGraph) {
        // Make our API call again, requesting fresh data
        $.getJSON("http://localhost/boot/get_montant_commande_par_type_30_jours_glissants_line.php", function (json) { 
            LineGraph.setData(json);
        });
        $("#hour_line").html(getActualHour());
        $("#date_line").html(getActualDate());
    }

});

function getActualHour() {
    var d = new Date();
    var h = addZero(d.getHours());
    var m = addZero(d.getMinutes());
    var s = addZero(d.getSeconds());
    return h + ":" + m + ":" + s;
}

function getActualDate() {
    var d = new Date();
    var day = addZero(d.getDate());
    var month = addZero(d.getMonth()+1);
    var year = addZero(d.getFullYear());
    return day + "/" + month + "/" + year;
}
function addZero(i) {
    if (i < 10) {
        i = "0" + i;
    }
    return i;
}


The hour and date of the treatment was integrated beside the title in order to get the actual time of the treatment (cf.  http://stackoverflow.com/questions/8398897/how-to-get-current-date-in-jquery)