Wednesday, 18 February 2015

Adding a column with delete button action within HTML table generated with DataTables JQuery plugin

The problem I encountered recently was to add  an action such as a "delete" link/button having a table using Ajax and DataTables JQuery plugin (from http://www.datatables.net/)

Since I may not be the only one having to solve that issue, I decided to make this article to share this solution.

The problem... 

Imagine an HTML table such  as :
 <head>
[...]
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

    <script  type="text/javascript"  src="../js/media/js/jquery.dataTables.min.js"></script> 
[..]
  <script type="text/javascript" src="../js/custom.js"></script>
</head>
  <body>
[..]
 <table  id="tbrefundall">
          <thead>
              <tr>
                 <th>No Order </th>
                 <th>Refund Amount</th>
                 <th>refund Type</th>
                 <th>Date Order</th>
                 <th>Date Refund</th>
               </tr>
           </thead>

           <tfoot>
               <tr>
                 <th>No Order </th>
                 <th>Refund Amount</th>
                 <th>refund Type</th>
                 <th>Date Order</th>
                 <th>Date Refund</th>
               </tr>
          </tfoot>
     </table>   
[..]
  <body>
[..]



And the javascript file, 'custom_delay.js'  with the following content :
var table_blocage_fraud_synchro =  $('#tbblocage_fraud_synchro').dataTable( {
       "language": {
           "url": "http://localhost/DataTables.French.json"  
       },
        "ajax": {
            "url": "http://localhost/table.json",
            "dataSrc": ""
        },
        "columns": [           
            { "data": "No_order" },
            { "data": "Amount_Refund" },
            { "data": "No_transaction_refund" },
            { "data": "Date_Order" },
            { "data": "Date_Refund" }
        ]
    } );

The Solution...

The first thing is to add a new column "head" and "foot" into the HTML file:
 <table  id="tbrefundall">
          <thead>
              <tr>
                 <th>No Order </th>
                 <th>Refund Amount</th>
                 <th>refund Type</th>
                 <th>Date Order</th>
                 <th>Date Refund</th>
                 <th>Action</th>
               </tr>
           </thead>

           <tfoot>
               <tr>
                 <th>No Order </th>
                 <th>Refund Amount</th>
                 <th>refund Type</th>
                 <th>Date Order</th>
                 <th>Date Refund</th>
                 <th>Action</th>
               </tr>
          </tfoot>
     </table>  


The second is to alter the javascript file, by adding the id of the delete action as the new column data in the dataTables (which will here the 'no_commande') and redefining the column content using columnDefs Datatable option :
var table_blocage_fraud_synchro =  $('#tbblocage_fraud_synchro').dataTable( {
       "language": {
           "url": "http://localhost/DataTables.French.json"  
       },
        "ajax": {
            "url": "http://localhost/table.json",
            "dataSrc": ""
        },
        "columns": [           
            { "data": "No_order" },
            { "data": "Amount_Refund" },
            { "data": "No_transaction_refund" },
            { "data": "Date_Order" },
            { "data": "Date_Refund" },
            { "data": "No_order" }
        ]
        "columnDefs":[
            {
                "render": function ( data, type, row ) {
                    var LnkDelete = '<a  href="http://localhost/delete.php?id=' + data + '"> delete' + ' </a>';
                    return lnkDelete;
                },
                "targets": [5]
            }


        ]
    } );

You can notice that, within the "render" function , "data" correspond here to the input data of the sixth column (id for the delete action), being referred by adding this option (0 corresponding to the first column) : "targets":[5];


You can transform a link to a button using bootstrap (cf. http://getbootstrap.com/), by adding this class element to the 'a'  tag :  class="btn btn-danger btn-sm"  role="button"

Redefining the content of an existing column

You can also alter the content of a column by defining a new render function within a new "json" input for "columnDefs" DataTables option; imagine that the No_transaction_refund  (column no 3 equivalent to targets[2])  data is not directly the data you would like to show in the table but the refund type being defined such as this : the refund type equals to "Goodwill Gesture", if No_transaction_refund  data is empty, otherwise, the refund type equals to "Cancellation"

The solution is shown below in Red :

        "columnDefs":[
            {
                "render": function ( data, type, row ) {
                    var LnkDelete = '<a  href="http://localhost/delete.php?id=' + data + '"> delete' + ' </a>';
                    return lnkDelete;
                },
                "targets": [5]
            },
           {"render": function ( data, type, row ) {
                    if (data === undefined || data === null) return '<span  class="label label-warning" > Goodwill Gesture</span>';
                    else return '<span  class="label label-info" > Cancellation</span>';
                },
                "targets": [2]
           }
]

For the use of the class defined above (class = "label .."), Bootstrap is required (cf. http://getbootstrap.com/) ; if  you do not want to depend on Bootstrap, you can just delete it;


Note that we can also use row properties to access column values to do the same thing  :



{ "render": function ( data, type, row ) {
                    if (row["No_transaction_refund"] === undefined || row["No_transaction_refund"] === null) return '<span  class="label label-warning" > Goodwill Gesture</span>';
                    else return '<span  class="label label-info" > Cancellation</span>';
                },
                "targets": [2]
}
 

Here is the final output :





How to change the default language when generating HTM Tables from DataTables JQuery Plugin ?

The default language for DataTables JQuery is English; Therefore, you might want, like me, have a different language (let's say in French); I found the solutions in these websites :
  • https://datatables.net/manual/i18n
  • http://www.datatables.net/examples/advanced_init/language_file (where you will find solutions for languages other than French)
Two ways are possible to solve that issue :

  • The first one is to add a 'language' option, followed by properties within json format data :

 var table_test =  $('#tbtest').dataTable( {
       "language": 
       {
        "processing":     "Traitement en cours...",
        "search":         "Rechercher&nbsp;:",
        "lengthMenu":    "Afficher _MENU_ &eacute;l&eacute;ments",
        "info":           "Affichage de l'&eacute;lement _START_ &agrave; _END_ sur _TOTAL_ &eacute;l&eacute;ments",
        "infoEmpty":      "Affichage de l'&eacute;lement 0 &agrave; 0 sur 0 &eacute;l&eacute;ments",
        "infoFiltered":   "(filtr&eacute; de _MAX_ &eacute;l&eacute;ments au total)",
        "infoPostFix":    "",
        "loadingRecords": "Chargement en cours...",
        "zeroRecords":    "Aucun &eacute;l&eacute;ment &agrave; afficher",
        "emptyTable":     "Aucune donnée disponible dans le tableau",
        "paginate": {
            "first":      "Premier",
            "previous":   "Pr&eacute;c&eacute;dent",
            "next":       "Suivant",
            "last":       "Dernier"
        },
        "aria": {
            "sortAscending":  ": activer pour trier la colonne par ordre croissant",
            "sortDescending": ": activer pour trier la colonne par ordre décroissant"
        }
       },
       "ajax": {
           "url": "../process.php?param=xxx",
          "dataSrc": ""
       }
[..]
} );

  • The second one is to save the json content (in orange above) into a file with a json extension into your web folder and access this file via Ajax using the language url option :

 var table_test =  $('#tbtest').dataTable( {
       "language": {
           "url": "../DataTables.French.json"  
       },
       "ajax": {
           "url": "../process.php?param=xxx",
          "dataSrc": ""
       }
[..]
} );
The resulting header will be that one for french translation


and that one for the footer:


Thursday, 12 February 2015

CodeIgniter: a good MVC PHP Framework to start with

Here is a list of books, that I particularly, recommend, if you would like to get familiar with CodeIgniter:
  1. "CodeIgniter for Rapid PHP Application", from David Upton (published by Packt Publishing), 2007
  2. "CodeIgniter 1.7 Professional Development", from Adam Griffiths (published by Packt Publishing), 2010
  3. "Wrox Professional CodeIgniter", from Thomas Myer (published by Wiley Publishing), 2008

Model - View - Controller

Model - View - Controller (MVC), as the name implies, is a design pattern that allows developers to cleanly separate their code into three categories:
  • Models maintain data : The Model represents any type of data that your application may use. Some examples of data that your application might use would be: a database, RSS Feeds, API calls, and any other action that involves retrieving, returning, updating, and removing data.
  • Views display data and user interface elements : Views are the information that is being presented on the screen to users through their web browsers. These are usually HTML files, sometimes containing PHP code that builds the template for the website.
  • Controllers handle user events that affect models and views : Controllers are the business logic of your application.They serve as an intermediary between Models and Views. Controllers are the core of your application because they determine how HTTP requests should be handled.The Controller will respond to HTTP requests and generate web pages. It’s the controller that monitors the activity of the user (who clicks a link, moves the mouse, or submits a form)  and takes the appropriate action (such as manipulating the model and updating the view). 

“ Convention over Configuration ”

"Ruby On Rails" has this idea that allows small teams of developers to create web applications in a tenth the time, with less debugging and fewer headaches. This idea has been incorporated into every single PHP framework, CodeIgniter included.
The result has been an enormous amount of time saving and effort reduction in development.

Comparing PHP MVC Frameworks

Several PHP MVC frameworks have emerged in the past few years, among them CakePHP, Symfony, and CodeIgniter. The next section provides a brief comparison of these three PHP
MVC frameworks.

  • CakePHP’s automatic approach allows the developer to create web applications quickly. For example, the automation allows a model to map easily to a database table. If you don ’ t really care how things work underneath, this approach can be strangely liberating. However, if you really want to understand what is happening, you sometimes have to dig around in the core code.
  • Symfony took a page from Ruby on Rails, providing developers with a series of command - line tools to help build admin panels, object - relational mapping schemes, views, and other niceties. Run a few scripts and suddenly you have a surprising amount of work done for you.
  • CodeIgniter has a different approach. Just about all your work will be in the controller. That ’ s where you load libraries, extract data from the model, and pull in views. Everything ’ s in plain sight, so it ’ s easy to keep things organized and troubleshoot problems if and when they occur. There is no standard naming convention for models and controllers. Developers can manually load models or autoload them in the main configuration, and the models don ’ t have to be named a certain way to match up to tables. What this means is that legacy applications are extremely easy to port over to CodeIgniter, and integration with outside database systems is generally very easy. CodeIgniter's approach to MVC is very loose. This means that Models are not required. This is for a number of reasons. Firstly, CodeIgniter's Database Library can be used in both Models and Controllers—meaning that the extra separation of Models can be bypassed. Secondly, the Model isn't tied to the database, as it is in other frameworks such as Ruby on Rails, so the Model isn't needed in this regard. Finally, if using a Model in your application will cause unnecessary complexity, then the Model can simply be ignored. However, Models are extremely useful, even though they are optional. Models can be loaded from any Controller, so if you use a Model function in multiple controllers and you need to change the function, you only need to edit it in one place rather than in all of the controllers. Complex queries should really be put into a Model. A collection of related queries should also be put into a Model as they can be grouped together. This makes your applications simpler, and it allows you to use the functions in any Controller.

CodeIgniter also allows a great deal of flexibility when querying tables.

//place raw SQL in the query() method
$q = $this- > db- > query(“select * from users”);
//or pass in a variable
$sql = “select * from users”;
$q = $this- > db- > query($sql);
//or use the built-in get() method
$q = $this- > db- > get(‘users’);

Helpers and Libraries

  • CakePHP is pretty light on built - in helpers and libraries,
  • Symfony ’ s suite of tools for unit testing, scaffolding, and admin generation is probably the best of all three. These tools may not be used every day, but they offer plenty of shortcuts for the developer.
  • CodeIgniter comes with an amazing range of libraries and helper files that cover a lot of what you will encounter in just about every project: caching, security, file uploads, link building, form building, text parsing, regular expressions, database queries, FTP, e - mail, calendaring, sessions, pagination, image manipulation, validation, XML - RPC, dates, cookies, XML, and more. You can also extend built - in libraries and helpers and create your own.

The Famous "Hello World" example using CodeIgniter v2.2

Let's create a simple Hello World controller, with a file called hello.php in codeigniter/application/controllers/.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class hello extends CI_Controller {

public function __construct(){
parent::__construct();
}
public function index()
{
echo("Hello, World!");
}   
}

Firstly, you can see that the controller is a class that extends the base CI_Controller class. Controllers should always extend the base class so that you can use all of CodeIgniter's syntax and have access to all CI resources.
If you have a constructor in your Controller then you need to call upon the CI_Controller constructor, as we have in the example hello Controller.
You should call it as follows:

parent::__construct();

The next thing to note is that there is a function with the name index. This is the default function, and will be called when another function has not been called. To see this being run, simply navigate to the URL http://yourwebsite.ext/index.php/hello/ and you should see the words Hello, World! on the screen.

here, CodeIgniter being my web project folder, thus, the appropriated URL will be the following one: http://localhost/CodeIgniter/index.php/hello


CodeIgniter URLs

CodeIgniter URLs use Uniform Resource Identifiers (URI). In simple terms, CodeIgniter's URLs are simply segments. These segments are then split up andused to load a particular controller and method. Here is a typical CodeIgniter URL:

http://mywebsite/index.php/controller/method/parameters

Everything after the index.php segment is used by CodeIgniter to determine what to load. The first segment is the name of the Controller. The second segment is used to determine which function to load—if this is blank then the index function will be used. The final segment will be used to pass any data to the function.


Defining a default Controller

CodeIgniter has the ability to set a Controller as the default controller. Thisis the controller that is to be called when no other controller is passed toindex.php. A default CodeIgniter install will set the default controller towelcome.php calling the view 'welcome_message'– this is the default CI welcome page.


<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends CI_Controller {

/**
* Index Page for this controller.
*
* Maps to the following URL
* http://example.com/index.php/welcome
* - or -  
* http://example.com/index.php/welcome/index
* - or -
* Since this controller is set as the default controller in 
* config/routes.php, it's displayed at http://example.com/
*
* So any other public methods not prefixed with an underscore will
* map to /index.php/welcome/<method_name>
* @see http://codeigniter.com/user_guide/general/urls.html
*/
public function index()
{
$this->load->view('welcome_message');
}
}

Here, you can see that the function $this->load->view is called to access a specific view 'welcome_message', corresponding to the file [codeigniter]/application/views/welcome_message.php

To set a different default controller, open the file application/config/routes.php and change welcome to the name of any other controller in your application.

$route['default_controller'] = "welcome";


Going further with "Hello World" example - introducing views

(The example will be based on that presented at http://12devsofxmas.co.uk/2011/12/codeigniter/, )

As you can see in our previous example, we’ve used this amazingly powerful framework to echo a line of text to the screen and frankly that’s embarrassing so we’d better get onto something vaguely resembling MVC…

Let's create a file called hello.php in the /application/views folder, so we can begin separating our code out nicely, and put this code inside it.

<?php echo $greeting; ?>

And let's change the content of the controller index function by the following code in order to call our view:

//create an array to hold the data we wish to pass to the view

$data = array();

$data['greeting'] = 'Hello world';

//use the load view function to load 'hello.php' and pass the $data array for the view to use 

$this->load->view('hello',$data); 

Now, let's again call http://localhost/codeigniter/index.php/hello and you should see the same output that before, excepted that  the whole point here is we’ve wrapped some data up in an array and passed it to the view ‘hello’ ;


Adding a variable for the name the function becomes : 


public function index($name = 'Alun')

{

    $data['greeting'] = 'Hello '.$name;



    $this->load->view('hello',$data);



}

http://localhost/codeigniter/index.php/hello/smith ; you should see "Hello Smith"


Going still further with "Hello World" example - introducing models

So now we’ve seen a View and a Controller but we’ve not done anything with the Models yet.

Let's create a model "hello_model", within application\models folder by creating a file hello_model.php with the following code :

class hello_model extends CI_Model {

    
    function hello($name, $lang)
    {

        //create an array of "greetings"

        $hello = array();
        $hello['en'] = 'Hello';
        $hello['fr'] = 'Bonjour';
        $hello['de'] = 'Guten Tag';
        $hello['lol'] = 'Oh Hai';

        /* check if a value has been found in the array */
        /* if not default it to 'en' */

        if( ! isset($hello[$lang]))
        {
            $lang = 'en';
        }
        return $hello[$lang]." ".$name;
    }
    
}

And, let's add a new function (action) "greeting" in our "hello" controller :
class hello_model extends CI_Model {

public function greeting($name)
{
           $this->load->model("hello_model"); 
           $data = array();  
           $data['greeting'] = $this->hello_model-> hello($name,$lang);  

           $this->load->view('greeting',$data);
}

Calling the URL http://localhost/CodeIgniter/index.php/hello/greeting/Smith/fr
will then give:

Bonjour Smith


Introducing Database in the model

Next step : that will be the introduction of database query in the model; for that, you will have to define the database access within the config\database.php file and add 'database' in $autoload['libraries'] array within the config\autoload.php file;

Let's create, for example, the following table :
--
-- Table structure for table `greetings`
--

CREATE TABLE `greetings` (
`greetingid` int(11) NOT NULL AUTO_INCREMENT,
`lang` varchar(10) CHARACTER SET utf8 NOT NULL,
`text` varchar(255) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`greetingid`)
) ;

--
-- Dumping data for table `greetings`
--

INSERT INTO `greetings` VALUES(1, 'de', 'Guten Tag ');
INSERT INTO `greetings` VALUES(2, 'en', 'Hello');
INSERT INTO `greetings` VALUES(3, 'fr', 'Bonjour');
INSERT INTO `greetings` VALUES(5, 'lol', 'Oh Hai');

The equivalent "hello" function of the previous model will be that one:


function hello($name, $lang){

        $data = array();

        $params = array('lang' => $lang);

        $result = $this-> db-> get_where('greetings', $params, 1);

        if ($result-> num_rows() > 0){

            // $data = $result-> row_array();

            $data =$result->result_array();

            $text = $data[0]['text']

        }
        // var_dump($data);
        $result-> free_result();
        return $text." ".$name;;
    }

Notice that build-in method for database access :

$this-> db-> get_where()

This function is identical to the use of the built-in get() method/function except that it permits you to add a "where" clause in the second parameter, instead of using the db->where() function:

$query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset);

You should read the CodeIgniter documentation related to active record, if you would like deeply andersstanding on database built-in functions, at https://ellislab.com/codeigniter/user-guide/database/active_record.html


Nota : differences between CodeIgniter version 1.7.2 and 2.X.X

I noticed that there are the major differences in the way controllers and models are constructed between version 1.7.2 and version 2.0.0, differences which concerns class constructors.
  • Version 1.7.2
Controllers
class Contact extends Controller {
  function Contact() {
    parent::Controller();
  }
}
Models

class Contact_model extends Model {
  function Contact_model() {
    parent::Model();
  }
}
  • Version 2.0.0

Controllers

class Contact extends CI_Controller {
  function __construct() {
    parent::__construct();
  }
}
Models

class Contact_model extends CI_Model {
  function __construct() {
    parent::__contruct();
  }
}


Create Restful webservices using CodeIgniter

There is a very good tutorial on that website:
http://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter--net-8814

You need to have  CodeIgniter already set-up (if not, you can go to http://www.codeigniter.com/ and follow to instruction for installation: http://www.codeigniter.com/userguide3/installation/index.html) 

Next, you will have to download the restserver Library  (cf. https://github.com/chriskacerguis/codeigniter-restserver) and merge the application folder with that of CodeIgniter website;

Two folders should be updated : application\library (3 files) et application\config (1 file : rest.php)

Next, we will show how to generate a simple RestFUL XML service:

Create a file for the controler within application\controllers: lets name it : hellows .php :



Not, instead of writing a basic CodeIgniter controler like 


<?php
class hellows extends CI_Controller {

}
...you will need to use:

<?php

require(APPPATH.'libraries/REST_Controller.php');

class hellows extends REST_Controller {


}

Working with Resources

Next, you will need to know what will be the ressource to call : say you want to call the world ressource ! you will then need to define 'world_get' function within that class if you want to access this ressource using a GET request (that will then be world_post for a POST request)


<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

require(APPPATH.'libraries/REST_Controller.php');


class hellows extends REST_Controller {


    function world_get() {
      // respond with information about world ressource
    }

}

Used to fetch information about an existing resource. This is used by browsers when you enter a URL and hit go, or when you click on a link, so it perfect for fetching information on one of your REST resources (like user).
Used to update an existing resource with information. Browsers use this to submit most types of forms on the internet, although some use GET as well by submitting the form action with a query string containing the field data.
Less commonly used and not supported by most browsers, PUT is used to create a new resource.
Also not used by many browsers, this HTTP verb rather obviously is used to delete a resource.
Here is the content of the file when accessing parameters and returning data:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

require(APPPATH.'libraries/REST_Controller.php');

class hellows extends REST_Controller {
        
    function world_get() {
        $data["returned"]= $this->get('id');
        $data['name'] = 'HELLO';
        $data['university'] = 'coventry';
        $this->response($data, 200);    
    }   
    
}

This example contains 2 new pieces of code:
Is used to return GET variables from either a query string like this index.php/hellows/world?id=1 or can be set in the more CodeIgniter'esque way with index.php/hellows/world/id/1.
Sends data to the browser in whichever data format has been requested, or defaults to XML. You can optionally pass a HTTP status code to show it has worked or failed. E.g if the ID provided was not in the database, you could use $this->response(array('error' => 'parameter not found.'), 404);

When calling the following URL:  http://localhost/CodeIgniter/index.php/hellows/world?id=1

You will get a JSON or XML file depending of  $config['rest_default_format'] value (i.e. 'json' or 'xml') in config/rest.php file;

{
  • returned: "1",
  • name: "HELLO",
  • university: "coventry"
}

Now, if you want to specify a different format (xml), you can also do it through the URL call:

http://localhost/CodeIgniter/index.php/hellows/world/id/1/format/xml

<xml><returned>1</returned><name>HELLO</name><university>coventry</university></xml>





Wednesday, 11 February 2015

Automatically refreshing JSON data from HTML tables using Datatables JQuery plugin

Imagine you have make a script passing data from JSON file to HTML table using DataTables JQuery plugin: this will be something like this :

    $("#hour_refundall").text('à '+ getActualHour());  
    
    var table_refund =  $('#tbrefundall').dataTable( {
        "ajax": {
            "url": "http://localhost/boot/late_payment.php?function=controle_remboursement_retard&param=json_all",
            "dataSrc": ""
        },
        "columns": [           
            { "data": "purchase_serial_number" },
            { "data": "refund_request_amount" },
            { "data": "order_detail_unit_id" },
            { "data": "purchase_creation_date" },
            { "data": "lastmod" },
        ],
        "columnDefs":[
            {
                // The `data` parameter refers to the data for the cell (defined by the
                // `data` option, which defaults to the column being worked with, in
                // this case `data: 0`.
                //"data" : "purchase_serial_number",
                "render": function ( data, type, row ) {

                    return '<a href="..?id=' + data + '"> ' + data + ' </a>';
                },
                "targets": [0]
            }

        ]
    } );

To add an automatic refresh on this table, you have just to add the following script:

    setInterval( function () {      
        table_refund.api().ajax.reload();
        $("#hour_refundall").text('à '+ getActualHour());  
        }, delay );


You will notice that I use the 'ColumnDefs' DataTables parameter to add an hyperlink to data on the table !!

Passing JSON data to build HighCharts plots Dynamically (using SetInterval)

As a reminder, here is the way of simply I did use previously to draw a Highcharts chart from JSON data :

 $(document).ready(function() {
                var options = {
                    chart: {
                        renderTo: 'graph_retard_refund',
                        type: 'area',
                        marginRight: 130,
                        marginBottom: 25
                    },
                    title: {
                        text: 'Nbre Commandes en Retards de remboursement par mois',
                        x: -20 //center
                    },
                    subtitle: {
                        text: '',
                        x: -20
                    },
                    xAxis: {
                        categories: []
                    },
                    yAxis: {
                        title: {
                            text: 'Nb de Commandes'
                        },
                        plotLines: [{
                            value: 0,
                            width: 1,
                            color: '#808080'
                        }]
                    },
                    tooltip: {
                        formatter: function() {
                            return '<b>'+ this.series.name +'</b><br/>'+
                            this.x +': '+ this.y;
                        }
                    },
                    legend: {
                        layout: 'vertical',
                        align: 'right',
                        verticalAlign: 'top',
                        x: -10,
                        y: 100,
                        borderWidth: 0
                    },
                    plotOptions: {
                        area: {
                            stacking: 'normal',
                            lineColor: '#666666',
                            lineWidth: 1,
                            marker: {
                                lineWidth: 1,
                                lineColor: '#666666'
                            }
                        }
                    },
                    series: []
                }

                $.getJSON("http://localhost/boot/late_payment.php?function=controle_remboursement_retard&param=graph", function(json) {
                    options.xAxis.categories = json[0]['data'];
                    options.series[0] = json[1];
                    chart = new Highcharts.Chart(options);
                });
            });


Now, if you want an automatic refresh of the graph every minute, you will to use  the "destroy()" function from HighCharts and the well-known setinterval JavaScript function  :

( see http://stackoverflow.com/questions/11752320/auto-refreshing-highcharts-with-php-js)

$(document).ready(function() {
    var options_payment = {
        chart: {
            renderTo: 'graph_retard_payment',
            type: 'area',
            marginRight: 130,
            marginBottom: 25
        },
        title: {
            text: 'Répartitions du nbre Commandes en Retards de paiements dans le temps',
            x: -20 //center
        },
        subtitle: {
            text: '',
            x: -20
        },
        xAxis: {
            categories: []
        },
        yAxis: {
            title: {
                text: 'Nb de Commandes'
            },
            plotLines: [{
                value: 0,
                width: 1,
                color: '#808080'
            }]
        },
        tooltip: {
            formatter: function() {
                return '<b>'+ this.series.name +'</b><br/>'+
                this.x +': '+ this.y;
            }
        },
        legend: {
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'top',
            x: -10,
            y: 100,
            borderWidth: 0
        },
        plotOptions: {
            area: {
                stacking: 'normal',
                lineColor: '#666666',
                lineWidth: 1,
                marker: {
                    lineWidth: 1,
                    lineColor: '#666666'
                }
            }
        },
        series: []
    }
    $.getJSON("http://localhost/boot/late_payment.php?function=controle_paiement_retard&param=graph", function(json) {
        // $('#graph_retard_payment').highcharts().destroy();
        // if(chart) chart.destroy();
        options_payment.xAxis.categories = json[0]['data'];
        options_payment.series[0] = json[1];
        chart = new Highcharts.Chart(options_payment);
        $("#hour_retard_payment").text('à '+ getActualHour()); 
    });

    var autoRefreshGraph_retard_paiement = setInterval(function() {

        $.getJSON("http://localhost/boot/late_payment.php?function=controle_paiement_retard&param=graph", function(json) {
            // $('#graph_retard_payment').highcharts().destroy();
            if(chart) chart.destroy();
            options_payment.xAxis.categories = json[0]['data'];
            options_payment.series[0] = json[1];
            chart = new Highcharts.Chart(options_payment);
            $("#hour_retard_payment").text('à '+ getActualHour()); 
        });
        } , delay);  
    }
); 

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)