Thursday, 26 February 2015

Updating HTML Table (with DataTables JQuery plugin) when clicking on data from a chart from HighCharts

The problem I had to solve was to trigger an event as I click on the chart ; the event was to update the corresponding details data within a table that was refreshed as I had clicked on different points on the chart.

Here is the solution :

// the table being identificated by id = table_retard_payment has to be initiated without any filter
    var table =  $('#table_retard_payment').dataTable( {
       "language": {
           "url": "http://localhost/boot/js/DataTables.French.json"
       },
        "ajax": {
            "url": "http://localhost/boot/late_payment.php?function=controle_paiement_retard&param=json",
            "dataSrc": ""
        },
        "columns": [        
            { "data": "purchase_serial_number" },
            { "data": "purchase_creation_date" },
            { "data": "lastmod" },
            { "data": "purchase_status_fraud" }
        ]
    } );

// the chart (identified by id = graph_retard_payment)  with "plotOptions:area" parameter containing the click event with the load of  url adding the x-value of data of the chart : '..&date=' + this.category

    var options_payment = {
        chart: {
            renderTo: 'graph_retard_payment',
            type: 'area',
            marginRight: 50,
            marginBottom: 100
        },
        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: 'bottom',
            x: -20,
            y: 200,
            borderWidth: 1
        },
        plotOptions: {
            area: {
                stacking: 'normal',
                lineColor: '#666666',
                lineWidth: 1,
                marker: {
                    lineWidth: 1,
                    lineColor: '#666666'
                },
                 point: {
                    events: {
                        click: function (e) {

                           table= $('#table_retard_payment').DataTable();
                           table.ajax.url("http://localhost/boot/late_payment.php?function=controle_paiement_retard&param=json&date="  + this.category).load();


                        }
                    }
                }
            }
        },
        series: []
    }

IN "aqua", indicate the code code that I added to initiate and update the data table (with datatabvle jquery pluggin)..

Here is the copy screen of the result table with the associated graph :



Wednesday, 25 February 2015

Using AngularJS & bootstrap UI: generating table with search, pagination filters through json data

Here is the web site that helps me to solve this issue :
  • http://stackoverflow.com/questions/28172165/angular-js-working-with-json-data
  • http://stackoverflow.com/questions/19409492/how-to-achieve-pagination-table-layout-with-angular-js
For the test data, I use a Json file that can be reached at : https://api.github.com/repos/angular-ui/bootstrap/issues

The script is limited to the one below..

Here is the HTML file :

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
        <script src="http://code.angularjs.org/1.2.16/angular.js"></script>
        <script src="http://code.angularjs.org/1.2.16/angular-resource.js"></script>
        <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
    </head>
    <body>
        <div ng-app="myApp" ng-controller="myCtrl">
            <div class="row">
                <div class="col-lg-6"> 
                    <div class="panel panel-info">
                        <div class="panel-heading">
                            <h3 class="panel-title"><i class="fa fa-table fa-fw"></i> Issues list</h3>                        
                            <div class="pull-right">Search: <input ng-model="query">
                            </div>
                            <div class="panel-body">
                                <table class="table table-striped table-hover table-bordered">
                                    <thead>
                                        <tr>
                                            <th>ID</th>
                                            <th>Title</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr ng-repeat="obj in issues  | filter : paginate  | filter : query">
                                            <td>{{obj.id}}</td>
                                            <td>{{obj.title}}</td>
                                        </tr>
                                    </tbody>
                                </table>
                                <pagination total-items="totalItems" ng-model="currentPage"
                                    max-size="5" boundary-links="true"
                                    items-per-page="numPerPage" class="pagination-sm">
                                </pagination>
                            </div> <!-- /panel-body -->
                        </div> <!-- /panel-heading -->
                    </div> <!-- /panel-info -->           
                </div> <!-- /col-lg-6 -->
            </div>
        </div>
        <script>
            var app = angular.module("myApp", ['ui.bootstrap', 'ngResource']);
            app.controller("myCtrl", function($scope,$http) {
                $http.get("https://api.github.com/repos/angular-ui/bootstrap/issues")
                .success(function(response) {
                    $scope.issues = response;
                    $scope.totalItems =response .length;
                    $scope.currentPage = 1;
                    $scope.numPerPage = 5;

                    $scope.paginate = function(value) {
                        var begin, end, index;
                        begin = ($scope.currentPage - 1) * $scope.numPerPage;
                        end = begin + $scope.numPerPage;
                        index = response .indexOf(value);
                        return (begin <= index && index < end);
                    };

                })
            });
        </script>
    </body>
</html>

A screen shot of the result is shown here :

Monday, 23 February 2015

Updating HTML Table (with DataTables JQuery plugin) when clicking on data from a Morris chart

Let's say that you have a certain Morris graph (donuts-like graph) and as you click to certain part of the donuts, you would to get the details of corresponding data in a table :



Well, in the case of data being populated by json file, you will have to apply a "on('click', function(i,row){
}" to you Morris graph.

The best thing is first to call the following console function  "console.log(i, row); ", and see the value in the console windows (in your debugger development tool such as "Firebug") as you click on the graph.

For Morris Donuts, you will then have 'row.label' corresponding to label ('restocking' above)  and 'row.value' ('8' above) of the part where you have clicked.

Having that information, you can , for example, upload a data-table depending on the label (row.label) you have clicked on :

DONUT
$.getJSON("http://localhost/boot/get_repartition_order_status_today_morris_donut.php?type=graph", function (json) 
{
        var DonutGraph = new  Morris.Donut({
            element: 'morris-donut-chart',
            data: json,
           
        }).on('click',function(i,row){

           tbtoday_orders_by_status =                      
           $('#tbtoday_orders_by_status').DataTable();

           tbtoday_orders_by_status.ajax.url( "http://localhost/boot/get_repartition_order_status_today_morris_donut.php?type=table&status=" + row.label).load();
                                              
           $("#hour_day_activity").html(getActualHour());
       });
       setInterval(function() {
            updateLiveDonutGraph();
       }, delay);
});



The best thing is first to show data-table with all the data (no -filter at all) as an initialization of the table (that's the reason of using ajax.url(..).load right above): 


var tbtoday_orders_by_status =  $('#tbtoday_orders_by_status').dataTable( {
        "language": {
            "url": "http://localhost/boot/js/DataTables.French.json"  
        },
        "ajax": {
            "url": "http://localhost/boot/get_repartition_order_status_today_morris_donut.php?type=table",
            "dataSrc": "" 
        },
        "columns": [           
            { "data": "purchase_serial_number" },
            { "data": "purchase_creation_date" },
            { "data": "lastmod" },
            { "data": "status" }
        ]

    } );  


For bar and line Morris graph, this will be quite similar:

BAR  $.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']
        }).on('click',function(i,row){
              alert("Element no " + i + " : date " + row.date_purchase + " - nb order waiting to be analysed (0) :" + row.y0 
              + " - nb order waiting for justification (40) :" + row.y40
              + " - nb order confirmed fraud (80) :" + row.y80
              + " - nb order cancelled (90) :" + row.y90
              + " - nb order accepted (100) :" + row.y100
              );
             console.log(i, row);
        });
        setInterval(function() { updateLiveBarGraph(BarGraph); }, delay);
    });

 
LINE   $.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"]
        }).on('click',function(i,row){
              alert("Element no " + i + ": " + row.date 
              + " - cancelled amount :" + row.annulation
              + " - goodwill gesture amount :" + row.geste_co
              + " - shipped amount :" + row.expedie
              );
             console.log(i, row);
        });
        setInterval(function() { updateLiveLineGraph(LineGraph); }, delay);
    });

    


Changing the default number of shown elements in table using DataTables JQuery plugin

Let's imagine you have an HTML table like this one ;
<table  id="tbrefundall">
   <thead>
       <tr>
         <th>No Commande (PSN)        </th>
         <th>Montant Rembt</th>
         <th>Type Rembt</th>
         <th>Date Commande</th>
         <th>Date Demande Rembt</th>
         <th>Action</th>
       </tr>
</table>



And the following JavaScript code to generate the table content from JSON data with Jquery DataTables plugin:

var table_refund =  $('#tbrefundall').dataTable( {
        "language": {
            "url": "http://localhost/boot/js/DataTables.French.json"  
        },
        "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" },
            { "data": "purchase_serial_number"  }
        ]
    } );

http://www.datatables.net/forums/discussion/542/dynamically-change-idisplaylength/p1
http://stackoverflow.com/questions/12301286/change-the-number-of-displayed-rows-in-jquery-datatable



By default, with DataTables JQuery plugin, the table comes with a set of default parameters ; these default parameters can be altered  in adding some parameters ; thus, for instants, there is a default number row to be shown (10) and the number of rows is limited to a certain of number within the following list (10,25, 50,100):







To alter this list and/or the default number you have  the parameter iDisplayLength ('i' for integer) and aLengthMenu ('a' for array):

If you want to show at first, the first five rows, you will set the following :   'iDisplayLength': 5
If you want to alter the menu for length, by adding 5 to the list :   "aLengthMenu":[[5, 10, 25, 50,100], [5,10, 25, 50, 100]],
If you want to alter the menu for length, by adding the possibility to see the whole list ; you will have to add "-1" and the corresponding text ('All" in English) :   "aLengthMenu":[[5, 10, 25, 50,100,-1], [5,10, 25, 50, 100,"all"]],

In the following, we then choose '5' to be the default number of rows to be shown and set the following menu : 5,10,25,50,100,-1 to be able to show the whole list:

var table_refund =  $('#tbrefundall').dataTable( {
        "language": {
            "url": "http://localhost/boot/js/DataTables.French.json"  
        },
        "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" },
            { "data": "purchase_serial_number"  }
        ],
        'iDisplayLength': 5,
        "aLengthMenu":[[5,10, 25, 50, -1], [5,10, 25, 50, "Tous"]],
    } );



Wednesday, 18 February 2015

Agile Methodologies (Extracted from "Professional CodeIgniter", Thomas Myer, 2008)

What Is Agile?


A lot of different definitions for Agile exist, ranging from the superficial to the authoritative and
pedantic. Not every definition is useful, nor is every definition really applicable to your job as a
software developer. Things only get more confusing once you realize that various Agile
methodologies exist, all of them competing for your attention.

At the end of the day, the most important thing to remember is this: Agile software development is
a conceptual framework that seeks to minimize risk by developing software in short amounts of
time. A typical iteration can last 1 to 4 weeks, during which time a software team performs tasks
from a complete project life cycle (planning, design, coding, testing, documentation). Each iteration
usually starts with stories (what Agile calls requirements ) and culminates in potentially shippable
software. Another important aspect of Agile is the team’s ability to self - organize as they
communicate face - to - face with stakeholders and other team members.

If you ’ re not familiar with Agile, you probably have one of two reactions:
  • “ How is this different from cowboy coding? Agile sounds just like every chaotic code - and -fix project I 've ever been part of. ”
  • “ How does anyone get anything done in so short a time? Agile sounds like a perpetual hamster wheel where everyone burns out. ”
First of all, if you have doubts when you first encounter Agile, welcome to the club. Rest assured that everyone who takes a closer look and sees Agile in action usually crosses over.
Second, many people out there made the initial mistake of distinguishing Agile methodologies as
somehow “ lightweight ” (as opposed to the heavyweight models like waterfall) or “ unplanned ” (which inspires the mistaken belief that Agile developers are undisciplined).

A better way to look at Agile is to say that the entire process is adaptive instead of predictive. For example, if you were to start a project using waterfall methods, you would spend a lot of time trying to nail down schedules, resources, requirements, deadlines, milestones, and the like. If anything changes, you have to go back and reevaluate your initial inputs. It ’ s very much like planning a road trip to Las Vegas down to the last detail (including where you would make rest stops, how much gas you would buy at each gas station, what sandwiches to pack) but then encountering a sandstorm right at the edge of the city and having to turn back home to try again later.

An Agile road trip to Vegas would be different. The process would start with a focus on gambling in
Vegas, and then a minimal amount of work would be done to get the car ready and rolling. Everyone
would bring his or her own snacks and gas money. Once on the road, travelers are free to take advantage of opportunities. Perhaps someone sees a casino just outside the town they left from, and the group decides to gamble there. After all, the goal is to gamble, right? It ’ s this kind of adaptive thinking that gives Agile its power and flexibility.

Third, many outsiders have a bone to pick over the short iterations in Agile. They can ’ t conceive that quality software can be developed in a week or two. Normally, this assertion would be true, but with the right tools (i.e., CodeIgniter and other MVC frameworks, especially those that focus on delivering convention - over - configuration benefits), you can achieve in hours what normally would take days or weeks. Most people don ’ t stop to consider that an enormous amount of overhead time is devoted to non - programming tasks. Developers tend to forget the painful hours spent in meetings, all the hours devoted to planning and analysis, and all the time spent debugging. On a typical project, a developer might spend 2 to 3 hours a day programming and the rest in meetings, debugging, documenting, or researching a tough problem. If she ’ s lucky! On the other hand, it is possible, with the right tools and the right methodologies, to create shippable software in very short iterations. The result is working software, happy customers, and developers with a sense of job satisfaction. What could be better?

Are there places where Agile is not a good idea? Of course: Agile works best when you have smaller
teams in one location, more experienced developers, quickly changing environments, and a culture that is not exclusively driven by top - down command and control structures. In other words, trying to build a giant weapons software platform for the Army that involves 1,000 developers in three geographically separate locations would probably not make a good case study for any Agile methodology.

That being said, your average web application can easily be built following Agile. It doesn ’ t matter what kind of application: blog, newsletter tool, content management, shopping cart, or content portal.

If you can keep the team under 20 developers (or better yet, a dozen) and keep them communicating well, you can pull it off.

Post - Agilism

Any successful movement will have some members who eventually move on to something else. In the case of Agile methodologies, there is Post - Agilism. What is Post - Agilism? It ’ s a loose group of developers and other IT professionals who have experience with Agile but have now moved on to other approaches.

The most thoughtful Post - Agilists (if they would allow themselves to be labeled as such, and even that is up for grabs) make a fine distinction between being “ agile ” (defined as being adaptive in a social or commercial circumstance) and being “ Agile ” (living by the rules, dogma, or inherited wisdom of a particular Agile methodology, like Scrum or XP). It ’ s therefore possible to be “ agile ” without necessarily having to take on all the trappings of any particular Agile approach.

Of course, the way I am using “ agile ” and “ Agile ” here is merely to differentiate the concepts. Within the Agile community and throughout this book, “ Agile ” is the way you see the word presented. There is no formal distinction between “ Agile ” and “ agile. ”

Another extremely valid concern brought up by Post - Agilists (again, please forgive the use of broad
labels) is that the Agile movement was once about shaking the industry out of the waterfall
methodology, the predictive mess to which everyone was so well accustomed. Now they feel that
everyone is trying to follow the Agile Manifesto (and other touchstone documents) as some kind of
canonical bible, replacing the earlier problem with a newer adherence - to - dogma problem.

To be clear, any time that “ Agile ” is mentioned in this book, it is in the spirit of little - “ a ” “ agile. ” It is more important for you, the developer, to be adaptive and successfully complete a project than to adhere strictly to the rules of a certain methodology.

Notable Agile Methodologies

Some people feel a little anxious about mixing methodologies. However, that is actually at the heart of being agile . Where Agile with a capital “ A ” focuses on the purity of the model, agile with a small “ a ” focuses on freeing you up to do whatever will help you quickly and easily achieve your goals. Being “ agile ” is about being adaptive and fast on your feet.

In the real world when you are working with clients, any time you have to decide between getting things done on schedule and strictly adhering to theoretical rules, always err on the side of getting things done.

It may get under your skin a bit, but it ’ s really the only way to keep the customer happy.

Scrum

Scrum is an Agile project management methodology that offers small teams a great deal of flexibility
(even by Agile standards). Here are the typical attributes of a Scrum undertaking:
  • You need a product backlog (fr:"carnet de commande")— a prioritized list of work items that need completion.
  • The self - organizing team uses the product backlog to create sprint backlogs .
  • Each sprint is a short period of duration (usually 1 to 4 weeks) in which highly focused activity takes place.
  • Each sprint begins with a sprint planning session , in which backlog items for the sprint are defined.
  • Each sprint ends with a retrospective , in which a postmortem is performed.
Each team has a ScrumMaster, who acts as coach, facilitator, and buffer against the outside world. The ScrumMaster is not the leader of the team! Many outsiders view the ScrumMaster as the chief project manager, but it ’ s not so.

Scrum recognizes that customers are wont to change their minds about what they want. Sometimes the changes in direction are subjective and capricious, and other times they come about because of market pressures. Regardless of the reason, change happens, and normal predictive methodologies have zero chance of predicting these changes (ironically). Instead, Scrum accepts that change is inevitable, unpredictable, and indefinable, and focuses instead on maximizing the team ’ s ability to adapt to change and still deliver a great product.

The team works closely with stakeholders (such as business owners, marketing managers, the CEO,
CFO, etc.) to develop a backlog of requirements that need to be addressed. Normally, this backlog of
requirements is maintained by a certain stakeholder called the “ product owner. ” In most cases, the
product owner is the CEO, but it can also be a marketing manager or project manager

The backlog is essentially a list of prioritized requirements that emanate from the end - customer. At the start of each sprint, the team takes the top remaining items from the product backlog and turns them into tasks on the sprint backlog. It ’ s important for the team to only take on as many tasks as can be completed in any given iteration.

The goal of any iteration is to create potentially shippable software — in other words, by the time you ’ re at the end of the time box (1 week, 2 weeks, whatever), what you have could be considered ready to ship. It is functionally complete, reasonably bug - free, and reasonably documented.

For example, a product backlog might have several prioritized items on it, like so:
  • The customer wants to be able to securely check page views and other stats about their web site.
  • The customer wants hyperlinks within the report.
  • The customer wants real - time access to data, without lag.
  • The customer wants info graphics associated with the data, not just tabular data.
The team might look at this product backlog and decide to convert the first two bullet items into a series of tasks:
  1. Create views to display the report.
  2. Create models to connect to data sources.
  3. Create a controller to identify and separate different destinations.
  4. Implement a security model.
The real task list would probably be longer than that, but you get the idea. Because the team is self -
organizing, the HTML/CSS expert would tackle the views, the database expert would construct the
models, and the security expert would implement the security model. If no security expert is on
the team, perhaps someone remembers that a security module was written for another project — might it not be useful in this context?

The sprint is set at 2 weeks, and the team takes on the tasks, meeting every day for a standup meeting that lasts no more than 10 minutes. At each meeting, the ScrumMaster asks three basic questions of each participant:
  1. What have you done since the last time we saw you?
  2. What are you going to do until the next time we see you?
  3. What obstacles or barriers are in your way?
The first question focuses on accomplishments , the second on to do ’ s , and the third on risks or
concerns . The standup meeting allows the entire team to check in and understand how the project is
going with a great deal of transparency. Very quickly, everyone gets a feeling for what ’ s been
accomplished, what is still left to do, and what ’ s standing in the way.

Outsiders (other than developers, ScrumMaster, and product owner) are allowed to join the meetings, of course, but they aren ’ t allowed to interfere directly in the project. What does “ interfere ” mean?

Well, in many software development projects, you see many business managers or complete outsiders dictating requirements. These requirements don ’ t come from the customers, they just arbitrarily live in the minds of senior management or outside stakeholders. Often, these arbitrary requirements impede schedules and complicate matters.

For example, there is rarely any real value to a requirement like “ It must ship in Q1. ” In the mind of the person who brought it up, it has importance, but not to anyone else. What does that mean? Well, on somebody ’ s strategic plan, such - and - such a product must ship in Q1, and the stakeholder ’ s bonus depends on it. The customer doesn ’ t care when the product comes out, just that it works the way they need it to when it does come out. (This is not to say that you should totally disregard a powerful stakeholder ’ s concerns about schedules and money. After all, they will hopefully be rehiring you or referring you to another business in the future. Treat them seriously and with respect. Just don ’ t let their concerns interfere with what you need to do to accomplish the project.)

What concepts are you going to take from Scrum? The idea of a backlog is key, as is the nature of sprints.

You ’ ll find that on many small projects, a sprint can last 1 or 2 days. You ’ ll also find that you don’ t need to have a daily standup meeting, especially if it ’ s just you working on things.

XP

The main thrust behind XP is to put in place daily practices that reconcile humanity and productivity.
What this means in practice is that there is more weight given to face - to - face communication and
feedback than to formal requirements’ gathering.

Furthermore, XP proponents expound on the value of doing something simple and clean today rather
than worrying about future problems that might entail complexity. For example, why worry about
scaling to 50,000 customers when you only have 5 customers today? Wouldn ’ t scaling out to 500
customers (or even 50!) be good enough to get something working now?

Another great thing from the XP movement involves the collegial respect between programmers.
Contributions are made in a give - and - take environment, and in fact, many programmers pair up to
tackle problems and work through issues. Finally, there is the matter of allowing programmers to take
ownership of their code. It is not unusual to see programmers refactor code to simplify even when it isn ’ t needed.

What are you going to take from XP? Definitely the simplicity and communication/feedback loops. It ’ s important to incorporate good listening skills to any Agile approach. When working with a client one -on - one, you will need to interface often. Make sure that you allow a significant amount of time for the face - to - face contact, as it can create a powerful bond between you and the client.

Modifying Scrum and XP

Scrum and XP (extreme programming), like all methodologies, are wonderful things, but one immediate drawback for you right now, as you read this book, is that you ’ re probably a lone programmer or work with a very small team. If so, you may be thinking that these approaches provide too much overhead even for you, and in some ways, you might be right. However, one of the great strengths of any Agile methodology is that it can be adapted to your needs.


CONCLUSIONS

  1. Agile methodologies are adaptive as opposed to predictive.
  2. Agile methodologies work best if you’ve got a small team working with a software project that is easily time - boxed. The team should meet regularly (daily if possible) and communicate about their achievements, to do’s, and risks.
  3. It ’ s almost always better to gather requirements by starting top - down and drawing mockups (fr: maquettes) with the customer.
  4. It ’ s important that the product owner (the customer) take charge of the product backlog as soon as possible. They ’ ve forgotten more about their business than you ’ ll ever know.
  5. It ’ s your job as developer to convert product backlog items into functional tasks in a sprint backlog.
  6. It is also your responsibility to estimate properly. Don ’ t overcommit with too many tasks in any given sprint.
  7. Don ’ t forget that many functional tasks can be leveraged across various areas of the current sprint (and even future sprints). For example, setting up good models for each database table allows you to quickly and easily work with those database tables for the rest of the project.
  8. The point of Agile is to break projects into manageable chunks. The emphasis is always on potentially shippable software at the end of any iteration or sprint. If a task can ’ t be completed properly or on time, it ’ s good and proper to try to reanalyze its importance and do something about it, instead of letting it fester and become a big problem.
  9. Because Agile projects tend to be iterative, it ’ s sometimes hard to give accurate estimates to customers. Remember to think in terms of time spent on units of work and in iterations, and only give ranges. The further out the timeline, the less accurate you can be. The bigger the unit of work, the less accurate you can be. For example, if you are estimating a 2 - week job, you might give an estimate that is plus - or - minus 5 percent. A 6 - month job may be on the order of plus - or -minus 30 percent.

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();
  }
}