Partage
  • Partager sur Facebook
  • Partager sur Twitter

Détecter l'inactivité d'un utilisateur

Javascript

Sujet résolu
    7 août 2007 à 18:47:23

    Salut ;)

    Je voudrais pouvoir détecter l'inactivité d'un utilisateur en surveillant son clavier et la souris.

    En gros, ouvrir une page parent au bout de 30 secondes d'inactivité...

    C'est possible ? Oui, mais comment ?

    Autant je me débrouille bien en PHP, autant je rame en JS ^^
    • Partager sur Facebook
    • Partager sur Twitter
      8 août 2007 à 3:35:46

      Bonjour à toi ami zéro :)

      Le principe de ce script est un peu original dans la mesure où tu n'attends pas un événement qui est par définition actif mais une inactivité qui se traduit par l'absence d'événements.

      Comme tu dois déjà le savoir, détecter un évément est chose aisée grâce à javascript alors qu'en détecter l'absence demande un petit plus d'astuce. Le principe serait de tester à des intervalles de temps réguliers si un événement ne s'est pas déclenché depuis un certain temps. Pour cela, un peu de préparation peut-être nécessaire, histoire d'avoir les idées claires. ;)

      Que veut-on ? Dans un premier temps, détecter une inactivité, et, dans un second, savoir depuis quand elle dure. Comme tu l'as bien précisé, on peut considérer que si le visiteur n'utilise ni son clavier, ni sa souris, c'est qu'il est inactif ^^ (sinon je demande à voir).


      Détecter l'inactivité



      Un peu de réflexion



      Pour atteindre notre premier but, il faut créer une fonction qui teste toutes les x secondes si la souris a bougé ou si une touche du clavier a été pressée. Pour ce faire, les événements javascript vont nous être indispensables :

      - pour détecter les mouvements de la souris, on utilise onmousemove
      - pour détecter l'activité du clavier, on utilise onkeydown (ou onkeypress)
      - pour lancer une fonction toutes les x secondes, on utilise la fonction setTimeout()

      Mais mais... o_O On ne peut pas utiliser ces événements dans la fonction que l'on va créer !

      Effectivement, la fonction n'est lancée que de temps en temps et il faut savoir si une activité quelconque a été détectée entre les deux derniers appels de fonctions. Pour cela, il suffit donc d'enregistrer toute activité dans une variable que la fonction testera une fois appellée.

      Supposons que l'on crée une variable booléenne (qui prend pour valeur true ou false) avec pour nom activite_detectee. Par défaut, la variable a pour valeur false (pas d'activite détectée) car le but étant de détecter une activité il faut prendre pour hypothése de départ que le visiteur est inactif.

      Ainsi, dès qu'un événement est détecté on change la valeur de activite_detectee pour true.
      Le but de notre fonction sera donc de tester la valeur de cette variable.

      C'est bien beau tout ça, mais dans ce scénario, dès qu'une activité est détectée, la variable prend la valeur true sans discontinuer... :colere2: Pas possible de détecter une activité une seconde fois alors !

      Justement, notre fonction va faire en sorte de repartir de zéro : soit aucune activité n'a été détectée et alors on attend encore, rien ne change, soit une activité a été détectée et alors on annule tout et on recommence, ce qui revient à donner pour valeur false à activite_detectee.

      Mise en application



      Le principe a été mis en place, nous pouvons nous lancer dans l'écriture du script capable de distinguer activité et inactivité chez un visiteur.
      Il est une bonne habitude à prendre lorsque l'on utilise un script javascript assez conséquent dans ses sites web, c'est de séparer javascript et html. Dans cet exemple, je vais donc créer un fichier activite.js à part que j'incluerais dans la page html.

      Par où commencer ? Quand on a une certaine expérience en ce qui concerne la programmation, il est possible de commencer indifférement par la détection des événements ou par la construction de la fonction, cependant, par souci de logique, je préfére démarrer par la détection des événements sans lesquels la fonction n'aurait aucun sens : c'est un peu comme travailler sur du vide.

      Mais au fait, on les pose où les événements javascript ? o_O

      On cherche à détecter toute activité quelle que soit sa "position" sur la page. Le plus logique reste donc de détecter ses événements au niveau du body. On a donc le document suivant :

      1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
      3.   <head>
      4.     <title>Activité et inactivité d'un visiteur</title>
      5.     <meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1" />
      6.     <script type="text/javascript" src="activite.js"></script>
      7.   </head>
      8.   <body onkeydown="activite_detectee = true;" onmousemove="activite_detectee = true;">
      9.     <h3>Bonjour et bienvenue, cher visiteur !</h3>
      10.     <p>Nous testons actuellement, et tout le long de votre présence sur cette page, votre activité et inactivité. Merci d'avoir bien accepté de participer à l'expérience.
      11. Orka et son équipe.</p>
      12.   </body>
      13. </html>

      Dans cette page, les seuls éléments importants sont les balises <script></script> et la balise <body>.
      En effet, les balises <script></script> permettent d'inclure le code javascript dans la page et la balise <body> permet de détecter les événements révélateurs d'une activité chez le visiteur, ce sont donc les seules choses qui font tourner le script et donc, qui nous intéressent.

      On voit bien que lorsqu'une touche est appuyée ou que la souris bouge, la variable activite_detectee prend pour valeur true, comme prévu.

      Il s'agit maintenant de créer le fichier activite.js qui déclarera et initialisera (à false) la variable activite_detectee et créera la fameuse fonction dont on ne cesse de parler depuis tout à l'heure et qui portera le nom de testerActivite. Voici :

      1. // On déclare et initialise la variable
      2. var activite_detectee = false;
      3. var intervalle = 100;
      4. // On crée la fonction qui teste toutes les x secondes l'activité du visiteur via activite_detectee
      5. function testerActivite() {
      6.   // On teste la variable activite_detectee
      7.      // Si une activité a été détectée [On réinitialise activite_detectee]
      8.      if(activite_detectee)
      9.        activite_detectee = false;
      10.      // Si aucune activité n'a été détectée [rien pour le moment]
      11.      else {}
      12. }

      Le code est simple, il est commenté et j'en ai déjà expliqué le principe plus haut, donc je ne m'attarderais pas dessus, en revanche, on peut remarquer que dans ce script, la fonction n'est appellée à aucun moment. Il va donc falloir lui apporter quelques modifications.

      Par ailleurs, une variable inconnue s'est infiltrée dans le code, intervalle. Elle contient juste la valeur, en millisecondes, de l'intervalle de temps qui s'écoule entre deux appels de fonction. Créer une telle variable permet une modification rapide du script et accroît la lisibilité du code. Voici le fichier désormais :

      1. // On déclare et initialise les variables utilisée
      2. var activite_detectee = false;
      3. var intervalle = 100;
      4. // On crée la fonction qui teste toutes les x secondes l'activité du visiteur via activite_detectee
      5. function testerActivite() {
      6.   // On teste la variable activite_detectee
      7.      // Si une activité a été détectée [On réinitialise activite_detectee]
      8.      if(activite_detectee)
      9.        activite_detectee = false;
      10.      // Si aucune activité n'a été détectée [rien pour le moment]
      11.      else {}
      12.   // On relance la fonction ce qui crée une boucle
      13.   setTimeout('testerActivite();', intervalle);
      14. }
      15. // On lance la fonction testerActivite() pour la première fois, au chargement de la page
      16. setTimeout('testerActivite();', intervalle);

      Et voilà, maintenant, le code est fonctionnel, parole de scout ! :)

      Bah, c'est nul, on peut pas savoir si il marche vraiment le code, quand on teste on voit rien... :(

      Oui, bon c'est vrai, ça manque de dynamisme mais mon but à la base était de nous amener à un code fonctionnel ^^

      Je ne vais donc pas perdre de temps à expliquer le code qui suit (et qui est, soit dit en passant, strictement inutile pour la suite du travail) et qui permet de voir dynamiquement ce qu'il se passe dans notre code. Les commentaires sont là tout de même pour aider à la compréhension :

      FICHIER HTML
      1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
      3.   <head>
      4.     <title>Activité et inactivité d'un visiteur</title>
      5.     <meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1" />
      6.     <script type="text/javascript" src="activite.js"></script>
      7.   </head>
      8.   <body onkeydown="activite_detectee = true; statut('actif');" onmousemove="activite_detectee = true; statut('actif');">
      9.     <h3>Bonjour et bienvenue, cher visiteur !</h3>
      10.     <p>Nous testons actuellement, et tout le long de votre présence sur cette page, votre activité et inactivité. Merci d'avoir bien accepté de participer à l'expérience.
      11. Orka et son équipe.</p>
      12.     <p id="statut" style="color:#ff0000;">Vous êtes inactif.</p>
      13.   </body>
      14. </html>

      FICHIER activite.js
      1. // On déclare et initialise les variables utilisée
      2. var activite_detectee = false;
      3. var intervalle = 100;
      4. // On crée la fonction qui teste toutes les x secondes l'activité du visiteur via activite_detectee
      5. function testerActivite() {
      6.   // On teste la variable activite_detectee
      7.      // Si une activité a été détectée [On réinitialise activite_detectee]
      8.      if(activite_detectee)
      9.        activite_detectee = false;
      10.      // Si aucune activité n'a été détectée [on actualise le statut du visiteur]
      11.      else
      12.        statut('inactif');
      13.   // On relance la fonction ce qui crée une boucle
      14.   setTimeout('testerActivite();', intervalle);
      15. }
      16. // On crée une fonction qui permet de mettre à jour le statut du visiteur
      17. function statut(statut) {
      18.   // On initialise la variable bloc créée par souci de lisibilité
      19.   var bloc = document.getElementById('statut');
      20.   // On supprime l'ancien statut affiché
      21.   bloc.removeChild(bloc.firstChild);
      22.   // Suivant le statut, on change la couleur d'écriture
      23.   if(statut == 'actif')
      24.     bloc.style.color = '#00ff00'; // Vert
      25.   else if(statut == 'inactif')
      26.     bloc.style.color = '#ff0000'; // Rouge
      27.   // On affiche le nouveau statut
      28.   bloc.appendChild(document.createTextNode('Vous êtes ' + statut + '.'));
      29. }
      30. // On lance la fonction testerActivite() pour la première fois, au chargement de la page
      31. setTimeout('testerActivite();', intervalle);

      Et voilà ! Cela peut paraître un peu long mais c'est nécessaire pour que tout soit bien expliqué ! :) Et avant de passer à la deuxième (et dernière) section, un lien de test : je veux tester ce fichu code.


      Calculer le temps d'inactivité



      Un peu de réflexion



      Nous avons bien avancé, mais il nous reste encore un petit bout de chemin à faire : il va falloir déterminer, si une inactivité est détectée, depuis combien de temps celle-ci dure. Une bonne préparation doit nous permettre de rédiger la fin du script en deux coups de cuillère à pot ! :)

      Il va bien évidemment falloir mettre en action une nouvelle variable contenant le temps depuis lequel dure l'inactivité. On peut l'appeller temps_inactivite avec pour valeur initiale zéro. L'important, c'est de savoir comment lui donner la bonne valeur au fur et à mesure que le temps passe.

      Dès qu'une inactivité est détectée il faut, à chaque appel de la fonction testerActivite() et tant que l'inactivité persiste, mettre à jour la valeur de temps_inactivite. Dès qu'une activité reprend, on remet le compteur à zéro et on recommence...

      Oui c'est bien beau tout ça, mais une question me turlupine... :-° Comment la fonction testerActivite() peut-elle savoir si l'inactivité détectée est persistante ou nouvelle ?

      En effet, pour que la fonction mette à jour la valeur de temps_inactivite, il faut qu'elle sache si l'inactivité a déjà été détectée auparavant ou non, et surtout, si elle est persistante, c'est à dire qu'aucune activité n'a été détectée entre temps.

      Pour résoudre le problème, il va tout simplement encore falloir faire appel à une variable booléenne.

      Supposons que l'on crée une variable avec pour nom inactivite_persistante. Lorsqu'une activité est détectée, on lui donne la valeur true et à chaque appel de testerActivite(), la fonction va savoir qu'il faut mettre à jour la valeur de temps_inactivite. Dès qu'une activité est détectée, on lui donne la valeur false et tout recommence.

      Une fois tout ceci fait, et bien il suffit de rajouter un bout de code testant la valeur de temps_inactivite et réagir si elle dépasse un certain seuil (tu donnais l'exemple de 30 secondes). Et voilà, la boucle est bouclée... :)

      Minute, minute... :colere2: On parle depuis tout à l'heure de "mettre à jour la valeur de la variable", mais cela revient à faire quoi, au juste ? :colere2:

      Ah oui, suis-je bête ^^ J'ai oublié de préciser ce qu'il convenait de faire.

      Et bien à chaque appel de fonction, il s'est passé un certain temps qui a pour valeur celle de la variable intervalle. Mettre à jour la variable temps_inactivite revient donc en fait à lui rajouter la valeur de intervalle.

      Maintenant, on peut passer à la pratique ;)

      Mise en application



      Tout (ou presque) a été expliqué ci-dessus, je propose donc directement le code suivant (la page HTML ne change pas) :

      1. // On déclare et initialise les variables utilisée
      2. var activite_detectee = false;
      3. var intervalle = 100;
      4. var temps_inactivite = 0;
      5. var inactivite_persistante = true;
      6. // On crée la fonction qui teste toutes les x secondes l'activité du visiteur via activite_detectee
      7. function testerActivite() {
      8.   // On teste la variable activite_detectee
      9.      // Si une activité a été détectée [On réinitialise activite_detectee, temps_inactivite et inactivite_persistante]
      10.      if(activite_detectee) {
      11.        activite_detectee = false;
      12.        temps_inactivite = 0;
      13.        inactivite_persistante = false;
      14.      }
      15.      // Si aucune activité n'a été détectée [on actualise le statut du visiteur et on teste/met à jour la valeur du temps d'inactivité]
      16.      else {
      17.        statut('inactif');
      18.        // Si l'inactivite est persistante [on met à jour temps_inactivite]
      19.        if(inactivite_persistante) {
      20.          temps_inactivite += intervalle;
      21.          // Si le temps d'inactivite dépasse les 30 secondes
      22.          if(temps_inactivite >= 30000)
      23.            alert('Trente secondes d\'inactivité viennent de s\'écouler.');
      24.        }
      25.        // Si l'inactivite est nouvelle [on met à jour inactivite_persistante]
      26.        else
      27.          inactivite_persistante = true;
      28.      }
      29.   // On relance la fonction ce qui crée une boucle
      30.   setTimeout('testerActivite();', intervalle);
      31. }
      32. // On crée une fonction qui permet de mettre à jour le statut du visiteur
      33. function statut(statut) {
      34.   // On initialise la variable bloc créée par souci de lisibilité
      35.   var bloc = document.getElementById('statut');
      36.   // On supprime l'ancien statut affiché
      37.   bloc.removeChild(bloc.firstChild);
      38.   // Suivant le statut, on change la couleur d'écriture
      39.   if(statut == 'actif')
      40.     bloc.style.color = '#00ff00'; // Vert
      41.   else if(statut == 'inactif')
      42.     bloc.style.color = '#ff0000'; // Rouge
      43.   // On affiche le nouveau statut
      44.   bloc.appendChild(document.createTextNode('Vous êtes ' + statut + '.'));
      45. }
      46. // On lance la fonction testerActivite() pour la première fois, au chargement de la page
      47. setTimeout('testerActivite();', intervalle);

      Et voilà enfin le code fonctionnel que tu désirais :)

      Sans doute peux-tu comprendre maintenant les raisons qui m'ont poussé à prendre autant de temps dans mes explications et mon souci d'aborder les principes du code avant de le démarrer car celui-ci et loin d'être aussi facile que l'on pourrait l'imaginer.

      En vérité, vu tel quel, il est difficilement compréhensible.
      Comme pour la première section, voici un code (non expliqué mais commenté) qui permet de voir le temps d'inactivité qui s'écoule et qui certifie le bon fonctionnement du code :

      FICHIER HTML
      1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
      3.   <head>
      4.     <title>Activité et inactivité d'un visiteur</title>
      5.     <meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1" />
      6.     <script type="text/javascript" src="activite_final.js"></script>
      7.   </head>
      8.   <body onkeydown="activite_detectee = true; statut('actif');" onmousemove="activite_detectee = true; statut('actif');">
      9.     <h3>Bonjour et bienvenue, cher visiteur !</h3>
      10.     <p>Nous testons actuellement, et tout le long de votre présence sur cette page, votre activité et inactivité. Merci d'avoir bien accepté de participer à l'expérience.
      11. Orka et son équipe.</p>
      12.     <p id="statut" style="color:#ff0000;">Vous êtes inactif depuis 0 secondes.</p>
      13.   </body>
      14. </html>

      FICHIER activite.js
      1. // On déclare et initialise les variables utilisée
      2. var activite_detectee = false;
      3. var intervalle = 100;
      4. var temps_inactivite = 0;
      5. var inactivite_persistante = true;
      6. // On crée la fonction qui teste toutes les x secondes l'activité du visiteur via activite_detectee
      7. function testerActivite() {
      8.   // On teste la variable activite_detectee
      9.      // Si une activité a été détectée [On réinitialise activite_detectee, temps_inactivite et inactivite_persistante]
      10.      if(activite_detectee) {
      11.        activite_detectee = false;
      12.        temps_inactivite = 0;
      13.        inactivite_persistante = false;
      14.      }
      15.      // Si aucune activité n'a été détectée [on actualise le statut du visiteur et on teste/met à jour la valeur du temps d'inactivité]
      16.      else {
      17.        statut('inactif');
      18.        // Si l'inactivite est persistante [on met à jour temps_inactivite]
      19.        if(inactivite_persistante) {
      20.          temps_inactivite += intervalle;
      21.          // Si le temps d'inactivite dépasse les 30 secondes
      22.          if(temps_inactivite >= 30000)
      23.            alert('Trente secondes d\'inactivité viennent de s\'écouler.');
      24.        }
      25.        // Si l'inactivite est nouvelle [on met à jour inactivite_persistante]
      26.        else
      27.          inactivite_persistante = true;
      28.      }
      29.   // On relance la fonction ce qui crée une boucle
      30.   setTimeout('testerActivite();', intervalle);
      31. }
      32. // On crée une fonction qui permet de mettre à jour le statut du visiteur
      33. function statut(statut) {
      34.   // On initialise la variable bloc créée par souci de lisibilité
      35.   var bloc = document.getElementById('statut');
      36.   // On supprime l'ancien statut affiché
      37.   bloc.removeChild(bloc.firstChild);
      38.   // Suivant le statut, on change la couleur d'écriture
      39.   if(statut == 'actif')
      40.     bloc.style.color = '#00ff00'; // Vert
      41.   else if(statut == 'inactif')
      42.     bloc.style.color = '#ff0000'; // Rouge
      43.   // On crée une variable statut_a_afficher [si il y a inactivité, on affiche le temps qui s'est écoulé depuis le début de l'inactivité]
      44.   if(statut == 'inactif') {
      45.     // On transforme le temps d'inactivité calculé en millisecondes en secondes
      46.     var temps_secondes = temps_inactivite / 1000;
      47.     var statut_a_afficher = statut + ' depuis ' + temps_secondes + ' secondes';
      48.   }
      49.   else
      50.     var statut_a_afficher = statut;
      51.   // On affiche le nouveau statut
      52.   bloc.appendChild(document.createTextNode('Vous êtes ' + statut_a_afficher + '.'));
      53. }
      54. // On lance la fonction testerActivite() pour la première fois, au chargement de la page
      55. setTimeout('testerActivite();', intervalle);

      Et voilààààààà :) Un petit lien pour tester : que je suis pressé de voir ce que ça donne.

      En espérant que mon aide t'aura satisfaite ;)
      • Partager sur Facebook
      • Partager sur Twitter
        8 août 2007 à 7:44:16

        Je dois l'avoué, une réponse aussi complète est très rare, soit chanceux :p
        Peut-être pourrais-tu en faire un tuto, BkM ?
        • Partager sur Facebook
        • Partager sur Twitter
          8 août 2007 à 10:09:38

          BkM, tu t'es laché là ^^

          Mais j'avoue que c'est TOP NICKEL !

          Que dire de plus, sinon merci ;)

          Delirium à raison, tu devrais mettre tout ça dans un tuto, car c'est pas facile à trouver sur le net...
          • Partager sur Facebook
          • Partager sur Twitter
            8 août 2007 à 10:36:25

            J'avoue c'est bluffant!!
            Je savais pas que c'était possible d'avoir de réponses aussi précises et complète.
            C'est un vrai tuto ta réponse en fait.Ca envie de se mettre au JS (car j'en suis encore a l'étape du php pour ma part :lol: )
            Félicitation
            • Partager sur Facebook
            • Partager sur Twitter
              8 août 2007 à 15:02:42

              Merci à tous pour les compliments, ça fait vraiment plaisir :)

              Pour ce qui est de faire un tuto, et bien regardez ma signature ;)

              Edit : Rendez-vous sur http://www.liketheweb.fr pour apprendre le JavaScript gratuitement ! :)
              • Partager sur Facebook
              • Partager sur Twitter
                8 octobre 2007 à 21:07:19

                Bravo, c'est vraiment rare des voir d'aussi bonnes réponses ^^
                • Partager sur Facebook
                • Partager sur Twitter
                  30 octobre 2014 à 10:47:36

                  Magnifique !

                  Réponse ultra-complète qui nous évite de recopier du code bêtement sans trop comprendre de ce qu'il fait.

                  Good job mec !

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    24 octobre 2015 à 19:45:54

                    Merci beaucoup pour ce code, très bien écrit :)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Détecter l'inactivité d'un utilisateur

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown