Aller au contenu principal


Ajax

AJAX (Asynchronous JavaScript and XML) permet aux navigateurs affichant une page web de réaliser des requêtes (par exemple de gestion de Bases de données) sur le serveur Web et de modifier en direct l'affichage de la page (par exemple pour y inclure les réponses du serveur).

Billet créé le :
18 nov 2020

Un exemple d'utilisation

Dans cet exemple d'utilisation d'AJAX, j'utilise (comme c'est très souvent le cas) 4 fichiers, tous écrits dans un langage de programmation différent (les noms des fichiers sont librement choisis par le programmeur de la page).

Les 3 suivant s'exécutent côté Client (navigateur) et sont écrits respectivement en HTML, en CSS et en Javascript (et avec la bibliothèque Jquery) :

  1. "index.html" contient les instructions écrites en HTML (HyperText Markup Language) ;

  2. "index.css" est écrit en CSS (Cascading Style Sheets) ;

  3. "index.js" contient les instructions écrites en JavaScript (et utilise la bibliothèque JQuery) ; 

  4. "ajaxTest.php" est  écrit en PHP (PHP HyperText Preprocessor).

Les 3 premiers s'exécutent sur l'ordinateur du navigateur Internet (côté Client), le dernier s'exécute sur le serveur concerné par la requête (côté serveur).

L'exécution des fichiers de cet exemple, affiche sur le navigateur de l'utilisateur, le bouton  "c'est parti" sur lequel il cliquera pour afficher la liste des enregistrements de la table "classe" d'une base de données.

Comme le montre l'image ci-contre, le programme affiche :

  • en grisé avec un liseret rouge à droite, les informations brutes (utiles pour le développeur) renvoyées par le serveur ;

  • et entre les deux traits horizontaux, les données mises en forme pour l'utilisateur.

Ces 4 fichiers sont étudiés dans les paragraphes suivants. Leur code se trouve dans les onglets respectifs du paragraphe "Le contenu des différents fichiers".

Le fichier index.html

Ce fichier est le cœur de l'exemple.
Dans l'entête (balise HTML "header") du fichier s'effectue la déclaration des "bibliothèques" javascript (fichiers jquery.js et index.js) et css ( fichiers jquery-ui.css et index.css) utilisées par la page.
Dans le corps du fichier (balise HTML "body"), les identifiants "test" et "test2" réservent l'espace pour afficher les données fournies par le script "index.js".

Le fichier index.css

Ce code est responsable de la mise en forme de la page affichée sur le navigateur : gestion des 2 colonnes pour l'affichage du message d'attente puis pour l'affichage des informations "développeur".

Le fichier index.js

En fonctionnement normal, la fonction ajaxSuccess ("  $(document).ajaxSuccess (function(event, req, settings, donnee ){}"),  du fichier index.js complète le code html de la balise "div" identifiée" test2" par la portion de code "{ ... $("#test2").append( ...};". Pour comprendre le morceau de code " $("#test2").append", lire ce billet.
Cette fonction est déclenchée dès que la fonction $.ajax en  a terminé son exécution sans erreur. Cette dernière est elle même appelée par la fonction $.listeTest avec deux paramètres lorsque l'utilisateur clique sur le bouton (identifié "btnSubmit") du formulaire.

La fonction ajaxComplete  ( "$(document).ajaxComplete(function (event,req,settings){..  $("#test").html( msg ); ....}) complète le code html de la balise "div" identifiée" test". Pour comprendre le morceau de code " $("#test").html()", lire ce billet.
Elle est déclenchée dès que la fonction $.ajax a terminé son exécution.

La fonction ajaxSend ("$(document).ajaxSend(function(event,req,settings){..  } ") est appelée au déclenchement de la fonction $.ajax et permet l'affichage d'une image "loading" pour faire patienter l'utilisateur.

Les fonctions  ajaxError, ajaxStop sont appelées par $.ajax selon les résultats de son exécution.

Par exemple, le résultat produit lorsque le mot de passe est mal renseigné dans le ficher ajaxTest.php est présenté ci-dessous :

Tout d'abord, affichage de la fenêtre d'alerte déclenchée par 

ajaxError ("$(document).ajaxError (function(event, req,settings , err ){
        alert("dans " + settings.extra + " " + err);  });")


 


Puis l''affichage final produit  par ajaxComplete.
 

Les appels des gestionnaires Ajax

Ils sont  de la forme function (event, request, settings, opt) dans lesquels :

  • event : de  type object

  • request : la requête, de type object

  • settings : les paramètres de la fonction ajax, de type object

  • opt ; dépend du gestionnaire

    •  err : pour le gestionnaire ajaxError() ; de type object;

      • contient l'erreur générée par le fichier php appelé par ajax : (ex : HTTP/1.1 426 requete trop mal formulee ! : l'argument operation est inattendu : select)      

    • data : pour le gestionnaire ajaxSucess(); de type string

      • contient les données générées par le fichier php appelé par ajax

    • n'existe pas sinon

On utilise habituellement :

  1. request.readyState
          rends 0 : requête non initialisée, 1 : en cours de chargement, 2 : chargée, 3 : en cours d'interaction, 4 : terminée

  2. request.status pour le n°  figurant dans le header retouné par l'exécution du fichier php (ex : 426);

  3. request.statusText pour le texte figurant dans ce header (ex : requete trop mal formulee ! : l'argument operation est inattendu : select);

  4. request.responseText pour la valeur ( en texte) de retour fournie par le fichier php ;

  5. request.responseHTML ;

  6. request.responseJSON ;

 

  1. settings.url pour l'url du fichier php appelé par ajax (ex : ajaxTest;php);

  2. setting.extra pour obtenir la valeur du paramètre extra que j'ai utilisé dans ma fonction ajax et distinguer parmi l'ensemble des appels ajax, celui qui a provoqué le déclenchement du "handler" (ex : selectClasse);

  3. settings.data pour obtenir la valeur du paramètre data. Dans mon exemple, il vaut : op=selectClasse&nom=abcdefgh (les données passées dans l'url, lorsque le fonctionnement ne retourne pas une erreur) ;

 

  1. event.type (ex : ajaxComplete) ;

  2. event.handleObj.handler : le handler passé au gestionnaire.

 

information complémentaire disponible en cliquant ici Les propriétés de l'objet "settings"


Pour obtenir la liste des propriétés d'un objet, il est possible de procéder avec la portion de code ci-dessous  utilisé pour l'objet "settings"

 

Object.getOwnPropertyNames(settings).forEach(function(val, idx, array) {
    msg += val + ' -> ' + settings (val ) + '</br>';
});



On accède à la valeur de la propriété par exemple par settings.url
    url -> ajaxTest.php
    type -> POST
    isLocal -> false
    global -> true
    processData -> true
    async -> true
    contentType -> application/x-www-form-urlencoded; charset=UTF-8
    accepts ->
    contents ->
    responseFields ->
    converters ->
    flatOptions ->
    xhr -> function (){try{return new XMLHttpRequest}catch(a){}}
    jsonp -> callback
    jsonpCallback -> function (){var a=Fb.pop()||n.expando+"_"+cb++;return this=!0,a}
    extra -> listeTest
    data -> op=selectClasse&nom=abcdefcghiklmnopqrstuvwxyz
    dataType -> json
    dataTypes -> text,json
    crossDomain -> false
    hasContent -> true

Le fichier ajaxTest.php

Ce code établit la connexion avec la base de données, manipule les données de cette base et renvoie le résultat sous l'encodage Json. Pour en savoir plus, vous pouvez consulter la page "tester un script de gestion de base de données".

Le contenu des différents fichiers

Cliquez sur le bouton pour copier le code 
dans le presse papier
    
            <?php
              # FileName="index.php"
              # etude de AJAX
              #
              header("Content-Type: text/html; charset=UTF-8");
            ?>
            <html>
            <head>
              <meta http-equiv="Content-Type" content="charset=utf-8"/>
              <title> Test des ajaxEvent </title>
              <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/cupertino/jquery-ui.css">
              <link rel="stylesheet" href="index.css">
              <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
              <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
              <script src="index.js"></script>
            </head>
            <body>
              <div>
                <div  class="colonne">
                  <div id="loading" class="colonne"">
                        <img src="loading.gif" width="100px">
                   </div
                   <div id="test" class="colonne"">
                      <!-- complete par le script   info pour le developpeur-->
                  </div>
                 </div>
                <hr/>
                <div id="test2">
                  <!-- complete par le script  info pour l utilisateur-->
                </div>
                <hr/>
                <form id="bySamClasseForm"  name="form1" action="" method="POST">
                    <input type="button" id="btnSubmit" value="C&#39;est parti..." />
                </form>
              </div>
            </body>
                     
Cliquez sur le bouton pour copier le code 
dans le presse papier
    
            /*
            * index.js
            * script pour index.php
            *
            */
            $(function(){
            // mes fonctions
                $.listeTest = function(operation, name) {
                    console.log ('dans listeEtudiant : operation = ' + operation );
                    <span style="background-color:#FFFF00;">$.</span><span style="background-color:#FFFF00;">ajax</span>({    
                        //voir ajaxSetup non recommandee par api.jquery
                        type: 'POST',
                        url: 'ajaxTest.php'
                        extra: 'listeTest',
                        data: {
                            op  : operation,
                            nom : name,
                        },
                        dataType: 'json'
                    });
                    return true;
                };
             //fin mes fonctions
                $("#loading").hide();
                $(document).ajaxSend(function(event,req,settings){
                    $("#loading").show();
                    $("#test").text("Lancement de la requete " +  settings.url  );    
                });
                $(document).ajaxSuccess (function(event, req, settings, donnee ){
                    var rows = donnee;
                    console.log ('dans ' + settings.extra + ' : data = ' + settings.data);
                    if (settings.extra == 'listeTest'){
                        for (var i in rows) {
                            $("#test2").append(rows[i].NomClasse + " : " + rows[i].NumClasse + " : " + rows[i].Libelle  + '<br/>');
                        }
                });
                $(document).ajaxError (function(event, req,settings , err ){
                    alert("dans " + settings.extra + " " + err);
                });
                $(document).ajaxStop(function(event, req, settings){
                    $("#loading").hide();
                })
            $(document).ajaxComplete(function (event,req,settings){
                    var msg = "Déclenché par le gestionnaire ajaxComplete :  ";
                    msg += "</br>requête : " + req.status + " -:- " + req.statusText;
                    msg += "</br>réponse reçue : "+ req.responseText;
                    msg += "</br>settings :";
                    msg += "</br>&nbsp;&nbsp;&nbsp; url :  " + settings.url;
                    msg += "</br>&nbsp;&nbsp;&nbsp;type : " + settings.type;
                    msg += "</br>&nbsp;&nbsp;&nbsp;data : " + settings.data;
               $("#test").html( msg ); });   
                $('#btnSubmit').on('click', function(e) {
                    $.<span style="background-color:#FFFF00;">listeTest</span>('selectClasse','abcdefcghiklmnopqrstuvwxyz');
                });
            });
                 
Cliquez sur le bouton pour copier le code 
dans le presse papier
   
            .colonne {
                display : table-cell;
                padding :10px;
            }
            .colonne:first-child{
                background:#F7F7EF;
                width : 19%;
                vertical-align: middle;
                border-right-color: red;
                border-right-style: groove;
            }
            .colonne + .colonne {
                border-left : 2px solid #fff;
                width :80%;
                vertical-align :middle;
             }
                 
Cliquez sur le bouton pour copier le code 
dans le presse papier
                      
            <?php
                # FileName="ajaxTest.php"
                # Type="MYSQL"
                header('Content-Type: text/html; charset=UTF-8');
                //connection a la BD
                $hostname = "localhost";
                $database = "gestconv";
                $username = "xxxxxx";
                $password = "**************";
                $mysqli = new mysqli($hostname, $username, $password, $database);
                // Check connection
                if (mysqli_connect_errno())
                     {
                    $msg = "HTTP/1.1 428 Failed to connect to MySQL:" . mysqli_connect_error();
                    header($msg);
                    exit();
                     }
                // Change character set to utf8
                mysqli_set_charset($mysqli,"utf8");
                //--------------------------------------------------------------------------
                // 2) Query database for data
                //--------------------------------------------------------------------------
                if (!(isset($_POST['op']) && strlen($_POST['op'])>0)){
                    $msg="HTTP/1.1 427 requete trop mal formulee ! : l'argument operation est inattendu : ";
                    header($msg);
                    exit();
                }  
                //sanitize post value, PHP filter FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH Strip tags, encode special characters.
                $op = filter_var($_POST["op"],FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
            switch ($op){
                    case "selectClasse":
                        // la requete SQL
                        $sql = "SELECT NumClasse, NomClasse, Libelle, PourcentageReussite FROM classe ORDER BY NomClasse ASC ";
                        $result = $mysqli
                            ->query($sql);   
                        $data = array();  
                        if ($result->num_rows > 0) {
                            // output data of each row
                            while($row = $result->fetch_assoc()) {
                                $data[] = $row;
                            }
                        }
                        else {
                            //pas d'enregistrement associe
                            $data[] = "vide";
                        };
                        $mysqli->close();
                        echo json_encode( $data );
                        //echo $data;            
                        break;
                    default :
                        $msg="HTTP/1.1 426 requete mal formulee ! : l argument operation est inattendu : " . $op;
                        header($msg);
                        break;
                }
            ?>
                 

Cliquez ici pour afficher ces  fichiers dans une fenêtre surgissante