HTML5 (LP IRSII) TP3 Jean-Yves Didier Situation initiale : Monsieur Lesieur, épicier, souhaite s équiper à moindre frais pour faciliter le passage en caisse de ses clients. Il a donc acheté un lecteur de code barre (qui se comporte comme un clavier : le lecteur énumère les chiffres du code barre comme s ils étaient tapés et ensuite simule une frappe sur la touche Entrée ). Il fait appel à vous pour lui développer une application qui lui permettrait de récupérer dans une base de données la désignation d un produit et le prix qui lui est associé en fonction du code barre. Monsieur Lesieur n ayant qu une caisse enregistreuse dans le magasin, vous lui proposez de développer l application en HTML5 ce qui lui permettra de s équiper moindre frais en termes de logiciels (en théorie, un navigateur récent suffira sur l ordinateur). L objectif de ce TP est donc de réaliser en partie cette application. 1 Prototypage des formulaires nécessaires L application web à développer devra être constituée de deux formulaires : le premier doit permettre à Monsieur Lesieur de saisir les produits en sa possession ( numéro de code barre, désignation du produit et prix associé), le second doit permettre de démarrer la création d un ticket de caisse, enregistrer les articles passés et calculer automatiquement le montant dû par le client. Dans cette première partie, nous vous demandons de créer les pages HTML nécessaires, la programmation javascript associée sera à faire dans les parties suivantes. 2 Enregistrement des produits Ici, il vous faudra développer la logique applicative associée. Vos scripts devront initialiser une base de données (en utilisant l API JavaScript IndexedDB) permettant de stocker la liste des produits. En toute logique, cela devrait aussi permettre de supprimer un produit ou de le modifier. Remarques : Pensez à utiliser les outils de débogage javascript de votre navigateur. Sous Firefox, cela se trouve dans le menu Tools, le sous-menu Web Developer et l option Web Console ; Sous Google Chrome, cela s active par l icône avec trois barres située en haut à droite, le sous-menu Tools, l option Developer Tools. Un exemple complet et fonctionnel d application web utilisant IndexedDB est disponible à l adresse suivante : http://evra.ibisc.univ-evry.fr/ didier/html5/students.html 1
3 Élaboration du ticket de caisse Lorsqu un nouveau ticket est demandé, la saisie d un code barre doit automatiquement ajouter à la liste nouvellement créée le produit avec sa dénomination et son prix. le coût total du ticket doit aussi être calculé. Cela peut se faire à l aide d une table temporaire dans la base de données ou en utilisant l API localstorage. 4 Mise à disposition hors-ligne de l application Faites le nécessaire pour l application soit disponible hors-ligne en mettant en place un fichier manifeste associé à votre application. Lorsque ceci est réalisé, chargez votre application par le biais d un serveur Web, puis faites fonctionner votre navigateur hors-ligne (hors connexion). Que constatezvous? Que pouvez-vous faire pour résoudre les problèmes? Annexes A L API WebStorage Cette API, à l instar des cookies permet de stocker des données du côté du navigateur. Le gros avantage est que, contrairement aux cookies qui transitent nécessairement entre le client et le serveur, les objets stockés côté navigateur ne transitent pas, ce qui économise la bande passante. L API définit une classe d objets Storage, deux objets de cette classe à disposition du navigateur : sessionstorage et localstorage et enfin des évènements pour actualiser les informations (storage). L objet sessionstorage est persistent pour l ensemble des pages d un même site web ouvertes dans une même fenêtre. L objet localstorage est persistent pour toutes les pages ouvertes vers un même site (même si les pages sont ouvertes à plusieurs jours d intervalle sur un même navigateur qui a été redémarré entre temps. A.1 Exemple d utilisation de l API webstorage Exemple d utilisation : Ici, c est dans le cadre d un script qui compte le nombre de fois que le navigateur a consulté une certaine page. <p> You have viewed t h i s page <span i d = c o u n t >an u n t o l d number of</ span> time ( s ). </ p> <s c r i p t> i f (! l o c a l S t o r a g e. pageloadcount ) l o c a l S t o r a g e. pageloadcount = 0 ; l o c a l S t o r a g e. pageloadcount = p a r s e I n t ( l o c a l S t o r a g e. pageloadcount ) + 1 ; document. getelementbyid ( count ). t e x t C o n t e n t = l o c a l S t o r a g e. pageloadcount ; / / r é a c t u a l i s a t i o n du décompte e t a f f i c h a g e dès qu un o n g l e t e s t o u v e r t s u r l a page. f u n c t i o n h a n d l e S t o r a g e ( e v e n t ) { i f ( e v e n t. key == pageloadcount ) { document. getelementbyid ( count ). t e x t C o n t e n t = e v e n t. newvalue ; window. a d d E v e n t L i s t e n e r ( s t o r a g e, h a n d l e S t o r a g e, f a l s e ) ; </ s c r i p t> 2
A.2 La classe Storage Cette classe permet de stocker des paires de type clé/valeur. Attribut length le nombre de paires stockées. Méthodes key(i) retourne la ième clé ; getitem(key) retourne la valeur associée à la clé key ; setitem(key,value) stocke une paire clé/valeur ; removeitem(key) retire la paire associée à la clé key ; clear() vide l objet de toutes ses paires clé/valeur. A.2.1 A.2.2 L évènement onstorage Fait partie de la classe Window ; Est traité par une fonction de rappel prenant en paramètre un objet de class StorageEvent. La classe StorageEvent Cette classe dérive de la classe générale Event. Attributs key la clé sur laquelle survient l évènement ; oldvalue l ancienne valeur associée à la clé ; newvalue la nouvelle valeur associée à la clé ; url l adresse du document dont la clé a été modifiée ; storagearea référence à la zone de stockage utilisée (localstorage ou sessionstorage. B L API IndexedDB Cette API permet de manipuler des bases de données dont les informations sont stockées par le navigateur. Elle comprend, entre autres, les classes suivantes : IDBFactory : classe de base permettant d obtenir la base de données ; IDBDatabase : base de données ; IDBObjectStore : équivalent d une table ; IDBTransaction : transaction ; IDBRequest : requête ; IDBCursor : curseur pour se déplacer dans une liste d objets renvoyés par une requête. B.1 Descriptif des classes de l API B.1.1 La classe IDBFactory C est une classe déjà implémentée dans le navigateur sous la forme d un objet (parfois préfixé) disponible sous différents noms : window.indexeddb ; window.mozindexeddb ; window.webkitindexeddb ; window.msindexeddb. Les méthodes associées, qui ont pour retour un objet de type IBDRequest sont les suivantes : open : ouverture de la base en donnant un nom et un numéro de version (optionnel) ; deletedatabase : destruction de la base en donnant son nom. 3
B.1.2 L objet IBDRequest Attributs result Résultat de la requête ; transaction transaction liée à la requête ; Evènements onsuccess requête effectuée avec succès ; onerror requête terminée mais infructueuse. onblocked lorsque l ouverture est empêchée par l utilisateur ; onupgradeneeded lorsque le numéro de version demandé ne concorde pas avec celui de la base à l ouverture. B.1.3 L objet IDBDatabase IBDBDatabase est en lien avec IBDRequest : le champ target.result des évènements envoyés par les IBDRequest est du type IDBDatabase. Attributs name nom de la base de données version version associée (entier) ; objectstorenames tableau des noms de tables ; Méthodes createobjectstore(nom,[params]) création d une table ; deleteobjectstore(nom) destruction d une table ; transaction(nom, mode) initialisation d une transaction ; close() fermeture de la base de données. Evènements onabort déclenché à l annulation ; onerror déclenché si erreur ; onsuccess déclenché si succès. B.1.4 L objet IBDObjectStore Attributs name nom de la table ; keypath nom de la clé ; transaction retourne la transaction liée à la table ; autoincrement Méthodes put(valeur,[cle]) stocke un objet dans la table ; add(valeur,[cle]) idem ; delete(cle) effacer un objet par sa clé ; get(cle) récupérer un objet par sa clé ; B.1.5 indique si la clé doit s auto-incrémenter. opencursor(...) parcours la table ; clear() vider la table de ses objets. L objet IBDCursor Attributs source objet sur lequel opère le curseur ; key clé courante sur laquelle est arrivé le curseur. Opérations continue() fait avancer le curseur d un cran si possible. 4
B.1.6 L objet IBDTransaction Attributs mode mode d ouverture de la base (readonly, readwrite) ; db base de données associée ; error message d erreur (si cela se produit). Opérations abort annulation de la transaction (annulation de tous les changements de la transaction en cours ; objectstore(nom) retourne la table au nom approprié. Evènements onabort déclenché en cas d annulation ; oncomplete déclenché lorsque la transaction est achevée ; onerror déclenché en cas d erreur. B.2 Exemples d utilisation de l API IndexedDB B.2.1 Ouverture de base de données v a r db={ ; db. indexeddb = window. indexeddb window. webkitindexeddb window. mozindexeddb window. msindexeddb ; i f ( db. indexeddb == n u l l ) { a l e r t ( IndexedDB n o t found. ) ; r e t u r n ; v a r r e q u e s t = db. indexeddb. open ( p o i n t a g e, 2 ) ; B.2.2 Création de la base de données Deux manières de faire : Utilisation de l évènement onupgradeneeded ; Par comparaison de version. r e q u e s t. o n s u c c e s s = f u n c t i o n ( e ) { v a r v e r s i o n = 2 ; v a r d a t a b a s e = e. t a r g e t. r e s u l t ; / / f a ç o n 1 i f ( v e r s i o n!= d a t a b a s e. v e r s i o n ) { v a r s e t V e r s i o n = d a t a b a s e. s e t V e r s i o n ( v e r s i o n ) ; s e t V e r s i o n. o n s u c c e s s = f u n c t i o n ( e ) { c r e a t e D a t a b a s e ( d a t a b a s e ) ; ; ; / / f a ç o n 2 r e q u e s t. onupgradeneeded = f u n c t i o n ( e ) { c r e a t e D a t a b a s e ( e. t a r g e t. r e s u l t ) ; ; B.2.3 Initialisation d une table c o n s t s t u d e n t s = [ { i d : j y d i d i e r, nom : D i d i e r, prenom : Jean Yves, n i v e a u : E n s e i g n a n t, f i l i e r e : MCF, { i d : 20021091, nom : C l i n t o n, prenom : B i l l, n i v e a u : P r e s i d e n t, f i l i e r e : USA, { i d : 20020007, nom : Bond, prenom : James, n i v e a u : M1, f i l i e r e : GEII ] ; f u n c t i o n c r e a t e D a t a b a s e ( d a t a b a s e ) { d a t a b a s e. c r e a t e O b j e c t S t o r e ( evenements,{ keypath : timestamp ) ; v a r s t o r e = d a t a b a s e. c r e a t e O b j e c t S t o r e ( e t u d i a n t s, { keypath : i d ) ; f o r ( v a r i i n s t u d e n t s ) { s t o r e. add ( s t u d e n t s [ i ] ) ; ; ; 5
B.2.4 Manipulation d une transaction v a r t r a n s a c t i o n = d a t a b a s e. t r a n s a c t i o n ( [ e t u d i a n t s ], r e a d o n l y ) ; v a r s t o r e = t r a n s a c t i o n. o b j e c t S t o r e ( e t u d i a n t s ) ; v a r c u r s o r R e q u e s t = s t o r e. opencursor ( ) ; c u r s o r R e q u e s t. o n s u c c e s s = f u n c t i o n ( e ) { v a r r e s u l t = e. t a r g e t. r e s u l t ; i f (!! r e s u l t == f a l s e ) r e t u r n ; / / e f f e c t u e r t r a i t e m e n t s u r r e s u l t. v a l u e / / o b j e t f o r m a t t é comme à l i n i t i a l i s a t i o n r e s u l t. c o n t i n u e ( ) ; c u r s o r R e q u e s t. o n e r r o r = f u n c t i o n ( e ) { / / t r a i t e m e n t en c a s d e r r e u r C Les manifestes pour les applications hors-ligne C.1 Le manifeste C.1.1 Donne la liste des fichiers nécessaires pour travailler hors-ligne ; Suit une syntaxe précise : Commence par la ligne CACHE MANIFEST ; Comprend trois sections ; La section CACHE: indique les fichiers à mettre en cache. Les premiers fichiers listés n appartenant pas à une section sont considérés comme étant dans CACHE: La section NETWORK: indique les fichiers qui sont à mettre à jour impérativement par le réseau ; La section FALLBACK: indique les substitutions à opérer. Exemple de manifeste CACHE MANIFEST NETWORK: comm.cgi CACHE: style/default.css images/sound-icon.png images/background.png FALLBACK: / /offline.html C.2 Associer un manifeste à un fichier html Au moyen de l attribut manifest de la balise html. Ceci se fait de la manière suivante : <!DOCTYPE html> <html m a n i f e s t = monapp. m a n i f e s t >... </ html> 6