HTML5 et Green IT : gérer la visibilité du navigateur

Mise à jour 29/11/2012 : Les spécifications ont changées

HTML5 introduit la notion de visibilité de page. En ajoutant quelques flags dans les variables de la page web, il est ainsi possible de gérer des évènements différents si la page courante est visible ou non.Voici le chemin vers les spécifications du W3C :

http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html

Tout ce que cette spécification définit en fait, c’est deux variables de document et un nouvel évènement :

  • document.hidden (boolean)
  • document.visibilityState (string)
  • visibilitychange (event)

document.hidden retourne vrai quand :

  • le navigateur est minimisé
  • l’onglet est en arrière-plan
  • le navigateur s’apprête à décharger la page
  • le navigateur s’apprête à atteindre une entrée de l’historique de session (la traduction est approximative)
  • l’écran de veille / verrouillage du système d’exploitation est affiché

document.visibilityState retourne quant à lui l’état de la page (visible, hidden, prerender ou unloaded). Ces états correspondent au cycle de vie du bloc du DOM sur lequel on effectue le test.

L’évènement visibilitychange se contente de retourner la valeur de visiblitychange lorsqu’elle change.

Là où intervient le Green IT, c’est qu’on va être capable de supprimer, ou retarder les appels AJAX par exemple, lorsque l’on en a pas besoin. Combien de sites ré-actualisent continuellement des parties de leur site ? Beaucoup, dont les plus gros en tête : Twitter, Facebook, Gmail… Combien d’utilisateurs ouvrent un navigateur avec tous ces sites chargés, en le laissant minimisé ? Beaucoup aussi ! Le gain potentiel en adoptant l’utilisation de ces spécifications peut être très élevé, en évitant de surcharger le serveur par des appels complètement inutiles.

J’ai modifié le petit script d’exemple fourni sur la page des spécifications pour rendre son exploitation plus parlante. Voir la démo ici :

Démonstration

Tout se passe dans la partie javascript, qui n’utilise volontairement aucun framework pour des raisons de clarté.

Attention : il ne s’agit que d’un draft (brouillon), et donc les spécifications risquent d’évoluer. Il est par contre supporté par les principaux navigateurs récents, avec leur propre préfixe habituel :

  • mozHidden pour Mozilla Firefox 10+
  • webkitHidden pour Chrome 13+
  • msHidden pour IE 10+

Voici le code source :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<script type="text/javascript">// <![CDATA[
var timer = 0;

   //timeout value when the page is visible
   var PERIOD_VISIBLE = 1000;

   //timeout value when the page is NOT visible
   var PERIOD_NOT_VISIBLE = 2000;

   //returns whether the page is hidden or not
   //not implemented on all browsers yet
   function getHiddenState() {
       if(document.hidden || document.webkitHidden || document.msHidden || document.mozHidden ) {
           return true;
       } else {
           return false;
       }
   }

   //returns whether the page is hidden or not
   //not implemented on all browsers yet
   function getVisibilityState() {
       if(undefined!=document.visibilityState) {
           return document.visibilityState;
       } else if(undefined!=document.webkitVisibilityState) {
           return document.webkitVisibilityState;
       } else if(undefined!=document.mozVisibilityState) {
           return document.mozVisibilityState;
       } else if(undefined!=document.msVisibilityState) {
           return document.msVisibilityState;
       } else {
           return "browser not yet supported";
       }
   }

   //Depending on visibility, set the delay value
   function getDelay() {
       if(getHiddenState()) {
           return PERIOD_NOT_VISIBLE;
       } else {
           return PERIOD_VISIBLE;
       }
   }

   //Loaded when body loads
   function onLoad() {
       timer = setInterval(logTime, getDelay());

       //Events
       //Not implemented on all browsers yet
       document.addEventListener("visibilitychange",visibilityChanged);  
       document.addEventListener("webkitvisibilitychange", visibilityChanged);  
       document.addEventListener("msvisibilitychange", visibilityChanged);  
   }

   //Function fired when visibility changes
   function visibilityChanged() {
       clearTimeout(timer);
       timer = setInterval(logTime, getDelay());
   }

   //Logs the current time and page visibility
   function logTime() {
     var currentTime = new Date();
     var visibilityState = getVisibilityState();
     var newLine = "

    <li>"
+currentTime.getTime()+" ("+visibilityState+")</li>

"
;
     document.getElementById("time").innerHTML = document.getElementById("time").innerHTML + newLine;
   }

// ]]></script>
<h1>TIME:</h1>

Documentation complémentaire avec démonstration pour chaque :

Une bonne pratique doit prévaloir sur l’exemple fourni : éviter les boucles infinies lorsque c’est possible, et utiliser les évènements.

A noter également que pageVisibility n’est qu’une partie d’un groupe de travail du W3C, appelé Web Performance Working Group, qui travaille sur différents moyens d’améliorer les performances des applications Web. Surement d’autres applications Green IT à mettre en oeuvre donc.

MAJ 15/01/2013 : Alsacréation a écrit un article détaillé et avec des mises en pratique intéressantes