"The explosive growth of the GeoWeb and geographic information has made GIS powerful media for the general public to communicate, but perhaps more importantly, GIS have also become media for constructive dialogs and interactions about social issues." - Sui & Goodchild
This is an old revision of the document!
HTML5 apporte beaucoup au développeur en permettant, notamment, de donner plus de sens à la source.
De nombreux nouveaux tags sont désormais valides header
, nav
, footer
, etc… et permettent une meilleure sémantique des pages. Ensuite, tous les tags HTML peuvent avoir des attributs personnalisés liés à l'application et suffixé de data
-. On trouvera donc data-monAttribut
plutôt que d'utiliser une classe inutile et dénuée de sens.
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" media="screen" href="ecran.css"> </head> <body> <header> <h1>Wake up sheeple!</h1> <p><a href="news.html">News</a> - <a href="blog.html">Blog</a> - <a href="forums.html">Forums</a></p> <p>Last Modified: <time>2009-04-01</time></p> <nav> <h1>Navigation</h1> <ul> <li><a href="articles.html">Index of all articles</a></li> <li><a href="today.html">Things sheeple need to wake up for today</a></li> <li><a href="successes.html">Sheeple we have managed to wake</a></li> </ul> </nav> </header> <div> <article> <header> <h1>My Day at the Beach</h1> </header> <div> <p>Today I went to the beach and had a lot of fun.</p> ...more content... </div> <footer> <p>Posted <time pubdate="" datetime="2009-10-10T14:36-08:00">Thursday</time>.</p> </footer> </article> ...more blog posts... </div> <footer> ... </footer> </body> </html>
De plus, HTML5 apporte une suite intéressantes d'APIs qui permettent permettraient de rendre les applications web encore plus performantes, indépendantes, etc :
De nombreux exemples concernant l'ensembles des APIs sont consultables sur http://slides.html5rocks.com/
L'interface proposée par le consortium W3C concernant les websockets est disponible à l'adresse: http://dev.w3.org/html5/websockets/
Elle est encore à l'état de draft (état au 24 mai 2011) mais certains navigateurs l'implémentent d'ores déjà; à savoir Chrome et Safari (y.c. la version mobile). La découverte d'une faille de sécurité relativement importante lors de la phase de handshake, certains browsers ont décidé de désactivé l'API pour le moment; c'est notamment le cas de firefox 4.
L'interface proposée par le W3C se présente de la manière suivante:
interface WebSocket { readonly attribute DOMString url; // ready state const unsigned short CONNECTING = 0; const unsigned short OPEN = 1; const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; readonly attribute unsigned long bufferedAmount; // networking attribute Function onopen; attribute Function onmessage; attribute Function onerror; attribute Function onclose; readonly attribute DOMString protocol; void send(in DOMString data); void close(); };
Dans le cadre des quelques démonstrations qui vont suivre, nous allons utiliser une librarie php
disponible sur github. Toutefois, il existe déjà d'autres implémentations de serveur websockets en Java, en Ruby,…
Afin de pouvoir satisfaire tout le monde (c-à-d ceux qui n'utilisent pas des browser modernes Safari ou Chrome :) ), il est possible d'établir une connexion persistante entre le serveur et ces clients via un fichier swf. Par contre, l'utilisation de cette méthode nécessite l'ajout de quelques classes et fichiers pour le client.
Le fonctionnement de cette application permet de faire la transition entre les requêtes ajax et les websockets.
Pour ce faire, on va établir une connexion persistante entre le client et le server mais les données ne transiterons qu'à la demande du client. Lorsque le client appellera le serveur, celui-ci lui renverra l'heure actuelle et elle sera ensuite affichée chez le client.
Dans cet exemple, le code javascript est très simple. On va créer un nouvel objet WebSocket
fourni par l'API du browser et ne fonctionnera que sur Chrome, Safari et Safari mobile.
var myWebsocket = new WebSocket(wsUri);
Le reste du code va simplement permettre de définir les méthodes onopen
, onclose
, onmessage
et onerror
de l'objet websocket
. On peut noter que la grande partie du code est utilisé pour l'esthétique de l'interface.
myWebsocket.onopen = function (evt) { console.log('Websocket open.'); $('#status').removeClass().addClass('online').html('online'); writeToScreen('connected to '+ wsUri) $('#send').attr('disabled', false); } myWebsocket.onclose = function(evt) { console.log('Websocket closed.'); $('#status').removeClass().addClass('offline').html('offline'); $('#send').attr('disabled', true); } myWebsocket.onmessage = function(evt) { console.log('Message received.') writeToScreen('Received: ' + evt.data); output.animate({scrollTop: output.attr('scrollHeight')}) } myWebsocket.onerror = function(evt) { console.error('Error') $('#status').removeClass().addClass('error').html('error'); }
Du point de vue du serveur, tout est très simple. Nous avons enregistré une nouvelle application et avons définis quelques méthodes au sein de celle-ci. Cette application va gérer la (dé)connexion des clients et leur répondre la date uniquement à leur demande.
class DateApplication extends Application { private $clients = array(); private $lastTime = 0; public function onConnect($client) { $this->clients[] = $client; } public function onDisconnect($client) { $key = array_search($client, $this->clients); if ($key) { unset($this->clients[$key]); } } public function onData($data, $client) { $client->send(date(DATE_RFC822)); } }
Le fonctionnement de cette application diffère de l'exemple précédent. Cette fois-ci, c'est le serveur qui va interagir avec le(s) client(s) connecté(s). Lors de l'ouverture de l'exemple, l'application va ouvrir une connexion sur le serveur. Celui-ci va enregistrer le client dans une liste puis, toutes les 3 secondes, le serveur va transmettre la date à tous les clients
public function onTick() { if (time() >= $this->lastTime + 3) { $this->lastTime = time(); foreach ($this->clients as $sendto) { $sendto->send(date(DATE_RFC822)); } } }
Cet exemple a pour but de créer un mini chat. Il faut alors que le serveur soit en mesure :
De leur côtés, les clients doivent être en mesure de :
var wsUri = "ws://monserveur:monport/echo"; var output; $(document).ready(function() { output = $("div#log"); initWebSocket(); $('#send').click(function(){ console.log('Message sent: ' + $('#message').val()); writeToScreen("Websocket called"); websocket.send($('#message').val()); }); }); function initWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function (evt) { console.log('Websocket open.'); $('#status').removeClass().addClass('online').html('online'); writeToScreen('connected to '+ wsUri) $('#send, #message').attr('disabled', false); } websocket.onclose = function(evt) { console.log('Websocket closed.'); $('#status').removeClass().addClass('offline').html('offline'); $('#send, #message').attr('disabled', true); $('#connection').text('Connect'); setTimeout(initWebSocket, 1000); } websocket.onmessage = function(evt) { console.log('Message received.') var data = JSON.parse(evt.data); writeToScreen('['+data.who+']: ' + data.msg); output.animate({scrollTop: output.attr('scrollHeight')}) } websocket.onerror = function(evt) { console.error('Error') $('#status').removeClass().addClass('error').html('error'); } } function writeToScreen(message) { var pre = document.createElement("pre"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.append(pre); }
public function onData($data, $client) { foreach ($this->clients as $sendto) { $obj = (object) null; $obj->who = $client->toString(); $obj->msg = $data; $sendto->send(json_encode($obj)); } }
Vouloir utiliser les web sockets pourrait, à plus ou moins long terme, devenir très intéressant. En attendant que tous les navigateurs acceptent et s'accordent sur l'API (et plus généralement sur toutes les APIs d'HTML5), il est nécessaire trouver des solutions afin de faire fonctionner les sockets d'une manière plus universelle.
Tout d'abord, on profitera de l'occasion, pour également intégrer la classe JSON qui n'est pas native sur certain browser.
<!-- Needed for old browser --> <script src="js/json2.js"></script>
En ce qui concerne les websockets, la solution qui convient le mieux pour les websockets est l'utilisation d'un composant flash. Hiroshi Ichikawa avec son projet https://github.com/gimite/web-socket-js propose une librarie toute faite qui ne demande qu'une modification mineur du code pour rendre fonctionnel l'objet websocket. On notera par contre, un léger délai sur la réception des données pour les browsers utilisant le composant flash.
<!-- Needed for browser who do not implement WebSocket --> <script src="js/swfobject.js"></script> <script src="js/FABridge.js"></script> <script type="text/javascript"> WEB_SOCKET_SWF_LOCATION = "js/WebSocketMain.swf"; </script>
En se basant sur l'exemple 1 et en modifiant ex-hash-template.zip, faire en sorte que le client envoie une chaine de caractères au serveur. Celui-ci lui renverra le hash md5 de la valeur au client qui l'affichera.
En partant de ex-irc-template.zip et de l'exemple 3, faire en sorte que :