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

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 n’est pas l’onglet courant
  • l’écran de veille du système d’exploitation est affiché

Attention : le navigateur n’est pas capable de savoir si la fenêtre est au premier plan ou non. document.hidden retournera donc false même si le navigateur est non minimisé mais caché par une autre fenêtre.

document.visibilityState retourne quant à lui l’état de la page (visible, hidden, ou preview). J’avoue que je n’ai pas vraiment compris le rôle de preview, peut-être une notion d’accessibilité ?

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, et je suis le premier à le faire ! Le gain serait je pense assez énorme côté serveur, puisqu’on éviterait de le surcharger 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
76
77
78
79
80
81
82
83
<!DOCTYPE html>
<html>
 <head>
  <script>
   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>
 </head>
 <body onload="onLoad()">
 
   <h1>TIME:</h1>
   <ul id="time"></ul>
 
 </body>
</html>

Documentation complémentaire avec démonstration pour chaque :

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.